From fc44c7c98884055f3ebad6a31300941eb00f590f Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Thu, 11 Dec 2025 11:41:01 -0800 Subject: [PATCH 0001/1133] FROMLIST: dt-bindings: phy: qcom,sc8280xp-qmp-usb43dp-phy: Add Glymur compatible Define a Glymur compatible string for the QMP combo PHY, along with resource requirements. Acked-by: Rob Herring (Arm) Signed-off-by: Wesley Cheng Link: https://lore.kernel.org/all/20251209-linux-next-12825-v8-1-42133596bda0@oss.qualcomm.com/ From 4000dd1d7219e6376d86c6a289c927ae0f753a0f Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Thu, 11 Dec 2025 11:47:27 -0800 Subject: [PATCH 0002/1133] FROMLIST: dt-bindings: phy: qcom-m31-eusb2: Add Glymur compatible Add the Glymur compatible to the M31 eUSB2 PHY, and use the SM8750 as the fallback. Signed-off-by: Wesley Cheng Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/all/20251209-linux-next-12825-v8-3-42133596bda0@oss.qualcomm.com/ From d5cd473531e2587ce8eb51d340d060f837cbefb6 Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Sat, 20 Dec 2025 12:05:35 +0530 Subject: [PATCH 0003/1133] usb: misc: onboard_usb_hub: Add Genesys Logic GL3590 hub support Add support for the GL3590 4 ports USB3.2 hub. This allows to control its reset pins with a gpio. Signed-off-by: Swati Agarwal --- drivers/usb/misc/onboard_usb_dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/onboard_usb_dev.h b/drivers/usb/misc/onboard_usb_dev.h index 3523f8f8a1496..62d93c9720ca7 100644 --- a/drivers/usb/misc/onboard_usb_dev.h +++ b/drivers/usb/misc/onboard_usb_dev.h @@ -153,7 +153,7 @@ static const struct of_device_id onboard_dev_match[] = { { .compatible = "usb5e3,608", .data = &genesys_gl850g_data, }, { .compatible = "usb5e3,610", .data = &genesys_gl852g_data, }, { .compatible = "usb5e3,620", .data = &genesys_gl852g_data, }, - { .compatible = "usb5e3,625", .data = &genesys_gl3590_data, }, + { .compatible = "usb5e3,625", .data = &genesys_gl852g_data, }, { .compatible = "usb5e3,626", .data = &genesys_gl852g_data, }, { .compatible = "usbbda,179", .data = &realtek_rtl8188etv_data, }, { .compatible = "usbbda,411", .data = &realtek_rts5411_data, }, From 64555fda5d39c6224951bd65f478ebde6db93dd8 Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Sat, 20 Dec 2025 12:05:34 +0530 Subject: [PATCH 0004/1133] dt-bindings: usb: Add binding for Genesys Logic GL3590 hub Add the binding for the USB3.2 Genesys Logic GL3590 hub. Signed-off-by: Swati Agarwal --- .../devicetree/bindings/usb/genesys,gl850g.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml index e8b8c03f87a0e..eb51c35059dc9 100644 --- a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml +++ b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml @@ -87,6 +87,17 @@ allOf: peer-hub: true vdd-supply: true + - if: + properties: + compatible: + contains: + enum: + - usb5e3,625 + then: + properties: + peer-hub: true + vdd-supply: false + unevaluatedProperties: false examples: From fa0ec61b71601790e689b5a2546c8db09e0e4aec Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:22 -0800 Subject: [PATCH 0005/1133] FROMLIST: dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Qualcomm Embedded USB Debugger (EUD) can intercept one or two independent High-Speed UTMI paths, depending on the SoC. Each path is distinct with its own HS-PHY interface, connector/controller wiring, and UTMI routing behavior. The EUD hardware sits between the USB2 PHY and the USB controller on each path. The existing binding models only a single UTMI path and does not provide a way to associate the required High-Speed USB PHY. EUD relies on the HS-PHY on the selected UTMI path for link signalling and correct operation of the hardware. Historically, EUD has worked on platforms that use a single UTMI path because the USB controller maintains ownership of the PHY during enumeration and normal operation. This implicit relationship allowed EUD to function even though the dependency on the PHY was not described in the binding. However, this behavior is not guaranteed by hardware. The current binding description is not sufficient for SoCs that expose two independent UTMI paths, where the PHY association and port wiring must be explicitly described. Introduce per-path eud-path child nodes so each UTMI path can describe its HS-PHY, port connections, and the role‑switching capability of its associated USB port. Signed-off-by: Elson Serrao Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-2-elson.serrao@oss.qualcomm.com/ --- .../bindings/soc/qcom/qcom,eud.yaml | 100 +++++++++++++----- 1 file changed, 74 insertions(+), 26 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml index 84218636c0d8d..0507252dbf27e 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml @@ -10,8 +10,11 @@ maintainers: - Souradeep Chowdhury description: - This binding is used to describe the Qualcomm Embedded USB Debugger, which is - mini USB-hub implemented on chip to support USB-based debug capabilities. + This binding describes the Qualcomm Embedded USB Debugger (EUD), an on-chip + mini USB hub that enables USB-based debug capabilities. The EUD block is + positioned between the High-Speed USB PHY and the USB controller, where it + intercepts the UTMI interface to support debug and bypass modes. EUD can be + supported on up to two High-Speed USB ports. properties: compatible: @@ -29,26 +32,62 @@ properties: description: EUD interrupt maxItems: 1 - ports: - $ref: /schemas/graph.yaml#/properties/ports + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + +patternProperties: + "^eud-path@[0-1]$": + type: object description: - These ports is to be attached to the endpoint of the DWC3 controller node - and type C connector node. The controller has the "usb-role-switch" - property. + Represents one High-Speed UTMI path that EUD intercepts. This node models + the physical data path intercepted by EUD and provides graph endpoints to + link the USB controller and the external connector associated with this path. properties: - port@0: - $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the DWC3 controller. + reg: + maxItems: 1 + description: Path number + + phys: + maxItems: 1 + description: High-Speed USB PHY associated with this data path. + + usb-role-switch: + type: boolean + description: + Set this property if the USB port on this path is role switch capable. + In device role, debug mode inserts the EUD hub into the UTMI path. In + host role, the EUD hub is bypassed and UTMI traffic flows directly + between the PHY and the USB controller. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + description: + These ports are to be attached to the endpoint of the USB controller node + and USB connector node. + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the USB controller. - port@1: - $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the type C connector. + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the USB connector. + + required: + - reg + - phys + - ports + + additionalProperties: false required: - compatible - reg - - ports additionalProperties: false @@ -58,21 +97,30 @@ examples: compatible = "qcom,sc7280-eud", "qcom,eud"; reg = <0x88e0000 0x2000>, <0x88e2000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + eud-path@0 { + reg = <0>; + phys = <&usb_1_hsphy>; + usb-role-switch; - ports { - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - eud_ep: endpoint { - remote-endpoint = <&usb2_role_switch>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + eud_ep: endpoint { + remote-endpoint = <&usb2_role_switch>; + }; }; - }; - port@1 { - reg = <1>; - eud_con: endpoint { - remote-endpoint = <&con_eud>; + port@1 { + reg = <1>; + eud_con: endpoint { + remote-endpoint = <&con_eud>; + }; }; }; }; From e9841944f764a4cd6cbb28cbc8b0be75ada20b1f Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:23 -0800 Subject: [PATCH 0006/1133] FROMLIST: usb: misc: qcom_eud: add sysfs attribute for port selection EUD can be mapped to either the primary USB port or the secondary USB port depending on the value of the EUD_PORT_SEL register. Add a 'port' sysfs attribute to allow userspace to select which port EUD should operate on and update the ABI documentation. This is needed for systems with dual USB ports where EUD needs to be accessible on either port depending on the system configuration and use case. Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-3-elson.serrao@oss.qualcomm.com/ --- Documentation/ABI/testing/sysfs-driver-eud | 16 ++++++++ drivers/usb/misc/qcom_eud.c | 43 ++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-eud b/Documentation/ABI/testing/sysfs-driver-eud index 2bab0db2d2f0f..67223f73ee606 100644 --- a/Documentation/ABI/testing/sysfs-driver-eud +++ b/Documentation/ABI/testing/sysfs-driver-eud @@ -7,3 +7,19 @@ Description: EUD based on a 1 or a 0 value. By enabling EUD, the user is able to activate the mini-usb hub of EUD for debug and trace capabilities. + +What: /sys/bus/platform/drivers/qcom_eud/.../port +Date: January 2026 +Contact: Elson Serrao +Description: + Selects which USB port the Embedded USB Debugger (EUD) + is mapped to on platforms providing multiple High-Speed + USB ports. + + Valid values: + 0 - Primary USB port + 1 - Secondary USB port + + The attribute is writable only while EUD is disabled. + Reading the attribute returns the currently selected + USB port number. diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 926419ca560fc..1a136f8f1ae52 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -23,8 +23,11 @@ #define EUD_REG_VBUS_INT_CLR 0x0080 #define EUD_REG_CSR_EUD_EN 0x1014 #define EUD_REG_SW_ATTACH_DET 0x1018 +#define EUD_REG_PORT_SEL 0x1028 #define EUD_REG_EUD_EN2 0x0000 +#define EUD_MAX_PORTS 2 + #define EUD_ENABLE BIT(0) #define EUD_INT_PET_EUD BIT(0) #define EUD_INT_VBUS BIT(2) @@ -40,6 +43,7 @@ struct eud_chip { int irq; bool enabled; bool usb_attached; + u8 port_idx; }; static int enable_eud(struct eud_chip *priv) @@ -104,8 +108,47 @@ static ssize_t enable_store(struct device *dev, static DEVICE_ATTR_RW(enable); +static ssize_t port_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct eud_chip *chip = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", chip->port_idx); +} + +static ssize_t port_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct eud_chip *chip = dev_get_drvdata(dev); + u8 port; + int ret; + + ret = kstrtou8(buf, 0, &port); + if (ret) + return ret; + + /* Only port 0 and port 1 are valid */ + if (port >= EUD_MAX_PORTS) + return -EINVAL; + + /* Port selection must be done before enabling EUD */ + if (chip->enabled) { + dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); + return -EBUSY; + } + + writel(port, chip->base + EUD_REG_PORT_SEL); + chip->port_idx = port; + + return count; +} + +static DEVICE_ATTR_RW(port); + static struct attribute *eud_attrs[] = { &dev_attr_enable.attr, + &dev_attr_port.attr, NULL, }; ATTRIBUTE_GROUPS(eud); From 0bcfcd54000d5629775984065b8841a40c835024 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:24 -0800 Subject: [PATCH 0007/1133] FROMLIST: usb: misc: qcom_eud: add per-path High-Speed PHY control EUD hardware can support multiple High-Speed USB paths, each routed through its own PHY. The active path is selected in hardware via the EUD_PORT_SEL register. As a High-Speed hub, EUD requires access to the High-Speed PHY associated with the active UTMI path. To support this multi-path capability, the driver must manage PHY resources on a per-path basis, ensuring that the PHY for the currently selected path is properly initialized and powered. This patch restructures the driver to implement per-path PHY management. The driver now powers the appropriate PHY based on the selected and enabled UTMI path, ensuring correct operation when EUD is enabled. Supporting this requires describing the available UTMI paths and their corresponding PHYs in Device Tree. This updates DT requirements and is not backward compatible with older DTs that lacked this description. Historically, EUD appeared to work on single-path systems because the USB controller kept the PHY initialized. However, EUD is designed to operate independently of the USB controller and therefore requires explicit PHY control. Signed-off-by: Elson Serrao Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-4-elson.serrao@oss.qualcomm.com/ --- drivers/usb/misc/qcom_eud.c | 130 +++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 1a136f8f1ae52..5cebb64f4a672 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -34,26 +35,96 @@ #define EUD_INT_SAFE_MODE BIT(4) #define EUD_INT_ALL (EUD_INT_VBUS | EUD_INT_SAFE_MODE) +struct eud_path { + struct eud_chip *chip; + struct phy *phy; + u8 num; +}; + struct eud_chip { struct device *dev; struct usb_role_switch *role_sw; void __iomem *base; + struct eud_path *paths[EUD_MAX_PORTS]; phys_addr_t mode_mgr; unsigned int int_status; int irq; bool enabled; bool usb_attached; + bool phy_enabled; u8 port_idx; }; +static int eud_phy_enable(struct eud_chip *chip) +{ + struct eud_path *path; + struct phy *phy; + int ret; + + if (chip->phy_enabled) + return 0; + + path = chip->paths[chip->port_idx]; + if (!path || !path->phy) { + dev_err(chip->dev, "No PHY configured for port %u\n", chip->port_idx); + return -ENODEV; + } + + phy = path->phy; + + ret = phy_init(phy); + if (ret) { + dev_err(chip->dev, "Failed to initialize USB2 PHY for port %u: %d\n", + chip->port_idx, ret); + return ret; + } + + ret = phy_power_on(phy); + if (ret) { + dev_err(chip->dev, "Failed to power on USB2 PHY for port %u: %d\n", + chip->port_idx, ret); + phy_exit(phy); + return ret; + } + + chip->phy_enabled = true; + + return 0; +} + +static void eud_phy_disable(struct eud_chip *chip) +{ + struct eud_path *path; + struct phy *phy; + + if (!chip->phy_enabled) + return; + + path = chip->paths[chip->port_idx]; + if (!path || !path->phy) + return; + + phy = path->phy; + + phy_power_off(phy); + phy_exit(phy); + chip->phy_enabled = false; +} + static int enable_eud(struct eud_chip *priv) { int ret; - ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); + ret = eud_phy_enable(priv); if (ret) return ret; + ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); + if (ret) { + eud_phy_disable(priv); + return ret; + } + writel(EUD_ENABLE, priv->base + EUD_REG_CSR_EUD_EN); writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, priv->base + EUD_REG_INT1_EN_MASK); @@ -70,6 +141,8 @@ static int disable_eud(struct eud_chip *priv) return ret; writel(0, priv->base + EUD_REG_CSR_EUD_EN); + eud_phy_disable(priv); + return 0; } @@ -132,6 +205,12 @@ static ssize_t port_store(struct device *dev, if (port >= EUD_MAX_PORTS) return -EINVAL; + /* Check if the corresponding path is available */ + if (!chip->paths[port]) { + dev_err(chip->dev, "EUD not supported on selected port\n"); + return -EOPNOTSUPP; + } + /* Port selection must be done before enabling EUD */ if (chip->enabled) { dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); @@ -231,8 +310,45 @@ static void eud_role_switch_release(void *data) usb_role_switch_put(chip->role_sw); } +static int eud_init_path(struct eud_chip *chip, struct device_node *np) +{ + struct eud_path *path; + u32 path_num; + int ret; + + ret = of_property_read_u32(np, "reg", &path_num); + if (ret) { + dev_err(chip->dev, "Missing 'reg' property in path node\n"); + return ret; + } + + if (path_num >= EUD_MAX_PORTS) { + dev_err(chip->dev, "Invalid path number: %u (max %d)\n", + path_num, EUD_MAX_PORTS - 1); + return -EINVAL; + } + + path = devm_kzalloc(chip->dev, sizeof(*path), GFP_KERNEL); + if (!path) + return -ENOMEM; + + path->chip = chip; + path->num = path_num; + + path->phy = devm_of_phy_get(chip->dev, np, NULL); + if (IS_ERR(path->phy)) + return dev_err_probe(chip->dev, PTR_ERR(path->phy), + "Failed to get PHY for path %d\n", path_num); + + chip->paths[path_num] = path; + + return 0; +} + static int eud_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; + struct device_node *child; struct eud_chip *chip; struct resource *res; int ret; @@ -252,6 +368,18 @@ static int eud_probe(struct platform_device *pdev) if (ret) return ret; + for_each_child_of_node(np, child) { + ret = eud_init_path(chip, child); + if (ret) { + of_node_put(child); + return ret; + } + } + + /* Primary path is mandatory. Secondary is optional */ + if (!chip->paths[0]) + return -ENODEV; + chip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chip->base)) return PTR_ERR(chip->base); From abdef2fdd8f1ba31c6ed088ca7b077c0f70c8124 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:25 -0800 Subject: [PATCH 0008/1133] FROMLIST: usb: misc: qcom_eud: add per-path role switch support The EUD hardware can support multiple High-Speed USB paths, each connected to different USB controllers. The current implementation uses a single chip-level role switch, which cannot properly handle multi-path configurations where each path needs independent role management. Since EUD is physically present between the USB connector and the controller, it should also relay the role change requests from the connector. Restructure the driver to support per-path role switches and remove the chip-level role switch. Additionally, as EUD need not modify the USB role upon enabling, remove the unnecessary role switch call from enable_eud(). Signed-off-by: Elson Serrao Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-5-elson.serrao@oss.qualcomm.com/ --- drivers/usb/misc/qcom_eud.c | 80 ++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 5cebb64f4a672..a58022f50484f 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -38,12 +38,15 @@ struct eud_path { struct eud_chip *chip; struct phy *phy; + struct usb_role_switch *controller_sw; + struct usb_role_switch *eud_sw; + enum usb_role curr_role; + char name[16]; u8 num; }; struct eud_chip { struct device *dev; - struct usb_role_switch *role_sw; void __iomem *base; struct eud_path *paths[EUD_MAX_PORTS]; phys_addr_t mode_mgr; @@ -129,7 +132,7 @@ static int enable_eud(struct eud_chip *priv) writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, priv->base + EUD_REG_INT1_EN_MASK); - return usb_role_switch_set_role(priv->role_sw, USB_ROLE_DEVICE); + return 0; } static int disable_eud(struct eud_chip *priv) @@ -287,15 +290,21 @@ static irqreturn_t handle_eud_irq(int irq, void *data) static irqreturn_t handle_eud_irq_thread(int irq, void *data) { struct eud_chip *chip = data; + struct eud_path *path; int ret; + path = chip->paths[chip->port_idx]; + if (!path || !path->controller_sw) + goto clear_irq; + if (chip->usb_attached) - ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_DEVICE); + ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_HOST); + ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_HOST); if (ret) dev_err(chip->dev, "failed to set role switch\n"); +clear_irq: /* set and clear vbus_int_clr[0] to clear interrupt */ writel(BIT(0), chip->base + EUD_REG_VBUS_INT_CLR); writel(0, chip->base + EUD_REG_VBUS_INT_CLR); @@ -303,15 +312,45 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) return IRQ_HANDLED; } +static int eud_role_switch_set(struct usb_role_switch *sw, enum usb_role role) +{ + struct eud_path *path = usb_role_switch_get_drvdata(sw); + int ret; + + /* Forward the role request to the USB controller */ + ret = usb_role_switch_set_role(path->controller_sw, role); + if (ret) { + dev_err(path->chip->dev, "Failed to set role %s for port %u: %d\n", + usb_role_string(role), path->num, ret); + return ret; + } + + path->curr_role = role; + + return 0; +} + static void eud_role_switch_release(void *data) { struct eud_chip *chip = data; + int i; - usb_role_switch_put(chip->role_sw); + for (i = 0; i < EUD_MAX_PORTS; i++) { + struct eud_path *path = chip->paths[i]; + + if (!path) + continue; + + if (path->eud_sw) + usb_role_switch_unregister(path->eud_sw); + if (path->controller_sw) + usb_role_switch_put(path->controller_sw); + } } static int eud_init_path(struct eud_chip *chip, struct device_node *np) { + struct usb_role_switch_desc role_sw_desc = {}; struct eud_path *path; u32 path_num; int ret; @@ -342,6 +381,32 @@ static int eud_init_path(struct eud_chip *chip, struct device_node *np) chip->paths[path_num] = path; + path->curr_role = USB_ROLE_NONE; + + if (!of_property_read_bool(np, "usb-role-switch")) + return 0; + + /* Fetch the USB controller's role switch */ + path->controller_sw = fwnode_usb_role_switch_get(of_fwnode_handle(np)); + if (IS_ERR(path->controller_sw)) + return dev_err_probe(chip->dev, PTR_ERR(path->controller_sw), + "Failed to get controller role switch for path %d\n", + path_num); + + /* Create a role switch */ + role_sw_desc.fwnode = of_fwnode_handle(np); + role_sw_desc.set = eud_role_switch_set; + role_sw_desc.driver_data = path; + snprintf(path->name, sizeof(path->name), "eud-path%u", path_num); + role_sw_desc.name = path->name; + + path->eud_sw = usb_role_switch_register(chip->dev, &role_sw_desc); + if (IS_ERR(path->eud_sw)) { + dev_err(chip->dev, "Failed to register EUD role switch for path %d: %ld\n", + path_num, PTR_ERR(path->eud_sw)); + return PTR_ERR(path->eud_sw); + } + return 0; } @@ -359,11 +424,6 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; - chip->role_sw = usb_role_switch_get(&pdev->dev); - if (IS_ERR(chip->role_sw)) - return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw), - "failed to get role switch\n"); - ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); if (ret) return ret; From ec8eff01cdd6afd9ce65ab5182ef339ac4b3829f Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:26 -0800 Subject: [PATCH 0009/1133] FROMLIST: usb: misc: qcom_eud: improve enable_store API Currently enable_store() allows operations irrespective of the EUD state, which can result in redundant operations. Avoid this by adding duplicate state checks to skip requests when EUD is already in the desired state. Additionally, improve error handling with explicit logging to provide better feedback. Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-6-elson.serrao@oss.qualcomm.com/ --- drivers/usb/misc/qcom_eud.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index a58022f50484f..0ea6491f963ce 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -168,18 +168,27 @@ static ssize_t enable_store(struct device *dev, if (kstrtobool(buf, &enable)) return -EINVAL; + /* Skip operation if already in desired state */ + if (chip->enabled == enable) + return count; + if (enable) { ret = enable_eud(chip); - if (!ret) - chip->enabled = enable; - else - disable_eud(chip); - + if (ret) { + dev_err(chip->dev, "failed to enable eud\n"); + return ret; + } } else { ret = disable_eud(chip); + if (ret) { + dev_err(chip->dev, "failed to disable eud\n"); + return ret; + } } - return ret < 0 ? ret : count; + chip->enabled = enable; + + return count; } static DEVICE_ATTR_RW(enable); From 57951b99e58e541080895a2af4bc418425f275ba Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:27 -0800 Subject: [PATCH 0010/1133] FROMLIST: usb: misc: qcom_eud: add host mode coordination EUD functions by presenting itself as a USB device to the host PC for debugging, making it incompatible in USB host mode configurations. Enabling EUD, when in host mode can also cause the USB controller to misbehave as the EUD hub can only have one upstream facing port. Handle below two scenarios to prevent these conflicts: 1. Prevent user from enabling EUD via sysfs when the USB port is in host mode. 2. Automatically disable EUD when USB port switches to host mode and re-enable it when exiting host mode. This ensures consistent state management without creating conflicts between the EUD debug hub and the USB controller. Signed-off-by: Elson Serrao Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-7-elson.serrao@oss.qualcomm.com/ --- drivers/usb/misc/qcom_eud.c | 79 ++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 0ea6491f963ce..3f1cc7ea2a6ae 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -49,12 +49,15 @@ struct eud_chip { struct device *dev; void __iomem *base; struct eud_path *paths[EUD_MAX_PORTS]; + /* serializes EUD control operations */ + struct mutex state_lock; phys_addr_t mode_mgr; unsigned int int_status; int irq; bool enabled; bool usb_attached; bool phy_enabled; + bool eud_disabled_for_host; u8 port_idx; }; @@ -162,32 +165,66 @@ static ssize_t enable_store(struct device *dev, const char *buf, size_t count) { struct eud_chip *chip = dev_get_drvdata(dev); + struct eud_path *path; bool enable; int ret; if (kstrtobool(buf, &enable)) return -EINVAL; + mutex_lock(&chip->state_lock); + /* Skip operation if already in desired state */ - if (chip->enabled == enable) + if (chip->enabled == enable) { + mutex_unlock(&chip->state_lock); return count; + } + + /* + * Handle double-disable scenario: User is disabling EUD that was already + * disabled due to host mode. Since the hardware is already disabled, we + * only need to clear the host-disabled flag to prevent unwanted re-enabling + * when exiting host mode. This respects the user's explicit disable request. + */ + if (!enable && chip->eud_disabled_for_host) { + chip->eud_disabled_for_host = false; + chip->enabled = false; + mutex_unlock(&chip->state_lock); + return count; + } if (enable) { + /* + * EUD functions by presenting itself as a USB device to the host PC for + * debugging, making it incompatible in USB host mode configuration. + * Prevent enabling EUD in this configuration to avoid hardware conflicts. + */ + path = chip->paths[chip->port_idx]; + if (path && path->curr_role == USB_ROLE_HOST) { + dev_err(chip->dev, "EUD not usable in host mode configuration\n"); + mutex_unlock(&chip->state_lock); + return -EBUSY; + } + ret = enable_eud(chip); if (ret) { dev_err(chip->dev, "failed to enable eud\n"); + mutex_unlock(&chip->state_lock); return ret; } } else { ret = disable_eud(chip); if (ret) { dev_err(chip->dev, "failed to disable eud\n"); + mutex_unlock(&chip->state_lock); return ret; } } chip->enabled = enable; + mutex_unlock(&chip->state_lock); + return count; } @@ -324,18 +361,56 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) static int eud_role_switch_set(struct usb_role_switch *sw, enum usb_role role) { struct eud_path *path = usb_role_switch_get_drvdata(sw); + struct eud_chip *chip = path->chip; int ret; + mutex_lock(&chip->state_lock); + + /* + * EUD must be disabled when USB operates in host mode. EUD functions by + * presenting itself as a USB device to the host PC for debugging, making + * it incompatible in host mode configuration. + * + * chip->enabled preserves user's sysfs configuration and is not modified + * during host mode transitions to maintain user intent. + */ + + /* Only act if EUD is enabled and this is the active path */ + if (chip->enabled && path->num == chip->port_idx) { + if (role == USB_ROLE_HOST && !chip->eud_disabled_for_host) { + ret = disable_eud(chip); + if (ret) { + dev_err(chip->dev, "Failed to disable EUD for host mode: %d\n", + ret); + mutex_unlock(&chip->state_lock); + return ret; + } + chip->eud_disabled_for_host = true; + } else if (role != USB_ROLE_HOST && chip->eud_disabled_for_host) { + ret = enable_eud(chip); + if (ret) { + dev_err(chip->dev, "Failed to re-enable EUD after host mode: %d\n", + ret); + mutex_unlock(&chip->state_lock); + return ret; + } + chip->eud_disabled_for_host = false; + } + } + /* Forward the role request to the USB controller */ ret = usb_role_switch_set_role(path->controller_sw, role); if (ret) { dev_err(path->chip->dev, "Failed to set role %s for port %u: %d\n", usb_role_string(role), path->num, ret); + mutex_unlock(&chip->state_lock); return ret; } path->curr_role = role; + mutex_unlock(&chip->state_lock); + return 0; } @@ -433,6 +508,8 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; + mutex_init(&chip->state_lock); + ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); if (ret) return ret; From f0f7bd212fcb7c8cc2a09b850963fef6535b890f Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:28 -0800 Subject: [PATCH 0011/1133] FROMLIST: usb: misc: qcom_eud: fix virtual attach/detach event handling EUD provides virtual USB attach/detach events to simulate cable plug/unplug while maintaining the physical debug connection. However, the current implementation incorrectly sets the USB role to HOST on virtual detach, which doesn't represent the disconnected state. Fix the virtual detach handling by setting the USB role to NONE instead of HOST, correctly representing the disconnected state. Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio https://lore.kernel.org/linux-usb/20260126233830.2193816-8-elson.serrao@oss.qualcomm.com/ --- drivers/usb/misc/qcom_eud.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 3f1cc7ea2a6ae..60f566427abe2 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -343,10 +343,26 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) if (!path || !path->controller_sw) goto clear_irq; + /* + * EUD virtual attach/detach event handling for low power debugging: + * + * When EUD is enabled in debug mode, the device remains physically + * connected to the PC throughout the debug session, keeping the USB + * controller active. This prevents testing of low power scenarios that + * require USB disconnection. + * + * EUD solves this by providing virtual USB attach/detach events while + * maintaining the physical connection. These events are triggered from + * the Host PC via the enumerated EUD control interface and delivered + * to the EUD driver as interrupts. + * + * These notifications are forwarded to the USB controller through role + * switch framework. + */ if (chip->usb_attached) ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_HOST); + ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_NONE); if (ret) dev_err(chip->dev, "failed to set role switch\n"); From 03770eb8f8b05756e0689a42a857ead1b3887aa6 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:29 -0800 Subject: [PATCH 0012/1133] FROMLIST: arm64: dts: qcom: kodiak: Align EUD node with binding The EUD node does not match the current binding and maps USB endpoints to the secondary controller. This SoC supports EUD only on the primary High-Speed USB path. The binding also requires a per-path PHY reference. Model the primary UTMI path as a child node with the required PHY and an empty ports graph. Leave endpoint mapping to board DTS files, and remove the secondary mapping and associated ports so the description conforms to the binding. Signed-off-by: Elson Serrao iLink: https://lore.kernel.org/linux-usb/20260126233830.2193816-9-elson.serrao@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 33 +++++++++++++++++----------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index fa540d8c2615d..1a616c0375d31 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -4404,12 +4404,6 @@ phy-names = "usb2-phy"; maximum-speed = "high-speed"; usb-role-switch; - - port { - usb2_role_switch: endpoint { - remote-endpoint = <&eud_ep>; - }; - }; }; qspi: spi@88dc000 { @@ -4736,16 +4730,29 @@ <0 0x88e2000 0 0x1000>; interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; - ports { - #address-cells = <1>; - #size-cells = <0>; + eud0: eud-path@0 { + reg = <0>; + phys = <&usb_1_hsphy>; - port@0 { - reg = <0>; - eud_ep: endpoint { - remote-endpoint = <&usb2_role_switch>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + eud_usb0: endpoint { + }; + }; + + port@1 { + reg = <1>; + eud_con0: endpoint { + }; }; }; }; From 44f0bf8b35553fd3ea2f9cb320d085ddf4cba698 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Mon, 26 Jan 2026 15:38:30 -0800 Subject: [PATCH 0013/1133] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality On this board, EUD resides on the primary High-Speed USB data path between the connector and the DWC3 controller. Update the device tree connections to correctly map the connector and controller endpoints, and describe role-switch capability on the EUD primary path. Signed-off-by: Elson Serrao Link: https://lore.kernel.org/linux-usb/20260126233830.2193816-10-elson.serrao@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 37a3b51323ce5..b320d000508a3 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -211,7 +211,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con0>; }; }; @@ -1403,13 +1403,29 @@ }; &usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; + remote-endpoint = <&eud_usb0>; }; &usb_1_dwc3_ss { remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>; }; +&eud_con0 { + remote-endpoint = <&pmic_glink_hs_in>; +}; + +&eud_usb0 { + remote-endpoint = <&usb_1_dwc3_hs>; +}; + +&eud { + status = "okay"; +}; + +&eud0 { + usb-role-switch; +}; + &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; From 53091ccc113ade402faa4502afd3ee0b2ad24618 Mon Sep 17 00:00:00 2001 From: Jan Remmet Date: Fri, 23 Jan 2026 15:52:37 +0100 Subject: [PATCH 0014/1133] FROMLIST: usb: typec: hd3ss3220: Enable VBUS based on role state For systems where the ID pin isn't available as gpio use the ATTACHED_STATE register instead to control vbus. >From the datasheet: "This is an additional method to communicate attach other than the ID pin. These bits can be read by the application to determine what was attached." Use this method if id-gpios property is not set, but the connector node has vbus-supply defined. Check regulator state as peripheral and detach can disable vbus. Signed-off-by: Jan Remmet From 0a6686f54058bec2c89ea8047adbd5d5b3af5cb6 Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Mon, 16 Feb 2026 01:35:33 +0530 Subject: [PATCH 0015/1133] FROMLIST: usb: typec: hd3ss3220: Add wakeup support from system suspend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The HD3SS3220's interrupt is disabled during system suspend, so a USB‑C cable connect/attach event cannot wake the system. This prevents resume from low‑power modes when the port controller is expected to act as a wakeup source. Add wakeup support by: - Initialize the device as wakeup‑capable. - Enable the HD3SS3220 IRQ as a wakeup interrupt. - Add suspend/resume callbacks to enable or disable the IRQ for wakeup depending on the device's wakeup configuration. With this, USB‑C cable insertion correctly wakes the system from suspend. Link: https://lore.kernel.org/all/20260215183325.3836178-2-swati.agarwal@oss.qualcomm.com/ Signed-off-by: Swati Agarwal --- drivers/usb/typec/hd3ss3220.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/usb/typec/hd3ss3220.c b/drivers/usb/typec/hd3ss3220.c index 3e39b800e6b5f..b56df9349f89b 100644 --- a/drivers/usb/typec/hd3ss3220.c +++ b/drivers/usb/typec/hd3ss3220.c @@ -501,6 +501,11 @@ static int hd3ss3220_probe(struct i2c_client *client) if (hd3ss3220->poll) schedule_delayed_work(&hd3ss3220->output_poll_work, HZ); + if (client->irq && device_property_read_bool(hd3ss3220->dev, "wakeup-source")) { + device_init_wakeup(&client->dev, true); + enable_irq_wake(client->irq); + } + dev_info(&client->dev, "probed revision=0x%x\n", ret); return 0; @@ -525,6 +530,35 @@ static void hd3ss3220_remove(struct i2c_client *client) usb_role_switch_put(hd3ss3220->role_sw); } +static int __maybe_unused hd3ss3220_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(client->irq); + else + disable_irq(client->irq); + + return 0; +} + +static int __maybe_unused hd3ss3220_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(client->irq); + else + enable_irq(client->irq); + + return 0; +} + +static const struct dev_pm_ops hd3ss3220_pm_ops = { + .suspend = hd3ss3220_suspend, + .resume = hd3ss3220_resume, +}; + static const struct of_device_id dev_ids[] = { { .compatible = "ti,hd3ss3220"}, {} @@ -535,6 +569,7 @@ static struct i2c_driver hd3ss3220_driver = { .driver = { .name = "hd3ss3220", .of_match_table = dev_ids, + .pm = &hd3ss3220_pm_ops, }, .probe = hd3ss3220_probe, .remove = hd3ss3220_remove, From c5610d5cb36b9ed719a84233f06ec44ba914a621 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 20 Feb 2026 16:01:25 +0530 Subject: [PATCH 0016/1133] Revert "FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality" This reverts commit e65028c6aae9f531066bdfc487454ed45e0834a9. Issue is observed with this commit e65028c6aae9f531066bdfc487454ed45e0834a9 leading to crash, with following call stack [ 19.706310][ T73] Call trace: [ 19.706312][ T73] usb_role_switch_unregister+0x28/0x70 (P) [ 19.706319][ T73] eud_role_switch_release+0x30/0x78 [qcom_eud] [ 19.884972][ T73] devm_action_release+0x1c/0x30 [ 19.884981][ T73] release_nodes+0x70/0x120 [ 19.884987][ T73] devres_release_all+0x98/0xf0 [ 19.884995][ T73] device_unbind_cleanup+0x20/0x98 [ 19.885000][ T73] really_probe+0x184/0x3f0 [ 19.885005][ T73] __driver_probe_device+0x88/0x190 [ 19.885010][ T73] driver_probe_device+0x44/0x120 [ 19.885015][ T73] __device_attach_driver+0xc4/0x178 [ 19.885020][ T73] bus_for_each_drv+0x90/0xf8 [ 19.885027][ T73] __device_attach+0xa8/0x1d8 [ 19.885032][ T73] device_initial_probe+0x58/0x68 [ 19.885037][ T73] bus_probe_device+0x40/0xb8 [ 19.885041][ T73] deferred_probe_work_func+0xbc/0x128 [ 19.885046][ T73] process_one_work+0x180/0x450 [ 19.885055][ T73] worker_thread+0x26c/0x388 [ 19.885062][ T73] kthread+0x120/0x140 [ 19.885068][ T73] ret_from_fork+0x10/0x20 [ 19.885079][ T73] Code: f9000bf3 aa0003f3 b140041f 54000168 (390c901f) [ 19.885083][ T73] ---[ end trace 0000000000000000 ]--- [ 19.885088][ T73] Kernel panic - not syncing: Oops: Fatal exception [ 19.885091][ T73] SMP: stopping secondary CPUs Revert commit for now. Signed-off-by: Salendarsingh Gaud --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index b320d000508a3..37a3b51323ce5 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -211,7 +211,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&eud_con0>; + remote-endpoint = <&usb_1_dwc3_hs>; }; }; @@ -1403,29 +1403,13 @@ }; &usb_1_dwc3_hs { - remote-endpoint = <&eud_usb0>; + remote-endpoint = <&pmic_glink_hs_in>; }; &usb_1_dwc3_ss { remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>; }; -&eud_con0 { - remote-endpoint = <&pmic_glink_hs_in>; -}; - -&eud_usb0 { - remote-endpoint = <&usb_1_dwc3_hs>; -}; - -&eud { - status = "okay"; -}; - -&eud0 { - usb-role-switch; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; From dc37b2a5bbba86d9a7578364ba97ee1a2351987c Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 20 Feb 2026 16:02:45 +0530 Subject: [PATCH 0017/1133] Revert "FROMLIST: arm64: dts: qcom: kodiak: Align EUD node with binding" This reverts commit 09ed0b6ddc99b87f0fb3141a9c4d55f015329c5c. Issue is observed with this commit 09ed0b6ddc99b87f0fb3141a9c4d55f015329c5c leading to crash, with following call stack [ 19.706310][ T73] Call trace: [ 19.706312][ T73] usb_role_switch_unregister+0x28/0x70 (P) [ 19.706319][ T73] eud_role_switch_release+0x30/0x78 [qcom_eud] [ 19.884972][ T73] devm_action_release+0x1c/0x30 [ 19.884981][ T73] release_nodes+0x70/0x120 [ 19.884987][ T73] devres_release_all+0x98/0xf0 [ 19.884995][ T73] device_unbind_cleanup+0x20/0x98 [ 19.885000][ T73] really_probe+0x184/0x3f0 [ 19.885005][ T73] __driver_probe_device+0x88/0x190 [ 19.885010][ T73] driver_probe_device+0x44/0x120 [ 19.885015][ T73] __device_attach_driver+0xc4/0x178 [ 19.885020][ T73] bus_for_each_drv+0x90/0xf8 [ 19.885027][ T73] __device_attach+0xa8/0x1d8 [ 19.885032][ T73] device_initial_probe+0x58/0x68 [ 19.885037][ T73] bus_probe_device+0x40/0xb8 [ 19.885041][ T73] deferred_probe_work_func+0xbc/0x128 [ 19.885046][ T73] process_one_work+0x180/0x450 [ 19.885055][ T73] worker_thread+0x26c/0x388 [ 19.885062][ T73] kthread+0x120/0x140 [ 19.885068][ T73] ret_from_fork+0x10/0x20 [ 19.885079][ T73] Code: f9000bf3 aa0003f3 b140041f 54000168 (390c901f) [ 19.885083][ T73] ---[ end trace 0000000000000000 ]--- [ 19.885088][ T73] Kernel panic - not syncing: Oops: Fatal exception [ 19.885091][ T73] SMP: stopping secondary CPUs Revert commit for now. Signed-off-by: Salendarsingh Gaud --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 33 +++++++++++----------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 1a616c0375d31..fa540d8c2615d 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -4404,6 +4404,12 @@ phy-names = "usb2-phy"; maximum-speed = "high-speed"; usb-role-switch; + + port { + usb2_role_switch: endpoint { + remote-endpoint = <&eud_ep>; + }; + }; }; qspi: spi@88dc000 { @@ -4730,29 +4736,16 @@ <0 0x88e2000 0 0x1000>; interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - eud0: eud-path@0 { - reg = <0>; - phys = <&usb_1_hsphy>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - eud_usb0: endpoint { - }; - }; + ports { + #address-cells = <1>; + #size-cells = <0>; - port@1 { - reg = <1>; - eud_con0: endpoint { - }; + port@0 { + reg = <0>; + eud_ep: endpoint { + remote-endpoint = <&usb2_role_switch>; }; }; }; From 12418f7456826085ca85faa83b1fd57454a02c7a Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:19:50 -0700 Subject: [PATCH 0018/1133] Revert "FROMLIST: usb: misc: qcom_eud: fix virtual attach/detach event handling" This reverts commit 7104631aca14a5f01ee8f33ebbfda4c2e4047d28. Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 60f566427abe2..3f1cc7ea2a6ae 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -343,26 +343,10 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) if (!path || !path->controller_sw) goto clear_irq; - /* - * EUD virtual attach/detach event handling for low power debugging: - * - * When EUD is enabled in debug mode, the device remains physically - * connected to the PC throughout the debug session, keeping the USB - * controller active. This prevents testing of low power scenarios that - * require USB disconnection. - * - * EUD solves this by providing virtual USB attach/detach events while - * maintaining the physical connection. These events are triggered from - * the Host PC via the enumerated EUD control interface and delivered - * to the EUD driver as interrupts. - * - * These notifications are forwarded to the USB controller through role - * switch framework. - */ if (chip->usb_attached) ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_NONE); + ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_HOST); if (ret) dev_err(chip->dev, "failed to set role switch\n"); From 986d37ad6a0e94046677245451cff48d6d1fdfa3 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:20:22 -0700 Subject: [PATCH 0019/1133] Revert "FROMLIST: usb: misc: qcom_eud: add host mode coordination" This reverts commit 583d6fc0f35f15b14ebed9dd244a7ba4bf845496. Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 79 +------------------------------------ 1 file changed, 1 insertion(+), 78 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 3f1cc7ea2a6ae..0ea6491f963ce 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -49,15 +49,12 @@ struct eud_chip { struct device *dev; void __iomem *base; struct eud_path *paths[EUD_MAX_PORTS]; - /* serializes EUD control operations */ - struct mutex state_lock; phys_addr_t mode_mgr; unsigned int int_status; int irq; bool enabled; bool usb_attached; bool phy_enabled; - bool eud_disabled_for_host; u8 port_idx; }; @@ -165,66 +162,32 @@ static ssize_t enable_store(struct device *dev, const char *buf, size_t count) { struct eud_chip *chip = dev_get_drvdata(dev); - struct eud_path *path; bool enable; int ret; if (kstrtobool(buf, &enable)) return -EINVAL; - mutex_lock(&chip->state_lock); - /* Skip operation if already in desired state */ - if (chip->enabled == enable) { - mutex_unlock(&chip->state_lock); + if (chip->enabled == enable) return count; - } - - /* - * Handle double-disable scenario: User is disabling EUD that was already - * disabled due to host mode. Since the hardware is already disabled, we - * only need to clear the host-disabled flag to prevent unwanted re-enabling - * when exiting host mode. This respects the user's explicit disable request. - */ - if (!enable && chip->eud_disabled_for_host) { - chip->eud_disabled_for_host = false; - chip->enabled = false; - mutex_unlock(&chip->state_lock); - return count; - } if (enable) { - /* - * EUD functions by presenting itself as a USB device to the host PC for - * debugging, making it incompatible in USB host mode configuration. - * Prevent enabling EUD in this configuration to avoid hardware conflicts. - */ - path = chip->paths[chip->port_idx]; - if (path && path->curr_role == USB_ROLE_HOST) { - dev_err(chip->dev, "EUD not usable in host mode configuration\n"); - mutex_unlock(&chip->state_lock); - return -EBUSY; - } - ret = enable_eud(chip); if (ret) { dev_err(chip->dev, "failed to enable eud\n"); - mutex_unlock(&chip->state_lock); return ret; } } else { ret = disable_eud(chip); if (ret) { dev_err(chip->dev, "failed to disable eud\n"); - mutex_unlock(&chip->state_lock); return ret; } } chip->enabled = enable; - mutex_unlock(&chip->state_lock); - return count; } @@ -361,56 +324,18 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) static int eud_role_switch_set(struct usb_role_switch *sw, enum usb_role role) { struct eud_path *path = usb_role_switch_get_drvdata(sw); - struct eud_chip *chip = path->chip; int ret; - mutex_lock(&chip->state_lock); - - /* - * EUD must be disabled when USB operates in host mode. EUD functions by - * presenting itself as a USB device to the host PC for debugging, making - * it incompatible in host mode configuration. - * - * chip->enabled preserves user's sysfs configuration and is not modified - * during host mode transitions to maintain user intent. - */ - - /* Only act if EUD is enabled and this is the active path */ - if (chip->enabled && path->num == chip->port_idx) { - if (role == USB_ROLE_HOST && !chip->eud_disabled_for_host) { - ret = disable_eud(chip); - if (ret) { - dev_err(chip->dev, "Failed to disable EUD for host mode: %d\n", - ret); - mutex_unlock(&chip->state_lock); - return ret; - } - chip->eud_disabled_for_host = true; - } else if (role != USB_ROLE_HOST && chip->eud_disabled_for_host) { - ret = enable_eud(chip); - if (ret) { - dev_err(chip->dev, "Failed to re-enable EUD after host mode: %d\n", - ret); - mutex_unlock(&chip->state_lock); - return ret; - } - chip->eud_disabled_for_host = false; - } - } - /* Forward the role request to the USB controller */ ret = usb_role_switch_set_role(path->controller_sw, role); if (ret) { dev_err(path->chip->dev, "Failed to set role %s for port %u: %d\n", usb_role_string(role), path->num, ret); - mutex_unlock(&chip->state_lock); return ret; } path->curr_role = role; - mutex_unlock(&chip->state_lock); - return 0; } @@ -508,8 +433,6 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; - mutex_init(&chip->state_lock); - ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); if (ret) return ret; From e5f26633bb188b0172aa81b99a315e1b98eb8bee Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:20:39 -0700 Subject: [PATCH 0020/1133] Revert "FROMLIST: usb: misc: qcom_eud: improve enable_store API" This reverts commit eb5da51b8cba5fc4ed3bd699d2cce066020e3415. Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 0ea6491f963ce..a58022f50484f 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -168,27 +168,18 @@ static ssize_t enable_store(struct device *dev, if (kstrtobool(buf, &enable)) return -EINVAL; - /* Skip operation if already in desired state */ - if (chip->enabled == enable) - return count; - if (enable) { ret = enable_eud(chip); - if (ret) { - dev_err(chip->dev, "failed to enable eud\n"); - return ret; - } + if (!ret) + chip->enabled = enable; + else + disable_eud(chip); + } else { ret = disable_eud(chip); - if (ret) { - dev_err(chip->dev, "failed to disable eud\n"); - return ret; - } } - chip->enabled = enable; - - return count; + return ret < 0 ? ret : count; } static DEVICE_ATTR_RW(enable); From 7b1b29fa7cac6cda53361c72d36051ce4056a9a3 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:21:03 -0700 Subject: [PATCH 0021/1133] Revert "FROMLIST: usb: misc: qcom_eud: add per-path role switch support" This reverts commit e7e656c813d8d651e26704a10f9c56a34a2f7e13. Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 80 +++++-------------------------------- 1 file changed, 10 insertions(+), 70 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index a58022f50484f..5cebb64f4a672 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -38,15 +38,12 @@ struct eud_path { struct eud_chip *chip; struct phy *phy; - struct usb_role_switch *controller_sw; - struct usb_role_switch *eud_sw; - enum usb_role curr_role; - char name[16]; u8 num; }; struct eud_chip { struct device *dev; + struct usb_role_switch *role_sw; void __iomem *base; struct eud_path *paths[EUD_MAX_PORTS]; phys_addr_t mode_mgr; @@ -132,7 +129,7 @@ static int enable_eud(struct eud_chip *priv) writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, priv->base + EUD_REG_INT1_EN_MASK); - return 0; + return usb_role_switch_set_role(priv->role_sw, USB_ROLE_DEVICE); } static int disable_eud(struct eud_chip *priv) @@ -290,21 +287,15 @@ static irqreturn_t handle_eud_irq(int irq, void *data) static irqreturn_t handle_eud_irq_thread(int irq, void *data) { struct eud_chip *chip = data; - struct eud_path *path; int ret; - path = chip->paths[chip->port_idx]; - if (!path || !path->controller_sw) - goto clear_irq; - if (chip->usb_attached) - ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_DEVICE); + ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_HOST); + ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_HOST); if (ret) dev_err(chip->dev, "failed to set role switch\n"); -clear_irq: /* set and clear vbus_int_clr[0] to clear interrupt */ writel(BIT(0), chip->base + EUD_REG_VBUS_INT_CLR); writel(0, chip->base + EUD_REG_VBUS_INT_CLR); @@ -312,45 +303,15 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) return IRQ_HANDLED; } -static int eud_role_switch_set(struct usb_role_switch *sw, enum usb_role role) -{ - struct eud_path *path = usb_role_switch_get_drvdata(sw); - int ret; - - /* Forward the role request to the USB controller */ - ret = usb_role_switch_set_role(path->controller_sw, role); - if (ret) { - dev_err(path->chip->dev, "Failed to set role %s for port %u: %d\n", - usb_role_string(role), path->num, ret); - return ret; - } - - path->curr_role = role; - - return 0; -} - static void eud_role_switch_release(void *data) { struct eud_chip *chip = data; - int i; - for (i = 0; i < EUD_MAX_PORTS; i++) { - struct eud_path *path = chip->paths[i]; - - if (!path) - continue; - - if (path->eud_sw) - usb_role_switch_unregister(path->eud_sw); - if (path->controller_sw) - usb_role_switch_put(path->controller_sw); - } + usb_role_switch_put(chip->role_sw); } static int eud_init_path(struct eud_chip *chip, struct device_node *np) { - struct usb_role_switch_desc role_sw_desc = {}; struct eud_path *path; u32 path_num; int ret; @@ -381,32 +342,6 @@ static int eud_init_path(struct eud_chip *chip, struct device_node *np) chip->paths[path_num] = path; - path->curr_role = USB_ROLE_NONE; - - if (!of_property_read_bool(np, "usb-role-switch")) - return 0; - - /* Fetch the USB controller's role switch */ - path->controller_sw = fwnode_usb_role_switch_get(of_fwnode_handle(np)); - if (IS_ERR(path->controller_sw)) - return dev_err_probe(chip->dev, PTR_ERR(path->controller_sw), - "Failed to get controller role switch for path %d\n", - path_num); - - /* Create a role switch */ - role_sw_desc.fwnode = of_fwnode_handle(np); - role_sw_desc.set = eud_role_switch_set; - role_sw_desc.driver_data = path; - snprintf(path->name, sizeof(path->name), "eud-path%u", path_num); - role_sw_desc.name = path->name; - - path->eud_sw = usb_role_switch_register(chip->dev, &role_sw_desc); - if (IS_ERR(path->eud_sw)) { - dev_err(chip->dev, "Failed to register EUD role switch for path %d: %ld\n", - path_num, PTR_ERR(path->eud_sw)); - return PTR_ERR(path->eud_sw); - } - return 0; } @@ -424,6 +359,11 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; + chip->role_sw = usb_role_switch_get(&pdev->dev); + if (IS_ERR(chip->role_sw)) + return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw), + "failed to get role switch\n"); + ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); if (ret) return ret; From 1483562653b069cb0b04eae1ad73a30c755d6eca Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:21:33 -0700 Subject: [PATCH 0022/1133] Revert "FROMLIST: usb: misc: qcom_eud: add per-path High-Speed PHY control" This reverts commit e2541a8409a99af58825af0a54178d0b26677f5b. Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 130 +----------------------------------- 1 file changed, 1 insertion(+), 129 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 5cebb64f4a672..1a136f8f1ae52 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -35,95 +34,25 @@ #define EUD_INT_SAFE_MODE BIT(4) #define EUD_INT_ALL (EUD_INT_VBUS | EUD_INT_SAFE_MODE) -struct eud_path { - struct eud_chip *chip; - struct phy *phy; - u8 num; -}; - struct eud_chip { struct device *dev; struct usb_role_switch *role_sw; void __iomem *base; - struct eud_path *paths[EUD_MAX_PORTS]; phys_addr_t mode_mgr; unsigned int int_status; int irq; bool enabled; bool usb_attached; - bool phy_enabled; u8 port_idx; }; -static int eud_phy_enable(struct eud_chip *chip) -{ - struct eud_path *path; - struct phy *phy; - int ret; - - if (chip->phy_enabled) - return 0; - - path = chip->paths[chip->port_idx]; - if (!path || !path->phy) { - dev_err(chip->dev, "No PHY configured for port %u\n", chip->port_idx); - return -ENODEV; - } - - phy = path->phy; - - ret = phy_init(phy); - if (ret) { - dev_err(chip->dev, "Failed to initialize USB2 PHY for port %u: %d\n", - chip->port_idx, ret); - return ret; - } - - ret = phy_power_on(phy); - if (ret) { - dev_err(chip->dev, "Failed to power on USB2 PHY for port %u: %d\n", - chip->port_idx, ret); - phy_exit(phy); - return ret; - } - - chip->phy_enabled = true; - - return 0; -} - -static void eud_phy_disable(struct eud_chip *chip) -{ - struct eud_path *path; - struct phy *phy; - - if (!chip->phy_enabled) - return; - - path = chip->paths[chip->port_idx]; - if (!path || !path->phy) - return; - - phy = path->phy; - - phy_power_off(phy); - phy_exit(phy); - chip->phy_enabled = false; -} - static int enable_eud(struct eud_chip *priv) { int ret; - ret = eud_phy_enable(priv); - if (ret) - return ret; - ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); - if (ret) { - eud_phy_disable(priv); + if (ret) return ret; - } writel(EUD_ENABLE, priv->base + EUD_REG_CSR_EUD_EN); writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, @@ -141,8 +70,6 @@ static int disable_eud(struct eud_chip *priv) return ret; writel(0, priv->base + EUD_REG_CSR_EUD_EN); - eud_phy_disable(priv); - return 0; } @@ -205,12 +132,6 @@ static ssize_t port_store(struct device *dev, if (port >= EUD_MAX_PORTS) return -EINVAL; - /* Check if the corresponding path is available */ - if (!chip->paths[port]) { - dev_err(chip->dev, "EUD not supported on selected port\n"); - return -EOPNOTSUPP; - } - /* Port selection must be done before enabling EUD */ if (chip->enabled) { dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); @@ -310,45 +231,8 @@ static void eud_role_switch_release(void *data) usb_role_switch_put(chip->role_sw); } -static int eud_init_path(struct eud_chip *chip, struct device_node *np) -{ - struct eud_path *path; - u32 path_num; - int ret; - - ret = of_property_read_u32(np, "reg", &path_num); - if (ret) { - dev_err(chip->dev, "Missing 'reg' property in path node\n"); - return ret; - } - - if (path_num >= EUD_MAX_PORTS) { - dev_err(chip->dev, "Invalid path number: %u (max %d)\n", - path_num, EUD_MAX_PORTS - 1); - return -EINVAL; - } - - path = devm_kzalloc(chip->dev, sizeof(*path), GFP_KERNEL); - if (!path) - return -ENOMEM; - - path->chip = chip; - path->num = path_num; - - path->phy = devm_of_phy_get(chip->dev, np, NULL); - if (IS_ERR(path->phy)) - return dev_err_probe(chip->dev, PTR_ERR(path->phy), - "Failed to get PHY for path %d\n", path_num); - - chip->paths[path_num] = path; - - return 0; -} - static int eud_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; - struct device_node *child; struct eud_chip *chip; struct resource *res; int ret; @@ -368,18 +252,6 @@ static int eud_probe(struct platform_device *pdev) if (ret) return ret; - for_each_child_of_node(np, child) { - ret = eud_init_path(chip, child); - if (ret) { - of_node_put(child); - return ret; - } - } - - /* Primary path is mandatory. Secondary is optional */ - if (!chip->paths[0]) - return -ENODEV; - chip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chip->base)) return PTR_ERR(chip->base); From c9707f04c077eb69816b211cfbfa343dcb211a1b Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:21:52 -0700 Subject: [PATCH 0023/1133] Revert "FROMLIST: usb: misc: qcom_eud: add sysfs attribute for port selection" This reverts commit c042ed7b42aff071249d6a1b91cedb7170e2d2d4. Signed-off-by: Elson Serrao --- Documentation/ABI/testing/sysfs-driver-eud | 16 -------- drivers/usb/misc/qcom_eud.c | 43 ---------------------- 2 files changed, 59 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-eud b/Documentation/ABI/testing/sysfs-driver-eud index 67223f73ee606..2bab0db2d2f0f 100644 --- a/Documentation/ABI/testing/sysfs-driver-eud +++ b/Documentation/ABI/testing/sysfs-driver-eud @@ -7,19 +7,3 @@ Description: EUD based on a 1 or a 0 value. By enabling EUD, the user is able to activate the mini-usb hub of EUD for debug and trace capabilities. - -What: /sys/bus/platform/drivers/qcom_eud/.../port -Date: January 2026 -Contact: Elson Serrao -Description: - Selects which USB port the Embedded USB Debugger (EUD) - is mapped to on platforms providing multiple High-Speed - USB ports. - - Valid values: - 0 - Primary USB port - 1 - Secondary USB port - - The attribute is writable only while EUD is disabled. - Reading the attribute returns the currently selected - USB port number. diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 1a136f8f1ae52..926419ca560fc 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -23,11 +23,8 @@ #define EUD_REG_VBUS_INT_CLR 0x0080 #define EUD_REG_CSR_EUD_EN 0x1014 #define EUD_REG_SW_ATTACH_DET 0x1018 -#define EUD_REG_PORT_SEL 0x1028 #define EUD_REG_EUD_EN2 0x0000 -#define EUD_MAX_PORTS 2 - #define EUD_ENABLE BIT(0) #define EUD_INT_PET_EUD BIT(0) #define EUD_INT_VBUS BIT(2) @@ -43,7 +40,6 @@ struct eud_chip { int irq; bool enabled; bool usb_attached; - u8 port_idx; }; static int enable_eud(struct eud_chip *priv) @@ -108,47 +104,8 @@ static ssize_t enable_store(struct device *dev, static DEVICE_ATTR_RW(enable); -static ssize_t port_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct eud_chip *chip = dev_get_drvdata(dev); - - return sysfs_emit(buf, "%u\n", chip->port_idx); -} - -static ssize_t port_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct eud_chip *chip = dev_get_drvdata(dev); - u8 port; - int ret; - - ret = kstrtou8(buf, 0, &port); - if (ret) - return ret; - - /* Only port 0 and port 1 are valid */ - if (port >= EUD_MAX_PORTS) - return -EINVAL; - - /* Port selection must be done before enabling EUD */ - if (chip->enabled) { - dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); - return -EBUSY; - } - - writel(port, chip->base + EUD_REG_PORT_SEL); - chip->port_idx = port; - - return count; -} - -static DEVICE_ATTR_RW(port); - static struct attribute *eud_attrs[] = { &dev_attr_enable.attr, - &dev_attr_port.attr, NULL, }; ATTRIBUTE_GROUPS(eud); From 51324352f7a58b743142989e5162581ec7d08500 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:22:10 -0700 Subject: [PATCH 0024/1133] Revert "FROMLIST: dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware" This reverts commit cfe135bf3401dee9bbb5c726594894cc453d28ea. Signed-off-by: Elson Serrao --- .../bindings/soc/qcom/qcom,eud.yaml | 100 +++++------------- 1 file changed, 26 insertions(+), 74 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml index 0507252dbf27e..84218636c0d8d 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml @@ -10,11 +10,8 @@ maintainers: - Souradeep Chowdhury description: - This binding describes the Qualcomm Embedded USB Debugger (EUD), an on-chip - mini USB hub that enables USB-based debug capabilities. The EUD block is - positioned between the High-Speed USB PHY and the USB controller, where it - intercepts the UTMI interface to support debug and bypass modes. EUD can be - supported on up to two High-Speed USB ports. + This binding is used to describe the Qualcomm Embedded USB Debugger, which is + mini USB-hub implemented on chip to support USB-based debug capabilities. properties: compatible: @@ -32,62 +29,26 @@ properties: description: EUD interrupt maxItems: 1 - '#address-cells': - const: 1 - - '#size-cells': - const: 0 - -patternProperties: - "^eud-path@[0-1]$": - type: object + ports: + $ref: /schemas/graph.yaml#/properties/ports description: - Represents one High-Speed UTMI path that EUD intercepts. This node models - the physical data path intercepted by EUD and provides graph endpoints to - link the USB controller and the external connector associated with this path. + These ports is to be attached to the endpoint of the DWC3 controller node + and type C connector node. The controller has the "usb-role-switch" + property. properties: - reg: - maxItems: 1 - description: Path number - - phys: - maxItems: 1 - description: High-Speed USB PHY associated with this data path. - - usb-role-switch: - type: boolean - description: - Set this property if the USB port on this path is role switch capable. - In device role, debug mode inserts the EUD hub into the UTMI path. In - host role, the EUD hub is bypassed and UTMI traffic flows directly - between the PHY and the USB controller. - - ports: - $ref: /schemas/graph.yaml#/properties/ports - description: - These ports are to be attached to the endpoint of the USB controller node - and USB connector node. - - properties: - port@0: - $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the USB controller. + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the DWC3 controller. - port@1: - $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the USB connector. - - required: - - reg - - phys - - ports - - additionalProperties: false + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the type C connector. required: - compatible - reg + - ports additionalProperties: false @@ -97,30 +58,21 @@ examples: compatible = "qcom,sc7280-eud", "qcom,eud"; reg = <0x88e0000 0x2000>, <0x88e2000 0x1000>; - #address-cells = <1>; - #size-cells = <0>; - - eud-path@0 { - reg = <0>; - phys = <&usb_1_hsphy>; - usb-role-switch; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - eud_ep: endpoint { - remote-endpoint = <&usb2_role_switch>; - }; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + eud_ep: endpoint { + remote-endpoint = <&usb2_role_switch>; }; + }; - port@1 { - reg = <1>; - eud_con: endpoint { - remote-endpoint = <&con_eud>; - }; + port@1 { + reg = <1>; + eud_con: endpoint { + remote-endpoint = <&con_eud>; }; }; }; From c0baeced125e6a1936c46520969bb170ab74383b Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:22:28 -0700 Subject: [PATCH 0025/1133] =?UTF-8?q?FROMLIST:=20dt-bindings:=20connector:?= =?UTF-8?q?=20Add=20role=E2=80=91switch=20provider=20phandle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an optional consumer→provider phandle on USB connectors to reference the USB role-switch provider when no direct graph link exists. The DRD controller remains the provider via its 'usb-role-switch' property. Link: https://lore.kernel.org/all/20260223191042.825136-2-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- .../devicetree/bindings/connector/usb-connector.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/connector/usb-connector.yaml b/Documentation/devicetree/bindings/connector/usb-connector.yaml index 8ca0292490a2c..ecad7781644ce 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.yaml +++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml @@ -95,6 +95,14 @@ properties: - device - dual + usb-role-switch: + $ref: /schemas/types.yaml#/definitions/phandle + description: + A phandle to the USB role-switch provider. The provider is typically + a dual-role (DRD) USB controller node that declares the boolean + 'usb-role-switch' property. Use this when the connector is not + directly linked to the provider in the OF graph. + typec-power-opmode: description: Determines the power operation mode that the Type C connector will support and will advertise through CC pins when it has no power From 4adc411813aeca96f1b9b94d7c567b8fc64a1165 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:23:13 -0700 Subject: [PATCH 0026/1133] FROMLIST: dt-bindings: soc: qcom: eud: Add support for dual-port configuration EUD hardware supports debugging on up to two USB ports depending on the SoC configuration. Debugging can be selected on either the primary or secondary USB port as controlled by the EUD_PORT_SELECT register. Extend the binding to support dual-port configurations by adding port@2 and port@3 for secondary USB controller and Type-C connector connections. Link: https://lore.kernel.org/all/20260309203337.803986-2-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- .../bindings/soc/qcom/qcom,eud.yaml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml index 84218636c0d8d..12560342f37fb 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml @@ -32,18 +32,27 @@ properties: ports: $ref: /schemas/graph.yaml#/properties/ports description: - These ports is to be attached to the endpoint of the DWC3 controller node - and type C connector node. The controller has the "usb-role-switch" - property. + These ports attach to endpoints of DWC3 controller nodes and Type-C + connector nodes. The controller has the "usb-role-switch" property. + EUD supports up to 2 USB ports. For single-port configurations, use + port@0 and port@1. For dual-port configurations, use all four ports. properties: port@0: $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the DWC3 controller. + description: This port is to be attached to the primary DWC3 controller. port@1: $ref: /schemas/graph.yaml#/properties/port - description: This port is to be attached to the type C connector. + description: This port is to be attached to the primary Type-C connector. + + port@2: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the secondary DWC3 controller. + + port@3: + $ref: /schemas/graph.yaml#/properties/port + description: This port is to be attached to the secondary Type-C connector. required: - compatible From c2052b2d61bc0f14f4a0431ef477708379891092 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:23:36 -0700 Subject: [PATCH 0027/1133] FROMLIST: usb: misc: qcom_eud: add sysfs attribute for port selection EUD can be mapped to either the primary USB port or the secondary USB port depending on the value of the EUD_PORT_SEL register. Add a 'port' sysfs attribute to allow userspace to select which port EUD should operate on and update the ABI documentation. This is needed for systems with dual USB ports where EUD needs to be accessible on either port depending on the system configuration and use case. Link: https://lore.kernel.org/all/20260309203337.803986-3-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio --- Documentation/ABI/testing/sysfs-driver-eud | 16 +++++++++ drivers/usb/misc/qcom_eud.c | 41 ++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-eud b/Documentation/ABI/testing/sysfs-driver-eud index 2bab0db2d2f0f..67223f73ee606 100644 --- a/Documentation/ABI/testing/sysfs-driver-eud +++ b/Documentation/ABI/testing/sysfs-driver-eud @@ -7,3 +7,19 @@ Description: EUD based on a 1 or a 0 value. By enabling EUD, the user is able to activate the mini-usb hub of EUD for debug and trace capabilities. + +What: /sys/bus/platform/drivers/qcom_eud/.../port +Date: January 2026 +Contact: Elson Serrao +Description: + Selects which USB port the Embedded USB Debugger (EUD) + is mapped to on platforms providing multiple High-Speed + USB ports. + + Valid values: + 0 - Primary USB port + 1 - Secondary USB port + + The attribute is writable only while EUD is disabled. + Reading the attribute returns the currently selected + USB port number. diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 926419ca560fc..35324e1e1ea7e 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -23,8 +23,11 @@ #define EUD_REG_VBUS_INT_CLR 0x0080 #define EUD_REG_CSR_EUD_EN 0x1014 #define EUD_REG_SW_ATTACH_DET 0x1018 +#define EUD_REG_PORT_SEL 0x1028 #define EUD_REG_EUD_EN2 0x0000 +#define EUD_MAX_PORTS 2 + #define EUD_ENABLE BIT(0) #define EUD_INT_PET_EUD BIT(0) #define EUD_INT_VBUS BIT(2) @@ -40,6 +43,7 @@ struct eud_chip { int irq; bool enabled; bool usb_attached; + u8 port_idx; }; static int enable_eud(struct eud_chip *priv) @@ -104,8 +108,45 @@ static ssize_t enable_store(struct device *dev, static DEVICE_ATTR_RW(enable); +static ssize_t port_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct eud_chip *chip = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", chip->port_idx); +} + +static ssize_t port_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct eud_chip *chip = dev_get_drvdata(dev); + u8 port; + int ret; + + ret = kstrtou8(buf, 0, &port); + if (ret) + return ret; + + /* Only port 0 and port 1 are valid */ + if (port >= EUD_MAX_PORTS) + return -EINVAL; + + /* Port selection must be done before enabling EUD */ + if (chip->enabled) { + dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); + return -EBUSY; + } + + writel(port, chip->base + EUD_REG_PORT_SEL); + chip->port_idx = port; + + return count; +} + +static DEVICE_ATTR_RW(port); + static struct attribute *eud_attrs[] = { &dev_attr_enable.attr, + &dev_attr_port.attr, NULL, }; ATTRIBUTE_GROUPS(eud); From 64ef5e3e829b19418767771831982f94f54a807f Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:35 -0700 Subject: [PATCH 0028/1133] FROMLIST: usb: misc: qcom_eud: add per-port High-Speed PHY control EUD hardware can support multiple High-Speed USB ports, each routed through its own PHY. The active port is selected in hardware via the EUD_PORT_SEL register. As a High-Speed hub, EUD requires access to the High-Speed PHY associated with the active port. To support this multi-port capability, the driver must manage PHY resources on a per-port basis, ensuring that the PHY for the currently selected port is properly initialized and powered. This patch adds per-port PHY management to the driver. The driver now powers the appropriate PHY based on the selected and enabled port, ensuring correct operation when EUD is enabled. Historically, EUD appeared to work on single-port systems because the USB controller kept the PHY initialized. However, EUD is designed to operate independently of the USB controller and therefore requires explicit PHY control for proper operation. Link: https://lore.kernel.org/all/20260309203337.803986-4-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- drivers/usb/misc/Kconfig | 1 + drivers/usb/misc/qcom_eud.c | 103 +++++++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 91b62acb537b3..4c0aa718ef267 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -147,6 +147,7 @@ config USB_APPLEDISPLAY config USB_QCOM_EUD tristate "Qualcomm Embedded USB Debugger(EUD) Driver" depends on ARCH_QCOM || COMPILE_TEST + depends on OF select QCOM_SCM select USB_ROLE_SWITCH help diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 35324e1e1ea7e..571b21323797b 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -37,23 +39,75 @@ struct eud_chip { struct device *dev; struct usb_role_switch *role_sw; + struct phy *phy[EUD_MAX_PORTS]; void __iomem *base; phys_addr_t mode_mgr; unsigned int int_status; int irq; bool enabled; bool usb_attached; + bool phy_enabled; u8 port_idx; }; +static int eud_phy_enable(struct eud_chip *chip) +{ + struct phy *phy; + int ret; + + if (chip->phy_enabled) + return 0; + + phy = chip->phy[chip->port_idx]; + + ret = phy_init(phy); + if (ret) { + dev_err(chip->dev, "Failed to initialize USB2 PHY for port %u: %d\n", + chip->port_idx, ret); + return ret; + } + + ret = phy_power_on(phy); + if (ret) { + dev_err(chip->dev, "Failed to power on USB2 PHY for port %u: %d\n", + chip->port_idx, ret); + phy_exit(phy); + return ret; + } + + chip->phy_enabled = true; + + return 0; +} + +static void eud_phy_disable(struct eud_chip *chip) +{ + struct phy *phy; + + if (!chip->phy_enabled) + return; + + phy = chip->phy[chip->port_idx]; + + phy_power_off(phy); + phy_exit(phy); + chip->phy_enabled = false; +} + static int enable_eud(struct eud_chip *priv) { int ret; - ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); + ret = eud_phy_enable(priv); if (ret) return ret; + ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); + if (ret) { + eud_phy_disable(priv); + return ret; + } + writel(EUD_ENABLE, priv->base + EUD_REG_CSR_EUD_EN); writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, priv->base + EUD_REG_INT1_EN_MASK); @@ -70,6 +124,8 @@ static int disable_eud(struct eud_chip *priv) return ret; writel(0, priv->base + EUD_REG_CSR_EUD_EN); + eud_phy_disable(priv); + return 0; } @@ -130,6 +186,11 @@ static ssize_t port_store(struct device *dev, struct device_attribute *attr, if (port >= EUD_MAX_PORTS) return -EINVAL; + if (!chip->phy[port]) { + dev_err(chip->dev, "EUD not supported on selected port\n"); + return -EOPNOTSUPP; + } + /* Port selection must be done before enabling EUD */ if (chip->enabled) { dev_err(chip->dev, "Cannot change port while EUD is enabled\n"); @@ -222,6 +283,35 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) return IRQ_HANDLED; } +static int eud_parse_dt_port(struct eud_chip *chip, u8 port_id) +{ + struct device_node *controller_node; + struct phy *phy; + + /* + * Multiply port_id by 2 to get controller port number: + * port_id 0 -> port@0 (primary USB controller) + * port_id 1 -> port@2 (secondary USB controller) + */ + controller_node = of_graph_get_remote_node(chip->dev->of_node, + port_id * 2, -1); + if (!controller_node) + return dev_err_probe(chip->dev, -ENODEV, + "failed to get controller node for port %u\n", port_id); + + phy = devm_of_phy_get_by_index(chip->dev, controller_node, 0); + if (IS_ERR(phy)) { + of_node_put(controller_node); + return dev_err_probe(chip->dev, PTR_ERR(phy), + "failed to get HS PHY for port %u\n", port_id); + } + chip->phy[port_id] = phy; + + of_node_put(controller_node); + + return 0; +} + static void eud_role_switch_release(void *data) { struct eud_chip *chip = data; @@ -241,6 +331,17 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; + /* + * Parse the DT resources for primary port. + * This is the default EUD port and is mandatory. + */ + ret = eud_parse_dt_port(chip, 0); + if (ret) + return ret; + + /* Secondary port is optional */ + eud_parse_dt_port(chip, 1); + chip->role_sw = usb_role_switch_get(&pdev->dev); if (IS_ERR(chip->role_sw)) return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw), From f2c0e913e68c9365f2b588d0af5f98e5a9fb4ec3 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:36 -0700 Subject: [PATCH 0029/1133] FROMLIST: usb: misc: qcom_eud: add per-port role switch support The EUD hardware can support multiple High-Speed USB ports, each connected to different USB controllers. The current implementation uses a single chip-level role switch, which cannot properly handle multi-port configurations where each USB port can operate in different role. Restructure the driver to support per-port role switches. Additionally, remove the unnecessary role switch call from enable_eud() as EUD need not modify the USB role upon enabling. Link: https://lore.kernel.org/all/20260309203337.803986-5-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index 571b21323797b..c484fc88dea4d 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -38,7 +38,7 @@ struct eud_chip { struct device *dev; - struct usb_role_switch *role_sw; + struct usb_role_switch *role_sw[EUD_MAX_PORTS]; struct phy *phy[EUD_MAX_PORTS]; void __iomem *base; phys_addr_t mode_mgr; @@ -112,7 +112,7 @@ static int enable_eud(struct eud_chip *priv) writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, priv->base + EUD_REG_INT1_EN_MASK); - return usb_role_switch_set_role(priv->role_sw, USB_ROLE_DEVICE); + return 0; } static int disable_eud(struct eud_chip *priv) @@ -270,9 +270,9 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) int ret; if (chip->usb_attached) - ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_DEVICE); + ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_HOST); + ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_HOST); if (ret) dev_err(chip->dev, "failed to set role switch\n"); @@ -287,6 +287,7 @@ static int eud_parse_dt_port(struct eud_chip *chip, u8 port_id) { struct device_node *controller_node; struct phy *phy; + struct usb_role_switch *role_sw; /* * Multiply port_id by 2 to get controller port number: @@ -307,16 +308,31 @@ static int eud_parse_dt_port(struct eud_chip *chip, u8 port_id) } chip->phy[port_id] = phy; + /* Only fetch role switch if usb-role-switch property exists */ + if (!of_property_read_bool(controller_node, "usb-role-switch")) { + of_node_put(controller_node); + return 0; + } + + role_sw = usb_role_switch_find_by_fwnode(of_fwnode_handle(controller_node)); of_node_put(controller_node); + if (!role_sw) + return dev_err_probe(chip->dev, -EPROBE_DEFER, + "failed to get role switch for port %u\n", port_id); + + chip->role_sw[port_id] = role_sw; + return 0; } static void eud_role_switch_release(void *data) { struct eud_chip *chip = data; + int i; - usb_role_switch_put(chip->role_sw); + for (i = 0; i < EUD_MAX_PORTS; i++) + usb_role_switch_put(chip->role_sw[i]); } static int eud_probe(struct platform_device *pdev) @@ -342,11 +358,6 @@ static int eud_probe(struct platform_device *pdev) /* Secondary port is optional */ eud_parse_dt_port(chip, 1); - chip->role_sw = usb_role_switch_get(&pdev->dev); - if (IS_ERR(chip->role_sw)) - return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw), - "failed to get role switch\n"); - ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); if (ret) return ret; From 1abc533bf16b038fd9f3f7998b4bcfc0a933fdd0 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:36 -0700 Subject: [PATCH 0030/1133] FROMLIST: usb: misc: qcom_eud: improve enable_store API Currently enable_store() allows operations irrespective of the EUD state, which can result in redundant operations. Avoid this by adding duplicate state checks to skip requests when EUD is already in the desired state. Additionally, improve error handling with explicit logging to provide better feedback. Link: https://lore.kernel.org/all/20260309203337.803986-6-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio --- drivers/usb/misc/qcom_eud.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index c484fc88dea4d..eee79774f5f8d 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -148,18 +148,27 @@ static ssize_t enable_store(struct device *dev, if (kstrtobool(buf, &enable)) return -EINVAL; + /* Skip operation if already in desired state */ + if (chip->enabled == enable) + return count; + if (enable) { ret = enable_eud(chip); - if (!ret) - chip->enabled = enable; - else - disable_eud(chip); - + if (ret) { + dev_err(chip->dev, "failed to enable eud\n"); + return ret; + } } else { ret = disable_eud(chip); + if (ret) { + dev_err(chip->dev, "failed to disable eud\n"); + return ret; + } } - return ret < 0 ? ret : count; + chip->enabled = enable; + + return count; } static DEVICE_ATTR_RW(enable); From 0383a15688997f81a2938007ae9e52c3a17276e8 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:36 -0700 Subject: [PATCH 0031/1133] FROMLIST: usb: misc: qcom_eud: fix virtual attach/detach event handling EUD provides virtual USB attach/detach events to simulate cable plug/unplug while maintaining the physical debug connection. However, the current implementation incorrectly sets the USB role to HOST on virtual detach, which doesn't represent the disconnected state. Fix the virtual detach handling by setting the USB role to NONE instead of HOST, correctly representing the disconnected state. Link: https://lore.kernel.org/all/20260309203337.803986-7-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao Reviewed-by: Konrad Dybcio --- drivers/usb/misc/qcom_eud.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index eee79774f5f8d..ae0c5b2f022a2 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -278,10 +278,26 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data) struct eud_chip *chip = data; int ret; + /* + * EUD virtual attach/detach event handling for low power debugging: + * + * When EUD is enabled in debug mode, the device remains physically + * connected to the PC throughout the debug session, keeping the USB + * controller active. This prevents testing of low power scenarios that + * require USB disconnection. + * + * EUD solves this by providing virtual USB attach/detach events while + * maintaining the physical connection. These events are triggered from + * the Host PC via the enumerated EUD control interface and delivered + * to the EUD driver as interrupts. + * + * These notifications are forwarded to the USB controller through role + * switch framework. + */ if (chip->usb_attached) ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_DEVICE); else - ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_HOST); + ret = usb_role_switch_set_role(chip->role_sw[chip->port_idx], USB_ROLE_NONE); if (ret) dev_err(chip->dev, "failed to set role switch\n"); From aa09ae014d56b97efa9a6bfb59e8e7db692165b8 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:37 -0700 Subject: [PATCH 0032/1133] FROMLIST: usb: misc: qcom_eud: add host mode coordination EUD functions by presenting itself as a USB device to the host PC for debugging, making it incompatible with USB host mode configurations. Handle below two scenarios to prevent these conflicts: 1. Prevent user from enabling EUD via sysfs when the USB port is in host mode. 2. Automatically disable EUD when USB port switches to host mode and re-enable it when exiting host mode. This is achieved via the exported qcom_eud_usb_role_notify() API that allows the USB controller driver to notify EUD of role changes. This ensures consistent state management without creating conflicts between the EUD debug hub and the USB controller. Link: https://lore.kernel.org/all/20260309203337.803986-8-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- drivers/usb/misc/qcom_eud.c | 110 ++++++++++++++++++++++++++++++++++- include/linux/usb/qcom_eud.h | 21 +++++++ 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 include/linux/usb/qcom_eud.h diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c index ae0c5b2f022a2..5b5cf11d6f526 100644 --- a/drivers/usb/misc/qcom_eud.c +++ b/drivers/usb/misc/qcom_eud.c @@ -12,11 +12,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #define EUD_REG_INT1_EN_MASK 0x0024 @@ -42,11 +44,14 @@ struct eud_chip { struct phy *phy[EUD_MAX_PORTS]; void __iomem *base; phys_addr_t mode_mgr; + /* serializes EUD control operations */ + struct mutex state_lock; unsigned int int_status; int irq; bool enabled; bool usb_attached; bool phy_enabled; + bool eud_disabled_for_host; u8 port_idx; }; @@ -142,17 +147,43 @@ static ssize_t enable_store(struct device *dev, const char *buf, size_t count) { struct eud_chip *chip = dev_get_drvdata(dev); + enum usb_role role; bool enable; int ret; if (kstrtobool(buf, &enable)) return -EINVAL; + guard(mutex)(&chip->state_lock); + /* Skip operation if already in desired state */ if (chip->enabled == enable) return count; + /* + * Handle double-disable scenario: User is disabling EUD that was already + * disabled due to host mode. Since the hardware is already disabled, we + * only need to clear the host-disabled flag to prevent unwanted re-enabling + * when exiting host mode. This respects the user's explicit disable request. + */ + if (!enable && chip->eud_disabled_for_host) { + chip->eud_disabled_for_host = false; + chip->enabled = false; + return count; + } + if (enable) { + /* + * EUD functions by presenting itself as a USB device to the host PC for + * debugging, making it incompatible with USB host mode configuration. + * Prevent enabling EUD in this configuration to avoid hardware conflicts. + */ + role = usb_role_switch_get_role(chip->role_sw[chip->port_idx]); + if (role == USB_ROLE_HOST) { + dev_err(chip->dev, "Cannot enable EUD: USB port is in host mode\n"); + return -EBUSY; + } + ret = enable_eud(chip); if (ret) { dev_err(chip->dev, "failed to enable eud\n"); @@ -351,6 +382,75 @@ static int eud_parse_dt_port(struct eud_chip *chip, u8 port_id) return 0; } +/** + * qcom_eud_usb_role_notify - Notify EUD of USB role change + * @eud_node: Device node of the EUD device + * @phy: HSUSB PHY of the port changing role + * @role: New role being set + * + * Notifies EUD that a USB port is changing roles. EUD will disable itself + * if the port is switching to HOST mode, as EUD is incompatible with host + * mode operation. This API should be called by the USB controller driver + * when it switches the USB role. + * + * The PHY parameter is used to identify which physical USB port is changing + * roles. This is important in multi-port systems where EUD may be active on + * one port while another port changes roles. + * + * This is a best-effort notification - failures are logged but do not affect + * the role change operation. + */ +void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, + enum usb_role role) +{ + struct platform_device *pdev; + struct eud_chip *chip; + int ret; + + if (!of_device_is_compatible(eud_node, "qcom,eud")) + return; + + pdev = of_find_device_by_node(eud_node); + if (!pdev) + return; + + chip = platform_get_drvdata(pdev); + if (!chip) + goto put_dev; + + mutex_lock(&chip->state_lock); + + /* Only act if this notification is for the currently active EUD port */ + if (!chip->enabled || chip->phy[chip->port_idx] != phy) { + mutex_unlock(&chip->state_lock); + goto put_dev; + } + + /* + * chip->enabled preserves user's sysfs configuration and is not modified + * during host mode transitions to preserve user intent. + */ + if (role == USB_ROLE_HOST && !chip->eud_disabled_for_host) { + ret = disable_eud(chip); + if (ret) + dev_err(chip->dev, "Failed to disable EUD for host mode: %d\n", ret); + else + chip->eud_disabled_for_host = true; + } else if (role != USB_ROLE_HOST && chip->eud_disabled_for_host) { + ret = enable_eud(chip); + if (ret) + dev_err(chip->dev, "Failed to re-enable EUD after host mode: %d\n", ret); + else + chip->eud_disabled_for_host = false; + } + + mutex_unlock(&chip->state_lock); + +put_dev: + platform_device_put(pdev); +} +EXPORT_SYMBOL_GPL(qcom_eud_usb_role_notify); + static void eud_role_switch_release(void *data) { struct eud_chip *chip = data; @@ -372,6 +472,8 @@ static int eud_probe(struct platform_device *pdev) chip->dev = &pdev->dev; + mutex_init(&chip->state_lock); + /* * Parse the DT resources for primary port. * This is the default EUD port and is mandatory. @@ -416,8 +518,14 @@ static void eud_remove(struct platform_device *pdev) { struct eud_chip *chip = platform_get_drvdata(pdev); - if (chip->enabled) + platform_set_drvdata(pdev, NULL); + + mutex_lock(&chip->state_lock); + if (chip->enabled) { disable_eud(chip); + chip->enabled = false; + } + mutex_unlock(&chip->state_lock); device_init_wakeup(&pdev->dev, false); disable_irq_wake(chip->irq); diff --git a/include/linux/usb/qcom_eud.h b/include/linux/usb/qcom_eud.h new file mode 100644 index 0000000000000..fe560426b78f3 --- /dev/null +++ b/include/linux/usb/qcom_eud.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __LINUX_USB_QCOM_EUD_H +#define __LINUX_USB_QCOM_EUD_H + +#include + +#if IS_ENABLED(CONFIG_USB_QCOM_EUD) +void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, + enum usb_role role); +#else +static inline void qcom_eud_usb_role_notify(struct device_node *eud_node, struct phy *phy, + enum usb_role role) +{ +} +#endif + +#endif /* __LINUX_USB_QCOM_EUD_H */ From 500d053aab949b7b2a73e69334e0000aaca4eb01 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:37 -0700 Subject: [PATCH 0033/1133] FROMLIST: usb: dwc3: qcom: notify EUD driver of role changes The EUD driver needs USB role information to control its operation as it is incompatible with host mode. Notify the EUD driver when role changes occur so it can manage its state accordingly. Link: https://lore.kernel.org/all/20260309203337.803986-9-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- drivers/usb/dwc3/Kconfig | 1 + drivers/usb/dwc3/dwc3-qcom.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 18169727a413e..ae03ae45e50e4 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -132,6 +132,7 @@ config USB_DWC3_QCOM depends on ARCH_QCOM || COMPILE_TEST depends on EXTCON || !EXTCON depends on OF + depends on USB_QCOM_EUD || !USB_QCOM_EUD default USB_DWC3 help Some Qualcomm SoCs use DesignWare Core IP for USB2/3 diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index f43f73ac36ff1..4c00b6b87f6d5 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include "core.h" #include "glue.h" @@ -561,6 +563,7 @@ static int dwc3_qcom_setup_irq(struct dwc3_qcom *qcom, struct platform_device *p static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_role) { struct dwc3_qcom *qcom = to_dwc3_qcom(dwc); + struct device_node *eud_node; if (qcom->current_role == next_role) return; @@ -570,6 +573,13 @@ static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_rol return; } + /* Notify EUD of role change */ + eud_node = of_graph_get_remote_node(qcom->dev->of_node, 0, -1); + if (eud_node) { + qcom_eud_usb_role_notify(eud_node, dwc->usb2_generic_phy[0], next_role); + of_node_put(eud_node); + } + if (qcom->current_role == USB_ROLE_DEVICE) dwc3_qcom_vbus_override_enable(qcom, false); else if (qcom->current_role != USB_ROLE_DEVICE) From 00c6452c414650e320d6ac20db559381134195cd Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:38 -0700 Subject: [PATCH 0034/1133] FROMLIST: arm64: dts: qcom: kodiak: Fix EUD USB controller connection The EUD node is currently mapped to the secondary USB controller. This SoC only supports EUD on the primary High-Speed USB path. Fix the graph connections to properly map EUD to the primary USB controller. Add an empty connector endpoint for board DTS files to complete the connection. Also enable EUD so debug is available by default on this SoC. Link: https://lore.kernel.org/all/20260309203337.803986-10-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index fa540d8c2615d..ffb11896ccfa1 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -4404,12 +4404,6 @@ phy-names = "usb2-phy"; maximum-speed = "high-speed"; usb-role-switch; - - port { - usb2_role_switch: endpoint { - remote-endpoint = <&eud_ep>; - }; - }; }; qspi: spi@88dc000 { @@ -4736,16 +4730,22 @@ <0 0x88e2000 0 0x1000>; interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>; - status = "disabled"; - ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; + eud_ep: endpoint { - remote-endpoint = <&usb2_role_switch>; + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + eud_con: endpoint { }; }; }; @@ -4972,6 +4972,7 @@ reg = <0>; usb_1_dwc3_hs: endpoint { + remote-endpoint = <&eud_ep>; }; }; From c3aa7d5c9b171a9fb9ae9d1a9adf4dab251508f9 Mon Sep 17 00:00:00 2001 From: Elson Serrao Date: Tue, 24 Mar 2026 15:25:38 -0700 Subject: [PATCH 0035/1133] FROMLIST: arm64: dts: qcom: Map USB connector to EUD for kodiak boards Map the USB connector HS endpoint to EUD for debug functionality on all boards using kodiak.dtsi. Since the controller is no longer a direct neighbor of the connector, add usb-role-switch phandle to map the USB role switch provider for this connector. Link: https://lore.kernel.org/all/20260309203337.803986-11-elson.serrao@oss.qualcomm.com/ Signed-off-by: Elson Serrao --- arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts | 11 ++++++----- arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts | 11 ++++++----- arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts | 11 ++++++----- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 11 ++++++----- .../boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts | 11 ++++++----- arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts | 11 ++++++----- 6 files changed, 36 insertions(+), 30 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts index 04cb9230d29fd..9f0cfd0b5005e 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts @@ -89,6 +89,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -98,7 +99,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -1478,10 +1479,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c>; vdda18-supply = <&vreg_l1c>; @@ -1521,3 +1518,7 @@ qcom,calibration-variant = "Fairphone_5"; status = "okay"; }; + +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts b/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts index bf18c48520813..ca9c1a09ca733 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-particle-tachyon.dts @@ -65,6 +65,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -74,7 +75,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -826,10 +827,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; @@ -862,3 +859,7 @@ &usb_dp_qmpphy_out { remote-endpoint = <&pmic_glink_ss_in>; }; + +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts b/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts index 797f37596bf19..eb7e228787c24 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-shift-otter.dts @@ -75,6 +75,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -84,7 +85,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -952,10 +953,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c>; vdda18-supply = <&vreg_l1c>; @@ -986,6 +983,10 @@ remote-endpoint = <&pmic_glink_ss_in>; }; +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; + &venus { firmware-name = "qcom/qcm6490/SHIFT/otter/venus.mbn"; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 37a3b51323ce5..4de0576c0f2fe 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -202,6 +202,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -211,7 +212,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -1402,14 +1403,14 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_dwc3_ss { remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>; }; +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; + &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts index f47efca42d48d..05cd73b5bcbe2 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts @@ -84,6 +84,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -93,7 +94,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -1090,10 +1091,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vreg_l10c_0p88>; vdda33-supply = <&vreg_l2b_3p072>; @@ -1127,6 +1124,10 @@ remote-endpoint = <&pmic_glink_ss_in>; }; +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; + &ufs_mem_hc { reset-gpios = <&tlmm 175 GPIO_ACTIVE_LOW>; vcc-supply = <&vreg_l7b_2p952>; diff --git a/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts b/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts index cb59c122f6f6a..f99a47334452f 100644 --- a/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts +++ b/arch/arm64/boot/dts/qcom/sm7325-nothing-spacewar.dts @@ -90,6 +90,7 @@ reg = <0>; power-role = "dual"; data-role = "dual"; + usb-role-switch = <&usb_1>; ports { #address-cells = <1>; @@ -99,7 +100,7 @@ reg = <0>; pmic_glink_hs_in: endpoint { - remote-endpoint = <&usb_1_dwc3_hs>; + remote-endpoint = <&eud_con>; }; }; @@ -1440,10 +1441,6 @@ status = "okay"; }; -&usb_1_dwc3_hs { - remote-endpoint = <&pmic_glink_hs_in>; -}; - &usb_1_hsphy { vdda-pll-supply = <&vdd_a_usbhs_core>; vdda18-supply = <&vdd_a_usbhs_1p8>; @@ -1459,3 +1456,7 @@ &wifi { status = "okay"; }; + +&eud_con { + remote-endpoint = <&pmic_glink_hs_in>; +}; From cd6dc9bc311e6594ac71ce62d410027161ec755b Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 8 Jan 2026 10:00:04 +0800 Subject: [PATCH 0036/1133] QCLINUX: qcom-dcc: Add driver support for Data Capture and Compare unit(DCC) The DCC is a DMA Engine designed to capture and store data during system crash or software triggers. The DCC operates based on user inputs via the debugfs interface. The user gives addresses as inputs and these addresses are stored in the dcc sram. In case of a system crash or a manual software trigger by the user through the debugfs interface, the dcc captures and stores the values at these addresses. This patch contains the driver which has all the methods pertaining to the debugfs interface, auxiliary functions to support all the four fundamental operations of dcc namely read, write, read/modify/write and loop. The probe method here instantiates all the resources necessary for dcc to operate mainly the dedicated dcc sram where it stores the values. The DCC driver can be used for debugging purposes without going for a reboot since it can perform software triggers as well based on user inputs. Also add the documentation for debugfs entries which explains the functionalities of each debugfs file that has been created for dcc. The following is the justification of using debugfs interface over the other alternatives like sysfs/ioctls i) As can be seen from the debugfs attribute descriptions, some of the debugfs attribute files here contains multiple arguments which needs to be accepted from the user. This goes against the design style of sysfs. ii) The user input patterns have been made simple and convenient in this case with the use of debugfs interface as user doesn't need to shuffle between different files to execute one instruction as was the case on using other alternatives. Signed-off-by: Jie Gan --- drivers/misc/Kconfig | 8 + drivers/misc/Makefile | 1 + drivers/misc/qcom-dcc.c | 1610 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 1619 insertions(+) create mode 100644 drivers/misc/qcom-dcc.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 7364931dad3a1..ea580f30da06f 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -275,6 +275,14 @@ config QCOM_FASTRPC applications DSP processor. Say M if you want to enable this module. +config QCOM_DCC + tristate "Qualcomm Technologies, Inc. Data Capture and Compare (DCC) engine driver" + depends on ARCH_QCOM || COMPILE_TEST + help + This option enables the driver for the Data Capture and Compare engine. DCC + driver provides interfaces to configure DCC block and read back the captured + data from the DCC's internal SRAM. The module name for this is qcom-dcc. + config APDS9802ALS tristate "Medfield Avago APDS9802 ALS Sensor module" depends on I2C diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index e8d8d5d88c0df..50e0f3f54f9a4 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -70,4 +70,5 @@ obj-$(CONFIG_MCHP_LAN966X_PCI) += lan966x-pci.o obj-y += keba/ obj-y += amd-sbi/ obj-$(CONFIG_MISC_RP1) += rp1/ +obj-$(CONFIG_QCOM_DCC) += qcom-dcc.o obj-$(CONFIG_INTEL_SSEI) += issei/ diff --git a/drivers/misc/qcom-dcc.c b/drivers/misc/qcom-dcc.c new file mode 100644 index 0000000000000..a511faac5d4b0 --- /dev/null +++ b/drivers/misc/qcom-dcc.c @@ -0,0 +1,1610 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/* + * DCC(Data Capture and Compare) is a DMA engine designed for debugging + * purposes. + * In case of a system crash or manual software triggers by the user the + * DCC hardware stores the value at the register addresses which can be + * used for debugging purposes. + * The DCC driver provides the user with debugfs interface to configure the + * register addresses. The options that the DCC hardware provides include + * reading from registers, writing to registers, first reading and then + * writing to registers and looping through the values of the same + * register. + * + * In certain cases a register write needs to be executed for accessing the + * rest of the registers, also the user might want to record the changing + * values of a register with time for which he has the option to use the + * loop feature. + * + * The options mentioned above are exposed to the user by debugfs files + * once the driver is probed. The details and usage of this debugfs files + * are documented in Documentation/ABI/testing/debugfs-driver-dcc. + * + * As an example let us consider a couple of debug scenarios where DCC has + * been proved to be effective for debugging purposes:- + * + * i)TimeStamp Related Issue + * + * On SC7180, there was a coresight timestamp issue where it would + * occasionally be all 0 instead of proper timestamp values. + * + * Proper timestamp: + * Idx:3373; ID:10; I_TIMESTAMP : Timestamp.; Updated val = + * 0x13004d8f5b7aa; CC=0x9e + * + * Zero timestamp: + * Idx:3387; ID:10; I_TIMESTAMP : Timestamp.; Updated val = 0x0; CC=0xa2 + * + * Now this is a non-fatal issue and doesn't need a system reset, but still + * needs to be rootcaused and fixed for those who do care about coresight + * etm traces. + * Since this is a timestamp issue, we would be looking for any timestamp + * related clocks and such. + * + * We get all the clk register details from IP documentation and configure + * it via DCC config debugfs node. Before that we set the current + * linked list. + * + * Program the linked list with the addresses + * echo R 0x10c004 > /sys/kernel/debug/qcom-dcc/../3/config + * echo R 0x10c008 > /sys/kernel/debug/qcom-dcc/../3/config + * echo R 0x10c00c > /sys/kernel/debug/qcom-dcc/../3/config + * echo R 0x10c010 > /sys/kernel/debug/qcom-dcc/../3/config + * ..... and so on for other timestamp related clk registers + * + * Other way of specifying is in "addr len" pair, in below case it + * specifies to capture 4 words starting 0x10C004 + * + * echo R 0x10C004 4 > /sys/kernel/debug/qcom-dcc/../3/config + * + * Configuration can be saved to a file and reuse it later. + * cat /sys/kernel/debug/qcom-dcc/../3/config > config_3 + * Post reboot, write the file to config. + * echo config_3 > /sys/kernel/debug/qcom-dcc/../3/config + * + * Enable DCC + * echo 1 > /sys/kernel/debug/qcom-dcc/../3/enable + * + * Run the timestamp test for working case + * + * Send SW trigger + * echo 1 > /sys/kernel/debug/qcom-dcc/../trigger + * + * Read SRAM + * cat /dev/dcc_sram > dcc_sram1.bin + * + * Run the timestamp test for non-working case + * + * Send SW trigger + * echo 1 > /sys/kernel/debug/qcom-dcc/../trigger + * + * Read SRAM + * cat /dev/dcc_sram > dcc_sram2.bin + * + * Get the parser from + * https://git.codelinaro.org/clo/le/platform/vendor/qcom-opensource/tools/-/tree/opensource-tools.lnx.1.0.r176-rel/dcc_parser + * + * Parse the SRAM bin + * python dcc_parser.py -s dcc_sram1.bin --v2 -o output/ python + * dcc_parser.py -s dcc_sram2.bin --v2 -o output/ + * + * Sample parsed output of dcc_sram1.bin: + * + * + * 03/14/21 + * Linux DCC Parser + * + * + * + * + * + * + * next_ll_offset : 0x1c + * + * ii)NOC register errors + * + * A particular class of registers called NOC which are functional + * registers was reporting errors while logging the values.To trace these + * errors the DCC has been used effectively. + * The steps followed were similar to the ones mentioned above. + * In addition to NOC registers a few other dependent registers were + * configured in DCC to monitor it's values during a crash. A look at the + * dependent register values revealed that the crash was happening due to a + * secured access to one of these dependent registers. + * All these debugging activity and finding the root cause was achieved + * using DCC. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STATUS_READY_TIMEOUT 5000 /* microseconds */ + +/* DCC registers */ +#define DCC_HW_INFO 0x04 +#define DCC_LL_NUM_INFO 0x10 +#define DCC_LL_LOCK 0x00 +#define DCC_LL_CFG 0x04 +#define DCC_LL_BASE 0x08 +#define DCC_FD_BASE 0x0c +#define DCC_LL_OFFSET 0x80 +#define DCC_LL_TIMEOUT 0x10 +#define DCC_LL_INT_ENABLE 0x18 +#define DCC_LL_INT_STATUS 0x1c +#define DCC_LL_SW_TRIGGER 0x2c +#define DCC_LL_BUS_ACCESS_STATUS 0x30 + +/* Default value used if a bit 6 in the HW_INFO register is set. */ +#define DCC_FIX_LOOP_OFFSET 16 + +/* Mask to find version info from HW_Info register */ +#define DCC_VER_INFO_MASK BIT(9) + +#define MAX_DCC_OFFSET GENMASK(9, 2) +#define MAX_DCC_LEN GENMASK(6, 0) +#define MAX_LOOP_CNT GENMASK(7, 0) +#define MAX_LOOP_ADDR 10 + +#define DCC_ADDR_DESCRIPTOR 0x00 +#define DCC_ADDR_LIMIT 27 +#define DCC_WORD_SIZE sizeof(u32) +#define DCC_ADDR_RANGE_MASK GENMASK(31, 4) +#define DCC_LOOP_DESCRIPTOR BIT(30) +#define DCC_RD_MOD_WR_DESCRIPTOR BIT(31) +#define DCC_LINK_DESCRIPTOR GENMASK(31, 30) +#define DCC_STATUS_MASK GENMASK(1, 0) +#define DCC_LOCK_MASK BIT(0) +#define DCC_LOOP_OFFSET_MASK BIT(6) +#define DCC_TRIGGER_MASK BIT(9) + +#define DCC_WRITE_MASK BIT(15) +#define DCC_WRITE_OFF_MASK GENMASK(7, 0) +#define DCC_WRITE_LEN_MASK GENMASK(14, 8) + +#define DCC_READ_IND 0x00 +#define DCC_WRITE_IND (BIT(28)) + +#define DCC_AHB_IND 0x00 +#define DCC_APB_IND BIT(29) + +#define DCC_MAX_LINK_LIST 8 + +#define DCC_VER_MASK2 GENMASK(5, 0) + +#define DCC_SRAM_WORD_LENGTH 4 + +#define DCC_RD_MOD_WR_ADDR 0xC105E + +#define MEM_MAP_VER1 0x1 +#define MEM_MAP_VER2 0x2 +#define MEM_MAP_VER3 0x3 + +#define LINE_BUFFER_MAX_SZ 50 +enum dcc_descriptor_type { + DCC_READ_TYPE, + DCC_LOOP_TYPE, + DCC_READ_WRITE_TYPE, + DCC_WRITE_TYPE +}; + +/** + * struct dcc_config_entry - configuration information related to each dcc instruction + * @base: Base address of the register to be configured in dcc + * @offset: Offset to the base address to be configured in dcc + * @len: Length of the address in words of 4 bytes to be configured in dcc + * @loop_cnt: The number of times to loop on the register address in case + of loop instructions + * @write_val: The value to be written on the register address in case of + write instructions + * @mask: Mask corresponding to the value to be written in case of + write instructions + * @apb_bus: Type of bus to be used for the instruction, can be either + 'apb' if 1 or 'ahb' if 0 + * @desc_type: Stores the type of dcc instruction + * @list: This is used to append this instruction to the list of + instructions + */ +struct dcc_config_entry { + u32 base; + u32 offset; + u32 len; + u32 loop_cnt; + u32 write_val; + u32 mask; + bool apb_bus; + enum dcc_descriptor_type desc_type; + struct list_head list; +}; + +/** + * struct dcc_drvdata - configuration information related to a dcc device + * @base: Base Address of the dcc device + * @dev: The device attached to the driver data + * @mutex: Lock to protect access and manipulation of dcc_drvdata + * @ram_base: Base address for the SRAM dedicated for the dcc device + * @ram_size: Total size of the SRAM dedicated for the dcc device + * @ram_offset: Offset to the SRAM dedicated for dcc device + * @ram_cfg: Used for address limit calculation for dcc + * @ram_start: Starting address of DCC SRAM + * @mem_map_ver: Memory map version of DCC hardware + * @sram_dev: Miscellaneous device equivalent of dcc SRAM + * @cfg_head: Points to the head of the linked list of addresses + * @dbg_dir: The dcc debugfs directory under which all the debugfs files are placed + * @max_link_list: Total number of linkedlists supported by the DCC configuration + * @loop_shift: Loop offset bits range for the addresses + * @enable_bitmap: Bitmap to capture the enabled status of each linked list of addresses + */ +struct dcc_drvdata { + void __iomem *base; + void __iomem *ram_base; + struct device *dev; + /* Lock to protect access and manipulation of dcc_drvdata */ + struct mutex mutex; + size_t ram_size; + u32 ram_offset; + unsigned int ram_cfg; + unsigned int ram_start; + u64 mem_map_ver; + struct miscdevice sram_dev; + struct list_head *cfg_head; + struct dentry *dbg_dir; + size_t max_link_list; + u8 loop_shift; + unsigned long *enable_bitmap; + char **temp_buff_ptr; +}; + +struct dcc_cfg_attr { + u32 addr; + u32 prev_addr; + u32 prev_off; + u32 link; + u32 sram_offset; +}; + +struct dcc_cfg_loop_attr { + u32 loop_cnt; + u32 loop_len; + u32 loop_off; + bool loop_start; +}; + +static inline u32 dcc_status(int version) +{ + return version == 1 ? 0x0c : 0x1c; +} + +static inline u32 dcc_list_offset(int version) +{ + if (version == 1) + return 0x1c; + else if (version == 2) + return 0x2c; + else + return 0x34; +} + +static inline void dcc_list_writel(struct dcc_drvdata *drvdata, + u32 val, u32 ll, u32 off) +{ + u32 offset = dcc_list_offset(drvdata->mem_map_ver) + off; + + writel(val, drvdata->base + ll * DCC_LL_OFFSET + offset); +} + +static inline u32 dcc_list_readl(struct dcc_drvdata *drvdata, u32 ll, u32 off) +{ + u32 offset = dcc_list_offset(drvdata->mem_map_ver) + off; + + return readl(drvdata->base + ll * DCC_LL_OFFSET + offset); +} + +static void dcc_sram_write_auto(struct dcc_drvdata *drvdata, + u32 val, u32 *off) +{ + /* If the overflow condition is met increment the offset + * and return to indicate that overflow has occurred + */ + if (*off > drvdata->ram_size - 4) { + *off += 4; + return; + } + + writel(val, drvdata->ram_base + *off); + + *off += 4; +} + +static int dcc_sw_trigger(struct dcc_drvdata *drvdata) +{ + void __iomem *addr; + int i; + u32 status; + u32 ll_cfg; + u32 tmp_ll_cfg; + u32 val; + int ret = 0; + + mutex_lock(&drvdata->mutex); + + for (i = 0; i < drvdata->max_link_list; i++) { + if (!test_bit(i, drvdata->enable_bitmap)) + continue; + ll_cfg = dcc_list_readl(drvdata, i, DCC_LL_CFG); + if (drvdata->mem_map_ver == MEM_MAP_VER3) + tmp_ll_cfg = ll_cfg & ~BIT(8); + else + tmp_ll_cfg = ll_cfg & ~DCC_TRIGGER_MASK; + + dcc_list_writel(drvdata, tmp_ll_cfg, i, DCC_LL_CFG); + dcc_list_writel(drvdata, 1, i, DCC_LL_SW_TRIGGER); + dcc_list_writel(drvdata, ll_cfg, i, DCC_LL_CFG); + } + + addr = drvdata->base + dcc_status(drvdata->mem_map_ver); + if (readl_poll_timeout(addr, val, !FIELD_GET(DCC_STATUS_MASK, val), + 1, STATUS_READY_TIMEOUT)) { + dev_err(drvdata->dev, "DCC is busy after receiving sw trigger\n"); + ret = -EBUSY; + goto out_unlock; + } + + for (i = 0; i < drvdata->max_link_list; i++) { + if (!test_bit(i, drvdata->enable_bitmap)) + continue; + + status = dcc_list_readl(drvdata, i, DCC_LL_BUS_ACCESS_STATUS); + if (!status) + continue; + + dev_err(drvdata->dev, "Read access error for list %d err: 0x%x\n", + i, status); + ll_cfg = dcc_list_readl(drvdata, i, DCC_LL_CFG); + if (drvdata->mem_map_ver == MEM_MAP_VER3) + tmp_ll_cfg = ll_cfg & ~BIT(8); + else + tmp_ll_cfg = ll_cfg & ~DCC_TRIGGER_MASK; + + dcc_list_writel(drvdata, tmp_ll_cfg, i, DCC_LL_CFG); + dcc_list_writel(drvdata, DCC_STATUS_MASK, i, DCC_LL_BUS_ACCESS_STATUS); + dcc_list_writel(drvdata, ll_cfg, i, DCC_LL_CFG); + ret = -ENODATA; + break; + } + +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static void dcc_ll_cfg_reset_link(struct dcc_cfg_attr *cfg) +{ + cfg->addr = 0x00; + cfg->link = 0; + cfg->prev_off = 0; + cfg->prev_addr = cfg->addr; +} + +static void dcc_emit_read_write(struct dcc_drvdata *drvdata, + struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg) +{ + if (cfg->link) { + /* + * write new offset = 1 to continue + * processing the list + */ + + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + /* Reset link and prev_off */ + dcc_ll_cfg_reset_link(cfg); + } + + cfg->addr = DCC_RD_MOD_WR_DESCRIPTOR; + dcc_sram_write_auto(drvdata, cfg->addr, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, entry->mask, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, entry->write_val, &cfg->sram_offset); + + cfg->addr = 0; +} + +static void dcc_emit_loop(struct dcc_drvdata *drvdata, struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg, + struct dcc_cfg_loop_attr *cfg_loop, + u32 *total_len) +{ + int loop; + + /* Check if we need to write link of prev entry */ + if (cfg->link) + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + if (cfg_loop->loop_start) { + loop = (cfg->sram_offset - cfg_loop->loop_off) / 4; + loop |= (cfg_loop->loop_cnt << drvdata->loop_shift) & + GENMASK(DCC_ADDR_LIMIT, drvdata->loop_shift); + loop |= DCC_LOOP_DESCRIPTOR; + *total_len += (*total_len - cfg_loop->loop_len) * cfg_loop->loop_cnt; + + dcc_sram_write_auto(drvdata, loop, &cfg->sram_offset); + + cfg_loop->loop_start = false; + cfg_loop->loop_len = 0; + cfg_loop->loop_off = 0; + } else { + cfg_loop->loop_start = true; + cfg_loop->loop_cnt = entry->loop_cnt - 1; + cfg_loop->loop_len = *total_len; + cfg_loop->loop_off = cfg->sram_offset; + } + + /* Reset link and prev_off */ + dcc_ll_cfg_reset_link(cfg); +} + +static void dcc_emit_write(struct dcc_drvdata *drvdata, + struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg) +{ + u32 off; + + if (cfg->link) { + /* + * write new offset = 1 to continue + * processing the list + */ + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + /* Reset link and prev_off */ + cfg->addr = 0x00; + cfg->prev_off = 0; + cfg->prev_addr = cfg->addr; + } + + off = entry->offset / 4; + /* write new offset-length pair to correct position */ + cfg->link |= ((off & DCC_WRITE_OFF_MASK) | DCC_WRITE_MASK | + FIELD_PREP(DCC_WRITE_LEN_MASK, entry->len)); + cfg->link |= DCC_LINK_DESCRIPTOR; + + /* Address type */ + cfg->addr = (entry->base >> 4) & GENMASK(DCC_ADDR_LIMIT, 0); + if (entry->apb_bus) + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_WRITE_IND | DCC_APB_IND; + else + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_WRITE_IND | DCC_AHB_IND; + dcc_sram_write_auto(drvdata, cfg->addr, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + + dcc_sram_write_auto(drvdata, entry->write_val, &cfg->sram_offset); + + cfg->addr = 0x00; + cfg->link = 0; +} + +static int dcc_emit_read(struct dcc_drvdata *drvdata, + struct dcc_config_entry *entry, + struct dcc_cfg_attr *cfg, + u32 *pos, u32 *total_len) +{ + u32 off; + u32 temp_off; + + cfg->addr = (entry->base >> 4) & GENMASK(27, 0); + + if (entry->apb_bus) + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_READ_IND | DCC_APB_IND; + else + cfg->addr |= DCC_ADDR_DESCRIPTOR | DCC_READ_IND | DCC_AHB_IND; + + off = entry->offset / 4; + + *total_len += entry->len * 4; + + if (!cfg->prev_addr || cfg->prev_addr != cfg->addr || cfg->prev_off > off) { + /* Check if we need to write prev link entry */ + if (cfg->link) + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + dev_dbg(drvdata->dev, "DCC: sram address 0x%x\n", cfg->sram_offset); + + /* Write address */ + dcc_sram_write_auto(drvdata, cfg->addr, &cfg->sram_offset); + + /* Reset link and prev_off */ + cfg->link = 0; + cfg->prev_off = 0; + } + + if ((off - cfg->prev_off) > 0xff || entry->len > MAX_DCC_LEN) { + dev_err(drvdata->dev, "DCC: Programming error Base: 0x%x, offset 0x%x\n", + entry->base, entry->offset); + return -EINVAL; + } + + if (cfg->link) { + /* + * link already has one offset-length so new + * offset-length needs to be placed at + * bits [29:15] + */ + *pos = 15; + + /* Clear bits [31:16] */ + cfg->link &= GENMASK(14, 0); + } else { + /* + * link is empty, so new offset-length needs + * to be placed at bits [15:0] + */ + *pos = 0; + cfg->link = 1 << 15; + } + + /* write new offset-length pair to correct position */ + temp_off = (off - cfg->prev_off) & GENMASK(7, 0); + cfg->link |= (temp_off | ((entry->len << 8) & GENMASK(14, 8))) << *pos; + + cfg->link |= DCC_LINK_DESCRIPTOR; + + if (*pos) { + dcc_sram_write_auto(drvdata, cfg->link, &cfg->sram_offset); + cfg->link = 0; + } + + cfg->prev_off = off + entry->len - 1; + cfg->prev_addr = cfg->addr; + return 0; +} + +static int dcc_emit_config(struct dcc_drvdata *drvdata, unsigned int curr_list) +{ + int ret; + u32 total_len, pos; + struct dcc_config_entry *entry; + struct dcc_cfg_attr cfg = {0}; + struct dcc_cfg_loop_attr cfg_loop = {0}; + + cfg.sram_offset = drvdata->ram_cfg * 4; + total_len = 0; + + list_for_each_entry(entry, &drvdata->cfg_head[curr_list], list) { + switch (entry->desc_type) { + case DCC_READ_WRITE_TYPE: + dcc_emit_read_write(drvdata, entry, &cfg); + break; + + case DCC_LOOP_TYPE: + dcc_emit_loop(drvdata, entry, &cfg, &cfg_loop, &total_len); + break; + + case DCC_WRITE_TYPE: + dcc_emit_write(drvdata, entry, &cfg); + break; + + case DCC_READ_TYPE: + ret = dcc_emit_read(drvdata, entry, &cfg, &pos, &total_len); + if (ret) + goto err; + break; + } + } + + if (cfg.link) + dcc_sram_write_auto(drvdata, cfg.link, &cfg.sram_offset); + + if (cfg_loop.loop_start) { + dev_err(drvdata->dev, "DCC: Programming error: Loop unterminated\n"); + ret = -EINVAL; + goto err; + } + + /* Handling special case of list ending with a rd_mod_wr */ + if (cfg.addr == DCC_RD_MOD_WR_DESCRIPTOR) { + cfg.addr = (DCC_RD_MOD_WR_ADDR) & GENMASK(27, 0); + cfg.addr |= DCC_ADDR_DESCRIPTOR; + dcc_sram_write_auto(drvdata, cfg.addr, &cfg.sram_offset); + } + + /* Setting zero to indicate end of the list */ + cfg.link = DCC_LINK_DESCRIPTOR; + dcc_sram_write_auto(drvdata, cfg.link, &cfg.sram_offset); + + /* Check if sram offset exceeds the ram size */ + if (cfg.sram_offset > drvdata->ram_size) + goto overstep; + + /* Update ram_cfg and check if the data will overstep */ + drvdata->ram_cfg = (cfg.sram_offset + total_len) / 4; + + if (cfg.sram_offset + total_len > drvdata->ram_size) { + cfg.sram_offset += total_len; + goto overstep; + } + + drvdata->ram_start = cfg.sram_offset / 4; + return 0; +overstep: + ret = -EINVAL; + memset_io(drvdata->ram_base, 0, drvdata->ram_size); + +err: + return ret; +} + +static bool dcc_valid_list(struct dcc_drvdata *drvdata, unsigned int curr_list) +{ + u32 lock_reg; + + if (list_empty(&drvdata->cfg_head[curr_list])) + return false; + + if (test_bit(curr_list, drvdata->enable_bitmap)) { + dev_err(drvdata->dev, "List %d is already enabled\n", curr_list); + return false; + } + + lock_reg = dcc_list_readl(drvdata, curr_list, DCC_LL_LOCK); + if (lock_reg & DCC_LOCK_MASK) { + dev_err(drvdata->dev, "List %d is already locked\n", curr_list); + return false; + } + + return true; +} + +static bool is_dcc_enabled(struct dcc_drvdata *drvdata) +{ + int list; + + for (list = 0; list < drvdata->max_link_list; list++) + if (test_bit(list, drvdata->enable_bitmap)) + return true; + + return false; +} + +static int dcc_enable(struct dcc_drvdata *drvdata, unsigned int curr_list) +{ + int ret; + u32 ram_cfg_base; + + mutex_lock(&drvdata->mutex); + + if (!dcc_valid_list(drvdata, curr_list)) { + ret = -EINVAL; + goto out_unlock; + } + + /* Fill dcc sram with the poison value. + * This helps in understanding bus + * hang from registers returning a zero + */ + if (!is_dcc_enabled(drvdata)) + memset_io(drvdata->ram_base, 0xde, drvdata->ram_size); + + /* 1. Take ownership of the list */ + dcc_list_writel(drvdata, DCC_LOCK_MASK, curr_list, DCC_LL_LOCK); + + /* 2. Program linked-list in the SRAM */ + ram_cfg_base = drvdata->ram_cfg; + ret = dcc_emit_config(drvdata, curr_list); + if (ret) { + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_LOCK); + goto out_unlock; + } + + /* 3. Program DCC_RAM_CFG reg */ + dcc_list_writel(drvdata, ram_cfg_base + + drvdata->ram_offset / 4, curr_list, DCC_LL_BASE); + dcc_list_writel(drvdata, drvdata->ram_start + + drvdata->ram_offset / 4, curr_list, DCC_FD_BASE); + dcc_list_writel(drvdata, 0xFFF, curr_list, DCC_LL_TIMEOUT); + + /* 4. Clears interrupt status register */ + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_INT_ENABLE); + dcc_list_writel(drvdata, (BIT(0) | BIT(1) | BIT(2)), + curr_list, DCC_LL_INT_STATUS); + + set_bit(curr_list, drvdata->enable_bitmap); + + /* 5. Configure trigger */ + if (drvdata->mem_map_ver == MEM_MAP_VER3) + dcc_list_writel(drvdata, BIT(8), + curr_list, DCC_LL_CFG); + else + dcc_list_writel(drvdata, DCC_TRIGGER_MASK, + curr_list, DCC_LL_CFG); + +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static void dcc_disable(struct dcc_drvdata *drvdata, int curr_list) +{ + mutex_lock(&drvdata->mutex); + + if (!test_bit(curr_list, drvdata->enable_bitmap)) + goto out_unlock; + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_CFG); + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_BASE); + dcc_list_writel(drvdata, 0, curr_list, DCC_FD_BASE); + dcc_list_writel(drvdata, 0, curr_list, DCC_LL_LOCK); + clear_bit(curr_list, drvdata->enable_bitmap); +out_unlock: + mutex_unlock(&drvdata->mutex); +} + +static u32 dcc_filp_curr_list(const struct file *filp) +{ + struct dentry *dentry = file_dentry(filp); + int curr_list, ret; + + ret = kstrtoint(dentry->d_parent->d_name.name, 0, &curr_list); + if (ret) + return ret; + + return curr_list; +} + +static ssize_t enable_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char *buf; + int curr_list = dcc_filp_curr_list(filp); + struct dcc_drvdata *drvdata = filp->private_data; + + if (curr_list < 0) + return curr_list; + + mutex_lock(&drvdata->mutex); + if (test_bit(curr_list, drvdata->enable_bitmap)) + buf = "Y\n"; + else + buf = "N\n"; + mutex_unlock(&drvdata->mutex); + + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); +} + +static ssize_t enable_write(struct file *filp, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + int ret = 0, curr_list; + bool val; + struct dcc_drvdata *drvdata = filp->private_data; + + curr_list = dcc_filp_curr_list(filp); + if (curr_list < 0) + return curr_list; + + ret = kstrtobool_from_user(userbuf, count, &val); + if (ret < 0) + return ret; + + if (val) { + ret = dcc_enable(drvdata, curr_list); + if (ret) + return ret; + } else { + dcc_disable(drvdata, curr_list); + } + + return count; +} + +static const struct file_operations enable_fops = { + .read = enable_read, + .write = enable_write, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static ssize_t trigger_write(struct file *filp, + const char __user *user_buf, size_t count, + loff_t *ppos) +{ + int ret; + unsigned int val; + struct dcc_drvdata *drvdata = filp->private_data; + + ret = kstrtouint_from_user(user_buf, count, 0, &val); + if (ret < 0) + return ret; + + if (val != 1) + return -EINVAL; + + ret = dcc_sw_trigger(drvdata); + if (ret < 0) + return ret; + + return count; +} + +static const struct file_operations trigger_fops = { + .write = trigger_write, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static int dcc_config_add(struct dcc_drvdata *drvdata, unsigned int addr, + unsigned int len, bool apb_bus, int curr_list) +{ + int ret = 0; + struct dcc_config_entry *entry, *pentry; + unsigned int base, offset; + + mutex_lock(&drvdata->mutex); + + if (!len || len > drvdata->ram_size / DCC_WORD_SIZE) { + dev_err(drvdata->dev, "DCC: Invalid length\n"); + ret = -EINVAL; + goto out_unlock; + } + + base = addr & DCC_ADDR_RANGE_MASK; + + if (!list_empty(&drvdata->cfg_head[curr_list])) { + pentry = list_last_entry(&drvdata->cfg_head[curr_list], + struct dcc_config_entry, list); + + if (pentry->desc_type == DCC_READ_TYPE && + addr >= (pentry->base + pentry->offset) && + addr <= (pentry->base + pentry->offset + MAX_DCC_OFFSET)) { + /* Re-use base address from last entry */ + base = pentry->base; + + if ((pentry->len * 4 + pentry->base + pentry->offset) + == addr) { + len += pentry->len; + + if (len > MAX_DCC_LEN) + pentry->len = MAX_DCC_LEN; + else + pentry->len = len; + + addr = pentry->base + pentry->offset + + pentry->len * 4; + len -= pentry->len; + } + } + } + + offset = addr - base; + + while (len) { + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + ret = -ENOMEM; + goto out_unlock; + } + + entry->base = base; + entry->offset = offset; + entry->len = min_t(u32, len, MAX_DCC_LEN); + entry->desc_type = DCC_READ_TYPE; + entry->apb_bus = apb_bus; + INIT_LIST_HEAD(&entry->list); + list_add_tail(&entry->list, + &drvdata->cfg_head[curr_list]); + + len -= entry->len; + offset += MAX_DCC_LEN * 4; + } + +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static ssize_t dcc_config_add_read(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + bool bus; + int len, nval; + unsigned int base; + char apb_bus[4]; + + nval = sscanf(buf, "%x %i %3s", &base, &len, apb_bus); + if (nval <= 0 || nval > 3) + return -EINVAL; + + if (nval == 1) { + len = 1; + bus = false; + } else if (nval == 2) { + bus = false; + } else if (!strcmp("apb", apb_bus)) { + bus = true; + } else if (!strcmp("ahb", apb_bus)) { + bus = false; + } else { + return -EINVAL; + } + + return dcc_config_add(drvdata, base, len, bus, curr_list); +} + +static void dcc_config_reset(struct dcc_drvdata *drvdata) +{ + struct dcc_config_entry *entry, *temp; + int curr_list; + + mutex_lock(&drvdata->mutex); + + for (curr_list = 0; curr_list < drvdata->max_link_list; curr_list++) { + list_for_each_entry_safe(entry, temp, + &drvdata->cfg_head[curr_list], list) { + list_del(&entry->list); + } + } + drvdata->ram_start = 0; + drvdata->ram_cfg = 0; + mutex_unlock(&drvdata->mutex); +} + +static ssize_t config_reset_write(struct file *filp, + const char __user *user_buf, size_t count, + loff_t *ppos) +{ + unsigned int val; + int ret; + struct dcc_drvdata *drvdata = filp->private_data; + + ret = kstrtouint_from_user(user_buf, count, 0, &val); + if (ret < 0) + return ret; + + if (val) + dcc_config_reset(drvdata); + + return count; +} + +static const struct file_operations config_reset_fops = { + .write = config_reset_write, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static ssize_t ready_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char *buf; + struct dcc_drvdata *drvdata = filp->private_data; + + if (!is_dcc_enabled(drvdata)) + return -EINVAL; + + if (!FIELD_GET(BIT(1), readl(drvdata->base + dcc_status(drvdata->mem_map_ver)))) + buf = "Y\n"; + else + buf = "N\n"; + + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf) + 1); +} + +static const struct file_operations ready_fops = { + .read = ready_read, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static ssize_t loop_offset_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char buf[4]; + struct dcc_drvdata *drvdata = filp->private_data; + + snprintf(buf, sizeof(buf), "%d", drvdata->loop_shift); + return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf) + 1); +} + +static const struct file_operations loop_offset_fops = { + .read = loop_offset_read, + .open = simple_open, + .llseek = generic_file_llseek, +}; +static int dcc_add_loop(struct dcc_drvdata *drvdata, unsigned long loop_cnt, int curr_list) +{ + struct dcc_config_entry *entry; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->loop_cnt = min_t(u32, loop_cnt, MAX_LOOP_CNT); + entry->desc_type = DCC_LOOP_TYPE; + INIT_LIST_HEAD(&entry->list); + list_add_tail(&entry->list, &drvdata->cfg_head[curr_list]); + + return 0; +} + +static ssize_t dcc_config_add_loop(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + int ret, i = 0; + char *token, *input; + char delim[2] = " "; + unsigned int val[MAX_LOOP_ADDR]; + + input = buf; + + while ((token = strsep(&input, delim)) && i < MAX_LOOP_ADDR) { + ret = kstrtouint(token, 0, &val[i++]); + if (ret) + return ret; + } + + if (token) { + dev_err(drvdata->dev, "Max limit %u of loop address exceeded\n", + MAX_LOOP_ADDR); + return -EINVAL; + } + + if (val[1] < 1 || val[1] > 8 || val[1] > (i - 2)) + return -EINVAL; + + ret = dcc_add_loop(drvdata, val[0], curr_list); + if (ret) + return ret; + + for (i = 0; i < val[1]; i++) + dcc_config_add(drvdata, val[i + 2], 1, false, curr_list); + + return dcc_add_loop(drvdata, 1, curr_list); +} + +static int dcc_rd_mod_wr_add(struct dcc_drvdata *drvdata, unsigned int mask, + unsigned int val, int curr_list) +{ + int ret = 0; + struct dcc_config_entry *entry; + + mutex_lock(&drvdata->mutex); + + if (list_empty(&drvdata->cfg_head[curr_list])) { + dev_err(drvdata->dev, "DCC: No read address programmed\n"); + ret = -EPERM; + goto out_unlock; + } + + entry = devm_kzalloc(drvdata->dev, sizeof(*entry), GFP_KERNEL); + if (!entry) { + ret = -ENOMEM; + goto out_unlock; + } + + entry->desc_type = DCC_READ_WRITE_TYPE; + entry->mask = mask; + entry->write_val = val; + list_add_tail(&entry->list, &drvdata->cfg_head[curr_list]); +out_unlock: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static ssize_t dcc_config_add_read_write(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + int ret; + int nval; + unsigned int addr, mask, val; + + nval = sscanf(buf, "%x %x %x", &addr, &mask, &val); + + if (nval <= 1 || nval > 3) + return -EINVAL; + + ret = dcc_config_add(drvdata, addr, 1, false, curr_list); + if (ret) + return ret; + + return dcc_rd_mod_wr_add(drvdata, mask, val, curr_list); +} + +static int dcc_add_write(struct dcc_drvdata *drvdata, unsigned int addr, + unsigned int write_val, int apb_bus, int curr_list) +{ + struct dcc_config_entry *entry; + + entry = devm_kzalloc(drvdata->dev, sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->desc_type = DCC_WRITE_TYPE; + entry->base = addr & GENMASK(31, 4); + entry->offset = addr - entry->base; + entry->write_val = write_val; + entry->len = 1; + entry->apb_bus = apb_bus; + list_add_tail(&entry->list, &drvdata->cfg_head[curr_list]); + + return 0; +} + +static ssize_t dcc_config_add_write(struct dcc_drvdata *drvdata, char *buf, int curr_list) +{ + bool bus; + int nval; + unsigned int addr, write_val; + char apb_bus[4]; + + nval = sscanf(buf, "%x %x %3s", &addr, &write_val, apb_bus); + + if (nval <= 1 || nval > 3) + return -EINVAL; + + if (nval == 2) + bus = false; + + if (nval == 3) { + if (!strcmp("apb", apb_bus)) + bus = true; + else if (!strcmp("ahb", apb_bus)) + bus = false; + else + return -EINVAL; + } + + return dcc_add_write(drvdata, addr, write_val, bus, curr_list); +} + +static int config_show(struct seq_file *m, void *data) +{ + struct dcc_drvdata *drvdata = m->private; + struct dcc_config_entry *entry, *next_entry, *prev_entry, *loop_entry; + int index = 0, curr_list, i; + unsigned int loop_val[MAX_LOOP_ADDR]; + + curr_list = dcc_filp_curr_list(m->file); + if (curr_list < 0) + return curr_list; + + mutex_lock(&drvdata->mutex); + + list_for_each_entry(entry, &drvdata->cfg_head[curr_list], list) { + index++; + switch (entry->desc_type) { + case DCC_READ_WRITE_TYPE: + prev_entry = list_prev_entry(entry, list); + seq_printf(m, "RW 0x%x 0x%x 0x%x\n", + prev_entry->base + prev_entry->offset, + entry->mask, + entry->write_val); + break; + case DCC_LOOP_TYPE: + loop_entry = entry; + loop_val[0] = loop_entry->loop_cnt; + loop_entry = list_next_entry(loop_entry, list); + for (i = 0; i < (MAX_LOOP_ADDR-2); + i++, loop_entry = list_next_entry(loop_entry, list)) { + if (loop_entry->desc_type == DCC_READ_TYPE) { + loop_val[i+2] = loop_entry->base + loop_entry->offset; + } else if (loop_entry->desc_type == DCC_LOOP_TYPE) { + loop_val[i+2] = loop_entry->loop_cnt; + loop_val[1] = i; + entry = loop_entry; + break; + } + } + seq_printf(m, "L 0x%x 0x%x", loop_val[0], loop_val[1]); + for (i = 0; i < loop_val[1]; i++) + seq_printf(m, " 0x%x", loop_val[i+2]); + seq_puts(m, "\n"); + break; + case DCC_WRITE_TYPE: + seq_printf(m, "W 0x%x 0x%x %s\n", + entry->base + entry->offset, + entry->write_val, + entry->apb_bus ? "apb":"ahb"); + break; + case DCC_READ_TYPE: + if (entry->len == 1) { + next_entry = list_next_entry(entry, list); + if (next_entry && next_entry->desc_type == DCC_READ_WRITE_TYPE) + continue; + } + seq_printf(m, "R 0x%x 0x%x %s\n", + entry->base + entry->offset, + entry->len, + entry->apb_bus ? "apb":"ahb"); + } + } + mutex_unlock(&drvdata->mutex); + return 0; +} + +static int config_open(struct inode *inode, struct file *file) +{ + struct dcc_drvdata *drvdata = inode->i_private; + + return single_open(file, config_show, drvdata); +} + +static ssize_t config_write(struct file *filp, + const char __user *user_buf, size_t count, + loff_t *ppos) +{ + int ret, curr_list; + char *token, *line; + char *buf, *bufp, *temp_buff; + char *delim = " "; + struct dcc_drvdata *drvdata = filp->f_inode->i_private; + ssize_t processed_len = 0; + + if (count == 0) + return -EINVAL; + buf = kzalloc(count+1, GFP_KERNEL); + if (buf) + bufp = buf; + else + return -ENOMEM; + + ret = copy_from_user(buf, user_buf, count); + if (ret) + goto err; + + curr_list = dcc_filp_curr_list(filp); + if (curr_list < 0) { + ret = curr_list; + goto err; + } + + while (bufp[0] != '\0') { + /* Parse line by line */ + line = strsep(&bufp, "\n"); + /* When one complete line could be parsed */ + if (line && bufp) { + processed_len += strlen(line) + 1; + if (drvdata->temp_buff_ptr && drvdata->temp_buff_ptr[curr_list]) { + temp_buff = drvdata->temp_buff_ptr[curr_list]; + /* Size of combined string must not be greater than + * allowed line size. + */ + if (strlen(line) + strlen(temp_buff) + 1 > LINE_BUFFER_MAX_SZ) { + dev_err(drvdata->dev, "Invalid input\n"); + ret = -EINVAL; + goto err; + } + strlcat(temp_buff, line, PAGE_SIZE); + line = temp_buff; + kfree(temp_buff); + drvdata->temp_buff_ptr[curr_list] = NULL; + } + + token = strsep(&line, delim); + + if (!strcmp("R", token)) { + ret = dcc_config_add_read(drvdata, line, curr_list); + } else if (!strcmp("W", token)) { + ret = dcc_config_add_write(drvdata, line, curr_list); + } else if (!strcmp("RW", token)) { + ret = dcc_config_add_read_write(drvdata, line, curr_list); + } else if (!strcmp("L", token)) { + ret = dcc_config_add_loop(drvdata, line, curr_list); + } else { + dev_err(drvdata->dev, "%s is not a correct input\n", token); + ret = -EINVAL; + } + + if (ret) + goto err; + } else { + /* Save the incomplete line to a temporary buffer and rejoin it later */ + if (!drvdata->temp_buff_ptr) { + drvdata->temp_buff_ptr = devm_kcalloc(drvdata->dev, + drvdata->max_link_list, + sizeof(char *), + GFP_KERNEL); + if (!drvdata->temp_buff_ptr) { + ret = -ENOMEM; + goto err; + } + } + drvdata->temp_buff_ptr[curr_list] = kzalloc(LINE_BUFFER_MAX_SZ, + GFP_KERNEL); + temp_buff = drvdata->temp_buff_ptr[curr_list]; + if (!temp_buff) { + ret = -ENOMEM; + goto err; + } + if ((count - processed_len) >= LINE_BUFFER_MAX_SZ) { + dev_err(drvdata->dev, "Invalid input\n"); + ret = -EINVAL; + goto err; + } + memcpy(temp_buff, line, count - processed_len); + temp_buff[count - processed_len + 1] = '\0'; + processed_len += (strlen(temp_buff) + 1); + break; + } + } + + kfree(buf); + return processed_len; + +err: + kfree(buf); + if (drvdata->temp_buff_ptr && drvdata->temp_buff_ptr[curr_list]) { + kfree(drvdata->temp_buff_ptr[curr_list]); + drvdata->temp_buff_ptr[curr_list] = NULL; + } + return ret; +} + +static const struct file_operations config_fops = { + .open = config_open, + .read = seq_read, + .write = config_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static void dcc_delete_debug_dir(struct dcc_drvdata *drvdata) +{ + debugfs_remove_recursive(drvdata->dbg_dir); +}; + +static void dcc_create_debug_dir(struct dcc_drvdata *drvdata) +{ + int i; + char list_num[10]; + struct dentry *dcc_dev, *list; + struct device *dev = drvdata->dev; + + drvdata->dbg_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); + dcc_dev = debugfs_create_dir(dev_name(dev), drvdata->dbg_dir); + + for (i = 0; i < drvdata->max_link_list; i++) { + snprintf(list_num, sizeof(list_num), "%d", i); + list = debugfs_create_dir(list_num, dcc_dev); + debugfs_create_file("enable", 0600, list, drvdata, &enable_fops); + debugfs_create_file("config", 0600, list, drvdata, &config_fops); + } + + debugfs_create_file("trigger", 0200, drvdata->dbg_dir, drvdata, &trigger_fops); + debugfs_create_file("ready", 0400, drvdata->dbg_dir, drvdata, &ready_fops); + debugfs_create_file("config_reset", 0200, drvdata->dbg_dir, drvdata, &config_reset_fops); + debugfs_create_file("loop_offset", 0400, drvdata->dbg_dir, drvdata, &loop_offset_fops); +} + +static ssize_t dcc_sram_read(struct file *file, char __user *data, + size_t len, loff_t *ppos) +{ + unsigned char *buf; + struct dcc_drvdata *drvdata; + + drvdata = container_of(file->private_data, struct dcc_drvdata, + sram_dev); + + /* EOF check */ + if (*ppos >= drvdata->ram_size) + return 0; + + if ((*ppos + len) > drvdata->ram_size) + len = (drvdata->ram_size - *ppos); + + buf = kzalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memcpy_fromio(buf, drvdata->ram_base + *ppos, len); + + if (copy_to_user(data, buf, len)) { + kfree(buf); + return -EFAULT; + } + + *ppos += len; + + kfree(buf); + + return len; +} + +static void dcc_configure_list(struct dcc_drvdata *drvdata, struct device_node *np) +{ + const char *prop; + int ret, curr_list, index = 0; + char *token, *bufp; + char *delim = " "; + u32 len, processed_len = 0; + + ret = of_property_read_u32(np, "qcom,curr-link-list", + &curr_list); + if (ret) + return; + + if(!of_get_property(np, "qcom,link-list", &len)) + return; + + bufp = kzalloc(len+1, GFP_KERNEL); + if (!bufp) + return; + + while (!of_property_read_string_index(np, "qcom,link-list", index, &prop)) { + strncpy(bufp, prop, strlen(prop)); + bufp[strlen(prop)] = '\0'; + + processed_len += strlen(bufp) + 1; + + token = strsep(&bufp, delim); + + if (!strcmp("R", token)) { + ret = dcc_config_add_read(drvdata, bufp, curr_list); + } else if (!strcmp("W", token)) { + ret = dcc_config_add_write(drvdata, bufp, curr_list); + } else if (!strcmp("RW", token)) { + ret = dcc_config_add_read_write(drvdata, bufp, curr_list); + } else if (!strcmp("L", token)) { + ret = dcc_config_add_loop(drvdata, bufp, curr_list); + } else { + dev_err(drvdata->dev, "%s is not a correct input\n", token); + ret = -EINVAL; + } + + if (ret < 0) + dev_err(drvdata->dev, "Configure line %s failed\n", prop); + + index++; + } + + dcc_enable(drvdata, curr_list); + kfree(bufp); +} + +static const struct file_operations dcc_sram_fops = { + .owner = THIS_MODULE, + .read = dcc_sram_read, +}; + +static int dcc_sram_dev_init(struct dcc_drvdata *drvdata) +{ + drvdata->sram_dev.minor = MISC_DYNAMIC_MINOR; + drvdata->sram_dev.name = "dcc_sram"; + drvdata->sram_dev.fops = &dcc_sram_fops; + + return misc_register(&drvdata->sram_dev); +} + +static void dcc_sram_dev_exit(struct dcc_drvdata *drvdata) +{ + misc_deregister(&drvdata->sram_dev); +} + +static int dcc_probe(struct platform_device *pdev) +{ + u32 val; + int ret = 0, i; + struct device *dev = &pdev->dev; + struct dcc_drvdata *drvdata; + struct resource *res; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + drvdata->dev = &pdev->dev; + platform_set_drvdata(pdev, drvdata); + + drvdata->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(drvdata->base)) + return PTR_ERR(drvdata->base); + + drvdata->ram_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res); + if (IS_ERR(drvdata->ram_base)) + return PTR_ERR(drvdata->ram_base); + + drvdata->ram_size = resource_size(res); + ret = of_property_read_u32(pdev->dev.of_node, "qcom,dcc-offset", + &drvdata->ram_offset); + if (ret) + return -EINVAL; + + drvdata->mem_map_ver = (u64)of_device_get_match_data(&pdev->dev); + + switch (drvdata->mem_map_ver) { + case MEM_MAP_VER3: + case MEM_MAP_VER2: + drvdata->max_link_list = readl(drvdata->base + DCC_LL_NUM_INFO); + if (!drvdata->max_link_list) + return -EINVAL; + break; + case MEM_MAP_VER1: + drvdata->max_link_list = DCC_MAX_LINK_LIST; + break; + default: + dev_err(drvdata->dev, "Unsupported memory map version.\n"); + return -EINVAL; + } + + val = readl(drvdata->base + DCC_HW_INFO); + /* Either set the fixed loop offset or calculate + * it from the total number of words in dcc_sram. + * Max consecutive addresses dcc can loop is + * equivalent to the words in dcc_sram. + */ + if (val & DCC_LOOP_OFFSET_MASK) + drvdata->loop_shift = DCC_FIX_LOOP_OFFSET; + else + drvdata->loop_shift = get_bitmask_order((drvdata->ram_offset + + drvdata->ram_size) / DCC_SRAM_WORD_LENGTH - 1); + + mutex_init(&drvdata->mutex); + + drvdata->enable_bitmap = devm_kcalloc(dev, BITS_TO_LONGS(drvdata->max_link_list), + sizeof(*drvdata->enable_bitmap), GFP_KERNEL); + if (!drvdata->enable_bitmap) + return -ENOMEM; + + drvdata->cfg_head = devm_kcalloc(dev, drvdata->max_link_list, + sizeof(*drvdata->cfg_head), GFP_KERNEL); + if (!drvdata->cfg_head) + return -ENOMEM; + + for (i = 0; i < drvdata->max_link_list; i++) + INIT_LIST_HEAD(&drvdata->cfg_head[i]); + + ret = dcc_sram_dev_init(drvdata); + if (ret) { + dev_err(drvdata->dev, "DCC: sram node not registered.\n"); + return ret; + } + + dcc_create_debug_dir(drvdata); + dcc_configure_list(drvdata, pdev->dev.of_node); + + return 0; +} + +static void dcc_remove(struct platform_device *pdev) +{ + struct dcc_drvdata *drvdata = platform_get_drvdata(pdev); + + dcc_delete_debug_dir(drvdata); + dcc_sram_dev_exit(drvdata); + dcc_config_reset(drvdata); +} + +static const struct of_device_id dcc_match_table[] = { + { .compatible = "qcom,dcc-v1", .data = (void *)MEM_MAP_VER1 }, + { .compatible = "qcom,dcc-v2", .data = (void *)MEM_MAP_VER2 }, + { .compatible = "qcom,dcc-v3", .data = (void *)MEM_MAP_VER3 }, + { } +}; +MODULE_DEVICE_TABLE(of, dcc_match_table); + +static struct platform_driver dcc_driver = { + .probe = dcc_probe, + .remove = dcc_remove, + .driver = { + .name = "qcom-dcc", + .of_match_table = dcc_match_table, + }, +}; + +module_platform_driver(dcc_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm Technologies Inc. DCC driver"); From 3b6145633a3a0db9d74330d7ef1c442f8ca7adb9 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 8 Jan 2026 11:28:06 +0800 Subject: [PATCH 0037/1133] QCLINUX: add qcom_debug.config for debug features The config file is created to contain specific debug features such as DCC/memory dump driver. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 1 + 1 file changed, 1 insertion(+) create mode 100644 arch/arm64/configs/qcom_debug.config diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config new file mode 100644 index 0000000000000..874f80f29d314 --- /dev/null +++ b/arch/arm64/configs/qcom_debug.config @@ -0,0 +1 @@ +CONFIG_QCOM_DCC=m From adff183d0674cf441e3051a9184066ab59e45652 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 8 Jan 2026 17:47:45 +0800 Subject: [PATCH 0038/1133] QCLINUX: qcom-dcc: add qcom-dcc dev driver Create qcom-dcc dev driver for matching the qcom-dcc driver without DT. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 1 + drivers/misc/Kconfig | 8 +- drivers/misc/Makefile | 1 + drivers/misc/qcom-dcc-dev.c | 116 +++++++++++++++++++++++++++ drivers/misc/qcom-dcc.c | 79 ++---------------- drivers/misc/qcom-dcc.h | 20 +++++ 6 files changed, 153 insertions(+), 72 deletions(-) create mode 100644 drivers/misc/qcom-dcc-dev.c create mode 100644 drivers/misc/qcom-dcc.h diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index 874f80f29d314..eb2b32af3b40b 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1 +1,2 @@ CONFIG_QCOM_DCC=m +CONFIG_QCOM_DCC_DEV=m diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index ea580f30da06f..5e7c93b5a517c 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -276,13 +276,19 @@ config QCOM_FASTRPC module. config QCOM_DCC - tristate "Qualcomm Technologies, Inc. Data Capture and Compare (DCC) engine driver" + tristate "Qualcomm Data Capture and Compare (DCC) engine driver" depends on ARCH_QCOM || COMPILE_TEST help This option enables the driver for the Data Capture and Compare engine. DCC driver provides interfaces to configure DCC block and read back the captured data from the DCC's internal SRAM. The module name for this is qcom-dcc. +config QCOM_DCC_DEV + tristate "Qualcomm Data Capture and Compare (DCC) engine device instance" + depends on QCOM_DCC + help + This is the device instance of the QCOM DCC driver. + config APDS9802ALS tristate "Medfield Avago APDS9802 ALS Sensor module" depends on I2C diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 50e0f3f54f9a4..48079fc22641c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -71,4 +71,5 @@ obj-y += keba/ obj-y += amd-sbi/ obj-$(CONFIG_MISC_RP1) += rp1/ obj-$(CONFIG_QCOM_DCC) += qcom-dcc.o +obj-$(CONFIG_QCOM_DCC_DEV) += qcom-dcc-dev.o obj-$(CONFIG_INTEL_SSEI) += issei/ diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c new file mode 100644 index 0000000000000..e0eb2e61d652b --- /dev/null +++ b/drivers/misc/qcom-dcc-dev.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include "qcom-dcc.h" + +#define DEV_NAME "qcom-dcc" + +static struct platform_device *dcc_pdev; + +static const struct dcc_pdata talos_pdata = { + .base = 0x010a2000, + .size = 0x00001000, + .ram_base = 0x010ae000, + .ram_size = 0x00002000, + .dcc_offset = 0x6000, + .map_ver = 0x1, +}; + +static const struct dcc_pdata lemans_pdata = { + .base = 0x040ff000, + .size = 0x00001000, + .ram_base = 0x040b8800, + .ram_size = 0x00006000, + .dcc_offset = 0x38800, + .map_ver = 0x3, +}; + +static const struct dcc_pdata kodiak_pdata = { + .base = 0x0117f000, + .size = 0x00001000, + .ram_base = 0x01112000, + .ram_size = 0x00006000, + .dcc_offset = 0x12000, + .map_ver = 0x2, +}; + +static int __init dcc_dev_init(void) +{ + int ret; + u32 soc_id; + + dcc_pdev = platform_device_alloc(DEV_NAME, -1); + if (!dcc_pdev) + return -ENOMEM; + + ret = qcom_smem_get_soc_id(&soc_id); + if (ret) + goto fail; + + switch (soc_id) { + case 475: + case 497: + case 498: + case 515: + ret = platform_device_add_data(dcc_pdev, &kodiak_pdata, sizeof(kodiak_pdata)); + if (ret) + goto fail; + + break; + case 534: + case 606: + case 667: + case 674: + case 675: + case 676: + ret = platform_device_add_data(dcc_pdev, &lemans_pdata, sizeof(lemans_pdata)); + if (ret) + goto fail; + + break; + case 377: + case 380: + case 384: + case 401: + case 406: + case 680: + ret = platform_device_add_data(dcc_pdev, &talos_pdata, sizeof(talos_pdata)); + if (ret) + goto fail; + + break; + default: + pr_err("DCC: Invalid SoC ID\n"); + ret = -EINVAL; + goto fail; + } + + ret = platform_device_add(dcc_pdev); + if (ret) + goto fail; + + pr_info("DCC platform device has registered\n"); + + return 0; + +fail: + pr_err("Failed to register DCC platform device\n"); + platform_device_put(dcc_pdev); + + return ret; +} + +static void __exit dcc_dev_exit(void) +{ + platform_device_unregister(dcc_pdev); +} + +module_init(dcc_dev_init); +module_exit(dcc_dev_exit); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm Technologies Inc. DCC driver, device stub"); diff --git a/drivers/misc/qcom-dcc.c b/drivers/misc/qcom-dcc.c index a511faac5d4b0..e75f98b90d8f7 100644 --- a/drivers/misc/qcom-dcc.c +++ b/drivers/misc/qcom-dcc.c @@ -135,6 +135,8 @@ #include #include +#include "qcom-dcc.h" + #define STATUS_READY_TIMEOUT 5000 /* microseconds */ /* DCC registers */ @@ -1423,57 +1425,6 @@ static ssize_t dcc_sram_read(struct file *file, char __user *data, return len; } -static void dcc_configure_list(struct dcc_drvdata *drvdata, struct device_node *np) -{ - const char *prop; - int ret, curr_list, index = 0; - char *token, *bufp; - char *delim = " "; - u32 len, processed_len = 0; - - ret = of_property_read_u32(np, "qcom,curr-link-list", - &curr_list); - if (ret) - return; - - if(!of_get_property(np, "qcom,link-list", &len)) - return; - - bufp = kzalloc(len+1, GFP_KERNEL); - if (!bufp) - return; - - while (!of_property_read_string_index(np, "qcom,link-list", index, &prop)) { - strncpy(bufp, prop, strlen(prop)); - bufp[strlen(prop)] = '\0'; - - processed_len += strlen(bufp) + 1; - - token = strsep(&bufp, delim); - - if (!strcmp("R", token)) { - ret = dcc_config_add_read(drvdata, bufp, curr_list); - } else if (!strcmp("W", token)) { - ret = dcc_config_add_write(drvdata, bufp, curr_list); - } else if (!strcmp("RW", token)) { - ret = dcc_config_add_read_write(drvdata, bufp, curr_list); - } else if (!strcmp("L", token)) { - ret = dcc_config_add_loop(drvdata, bufp, curr_list); - } else { - dev_err(drvdata->dev, "%s is not a correct input\n", token); - ret = -EINVAL; - } - - if (ret < 0) - dev_err(drvdata->dev, "Configure line %s failed\n", prop); - - index++; - } - - dcc_enable(drvdata, curr_list); - kfree(bufp); -} - static const struct file_operations dcc_sram_fops = { .owner = THIS_MODULE, .read = dcc_sram_read, @@ -1499,7 +1450,7 @@ static int dcc_probe(struct platform_device *pdev) int ret = 0, i; struct device *dev = &pdev->dev; struct dcc_drvdata *drvdata; - struct resource *res; + const struct dcc_pdata *pdata = dev_get_platdata(dev); drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) @@ -1508,21 +1459,17 @@ static int dcc_probe(struct platform_device *pdev) drvdata->dev = &pdev->dev; platform_set_drvdata(pdev, drvdata); - drvdata->base = devm_platform_ioremap_resource(pdev, 0); + drvdata->base = devm_ioremap(dev, pdata->base, pdata->size); if (IS_ERR(drvdata->base)) return PTR_ERR(drvdata->base); - drvdata->ram_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res); + drvdata->ram_base = devm_ioremap(dev, pdata->ram_base, pdata->ram_size); if (IS_ERR(drvdata->ram_base)) return PTR_ERR(drvdata->ram_base); - drvdata->ram_size = resource_size(res); - ret = of_property_read_u32(pdev->dev.of_node, "qcom,dcc-offset", - &drvdata->ram_offset); - if (ret) - return -EINVAL; - - drvdata->mem_map_ver = (u64)of_device_get_match_data(&pdev->dev); + drvdata->ram_size = pdata->ram_size; + drvdata->ram_offset = pdata->dcc_offset; + drvdata->mem_map_ver = pdata->map_ver; switch (drvdata->mem_map_ver) { case MEM_MAP_VER3: @@ -1573,7 +1520,6 @@ static int dcc_probe(struct platform_device *pdev) } dcc_create_debug_dir(drvdata); - dcc_configure_list(drvdata, pdev->dev.of_node); return 0; } @@ -1587,20 +1533,11 @@ static void dcc_remove(struct platform_device *pdev) dcc_config_reset(drvdata); } -static const struct of_device_id dcc_match_table[] = { - { .compatible = "qcom,dcc-v1", .data = (void *)MEM_MAP_VER1 }, - { .compatible = "qcom,dcc-v2", .data = (void *)MEM_MAP_VER2 }, - { .compatible = "qcom,dcc-v3", .data = (void *)MEM_MAP_VER3 }, - { } -}; -MODULE_DEVICE_TABLE(of, dcc_match_table); - static struct platform_driver dcc_driver = { .probe = dcc_probe, .remove = dcc_remove, .driver = { .name = "qcom-dcc", - .of_match_table = dcc_match_table, }, }; diff --git a/drivers/misc/qcom-dcc.h b/drivers/misc/qcom-dcc.h new file mode 100644 index 0000000000000..513c95dc742b5 --- /dev/null +++ b/drivers/misc/qcom-dcc.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_H +#define _QCOM_DCC_H + +#include + +struct dcc_pdata { + phys_addr_t base; + resource_size_t size; + phys_addr_t ram_base; + resource_size_t ram_size; + u32 dcc_offset; + u8 map_ver; +}; + +#endif From f4bca8fc7d33cbbb6af313b72cd26ee978c07fc5 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 9 Jan 2026 14:42:21 +0800 Subject: [PATCH 0039/1133] QCLINUX: memory-dump: add QCOM memory dump driver The memory dump driver allows various client subsystems to register respective dump regions. At the time of deadlocks or cpu hangs these dump regions are captured to give a snapshot of the system at the time of the crash. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 1 + drivers/firmware/qcom/Kconfig | 9 + drivers/firmware/qcom/Makefile | 1 + drivers/firmware/qcom/memory_dump_v2.c | 1143 +++++++++++++++++++++ include/linux/firmware/qcom/memory_dump.h | 136 +++ 5 files changed, 1290 insertions(+) create mode 100644 drivers/firmware/qcom/memory_dump_v2.c create mode 100644 include/linux/firmware/qcom/memory_dump.h diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index eb2b32af3b40b..2e85e8df0469b 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1,2 +1,3 @@ CONFIG_QCOM_DCC=m CONFIG_QCOM_DCC_DEV=m +CONFIG_QCOM_MEMORY_DUMP_V2=m diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index c7f8413ab996c..2a541811c1562 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -94,4 +94,13 @@ config QCOM_QSEECOM_UEFISECAPP Select Y here to provide access to EFI variables on the aforementioned platforms. +config QCOM_MEMORY_DUMP_V2 + tristate "QCOM Memory Dump V2 Support" + depends on QCOM_TZMEM + help + This enables memory dump feature. It allows various client + subsystems to register respective dump regions. At the time + of deadlocks or cpu hangs these dump regions are captured to + give a snapshot of the system at the time of the crash. + endmenu diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile index 88ce74d74c3e2..1953b51786751 100644 --- a/drivers/firmware/qcom/Makefile +++ b/drivers/firmware/qcom/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o obj-$(CONFIG_QCOM_PAS) += qcom_pas.o obj-$(CONFIG_QCOM_PAS_TEE) += qcom_pas_tee.o +obj-$(CONFIG_QCOM_MEMORY_DUMP_V2) += memory_dump_v2.o diff --git a/drivers/firmware/qcom/memory_dump_v2.c b/drivers/firmware/qcom/memory_dump_v2.c new file mode 100644 index 0000000000000..baf4c980f39fb --- /dev/null +++ b/drivers/firmware/qcom/memory_dump_v2.c @@ -0,0 +1,1143 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014-2017, 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MSM_DUMP_TABLE_VERSION MSM_DUMP_MAKE_VERSION(2, 0) + +#define SCM_CMD_DEBUG_LAR_UNLOCK 0x4 + +#define CPUSS_REGDUMP 0xEF +#define SPR_DUMP_CPU0 0x1F0 +#define SPR_DUMP_CPU1 0x1F1 +#define SPR_DUMP_CPU2 0x1F2 +#define SPR_DUMP_CPU3 0x1F3 +#define SPR_DUMP_CPU4 0x1F4 +#define SPR_DUMP_CPU5 0x1F5 +#define SPR_DUMP_CPU6 0x1F6 +#define SPR_DUMP_CPU7 0x1F7 +#define SPR_DATA_HEADER_SIZE 5 +#define SPR_DATA_HEADER_TAIL_SIZE 1 +#define SPR_INPUT_DATA_TAIL_SIZE 1 +#define SPR_INPUT_DATA_SIZE 1 +#define SPR_OUTPUT_DATA_SIZE 2 +#define MAX_CORE_NUM 8 + +#define INPUT_DATA_BY_HLOS 0x00C0FFEE +#define FORMAT_VERSION_1 0x1 +#define FORMAT_VERSION_2 0x2 +#define CORE_REG_NUM_DEFAULT 0x1 + +#define MAGIC_INDEX 0 +#define FORMAT_VERSION_INDEX 1 +#define SYS_REG_INPUT_INDEX 2 +#define OUTPUT_DUMP_INDEX 3 +#define PERCORE_INDEX 4 +#define SYSTEM_REGS_INPUT_INDEX 5 + +#define CMD_REPEAT_READ (0x2 << 24) +#define CMD_DELAY (0x1 << 24) +#define CMD_READ 0x0 +#define CMD_READ_WORD 0x1 +#define CMD_WRITE 0x2 +#define CMD_EXTRA 0x3 + +#define CMD_MASK 0x3 +#define OFFSET_MASK GENMASK(31, 2) +#define EXTRA_CMD_MASK GENMASK(31, 24) +#define EXTRA_VALUE_MASK GENMASK(23, 0) +#define MAX_EXTRA_VALUE 0xffffff + +struct sprs_dump_data { + void *dump_vaddr; + u32 size; + u32 sprs_data_index; + u32 used_memory; +}; + +struct cpuss_regdump_data { + void *dump_vaddr; + u32 size; + u32 core_reg_num; + u32 core_reg_used_num; + u32 core_reg_end_index; + u32 sys_reg_size; + u32 used_memory; +}; + +struct cpuss_dump_data { + struct mutex mutex; + struct cpuss_regdump_data *cpussregdata; + struct sprs_dump_data *sprdata[MAX_CORE_NUM]; +}; + +struct reg_dump_data { + uint32_t magic; + uint32_t version; + uint32_t system_regs_input_index; + uint32_t regdump_output_byte_offset; +}; + +struct msm_dump_table { + uint32_t version; + uint32_t num_entries; + struct msm_dump_entry entries[MAX_NUM_ENTRIES]; +}; + +struct msm_memory_dump { + uint64_t table_phys; + struct msm_dump_table *table; +}; + +/** + * Set bit 0 if percore reg dump initialized. + * Set bit 1 if spr dump initialized. + */ +#define PERCORE_REG_INITIALIZED BIT(0) +#define SPRS_INITIALIZED BIT(1) + +static struct msm_memory_dump memdump; + +/** + * reset_sprs_dump_table - reset the sprs dump table + * + * This function calculates system_regs_input_index and + * regdump_output_byte_offset to store into the dump memory. + * It also updates members of cpudata by the parameter core_reg_num. + * + * Returns 0 on success, or -ENOMEM on error of no enough memory. + */ +static int reset_sprs_dump_table(struct device *dev) +{ + int ret = 0; + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + int i = 0; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + for (i = 0; i < MAX_CORE_NUM; i++) { + if (cpudata->sprdata[i]) { + cpudata->sprdata[i]->sprs_data_index = 0; + cpudata->sprdata[i]->used_memory = (SPR_DATA_HEADER_SIZE + + SPR_INPUT_DATA_TAIL_SIZE) * sizeof(uint32_t); + memset(cpudata->sprdata[i]->dump_vaddr, 0xDE, + cpudata->sprdata[i]->size); + p = (struct reg_dump_data *)cpudata->sprdata[i]->dump_vaddr; + p->magic = INPUT_DATA_BY_HLOS; + p->version = FORMAT_VERSION_1; + p->system_regs_input_index = SYSTEM_REGS_INPUT_INDEX; + p->regdump_output_byte_offset = (SPR_DATA_HEADER_SIZE + + SPR_INPUT_DATA_TAIL_SIZE) * sizeof(uint32_t); + memset((uint32_t *)cpudata->sprdata[i]->dump_vaddr + + PERCORE_INDEX, 0x0, (SPR_DATA_HEADER_TAIL_SIZE + + SPR_INPUT_DATA_TAIL_SIZE) * sizeof(uint32_t)); + } + } + + mutex_unlock(&cpudata->mutex); + return ret; +} + + +/** + * update_reg_dump_table - update the register dump table + * @core_reg_num: the number of per-core registers + * + * This function calculates system_regs_input_index and + * regdump_output_byte_offset to store into the dump memory. + * It also updates members of cpudata by the parameter core_reg_num. + * + * Returns 0 on success, or -ENOMEM on error of no enough memory. + */ +static int update_reg_dump_table(struct device *dev, u32 core_reg_num) +{ + int ret = 0; + u32 system_regs_input_index = SYSTEM_REGS_INPUT_INDEX + + core_reg_num * 2; + u32 regdump_output_byte_offset = (system_regs_input_index + 1) + * sizeof(uint32_t); + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + mutex_lock(&cpudata->mutex); + + if (regdump_output_byte_offset >= cpudata->cpussregdata->size || + regdump_output_byte_offset / sizeof(uint32_t) + < system_regs_input_index + 1) { + ret = -ENOMEM; + goto err; + } + + cpudata->cpussregdata->core_reg_num = core_reg_num; + cpudata->cpussregdata->core_reg_used_num = 0; + cpudata->cpussregdata->core_reg_end_index = PERCORE_INDEX; + cpudata->cpussregdata->sys_reg_size = 0; + cpudata->cpussregdata->used_memory = regdump_output_byte_offset; + + memset(cpudata->cpussregdata->dump_vaddr, 0xDE, cpudata->cpussregdata->size); + p = (struct reg_dump_data *)cpudata->cpussregdata->dump_vaddr; + p->magic = INPUT_DATA_BY_HLOS; + p->version = FORMAT_VERSION_2; + p->system_regs_input_index = system_regs_input_index; + p->regdump_output_byte_offset = regdump_output_byte_offset; + memset((uint32_t *)cpudata->cpussregdata->dump_vaddr + PERCORE_INDEX, 0x0, + (system_regs_input_index - PERCORE_INDEX + 1) + * sizeof(uint32_t)); + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} + +static ssize_t core_reg_num_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + ret = scnprintf(buf, PAGE_SIZE, "%u\n", cpudata->cpussregdata->core_reg_num); + + mutex_unlock(&cpudata->mutex); + return ret; +} + +static ssize_t core_reg_num_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + unsigned int val; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + if (kstrtouint(buf, 16, &val)) + return -EINVAL; + + mutex_lock(&cpudata->mutex); + + if (cpudata->cpussregdata->core_reg_used_num || cpudata->cpussregdata->sys_reg_size) { + dev_err(dev, "Couldn't set core_reg_num, register available in list\n"); + ret = -EPERM; + goto err; + } + if (val == cpudata->cpussregdata->core_reg_num) { + mutex_unlock(&cpudata->mutex); + return size; + } + + mutex_unlock(&cpudata->mutex); + + ret = update_reg_dump_table(dev, val); + if (ret) { + dev_err(dev, "Couldn't set core_reg_num, no enough memory\n"); + return ret; + } + + return size; + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RW(core_reg_num); + +/** + * This function shows configs of per-core and system registers. + */ +static ssize_t register_config_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char local_buf[64]; + int len = 0, count = 0; + int index, system_index_start, index_end; + uint32_t register_offset, val; + uint32_t *p, cmd; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + buf[0] = '\0'; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + p = (uint32_t *)cpudata->cpussregdata->dump_vaddr; + + /* print per-core & system registers */ + len = scnprintf(local_buf, 64, "per-core registers:\n"); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + + system_index_start = *(p + SYS_REG_INPUT_INDEX); + index_end = system_index_start + + cpudata->cpussregdata->sys_reg_size / sizeof(uint32_t) + 1; + for (index = PERCORE_INDEX; index < index_end;) { + if (index == system_index_start) { + len = scnprintf(local_buf, 64, "system registers:\n"); + if ((count + len) > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + } + + register_offset = *(p + index); + if (register_offset == 0) { + index++; + continue; + } + + cmd = register_offset & CMD_MASK; + register_offset &= OFFSET_MASK; + + switch (cmd) { + case CMD_READ: + val = *(p + index + 1); + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, r\n", + register_offset, val); + index += 2; + break; + case CMD_READ_WORD: + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, r\n", + register_offset, 0x4); + index++; + break; + case CMD_WRITE: + val = *(p + index + 1); + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, w\n", + register_offset, val); + index += 2; + break; + case CMD_EXTRA: + val = *(p + index + 1); + cmd = val & EXTRA_CMD_MASK; + val &= EXTRA_VALUE_MASK; + if (cmd == CMD_DELAY) + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, d\n", + register_offset, val); + else + len = scnprintf(local_buf, 64, + "0x%x, 0x%x, R\n", + register_offset, val); + index += 2; + break; + } + + if ((count + len) > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + } + + mutex_unlock(&cpudata->mutex); + return count; +} + +static int config_cpuss_register(struct device *dev, + uint32_t *p, uint32_t index, char cmd, + uint32_t register_offset, uint32_t val) +{ + int ret = 0; + + switch (cmd) { + case 'r': + if (val > 4) { + *(p + index) = register_offset; + *(p + index + 1) = val; + } else { + *(p + index) = register_offset | CMD_READ_WORD; + } + break; + case 'R': + if (val > MAX_EXTRA_VALUE) { + dev_err(dev, "repeat read time exceeded the limit\n"); + ret = -EINVAL; + return ret; + } + *(p + index) = register_offset | CMD_EXTRA; + *(p + index + 1) = val | CMD_REPEAT_READ; + break; + case 'd': + if (val > MAX_EXTRA_VALUE) { + dev_err(dev, "sleep time exceeded the limit\n"); + ret = -EINVAL; + return ret; + } + *(p + index) = CMD_EXTRA; + *(p + index + 1) = val | CMD_DELAY; + break; + case 'w': + *(p + index) = register_offset | CMD_WRITE; + *(p + index + 1) = val; + break; + default: + dev_err(dev, "Don't support this command\n"); + ret = -EINVAL; + } + return ret; +} +/** + * This function sets configs of per-core or system registers. + */ +static ssize_t register_config_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + uint32_t register_offset, val, reserve_size = 4, per_core = 0; + int nval; + char cmd; + uint32_t num_cores; + u32 extra_memory; + u32 used_memory; + u32 system_reg_end_index; + uint32_t *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + nval = sscanf(buf, "%x %x %c %u", ®ister_offset, + &val, &cmd, &per_core); + if (nval < 2) + return -EINVAL; + if (nval == 2) + cmd = 'r'; + if (per_core > 1) + return -EINVAL; + if (register_offset & 0x3) { + dev_err(dev, "Invalid address, must be 4 byte aligned\n"); + return -EINVAL; + } + + if (cmd == 'r' || cmd == 'R') { + if (val == 0) { + dev_err(dev, "Invalid length of 0\n"); + return -EINVAL; + } + if (cmd == 'r' && val & 0x3) { + dev_err(dev, "Invalid length, must be 4 byte aligned\n"); + return -EINVAL; + } + if (cmd == 'R') + reserve_size = val * 4; + else + reserve_size = val; + } + + mutex_lock(&cpudata->mutex); + + p = (uint32_t *)cpudata->cpussregdata->dump_vaddr; + if (per_core) { /* per-core register */ + if (cpudata->cpussregdata->core_reg_used_num == + cpudata->cpussregdata->core_reg_num) { + dev_err(dev, "Couldn't add per-core config, out of range\n"); + ret = -EINVAL; + goto err; + } + + num_cores = num_possible_cpus(); + extra_memory = reserve_size * num_cores; + used_memory = cpudata->cpussregdata->used_memory + extra_memory; + if (extra_memory / num_cores < reserve_size || + used_memory > cpudata->cpussregdata->size || + used_memory < cpudata->cpussregdata->used_memory) { + dev_err(dev, "Couldn't add per-core reg config, no enough memory\n"); + ret = -ENOMEM; + goto err; + } + + ret = config_cpuss_register(dev, p, cpudata->cpussregdata->core_reg_end_index, + cmd, register_offset, val); + if (ret) + goto err; + + if (cmd == 'r' && val == 4) + cpudata->cpussregdata->core_reg_end_index++; + else + cpudata->cpussregdata->core_reg_end_index += 2; + + cpudata->cpussregdata->core_reg_used_num++; + cpudata->cpussregdata->used_memory = used_memory; + } else { /* system register */ + system_reg_end_index = *(p + SYS_REG_INPUT_INDEX) + + cpudata->cpussregdata->sys_reg_size / sizeof(uint32_t); + + if (cmd == 'r' && reserve_size == 4) + extra_memory = sizeof(uint32_t) + reserve_size; + else + extra_memory = sizeof(uint32_t) * 2 + reserve_size; + + used_memory = cpudata->cpussregdata->used_memory + extra_memory; + if (extra_memory < reserve_size || + used_memory > cpudata->cpussregdata->size || + used_memory < cpudata->cpussregdata->used_memory) { + dev_err(dev, "Couldn't add system reg config, no enough memory\n"); + ret = -ENOMEM; + goto err; + } + + ret = config_cpuss_register(dev, p, system_reg_end_index, + cmd, register_offset, val); + if (ret) + goto err; + + if (cmd == 'r' && val == 4) { + system_reg_end_index++; + cpudata->cpussregdata->sys_reg_size += sizeof(uint32_t); + } else { + system_reg_end_index += 2; + cpudata->cpussregdata->sys_reg_size += sizeof(uint32_t) * 2; + } + + cpudata->cpussregdata->used_memory = used_memory; + *(p + system_reg_end_index) = 0x0; + *(p + OUTPUT_DUMP_INDEX) = (system_reg_end_index + 1) + * sizeof(uint32_t); + } + + ret = size; + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RW(register_config); + +static ssize_t format_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + p = (struct reg_dump_data *)cpudata->cpussregdata->dump_vaddr; + ret = scnprintf(buf, PAGE_SIZE, "%u\n", p->version); + + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RO(format_version); +/** + * This function resets the register dump table. + */ +static ssize_t register_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned int val; + + if (kstrtouint(buf, 16, &val)) + return -EINVAL; + if (val != 1) + return -EINVAL; + + update_reg_dump_table(dev, CORE_REG_NUM_DEFAULT); + + return size; +} +static DEVICE_ATTR_WO(register_reset); + +/** + * This function shows configs of per-core spr dump. + */ +static ssize_t spr_config_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char local_buf[64]; + int len = 0, count = 0; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + int i = 0, index = 0; + uint32_t *p; + + buf[0] = '\0'; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + len = scnprintf(local_buf, 64, "spr data list below:\n"); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + + for (i = 0; i < MAX_CORE_NUM; i++) { + if (count > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + if (!cpudata->sprdata[i]) { + dev_err(dev, "SPR data pinter for CPU%d is empty\n", i); + continue; + } + p = (uint32_t *)cpudata->sprdata[i]->dump_vaddr; + len = scnprintf(local_buf, 64, "spr data for CPU[%d] below:\n", i); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + index = 0; + while (index < cpudata->sprdata[i]->sprs_data_index) { + if (count > PAGE_SIZE) { + dev_err(dev, "Couldn't write complete config\n"); + break; + } + len = scnprintf(local_buf, 64, "%d\n", *(p + SPR_DATA_HEADER_SIZE + index)); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + index++; + } + } + + mutex_unlock(&cpudata->mutex); + return count; +} + +/** + * This function sets configs for sprs dump. + */ +static ssize_t spr_config_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + uint32_t spr_data, cpu_num; + uint32_t index; + int nval; + uint32_t *p; + u32 reserved = 0; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + nval = sscanf(buf, "%d %d", &spr_data, &cpu_num); + if (nval != 2) + return -EINVAL; + if (!cpudata) + return -EFAULT; + + if (cpu_num >= MAX_CORE_NUM) { + dev_err(dev, "Input the wrong CPU number\n"); + return -EINVAL; + } + reserved = (SPR_INPUT_DATA_SIZE + SPR_OUTPUT_DATA_SIZE) * sizeof(uint32_t); + + mutex_lock(&cpudata->mutex); + if (cpudata->sprdata[cpu_num]) { + p = (uint32_t *)cpudata->sprdata[cpu_num]->dump_vaddr; + index = cpudata->sprdata[cpu_num]->sprs_data_index; + + if (cpudata->sprdata[cpu_num]->size > + cpudata->sprdata[cpu_num]->used_memory + reserved) { + p = (uint32_t *)cpudata->sprdata[cpu_num]->dump_vaddr; + *(p + OUTPUT_DUMP_INDEX) = (SPR_DATA_HEADER_SIZE + + index + SPR_INPUT_DATA_TAIL_SIZE + 1) * sizeof(uint32_t); + *(p + SPR_DATA_HEADER_SIZE + index) = spr_data; + *(p + SPR_DATA_HEADER_SIZE + index + 1) = 0; + cpudata->sprdata[cpu_num]->sprs_data_index++; + cpudata->sprdata[cpu_num]->used_memory = + cpudata->sprdata[cpu_num]->used_memory + reserved; + } else { + dev_err(dev, "Couldn't add SPR config, no enough memory\n"); + ret = -ENOMEM; + goto err; + } + } + ret = size; + +err: + mutex_unlock(&cpudata->mutex); + return ret; +} +static DEVICE_ATTR_RW(spr_config); + +/** + * This function resets the sprs dump table. + */ +static ssize_t sprs_register_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned int val; + + if (kstrtouint(buf, 16, &val)) + return -EINVAL; + if (val != 1) + return -EINVAL; + + reset_sprs_dump_table(dev); + + return size; +} +static DEVICE_ATTR_WO(sprs_register_reset); + +static ssize_t sprs_format_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char local_buf[64]; + int len = 0, count = 0, i = 0; + struct reg_dump_data *p; + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + buf[0] = '\0'; + + if (!cpudata) + return -EFAULT; + + mutex_lock(&cpudata->mutex); + + for (i = 0; i < MAX_CORE_NUM; i++) { + if (cpudata->sprdata[i]) { + p = (struct reg_dump_data *)cpudata->sprdata[i]->dump_vaddr; + len = scnprintf(local_buf, 64, + "SPR data format version for cpu%d is %d\n", i, p->version); + strlcat(buf, local_buf, PAGE_SIZE); + count += len; + } + } + + mutex_unlock(&cpudata->mutex); + return count; +} +static DEVICE_ATTR_RO(sprs_format_version); + + +static const struct device_attribute *register_dump_attrs[] = { + &dev_attr_core_reg_num, + &dev_attr_register_config, + &dev_attr_register_reset, + &dev_attr_format_version, + NULL, +}; + +static const struct device_attribute *spr_dump_attrs[] = { + &dev_attr_spr_config, + &dev_attr_sprs_register_reset, + &dev_attr_sprs_format_version, + NULL, +}; + +static int memory_dump_create_files(struct device *dev, + const struct device_attribute **attrs) +{ + int ret = 0; + int i, j; + + for (i = 0; attrs[i] != NULL; i++) { + ret = device_create_file(dev, attrs[i]); + if (ret) { + dev_err(dev, "Couldn't create sysfs attribute: %s\n", + attrs[i]->attr.name); + for (j = 0; j < i; j++) + device_remove_file(dev, attrs[j]); + break; + } + } + return ret; +} + +static void cpuss_create_nodes(struct platform_device *pdev, + int initialized) +{ + if (initialized & PERCORE_REG_INITIALIZED) { + if (memory_dump_create_files(&pdev->dev, register_dump_attrs)) + dev_err(&pdev->dev, "Fail to create files for cpuss register dump\n"); + } + if (initialized & SPRS_INITIALIZED) { + if (memory_dump_create_files(&pdev->dev, spr_dump_attrs)) + dev_err(&pdev->dev, "Fail to create files for spr dump\n"); + } +} + +uint32_t msm_dump_table_version(void) +{ + return MSM_DUMP_TABLE_VERSION; +} +EXPORT_SYMBOL_GPL(msm_dump_table_version); + +static int msm_dump_table_register(struct msm_dump_entry *entry) +{ + struct msm_dump_entry *e; + struct msm_dump_table *table = memdump.table; + + if (!table || table->num_entries >= MAX_NUM_ENTRIES) + return -EINVAL; + + e = &table->entries[table->num_entries]; + e->id = entry->id; + e->type = MSM_DUMP_TYPE_TABLE; + e->addr = entry->addr; + table->num_entries++; + + return 0; +} + +static struct msm_dump_table *msm_dump_get_table(enum msm_dump_table_ids id) +{ + struct msm_dump_table *table = memdump.table; + int i; + unsigned long offset; + + if (!table) { + pr_err("mem dump base table does not exist\n"); + return ERR_PTR(-EINVAL); + } + + for (i = 0; i < MAX_NUM_ENTRIES; i++) { + if (table->entries[i].id == id) + break; + } + if (i == MAX_NUM_ENTRIES || !table->entries[i].addr) { + pr_err("mem dump base table entry %d invalid\n", id); + return ERR_PTR(-EINVAL); + } + + offset = table->entries[i].addr - memdump.table_phys; + /* Get the apps table pointer */ + table = (void *)memdump.table + offset; + + return table; +} + +static int register_dump_table_entry(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + struct msm_dump_entry *e; + struct msm_dump_table *table; + + table = msm_dump_get_table(id); + if (IS_ERR(table)) + return PTR_ERR(table); + + if (!table || table->num_entries >= MAX_NUM_ENTRIES) + return -EINVAL; + + e = &table->entries[table->num_entries]; + e->id = entry->id; + e->type = MSM_DUMP_TYPE_DATA; + e->addr = entry->addr; + table->num_entries++; + + return 0; +} + +/** + * msm_dump_data_register_nominidump - register to dump data framework + * @id: ID of the dump table. + * @entry: dump entry to be registered + * This api will register the entry passed to dump table only + */ +int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + return register_dump_table_entry(id, entry); +} +EXPORT_SYMBOL_GPL(msm_dump_data_register_nominidump); + +#define MSM_DUMP_TOTAL_SIZE_OFFSET 0x724 +static int init_memdump_imem_area(size_t size) +{ + struct device_node *np; + void __iomem *imem_base; + + np = of_find_compatible_node(NULL, NULL, + "qcom,msm-imem-mem-dump-table"); + if (!np) { + pr_err("mem dump base table DT node does not exist\n"); + return -ENODEV; + } + + imem_base = of_iomap(np, 0); + if (!imem_base) { + pr_err("mem dump base table imem offset mapping failed\n"); + return -ENOMEM; + } + + memcpy_toio(imem_base, &memdump.table_phys, + sizeof(memdump.table_phys)); + memcpy_toio(imem_base + MSM_DUMP_TOTAL_SIZE_OFFSET, + &size, sizeof(size_t)); + + /* Ensure write to imem_base is complete before unmapping */ + mb(); + pr_info("MSM Memory Dump base table set up in IMEM\n"); + + iounmap(imem_base); + return 0; +} + +static int init_memory_dump(void *dump_vaddr, phys_addr_t phys_addr) +{ + struct msm_dump_table *table; + struct msm_dump_entry entry; + int ret; + + memdump.table = dump_vaddr; + memdump.table->version = MSM_DUMP_TABLE_VERSION; + memdump.table_phys = phys_addr; + dump_vaddr += sizeof(*table); + phys_addr += sizeof(*table); + table = dump_vaddr; + table->version = MSM_DUMP_TABLE_VERSION; + entry.id = MSM_DUMP_TABLE_APPS; + entry.addr = phys_addr; + ret = msm_dump_table_register(&entry); + if (ret) { + pr_err("mem dump apps data table register failed\n"); + return ret; + } + pr_info("MSM Memory Dump apps data table set up\n"); + + return 0; +} + +static int mem_dump_reserve_mem(struct device *dev) +{ + struct device_node *mem_node; + int ret; + + mem_node = of_parse_phandle(dev->of_node, "memory-region", 0); + if (mem_node) { + ret = of_reserved_mem_device_init_by_idx(dev, + dev->of_node, 0); + of_node_put(dev->of_node); + if (ret) { + dev_err(dev, + "Failed to initialize reserved mem, ret %d\n", + ret); + return ret; + } + } + return 0; +} + +static int cpuss_regdump_init(struct device *dev, + void *dump_vaddr, u32 size) +{ + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + + cpudata->cpussregdata = devm_kzalloc(dev, + sizeof(struct cpuss_regdump_data), GFP_KERNEL); + + if (cpudata->cpussregdata) { + cpudata->cpussregdata->dump_vaddr = dump_vaddr; + cpudata->cpussregdata->size = size; + return 0; + } + return -ENOMEM; +} + +static int sprs_dump_init(struct device *dev, + void *dump_vaddr, u32 size, u32 id) +{ + struct cpuss_dump_data *cpudata = dev_get_drvdata(dev); + int core_num = 0; + + core_num = id - SPR_DUMP_CPU0; + + cpudata->sprdata[core_num] = devm_kzalloc(dev, + sizeof(struct sprs_dump_data), GFP_KERNEL); + if (cpudata->sprdata[core_num]) { + cpudata->sprdata[core_num]->dump_vaddr = dump_vaddr; + cpudata->sprdata[core_num]->size = size; + return 0; + } + return -ENOMEM; +} + +static int cpuss_dump_init(struct platform_device *pdev, + void *dump_vaddr, u32 size, u32 id) +{ + struct cpuss_dump_data *cpudata = dev_get_drvdata(&pdev->dev); + static int initialized; + + if (!cpudata) { + cpudata = devm_kzalloc(&pdev->dev, + sizeof(struct cpuss_dump_data), GFP_KERNEL); + if (cpudata) { + mutex_init(&cpudata->mutex); + platform_set_drvdata(pdev, cpudata); + } else + return initialized; + } + + if (id == CPUSS_REGDUMP) { + if (!cpuss_regdump_init(&pdev->dev, dump_vaddr, size)) + initialized |= PERCORE_REG_INITIALIZED; + } else { + if (!sprs_dump_init(&pdev->dev, dump_vaddr, size, id)) + initialized |= SPRS_INITIALIZED; + } + + return initialized; +} + +#define MSM_DUMP_DATA_SIZE sizeof(struct msm_dump_data) +static int mem_dump_alloc(struct platform_device *pdev) +{ + struct device_node *child_node; + const struct device_node *node = pdev->dev.of_node; + struct msm_dump_data *dump_data; + struct msm_dump_entry dump_entry; + size_t total_size; + u32 size, id; + int ret, no_of_nodes; + dma_addr_t dma_handle; + phys_addr_t phys_addr; + struct sg_table mem_dump_sgt; + void *dump_vaddr; + u64 shm_bridge_handle; + int initialized = 0; + + if (mem_dump_reserve_mem(&pdev->dev) != 0) + return -ENOMEM; + total_size = size = ret = no_of_nodes = 0; + /* For dump table registration with IMEM */ + total_size = sizeof(struct msm_dump_table) * 2; + for_each_available_child_of_node(node, child_node) { + ret = of_property_read_u32(child_node, "qcom,dump-size", &size); + if (ret) { + dev_err(&pdev->dev, "Unable to find size for %s\n", + child_node->name); + continue; + } + + total_size += size; + no_of_nodes++; + } + + total_size += (MSM_DUMP_DATA_SIZE * no_of_nodes); + total_size = ALIGN(total_size, SZ_4K); + dump_vaddr = dmam_alloc_coherent(&pdev->dev, total_size, + &dma_handle, GFP_KERNEL); + if (!dump_vaddr) + return -ENOMEM; + + dma_get_sgtable(&pdev->dev, &mem_dump_sgt, dump_vaddr, + dma_handle, total_size); + phys_addr = page_to_phys(sg_page(mem_dump_sgt.sgl)); + sg_free_table(&mem_dump_sgt); + + memset(dump_vaddr, 0x0, total_size); + ret = qcom_tzmem_shm_bridge_create(phys_addr, total_size, &shm_bridge_handle); + if (ret) { + dev_err(&pdev->dev, "Failed to create shm bridge.ret=%d\n", ret); + return ret; + } + + ret = init_memory_dump(dump_vaddr, phys_addr); + if (ret) { + dev_err(&pdev->dev, "Memory Dump table set up is failed\n"); + qcom_tzmem_shm_bridge_delete(shm_bridge_handle); + return ret; + } + + ret = init_memdump_imem_area(total_size); + if (ret) { + qcom_tzmem_shm_bridge_delete(shm_bridge_handle); + return ret; + } + + dump_vaddr += (sizeof(struct msm_dump_table) * 2); + phys_addr += (sizeof(struct msm_dump_table) * 2); + for_each_available_child_of_node(node, child_node) { + ret = of_property_read_u32(child_node, "qcom,dump-size", &size); + if (ret) + continue; + + ret = of_property_read_u32(child_node, "qcom,dump-id", &id); + if (ret) { + dev_err(&pdev->dev, "Unable to find id for %s\n", + child_node->name); + continue; + } + + dump_data = dump_vaddr; + dump_data->addr = phys_addr + MSM_DUMP_DATA_SIZE; + dump_data->len = size; + dump_entry.id = id; + strscpy(dump_data->name, child_node->name, + sizeof(dump_data->name)); + dump_entry.addr = phys_addr; + ret = msm_dump_data_register_nominidump(MSM_DUMP_TABLE_APPS, + &dump_entry); + if (ret) + dev_err(&pdev->dev, "Data dump setup failed, id = %d\n", + id); + + if ((id == CPUSS_REGDUMP) || + ((id >= SPR_DUMP_CPU0) && (id <= SPR_DUMP_CPU7))) + initialized = cpuss_dump_init(pdev, + (dump_vaddr + MSM_DUMP_DATA_SIZE), size, id); + + dump_vaddr += (size + MSM_DUMP_DATA_SIZE); + phys_addr += (size + MSM_DUMP_DATA_SIZE); + } + + cpuss_create_nodes(pdev, initialized); + + if (initialized & SPRS_INITIALIZED) + reset_sprs_dump_table(&pdev->dev); + + return ret; +} + +static int mem_dump_probe(struct platform_device *pdev) +{ + int ret; + + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (ret < 0) + return ret; + + ret = mem_dump_alloc(pdev); + return ret; +} + +static const struct of_device_id mem_dump_match_table[] = { + {.compatible = "qcom,mem-dump",}, + {} +}; + +static struct platform_driver mem_dump_driver = { + .probe = mem_dump_probe, + .driver = { + .name = "msm_mem_dump", + .of_match_table = mem_dump_match_table, + }, +}; + +module_platform_driver(mem_dump_driver); + +MODULE_DESCRIPTION("Memory Dump V2 Driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/firmware/qcom/memory_dump.h b/include/linux/firmware/qcom/memory_dump.h new file mode 100644 index 0000000000000..ebb7c89d2f243 --- /dev/null +++ b/include/linux/firmware/qcom/memory_dump.h @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012, 2014-2017, 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __MSM_MEMORY_DUMP_H +#define __MSM_MEMORY_DUMP_H + +#include +#include + +enum dump_client_type { + MSM_CPU_CTXT = 0, + MSM_L1_CACHE, + MSM_L2_CACHE, + MSM_OCMEM, + MSM_TMC_ETFETB, + MSM_ETM0_REG, + MSM_ETM1_REG, + MSM_ETM2_REG, + MSM_ETM3_REG, + MSM_TMC0_REG, /* TMC_ETR */ + MSM_TMC1_REG, /* TMC_ETF */ + MSM_LOG_BUF, + MSM_LOG_BUF_FIRST_IDX, + MAX_NUM_CLIENTS, +}; + +struct msm_client_dump { + enum dump_client_type id; + unsigned long start_addr; + unsigned long end_addr; +}; + +#ifdef CONFIG_QCOM_MEMORY_DUMP +extern int msm_dump_tbl_register(struct msm_client_dump *client_entry); +#else +static inline int msm_dump_tbl_register(struct msm_client_dump *entry) +{ + return -EIO; +} +#endif + + +#if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2) +extern uint32_t msm_dump_table_version(void); +#else +static inline uint32_t msm_dump_table_version(void) +{ + return 0; +} +#endif + +#define MSM_DUMP_MAKE_VERSION(ma, mi) ((ma << 20) | mi) +#define MSM_DUMP_MAJOR(val) (val >> 20) +#define MSM_DUMP_MINOR(val) (val & 0xFFFFF) + + +#define MAX_NUM_ENTRIES 0x150 + +enum msm_dump_data_ids { + MSM_DUMP_DATA_CPU_CTX = 0x00, + MSM_DUMP_DATA_L1_INST_CACHE = 0x60, + MSM_DUMP_DATA_L1_DATA_CACHE = 0x80, + MSM_DUMP_DATA_ETM_REG = 0xA0, + MSM_DUMP_DATA_L2_CACHE = 0xC0, + MSM_DUMP_DATA_L3_CACHE = 0xD0, + MSM_DUMP_DATA_OCMEM = 0xE0, + MSM_DUMP_DATA_CNSS_WLAN = 0xE1, + MSM_DUMP_DATA_WIGIG = 0xE2, + MSM_DUMP_DATA_PMIC = 0xE4, + MSM_DUMP_DATA_DBGUI_REG = 0xE5, + MSM_DUMP_DATA_DCC_REG = 0xE6, + MSM_DUMP_DATA_DCC_SRAM = 0xE7, + MSM_DUMP_DATA_MISC = 0xE8, + MSM_DUMP_DATA_VSENSE = 0xE9, + MSM_DUMP_DATA_RPM = 0xEA, + MSM_DUMP_DATA_SCANDUMP = 0xEB, + MSM_DUMP_DATA_RPMH = 0xEC, + MSM_DUMP_DATA_TMC_ETF = 0xF0, + MSM_DUMP_DATA_TMC_ETF_SWAO = 0xF1, + MSM_DUMP_DATA_TMC_REG = 0x100, + MSM_DUMP_DATA_TMC_ETF_SWAO_REG = 0x102, + MSM_DUMP_DATA_LOG_BUF = 0x110, + MSM_DUMP_DATA_LOG_BUF_FIRST_IDX = 0x111, + MSM_DUMP_DATA_SCANDUMP_PER_CPU = 0x130, + MSM_DUMP_DATA_LLCC_PER_INSTANCE = 0x140, + MSM_DUMP_DATA_MAX = MAX_NUM_ENTRIES, +}; + +enum msm_dump_table_ids { + MSM_DUMP_TABLE_APPS, + MSM_DUMP_TABLE_MAX = MAX_NUM_ENTRIES, +}; + +enum msm_dump_type { + MSM_DUMP_TYPE_DATA, + MSM_DUMP_TYPE_TABLE, +}; + +struct msm_dump_data { + uint32_t version; + uint32_t magic; + char name[32]; + uint64_t addr; + uint64_t len; + uint32_t reserved; +}; + +struct msm_dump_entry { + uint32_t id; + char name[32]; + uint32_t type; + uint64_t addr; +}; + +#if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2) +extern int msm_dump_data_register(enum msm_dump_table_ids id, + struct msm_dump_entry *entry); +extern int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, + struct msm_dump_entry *entry); +#else +static inline int msm_dump_data_register(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + return -EINVAL; +} +static inline int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, + struct msm_dump_entry *entry) +{ + return -EINVAL; +} +#endif + +#endif From 54a19bea52b909a29901e9576240c648b67b8824 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 12 Jan 2026 11:30:00 +0800 Subject: [PATCH 0040/1133] QCLINUX: mem-dump: add memory dump device driver Create memory dump device driver for matching the memory dump v2 driver without DT configuration. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 1 + drivers/firmware/qcom/Kconfig | 6 + drivers/firmware/qcom/Makefile | 1 + drivers/firmware/qcom/memory_dump_dev.c | 379 ++++++++++++++++++++++ drivers/firmware/qcom/memory_dump_v2.c | 67 ++-- include/linux/firmware/qcom/memory_dump.h | 13 + 6 files changed, 420 insertions(+), 47 deletions(-) create mode 100644 drivers/firmware/qcom/memory_dump_dev.c diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index 2e85e8df0469b..d50f78f3a3ea2 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1,3 +1,4 @@ CONFIG_QCOM_DCC=m CONFIG_QCOM_DCC_DEV=m CONFIG_QCOM_MEMORY_DUMP_V2=m +CONFIG_QCOM_MEMORY_DUMP_DEV=m diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index 2a541811c1562..d1f4d835f8420 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -103,4 +103,10 @@ config QCOM_MEMORY_DUMP_V2 of deadlocks or cpu hangs these dump regions are captured to give a snapshot of the system at the time of the crash. +config QCOM_MEMORY_DUMP_DEV + tristate "QCOM Memory Dump V2 device stub" + depends on QCOM_MEMORY_DUMP_V2 + help + Device stub for memory dump V2 driver. + endmenu diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile index 1953b51786751..2b3819c3f51e8 100644 --- a/drivers/firmware/qcom/Makefile +++ b/drivers/firmware/qcom/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o obj-$(CONFIG_QCOM_PAS) += qcom_pas.o obj-$(CONFIG_QCOM_PAS_TEE) += qcom_pas_tee.o obj-$(CONFIG_QCOM_MEMORY_DUMP_V2) += memory_dump_v2.o +obj-$(CONFIG_QCOM_MEMORY_DUMP_DEV) += memory_dump_dev.o diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c new file mode 100644 index 0000000000000..556ebafae5280 --- /dev/null +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -0,0 +1,379 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#define DEV_NAME "msm_mem_dump" + +static struct platform_device *mem_dump_pdev; + +enum dump_ids { + C0_CONTEXT = 0x0, + C100_CONTEXT = 0x1, + C200_CONTEXT = 0x2, + C300_CONTEXT = 0x3, + C400_CONTEXT = 0x4, + C500_CONTEXT = 0x5, + C600_CONTEXT = 0x6, + C700_CONTEXT = 0x7, + L1_ITLB10000 = 0x24, + L1_ITLB10100 = 0x25, + L1_ITLB10200 = 0x26, + L1_ITLB10300 = 0x27, + L1_DTLB10000 = 0x44, + L1_DTLB10100 = 0x45, + L1_DTLB10200 = 0x46, + L1_DTLB10300 = 0x47, + L1_ICACHE0 = 0x60, + L1_ICACHE100 = 0x61, + L1_ICACHE200 = 0x62, + L1_ICACHE300 = 0x63, + L1_ICACHE10000 = 0x64, + L1_ICACHE10100 = 0x65, + L1_ICACHE10200 = 0x66, + L1_ICACHE10300 = 0x67, + L1_DCACHE0 = 0x80, + L1_DCACHE100 = 0x81, + L1_DCACHE200 = 0x82, + L1_DCACHE300 = 0x83, + L1_DCACHE10000 = 0x84, + L1_DCACHE10100 = 0x85, + L1_DCACHE10200 = 0x86, + L1_DCACHE10300 = 0x87, + L2_CACHE10000 = 0xc4, + L2_CACHE10100 = 0xc5, + L2_CACHE10200 = 0xc6, + L2_CACHE10300 = 0xc7, + PMIC = 0xe4, + MISC_DATA = 0xe8, + RPM_SW = 0xea, + RPMH = 0xec, + CPUSS_REG = 0xef, + TMC_ETF = 0xf0, + ETF_SWAO = 0xf1, + ETF_LPASS = 0xf4, + FCM = 0xee, + ETR_REG = 0x100, + ETF_REG = 0x101, + ETFSWAO_REG = 0x102, + ETFLPASS_REG = 0x104, + L2_TLB0 = 0x120, + L2_TLB100 = 0x121, + L2_TLB200 = 0x122, + L2_TLB300 = 0x123, + L2_TLB10000 = 0x124, + L2_TLB10100 = 0x125, + L2_TLB10200 = 0x126, + L2_TLB10300 = 0x127, + C0_SCANDUMP = 0x130, + C100_SCANDUMP = 0x131, + C200_SCANDUMP = 0x132, + C300_SCANDUMP = 0x133, + C10000_SCANDUMP = 0x134, + C10100_SCANDUMP = 0x135, + C10200_SCANDUMP = 0x136, + C10300_SCANDUMP = 0x137, + LLCC1_D_CACHE = 0x140, + LLCC2_D_CACHE = 0x141, + MHM_SCAN = 0x161, + GEMNOC = 0x162, + OSM_REG = 0x163, + PCU_REG = 0x164, + FSM_DATA = 0x165, +}; + +static const struct dump_item lemans_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C0_SCANDUMP, 0x40000, "c0-scandump" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C100_SCANDUMP, 0x40000, "c100-scandump" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C200_SCANDUMP, 0x40000, "c200-scandump" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C300_SCANDUMP, 0x40000, "c300-scandump" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { C10000_SCANDUMP, 0x40000, "c10000-scandump" }, + { C10100_SCANDUMP, 0x40000, "c10100-scandump" }, + { C10200_SCANDUMP, 0x40000, "c10200-scandump" }, + { C10300_SCANDUMP, 0x40000, "c10300-scandump" }, + { CPUSS_REG, 0x20000, "cpuss-reg" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR_REG, 0x1000, "etr-reg" }, + { FCM, 0x8400, "fcm" }, + { L1_DCACHE0, 0x12100, "l1-dcache0" }, + { L1_DCACHE100, 0x12100, "l1-dcache100" }, + { L1_DCACHE200, 0x12100, "l1-dcache200" }, + { L1_DCACHE300, 0x12100, "l1-dcache300" }, + { L1_DCACHE10000, 0x12100, "l1-dcache10000" }, + { L1_DCACHE10100, 0x12100, "l1-dcache10100" }, + { L1_DCACHE10200, 0x12100, "l1-dcache10200" }, + { L1_DCACHE10300, 0x12100, "l1-dcache10300" }, + { L1_DTLB10000, 0x300, "l1-dtlb10000" }, + { L1_DTLB10100, 0x300, "l1-dtlb10100" }, + { L1_DTLB10200, 0x300, "l1-dtlb10200" }, + { L1_DTLB10300, 0x300, "l1-dtlb10300" }, + { L1_ICACHE0, 0x26100, "l1-icache0" }, + { L1_ICACHE100, 0x26100, "l1-icache100" }, + { L1_ICACHE200, 0x26100, "l1-icache200" }, + { L1_ICACHE300, 0x26100, "l1-icache300" }, + { L1_ICACHE10000, 0x26100, "l1-icache10000" }, + { L1_ICACHE10100, 0x26100, "l1-icache10100" }, + { L1_ICACHE10200, 0x26100, "l1-icache10200" }, + { L1_ICACHE10300, 0x26100, "l1-icache10300" }, + { L1_ITLB10000, 0x300, "l1-itlb10000" }, + { L1_ITLB10100, 0x300, "l1-itlb10100" }, + { L1_ITLB10200, 0x300, "l1-itlb10200" }, + { L1_ITLB10300, 0x300, "l1-itlb10300" }, + { L2_CACHE10000, 0x90100, "l2-cache10000" }, + { L2_CACHE10100, 0x90100, "l2-cache10100" }, + { L2_CACHE10200, 0x90100, "l2-cache10200" }, + { L2_CACHE10300, 0x90100, "l2-cache10300" }, + { L2_TLB0, 0x6100, "l2-tlb0" }, + { L2_TLB100, 0x6100, "l2-tlb100" }, + { L2_TLB200, 0x6100, "l2-tlb200" }, + { L2_TLB300, 0x6100, "l2-tlb300" }, + { L2_TLB10000, 0x6100, "l2-tlb10000" }, + { L2_TLB10100, 0x6100, "l2-tlb10100" }, + { L2_TLB10200, 0x6100, "l2-tlb10200" }, + { L2_TLB10300, 0x6100, "l2-tlb10300" }, + { MISC_DATA, 0x1000, "misc-data" }, + { PMIC, 0x80000, "pmic" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { RPMH, 0x2000000, "rpmh" }, +}; + +static const struct dump_item talos_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0x2000000, "rpmh" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { PMIC, 0x10000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { TMC_ETF, 0x8000, "tmc-etf" }, + { ETF_SWAO, 0x8000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETF_REG, 0x1000, "etf-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { MISC_DATA, 0x1000, "misc-data" }, + { L1_ICACHE0, 0x8800, "l1-icache0" }, + { L1_ICACHE100, 0x8800, "l1-icache100" }, + { L1_ICACHE200, 0x8800, "l1-icache200" }, + { L1_ICACHE300, 0x8800, "l1-icache300" }, + { L1_ICACHE10000, 0x8800, "l1-icache400" }, + { L1_ICACHE10100, 0x8800, "l1-icache500" }, + { L1_ICACHE10200, 0x11000, "l1-icache600" }, + { L1_ICACHE10300, 0x11000, "l1-icache700" }, + { L1_DCACHE0, 0x9000, "l1-dcache0" }, + { L1_DCACHE100, 0x9000, "l1-dcache100" }, + { L1_DCACHE200, 0x9000, "l1-dcache200" }, + { L1_DCACHE300, 0x9000, "l1-dcache300" }, + { L1_DCACHE10000, 0x9000, "l1-dcache400" }, + { L1_DCACHE10100, 0x9000, "l1-dcache500" }, + { L1_DCACHE10200, 0x12000, "l1-dcache600" }, + { L1_DCACHE10300, 0x12000, "l1-dcache700" }, + { L1_ITLB10200, 0x300, "l1-itlb600" }, + { L1_ITLB10300, 0x300, "l1-itlb700" }, + { L1_DTLB10200, 0x480, "l1-dtlb600" }, + { L1_DTLB10300, 0x480, "l1-dtlb700" }, + { L2_CACHE10200, 0x48000, "l2-cache600" }, + { L2_CACHE10300, 0x48000, "l2-cache700" }, + { L2_TLB0, 0x5000, "l2-tlb0" }, + { L2_TLB100, 0x5000, "l2-tlb100" }, + { L2_TLB200, 0x5000, "l2-tlb200" }, + { L2_TLB300, 0x5000, "l2-tlb300" }, + { L2_TLB10000, 0x5000, "l2-tlb400" }, + { L2_TLB10100, 0x5000, "l2-tlb500" }, + { L2_TLB10200, 0x7800, "l2-tlb600" }, + { L2_TLB10300, 0x7800, "l2-tlb700" }, + { LLCC1_D_CACHE, 0x6c000, "llcc1-d-cache" }, +}; + +static const struct dump_item kodiak_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C0_SCANDUMP, 0x10100, "c0-scandump" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C100_SCANDUMP, 0x10100, "c100-scandump" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C200_SCANDUMP, 0x10100, "c200-scandump" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C300_SCANDUMP, 0x10100, "c300-scandump" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C10000_SCANDUMP, 0x40000, "c400-scandump" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C10100_SCANDUMP, 0x40000, "c500-scandump" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C10200_SCANDUMP, 0x40000, "c600-scandump" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { C10300_SCANDUMP, 0x40000, "c700-scandump" }, + { CPUSS_REG, 0x30000, "cpuss-reg" }, + { ETF_LPASS, 0x4000, "etf-lpass" }, + { ETFLPASS_REG, 0x1000, "etflpass-reg" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR_REG, 0x1000, "etr-reg" }, + { FCM, 0x8400, "fcm" }, + { FSM_DATA, 0x400, "fsm-data" }, + { GEMNOC, 0x100000, "gemnoc" }, + { L1_DCACHE0, 0x9100, "l1-dcache0" }, + { L1_DCACHE100, 0x9100, "l1-dcache100" }, + { L1_DCACHE200, 0x9100, "l1-dcache200" }, + { L1_DCACHE300, 0x9100, "l1-dcache300" }, + { L1_DCACHE10000, 0x9100, "l1-dcache400" }, + { L1_DCACHE10100, 0x9100, "l1-dcache500" }, + { L1_DCACHE10200, 0x9100, "l1-dcache600" }, + { L1_DCACHE10300, 0x12100, "l1-dcache700" }, + { L1_DTLB10000, 0x300, "l1-dtlb400" }, + { L1_DTLB10100, 0x300, "l1-dtlb500" }, + { L1_DTLB10200, 0x300, "l1-dtlb600" }, + { L1_DTLB10300, 0x3a0, "l1-dtlb700" }, + { L1_ICACHE0, 0x10900, "l1-icache0" }, + { L1_ICACHE100, 0x10900, "l1-icache100" }, + { L1_ICACHE200, 0x10900, "l1-icache200" }, + { L1_ICACHE300, 0x10900, "l1-icache300" }, + { L1_ICACHE10000, 0x15100, "l1-icache400" }, + { L1_ICACHE10100, 0x15100, "l1-icache500" }, + { L1_ICACHE10200, 0x15100, "l1-icache600" }, + { L1_ICACHE10300, 0x32100, "l1-icache700" }, + { L1_ITLB10000, 0x300, "l1-itlb400" }, + { L1_ITLB10100, 0x300, "l1-itlb500" }, + { L1_ITLB10200, 0x300, "l1-itlb600" }, + { L1_ITLB10300, 0x400, "l1-itlb700" }, + { L2_CACHE10000, 0x90100, "l2-cache400" }, + { L2_CACHE10100, 0x90100, "l2-cache500" }, + { L2_CACHE10200, 0x90100, "l2-cache600" }, + { L2_CACHE10300, 0x120100, "l2-cache700" }, + { L2_TLB0, 0x5b00, "l2-tlb0" }, + { L2_TLB100, 0x5b00, "l2-tlb100" }, + { L2_TLB200, 0x5b00, "l2-tlb200" }, + { L2_TLB300, 0x5b00, "l2-tlb300" }, + { L2_TLB10000, 0x6100, "l2-tlb400" }, + { L2_TLB10100, 0x6100, "l2-tlb500" }, + { L2_TLB10200, 0x6100, "l2-tlb600" }, + { L2_TLB10300, 0xc100, "l2-tlb700" }, + { LLCC1_D_CACHE, 0x1141c0, "llcc1-d-cache" }, + { LLCC2_D_CACHE, 0x1141c0, "llcc2-d-cache" }, + { MHM_SCAN, 0x20000, "mhm-scan" }, + { MISC_DATA, 0x1000, "misc-data" }, + { OSM_REG, 0x400, "osm-reg" }, + { PCU_REG, 0x400, "pcu-reg" }, + { PMIC, 0x200000, "pmic" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { RPMH, 0x2000000, "rpmh" }, +}; + +static const struct dump_table lemans_dump_table = { + .items = lemans_items, + .num_of_items = ARRAY_SIZE(lemans_items), + .imem_base = 0x146d8010, + .imem_size = 0x8, +}; + +static const struct dump_table talos_dump_table = { + .items = talos_items, + .num_of_items = ARRAY_SIZE(lemans_items), + .imem_base = 0x146aa010, + .imem_size = 0x8, +}; + +static const struct dump_table kodiak_dump_table = { + .items = kodiak_items, + .num_of_items = ARRAY_SIZE(kodiak_items), + .imem_base = 0x146aa010, + .imem_size = 0x8, +}; + +static int __init mem_dump_dev_init(void) +{ + int ret; + u32 soc_id; + + mem_dump_pdev = platform_device_alloc(DEV_NAME, -1); + if (!mem_dump_pdev) + return -ENOMEM; + + ret = qcom_smem_get_soc_id(&soc_id); + if (ret) + goto fail; + + switch (soc_id) { + case 377: + case 380: + case 384: + case 401: + case 406: + case 680: + ret = platform_device_add_data(mem_dump_pdev, + &talos_dump_table, sizeof(talos_dump_table)); + if (ret) + goto fail; + + break; + case 534: + case 606: + case 667: + case 674: + case 675: + case 676: + ret = platform_device_add_data(mem_dump_pdev, + &lemans_dump_table, sizeof(lemans_dump_table)); + if (ret) + goto fail; + + break; + case 475: + case 497: + case 498: + case 515: + ret = platform_device_add_data(mem_dump_pdev, + &kodiak_dump_table, sizeof(kodiak_dump_table)); + if (ret) + goto fail; + + break; + default: + dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); + ret = -EINVAL; + goto fail; + } + + ret = platform_device_add(mem_dump_pdev); + if (ret) + goto fail; + + dev_info(&mem_dump_pdev->dev, "Register platform device successfully\n"); + + return 0; + +fail: + dev_err(&mem_dump_pdev->dev, + "Failed to register memory dump platform device\n"); + platform_device_put(mem_dump_pdev); + + return ret; +} + +static void __exit mem_dump_dev_exit(void) +{ + platform_device_unregister(mem_dump_pdev); +} + +module_init(mem_dump_dev_init); +module_exit(mem_dump_dev_exit); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm Technologies Inc. Memory Dump driver V2, device stub"); diff --git a/drivers/firmware/qcom/memory_dump_v2.c b/drivers/firmware/qcom/memory_dump_v2.c index baf4c980f39fb..470d6047ee656 100644 --- a/drivers/firmware/qcom/memory_dump_v2.c +++ b/drivers/firmware/qcom/memory_dump_v2.c @@ -865,19 +865,11 @@ int msm_dump_data_register_nominidump(enum msm_dump_table_ids id, EXPORT_SYMBOL_GPL(msm_dump_data_register_nominidump); #define MSM_DUMP_TOTAL_SIZE_OFFSET 0x724 -static int init_memdump_imem_area(size_t size) +static int init_memdump_imem_area(const struct dump_table *table, size_t size) { - struct device_node *np; void __iomem *imem_base; - np = of_find_compatible_node(NULL, NULL, - "qcom,msm-imem-mem-dump-table"); - if (!np) { - pr_err("mem dump base table DT node does not exist\n"); - return -ENODEV; - } - - imem_base = of_iomap(np, 0); + imem_base = ioremap(table->imem_base, table->imem_size); if (!imem_base) { pr_err("mem dump base table imem offset mapping failed\n"); return -ENOMEM; @@ -924,13 +916,17 @@ static int init_memory_dump(void *dump_vaddr, phys_addr_t phys_addr) static int mem_dump_reserve_mem(struct device *dev) { struct device_node *mem_node; + struct reserved_mem *rmem; int ret; - mem_node = of_parse_phandle(dev->of_node, "memory-region", 0); + mem_node = of_find_node_by_path("/reserved-memory/mem-dump-region"); if (mem_node) { - ret = of_reserved_mem_device_init_by_idx(dev, - dev->of_node, 0); - of_node_put(dev->of_node); + rmem = of_reserved_mem_lookup(mem_node); + of_node_put(mem_node); + if (!rmem || !rmem->ops || !rmem->ops->device_init) + return -EINVAL; + + ret = rmem->ops->device_init(rmem, dev); if (ret) { dev_err(dev, "Failed to initialize reserved mem, ret %d\n", @@ -1005,34 +1001,26 @@ static int cpuss_dump_init(struct platform_device *pdev, #define MSM_DUMP_DATA_SIZE sizeof(struct msm_dump_data) static int mem_dump_alloc(struct platform_device *pdev) { - struct device_node *child_node; - const struct device_node *node = pdev->dev.of_node; struct msm_dump_data *dump_data; struct msm_dump_entry dump_entry; size_t total_size; u32 size, id; - int ret, no_of_nodes; + int i, ret, no_of_nodes; dma_addr_t dma_handle; phys_addr_t phys_addr; struct sg_table mem_dump_sgt; void *dump_vaddr; u64 shm_bridge_handle; int initialized = 0; + const struct dump_table *table = dev_get_platdata(&pdev->dev); if (mem_dump_reserve_mem(&pdev->dev) != 0) return -ENOMEM; total_size = size = ret = no_of_nodes = 0; /* For dump table registration with IMEM */ total_size = sizeof(struct msm_dump_table) * 2; - for_each_available_child_of_node(node, child_node) { - ret = of_property_read_u32(child_node, "qcom,dump-size", &size); - if (ret) { - dev_err(&pdev->dev, "Unable to find size for %s\n", - child_node->name); - continue; - } - - total_size += size; + for (i = 0; i < table->num_of_items; i++) { + total_size += table->items[i].size; no_of_nodes++; } @@ -1062,7 +1050,7 @@ static int mem_dump_alloc(struct platform_device *pdev) return ret; } - ret = init_memdump_imem_area(total_size); + ret = init_memdump_imem_area(table, total_size); if (ret) { qcom_tzmem_shm_bridge_delete(shm_bridge_handle); return ret; @@ -1070,24 +1058,15 @@ static int mem_dump_alloc(struct platform_device *pdev) dump_vaddr += (sizeof(struct msm_dump_table) * 2); phys_addr += (sizeof(struct msm_dump_table) * 2); - for_each_available_child_of_node(node, child_node) { - ret = of_property_read_u32(child_node, "qcom,dump-size", &size); - if (ret) - continue; - - ret = of_property_read_u32(child_node, "qcom,dump-id", &id); - if (ret) { - dev_err(&pdev->dev, "Unable to find id for %s\n", - child_node->name); - continue; - } - + for (i = 0; i < table->num_of_items; i++) { + size = table->items[i].size; + id = table->items[i].dump_id; dump_data = dump_vaddr; dump_data->addr = phys_addr + MSM_DUMP_DATA_SIZE; dump_data->len = size; dump_entry.id = id; - strscpy(dump_data->name, child_node->name, - sizeof(dump_data->name)); + strscpy(dump_data->name, table->items[i].name, + sizeof(table->items[i].name)); dump_entry.addr = phys_addr; ret = msm_dump_data_register_nominidump(MSM_DUMP_TABLE_APPS, &dump_entry); @@ -1124,16 +1103,10 @@ static int mem_dump_probe(struct platform_device *pdev) return ret; } -static const struct of_device_id mem_dump_match_table[] = { - {.compatible = "qcom,mem-dump",}, - {} -}; - static struct platform_driver mem_dump_driver = { .probe = mem_dump_probe, .driver = { .name = "msm_mem_dump", - .of_match_table = mem_dump_match_table, }, }; diff --git a/include/linux/firmware/qcom/memory_dump.h b/include/linux/firmware/qcom/memory_dump.h index ebb7c89d2f243..e72436feb0544 100644 --- a/include/linux/firmware/qcom/memory_dump.h +++ b/include/linux/firmware/qcom/memory_dump.h @@ -115,6 +115,19 @@ struct msm_dump_entry { uint64_t addr; }; +struct dump_item { + u32 dump_id; + size_t size; + const char *name; +}; + +struct dump_table { + const struct dump_item *items; + u32 num_of_items; + phys_addr_t imem_base; + resource_size_t imem_size; +}; + #if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2) extern int msm_dump_data_register(enum msm_dump_table_ids id, struct msm_dump_entry *entry); From dc0ead6d2f9292f23a4c2df7a7325dbdfef4eaa3 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 2 Feb 2026 18:16:25 +0800 Subject: [PATCH 0041/1133] QCLINUX: memory-dump: add logic for reserving CMA memory Memory dump driver needs a large CMA memory zone for storing memory dump table. Add codes for reserving CMA memory during the init stage. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 2 +- arch/arm64/mm/init.c | 4 ++ drivers/firmware/qcom/Kconfig | 1 + drivers/firmware/qcom/memory_dump_v2.c | 58 +++++++++-------------- include/linux/firmware/qcom/memory_dump.h | 4 +- 5 files changed, 31 insertions(+), 38 deletions(-) diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index d50f78f3a3ea2..48ae2fb9737ac 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1,4 +1,4 @@ CONFIG_QCOM_DCC=m CONFIG_QCOM_DCC_DEV=m -CONFIG_QCOM_MEMORY_DUMP_V2=m +CONFIG_QCOM_MEMORY_DUMP_V2=y CONFIG_QCOM_MEMORY_DUMP_DEV=m diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index fbf215ecc7d06..f44f20f6fe88a 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -50,6 +50,7 @@ #include #include #include +#include /* * We need to be able to catch inadvertent references to memstart_addr @@ -327,6 +328,9 @@ void __init bootmem_init(void) * reserved, so do it here. */ arch_reserve_crashkernel(); +#if defined(CONFIG_QCOM_MEMORY_DUMP_V2) + reserve_memdump_cma(); +#endif memblock_dump_all(); } diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index d1f4d835f8420..e18fb19ce5e32 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -97,6 +97,7 @@ config QCOM_QSEECOM_UEFISECAPP config QCOM_MEMORY_DUMP_V2 tristate "QCOM Memory Dump V2 Support" depends on QCOM_TZMEM + depends on CMA help This enables memory dump feature. It allows various client subsystems to register respective dump regions. At the time diff --git a/drivers/firmware/qcom/memory_dump_v2.c b/drivers/firmware/qcom/memory_dump_v2.c index 470d6047ee656..831d1aea86e09 100644 --- a/drivers/firmware/qcom/memory_dump_v2.c +++ b/drivers/firmware/qcom/memory_dump_v2.c @@ -18,6 +18,10 @@ #include #include #include +#include +#include +#include +#include #define MSM_DUMP_TABLE_VERSION MSM_DUMP_MAKE_VERSION(2, 0) @@ -913,30 +917,6 @@ static int init_memory_dump(void *dump_vaddr, phys_addr_t phys_addr) return 0; } -static int mem_dump_reserve_mem(struct device *dev) -{ - struct device_node *mem_node; - struct reserved_mem *rmem; - int ret; - - mem_node = of_find_node_by_path("/reserved-memory/mem-dump-region"); - if (mem_node) { - rmem = of_reserved_mem_lookup(mem_node); - of_node_put(mem_node); - if (!rmem || !rmem->ops || !rmem->ops->device_init) - return -EINVAL; - - ret = rmem->ops->device_init(rmem, dev); - if (ret) { - dev_err(dev, - "Failed to initialize reserved mem, ret %d\n", - ret); - return ret; - } - } - return 0; -} - static int cpuss_regdump_init(struct device *dev, void *dump_vaddr, u32 size) { @@ -998,6 +978,18 @@ static int cpuss_dump_init(struct platform_device *pdev, return initialized; } +struct cma *memdump_cma; +void __init reserve_memdump_cma(void) +{ + unsigned long long cma_size = 0x3000000; + unsigned long long request_size = roundup(cma_size, PAGE_SIZE); + + if (cma_declare_contiguous(0, request_size, 0, 0, 0, false, + "memdump", &memdump_cma)) { + pr_warn("memdump CMA reservation failed\n"); + } +} + #define MSM_DUMP_DATA_SIZE sizeof(struct msm_dump_data) static int mem_dump_alloc(struct platform_device *pdev) { @@ -1006,16 +998,13 @@ static int mem_dump_alloc(struct platform_device *pdev) size_t total_size; u32 size, id; int i, ret, no_of_nodes; - dma_addr_t dma_handle; phys_addr_t phys_addr; - struct sg_table mem_dump_sgt; void *dump_vaddr; u64 shm_bridge_handle; int initialized = 0; const struct dump_table *table = dev_get_platdata(&pdev->dev); + struct page *reserved_page; - if (mem_dump_reserve_mem(&pdev->dev) != 0) - return -ENOMEM; total_size = size = ret = no_of_nodes = 0; /* For dump table registration with IMEM */ total_size = sizeof(struct msm_dump_table) * 2; @@ -1026,15 +1015,12 @@ static int mem_dump_alloc(struct platform_device *pdev) total_size += (MSM_DUMP_DATA_SIZE * no_of_nodes); total_size = ALIGN(total_size, SZ_4K); - dump_vaddr = dmam_alloc_coherent(&pdev->dev, total_size, - &dma_handle, GFP_KERNEL); - if (!dump_vaddr) + reserved_page = cma_alloc(memdump_cma, total_size >> PAGE_SHIFT, + 0, false); + if (!reserved_page) return -ENOMEM; - - dma_get_sgtable(&pdev->dev, &mem_dump_sgt, dump_vaddr, - dma_handle, total_size); - phys_addr = page_to_phys(sg_page(mem_dump_sgt.sgl)); - sg_free_table(&mem_dump_sgt); + phys_addr = page_to_phys(reserved_page); + dump_vaddr = page_to_virt(reserved_page); memset(dump_vaddr, 0x0, total_size); ret = qcom_tzmem_shm_bridge_create(phys_addr, total_size, &shm_bridge_handle); diff --git a/include/linux/firmware/qcom/memory_dump.h b/include/linux/firmware/qcom/memory_dump.h index e72436feb0544..ead7add4265c5 100644 --- a/include/linux/firmware/qcom/memory_dump.h +++ b/include/linux/firmware/qcom/memory_dump.h @@ -33,6 +33,9 @@ struct msm_client_dump { unsigned long end_addr; }; +void __init reserve_memdump_cma(void); +extern struct cma *memdump_cma; + #ifdef CONFIG_QCOM_MEMORY_DUMP extern int msm_dump_tbl_register(struct msm_client_dump *client_entry); #else @@ -42,7 +45,6 @@ static inline int msm_dump_tbl_register(struct msm_client_dump *entry) } #endif - #if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2) extern uint32_t msm_dump_table_version(void); #else From f9e18d3f626da7a8284b7f357e0e64b1d2d7f325 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 13:44:34 +0800 Subject: [PATCH 0042/1133] QCLINUX: qcom-dcc: add device configuration for Pakala Add device configuration to enable DCC on Pakala platform. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index e0eb2e61d652b..0c2369a4843ae 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -39,6 +39,15 @@ static const struct dcc_pdata kodiak_pdata = { .map_ver = 0x2, }; +static const struct dcc_pdata pakala_pdata = { + .base = 0x100ff000, + .size = 0x00001000, + .ram_base = 0x10084000, + .ram_size = 0x4000, + .dcc_offset = 0x4000, + .map_ver = 0x3, +}; + static int __init dcc_dev_init(void) { int ret; @@ -83,6 +92,15 @@ static int __init dcc_dev_init(void) if (ret) goto fail; + break; + case 618: + case 639: + case 705: + case 706: + ret = platform_device_add_data(dcc_pdev, &pakala_pdata, sizeof(pakala_pdata)); + if (ret) + goto fail; + break; default: pr_err("DCC: Invalid SoC ID\n"); From 67750e8682457291c1200c22767864c13d2f39e4 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 14:10:29 +0800 Subject: [PATCH 0043/1133] QCLINUX: memory-dump: add memory dump table for Pakala Add memory dump table configuration to enable memory dump function on Pakala platform. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 50 +++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 556ebafae5280..1626a67017990 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -57,12 +57,15 @@ enum dump_ids { CPUSS_REG = 0xef, TMC_ETF = 0xf0, ETF_SWAO = 0xf1, + ETF_SLPI = 0xf3, ETF_LPASS = 0xf4, FCM = 0xee, ETR_REG = 0x100, ETF_REG = 0x101, ETFSWAO_REG = 0x102, + ETFSLPI_REG = 0x103, ETFLPASS_REG = 0x104, + ETR1_REG = 0x105, L2_TLB0 = 0x120, L2_TLB100 = 0x121, L2_TLB200 = 0x122, @@ -86,6 +89,7 @@ enum dump_ids { OSM_REG = 0x163, PCU_REG = 0x164, FSM_DATA = 0x165, + SCANDUMP_SMMU = 0x220, }; static const struct dump_item lemans_items[] = { @@ -277,6 +281,35 @@ static const struct dump_item kodiak_items[] = { { RPMH, 0x2000000, "rpmh" }, }; +static const struct dump_item pakala_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0x400000, "rpmh" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { PMIC, 0x200000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { MISC_DATA, 0x1000, "misc-data" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR1_REG, 0x1000, "etr1-reg" }, + { ETF_SLPI, 0x4000, "etf-slpi" }, + { ETFSLPI_REG, 0x1000, "etfslpi-reg" }, + { ETF_LPASS, 0x4000, "etf-lpass" }, + { ETFLPASS_REG, 0x1000, "etflpass-reg" }, + { OSM_REG, 0x400, "osm-reg" }, + { PCU_REG, 0x400, "pcu-reg" }, + { FSM_DATA, 0x400, "fsm-data" }, + { SCANDUMP_SMMU, 0x40000, "scandump-smmu" }, + { C0_SCANDUMP, 0x380000, "apps-scandump" }, +}; + static const struct dump_table lemans_dump_table = { .items = lemans_items, .num_of_items = ARRAY_SIZE(lemans_items), @@ -298,6 +331,13 @@ static const struct dump_table kodiak_dump_table = { .imem_size = 0x8, }; +static const struct dump_table pakala_dump_table = { + .items = pakala_items, + .num_of_items = ARRAY_SIZE(pakala_items), + .imem_base = 0x14680010, + .imem_size = 0x8, +}; + static int __init mem_dump_dev_init(void) { int ret; @@ -345,6 +385,16 @@ static int __init mem_dump_dev_init(void) if (ret) goto fail; + break; + case 618: + case 639: + case 705: + case 706: + ret = platform_device_add_data(mem_dump_pdev, + &pakala_dump_table, sizeof(pakala_dump_table)); + if (ret) + goto fail; + break; default: dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); From 5db740862eed461da8cb88b4d3c68173eabc3374 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 14:58:04 +0800 Subject: [PATCH 0044/1133] QCLINUX: qcom-dcc: add device configuration for Kaanapali Add device configuration to enable DCC on Kaanapali platform. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 0c2369a4843ae..5ed2a117b9e81 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -48,6 +48,15 @@ static const struct dcc_pdata pakala_pdata = { .map_ver = 0x3, }; +static const struct dcc_pdata kaanapali_pdata = { + .base = 0x100ff000, + .size = 0x1000, + .ram_base = 0x10080000, + .ram_size = 0x8000, + .dcc_offset = 0x0, + .map_ver = 0x3, +}; + static int __init dcc_dev_init(void) { int ret; @@ -101,6 +110,18 @@ static int __init dcc_dev_init(void) if (ret) goto fail; + break; + case 660: + case 661: + case 704: + case 722: + case 723: + case 730: + case 743: + ret = platform_device_add_data(dcc_pdev, &kaanapali_pdata, sizeof(kaanapali_pdata)); + if (ret) + goto fail; + break; default: pr_err("DCC: Invalid SoC ID\n"); From d6e8e9cec49d096fbfa91845bb174a23ac9c036c Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 15:16:19 +0800 Subject: [PATCH 0045/1133] QCLINUX: memory-dump: add memory dump table for Kaanapali Add memory dump table configuration to enable memory dump function on Kaanapali platform. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 49 +++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 1626a67017990..d02e6af6c03a0 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -310,6 +310,35 @@ static const struct dump_item pakala_items[] = { { C0_SCANDUMP, 0x380000, "apps-scandump" }, }; +static const struct dump_item kaanapali_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0x400000, "rpmh" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { PMIC, 0x200000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { MISC_DATA, 0x1000, "misc-data" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR1_REG, 0x1000, "etr1-reg" }, + { ETF_SLPI, 0x4000, "etf-slpi" }, + { ETFSLPI_REG, 0x1000, "etfslpi-reg" }, + { ETF_LPASS, 0x4000, "etf-lpass" }, + { ETFLPASS_REG, 0x1000, "etflpass-reg" }, + { OSM_REG, 0x400, "osm-reg" }, + { PCU_REG, 0x400, "pcu-reg" }, + { FSM_DATA, 0x400, "fsm-data" }, + { SCANDUMP_SMMU, 0x40000, "scandump-smmu" }, + { C0_SCANDUMP, 0x380000, "apps-scandump" }, +}; + static const struct dump_table lemans_dump_table = { .items = lemans_items, .num_of_items = ARRAY_SIZE(lemans_items), @@ -338,6 +367,13 @@ static const struct dump_table pakala_dump_table = { .imem_size = 0x8, }; +static const struct dump_table kaanapali_dump_table = { + .items = kaanapali_items, + .num_of_items = ARRAY_SIZE(kaanapali_items), + .imem_base = 0x14680010, + .imem_size = 0x8, +}; + static int __init mem_dump_dev_init(void) { int ret; @@ -395,6 +431,19 @@ static int __init mem_dump_dev_init(void) if (ret) goto fail; + break; + case 660: + case 661: + case 704: + case 722: + case 723: + case 730: + case 743: + ret = platform_device_add_data(mem_dump_pdev, + &kaanapali_dump_table, sizeof(kaanapali_dump_table)); + if (ret) + goto fail; + break; default: dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); From 98053838312201d7b539d9754901e6afb809df0e Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 15:32:10 +0800 Subject: [PATCH 0046/1133] QCLINUX: qcom-dcc: add device configuration for Hamoa Add device configuration to enable DCC on Hamoa platform. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 5ed2a117b9e81..ff19dac70011f 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -57,6 +57,15 @@ static const struct dcc_pdata kaanapali_pdata = { .map_ver = 0x3, }; +static const struct dcc_pdata hamoa_pdata = { + .base = 0x100ff000, + .size = 0x1000, + .ram_base = 0x10080000, + .ram_size = 0x18000, + .dcc_offset = 0x0, + .map_ver = 0x3, +}; + static int __init dcc_dev_init(void) { int ret; @@ -122,6 +131,16 @@ static int __init dcc_dev_init(void) if (ret) goto fail; + break; + case 555: + case 615: + case 616: + case 709: + case 710: + ret = platform_device_add_data(dcc_pdev, &hamoa_pdata, sizeof(hamoa_pdata)); + if (ret) + goto fail; + break; default: pr_err("DCC: Invalid SoC ID\n"); From f154ef34ed884ca719305bd905c7385ecd15a337 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 9 Feb 2026 15:45:31 +0800 Subject: [PATCH 0047/1133] QCLINUX: memory-dump: add memory dump table for Hamoa Add memory dump table configuration to enable memory dump function on Hamoa platform. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index d02e6af6c03a0..0f89cb201b783 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -339,6 +339,22 @@ static const struct dump_item kaanapali_items[] = { { C0_SCANDUMP, 0x380000, "apps-scandump" }, }; +static const struct dump_item hamoa_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { RPMH, 0xc10000, "rpmh" }, + { PMIC, 0x200000, "pmic" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, +}; + static const struct dump_table lemans_dump_table = { .items = lemans_items, .num_of_items = ARRAY_SIZE(lemans_items), @@ -374,6 +390,13 @@ static const struct dump_table kaanapali_dump_table = { .imem_size = 0x8, }; +static const struct dump_table hamoa_dump_table = { + .items = hamoa_items, + .num_of_items = ARRAY_SIZE(hamoa_items), + .imem_base = 0x146aa010, + .imem_size = 0x8, +}; + static int __init mem_dump_dev_init(void) { int ret; @@ -444,6 +467,17 @@ static int __init mem_dump_dev_init(void) if (ret) goto fail; + break; + case 555: + case 615: + case 616: + case 709: + case 710: + ret = platform_device_add_data(mem_dump_pdev, + &hamoa_dump_table, sizeof(hamoa_dump_table)); + if (ret) + goto fail; + break; default: dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); From 8a6d7ab552764fabafcd303dc7bff9ab01f2f092 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 4 Mar 2026 09:15:02 +0800 Subject: [PATCH 0048/1133] QCLINUX: memory-dump: fix array size issue for Talos Fix the wrong arrary size issue for Talos. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 0f89cb201b783..78fb377800bc9 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -364,7 +364,7 @@ static const struct dump_table lemans_dump_table = { static const struct dump_table talos_dump_table = { .items = talos_items, - .num_of_items = ARRAY_SIZE(lemans_items), + .num_of_items = ARRAY_SIZE(talos_items), .imem_base = 0x146aa010, .imem_size = 0x8, }; From 7be9ec51947720b0bf9df1751cb4021c9095a8f5 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 2 Mar 2026 15:23:32 +0800 Subject: [PATCH 0049/1133] QCLINUX: qcom-dcc: add device configuration for Glymur Add device configuration to enable DCC on Glymur platform. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index ff19dac70011f..5da18b4d221dd 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -66,6 +66,15 @@ static const struct dcc_pdata hamoa_pdata = { .map_ver = 0x3, }; +static const struct dcc_pdata glymur_pdata = { + .base = 0x100ff000, + .size = 0x1000, + .ram_base = 0x10080000, + .ram_size = 0x8000, + .dcc_offset = 0x0, + .map_ver = 0x3, +}; + static int __init dcc_dev_init(void) { int ret; @@ -141,6 +150,16 @@ static int __init dcc_dev_init(void) if (ret) goto fail; + break; + case 662: + case 698: + case 699: + case 718: + case 719: + ret = platform_device_add_data(dcc_pdev, &glymur_pdata, sizeof(glymur_pdata)); + if (ret) + goto fail; + break; default: pr_err("DCC: Invalid SoC ID\n"); From 709ebaf5a2aff4982a855f8f7c20f6ae3b554b12 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 2 Mar 2026 15:14:07 +0800 Subject: [PATCH 0050/1133] QCLINUX: memory-dump: add support for Glymur Glymur is sharing the same dump table content with Hamoa. So add Glymur's chip IDs for registering the dump table in memory. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 78fb377800bc9..0c0cb06462cc5 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -468,11 +468,18 @@ static int __init mem_dump_dev_init(void) goto fail; break; + /* Hamoa chip IDs */ case 555: case 615: case 616: case 709: case 710: + /* Glymur chip IDs */ + case 662: + case 698: + case 699: + case 718: + case 719: ret = platform_device_add_data(mem_dump_pdev, &hamoa_dump_table, sizeof(hamoa_dump_table)); if (ret) From b167fd98088d0bea52176b812141aa2cc544ed8c Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Apr 2026 14:15:20 +0800 Subject: [PATCH 0051/1133] QCLINUX: qcom-dcc: add logic to configure linked list in probe Configure the linked list with defined register entries in dcc_probe. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 38 +++++++++++++++++++++ drivers/misc/qcom-dcc.c | 67 +++++++++++++++++++++++++++++++++++++ drivers/misc/qcom-dcc.h | 16 +++++++++ 3 files changed, 121 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 5da18b4d221dd..52571a2a6228e 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -12,6 +12,24 @@ static struct platform_device *dcc_pdev; +static const struct dcc_register_entry talos_dcc_entries[] = { + { "R 0x3d96000" }, + { "R 0x3d96004" }, +}; + +static const struct dcc_link_config talos_link_configs[] = { + { + .link_list = 3, + .entries = talos_dcc_entries, + .num_entries = ARRAY_SIZE(talos_dcc_entries), + }, +}; + +static const struct dcc_config talos_config = { + .lists = talos_link_configs, + .num_lists = ARRAY_SIZE(talos_link_configs), +}; + static const struct dcc_pdata talos_pdata = { .base = 0x010a2000, .size = 0x00001000, @@ -19,6 +37,25 @@ static const struct dcc_pdata talos_pdata = { .ram_size = 0x00002000, .dcc_offset = 0x6000, .map_ver = 0x1, + .config = &talos_config, +}; + +static const struct dcc_register_entry lemans_dcc_entries[] = { + { "R 0x610110 1" }, + { "R 0x9050008 1" }, +}; + +static const struct dcc_link_config lemans_link_configs[] = { + { + .link_list = 6, + .entries = lemans_dcc_entries, + .num_entries = ARRAY_SIZE(lemans_dcc_entries), + }, +}; + +static const struct dcc_config lemans_config = { + .lists = lemans_link_configs, + .num_lists = ARRAY_SIZE(lemans_link_configs), }; static const struct dcc_pdata lemans_pdata = { @@ -28,6 +65,7 @@ static const struct dcc_pdata lemans_pdata = { .ram_size = 0x00006000, .dcc_offset = 0x38800, .map_ver = 0x3, + .config = &lemans_config, }; static const struct dcc_pdata kodiak_pdata = { diff --git a/drivers/misc/qcom-dcc.c b/drivers/misc/qcom-dcc.c index e75f98b90d8f7..d38c5f4a680b6 100644 --- a/drivers/misc/qcom-dcc.c +++ b/drivers/misc/qcom-dcc.c @@ -1425,6 +1425,72 @@ static ssize_t dcc_sram_read(struct file *file, char __user *data, return len; } +static void dcc_configure_list(struct dcc_drvdata *drvdata, + const struct dcc_config *config) +{ + const struct dcc_link_config *link; + const struct dcc_register_entry *entry; + char *token, *bufp, *buf_orig; + char *delim = " "; + int ret, i, j, configured; + size_t len; + + if (!config || !config->num_lists) + return; + + for (i = 0; i < config->num_lists; i++) { + link = &config->lists[i]; + + if (link->link_list >= drvdata->max_link_list) { + dev_err(drvdata->dev, "Invalid link list index %d\n", link->link_list); + continue; + } + + configured = 0; + + for (j = 0; j < link->num_entries; j++) { + entry = &link->entries[j]; + + len = strlen(entry->config); + buf_orig = kzalloc(len + 1, GFP_KERNEL); + if (!buf_orig) + return; + + strscpy(buf_orig, entry->config, len + 1); + bufp = buf_orig; + + token = strsep(&bufp, delim); + if (!bufp) { + dev_err(drvdata->dev, "Malformed entry: \"%s\"\n", + entry->config); + kfree(buf_orig); + continue; + } + + if (!strcmp("R", token)) { + ret = dcc_config_add_read(drvdata, bufp, link->link_list); + } else if (!strcmp("W", token)) { + ret = dcc_config_add_write(drvdata, bufp, link->link_list); + } else if (!strcmp("RW", token)) { + ret = dcc_config_add_read_write(drvdata, bufp, link->link_list); + } else if (!strcmp("L", token)) { + ret = dcc_config_add_loop(drvdata, bufp, link->link_list); + } else { + dev_err(drvdata->dev, "%s is not a correct input\n", token); + ret = -EINVAL; + } + + if (ret >= 0) + configured++; + + kfree(buf_orig); + } + + if (configured) + dcc_enable(drvdata, link->link_list); + } +} + static const struct file_operations dcc_sram_fops = { .owner = THIS_MODULE, .read = dcc_sram_read, @@ -1520,6 +1586,7 @@ static int dcc_probe(struct platform_device *pdev) } dcc_create_debug_dir(drvdata); + dcc_configure_list(drvdata, pdata->config); return 0; } diff --git a/drivers/misc/qcom-dcc.h b/drivers/misc/qcom-dcc.h index 513c95dc742b5..ce8551141062d 100644 --- a/drivers/misc/qcom-dcc.h +++ b/drivers/misc/qcom-dcc.h @@ -8,6 +8,21 @@ #include +struct dcc_register_entry { + const char *config; +}; + +struct dcc_link_config { + int link_list; + const struct dcc_register_entry *entries; + int num_entries; +}; + +struct dcc_config { + const struct dcc_link_config *lists; + int num_lists; +}; + struct dcc_pdata { phys_addr_t base; resource_size_t size; @@ -15,6 +30,7 @@ struct dcc_pdata { resource_size_t ram_size; u32 dcc_offset; u8 map_ver; + const struct dcc_config *config; }; #endif From f7c6a71ccec77c508911763cb57337ab08a7ab92 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Apr 2026 14:15:33 +0800 Subject: [PATCH 0052/1133] QCLINUX: qcom-dcc: add register list for the Talos Add the registers for configuring the linked_list of the DCC driver for debugging purpose. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 753 ++++++++++++++++++++++++++++++++++++ 1 file changed, 753 insertions(+) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 52571a2a6228e..7656e8e90aa1c 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -13,6 +13,759 @@ static struct platform_device *dcc_pdev; static const struct dcc_register_entry talos_dcc_entries[] = { + { "R 0x9680000" }, + { "R 0x9680004" }, + { "R 0x9681000" }, + { "R 0x9681004" }, + { "R 0x9681008" }, + { "R 0x968100c" }, + { "R 0x9681010" }, + { "R 0x9681014" }, + { "R 0x968101c" }, + { "R 0x9681020" }, + { "R 0x9681024" }, + { "R 0x9681028" }, + { "R 0x968102c" }, + { "R 0x9681030" }, + { "R 0x9681034" }, + { "R 0x968103c" }, + { "R 0x9698100" }, + { "R 0x9698104" }, + { "R 0x9698108" }, + { "R 0x9698110" }, + { "R 0x9698120" }, + { "R 0x9698124" }, + { "R 0x9698128" }, + { "R 0x969812c" }, + { "R 0x9698130" }, + { "R 0x9698134" }, + { "R 0x9698138" }, + { "R 0x969813c" }, + { "R 0x9698500" }, + { "R 0x9698504" }, + { "R 0x9698508" }, + { "R 0x969850c" }, + { "R 0x9698510" }, + { "R 0x9698514" }, + { "R 0x9698518" }, + { "R 0x969851c" }, + { "R 0x9698700" }, + { "R 0x9698704" }, + { "R 0x9698708" }, + { "R 0x969870c" }, + { "R 0x9698714" }, + { "R 0x9698718" }, + { "R 0x969871c" }, + { "R 0x1620204" }, + { "R 0x1620240" }, + { "R 0x1620248" }, + { "R 0x1620288" }, + { "R 0x162028C" }, + { "R 0x1620290" }, + { "R 0x1620294" }, + { "R 0x16202A8" }, + { "R 0x16202AC" }, + { "R 0x16202B0" }, + { "R 0x16202B4" }, + { "R 0x1620300" }, + { "R 0x1700204" }, + { "R 0x1700240" }, + { "R 0x1700248" }, + { "R 0x1700288" }, + { "R 0x1700290" }, + { "R 0x1700300" }, + { "R 0x1700304" }, + { "R 0x1700308" }, + { "R 0x170030C" }, + { "R 0x1700310" }, + { "R 0x1700314" }, + { "R 0x1700C08" }, + { "R 0x1700C10" }, + { "R 0x1700C20" }, + { "R 0x1700C24" }, + { "R 0x1700C28" }, + { "R 0x1700C2C" }, + { "R 0x1700C30" }, + { "R 0x1700C34" }, + { "R 0x1700C38" }, + { "R 0x1700C3C" }, + { "R 0x1740240" }, + { "R 0x1740248" }, + { "R 0x1740288" }, + { "R 0x1740290" }, + { "R 0x1740300" }, + { "R 0x1740304" }, + { "R 0x1740308" }, + { "R 0x174030C" }, + { "R 0x1740310" }, + { "R 0x1740314" }, + { "R 0x1740004" }, + { "R 0x1740008" }, + { "R 0x1740010" }, + { "R 0x1740020" }, + { "R 0x1740024" }, + { "R 0x1740028" }, + { "R 0x174002C" }, + { "R 0x1740030" }, + { "R 0x1740034" }, + { "R 0x1740038" }, + { "R 0x174003C" }, + { "R 0x9698204" }, + { "R 0x9698240" }, + { "R 0x9698244" }, + { "R 0x9698248" }, + { "R 0x969824C" }, + { "R 0x9681010" }, + { "R 0x9681014" }, + { "R 0x9681018" }, + { "R 0x968101C" }, + { "R 0x9681020" }, + { "R 0x9681024" }, + { "R 0x9681028" }, + { "R 0x968102C" }, + { "R 0x9681030" }, + { "R 0x9681034" }, + { "R 0x968103C" }, + { "R 0x9698100" }, + { "R 0x9698104" }, + { "R 0x9698108" }, + { "R 0x9698110" }, + { "R 0x9698120" }, + { "R 0x9698124" }, + { "R 0x9698128" }, + { "R 0x969812C" }, + { "R 0x9698130" }, + { "R 0x9698134" }, + { "R 0x9698138" }, + { "R 0x969813C" }, + { "R 0x62BE2004" }, + { "R 0x62BE2040" }, + { "R 0x62BE2048" }, + { "R 0x62BE2088" }, + { "R 0x62BE2090" }, + { "R 0x62BE2100" }, + { "R 0x62BE2104" }, + { "R 0x62BE2108" }, + { "R 0x62BE210C" }, + { "R 0x62BE2110" }, + { "R 0x62BE2114" }, + { "R 0x62BE2118" }, + { "R 0x62BE0010" }, + { "R 0x62BE0020" }, + { "R 0x62BE0024" }, + { "R 0x62BE0028" }, + { "R 0x62BE002C" }, + { "R 0x62BE0030" }, + { "R 0x62BE0034" }, + { "R 0x62BE0038" }, + { "R 0x62BE003C" }, + { "R 0x9160204" }, + { "R 0x9160240" }, + { "R 0x9160248" }, + { "R 0x9160288" }, + { "R 0x9160290" }, + { "R 0x9160300" }, + { "R 0x9160304" }, + { "R 0x9160308" }, + { "R 0x916030C" }, + { "R 0x9160310" }, + { "R 0x9160314" }, + { "R 0x9160318" }, + { "R 0x9160008" }, + { "R 0x9160010" }, + { "R 0x9160020" }, + { "R 0x9160024" }, + { "R 0x9160028" }, + { "R 0x916002C" }, + { "R 0x9160030" }, + { "R 0x9160034" }, + { "R 0x9160038" }, + { "R 0x916003C" }, + { "R 0x1620500 4" }, + { "R 0x1620700 4" }, + { "R 0x1620300" }, + { "R 0x1620F00 2" }, + { "R 0x1620B00 2" }, + { "R 0x1700B00 2" }, + { "R 0x1700700 3" }, + { "R 0x9163100" }, + { "R 0x96AA100" }, + { "R 0x9050008" }, + { "R 0x9050068" }, + { "R 0x9050078" }, + { "R 0x18200400" }, + { "R 0x18200404" }, + { "R 0x18200408" }, + { "R 0x18200038" }, + { "R 0x18200040" }, + { "R 0x18200048" }, + { "R 0x18220038" }, + { "R 0x18220040" }, + { "R 0x182200D0" }, + { "R 0x18200030" }, + { "R 0x18200010" }, + { "R 0x1822000c" }, + { "R 0x18220d14" }, + { "R 0x18220fb4" }, + { "R 0x18221254" }, + { "R 0x182214f4" }, + { "R 0x18221794" }, + { "R 0x18221a34" }, + { "R 0x18221cd4" }, + { "R 0x18221f74" }, + { "R 0x18220d18" }, + { "R 0x18220fb8" }, + { "R 0x18221258" }, + { "R 0x182214f8" }, + { "R 0x18221798" }, + { "R 0x18221a38" }, + { "R 0x18221cd8" }, + { "R 0x18221f78" }, + { "R 0x18220d00" }, + { "R 0x18220d04" }, + { "R 0x18220d1c" }, + { "R 0x18220fbc" }, + { "R 0x1822125c" }, + { "R 0x182214fc" }, + { "R 0x1822179c" }, + { "R 0x18221a3c" }, + { "R 0x18221cdc" }, + { "R 0x18221f7c" }, + { "R 0x18221274" }, + { "R 0x18221288" }, + { "R 0x1822129c" }, + { "R 0x182212b0" }, + { "R 0x182212c4" }, + { "R 0x182212d8" }, + { "R 0x182212ec" }, + { "R 0x18221300" }, + { "R 0x18221314" }, + { "R 0x18221328" }, + { "R 0x1822133c" }, + { "R 0x18221350" }, + { "R 0x18221364" }, + { "R 0x18221378" }, + { "R 0x1822138c" }, + { "R 0x182213a0" }, + { "R 0x18221514" }, + { "R 0x18221528" }, + { "R 0x1822153c" }, + { "R 0x18221550" }, + { "R 0x18221564" }, + { "R 0x18221578" }, + { "R 0x1822158c" }, + { "R 0x182215a0" }, + { "R 0x182215b4" }, + { "R 0x182215c8" }, + { "R 0x182215dc" }, + { "R 0x182215f0" }, + { "R 0x18221604" }, + { "R 0x18221618" }, + { "R 0x1822162c" }, + { "R 0x18221640" }, + { "R 0x182217b4" }, + { "R 0x182217c8" }, + { "R 0x182217dc" }, + { "R 0x182217f0" }, + { "R 0x18221804" }, + { "R 0x18221818" }, + { "R 0x1822182c" }, + { "R 0x18221840" }, + { "R 0x18221854" }, + { "R 0x18221868" }, + { "R 0x1822187c" }, + { "R 0x18221890" }, + { "R 0x182218a4" }, + { "R 0x182218b8" }, + { "R 0x182218cc" }, + { "R 0x182218e0" }, + { "R 0x18221a54" }, + { "R 0x18221a68" }, + { "R 0x18221a7c" }, + { "R 0x18221a90" }, + { "R 0x18221aa4" }, + { "R 0x18221ab8" }, + { "R 0x18221acc" }, + { "R 0x18221ae0" }, + { "R 0x18221af4" }, + { "R 0x18221b08" }, + { "R 0x18221b1c" }, + { "R 0x18221b30" }, + { "R 0x18221b44" }, + { "R 0x18221b58" }, + { "R 0x18221b6c" }, + { "R 0x18221b80" }, + { "R 0x18221cf4" }, + { "R 0x18221d08" }, + { "R 0x18221d1c" }, + { "R 0x18221d30" }, + { "R 0x18221d44" }, + { "R 0x18221d58" }, + { "R 0x18221d6c" }, + { "R 0x18221d80" }, + { "R 0x18221d94" }, + { "R 0x18221da8" }, + { "R 0x18221dbc" }, + { "R 0x18221dd0" }, + { "R 0x18221de4" }, + { "R 0x18221df8" }, + { "R 0x18221e0c" }, + { "R 0x18221e20" }, + { "R 0x18221f94" }, + { "R 0x18221fa8" }, + { "R 0x18221fbc" }, + { "R 0x18221fd0" }, + { "R 0x18221fe4" }, + { "R 0x18221ff8" }, + { "R 0x1822200c" }, + { "R 0x18222020" }, + { "R 0x18222034" }, + { "R 0x18222048" }, + { "R 0x1822205c" }, + { "R 0x18222070" }, + { "R 0x18222084" }, + { "R 0x18222098" }, + { "R 0x182220ac" }, + { "R 0x182220c0" }, + { "R 0x18221278" }, + { "R 0x1822128c" }, + { "R 0x182212a0" }, + { "R 0x182212b4" }, + { "R 0x182212c8" }, + { "R 0x182212dc" }, + { "R 0x182212f0" }, + { "R 0x18221304" }, + { "R 0x18221318" }, + { "R 0x1822132c" }, + { "R 0x18221340" }, + { "R 0x18221354" }, + { "R 0x18221368" }, + { "R 0x1822137c" }, + { "R 0x18221390" }, + { "R 0x182213a4" }, + { "R 0x18221518" }, + { "R 0x1822152c" }, + { "R 0x18221540" }, + { "R 0x18221554" }, + { "R 0x18221568" }, + { "R 0x1822157c" }, + { "R 0x18221590" }, + { "R 0x182215a4" }, + { "R 0x182215b8" }, + { "R 0x182215cc" }, + { "R 0x182215e0" }, + { "R 0x182215f4" }, + { "R 0x18221608" }, + { "R 0x1822161c" }, + { "R 0x18221630" }, + { "R 0x18221644" }, + { "R 0x182217b8" }, + { "R 0x182217cc" }, + { "R 0x182217e0" }, + { "R 0x182217f4" }, + { "R 0x18221808" }, + { "R 0x1822181c" }, + { "R 0x18221830" }, + { "R 0x18221844" }, + { "R 0x18221858" }, + { "R 0x1822186c" }, + { "R 0x18221880" }, + { "R 0x18221894" }, + { "R 0x182218a8" }, + { "R 0x182218bc" }, + { "R 0x182218d0" }, + { "R 0x182218e4" }, + { "R 0x18221a58" }, + { "R 0x18221a6c" }, + { "R 0x18221a80" }, + { "R 0x18221a94" }, + { "R 0x18221aa8" }, + { "R 0x18221abc" }, + { "R 0x18221ad0" }, + { "R 0x18221ae4" }, + { "R 0x18221af8" }, + { "R 0x18221b0c" }, + { "R 0x18221b20" }, + { "R 0x18221b34" }, + { "R 0x18221b48" }, + { "R 0x18221b5c" }, + { "R 0x18221b70" }, + { "R 0x18221b84" }, + { "R 0x18221cf8" }, + { "R 0x18221d0c" }, + { "R 0x18221d20" }, + { "R 0x18221d34" }, + { "R 0x18221d48" }, + { "R 0x18221d5c" }, + { "R 0x18221d70" }, + { "R 0x18221d84" }, + { "R 0x18221d98" }, + { "R 0x18221dac" }, + { "R 0x18221dc0" }, + { "R 0x18221dd4" }, + { "R 0x18221de8" }, + { "R 0x18221dfc" }, + { "R 0x18221e10" }, + { "R 0x18221e24" }, + { "R 0x18221f98" }, + { "R 0x18221fac" }, + { "R 0x18221fc0" }, + { "R 0x18221fd4" }, + { "R 0x18221fe8" }, + { "R 0x18221ffc" }, + { "R 0x18222010" }, + { "R 0x18222024" }, + { "R 0x18222038" }, + { "R 0x1822204c" }, + { "R 0x18222060" }, + { "R 0x18222074" }, + { "R 0x18222088" }, + { "R 0x1822209c" }, + { "R 0x182220b0" }, + { "R 0x182220c4" }, + { "R 0x18000024" }, + { "R 0x18000040" }, + { "R 0x18010024" }, + { "R 0x18010040" }, + { "R 0x18020024" }, + { "R 0x18020040" }, + { "R 0x18030024" }, + { "R 0x18030040" }, + { "R 0x18040024" }, + { "R 0x18040040" }, + { "R 0x18050024" }, + { "R 0x18050040" }, + { "R 0x18060024" }, + { "R 0x18060040" }, + { "R 0x18070024" }, + { "R 0x18070040" }, + { "R 0x18080024" }, + { "R 0x18080040" }, + { "R 0x180800F8" }, + { "R 0x18080104" }, + { "R 0x1808011C" }, + { "R 0x18080128" }, + { "R 0x90b0280" }, + { "R 0x90b0288" }, + { "R 0x90b028c" }, + { "R 0x90b0290" }, + { "R 0x90b0294" }, + { "R 0x90b0298" }, + { "R 0x90b029c" }, + { "R 0x90b02a0" }, + { "R 0x18321700" }, + { "R 0x18322C18" }, + { "R 0x18323700" }, + { "R 0x18324C18" }, + { "R 0x18325F00" }, + { "R 0x18327418" }, + { "R 0x9236028" }, + { "R 0x923602C" }, + { "R 0x9236030" }, + { "R 0x9236034" }, + { "R 0x9236038" }, + { "R 0x9232100" }, + { "R 0x92360b0" }, + { "R 0x9236044" }, + { "R 0x9236048" }, + { "R 0x923604c" }, + { "R 0x9236050" }, + { "R 0x923e030" }, + { "R 0x923e034" }, + { "R 0x9241000" }, + { "R 0x9248058" }, + { "R 0x924805c" }, + { "R 0x9248060" }, + { "R 0x9248064" }, + { "R 0x9260410" }, + { "R 0x92e0410" }, + { "R 0x9260414" }, + { "R 0x92e0414" }, + { "R 0x9260418" }, + { "R 0x92e0418" }, + { "R 0x9260420" }, + { "R 0x9260424" }, + { "R 0x9260430" }, + { "R 0x9260440" }, + { "R 0x9260448" }, + { "R 0x92604a0" }, + { "R 0x92e0420" }, + { "R 0x92e0424" }, + { "R 0x92e0430" }, + { "R 0x92e0440" }, + { "R 0x92e0448" }, + { "R 0x92e04a0" }, + { "R 0x9600000" }, + { "R 0x9601000" }, + { "R 0x9602000" }, + { "R 0x9603000" }, + { "R 0x9604000" }, + { "R 0x9605000" }, + { "R 0x9606000" }, + { "R 0x9607000" }, + { "R 0x9608000" }, + { "R 0x9609000" }, + { "R 0x960a000" }, + { "R 0x960b000" }, + { "R 0x960c000" }, + { "R 0x960d000" }, + { "R 0x960e000" }, + { "R 0x960f000" }, + { "R 0x9610000" }, + { "R 0x9611000" }, + { "R 0x9612000" }, + { "R 0x9613000" }, + { "R 0x9614000" }, + { "R 0x9615000" }, + { "R 0x9616000" }, + { "R 0x9617000" }, + { "R 0x9618000" }, + { "R 0x9619000" }, + { "R 0x961a000" }, + { "R 0x961b000" }, + { "R 0x961c000" }, + { "R 0x961d000" }, + { "R 0x961e000" }, + { "R 0x961f000" }, + { "R 0x9600004" }, + { "R 0x9601004" }, + { "R 0x9602004" }, + { "R 0x9603004" }, + { "R 0x9604004" }, + { "R 0x9605004" }, + { "R 0x9606004" }, + { "R 0x9607004" }, + { "R 0x9608004" }, + { "R 0x9609004" }, + { "R 0x960a004" }, + { "R 0x960b004" }, + { "R 0x960c004" }, + { "R 0x960d004" }, + { "R 0x960e004" }, + { "R 0x960f004" }, + { "R 0x9610004" }, + { "R 0x9611004" }, + { "R 0x9612004" }, + { "R 0x9613004" }, + { "R 0x9614004" }, + { "R 0x9615004" }, + { "R 0x9616004" }, + { "R 0x9617004" }, + { "R 0x9618004" }, + { "R 0x9619004" }, + { "R 0x961a004" }, + { "R 0x961b004" }, + { "R 0x961c004" }, + { "R 0x961d004" }, + { "R 0x961e004" }, + { "R 0x961f004" }, + { "R 0x9266418" }, + { "R 0x92e6418" }, + { "R 0x9265804" }, + { "R 0x92e5804" }, + { "R 0x92604b8" }, + { "R 0x92e04b8" }, + { "R 0x0C201244 1" }, + { "R 0x0C202244 1" }, + { "R 0x18100C18 1" }, + { "R 0x18101C18 1" }, + { "R 0x18300000 1" }, + { "R 0x183A3A84 2" }, + { "R 0x18393A84 2" }, + { "R 0x00100000" }, + { "R 0x00100004" }, + { "R 0x00100008" }, + { "R 0x0010000C" }, + { "R 0x00100010" }, + { "R 0x00100014" }, + { "R 0x00100018" }, + { "R 0x0010001C" }, + { "R 0x00100020" }, + { "R 0x00100024" }, + { "R 0x00100028" }, + { "R 0x0010002C" }, + { "R 0x00100030" }, + { "R 0x00100034" }, + { "R 0x00100100" }, + { "R 0x00100104" }, + { "R 0x00100108" }, + { "R 0x0010010C" }, + { "R 0x00101000" }, + { "R 0x00101004" }, + { "R 0x00101008" }, + { "R 0x0010100C" }, + { "R 0x00101010" }, + { "R 0x00101014" }, + { "R 0x00101018" }, + { "R 0x0010101C" }, + { "R 0x00101020" }, + { "R 0x00101024" }, + { "R 0x00101028" }, + { "R 0x0010102C" }, + { "R 0x00101030" }, + { "R 0x00101034" }, + { "R 0x00102000" }, + { "R 0x00102004" }, + { "R 0x00102008" }, + { "R 0x0010200C" }, + { "R 0x00102010" }, + { "R 0x00102014" }, + { "R 0x00102018" }, + { "R 0x0010201C" }, + { "R 0x00102020" }, + { "R 0x00102024" }, + { "R 0x00102028" }, + { "R 0x0010202C" }, + { "R 0x00102030" }, + { "R 0x00102034" }, + { "R 0x00103000" }, + { "R 0x00103004" }, + { "R 0x00103008" }, + { "R 0x0010300C" }, + { "R 0x00103010" }, + { "R 0x00103014" }, + { "R 0x00103018" }, + { "R 0x0010301C" }, + { "R 0x00103020" }, + { "R 0x00103024" }, + { "R 0x00103028" }, + { "R 0x0010302C" }, + { "R 0x00103030" }, + { "R 0x00103034" }, + { "R 0x00113000" }, + { "R 0x00113004" }, + { "R 0x00113008" }, + { "R 0x0011300C" }, + { "R 0x00113010" }, + { "R 0x00113014" }, + { "R 0x00113018" }, + { "R 0x0011301C" }, + { "R 0x00113020" }, + { "R 0x00113024" }, + { "R 0x00113028" }, + { "R 0x0011302C" }, + { "R 0x00113030" }, + { "R 0x00113034" }, + { "R 0x0011A000" }, + { "R 0x0011A004" }, + { "R 0x0011A008" }, + { "R 0x0011A00C" }, + { "R 0x0011A010" }, + { "R 0x0011A014" }, + { "R 0x0011A018" }, + { "R 0x0011A01C" }, + { "R 0x0011A020" }, + { "R 0x0011A024" }, + { "R 0x0011A028" }, + { "R 0x0011A02C" }, + { "R 0x0011A030" }, + { "R 0x0011A034" }, + { "R 0x0011B000" }, + { "R 0x0011B004" }, + { "R 0x0011B008" }, + { "R 0x0011B00C" }, + { "R 0x0011B010" }, + { "R 0x0011B014" }, + { "R 0x0011B018" }, + { "R 0x0011B01C" }, + { "R 0x0011B020" }, + { "R 0x0011B024" }, + { "R 0x0011B028" }, + { "R 0x0011B02C" }, + { "R 0x0011B030" }, + { "R 0x0011B034" }, + { "R 0x00174000" }, + { "R 0x00174004" }, + { "R 0x00174008" }, + { "R 0x0017400C" }, + { "R 0x00174010" }, + { "R 0x00174014" }, + { "R 0x00174018" }, + { "R 0x0017401C" }, + { "R 0x00174020" }, + { "R 0x00174024" }, + { "R 0x00174028" }, + { "R 0x0017402C" }, + { "R 0x00174030" }, + { "R 0x00174034" }, + { "R 0x00176000" }, + { "R 0x00176004" }, + { "R 0x00176008" }, + { "R 0x0017600C" }, + { "R 0x00176010" }, + { "R 0x00176014" }, + { "R 0x00176018" }, + { "R 0x0017601C" }, + { "R 0x00176020" }, + { "R 0x00176024" }, + { "R 0x00176028" }, + { "R 0x0017602C" }, + { "R 0x00176030" }, + { "R 0x00176034" }, + { "R 0x0010401C" }, + { "R 0x00183024" }, + { "R 0x00144168" }, + { "R 0x0011702C" }, + { "R 0x0010904C" }, + { "R 0x00189038" }, + { "R 0x001443E8" }, + { "R 0x001442B8" }, + { "R 0x00105060" }, + { "R 0x00141024" }, + { "R 0x00145038" }, + { "R 0x00109004" }, + { "R 0x00189004" }, + { "R 0x00190004" }, + { "R 0x0C2A0000" }, + { "R 0x0C2A0004" }, + { "R 0x0C2A0008" }, + { "R 0x0C2A000C" }, + { "R 0x0C2A0010" }, + { "R 0x0C2A0014" }, + { "R 0x0C2A0018" }, + { "R 0x0C2A001C" }, + { "R 0x0C2A0020" }, + { "R 0x0C2A0024" }, + { "R 0x0C2A0028" }, + { "R 0x0C2A002C" }, + { "R 0x0C2A0030" }, + { "R 0x0C2A0034" }, + { "R 0x0C2A1000" }, + { "R 0x0C2A1004" }, + { "R 0x0C2A1008" }, + { "R 0x0C2A100C" }, + { "R 0x0C2A1010" }, + { "R 0x0C2A1014" }, + { "R 0x0C2A1018" }, + { "R 0x0C2A101C" }, + { "R 0x0C2A1020" }, + { "R 0x0C2A1024" }, + { "R 0x0C2A1028" }, + { "R 0x0C2A102C" }, + { "R 0x0C2A1030" }, + { "R 0x0C2A2260" }, + { "R 0x0C2A2264" }, + { "R 0x0C2A3008" }, + { "R 0x0C2A300C" }, + { "R 0x0C2A3010" }, + { "R 0x0C2A3014" }, + { "R 0x0C2A3024" }, + { "R 0x0C2A2034" }, + { "R 0x0C2A214C" }, + { "R 0x0C2A2150" }, + { "R 0x0C2A2154" }, + { "R 0x0C2630A0 4" }, + { "R 0x0C2630B0 4" }, + { "R 0x0C2630C0 4" }, + { "R 0x0C2630D0 4" }, + { "R 0x1800005C 1" }, + { "R 0x1801005C 1" }, + { "R 0x1802005C 1" }, + { "R 0x1803005C 1" }, + { "R 0x1804005C 1" }, + { "R 0x1805005C 1" }, + { "R 0x1806005C 1" }, + { "R 0x1807005C 1" }, { "R 0x3d96000" }, { "R 0x3d96004" }, }; From a0c6ec44d1888744a41a1d85a50e60a11d19e2ad Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Apr 2026 21:26:53 +0800 Subject: [PATCH 0053/1133] QCLINUX: qcom-dcc: use late_initcall and build as built-in for boot debug The DCC device stub driver was registered with module_init(), which runs during the initcall sequence before late_initcall(). The DCC hardware depends on resources that are not yet available at that point, causing the driver to fail silently during early boot. Switch to late_initcall() so the driver initialises after all subsystem dependencies are ready. Remove the module_exit() registration since the driver is now built-in only. Update qcom_debug.config to build CONFIG_QCOM_DCC and CONFIG_QCOM_DCC_DEV as built-in (=y) instead of loadable modules (=m) to match the late_initcall() requirement and allow early boot debugging. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 4 ++-- drivers/misc/qcom-dcc-dev.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index 48ae2fb9737ac..0419414d6c51b 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1,4 +1,4 @@ -CONFIG_QCOM_DCC=m -CONFIG_QCOM_DCC_DEV=m +CONFIG_QCOM_DCC=y +CONFIG_QCOM_DCC_DEV=y CONFIG_QCOM_MEMORY_DUMP_V2=y CONFIG_QCOM_MEMORY_DUMP_DEV=m diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 7656e8e90aa1c..4d0c9c9526da3 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -978,7 +978,6 @@ static void __exit dcc_dev_exit(void) platform_device_unregister(dcc_pdev); } -module_init(dcc_dev_init); -module_exit(dcc_dev_exit); +late_initcall(dcc_dev_init); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Qualcomm Technologies Inc. DCC driver, device stub"); From 6ec91c7c9ea6d2998d44f2872a57311d591e7300 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Apr 2026 21:27:10 +0800 Subject: [PATCH 0054/1133] QCLINUX: memory-dump: use late_initcall and build as built-in for boot debug The memory dump device stub driver was registered with module_init(), which runs before late_initcall(). The memory dump subsystem depends on resources that are not yet available at that point, causing the driver to fail silently during early boot. Switch to late_initcall() so the driver initialises after all subsystem dependencies are ready. Remove the module_exit() registration since the driver is now built-in only. Update qcom_debug.config to build CONFIG_QCOM_MEMORY_DUMP_DEV as built-in (=y) instead of a loadable module (=m) to match the late_initcall() requirement and allow early boot debugging. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom_debug.config | 2 +- drivers/firmware/qcom/memory_dump_dev.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm64/configs/qcom_debug.config b/arch/arm64/configs/qcom_debug.config index 0419414d6c51b..1399972795b68 100644 --- a/arch/arm64/configs/qcom_debug.config +++ b/arch/arm64/configs/qcom_debug.config @@ -1,4 +1,4 @@ CONFIG_QCOM_DCC=y CONFIG_QCOM_DCC_DEV=y CONFIG_QCOM_MEMORY_DUMP_V2=y -CONFIG_QCOM_MEMORY_DUMP_DEV=m +CONFIG_QCOM_MEMORY_DUMP_DEV=y diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 0c0cb06462cc5..0845aa152dc2f 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -513,7 +513,6 @@ static void __exit mem_dump_dev_exit(void) platform_device_unregister(mem_dump_pdev); } -module_init(mem_dump_dev_init); -module_exit(mem_dump_dev_exit); +late_initcall(mem_dump_dev_init); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Qualcomm Technologies Inc. Memory Dump driver V2, device stub"); From 6216289e470a54bc9f56f20cbbc35c4dbc55545d Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 29 Apr 2026 11:34:26 +0800 Subject: [PATCH 0055/1133] QCLINUX: qcom-dcc: add lemans register list and move config to header Add the full DCC register capture list for the Lemans platform derived from debug_config_qcs9100.sh. The registers cover LPM, TSENS, PLL, LIMITS, and DDR subsystems, all configured on linked list 6 to match the runtime script (LLNUM=6 in configure_dcc()). Consecutive single-word reads are merged into burst entries (e.g. "R addr N") to keep the array compact; the kernel driver merges them identically via dcc_config_add(). Estimated SRAM usage is ~19 KB, within the 24 KB (0x6000) budget for the Lemans DCC RAM. Move the lemans DCC configuration (entries array, link config, dcc config, and pdata) into a dedicated header qcom-dcc-lemans-config.h to avoid bloating qcom-dcc-dev.c with the large register table. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 29 +- drivers/misc/qcom-dcc-lemans-config.h | 1630 +++++++++++++++++++++++++ 2 files changed, 1631 insertions(+), 28 deletions(-) create mode 100644 drivers/misc/qcom-dcc-lemans-config.h diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 4d0c9c9526da3..d3dcda2d3e5fc 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -7,6 +7,7 @@ #include #include #include "qcom-dcc.h" +#include "qcom-dcc-lemans-config.h" #define DEV_NAME "qcom-dcc" @@ -793,34 +794,6 @@ static const struct dcc_pdata talos_pdata = { .config = &talos_config, }; -static const struct dcc_register_entry lemans_dcc_entries[] = { - { "R 0x610110 1" }, - { "R 0x9050008 1" }, -}; - -static const struct dcc_link_config lemans_link_configs[] = { - { - .link_list = 6, - .entries = lemans_dcc_entries, - .num_entries = ARRAY_SIZE(lemans_dcc_entries), - }, -}; - -static const struct dcc_config lemans_config = { - .lists = lemans_link_configs, - .num_lists = ARRAY_SIZE(lemans_link_configs), -}; - -static const struct dcc_pdata lemans_pdata = { - .base = 0x040ff000, - .size = 0x00001000, - .ram_base = 0x040b8800, - .ram_size = 0x00006000, - .dcc_offset = 0x38800, - .map_ver = 0x3, - .config = &lemans_config, -}; - static const struct dcc_pdata kodiak_pdata = { .base = 0x0117f000, .size = 0x00001000, diff --git a/drivers/misc/qcom-dcc-lemans-config.h b/drivers/misc/qcom-dcc-lemans-config.h new file mode 100644 index 0000000000000..01327a67eac91 --- /dev/null +++ b/drivers/misc/qcom-dcc-lemans-config.h @@ -0,0 +1,1630 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_LEMANS_CONFIG_H +#define _QCOM_DCC_LEMANS_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry lemans_dcc_entries[] = { + /* lpm */ + { "R 0x18000040" }, + { "R 0x18000024" }, + { "R 0x18010024" }, + { "R 0x18010040" }, + { "R 0x18020024" }, + { "R 0x18020040" }, + { "R 0x18030024" }, + { "R 0x18030040" }, + { "R 0x18040024" }, + { "R 0x18040040" }, + { "R 0x18050024" }, + { "R 0x18050040" }, + { "R 0x18060024" }, + { "R 0x18060040" }, + { "R 0x18070024" }, + { "R 0x18070040" }, + { "R 0x18080024" }, + { "R 0x18080040" }, + { "R 0x18090024" }, + { "R 0x18090040" }, + { "R 0x18090104" }, + { "R 0x180900f8" }, + { "R 0x180800f4" }, + { "R 0x18080104" }, + { "R 0x180800f8" }, + { "R 0x180900f4" }, + { "R 0x18210404 2" }, + { "R 0xb201024" }, + { "R 0xb201020" }, + { "R 0xb211020" }, + { "R 0xb221020" }, + { "R 0xb232020" }, + /* tsens */ + { "R 0xc222004" }, + { "R 0xc263014" }, + { "R 0xc2630e0" }, + { "R 0xc2630ec" }, + { "R 0xc2630a0 16" }, + { "R 0xc2630e8" }, + { "R 0xc26313c" }, + { "R 0xc223004" }, + { "R 0xc265014" }, + { "R 0xc2650e0" }, + { "R 0xc2650ec" }, + { "R 0xc2650a0 16" }, + { "R 0xc2650e8" }, + { "R 0xc26513c" }, + { "R 0xc224004" }, + { "R 0xc251014" }, + { "R 0xc2510e0" }, + { "R 0xc2510ec" }, + { "R 0xc2510a0 16" }, + { "R 0xc2510e8" }, + { "R 0xc25113c" }, + { "R 0xc225004" }, + { "R 0xc252014" }, + { "R 0xc2520e0" }, + { "R 0xc2520ec" }, + { "R 0xc2520a0 16" }, + { "R 0xc2520e8" }, + { "R 0xc25213c" }, + /* pll */ + { "R 0x182b0000 12" }, + { "R 0x182b003c" }, + { "R 0x182b4000 12" }, + { "R 0x182b403c" }, + { "R 0x18280044" }, + { "R 0x1828004c" }, + { "R 0x18280060" }, + { "R 0x18284044" }, + { "R 0x1828404c" }, + { "R 0x18284060" }, + { "R 0x182b2000 12" }, + { "R 0x182b203c" }, + { "R 0x182b6000 12" }, + { "R 0x182b603c" }, + { "R 0x18282044" }, + { "R 0x1828204c" }, + { "R 0x18282060" }, + { "R 0x18286044" }, + { "R 0x1828604c" }, + { "R 0x18286060" }, + /* limits */ + { "R 0xec80010" }, + { "R 0xec81000" }, + { "R 0xec81010 64" }, + { "R 0x18378220 2" }, + { "R 0x183782a0 2" }, + { "R 0x183784a0 12" }, + { "R 0x18378520" }, + { "R 0x18378588" }, + { "R 0x18378d90 12" }, + { "R 0x18379010 10" }, + { "R 0x18379090 10" }, + { "R 0x18379a90 8" }, + { "R 0x18370220 2" }, + { "R 0x183702a0 2" }, + { "R 0x183704a0 12" }, + { "R 0x18370520" }, + { "R 0x18370588" }, + { "R 0x18370d90 12" }, + { "R 0x18371010 10" }, + { "R 0x18371090 10" }, + { "R 0x18371a90 8" }, + { "R 0x26310220 3" }, + { "R 0x263102a0 3" }, + { "R 0x263104a0 6" }, + { "R 0x26310520" }, + { "R 0x26310588" }, + { "R 0x26310d90 8" }, + { "R 0x26311010 6" }, + { "R 0x26311090 6" }, + { "R 0x26311a90 3" }, + { "R 0x2a310220 3" }, + { "R 0x2a3102a0 3" }, + { "R 0x2a3104a0 6" }, + { "R 0x2a310520" }, + { "R 0x2a310588" }, + { "R 0x2a310d90 8" }, + { "R 0x2a311010 6" }, + { "R 0x2a311090 6" }, + { "R 0x2a311a90 3" }, + /* ddr */ + { "R 0x610110" }, + { "R 0x9050008" }, + { "R 0x905001c" }, + { "R 0x9050030" }, + { "R 0x9050050" }, + { "R 0x9050070" }, + { "R 0x9050948" }, + { "R 0x905104c" }, + { "R 0x9050078" }, + { "R 0x9050114" }, + { "R 0x90a0008 2" }, + { "R 0x90a0080" }, + { "R 0x90a1008 2" }, + { "R 0x90a80e4 2" }, + { "R 0x90a816c 2" }, + { "R 0x90a80f8" }, + { "R 0x90a8180 2" }, + { "R 0x90a81a0 2" }, + { "R 0x90a81c0 2" }, + { "R 0x90a81e4" }, + { "R 0x90a81f4" }, + { "R 0x90a8204" }, + { "R 0x90a8218" }, + { "R 0x90a8228" }, + { "R 0x90a8264 2" }, + { "R 0x90a8270" }, + { "R 0x90a80fc 4" }, + { "R 0x90a8148 2" }, + { "R 0x90a8158 2" }, + { "R 0x90a8190 2" }, + { "R 0x90a81b0 2" }, + { "R 0x90a81d0 2" }, + { "R 0x90a84f4" }, + { "R 0x90a8138" }, + { "R 0x90a8150" }, + { "R 0x90a8160" }, + { "R 0x90a8198" }, + { "R 0x90a81b8" }, + { "R 0x90a81d8" }, + { "R 0x90a8280" }, + { "R 0x90a819c" }, + { "R 0x90a81bc" }, + { "R 0x90a81dc" }, + { "R 0x90a821c" }, + { "R 0x90a822c" }, + { "R 0x90a84f8" }, + { "R 0x90a9204" }, + { "R 0x90a880c" }, + { "R 0x90a8834" }, + { "R 0x90a8840 2" }, + { "R 0x90a8850 2" }, + { "R 0x90a8860 3" }, + { "R 0x90a8878" }, + { "R 0x90a8884" }, + { "R 0x90a9260" }, + { "R 0x90a8900" }, + { "R 0x90a9134 2" }, + { "R 0x90a8880 3" }, + { "R 0x90e0000" }, + { "R 0x90e0008" }, + { "R 0x90e0010" }, + { "R 0x90e0020 8" }, + { "R 0x90e0248" }, + { "R 0x90e3100" }, + { "R 0x90e4100 7" }, + { "R 0x90e5008" }, + { "R 0x90e5010 3" }, + { "R 0x9080024" }, + { "R 0x908002c" }, + { "R 0x9080034" }, + { "R 0x908003c" }, + { "R 0x9080044" }, + { "R 0x908004c" }, + { "R 0x9080054 3" }, + { "R 0x90800b8 2" }, + { "R 0x90800c8" }, + { "R 0x90800d4" }, + { "R 0x90800e0" }, + { "R 0x90800ec" }, + { "R 0x90800f8" }, + { "R 0x9080104 2" }, + { "R 0x9080114" }, + { "R 0x9080144" }, + { "R 0x908014c" }, + { "R 0x9080168" }, + { "R 0x9080174" }, + { "R 0x90801ac" }, + { "R 0x90801b4" }, + { "R 0x90801bc" }, + { "R 0x90801c4" }, + { "R 0x90801cc" }, + { "R 0x90801d4" }, + { "R 0x90801dc" }, + { "R 0x90801e4" }, + { "R 0x90801ec" }, + { "R 0x90801f4 2" }, + { "R 0x90ba000" }, + { "R 0x90ba050" }, + { "R 0x90ba280" }, + { "R 0x90ba288" }, + { "R 0x9280610 4" }, + { "R 0x9280680 4" }, + { "R 0x9380610" }, + { "R 0x9280614" }, + { "R 0x9380618 2" }, + { "R 0x9380680 4" }, + { "R 0x9480610 4" }, + { "R 0x9480680 4" }, + { "R 0x9580610 4" }, + { "R 0x9580680 4" }, + { "R 0x9680610 4" }, + { "R 0x9680680 4" }, + { "R 0x9380610" }, + { "R 0x9280614" }, + { "R 0x9380618 2" }, + { "R 0x9380680 4" }, + { "R 0x9100008" }, + { "R 0x9100010" }, + { "R 0x9100408" }, + { "R 0x9100410" }, + { "R 0x9100808" }, + { "R 0x9100810" }, + { "R 0x9100c08" }, + { "R 0x9100c10" }, + { "R 0x9101008" }, + { "R 0x9101010" }, + { "R 0x9101408" }, + { "R 0x9101410" }, + { "R 0x9101808" }, + { "R 0x9101810" }, + { "R 0x9101c08" }, + { "R 0x9101c10" }, + { "R 0x9102008" }, + { "R 0x9102010" }, + { "R 0x9102408" }, + { "R 0x9102410" }, + { "R 0x9102808" }, + { "R 0x9102810" }, + { "R 0x9102c08" }, + { "R 0x9102c10" }, + { "R 0x9103000 3" }, + { "R 0x9103010 3" }, + { "R 0x9103080 3" }, + { "R 0x9103090 3" }, + { "R 0x9104008" }, + { "R 0x9105008" }, + { "R 0x9106008" }, + { "R 0x9107008" }, + { "R 0x9108008" }, + { "R 0x9108808" }, + { "R 0x9109008" }, + { "R 0x9109808" }, + { "R 0x9122008" }, + { "R 0x9122408" }, + { "R 0x9122808" }, + { "R 0x9122c08" }, + { "R 0x9123008" }, + { "R 0x9123408" }, + { "R 0x9123808" }, + { "R 0x9123c08" }, + { "R 0x9124008" }, + { "R 0x9124408" }, + { "R 0x9124808" }, + { "R 0x9124c08" }, + { "R 0x9138008" }, + { "R 0x9138088" }, + { "R 0x9138108" }, + { "R 0x9138188" }, + { "R 0x9138208" }, + { "R 0x9138288" }, + { "R 0x9138308" }, + { "R 0x9138388" }, + { "R 0x9138408" }, + { "R 0x9138488" }, + { "R 0x9138508" }, + { "R 0x9138588" }, + { "R 0x9138608" }, + { "R 0x9138688" }, + { "R 0x9140000 5" }, + { "R 0x9140018" }, + { "R 0x9140020 3" }, + { "R 0x9140030 3" }, + { "R 0x9140040 3" }, + { "R 0x9140400 5" }, + { "R 0x9140418" }, + { "R 0x9140420 3" }, + { "R 0x9140430 3" }, + { "R 0x9140440 3" }, + { "R 0x9140800 5" }, + { "R 0x9140818" }, + { "R 0x9140820 3" }, + { "R 0x9140830 3" }, + { "R 0x9140840 3" }, + { "R 0x9140c00 5" }, + { "R 0x9140c18" }, + { "R 0x9140c20 3" }, + { "R 0x9140c30 3" }, + { "R 0x9140c40 3" }, + { "R 0x9141000 5" }, + { "R 0x9141018" }, + { "R 0x9141020 3" }, + { "R 0x9141030 3" }, + { "R 0x9141040 3" }, + { "R 0x9141400 5" }, + { "R 0x9141418" }, + { "R 0x9141420 3" }, + { "R 0x9141430 3" }, + { "R 0x9141440 3" }, + { "R 0x9141800 3" }, + { "R 0x9141810 3" }, + { "R 0x9141880 3" }, + { "R 0x9141890 3" }, + { "R 0x9142008" }, + { "R 0x9143008" }, + { "R 0x9144008" }, + { "R 0x9145008" }, + { "R 0x9146008" }, + { "R 0x9147008" }, + { "R 0x9148008" }, + { "R 0x9149008" }, + { "R 0x914a008" }, + { "R 0x914b008" }, + { "R 0x914c008" }, + { "R 0x914d008" }, + { "R 0x914e008" }, + { "R 0x914e208" }, + { "R 0x914e408" }, + { "R 0x914e608" }, + { "R 0x914e808" }, + { "R 0x914ea08" }, + { "R 0x914f008" }, + { "R 0x914f808" }, + { "R 0x9150008" }, + { "R 0x9150808" }, + { "R 0x9151008" }, + { "R 0x9151808" }, + { "R 0x9152008" }, + { "R 0x9153008" }, + { "R 0x9154008" }, + { "R 0x9155008" }, + { "R 0x9156008" }, + { "R 0x9157008" }, + { "R 0x9163008" }, + { "R 0x9163010" }, + { "R 0x9165008" }, + { "R 0x9165010" }, + { "R 0x9167008" }, + { "R 0x9167010" }, + { "R 0x9169008" }, + { "R 0x9169010" }, + { "R 0x916b008" }, + { "R 0x916b010" }, + { "R 0x916d008" }, + { "R 0x916d010" }, + { "R 0x9170000 3" }, + { "R 0x9170010" }, + { "R 0x9170018" }, + { "R 0x9170020 6" }, + { "R 0x9170400 3" }, + { "R 0x9170410" }, + { "R 0x9170418" }, + { "R 0x9170420 6" }, + { "R 0x9170800 3" }, + { "R 0x9170810" }, + { "R 0x9170818" }, + { "R 0x9170820 6" }, + { "R 0x9170c00 3" }, + { "R 0x9170c10" }, + { "R 0x9170c18" }, + { "R 0x9170c20 6" }, + { "R 0x9171000 3" }, + { "R 0x9171010" }, + { "R 0x9171018" }, + { "R 0x9171020 6" }, + { "R 0x9171400 3" }, + { "R 0x9171410" }, + { "R 0x9171418" }, + { "R 0x9171420 6" }, + { "R 0x9178008" }, + { "R 0x9178088" }, + { "R 0x9178108" }, + { "R 0x9178188" }, + { "R 0x9178208" }, + { "R 0x9178288" }, + { "R 0x9178308" }, + { "R 0x9178388" }, + { "R 0x9178408" }, + { "R 0x9178488" }, + { "R 0x9178508" }, + { "R 0x9180000 5" }, + { "R 0x9180018" }, + { "R 0x9180020 3" }, + { "R 0x9180030 3" }, + { "R 0x9180040 3" }, + { "R 0x9180400 5" }, + { "R 0x9180418" }, + { "R 0x9180420 3" }, + { "R 0x9180430 3" }, + { "R 0x9180440 3" }, + { "R 0x9180800 3" }, + { "R 0x9180810 3" }, + { "R 0x9180880 3" }, + { "R 0x9180890 3" }, + { "R 0x9180900 3" }, + { "R 0x9180910 3" }, + { "R 0x9180a08" }, + { "R 0x9181008" }, + { "R 0x9181808" }, + { "R 0x9182208" }, + { "R 0x9182408" }, + { "R 0x9182608" }, + { "R 0x9182808" }, + { "R 0x9182a08" }, + { "R 0x9182c08" }, + { "R 0x9182e08" }, + { "R 0x9183008" }, + { "R 0x9183808" }, + { "R 0x9184008" }, + { "R 0x9185008" }, + { "R 0x9186008" }, + { "R 0x9187008" }, + { "R 0x9188008" }, + { "R 0x9189008" }, + { "R 0x918a008" }, + { "R 0x918b008" }, + { "R 0x9190000 3" }, + { "R 0x9190010" }, + { "R 0x9190018" }, + { "R 0x9190020 6" }, + { "R 0x9190400 3" }, + { "R 0x9190410" }, + { "R 0x9190418" }, + { "R 0x9190420 6" }, + { "R 0x9197008" }, + { "R 0x9197088" }, + { "R 0x9198008" }, + { "R 0x9198088" }, + { "R 0x9198108" }, + { "R 0x9198188" }, + { "R 0x9198208" }, + { "R 0x9198288" }, + { "R 0x9198308" }, + { "R 0x9198388" }, + { "R 0x9198408" }, + { "R 0x9198508" }, + { "R 0x9198588" }, + { "R 0x9198608" }, + { "R 0x9198688" }, + { "R 0x9198708" }, + { "R 0x9198788" }, + { "R 0x9198808" }, + { "R 0x9198888" }, + { "R 0x9198908" }, + { "R 0x9198988" }, + { "R 0x9198a08" }, + { "R 0x9198a88" }, + { "R 0x9198b08" }, + { "R 0x9198b88" }, + { "R 0x9198c08" }, + { "R 0x9198e40" }, + { "R 0x9198e48" }, + { "R 0x91a0008" }, + { "R 0x91a1008" }, + { "R 0x91a2008" }, + { "R 0x91a6040" }, + { "R 0x91a6048" }, + { "R 0x91a8100 4" }, + { "R 0x91ab100" }, + { "R 0x91ac040" }, + { "R 0x91ac048" }, + { "R 0x91ad008" }, + { "R 0x91ad010" }, + { "R 0x91ae008" }, + { "R 0x91ae010" }, + { "R 0x91af008" }, + { "R 0x91af010" }, + { "R 0x91b0008" }, + { "R 0x91b0010" }, + { "R 0x91b1008" }, + { "R 0x91b1010" }, + { "R 0x91b2008" }, + { "R 0x91b2010" }, + { "R 0x91b3008" }, + { "R 0x91b3010" }, + { "R 0x91b4008" }, + { "R 0x91b4010" }, + { "R 0x91b5008" }, + { "R 0x91b5010" }, + { "R 0x91b6008" }, + { "R 0x91b6010" }, + { "R 0x91b7008" }, + { "R 0x91b7010" }, + { "R 0x91b8008" }, + { "R 0x91b8010" }, + { "R 0x91b9008" }, + { "R 0x91b9010" }, + { "R 0x91ba008" }, + { "R 0x91ba010" }, + { "R 0x91c0008" }, + { "R 0x91c0208" }, + { "R 0x91c0408" }, + { "R 0x91c0608" }, + { "R 0x91c0808" }, + { "R 0x91c0a08" }, + { "R 0x91c0c08" }, + { "R 0x91c0e08" }, + { "R 0x91c1008" }, + { "R 0x91c1208" }, + { "R 0x91c1408" }, + { "R 0x91c1608" }, + { "R 0x91c1808" }, + { "R 0x91c1a08" }, + { "R 0x91c1c08" }, + { "R 0x91c1e08" }, + { "R 0x91d8008" }, + { "R 0x91d8088" }, + { "R 0x91d8108" }, + { "R 0x91d8188" }, + { "R 0x91d8208" }, + { "R 0x91d8288" }, + { "R 0x91d8308" }, + { "R 0x91d8388" }, + { "R 0x91d8408" }, + { "R 0x91d8488" }, + { "R 0x91d8508" }, + { "R 0x91d8588" }, + { "R 0x91d8608" }, + { "R 0x91d8688" }, + { "R 0x91d8708" }, + { "R 0x91d8788" }, + { "R 0x91e1008" }, + { "R 0x91e1088" }, + { "R 0x91e1108" }, + { "R 0x91e3008" }, + { "R 0x91e3010" }, + { "R 0x91e4008" }, + { "R 0x91e4010" }, + { "R 0x91e5008" }, + { "R 0x91e5010" }, + { "R 0x91e6008" }, + { "R 0x91e6010" }, + { "R 0x91e7008" }, + { "R 0x91e7010" }, + { "R 0x91e8008" }, + { "R 0x91e8010" }, + { "R 0x91e9008" }, + { "R 0x91e9010" }, + { "R 0x91ea008" }, + { "R 0x91ea010" }, + { "R 0x91eb008" }, + { "R 0x91eb010" }, + { "R 0x91ec008" }, + { "R 0x91ec010" }, + { "R 0x91ed008" }, + { "R 0x91ed010" }, + { "R 0x91ee008" }, + { "R 0x91ee010" }, + { "R 0x91ef008" }, + { "R 0x91ef010" }, + { "R 0x91f0008" }, + { "R 0x91f0010" }, + { "R 0x91f1008" }, + { "R 0x91f1010" }, + { "R 0x91f2008" }, + { "R 0x91f2010" }, + { "R 0x91f3008" }, + { "R 0x91f3010" }, + { "R 0x91f4008" }, + { "R 0x91f4010" }, + { "R 0x91f5008" }, + { "R 0x91f5010" }, + { "R 0x91f6008" }, + { "R 0x91f6010" }, + { "R 0x9220344 9" }, + { "R 0x9220370 7" }, + { "R 0x9220480" }, + { "R 0x9222400 26" }, + { "R 0x9222470 5" }, + { "R 0x922320c" }, + { "R 0x9223214 2" }, + { "R 0x9223220 4" }, + { "R 0x9223308" }, + { "R 0x9223318" }, + { "R 0x922358c" }, + { "R 0x9234010" }, + { "R 0x923801c 8" }, + { "R 0x9238050" }, + { "R 0x9238100 7" }, + { "R 0x923c004" }, + { "R 0x923c014" }, + { "R 0x923c020" }, + { "R 0x923c030" }, + { "R 0x923c05c 3" }, + { "R 0x923c074" }, + { "R 0x923c088" }, + { "R 0x923c0a0" }, + { "R 0x923c0b0" }, + { "R 0x923c0c0" }, + { "R 0x923c0d0" }, + { "R 0x923c0e0" }, + { "R 0x923c0f0" }, + { "R 0x923c100" }, + { "R 0x923d064" }, + { "R 0x9240008 6" }, + { "R 0x9240028" }, + { "R 0x924203c 6" }, + { "R 0x9242058 7" }, + { "R 0x924208c" }, + { "R 0x92420b0" }, + { "R 0x92420b8 3" }, + { "R 0x92420f4" }, + { "R 0x92420fc 7" }, + { "R 0x9242324 14" }, + { "R 0x9242410" }, + { "R 0x92430a8" }, + { "R 0x9248004 7" }, + { "R 0x9248024" }, + { "R 0x9248040" }, + { "R 0x9248048" }, + { "R 0x9249064" }, + { "R 0x924c000" }, + { "R 0x924c030 3" }, + { "R 0x924c040 3" }, + { "R 0x924c054 2" }, + { "R 0x924c078" }, + { "R 0x924c108" }, + { "R 0x924c110" }, + { "R 0x9250020" }, + { "R 0x9251054" }, + { "R 0x9252014 3" }, + { "R 0x9252028 17" }, + { "R 0x9252070 8" }, + { "R 0x9252098" }, + { "R 0x92520a0" }, + { "R 0x92520b4" }, + { "R 0x92520c0 4" }, + { "R 0x92520f4 10" }, + { "R 0x9252120 12" }, + { "R 0x925802c" }, + { "R 0x925809c 2" }, + { "R 0x92580a8 3" }, + { "R 0x92580b8" }, + { "R 0x92580c0 7" }, + { "R 0x92580e0" }, + { "R 0x92580e8" }, + { "R 0x92580f0" }, + { "R 0x92580f8" }, + { "R 0x9258100" }, + { "R 0x9258108" }, + { "R 0x9258110" }, + { "R 0x9258118" }, + { "R 0x9258120" }, + { "R 0x9258128" }, + { "R 0x9258210 3" }, + { "R 0x9259010" }, + { "R 0x9259070" }, + { "R 0x925b004" }, + { "R 0x926004c 10" }, + { "R 0x9260078" }, + { "R 0x926020c" }, + { "R 0x9260214" }, + { "R 0x9261084" }, + { "R 0x9262020" }, + { "R 0x9263020" }, + { "R 0x9264020" }, + { "R 0x9265020" }, + { "R 0x9320344 9" }, + { "R 0x9320370 7" }, + { "R 0x9320480" }, + { "R 0x9322400 26" }, + { "R 0x9322470 5" }, + { "R 0x932320c" }, + { "R 0x9323214 2" }, + { "R 0x9323220 4" }, + { "R 0x9323308" }, + { "R 0x9323318" }, + { "R 0x932358c" }, + { "R 0x9334010" }, + { "R 0x933801c 8" }, + { "R 0x9338050" }, + { "R 0x9338100 7" }, + { "R 0x933c004" }, + { "R 0x933c014" }, + { "R 0x933c020" }, + { "R 0x933c030" }, + { "R 0x933c05c 3" }, + { "R 0x933c074" }, + { "R 0x933c088" }, + { "R 0x933c0a0" }, + { "R 0x933c0b0" }, + { "R 0x933c0c0" }, + { "R 0x933c0d0" }, + { "R 0x933c0e0" }, + { "R 0x933c0f0" }, + { "R 0x933c100" }, + { "R 0x933d064" }, + { "R 0x9340008 6" }, + { "R 0x9340028" }, + { "R 0x934203c 6" }, + { "R 0x9342058 7" }, + { "R 0x934208c" }, + { "R 0x93420b0" }, + { "R 0x93420b8 3" }, + { "R 0x93420f4" }, + { "R 0x93420fc 7" }, + { "R 0x9342324 14" }, + { "R 0x9342410" }, + { "R 0x93430a8" }, + { "R 0x9348004 7" }, + { "R 0x9348024" }, + { "R 0x9348040" }, + { "R 0x9348048" }, + { "R 0x9349064" }, + { "R 0x934c000" }, + { "R 0x934c030 3" }, + { "R 0x934c040 3" }, + { "R 0x934c054 2" }, + { "R 0x934c078" }, + { "R 0x934c108" }, + { "R 0x934c110" }, + { "R 0x9350020" }, + { "R 0x9351054" }, + { "R 0x9352014 3" }, + { "R 0x9352028 17" }, + { "R 0x9352070 8" }, + { "R 0x9352098" }, + { "R 0x93520a0" }, + { "R 0x93520b4" }, + { "R 0x93520c0 4" }, + { "R 0x93520f4 10" }, + { "R 0x9352120 12" }, + { "R 0x935802c" }, + { "R 0x935809c 2" }, + { "R 0x93580a8 3" }, + { "R 0x93580b8" }, + { "R 0x93580c0 7" }, + { "R 0x93580e0" }, + { "R 0x93580e8" }, + { "R 0x93580f0" }, + { "R 0x93580f8" }, + { "R 0x9358100" }, + { "R 0x9358108" }, + { "R 0x9358110" }, + { "R 0x9358118" }, + { "R 0x9358120" }, + { "R 0x9358128" }, + { "R 0x9358210 3" }, + { "R 0x9359010" }, + { "R 0x9359070" }, + { "R 0x935b004" }, + { "R 0x936004c 10" }, + { "R 0x9360078" }, + { "R 0x936020c" }, + { "R 0x9360214" }, + { "R 0x9361084" }, + { "R 0x9362020" }, + { "R 0x9363020" }, + { "R 0x9364020" }, + { "R 0x9365020" }, + { "R 0x9420344 9" }, + { "R 0x9420370 7" }, + { "R 0x9420480" }, + { "R 0x9422400 26" }, + { "R 0x9422470 5" }, + { "R 0x942320c" }, + { "R 0x9423214 2" }, + { "R 0x9423220 4" }, + { "R 0x9423308" }, + { "R 0x9423318" }, + { "R 0x942358c" }, + { "R 0x9434010" }, + { "R 0x943801c 8" }, + { "R 0x9438050" }, + { "R 0x9438100 7" }, + { "R 0x943c004" }, + { "R 0x943c014" }, + { "R 0x943c020" }, + { "R 0x943c030" }, + { "R 0x943c05c 3" }, + { "R 0x943c074" }, + { "R 0x943c088" }, + { "R 0x943c0a0" }, + { "R 0x943c0b0" }, + { "R 0x943c0c0" }, + { "R 0x943c0d0" }, + { "R 0x943c0e0" }, + { "R 0x943c0f0" }, + { "R 0x943c100" }, + { "R 0x943d064" }, + { "R 0x9440008 6" }, + { "R 0x9440028" }, + { "R 0x944203c 6" }, + { "R 0x9442058 7" }, + { "R 0x944208c" }, + { "R 0x94420b0" }, + { "R 0x94420b8 3" }, + { "R 0x94420f4" }, + { "R 0x94420fc 7" }, + { "R 0x9442324 14" }, + { "R 0x9442410" }, + { "R 0x94430a8" }, + { "R 0x9448004 7" }, + { "R 0x9448024" }, + { "R 0x9448040" }, + { "R 0x9448048" }, + { "R 0x9449064" }, + { "R 0x944c000" }, + { "R 0x944c030 3" }, + { "R 0x944c040 3" }, + { "R 0x944c054 2" }, + { "R 0x944c078" }, + { "R 0x944c108" }, + { "R 0x944c110" }, + { "R 0x9450020" }, + { "R 0x9451054" }, + { "R 0x9452014 3" }, + { "R 0x9452028 17" }, + { "R 0x9452070 8" }, + { "R 0x9452098" }, + { "R 0x94520a0" }, + { "R 0x94520b4" }, + { "R 0x94520c0 4" }, + { "R 0x94520f4 10" }, + { "R 0x9452120 12" }, + { "R 0x945802c" }, + { "R 0x945809c 2" }, + { "R 0x94580a8 3" }, + { "R 0x94580b8" }, + { "R 0x94580c0 7" }, + { "R 0x94580e0" }, + { "R 0x94580e8" }, + { "R 0x94580f0" }, + { "R 0x94580f8" }, + { "R 0x9458100" }, + { "R 0x9458108" }, + { "R 0x9458110" }, + { "R 0x9458118" }, + { "R 0x9458120" }, + { "R 0x9458128" }, + { "R 0x9458210 3" }, + { "R 0x9459010" }, + { "R 0x9459070" }, + { "R 0x945b004" }, + { "R 0x946004c 10" }, + { "R 0x9460078" }, + { "R 0x946020c" }, + { "R 0x9460214" }, + { "R 0x9461084" }, + { "R 0x9462020" }, + { "R 0x9463020" }, + { "R 0x9464020" }, + { "R 0x9465020" }, + { "R 0x9520344 9" }, + { "R 0x9520370 7" }, + { "R 0x9520480" }, + { "R 0x9522400 26" }, + { "R 0x9522470 5" }, + { "R 0x952320c" }, + { "R 0x9523214 2" }, + { "R 0x9523220 4" }, + { "R 0x9523308" }, + { "R 0x9523318" }, + { "R 0x952358c" }, + { "R 0x9534010" }, + { "R 0x953801c 8" }, + { "R 0x9538050" }, + { "R 0x9538100 7" }, + { "R 0x953c004" }, + { "R 0x953c014" }, + { "R 0x953c020" }, + { "R 0x953c030" }, + { "R 0x953c05c 3" }, + { "R 0x953c074" }, + { "R 0x953c088" }, + { "R 0x953c0a0" }, + { "R 0x953c0b0" }, + { "R 0x953c0c0" }, + { "R 0x953c0d0" }, + { "R 0x953c0e0" }, + { "R 0x953c0f0" }, + { "R 0x953c100" }, + { "R 0x953d064" }, + { "R 0x9540008 6" }, + { "R 0x9540028" }, + { "R 0x954203c 6" }, + { "R 0x9542058 7" }, + { "R 0x954208c" }, + { "R 0x95420b0" }, + { "R 0x95420b8 3" }, + { "R 0x95420f4" }, + { "R 0x95420fc 7" }, + { "R 0x9542324 14" }, + { "R 0x9542410" }, + { "R 0x95430a8" }, + { "R 0x9548004 7" }, + { "R 0x9548024" }, + { "R 0x9548040" }, + { "R 0x9548048" }, + { "R 0x9549064" }, + { "R 0x954c000" }, + { "R 0x954c030 3" }, + { "R 0x954c040 3" }, + { "R 0x954c054 2" }, + { "R 0x954c078" }, + { "R 0x954c108" }, + { "R 0x954c110" }, + { "R 0x9550020" }, + { "R 0x9551054" }, + { "R 0x9552014 3" }, + { "R 0x9552028 17" }, + { "R 0x9552070 8" }, + { "R 0x9552098" }, + { "R 0x95520a0" }, + { "R 0x95520b4" }, + { "R 0x95520c0 4" }, + { "R 0x95520f4 10" }, + { "R 0x9552120 12" }, + { "R 0x955802c" }, + { "R 0x955809c 2" }, + { "R 0x95580a8 3" }, + { "R 0x95580b8" }, + { "R 0x95580c0 7" }, + { "R 0x95580e0" }, + { "R 0x95580e8" }, + { "R 0x95580f0" }, + { "R 0x95580f8" }, + { "R 0x9558100" }, + { "R 0x9558108" }, + { "R 0x9558110" }, + { "R 0x9558118" }, + { "R 0x9558120" }, + { "R 0x9558128" }, + { "R 0x9558210 3" }, + { "R 0x9559010" }, + { "R 0x9559070" }, + { "R 0x955b004" }, + { "R 0x956004c 10" }, + { "R 0x9560078" }, + { "R 0x956020c" }, + { "R 0x9560214" }, + { "R 0x9561084" }, + { "R 0x9562020" }, + { "R 0x9563020" }, + { "R 0x9564020" }, + { "R 0x9565020" }, + { "R 0x9620344 9" }, + { "R 0x9620370 7" }, + { "R 0x9620480" }, + { "R 0x9622400 26" }, + { "R 0x9622470 5" }, + { "R 0x962320c" }, + { "R 0x9623214 2" }, + { "R 0x9623220 4" }, + { "R 0x9623308" }, + { "R 0x9623318" }, + { "R 0x962358c" }, + { "R 0x9634010" }, + { "R 0x963801c 8" }, + { "R 0x9638050" }, + { "R 0x9638100 7" }, + { "R 0x963c004" }, + { "R 0x963c014" }, + { "R 0x963c020" }, + { "R 0x963c030" }, + { "R 0x963c05c 3" }, + { "R 0x963c074" }, + { "R 0x963c088" }, + { "R 0x963c0a0" }, + { "R 0x963c0b0" }, + { "R 0x963c0c0" }, + { "R 0x963c0d0" }, + { "R 0x963c0e0" }, + { "R 0x963c0f0" }, + { "R 0x963c100" }, + { "R 0x963d064" }, + { "R 0x9640008 6" }, + { "R 0x9640028" }, + { "R 0x964203c 6" }, + { "R 0x9642058 7" }, + { "R 0x964208c" }, + { "R 0x96420b0" }, + { "R 0x96420b8 3" }, + { "R 0x96420f4" }, + { "R 0x96420fc 7" }, + { "R 0x9642324 14" }, + { "R 0x9642410" }, + { "R 0x96430a8" }, + { "R 0x9648004 7" }, + { "R 0x9648024" }, + { "R 0x9648040" }, + { "R 0x9648048" }, + { "R 0x9649064" }, + { "R 0x964c000" }, + { "R 0x964c030 3" }, + { "R 0x964c040 3" }, + { "R 0x964c054 2" }, + { "R 0x964c078" }, + { "R 0x964c108" }, + { "R 0x964c110" }, + { "R 0x9650020" }, + { "R 0x9651054" }, + { "R 0x9652014 3" }, + { "R 0x9652028 17" }, + { "R 0x9652070 8" }, + { "R 0x9652098" }, + { "R 0x96520a0" }, + { "R 0x96520b4" }, + { "R 0x96520c0 4" }, + { "R 0x96520f4 10" }, + { "R 0x9652120 12" }, + { "R 0x965802c" }, + { "R 0x965809c 2" }, + { "R 0x96580a8 3" }, + { "R 0x96580b8" }, + { "R 0x96580c0 7" }, + { "R 0x96580e0" }, + { "R 0x96580e8" }, + { "R 0x96580f0" }, + { "R 0x96580f8" }, + { "R 0x9658100" }, + { "R 0x9658108" }, + { "R 0x9658110" }, + { "R 0x9658118" }, + { "R 0x9658120" }, + { "R 0x9658128" }, + { "R 0x9658210 3" }, + { "R 0x9659010" }, + { "R 0x9659070" }, + { "R 0x965b004" }, + { "R 0x966004c 10" }, + { "R 0x9660078" }, + { "R 0x966020c" }, + { "R 0x9660214" }, + { "R 0x9661084" }, + { "R 0x9662020" }, + { "R 0x9663020" }, + { "R 0x9664020" }, + { "R 0x9665020" }, + { "R 0x9720344 9" }, + { "R 0x9720370 7" }, + { "R 0x9720480" }, + { "R 0x9722400 26" }, + { "R 0x9722470 5" }, + { "R 0x972320c" }, + { "R 0x9723214 2" }, + { "R 0x9723220 4" }, + { "R 0x9723308" }, + { "R 0x9723318" }, + { "R 0x972358c" }, + { "R 0x9734010" }, + { "R 0x973801c 8" }, + { "R 0x9738050" }, + { "R 0x9738100 7" }, + { "R 0x973c004" }, + { "R 0x973c014" }, + { "R 0x973c020" }, + { "R 0x973c030" }, + { "R 0x973c05c 3" }, + { "R 0x973c074" }, + { "R 0x973c088" }, + { "R 0x973c0a0" }, + { "R 0x973c0b0" }, + { "R 0x973c0c0" }, + { "R 0x973c0d0" }, + { "R 0x973c0e0" }, + { "R 0x973c0f0" }, + { "R 0x973c100" }, + { "R 0x973d064" }, + { "R 0x9740008 6" }, + { "R 0x9740028" }, + { "R 0x974203c 6" }, + { "R 0x9742058 7" }, + { "R 0x974208c" }, + { "R 0x97420b0" }, + { "R 0x97420b8 3" }, + { "R 0x97420f4" }, + { "R 0x97420fc 7" }, + { "R 0x9742324 14" }, + { "R 0x9742410" }, + { "R 0x97430a8" }, + { "R 0x9748004 7" }, + { "R 0x9748024" }, + { "R 0x9748040" }, + { "R 0x9748048" }, + { "R 0x9749064" }, + { "R 0x974c000" }, + { "R 0x974c030 3" }, + { "R 0x974c040 3" }, + { "R 0x974c054 2" }, + { "R 0x974c078" }, + { "R 0x974c108" }, + { "R 0x974c110" }, + { "R 0x9750020" }, + { "R 0x9751054" }, + { "R 0x9752014 3" }, + { "R 0x9752028 17" }, + { "R 0x9752070 8" }, + { "R 0x9752098" }, + { "R 0x97520a0" }, + { "R 0x97520b4" }, + { "R 0x97520c0 4" }, + { "R 0x97520f4 10" }, + { "R 0x9752120 12" }, + { "R 0x975802c" }, + { "R 0x975809c 2" }, + { "R 0x97580a8 3" }, + { "R 0x97580b8" }, + { "R 0x97580c0 7" }, + { "R 0x97580e0" }, + { "R 0x97580e8" }, + { "R 0x97580f0" }, + { "R 0x97580f8" }, + { "R 0x9758100" }, + { "R 0x9758108" }, + { "R 0x9758110" }, + { "R 0x9758118" }, + { "R 0x9758120" }, + { "R 0x9758128" }, + { "R 0x9758210 3" }, + { "R 0x9759010" }, + { "R 0x9759070" }, + { "R 0x975b004" }, + { "R 0x976004c 10" }, + { "R 0x9760078" }, + { "R 0x976020c" }, + { "R 0x9760214" }, + { "R 0x9761084" }, + { "R 0x9762020" }, + { "R 0x9763020" }, + { "R 0x9764020" }, + { "R 0x9765020" }, + { "R 0x92a0304" }, + { "R 0x92a0080" }, + { "R 0x92a0310" }, + { "R 0x92a0400 2" }, + { "R 0x92a0410 6" }, + { "R 0x92a0430" }, + { "R 0x92a0440" }, + { "R 0x92a0448" }, + { "R 0x92a04a0" }, + { "R 0x92a04b0 4" }, + { "R 0x92a04d0 2" }, + { "R 0x92a1400" }, + { "R 0x92a1408" }, + { "R 0x92a2400 2" }, + { "R 0x92a2438 2" }, + { "R 0x92a2454" }, + { "R 0x92a3400 4" }, + { "R 0x92a3418 3" }, + { "R 0x92a4700" }, + { "R 0x92a53b0" }, + { "R 0x92a5804" }, + { "R 0x92a590c" }, + { "R 0x92a5a14" }, + { "R 0x92a5c0c" }, + { "R 0x92a5c18 2" }, + { "R 0x92a5c2c 2" }, + { "R 0x92a5c38" }, + { "R 0x92a5c4c" }, + { "R 0x92a5ca4" }, + { "R 0x92a5cac 3" }, + { "R 0x92a6400" }, + { "R 0x92a6418 2" }, + { "R 0x92a9100" }, + { "R 0x92a9110" }, + { "R 0x92a9120" }, + { "R 0x92a9180 2" }, + { "R 0x92a91a0" }, + { "R 0x92a91b0" }, + { "R 0x92a91c0 2" }, + { "R 0x92a91e0" }, + { "R 0x93a0304" }, + { "R 0x93a0080" }, + { "R 0x93a0310" }, + { "R 0x93a0400 2" }, + { "R 0x93a0410 6" }, + { "R 0x93a0430" }, + { "R 0x93a0440" }, + { "R 0x93a0448" }, + { "R 0x93a04a0" }, + { "R 0x93a04b0 4" }, + { "R 0x93a04d0 2" }, + { "R 0x93a1400" }, + { "R 0x93a1408" }, + { "R 0x93a2400 2" }, + { "R 0x93a2438 2" }, + { "R 0x93a2454" }, + { "R 0x93a3400 4" }, + { "R 0x93a3418 3" }, + { "R 0x93a4700" }, + { "R 0x93a53b0" }, + { "R 0x93a5804" }, + { "R 0x93a590c" }, + { "R 0x93a5a14" }, + { "R 0x93a5c0c" }, + { "R 0x93a5c18 2" }, + { "R 0x93a5c2c 2" }, + { "R 0x93a5c38" }, + { "R 0x93a5c4c" }, + { "R 0x93a5ca4" }, + { "R 0x93a5cac 3" }, + { "R 0x93a6400" }, + { "R 0x93a6418 2" }, + { "R 0x93a9100" }, + { "R 0x93a9110" }, + { "R 0x93a9120" }, + { "R 0x93a9180 2" }, + { "R 0x93a91a0" }, + { "R 0x93a91b0" }, + { "R 0x93a91c0 2" }, + { "R 0x93a91e0" }, + { "R 0x94a0304" }, + { "R 0x94a0080" }, + { "R 0x94a0310" }, + { "R 0x94a0400 2" }, + { "R 0x94a0410 6" }, + { "R 0x94a0430" }, + { "R 0x94a0440" }, + { "R 0x94a0448" }, + { "R 0x94a04a0" }, + { "R 0x94a04b0 4" }, + { "R 0x94a04d0 2" }, + { "R 0x94a1400" }, + { "R 0x94a1408" }, + { "R 0x94a2400 2" }, + { "R 0x94a2438 2" }, + { "R 0x94a2454" }, + { "R 0x94a3400 4" }, + { "R 0x94a3418 3" }, + { "R 0x94a4700" }, + { "R 0x94a53b0" }, + { "R 0x94a5804" }, + { "R 0x94a590c" }, + { "R 0x94a5a14" }, + { "R 0x94a5c0c" }, + { "R 0x94a5c18 2" }, + { "R 0x94a5c2c 2" }, + { "R 0x94a5c38" }, + { "R 0x94a5c4c" }, + { "R 0x94a5ca4" }, + { "R 0x94a5cac 3" }, + { "R 0x94a6400" }, + { "R 0x94a6418 2" }, + { "R 0x94a9100" }, + { "R 0x94a9110" }, + { "R 0x94a9120" }, + { "R 0x94a9180 2" }, + { "R 0x94a91a0" }, + { "R 0x94a91b0" }, + { "R 0x94a91c0 2" }, + { "R 0x94a91e0" }, + { "R 0x95a0304" }, + { "R 0x95a0080" }, + { "R 0x95a0310" }, + { "R 0x95a0400 2" }, + { "R 0x95a0410 6" }, + { "R 0x95a0430" }, + { "R 0x95a0440" }, + { "R 0x95a0448" }, + { "R 0x95a04a0" }, + { "R 0x95a04b0 4" }, + { "R 0x95a04d0 2" }, + { "R 0x95a1400" }, + { "R 0x95a1408" }, + { "R 0x95a2400 2" }, + { "R 0x95a2438 2" }, + { "R 0x95a2454" }, + { "R 0x95a3400 4" }, + { "R 0x95a3418 3" }, + { "R 0x95a4700" }, + { "R 0x95a53b0" }, + { "R 0x95a5804" }, + { "R 0x95a590c" }, + { "R 0x95a5a14" }, + { "R 0x95a5c0c" }, + { "R 0x95a5c18 2" }, + { "R 0x95a5c2c 2" }, + { "R 0x95a5c38" }, + { "R 0x95a5c4c" }, + { "R 0x95a5ca4" }, + { "R 0x95a5cac 3" }, + { "R 0x95a6400" }, + { "R 0x95a6418 2" }, + { "R 0x95a9100" }, + { "R 0x95a9110" }, + { "R 0x95a9120" }, + { "R 0x95a9180 2" }, + { "R 0x95a91a0" }, + { "R 0x95a91b0" }, + { "R 0x95a91c0 2" }, + { "R 0x95a91e0" }, + { "R 0x96a0304" }, + { "R 0x96a0080" }, + { "R 0x96a0310" }, + { "R 0x96a0400 2" }, + { "R 0x96a0410 6" }, + { "R 0x96a0430" }, + { "R 0x96a0440" }, + { "R 0x96a0448" }, + { "R 0x96a04a0" }, + { "R 0x96a04b0 4" }, + { "R 0x96a04d0 2" }, + { "R 0x96a1400" }, + { "R 0x96a1408" }, + { "R 0x96a2400 2" }, + { "R 0x96a2438 2" }, + { "R 0x96a2454" }, + { "R 0x96a3400 4" }, + { "R 0x96a3418 3" }, + { "R 0x96a4700" }, + { "R 0x96a53b0" }, + { "R 0x96a5804" }, + { "R 0x96a590c" }, + { "R 0x96a5a14" }, + { "R 0x96a5c0c" }, + { "R 0x96a5c18 2" }, + { "R 0x96a5c2c 2" }, + { "R 0x96a5c38" }, + { "R 0x96a5c4c" }, + { "R 0x96a5ca4" }, + { "R 0x96a5cac 3" }, + { "R 0x96a6400" }, + { "R 0x96a6418 2" }, + { "R 0x96a9100" }, + { "R 0x96a9110" }, + { "R 0x96a9120" }, + { "R 0x96a9180 2" }, + { "R 0x96a91a0" }, + { "R 0x96a91b0" }, + { "R 0x96a91c0 2" }, + { "R 0x96a91e0" }, + { "R 0x97a0304" }, + { "R 0x97a0080" }, + { "R 0x97a0310" }, + { "R 0x97a0400 2" }, + { "R 0x97a0410 6" }, + { "R 0x97a0430" }, + { "R 0x97a0440" }, + { "R 0x97a0448" }, + { "R 0x97a04a0" }, + { "R 0x97a04b0 4" }, + { "R 0x97a04d0 2" }, + { "R 0x97a1400" }, + { "R 0x97a1408" }, + { "R 0x97a2400 2" }, + { "R 0x97a2438 2" }, + { "R 0x97a2454" }, + { "R 0x97a3400 4" }, + { "R 0x97a3418 3" }, + { "R 0x97a4700" }, + { "R 0x97a53b0" }, + { "R 0x97a5804" }, + { "R 0x97a590c" }, + { "R 0x97a5a14" }, + { "R 0x97a5c0c" }, + { "R 0x97a5c18 2" }, + { "R 0x97a5c2c 2" }, + { "R 0x97a5c38" }, + { "R 0x97a5c4c" }, + { "R 0x97a5ca4" }, + { "R 0x97a5cac 3" }, + { "R 0x97a6400" }, + { "R 0x97a6418 2" }, + { "R 0x97a9100" }, + { "R 0x97a9110" }, + { "R 0x97a9120" }, + { "R 0x97a9180 2" }, + { "R 0x97a91a0" }, + { "R 0x97a91b0" }, + { "R 0x97a91c0 2" }, + { "R 0x97a91e0" }, + { "R 0x9b01e64" }, + { "R 0x9b01ea0" }, + { "R 0x9b01f30 2" }, + { "R 0x9b03e64" }, + { "R 0x9b03ea0" }, + { "R 0x9b03f30 2" }, + { "R 0x9b0527c" }, + { "R 0x9b05290" }, + { "R 0x9b054ec" }, + { "R 0x9b054f4" }, + { "R 0x9b05514" }, + { "R 0x9b0551c" }, + { "R 0x9b05524" }, + { "R 0x9b05548" }, + { "R 0x9b05550" }, + { "R 0x9b05558" }, + { "R 0x9b055b8" }, + { "R 0x9b055c0" }, + { "R 0x9b055ec" }, + { "R 0x9b05860" }, + { "R 0x9b05870" }, + { "R 0x9b058a0" }, + { "R 0x9b058a8" }, + { "R 0x9b058b0" }, + { "R 0x9b058b8" }, + { "R 0x9b058d8 2" }, + { "R 0x9b058f4" }, + { "R 0x9b058fc" }, + { "R 0x9b05920" }, + { "R 0x9b05928" }, + { "R 0x9b05944" }, + { "R 0x9b06604" }, + { "R 0x9b0660c" }, + { "R 0x9b41e64" }, + { "R 0x9b41ea0" }, + { "R 0x9b41f30 2" }, + { "R 0x9b43e64" }, + { "R 0x9b43ea0" }, + { "R 0x9b43f30 2" }, + { "R 0x9b4527c" }, + { "R 0x9b45290" }, + { "R 0x9b454ec" }, + { "R 0x9b454f4" }, + { "R 0x9b45514" }, + { "R 0x9b4551c" }, + { "R 0x9b45524" }, + { "R 0x9b45548" }, + { "R 0x9b45550" }, + { "R 0x9b45558" }, + { "R 0x9b455b8" }, + { "R 0x9b455c0" }, + { "R 0x9b455ec" }, + { "R 0x9b45860" }, + { "R 0x9b45870" }, + { "R 0x9b458a0" }, + { "R 0x9b458a8" }, + { "R 0x9b458b0" }, + { "R 0x9b458b8" }, + { "R 0x9b458d8 2" }, + { "R 0x9b458f4" }, + { "R 0x9b458fc" }, + { "R 0x9b45920" }, + { "R 0x9b45928" }, + { "R 0x9b45944" }, + { "R 0x9b46604" }, + { "R 0x9b4660c" }, + { "R 0x9b81e64" }, + { "R 0x9b81ea0" }, + { "R 0x9b81f30 2" }, + { "R 0x9b83e64" }, + { "R 0x9b83ea0" }, + { "R 0x9b83f30 2" }, + { "R 0x9b8527c" }, + { "R 0x9b85290" }, + { "R 0x9b854ec" }, + { "R 0x9b854f4" }, + { "R 0x9b85514" }, + { "R 0x9b8551c" }, + { "R 0x9b85524" }, + { "R 0x9b85548" }, + { "R 0x9b85550" }, + { "R 0x9b85558" }, + { "R 0x9b855b8" }, + { "R 0x9b855c0" }, + { "R 0x9b855ec" }, + { "R 0x9b85860" }, + { "R 0x9b85870" }, + { "R 0x9b858a0" }, + { "R 0x9b858a8" }, + { "R 0x9b858b0" }, + { "R 0x9b858b8" }, + { "R 0x9b858d8 2" }, + { "R 0x9b858f4" }, + { "R 0x9b858fc" }, + { "R 0x9b85920" }, + { "R 0x9b85928" }, + { "R 0x9b85944" }, + { "R 0x9b86604" }, + { "R 0x9b8660c" }, + { "R 0x9bc1e64" }, + { "R 0x9bc1ea0" }, + { "R 0x9bc1f30 2" }, + { "R 0x9bc3e64" }, + { "R 0x9bc3ea0" }, + { "R 0x9bc3f30 2" }, + { "R 0x9bc527c" }, + { "R 0x9bc5290" }, + { "R 0x9bc54ec" }, + { "R 0x9bc54f4" }, + { "R 0x9bc5514" }, + { "R 0x9bc551c" }, + { "R 0x9bc5524" }, + { "R 0x9bc5548" }, + { "R 0x9bc5550" }, + { "R 0x9bc5558" }, + { "R 0x9bc55b8" }, + { "R 0x9bc55c0" }, + { "R 0x9bc55ec" }, + { "R 0x9bc5860" }, + { "R 0x9bc5870" }, + { "R 0x9bc58a0" }, + { "R 0x9bc58a8" }, + { "R 0x9bc58b0" }, + { "R 0x9bc58b8" }, + { "R 0x9bc58d8 2" }, + { "R 0x9bc58f4" }, + { "R 0x9bc58fc" }, + { "R 0x9bc5920" }, + { "R 0x9bc5928" }, + { "R 0x9bc5944" }, + { "R 0x9bc6604" }, + { "R 0x9bc660c" }, + { "R 0x9c01e64" }, + { "R 0x9c01ea0" }, + { "R 0x9c01f30 2" }, + { "R 0x9c03e64" }, + { "R 0x9c03ea0" }, + { "R 0x9c03f30 2" }, + { "R 0x9c0527c" }, + { "R 0x9c05290" }, + { "R 0x9c054ec" }, + { "R 0x9c054f4" }, + { "R 0x9c05514" }, + { "R 0x9c0551c" }, + { "R 0x9c05524" }, + { "R 0x9c05548" }, + { "R 0x9c05550" }, + { "R 0x9c05558" }, + { "R 0x9c055b8" }, + { "R 0x9c055c0" }, + { "R 0x9c055ec" }, + { "R 0x9c05860" }, + { "R 0x9c05870" }, + { "R 0x9c058a0" }, + { "R 0x9c058a8" }, + { "R 0x9c058b0" }, + { "R 0x9c058b8" }, + { "R 0x9c058d8 2" }, + { "R 0x9c058f4" }, + { "R 0x9c058fc" }, + { "R 0x9c05920" }, + { "R 0x9c05928" }, + { "R 0x9c05944" }, + { "R 0x9c06604" }, + { "R 0x9c0660c" }, + { "R 0x9c41e64" }, + { "R 0x9c41ea0" }, + { "R 0x9c41f30 2" }, + { "R 0x9c43e64" }, + { "R 0x9c43ea0" }, + { "R 0x9c43f30 2" }, + { "R 0x9c4527c" }, + { "R 0x9c45290" }, + { "R 0x9c454ec" }, + { "R 0x9c454f4" }, + { "R 0x9c45514" }, + { "R 0x9c4551c" }, + { "R 0x9c45524" }, + { "R 0x9c45548" }, + { "R 0x9c45550" }, + { "R 0x9c45558" }, + { "R 0x9c455b8" }, + { "R 0x9c455c0" }, + { "R 0x9c455ec" }, + { "R 0x9c45860" }, + { "R 0x9c45870" }, + { "R 0x9c458a0" }, + { "R 0x9c458a8" }, + { "R 0x9c458b0" }, + { "R 0x9c458b8" }, + { "R 0x9c458d8 2" }, + { "R 0x9c458f4" }, + { "R 0x9c458fc" }, + { "R 0x9c45920" }, + { "R 0x9c45928" }, + { "R 0x9c45944" }, + { "R 0x9c46604" }, + { "R 0x9c4660c" }, +}; + +static const struct dcc_link_config lemans_link_configs[] = { + { + .link_list = 6, + .entries = lemans_dcc_entries, + .num_entries = ARRAY_SIZE(lemans_dcc_entries), + }, +}; + +static const struct dcc_config lemans_config = { + .lists = lemans_link_configs, + .num_lists = ARRAY_SIZE(lemans_link_configs), +}; + +static const struct dcc_pdata lemans_pdata = { + .base = 0x040ff000, + .size = 0x00001000, + .ram_base = 0x040b8800, + .ram_size = 0x00006000, + .dcc_offset = 0x38800, + .map_ver = 0x3, + .config = &lemans_config, +}; + +#endif /* _QCOM_DCC_LEMANS_CONFIG_H */ From 3ea9bdbedbfe2f2740389f18d056490e8db5faa0 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 29 Apr 2026 11:34:33 +0800 Subject: [PATCH 0056/1133] QCLINUX: qcom-dcc: move talos config to qcom-dcc-talos-config.h Move the talos DCC configuration (entries array, link config, dcc config, and pdata) into a dedicated header qcom-dcc-talos-config.h, consistent with the approach used for the lemans config. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 782 +------------------------- drivers/misc/qcom-dcc-talos-config.h | 792 +++++++++++++++++++++++++++ 2 files changed, 793 insertions(+), 781 deletions(-) create mode 100644 drivers/misc/qcom-dcc-talos-config.h diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index d3dcda2d3e5fc..83efad89b4d76 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -7,793 +7,13 @@ #include #include #include "qcom-dcc.h" +#include "qcom-dcc-talos-config.h" #include "qcom-dcc-lemans-config.h" #define DEV_NAME "qcom-dcc" static struct platform_device *dcc_pdev; -static const struct dcc_register_entry talos_dcc_entries[] = { - { "R 0x9680000" }, - { "R 0x9680004" }, - { "R 0x9681000" }, - { "R 0x9681004" }, - { "R 0x9681008" }, - { "R 0x968100c" }, - { "R 0x9681010" }, - { "R 0x9681014" }, - { "R 0x968101c" }, - { "R 0x9681020" }, - { "R 0x9681024" }, - { "R 0x9681028" }, - { "R 0x968102c" }, - { "R 0x9681030" }, - { "R 0x9681034" }, - { "R 0x968103c" }, - { "R 0x9698100" }, - { "R 0x9698104" }, - { "R 0x9698108" }, - { "R 0x9698110" }, - { "R 0x9698120" }, - { "R 0x9698124" }, - { "R 0x9698128" }, - { "R 0x969812c" }, - { "R 0x9698130" }, - { "R 0x9698134" }, - { "R 0x9698138" }, - { "R 0x969813c" }, - { "R 0x9698500" }, - { "R 0x9698504" }, - { "R 0x9698508" }, - { "R 0x969850c" }, - { "R 0x9698510" }, - { "R 0x9698514" }, - { "R 0x9698518" }, - { "R 0x969851c" }, - { "R 0x9698700" }, - { "R 0x9698704" }, - { "R 0x9698708" }, - { "R 0x969870c" }, - { "R 0x9698714" }, - { "R 0x9698718" }, - { "R 0x969871c" }, - { "R 0x1620204" }, - { "R 0x1620240" }, - { "R 0x1620248" }, - { "R 0x1620288" }, - { "R 0x162028C" }, - { "R 0x1620290" }, - { "R 0x1620294" }, - { "R 0x16202A8" }, - { "R 0x16202AC" }, - { "R 0x16202B0" }, - { "R 0x16202B4" }, - { "R 0x1620300" }, - { "R 0x1700204" }, - { "R 0x1700240" }, - { "R 0x1700248" }, - { "R 0x1700288" }, - { "R 0x1700290" }, - { "R 0x1700300" }, - { "R 0x1700304" }, - { "R 0x1700308" }, - { "R 0x170030C" }, - { "R 0x1700310" }, - { "R 0x1700314" }, - { "R 0x1700C08" }, - { "R 0x1700C10" }, - { "R 0x1700C20" }, - { "R 0x1700C24" }, - { "R 0x1700C28" }, - { "R 0x1700C2C" }, - { "R 0x1700C30" }, - { "R 0x1700C34" }, - { "R 0x1700C38" }, - { "R 0x1700C3C" }, - { "R 0x1740240" }, - { "R 0x1740248" }, - { "R 0x1740288" }, - { "R 0x1740290" }, - { "R 0x1740300" }, - { "R 0x1740304" }, - { "R 0x1740308" }, - { "R 0x174030C" }, - { "R 0x1740310" }, - { "R 0x1740314" }, - { "R 0x1740004" }, - { "R 0x1740008" }, - { "R 0x1740010" }, - { "R 0x1740020" }, - { "R 0x1740024" }, - { "R 0x1740028" }, - { "R 0x174002C" }, - { "R 0x1740030" }, - { "R 0x1740034" }, - { "R 0x1740038" }, - { "R 0x174003C" }, - { "R 0x9698204" }, - { "R 0x9698240" }, - { "R 0x9698244" }, - { "R 0x9698248" }, - { "R 0x969824C" }, - { "R 0x9681010" }, - { "R 0x9681014" }, - { "R 0x9681018" }, - { "R 0x968101C" }, - { "R 0x9681020" }, - { "R 0x9681024" }, - { "R 0x9681028" }, - { "R 0x968102C" }, - { "R 0x9681030" }, - { "R 0x9681034" }, - { "R 0x968103C" }, - { "R 0x9698100" }, - { "R 0x9698104" }, - { "R 0x9698108" }, - { "R 0x9698110" }, - { "R 0x9698120" }, - { "R 0x9698124" }, - { "R 0x9698128" }, - { "R 0x969812C" }, - { "R 0x9698130" }, - { "R 0x9698134" }, - { "R 0x9698138" }, - { "R 0x969813C" }, - { "R 0x62BE2004" }, - { "R 0x62BE2040" }, - { "R 0x62BE2048" }, - { "R 0x62BE2088" }, - { "R 0x62BE2090" }, - { "R 0x62BE2100" }, - { "R 0x62BE2104" }, - { "R 0x62BE2108" }, - { "R 0x62BE210C" }, - { "R 0x62BE2110" }, - { "R 0x62BE2114" }, - { "R 0x62BE2118" }, - { "R 0x62BE0010" }, - { "R 0x62BE0020" }, - { "R 0x62BE0024" }, - { "R 0x62BE0028" }, - { "R 0x62BE002C" }, - { "R 0x62BE0030" }, - { "R 0x62BE0034" }, - { "R 0x62BE0038" }, - { "R 0x62BE003C" }, - { "R 0x9160204" }, - { "R 0x9160240" }, - { "R 0x9160248" }, - { "R 0x9160288" }, - { "R 0x9160290" }, - { "R 0x9160300" }, - { "R 0x9160304" }, - { "R 0x9160308" }, - { "R 0x916030C" }, - { "R 0x9160310" }, - { "R 0x9160314" }, - { "R 0x9160318" }, - { "R 0x9160008" }, - { "R 0x9160010" }, - { "R 0x9160020" }, - { "R 0x9160024" }, - { "R 0x9160028" }, - { "R 0x916002C" }, - { "R 0x9160030" }, - { "R 0x9160034" }, - { "R 0x9160038" }, - { "R 0x916003C" }, - { "R 0x1620500 4" }, - { "R 0x1620700 4" }, - { "R 0x1620300" }, - { "R 0x1620F00 2" }, - { "R 0x1620B00 2" }, - { "R 0x1700B00 2" }, - { "R 0x1700700 3" }, - { "R 0x9163100" }, - { "R 0x96AA100" }, - { "R 0x9050008" }, - { "R 0x9050068" }, - { "R 0x9050078" }, - { "R 0x18200400" }, - { "R 0x18200404" }, - { "R 0x18200408" }, - { "R 0x18200038" }, - { "R 0x18200040" }, - { "R 0x18200048" }, - { "R 0x18220038" }, - { "R 0x18220040" }, - { "R 0x182200D0" }, - { "R 0x18200030" }, - { "R 0x18200010" }, - { "R 0x1822000c" }, - { "R 0x18220d14" }, - { "R 0x18220fb4" }, - { "R 0x18221254" }, - { "R 0x182214f4" }, - { "R 0x18221794" }, - { "R 0x18221a34" }, - { "R 0x18221cd4" }, - { "R 0x18221f74" }, - { "R 0x18220d18" }, - { "R 0x18220fb8" }, - { "R 0x18221258" }, - { "R 0x182214f8" }, - { "R 0x18221798" }, - { "R 0x18221a38" }, - { "R 0x18221cd8" }, - { "R 0x18221f78" }, - { "R 0x18220d00" }, - { "R 0x18220d04" }, - { "R 0x18220d1c" }, - { "R 0x18220fbc" }, - { "R 0x1822125c" }, - { "R 0x182214fc" }, - { "R 0x1822179c" }, - { "R 0x18221a3c" }, - { "R 0x18221cdc" }, - { "R 0x18221f7c" }, - { "R 0x18221274" }, - { "R 0x18221288" }, - { "R 0x1822129c" }, - { "R 0x182212b0" }, - { "R 0x182212c4" }, - { "R 0x182212d8" }, - { "R 0x182212ec" }, - { "R 0x18221300" }, - { "R 0x18221314" }, - { "R 0x18221328" }, - { "R 0x1822133c" }, - { "R 0x18221350" }, - { "R 0x18221364" }, - { "R 0x18221378" }, - { "R 0x1822138c" }, - { "R 0x182213a0" }, - { "R 0x18221514" }, - { "R 0x18221528" }, - { "R 0x1822153c" }, - { "R 0x18221550" }, - { "R 0x18221564" }, - { "R 0x18221578" }, - { "R 0x1822158c" }, - { "R 0x182215a0" }, - { "R 0x182215b4" }, - { "R 0x182215c8" }, - { "R 0x182215dc" }, - { "R 0x182215f0" }, - { "R 0x18221604" }, - { "R 0x18221618" }, - { "R 0x1822162c" }, - { "R 0x18221640" }, - { "R 0x182217b4" }, - { "R 0x182217c8" }, - { "R 0x182217dc" }, - { "R 0x182217f0" }, - { "R 0x18221804" }, - { "R 0x18221818" }, - { "R 0x1822182c" }, - { "R 0x18221840" }, - { "R 0x18221854" }, - { "R 0x18221868" }, - { "R 0x1822187c" }, - { "R 0x18221890" }, - { "R 0x182218a4" }, - { "R 0x182218b8" }, - { "R 0x182218cc" }, - { "R 0x182218e0" }, - { "R 0x18221a54" }, - { "R 0x18221a68" }, - { "R 0x18221a7c" }, - { "R 0x18221a90" }, - { "R 0x18221aa4" }, - { "R 0x18221ab8" }, - { "R 0x18221acc" }, - { "R 0x18221ae0" }, - { "R 0x18221af4" }, - { "R 0x18221b08" }, - { "R 0x18221b1c" }, - { "R 0x18221b30" }, - { "R 0x18221b44" }, - { "R 0x18221b58" }, - { "R 0x18221b6c" }, - { "R 0x18221b80" }, - { "R 0x18221cf4" }, - { "R 0x18221d08" }, - { "R 0x18221d1c" }, - { "R 0x18221d30" }, - { "R 0x18221d44" }, - { "R 0x18221d58" }, - { "R 0x18221d6c" }, - { "R 0x18221d80" }, - { "R 0x18221d94" }, - { "R 0x18221da8" }, - { "R 0x18221dbc" }, - { "R 0x18221dd0" }, - { "R 0x18221de4" }, - { "R 0x18221df8" }, - { "R 0x18221e0c" }, - { "R 0x18221e20" }, - { "R 0x18221f94" }, - { "R 0x18221fa8" }, - { "R 0x18221fbc" }, - { "R 0x18221fd0" }, - { "R 0x18221fe4" }, - { "R 0x18221ff8" }, - { "R 0x1822200c" }, - { "R 0x18222020" }, - { "R 0x18222034" }, - { "R 0x18222048" }, - { "R 0x1822205c" }, - { "R 0x18222070" }, - { "R 0x18222084" }, - { "R 0x18222098" }, - { "R 0x182220ac" }, - { "R 0x182220c0" }, - { "R 0x18221278" }, - { "R 0x1822128c" }, - { "R 0x182212a0" }, - { "R 0x182212b4" }, - { "R 0x182212c8" }, - { "R 0x182212dc" }, - { "R 0x182212f0" }, - { "R 0x18221304" }, - { "R 0x18221318" }, - { "R 0x1822132c" }, - { "R 0x18221340" }, - { "R 0x18221354" }, - { "R 0x18221368" }, - { "R 0x1822137c" }, - { "R 0x18221390" }, - { "R 0x182213a4" }, - { "R 0x18221518" }, - { "R 0x1822152c" }, - { "R 0x18221540" }, - { "R 0x18221554" }, - { "R 0x18221568" }, - { "R 0x1822157c" }, - { "R 0x18221590" }, - { "R 0x182215a4" }, - { "R 0x182215b8" }, - { "R 0x182215cc" }, - { "R 0x182215e0" }, - { "R 0x182215f4" }, - { "R 0x18221608" }, - { "R 0x1822161c" }, - { "R 0x18221630" }, - { "R 0x18221644" }, - { "R 0x182217b8" }, - { "R 0x182217cc" }, - { "R 0x182217e0" }, - { "R 0x182217f4" }, - { "R 0x18221808" }, - { "R 0x1822181c" }, - { "R 0x18221830" }, - { "R 0x18221844" }, - { "R 0x18221858" }, - { "R 0x1822186c" }, - { "R 0x18221880" }, - { "R 0x18221894" }, - { "R 0x182218a8" }, - { "R 0x182218bc" }, - { "R 0x182218d0" }, - { "R 0x182218e4" }, - { "R 0x18221a58" }, - { "R 0x18221a6c" }, - { "R 0x18221a80" }, - { "R 0x18221a94" }, - { "R 0x18221aa8" }, - { "R 0x18221abc" }, - { "R 0x18221ad0" }, - { "R 0x18221ae4" }, - { "R 0x18221af8" }, - { "R 0x18221b0c" }, - { "R 0x18221b20" }, - { "R 0x18221b34" }, - { "R 0x18221b48" }, - { "R 0x18221b5c" }, - { "R 0x18221b70" }, - { "R 0x18221b84" }, - { "R 0x18221cf8" }, - { "R 0x18221d0c" }, - { "R 0x18221d20" }, - { "R 0x18221d34" }, - { "R 0x18221d48" }, - { "R 0x18221d5c" }, - { "R 0x18221d70" }, - { "R 0x18221d84" }, - { "R 0x18221d98" }, - { "R 0x18221dac" }, - { "R 0x18221dc0" }, - { "R 0x18221dd4" }, - { "R 0x18221de8" }, - { "R 0x18221dfc" }, - { "R 0x18221e10" }, - { "R 0x18221e24" }, - { "R 0x18221f98" }, - { "R 0x18221fac" }, - { "R 0x18221fc0" }, - { "R 0x18221fd4" }, - { "R 0x18221fe8" }, - { "R 0x18221ffc" }, - { "R 0x18222010" }, - { "R 0x18222024" }, - { "R 0x18222038" }, - { "R 0x1822204c" }, - { "R 0x18222060" }, - { "R 0x18222074" }, - { "R 0x18222088" }, - { "R 0x1822209c" }, - { "R 0x182220b0" }, - { "R 0x182220c4" }, - { "R 0x18000024" }, - { "R 0x18000040" }, - { "R 0x18010024" }, - { "R 0x18010040" }, - { "R 0x18020024" }, - { "R 0x18020040" }, - { "R 0x18030024" }, - { "R 0x18030040" }, - { "R 0x18040024" }, - { "R 0x18040040" }, - { "R 0x18050024" }, - { "R 0x18050040" }, - { "R 0x18060024" }, - { "R 0x18060040" }, - { "R 0x18070024" }, - { "R 0x18070040" }, - { "R 0x18080024" }, - { "R 0x18080040" }, - { "R 0x180800F8" }, - { "R 0x18080104" }, - { "R 0x1808011C" }, - { "R 0x18080128" }, - { "R 0x90b0280" }, - { "R 0x90b0288" }, - { "R 0x90b028c" }, - { "R 0x90b0290" }, - { "R 0x90b0294" }, - { "R 0x90b0298" }, - { "R 0x90b029c" }, - { "R 0x90b02a0" }, - { "R 0x18321700" }, - { "R 0x18322C18" }, - { "R 0x18323700" }, - { "R 0x18324C18" }, - { "R 0x18325F00" }, - { "R 0x18327418" }, - { "R 0x9236028" }, - { "R 0x923602C" }, - { "R 0x9236030" }, - { "R 0x9236034" }, - { "R 0x9236038" }, - { "R 0x9232100" }, - { "R 0x92360b0" }, - { "R 0x9236044" }, - { "R 0x9236048" }, - { "R 0x923604c" }, - { "R 0x9236050" }, - { "R 0x923e030" }, - { "R 0x923e034" }, - { "R 0x9241000" }, - { "R 0x9248058" }, - { "R 0x924805c" }, - { "R 0x9248060" }, - { "R 0x9248064" }, - { "R 0x9260410" }, - { "R 0x92e0410" }, - { "R 0x9260414" }, - { "R 0x92e0414" }, - { "R 0x9260418" }, - { "R 0x92e0418" }, - { "R 0x9260420" }, - { "R 0x9260424" }, - { "R 0x9260430" }, - { "R 0x9260440" }, - { "R 0x9260448" }, - { "R 0x92604a0" }, - { "R 0x92e0420" }, - { "R 0x92e0424" }, - { "R 0x92e0430" }, - { "R 0x92e0440" }, - { "R 0x92e0448" }, - { "R 0x92e04a0" }, - { "R 0x9600000" }, - { "R 0x9601000" }, - { "R 0x9602000" }, - { "R 0x9603000" }, - { "R 0x9604000" }, - { "R 0x9605000" }, - { "R 0x9606000" }, - { "R 0x9607000" }, - { "R 0x9608000" }, - { "R 0x9609000" }, - { "R 0x960a000" }, - { "R 0x960b000" }, - { "R 0x960c000" }, - { "R 0x960d000" }, - { "R 0x960e000" }, - { "R 0x960f000" }, - { "R 0x9610000" }, - { "R 0x9611000" }, - { "R 0x9612000" }, - { "R 0x9613000" }, - { "R 0x9614000" }, - { "R 0x9615000" }, - { "R 0x9616000" }, - { "R 0x9617000" }, - { "R 0x9618000" }, - { "R 0x9619000" }, - { "R 0x961a000" }, - { "R 0x961b000" }, - { "R 0x961c000" }, - { "R 0x961d000" }, - { "R 0x961e000" }, - { "R 0x961f000" }, - { "R 0x9600004" }, - { "R 0x9601004" }, - { "R 0x9602004" }, - { "R 0x9603004" }, - { "R 0x9604004" }, - { "R 0x9605004" }, - { "R 0x9606004" }, - { "R 0x9607004" }, - { "R 0x9608004" }, - { "R 0x9609004" }, - { "R 0x960a004" }, - { "R 0x960b004" }, - { "R 0x960c004" }, - { "R 0x960d004" }, - { "R 0x960e004" }, - { "R 0x960f004" }, - { "R 0x9610004" }, - { "R 0x9611004" }, - { "R 0x9612004" }, - { "R 0x9613004" }, - { "R 0x9614004" }, - { "R 0x9615004" }, - { "R 0x9616004" }, - { "R 0x9617004" }, - { "R 0x9618004" }, - { "R 0x9619004" }, - { "R 0x961a004" }, - { "R 0x961b004" }, - { "R 0x961c004" }, - { "R 0x961d004" }, - { "R 0x961e004" }, - { "R 0x961f004" }, - { "R 0x9266418" }, - { "R 0x92e6418" }, - { "R 0x9265804" }, - { "R 0x92e5804" }, - { "R 0x92604b8" }, - { "R 0x92e04b8" }, - { "R 0x0C201244 1" }, - { "R 0x0C202244 1" }, - { "R 0x18100C18 1" }, - { "R 0x18101C18 1" }, - { "R 0x18300000 1" }, - { "R 0x183A3A84 2" }, - { "R 0x18393A84 2" }, - { "R 0x00100000" }, - { "R 0x00100004" }, - { "R 0x00100008" }, - { "R 0x0010000C" }, - { "R 0x00100010" }, - { "R 0x00100014" }, - { "R 0x00100018" }, - { "R 0x0010001C" }, - { "R 0x00100020" }, - { "R 0x00100024" }, - { "R 0x00100028" }, - { "R 0x0010002C" }, - { "R 0x00100030" }, - { "R 0x00100034" }, - { "R 0x00100100" }, - { "R 0x00100104" }, - { "R 0x00100108" }, - { "R 0x0010010C" }, - { "R 0x00101000" }, - { "R 0x00101004" }, - { "R 0x00101008" }, - { "R 0x0010100C" }, - { "R 0x00101010" }, - { "R 0x00101014" }, - { "R 0x00101018" }, - { "R 0x0010101C" }, - { "R 0x00101020" }, - { "R 0x00101024" }, - { "R 0x00101028" }, - { "R 0x0010102C" }, - { "R 0x00101030" }, - { "R 0x00101034" }, - { "R 0x00102000" }, - { "R 0x00102004" }, - { "R 0x00102008" }, - { "R 0x0010200C" }, - { "R 0x00102010" }, - { "R 0x00102014" }, - { "R 0x00102018" }, - { "R 0x0010201C" }, - { "R 0x00102020" }, - { "R 0x00102024" }, - { "R 0x00102028" }, - { "R 0x0010202C" }, - { "R 0x00102030" }, - { "R 0x00102034" }, - { "R 0x00103000" }, - { "R 0x00103004" }, - { "R 0x00103008" }, - { "R 0x0010300C" }, - { "R 0x00103010" }, - { "R 0x00103014" }, - { "R 0x00103018" }, - { "R 0x0010301C" }, - { "R 0x00103020" }, - { "R 0x00103024" }, - { "R 0x00103028" }, - { "R 0x0010302C" }, - { "R 0x00103030" }, - { "R 0x00103034" }, - { "R 0x00113000" }, - { "R 0x00113004" }, - { "R 0x00113008" }, - { "R 0x0011300C" }, - { "R 0x00113010" }, - { "R 0x00113014" }, - { "R 0x00113018" }, - { "R 0x0011301C" }, - { "R 0x00113020" }, - { "R 0x00113024" }, - { "R 0x00113028" }, - { "R 0x0011302C" }, - { "R 0x00113030" }, - { "R 0x00113034" }, - { "R 0x0011A000" }, - { "R 0x0011A004" }, - { "R 0x0011A008" }, - { "R 0x0011A00C" }, - { "R 0x0011A010" }, - { "R 0x0011A014" }, - { "R 0x0011A018" }, - { "R 0x0011A01C" }, - { "R 0x0011A020" }, - { "R 0x0011A024" }, - { "R 0x0011A028" }, - { "R 0x0011A02C" }, - { "R 0x0011A030" }, - { "R 0x0011A034" }, - { "R 0x0011B000" }, - { "R 0x0011B004" }, - { "R 0x0011B008" }, - { "R 0x0011B00C" }, - { "R 0x0011B010" }, - { "R 0x0011B014" }, - { "R 0x0011B018" }, - { "R 0x0011B01C" }, - { "R 0x0011B020" }, - { "R 0x0011B024" }, - { "R 0x0011B028" }, - { "R 0x0011B02C" }, - { "R 0x0011B030" }, - { "R 0x0011B034" }, - { "R 0x00174000" }, - { "R 0x00174004" }, - { "R 0x00174008" }, - { "R 0x0017400C" }, - { "R 0x00174010" }, - { "R 0x00174014" }, - { "R 0x00174018" }, - { "R 0x0017401C" }, - { "R 0x00174020" }, - { "R 0x00174024" }, - { "R 0x00174028" }, - { "R 0x0017402C" }, - { "R 0x00174030" }, - { "R 0x00174034" }, - { "R 0x00176000" }, - { "R 0x00176004" }, - { "R 0x00176008" }, - { "R 0x0017600C" }, - { "R 0x00176010" }, - { "R 0x00176014" }, - { "R 0x00176018" }, - { "R 0x0017601C" }, - { "R 0x00176020" }, - { "R 0x00176024" }, - { "R 0x00176028" }, - { "R 0x0017602C" }, - { "R 0x00176030" }, - { "R 0x00176034" }, - { "R 0x0010401C" }, - { "R 0x00183024" }, - { "R 0x00144168" }, - { "R 0x0011702C" }, - { "R 0x0010904C" }, - { "R 0x00189038" }, - { "R 0x001443E8" }, - { "R 0x001442B8" }, - { "R 0x00105060" }, - { "R 0x00141024" }, - { "R 0x00145038" }, - { "R 0x00109004" }, - { "R 0x00189004" }, - { "R 0x00190004" }, - { "R 0x0C2A0000" }, - { "R 0x0C2A0004" }, - { "R 0x0C2A0008" }, - { "R 0x0C2A000C" }, - { "R 0x0C2A0010" }, - { "R 0x0C2A0014" }, - { "R 0x0C2A0018" }, - { "R 0x0C2A001C" }, - { "R 0x0C2A0020" }, - { "R 0x0C2A0024" }, - { "R 0x0C2A0028" }, - { "R 0x0C2A002C" }, - { "R 0x0C2A0030" }, - { "R 0x0C2A0034" }, - { "R 0x0C2A1000" }, - { "R 0x0C2A1004" }, - { "R 0x0C2A1008" }, - { "R 0x0C2A100C" }, - { "R 0x0C2A1010" }, - { "R 0x0C2A1014" }, - { "R 0x0C2A1018" }, - { "R 0x0C2A101C" }, - { "R 0x0C2A1020" }, - { "R 0x0C2A1024" }, - { "R 0x0C2A1028" }, - { "R 0x0C2A102C" }, - { "R 0x0C2A1030" }, - { "R 0x0C2A2260" }, - { "R 0x0C2A2264" }, - { "R 0x0C2A3008" }, - { "R 0x0C2A300C" }, - { "R 0x0C2A3010" }, - { "R 0x0C2A3014" }, - { "R 0x0C2A3024" }, - { "R 0x0C2A2034" }, - { "R 0x0C2A214C" }, - { "R 0x0C2A2150" }, - { "R 0x0C2A2154" }, - { "R 0x0C2630A0 4" }, - { "R 0x0C2630B0 4" }, - { "R 0x0C2630C0 4" }, - { "R 0x0C2630D0 4" }, - { "R 0x1800005C 1" }, - { "R 0x1801005C 1" }, - { "R 0x1802005C 1" }, - { "R 0x1803005C 1" }, - { "R 0x1804005C 1" }, - { "R 0x1805005C 1" }, - { "R 0x1806005C 1" }, - { "R 0x1807005C 1" }, - { "R 0x3d96000" }, - { "R 0x3d96004" }, -}; - -static const struct dcc_link_config talos_link_configs[] = { - { - .link_list = 3, - .entries = talos_dcc_entries, - .num_entries = ARRAY_SIZE(talos_dcc_entries), - }, -}; - -static const struct dcc_config talos_config = { - .lists = talos_link_configs, - .num_lists = ARRAY_SIZE(talos_link_configs), -}; - -static const struct dcc_pdata talos_pdata = { - .base = 0x010a2000, - .size = 0x00001000, - .ram_base = 0x010ae000, - .ram_size = 0x00002000, - .dcc_offset = 0x6000, - .map_ver = 0x1, - .config = &talos_config, -}; - static const struct dcc_pdata kodiak_pdata = { .base = 0x0117f000, .size = 0x00001000, diff --git a/drivers/misc/qcom-dcc-talos-config.h b/drivers/misc/qcom-dcc-talos-config.h new file mode 100644 index 0000000000000..2c2316ae37853 --- /dev/null +++ b/drivers/misc/qcom-dcc-talos-config.h @@ -0,0 +1,792 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_TALOS_CONFIG_H +#define _QCOM_DCC_TALOS_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry talos_dcc_entries[] = { + { "R 0x9680000" }, + { "R 0x9680004" }, + { "R 0x9681000" }, + { "R 0x9681004" }, + { "R 0x9681008" }, + { "R 0x968100c" }, + { "R 0x9681010" }, + { "R 0x9681014" }, + { "R 0x968101c" }, + { "R 0x9681020" }, + { "R 0x9681024" }, + { "R 0x9681028" }, + { "R 0x968102c" }, + { "R 0x9681030" }, + { "R 0x9681034" }, + { "R 0x968103c" }, + { "R 0x9698100" }, + { "R 0x9698104" }, + { "R 0x9698108" }, + { "R 0x9698110" }, + { "R 0x9698120" }, + { "R 0x9698124" }, + { "R 0x9698128" }, + { "R 0x969812c" }, + { "R 0x9698130" }, + { "R 0x9698134" }, + { "R 0x9698138" }, + { "R 0x969813c" }, + { "R 0x9698500" }, + { "R 0x9698504" }, + { "R 0x9698508" }, + { "R 0x969850c" }, + { "R 0x9698510" }, + { "R 0x9698514" }, + { "R 0x9698518" }, + { "R 0x969851c" }, + { "R 0x9698700" }, + { "R 0x9698704" }, + { "R 0x9698708" }, + { "R 0x969870c" }, + { "R 0x9698714" }, + { "R 0x9698718" }, + { "R 0x969871c" }, + { "R 0x1620204" }, + { "R 0x1620240" }, + { "R 0x1620248" }, + { "R 0x1620288" }, + { "R 0x162028C" }, + { "R 0x1620290" }, + { "R 0x1620294" }, + { "R 0x16202A8" }, + { "R 0x16202AC" }, + { "R 0x16202B0" }, + { "R 0x16202B4" }, + { "R 0x1620300" }, + { "R 0x1700204" }, + { "R 0x1700240" }, + { "R 0x1700248" }, + { "R 0x1700288" }, + { "R 0x1700290" }, + { "R 0x1700300" }, + { "R 0x1700304" }, + { "R 0x1700308" }, + { "R 0x170030C" }, + { "R 0x1700310" }, + { "R 0x1700314" }, + { "R 0x1700C08" }, + { "R 0x1700C10" }, + { "R 0x1700C20" }, + { "R 0x1700C24" }, + { "R 0x1700C28" }, + { "R 0x1700C2C" }, + { "R 0x1700C30" }, + { "R 0x1700C34" }, + { "R 0x1700C38" }, + { "R 0x1700C3C" }, + { "R 0x1740240" }, + { "R 0x1740248" }, + { "R 0x1740288" }, + { "R 0x1740290" }, + { "R 0x1740300" }, + { "R 0x1740304" }, + { "R 0x1740308" }, + { "R 0x174030C" }, + { "R 0x1740310" }, + { "R 0x1740314" }, + { "R 0x1740004" }, + { "R 0x1740008" }, + { "R 0x1740010" }, + { "R 0x1740020" }, + { "R 0x1740024" }, + { "R 0x1740028" }, + { "R 0x174002C" }, + { "R 0x1740030" }, + { "R 0x1740034" }, + { "R 0x1740038" }, + { "R 0x174003C" }, + { "R 0x9698204" }, + { "R 0x9698240" }, + { "R 0x9698244" }, + { "R 0x9698248" }, + { "R 0x969824C" }, + { "R 0x9681010" }, + { "R 0x9681014" }, + { "R 0x9681018" }, + { "R 0x968101C" }, + { "R 0x9681020" }, + { "R 0x9681024" }, + { "R 0x9681028" }, + { "R 0x968102C" }, + { "R 0x9681030" }, + { "R 0x9681034" }, + { "R 0x968103C" }, + { "R 0x9698100" }, + { "R 0x9698104" }, + { "R 0x9698108" }, + { "R 0x9698110" }, + { "R 0x9698120" }, + { "R 0x9698124" }, + { "R 0x9698128" }, + { "R 0x969812C" }, + { "R 0x9698130" }, + { "R 0x9698134" }, + { "R 0x9698138" }, + { "R 0x969813C" }, + { "R 0x62BE2004" }, + { "R 0x62BE2040" }, + { "R 0x62BE2048" }, + { "R 0x62BE2088" }, + { "R 0x62BE2090" }, + { "R 0x62BE2100" }, + { "R 0x62BE2104" }, + { "R 0x62BE2108" }, + { "R 0x62BE210C" }, + { "R 0x62BE2110" }, + { "R 0x62BE2114" }, + { "R 0x62BE2118" }, + { "R 0x62BE0010" }, + { "R 0x62BE0020" }, + { "R 0x62BE0024" }, + { "R 0x62BE0028" }, + { "R 0x62BE002C" }, + { "R 0x62BE0030" }, + { "R 0x62BE0034" }, + { "R 0x62BE0038" }, + { "R 0x62BE003C" }, + { "R 0x9160204" }, + { "R 0x9160240" }, + { "R 0x9160248" }, + { "R 0x9160288" }, + { "R 0x9160290" }, + { "R 0x9160300" }, + { "R 0x9160304" }, + { "R 0x9160308" }, + { "R 0x916030C" }, + { "R 0x9160310" }, + { "R 0x9160314" }, + { "R 0x9160318" }, + { "R 0x9160008" }, + { "R 0x9160010" }, + { "R 0x9160020" }, + { "R 0x9160024" }, + { "R 0x9160028" }, + { "R 0x916002C" }, + { "R 0x9160030" }, + { "R 0x9160034" }, + { "R 0x9160038" }, + { "R 0x916003C" }, + { "R 0x1620500 4" }, + { "R 0x1620700 4" }, + { "R 0x1620300" }, + { "R 0x1620F00 2" }, + { "R 0x1620B00 2" }, + { "R 0x1700B00 2" }, + { "R 0x1700700 3" }, + { "R 0x9163100" }, + { "R 0x96AA100" }, + { "R 0x9050008" }, + { "R 0x9050068" }, + { "R 0x9050078" }, + { "R 0x18200400" }, + { "R 0x18200404" }, + { "R 0x18200408" }, + { "R 0x18200038" }, + { "R 0x18200040" }, + { "R 0x18200048" }, + { "R 0x18220038" }, + { "R 0x18220040" }, + { "R 0x182200D0" }, + { "R 0x18200030" }, + { "R 0x18200010" }, + { "R 0x1822000c" }, + { "R 0x18220d14" }, + { "R 0x18220fb4" }, + { "R 0x18221254" }, + { "R 0x182214f4" }, + { "R 0x18221794" }, + { "R 0x18221a34" }, + { "R 0x18221cd4" }, + { "R 0x18221f74" }, + { "R 0x18220d18" }, + { "R 0x18220fb8" }, + { "R 0x18221258" }, + { "R 0x182214f8" }, + { "R 0x18221798" }, + { "R 0x18221a38" }, + { "R 0x18221cd8" }, + { "R 0x18221f78" }, + { "R 0x18220d00" }, + { "R 0x18220d04" }, + { "R 0x18220d1c" }, + { "R 0x18220fbc" }, + { "R 0x1822125c" }, + { "R 0x182214fc" }, + { "R 0x1822179c" }, + { "R 0x18221a3c" }, + { "R 0x18221cdc" }, + { "R 0x18221f7c" }, + { "R 0x18221274" }, + { "R 0x18221288" }, + { "R 0x1822129c" }, + { "R 0x182212b0" }, + { "R 0x182212c4" }, + { "R 0x182212d8" }, + { "R 0x182212ec" }, + { "R 0x18221300" }, + { "R 0x18221314" }, + { "R 0x18221328" }, + { "R 0x1822133c" }, + { "R 0x18221350" }, + { "R 0x18221364" }, + { "R 0x18221378" }, + { "R 0x1822138c" }, + { "R 0x182213a0" }, + { "R 0x18221514" }, + { "R 0x18221528" }, + { "R 0x1822153c" }, + { "R 0x18221550" }, + { "R 0x18221564" }, + { "R 0x18221578" }, + { "R 0x1822158c" }, + { "R 0x182215a0" }, + { "R 0x182215b4" }, + { "R 0x182215c8" }, + { "R 0x182215dc" }, + { "R 0x182215f0" }, + { "R 0x18221604" }, + { "R 0x18221618" }, + { "R 0x1822162c" }, + { "R 0x18221640" }, + { "R 0x182217b4" }, + { "R 0x182217c8" }, + { "R 0x182217dc" }, + { "R 0x182217f0" }, + { "R 0x18221804" }, + { "R 0x18221818" }, + { "R 0x1822182c" }, + { "R 0x18221840" }, + { "R 0x18221854" }, + { "R 0x18221868" }, + { "R 0x1822187c" }, + { "R 0x18221890" }, + { "R 0x182218a4" }, + { "R 0x182218b8" }, + { "R 0x182218cc" }, + { "R 0x182218e0" }, + { "R 0x18221a54" }, + { "R 0x18221a68" }, + { "R 0x18221a7c" }, + { "R 0x18221a90" }, + { "R 0x18221aa4" }, + { "R 0x18221ab8" }, + { "R 0x18221acc" }, + { "R 0x18221ae0" }, + { "R 0x18221af4" }, + { "R 0x18221b08" }, + { "R 0x18221b1c" }, + { "R 0x18221b30" }, + { "R 0x18221b44" }, + { "R 0x18221b58" }, + { "R 0x18221b6c" }, + { "R 0x18221b80" }, + { "R 0x18221cf4" }, + { "R 0x18221d08" }, + { "R 0x18221d1c" }, + { "R 0x18221d30" }, + { "R 0x18221d44" }, + { "R 0x18221d58" }, + { "R 0x18221d6c" }, + { "R 0x18221d80" }, + { "R 0x18221d94" }, + { "R 0x18221da8" }, + { "R 0x18221dbc" }, + { "R 0x18221dd0" }, + { "R 0x18221de4" }, + { "R 0x18221df8" }, + { "R 0x18221e0c" }, + { "R 0x18221e20" }, + { "R 0x18221f94" }, + { "R 0x18221fa8" }, + { "R 0x18221fbc" }, + { "R 0x18221fd0" }, + { "R 0x18221fe4" }, + { "R 0x18221ff8" }, + { "R 0x1822200c" }, + { "R 0x18222020" }, + { "R 0x18222034" }, + { "R 0x18222048" }, + { "R 0x1822205c" }, + { "R 0x18222070" }, + { "R 0x18222084" }, + { "R 0x18222098" }, + { "R 0x182220ac" }, + { "R 0x182220c0" }, + { "R 0x18221278" }, + { "R 0x1822128c" }, + { "R 0x182212a0" }, + { "R 0x182212b4" }, + { "R 0x182212c8" }, + { "R 0x182212dc" }, + { "R 0x182212f0" }, + { "R 0x18221304" }, + { "R 0x18221318" }, + { "R 0x1822132c" }, + { "R 0x18221340" }, + { "R 0x18221354" }, + { "R 0x18221368" }, + { "R 0x1822137c" }, + { "R 0x18221390" }, + { "R 0x182213a4" }, + { "R 0x18221518" }, + { "R 0x1822152c" }, + { "R 0x18221540" }, + { "R 0x18221554" }, + { "R 0x18221568" }, + { "R 0x1822157c" }, + { "R 0x18221590" }, + { "R 0x182215a4" }, + { "R 0x182215b8" }, + { "R 0x182215cc" }, + { "R 0x182215e0" }, + { "R 0x182215f4" }, + { "R 0x18221608" }, + { "R 0x1822161c" }, + { "R 0x18221630" }, + { "R 0x18221644" }, + { "R 0x182217b8" }, + { "R 0x182217cc" }, + { "R 0x182217e0" }, + { "R 0x182217f4" }, + { "R 0x18221808" }, + { "R 0x1822181c" }, + { "R 0x18221830" }, + { "R 0x18221844" }, + { "R 0x18221858" }, + { "R 0x1822186c" }, + { "R 0x18221880" }, + { "R 0x18221894" }, + { "R 0x182218a8" }, + { "R 0x182218bc" }, + { "R 0x182218d0" }, + { "R 0x182218e4" }, + { "R 0x18221a58" }, + { "R 0x18221a6c" }, + { "R 0x18221a80" }, + { "R 0x18221a94" }, + { "R 0x18221aa8" }, + { "R 0x18221abc" }, + { "R 0x18221ad0" }, + { "R 0x18221ae4" }, + { "R 0x18221af8" }, + { "R 0x18221b0c" }, + { "R 0x18221b20" }, + { "R 0x18221b34" }, + { "R 0x18221b48" }, + { "R 0x18221b5c" }, + { "R 0x18221b70" }, + { "R 0x18221b84" }, + { "R 0x18221cf8" }, + { "R 0x18221d0c" }, + { "R 0x18221d20" }, + { "R 0x18221d34" }, + { "R 0x18221d48" }, + { "R 0x18221d5c" }, + { "R 0x18221d70" }, + { "R 0x18221d84" }, + { "R 0x18221d98" }, + { "R 0x18221dac" }, + { "R 0x18221dc0" }, + { "R 0x18221dd4" }, + { "R 0x18221de8" }, + { "R 0x18221dfc" }, + { "R 0x18221e10" }, + { "R 0x18221e24" }, + { "R 0x18221f98" }, + { "R 0x18221fac" }, + { "R 0x18221fc0" }, + { "R 0x18221fd4" }, + { "R 0x18221fe8" }, + { "R 0x18221ffc" }, + { "R 0x18222010" }, + { "R 0x18222024" }, + { "R 0x18222038" }, + { "R 0x1822204c" }, + { "R 0x18222060" }, + { "R 0x18222074" }, + { "R 0x18222088" }, + { "R 0x1822209c" }, + { "R 0x182220b0" }, + { "R 0x182220c4" }, + { "R 0x18000024" }, + { "R 0x18000040" }, + { "R 0x18010024" }, + { "R 0x18010040" }, + { "R 0x18020024" }, + { "R 0x18020040" }, + { "R 0x18030024" }, + { "R 0x18030040" }, + { "R 0x18040024" }, + { "R 0x18040040" }, + { "R 0x18050024" }, + { "R 0x18050040" }, + { "R 0x18060024" }, + { "R 0x18060040" }, + { "R 0x18070024" }, + { "R 0x18070040" }, + { "R 0x18080024" }, + { "R 0x18080040" }, + { "R 0x180800F8" }, + { "R 0x18080104" }, + { "R 0x1808011C" }, + { "R 0x18080128" }, + { "R 0x90b0280" }, + { "R 0x90b0288" }, + { "R 0x90b028c" }, + { "R 0x90b0290" }, + { "R 0x90b0294" }, + { "R 0x90b0298" }, + { "R 0x90b029c" }, + { "R 0x90b02a0" }, + { "R 0x18321700" }, + { "R 0x18322C18" }, + { "R 0x18323700" }, + { "R 0x18324C18" }, + { "R 0x18325F00" }, + { "R 0x18327418" }, + { "R 0x9236028" }, + { "R 0x923602C" }, + { "R 0x9236030" }, + { "R 0x9236034" }, + { "R 0x9236038" }, + { "R 0x9232100" }, + { "R 0x92360b0" }, + { "R 0x9236044" }, + { "R 0x9236048" }, + { "R 0x923604c" }, + { "R 0x9236050" }, + { "R 0x923e030" }, + { "R 0x923e034" }, + { "R 0x9241000" }, + { "R 0x9248058" }, + { "R 0x924805c" }, + { "R 0x9248060" }, + { "R 0x9248064" }, + { "R 0x9260410" }, + { "R 0x92e0410" }, + { "R 0x9260414" }, + { "R 0x92e0414" }, + { "R 0x9260418" }, + { "R 0x92e0418" }, + { "R 0x9260420" }, + { "R 0x9260424" }, + { "R 0x9260430" }, + { "R 0x9260440" }, + { "R 0x9260448" }, + { "R 0x92604a0" }, + { "R 0x92e0420" }, + { "R 0x92e0424" }, + { "R 0x92e0430" }, + { "R 0x92e0440" }, + { "R 0x92e0448" }, + { "R 0x92e04a0" }, + { "R 0x9600000" }, + { "R 0x9601000" }, + { "R 0x9602000" }, + { "R 0x9603000" }, + { "R 0x9604000" }, + { "R 0x9605000" }, + { "R 0x9606000" }, + { "R 0x9607000" }, + { "R 0x9608000" }, + { "R 0x9609000" }, + { "R 0x960a000" }, + { "R 0x960b000" }, + { "R 0x960c000" }, + { "R 0x960d000" }, + { "R 0x960e000" }, + { "R 0x960f000" }, + { "R 0x9610000" }, + { "R 0x9611000" }, + { "R 0x9612000" }, + { "R 0x9613000" }, + { "R 0x9614000" }, + { "R 0x9615000" }, + { "R 0x9616000" }, + { "R 0x9617000" }, + { "R 0x9618000" }, + { "R 0x9619000" }, + { "R 0x961a000" }, + { "R 0x961b000" }, + { "R 0x961c000" }, + { "R 0x961d000" }, + { "R 0x961e000" }, + { "R 0x961f000" }, + { "R 0x9600004" }, + { "R 0x9601004" }, + { "R 0x9602004" }, + { "R 0x9603004" }, + { "R 0x9604004" }, + { "R 0x9605004" }, + { "R 0x9606004" }, + { "R 0x9607004" }, + { "R 0x9608004" }, + { "R 0x9609004" }, + { "R 0x960a004" }, + { "R 0x960b004" }, + { "R 0x960c004" }, + { "R 0x960d004" }, + { "R 0x960e004" }, + { "R 0x960f004" }, + { "R 0x9610004" }, + { "R 0x9611004" }, + { "R 0x9612004" }, + { "R 0x9613004" }, + { "R 0x9614004" }, + { "R 0x9615004" }, + { "R 0x9616004" }, + { "R 0x9617004" }, + { "R 0x9618004" }, + { "R 0x9619004" }, + { "R 0x961a004" }, + { "R 0x961b004" }, + { "R 0x961c004" }, + { "R 0x961d004" }, + { "R 0x961e004" }, + { "R 0x961f004" }, + { "R 0x9266418" }, + { "R 0x92e6418" }, + { "R 0x9265804" }, + { "R 0x92e5804" }, + { "R 0x92604b8" }, + { "R 0x92e04b8" }, + { "R 0x0C201244 1" }, + { "R 0x0C202244 1" }, + { "R 0x18100C18 1" }, + { "R 0x18101C18 1" }, + { "R 0x18300000 1" }, + { "R 0x183A3A84 2" }, + { "R 0x18393A84 2" }, + { "R 0x00100000" }, + { "R 0x00100004" }, + { "R 0x00100008" }, + { "R 0x0010000C" }, + { "R 0x00100010" }, + { "R 0x00100014" }, + { "R 0x00100018" }, + { "R 0x0010001C" }, + { "R 0x00100020" }, + { "R 0x00100024" }, + { "R 0x00100028" }, + { "R 0x0010002C" }, + { "R 0x00100030" }, + { "R 0x00100034" }, + { "R 0x00100100" }, + { "R 0x00100104" }, + { "R 0x00100108" }, + { "R 0x0010010C" }, + { "R 0x00101000" }, + { "R 0x00101004" }, + { "R 0x00101008" }, + { "R 0x0010100C" }, + { "R 0x00101010" }, + { "R 0x00101014" }, + { "R 0x00101018" }, + { "R 0x0010101C" }, + { "R 0x00101020" }, + { "R 0x00101024" }, + { "R 0x00101028" }, + { "R 0x0010102C" }, + { "R 0x00101030" }, + { "R 0x00101034" }, + { "R 0x00102000" }, + { "R 0x00102004" }, + { "R 0x00102008" }, + { "R 0x0010200C" }, + { "R 0x00102010" }, + { "R 0x00102014" }, + { "R 0x00102018" }, + { "R 0x0010201C" }, + { "R 0x00102020" }, + { "R 0x00102024" }, + { "R 0x00102028" }, + { "R 0x0010202C" }, + { "R 0x00102030" }, + { "R 0x00102034" }, + { "R 0x00103000" }, + { "R 0x00103004" }, + { "R 0x00103008" }, + { "R 0x0010300C" }, + { "R 0x00103010" }, + { "R 0x00103014" }, + { "R 0x00103018" }, + { "R 0x0010301C" }, + { "R 0x00103020" }, + { "R 0x00103024" }, + { "R 0x00103028" }, + { "R 0x0010302C" }, + { "R 0x00103030" }, + { "R 0x00103034" }, + { "R 0x00113000" }, + { "R 0x00113004" }, + { "R 0x00113008" }, + { "R 0x0011300C" }, + { "R 0x00113010" }, + { "R 0x00113014" }, + { "R 0x00113018" }, + { "R 0x0011301C" }, + { "R 0x00113020" }, + { "R 0x00113024" }, + { "R 0x00113028" }, + { "R 0x0011302C" }, + { "R 0x00113030" }, + { "R 0x00113034" }, + { "R 0x0011A000" }, + { "R 0x0011A004" }, + { "R 0x0011A008" }, + { "R 0x0011A00C" }, + { "R 0x0011A010" }, + { "R 0x0011A014" }, + { "R 0x0011A018" }, + { "R 0x0011A01C" }, + { "R 0x0011A020" }, + { "R 0x0011A024" }, + { "R 0x0011A028" }, + { "R 0x0011A02C" }, + { "R 0x0011A030" }, + { "R 0x0011A034" }, + { "R 0x0011B000" }, + { "R 0x0011B004" }, + { "R 0x0011B008" }, + { "R 0x0011B00C" }, + { "R 0x0011B010" }, + { "R 0x0011B014" }, + { "R 0x0011B018" }, + { "R 0x0011B01C" }, + { "R 0x0011B020" }, + { "R 0x0011B024" }, + { "R 0x0011B028" }, + { "R 0x0011B02C" }, + { "R 0x0011B030" }, + { "R 0x0011B034" }, + { "R 0x00174000" }, + { "R 0x00174004" }, + { "R 0x00174008" }, + { "R 0x0017400C" }, + { "R 0x00174010" }, + { "R 0x00174014" }, + { "R 0x00174018" }, + { "R 0x0017401C" }, + { "R 0x00174020" }, + { "R 0x00174024" }, + { "R 0x00174028" }, + { "R 0x0017402C" }, + { "R 0x00174030" }, + { "R 0x00174034" }, + { "R 0x00176000" }, + { "R 0x00176004" }, + { "R 0x00176008" }, + { "R 0x0017600C" }, + { "R 0x00176010" }, + { "R 0x00176014" }, + { "R 0x00176018" }, + { "R 0x0017601C" }, + { "R 0x00176020" }, + { "R 0x00176024" }, + { "R 0x00176028" }, + { "R 0x0017602C" }, + { "R 0x00176030" }, + { "R 0x00176034" }, + { "R 0x0010401C" }, + { "R 0x00183024" }, + { "R 0x00144168" }, + { "R 0x0011702C" }, + { "R 0x0010904C" }, + { "R 0x00189038" }, + { "R 0x001443E8" }, + { "R 0x001442B8" }, + { "R 0x00105060" }, + { "R 0x00141024" }, + { "R 0x00145038" }, + { "R 0x00109004" }, + { "R 0x00189004" }, + { "R 0x00190004" }, + { "R 0x0C2A0000" }, + { "R 0x0C2A0004" }, + { "R 0x0C2A0008" }, + { "R 0x0C2A000C" }, + { "R 0x0C2A0010" }, + { "R 0x0C2A0014" }, + { "R 0x0C2A0018" }, + { "R 0x0C2A001C" }, + { "R 0x0C2A0020" }, + { "R 0x0C2A0024" }, + { "R 0x0C2A0028" }, + { "R 0x0C2A002C" }, + { "R 0x0C2A0030" }, + { "R 0x0C2A0034" }, + { "R 0x0C2A1000" }, + { "R 0x0C2A1004" }, + { "R 0x0C2A1008" }, + { "R 0x0C2A100C" }, + { "R 0x0C2A1010" }, + { "R 0x0C2A1014" }, + { "R 0x0C2A1018" }, + { "R 0x0C2A101C" }, + { "R 0x0C2A1020" }, + { "R 0x0C2A1024" }, + { "R 0x0C2A1028" }, + { "R 0x0C2A102C" }, + { "R 0x0C2A1030" }, + { "R 0x0C2A2260" }, + { "R 0x0C2A2264" }, + { "R 0x0C2A3008" }, + { "R 0x0C2A300C" }, + { "R 0x0C2A3010" }, + { "R 0x0C2A3014" }, + { "R 0x0C2A3024" }, + { "R 0x0C2A2034" }, + { "R 0x0C2A214C" }, + { "R 0x0C2A2150" }, + { "R 0x0C2A2154" }, + { "R 0x0C2630A0 4" }, + { "R 0x0C2630B0 4" }, + { "R 0x0C2630C0 4" }, + { "R 0x0C2630D0 4" }, + { "R 0x1800005C 1" }, + { "R 0x1801005C 1" }, + { "R 0x1802005C 1" }, + { "R 0x1803005C 1" }, + { "R 0x1804005C 1" }, + { "R 0x1805005C 1" }, + { "R 0x1806005C 1" }, + { "R 0x1807005C 1" }, + { "R 0x3d96000" }, + { "R 0x3d96004" }, +}; + +static const struct dcc_link_config talos_link_configs[] = { + { + .link_list = 3, + .entries = talos_dcc_entries, + .num_entries = ARRAY_SIZE(talos_dcc_entries), + }, +}; + +static const struct dcc_config talos_config = { + .lists = talos_link_configs, + .num_lists = ARRAY_SIZE(talos_link_configs), +}; + +static const struct dcc_pdata talos_pdata = { + .base = 0x010a2000, + .size = 0x00001000, + .ram_base = 0x010ae000, + .ram_size = 0x00002000, + .dcc_offset = 0x6000, + .map_ver = 0x1, + .config = &talos_config, +}; + +#endif /* _QCOM_DCC_TALOS_CONFIG_H */ From 93c23a3ff307f7f7e4b400e48025fd4685ffd724 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 29 Apr 2026 12:18:22 +0800 Subject: [PATCH 0057/1133] QCLINUX: qcom-dcc: group lemans and monaco SoC IDs with comments The lemans_pdata is shared by both Lemans (534, 667, 676) and Monaco (606, 674, 675) SoC variants. Add comments to distinguish the two groups and reorder the case labels accordingly. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 83efad89b4d76..3595200b37d7a 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -82,12 +82,14 @@ static int __init dcc_dev_init(void) goto fail; break; + /* lemans IDs */ case 534: - case 606: case 667: + case 676: + /* monaco IDs */ + case 606: case 674: case 675: - case 676: ret = platform_device_add_data(dcc_pdev, &lemans_pdata, sizeof(lemans_pdata)); if (ret) goto fail; From 32cffa07b7fab492b5dd26e754ae760323d669a3 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 29 Apr 2026 13:56:57 +0800 Subject: [PATCH 0058/1133] QCLINUX: qcom-dcc: add kodiak register list and move config to header Add the full DCC register capture list for the Kodiak platform derived from debug_config_qcm6490.sh. The registers are distributed across three linked lists: - Link list 6: pcu, epss, pimem, core, gemnoc, tsens, spmi, gpu, sysnoc, aggrenoc, gcc (430 entries) - Link list 4: confignoc, limits, gic, mmssnoc, apps_rsc, misc, ddr (450 entries) - Link list 3: lpass_rsc, nsp_rsc, sdi_debug, lpass_cdsp_tunning, wpss_rsc, video_noc (231 entries) Estimated SRAM usage is ~14 KB, well within the 24 KB (0x6000) budget. Move the kodiak DCC configuration (entries arrays, link configs, dcc config, and pdata) into a dedicated header qcom-dcc-kodiak-config.h, consistent with the approach used for talos and lemans. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 10 +- drivers/misc/qcom-dcc-kodiak-config.h | 1188 +++++++++++++++++++++++++ 2 files changed, 1189 insertions(+), 9 deletions(-) create mode 100644 drivers/misc/qcom-dcc-kodiak-config.h diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 3595200b37d7a..cd8bad68a6077 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -9,20 +9,12 @@ #include "qcom-dcc.h" #include "qcom-dcc-talos-config.h" #include "qcom-dcc-lemans-config.h" +#include "qcom-dcc-kodiak-config.h" #define DEV_NAME "qcom-dcc" static struct platform_device *dcc_pdev; -static const struct dcc_pdata kodiak_pdata = { - .base = 0x0117f000, - .size = 0x00001000, - .ram_base = 0x01112000, - .ram_size = 0x00006000, - .dcc_offset = 0x12000, - .map_ver = 0x2, -}; - static const struct dcc_pdata pakala_pdata = { .base = 0x100ff000, .size = 0x00001000, diff --git a/drivers/misc/qcom-dcc-kodiak-config.h b/drivers/misc/qcom-dcc-kodiak-config.h new file mode 100644 index 0000000000000..7184252734917 --- /dev/null +++ b/drivers/misc/qcom-dcc-kodiak-config.h @@ -0,0 +1,1188 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_KODIAK_CONFIG_H +#define _QCOM_DCC_KODIAK_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry kodiak_dcc_entries_ll6[] = { + /* pcu */ + { "R 0x18000010" }, + { "R 0x18000024" }, + { "R 0x18000038 6" }, + { "R 0x18010010" }, + { "R 0x18010024" }, + { "R 0x18010038 6" }, + { "R 0x18020010" }, + { "R 0x18020024" }, + { "R 0x18020038 6" }, + { "R 0x18030010" }, + { "R 0x18030024" }, + { "R 0x18030038 6" }, + { "R 0x18040010" }, + { "R 0x18040024" }, + { "R 0x18040038 6" }, + { "R 0x18050010" }, + { "R 0x18050024" }, + { "R 0x18050038 6" }, + { "R 0x18060010" }, + { "R 0x18060024" }, + { "R 0x18060038 6" }, + { "R 0x18070010" }, + { "R 0x18070024" }, + { "R 0x18070038 6" }, + { "R 0x18080010" }, + { "R 0x18080024" }, + { "R 0x18080038 6" }, + { "R 0x1808006c 5" }, + { "R 0x18080084" }, + { "R 0x180800f4 18" }, + { "R 0x18080158 5" }, + { "R 0x18080170 2" }, + { "R 0x18080188 5" }, + { "R 0x180801ac 6" }, + { "R 0x180801c8" }, + { "R 0x180801f0" }, + /* epss */ + { "R 0x18598020" }, + { "R 0x1859001c 2" }, + { "R 0x1859002c" }, + { "R 0x18590064 6" }, + { "R 0x1859008c" }, + { "R 0x185900dc" }, + { "R 0x185900e8 3" }, + { "R 0x18590300" }, + { "R 0x1859030c" }, + { "R 0x18590320" }, + { "R 0x1859034c" }, + { "R 0x185903bc 2" }, + { "R 0x1859101c 2" }, + { "R 0x1859102c" }, + { "R 0x18591064 6" }, + { "R 0x1859108c" }, + { "R 0x185910dc" }, + { "R 0x185910e8 3" }, + { "R 0x18591300" }, + { "R 0x1859130c" }, + { "R 0x18591320" }, + { "R 0x1859134c" }, + { "R 0x185913bc 2" }, + { "R 0x1859201c 2" }, + { "R 0x1859202c" }, + { "R 0x18592064 6" }, + { "R 0x1859208c" }, + { "R 0x185920dc" }, + { "R 0x185920e8 3" }, + { "R 0x18592300" }, + { "R 0x1859230c" }, + { "R 0x18592320" }, + { "R 0x1859234c" }, + { "R 0x185923bc 2" }, + { "R 0x1859301c 2" }, + { "R 0x18593064 6" }, + { "R 0x1859308c" }, + { "R 0x185930dc" }, + { "R 0x185930e8 3" }, + { "R 0x18593300" }, + { "R 0x1859330c" }, + { "R 0x18593320" }, + { "R 0x1859302c" }, + { "R 0x1859334c" }, + { "R 0x185933bc 2" }, + { "R 0x18300000" }, + { "R 0x1830000c" }, + { "R 0x18300018" }, + { "R 0x17c21000 2" }, + { "R 0x18393a84 2" }, + { "R 0x183a3a84 2" }, + { "R 0x18280000 2" }, + { "R 0x18282000 2" }, + { "R 0x18284000 2" }, + { "R 0x18286000 2" }, + { "R 0x18300000" }, + { "R 0x18200400 3" }, + { "R 0x18200038" }, + { "R 0x18200040" }, + { "R 0x18200048" }, + { "R 0x18220038" }, + { "R 0x18220040" }, + { "R 0x182200d0" }, + { "R 0x18200030" }, + { "R 0x18200010" }, + /* pimem */ + { "R 0x610100 11" }, + /* core */ + { "R 0x18000058 4" }, + { "R 0x1800006c" }, + { "R 0x180000f0 2" }, + { "R 0x18010058 4" }, + { "R 0x1801006c" }, + { "R 0x180100f0 2" }, + { "R 0x18020058 4" }, + { "R 0x1802006c" }, + { "R 0x180200f0 2" }, + { "R 0x18030058 4" }, + { "R 0x1803006c" }, + { "R 0x180300f0 2" }, + { "R 0x18040058 4" }, + { "R 0x1804006c" }, + { "R 0x180400f0 2" }, + { "R 0x18050058 4" }, + { "R 0x1805006c" }, + { "R 0x180500f0 2" }, + { "R 0x18060058 4" }, + { "R 0x1806006c" }, + { "R 0x180600f0 2" }, + { "R 0x18070058 4" }, + { "R 0x1807006c" }, + { "R 0x180700f0 2" }, + { "R 0x18101908" }, + { "R 0x18101c18" }, + { "R 0x18390810" }, + { "R 0x18390c50" }, + { "R 0x18390814" }, + { "R 0x18390c54" }, + { "R 0x18390818" }, + { "R 0x18390c58" }, + { "R 0x18393a84 2" }, + { "R 0x18100908" }, + { "R 0x18100c18" }, + { "R 0x183a0810" }, + { "R 0x183a0c50" }, + { "R 0x183a0814" }, + { "R 0x183a0c54" }, + { "R 0x183a0818" }, + { "R 0x183a0c58" }, + { "R 0x183a3a84 2" }, + { "R 0x18393500" }, + { "R 0x18393580" }, + { "R 0x183a3500" }, + { "R 0x183a3580" }, + { "R 0x18282000 4" }, + { "R 0x18282028" }, + { "R 0x18282038" }, + { "R 0x18282080 5" }, + { "R 0x18286000 4" }, + { "R 0x18286028" }, + { "R 0x18286038" }, + { "R 0x18286080 5" }, + { "R 0xc201244" }, + { "R 0xc202244" }, + { "R 0x18300000" }, + { "R 0x1829208c" }, + { "R 0x18292098" }, + { "R 0x18292098" }, + { "R 0x1829608c" }, + { "R 0x18296098" }, + { "R 0x18296098" }, + { "R 0x784184" }, + /* gemnoc */ + { "R 0x9103008" }, + { "R 0x9103408" }, + { "R 0x9143008" }, + { "R 0x9143408" }, + { "R 0x91b0008" }, + { "R 0x91b1008" }, + { "R 0x9101808 2" }, + { "R 0x9141808 2" }, + { "R 0x91a8008 2" }, + { "R 0x91a8808 2" }, + { "R 0x9100000" }, + { "R 0x9100008 2" }, + { "R 0x9140000" }, + { "R 0x9140008 2" }, + { "R 0x9180000" }, + { "R 0x9180008 2" }, + { "R 0x9180404 3" }, + { "R 0x9181010" }, + { "R 0x9181020 8" }, + { "R 0x91e1048" }, + { "R 0x9121010" }, + { "R 0x9122010" }, + { "R 0x9123010" }, + { "R 0x9125010" }, + { "R 0x9161010" }, + { "R 0x9162010" }, + { "R 0x9163010" }, + { "R 0x9165010" }, + { "R 0x91cf010" }, + { "R 0x91d0010" }, + { "R 0x91d1010" }, + { "R 0x91d2010" }, + { "R 0x91d3010" }, + { "R 0x91d4010" }, + { "R 0x91d5010" }, + { "R 0x91d6010" }, + { "R 0x91d7010" }, + { "R 0x9101408" }, + { "R 0x9141410" }, + { "R 0x9100810" }, + { "R 0x9140810" }, + { "R 0x9100820" }, + { "R 0x9140820" }, + { "R 0x9100828 2" }, + { "R 0x9140828 2" }, + /* tsens */ + { "R 0xc222004" }, + { "R 0xc263014" }, + { "R 0xc2630e0" }, + { "R 0xc2630ec" }, + { "R 0xc2630a0 16" }, + { "R 0xc2630e8" }, + { "R 0xc26313c" }, + { "R 0xc223004" }, + { "R 0xc265014" }, + { "R 0xc2650e0" }, + { "R 0xc2650ec" }, + { "R 0xc2650a0 16" }, + { "R 0xc2650e8" }, + { "R 0xc26513c" }, + /* spmi */ + { "R 0xc410000" }, + { "R 0xc40af04" }, + { "R 0xc40af10" }, + { "R 0xc40a000" }, + { "R 0xc40a018" }, + { "R 0xc40a028 2" }, + { "R 0xc40a100" }, + { "R 0xc2a22fc 3" }, + { "R 0xc440200 2" }, + { "R 0xc442200 4" }, + /* gpu */ + { "R 0x3d9100c 3" }, + { "R 0x3d9106c 3" }, + { "R 0x3d91004" }, + { "R 0x3d91054 5" }, + { "R 0x3d91070 2" }, + { "R 0x3d91080 3" }, + { "R 0x3d91078 2" }, + { "R 0x3d9108c 2" }, + { "R 0x3d91098 2" }, + { "R 0x3d910a4 2" }, + { "R 0x3d910f0 2" }, + { "R 0x3d91100" }, + { "R 0x3d91118" }, + { "R 0x3d91164 2" }, + { "R 0x3d91170" }, + { "R 0x3d91178" }, + { "R 0x3d91204" }, + { "R 0x3d9120c" }, + { "R 0x3d98024" }, + { "R 0x3d9802c 2" }, + { "R 0x3d92000 2" }, + { "R 0x3d93000 2" }, + { "R 0x3d95000 2" }, + { "R 0x3d96000 2" }, + { "R 0x3d97000 2" }, + { "R 0x119000" }, + { "R 0x11903c" }, + { "R 0x171004 3" }, + { "R 0x171014 2" }, + { "R 0x171154 3" }, + { "R 0x17a04c" }, + { "R 0x17b000" }, + { "R 0x17b03c" }, + { "R 0x17c000" }, + { "R 0x17c03c" }, + { "R 0x17d000" }, + { "R 0x17d03c" }, + { "R 0x17e000" }, + { "R 0x17e03c" }, + { "R 0x187000" }, + { "R 0x18703c" }, + { "R 0x3d91534" }, + { "R 0x3d002b4" }, + { "R 0x3d00410 2" }, + { "R 0x3d00818" }, + { "R 0x3d7e220 2" }, + /* sysnoc */ + { "R 0x1680000" }, + { "R 0x1680008" }, + { "R 0x1680010" }, + { "R 0x1680020 8" }, + { "R 0x1680248" }, + { "R 0x1680b00 6" }, + /* aggrenoc */ + { "R 0x16e4008" }, + { "R 0x1706208" }, + { "R 0x16e0000" }, + { "R 0x16e0010" }, + { "R 0x16e0008" }, + { "R 0x16e0020 8" }, + { "R 0x16e5048" }, + { "R 0x16e5248" }, + { "R 0x16e5448" }, + { "R 0x16e5100 5" }, + { "R 0x16e5300 2" }, + { "R 0x16e5500 2" }, + { "R 0x1700000" }, + { "R 0x1700008" }, + { "R 0x1700010" }, + { "R 0x1700020 8" }, + { "R 0x170b100 5" }, + { "R 0x170b048" }, + /* gcc */ + { "R 0x100000 15" }, + { "R 0x101000 15" }, + { "R 0x176000 15" }, + { "R 0x174000 15" }, + { "R 0x113000 15" }, + { "R 0x11a000 15" }, + { "R 0x11c000 15" }, + { "R 0x11c048 3" }, + { "R 0x11e000 15" }, + { "R 0x10401c" }, + { "R 0x105074" }, + { "R 0x183024" }, + { "R 0x109050" }, + { "R 0x123020" }, + { "R 0x117024" }, + { "R 0x117154" }, + { "R 0x117284" }, + { "R 0x1173b4" }, + { "R 0x1174e4" }, + { "R 0x117614" }, + { "R 0x117744" }, + { "R 0x117874" }, + { "R 0x118024" }, + { "R 0x118154" }, + { "R 0x118284" }, + { "R 0x1183b4" }, + { "R 0x1184e4" }, + { "R 0x118614" }, + { "R 0x118744" }, + { "R 0x118874" }, + { "R 0x129020" }, + { "R 0x11d020" }, + { "R 0x134024" }, + { "R 0x141024" }, + { "R 0x14415c" }, + { "R 0x14504c" }, + { "R 0x18903c" }, + { "R 0x151000" }, + { "R 0x151008" }, + { "R 0x151010" }, + { "R 0x152000" }, + { "R 0x152008" }, + { "R 0x152010" }, + { "R 0x153020" }, + { "R 0x153028" }, + { "R 0x153030" }, + { "R 0x155000" }, + { "R 0x155008" }, + { "R 0x155010" }, + { "R 0x15b000" }, + { "R 0x15b008" }, + { "R 0x15b010" }, + { "R 0x157000" }, + { "R 0x157008" }, + { "R 0x157010" }, + { "R 0x135020" }, + { "R 0x135028" }, + { "R 0x135030" }, + { "R 0x156000" }, + { "R 0x156008" }, + { "R 0x156010" }, + { "R 0x15a000" }, + { "R 0x15a008" }, + { "R 0x15a010" }, + { "R 0x190004" }, + { "R 0x109008" }, + { "R 0x190010" }, + { "R 0x190020" }, + { "R 0x190028" }, + { "R 0x109010" }, + { "R 0x109018" }, + { "R 0x109018" }, + { "R 0x109020" }, + { "R 0x18d080" }, + { "R 0x145014" }, + { "R 0x14501c" }, + { "R 0x183004 2" }, + { "R 0x183140" }, + { "R 0x171158 2" }, + { "R 0x109004 3" }, + { "R 0x109160" }, + { "R 0x109468" }, + { "R 0x10f004 3" }, + { "R 0x145000 3" }, + { "R 0x16b004 3" }, + { "R 0x18d004 3" }, + { "R 0x177004 3" }, + { "R 0x189004 3" }, + { "R 0x153000 9" }, + { "R 0x135000 9" }, + { "R 0x106100" }, + { "R 0x147004" }, + { "R 0x17b000 12" }, + { "R 0x17b03c 12" }, + { "R 0x17c000 12" }, + { "R 0x17c03c 12" }, + { "R 0x153124" }, + { "R 0x156124" }, + { "R 0x1453a4" }, + { "R 0x182884" }, + { "R 0x145384" }, + { "R 0xc2a0000 15" }, + { "R 0xc2a1000 15" }, + { "R 0x17101c 2" }, + { "R 0x14401c 2" }, + { "R 0x183010 2" }, + { "R 0x18a160 2" }, + { "R 0x18a004" }, + { "R 0x18a01c 3" }, + { "R 0x19d004 2" }, + { "R 0x196100" }, + { "R 0x10003c" }, + { "R 0x10103c" }, + { "R 0x10203c" }, + { "R 0x10303c" }, + { "R 0x11303c" }, + { "R 0x11a03c" }, + { "R 0x11c03c" }, + { "R 0x17403c" }, + { "R 0x17603c" }, + { "R 0x11e03c" }, + { "R 0xbbf0004 12" }, + { "R 0xbbf0800 12" }, + { "R 0xbbf0004 12" }, + { "R 0xbbf0800 12" }, +}; + +static const struct dcc_register_entry kodiak_dcc_entries_ll4[] = { + /* confignoc */ + { "R 0x1510008" }, + { "R 0x151d208" }, + { "R 0x1507008" }, + { "R 0x151d308" }, + { "R 0x1509008" }, + { "R 0x1514008" }, + { "R 0x1500000" }, + { "R 0x1500010" }, + { "R 0x1510010" }, + { "R 0x1500020 8" }, + { "R 0x1510020 8" }, + { "R 0x1511048" }, + { "R 0x1501048 2" }, + { "R 0x1501058" }, + { "R 0x1501248" }, + { "R 0x1511248" }, + { "R 0x1501248" }, + { "R 0x1511b00" }, + { "R 0x151e100" }, + { "R 0x150b100" }, + /* limits */ + { "R 0xec80004" }, + { "R 0xec80058" }, + { "R 0xec80060 8" }, + { "R 0xec800a0 40" }, + { "R 0x634008" }, + { "R 0x634f00 8" }, + { "R 0x635560" }, + { "R 0x635570" }, + { "R 0x635580" }, + { "R 0x635590" }, + { "R 0x6355a0 4" }, + { "R 0x635600" }, + { "R 0x635610" }, + { "R 0x636008" }, + { "R 0x636f00 8" }, + { "R 0x637560" }, + { "R 0x637570" }, + { "R 0x637580" }, + { "R 0x637590" }, + { "R 0x6375a0 4" }, + { "R 0x637600" }, + { "R 0x637610" }, + { "R 0x18370220 2" }, + { "R 0x183702a0 2" }, + { "R 0x183704a0 12" }, + { "R 0x18370520" }, + { "R 0x18370588" }, + { "R 0x18370d10 12" }, + { "R 0x18370f90 10" }, + { "R 0x18371010 10" }, + { "R 0x18371a10 8" }, + { "R 0x183784a0 12" }, + { "R 0x18378520" }, + { "R 0x18378588" }, + { "R 0x18378d10 8" }, + { "R 0x18378f90 6" }, + { "R 0x18379010 6" }, + { "R 0x18379a10 4" }, + { "R 0xa310220 3" }, + { "R 0xa3102a0 3" }, + { "R 0xa3104a0 6" }, + { "R 0xa310520" }, + { "R 0xa310588" }, + { "R 0xa310d10 8" }, + { "R 0xa310f90 6" }, + { "R 0xa311010 6" }, + { "R 0xa311a10 3" }, + /* gic */ + { "R 0x17a00104 29" }, + { "R 0x17a00204 29" }, + /* mmssnoc */ + { "R 0x1741008" }, + { "R 0x1740000" }, + { "R 0x1740008" }, + { "R 0x1740010" }, + { "R 0x1740020 8" }, + { "R 0x174b048" }, + { "R 0x174b100 8" }, + { "R 0x90e0000" }, + { "R 0x90e0008" }, + { "R 0x90e0010" }, + { "R 0x90e0020 8" }, + { "R 0x90e0248" }, + { "R 0x90e3100" }, + { "R 0x90e4100 7" }, + { "R 0x1750010" }, + { "R 0x1750190" }, + { "R 0x1751010" }, + { "R 0x1752010" }, + { "R 0x1754010" }, + { "R 0x1755010" }, + { "R 0x1756010" }, + { "R 0x1758010" }, + { "R 0x1758090" }, + { "R 0x1759010" }, + { "R 0x175a010" }, + { "R 0x175c010" }, + { "R 0x175d010" }, + { "R 0x175e010" }, + /* apps_rsc */ + { "R 0xb201020 2" }, + { "R 0xb200010 4" }, + { "R 0xb220010 4" }, + { "R 0xb200900 4" }, + { "R 0xb220900 4" }, + { "R 0xb201030" }, + { "R 0xb201204" }, + { "R 0xb201218" }, + { "R 0xb20122c" }, + { "R 0xb201240" }, + { "R 0xb201254" }, + { "R 0xb201208" }, + { "R 0xb20121c" }, + { "R 0xb201230" }, + { "R 0xb201244" }, + { "R 0xb201258" }, + { "R 0xb204510 2" }, + { "R 0xb204520" }, + { "R 0xb211024" }, + { "R 0xb221024" }, + { "R 0xb231024" }, + { "R 0x18220010" }, + { "R 0x18220030" }, + { "R 0x182200d0" }, + { "R 0x18220408" }, + { "R 0x18230408" }, + /* misc */ + { "R 0x17e00434" }, + { "R 0x17e0043c 2" }, + { "R 0x17c00038 2" }, + { "R 0x17c00438" }, + { "R 0x17e0041c 2" }, + { "R 0x17e00404" }, + { "R 0xc220000 2" }, + { "R 0xc230000 6" }, + { "R 0xc260008" }, + { "R 0x18598014" }, + { "R 0x4d8634" }, + { "R 0x4d8834" }, + { "R 0x418620" }, + { "R 0x418820" }, + /* ddr */ + { "R 0x9084208" }, + { "R 0x9084204" }, + { "R 0x9084108" }, + { "R 0x90841c0" }, + { "R 0x10c034 2" }, + { "R 0x144018" }, + { "R 0x9050078" }, + { "R 0x9050110 8" }, + { "R 0x9080058 2" }, + { "R 0x90800c8" }, + { "R 0x90800d4" }, + { "R 0x90800e0" }, + { "R 0x90800fc" }, + { "R 0x9084030" }, + { "R 0x9084038 2" }, + { "R 0x90840e4" }, + { "R 0x90840f4" }, + { "R 0x9084104 2" }, + { "R 0x9084198" }, + { "R 0x9084804" }, + { "R 0x908480c" }, + { "R 0x9084844" }, + { "R 0x9084850 2" }, + { "R 0x9084860 3" }, + { "R 0x9084888 2" }, + { "R 0x908409c 2" }, + { "R 0x908426c" }, + { "R 0x908439c" }, + { "R 0x9085124" }, + { "R 0x9085134 2" }, + { "R 0x9084840" }, + { "R 0x9084834" }, + { "R 0x9085124" }, + { "R 0x90ba280" }, + { "R 0x90ba288 7" }, + { "R 0x9258610 4" }, + { "R 0x92d8610 4" }, + { "R 0x9220344 8" }, + { "R 0x9220370 6" }, + { "R 0x9220480" }, + { "R 0x9222400" }, + { "R 0x922240c" }, + { "R 0x9223214 2" }, + { "R 0x9223220 3" }, + { "R 0x9223308" }, + { "R 0x9223318" }, + { "R 0x9232100" }, + { "R 0x9236040 6" }, + { "R 0x92360b0" }, + { "R 0x923a004 4" }, + { "R 0x923e030 2" }, + { "R 0x9241000" }, + { "R 0x9242028" }, + { "R 0x9242044 3" }, + { "R 0x9242070" }, + { "R 0x9248030" }, + { "R 0x9248048 8" }, + { "R 0x9238030" }, + { "R 0x9238060 2" }, + { "R 0x9238074" }, + { "R 0x9238088" }, + { "R 0x92380a0" }, + { "R 0x92380b0" }, + { "R 0x92a0344 8" }, + { "R 0x92a0370 6" }, + { "R 0x92a0480" }, + { "R 0x92a2400" }, + { "R 0x92a240c" }, + { "R 0x92a3214 2" }, + { "R 0x92a3220 3" }, + { "R 0x92a3308" }, + { "R 0x92a3318" }, + { "R 0x92b2100" }, + { "R 0x92b6040 6" }, + { "R 0x92b60b0" }, + { "R 0x92ba004 4" }, + { "R 0x92be030 2" }, + { "R 0x92c1000" }, + { "R 0x92c2028" }, + { "R 0x92c2044 3" }, + { "R 0x92c2070" }, + { "R 0x92c8030" }, + { "R 0x92c8048 8" }, + { "R 0x92b8030" }, + { "R 0x92b8060 2" }, + { "R 0x92b8074" }, + { "R 0x92b8088" }, + { "R 0x92b80a0" }, + { "R 0x92b80b0" }, + { "R 0x92c8064" }, + { "R 0x9270080" }, + { "R 0x9270310" }, + { "R 0x9270400" }, + { "R 0x9270410 6" }, + { "R 0x9270430" }, + { "R 0x9270440" }, + { "R 0x9270448" }, + { "R 0x92704a0" }, + { "R 0x92704b0" }, + { "R 0x92704b8 2" }, + { "R 0x92704d0 2" }, + { "R 0x9271400" }, + { "R 0x9271408" }, + { "R 0x927341c 2" }, + { "R 0x92753b0" }, + { "R 0x9275804" }, + { "R 0x9275c18 2" }, + { "R 0x9275c2c" }, + { "R 0x9275c38" }, + { "R 0x9276418 2" }, + { "R 0x9279100" }, + { "R 0x9279110" }, + { "R 0x9279120" }, + { "R 0x9279180 2" }, + { "R 0x92f0080" }, + { "R 0x92f0310" }, + { "R 0x92f0400" }, + { "R 0x92f0410 6" }, + { "R 0x92f0430" }, + { "R 0x92f0440" }, + { "R 0x92f0448" }, + { "R 0x92f04a0" }, + { "R 0x92f04b0" }, + { "R 0x92f04b8 2" }, + { "R 0x92f04d0 2" }, + { "R 0x92f1400" }, + { "R 0x92f1408" }, + { "R 0x92f341c 2" }, + { "R 0x92f53b0" }, + { "R 0x92f5804" }, + { "R 0x92f5c18 2" }, + { "R 0x92f5c2c" }, + { "R 0x92f5c38" }, + { "R 0x92f6418 2" }, + { "R 0x92f9100" }, + { "R 0x92f9110" }, + { "R 0x92f9120" }, + { "R 0x92f9180 2" }, + { "R 0x9260080" }, + { "R 0x9260400" }, + { "R 0x9260410 3" }, + { "R 0x9260420 2" }, + { "R 0x9260430" }, + { "R 0x9260440" }, + { "R 0x9260448" }, + { "R 0x92604a0" }, + { "R 0x92604b0" }, + { "R 0x92604b8 2" }, + { "R 0x92604d0 2" }, + { "R 0x9261400" }, + { "R 0x9263410" }, + { "R 0x92653b0" }, + { "R 0x9265804" }, + { "R 0x9265b1c" }, + { "R 0x9265b2c" }, + { "R 0x9265b38" }, + { "R 0x9269100" }, + { "R 0x9269108" }, + { "R 0x9269110" }, + { "R 0x9269118" }, + { "R 0x9269120" }, + { "R 0x9269180 2" }, + { "R 0x92e0080" }, + { "R 0x92e0400" }, + { "R 0x92e0410 3" }, + { "R 0x92e0420 2" }, + { "R 0x92e0430" }, + { "R 0x92e0440" }, + { "R 0x92e0448" }, + { "R 0x92e04a0" }, + { "R 0x92e04b0" }, + { "R 0x92e04b8 2" }, + { "R 0x92e04d0 2" }, + { "R 0x92e1400" }, + { "R 0x92e3410" }, + { "R 0x92e53b0" }, + { "R 0x92e5804" }, + { "R 0x92e5b1c" }, + { "R 0x92e5b2c" }, + { "R 0x92e5b38" }, + { "R 0x92e9100" }, + { "R 0x92e9108" }, + { "R 0x92e9110" }, + { "R 0x92e9118" }, + { "R 0x92e9120" }, + { "R 0x92e9180 2" }, + { "R 0x96b0868" }, + { "R 0x96b0870" }, + { "R 0x96b1004" }, + { "R 0x96b100c" }, + { "R 0x96b1014" }, + { "R 0x96b1204" }, + { "R 0x96b120c" }, + { "R 0x96b1214" }, + { "R 0x96b1504" }, + { "R 0x96b150c" }, + { "R 0x96b1514" }, + { "R 0x96b1604" }, + { "R 0x96b8100" }, + { "R 0x96b813c" }, + { "R 0x96b8500" }, + { "R 0x96b853c" }, + { "R 0x96b8a04" }, + { "R 0x96b8a18" }, + { "R 0x96b8ea8" }, + { "R 0x96b9044" }, + { "R 0x96b904c" }, + { "R 0x96b9054" }, + { "R 0x96b905c" }, + { "R 0x96b910c 2" }, + { "R 0x96b9204" }, + { "R 0x96b920c" }, + { "R 0x96b9238" }, + { "R 0x96b9240" }, + { "R 0x96b926c" }, + { "R 0x96b9394" }, + { "R 0x96b939c" }, + { "R 0x96b9704" }, + { "R 0x96b970c" }, + { "R 0x96f0868" }, + { "R 0x96f0870" }, + { "R 0x96f1004" }, + { "R 0x96f100c" }, + { "R 0x96f1014" }, + { "R 0x96f1204" }, + { "R 0x96f120c" }, + { "R 0x96f1214" }, + { "R 0x96f1504" }, + { "R 0x96f150c" }, + { "R 0x96f1514" }, + { "R 0x96f1604" }, + { "R 0x96f8100" }, + { "R 0x96f813c" }, + { "R 0x96f8500" }, + { "R 0x96f853c" }, + { "R 0x96f8a04" }, + { "R 0x96f8a18" }, + { "R 0x96f8ea8" }, + { "R 0x96f9044" }, + { "R 0x96f904c" }, + { "R 0x96f9054" }, + { "R 0x96f905c" }, + { "R 0x96f910c 2" }, + { "R 0x96f9204" }, + { "R 0x96f920c" }, + { "R 0x96f9238" }, + { "R 0x96f9240" }, + { "R 0x96f926c" }, + { "R 0x96f9394" }, + { "R 0x96f939c" }, + { "R 0x96f9704" }, + { "R 0x96f970c" }, + { "R 0x9130100 3" }, + { "R 0x9170100 3" }, + { "R 0x91dd100 4" }, + { "R 0x91df100" }, + { "R 0x610110 5" }, + { "R 0x9230010" }, + { "R 0x9230020" }, + { "R 0x9230030" }, + { "R 0x9230040" }, + { "R 0x92b0010" }, + { "R 0x92b0020" }, + { "R 0x92b0030" }, + { "R 0x92b0040" }, + { "R 0x9232050" }, + { "R 0x923605c 2" }, + { "R 0x92360a0" }, + { "R 0x923a018 2" }, + { "R 0x92b2050" }, + { "R 0x92b605c 2" }, + { "R 0x92b60a0" }, + { "R 0x92ba018 2" }, + { "R 0x9222404 2" }, + { "R 0x9222410" }, + { "R 0x9238004" }, + { "R 0x9238014" }, + { "R 0x923805c" }, + { "R 0x923a014" }, + { "R 0x92a2404 2" }, + { "R 0x92a2410" }, + { "R 0x92b8004" }, + { "R 0x92b8014" }, + { "R 0x92b805c" }, + { "R 0x92ba014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x6e0a014" }, + { "R 0x9067e00 124" }, + { "R 0x905000c" }, + { "R 0x9050948" }, + { "R 0x9050078" }, + { "R 0x9050008" }, +}; + +static const struct dcc_register_entry kodiak_dcc_entries_ll3[] = { + /* lpass_rsc */ + { "R 0xb254520" }, + { "R 0xb251020 2" }, + { "R 0xb251030" }, + { "R 0xb251200" }, + { "R 0xb251214" }, + { "R 0xb251228" }, + { "R 0xb25123c" }, + { "R 0xb251250" }, + { "R 0xb251204" }, + { "R 0xb251218" }, + { "R 0xb25122c" }, + { "R 0xb251240" }, + { "R 0xb251254" }, + { "R 0xb251208" }, + { "R 0xb25121c" }, + { "R 0xb251230" }, + { "R 0xb251244" }, + { "R 0xb251258" }, + { "R 0xb254510 2" }, + { "R 0xb250010 2" }, + { "R 0xb250900 2" }, + { "R 0x3500010 3" }, + { "R 0x3500030" }, + { "R 0x3500038" }, + { "R 0x3500040" }, + { "R 0x3500048" }, + { "R 0x35000d0" }, + { "R 0x3500210" }, + { "R 0x3500230" }, + { "R 0x3500250" }, + { "R 0x3500270" }, + { "R 0x3500290" }, + { "R 0x35002b0" }, + { "R 0x3500208" }, + { "R 0x3500228" }, + { "R 0x3500248" }, + { "R 0x3500268" }, + { "R 0x3500288" }, + { "R 0x35002a8" }, + { "R 0x350020c" }, + { "R 0x350022c" }, + { "R 0x350024c" }, + { "R 0x350026c" }, + { "R 0x350028c" }, + { "R 0x35002ac" }, + { "R 0x3500400 3" }, + { "R 0x3500d04" }, + { "R 0x30b0010 3" }, + { "R 0x30b0210" }, + { "R 0x30b0230" }, + { "R 0x30b0250" }, + { "R 0x30b0270" }, + { "R 0x30b0290" }, + { "R 0x30b02b0" }, + { "R 0x30b0208" }, + { "R 0x30b0228" }, + { "R 0x30b0248" }, + { "R 0x30b0268" }, + { "R 0x30b0288" }, + { "R 0x30b02a8" }, + { "R 0x30b020c" }, + { "R 0x30b022c" }, + { "R 0x30b024c" }, + { "R 0x30b026c" }, + { "R 0x30b028c" }, + { "R 0x30b02ac" }, + { "R 0x30b0400 3" }, + /* nsp_rsc */ + { "R 0xb2b4520" }, + { "R 0xb2b1020 2" }, + { "R 0xb2b1030" }, + { "R 0xb2b1200" }, + { "R 0xb2b1214" }, + { "R 0xb2b1228" }, + { "R 0xb2b123c" }, + { "R 0xb2b1250" }, + { "R 0xb2b1204" }, + { "R 0xb2b1218" }, + { "R 0xb2b122c" }, + { "R 0xb2b1240" }, + { "R 0xb2b1254" }, + { "R 0xb2b1208" }, + { "R 0xb2b121c" }, + { "R 0xb2b1230" }, + { "R 0xb2b1244" }, + { "R 0xb2b1258" }, + { "R 0xb2b4510 2" }, + { "R 0xb2b0010" }, + { "R 0xb2b0900" }, + { "R 0xa302028" }, + { "R 0xa0a4010 3" }, + { "R 0xa0a4030" }, + { "R 0xa0a4038" }, + { "R 0xa0a4040 2" }, + { "R 0xa0a40d0" }, + { "R 0xa0a4210" }, + { "R 0xa0a4230" }, + { "R 0xa0a4250" }, + { "R 0xa0a4270" }, + { "R 0xa0a4290" }, + { "R 0xa0a42b0" }, + { "R 0xa0a4208" }, + { "R 0xa0a4228" }, + { "R 0xa0a4248" }, + { "R 0xa0a4268" }, + { "R 0xa0a4288" }, + { "R 0xa0a42a8" }, + { "R 0xa0a420c" }, + { "R 0xa0a422c" }, + { "R 0xa0a424c" }, + { "R 0xa0a426c" }, + { "R 0xa0a428c" }, + { "R 0xa0a42ac" }, + { "R 0xa0a4400 2" }, + { "R 0xa0a4d04" }, + { "R 0xa3b0010 3" }, + { "R 0xa3b0210" }, + { "R 0xa3b0230" }, + { "R 0xa3b0250" }, + { "R 0xa3b0270" }, + { "R 0xa3b0290" }, + { "R 0xa3b02b0" }, + { "R 0xa3b0208" }, + { "R 0xa3b0228" }, + { "R 0xa3b0248" }, + { "R 0xa3b0268" }, + { "R 0xa3b0288" }, + { "R 0xa3b02a8" }, + { "R 0xa3b020c" }, + { "R 0xa3b022c" }, + { "R 0xa3b024c" }, + { "R 0xa3b026c" }, + { "R 0xa3b028c" }, + { "R 0xa3b02ac" }, + { "R 0xa3b0400 3" }, + /* sdi_debug */ + { "R 0x10413c" }, + { "R 0x105024" }, + { "R 0x108008" }, + { "R 0x108004" }, + { "R 0x10500c" }, + { "R 0x105658" }, + { "R 0x105640 2" }, + { "R 0x105010" }, + { "R 0x10500c" }, + { "R 0x105024" }, + /* lpass_cdsp_tunning */ + { "R 0x3500d00 3" }, + { "R 0x3500d10 4" }, + { "R 0x3500fb0 4" }, + { "R 0x3501250 4" }, + { "R 0x35014f0 4" }, + { "R 0x3501790 4" }, + { "R 0x3501a30 4" }, + { "R 0x3503d44 4" }, + { "R 0x35000d0 3" }, + { "R 0x3500100" }, + { "R 0x3500d3c" }, + { "R 0xa0a40d0 3" }, + { "R 0xa0a4100" }, + { "R 0xa0a4d3c" }, + { "R 0xa0a7d44 4" }, + { "R 0xa0a4d00 3" }, + /* wpss_rsc */ + { "R 0x8a02028" }, + { "R 0x8b00000 2" }, + { "R 0x8b00010 15" }, + { "R 0x8b000d0" }, + { "R 0x8b000d8" }, + { "R 0x8b00100 3" }, + { "R 0x8b00200 2" }, + { "R 0x8b00224" }, + { "R 0x8b00244" }, + { "R 0x8b00264" }, + { "R 0x8b00284" }, + { "R 0x8b002a4" }, + { "R 0x8b00208" }, + { "R 0x8b00228" }, + { "R 0x8b00248" }, + { "R 0x8b00268" }, + { "R 0x8b00288" }, + { "R 0x8b002a8" }, + { "R 0x8b0020c" }, + { "R 0x8b0022c" }, + { "R 0x8b0024c" }, + { "R 0x8b0026c" }, + { "R 0x8b0028c" }, + { "R 0x8b002ac" }, + { "R 0x8b00210" }, + { "R 0x8b00230" }, + { "R 0x8b00250" }, + { "R 0x8b00270" }, + { "R 0x8b00290" }, + { "R 0x8b002b0" }, + { "R 0x8b00400 3" }, + { "R 0x8b00460 2" }, + { "R 0x8b004a0 7" }, + { "R 0x8ab0000 2" }, + { "R 0x8ab0010 3" }, + { "R 0x8ab00d0" }, + { "R 0x8ab00d8" }, + { "R 0x8ab0100 3" }, + { "R 0x8ab0200 2" }, + { "R 0x8ab0224" }, + { "R 0x8ab0244" }, + { "R 0x8ab0264" }, + { "R 0x8ab0284" }, + { "R 0x8ab02a4" }, + { "R 0x8ab0208" }, + { "R 0x8ab0228" }, + { "R 0x8ab0248" }, + { "R 0x8ab0268" }, + { "R 0x8ab0288" }, + { "R 0x8ab02a8" }, + { "R 0x8ab020c" }, + { "R 0x8ab022c" }, + { "R 0x8ab024c" }, + { "R 0x8ab026c" }, + { "R 0x8ab028c" }, + { "R 0x8ab02ac" }, + { "R 0x8ab0210" }, + { "R 0x8ab0230" }, + { "R 0x8ab0250" }, + { "R 0x8ab0270" }, + { "R 0x8ab0290" }, + { "R 0x8ab02b0" }, + { "R 0x8ab0400 3" }, + { "R 0x8ab0460 2" }, + { "R 0x8ab04a0 7" }, + /* video_noc */ + { "R 0xaa10504 2" }, + { "R 0xaa10510" }, + { "R 0xaa10520 8" }, + { "R 0xaa10300" }, + { "R 0xaa10010" }, + { "R 0xaa10020" }, +}; + +static const struct dcc_link_config kodiak_link_configs[] = { + { + .link_list = 6, + .entries = kodiak_dcc_entries_ll6, + .num_entries = ARRAY_SIZE(kodiak_dcc_entries_ll6), + }, + { + .link_list = 4, + .entries = kodiak_dcc_entries_ll4, + .num_entries = ARRAY_SIZE(kodiak_dcc_entries_ll4), + }, + { + .link_list = 3, + .entries = kodiak_dcc_entries_ll3, + .num_entries = ARRAY_SIZE(kodiak_dcc_entries_ll3), + }, +}; + +static const struct dcc_config kodiak_config = { + .lists = kodiak_link_configs, + .num_lists = ARRAY_SIZE(kodiak_link_configs), +}; + +static const struct dcc_pdata kodiak_pdata = { + .base = 0x0117f000, + .size = 0x00001000, + .ram_base = 0x01112000, + .ram_size = 0x00006000, + .dcc_offset = 0x12000, + .map_ver = 0x2, + .config = &kodiak_config, +}; + +#endif /* _QCOM_DCC_KODIAK_CONFIG_H */ From ac3330d945423ddd9ef225062f8db35ca2971d21 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 29 Apr 2026 14:12:34 +0800 Subject: [PATCH 0059/1133] QCLINUX: qcom-dcc: add pakala register list and move config to header Add the DCC register capture list for the Pakala platform. The registers are distributed across two linked lists: - Link list 6: 910 entries - Link list 4: 212 entries Estimated SRAM usage is ~15 KB, within the 16 KB (0x4000) budget. Move the pakala DCC configuration (entries arrays, link configs, dcc config, and pdata) into a dedicated header qcom-dcc-pakala-config.h, consistent with the approach used for other platforms. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 10 +- drivers/misc/qcom-dcc-pakala-config.h | 1167 +++++++++++++++++++++++++ 2 files changed, 1168 insertions(+), 9 deletions(-) create mode 100644 drivers/misc/qcom-dcc-pakala-config.h diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index cd8bad68a6077..a77b5bc144982 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -10,20 +10,12 @@ #include "qcom-dcc-talos-config.h" #include "qcom-dcc-lemans-config.h" #include "qcom-dcc-kodiak-config.h" +#include "qcom-dcc-pakala-config.h" #define DEV_NAME "qcom-dcc" static struct platform_device *dcc_pdev; -static const struct dcc_pdata pakala_pdata = { - .base = 0x100ff000, - .size = 0x00001000, - .ram_base = 0x10084000, - .ram_size = 0x4000, - .dcc_offset = 0x4000, - .map_ver = 0x3, -}; - static const struct dcc_pdata kaanapali_pdata = { .base = 0x100ff000, .size = 0x1000, diff --git a/drivers/misc/qcom-dcc-pakala-config.h b/drivers/misc/qcom-dcc-pakala-config.h new file mode 100644 index 0000000000000..25e6221805d27 --- /dev/null +++ b/drivers/misc/qcom-dcc-pakala-config.h @@ -0,0 +1,1167 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_PAKALA_CONFIG_H +#define _QCOM_DCC_PAKALA_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry pakala_dcc_entries_ll6[] = { + { "R 0x16801000 2" }, + { "R 0x18880258 10" }, + { "R 0x18880288 6" }, + { "R 0x188802a8 10" }, + { "R 0x18880328 6" }, + { "R 0x188803d8 10" }, + { "R 0x18880408 2" }, + { "R 0x19880258 10" }, + { "R 0x19880288 6" }, + { "R 0x198802a8 10" }, + { "R 0x19880328 6" }, + { "R 0x198803d8 10" }, + { "R 0x19880408 2" }, + { "R 0x188b0000 4" }, + { "R 0x188b0050 2" }, + { "R 0x188b00e8 36" }, + { "R 0x188b0788 2" }, + { "R 0x188b0c18 2" }, + { "R 0x198b0000 4" }, + { "R 0x198b0050 2" }, + { "R 0x198b00e8 36" }, + { "R 0x198b0788 2" }, + { "R 0x198b0c18 2" }, + { "R 0x17988814 2" }, + { "R 0x17998814 2" }, + { "R 0x179d2000 3" }, + { "R 0x179d2020 3" }, + { "R 0x179d2040 2" }, + { "R 0x179d2060 2" }, + { "R 0x179d2080 2" }, + { "R 0x179d20a0" }, + { "R 0x179d20b0" }, + { "R 0x179d20c0" }, + { "R 0x179d2200 2" }, + { "R 0x179d2220 2" }, + { "R 0x179d2280 2" }, + { "R 0x179d22f0" }, + { "R 0x179d2304" }, + { "R 0x179d2310" }, + { "R 0x179d2400 4" }, + { "R 0x179d2420" }, + { "R 0x179d2428 2" }, + { "R 0x179d2440 2" }, + { "R 0x179d2520 2" }, + { "R 0x179d2600 2" }, + { "R 0x179d2710 2" }, + { "R 0x179d2720 2" }, + { "R 0x179d2740 2" }, + { "R 0x179d3080 2" }, + { "R 0x17846018 2" }, + { "R 0x17846060" }, + { "R 0x17846100 2" }, + { "R 0x17846110" }, + { "R 0x17847030 2" }, + { "R 0x17847040 2" }, + { "R 0x17847050 2" }, + { "R 0x17847060 2" }, + { "R 0x17847070 2" }, + { "R 0x17847080 2" }, + { "R 0x17847090 2" }, + { "R 0x178470a0 2" }, + { "R 0x178470b0 2" }, + { "R 0x178470c0 2" }, + { "R 0x17850000 2" }, + { "R 0x17850010 2" }, + { "R 0x17850030 2" }, + { "R 0x17850040" }, + { "R 0x17854000" }, + { "R 0x17854008 4" }, + { "R 0x179c8814 2" }, + { "R 0x179d0104" }, + { "R 0x179d0118 2" }, + { "R 0x179d0148 2" }, + { "R 0x179d1600" }, + { "R 0x179d1678" }, + { "R 0x179d1688 2" }, + { "R 0x179d1694 3" }, + { "R 0x179d1820 3" }, + { "R 0x17b70000" }, + { "R 0x17b70008 2" }, + { "R 0x17b71000" }, + { "R 0x17b71008 2" }, + { "R 0x164807f8" }, + { "R 0x16480810 3" }, + { "R 0x16483000 40" }, + { "R 0x16483a00 2" }, + { "R 0x16488908" }, + { "R 0x16488c18" }, + { "R 0x164a8908" }, + { "R 0x164a8c18" }, + { "R 0x164a07f8" }, + { "R 0x164a0810 3" }, + { "R 0x164a3000 40" }, + { "R 0x164a3a00 2" }, + { "R 0x16493000 40" }, + { "R 0x16493a00 2" }, + { "R 0x16498c18" }, + { "R 0x164b8c18" }, + { "R 0x164b3a00 2" }, + { "R 0x16440000 2" }, + { "R 0x16440020 3" }, + { "R 0x16440030" }, + { "R 0x1644003c" }, + { "R 0x16440044 3" }, + { "R 0x16440438" }, + { "R 0x16440500 5" }, + { "R 0x16562000 2" }, + { "R 0x16565004" }, + { "R 0x17000bd0" }, + { "R 0x170404a0" }, + { "R 0x170a0590" }, + { "R 0x170c0330" }, + { "R 0x170c0338" }, + { "R 0x170c0340" }, + { "R 0x170c0518" }, + { "R 0x170c0528" }, + { "R 0x170c0538" }, + { "R 0x170c0560 4" }, + { "R 0x17200bd0" }, + { "R 0x172404a0" }, + { "R 0x172a0590" }, + { "R 0x172c0330" }, + { "R 0x172c0338" }, + { "R 0x172c0340" }, + { "R 0x172c0518" }, + { "R 0x172c0528" }, + { "R 0x172c0538" }, + { "R 0x172c0560 4" }, + { "R 0x1641000c" }, + { "R 0x1641400c" }, + { "R 0x18830320 2" }, + { "R 0x19830320 2" }, + { "R 0x18040010 6" }, + { "R 0x18040040 10" }, + { "R 0x18040090 6" }, + { "R 0x18850020 2" }, + { "R 0x18850060 2" }, + { "R 0x188500a0 2" }, + { "R 0x188500e0 2" }, + { "R 0x18850120 2" }, + { "R 0x18850160 2" }, + { "R 0x189c1000" }, + { "R 0x199c1000" }, + { "R 0x18a30000 9" }, + { "R 0x18a30030" }, + { "R 0x18a3003c 2" }, + { "R 0x19a30000 9" }, + { "R 0x19a30030" }, + { "R 0x19a3003c 2" }, + { "R 0x24201040" }, + { "R 0x24201048" }, + { "R 0x24100010" }, + { "R 0x24100020 6" }, + { "R 0x24180010" }, + { "R 0x24180020 6" }, + { "R 0x24200010" }, + { "R 0x24200020 6" }, + { "R 0x24200410" }, + { "R 0x24200420 6" }, + { "R 0x24102010" }, + { "R 0x24102038" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 3" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 3" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 3" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102008 2" }, + { "R 0x24181010" }, + { "R 0x24181038" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 3" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 3" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 3" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181008 2" }, + { "R 0x24203010" }, + { "R 0x24203038" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 3" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 3" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 3" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203030 2" }, + { "R 0x24203008 2" }, + { "R 0x24203410" }, + { "R 0x24203438" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 3" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 3" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 3" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203430 2" }, + { "R 0x24203408 2" }, + { "R 0x24104018" }, + { "R 0x24104008" }, + { "R 0x24104010 2" }, + { "R 0x24104010 2" }, + { "R 0x24104010 2" }, + { "R 0x24104010 2" }, + { "R 0x24104098" }, + { "R 0x24104088" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24104090 2" }, + { "R 0x24182018" }, + { "R 0x24182008" }, + { "R 0x24182010 2" }, + { "R 0x24182010 2" }, + { "R 0x24182010 2" }, + { "R 0x24182010 2" }, + { "R 0x24182098" }, + { "R 0x24182088" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24182090 2" }, + { "R 0x24204018" }, + { "R 0x24204008" }, + { "R 0x24204010 2" }, + { "R 0x24204010 2" }, + { "R 0x24204010 2" }, + { "R 0x24204098" }, + { "R 0x24204088" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24204090 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24102030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x24181030 2" }, + { "R 0x16801000 2" }, + { "R 0x240ba050" }, + { "R 0x240ba164" }, + { "R 0x240ba280" }, + { "R 0x240ba288 8" }, + { "R 0x240ba2c0 2" }, + { "R 0x24bc0610 11" }, + { "R 0x24bc0640 2" }, + { "R 0x24bc06a0" }, + { "R 0x24fc0610 11" }, + { "R 0x24fc0640 2" }, + { "R 0x24fc06a0" }, + { "R 0x25bc0610 11" }, + { "R 0x25bc0640 2" }, + { "R 0x25bc06a0" }, + { "R 0x25fc0610 11" }, + { "R 0x25fc0640 2" }, + { "R 0x25fc06a0" }, + { "R 0x240a801c 2" }, + { "R 0x240a8038 3" }, + { "R 0x240a8058 5" }, + { "R 0x240a8074 4" }, + { "R 0x240a80a8" }, + { "R 0x240a80b8" }, + { "R 0x240a80ec 5" }, + { "R 0x240a8140" }, + { "R 0x240a8164 2" }, + { "R 0x240a81c4 2" }, + { "R 0x240a81dc 2" }, + { "R 0x240a844c" }, + { "R 0x240a845c" }, + { "R 0x240a84c8 27" }, + { "R 0x240a9000 2" }, + { "R 0x240a9010 2" }, + { "R 0x240a9020 3" }, + { "R 0x240a9034 2" }, + { "R 0x240a9130 3" }, + { "R 0x240a9140 18" }, + { "R 0x240a91ac 6" }, + { "R 0x240a91c8" }, + { "R 0x240a920c" }, + { "R 0x240a9220 2" }, + { "R 0x240a9264" }, + { "R 0x240a9294 7" }, + { "R 0x240a92b8" }, + { "R 0x240a92f8" }, + { "R 0x24800004" }, + { "R 0x24801004" }, + { "R 0x24802004" }, + { "R 0x24803004" }, + { "R 0x24804004" }, + { "R 0x24805004" }, + { "R 0x24806004" }, + { "R 0x24807004" }, + { "R 0x24808004" }, + { "R 0x24809004" }, + { "R 0x2480a004" }, + { "R 0x2480b004" }, + { "R 0x2480c004" }, + { "R 0x2480d004" }, + { "R 0x2480e004" }, + { "R 0x2480f004" }, + { "R 0x24810004" }, + { "R 0x24811004" }, + { "R 0x24812004" }, + { "R 0x24813004" }, + { "R 0x24814004" }, + { "R 0x24815004" }, + { "R 0x24816004" }, + { "R 0x24817004" }, + { "R 0x24818004" }, + { "R 0x24819004" }, + { "R 0x2481a004" }, + { "R 0x2481b004" }, + { "R 0x2481c004" }, + { "R 0x2481d004" }, + { "R 0x2481e004" }, + { "R 0x2481f004" }, + { "R 0x24820004" }, + { "R 0x24821004" }, + { "R 0x24822004" }, + { "R 0x24823004" }, + { "R 0x24843350 2" }, + { "R 0x248433f4 11" }, + { "R 0x248434c0 6" }, + { "R 0x24843600" }, + { "R 0x2484360c" }, + { "R 0x24845040" }, + { "R 0x24845048" }, + { "R 0x24845050" }, + { "R 0x24845058" }, + { "R 0x24845060" }, + { "R 0x24845068" }, + { "R 0x24845070 4" }, + { "R 0x24845090 14" }, + { "R 0x248450cc 2" }, + { "R 0x24845240" }, + { "R 0x248452a0" }, + { "R 0x24845300" }, + { "R 0x24845310" }, + { "R 0x24845320" }, + { "R 0x24845330 3" }, + { "R 0x24847404" }, + { "R 0x2484740c 3" }, + { "R 0x24847448" }, + { "R 0x24847450" }, + { "R 0x24847458 2" }, + { "R 0x24847600" }, + { "R 0x24849000" }, + { "R 0x24849010" }, + { "R 0x2487c000" }, + { "R 0x2487c01c 3" }, + { "R 0x2487c030 8" }, + { "R 0x2487c054 2" }, + { "R 0x2487c078" }, + { "R 0x2487c108 9" }, + { "R 0x2487c20c 3" }, + { "R 0x248a600c 4" }, + { "R 0x248a6020 3" }, + { "R 0x248a6034 2" }, + { "R 0x248a6040" }, + { "R 0x248a6050" }, + { "R 0x248a6058" }, + { "R 0x248a6060 4" }, + { "R 0x248a7020" }, + { "R 0x248a7030 2" }, + { "R 0x248a7078 4" }, + { "R 0x248a708c 6" }, + { "R 0x248e002c" }, + { "R 0x248e009c 2" }, + { "R 0x248e00a8 3" }, + { "R 0x248e00b8" }, + { "R 0x248e00c0 7" }, + { "R 0x248e00e0" }, + { "R 0x248e00e8" }, + { "R 0x248e00f0" }, + { "R 0x248e00f8" }, + { "R 0x248e0100" }, + { "R 0x248e0108" }, + { "R 0x248e0110" }, + { "R 0x248e0118" }, + { "R 0x248e0120" }, + { "R 0x248e0128" }, + { "R 0x248e0150 4" }, + { "R 0x248e0164" }, + { "R 0x248e01e8" }, + { "R 0x248e1010" }, + { "R 0x248e1060 3" }, + { "R 0x248e1070" }, + { "R 0x248e1084 3" }, + { "R 0x248e3004" }, + { "R 0x248e300c" }, + { "R 0x248e4004" }, + { "R 0x248e4010 2" }, + { "R 0x248e4024 2" }, + { "R 0x248e4038 2" }, + { "R 0x248e600c 5" }, + { "R 0x248e700c 5" }, + { "R 0x248e9004" }, + { "R 0x248e9010 3" }, + { "R 0x248e9020 3" }, + { "R 0x248e9030 3" }, + { "R 0x248e9040 3" }, + { "R 0x248e9050 3" }, + { "R 0x248ea004" }, + { "R 0x248ea010 3" }, + { "R 0x248ea020 3" }, + { "R 0x248ea030 3" }, + { "R 0x248ea040 3" }, + { "R 0x248ea050 3" }, + { "R 0x248f001c" }, + { "R 0x248f0050" }, + { "R 0x248f0058" }, + { "R 0x24c00004" }, + { "R 0x24c01004" }, + { "R 0x24c02004" }, + { "R 0x24c03004" }, + { "R 0x24c04004" }, + { "R 0x24c05004" }, + { "R 0x24c06004" }, + { "R 0x24c07004" }, + { "R 0x24c08004" }, + { "R 0x24c09004" }, + { "R 0x24c0a004" }, + { "R 0x24c0b004" }, + { "R 0x24c0c004" }, + { "R 0x24c0d004" }, + { "R 0x24c0e004" }, + { "R 0x24c0f004" }, + { "R 0x24c10004" }, + { "R 0x24c11004" }, + { "R 0x24c12004" }, + { "R 0x24c13004" }, + { "R 0x24c14004" }, + { "R 0x24c15004" }, + { "R 0x24c16004" }, + { "R 0x24c17004" }, + { "R 0x24c18004" }, + { "R 0x24c19004" }, + { "R 0x24c1a004" }, + { "R 0x24c1b004" }, + { "R 0x24c1c004" }, + { "R 0x24c1d004" }, + { "R 0x24c1e004" }, + { "R 0x24c1f004" }, + { "R 0x24c20004" }, + { "R 0x24c21004" }, + { "R 0x24c22004" }, + { "R 0x24c23004" }, + { "R 0x24c43350 2" }, + { "R 0x24c433f4 11" }, + { "R 0x24c434c0 6" }, + { "R 0x24c43600" }, + { "R 0x24c4360c" }, + { "R 0x24c45040" }, + { "R 0x24c45048" }, + { "R 0x24c45050" }, + { "R 0x24c45058" }, + { "R 0x24c45060" }, + { "R 0x24c45068" }, + { "R 0x24c45070 4" }, + { "R 0x24c45090 14" }, + { "R 0x24c450cc 2" }, + { "R 0x24c45240" }, + { "R 0x24c452a0" }, + { "R 0x24c45300" }, + { "R 0x24c45310" }, + { "R 0x24c45320" }, + { "R 0x24c45330 3" }, + { "R 0x24c47404" }, + { "R 0x24c4740c 3" }, + { "R 0x24c47448" }, + { "R 0x24c47450" }, + { "R 0x24c47458 2" }, + { "R 0x24c47600" }, + { "R 0x24c49000" }, + { "R 0x24c49010" }, + { "R 0x24c7c000" }, + { "R 0x24c7c01c 3" }, + { "R 0x24c7c030 8" }, + { "R 0x24c7c054 2" }, + { "R 0x24c7c078" }, + { "R 0x24c7c108 9" }, + { "R 0x24c7c20c 3" }, + { "R 0x24ca600c 4" }, + { "R 0x24ca6020 3" }, + { "R 0x24ca6034 2" }, + { "R 0x24ca6040" }, + { "R 0x24ca6050" }, + { "R 0x24ca6058" }, + { "R 0x24ca6060 4" }, + { "R 0x24ca7020" }, + { "R 0x24ca7030 2" }, + { "R 0x24ca7078 4" }, + { "R 0x24ca708c 6" }, + { "R 0x24ce002c" }, + { "R 0x24ce009c 2" }, + { "R 0x24ce00a8 3" }, + { "R 0x24ce00b8" }, + { "R 0x24ce00c0 7" }, + { "R 0x24ce00e0" }, + { "R 0x24ce00e8" }, + { "R 0x24ce00f0" }, + { "R 0x24ce00f8" }, + { "R 0x24ce0100" }, + { "R 0x24ce0108" }, + { "R 0x24ce0110" }, + { "R 0x24ce0118" }, + { "R 0x24ce0120" }, + { "R 0x24ce0128" }, + { "R 0x24ce0150 4" }, + { "R 0x24ce0164" }, + { "R 0x24ce01e8" }, + { "R 0x24ce1010" }, + { "R 0x24ce1060 3" }, + { "R 0x24ce1070" }, + { "R 0x24ce1084 3" }, + { "R 0x24ce3004" }, + { "R 0x24ce300c" }, + { "R 0x24ce4004" }, + { "R 0x24ce4010 2" }, + { "R 0x24ce4024 2" }, + { "R 0x24ce4038 2" }, + { "R 0x24ce600c 5" }, + { "R 0x24ce700c 5" }, + { "R 0x24ce9004" }, + { "R 0x24ce9010 3" }, + { "R 0x24ce9020 3" }, + { "R 0x24ce9030 3" }, + { "R 0x24ce9040 3" }, + { "R 0x24ce9050 3" }, + { "R 0x24cea004" }, + { "R 0x24cea010 3" }, + { "R 0x24cea020 3" }, + { "R 0x24cea030 3" }, + { "R 0x24cea040 3" }, + { "R 0x24cea050 3" }, + { "R 0x24cf001c" }, + { "R 0x24cf0050" }, + { "R 0x24cf0058" }, + { "R 0x25800004" }, + { "R 0x25801004" }, + { "R 0x25802004" }, + { "R 0x25803004" }, + { "R 0x25804004" }, + { "R 0x25805004" }, + { "R 0x25806004" }, + { "R 0x25807004" }, + { "R 0x25808004" }, + { "R 0x25809004" }, + { "R 0x2580a004" }, + { "R 0x2580b004" }, + { "R 0x2580c004" }, + { "R 0x2580d004" }, + { "R 0x2580e004" }, + { "R 0x2580f004" }, + { "R 0x25810004" }, + { "R 0x25811004" }, + { "R 0x25812004" }, + { "R 0x25813004" }, + { "R 0x25814004" }, + { "R 0x25815004" }, + { "R 0x25816004" }, + { "R 0x25817004" }, + { "R 0x25818004" }, + { "R 0x25819004" }, + { "R 0x2581a004" }, + { "R 0x2581b004" }, + { "R 0x2581c004" }, + { "R 0x2581d004" }, + { "R 0x2581e004" }, + { "R 0x2581f004" }, + { "R 0x25820004" }, + { "R 0x25821004" }, + { "R 0x25822004" }, + { "R 0x25823004" }, + { "R 0x25843350 2" }, + { "R 0x258433f4 11" }, + { "R 0x258434c0 6" }, + { "R 0x25843600" }, + { "R 0x2584360c" }, + { "R 0x25845040" }, + { "R 0x25845048" }, + { "R 0x25845050" }, + { "R 0x25845058" }, + { "R 0x25845060" }, + { "R 0x25845068" }, + { "R 0x25845070 4" }, + { "R 0x25845090 14" }, + { "R 0x258450cc 2" }, + { "R 0x25845240" }, + { "R 0x258452a0" }, + { "R 0x25845300" }, + { "R 0x25845310" }, + { "R 0x25845320" }, + { "R 0x25845330 3" }, + { "R 0x25847404" }, + { "R 0x2584740c 3" }, + { "R 0x25847448" }, + { "R 0x25847450" }, + { "R 0x25847458 2" }, + { "R 0x25847600" }, + { "R 0x25849000" }, + { "R 0x25849010" }, + { "R 0x2587c000" }, + { "R 0x2587c01c 3" }, + { "R 0x2587c030 8" }, + { "R 0x2587c054 2" }, + { "R 0x2587c078" }, + { "R 0x2587c108 9" }, + { "R 0x2587c20c 3" }, + { "R 0x258a600c 4" }, + { "R 0x258a6020 3" }, + { "R 0x258a6034 2" }, + { "R 0x258a6040" }, + { "R 0x258a6050" }, + { "R 0x258a6058" }, + { "R 0x258a6060 4" }, + { "R 0x258a7020" }, + { "R 0x258a7030 2" }, + { "R 0x258a7078 4" }, + { "R 0x258a708c 6" }, + { "R 0x258e002c" }, + { "R 0x258e009c 2" }, + { "R 0x258e00a8 3" }, + { "R 0x258e00b8" }, + { "R 0x258e00c0 7" }, + { "R 0x258e00e0" }, + { "R 0x258e00e8" }, + { "R 0x258e00f0" }, + { "R 0x258e00f8" }, + { "R 0x258e0100" }, + { "R 0x258e0108" }, + { "R 0x258e0110" }, + { "R 0x258e0118" }, + { "R 0x258e0120" }, + { "R 0x258e0128" }, + { "R 0x258e0150 4" }, + { "R 0x258e0164" }, + { "R 0x258e01e8" }, + { "R 0x258e1010" }, + { "R 0x258e1060 3" }, + { "R 0x258e1070" }, + { "R 0x258e1084 3" }, + { "R 0x258e3004" }, + { "R 0x258e300c" }, + { "R 0x258e4004" }, + { "R 0x258e4010 2" }, + { "R 0x258e4024 2" }, + { "R 0x258e4038 2" }, + { "R 0x258e600c 5" }, + { "R 0x258e700c 5" }, + { "R 0x258e9004" }, + { "R 0x258e9010 3" }, + { "R 0x258e9020 3" }, + { "R 0x258e9030 3" }, + { "R 0x258e9040 3" }, + { "R 0x258e9050 3" }, + { "R 0x258ea004" }, + { "R 0x258ea010 3" }, + { "R 0x258ea020 3" }, + { "R 0x258ea030 3" }, + { "R 0x258ea040 3" }, + { "R 0x258ea050 3" }, + { "R 0x258f001c" }, + { "R 0x258f0050" }, + { "R 0x258f0058" }, + { "R 0x25c00004" }, + { "R 0x25c01004" }, + { "R 0x25c02004" }, + { "R 0x25c03004" }, + { "R 0x25c04004" }, + { "R 0x25c05004" }, + { "R 0x25c06004" }, + { "R 0x25c07004" }, + { "R 0x25c08004" }, + { "R 0x25c09004" }, + { "R 0x25c0a004" }, + { "R 0x25c0b004" }, + { "R 0x25c0c004" }, + { "R 0x25c0d004" }, + { "R 0x25c0e004" }, + { "R 0x25c0f004" }, + { "R 0x25c10004" }, + { "R 0x25c11004" }, + { "R 0x25c12004" }, + { "R 0x25c13004" }, + { "R 0x25c14004" }, + { "R 0x25c15004" }, + { "R 0x25c16004" }, + { "R 0x25c17004" }, + { "R 0x25c18004" }, + { "R 0x25c19004" }, + { "R 0x25c1a004" }, + { "R 0x25c1b004" }, + { "R 0x25c1c004" }, + { "R 0x25c1d004" }, + { "R 0x25c1e004" }, + { "R 0x25c1f004" }, + { "R 0x25c20004" }, + { "R 0x25c21004" }, + { "R 0x25c22004" }, + { "R 0x25c23004" }, + { "R 0x25c43350 2" }, + { "R 0x25c433f4 11" }, + { "R 0x25c434c0 6" }, + { "R 0x25c43600" }, + { "R 0x25c4360c" }, + { "R 0x25c45040" }, + { "R 0x25c45048" }, + { "R 0x25c45050" }, + { "R 0x25c45058" }, + { "R 0x25c45060" }, + { "R 0x25c45068" }, + { "R 0x25c45070 4" }, + { "R 0x25c45090 14" }, + { "R 0x25c450cc 2" }, + { "R 0x25c45240" }, + { "R 0x25c452a0" }, + { "R 0x25c45300" }, + { "R 0x25c45310" }, + { "R 0x25c45320" }, + { "R 0x25c45330 3" }, + { "R 0x25c47404" }, + { "R 0x25c4740c 3" }, + { "R 0x25c47448" }, + { "R 0x25c47450" }, + { "R 0x25c47458 2" }, + { "R 0x25c47600" }, + { "R 0x25c49000" }, + { "R 0x25c49010" }, + { "R 0x25c7c000" }, + { "R 0x25c7c01c 3" }, + { "R 0x25c7c030 8" }, + { "R 0x25c7c054 2" }, + { "R 0x25c7c078" }, + { "R 0x25c7c108 9" }, + { "R 0x25c7c20c 3" }, + { "R 0x25ca600c 4" }, + { "R 0x25ca6020 3" }, + { "R 0x25ca6034 2" }, + { "R 0x25ca6040" }, + { "R 0x25ca6050" }, + { "R 0x25ca6058" }, + { "R 0x25ca6060 4" }, + { "R 0x25ca7020" }, + { "R 0x25ca7030 2" }, + { "R 0x25ca7078 4" }, + { "R 0x25ca708c 6" }, + { "R 0x25ce002c" }, + { "R 0x25ce009c 2" }, + { "R 0x25ce00a8 3" }, + { "R 0x25ce00b8" }, + { "R 0x25ce00c0 7" }, + { "R 0x25ce00e0" }, + { "R 0x25ce00e8" }, + { "R 0x25ce00f0" }, + { "R 0x25ce00f8" }, + { "R 0x25ce0100" }, + { "R 0x25ce0108" }, + { "R 0x25ce0110" }, + { "R 0x25ce0118" }, + { "R 0x25ce0120" }, + { "R 0x25ce0128" }, + { "R 0x25ce0150 4" }, + { "R 0x25ce0164" }, + { "R 0x25ce01e8" }, + { "R 0x25ce1010" }, + { "R 0x25ce1060 3" }, + { "R 0x25ce1070" }, + { "R 0x25ce1084 3" }, + { "R 0x25ce3004" }, + { "R 0x25ce300c" }, + { "R 0x25ce4004" }, + { "R 0x25ce4010 2" }, + { "R 0x25ce4024 2" }, + { "R 0x25ce4038 2" }, + { "R 0x25ce600c 5" }, + { "R 0x25ce700c 5" }, + { "R 0x25ce9004" }, + { "R 0x25ce9010 3" }, + { "R 0x25ce9020 3" }, + { "R 0x25ce9030 3" }, + { "R 0x25ce9040 3" }, + { "R 0x25ce9050 3" }, + { "R 0x25cea004" }, + { "R 0x25cea010 3" }, + { "R 0x25cea020 3" }, + { "R 0x25cea030 3" }, + { "R 0x25cea040 3" }, + { "R 0x25cea050 3" }, + { "R 0x25cf001c" }, + { "R 0x25cf0050" }, + { "R 0x25cf0058" }, + { "R 0x240a0008 2" }, + { "R 0x240a1008 2" }, + { "R 0x248e0070 7" }, + { "R 0x248e0094 2" }, + { "R 0x248e012c 9" }, + { "R 0x248e0160" }, + { "R 0x248e0364 2" }, + { "R 0x24ce0070 7" }, + { "R 0x24ce0094 2" }, + { "R 0x24ce012c 9" }, + { "R 0x24ce0160" }, + { "R 0x24ce0364 2" }, + { "R 0x258e0070 7" }, + { "R 0x258e0094 2" }, + { "R 0x258e012c 9" }, + { "R 0x258e0160" }, + { "R 0x258e0364 2" }, + { "R 0x25ce0070 7" }, + { "R 0x25ce0094 2" }, + { "R 0x25ce012c 9" }, + { "R 0x25ce0160" }, + { "R 0x25ce0364 2" }, + { "R 0x248e0358" }, + { "R 0x24ce0358" }, + { "R 0x258e0358" }, + { "R 0x25ce0358" }, + { "R 0x248e0008" }, + { "R 0x24ce0008" }, + { "R 0x258e0008" }, + { "R 0x25ce0008" }, + { "R 0x24076b00 2" }, + { "R 0x24076b0c 2" }, + { "R 0x24076b18 2" }, + { "R 0x24076b24 2" }, + { "R 0x24076b30 2" }, + { "R 0x24076b3c 2" }, + { "R 0x24076b48 2" }, + { "R 0x24076b54 2" }, + { "R 0x24076b60 2" }, + { "R 0x24076b6c 2" }, + { "R 0x24076b78 2" }, + { "R 0x24076b84 2" }, + { "R 0x24076b90 2" }, + { "R 0x24076b9c 2" }, + { "R 0x24076ba8 2" }, + { "R 0x24076bb4 2" }, + { "R 0x24076bc0 2" }, + { "R 0x24076bcc 2" }, + { "R 0x24076bd8 2" }, + { "R 0x24076be4 2" }, + { "R 0x24076bf0 2" }, + { "R 0x24076bfc 2" }, + { "R 0x24076c08 2" }, + { "R 0x24076c14 2" }, + { "R 0x24076c20 2" }, + { "R 0x24076c2c 2" }, + { "R 0x24076c38 2" }, + { "R 0x24076c44 2" }, + { "R 0x24076c50 2" }, + { "R 0x24076c5c 2" }, + { "R 0x24076c68 2" }, + { "R 0x24076c74 2" }, + { "R 0x24076950" }, + { "R 0x240760a4" }, + { "R 0x248720b0" }, + { "R 0x258720b0" }, + { "R 0x24c720b0" }, + { "R 0x25c720b0" }, +}; + +static const struct dcc_register_entry pakala_dcc_entries_ll4[] = { + { "R 0x16801000 2" }, + { "R 0x240e0010" }, + { "R 0x240e0020 8" }, + { "R 0x240e0248" }, + { "R 0x24330010" }, + { "R 0x24330020 8" }, + { "R 0x24330248" }, + { "R 0x240e1018" }, + { "R 0x240e1008" }, + { "R 0x240e1010 2" }, + { "R 0x24331018" }, + { "R 0x24331008" }, + { "R 0x24331010 2" }, + { "R 0x1780010" }, + { "R 0x1780020 8" }, + { "R 0x1780248" }, + { "R 0x1782018" }, + { "R 0x1782008" }, + { "R 0x1782010 2" }, + { "R 0x1783018" }, + { "R 0x1783008" }, + { "R 0x1783010 2" }, + { "R 0x1680010" }, + { "R 0x1680020 8" }, + { "R 0x1681048" }, + { "R 0x1682018" }, + { "R 0x1682008" }, + { "R 0x1682010 2" }, + { "R 0x16e0010" }, + { "R 0x16e0020 8" }, + { "R 0x16e0248" }, + { "R 0x16e1018" }, + { "R 0x16e1008" }, + { "R 0x16e1010 2" }, + { "R 0x16e1098" }, + { "R 0x16e1088" }, + { "R 0x16e1090 2" }, + { "R 0x16e1118" }, + { "R 0x16e1108" }, + { "R 0x16e1110 2" }, + { "R 0x1700010" }, + { "R 0x1700020 8" }, + { "R 0x1700248" }, + { "R 0x1702018" }, + { "R 0x1702008" }, + { "R 0x1702010 2" }, + { "R 0x1702218" }, + { "R 0x1702208" }, + { "R 0x1702210 2" }, + { "R 0x1702118" }, + { "R 0x1702108" }, + { "R 0x1702110 2" }, + { "R 0x1600010" }, + { "R 0x1600020 8" }, + { "R 0x1600248 2" }, + { "R 0x1600258" }, + { "R 0x1602018" }, + { "R 0x1602008" }, + { "R 0x1602010 2" }, + { "R 0x1602098" }, + { "R 0x1602088" }, + { "R 0x1602090 2" }, + { "R 0x1602118" }, + { "R 0x1602108" }, + { "R 0x1602110 2" }, + { "R 0x1602198" }, + { "R 0x1602188" }, + { "R 0x1602190 2" }, + { "R 0x1602218" }, + { "R 0x1602208" }, + { "R 0x1602210 2" }, + { "R 0x1602098" }, + { "R 0x1602088" }, + { "R 0x1602090 2" }, + { "R 0x1500010" }, + { "R 0x1500020 8" }, + { "R 0x1500248" }, + { "R 0x1500448" }, + { "R 0x1502018" }, + { "R 0x1502008" }, + { "R 0x1502010 2" }, + { "R 0x1502098" }, + { "R 0x1502088" }, + { "R 0x1502090 2" }, + { "R 0x16e00010" }, + { "R 0x16e00020 8" }, + { "R 0x16e00248" }, + { "R 0x16e01018" }, + { "R 0x16e01008" }, + { "R 0x16e01010 2" }, + { "R 0x1b600010" }, + { "R 0x1b600020 8" }, + { "R 0x1b600248" }, + { "R 0x1b601018" }, + { "R 0x1b601008" }, + { "R 0x1b601010 2" }, + { "R 0x16000104 30" }, + { "R 0x16000204 29" }, + { "R 0x16000384 30" }, + { "R 0xb291024" }, + { "R 0xc201244" }, + { "R 0xc202244" }, + { "R 0xbde1034 2" }, + { "R 0xb201020 2" }, + { "R 0xb211020 2" }, + { "R 0xb221020 2" }, + { "R 0xb231020 2" }, + { "R 0xb204520" }, + { "R 0xb200000" }, + { "R 0xb210000" }, + { "R 0xb220000" }, + { "R 0xb230000" }, + { "R 0x16500010" }, + { "R 0x16510010" }, + { "R 0x16520010" }, + { "R 0x16530010" }, + { "R 0x16500030" }, + { "R 0x16510030" }, + { "R 0x16520030" }, + { "R 0x16530030" }, + { "R 0x16500038" }, + { "R 0x16510038" }, + { "R 0x16520038" }, + { "R 0x16530038" }, + { "R 0x16500040" }, + { "R 0x16510040" }, + { "R 0x16520040" }, + { "R 0x16530040" }, + { "R 0x16500048" }, + { "R 0x16500400 3" }, + { "R 0x16510400 3" }, + { "R 0x16520400 3" }, + { "R 0x16530400 3" }, + { "R 0x16510d3c" }, + { "R 0x16510d54" }, + { "R 0x16510d6c" }, + { "R 0x16510d84" }, + { "R 0x16510d9c" }, + { "R 0x16510db4" }, + { "R 0x16510dcc" }, + { "R 0x16510de4" }, + { "R 0x16510dfc" }, + { "R 0x16510e14" }, + { "R 0x16510e2c" }, + { "R 0x16510e44" }, + { "R 0x16510e5c" }, + { "R 0x16510e74" }, + { "R 0x16510e8c" }, + { "R 0x16510ea4" }, + { "R 0x16510fdc" }, + { "R 0x16510ff4" }, + { "R 0x1651100c" }, + { "R 0x16511024" }, + { "R 0x1651103c" }, + { "R 0x16511054" }, + { "R 0x1651106c" }, + { "R 0x16511084" }, + { "R 0x1651109c" }, + { "R 0x165110b4" }, + { "R 0x165110cc" }, + { "R 0x165110e4" }, + { "R 0x165110fc" }, + { "R 0x16511114" }, + { "R 0x1651112c" }, + { "R 0x16511144" }, + { "R 0x1651127c" }, + { "R 0x16511294" }, + { "R 0x165112ac" }, + { "R 0x165112c4" }, + { "R 0x165112dc" }, + { "R 0x165112f4" }, + { "R 0x1651130c" }, + { "R 0x16511324" }, + { "R 0x1651133c" }, + { "R 0x16511354" }, + { "R 0x1651136c" }, + { "R 0x16511384" }, + { "R 0x1651139c" }, + { "R 0x165113b4" }, + { "R 0x165113cc" }, + { "R 0x165113e4" }, + { "R 0x1651151c" }, + { "R 0x16511534" }, + { "R 0x1651154c" }, + { "R 0x16511564" }, + { "R 0x1651157c" }, + { "R 0x16511594" }, + { "R 0x165115ac" }, + { "R 0x165115c4" }, + { "R 0x165115dc" }, + { "R 0x165115f4" }, + { "R 0x1651160c" }, + { "R 0x16511624" }, + { "R 0x1651163c" }, + { "R 0x16511654" }, + { "R 0x1651166c" }, + { "R 0x16511684" }, + { "R 0x110004 2" }, + { "R 0x11003c 3" }, + { "R 0x176040" }, + { "R 0x10c0000 4" }, + { "R 0x10c1000 2" }, + { "R 0x10c1010 7" }, + { "R 0x10c1100 3" }, + { "R 0x10c1110 5" }, + { "R 0x10c1130 2" }, + { "R 0x10c113c 2" }, + { "R 0x10c1148 3" }, + { "R 0x10c1800 11" }, + { "R 0x10c2000" }, + { "R 0x10cf004" }, + { "R 0x16801000 2" }, +}; + +static const struct dcc_link_config pakala_link_configs[] = { + { + .link_list = 6, + .entries = pakala_dcc_entries_ll6, + .num_entries = ARRAY_SIZE(pakala_dcc_entries_ll6), + }, + { + .link_list = 4, + .entries = pakala_dcc_entries_ll4, + .num_entries = ARRAY_SIZE(pakala_dcc_entries_ll4), + }, +}; + +static const struct dcc_config pakala_config = { + .lists = pakala_link_configs, + .num_lists = ARRAY_SIZE(pakala_link_configs), +}; + +static const struct dcc_pdata pakala_pdata = { + .base = 0x100ff000, + .size = 0x00001000, + .ram_base = 0x10084000, + .ram_size = 0x4000, + .dcc_offset = 0x4000, + .map_ver = 0x3, + .config = &pakala_config, +}; + +#endif /* _QCOM_DCC_PAKALA_CONFIG_H */ From dab2753d332408abc9d4084b6b3780f413de69ca Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 14 May 2026 18:06:38 +0800 Subject: [PATCH 0060/1133] QCLINUX: qcom-dcc: add shikra register list and move config to header Add the DCC register capture list for the Shikra platform (SoC IDs 756, 758, 759) across two linked lists and move the configuration into a dedicated header qcom-dcc-shikra-config.h. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 8 + drivers/misc/qcom-dcc-shikra-config.h | 677 ++++++++++++++++++++++++++ 2 files changed, 685 insertions(+) create mode 100644 drivers/misc/qcom-dcc-shikra-config.h diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index a77b5bc144982..73994f39de30e 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -11,6 +11,7 @@ #include "qcom-dcc-lemans-config.h" #include "qcom-dcc-kodiak-config.h" #include "qcom-dcc-pakala-config.h" +#include "qcom-dcc-shikra-config.h" #define DEV_NAME "qcom-dcc" @@ -131,6 +132,13 @@ static int __init dcc_dev_init(void) goto fail; break; + case 756: + case 758: + case 759: + ret = platform_device_add_data(dcc_pdev, &shikra_pdata, sizeof(shikra_pdata)); + if (ret) + goto fail; + break; default: pr_err("DCC: Invalid SoC ID\n"); ret = -EINVAL; diff --git a/drivers/misc/qcom-dcc-shikra-config.h b/drivers/misc/qcom-dcc-shikra-config.h new file mode 100644 index 0000000000000..fdf3d0c34695c --- /dev/null +++ b/drivers/misc/qcom-dcc-shikra-config.h @@ -0,0 +1,677 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_SHIKRA_CONFIG_H +#define _QCOM_DCC_SHIKRA_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry shikra_dcc_entries_ll2[] = { + /* timer */ + { "R 0x17421000 2" }, + /* clock */ + { "R 0x1400000 10" }, + { "R 0x1401000 10" }, + { "R 0x1402000 10" }, + { "R 0x1403000 10" }, + { "R 0x1404000 10" }, + { "R 0x1405000 10" }, + { "R 0x1406000 10" }, + { "R 0x1407000 10" }, + { "R 0x1408000 10" }, + { "R 0x1409000 9" }, + { "R 0x140a000 10" }, + { "R 0x140b000 10" }, + { "R 0x140c000 10" }, + { "R 0x141001c" }, + { "R 0x14103d0" }, + { "R 0x1414024" }, + { "R 0x1415034 2" }, + { "R 0x141f02c" }, + { "R 0x141f15c" }, + { "R 0x141f28c" }, + { "R 0x141f3bc" }, + { "R 0x141f4ec" }, + { "R 0x141f61c" }, + { "R 0x141f74c" }, + { "R 0x141f87c" }, + { "R 0x141f9ac" }, + { "R 0x141fadc" }, + { "R 0x141fc0c" }, + { "R 0x1427024" }, + { "R 0x1432034" }, + { "R 0x1434028" }, + { "R 0x1434154" }, + { "R 0x143c018" }, + { "R 0x1446024" }, + { "R 0x1446154" }, + { "R 0x1449018" }, + { "R 0x14b4014" }, + { "R 0x146b000 14" }, + { "R 0xfa80000 6" }, + { "R 0xfa8001c 2" }, + { "R 0xfa80028" }, + { "R 0xfa80034 2" }, + { "R 0xfa80080 3" }, + { "R 0xfa84000 6" }, + { "R 0xfa8401c 2" }, + { "R 0xfa84028" }, + { "R 0xfa84034 2" }, + { "R 0xfa84080 3" }, + { "R 0xfa88000 6" }, + { "R 0xfa8801c 2" }, + { "R 0xfa88028" }, + { "R 0xfa88034 2" }, + { "R 0xfa88080 3" }, + { "R 0x440c000" }, + { "R 0x440c008" }, + { "R 0x440c040 9" }, + { "R 0x440c068 2" }, + /* global_cpr */ + { "R 0x1648000 2" }, + { "R 0x16480e0" }, + { "R 0x1648100" }, + { "R 0x1648120" }, + { "R 0x1648140" }, + { "R 0x1648200" }, + { "R 0x164880c 4" }, + { "R 0x164c000 2" }, + { "R 0x164c0e0" }, + { "R 0x164c100" }, + { "R 0x164c120" }, + { "R 0x164c140" }, + { "R 0x164c200" }, + { "R 0x164c80c 4" }, + { "R 0x1b44268 7" }, + { "R 0x1b44288 11" }, + { "R 0x1b442d0" }, + /* cpr */ + { "R 0xfd9001c 3" }, + { "R 0xfd90090" }, + { "R 0xfd900b0 2" }, + { "R 0xfd900d8" }, + { "R 0xfd900e8" }, + { "R 0xfd90300" }, + { "R 0xfd90320" }, + { "R 0xfd90348 3" }, + { "R 0xfd90360" }, + { "R 0xfd90368 2" }, + { "R 0xfd9101c 3" }, + { "R 0xfd91090" }, + { "R 0xfd910b0 2" }, + { "R 0xfd910d8" }, + { "R 0xfd910e8" }, + { "R 0xfd91300" }, + { "R 0xfd91320" }, + { "R 0xfd91348 3" }, + { "R 0xfd91360" }, + { "R 0xfd91368 2" }, + { "R 0xfd9201c 3" }, + { "R 0xfd92090" }, + { "R 0xfd920b0 2" }, + { "R 0xfd920d8" }, + { "R 0xfd920e8" }, + { "R 0xfd92300" }, + { "R 0xfd92320" }, + { "R 0xfd92348 4" }, + { "R 0xfd92360" }, + { "R 0xfd92368 2" }, + { "R 0xfd98004" }, + { "R 0xfd98018 3" }, + { "R 0xf900c14 2" }, + { "R 0xfba0008" }, + { "R 0xfba0020 2" }, + { "R 0xfba0070" }, + { "R 0xfba0810" }, + { "R 0xfba3500" }, + { "R 0xfba3a84 2" }, + { "R 0xfa90004" }, + { "R 0xfa92004" }, + { "R 0xfa94004" }, + { "R 0xfba3a84 3" }, + { "R 0xfd90200 12" }, + { "R 0xfd91200 12" }, + { "R 0xfd92200 12" }, + { "R 0xfba3500 40" }, + /* cpucp */ + { "R 0xfd80110" }, + { "R 0xfd9001c" }, + { "R 0xfd90090" }, + { "R 0xfd900b0" }, + { "R 0xfd900d8" }, + { "R 0xfd900e8" }, + { "R 0xfd90300" }, + { "R 0xfd90320" }, + { "R 0xfd90348" }, + { "R 0xfd9101c" }, + { "R 0xfd91090" }, + { "R 0xfd910b0" }, + { "R 0xfd910d8" }, + { "R 0xfd910e8" }, + { "R 0xfd91300" }, + { "R 0xfd91320" }, + { "R 0xfd91348" }, + { "R 0xfd9201c" }, + { "R 0xfd92090" }, + { "R 0xfd920b0" }, + { "R 0xfd920d8" }, + { "R 0xfd920e8" }, + { "R 0xfd92300" }, + { "R 0xfd92320" }, + { "R 0xfd92348" }, + { "R 0xfd98004" }, + { "R 0xfd98018" }, + { "R 0xf900c00" }, + { "R 0xfb00000" }, + { "R 0xfba0000" }, + { "R 0xf800000" }, + { "R 0xf810000" }, + { "R 0xf820000" }, + { "R 0xf830000" }, + { "R 0xf840000" }, + { "R 0xf850000" }, + { "R 0xf860000" }, + { "R 0xf870000" }, + { "R 0xfd91000" }, + { "R 0xfd92000" }, + { "R 0xf880000" }, + { "R 0xfd90000" }, + { "R 0xf900c18" }, + { "R 0xfd9134c" }, + { "R 0xfd9234c" }, + { "R 0xfd9034c" }, + { "R 0xfba3a84" }, + { "R 0xfba3a88" }, + { "R 0xfba3a8c" }, + { "R 0xfd91020" }, + { "R 0xfd92020" }, + { "R 0xfd90020" }, + /* modem */ + { "R 0x6080400 3" }, + { "R 0x6080410 2" }, + { "R 0x6080060 5" }, + { "R 0x61f100c" }, + { "R 0x143314c" }, + { "R 0x6140400 3" }, + { "R 0x6082028" }, + { "R 0x6080304" }, + { "R 0xd2f010" }, + { "R 0x6104000 8" }, + { "R 0x6140208 3" }, + { "R 0x6140228 3" }, + { "R 0x6140248 3" }, + { "R 0x6140268 3" }, + { "R 0x6140288 3" }, + { "R 0x6140400 3" }, + { "R 0x6082028" }, + { "R 0x6080304" }, + { "R 0x6140200" }, + { "R 0x6140404" }, + { "R 0x608030c" }, + /* ICB - SYSTEM_NOC */ + { "R 0x1880000" }, + { "R 0x1880004" }, + { "R 0x1880008" }, + { "R 0x1880010" }, + { "R 0x1880020" }, + { "R 0x1880024" }, + { "R 0x1880028" }, + { "R 0x188002c" }, + { "R 0x1880030" }, + { "R 0x1880034" }, + { "R 0x1880038" }, + { "R 0x188003c" }, + { "R 0x1880240" }, + { "R 0x1880248" }, + { "R 0x1881018" }, + { "R 0x1881008" }, + { "R 0x1881010 2" }, + { "R 0x1881098" }, + { "R 0x1881088" }, + { "R 0x1881090 2" }, + { "R 0x1881118" }, + { "R 0x1881108" }, + { "R 0x1881110 2" }, + { "R 0x1881198" }, + { "R 0x1881188" }, + { "R 0x1881190 2" }, + { "R 0x1881218" }, + { "R 0x1881208" }, + { "R 0x1881210 2" }, + /* ICB - CONFIG_NOC */ + { "R 0x1900000" }, + { "R 0x1900004" }, + { "R 0x1900008" }, + { "R 0x1900010" }, + { "R 0x1900020" }, + { "R 0x1900024" }, + { "R 0x1900028" }, + { "R 0x190002c" }, + { "R 0x1900030" }, + { "R 0x1900034" }, + { "R 0x1900038" }, + { "R 0x190003c" }, + { "R 0x1900240" }, + { "R 0x1900244" }, + { "R 0x1900248" }, + { "R 0x190024c" }, + { "R 0x1901018" }, + { "R 0x1901008" }, + { "R 0x1901010 2" }, + { "R 0x1901118" }, + { "R 0x1901108" }, + { "R 0x1901110 2" }, + { "R 0x1901218" }, + { "R 0x1901208" }, + { "R 0x1901210 2" }, + { "R 0x1901318" }, + { "R 0x1901308" }, + { "R 0x1901310 2" }, + /* ICB - MEMNOC */ + { "R 0xd00000" }, + { "R 0xd00004" }, + { "R 0xd00008" }, + { "R 0xd00010" }, + { "R 0xd00020" }, + { "R 0xd00024" }, + { "R 0xd00028" }, + { "R 0xd0002c" }, + { "R 0xd00030" }, + { "R 0xd00034" }, + { "R 0xd00038" }, + { "R 0xd0003c" }, + { "R 0xd40000" }, + { "R 0xd40004" }, + { "R 0xd40008" }, + { "R 0xd40010" }, + { "R 0xd40020" }, + { "R 0xd40024" }, + { "R 0xd40028" }, + { "R 0xd4002c" }, + { "R 0xd40030" }, + { "R 0xd40034" }, + { "R 0xd40038" }, + { "R 0xd4003c" }, + { "R 0xd00240" }, + { "R 0xd00248" }, + { "R 0xd40440" }, + { "R 0xd40448" }, + { "R 0xd41018" }, + { "R 0xd41008" }, + { "R 0xd41010 2" }, + { "R 0xd01018" }, + { "R 0xd01008" }, + { "R 0xd01010 2" }, + /* ICB - DC_NOC */ + { "R 0xce5018" }, + { "R 0xce5008" }, + { "R 0xce5010 2" }, + { "R 0xce0010" }, + { "R 0xce0020 8" }, + { "R 0xce0248" }, + /* ICB - QoS - system noc */ + { "R 0x18d1010" }, + { "R 0x18d2010" }, + { "R 0x18d3010" }, + { "R 0x18d4010" }, + { "R 0x18d5010" }, + { "R 0x18d6010" }, + { "R 0x18d7010" }, + { "R 0x18d8010" }, + { "R 0x18d9010" }, + { "R 0x18da010" }, + { "R 0x18db010" }, + { "R 0x18dc010" }, + { "R 0x18dd010" }, + { "R 0x18de010" }, + { "R 0x18df010" }, + { "R 0x18e0010" }, + { "R 0x18e1010" }, + { "R 0x18e2010" }, + { "R 0x18e3010" }, + { "R 0x18e4010" }, + { "R 0x18e5010" }, + { "R 0x18e6010" }, + { "R 0x18e7010" }, + { "R 0x18e8010" }, + { "R 0x18e9010" }, + { "R 0x18ea010" }, + /* ICB - QoS - mem noc */ + { "R 0xd28010" }, + { "R 0xd2a010" }, + { "R 0xd2b010" }, + { "R 0xd2c010" }, + { "R 0xd2d010" }, + { "R 0xd2e010" }, + { "R 0xd2f010" }, + /* ddr */ + { "R 0x1089180 2" }, + { "R 0x10804d4" }, + { "R 0x10804b8 2" }, + { "R 0x1089100" }, + { "R 0x1089110" }, + { "R 0x1089120" }, + { "R 0x10891a0" }, + { "R 0x108340c" }, + { "R 0x1083404" }, + { "R 0x1083410" }, + { "R 0x1083408" }, + { "R 0x1083400" }, + { "R 0x1086418" }, + { "R 0x1086400" }, + { "R 0x1086420" }, + { "R 0x1086410" }, + { "R 0x10891c0" }, + { "R 0x10891e0" }, + { "R 0x1085b14" }, + { "R 0x1085b10" }, + { "R 0x1085b0c" }, + { "R 0x1085b00" }, + { "R 0x10853b0" }, + { "R 0x1085b1c" }, + { "R 0x1085b08" }, + { "R 0x1085b38" }, + { "R 0x1085b30" }, + { "R 0x1085b2c" }, + { "R 0x1085804" }, + { "R 0x1085b28" }, + { "R 0x1085b18" }, + { "R 0x1085230" }, + { "R 0x1085210" }, + { "R 0xc800b0 2" }, + { "R 0xcb6000" }, + { "R 0x1286074 5" }, + { "R 0x1286260 5" }, + { "R 0xc80018" }, + { "R 0xc80108" }, + { "R 0xc840e0 2" }, + { "R 0xcba070 2" }, + { "R 0xcba054" }, + { "R 0xcba078 2" }, + { "R 0xcba058" }, + { "R 0xcba080" }, + { "R 0xcba084" }, + { "R 0xcba05c" }, + { "R 0xcba088" }, + { "R 0xcba08c" }, + { "R 0xcba060" }, + { "R 0xcba090 2" }, + { "R 0xcba064" }, + { "R 0xcba098 2" }, + { "R 0x1090018" }, + { "R 0x1090110 4" }, + { "R 0x1090004" }, + { "R 0x10900a0" }, + { "R 0x1090170" }, + { "R 0x1090180 4" }, + { "R 0x1090078" }, + { "R 0x1090150 4" }, + { "R 0x1090080" }, + { "R 0x1090088" }, + { "R 0x1090090" }, + { "R 0x1090070 2" }, + { "R 0x10900b0" }, + { "R 0x1090130" }, + { "R 0x1090140" }, + { "R 0x1090030 3" }, + { "R 0x1090044" }, + { "R 0x1090144" }, + { "R 0x1090040 3" }, + { "R 0x10900c8 2" }, + { "R 0x1090050" }, + { "R 0x1090128 2" }, + { "R 0x10900e4 5" }, + { "R 0x1090124" }, + { "R 0x1090100" }, + { "R 0xe90018" }, + { "R 0xe90110 4" }, + { "R 0xe90004" }, + { "R 0xe900a0" }, + { "R 0xe90170" }, + { "R 0xe90180 4" }, + { "R 0xe90078" }, + { "R 0xe90150" }, + { "R 0xe90080" }, + { "R 0xe90154" }, + { "R 0xe90088" }, + { "R 0xe90158" }, + { "R 0xe90090" }, + { "R 0xe9015c" }, + { "R 0xe90070 2" }, + { "R 0xe900b0" }, + { "R 0xe90130" }, + { "R 0xe90034" }, + { "R 0xe90140" }, + { "R 0xe90038" }, + { "R 0xe90030" }, + { "R 0xe90044" }, + { "R 0xe90144" }, + { "R 0xe90048" }, + { "R 0xe90040" }, + { "R 0xe900c8 2" }, + { "R 0xe90050" }, + { "R 0xe90128 2" }, + { "R 0xe900e4 3" }, + { "R 0xe900f0 2" }, + { "R 0xe90124" }, + { "R 0xe90100" }, + { "R 0xf90018" }, + { "R 0xf90110 4" }, + { "R 0xf90004" }, + { "R 0xf900a0" }, + { "R 0xf90170" }, + { "R 0xf90180 4" }, + { "R 0xf90078" }, + { "R 0xf90150 4" }, + { "R 0xf90080" }, + { "R 0xf90088" }, + { "R 0xf90090" }, + { "R 0xf90070 2" }, + { "R 0xf900b0" }, + { "R 0xf90130 2" }, + { "R 0xf90140" }, + { "R 0xf90038" }, + { "R 0xf90030" }, + { "R 0xf90044" }, + { "R 0xf90144" }, + { "R 0xf90048" }, + { "R 0xf90040" }, + { "R 0xf900c8 2" }, + { "R 0xf90050" }, + { "R 0xf90128 2" }, + { "R 0xf900e4 5" }, + { "R 0xf90124" }, + { "R 0xf90100" }, + { "R 0xcba218" }, + { "R 0xcba050" }, + { "R 0xcba210" }, + { "R 0xcba280" }, + { "R 0xcba180 4" }, + { "R 0xcba214" }, + { "R 0xcba004" }, + { "R 0xcba000" }, + { "R 0xcba014 2" }, + { "R 0xcba020 2" }, + { "R 0xcba010" }, + { "R 0xcba288 7" }, + { "R 0xcba150 2" }, + { "R 0xcba200" }, + { "R 0xcba140 2" }, + { "R 0xcba230 2" }, + { "R 0xcba0c8 2" }, + { "R 0xcba0b0 4" }, + { "R 0xcba240 2" }, + { "R 0xcba250 4" }, + { "R 0xcba100 5" }, + { "R 0xcba120 3" }, + { "R 0xcba130" }, + { "R 0xcba134" }, + { "R 0xcba270" }, + { "R 0xc35008" }, + { "R 0xc350b4" }, + { "R 0xc35100" }, + { "R 0x1059070" }, + { "R 0x103801c 7" }, + { "R 0x1023318" }, + { "R 0x1020488" }, + { "R 0x1020480" }, + { "R 0x1023594" }, + { "R 0x102358c" }, + { "R 0x10223a0" }, + { "R 0x1022398" }, + { "R 0x10223ac" }, + { "R 0x10223a4" }, + { "R 0x128007c" }, + { "R 0x128107c" }, + { "R 0x128207c" }, + { "R 0x128307c" }, + { "R 0x128407c" }, + { "R 0x128507c" }, + { "R 0x12800a4" }, + { "R 0x12810a4" }, + { "R 0x12820a4" }, + { "R 0x12830a4" }, + { "R 0x12840a4" }, + { "R 0x12850a4" }, + { "R 0x1280100" }, + { "R 0x1281100" }, + { "R 0x1282100" }, + { "R 0x1283100" }, + { "R 0x1284100" }, + { "R 0x1285100" }, + { "R 0x128011c" }, + { "R 0x128111c" }, + { "R 0x128211c" }, + { "R 0x128311c" }, + { "R 0x128411c" }, + { "R 0x128511c" }, + { "R 0x1280568" }, + { "R 0x1281568" }, + { "R 0x1282568" }, + { "R 0x1283568" }, + { "R 0x1284568" }, + { "R 0x1285568" }, + { "R 0x128082c" }, + { "R 0x128182c" }, + { "R 0x128282c" }, + { "R 0x128382c" }, + { "R 0x128482c" }, + { "R 0x128582c" }, + { "R 0x128007c" }, + { "R 0x128107c" }, + { "R 0x128207c" }, + { "R 0x128307c" }, + { "R 0x128407c" }, + { "R 0x128507c" }, + { "R 0x12800a4" }, + { "R 0x12810a4" }, + { "R 0x12820a4" }, + { "R 0x12830a4" }, + { "R 0x12840a4" }, + { "R 0x12850a4" }, + { "R 0xc80058 2" }, + { "R 0xc800c8" }, + { "R 0xc800d4" }, + { "R 0xc80114" }, + { "R 0xc80104 2" }, + { "R 0xc800b0 2" }, + { "R 0xc80098" }, + { "R 0xd00248" }, +}; + +static const struct dcc_register_entry shikra_dcc_entries_ll3[] = { + /* gpu */ + { "R 0x599106c" }, + { "R 0x599100c" }, + { "R 0x59910a4" }, + { "R 0x5991054" }, + { "R 0x5991098 2" }, + { "R 0x5991078" }, + { "R 0x5991508" }, + { "R 0x599150c" }, + { "R 0x143600c" }, + { "R 0x1471000" }, + { "R 0x1436018" }, + /* cdsp */ + { "R 0xb3b0208 3" }, + { "R 0xb3b0228 3" }, + { "R 0xb3b0248 3" }, + { "R 0xb3b0268 3" }, + { "R 0xb3b0290" }, + { "R 0xb3b02b0" }, + { "R 0xb3b0400 3" }, + { "R 0xb302028" }, + { "R 0xb300304" }, + { "R 0xb3b0200" }, + { "R 0xb3b0404" }, + { "R 0x608030c" }, + /* apps_pcu */ + { "R 0xf800024" }, + { "R 0xf800040" }, + { "R 0xf80004c" }, + { "R 0xf800054" }, + { "R 0xf810024" }, + { "R 0xf810040" }, + { "R 0xf81004c" }, + { "R 0xf810054" }, + { "R 0xf820024" }, + { "R 0xf820040" }, + { "R 0xf82004c" }, + { "R 0xf820054" }, + { "R 0xf830024" }, + { "R 0xf830040" }, + { "R 0xf83004c" }, + { "R 0xf830054" }, + { "R 0xf880024" }, + { "R 0xf880040" }, + { "R 0xf880098" }, + { "R 0xfa80000 2" }, + { "R 0xfa84000 2" }, + { "R 0xfa88000 2" }, + { "R 0xf880200" }, + { "R 0xf8801b4 3" }, + { "R 0xf880044 3" }, + { "R 0xf880054" }, + { "R 0xf88006c" }, + { "R 0xf880070 4" }, + { "R 0xfd90348 2" }, + { "R 0xfd91348 2" }, + { "R 0xfd92348 2" }, + { "R 0xfd800fc" }, + { "R 0xfd800ec" }, + { "R 0xfd8010c" }, + { "R 0xfd91060 8" }, + { "R 0xfd92064 8" }, +}; + +static const struct dcc_link_config shikra_link_configs[] = { + { + .link_list = 2, + .entries = shikra_dcc_entries_ll2, + .num_entries = ARRAY_SIZE(shikra_dcc_entries_ll2), + }, + { + .link_list = 3, + .entries = shikra_dcc_entries_ll3, + .num_entries = ARRAY_SIZE(shikra_dcc_entries_ll3), + }, +}; + +static const struct dcc_config shikra_config = { + .lists = shikra_link_configs, + .num_lists = ARRAY_SIZE(shikra_link_configs), +}; + +static const struct dcc_pdata shikra_pdata = { + .base = 0x080ff000, + .size = 0x00001000, + .ram_base = 0x08086000, + .ram_size = 0x00002000, + .dcc_offset = 0x6000, + .map_ver = 0x3, + .config = &shikra_config, +}; + +#endif /* _QCOM_DCC_SHIKRA_CONFIG_H */ From e6630dd95421c7cf0bb607b537258e532df4ccd7 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 20 May 2026 16:26:37 +0800 Subject: [PATCH 0061/1133] QCLINUX: memory-dump: add memory dump table for Shikra Add memory dump table configuration to enable memory dump function on Shikra platform. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 46 +++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 0845aa152dc2f..fb9d4dc0dceab 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -355,6 +355,37 @@ static const struct dump_item hamoa_items[] = { { ETFSWAO_REG, 0x1000, "etfswao-reg" }, }; +static const struct dump_item shikra_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C0_SCANDUMP, 0x10000, "c0-scandump" }, + { C100_SCANDUMP, 0x10000, "c100-scandump" }, + { C200_SCANDUMP, 0x10000, "c200-scandump" }, + { C300_SCANDUMP, 0x40000, "c300-scandump" }, + { L1_ICACHE0, 0x8900, "l1-icache0" }, + { L1_ICACHE100, 0x8900, "l1-icache100" }, + { L1_ICACHE200, 0x8900, "l1-icache200" }, + { L1_ICACHE300, 0x8900, "l1-icache300" }, + { L1_DCACHE0, 0x9100, "l1-dcache0" }, + { L1_DCACHE100, 0x9100, "l1-dcache100" }, + { L1_DCACHE200, 0x9100, "l1-dcache200" }, + { L1_DCACHE300, 0x9100, "l1-dcache300" }, + { L2_TLB0, 0x2100, "l2-tlb0" }, + { L2_TLB100, 0x2100, "l2-tlb100" }, + { L2_TLB200, 0x2100, "l2-tlb200" }, + { L2_TLB300, 0x2100, "l2-tlb300" }, + { RPM_SW, 0x30000, "rpm-sw" }, + { PMIC, 0x40000, "pmic" }, + { FCM, 0x8400, "fcm" }, + { TMC_ETF, 0x8000, "tmc-etf" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETF_REG, 0x1000, "etf-reg" }, + { MISC_DATA, 0x1000, "misc-data" }, + { ETF_LPASS, 0x8000, "etf-lpass" }, +}; + static const struct dump_table lemans_dump_table = { .items = lemans_items, .num_of_items = ARRAY_SIZE(lemans_items), @@ -397,6 +428,13 @@ static const struct dump_table hamoa_dump_table = { .imem_size = 0x8, }; +static const struct dump_table shikra_dump_table = { + .items = shikra_items, + .num_of_items = ARRAY_SIZE(shikra_items), + .imem_base = 0xc11e010, + .imem_size = 0x8, +}; + static int __init mem_dump_dev_init(void) { int ret; @@ -486,6 +524,14 @@ static int __init mem_dump_dev_init(void) goto fail; break; + case 756: + case 758: + case 759: + ret = platform_device_add_data(mem_dump_pdev, + &shikra_dump_table, sizeof(shikra_dump_table)); + if (ret) + goto fail; + break; default: dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); ret = -EINVAL; From 9b5490611d6749390351467923f833153a7bdacd Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 10 Aug 2026 16:22:31 +0800 Subject: [PATCH 0062/1133] QCLINUX: memory-dump: add memory dump table for Glymur Glymur was reusing Hamoa's dump table, but its IMEM base address differs. Add a dedicated dump table for Glymur with the correct imem_base and register it under Glymur's chip IDs. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index fb9d4dc0dceab..0d44f2a7bf904 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -435,6 +435,13 @@ static const struct dump_table shikra_dump_table = { .imem_size = 0x8, }; +static const struct dump_table glymur_dump_table = { + .items = hamoa_items, + .num_of_items = ARRAY_SIZE(hamoa_items), + .imem_base = 0x14680010, + .imem_size = 0x8, +}; + static int __init mem_dump_dev_init(void) { int ret; @@ -512,12 +519,6 @@ static int __init mem_dump_dev_init(void) case 616: case 709: case 710: - /* Glymur chip IDs */ - case 662: - case 698: - case 699: - case 718: - case 719: ret = platform_device_add_data(mem_dump_pdev, &hamoa_dump_table, sizeof(hamoa_dump_table)); if (ret) @@ -532,6 +533,16 @@ static int __init mem_dump_dev_init(void) if (ret) goto fail; break; + case 662: + case 698: + case 699: + case 718: + case 719: + ret = platform_device_add_data(mem_dump_pdev, + &glymur_dump_table, sizeof(glymur_dump_table)); + if (ret) + goto fail; + break; default: dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); ret = -EINVAL; From eeb91de783a10ed7789c5d45eb415a44104c5707 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 10 Aug 2026 17:11:18 +0800 Subject: [PATCH 0063/1133] QCLINUX: memory-dump: add CPU8-CPU11 context entries for Hamoa Add C800-C1100 context dump items to Hamoa's dump table to cover CPU8-CPU11, and bump the ETR/ETFSWAO register dump sizes to match. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 0d44f2a7bf904..4fa6f108e493c 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -22,6 +22,16 @@ enum dump_ids { C500_CONTEXT = 0x5, C600_CONTEXT = 0x6, C700_CONTEXT = 0x7, + C800_CONTEXT = 0x8, + C900_CONTEXT = 0x9, + C1000_CONTEXT = 0xa, + C1100_CONTEXT = 0xb, + C1200_CONTEXT = 0xc, + C1300_CONTEXT = 0xd, + C1400_CONTEXT = 0xe, + C1500_CONTEXT = 0xf, + C1600_CONTEXT = 0x10, + C1700_CONTEXT = 0x11, L1_ITLB10000 = 0x24, L1_ITLB10100 = 0x25, L1_ITLB10200 = 0x26, @@ -348,11 +358,15 @@ static const struct dump_item hamoa_items[] = { { C500_CONTEXT, 0x800, "c500-context" }, { C600_CONTEXT, 0x800, "c600-context" }, { C700_CONTEXT, 0x800, "c700-context" }, + { C800_CONTEXT, 0x800, "c800-context" }, + { C900_CONTEXT, 0x800, "c900-context" }, + { C1000_CONTEXT, 0x800, "c1000-context" }, + { C1100_CONTEXT, 0x800, "c1100-context" }, { RPMH, 0xc10000, "rpmh" }, { PMIC, 0x200000, "pmic" }, { ETF_SWAO, 0x10000, "etf-swao" }, - { ETR_REG, 0x1000, "etr-reg" }, - { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { ETR_REG, 0x4000, "etr-reg" }, + { ETFSWAO_REG, 0x4000, "etfswao-reg" }, }; static const struct dump_item shikra_items[] = { From c90fa85ab6b7e00d9a9450ce423634b33896d57f Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 10 Aug 2026 17:15:10 +0800 Subject: [PATCH 0064/1133] QCLINUX: memory-dump: add dedicated dump table for Glymur Glymur was reusing Hamoa's dump table, but it has additional CPUs. Add a dedicated Glymur dump table with Hamoa's items plus C1200-C1700 context entries to cover CPU12-CPU17. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 30 +++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 4fa6f108e493c..6a2dc5d6d335e 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -369,6 +369,32 @@ static const struct dump_item hamoa_items[] = { { ETFSWAO_REG, 0x4000, "etfswao-reg" }, }; +static const struct dump_item glymur_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c100-context" }, + { C200_CONTEXT, 0x800, "c200-context" }, + { C300_CONTEXT, 0x800, "c300-context" }, + { C400_CONTEXT, 0x800, "c400-context" }, + { C500_CONTEXT, 0x800, "c500-context" }, + { C600_CONTEXT, 0x800, "c600-context" }, + { C700_CONTEXT, 0x800, "c700-context" }, + { C800_CONTEXT, 0x800, "c800-context" }, + { C900_CONTEXT, 0x800, "c900-context" }, + { C1000_CONTEXT, 0x800, "c1000-context" }, + { C1100_CONTEXT, 0x800, "c1100-context" }, + { C1200_CONTEXT, 0x800, "c1200-context" }, + { C1300_CONTEXT, 0x800, "c1300-context" }, + { C1400_CONTEXT, 0x800, "c1400-context" }, + { C1500_CONTEXT, 0x800, "c1500-context" }, + { C1600_CONTEXT, 0x800, "c1600-context" }, + { C1700_CONTEXT, 0x800, "c1700-context" }, + { RPMH, 0xc10000, "rpmh" }, + { PMIC, 0x200000, "pmic" }, + { ETF_SWAO, 0x10000, "etf-swao" }, + { ETR_REG, 0x4000, "etr-reg" }, + { ETFSWAO_REG, 0x4000, "etfswao-reg" }, +}; + static const struct dump_item shikra_items[] = { { C0_CONTEXT, 0x800, "c0-context" }, { C100_CONTEXT, 0x800, "c100-context" }, @@ -450,8 +476,8 @@ static const struct dump_table shikra_dump_table = { }; static const struct dump_table glymur_dump_table = { - .items = hamoa_items, - .num_of_items = ARRAY_SIZE(hamoa_items), + .items = glymur_items, + .num_of_items = ARRAY_SIZE(glymur_items), .imem_base = 0x14680010, .imem_size = 0x8, }; From 412e82ca46d5da5ab83834a071edf4f1ce93d5b4 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 13 Aug 2026 09:59:48 +0800 Subject: [PATCH 0065/1133] QCLINUX: memory-dump: extend SPR CPU dump range to CPU11 Replace the SPR_DUMP_CPU1-CPU7 macros with SPR_DUMP_CPU11 and update the range check in mem_dump_alloc() so SPR dump initialization covers CPU0-CPU11 instead of stopping at CPU7. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_v2.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/firmware/qcom/memory_dump_v2.c b/drivers/firmware/qcom/memory_dump_v2.c index 831d1aea86e09..e8a4174ae7bb5 100644 --- a/drivers/firmware/qcom/memory_dump_v2.c +++ b/drivers/firmware/qcom/memory_dump_v2.c @@ -29,13 +29,7 @@ #define CPUSS_REGDUMP 0xEF #define SPR_DUMP_CPU0 0x1F0 -#define SPR_DUMP_CPU1 0x1F1 -#define SPR_DUMP_CPU2 0x1F2 -#define SPR_DUMP_CPU3 0x1F3 -#define SPR_DUMP_CPU4 0x1F4 -#define SPR_DUMP_CPU5 0x1F5 -#define SPR_DUMP_CPU6 0x1F6 -#define SPR_DUMP_CPU7 0x1F7 +#define SPR_DUMP_CPU11 0x1Fb #define SPR_DATA_HEADER_SIZE 5 #define SPR_DATA_HEADER_TAIL_SIZE 1 #define SPR_INPUT_DATA_TAIL_SIZE 1 @@ -1061,7 +1055,7 @@ static int mem_dump_alloc(struct platform_device *pdev) id); if ((id == CPUSS_REGDUMP) || - ((id >= SPR_DUMP_CPU0) && (id <= SPR_DUMP_CPU7))) + ((id >= SPR_DUMP_CPU0) && (id <= SPR_DUMP_CPU11))) initialized = cpuss_dump_init(pdev, (dump_vaddr + MSM_DUMP_DATA_SIZE), size, id); From f56999d046222402a87cc12f914ba9b049080020 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 13 Aug 2026 09:34:32 +0800 Subject: [PATCH 0066/1133] QCLINUX: memory-dump: add SPR/cache dump entries for Hamoa Add per-CPU SPR context, per-CPU and per-cluster cache dump entries, a combined CPU context entry, and the CPUSS_REG dump item to Hamoa's dump table to cover CPU0-CPU11. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 57 +++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 6a2dc5d6d335e..56a8422c20dbb 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -99,7 +99,35 @@ enum dump_ids { OSM_REG = 0x163, PCU_REG = 0x164, FSM_DATA = 0x165, + SPR_CPU0 = 0x1f0, + SPR_CPU1 = 0x1f1, + SPR_CPU2 = 0x1f2, + SPR_CPU3 = 0x1f3, + SPR_CPU4 = 0x1f4, + SPR_CPU5 = 0x1f5, + SPR_CPU6 = 0x1f6, + SPR_CPU7 = 0x1f7, + SPR_CPU8 = 0x1f8, + SPR_CPU9 = 0x1f9, + SPR_CPU10 = 0x1fa, + SPR_CPU11 = 0x1fb, SCANDUMP_SMMU = 0x220, + CACHE_CPU0 = 0x230, + CACHE_CPU1 = 0x231, + CACHE_CPU2 = 0x232, + CACHE_CPU3 = 0x233, + CACHE_CPU4 = 0x234, + CACHE_CPU5 = 0x235, + CACHE_CPU6 = 0x236, + CACHE_CPU7 = 0x237, + CACHE_CPU8 = 0x238, + CACHE_CPU9 = 0x239, + CACHE_CPU10 = 0x23a, + CACHE_CPU11 = 0x23b, + CACHE_CLUSTER0 = 0x240, + CACHE_CLUSTER1 = 0x241, + CACHE_CLUSTER2 = 0x242, + C_CONTEXT = 0x250, }; static const struct dump_item lemans_items[] = { @@ -362,11 +390,40 @@ static const struct dump_item hamoa_items[] = { { C900_CONTEXT, 0x800, "c900-context" }, { C1000_CONTEXT, 0x800, "c1000-context" }, { C1100_CONTEXT, 0x800, "c1100-context" }, + { CPUSS_REG, 0xa00000, "cpuss-reg" }, { RPMH, 0xc10000, "rpmh" }, { PMIC, 0x200000, "pmic" }, { ETF_SWAO, 0x10000, "etf-swao" }, { ETR_REG, 0x4000, "etr-reg" }, { ETFSWAO_REG, 0x4000, "etfswao-reg" }, + { SPR_CPU0, 0x2000, "spr-cpu0" }, + { SPR_CPU1, 0x2000, "spr-cpu1" }, + { SPR_CPU2, 0x2000, "spr-cpu2" }, + { SPR_CPU3, 0x2000, "spr-cpu3" }, + { SPR_CPU4, 0x2000, "spr-cpu4" }, + { SPR_CPU5, 0x2000, "spr-cpu5" }, + { SPR_CPU6, 0x2000, "spr-cpu6" }, + { SPR_CPU7, 0x2000, "spr-cpu7" }, + { SPR_CPU8, 0x2000, "spr-cpu8" }, + { SPR_CPU9, 0x2000, "spr-cpu9" }, + { SPR_CPU10, 0x2000, "spr-cpu10" }, + { SPR_CPU11, 0x2000, "spr-cpu11" }, + { CACHE_CPU0, 0x2aa000, "cache-cpu0" }, + { CACHE_CPU1, 0x2aa000, "cache-cpu1" }, + { CACHE_CPU2, 0x2aa000, "cache-cpu2" }, + { CACHE_CPU3, 0x2aa000, "cache-cpu3" }, + { CACHE_CPU4, 0x2aa000, "cache-cpu4" }, + { CACHE_CPU5, 0x2aa000, "cache-cpu5" }, + { CACHE_CPU6, 0x2aa000, "cache-cpu6" }, + { CACHE_CPU7, 0x2aa000, "cache-cpu7" }, + { CACHE_CPU8, 0x2aa000, "cache-cpu8" }, + { CACHE_CPU9, 0x2aa000, "cache-cpu9" }, + { CACHE_CPU10, 0x2aa000, "cache-cpu10" }, + { CACHE_CPU11, 0x2aa000, "cache-cpu11" }, + { CACHE_CLUSTER0, 0x2430000, "cache-cluster0" }, + { CACHE_CLUSTER1, 0x2430000, "cache-cluster1" }, + { CACHE_CLUSTER2, 0x2430000, "cache-cluster2" }, + { C_CONTEXT, 0x2af0, "cpu-context" }, }; static const struct dump_item glymur_items[] = { From d65827ea2dd5e69b256239530333f29e8fb6caf9 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 13 Aug 2026 09:40:24 +0800 Subject: [PATCH 0067/1133] QCLINUX: memory-dump: add SPR/cache dump entries for Glymur Add per-CPU SPR context, per-CPU and per-cluster cache dump entries, a combined CPU context entry, and the CPUSS_REG dump item to Glymur's dump table to cover CPU0-CPU11. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 56a8422c20dbb..3e84a1405d532 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -445,11 +445,40 @@ static const struct dump_item glymur_items[] = { { C1500_CONTEXT, 0x800, "c1500-context" }, { C1600_CONTEXT, 0x800, "c1600-context" }, { C1700_CONTEXT, 0x800, "c1700-context" }, + { CPUSS_REG, 0xa00000, "cpuss-reg" }, { RPMH, 0xc10000, "rpmh" }, { PMIC, 0x200000, "pmic" }, { ETF_SWAO, 0x10000, "etf-swao" }, { ETR_REG, 0x4000, "etr-reg" }, { ETFSWAO_REG, 0x4000, "etfswao-reg" }, + { SPR_CPU0, 0x2000, "spr-cpu0" }, + { SPR_CPU1, 0x2000, "spr-cpu1" }, + { SPR_CPU2, 0x2000, "spr-cpu2" }, + { SPR_CPU3, 0x2000, "spr-cpu3" }, + { SPR_CPU4, 0x2000, "spr-cpu4" }, + { SPR_CPU5, 0x2000, "spr-cpu5" }, + { SPR_CPU6, 0x2000, "spr-cpu6" }, + { SPR_CPU7, 0x2000, "spr-cpu7" }, + { SPR_CPU8, 0x2000, "spr-cpu8" }, + { SPR_CPU9, 0x2000, "spr-cpu9" }, + { SPR_CPU10, 0x2000, "spr-cpu10" }, + { SPR_CPU11, 0x2000, "spr-cpu11" }, + { CACHE_CPU0, 0x2aa000, "cache-cpu0" }, + { CACHE_CPU1, 0x2aa000, "cache-cpu1" }, + { CACHE_CPU2, 0x2aa000, "cache-cpu2" }, + { CACHE_CPU3, 0x2aa000, "cache-cpu3" }, + { CACHE_CPU4, 0x2aa000, "cache-cpu4" }, + { CACHE_CPU5, 0x2aa000, "cache-cpu5" }, + { CACHE_CPU6, 0x2aa000, "cache-cpu6" }, + { CACHE_CPU7, 0x2aa000, "cache-cpu7" }, + { CACHE_CPU8, 0x2aa000, "cache-cpu8" }, + { CACHE_CPU9, 0x2aa000, "cache-cpu9" }, + { CACHE_CPU10, 0x2aa000, "cache-cpu10" }, + { CACHE_CPU11, 0x2aa000, "cache-cpu11" }, + { CACHE_CLUSTER0, 0x2430000, "cache-cluster0" }, + { CACHE_CLUSTER1, 0x2430000, "cache-cluster1" }, + { CACHE_CLUSTER2, 0x2430000, "cache-cluster2" }, + { C_CONTEXT, 0x4050, "cpu-context" }, }; static const struct dump_item shikra_items[] = { From f017bf6f887ed0f8d4dab8daf094d220bfef2135 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 13 Aug 2026 16:10:42 +0800 Subject: [PATCH 0068/1133] QCLINUX: firmware: qcom: memory_dump_v2: assign dump table region to non-secure world Add assign_dump_table_region() to notify TZ that the memory dump table region should be made accessible to AOP, via a self-contained SCM SMC call (QCOM_SCM_SVC_UTIL / QCOM_SCM_UTIL_DUMP_TABLE_ASSIGN). The SMC convention probe (__get_convention()) and dispatch helper are kept local to this driver rather than exported from qcom_scm, since only the register-argument SMC path is needed here. Wire it into mem_dump_alloc(), falling back to the IMEM-based dump table registration path if the SCM call fails. signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_v2.c | 135 ++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/qcom/memory_dump_v2.c b/drivers/firmware/qcom/memory_dump_v2.c index e8a4174ae7bb5..af1103bd1a6da 100644 --- a/drivers/firmware/qcom/memory_dump_v2.c +++ b/drivers/firmware/qcom/memory_dump_v2.c @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include "qcom_scm.h" #define MSM_DUMP_TABLE_VERSION MSM_DUMP_MAKE_VERSION(2, 0) @@ -62,6 +65,10 @@ #define EXTRA_VALUE_MASK GENMASK(23, 0) #define MAX_EXTRA_VALUE 0xffffff +/* IDs for Dump Table*/ +#define QCOM_SCM_SVC_UTIL 0x03 +#define QCOM_SCM_UTIL_DUMP_TABLE_ASSIGN 0x13 + struct sprs_dump_data { void *dump_vaddr; u32 size; @@ -984,6 +991,125 @@ void __init reserve_memdump_cma(void) } } +static enum qcom_scm_convention memdump_scm_convention = SMC_CONVENTION_UNKNOWN; +static DEFINE_SPINLOCK(memdump_scm_query_lock); + +#define MEMDUMP_SCM_N_REG_ARGS 4 +#define MEMDUMP_SCM_FIRST_REG_IDX 2 + +static int memdump_scm_smc_call(const struct qcom_scm_desc *desc, + enum qcom_scm_convention convention, + struct qcom_scm_res *res, bool atomic) +{ + int i; + u32 smccc_call_type = atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL; + u32 qcom_smccc_convention = (convention == SMC_CONVENTION_ARM_32) ? + ARM_SMCCC_SMC_32 : ARM_SMCCC_SMC_64; + struct arm_smccc_res smc_res; + struct arm_smccc_quirk quirk = { .id = ARM_SMCCC_QUIRK_QCOM_A6 }; + unsigned long args[8] = {0}; + + args[0] = ARM_SMCCC_CALL_VAL(smccc_call_type, qcom_smccc_convention, + desc->owner, + SCM_SMC_FNID(desc->svc, desc->cmd)); + args[1] = desc->arginfo; + for (i = 0; i < MEMDUMP_SCM_N_REG_ARGS; i++) + args[i + MEMDUMP_SCM_FIRST_REG_IDX] = desc->args[i]; + + quirk.state.a6 = 0; + do { + arm_smccc_smc_quirk(args[0], args[1], args[2], args[3], + args[4], args[5], quirk.state.a6, + args[7], &smc_res, &quirk); + + if (smc_res.a0 == QCOM_SCM_INTERRUPTED) + args[0] = smc_res.a0; + } while (smc_res.a0 == QCOM_SCM_INTERRUPTED); + + if (res) { + res->result[0] = smc_res.a1; + res->result[1] = smc_res.a2; + res->result[2] = smc_res.a3; + } + + if (smc_res.a0 == QCOM_SCM_WAITQ_SLEEP) + pr_err("SCM call (svc=%#x cmd=%#x) requested WAITQ_SLEEP resume, which is unsupported here\n", + desc->svc, desc->cmd); + + return (long)smc_res.a0 ? qcom_scm_remap_error(smc_res.a0) : 0; +} + +static enum qcom_scm_convention __get_convention(void) +{ + unsigned long flags; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_INFO, + .cmd = QCOM_SCM_INFO_IS_CALL_AVAIL, + .args[0] = SCM_SMC_FNID(QCOM_SCM_SVC_INFO, + QCOM_SCM_INFO_IS_CALL_AVAIL) | + (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT), + .arginfo = QCOM_SCM_ARGS(1), + .owner = ARM_SMCCC_OWNER_SIP, + }; + struct qcom_scm_res res; + enum qcom_scm_convention probed_convention; + int ret; + + if (likely(memdump_scm_convention != SMC_CONVENTION_UNKNOWN)) + return memdump_scm_convention; + + /* + * Per the "SMC calling convention specification", the 64-bit calling + * convention can only be used when the client is 64-bit, otherwise + * system will encounter the undefined behaviour. + */ +#if IS_ENABLED(CONFIG_ARM64) + probed_convention = SMC_CONVENTION_ARM_64; + ret = memdump_scm_smc_call(&desc, probed_convention, &res, true); + if (!ret && res.result[0] == 1) + goto found; +#endif + + probed_convention = SMC_CONVENTION_ARM_32; + ret = memdump_scm_smc_call(&desc, probed_convention, &res, true); + if (!ret && res.result[0] == 1) + goto found; + + probed_convention = SMC_CONVENTION_LEGACY; +found: + spin_lock_irqsave(&memdump_scm_query_lock, flags); + memdump_scm_convention = probed_convention; + spin_unlock_irqrestore(&memdump_scm_query_lock, flags); + + return memdump_scm_convention; +} + +static int assign_dump_table_region(bool is_assign, phys_addr_t addr, size_t size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_UTIL, + .cmd = QCOM_SCM_UTIL_DUMP_TABLE_ASSIGN, + .arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL), + .owner = ARM_SMCCC_OWNER_SIP, + .args[0] = is_assign, + .args[1] = addr, + .args[2] = size, + }; + struct qcom_scm_res res; + enum qcom_scm_convention convention = __get_convention(); + int ret; + + might_sleep(); + switch (convention) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + return memdump_scm_smc_call(&desc, convention, &res, false); + default: + pr_err("Unsupported SCM calling convention.\n"); + return -EOPNOTSUPP; + } +} + #define MSM_DUMP_DATA_SIZE sizeof(struct msm_dump_data) static int mem_dump_alloc(struct platform_device *pdev) { @@ -1030,10 +1156,13 @@ static int mem_dump_alloc(struct platform_device *pdev) return ret; } - ret = init_memdump_imem_area(table, total_size); + ret = assign_dump_table_region(1, phys_addr, total_size); if (ret) { - qcom_tzmem_shm_bridge_delete(shm_bridge_handle); - return ret; + ret = init_memdump_imem_area(table, total_size); + if (ret) { + qcom_tzmem_shm_bridge_delete(shm_bridge_handle); + return ret; + } } dump_vaddr += (sizeof(struct msm_dump_table) * 2); From 4b9754e015de244843473daaf94f931880bcf8cc Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 15 Sep 2026 16:38:39 +0800 Subject: [PATCH 0069/1133] QCLINUX: memory-dump: extend MAX_CORE_NUM to 12 MAX_CORE_NUM bounds the sprdata[] array and the SPR CPU index checks in mem_dump_alloc()/spr_config_store(). It was still set to 8 even though the SPR dump range was already extended to cover CPU0-CPU11. Bump it to 12 so all cores are accounted for. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/memory_dump_v2.c b/drivers/firmware/qcom/memory_dump_v2.c index af1103bd1a6da..8300f5080edb3 100644 --- a/drivers/firmware/qcom/memory_dump_v2.c +++ b/drivers/firmware/qcom/memory_dump_v2.c @@ -38,7 +38,7 @@ #define SPR_INPUT_DATA_TAIL_SIZE 1 #define SPR_INPUT_DATA_SIZE 1 #define SPR_OUTPUT_DATA_SIZE 2 -#define MAX_CORE_NUM 8 +#define MAX_CORE_NUM 12 #define INPUT_DATA_BY_HLOS 0x00C0FFEE #define FORMAT_VERSION_1 0x1 From 92757057bb4a1c54f4cd80727e56b11c3b99c1fd Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Thu, 17 Sep 2026 15:10:09 +0530 Subject: [PATCH 0070/1133] FROMLIST: phy: qualcomm: phy-qcom-eusb2-repeater: Fix SMB Power leakage issue On Glymur, it is observed that although the exit call is done, there is a power leakage seen on SMB2370 charger (which embeds the eUSB2 module as well). As per recommendation of HW team, disable the repeater during the exit call to prevent this power leakage. Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Link: https://lore.kernel.org/all/20260917-smb-repeater-power-leakage-v1-1-6d7311c3c03e@oss.qualcomm.com/ Signed-off-by: Krishna Kurapati --- drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c b/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c index efeec4709a15d..7db2fbff61638 100644 --- a/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c +++ b/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c @@ -229,7 +229,10 @@ static int eusb2_repeater_set_mode(struct phy *phy, static int eusb2_repeater_exit(struct phy *phy) { struct eusb2_repeater *rptr = phy_get_drvdata(phy); + struct regmap *regmap = rptr->regmap; + u32 base = rptr->base; + regmap_write(regmap, base + EUSB2_EN_CTL1, 0); return regulator_bulk_disable(rptr->cfg->num_vregs, rptr->vregs); } From 4fcc5aca7386ce276947933ca7df54508ec9fbcd Mon Sep 17 00:00:00 2001 From: Xu Rao Date: Wed, 12 Aug 2026 17:46:32 +0800 Subject: [PATCH 0071/1133] UPSTREAM: usb: typec: hd3ss3220: fix VBUS regulator error message hd3ss3220_regulator_control() enables the VBUS regulator when @on is true and disables it when @on is false. However, its error message uses the opposite operation name, so an enable failure is reported as a disable failure and vice versa. Print the operation that was actually attempted. Reporting the opposite regulator operation on failures can mislead debugging of VBUS problems. Fixes: 27fbc19e52b9 ("usb: typec: hd3ss3220: Enable VBUS based on role state") Cc: stable@vger.kernel.org Reviewed-by: Heikki Krogerus Signed-off-by: Xu Rao Link: https://patch.msgid.link/7A42A287B2B588D0+20260812094632.348581-1-raoxu@uniontech.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Krishna Kurapati --- drivers/usb/typec/hd3ss3220.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/typec/hd3ss3220.c b/drivers/usb/typec/hd3ss3220.c index b56df9349f89b..b63e0bfe5ecc6 100644 --- a/drivers/usb/typec/hd3ss3220.c +++ b/drivers/usb/typec/hd3ss3220.c @@ -218,7 +218,7 @@ static void hd3ss3220_regulator_control(struct hd3ss3220 *hd3ss3220, bool on) if (ret) dev_err(hd3ss3220->dev, - "vbus regulator %s failed: %d\n", on ? "disable" : "enable", ret); + "vbus regulator %s failed: %d\n", on ? "enable" : "disable", ret); } static void hd3ss3220_set_role(struct hd3ss3220 *hd3ss3220) From b94824df2da48cbe95cc99a0fdd2bd309605f79e Mon Sep 17 00:00:00 2001 From: Chang Wu Date: Wed, 19 Aug 2026 23:20:27 +0800 Subject: [PATCH 0072/1133] UPSTREAM: usb: typec: hd3ss3220: track VBUS enable state per consumer regulator_is_enabled() reports the aggregate regulator state, not whether this consumer holds an enable reference. If another consumer enables VBUS first, the driver can skip its own regulator_enable() call and later attempt to drop a reference it never acquired, triggering an unbalanced regulator disable warning. Track successful enable and disable calls locally. Keep the state unchanged when an operation fails so a later role or ID notification retries the operation while this consumer keeps balanced references. Fixes: b3f9d6e491fd ("usb: typec: hd3ss3220: Check if regulator needs to be switched") Cc: stable Link: https://github.com/qualcomm-linux/kernel/issues/472 Signed-off-by: Chang Wu Reviewed-by: Heikki Krogerus Tested-by: Jan Remmet Reviewed-by: Krishna Kurapati Link: https://patch.msgid.link/20260819152027.90994-1-kunjinkao.jp@gmail.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Krishna Kurapati --- drivers/usb/typec/hd3ss3220.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/typec/hd3ss3220.c b/drivers/usb/typec/hd3ss3220.c index b63e0bfe5ecc6..8d0f38fb70442 100644 --- a/drivers/usb/typec/hd3ss3220.c +++ b/drivers/usb/typec/hd3ss3220.c @@ -62,6 +62,7 @@ struct hd3ss3220 { int id_irq; struct regulator *vbus; + bool vbus_enabled; }; static int hd3ss3220_set_power_opmode(struct hd3ss3220 *hd3ss3220, int power_opmode) @@ -208,7 +209,7 @@ static void hd3ss3220_regulator_control(struct hd3ss3220 *hd3ss3220, bool on) { int ret; - if (regulator_is_enabled(hd3ss3220->vbus) == on) + if (hd3ss3220->vbus_enabled == on) return; if (on) @@ -216,9 +217,13 @@ static void hd3ss3220_regulator_control(struct hd3ss3220 *hd3ss3220, bool on) else ret = regulator_disable(hd3ss3220->vbus); - if (ret) + if (ret) { dev_err(hd3ss3220->dev, "vbus regulator %s failed: %d\n", on ? "enable" : "disable", ret); + return; + } + + hd3ss3220->vbus_enabled = on; } static void hd3ss3220_set_role(struct hd3ss3220 *hd3ss3220) From 81fc6e2c356d01f1606ae1323b1b1ef3b6db0ad2 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 15 Sep 2026 13:37:03 +0100 Subject: [PATCH 0073/1133] Revert "interconnect: qcom: x1e80100: enable QoS configuration" This reverts commit 5a8b2cc36e796d595c9d97eab23c2be22805cc1c. Since the introduction of this QoS change, X1 machines based on the Purwa SoC (such as the Lenovo Mini X) take a hard reset at boot time. Other machines based on Hamoa (such as the X1E001DE Snapdragon Devkit) end-up with a similar hard reset while under load, most likely due to the PCIe ports being starved of traffic. Revert the whole thing until someone figures out what magic parameters allow QoS to work in a sensible manner, as a usable machine is somehow preferable to one that crashes efficiently. Link: https://lore.kernel.org/all/apgeBNSiP01YfNcs@google.com Link: https://lore.kernel.org/all/86ld9d4h4n.wl-maz@kernel.org Signed-off-by: Marc Zyngier Cc: Georgi Djakov Cc: Raviteja Laggyshetty Cc: Konrad Dybcio Cc: Abel Vesa Cc: Bjorn Andersson Cc: Mostafa Saleh Cc: Thorsten Leemhuis Reviewed-by: Mostafa Saleh Tested-by: Mostafa Saleh Reviewed-by: Abel Vesa --- drivers/interconnect/qcom/x1e80100.c | 485 --------------------------- 1 file changed, 485 deletions(-) diff --git a/drivers/interconnect/qcom/x1e80100.c b/drivers/interconnect/qcom/x1e80100.c index 8075e0ff20597..2ba2823c7860e 100644 --- a/drivers/interconnect/qcom/x1e80100.c +++ b/drivers/interconnect/qcom/x1e80100.c @@ -173,13 +173,6 @@ static struct qcom_icc_node qhm_qspi = { .name = "qhm_qspi", .channels = 1, .buswidth = 4, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xb000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_a1noc_snoc }, }; @@ -188,13 +181,6 @@ static struct qcom_icc_node qhm_qup1 = { .name = "qhm_qup1", .channels = 1, .buswidth = 4, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xc000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_a1noc_snoc }, }; @@ -203,13 +189,6 @@ static struct qcom_icc_node xm_sdc4 = { .name = "xm_sdc4", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xd000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_a1noc_snoc }, }; @@ -218,13 +197,6 @@ static struct qcom_icc_node xm_ufs_mem = { .name = "xm_ufs_mem", .channels = 1, .buswidth = 16, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xe000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_a1noc_snoc }, }; @@ -233,13 +205,6 @@ static struct qcom_icc_node qhm_qup0 = { .name = "qhm_qup0", .channels = 1, .buswidth = 4, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x16000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_a2noc_snoc }, }; @@ -248,13 +213,6 @@ static struct qcom_icc_node qhm_qup2 = { .name = "qhm_qup2", .channels = 1, .buswidth = 4, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x11000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_a2noc_snoc }, }; @@ -263,13 +221,6 @@ static struct qcom_icc_node qxm_crypto = { .name = "qxm_crypto", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x12000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_a2noc_snoc }, }; @@ -286,13 +237,6 @@ static struct qcom_icc_node xm_qdss_etr_0 = { .name = "xm_qdss_etr_0", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x13000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_a2noc_snoc }, }; @@ -301,13 +245,6 @@ static struct qcom_icc_node xm_qdss_etr_1 = { .name = "xm_qdss_etr_1", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x14000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_a2noc_snoc }, }; @@ -316,13 +253,6 @@ static struct qcom_icc_node xm_sdc2 = { .name = "xm_sdc2", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x15000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_a2noc_snoc }, }; @@ -407,13 +337,6 @@ static struct qcom_icc_node alm_gpu_tcu = { .name = "alm_gpu_tcu", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x271000 }, - .prio = 1, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 2, .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc }, }; @@ -422,13 +345,6 @@ static struct qcom_icc_node alm_pcie_tcu = { .name = "alm_pcie_tcu", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x27d000 }, - .prio = 3, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 2, .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc }, }; @@ -437,13 +353,6 @@ static struct qcom_icc_node alm_sys_tcu = { .name = "alm_sys_tcu", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x273000 }, - .prio = 6, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 2, .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc }, }; @@ -461,13 +370,6 @@ static struct qcom_icc_node qnm_gpu = { .name = "qnm_gpu", .channels = 4, .buswidth = 32, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 4, - .port_offsets = { 0x51000, 0x58000, 0xd1000, 0xd8000 }, - .prio = 0, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 2, .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc }, }; @@ -476,13 +378,6 @@ static struct qcom_icc_node qnm_lpass = { .name = "qnm_lpass", .channels = 1, .buswidth = 16, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x275000 }, - .prio = 0, - .urg_fwd = 1, - .prio_fwd_disable = 0, - }, .num_links = 3, .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, &qns_pcie }, @@ -492,13 +387,6 @@ static struct qcom_icc_node qnm_mnoc_hf = { .name = "qnm_mnoc_hf", .channels = 2, .buswidth = 32, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 2, - .port_offsets = { 0x53000, 0xd3000 }, - .prio = 0, - .urg_fwd = 1, - .prio_fwd_disable = 0, - }, .num_links = 2, .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc }, }; @@ -507,13 +395,6 @@ static struct qcom_icc_node qnm_mnoc_sf = { .name = "qnm_mnoc_sf", .channels = 2, .buswidth = 32, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 2, - .port_offsets = { 0x55000, 0xd5000 }, - .prio = 0, - .urg_fwd = 1, - .prio_fwd_disable = 0, - }, .num_links = 2, .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc }, }; @@ -522,13 +403,6 @@ static struct qcom_icc_node qnm_nsp_noc = { .name = "qnm_nsp_noc", .channels = 2, .buswidth = 32, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 2, - .port_offsets = { 0x57000, 0xd7000 }, - .prio = 0, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 3, .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, &qns_pcie }, @@ -538,13 +412,6 @@ static struct qcom_icc_node qnm_pcie = { .name = "qnm_pcie", .channels = 1, .buswidth = 64, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x277000 }, - .prio = 0, - .urg_fwd = 1, - .prio_fwd_disable = 0, - }, .num_links = 2, .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc }, }; @@ -553,13 +420,6 @@ static struct qcom_icc_node qnm_snoc_sf = { .name = "qnm_snoc_sf", .channels = 1, .buswidth = 64, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x27b000 }, - .prio = 2, - .urg_fwd = 1, - .prio_fwd_disable = 0, - }, .num_links = 3, .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc, &qns_pcie }, @@ -569,13 +429,6 @@ static struct qcom_icc_node xm_gic = { .name = "xm_gic", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x27f000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_llcc }, }; @@ -616,13 +469,6 @@ static struct qcom_icc_node qnm_av1_enc = { .name = "qnm_av1_enc", .channels = 1, .buswidth = 32, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x2f000 }, - .prio = 4, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_mem_noc_sf }, }; @@ -631,13 +477,6 @@ static struct qcom_icc_node qnm_camnoc_hf = { .name = "qnm_camnoc_hf", .channels = 2, .buswidth = 32, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 2, - .port_offsets = { 0x28000, 0x29000 }, - .prio = 0, - .urg_fwd = 1, - .prio_fwd_disable = 0, - }, .num_links = 1, .link_nodes = { &qns_mem_noc_hf }, }; @@ -646,13 +485,6 @@ static struct qcom_icc_node qnm_camnoc_icp = { .name = "qnm_camnoc_icp", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x2a000 }, - .prio = 4, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_mem_noc_sf }, }; @@ -661,13 +493,6 @@ static struct qcom_icc_node qnm_camnoc_sf = { .name = "qnm_camnoc_sf", .channels = 2, .buswidth = 32, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 2, - .port_offsets = { 0x2b000, 0x2c000 }, - .prio = 0, - .urg_fwd = 1, - .prio_fwd_disable = 0, - }, .num_links = 1, .link_nodes = { &qns_mem_noc_sf }, }; @@ -676,13 +501,6 @@ static struct qcom_icc_node qnm_eva = { .name = "qnm_eva", .channels = 1, .buswidth = 32, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x33000 }, - .prio = 0, - .urg_fwd = 1, - .prio_fwd_disable = 0, - }, .num_links = 1, .link_nodes = { &qns_mem_noc_sf }, }; @@ -691,13 +509,6 @@ static struct qcom_icc_node qnm_mdp = { .name = "qnm_mdp", .channels = 2, .buswidth = 32, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 2, - .port_offsets = { 0x2d000, 0x2e000 }, - .prio = 0, - .urg_fwd = 1, - .prio_fwd_disable = 0, - }, .num_links = 1, .link_nodes = { &qns_mem_noc_hf }, }; @@ -706,13 +517,6 @@ static struct qcom_icc_node qnm_video = { .name = "qnm_video", .channels = 2, .buswidth = 32, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 2, - .port_offsets = { 0x30000, 0x31000 }, - .prio = 0, - .urg_fwd = 1, - .prio_fwd_disable = 0, - }, .num_links = 1, .link_nodes = { &qns_mem_noc_sf }, }; @@ -721,13 +525,6 @@ static struct qcom_icc_node qnm_video_cv_cpu = { .name = "qnm_video_cv_cpu", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x32000 }, - .prio = 4, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_mem_noc_sf }, }; @@ -736,13 +533,6 @@ static struct qcom_icc_node qnm_video_v_cpu = { .name = "qnm_video_v_cpu", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x34000 }, - .prio = 4, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_mem_noc_sf }, }; @@ -783,13 +573,6 @@ static struct qcom_icc_node xm_pcie_3 = { .name = "xm_pcie_3", .channels = 1, .buswidth = 64, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x7000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_pcie_north_gem_noc }, }; @@ -798,13 +581,6 @@ static struct qcom_icc_node xm_pcie_4 = { .name = "xm_pcie_4", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x8000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_pcie_north_gem_noc }, }; @@ -813,13 +589,6 @@ static struct qcom_icc_node xm_pcie_5 = { .name = "xm_pcie_5", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x9000 }, - .prio = 3, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_pcie_north_gem_noc }, }; @@ -828,13 +597,6 @@ static struct qcom_icc_node xm_pcie_0 = { .name = "xm_pcie_0", .channels = 1, .buswidth = 16, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x9000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_pcie_south_gem_noc }, }; @@ -843,13 +605,6 @@ static struct qcom_icc_node xm_pcie_1 = { .name = "xm_pcie_1", .channels = 1, .buswidth = 16, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xa000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_pcie_south_gem_noc }, }; @@ -858,13 +613,6 @@ static struct qcom_icc_node xm_pcie_2 = { .name = "xm_pcie_2", .channels = 1, .buswidth = 16, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xb000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_pcie_south_gem_noc }, }; @@ -873,13 +621,6 @@ static struct qcom_icc_node xm_pcie_6a = { .name = "xm_pcie_6a", .channels = 1, .buswidth = 32, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xc000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_pcie_south_gem_noc }, }; @@ -888,13 +629,6 @@ static struct qcom_icc_node xm_pcie_6b = { .name = "xm_pcie_6b", .channels = 1, .buswidth = 16, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xd000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_pcie_south_gem_noc }, }; @@ -919,13 +653,6 @@ static struct qcom_icc_node qnm_gic = { .name = "qnm_gic", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x1c000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_gemnoc_sf }, }; @@ -958,13 +685,6 @@ static struct qcom_icc_node xm_usb2_0 = { .name = "xm_usb2_0", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x6000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_aggre_usb_north_snoc }, }; @@ -973,13 +693,6 @@ static struct qcom_icc_node xm_usb3_mp = { .name = "xm_usb3_mp", .channels = 1, .buswidth = 16, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0x7000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_aggre_usb_north_snoc }, }; @@ -988,13 +701,6 @@ static struct qcom_icc_node xm_usb3_0 = { .name = "xm_usb3_0", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xa000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_aggre_usb_south_snoc }, }; @@ -1003,13 +709,6 @@ static struct qcom_icc_node xm_usb3_1 = { .name = "xm_usb3_1", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xb000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_aggre_usb_south_snoc }, }; @@ -1018,13 +717,6 @@ static struct qcom_icc_node xm_usb3_2 = { .name = "xm_usb3_2", .channels = 1, .buswidth = 8, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xc000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_aggre_usb_south_snoc }, }; @@ -1033,13 +725,6 @@ static struct qcom_icc_node xm_usb4_0 = { .name = "xm_usb4_0", .channels = 1, .buswidth = 16, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xd000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_aggre_usb_south_snoc }, }; @@ -1048,13 +733,6 @@ static struct qcom_icc_node xm_usb4_1 = { .name = "xm_usb4_1", .channels = 1, .buswidth = 16, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xe000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_aggre_usb_south_snoc }, }; @@ -1063,13 +741,6 @@ static struct qcom_icc_node xm_usb4_2 = { .name = "xm_usb4_2", .channels = 1, .buswidth = 16, - .qosbox = &(const struct qcom_icc_qosbox) { - .num_ports = 1, - .port_offsets = { 0xf000 }, - .prio = 2, - .urg_fwd = 0, - .prio_fwd_disable = 1, - }, .num_links = 1, .link_nodes = { &qns_aggre_usb_south_snoc }, }; @@ -1795,21 +1466,11 @@ static struct qcom_icc_node * const aggre1_noc_nodes[] = { [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc, }; -static const struct regmap_config x1e80100_aggre1_noc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x14400, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_aggre1_noc = { - .config = &x1e80100_aggre1_noc_regmap_config, .nodes = aggre1_noc_nodes, .num_nodes = ARRAY_SIZE(aggre1_noc_nodes), .bcms = aggre1_noc_bcms, .num_bcms = ARRAY_SIZE(aggre1_noc_bcms), - .qos_requires_clocks = true, }; static struct qcom_icc_bcm * const aggre2_noc_bcms[] = { @@ -1827,16 +1488,7 @@ static struct qcom_icc_node * const aggre2_noc_nodes[] = { [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc, }; -static const struct regmap_config x1e80100_aggre2_noc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x1c400, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_aggre2_noc = { - .config = &x1e80100_aggre2_noc_regmap_config, .nodes = aggre2_noc_nodes, .num_nodes = ARRAY_SIZE(aggre2_noc_nodes), .bcms = aggre2_noc_bcms, @@ -1921,16 +1573,7 @@ static struct qcom_icc_node * const cnoc_cfg_nodes[] = { [SLAVE_TCU] = &xs_sys_tcu_cfg, }; -static const struct regmap_config x1e80100_cnoc_cfg_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x6600, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_cnoc_cfg = { - .config = &x1e80100_cnoc_cfg_regmap_config, .nodes = cnoc_cfg_nodes, .num_nodes = ARRAY_SIZE(cnoc_cfg_nodes), .bcms = cnoc_cfg_bcms, @@ -1960,16 +1603,7 @@ static struct qcom_icc_node * const cnoc_main_nodes[] = { [SLAVE_PCIE_6B] = &xs_pcie_6b, }; -static const struct regmap_config x1e80100_cnoc_main_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x14400, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_cnoc_main = { - .config = &x1e80100_cnoc_main_regmap_config, .nodes = cnoc_main_nodes, .num_nodes = ARRAY_SIZE(cnoc_main_nodes), .bcms = cnoc_main_bcms, @@ -1999,16 +1633,7 @@ static struct qcom_icc_node * const gem_noc_nodes[] = { [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_pcie, }; -static const struct regmap_config x1e80100_gem_noc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x311200, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_gem_noc = { - .config = &x1e80100_gem_noc_regmap_config, .nodes = gem_noc_nodes, .num_nodes = ARRAY_SIZE(gem_noc_nodes), .bcms = gem_noc_bcms, @@ -2023,16 +1648,7 @@ static struct qcom_icc_node * const lpass_ag_noc_nodes[] = { [SLAVE_LPASS_GEM_NOC] = &qns_lpass_ag_noc_gemnoc, }; -static const struct regmap_config x1e80100_lpass_ag_noc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0xe080, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_lpass_ag_noc = { - .config = &x1e80100_lpass_ag_noc_regmap_config, .nodes = lpass_ag_noc_nodes, .num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes), .bcms = lpass_ag_noc_bcms, @@ -2048,16 +1664,7 @@ static struct qcom_icc_node * const lpass_lpiaon_noc_nodes[] = { [SLAVE_LPIAON_NOC_LPASS_AG_NOC] = &qns_lpass_aggnoc, }; -static const struct regmap_config x1e80100_lpass_lpiaon_noc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x19080, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_lpass_lpiaon_noc = { - .config = &x1e80100_lpass_lpiaon_noc_regmap_config, .nodes = lpass_lpiaon_noc_nodes, .num_nodes = ARRAY_SIZE(lpass_lpiaon_noc_nodes), .bcms = lpass_lpiaon_noc_bcms, @@ -2072,16 +1679,7 @@ static struct qcom_icc_node * const lpass_lpicx_noc_nodes[] = { [SLAVE_LPICX_NOC_LPIAON_NOC] = &qns_lpi_aon_noc, }; -static const struct regmap_config x1e80100_lpass_lpicx_noc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x3a200, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_lpass_lpicx_noc = { - .config = &x1e80100_lpass_lpicx_noc_regmap_config, .nodes = lpass_lpicx_noc_nodes, .num_nodes = ARRAY_SIZE(lpass_lpicx_noc_nodes), .bcms = lpass_lpicx_noc_bcms, @@ -2126,16 +1724,7 @@ static struct qcom_icc_node * const mmss_noc_nodes[] = { [SLAVE_SERVICE_MNOC] = &srvc_mnoc, }; -static const struct regmap_config x1e80100_mmss_noc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x5b800, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_mmss_noc = { - .config = &x1e80100_mmss_noc_regmap_config, .nodes = mmss_noc_nodes, .num_nodes = ARRAY_SIZE(mmss_noc_nodes), .bcms = mmss_noc_bcms, @@ -2151,16 +1740,7 @@ static struct qcom_icc_node * const nsp_noc_nodes[] = { [SLAVE_CDSP_MEM_NOC] = &qns_nsp_gemnoc, }; -static const struct regmap_config x1e80100_nsp_noc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0xe080, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_nsp_noc = { - .config = &x1e80100_nsp_noc_regmap_config, .nodes = nsp_noc_nodes, .num_nodes = ARRAY_SIZE(nsp_noc_nodes), .bcms = nsp_noc_bcms, @@ -2177,16 +1757,7 @@ static struct qcom_icc_node * const pcie_center_anoc_nodes[] = { [SLAVE_ANOC_PCIE_GEM_NOC] = &qns_pcie_mem_noc, }; -static const struct regmap_config x1e80100_pcie_center_anoc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x7000, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_pcie_center_anoc = { - .config = &x1e80100_pcie_center_anoc_regmap_config, .nodes = pcie_center_anoc_nodes, .num_nodes = ARRAY_SIZE(pcie_center_anoc_nodes), .bcms = pcie_center_anoc_bcms, @@ -2203,16 +1774,7 @@ static struct qcom_icc_node * const pcie_north_anoc_nodes[] = { [SLAVE_PCIE_NORTH] = &qns_pcie_north_gem_noc, }; -static const struct regmap_config x1e80100_pcie_north_anoc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x9080, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_pcie_north_anoc = { - .config = &x1e80100_pcie_north_anoc_regmap_config, .nodes = pcie_north_anoc_nodes, .num_nodes = ARRAY_SIZE(pcie_north_anoc_nodes), .bcms = pcie_north_anoc_bcms, @@ -2231,16 +1793,7 @@ static struct qcom_icc_node * const pcie_south_anoc_nodes[] = { [SLAVE_PCIE_SOUTH] = &qns_pcie_south_gem_noc, }; -static const struct regmap_config x1e80100_pcie_south_anoc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0xd080, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_pcie_south_anoc = { - .config = &x1e80100_pcie_south_anoc_regmap_config, .nodes = pcie_south_anoc_nodes, .num_nodes = ARRAY_SIZE(pcie_south_anoc_nodes), .bcms = pcie_south_anoc_bcms, @@ -2262,16 +1815,7 @@ static struct qcom_icc_node * const system_noc_nodes[] = { [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf, }; -static const struct regmap_config x1e80100_system_noc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x1c080, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_system_noc = { - .config = &x1e80100_system_noc_regmap_config, .nodes = system_noc_nodes, .num_nodes = ARRAY_SIZE(system_noc_nodes), .bcms = system_noc_bcms, @@ -2287,16 +1831,7 @@ static struct qcom_icc_node * const usb_center_anoc_nodes[] = { [SLAVE_USB_NOC_SNOC] = &qns_aggre_usb_snoc, }; -static const struct regmap_config x1e80100_usb_center_anoc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x8800, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_usb_center_anoc = { - .config = &x1e80100_usb_center_anoc_regmap_config, .nodes = usb_center_anoc_nodes, .num_nodes = ARRAY_SIZE(usb_center_anoc_nodes), .bcms = usb_center_anoc_bcms, @@ -2312,21 +1847,11 @@ static struct qcom_icc_node * const usb_north_anoc_nodes[] = { [SLAVE_AGGRE_USB_NORTH] = &qns_aggre_usb_north_snoc, }; -static const struct regmap_config x1e80100_usb_north_anoc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x7080, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_usb_north_anoc = { - .config = &x1e80100_usb_north_anoc_regmap_config, .nodes = usb_north_anoc_nodes, .num_nodes = ARRAY_SIZE(usb_north_anoc_nodes), .bcms = usb_north_anoc_bcms, .num_bcms = ARRAY_SIZE(usb_north_anoc_bcms), - .qos_requires_clocks = true, }; static struct qcom_icc_bcm * const usb_south_anoc_bcms[] = { @@ -2342,21 +1867,11 @@ static struct qcom_icc_node * const usb_south_anoc_nodes[] = { [SLAVE_AGGRE_USB_SOUTH] = &qns_aggre_usb_south_snoc, }; -static const struct regmap_config x1e80100_usb_south_anoc_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0xf080, - .fast_io = true, -}; - static const struct qcom_icc_desc x1e80100_usb_south_anoc = { - .config = &x1e80100_usb_south_anoc_regmap_config, .nodes = usb_south_anoc_nodes, .num_nodes = ARRAY_SIZE(usb_south_anoc_nodes), .bcms = usb_south_anoc_bcms, .num_bcms = ARRAY_SIZE(usb_south_anoc_bcms), - .qos_requires_clocks = true, }; static const struct of_device_id qnoc_of_match[] = { From 5cece9cbdeec9a4fb51d5e5265542b3daa0c5981 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 24 Sep 2026 09:33:16 +0800 Subject: [PATCH 0074/1133] QCLINUX: memory-dump: drop per-cluster cache entries, grow CMA reservation Remove the CACHE_CLUSTER0-2 dump entries from Hamoa's and Glymur's dump tables; the per-cluster cache dump is redundant with the existing per-CPU CACHE_CPU0-11 entries and pushed the table size well past the reserved CMA pool. Grow the memdump CMA reservation from 0x3000000 to 0x5000000 so it covers the largest dump table (Hamoa/Glymur, now ~56MB with per-CPU SPR/cache entries for CPU0-CPU11) with headroom. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 6 ------ drivers/firmware/qcom/memory_dump_v2.c | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 3e84a1405d532..996f79aeb2a99 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -420,9 +420,6 @@ static const struct dump_item hamoa_items[] = { { CACHE_CPU9, 0x2aa000, "cache-cpu9" }, { CACHE_CPU10, 0x2aa000, "cache-cpu10" }, { CACHE_CPU11, 0x2aa000, "cache-cpu11" }, - { CACHE_CLUSTER0, 0x2430000, "cache-cluster0" }, - { CACHE_CLUSTER1, 0x2430000, "cache-cluster1" }, - { CACHE_CLUSTER2, 0x2430000, "cache-cluster2" }, { C_CONTEXT, 0x2af0, "cpu-context" }, }; @@ -475,9 +472,6 @@ static const struct dump_item glymur_items[] = { { CACHE_CPU9, 0x2aa000, "cache-cpu9" }, { CACHE_CPU10, 0x2aa000, "cache-cpu10" }, { CACHE_CPU11, 0x2aa000, "cache-cpu11" }, - { CACHE_CLUSTER0, 0x2430000, "cache-cluster0" }, - { CACHE_CLUSTER1, 0x2430000, "cache-cluster1" }, - { CACHE_CLUSTER2, 0x2430000, "cache-cluster2" }, { C_CONTEXT, 0x4050, "cpu-context" }, }; diff --git a/drivers/firmware/qcom/memory_dump_v2.c b/drivers/firmware/qcom/memory_dump_v2.c index 8300f5080edb3..ae905252d927f 100644 --- a/drivers/firmware/qcom/memory_dump_v2.c +++ b/drivers/firmware/qcom/memory_dump_v2.c @@ -982,7 +982,7 @@ static int cpuss_dump_init(struct platform_device *pdev, struct cma *memdump_cma; void __init reserve_memdump_cma(void) { - unsigned long long cma_size = 0x3000000; + unsigned long long cma_size = 0x5000000; unsigned long long request_size = roundup(cma_size, PAGE_SIZE); if (cma_declare_contiguous(0, request_size, 0, 0, 0, false, From 3ba1f2e91809e6f33e0c8c5a1563f9fef0540214 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 23 Sep 2026 13:56:45 +0800 Subject: [PATCH 0075/1133] QCLINUX: memory-dump: add memory dump table for Nord Add the memory dump table for the Nord platform (SoC IDs 648, 690, 691, 692, 798, 803), including new CPUSS cluster/per-CPU and GPU scandump entries in the dump_ids enum. Signed-off-by: Jie Gan --- drivers/firmware/qcom/memory_dump_dev.c | 112 ++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/drivers/firmware/qcom/memory_dump_dev.c b/drivers/firmware/qcom/memory_dump_dev.c index 996f79aeb2a99..b4182d9ab0212 100644 --- a/drivers/firmware/qcom/memory_dump_dev.c +++ b/drivers/firmware/qcom/memory_dump_dev.c @@ -69,6 +69,7 @@ enum dump_ids { ETF_SWAO = 0xf1, ETF_SLPI = 0xf3, ETF_LPASS = 0xf4, + CPUCP = 0xf5, FCM = 0xee, ETR_REG = 0x100, ETF_REG = 0x101, @@ -112,6 +113,7 @@ enum dump_ids { SPR_CPU10 = 0x1fa, SPR_CPU11 = 0x1fb, SCANDUMP_SMMU = 0x220, + SCANDUMP_GPU = 0x221, CACHE_CPU0 = 0x230, CACHE_CPU1 = 0x231, CACHE_CPU2 = 0x232, @@ -128,6 +130,21 @@ enum dump_ids { CACHE_CLUSTER1 = 0x241, CACHE_CLUSTER2 = 0x242, C_CONTEXT = 0x250, + CPUSS_CLUSTER0 = 0x270, + CPUSS_CLUSTER1 = 0x271, + CPUSS_CLUSTER2 = 0x272, + CPUSS_CPU0 = 0x280, + CPUSS_CPU1 = 0x281, + CPUSS_CPU2 = 0x282, + CPUSS_CPU3 = 0x283, + CPUSS_CPU4 = 0x284, + CPUSS_CPU5 = 0x285, + CPUSS_CPU6 = 0x286, + CPUSS_CPU7 = 0x287, + CPUSS_CPU8 = 0x288, + CPUSS_CPU9 = 0x289, + CPUSS_CPU10 = 0x28a, + CPUSS_CPU11 = 0x28b, }; static const struct dump_item lemans_items[] = { @@ -506,6 +523,83 @@ static const struct dump_item shikra_items[] = { { ETF_LPASS, 0x8000, "etf-lpass" }, }; +static const struct dump_item nord_items[] = { + { C0_CONTEXT, 0x800, "c0-context" }, + { C100_CONTEXT, 0x800, "c1-context" }, + { C200_CONTEXT, 0x800, "c2-context" }, + { C300_CONTEXT, 0x800, "c3-context" }, + { C400_CONTEXT, 0x800, "c4-context" }, + { C500_CONTEXT, 0x800, "c5-context" }, + { C600_CONTEXT, 0x800, "c6-context" }, + { C700_CONTEXT, 0x800, "c7-context" }, + { C800_CONTEXT, 0x800, "c8-context" }, + { C900_CONTEXT, 0x800, "c9-context" }, + { C1000_CONTEXT, 0x800, "c10-context" }, + { C1100_CONTEXT, 0x800, "c11-context" }, + { C1200_CONTEXT, 0x800, "c12-context" }, + { C1300_CONTEXT, 0x800, "c13-context" }, + { C1400_CONTEXT, 0x800, "c14-context" }, + { C1500_CONTEXT, 0x800, "c15-context" }, + { C1600_CONTEXT, 0x800, "c16-context" }, + { C1700_CONTEXT, 0x800, "c17-context" }, + { PMIC, 0x80000, "pmic" }, + { MISC_DATA, 0x1000, "misc-data" }, + { RPM_SW, 0x28000, "rpm-sw" }, + { RPMH, 0x2000000, "rpmh" }, + { FCM, 0x8400, "fcm" }, + { TMC_ETF, 0x10000, "tmc-etf" }, + { ETF_SWAO, 0x8400, "etf-swao" }, + { ETR_REG, 0x1000, "etr-reg" }, + { ETR1_REG, 0x1000, "etr1-reg" }, + { ETF_REG, 0x1000, "etf-reg" }, + { ETFSWAO_REG, 0x1000, "etfswao-reg" }, + { C0_SCANDUMP, 0x380000, "apps-scandump" }, + { FSM_DATA, 0x400, "fsm-data" }, + { SCANDUMP_SMMU, 0x40000, "scandump-smmu" }, + { CACHE_CPU0, 0x100000, "cache-cpu0" }, + { CACHE_CPU1, 0x100000, "cache-cpu1" }, + { CACHE_CPU2, 0x100000, "cache-cpu2" }, + { CACHE_CPU3, 0x100000, "cache-cpu3" }, + { CACHE_CPU4, 0x100000, "cache-cpu4" }, + { CACHE_CPU5, 0x100000, "cache-cpu5" }, + { CACHE_CPU6, 0x100000, "cache-cpu6" }, + { CACHE_CPU7, 0x100000, "cache-cpu7" }, + { CACHE_CPU8, 0x100000, "cache-cpu8" }, + { CACHE_CPU9, 0x100000, "cache-cpu9" }, + { CACHE_CPU10, 0x100000, "cache-cpu10" }, + { CACHE_CPU11, 0x100000, "cache-cpu11" }, + { CPUCP, 0x80000, "cpucp" }, + { CPUSS_CLUSTER0, 0x40000, "cpuss-cluster0" }, + { CPUSS_CLUSTER1, 0x40000, "cpuss-cluster1" }, + { CPUSS_CLUSTER2, 0x40000, "cpuss-cluster2" }, + { CPUSS_CPU0, 0x40000, "cpuss-cpu0" }, + { CPUSS_CPU1, 0x40000, "cpuss-cpu1" }, + { CPUSS_CPU2, 0x40000, "cpuss-cpu2" }, + { CPUSS_CPU3, 0x40000, "cpuss-cpu3" }, + { CPUSS_CPU4, 0x40000, "cpuss-cpu4" }, + { CPUSS_CPU5, 0x40000, "cpuss-cpu5" }, + { CPUSS_CPU6, 0x40000, "cpuss-cpu6" }, + { CPUSS_CPU7, 0x40000, "cpuss-cpu7" }, + { CPUSS_CPU8, 0x40000, "cpuss-cpu8" }, + { CPUSS_CPU9, 0x40000, "cpuss-cpu9" }, + { CPUSS_CPU10, 0x40000, "cpuss-cpu10" }, + { CPUSS_CPU11, 0x40000, "cpuss-cpu11" }, + { SPR_CPU0, 0x2000, "spr-cpu0" }, + { SPR_CPU1, 0x2000, "spr-cpu1" }, + { SPR_CPU2, 0x2000, "spr-cpu2" }, + { SPR_CPU3, 0x2000, "spr-cpu3" }, + { SPR_CPU4, 0x2000, "spr-cpu4" }, + { SPR_CPU5, 0x2000, "spr-cpu5" }, + { SPR_CPU6, 0x2000, "spr-cpu6" }, + { SPR_CPU7, 0x2000, "spr-cpu7" }, + { SPR_CPU8, 0x2000, "spr-cpu8" }, + { SPR_CPU9, 0x2000, "spr-cpu9" }, + { SPR_CPU10, 0x2000, "spr-cpu10" }, + { SPR_CPU11, 0x2000, "spr-cpu11" }, + { CPUSS_REG, 0xa00000, "cpuss-reg" }, + { SCANDUMP_GPU, 0x300000, "scandump-gpu" }, +}; + static const struct dump_table lemans_dump_table = { .items = lemans_items, .num_of_items = ARRAY_SIZE(lemans_items), @@ -562,6 +656,13 @@ static const struct dump_table glymur_dump_table = { .imem_size = 0x8, }; +static const struct dump_table nord_dump_table = { + .items = nord_items, + .num_of_items = ARRAY_SIZE(nord_items), + .imem_base = 0x14680010, + .imem_size = 0x8, +}; + static int __init mem_dump_dev_init(void) { int ret; @@ -663,6 +764,17 @@ static int __init mem_dump_dev_init(void) if (ret) goto fail; break; + case 648: + case 690: + case 691: + case 692: + case 798: + case 803: + ret = platform_device_add_data(mem_dump_pdev, + &nord_dump_table, sizeof(nord_dump_table)); + if (ret) + goto fail; + break; default: dev_err(&mem_dump_pdev->dev, "Invalid SoC ID\n"); ret = -EINVAL; From 9f1e8aefe2eaa112abe0bbb5e9f67284effa3d8d Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 23 Sep 2026 10:08:22 +0800 Subject: [PATCH 0076/1133] QCLINUX: qcom-dcc: add nord register list and enable DCC support Add the DCC register capture list for the Nord platform (SoC IDs 648, 690, 691, 692, 798, 803) in a dedicated header qcom-dcc-nord-config.h and enable DCC support for it. Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-dev.c | 11 +++++++++ drivers/misc/qcom-dcc-nord-config.h | 37 +++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 drivers/misc/qcom-dcc-nord-config.h diff --git a/drivers/misc/qcom-dcc-dev.c b/drivers/misc/qcom-dcc-dev.c index 73994f39de30e..2996e0c29add0 100644 --- a/drivers/misc/qcom-dcc-dev.c +++ b/drivers/misc/qcom-dcc-dev.c @@ -12,6 +12,7 @@ #include "qcom-dcc-kodiak-config.h" #include "qcom-dcc-pakala-config.h" #include "qcom-dcc-shikra-config.h" +#include "qcom-dcc-nord-config.h" #define DEV_NAME "qcom-dcc" @@ -139,6 +140,16 @@ static int __init dcc_dev_init(void) if (ret) goto fail; break; + case 648: + case 690: + case 691: + case 692: + case 798: + case 803: + ret = platform_device_add_data(dcc_pdev, &nord_pdata, sizeof(nord_pdata)); + if (ret) + goto fail; + break; default: pr_err("DCC: Invalid SoC ID\n"); ret = -EINVAL; diff --git a/drivers/misc/qcom-dcc-nord-config.h b/drivers/misc/qcom-dcc-nord-config.h new file mode 100644 index 0000000000000..fb3baa26f0846 --- /dev/null +++ b/drivers/misc/qcom-dcc-nord-config.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_DCC_NORD_CONFIG_H +#define _QCOM_DCC_NORD_CONFIG_H + +#include "qcom-dcc.h" + +static const struct dcc_register_entry nord_dcc_entries_ll6[] = { +}; + +static const struct dcc_link_config nord_link_configs[] = { + { + .link_list = 6, + .entries = nord_dcc_entries_ll6, + .num_entries = ARRAY_SIZE(nord_dcc_entries_ll6), + }, +}; + +static const struct dcc_config nord_config = { + .lists = nord_link_configs, + .num_lists = ARRAY_SIZE(nord_link_configs), +}; + +static const struct dcc_pdata nord_pdata = { + .base = 0x100ff000, + .size = 0x00001000, + .ram_base = 0x10081000, + .ram_size = 0x00007000, + .dcc_offset = 0x1000, + .map_ver = 0x3, + .config = &nord_config, +}; + +#endif /* _QCOM_DCC_NORD_CONFIG_H */ From 0d348e9f0a31a8c54c1485e8fbfe6bf64c7a094e Mon Sep 17 00:00:00 2001 From: Prashanth K Date: Wed, 7 Oct 2026 15:56:00 +0530 Subject: [PATCH 0077/1133] FROMLIST: phy: qcom: qmp-combo: Add PM suspend/resume callbacks Currently when we perform system suspend, the USB clocks are not turned off, this leads to power leakage. Prevent this by adding PM suspend/resume callbacks for the qmp-combo phy which toggles clocks on/off correspondingly. Link: https://lore.kernel.org/all/20261022104321.306679-2-prashanth.k@oss.qualcomm.com/ Signed-off-by: Prashanth K --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index cdcfad2e86b1d..a36e309958454 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -4113,9 +4113,26 @@ static int __maybe_unused qmp_combo_runtime_resume(struct device *dev) return 0; } +static int __maybe_unused qmp_combo_pm_suspend(struct device *dev) +{ + if (pm_runtime_suspended(dev)) + return 0; + + return qmp_combo_runtime_suspend(dev); +} + +static int __maybe_unused qmp_combo_pm_resume(struct device *dev) +{ + if (pm_runtime_suspended(dev)) + return 0; + + return qmp_combo_runtime_resume(dev); +} + static const struct dev_pm_ops qmp_combo_pm_ops = { SET_RUNTIME_PM_OPS(qmp_combo_runtime_suspend, qmp_combo_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(qmp_combo_pm_suspend, qmp_combo_pm_resume) }; static int qmp_combo_reset_init(struct qmp_combo *qmp) From 453569726aa183e2eb3af3c2d098314bd7b190e4 Mon Sep 17 00:00:00 2001 From: Prashanth K Date: Wed, 7 Oct 2026 15:43:02 +0530 Subject: [PATCH 0078/1133] FROMLIST: phy: qcom: qmp-usb: Add PM suspend/resume callbacks Currently when we perform system suspend, the USB clocks are not turned off, this leads to power leakage. Prevent this by adding PM suspend/resume callbacks for the qmp-usb phy which toggles clocks on/off correspondingly. Link: https://lore.kernel.org/all/20261022104321.306679-3-prashanth.k@oss.qualcomm.com/ Signed-off-by: Prashanth K --- drivers/phy/qualcomm/phy-qcom-qmp-usb.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c index c5507168e1354..d8821688585d9 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c @@ -2142,9 +2142,26 @@ static int __maybe_unused qmp_usb_runtime_resume(struct device *dev) return 0; } +static int __maybe_unused qmp_usb_pm_suspend(struct device *dev) +{ + if (pm_runtime_suspended(dev)) + return 0; + + return qmp_usb_runtime_suspend(dev); +} + +static int __maybe_unused qmp_usb_pm_resume(struct device *dev) +{ + if (pm_runtime_suspended(dev)) + return 0; + + return qmp_usb_runtime_resume(dev); +} + static const struct dev_pm_ops qmp_usb_pm_ops = { SET_RUNTIME_PM_OPS(qmp_usb_runtime_suspend, qmp_usb_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(qmp_usb_pm_suspend, qmp_usb_pm_resume) }; static int qmp_usb_reset_init(struct qmp_usb *qmp, From 42fa88a1f9146b247d093067c4a72bfd65b5402e Mon Sep 17 00:00:00 2001 From: Sandeepkumar Yenugula Date: Fri, 9 Oct 2026 12:48:09 +0530 Subject: [PATCH 0079/1133] QCLINUX: qcom-dcc: add thermal registers to shikra config Add thermal debug register reads to the Shikra DCC LL3 capture list. This extends the existing dump set with thermal-related addresses so postmortem captures include key thermal state alongside existing LL3 debug context. Signed-off-by: Sandeepkumar Yenugula Signed-off-by: Jie Gan --- drivers/misc/qcom-dcc-shikra-config.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/misc/qcom-dcc-shikra-config.h b/drivers/misc/qcom-dcc-shikra-config.h index fdf3d0c34695c..967b614a55d21 100644 --- a/drivers/misc/qcom-dcc-shikra-config.h +++ b/drivers/misc/qcom-dcc-shikra-config.h @@ -644,6 +644,22 @@ static const struct dcc_register_entry shikra_dcc_entries_ll3[] = { { "R 0xfd8010c" }, { "R 0xfd91060 8" }, { "R 0xfd92064 8" }, + + /* thermal */ + { "R 0x4410004 1" }, + { "R 0x4411014 1" }, + { "R 0x44110E0 1" }, + { "R 0x44110EC 1" }, + { "R 0x44110A0 16" }, + { "R 0x44110E8 1" }, + { "R 0x4411170 1" }, + { "R 0x4412010 1" }, + { "R 0xEC81000 1" }, + { "R 0x4412100 16" }, + { "R 0xFB784A0 12" }, + { "R 0xFB78D10 12" }, + { "R 0xFB78F90 10" }, + { "R 0xFB79A10 4" }, }; static const struct dcc_link_config shikra_link_configs[] = { From 39378e0206b27255c83da4477c4071a70149525e Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:15 +0530 Subject: [PATCH 0080/1133] power: reset: reboot-mode: Add firmware node based registration The reboot-mode driver does not have a strict requirement for device-based registration. It primarily uses the device's of_node to read mode- properties. Remove the dependency on struct device and introduce support for firmware node (fwnode) based registration. This enables drivers that are not associated with a struct device to leverage the reboot-mode framework. Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-2-46e085bca4cc@oss.qualcomm.com --- drivers/power/reset/reboot-mode.c | 17 ++++++++++++++--- include/linux/reboot-mode.h | 4 +++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index 3611bed341e14..a8ef487a1be4b 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -164,18 +164,26 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) /** * reboot_mode_register - register a reboot mode driver * @reboot: reboot mode driver + * @fwnode: Firmware node with reboot-mode configuration * * Returns: 0 on success or a negative error code on failure. */ -int reboot_mode_register(struct reboot_mode_driver *reboot) +int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle *fwnode) { struct mode_info *info = NULL; + struct device_node *np; struct property *prop; - struct device_node *np = reboot->dev->of_node; size_t len = strlen(PREFIX); u32 magic; int ret; + if (!fwnode) + return -EINVAL; + + np = to_of_node(fwnode); + if (!np) + return -EINVAL; + INIT_LIST_HEAD(&reboot->head); for_each_property_of_node(np, prop) { @@ -298,11 +306,14 @@ int devm_reboot_mode_register(struct device *dev, struct reboot_mode_driver **dr; int rc; + if (!reboot->dev || !reboot->dev->of_node) + return -EINVAL; + dr = devres_alloc(devm_reboot_mode_release, sizeof(*dr), GFP_KERNEL); if (!dr) return -ENOMEM; - rc = reboot_mode_register(reboot); + rc = reboot_mode_register(reboot, of_fwnode_handle(reboot->dev->of_node)); if (rc) { devres_free(dr); return rc; diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index 4a2abb38d1d61..22f707ade4ba9 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -2,6 +2,8 @@ #ifndef __REBOOT_MODE_H__ #define __REBOOT_MODE_H__ +#include + struct reboot_mode_driver { struct device *dev; struct list_head head; @@ -9,7 +11,7 @@ struct reboot_mode_driver { struct notifier_block reboot_notifier; }; -int reboot_mode_register(struct reboot_mode_driver *reboot); +int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle *fwnode); int reboot_mode_unregister(struct reboot_mode_driver *reboot); int devm_reboot_mode_register(struct device *dev, struct reboot_mode_driver *reboot); From 50c5717ccbed44886b5089f75348f4bbd2097cd7 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:16 +0530 Subject: [PATCH 0081/1133] power: reset: reboot-mode: Add support for 64 bit magic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current reboot-mode supports a single 32-bit argument for any supported mode. Some reboot-mode based drivers may require passing two independent 32-bit arguments during a reboot sequence, for uses-cases, where a mode requires an additional argument. Such drivers may not be able to use the reboot-mode driver. For example, ARM PSCI vendor-specific resets, need two arguments for its operation – reset_type and cookie, to complete the reset operation. If a driver wants to implement this firmware-based reset, it cannot use reboot-mode framework. Introduce 64-bit magic values in reboot-mode driver to accommodate dual 32-bit arguments when specified via device tree. In cases, where no second argument is passed from device tree, keep the upper 32-bit of magic un-changed(0) to maintain backward compatibility. Update the current drivers using reboot-mode for a 64-bit magic value. Reviewed-by: Umang Chheda Reviewed-by: Nirmesh Kumar Singh Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-3-46e085bca4cc@oss.qualcomm.com --- drivers/power/reset/nvmem-reboot-mode.c | 11 ++++++++--- drivers/power/reset/qcom-pon.c | 11 ++++++++--- drivers/power/reset/reboot-mode.c | 22 +++++++++++++--------- drivers/power/reset/syscon-reboot-mode.c | 11 ++++++++--- include/linux/reboot-mode.h | 3 ++- 5 files changed, 39 insertions(+), 19 deletions(-) diff --git a/drivers/power/reset/nvmem-reboot-mode.c b/drivers/power/reset/nvmem-reboot-mode.c index d260715fccf67..4479c874077c7 100644 --- a/drivers/power/reset/nvmem-reboot-mode.c +++ b/drivers/power/reset/nvmem-reboot-mode.c @@ -17,14 +17,19 @@ struct nvmem_reboot_mode { struct nvmem_cell *cell; }; -static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct nvmem_reboot_mode *nvmem_rbm; size_t buf_len; + u32 magic_32; void *buf; int ret; + if (magic > U32_MAX) + return -EINVAL; + + magic_32 = magic; + nvmem_rbm = container_of(reboot, struct nvmem_reboot_mode, reboot); buf = nvmem_cell_read(nvmem_rbm->cell, &buf_len); @@ -35,7 +40,7 @@ static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, if (buf_len > sizeof(magic)) return -EINVAL; - ret = nvmem_cell_write(nvmem_rbm->cell, &magic, buf_len); + ret = nvmem_cell_write(nvmem_rbm->cell, &magic_32, sizeof(magic_32)); if (ret < 0) dev_err(reboot->dev, "update reboot mode bits failed\n"); diff --git a/drivers/power/reset/qcom-pon.c b/drivers/power/reset/qcom-pon.c index cd7ba680b8413..e74407f9b74ae 100644 --- a/drivers/power/reset/qcom-pon.c +++ b/drivers/power/reset/qcom-pon.c @@ -27,17 +27,22 @@ struct qcom_pon { long reason_shift; }; -static int qcom_pon_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int qcom_pon_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct qcom_pon *pon = container_of (reboot, struct qcom_pon, reboot_mode); + u32 magic_32; int ret; + if (magic > U32_MAX || (magic << pon->reason_shift) > U32_MAX) + return -EINVAL; + + magic_32 = magic << pon->reason_shift; + ret = regmap_update_bits(pon->regmap, PON_SOFT_RB_SPARE, GENMASK(7, pon->reason_shift), - magic << pon->reason_shift); + magic_32); if (ret < 0) dev_err(pon->dev, "update reboot mode bits failed\n"); diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index a8ef487a1be4b..554016978a4fb 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -20,7 +20,7 @@ struct mode_info { const char *mode; - u32 magic; + u64 magic; struct list_head list; }; @@ -72,8 +72,7 @@ static const struct class reboot_mode_class = { .dev_groups = reboot_mode_groups, }; -static unsigned int get_reboot_mode_magic(struct reboot_mode_driver *reboot, - const char *cmd) +static u64 get_reboot_mode_magic(struct reboot_mode_driver *reboot, const char *cmd) { const char *normal = "normal"; struct mode_info *info; @@ -105,7 +104,7 @@ static int reboot_mode_notify(struct notifier_block *this, unsigned long mode, void *cmd) { struct reboot_mode_driver *reboot; - unsigned int magic; + u64 magic; reboot = container_of(this, struct reboot_mode_driver, reboot_notifier); magic = get_reboot_mode_magic(reboot, cmd); @@ -174,7 +173,8 @@ int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle struct device_node *np; struct property *prop; size_t len = strlen(PREFIX); - u32 magic; + u32 magic_arg1; + u32 magic_arg2; int ret; if (!fwnode) @@ -190,19 +190,23 @@ int reboot_mode_register(struct reboot_mode_driver *reboot, struct fwnode_handle if (strncmp(prop->name, PREFIX, len)) continue; - if (device_property_read_u32(reboot->dev, prop->name, &magic)) { - dev_dbg(reboot->dev, "reboot mode %s without magic number\n", - prop->name); + if (of_property_read_u32(np, prop->name, &magic_arg1)) { + pr_err("reboot mode without magic number\n"); continue; } + if (of_property_read_u32_index(np, prop->name, 1, &magic_arg2)) + magic_arg2 = 0; + info = kzalloc_obj(*info); if (!info) { ret = -ENOMEM; goto error; } - info->magic = magic; + info->magic = magic_arg2; + info->magic = (info->magic << 32) | magic_arg1; + info->mode = kstrdup_const(prop->name + len, GFP_KERNEL); if (!info->mode) { ret = -ENOMEM; diff --git a/drivers/power/reset/syscon-reboot-mode.c b/drivers/power/reset/syscon-reboot-mode.c index e0772c9f70f7a..3cbd000c51223 100644 --- a/drivers/power/reset/syscon-reboot-mode.c +++ b/drivers/power/reset/syscon-reboot-mode.c @@ -20,16 +20,21 @@ struct syscon_reboot_mode { u32 mask; }; -static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct syscon_reboot_mode *syscon_rbm; + u32 magic_32; int ret; + if (magic > U32_MAX) + return -EINVAL; + + magic_32 = magic; + syscon_rbm = container_of(reboot, struct syscon_reboot_mode, reboot); ret = regmap_update_bits(syscon_rbm->map, syscon_rbm->offset, - syscon_rbm->mask, magic); + syscon_rbm->mask, magic_32); if (ret < 0) dev_err(reboot->dev, "update reboot mode bits failed\n"); diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index 22f707ade4ba9..e0d3e8a54050a 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -3,11 +3,12 @@ #define __REBOOT_MODE_H__ #include +#include struct reboot_mode_driver { struct device *dev; struct list_head head; - int (*write)(struct reboot_mode_driver *reboot, unsigned int magic); + int (*write)(struct reboot_mode_driver *reboot, u64 magic); struct notifier_block reboot_notifier; }; From 3df31afc6d6eb8e5866f5b2b0bf7cebe5428933c Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:20 +0530 Subject: [PATCH 0082/1133] firmware: psci: Implement vendor-specific resets as reboot-mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SoC vendors have different types of resets which are controlled through various hardware registers. For instance, Qualcomm SoC may have a requirement that reboot with “bootloader” command should reboot the device to bootloader flashing mode and reboot with “edl” should reboot the device into Emergency flashing mode. Setting up such reboots on Qualcomm devices can be inconsistent across SoC platforms and may require setting different HW registers, where some of these registers may not be accessible to HLOS. These knobs evolve over product generations and require more drivers. PSCI spec defines, SYSTEM_RESET2, vendor-specific reset which can help align this requirement. Add support for PSCI SYSTEM_RESET2, vendor-specific resets and align the implementation to allow user-space initiated reboots to trigger these resets. Implement the PSCI vendor-specific resets by registering to the reboot-mode framework. As psci init is done at early kernel init, reboot-mode registration cannot be done at the time of psci init. This is because reboot-mode creates a “reboot-mode” class for exposing sysfs, which can fail at early kernel init. To overcome this, introduce a late_initcall to register PSCI vendor-specific resets as reboot modes. Implement a reboot-mode write function that sets reset_type and cookie values during the reboot notifier callback. Introduce a firmware-based call for SYSTEM_RESET2 vendor-specific reset in the psci_sys_reset path, using reset_type and cookie if supported by secure firmware. Register a panic notifier and clear vendor_reset valid status during panic. This is needed for any kernel panic that occurs post reboot_notifiers. By using the above implementation, userspace will be able to issue such resets using the reboot() system call with the "*arg" parameter as a string based command. The commands can be defined in PSCI device tree node under “reboot-mode” and are based on the reboot-mode based commands. Reviewed-by: Umang Chheda Reviewed-by: Kathiravan Thirumoorthy Reviewed-by: Nirmesh Kumar Singh Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20251109-arm-psci-system_reset2-vendor-reboots-v17-7-46e085bca4cc@oss.qualcomm.com --- drivers/firmware/psci/Kconfig | 2 + drivers/firmware/psci/psci.c | 91 ++++++++++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/psci/Kconfig b/drivers/firmware/psci/Kconfig index 97944168b5e66..93ff7b071a0c3 100644 --- a/drivers/firmware/psci/Kconfig +++ b/drivers/firmware/psci/Kconfig @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only config ARM_PSCI_FW bool + select POWER_RESET + select REBOOT_MODE config ARM_PSCI_CHECKER bool "ARM PSCI checker" diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index e73bae6cb23a3..82f99c7a410f9 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -8,15 +8,18 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include #include +#include #include #include @@ -51,6 +54,24 @@ static int resident_cpu = -1; struct psci_operations psci_ops; static enum arm_smccc_conduit psci_conduit = SMCCC_CONDUIT_NONE; +struct psci_vendor_sysreset2 { + u32 reset_type; + u32 cookie; + bool valid; +}; + +static struct psci_vendor_sysreset2 vendor_reset; + +static int psci_panic_event(struct notifier_block *nb, unsigned long v, void *p) +{ + vendor_reset.valid = false; + return NOTIFY_DONE; +} + +static struct notifier_block psci_panic_block = { + .notifier_call = psci_panic_event +}; + bool psci_tos_resident_on(int cpu) { return cpu == resident_cpu; @@ -309,7 +330,10 @@ static int get_set_conduit_method(const struct device_node *np) static int psci_sys_reset(struct notifier_block *nb, unsigned long action, void *data) { - if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) && + if (vendor_reset.valid && psci_system_reset2_supported) { + invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), vendor_reset.reset_type, + vendor_reset.cookie, 0); + } else if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) && psci_system_reset2_supported) { /* * reset_type[31] = 0 (architectural) @@ -557,6 +581,71 @@ static const struct platform_suspend_ops psci_suspend_ops = { .begin = psci_system_suspend_begin, }; +static int psci_set_vendor_sys_reset2(struct reboot_mode_driver *reboot, u64 magic) +{ + u32 magic_32; + + if (psci_system_reset2_supported) { + magic_32 = magic & GENMASK(31, 0); + vendor_reset.reset_type = PSCI_1_1_RESET_TYPE_VENDOR_START | magic_32; + vendor_reset.cookie = (magic >> 32) & GENMASK(31, 0); + vendor_reset.valid = true; + } + + return NOTIFY_DONE; +} + +static int __init psci_init_vendor_reset(void) +{ + struct reboot_mode_driver *reboot; + struct device_node *psci_np; + struct device_node *np; + int ret; + + if (!psci_system_reset2_supported) + return -EINVAL; + + psci_np = of_find_compatible_node(NULL, NULL, "arm,psci-1.0"); + if (!psci_np) + return -ENODEV; + + np = of_find_node_by_name(psci_np, "reboot-mode"); + if (!np) { + of_node_put(psci_np); + return -ENODEV; + } + + ret = atomic_notifier_chain_register(&panic_notifier_list, &psci_panic_block); + if (ret) + goto err_notifier; + + reboot = kzalloc(sizeof(*reboot), GFP_KERNEL); + if (!reboot) { + ret = -ENOMEM; + goto err_kzalloc; + } + + reboot->write = psci_set_vendor_sys_reset2; + + ret = reboot_mode_register(reboot, of_fwnode_handle(np)); + if (ret) + goto err_register; + + of_node_put(psci_np); + of_node_put(np); + return 0; + +err_register: + kfree(reboot); +err_kzalloc: + atomic_notifier_chain_unregister(&panic_notifier_list, &psci_panic_block); +err_notifier: + of_node_put(psci_np); + of_node_put(np); + return ret; +} +late_initcall(psci_init_vendor_reset) + static void __init psci_init_system_reset2(void) { int ret; From 207391ffca2f87ee03d3b7a3006237f767196b7b Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 8 May 2026 09:36:34 +0530 Subject: [PATCH 0083/1133] WORKAROUND: power: reset: reboot-mode: fix NULL deref when dev is not set reboot_mode_create_device() and reboot_mode_unregister_device() unconditionally dereference reboot->dev->driver->name to name the sysfs device. psci_init_vendor_reset() allocates a reboot_mode_driver with kzalloc (so reboot->dev == NULL) and never sets reboot->dev, causing a NULL pointer dereference at boot: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000068 pc : reboot_mode_register+0x334/0x3b8 psci_init_vendor_reset+0xdc/0x128 Kernel panic - not syncing: Oops: Fatal exception The offset 0x68 is the 'driver' pointer inside struct device on arm64, confirming that reboot->dev itself is NULL. Fix this by adding a 'name' field to struct reboot_mode_driver. reboot_mode_create_device() and reboot_mode_unregister_device() now prefer reboot->name; they fall back to reboot->dev->driver->name only when reboot->name is NULL, and return -EINVAL / return early if neither source is available. Set reboot->name = "psci" in psci_init_vendor_reset() so the sysfs device is correctly named. Existing device-based callers (nvmem-reboot-mode, syscon-reboot-mode, qcom-pon) are unaffected: they set reboot->dev before calling devm_reboot_mode_register(), so the fallback path is taken as before. Fixes: cfaf0a90789a ("power: reset: reboot-mode: Expose sysfs for registered reboot_modes") Fixes: 614b17a3ce6e ("firmware: psci: Implement vendor-specific resets as reboot-mode") Reported-by: LAVA job 91409 Signed-off-by: Salendarsingh Gaud --- drivers/firmware/psci/psci.c | 1 + drivers/power/reset/reboot-mode.c | 20 ++++++++++++++++++-- include/linux/reboot-mode.h | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index 82f99c7a410f9..158a0a1b9b879 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -626,6 +626,7 @@ static int __init psci_init_vendor_reset(void) } reboot->write = psci_set_vendor_sys_reset2; + reboot->name = "psci"; ret = reboot_mode_register(reboot, of_fwnode_handle(np)); if (ret) diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index 554016978a4fb..acd9b533db6c6 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -119,8 +119,16 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) struct reboot_mode_sysfs_data *priv; struct mode_info *sysfs_info; struct mode_info *info; + const char *dev_name; int ret; + dev_name = reboot->name; + if (!dev_name) { + if (!reboot->dev || !reboot->dev->driver) + return -EINVAL; + dev_name = reboot->dev->driver->name; + } + priv = kzalloc_obj(*priv); if (!priv) return -ENOMEM; @@ -146,7 +154,7 @@ static int reboot_mode_create_device(struct reboot_mode_driver *reboot) priv->reboot_mode_device = device_create(&reboot_mode_class, NULL, 0, (void *)priv, "%s", - reboot->dev->driver->name); + dev_name); if (IS_ERR(priv->reboot_mode_device)) { ret = PTR_ERR(priv->reboot_mode_device); goto error; @@ -253,8 +261,16 @@ static inline void reboot_mode_unregister_device(struct reboot_mode_driver *rebo { struct reboot_mode_sysfs_data *priv; struct device *reboot_mode_device; + const char *dev_name; + + dev_name = reboot->name; + if (!dev_name) { + if (!reboot->dev || !reboot->dev->driver) + return; + dev_name = reboot->dev->driver->name; + } - reboot_mode_device = class_find_device(&reboot_mode_class, NULL, reboot->dev->driver->name, + reboot_mode_device = class_find_device(&reboot_mode_class, NULL, dev_name, reboot_mode_match_by_name); if (!reboot_mode_device) diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index e0d3e8a54050a..56581199af234 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -7,6 +7,7 @@ struct reboot_mode_driver { struct device *dev; + const char *name; struct list_head head; int (*write)(struct reboot_mode_driver *reboot, u64 magic); struct notifier_block reboot_notifier; From f34d3332d541e5020c42cd283bd899f85dcc0225 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Wed, 12 Aug 2026 11:42:22 +0530 Subject: [PATCH 0084/1133] FROMLIST: soc: qcom: cmd-db: export RPMh accelerator type string helper RPMh resource addresses encode the accelerator type (ARC, VRM, BCM) in bits [19:16], matching the cmd_db_hw_type enum values. Add cmd_db_hw_type_str() to map an RPMh address to its accelerator type name string using the existing SLAVE_ID() macro, and export it so drivers that handle raw RPMh addresses can produce human-readable diagnostic output without duplicating the address encoding knowledge. Link: https://lore.kernel.org/linux-arm-msm/20260812-rpmh-timeout-debug-v1-v3-1-68c0a40dce23@oss.qualcomm.com/ Assisted-by: Claude:claude-sonnet-4-5 Reviewed-by: Dmitry Baryshkov Reviewed-by: Navya Malempati Reviewed-by: Konrad Dybcio Signed-off-by: Maulik Shah --- drivers/soc/qcom/cmd-db.c | 20 ++++++++++++++++++++ include/soc/qcom/cmd-db.h | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c index 3f1eee7843876..117f810d5ca4e 100644 --- a/drivers/soc/qcom/cmd-db.c +++ b/drivers/soc/qcom/cmd-db.c @@ -267,6 +267,26 @@ enum cmd_db_hw_type cmd_db_read_slave_id(const char *id) } EXPORT_SYMBOL_GPL(cmd_db_read_slave_id); +/** + * cmd_db_hw_type_str() - Return the name string for an RPMh accelerator address. + * @addr: RPMh resource address whose slave ID encodes the accelerator type. + * + * Extracts the slave ID from bits [19:16] of @addr and maps it to the + * corresponding cmd_db_hw_type name. + * + * Return: A constant string: "ARC", "VRM", "BCM", or "unknown". + */ +const char *cmd_db_hw_type_str(u32 addr) +{ + switch (SLAVE_ID(addr)) { + case CMD_DB_HW_ARC: return "ARC"; + case CMD_DB_HW_VRM: return "VRM"; + case CMD_DB_HW_BCM: return "BCM"; + default: return "unknown"; + } +} +EXPORT_SYMBOL_GPL(cmd_db_hw_type_str); + #ifdef CONFIG_DEBUG_FS static int cmd_db_debugfs_dump(struct seq_file *seq, void *p) { diff --git a/include/soc/qcom/cmd-db.h b/include/soc/qcom/cmd-db.h index 47a6cab75e630..34adc04eac943 100644 --- a/include/soc/qcom/cmd-db.h +++ b/include/soc/qcom/cmd-db.h @@ -29,6 +29,8 @@ bool cmd_db_match_resource_addr(u32 addr1, u32 addr2); enum cmd_db_hw_type cmd_db_read_slave_id(const char *resource_id); int cmd_db_ready(void); + +const char *cmd_db_hw_type_str(u32 addr); #else static inline u32 cmd_db_read_addr(const char *resource_id) { return 0; } @@ -44,5 +46,8 @@ static inline enum cmd_db_hw_type cmd_db_read_slave_id(const char *resource_id) static inline int cmd_db_ready(void) { return -ENODEV; } + +static inline const char *cmd_db_hw_type_str(u32 addr) +{ return "unknown"; } #endif /* CONFIG_QCOM_COMMAND_DB */ #endif /* __QCOM_COMMAND_DB_H__ */ From e76ed68bb889351aaacc53c05fb3b9a3b6f9bec4 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Wed, 12 Aug 2026 11:42:23 +0530 Subject: [PATCH 0085/1133] FROMLIST: soc: qcom: cmd-db: add reverse address-to-name lookup RPMh resource addresses are opaque 32-bit values. While the slave ID in bits [19:16] identifies the accelerator type (ARC/VRM/BCM), the lower bits encode a resource index that is only meaningful when mapped back to the human-readable resource name stored in the command DB (e.g. 0x30000 -> cx.lvl). Add cmd_db_read_name() to perform this reverse lookup by iterating the command DB entries and matching on address. Unlike other exported cmd-db APIs which go through cmd_db_get_header() (which calls cmd_db_ready() internally), this function iterates cmd_db_header directly for address matching, so it calls cmd_db_ready() itself. For VRM resources, which have up to 4 contiguous 4-byte-aligned addresses per resource, the match uses VRM_ADDR() on bits [19:4] so that any sub-address (enable, voltage, mode, headroom) resolves to the same resource name. Also export CMD_DB_ID_SIZE so callers can size their name buffers correctly without open-coding the magic constant 8. Link: https://lore.kernel.org/linux-arm-msm/20260812-rpmh-timeout-debug-v1-v3-2-68c0a40dce23@oss.qualcomm.com/ Assisted-by: Claude:claude-sonnet-4-5 Reviewed-by: Dmitry Baryshkov Reviewed-by: Navya Malempati Reviewed-by: Konrad Dybcio Signed-off-by: Maulik Shah --- drivers/soc/qcom/cmd-db.c | 45 +++++++++++++++++++++++++++++++++++++++ include/soc/qcom/cmd-db.h | 5 +++++ 2 files changed, 50 insertions(+) diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c index 117f810d5ca4e..e1453b194aa3f 100644 --- a/drivers/soc/qcom/cmd-db.c +++ b/drivers/soc/qcom/cmd-db.c @@ -287,6 +287,51 @@ const char *cmd_db_hw_type_str(u32 addr) } EXPORT_SYMBOL_GPL(cmd_db_hw_type_str); +/** + * cmd_db_read_name() - Look up the resource name for a given RPMh address. + * @addr: RPMh resource address to reverse-look up. + * @buf: Output buffer to write the resource name into. + * @len: Size of @buf; must be at least CMD_DB_ID_SIZE + 1. + * + * Iterates the command DB to find the entry whose address matches @addr. + * For VRM resources, which have up to 4 contiguous 4-byte-aligned addresses + * per resource, the match is performed on bits [19:4] so that any of the + * sub-addresses resolve to the same resource name. + * + * Return: 0 on success, -ENODEV if not found or DB not ready. + */ +int cmd_db_read_name(u32 addr, char *buf, size_t len) +{ + const struct rsc_hdr *rsc_hdr; + const struct entry_header *ent; + int ret, i, j; + + ret = cmd_db_ready(); + if (ret) + return ret; + + for (i = 0; i < MAX_SLV_ID; i++) { + rsc_hdr = &cmd_db_header->header[i]; + if (!rsc_hdr->slv_id) + break; + + ent = rsc_to_entry_header(rsc_hdr); + for (j = 0; j < le16_to_cpu(rsc_hdr->cnt); j++, ent++) { + u32 ent_addr = le32_to_cpu(ent->addr); + + if (cmd_db_match_resource_addr(ent_addr, addr)) { + snprintf(buf, len, "%.*s", + (int)strnlen(ent->id, sizeof(ent->id)), + ent->id); + return 0; + } + } + } + + return -ENODEV; +} +EXPORT_SYMBOL_GPL(cmd_db_read_name); + #ifdef CONFIG_DEBUG_FS static int cmd_db_debugfs_dump(struct seq_file *seq, void *p) { diff --git a/include/soc/qcom/cmd-db.h b/include/soc/qcom/cmd-db.h index 34adc04eac943..d03d64f3407d3 100644 --- a/include/soc/qcom/cmd-db.h +++ b/include/soc/qcom/cmd-db.h @@ -9,6 +9,8 @@ #include +#define CMD_DB_ID_SIZE 8 + enum cmd_db_hw_type { CMD_DB_HW_INVALID = 0, CMD_DB_HW_MIN = 3, @@ -31,6 +33,7 @@ enum cmd_db_hw_type cmd_db_read_slave_id(const char *resource_id); int cmd_db_ready(void); const char *cmd_db_hw_type_str(u32 addr); +int cmd_db_read_name(u32 addr, char *buf, size_t len); #else static inline u32 cmd_db_read_addr(const char *resource_id) { return 0; } @@ -49,5 +52,7 @@ static inline int cmd_db_ready(void) static inline const char *cmd_db_hw_type_str(u32 addr) { return "unknown"; } +static inline int cmd_db_read_name(u32 addr, char *buf, size_t len) +{ return -ENODEV; } #endif /* CONFIG_QCOM_COMMAND_DB */ #endif /* __QCOM_COMMAND_DB_H__ */ From a4265460451b4787ad16a255d403ab20677c5c72 Mon Sep 17 00:00:00 2001 From: "Raju P.L.S.S.S.N" Date: Wed, 12 Aug 2026 11:42:24 +0530 Subject: [PATCH 0086/1133] FROMLIST: soc: qcom: rpmh-rsc: Output debug information from RSC When an RPMh transfer times out there is no visibility into which TCS was stuck, what commands it was carrying, or whether the completion IRQ was pending at the GIC. Add rpmh_rsc_debug() to capture this state at timeout: - Iterates all in-use TCSes and dumps per-TCS control register state (controller status, AMC mode, IRQ status) and per-command register state (address, data, message ID, completion status). The accelerator type (ARC/VRM/BCM) is decoded from the address using cmd_db_hw_type_str(). - Queries the GIC pending state for the RSC IRQ via irq_get_irqchip_state() to distinguish two failure modes: * AOSS firmware did not respond (IRQ never fired) * Linux lockup (IRQ pending at GIC but handler never ran) - Reports the completion object state to cross-check with the IRQ status. Store the IRQ number in struct rsc_drv to enable the GIC query. Wire rpmh_rsc_debug() into the rpmh_write(), rpmh_write_batch(), and rpmh_read() timeout paths so that all three blocking RPMh callers produce the same structured TCS/GIC diagnostic output on timeout. Link: https://lore.kernel.org/linux-arm-msm/20260812-rpmh-timeout-debug-v1-v3-3-68c0a40dce23@oss.qualcomm.com/ Signed-off-by: Raju P.L.S.S.S.N Co-developed-by: Maulik Shah Signed-off-by: Maulik Shah --- drivers/soc/qcom/rpmh-internal.h | 5 ++ drivers/soc/qcom/rpmh-rsc.c | 90 ++++++++++++++++++++++++++++++++ drivers/soc/qcom/rpmh.c | 12 ++++- 3 files changed, 106 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h index 39441a25af9ba..4e465bdb5a270 100644 --- a/drivers/soc/qcom/rpmh-internal.h +++ b/drivers/soc/qcom/rpmh-internal.h @@ -104,6 +104,9 @@ struct rsc_ver { * @tcs_base: Start address of the TCS registers in this controller. * @id: Instance id in the controller (Direct Resource Voter). * @num_tcs: Number of TCSes in this DRV. + * @irq: IRQ number used by the TCS completion interrupt; + * stored to allow querying GIC pending state for + * timeout diagnostics. * @rsc_pm: CPU PM notifier for controller. * Used when solver mode is not present. * @cpus_in_pm: Number of CPUs not in idle power collapse. @@ -131,6 +134,7 @@ struct rsc_drv { void __iomem *tcs_base; int id; int num_tcs; + int irq; struct notifier_block rsc_pm; struct notifier_block genpd_nb; atomic_t cpus_in_pm; @@ -149,6 +153,7 @@ int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv, const struct tcs_request *msg); void rpmh_rsc_invalidate(struct rsc_drv *drv); void rpmh_rsc_write_next_wakeup(struct rsc_drv *drv); +void rpmh_rsc_debug(struct rsc_drv *drv, struct completion *compl); void rpmh_tx_done(const struct tcs_request *msg); int rpmh_flush(struct rpmh_ctrlr *ctrlr); diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index c4542318eac47..be995bebf6b86 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -89,6 +90,7 @@ enum { #define CMD_MSGID_LEN 8 #define CMD_MSGID_RESP_REQ BIT(8) #define CMD_MSGID_WRITE BIT(16) +#define CMD_STATUS_TRIGGERED BIT(0) #define CMD_STATUS_ISSUED BIT(8) #define CMD_STATUS_COMPL BIT(16) @@ -693,6 +695,92 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) return 0; } +static void print_tcs_info(struct rsc_drv *drv, int tcs_id, + bool *aoss_irq_sts) +{ + const struct tcs_request *req = get_req_from_tcs(drv, tcs_id); + unsigned long cmds_enabled; + char rname[CMD_DB_ID_SIZE + 1]; + u32 addr, data, msgid, sts, irq_sts; + bool in_use = test_bit(tcs_id, drv->tcs_in_use); + int i; + + sts = read_tcs_reg(drv, drv->regs[RSC_DRV_STATUS], tcs_id); + cmds_enabled = read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id); + if (!cmds_enabled) + return; + + if (!req) + goto print_tcs_data; + + data = read_tcs_reg(drv, drv->regs[RSC_DRV_CONTROL], tcs_id); + irq_sts = readl_relaxed(drv->tcs_base + drv->regs[RSC_DRV_IRQ_STATUS]); + pr_warn("Request: tcs-in-use:%s state=%d wait_for_compl=%u\n", + in_use ? "YES" : "NO", + req->state, req->wait_for_compl); + pr_warn("TCS=%d [ctrlr-sts:%s amc-mode:0x%x irq-sts:%s]\n", + tcs_id, sts ? "IDLE" : "BUSY", data, + (irq_sts & BIT(tcs_id)) ? "DONE" : "WAITING"); + + *aoss_irq_sts = !!(irq_sts & BIT(tcs_id)); + +print_tcs_data: + /* All TCSes on a given SoC have the same number of commands per TCS. */ + for_each_set_bit(i, &cmds_enabled, drv->tcs[0].ncpt) { + addr = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], tcs_id, i); + data = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, i); + msgid = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_MSGID], tcs_id, i); + sts = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_STATUS], tcs_id, i); + cmd_db_read_name(addr, rname, sizeof(rname)); + pr_warn("\tCMD=%d [addr=0x%x(%s/%s) data=0x%x %s sts=%s%s%s]\n", + i, addr, cmd_db_hw_type_str(addr), rname, data, + (msgid & CMD_MSGID_RESP_REQ) ? "resp-required" : "fire-n-forget", + (sts & CMD_STATUS_TRIGGERED) ? "triggered" : "-", + (sts & CMD_STATUS_ISSUED) ? "+sent-to-aoss" : "", + (sts & CMD_STATUS_COMPL) ? "+resp-received" : ""); + } +} + +/** + * rpmh_rsc_debug() - Dump debug information on a transfer timeout. + * @drv: The RSC controller. + * @compl: The completion object that timed out. + * + * Dumps TCS state for all in-use TCSes and reports which accelerators + * did not respond, to aid in diagnosing RPMH timeout failures. + */ +void rpmh_rsc_debug(struct rsc_drv *drv, struct completion *compl) +{ + struct irq_data *rsc_irq_data = irq_get_irq_data(drv->irq); + bool gic_irq_sts, aoss_irq_sts = false; + int i, busy = 0; + + pr_err("RSC:%s\n", drv->name); + + for (i = 0; i < drv->num_tcs; i++) { + if (!test_bit(i, drv->tcs_in_use)) + continue; + busy++; + print_tcs_info(drv, i, &aoss_irq_sts); + } + + if (!rsc_irq_data) { + pr_err("No IRQ data for RSC:%s\n", drv->name); + return; + } + + irq_get_irqchip_state(drv->irq, IRQCHIP_STATE_PENDING, &gic_irq_sts); + pr_warn("HW IRQ %lu is %s at GIC\n", rsc_irq_data->hwirq, + gic_irq_sts ? "PENDING" : "NOT PENDING"); + pr_warn("Completion is %s\n", + completion_done(compl) ? "done" : "not done"); + + if ((busy && !gic_irq_sts) || !aoss_irq_sts) + pr_err("ERROR: Accelerator(s) at AOSS did not respond\n"); + else if (gic_irq_sts) + pr_err("ERROR: IRQ pending at GIC but not handled within timeout\n"); +} + /** * find_slots() - Find a place to write the given message. * @tcs: The tcs group to search. @@ -1114,6 +1202,8 @@ static int rpmh_rsc_probe(struct platform_device *pdev) if (ret) return ret; + drv->irq = irq; + /* * CPU PM/genpd notification are not required for controllers that support * 'HW solver' mode where they can be in autonomous mode executing low diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index 360242a315e37..8ffee546fe88a 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -240,6 +240,7 @@ int rpmh_read(const struct device *dev, struct tcs_cmd *cmd) { DECLARE_COMPLETION_ONSTACK(compl); DEFINE_RPMH_MSG_ONSTACK(dev, RPMH_ACTIVE_ONLY_STATE, &compl, rpm_msg); + struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); int ret; ret = __fill_rpmh_msg(&rpm_msg, RPMH_ACTIVE_ONLY_STATE, cmd, 1, true); @@ -251,6 +252,10 @@ int rpmh_read(const struct device *dev, struct tcs_cmd *cmd) return ret; ret = wait_for_completion_timeout(&compl, RPMH_TIMEOUT_MS); + if (!ret) { + rpmh_rsc_debug(ctrlr_to_drv(ctrlr), &compl); + WARN_ON(1); + } cmd[0].data = rpm_msg.cmd[0].data; return (ret > 0) ? 0 : -ETIMEDOUT; @@ -308,6 +313,7 @@ int rpmh_write(const struct device *dev, enum rpmh_state state, { DECLARE_COMPLETION_ONSTACK(compl); DEFINE_RPMH_MSG_ONSTACK(dev, state, &compl, rpm_msg); + struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); int ret; ret = __fill_rpmh_msg(&rpm_msg, state, cmd, n, false); @@ -319,7 +325,10 @@ int rpmh_write(const struct device *dev, enum rpmh_state state, return ret; ret = wait_for_completion_timeout(&compl, RPMH_TIMEOUT_MS); - WARN_ON(!ret); + if (!ret) { + rpmh_rsc_debug(ctrlr_to_drv(ctrlr), &compl); + WARN_ON(1); + } return (ret > 0) ? 0 : -ETIMEDOUT; } EXPORT_SYMBOL_GPL(rpmh_write); @@ -438,6 +447,7 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state, * the completion that we're going to free once * we've returned from this function. */ + rpmh_rsc_debug(ctrlr_to_drv(ctrlr), &compls[i]); WARN_ON(1); ret = -ETIMEDOUT; goto exit; From f1a26a65545f84e96590eb7b0cb0ce7e276dd80b Mon Sep 17 00:00:00 2001 From: Navya Malempati Date: Tue, 1 Sep 2026 11:53:36 +0530 Subject: [PATCH 0087/1133] FROMLIST: soc: qcom: qcom_stats: Add support for NSP subsystem stats Add SMEM items for four NSP subsystems stats which are present in Nord SoC. Rename CDSP stats as CDSP_NSP as both use same PID and SMEM item id. Add new entries for NSP1/2/3. Link: https://lore.kernel.org/linux-arm-msm/20260908-nord_stats-v1-1-a55adb083d65@oss.qualcomm.com/ Signed-off-by: Navya Malempati --- drivers/soc/qcom/qcom_stats.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom_stats.c b/drivers/soc/qcom/qcom_stats.c index 3422d6df7b51f..d3dd6d98a3242 100644 --- a/drivers/soc/qcom/qcom_stats.c +++ b/drivers/soc/qcom/qcom_stats.c @@ -43,8 +43,11 @@ static const struct subsystem_data subsystems[] = { { "modem", 605, 1 }, { "wpss", 605, 13 }, { "adsp", 606, 2 }, - { "cdsp", 607, 5 }, + { "cdsp_nsp", 607, 5 }, { "cdsp1", 607, 12 }, + { "cdsp_nsp_1", 607, 69 }, + { "cdsp_nsp_2", 607, 133 }, + { "cdsp_nsp_3", 607, 197 }, { "gpdsp0", 607, 17 }, { "gpdsp1", 607, 18 }, { "soccp", 607, 19 }, From 68fda95e98a9ff074ca1ac7c4dcaea4ff09f93ec Mon Sep 17 00:00:00 2001 From: Linghui Wu Date: Mon, 19 Oct 2026 05:47:35 +0000 Subject: [PATCH 0088/1133] FROMLIST: dt-bindings: regulator: qcom,wcn3990-pmu: document wakeup-source The SW_CTRL GPIO can be used as a wake signal on platforms where the WCN device needs to wake the application processor. Document wakeup-source and require the existing swctrl-gpios property when wakeup-source is present. Link: https://lore.kernel.org/r/20261019093911.3199891-2-linghui.wu@oss.qualcomm.com Signed-off-by: Linghui Wu --- .../devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml b/Documentation/devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml index 9a7abc878b831..f0372e28c99e0 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,wcn3990-pmu.yaml @@ -42,6 +42,8 @@ properties: maxItems: 1 description: GPIO line indicating the state of the clock supply to the BT module + wakeup-source: true + clocks: maxItems: 1 description: Reference clock handle @@ -67,6 +69,10 @@ required: - vddrf-supply - vddch0-supply +dependentRequired: + wakeup-source: + - swctrl-gpios + additionalProperties: false examples: From 5be4911949a060384d6897638db2edc919241e49 Mon Sep 17 00:00:00 2001 From: Linghui Wu Date: Mon, 19 Oct 2026 05:47:58 +0000 Subject: [PATCH 0089/1133] FROMLIST: power: sequencing: qcom-wcn: support SW_CTRL wake IRQ Some WCN3990-family devices use SW_CTRL to signal that resources need remain available while the application processor is suspended. When the PMU is marked as a wakeup source, request the existing SW_CTRL GPIO as an input, map it to an IRQ and register it as a dedicated wake IRQ. The PM core then keeps the IRQ disabled during normal operation and arms it for system suspend. Link: https://lore.kernel.org/r/20261019093911.3199891-3-linghui.wu@oss.qualcomm.com Signed-off-by: Linghui Wu --- drivers/power/sequencing/pwrseq-qcom-wcn.c | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/power/sequencing/pwrseq-qcom-wcn.c b/drivers/power/sequencing/pwrseq-qcom-wcn.c index 636dd7e638917..69b7eb565996e 100644 --- a/drivers/power/sequencing/pwrseq-qcom-wcn.c +++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -484,11 +486,18 @@ static int pwrseq_qcom_wcn3990_match(struct pwrseq_device *pwrseq, return pwrseq_qcom_wcn_match_regulator(pwrseq, dev, "vdd-1.8-xo-supply"); } +static void pwrseq_qcom_wcn_clear_wake_irq(void *data) +{ + dev_pm_clear_wake_irq(data); +} + static int pwrseq_qcom_wcn_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct pwrseq_qcom_wcn_ctx *ctx; + struct gpio_desc *swctrl_gpio; struct pwrseq_config config; + int wake_irq; int i, ret; ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); @@ -526,6 +535,33 @@ static int pwrseq_qcom_wcn_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(ctx->bt_gpio), "Failed to get the Bluetooth enable GPIO\n"); + if (device_property_read_bool(dev, "wakeup-source")) { + swctrl_gpio = devm_gpiod_get(dev, "swctrl", GPIOD_IN); + if (IS_ERR(swctrl_gpio)) + return dev_err_probe(dev, PTR_ERR(swctrl_gpio), + "Failed to get the SW_CTRL GPIO\n"); + + wake_irq = gpiod_to_irq(swctrl_gpio); + if (wake_irq < 0) + return dev_err_probe(dev, wake_irq, + "Failed to get the SW_CTRL wake IRQ\n"); + + ret = devm_device_init_wakeup(dev); + if (ret) + return dev_err_probe(dev, ret, + "Failed to enable wakeup\n"); + + ret = dev_pm_set_dedicated_wake_irq(dev, wake_irq); + if (ret) + return dev_err_probe(dev, ret, + "Failed to set the SW_CTRL wake IRQ\n"); + + ret = devm_add_action_or_reset(dev, + pwrseq_qcom_wcn_clear_wake_irq, dev); + if (ret) + return ret; + } + ctx->wlan_gpio = devm_gpiod_get_optional(dev, "wlan-enable", GPIOD_OUT_LOW); if (IS_ERR(ctx->wlan_gpio)) From 0b35003d23b11215fe60bcffe1301e7ba674cf60 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Fri, 25 Sep 2026 11:09:48 +0200 Subject: [PATCH 0090/1133] FROMLIST: media: qcom: camss: Add V4L2 meta format for CAMSS ISP parameters Add a V4L2 meta format code (V4L2_META_FMT_QCOM_ISP_PARAMS) for the Qualcomm CAMSS ISP parameter buffer. This format is used by the params video node exposed by CAMSS offline ISP drivers (e.g. OPE) to carry ISP tuning data such as white balance, color correction and chroma enhancement settings. Signed-off-by: Loic Poulain Link: https://lore.kernel.org/all/20260925-camss-isp-ope-v10-1-2622411034cb@oss.qualcomm.com/ --- drivers/media/v4l2-core/v4l2-ioctl.c | 1 + include/uapi/linux/videodev2.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 17ba1ae707355..cef1593c18350 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1471,6 +1471,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_META_FMT_C3ISP_STATS: descr = "Amlogic C3 ISP Statistics"; break; case V4L2_META_FMT_MALI_C55_PARAMS: descr = "ARM Mali-C55 ISP Parameters"; break; case V4L2_META_FMT_MALI_C55_STATS: descr = "ARM Mali-C55 ISP 3A Statistics"; break; + case V4L2_META_FMT_QCOM_ISP_PARAMS: descr = "Qualcomm CAMSS ISP Parameters"; break; case V4L2_META_FMT_RPPX1_PARAMS: descr = "Dreamchip RPP-X1 ISP Parameters"; break; case V4L2_META_FMT_RPPX1_STATS: descr = "Dreamchip RPP-X1 ISP Statistics"; break; case V4L2_PIX_FMT_NV12_8L128: descr = "NV12 (8x128 Linear)"; break; diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 5373dba640fae..70208a9443d8a 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -893,6 +893,9 @@ struct v4l2_pix_format { #define V4L2_META_FMT_RPPX1_PARAMS v4l2_fourcc('D', 'R', '1', 'P') /* Dreamchip RPP-X1 Parameters */ #define V4L2_META_FMT_RPPX1_STATS v4l2_fourcc('D', 'R', '1', 'S') /* Dreamchip RPP-X1 Statistics */ +/* Vendor specific - used for Qualcomm CAMSS ISP */ +#define V4L2_META_FMT_QCOM_ISP_PARAMS v4l2_fourcc('Q', 'C', 'I', 'P') /* Qualcomm CAMSS ISP Parameters */ + #ifdef __KERNEL__ /* * Line-based metadata formats. Remember to update v4l_fill_fmtdesc() when From f3281a1b3c9bd4f2433d162603b99a4ca0b8809d Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Fri, 25 Sep 2026 11:09:49 +0200 Subject: [PATCH 0091/1133] FROMLIST: dt-bindings: media: qcom: Add CAMSS Offline Processing Engine (OPE) Add Devicetree binding documentation for the Qualcomm Camera Subsystem Offline Processing Engine (OPE) found on platforms such as Agatti. The OPE is a memory-to-memory image processing block which operates on frames read from and written back to system memory. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Loic Poulain Link: https://lore.kernel.org/all/20260925-camss-isp-ope-v10-2-2622411034cb@oss.qualcomm.com/ --- .../media/qcom,qcm2290-camss-ope.yaml | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,qcm2290-camss-ope.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-camss-ope.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss-ope.yaml new file mode 100644 index 0000000000000..f9c31bc88e94b --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss-ope.yaml @@ -0,0 +1,151 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,qcm2290-camss-ope.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Camera Subsystem Offline Processing Engine + +maintainers: + - Loic Poulain + +description: + The Qualcomm Camera Subsystem (CAMSS) Offline Processing Engine (OPE) + is a memory-to-memory image processing block. It supports a range of + pixel-processing operations such as scaling, cropping, gain adjustments, + white-balancing, and various format conversions. The OPE does not + interface directly with image sensors, instead, it processes frames + sourced from and written back to system memory. + +properties: + compatible: + const: qcom,qcm2290-camss-ope + + reg: + maxItems: 6 + + reg-names: + items: + - const: cdm + - const: top + - const: qos + - const: pipeline + - const: bus_read + - const: bus_write + + clocks: + maxItems: 5 + + clock-names: + items: + - const: axi + - const: core + - const: iface + - const: nrt + - const: top + + interrupts: + maxItems: 1 + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: config + - const: data + + iommus: + items: + - description: OPE CDM (Configuration DMA) port. + - description: OPE read (fetch engine) port. + - description: OPE write (write engine) port. + + operating-points-v2: true + + opp-table: + type: object + + power-domains: + items: + - description: GDSC CAMSS Block, Global Distributed Switch Controller. + - description: CX power domain. + + power-domain-names: + items: + - const: camss + - const: cx + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + + camss_ope: isp@5c42000 { + compatible = "qcom,qcm2290-camss-ope"; + + reg = <0x5c42000 0x400>, + <0x5c42400 0x200>, + <0x5c42600 0x200>, + <0x5c42800 0x4400>, + <0x5c46c00 0x190>, + <0x5c46d90 0xa00>; + reg-names = "cdm", "top", "qos", "pipeline", + "bus_read", "bus_write"; + + clocks = <&gcc GCC_CAMSS_AXI_CLK>, + <&gcc GCC_CAMSS_OPE_CLK>, + <&gcc GCC_CAMSS_OPE_AHB_CLK>, + <&gcc GCC_CAMSS_NRT_AXI_CLK>, + <&gcc GCC_CAMSS_TOP_AHB_CLK>; + clock-names = "axi", "core", "iface", "nrt", "top"; + + interrupts = ; + + interconnects = <&bimc MASTER_APPSS_PROC RPM_ACTIVE_TAG + &config_noc SLAVE_CAMERA_CFG RPM_ACTIVE_TAG>, + <&mmnrt_virt MASTER_CAMNOC_SF RPM_ALWAYS_TAG + &bimc SLAVE_EBI1 RPM_ALWAYS_TAG>; + interconnect-names = "config", "data"; + + iommus = <&apps_smmu 0x800 0x0>, + <&apps_smmu 0x820 0x0>, + <&apps_smmu 0x840 0x0>; + + operating-points-v2 = <&ope_opp_table>; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>, + <&rpmpd QCM2290_VDDCX>; + power-domain-names = "camss", "cx"; + + ope_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-465000000 { + opp-hz = /bits/ 64 <465000000>; + required-opps = <&rpmpd_opp_nom>; + }; + }; + }; From 52a2043c1c276ec127a9f55235f47933ede27664 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Fri, 25 Sep 2026 11:09:50 +0200 Subject: [PATCH 0092/1133] FROMLIST: dt-bindings: media: qcom,qcm2290-camss-ope: Document shikra compatible Shikra uses the same Offline Processing Engine hardware as QCM2290, add qcom,shikra-camss-ope compatible string with qcom,qcm2290-camss-ope as the fallback. Signed-off-by: Loic Poulain Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260925-camss-isp-ope-v10-3-2622411034cb@oss.qualcomm.com/ --- .../devicetree/bindings/media/qcom,qcm2290-camss-ope.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-camss-ope.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss-ope.yaml index f9c31bc88e94b..3359581bfb13e 100644 --- a/Documentation/devicetree/bindings/media/qcom,qcm2290-camss-ope.yaml +++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss-ope.yaml @@ -19,7 +19,11 @@ description: properties: compatible: - const: qcom,qcm2290-camss-ope + oneOf: + - items: + - const: qcom,shikra-camss-ope + - const: qcom,qcm2290-camss-ope + - const: qcom,qcm2290-camss-ope reg: maxItems: 6 From 840b7f5efedcfe76ca0176b0a275dc523b6515a5 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Fri, 25 Sep 2026 11:09:51 +0200 Subject: [PATCH 0093/1133] FROMLIST: media: uapi: Add CAMSS ISP configuration definition Add the uapi header qcom-camss-config.h defining the ISP parameter structures used by the CAMSS Offline Processing Engine (OPE) driver. This includes structures for white balance, chroma enhancement and color correction configuration. The block type enum is shared across CAMSS ISPs so that userspace only has to deal with a single set of block identifiers. Signed-off-by: Loic Poulain Link: https://lore.kernel.org/all/20260925-camss-isp-ope-v10-4-2622411034cb@oss.qualcomm.com/ --- include/uapi/linux/qcom-camss-config.h | 212 +++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 include/uapi/linux/qcom-camss-config.h diff --git a/include/uapi/linux/qcom-camss-config.h b/include/uapi/linux/qcom-camss-config.h new file mode 100644 index 0000000000000..aa3d97cfcc78e --- /dev/null +++ b/include/uapi/linux/qcom-camss-config.h @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Qualcomm CAMSS ISP Driver - Userspace API + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _UAPI_LINUX_QCOM_CAMSS_CONFIG_H +#define _UAPI_LINUX_QCOM_CAMSS_CONFIG_H + +#include +#include + +/** + * enum camss_params_block_type - CAMSS ISP parameter block identifiers + * + * Each value identifies one ISP processing block. The value is placed in + * the @type field of &struct v4l2_isp_params_block_header. + * + * @CAMSS_PARAMS_WB_GAIN: white balance gains and offsets (CLC_WB), + * &struct camss_params_wb_gain + * @CAMSS_PARAMS_CHROMA_ENHAN: RGB to YUV colour transfer matrix + * (CLC_CHROMA_ENHAN), &struct camss_params_chroma_enhan + * @CAMSS_PARAMS_COLOR_CORRECT: colour correction matrix (CLC_CC), + * &struct camss_params_color_correct + * @CAMSS_PARAMS_GAMMA: per-channel gamma correction curves (CLC_GLUT), + * &struct camss_params_gamma + */ +enum camss_params_block_type { + CAMSS_PARAMS_WB_GAIN = 1, + CAMSS_PARAMS_CHROMA_ENHAN = 2, + CAMSS_PARAMS_COLOR_CORRECT = 3, + CAMSS_PARAMS_GAMMA = 4, +}; + +/* Number of entries in each gamma channel LUT. */ +#define CAMSS_GAMMA_LUT_SIZE 256 + +/** + * struct camss_params_wb_gain - White Balance gains + * + * Implements the CLC_WB pipeline module. The pipeline applies three + * sequential operations per channel: + * 1. Subtract sub-offset (black-level subtraction) + * 2. Multiply by gain (colour balance) + * 3. Add add-offset (output pedestal) + * + * Gains are 15uQ10 (15-bit unsigned, 10 fractional bits). Offsets + * are 16-bit unsigned, normalised to full input scale (65535 = 1.0) + * + * @header: block header; @header.type = CAMSS_PARAMS_WB_GAIN + * @g_gain: green channel gain (15uQ10, 1024 = 1.0) + * @b_gain: blue channel gain (15uQ10, 1024 = 1.0) + * @r_gain: red channel gain (15uQ10, 1024 = 1.0) + * @g_sub: green sub-offset, subtracted before gain (16u) + * @b_sub: blue sub-offset, subtracted before gain (16u) + * @r_sub: red sub-offset, subtracted before gain (16u) + * @g_add: green add-offset, added after gain (16u) + * @b_add: blue add-offset, added after gain (16u) + * @r_add: red add-offset, added after gain (16u) + * @_pad: padding for 64-bit alignment, must be zero + */ +struct camss_params_wb_gain { + struct v4l2_isp_params_block_header header; + __u16 g_gain; + __u16 b_gain; + __u16 r_gain; + __u16 g_sub; + __u16 b_sub; + __u16 r_sub; + __u16 g_add; + __u16 b_add; + __u16 r_add; + __u16 _pad[3]; +} __attribute__((aligned(8))); + +/** + * struct camss_params_chroma_enhan - RGB to YUV colour transfer matrix + * + * Implements the CLC_CHROMA_ENHAN pipeline module. All coefficients are + * signed 12-bit fixed-point Q3.8 (range roughly -8.0 to +7.996). + * + * RGB2Y - Luma (Y) coefficients + * Y = v0 * R + v1 * G + v2 * B + * + * @luma_v0: R-to-Y coefficient (12sQ8) + * @luma_v1: G-to-Y coefficient (12sQ8) + * @luma_v2: B-to-Y coefficient (12sQ8) + * @luma_k: Y output offset (9s, 0 = no offset) + * + * RGB2Cb - Chroma (Cb) coefficients + * Cb = a x ((B - G) + b(R - G)) + KCb + * with: + * a = ap, when (B-G) + b(R-G) > 0; a = am, when (B-G) + b(R-G) ≤ 0; + * b = bp when (R-G) > 0; b = bm when (R-G) ≤ 0 + * + * @coeff_ap: Cb positive coefficient (12sQ8) + * @coeff_am: Cb negative coefficient (12sQ8) + * @coeff_bp: Cb positive coefficient (12sQ8) + * @coeff_bm: Cb negative coefficient (12sQ8) + * @kcb: Cb output offset (11s) + * + * RGB2Cr - Chroma (Cr) coefficients: + * Cr = c x ((R - G) + d(B - G)) + KCr + * with: + * c = cp, when (R-G) + d(B-G) > 0; c = cm, when (R-G) + d(B-G) ≤ 0 + * d = dp when (B-G) > 0; d = dm when (B-G) ≤ 0 + * + * @coeff_cp: Cr positive coefficient (12sQ8) + * @coeff_cm: Cr negative coefficient (12sQ8) + * @coeff_dp: Cr positive coefficient (12sQ8) + * @coeff_dm: Cr negative coefficient (12sQ8) + * @kcr: Cr output offset (11s) + * + * @header: generic block header; @header.type = CAMSS_PARAMS_CHROMA_ENHAN + * @_pad: padding for 64-bit alignment, must be zero + */ +struct camss_params_chroma_enhan { + struct v4l2_isp_params_block_header header; + __u16 luma_v0; + __u16 luma_v1; + __u16 luma_v2; + __u16 luma_k; + __u16 coeff_ap; + __u16 coeff_am; + __u16 coeff_bp; + __u16 coeff_bm; + __u16 coeff_cp; + __u16 coeff_cm; + __u16 coeff_dp; + __u16 coeff_dm; + __u16 kcb; + __u16 kcr; + __u16 _pad[2]; +} __attribute__((aligned(8))); + +/** + * struct camss_params_color_correct - colour correction matrix + * + * Implements the CLC_CC pipeline module. The matrix computes: + * Out_ch0 (G) = a0*G + b0*B + c0*R + k0 + * Out_ch1 (B) = a1*G + b1*B + c1*R + k1 + * Out_ch2 (R) = a2*G + b2*B + c2*R + k2 + * + * @header: block header; @header.type = CAMSS_PARAMS_COLOR_CORRECT + * @a: G-input coefficients per output channel (12s; + * a[0]=Out_G, a[1]=Out_B, a[2]=Out_R) + * @b: B-input coefficients (12s) + * @c: R-input coefficients (12s) + * @k: per-output-channel offsets (typically 9s effective) + * @qfactor: Q-format selector (2u): + * 0 = 12sQ7 (range ~-16.0 .. +15.992) + * 1 = 12sQ8 (range ~-8.0 .. +7.996) + * 2 = 12sQ9 (range ~-4.0 .. +3.998) + * 3 = 12sQ10 (range ~-2.0 .. +1.999) + * @_pad: padding for 64-bit alignment, must be zero + */ +struct camss_params_color_correct { + struct v4l2_isp_params_block_header header; + __u16 a[3]; + __u16 b[3]; + __u16 c[3]; + __u16 k[3]; + __u16 qfactor; + __u16 _pad[3]; +} __attribute__((aligned(8))); + +/** + * struct camss_params_gamma - per-channel gamma correction curves + * + * Implements the CLC_GLUT pipeline module, applied in the RGB domain. It + * holds one independent lookup table per colour channel. Each table is a + * direct (not segmented) map of input level to output level. + * + * Each table has @CAMSS_GAMMA_LUT_SIZE (256) entries of 16-bit unsigned + * output. The number of significant output bits follows the width of the + * engine's internal bus; the upper bits are ignored by the hardware. + * + * The module maps a 12-bit input to an 8-bit output: the top 8 input bits + * index the table and the low 4 bits are used to linearly interpolate + * between adjacent entries. Entry i therefore represents the output for + * input level i/255 of full scale. + * Output range: 0x00 = black, 0xFF = white. + * + * How to fill a curve (same on all three channels for pure luminance + * gamma; different curves per channel additionally shift colour balance): + * + * Identity (pass-through, gamma 1.0): + * lut[i] = i; // i = 0..255 + * + * Encode with gamma g (e.g. sRGB-like, g = 2.2): + * lut[i] = round(pow(i / 255.0, 1.0 / g) * 255.0); + * + * @header: block header; @header.type = CAMSS_PARAMS_GAMMA + * @glut: green channel gamma curve + * @blut: blue channel gamma curve + * @rlut: red channel gamma curve + */ +struct camss_params_gamma { + struct v4l2_isp_params_block_header header; + __u16 glut[CAMSS_GAMMA_LUT_SIZE]; + __u16 blut[CAMSS_GAMMA_LUT_SIZE]; + __u16 rlut[CAMSS_GAMMA_LUT_SIZE]; +} __attribute__((aligned(8))); + +#define CAMSS_PARAMS_OPE_MAX_PAYLOAD \ + (sizeof(struct camss_params_wb_gain) +\ + sizeof(struct camss_params_chroma_enhan) +\ + sizeof(struct camss_params_color_correct) +\ + sizeof(struct camss_params_gamma)) + +#endif /* _UAPI_LINUX_QCOM_CAMSS_CONFIG_H */ From dcd44af62a8912b2015042f9af8d196809333701 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Fri, 25 Sep 2026 11:09:52 +0200 Subject: [PATCH 0094/1133] FROMLIST: media: Documentation: uapi: Add qcom-camss ISP params documentation Add documentation for the Qualcomm CAMSS ISP parameters metadata format (V4L2_META_FMT_QCOM_ISP_PARAMS). The format is built on the V4L2 extensible ISP parameters system, with per-block structs defined in the qcom-camss-config.h uAPI header, and is designed to be shared by any CAMSS ISP engine exposing a parameters metadata output video node. The Offline Processing Engine (OPE) ope_params node is the first consumer, with additional engines expected to add their own parameter blocks in the future. Signed-off-by: Loic Poulain Link: https://lore.kernel.org/all/20260925-camss-isp-ope-v10-5-2622411034cb@oss.qualcomm.com/ --- .../userspace-api/media/v4l/meta-formats.rst | 1 + .../media/v4l/metafmt-qcom-isp.rst | 147 ++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 149 insertions(+) create mode 100644 Documentation/userspace-api/media/v4l/metafmt-qcom-isp.rst diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst b/Documentation/userspace-api/media/v4l/meta-formats.rst index b5455229837e7..25b46af4d9f7f 100644 --- a/Documentation/userspace-api/media/v4l/meta-formats.rst +++ b/Documentation/userspace-api/media/v4l/meta-formats.rst @@ -20,6 +20,7 @@ These formats are used for the :ref:`metadata` interface only. metafmt-intel-ipu3 metafmt-pisp-be metafmt-pisp-fe + metafmt-qcom-isp metafmt-rkisp1 metafmt-rppx1 metafmt-uvc diff --git a/Documentation/userspace-api/media/v4l/metafmt-qcom-isp.rst b/Documentation/userspace-api/media/v4l/metafmt-qcom-isp.rst new file mode 100644 index 0000000000000..2f3654a9ba897 --- /dev/null +++ b/Documentation/userspace-api/media/v4l/metafmt-qcom-isp.rst @@ -0,0 +1,147 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. c:namespace:: V4L + +.. _v4l2-meta-fmt-qcom-isp-params: + +************************************** +V4L2_META_FMT_QCOM_ISP_PARAMS ('QCIP') +************************************** + +Configuration Parameters +======================== + +The ``V4L2_META_FMT_QCOM_ISP_PARAMS`` format carries image processing +configuration for the ISP engines found in the Qualcomm Camera Subsystem +(CAMSS). It is passed to a metadata output video node using the +:c:type:`v4l2_meta_format` interface. + +Rather than a single struct containing sub-structs for each configurable area +of the ISP, parameters use the :ref:`v4l2-isp` parameters system, through which +groups of parameters are defined as distinct structs or "blocks" which may be +added to the data member of :c:type:`v4l2_isp_params_buffer`. Userspace is +responsible for populating the data member with the blocks that need to be +configured by the driver. Each block-specific struct embeds +:c:type:`v4l2_isp_params_block_header` as its first member and userspace must +populate the type member with a value from :c:type:`camss_params_block_type`. +Populated blocks must be placed consecutively in the data member, and the +combined size of all populated blocks must be set in the data_size member of +:c:type:`v4l2_isp_params_buffer`. + +The set of supported blocks depends on the CAMSS engine consuming the buffer. +The block definitions themselves are shared across CAMSS ISPs; currently the +Offline Processing Engine (OPE) is the only engine consuming them, through its +``ope_params`` metadata output video node. Additional engines and blocks may be +added to this format in the future. + +A block carrying ``V4L2_ISP_PARAMS_FL_BLOCK_DISABLE`` bypasses the +corresponding hardware module. Any other block updates the module's +configuration and leaves it enabled. Blocks omitted from a buffer keep their +previously programmed configuration and enable state; until userspace submits +a block for a given module, the driver's default configuration applies. + +OPE processing pipeline +======================= + +The OPE is a memory-to-memory engine that reads a Bayer RAW frame from its +``ope_input`` node and writes a YUV frame to its ``ope_disp_output`` node. The +parameter blocks configure fixed-function hardware modules that the frame data +passes through, in the following order: + +.. code-block:: none + + Bayer RAW in RGB domain YUV domain YUV out + (8/10-bit) +------+ +------+ +------+ +------+ +------+ +------+ (NV12/NV16/ + ----------> | WB |-->| DEMO |-->| CC |-->| GLUT |-->|CHROMA|-->| DSC |-----------> + +------+ +------+ +------+ +------+ |ENHAN | +------+ NV24/GREY) + +------+ + +The stages, and the parameter block that configures each one, are: + +.. flat-table:: OPE pipeline stages + :header-rows: 1 + :stub-columns: 0 + + * - Stage + - Module + - Parameter block + - Function + * - WB + - CLC_WB + - :c:type:`camss_params_wb_gain` + - Per-channel white balance gains and black-level / pedestal offsets, + applied to the raw Bayer data. + * - DEMO + - CLC_DEMO + - *(none)* + - Demosaic: reconstructs a full-resolution RGB image from the Bayer + mosaic. Always enabled; not configurable through this format. + * - CC + - CLC_CC + - :c:type:`camss_params_color_correct` + - Color correction matrix applied in the RGB domain. + * - GLUT + - CLC_GLUT + - :c:type:`camss_params_gamma` + - Per-channel gamma correction curves (256-entry LUTs). + * - CHROMA_ENHAN + - CLC_CHROMA_ENHAN + - :c:type:`camss_params_chroma_enhan` + - RGB to YUV color transfer matrix. + * - DSC + - Downscaler + - *(none)* + - Chroma (and, when required, luma) downscaling to produce the requested + YUV subsampling, e.g. YUV 4:4:4 to 4:2:2 (NV16) or 4:2:0 (NV12). + +The input node accepts 8-bit and 10-bit packed Bayer RAW formats (for example +``V4L2_PIX_FMT_SRGGB8`` and ``V4L2_PIX_FMT_SRGGB10P``). The output node +produces semi-planar YUV (``V4L2_PIX_FMT_NV12`` / ``NV21`` / ``NV16`` / +``NV61`` / ``NV24`` / ``NV42``) or luma-only ``V4L2_PIX_FMT_GREY``. A +configurable stage is bypassed while its block carries +``V4L2_ISP_PARAMS_FL_BLOCK_DISABLE``. + +The following example populates an OPE parameters buffer with a white balance +and a gamma correction block: + +.. code-block:: c + + struct v4l2_isp_params_buffer *params = + (struct v4l2_isp_params_buffer *)buffer; + + params->version = V4L2_ISP_PARAMS_VERSION_V1; + params->data_size = sizeof(struct camss_params_wb_gain) + + sizeof(struct camss_params_gamma); + + __u8 *data = params->data; + + struct camss_params_wb_gain *wb = + (struct camss_params_wb_gain *)data; + + memset(wb, 0, sizeof(*wb)); + wb->header.type = CAMSS_PARAMS_WB_GAIN; + wb->header.flags = V4L2_ISP_PARAMS_FL_BLOCK_ENABLE; + wb->header.size = sizeof(struct camss_params_wb_gain); + + /* Unity gain on all three channels (15uQ10, 1024 = 1.0) */ + wb->g_gain = 1024; + wb->b_gain = 1024; + wb->r_gain = 1024; + + data += sizeof(struct camss_params_wb_gain); + + struct camss_params_gamma *gamma = + (struct camss_params_gamma *)data; + + memset(gamma, 0, sizeof(*gamma)); + gamma->header.type = CAMSS_PARAMS_GAMMA; + gamma->header.flags = V4L2_ISP_PARAMS_FL_BLOCK_ENABLE; + gamma->header.size = sizeof(struct camss_params_gamma); + + /* Identity curve (pass-through, gamma 1.0) */ + for (unsigned int i = 0; i < CAMSS_GAMMA_LUT_SIZE; i++) + gamma->glut[i] = gamma->blut[i] = gamma->rlut[i] = i; + +Qualcomm CAMSS ISP uAPI data types +================================== + +.. kernel-doc:: include/uapi/linux/qcom-camss-config.h diff --git a/MAINTAINERS b/MAINTAINERS index 93abbb315065d..80748cabb2eb3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22880,6 +22880,7 @@ L: linux-media@vger.kernel.org S: Maintained F: Documentation/admin-guide/media/qcom_camss.rst F: Documentation/devicetree/bindings/media/qcom,*camss* +F: Documentation/userspace-api/media/v4l/metafmt-qcom-isp.rst F: drivers/media/platform/qcom/camss/ QUALCOMM CLOCK DRIVERS From f929c2c45d0c3ec6a9ec9c56652657a804645e3b Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Fri, 25 Sep 2026 11:09:53 +0200 Subject: [PATCH 0095/1133] FROMLIST: media: qcom: camss: Add CAMSS Offline Processing Engine driver Add an image processing driver for the Qualcomm Offline Processing Engine (OPE). OPE is a memory-to-memory ISP block that converts raw Bayer frames to YUV, performing white balance, demosaic, chroma enhancement, color correction and downscaling. The hardware architecture consists of Fetch Engines and Write Engines, connected through intermediate pipeline modules for pix processing. The driver exposes three video nodes per pipeline instance: - ope_input: Bayer RAW input (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - ope_disp_output: YUV output (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - ope_params: ISP parameters (V4L2_BUF_TYPE_META_OUTPUT) Hardware features: - Stripe-based processing (up to 336 pixels wide per stripe) - White balance (CLC_WB) - Demosaic / Bayer-to-RGB (CLC_DEMO) - Color correction matrix (CLC_CC) - Gamma LUT (CLC_GAMMA) - RGB-to-YUV conversion (CLC_CHROMA_ENHAN) - MN downscaler for chroma and luma planes Default configuration values are based on public standards such as BT.601. Processing Model: OPE processes frames in stripes of up to 336 pixels. Therefore, frames must be split into stripes for processing. Each stripe is configured after the previous one has been acquired (double buffered registers). To minimize inter-stripe latency, stripe configurations are generated ahead of time. The driver is split into three source files under the ope/ directory: - core.c: the OPE m2m driver itself: probe, power management, V4L2/media device setup, format handling, stripe generation and hardware programming. - pipeline.c/.h: a small declarative media-controller topology builder. Drivers describe their entire media graph, entities (video devices, subdevs, or base entities), their pads, and the links between them, in a static descriptor table. The builder validates the table, allocates and registers all entities, and creates all MC pad links. It is kept generic but currently only used by OPE. - params.c/.h: V4L2 ISP parameter buffer validation and dispatch. It wraps the extensible V4L2 ISP parameters buffer format, validating the buffer size and each per-block header before forwarding every block to its driver-supplied handler. A userspace libcamera support can be found at: https://github.com/jwrdegoede/libcamera/commits/camss_pipeline_v2.1/ A test tool, camss-isp-m2m, can be found at: https://github.com/loicpoulain/camss-isp-m2m-test Assisted-by: LLM Co-developed-by: Hans de Goede Signed-off-by: Hans de Goede Link: https://github.com/jwrdegoede/libcamera/commits/camss_pipeline_v2.1/ Link: https://github.com/loicpoulain/camss-isp-m2m-test Signed-off-by: Loic Poulain Link: https://lore.kernel.org/all/20260925-camss-isp-ope-v10-6-2622411034cb@oss.qualcomm.com/ --- MAINTAINERS | 1 + drivers/media/platform/qcom/camss/Kconfig | 2 + drivers/media/platform/qcom/camss/Makefile | 2 + drivers/media/platform/qcom/camss/ope/Kconfig | 17 + .../media/platform/qcom/camss/ope/Makefile | 9 + drivers/media/platform/qcom/camss/ope/core.c | 3843 +++++++++++++++++ .../media/platform/qcom/camss/ope/params.c | 78 + .../media/platform/qcom/camss/ope/params.h | 95 + .../media/platform/qcom/camss/ope/pipeline.c | 405 ++ .../media/platform/qcom/camss/ope/pipeline.h | 239 + 10 files changed, 4691 insertions(+) create mode 100644 drivers/media/platform/qcom/camss/ope/Kconfig create mode 100644 drivers/media/platform/qcom/camss/ope/Makefile create mode 100644 drivers/media/platform/qcom/camss/ope/core.c create mode 100644 drivers/media/platform/qcom/camss/ope/params.c create mode 100644 drivers/media/platform/qcom/camss/ope/params.h create mode 100644 drivers/media/platform/qcom/camss/ope/pipeline.c create mode 100644 drivers/media/platform/qcom/camss/ope/pipeline.h diff --git a/MAINTAINERS b/MAINTAINERS index 80748cabb2eb3..4721091a93ca5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22882,6 +22882,7 @@ F: Documentation/admin-guide/media/qcom_camss.rst F: Documentation/devicetree/bindings/media/qcom,*camss* F: Documentation/userspace-api/media/v4l/metafmt-qcom-isp.rst F: drivers/media/platform/qcom/camss/ +F: include/uapi/linux/qcom-camss-config.h QUALCOMM CLOCK DRIVERS M: Bjorn Andersson diff --git a/drivers/media/platform/qcom/camss/Kconfig b/drivers/media/platform/qcom/camss/Kconfig index b51745c942c9f..b66faac2683c9 100644 --- a/drivers/media/platform/qcom/camss/Kconfig +++ b/drivers/media/platform/qcom/camss/Kconfig @@ -9,3 +9,5 @@ config VIDEO_QCOM_CAMSS select V4L2_FWNODE select GENERIC_PHY imply PHY_QCOM_MIPI_CSI2 + +source "drivers/media/platform/qcom/camss/ope/Kconfig" diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index 27898b3cc7d3c..b79c40626c401 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -31,3 +31,5 @@ qcom-camss-objs += \ camss-video.o obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom-camss.o + +obj-$(CONFIG_VIDEO_QCOM_CAMSS_OPE) += ope/ diff --git a/drivers/media/platform/qcom/camss/ope/Kconfig b/drivers/media/platform/qcom/camss/ope/Kconfig new file mode 100644 index 0000000000000..d9f96430f145a --- /dev/null +++ b/drivers/media/platform/qcom/camss/ope/Kconfig @@ -0,0 +1,17 @@ +config VIDEO_QCOM_CAMSS_OPE + tristate "Qualcomm Offline Processing Engine (OPE) driver" + depends on V4L_PLATFORM_DRIVERS + depends on MEDIA_CONTROLLER + depends on VIDEO_DEV + depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST + select V4L2_ISP + select VIDEOBUF2_DMA_CONTIG + select VIDEOBUF2_VMALLOC + help + Enable support for the Qualcomm Offline Processing Engine (OPE). + OPE is a memory-to-memory ISP block that converts raw Bayer frames + to YUV, performing white balance, demosaic, chroma enhancement and + downscaling. Found on QCM2290 and related SoCs. + + To compile this driver as a module, choose M here: the module + will be called qcom-camss-ope. diff --git a/drivers/media/platform/qcom/camss/ope/Makefile b/drivers/media/platform/qcom/camss/ope/Makefile new file mode 100644 index 0000000000000..02599a7b46e17 --- /dev/null +++ b/drivers/media/platform/qcom/camss/ope/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Makefile for Qualcomm CAMSS Offline Processing Engine (OPE) driver + +qcom-camss-ope-objs := \ + core.o \ + pipeline.o \ + params.o + +obj-$(CONFIG_VIDEO_QCOM_CAMSS_OPE) += qcom-camss-ope.o diff --git a/drivers/media/platform/qcom/camss/ope/core.c b/drivers/media/platform/qcom/camss/ope/core.c new file mode 100644 index 0000000000000..122e6c8deb022 --- /dev/null +++ b/drivers/media/platform/qcom/camss/ope/core.c @@ -0,0 +1,3843 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ope/core.c + * + * Qualcomm MSM Camera Subsystem - Offline Processing Engine + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/* + * This driver provides driver implementation for the Qualcomm Offline + * Processing Engine (OPE). OPE is a memory-to-memory hardware block + * designed for image processing on a source frame. Typically, the input + * frame originates from the SoC CSI capture path, though not limited to. + * + * The hardware architecture consists of Fetch Engines and Write Engines, + * connected through intermediate pipeline modules: + * [FETCH ENGINES] => [Pipeline Modules] => [WRITE ENGINES] + * + * Current Configuration: + * Fetch Engine: One fetch engine is used for Bayer frame input. + * Write Engines: Two display write engines for Y and UV planes output. + * + * Only a subset of the pipeline modules are enabled: + * WB: White balance for channel gain configuration + * DEMO: Demosaic for Bayer to RGB conversion + * CC: Color Correct, coefficient based RGB correction + * GLUT: Gamma LUT, redistributes brightness levels + * CHROMA_ENHAN: for RGB to YUV conversion + * DOWNSCALE*: Downscaling for UV (YUV444 -> YUV422/YUV420) and YUV planes + * + * Default configuration values are based on public standards such as BT.601. + * + * Processing Model: + * OPE processes frames in stripes of up to 336 pixels. Therefore, frames must + * be split into stripes for processing. Each stripe is configured after the + * previous one has been acquired (double buffered registers). To minimize + * inter-stripe latency, the stripe configurations are generated ahead of time. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pipeline.h" + +#include +#include + +#include + +#include "params.h" + +#define OPE_NAME "qcom-camss-ope" + +/* Format descriptor */ +struct ope_fmt { + u32 fourcc; + unsigned int depth; + unsigned int align; + unsigned int num_planes; + u32 mbus_code; + unsigned int c_hsub; + unsigned int c_vsub; +}; + +/* Per-queue format state */ +struct ope_fmt_state { + const struct ope_fmt *fmt; + unsigned int width; + unsigned int height; + struct v4l2_rect crop; + unsigned int bytesperline; + unsigned int sizeimage; + enum v4l2_colorspace colorspace; + enum v4l2_xfer_func xfer_func; + enum v4l2_ycbcr_encoding ycbcr_enc; + enum v4l2_quantization quantization; + unsigned int sequence; + struct v4l2_fract timeperframe; +}; + +/* -------- Register layout -------- */ + +#define OPE_TOP_HW_VERSION 0x000 +#define OPE_TOP_HW_VERSION_STEP GENMASK(15, 0) +#define OPE_TOP_HW_VERSION_REV GENMASK(27, 16) +#define OPE_TOP_HW_VERSION_GEN GENMASK(31, 28) +#define OPE_TOP_RESET_CMD 0x004 +#define OPE_TOP_RESET_CMD_HW BIT(0) +#define OPE_TOP_RESET_CMD_SW BIT(1) +#define OPE_TOP_IRQ_STATUS 0x014 +#define OPE_TOP_IRQ_MASK 0x018 +#define OPE_TOP_IRQ_STATUS_RST_DONE BIT(0) +#define OPE_TOP_IRQ_STATUS_WE BIT(1) +#define OPE_TOP_IRQ_STATUS_FE BIT(2) +#define OPE_TOP_IRQ_STATUS_VIOL BIT(3) +#define OPE_TOP_IRQ_STATUS_IDLE BIT(4) +#define OPE_TOP_IRQ_CLEAR 0x01c +#define OPE_TOP_IRQ_CMD 0x024 +#define OPE_TOP_IRQ_CMD_CLEAR BIT(0) +#define OPE_TOP_VIOLATION_STATUS 0x028 + +/* Fetch engine */ +#define OPE_BUS_RD_INPUT_IF_IRQ_MASK 0x00c +#define OPE_BUS_RD_INPUT_IF_IRQ_CLEAR 0x010 +#define OPE_BUS_RD_INPUT_IF_IRQ_CMD 0x014 +#define OPE_BUS_RD_INPUT_IF_IRQ_CMD_CLEAR BIT(0) +#define OPE_BUS_RD_INPUT_IF_IRQ_STATUS 0x018 +#define OPE_BUS_RD_INPUT_IF_IRQ_STATUS_RST_DONE BIT(0) +#define OPE_BUS_RD_INPUT_IF_IRQ_STATUS_RUP_DONE BIT(1) +#define OPE_BUS_RD_INPUT_IF_IRQ_STATUS_BUF_DONE GENMASK(3, 2) +#define OPE_BUS_RD_INPUT_IF_IRQ_STATUS_CCIF_VIOL GENMASK(17, 16) +#define OPE_BUS_RD_INPUT_IF_CMD 0x01c +#define OPE_BUS_RD_INPUT_IF_CMD_GO_CMD BIT(0) +#define OPE_BUS_RD_CLIENT_0_CORE_CFG 0x050 +#define OPE_BUS_RD_CLIENT_0_CORE_CFG_EN BIT(0) +#define OPE_BUS_RD_CLIENT_0_CCIF_META_DATA 0x054 +#define OPE_BUS_RD_CLIENT_0_CCIF_MD_PIX_PATTERN GENMASK(7, 2) +#define OPE_BUS_RD_CLIENT_0_ADDR_IMAGE 0x058 +#define OPE_BUS_RD_CLIENT_0_RD_BUFFER_SIZE 0x05c +#define OPE_BUS_RD_CLIENT_0_RD_STRIDE 0x060 +#define OPE_BUS_RD_CLIENT_0_UNPACK_CFG_0 0x064 + +/* Write engines */ +#define OPE_BUS_WR_INPUT_IF_IRQ_MASK_0 0x018 +#define OPE_BUS_WR_INPUT_IF_IRQ_MASK_1 0x01c +#define OPE_BUS_WR_INPUT_IF_IRQ_CLEAR_0 0x020 +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0 0x028 +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_RUP_DONE BIT(0) +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_BUF_DONE BIT(8) +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_CONS_VIOL BIT(28) +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_VIOL BIT(30) +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_IMG_SZ_VIOL BIT(31) +#define OPE_BUS_WR_INPUT_IF_IRQ_CMD 0x030 +#define OPE_BUS_WR_INPUT_IF_IRQ_CMD_CLEAR BIT(0) +#define OPE_BUS_WR_VIOLATION_STATUS 0x064 +#define OPE_BUS_WR_IMAGE_SIZE_VIOLATION_STATUS 0x070 +#define OPE_BUS_WR_CLIENT_CFG(c) (0x200 + (c) * 0x100) +#define OPE_BUS_WR_CLIENT_CFG_EN BIT(0) +#define OPE_BUS_WR_CLIENT_CFG_AUTORECOVER BIT(4) +#define OPE_BUS_WR_CLIENT_ADDR_IMAGE(c) (0x204 + (c) * 0x100) +#define OPE_BUS_WR_CLIENT_IMAGE_CFG_0(c) (0x20c + (c) * 0x100) +#define OPE_BUS_WR_CLIENT_IMAGE_CFG_1(c) (0x210 + (c) * 0x100) +#define OPE_BUS_WR_CLIENT_IMAGE_CFG_2(c) (0x214 + (c) * 0x100) +#define OPE_BUS_WR_CLIENT_PACKER_CFG(c) (0x218 + (c) * 0x100) + +/* Pipeline modules */ + +#define OPE_PP_HW_VERSION(base) ((base) + 0x00) +#define OPE_PP_HW_STATUS(base) ((base) + 0x04) +#define OPE_HW_VERSION_GEN(v) ((u32)FIELD_GET(OPE_TOP_HW_VERSION_GEN, (v))) +#define OPE_HW_VERSION_REV(v) ((u32)FIELD_GET(OPE_TOP_HW_VERSION_REV, (v))) +#define OPE_HW_VERSION_STEP(v) ((u32)FIELD_GET(OPE_TOP_HW_VERSION_STEP, (v))) + +#define OPE_PP_WB_GAIN_BASE 0x200 +#define OPE_PP_WB_GAIN_MODULE_CFG (OPE_PP_WB_GAIN_BASE + 0x60) +#define OPE_PP_WB_GAIN_MODULE_CFG_EN BIT(0) +#define OPE_PP_WB_GAIN_WB_CFG(ch) (OPE_PP_WB_GAIN_BASE + 0x68 + 4 * (ch)) +#define OPE_PP_WB_GAIN_WB_CFG_GAIN GENMASK(14, 0) +#define OPE_PP_WB_GAIN_WB_SUB_CFG(ch) (OPE_PP_WB_GAIN_BASE + 0x74 + 4 * (ch)) +#define OPE_PP_WB_GAIN_WB_SUB_CFG_VAL GENMASK(31, 20) +#define OPE_PP_WB_GAIN_WB_ADD_CFG(ch) (OPE_PP_WB_GAIN_BASE + 0x80 + 4 * (ch)) +#define OPE_PP_WB_GAIN_WB_ADD_CFG_VAL GENMASK(31, 20) + +#define OPE_PP_CC_BASE 0xa00 +#define OPE_PP_CC_MODULE_CFG (OPE_PP_CC_BASE + 0x60) +#define OPE_PP_CC_MODULE_CFG_EN BIT(0) +#define OPE_PP_CC_COEFF_A_CFG_0 (OPE_PP_CC_BASE + 0x68) +#define OPE_PP_CC_COEFF_A_CFG_0_A0 GENMASK(11, 0) +#define OPE_PP_CC_COEFF_A_CFG_0_A1 GENMASK(27, 16) +#define OPE_PP_CC_COEFF_A_CFG_1 (OPE_PP_CC_BASE + 0x6c) +#define OPE_PP_CC_COEFF_A_CFG_1_A2 GENMASK(11, 0) +#define OPE_PP_CC_COEFF_B_CFG_0 (OPE_PP_CC_BASE + 0x70) +#define OPE_PP_CC_COEFF_B_CFG_0_B0 GENMASK(11, 0) +#define OPE_PP_CC_COEFF_B_CFG_0_B1 GENMASK(27, 16) +#define OPE_PP_CC_COEFF_B_CFG_1 (OPE_PP_CC_BASE + 0x74) +#define OPE_PP_CC_COEFF_B_CFG_1_B2 GENMASK(11, 0) +#define OPE_PP_CC_COEFF_C_CFG_0 (OPE_PP_CC_BASE + 0x78) +#define OPE_PP_CC_COEFF_C_CFG_0_C0 GENMASK(11, 0) +#define OPE_PP_CC_COEFF_C_CFG_0_C1 GENMASK(27, 16) +#define OPE_PP_CC_COEFF_C_CFG_1 (OPE_PP_CC_BASE + 0x7c) +#define OPE_PP_CC_COEFF_C_CFG_1_C2 GENMASK(11, 0) +#define OPE_PP_CC_COEFF_K_CFG_0 (OPE_PP_CC_BASE + 0x80) +#define OPE_PP_CC_COEFF_K_CFG_0_K0 GENMASK(31, 21) +#define OPE_PP_CC_COEFF_K_CFG_1 (OPE_PP_CC_BASE + 0x84) +#define OPE_PP_CC_COEFF_K_CFG_1_K1 GENMASK(31, 21) +#define OPE_PP_CC_COEFF_K_CFG_2 (OPE_PP_CC_BASE + 0x88) +#define OPE_PP_CC_COEFF_K_CFG_2_K2 GENMASK(31, 21) +#define OPE_PP_CC_COEFF_M_CFG (OPE_PP_CC_BASE + 0x8c) +#define OPE_PP_CC_COEFF_M_CFG_M GENMASK(1, 0) + +#define OPE_PP_GLUT_BASE 0x1000 +#define OPE_PP_GLUT_DMI_CFG (OPE_PP_GLUT_BASE + 0x08) +#define OPE_PP_GLUT_DMI_CFG_AUTO_LOAD_EN BIT(20) +#define OPE_PP_GLUT_DMI_CFG_ADDR GENMASK(7, 0) +#define OPE_PP_GLUT_DMI_LUT_CFG (OPE_PP_GLUT_BASE + 0x0c) +#define OPE_PP_GLUT_DMI_LUT_CFG_SEL GENMASK(1, 0) +#define OPE_PP_GLUT_DMI_DATA (OPE_PP_GLUT_BASE + 0x10) +#define OPE_PP_GLUT_DMI_LUT_BANK_CFG (OPE_PP_GLUT_BASE + 0x58) +#define OPE_PP_GLUT_DMI_LUT_BANK_CFG_SEL BIT(0) +#define OPE_PP_GLUT_MODULE_LUT_BANK_CFG (OPE_PP_GLUT_BASE + 0x5c) +#define OPE_PP_GLUT_MODULE_LUT_BANK_CFG_SEL BIT(0) +#define OPE_PP_GLUT_MODULE_CFG (OPE_PP_GLUT_BASE + 0x60) +#define OPE_PP_GLUT_MODULE_CFG_EN BIT(0) + +#define OPE_PP_DEMO_BASE 0x800 +#define OPE_PP_DEMO_MODULE_CFG (OPE_PP_DEMO_BASE + 0x60) +#define OPE_PP_DEMO_MODULE_CFG_EN BIT(0) +#define OPE_PP_DEMO_MODULE_CFG_DYN_G_CLAMP_EN BIT(14) +#define OPE_PP_DEMO_MODULE_CFG_DYN_RB_CLAMP_EN BIT(15) +#define OPE_PP_DEMO_INTERP_COEFF_CFG (OPE_PP_DEMO_BASE + 0x68) +#define OPE_PP_DEMO_INTERP_COEFF_CFG_LAMBDA_G GENMASK(7, 0) +#define OPE_PP_DEMO_INTERP_COEFF_CFG_LAMBDA_RB GENMASK(23, 16) +#define OPE_PP_DEMO_INTERP_CLASSIFIER_CFG_0 (OPE_PP_DEMO_BASE + 0x6c) +#define OPE_PP_DEMO_INTERP_CLASSIFIER_CFG_0_AK GENMASK(31, 20) +#define OPE_PP_DEMO_INTERP_CLASSIFIER_CFG_1 (OPE_PP_DEMO_BASE + 0x70) +#define OPE_PP_DEMO_INTERP_CLASSIFIER_CFG_1_WK GENMASK(9, 0) + +#define OPE_PP_DOWNSCALE_MN_DS_C_PRE_BASE 0x1c00 +#define OPE_PP_DOWNSCALE_MN_DS_Y_DISP_BASE 0x3000 +#define OPE_PP_DOWNSCALE_MN_DS_C_DISP_BASE 0x3200 +#define OPE_PP_CROP_RND_CLAMP_Y_DISP_BASE 0x3400 +#define OPE_PP_CROP_RND_CLAMP_C_DISP_BASE 0x3600 +#define OPE_PP_CROP_RND_CLAMP_HW_STATUS(base) OPE_PP_HW_STATUS(base) +#define OPE_PP_CROP_RND_CLAMP_HEIGHT_VIOL BIT(2) +#define OPE_PP_CROP_RND_CLAMP_WIDTH_VIOL BIT(1) +#define OPE_PP_CROP_RND_CLAMP_MODULE_CFG(base) ((base) + 0x60) +#define OPE_PP_CROP_RND_CLAMP_EN BIT(0) +#define OPE_PP_CROP_RND_CLAMP_CROP_EN BIT(9) +#define OPE_PP_CROP_RND_CLAMP_CROP_LINE_CFG(base) ((base) + 0x68) +#define OPE_PP_CROP_RND_CLAMP_CROP_PIXEL_CFG(base) ((base) + 0x6c) +#define OPE_PP_CROP_RND_CLAMP_CROP_FIRST GENMASK(29, 16) +#define OPE_PP_CROP_RND_CLAMP_CROP_LAST GENMASK(13, 0) +#define OPE_PP_DOWNSCALE_MN_CFG(ds) ((ds) + 0x60) +#define OPE_PP_DOWNSCALE_MN_CFG_EN BIT(0) +#define OPE_PP_DOWNSCALE_MN_DS_CFG(ds) ((ds) + 0x64) +#define OPE_PP_DOWNSCALE_MN_DS_CFG_H_SCALE_EN BIT(9) +#define OPE_PP_DOWNSCALE_MN_DS_CFG_V_SCALE_EN BIT(10) +#define OPE_PP_DOWNSCALE_MN_DS_IMAGE_SIZE_CFG(ds) ((ds) + 0x68) +#define OPE_PP_DOWNSCALE_MN_DS_MN_H_CFG(ds) ((ds) + 0x6c) +#define OPE_PP_DOWNSCALE_MN_DS_MN_H_PHASE_CFG(ds) ((ds) + 0x70) +#define OPE_PP_DOWNSCALE_MN_DS_MN_V_CFG(ds) ((ds) + 0x74) +#define OPE_PP_DOWNSCALE_MN_DS_MN_V_PHASE_CFG(ds) ((ds) + 0x78) + +#define OPE_PP_CHROMA_ENHAN_BASE 0x1200 +#define OPE_PP_CHROMA_ENHAN_MODULE_CFG (OPE_PP_CHROMA_ENHAN_BASE + 0x60) +#define OPE_PP_CHROMA_ENHAN_MODULE_CFG_EN BIT(0) +#define OPE_PP_CHROMA_ENHAN_LUMA_CFG_0 (OPE_PP_CHROMA_ENHAN_BASE + 0x68) +#define OPE_PP_CHROMA_ENHAN_LUMA_CFG_0_V0 GENMASK(11, 0) +#define OPE_PP_CHROMA_ENHAN_LUMA_CFG_0_V1 GENMASK(27, 16) +#define OPE_PP_CHROMA_ENHAN_LUMA_CFG_1 (OPE_PP_CHROMA_ENHAN_BASE + 0x6c) +#define OPE_PP_CHROMA_ENHAN_LUMA_CFG_1_K GENMASK(31, 23) +#define OPE_PP_CHROMA_ENHAN_LUMA_CFG_2 (OPE_PP_CHROMA_ENHAN_BASE + 0x70) +#define OPE_PP_CHROMA_ENHAN_LUMA_CFG_2_V2 GENMASK(11, 0) +#define OPE_PP_CHROMA_ENHAN_COEFF_A_CFG (OPE_PP_CHROMA_ENHAN_BASE + 0x74) +#define OPE_PP_CHROMA_ENHAN_COEFF_A_CFG_AP GENMASK(11, 0) +#define OPE_PP_CHROMA_ENHAN_COEFF_A_CFG_AM GENMASK(27, 16) +#define OPE_PP_CHROMA_ENHAN_COEFF_B_CFG (OPE_PP_CHROMA_ENHAN_BASE + 0x78) +#define OPE_PP_CHROMA_ENHAN_COEFF_B_CFG_BP GENMASK(11, 0) +#define OPE_PP_CHROMA_ENHAN_COEFF_B_CFG_BM GENMASK(27, 16) +#define OPE_PP_CHROMA_ENHAN_COEFF_C_CFG (OPE_PP_CHROMA_ENHAN_BASE + 0x7C) +#define OPE_PP_CHROMA_ENHAN_COEFF_C_CFG_CP GENMASK(11, 0) +#define OPE_PP_CHROMA_ENHAN_COEFF_C_CFG_CM GENMASK(27, 16) +#define OPE_PP_CHROMA_ENHAN_COEFF_D_CFG (OPE_PP_CHROMA_ENHAN_BASE + 0x80) +#define OPE_PP_CHROMA_ENHAN_COEFF_D_CFG_DP GENMASK(11, 0) +#define OPE_PP_CHROMA_ENHAN_COEFF_D_CFG_DM GENMASK(27, 16) +#define OPE_PP_CHROMA_ENHAN_CHROMA_CFG_0 (OPE_PP_CHROMA_ENHAN_BASE + 0x84) +#define OPE_PP_CHROMA_ENHAN_CHROMA_CFG_0_KCB GENMASK(31, 21) +#define OPE_PP_CHROMA_ENHAN_CHROMA_CFG_1 (OPE_PP_CHROMA_ENHAN_BASE + 0x88) +#define OPE_PP_CHROMA_ENHAN_CHROMA_CFG_1_KCR GENMASK(31, 21) + +/* -------- OPE-specific constants -------- */ + +#define OPE_STRIPE_MAX_W 336 +#define OPE_STRIPE_MAX_H 8192 +#define OPE_STRIPE_MIN_W 16 +#define OPE_STRIPE_MIN_H OPE_STRIPE_MIN_W +#define OPE_MAX_STRIPE 16 +#define OPE_ALIGN_H 1 +#define OPE_ALIGN_W 1 +#define OPE_MIN_W 24 +#define OPE_MIN_H 16 +#define OPE_MAX_W (OPE_STRIPE_MAX_W * OPE_MAX_STRIPE) +#define OPE_MAX_H OPE_STRIPE_MAX_H +#define OPE_MAX_STRIDE 0xffff +#define OPE_RESET_TIMEOUT_MS 100 +#define OPE_RESET_POLL_US 50 +#define DEFAULT_FRAMERATE 60 +#define OPE_MAX_FRAMERATE 1000 + +/* + * AXI clock is shared across CAMSS blocks and not dynamically scaled, + * just request the highest supported rate. + */ +#define OPE_AXI_CLK_RATE (300 * HZ_PER_MHZ) + +/* Downscaler fixed-point helpers */ +#define Q21(v) (((uint64_t)(v)) << 21) +#define DS_Q21(n, d) ((uint32_t)(((uint64_t)(n) << 21) / (d))) +#define DS_RESOLUTION(in, out) \ + (((out) * 128 <= (in)) ? 0x0 : \ + ((out) * 16 <= (in)) ? 0x1 : \ + ((out) * 8 <= (in)) ? 0x2 : 0x3) +#define DS_OUTPUT_PIX(in, phase_init, phase_step) \ + ((Q21(in) - (phase_init)) / (phase_step)) +#define OPE_WB(n, d) (((n) << 10) / (d)) + +enum ope_downscaler { + OPE_DS_C_PRE, + OPE_DS_C_DISP, + OPE_DS_Y_DISP, + OPE_DS_MAX, +}; + +enum ope_glut_sel { + OPE_GLUT_SEL_NONE, + OPE_GLUT_SEL_G, + OPE_GLUT_SEL_B, + OPE_GLUT_SEL_R, +}; + +static const u32 ope_ds_base[OPE_DS_MAX] = { + OPE_PP_DOWNSCALE_MN_DS_C_PRE_BASE, + OPE_PP_DOWNSCALE_MN_DS_C_DISP_BASE, + OPE_PP_DOWNSCALE_MN_DS_Y_DISP_BASE, +}; + +enum ope_wr_client { + OPE_WR_CLIENT_VID_Y, + OPE_WR_CLIENT_VID_C, + OPE_WR_CLIENT_DISP_Y, + OPE_WR_CLIENT_DISP_C, + OPE_WR_CLIENT_MAX, +}; + +enum ope_pixel_pattern { + OPE_PIXEL_PATTERN_RGRGRG, + OPE_PIXEL_PATTERN_GRGRGR, + OPE_PIXEL_PATTERN_BGBGBG, + OPE_PIXEL_PATTERN_GBGBGB, + OPE_PIXEL_PATTERN_YCBYCR, + OPE_PIXEL_PATTERN_YCRYCB, + OPE_PIXEL_PATTERN_CBYCRY, + OPE_PIXEL_PATTERN_CRYCBY, +}; + +enum ope_stripe_location { + OPE_STRIPE_LOCATION_FULL, + OPE_STRIPE_LOCATION_LEFT, + OPE_STRIPE_LOCATION_RIGHT, + OPE_STRIPE_LOCATION_MIDDLE, +}; + +enum ope_unpacker_format { + OPE_UNPACKER_FMT_PLAIN_8 = 1, + OPE_UNPACKER_FMT_PLAIN_16_10BPP = 2, + OPE_UNPACKER_FMT_MIPI_10 = 13, +}; + +enum ope_packer_format { + OPE_PACKER_FMT_PLAIN_8 = 1, + OPE_PACKER_FMT_PLAIN_8_ODD_EVEN = 2, + OPE_PACKER_FMT_MIPI_10 = 12, +}; + +struct ope_hw_fmt { + u32 fourcc; + enum ope_pixel_pattern pattern; + enum ope_unpacker_format unpacker; + enum ope_packer_format packer; +}; + +static const struct ope_hw_fmt ope_hw_fmts[] = { + { V4L2_PIX_FMT_SBGGR10P, OPE_PIXEL_PATTERN_BGBGBG, + OPE_UNPACKER_FMT_MIPI_10, OPE_PACKER_FMT_MIPI_10 }, + { V4L2_PIX_FMT_SGBRG10P, OPE_PIXEL_PATTERN_GBGBGB, + OPE_UNPACKER_FMT_MIPI_10, OPE_PACKER_FMT_MIPI_10 }, + { V4L2_PIX_FMT_SGRBG10P, OPE_PIXEL_PATTERN_GRGRGR, + OPE_UNPACKER_FMT_MIPI_10, OPE_PACKER_FMT_MIPI_10 }, + { V4L2_PIX_FMT_SRGGB10P, OPE_PIXEL_PATTERN_RGRGRG, + OPE_UNPACKER_FMT_MIPI_10, OPE_PACKER_FMT_MIPI_10 }, + { V4L2_PIX_FMT_SRGGB8, OPE_PIXEL_PATTERN_RGRGRG, + OPE_UNPACKER_FMT_PLAIN_8, OPE_PACKER_FMT_PLAIN_8 }, + { V4L2_PIX_FMT_SBGGR8, OPE_PIXEL_PATTERN_BGBGBG, + OPE_UNPACKER_FMT_PLAIN_8, OPE_PACKER_FMT_PLAIN_8 }, + { V4L2_PIX_FMT_SGBRG8, OPE_PIXEL_PATTERN_GBGBGB, + OPE_UNPACKER_FMT_PLAIN_8, OPE_PACKER_FMT_PLAIN_8 }, + { V4L2_PIX_FMT_SGRBG8, OPE_PIXEL_PATTERN_GRGRGR, + OPE_UNPACKER_FMT_PLAIN_8, OPE_PACKER_FMT_PLAIN_8 }, + { V4L2_PIX_FMT_NV24, OPE_PIXEL_PATTERN_YCBYCR, + OPE_UNPACKER_FMT_PLAIN_8, OPE_PACKER_FMT_PLAIN_8 }, + { V4L2_PIX_FMT_NV42, OPE_PIXEL_PATTERN_YCRYCB, + OPE_UNPACKER_FMT_PLAIN_8, OPE_PACKER_FMT_PLAIN_8_ODD_EVEN }, + { V4L2_PIX_FMT_NV16, OPE_PIXEL_PATTERN_CBYCRY, + OPE_UNPACKER_FMT_PLAIN_8, OPE_PACKER_FMT_PLAIN_8 }, + { V4L2_PIX_FMT_NV61, OPE_PIXEL_PATTERN_CBYCRY, + OPE_UNPACKER_FMT_PLAIN_8, OPE_PACKER_FMT_PLAIN_8_ODD_EVEN }, + { V4L2_PIX_FMT_NV12, OPE_PIXEL_PATTERN_CBYCRY, + OPE_UNPACKER_FMT_PLAIN_8, OPE_PACKER_FMT_PLAIN_8 }, + { V4L2_PIX_FMT_NV21, OPE_PIXEL_PATTERN_CBYCRY, + OPE_UNPACKER_FMT_PLAIN_8, OPE_PACKER_FMT_PLAIN_8_ODD_EVEN }, + { V4L2_PIX_FMT_GREY, OPE_PIXEL_PATTERN_RGRGRG, + OPE_UNPACKER_FMT_PLAIN_8, OPE_PACKER_FMT_PLAIN_8 }, +}; + +static const struct ope_hw_fmt *ope_find_hw_fmt(u32 fourcc) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(ope_hw_fmts); i++) + if (ope_hw_fmts[i].fourcc == fourcc) + return &ope_hw_fmts[i]; + + return NULL; +} + +static const struct ope_fmt ope_input_fmts[] = { + { V4L2_PIX_FMT_SBGGR10P, 10, 2, 1, MEDIA_BUS_FMT_SBGGR10_1X10 }, + { V4L2_PIX_FMT_SGBRG10P, 10, 2, 1, MEDIA_BUS_FMT_SGBRG10_1X10 }, + { V4L2_PIX_FMT_SGRBG10P, 10, 2, 1, MEDIA_BUS_FMT_SGRBG10_1X10 }, + { V4L2_PIX_FMT_SRGGB10P, 10, 2, 1, MEDIA_BUS_FMT_SRGGB10_1X10 }, + { V4L2_PIX_FMT_SRGGB8, 8, 0, 1, MEDIA_BUS_FMT_SRGGB8_1X8 }, + { V4L2_PIX_FMT_SBGGR8, 8, 0, 1, MEDIA_BUS_FMT_SBGGR8_1X8 }, + { V4L2_PIX_FMT_SGBRG8, 8, 0, 1, MEDIA_BUS_FMT_SGBRG8_1X8 }, + { V4L2_PIX_FMT_SGRBG8, 8, 0, 1, MEDIA_BUS_FMT_SGRBG8_1X8 }, +}; + +static const struct ope_fmt ope_output_fmts[] = { + { V4L2_PIX_FMT_NV24, 24, 0, 1, MEDIA_BUS_FMT_YUV8_1X24, 1, 1 }, + { V4L2_PIX_FMT_NV42, 24, 0, 1, MEDIA_BUS_FMT_YUV8_1X24, 1, 1 }, + { V4L2_PIX_FMT_NV16, 16, 1, 1, MEDIA_BUS_FMT_YUYV8_2X8, 2, 1 }, + { V4L2_PIX_FMT_NV61, 16, 1, 1, MEDIA_BUS_FMT_YUYV8_2X8, 2, 1 }, + { V4L2_PIX_FMT_NV12, 12, 1, 1, MEDIA_BUS_FMT_YUYV8_1_5X8, 2, 2 }, + { V4L2_PIX_FMT_NV21, 12, 1, 1, MEDIA_BUS_FMT_YUYV8_1_5X8, 2, 2 }, + { V4L2_PIX_FMT_GREY, 8, 0, 1, MEDIA_BUS_FMT_Y8_1X8, 1, 1 }, +}; + +struct ope_dsc_config { + u32 input_width; + u32 input_height; + u32 output_width; + u32 output_height; + u32 phase_step_h; + u32 phase_step_v; + u32 crop_last_pixel; + u32 crop_last_line; +}; + +struct ope_stripe { + struct { + dma_addr_t addr; + u32 width; + u32 height; + u32 stride; + enum ope_stripe_location location; + enum ope_pixel_pattern pattern; + enum ope_unpacker_format format; + } src; + struct { + dma_addr_t addr; + u32 width; + u32 height; + u32 stride; + u32 x_init; + enum ope_packer_format format; + bool enabled; + } dst[OPE_WR_CLIENT_MAX]; + struct ope_dsc_config dsc[OPE_DS_MAX]; +}; + +/* OPE tuning parameter state */ + +/* Demosaic (CLC_DEMO) coefficients, internal only, not user-configurable. */ +#define CAMSS_PARAMS_INTERNAL (-1) + +struct ope_params_demo { + struct v4l2_isp_params_block_header header; + u8 lambda_rb; + u8 lambda_g; + u16 a_k; + u16 w_k; + u16 _pad; +}; + +/* OPE tuning parameter state */ +struct ope_config { + struct camss_params_wb_gain wb_gain; + struct camss_params_chroma_enhan chroma_enhan; + struct camss_params_color_correct color_correct; + struct camss_params_gamma gamma; + struct ope_params_demo demo; +}; + +enum ope_entity { + OPE_ENTITY_FRAME_IN, + OPE_ENTITY_PARAMS, + OPE_ENTITY_PROC, + OPE_ENTITY_DISP, + OPE_ENTITY_DISP_OUT, + OPE_ENTITY_COUNT +}; + +enum ope_queue_idx { + OPE_QUEUE_FRAME_IN, + OPE_QUEUE_DISP_OUT, + OPE_QUEUE_PARAMS, + OPE_QUEUE_COUNT +}; + +struct camss_isp_buf { + struct vb2_v4l2_buffer vb; /* must be first */ + struct list_head list; +}; + +struct ope_queue { + struct vb2_queue vq; + struct list_head rdy_queue; + spinlock_t rdy_spinlock; +}; + +enum ope_proc_pad { + OPE_PROC_PAD_SINK_IN, + OPE_PROC_PAD_SINK_PAR, + OPE_PROC_PAD_SOURCE, + OPE_PROC_PADS_NUM, +}; + +enum ope_disp_pad { + OPE_DISP_PAD_SINK, + OPE_DISP_PAD_SOURCE, + OPE_DISP_PADS_NUM, +}; + +/* per-context state */ +struct ope_ctx { + bool queued; + struct ope_dev *ope; + struct mutex vbq_lock; + struct ope_queue queues[OPE_QUEUE_COUNT]; + + unsigned int framerate; + struct ope_fmt_state fmt_in; + struct ope_fmt_state fmt_out; + + struct list_head list; + bool started; + + struct ope_config config; + u8 current_stripe; + struct ope_stripe stripe[OPE_MAX_STRIPE]; + + struct v4l2_isp_params_buffer *params_buf; +}; + +/* Per OPE device state */ +struct ope_dev { + struct device *dev; + struct v4l2_device v4l2_dev; + struct media_device mdev; + struct camss_isp_pipeline *pipeline; + struct mutex mutex; + struct work_struct run_work; + + /* Scheduler state, all owned by sched_lock */ + spinlock_t sched_lock; + struct ope_ctx *curr_ctx; + struct ope_ctx *hw_ctx; + bool hw_running; + + int irq; + u32 hw_version; + + struct icc_path *icc_data; + struct icc_path *icc_config; + + void __iomem *base; + void __iomem *base_rd; + void __iomem *base_wr; + void __iomem *base_pp; + + struct completion reset_complete; + + struct list_head ctx_list; + spinlock_t ctx_lock; + + struct ope_ctx *shared_ctx; + unsigned int open_count; + + /* Gamma LUTs handling */ + struct { + struct ope_ctx *owner; + bool valid; + } glut_bank[2]; + u8 glut_cur_bank; + u8 glut_mru_bank; +}; + +/* -------- Register accessors -------- */ + +static inline u32 ope_read(struct ope_dev *ope, u32 reg) +{ + return readl(ope->base + reg); +} + +static inline void ope_write(struct ope_dev *ope, u32 reg, u32 val) +{ + writel(val, ope->base + reg); +} + +static inline void ope_write_wr(struct ope_dev *ope, u32 reg, u32 val) +{ + writel_relaxed(val, ope->base_wr + reg); +} + +static inline u32 ope_read_wr(struct ope_dev *ope, u32 reg) +{ + return readl_relaxed(ope->base_wr + reg); +} + +static inline void ope_write_rd(struct ope_dev *ope, u32 reg, u32 val) +{ + writel_relaxed(val, ope->base_rd + reg); +} + +static inline void ope_write_pp(struct ope_dev *ope, u32 reg, u32 val) +{ + writel_relaxed(val, ope->base_pp + reg); +} + +static inline u32 ope_read_pp(struct ope_dev *ope, u32 reg) +{ + return readl_relaxed(ope->base_pp + reg); +} + +static inline void ope_start(struct ope_dev *ope) +{ + wmb(); /* ensure all register writes are visible before GO_CMD */ + ope_write_rd(ope, OPE_BUS_RD_INPUT_IF_CMD, OPE_BUS_RD_INPUT_IF_CMD_GO_CMD); +} + +static inline bool ope_hw_available(struct ope_dev *ope) +{ + /* v4l2_device_unregister() clear the dev pointer */ + return !!ope->v4l2_dev.dev; +} + +/* -------- Stripe helpers -------- */ + +static inline enum ope_stripe_location ope_stripe_location(unsigned int idx, unsigned int count) +{ + if (count == 1) + return OPE_STRIPE_LOCATION_FULL; + if (idx == 0) + return OPE_STRIPE_LOCATION_LEFT; + if (idx == count - 1) + return OPE_STRIPE_LOCATION_RIGHT; + + return OPE_STRIPE_LOCATION_MIDDLE; +} + +static inline bool ope_stripe_is_last(const struct ope_stripe *s) +{ + return s && (s->src.location == OPE_STRIPE_LOCATION_RIGHT || + s->src.location == OPE_STRIPE_LOCATION_FULL); +} + +static inline struct ope_stripe *ope_current_stripe(struct ope_ctx *ctx) +{ + if (ctx->current_stripe >= OPE_MAX_STRIPE) + return NULL; + + return &ctx->stripe[ctx->current_stripe]; +} + +static inline unsigned int ope_stripe_index(struct ope_ctx *ctx, const struct ope_stripe *stripe) +{ + return stripe - &ctx->stripe[0]; +} + +static inline struct ope_stripe *ope_prev_stripe(struct ope_ctx *ctx, struct ope_stripe *stripe) +{ + unsigned int idx = ope_stripe_index(ctx, stripe); + + return idx ? &ctx->stripe[idx - 1] : NULL; +} + +static unsigned int ope_split_stripes(unsigned int src_width, unsigned int align, + unsigned int *widths, u32 *height) +{ + unsigned int nstripes, i; + u32 w; + + if (src_width > OPE_MAX_W) + return 0; + + nstripes = DIV_ROUND_UP(src_width, OPE_STRIPE_MAX_W); + w = ALIGN(DIV_ROUND_UP(src_width, nstripes), max(2u, 1u << align)); + + v4l_bound_align_image(&w, OPE_STRIPE_MIN_W, OPE_STRIPE_MAX_W, align, + height, OPE_STRIPE_MIN_H, OPE_STRIPE_MAX_H, + OPE_ALIGN_H, 0); + + for (i = 0; i + 1 < nstripes; i++) + widths[i] = w; + + /* The trailing stripe takes what is left */ + widths[nstripes - 1] = src_width - i * w; + + return nstripes; +} + +static unsigned int ope_calc_h_scale(unsigned int src, unsigned int dst, + const unsigned int *widths, unsigned int nstripes, + unsigned int c_hsub, unsigned int sw_align) +{ + unsigned int last_sw = widths[nstripes - 1]; + unsigned int denom; + + if (src == dst) + return DS_Q21(src, src); + + /* Find the smallest h_scale denominator >= dst such that the + * last-stripe adjustment can satisfy both Y and C pixel counts. + */ + for (denom = dst; denom <= dst + 16 * nstripes; denom++) { + unsigned int hs = DS_Q21(src, denom); + unsigned int tw = 0, tc = 0; + unsigned int ry, rc, s_y, s_c, s, i; + + for (i = 0; i < nstripes - 1; i++) { + tw += DS_OUTPUT_PIX(widths[i], 0, hs); + tc += DS_OUTPUT_PIX(widths[i] / c_hsub, 0, hs); + } + + if (tw > dst || tc > dst / c_hsub) + continue; + + ry = dst - tw; + rc = dst / c_hsub - tc; + s_y = DIV_ROUND_UP((u64)ry * hs, Q21(1)); + s_c = DIV_ROUND_UP((u64)rc * hs, Q21(1)) * c_hsub; + s = ALIGN(max(s_y, s_c), sw_align); + + s = clamp(s, OPE_STRIPE_MIN_W, last_sw); + tw += DS_OUTPUT_PIX(s, 0, hs); + tc += DS_OUTPUT_PIX(s / c_hsub, 0, hs); + + if (tw == dst && tc * c_hsub == dst) + return hs; + } + + return DS_Q21(src, dst); +} + +static unsigned int ope_calc_v_scale(unsigned int src, unsigned int dst) +{ + return DS_Q21(src, dst); +} + +static void ope_gen_stripe_chroma_dsc(struct ope_ctx *ctx, + struct ope_stripe *stripe) +{ + struct ope_dsc_config *dsc = &stripe->dsc[OPE_DS_C_PRE]; + const struct ope_fmt *fmt = ctx->fmt_out.fmt; + + dsc->input_width = stripe->src.width; + dsc->input_height = stripe->src.height; + + dsc->output_width = dsc->input_width / fmt->c_hsub; + dsc->output_height = dsc->input_height / fmt->c_vsub; + + dsc->phase_step_h = DS_Q21(dsc->input_width, dsc->output_width); + dsc->phase_step_v = DS_Q21(dsc->input_height, dsc->output_height); +} + +static void ope_gen_stripe_dsc(struct ope_ctx *ctx, struct ope_stripe *stripe, + unsigned int h_scale, unsigned int v_scale) +{ + struct ope_dsc_config *dsc_c = &stripe->dsc[OPE_DS_C_DISP]; + struct ope_dsc_config *dsc_y = &stripe->dsc[OPE_DS_Y_DISP]; + unsigned int sw = stripe->src.width; + unsigned int sw_c = stripe->dsc[OPE_DS_C_PRE].output_width; + + dsc_c->phase_step_h = dsc_y->phase_step_h = h_scale; + dsc_c->phase_step_v = dsc_y->phase_step_v = v_scale; + + dsc_c->input_width = stripe->dsc[OPE_DS_C_PRE].output_width; + dsc_c->input_height = stripe->dsc[OPE_DS_C_PRE].output_height; + dsc_y->input_width = stripe->src.width; + dsc_y->input_height = stripe->src.height; + + /* Clip the output so the WE always receives the expected count */ + dsc_y->output_width = DS_OUTPUT_PIX(sw, 0, h_scale); + dsc_y->output_height = DS_OUTPUT_PIX(stripe->src.height, 0, v_scale); + dsc_c->output_width = DS_OUTPUT_PIX(sw_c, 0, h_scale); + dsc_c->output_height = DS_OUTPUT_PIX(stripe->dsc[OPE_DS_C_PRE].output_height, 0, v_scale); + + dsc_y->output_width = max_t(unsigned int, dsc_y->output_width, 1); + dsc_y->output_height = max_t(unsigned int, dsc_y->output_height, 1); + dsc_c->output_width = max_t(unsigned int, dsc_c->output_width, 1); + dsc_c->output_height = max_t(unsigned int, dsc_c->output_height, 1); + + dsc_y->crop_last_pixel = dsc_y->output_width - 1; + dsc_y->crop_last_line = dsc_y->output_height - 1; + dsc_c->crop_last_pixel = dsc_c->output_width - 1; + dsc_c->crop_last_line = dsc_c->output_height - 1; +} + +static void ope_gen_stripe_yuv_dst(struct ope_ctx *ctx, struct ope_stripe *stripe, + dma_addr_t dst, const struct v4l2_rect *compose) +{ + const struct ope_fmt_state *fo = &ctx->fmt_out; + const struct ope_hw_fmt *hw = ope_find_hw_fmt(fo->fmt->fourcc); + struct ope_stripe *prev = ope_prev_stripe(ctx, stripe); + unsigned int bpl = fo->bytesperline; + unsigned int img_h = fo->height; + unsigned int c_stride; + unsigned int x_init; + dma_addr_t base; + + stripe->dst[OPE_WR_CLIENT_DISP_Y].enabled = true; + stripe->dst[OPE_WR_CLIENT_DISP_C].enabled = true; + + /* Y plane */ + base = dst + compose->top * bpl; + + if (prev) + x_init = prev->dst[OPE_WR_CLIENT_DISP_Y].x_init + + prev->dst[OPE_WR_CLIENT_DISP_Y].width; + else + x_init = compose->left; + + stripe->dst[OPE_WR_CLIENT_DISP_Y].addr = base; + stripe->dst[OPE_WR_CLIENT_DISP_Y].x_init = x_init; + stripe->dst[OPE_WR_CLIENT_DISP_Y].width = stripe->dsc[OPE_DS_Y_DISP].output_width; + stripe->dst[OPE_WR_CLIENT_DISP_Y].height = stripe->dsc[OPE_DS_Y_DISP].output_height; + stripe->dst[OPE_WR_CLIENT_DISP_Y].stride = bpl; + stripe->dst[OPE_WR_CLIENT_DISP_Y].format = OPE_PACKER_FMT_PLAIN_8; + + /* UV plane (appended to Y plane)*/ + c_stride = bpl * 2 / fo->fmt->c_hsub; + base = dst + bpl * img_h + (compose->top / fo->fmt->c_vsub) * c_stride; + + if (prev) + x_init = prev->dst[OPE_WR_CLIENT_DISP_C].x_init + + prev->dst[OPE_WR_CLIENT_DISP_C].width; + else + x_init = compose->left * 2 / fo->fmt->c_hsub; + + stripe->dst[OPE_WR_CLIENT_DISP_C].addr = base; + stripe->dst[OPE_WR_CLIENT_DISP_C].x_init = x_init; + stripe->dst[OPE_WR_CLIENT_DISP_C].format = hw ? hw->packer : OPE_PACKER_FMT_PLAIN_8; + stripe->dst[OPE_WR_CLIENT_DISP_C].width = stripe->dsc[OPE_DS_C_DISP].output_width * 2; + stripe->dst[OPE_WR_CLIENT_DISP_C].height = stripe->dsc[OPE_DS_C_DISP].output_height; + + switch (fo->fmt->fourcc) { + case V4L2_PIX_FMT_GREY: + stripe->dst[OPE_WR_CLIENT_DISP_C].enabled = false; + break; + default: + stripe->dst[OPE_WR_CLIENT_DISP_C].stride = c_stride; + break; + } +} + +static int ope_gen_stripes(struct ope_ctx *ctx, dma_addr_t src, dma_addr_t dst) +{ + const struct ope_fmt_state *fi = &ctx->fmt_in; + const struct ope_hw_fmt *src_hw = ope_find_hw_fmt(fi->fmt->fourcc); + unsigned int h_scale, v_scale, num_stripes, x_out, x_out_c; + const struct ope_fmt_state *fo = &ctx->fmt_out; + const struct v4l2_rect *compose, *crop; + unsigned int c_hsub = fo->fmt->c_hsub; + unsigned int widths[OPE_MAX_STRIPE]; + struct v4l2_subdev_state *sd_state; + struct v4l2_subdev *proc_sd; + int ret = 0; + u32 height; + + proc_sd = camss_isp_pipeline_get_subdev(ctx->ope->pipeline, OPE_ENTITY_PROC); + sd_state = v4l2_subdev_lock_and_get_active_state(proc_sd); + crop = v4l2_subdev_state_get_crop(sd_state, OPE_PROC_PAD_SINK_IN); + compose = v4l2_subdev_state_get_compose(sd_state, OPE_PROC_PAD_SOURCE); + + if (compose->left + compose->width > fo->width || + compose->top + compose->height > fo->height) { + ret = -ERANGE; + goto out; + } + + /* Advance source pointer to the crop origin */ + src += crop->top * fi->bytesperline + crop->left * fi->fmt->depth / 8; + + height = crop->height; + num_stripes = ope_split_stripes(crop->width, fi->fmt->align, widths, &height); + if (!num_stripes) { + ret = -ERANGE; + goto out; + } + + h_scale = ope_calc_h_scale(crop->width, compose->width, widths, num_stripes, c_hsub, + max(2u, 1u << fi->fmt->align)); + v_scale = ope_calc_v_scale(crop->height, compose->height); + + x_out = x_out_c = 0; + + for (unsigned int i = 0; i < num_stripes; i++) { + struct ope_stripe *stripe = &ctx->stripe[i]; + + memset(stripe, 0, sizeof(*stripe)); + + stripe->src.addr = src; + stripe->src.width = widths[i]; + stripe->src.height = height; + stripe->src.stride = fi->bytesperline; + stripe->src.location = ope_stripe_location(i, num_stripes); + stripe->src.pattern = src_hw ? src_hw->pattern : 0; + stripe->src.format = src_hw ? src_hw->unpacker : 0; + + src += stripe->src.width * fi->fmt->depth / 8; + + /* Last-stripe adjustment: compute the minimum input width that + * delivers exactly the remaining output pixels for Y and C. + */ + if (ope_stripe_is_last(stripe)) { + unsigned int rem_y = compose->width - x_out; + unsigned int rem_c = compose->width / c_hsub - x_out_c; + unsigned int s_y = DIV_ROUND_UP((u64)rem_y * h_scale, Q21(1)); + unsigned int s_c = DIV_ROUND_UP((u64)rem_c * h_scale, Q21(1)) * c_hsub; + unsigned int s = ALIGN(max(s_y, s_c), max(2u, 1u << fi->fmt->align)); + + stripe->src.width = clamp(s, OPE_STRIPE_MIN_W, stripe->src.width); + } + + ope_gen_stripe_chroma_dsc(ctx, stripe); + ope_gen_stripe_dsc(ctx, stripe, h_scale, v_scale); + ope_gen_stripe_yuv_dst(ctx, stripe, dst, compose); + + x_out += stripe->dsc[OPE_DS_Y_DISP].output_width; + x_out_c += stripe->dsc[OPE_DS_C_DISP].output_width; + + /* Width in bytes for the fetch engine */ + stripe->src.width = stripe->src.width * fi->fmt->depth / 8; + } + + if (x_out != compose->width || x_out_c != compose->width / c_hsub) + ret = -ERANGE; + +out: + v4l2_subdev_unlock_state(sd_state); + + return ret; +} + +/* -------- Pipeline IQ module programming -------- */ + +static bool ope_module_update(struct ope_ctx *ctx, u32 module_cfg_reg, u32 enable_mask, + struct v4l2_isp_params_block_header *hdr, bool force) +{ + bool enable = !(hdr->flags & V4L2_ISP_PARAMS_FL_BLOCK_DISABLE); + bool dirty = hdr->flags & CAMSS_ISP_PARAMS_FL_BLOCK_DIRTY; + + /* skip if neither forced (new context) nor dirty (updated params) */ + if (!force && !dirty) + return false; + + hdr->flags &= ~CAMSS_ISP_PARAMS_FL_BLOCK_DIRTY; + + ope_write_pp(ctx->ope, module_cfg_reg, enable ? enable_mask : 0); + + /* If module is disabled, not need to update content */ + if (!enable) + return false; + + dev_dbg(ctx->ope->dev, "IQ module (%u) update (flags:0x%x)\n", hdr->type, hdr->flags); + + return true; +} + +static void ope_prog_wb(struct ope_ctx *ctx, bool force) +{ + struct camss_params_wb_gain *wb = &ctx->config.wb_gain; + struct ope_dev *ope = ctx->ope; + + if (!ope_module_update(ctx, OPE_PP_WB_GAIN_MODULE_CFG, + OPE_PP_WB_GAIN_MODULE_CFG_EN, + &wb->header, force)) + return; + + ope_write_pp(ope, OPE_PP_WB_GAIN_WB_CFG(0), + FIELD_PREP(OPE_PP_WB_GAIN_WB_CFG_GAIN, wb->g_gain)); + ope_write_pp(ope, OPE_PP_WB_GAIN_WB_CFG(1), + FIELD_PREP(OPE_PP_WB_GAIN_WB_CFG_GAIN, wb->b_gain)); + ope_write_pp(ope, OPE_PP_WB_GAIN_WB_CFG(2), + FIELD_PREP(OPE_PP_WB_GAIN_WB_CFG_GAIN, wb->r_gain)); + ope_write_pp(ope, OPE_PP_WB_GAIN_WB_SUB_CFG(0), + FIELD_PREP(OPE_PP_WB_GAIN_WB_SUB_CFG_VAL, wb->g_sub)); + ope_write_pp(ope, OPE_PP_WB_GAIN_WB_SUB_CFG(1), + FIELD_PREP(OPE_PP_WB_GAIN_WB_SUB_CFG_VAL, wb->b_sub)); + ope_write_pp(ope, OPE_PP_WB_GAIN_WB_SUB_CFG(2), + FIELD_PREP(OPE_PP_WB_GAIN_WB_SUB_CFG_VAL, wb->r_sub)); + ope_write_pp(ope, OPE_PP_WB_GAIN_WB_ADD_CFG(0), + FIELD_PREP(OPE_PP_WB_GAIN_WB_ADD_CFG_VAL, wb->g_add)); + ope_write_pp(ope, OPE_PP_WB_GAIN_WB_ADD_CFG(1), + FIELD_PREP(OPE_PP_WB_GAIN_WB_ADD_CFG_VAL, wb->b_add)); + ope_write_pp(ope, OPE_PP_WB_GAIN_WB_ADD_CFG(2), + FIELD_PREP(OPE_PP_WB_GAIN_WB_ADD_CFG_VAL, wb->r_add)); +} + +static void ope_prog_bayer2rgb(struct ope_ctx *ctx, bool force) +{ + struct ope_params_demo *demo = &ctx->config.demo; + struct ope_dev *ope = ctx->ope; + + if (!ope_module_update(ctx, OPE_PP_DEMO_MODULE_CFG, + OPE_PP_DEMO_MODULE_CFG_EN | + OPE_PP_DEMO_MODULE_CFG_DYN_G_CLAMP_EN | + OPE_PP_DEMO_MODULE_CFG_DYN_RB_CLAMP_EN, + &demo->header, force)) + return; + + ope_write_pp(ope, OPE_PP_DEMO_INTERP_COEFF_CFG, + FIELD_PREP(OPE_PP_DEMO_INTERP_COEFF_CFG_LAMBDA_G, demo->lambda_g) | + FIELD_PREP(OPE_PP_DEMO_INTERP_COEFF_CFG_LAMBDA_RB, demo->lambda_rb)); + ope_write_pp(ope, OPE_PP_DEMO_INTERP_CLASSIFIER_CFG_0, + FIELD_PREP(OPE_PP_DEMO_INTERP_CLASSIFIER_CFG_0_AK, demo->a_k)); + ope_write_pp(ope, OPE_PP_DEMO_INTERP_CLASSIFIER_CFG_1, + FIELD_PREP(OPE_PP_DEMO_INTERP_CLASSIFIER_CFG_1_WK, demo->w_k)); +} + +static void ope_prog_rgb2yuv(struct ope_ctx *ctx, bool force) +{ + struct camss_params_chroma_enhan *cc = &ctx->config.chroma_enhan; + struct ope_dev *ope = ctx->ope; + + if (!ope_module_update(ctx, OPE_PP_CHROMA_ENHAN_MODULE_CFG, + OPE_PP_CHROMA_ENHAN_MODULE_CFG_EN, + &cc->header, force)) + return; + + ope_write_pp(ope, OPE_PP_CHROMA_ENHAN_LUMA_CFG_0, + FIELD_PREP(OPE_PP_CHROMA_ENHAN_LUMA_CFG_0_V0, cc->luma_v0) | + FIELD_PREP(OPE_PP_CHROMA_ENHAN_LUMA_CFG_0_V1, cc->luma_v1)); + ope_write_pp(ope, OPE_PP_CHROMA_ENHAN_LUMA_CFG_1, + FIELD_PREP(OPE_PP_CHROMA_ENHAN_LUMA_CFG_1_K, cc->luma_k)); + ope_write_pp(ope, OPE_PP_CHROMA_ENHAN_LUMA_CFG_2, + FIELD_PREP(OPE_PP_CHROMA_ENHAN_LUMA_CFG_2_V2, cc->luma_v2)); + ope_write_pp(ope, OPE_PP_CHROMA_ENHAN_COEFF_A_CFG, + FIELD_PREP(OPE_PP_CHROMA_ENHAN_COEFF_A_CFG_AP, cc->coeff_ap) | + FIELD_PREP(OPE_PP_CHROMA_ENHAN_COEFF_A_CFG_AM, cc->coeff_am)); + ope_write_pp(ope, OPE_PP_CHROMA_ENHAN_COEFF_B_CFG, + FIELD_PREP(OPE_PP_CHROMA_ENHAN_COEFF_B_CFG_BP, cc->coeff_bp) | + FIELD_PREP(OPE_PP_CHROMA_ENHAN_COEFF_B_CFG_BM, cc->coeff_bm)); + ope_write_pp(ope, OPE_PP_CHROMA_ENHAN_COEFF_C_CFG, + FIELD_PREP(OPE_PP_CHROMA_ENHAN_COEFF_C_CFG_CP, cc->coeff_cp) | + FIELD_PREP(OPE_PP_CHROMA_ENHAN_COEFF_C_CFG_CM, cc->coeff_cm)); + ope_write_pp(ope, OPE_PP_CHROMA_ENHAN_COEFF_D_CFG, + FIELD_PREP(OPE_PP_CHROMA_ENHAN_COEFF_D_CFG_DP, cc->coeff_dp) | + FIELD_PREP(OPE_PP_CHROMA_ENHAN_COEFF_D_CFG_DM, cc->coeff_dm)); + ope_write_pp(ope, OPE_PP_CHROMA_ENHAN_CHROMA_CFG_0, + FIELD_PREP(OPE_PP_CHROMA_ENHAN_CHROMA_CFG_0_KCB, cc->kcb)); + ope_write_pp(ope, OPE_PP_CHROMA_ENHAN_CHROMA_CFG_1, + FIELD_PREP(OPE_PP_CHROMA_ENHAN_CHROMA_CFG_1_KCR, cc->kcr)); +} + +static void ope_prog_color_correct(struct ope_ctx *ctx, bool force) +{ + struct camss_params_color_correct *cc = &ctx->config.color_correct; + struct ope_dev *ope = ctx->ope; + + if (!ope_module_update(ctx, OPE_PP_CC_MODULE_CFG, + OPE_PP_CC_MODULE_CFG_EN, + &cc->header, force)) + return; + + ope_write_pp(ope, OPE_PP_CC_COEFF_A_CFG_0, + FIELD_PREP(OPE_PP_CC_COEFF_A_CFG_0_A0, cc->a[0]) | + FIELD_PREP(OPE_PP_CC_COEFF_A_CFG_0_A1, cc->a[1])); + ope_write_pp(ope, OPE_PP_CC_COEFF_A_CFG_1, + FIELD_PREP(OPE_PP_CC_COEFF_A_CFG_1_A2, cc->a[2])); + ope_write_pp(ope, OPE_PP_CC_COEFF_B_CFG_0, + FIELD_PREP(OPE_PP_CC_COEFF_B_CFG_0_B0, cc->b[0]) | + FIELD_PREP(OPE_PP_CC_COEFF_B_CFG_0_B1, cc->b[1])); + ope_write_pp(ope, OPE_PP_CC_COEFF_B_CFG_1, + FIELD_PREP(OPE_PP_CC_COEFF_B_CFG_1_B2, cc->b[2])); + ope_write_pp(ope, OPE_PP_CC_COEFF_C_CFG_0, + FIELD_PREP(OPE_PP_CC_COEFF_C_CFG_0_C0, cc->c[0]) | + FIELD_PREP(OPE_PP_CC_COEFF_C_CFG_0_C1, cc->c[1])); + ope_write_pp(ope, OPE_PP_CC_COEFF_C_CFG_1, + FIELD_PREP(OPE_PP_CC_COEFF_C_CFG_1_C2, cc->c[2])); + ope_write_pp(ope, OPE_PP_CC_COEFF_K_CFG_0, + FIELD_PREP(OPE_PP_CC_COEFF_K_CFG_0_K0, cc->k[0])); + ope_write_pp(ope, OPE_PP_CC_COEFF_K_CFG_1, + FIELD_PREP(OPE_PP_CC_COEFF_K_CFG_1_K1, cc->k[1])); + ope_write_pp(ope, OPE_PP_CC_COEFF_K_CFG_2, + FIELD_PREP(OPE_PP_CC_COEFF_K_CFG_2_K2, cc->k[2])); + ope_write_pp(ope, OPE_PP_CC_COEFF_M_CFG, + FIELD_PREP(OPE_PP_CC_COEFF_M_CFG_M, cc->qfactor)); +} + +static void ope_glut_load_lut(struct ope_dev *ope, enum ope_glut_sel ch, + u8 bank, const u16 *lut) +{ + ope_write_pp(ope, OPE_PP_GLUT_DMI_LUT_BANK_CFG, + FIELD_PREP(OPE_PP_GLUT_DMI_LUT_BANK_CFG_SEL, bank)); + ope_write_pp(ope, OPE_PP_GLUT_DMI_LUT_CFG, + FIELD_PREP(OPE_PP_GLUT_DMI_LUT_CFG_SEL, ch)); + ope_write_pp(ope, OPE_PP_GLUT_DMI_CFG, + OPE_PP_GLUT_DMI_CFG_AUTO_LOAD_EN | + FIELD_PREP(OPE_PP_GLUT_DMI_CFG_ADDR, 0)); + for (unsigned int i = 0; i < CAMSS_GAMMA_LUT_SIZE; i++) + ope_write_pp(ope, OPE_PP_GLUT_DMI_DATA, lut[i]); +} + +static void ope_glut_upload(struct ope_ctx *ctx, u8 bank) +{ + struct camss_params_gamma *gamma = &ctx->config.gamma; + struct ope_dev *ope = ctx->ope; + + ope_glut_load_lut(ope, OPE_GLUT_SEL_R, bank, gamma->rlut); + ope_glut_load_lut(ope, OPE_GLUT_SEL_G, bank, gamma->glut); + ope_glut_load_lut(ope, OPE_GLUT_SEL_B, bank, gamma->blut); + + ope_write_pp(ope, OPE_PP_GLUT_DMI_LUT_CFG, + FIELD_PREP(OPE_PP_GLUT_DMI_LUT_CFG_SEL, + OPE_GLUT_SEL_NONE)); + + ope->glut_bank[bank].owner = ctx; + ope->glut_bank[bank].valid = true; +} + +static bool ope_glut_bank_resident(struct ope_dev *ope, u8 bank, + struct ope_ctx *ctx) +{ + return ope->glut_bank[bank].valid && + ope->glut_bank[bank].owner == ctx; +} + +static void ope_prog_gamma(struct ope_ctx *ctx, bool force) +{ + struct camss_params_gamma *gamma = &ctx->config.gamma; + bool enable = !(gamma->header.flags & V4L2_ISP_PARAMS_FL_BLOCK_DISABLE); + bool dirty = gamma->header.flags & CAMSS_ISP_PARAMS_FL_BLOCK_DIRTY; + struct ope_dev *ope = ctx->ope; + u8 bank; + + if (!force && !dirty) + return; + + gamma->header.flags &= ~CAMSS_ISP_PARAMS_FL_BLOCK_DIRTY; + + if (!enable) { + ope_write_pp(ope, OPE_PP_GLUT_MODULE_CFG, 0); + return; + } + + if (!dirty && ope_glut_bank_resident(ope, ope->glut_cur_bank, ctx)) { + /* Already active in the read bank: only (re)enable the module. */ + bank = ope->glut_cur_bank; + } else if (!dirty && ope_glut_bank_resident(ope, !ope->glut_cur_bank, ctx)) { + /* Resident in the other bank: flip to it, no upload. */ + bank = !ope->glut_cur_bank; + } else { + /* Dirty, or miss in both banks: upload into the LRU bank. */ + bank = !ope->glut_mru_bank; + ope_glut_upload(ctx, bank); + } + + ope->glut_mru_bank = bank; + + dev_dbg(ope->dev, + "IQ module (%u) update (flags:0x%x) glut bank %u->%u)\n", + gamma->header.type, gamma->header.flags, + ope->glut_cur_bank, bank); + + ope_write_pp(ope, OPE_PP_GLUT_MODULE_LUT_BANK_CFG, + FIELD_PREP(OPE_PP_GLUT_MODULE_LUT_BANK_CFG_SEL, bank)); + ope->glut_cur_bank = bank; + + ope_write_pp(ope, OPE_PP_GLUT_MODULE_CFG, OPE_PP_GLUT_MODULE_CFG_EN); +} + +static void ope_glut_cache_invalidate(struct ope_dev *ope) +{ + ope->glut_bank[0].valid = false; + ope->glut_bank[1].valid = false; + ope->glut_cur_bank = 0; + ope->glut_mru_bank = 0; +} + +static void ope_prog_crop_rnd_clamp(struct ope_dev *ope, const struct ope_stripe *stripe) +{ + static const u32 crop_bases[] = { + OPE_PP_CROP_RND_CLAMP_Y_DISP_BASE, + OPE_PP_CROP_RND_CLAMP_C_DISP_BASE, + }; + static const enum ope_downscaler ds_idx[] = { + OPE_DS_Y_DISP, + OPE_DS_C_DISP, + }; + + for (unsigned int i = 0; i < ARRAY_SIZE(crop_bases); i++) { + const struct ope_dsc_config *dsc = &stripe->dsc[ds_idx[i]]; + u32 cbase = crop_bases[i]; + + if (!dsc->output_width || !dsc->output_height) { + ope_write_pp(ope, OPE_PP_CROP_RND_CLAMP_MODULE_CFG(cbase), 0); + continue; + } + + ope_write_pp(ope, OPE_PP_CROP_RND_CLAMP_CROP_PIXEL_CFG(cbase), + FIELD_PREP(OPE_PP_CROP_RND_CLAMP_CROP_FIRST, 0) | + FIELD_PREP(OPE_PP_CROP_RND_CLAMP_CROP_LAST, + dsc->crop_last_pixel)); + ope_write_pp(ope, OPE_PP_CROP_RND_CLAMP_CROP_LINE_CFG(cbase), + FIELD_PREP(OPE_PP_CROP_RND_CLAMP_CROP_FIRST, 0) | + FIELD_PREP(OPE_PP_CROP_RND_CLAMP_CROP_LAST, dsc->crop_last_line)); + ope_write_pp(ope, OPE_PP_CROP_RND_CLAMP_MODULE_CFG(cbase), + OPE_PP_CROP_RND_CLAMP_EN | OPE_PP_CROP_RND_CLAMP_CROP_EN); + } +} + +static void ope_prog_stripe(struct ope_ctx *ctx, struct ope_stripe *stripe) +{ + struct ope_dev *ope = ctx->ope; + + dev_dbg(ope->dev, "ctx=%p programming stripe %u\n", + ctx, (unsigned int)(stripe - ctx->stripe)); + + /* Fetch Engine */ + ope_write_rd(ope, OPE_BUS_RD_CLIENT_0_UNPACK_CFG_0, stripe->src.format); + ope_write_rd(ope, OPE_BUS_RD_CLIENT_0_RD_BUFFER_SIZE, + (stripe->src.width << 16) | stripe->src.height); + ope_write_rd(ope, OPE_BUS_RD_CLIENT_0_ADDR_IMAGE, stripe->src.addr); + ope_write_rd(ope, OPE_BUS_RD_CLIENT_0_RD_STRIDE, stripe->src.stride); + ope_write_rd(ope, OPE_BUS_RD_CLIENT_0_CCIF_META_DATA, + FIELD_PREP(OPE_BUS_RD_CLIENT_0_CCIF_MD_PIX_PATTERN, + stripe->src.pattern)); + ope_write_rd(ope, OPE_BUS_RD_CLIENT_0_CORE_CFG, + OPE_BUS_RD_CLIENT_0_CORE_CFG_EN); + + /* Write Engines */ + for (int i = 0; i < OPE_WR_CLIENT_MAX; i++) { + if (!stripe->dst[i].enabled) { + ope_write_wr(ope, OPE_BUS_WR_CLIENT_CFG(i), 0); + continue; + } + + ope_write_wr(ope, OPE_BUS_WR_CLIENT_ADDR_IMAGE(i), + stripe->dst[i].addr); + ope_write_wr(ope, OPE_BUS_WR_CLIENT_IMAGE_CFG_0(i), + (stripe->dst[i].height << 16) | stripe->dst[i].width); + ope_write_wr(ope, OPE_BUS_WR_CLIENT_IMAGE_CFG_1(i), + stripe->dst[i].x_init); + ope_write_wr(ope, OPE_BUS_WR_CLIENT_IMAGE_CFG_2(i), + stripe->dst[i].stride); + ope_write_wr(ope, OPE_BUS_WR_CLIENT_PACKER_CFG(i), + stripe->dst[i].format); + ope_write_wr(ope, OPE_BUS_WR_CLIENT_CFG(i), + OPE_BUS_WR_CLIENT_CFG_EN | + OPE_BUS_WR_CLIENT_CFG_AUTORECOVER); + } + + /* Downscalers */ + for (int i = 0; i < OPE_DS_MAX; i++) { + struct ope_dsc_config *dsc = &stripe->dsc[i]; + u32 base = ope_ds_base[i]; + u32 cfg = 0; + + if (dsc->input_width != dsc->output_width) { + dsc->phase_step_h |= + DS_RESOLUTION(dsc->input_width, + dsc->output_width) << 30; + cfg |= OPE_PP_DOWNSCALE_MN_DS_CFG_H_SCALE_EN; + } + if (dsc->input_height != dsc->output_height) { + dsc->phase_step_v |= + DS_RESOLUTION(dsc->input_height, + dsc->output_height) << 30; + cfg |= OPE_PP_DOWNSCALE_MN_DS_CFG_V_SCALE_EN; + } + + ope_write_pp(ope, OPE_PP_DOWNSCALE_MN_DS_CFG(base), cfg); + ope_write_pp(ope, OPE_PP_DOWNSCALE_MN_DS_IMAGE_SIZE_CFG(base), + ((dsc->input_width - 1) << 16) | (dsc->input_height - 1)); + ope_write_pp(ope, OPE_PP_DOWNSCALE_MN_DS_MN_H_CFG(base), + dsc->phase_step_h); + ope_write_pp(ope, OPE_PP_DOWNSCALE_MN_DS_MN_V_CFG(base), + dsc->phase_step_v); + ope_write_pp(ope, OPE_PP_DOWNSCALE_MN_CFG(base), + cfg ? OPE_PP_DOWNSCALE_MN_CFG_EN : 0); + + dev_dbg(ope->dev, "DS[%d] cfg=0x%x in=%ux%u out=%ux%u\n", + i, cfg, dsc->input_width, dsc->input_height, + dsc->output_width, dsc->output_height); + } + + ope_prog_crop_rnd_clamp(ope, stripe); +} + +static void ope_params_apply_wb(void *priv, const union camss_isp_params_block *block) +{ + struct ope_ctx *ctx = priv; + + if (!camss_isp_params_copy_block(&ctx->config.wb_gain, block, sizeof(ctx->config.wb_gain))) + return; + + ctx->config.wb_gain.g_sub = block->wb_gain.g_sub >> 4; + ctx->config.wb_gain.b_sub = block->wb_gain.b_sub >> 4; + ctx->config.wb_gain.r_sub = block->wb_gain.r_sub >> 4; + ctx->config.wb_gain.g_add = block->wb_gain.g_add >> 4; + ctx->config.wb_gain.b_add = block->wb_gain.b_add >> 4; + ctx->config.wb_gain.r_add = block->wb_gain.r_add >> 4; +} + +static void ope_params_apply_chroma_enhan(void *priv, const union camss_isp_params_block *block) +{ + struct ope_ctx *ctx = priv; + + camss_isp_params_copy_block(&ctx->config.chroma_enhan, block, + sizeof(ctx->config.chroma_enhan)); +} + +static void ope_params_apply_color_correct(void *priv, const union camss_isp_params_block *block) +{ + struct ope_ctx *ctx = priv; + + camss_isp_params_copy_block(&ctx->config.color_correct, block, + sizeof(ctx->config.color_correct)); +} + +static void ope_params_apply_gamma(void *priv, const union camss_isp_params_block *block) +{ + struct ope_ctx *ctx = priv; + + camss_isp_params_copy_block(&ctx->config.gamma, block, sizeof(ctx->config.gamma)); +} + +static const struct v4l2_isp_params_block_type_info ope_params_type_info[] = { + [CAMSS_PARAMS_WB_GAIN] = { sizeof(struct camss_params_wb_gain) }, + [CAMSS_PARAMS_CHROMA_ENHAN] = { sizeof(struct camss_params_chroma_enhan) }, + [CAMSS_PARAMS_COLOR_CORRECT] = { sizeof(struct camss_params_color_correct) }, + [CAMSS_PARAMS_GAMMA] = { sizeof(struct camss_params_gamma) }, +}; + +static const camss_isp_params_handler_fn ope_params_handlers[] = { + [CAMSS_PARAMS_WB_GAIN] = ope_params_apply_wb, + [CAMSS_PARAMS_CHROMA_ENHAN] = ope_params_apply_chroma_enhan, + [CAMSS_PARAMS_COLOR_CORRECT] = ope_params_apply_color_correct, + [CAMSS_PARAMS_GAMMA] = ope_params_apply_gamma, +}; + +static struct vb2_v4l2_buffer *ope_queue_remove(struct ope_ctx *ctx, + unsigned int idx) +{ + struct ope_queue *q = &ctx->queues[idx]; + struct camss_isp_buf *buf; + + scoped_guard(spinlock_irqsave, &q->rdy_spinlock) { + buf = list_first_entry_or_null(&q->rdy_queue, struct camss_isp_buf, list); + if (buf) + list_del(&buf->list); + } + + return buf ? &buf->vb : NULL; +} + +static struct vb2_v4l2_buffer *ope_queue_peek(struct ope_ctx *ctx, + unsigned int idx) +{ + struct ope_queue *q = &ctx->queues[idx]; + struct camss_isp_buf *buf; + + scoped_guard(spinlock_irqsave, &q->rdy_spinlock) + buf = list_first_entry_or_null(&q->rdy_queue, struct camss_isp_buf, list); + + return buf ? &buf->vb : NULL; +} + +static void ope_queue_drain(struct ope_ctx *ctx, unsigned int idx, + enum vb2_buffer_state state) +{ + struct vb2_v4l2_buffer *vbuf; + + while ((vbuf = ope_queue_remove(ctx, idx))) + vb2_buffer_done(&vbuf->vb2_buf, state); +} + +static int ope_apply_params(struct ope_ctx *ctx) +{ + struct vb2_v4l2_buffer *vbuf; + + vbuf = ope_queue_peek(ctx, OPE_QUEUE_PARAMS); + if (!vbuf) + return 0; + + return camss_isp_params_apply(ctx->ope->dev, &vbuf->vb2_buf, + ctx->params_buf, + ope_params_type_info, + ope_params_handlers, + ARRAY_SIZE(ope_params_handlers), + ctx); +} + +/* Default/initial tuning parameters */ +static const struct ope_config ope_default_config = { + .wb_gain = { + .header.type = CAMSS_PARAMS_WB_GAIN, + .header.flags = V4L2_ISP_PARAMS_FL_BLOCK_ENABLE | + CAMSS_ISP_PARAMS_FL_BLOCK_DIRTY, + .g_gain = OPE_WB(1, 1), + .b_gain = OPE_WB(3, 2), + .r_gain = OPE_WB(3, 2), + }, + .demo = { + .header.type = CAMSS_PARAMS_INTERNAL, + .header.flags = V4L2_ISP_PARAMS_FL_BLOCK_ENABLE | + CAMSS_ISP_PARAMS_FL_BLOCK_DIRTY, + .lambda_rb = 0, + .lambda_g = 128, + .a_k = 128, + .w_k = 102, + }, + .chroma_enhan = { /* RGB -> YUV values from BT.601/Full-Range */ + .header.type = CAMSS_PARAMS_CHROMA_ENHAN, + .header.flags = V4L2_ISP_PARAMS_FL_BLOCK_ENABLE | + CAMSS_ISP_PARAMS_FL_BLOCK_DIRTY, + .luma_v0 = 0x04d, /* 0.299 */ + .luma_v1 = 0x096, /* 0.587 */ + .luma_v2 = 0x01d, /* 0.114 */ + .luma_k = 0, + .coeff_ap = 0x077, /* 0.464 */ + .coeff_am = 0x070, /* 0.438 */ + .coeff_bp = 0xfac, /* -0.329 */ + .coeff_bm = 0xfc4, /* -0.234 */ + .coeff_cp = 0x086, /* 0.524 */ + .coeff_cm = 0x089, /* 0.535 */ + .coeff_dp = 0xfff, /* -0.004 */ + .coeff_dm = 0xfdf, /* -0.130 */ + .kcb = 128, + .kcr = 128, + }, + .color_correct = { + .header.type = CAMSS_PARAMS_COLOR_CORRECT, + .header.flags = V4L2_ISP_PARAMS_FL_BLOCK_DISABLE | + CAMSS_ISP_PARAMS_FL_BLOCK_DIRTY, + }, + .gamma = { + .header.type = CAMSS_PARAMS_GAMMA, + .header.flags = V4L2_ISP_PARAMS_FL_BLOCK_DISABLE | + CAMSS_ISP_PARAMS_FL_BLOCK_DIRTY, + }, +}; + +static void ope_try_schedule(struct ope_ctx *ctx); + +static int ope_hw_reset_sync(struct ope_dev *ope) +{ + reinit_completion(&ope->reset_complete); + ope_write(ope, OPE_TOP_RESET_CMD, OPE_TOP_RESET_CMD_SW); + + if (!wait_for_completion_timeout(&ope->reset_complete, + msecs_to_jiffies(OPE_RESET_TIMEOUT_MS))) + return -ETIMEDOUT; + + return 0; +} + +static int ope_hw_reset_poll(struct ope_dev *ope) +{ + u32 status; + int ret; + + ope_write(ope, OPE_TOP_IRQ_MASK, OPE_TOP_IRQ_STATUS_RST_DONE); + ope_write(ope, OPE_TOP_RESET_CMD, OPE_TOP_RESET_CMD_SW); + + ret = read_poll_timeout(ope_read, status, + status & OPE_TOP_IRQ_STATUS_RST_DONE, + OPE_RESET_POLL_US, + OPE_RESET_TIMEOUT_MS * USEC_PER_MSEC, false, + ope, OPE_TOP_IRQ_STATUS); + + ope_write(ope, OPE_TOP_IRQ_CLEAR, OPE_TOP_IRQ_STATUS_RST_DONE); + ope_write(ope, OPE_TOP_IRQ_CMD, OPE_TOP_IRQ_CMD_CLEAR); + ope_write(ope, OPE_TOP_IRQ_MASK, 0); + + if (ret) + return ret; + + ope_glut_cache_invalidate(ope); + + return 0; +} + +/* -------- Job scheduling -------- */ +static bool ope_job_ready(void *priv) +{ + struct ope_ctx *ctx = priv; + + return ctx->started && + !list_empty(&ctx->queues[OPE_QUEUE_FRAME_IN].rdy_queue) && + !list_empty(&ctx->queues[OPE_QUEUE_DISP_OUT].rdy_queue); +} + +static void ope_job_finish(struct ope_ctx *ctx, enum vb2_buffer_state state) +{ + struct vb2_v4l2_buffer *src, *dst, *params; + struct ope_dev *ope = ctx->ope; + + src = ope_queue_remove(ctx, OPE_QUEUE_FRAME_IN); + dst = ope_queue_remove(ctx, OPE_QUEUE_DISP_OUT); + params = ope_queue_remove(ctx, OPE_QUEUE_PARAMS); + + if (dst) { + dst->sequence = ctx->fmt_in.sequence++; + if (src) + dst->vb2_buf.timestamp = src->vb2_buf.timestamp; + } + + if (dst) + vb2_buffer_done(&dst->vb2_buf, state); + if (src) + vb2_buffer_done(&src->vb2_buf, state); + if (params) + vb2_buffer_done(¶ms->vb2_buf, state); + + scoped_guard(spinlock_irqsave, &ope->sched_lock) { + ope->hw_running = false; + ope->curr_ctx = NULL; + ctx->queued = false; + + /* A failed job leaves the configuration in an unknown state */ + if (state != VB2_BUF_STATE_DONE) + ope->hw_ctx = NULL; + } + + dev_dbg(ctx->ope->dev, "done ctx=%p state=%u\n", ctx, state); + + ope_try_schedule(ctx); +} + +static dma_addr_t ope_buf_dma_addr(struct ope_ctx *ctx, unsigned int queue_idx) +{ + struct vb2_v4l2_buffer *vbuf = ope_queue_peek(ctx, queue_idx); + + if (!vbuf) + return 0; + + return vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); +} + +static void ope_run_job(void *priv, bool ctx_changed) +{ + struct ope_ctx *ctx = priv; + struct ope_dev *ope = ctx->ope; + dma_addr_t src, dst; + + src = ope_buf_dma_addr(ctx, OPE_QUEUE_FRAME_IN); + dst = ope_buf_dma_addr(ctx, OPE_QUEUE_DISP_OUT); + + if (!src || !dst) { + dev_warn(ope->dev, "Job cannot run, missing buffer\n"); + ope_hw_reset_sync(ope); + ope_job_finish(ctx, VB2_BUF_STATE_ERROR); + return; + } + + dev_dbg(ope->dev, "start ctx=%p->%p src=%pad dst=%pad\n", + ope->hw_ctx, ctx, &src, &dst); + + if (ope_apply_params(ctx)) + dev_warn_ratelimited(ope->dev, "Invalid parameters\n"); + + if (ope_gen_stripes(ctx, src, dst)) { + dev_warn_ratelimited(ope->dev, "Job cannot run, invalid geometry\n"); + ope_hw_reset_sync(ope); + ope_job_finish(ctx, VB2_BUF_STATE_ERROR); + return; + } + + ope_prog_wb(ctx, ctx_changed); + ope_prog_bayer2rgb(ctx, ctx_changed); + ope_prog_color_correct(ctx, ctx_changed); + ope_prog_gamma(ctx, ctx_changed); + ope_prog_rgb2yuv(ctx, ctx_changed); + + ctx->current_stripe = 0; + + scoped_guard(spinlock_irqsave, &ope->sched_lock) { + ope->hw_ctx = ctx; + ope->hw_running = true; + } + + ope_prog_stripe(ctx, &ctx->stripe[0]); + + ope_start(ope); +} + +static void ope_sched_cancel(struct ope_ctx *ctx) +{ + struct ope_dev *ope = ctx->ope; + bool running; + + disable_work_sync(&ope->run_work); + + scoped_guard(spinlock_irqsave, &ope->sched_lock) + running = (ope->hw_running && ope->hw_ctx == ctx); + + if (running && ope_hw_reset_sync(ope)) { + dev_err(ope->dev, "reset timeout during cancel\n"); + synchronize_irq(ope->irq); + ope_job_finish(ctx, VB2_BUF_STATE_ERROR); + } + + scoped_guard(spinlock_irqsave, &ope->sched_lock) { + ctx->queued = false; + if (ope->curr_ctx == ctx) + ope->curr_ctx = NULL; + if (ope->hw_ctx == ctx) { + ope->hw_ctx = NULL; + ope->hw_running = false; + } + } +} + +static void ope_sched_resume(struct ope_ctx *ctx) +{ + if (enable_work(&ctx->ope->run_work)) + ope_try_schedule(ctx); +} + +static void ope_run_work(struct work_struct *work) +{ + struct ope_dev *ope = container_of(work, struct ope_dev, run_work); + struct ope_ctx *ctx; + bool ctx_changed; + + if (unlikely(!ope_hw_available(ope))) + return; + + scoped_guard(spinlock_irqsave, &ope->sched_lock) { + ctx = ope->curr_ctx; + + if (!ctx || !ctx->queued || ope->hw_running) + return; + + if (!ope_job_ready(ctx)) { + ctx->queued = false; + ope->curr_ctx = NULL; + return; + } + + /* The registers still hold the parameters of @hw_ctx */ + ctx_changed = (ope->hw_ctx != ctx); + } + + ope_run_job(ctx, ctx_changed); +} + +static void ope_try_schedule(struct ope_ctx *ctx) +{ + struct ope_dev *ope = ctx->ope; + + if (!ope_job_ready(ctx)) + return; + + /* Claim the job slot. */ + scoped_guard(spinlock_irqsave, &ope->sched_lock) { + if (ctx->queued || ope->curr_ctx) + return; + ctx->queued = true; + ope->curr_ctx = ctx; + } + + schedule_work(&ope->run_work); +} + +/* -------- Interrupt handlers -------- */ + +static void ope_fe_irq(struct ope_dev *ope) +{ + u32 status = readl_relaxed(ope->base_rd + OPE_BUS_RD_INPUT_IF_IRQ_STATUS); + + writel_relaxed(status, ope->base_rd + OPE_BUS_RD_INPUT_IF_IRQ_CLEAR); + writel_relaxed(OPE_BUS_RD_INPUT_IF_IRQ_CMD_CLEAR, + ope->base_rd + OPE_BUS_RD_INPUT_IF_IRQ_CMD); + + if (status & OPE_BUS_RD_INPUT_IF_IRQ_STATUS_CCIF_VIOL) + dev_err_ratelimited(ope->dev, "FE: CCIF violation (status=0x%08x)\n", status); +} + +static bool ope_we_irq(struct ope_dev *ope, struct ope_ctx *ctx) +{ + bool reset = false; + u32 status; + + status = ope_read_wr(ope, OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0); + ope_write_wr(ope, OPE_BUS_WR_INPUT_IF_IRQ_CLEAR_0, status); + ope_write_wr(ope, OPE_BUS_WR_INPUT_IF_IRQ_CMD, OPE_BUS_WR_INPUT_IF_IRQ_CMD_CLEAR); + + if (!ctx) + return false; + + if (status & OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_CONS_VIOL) { + u32 viol = ope_read_wr(ope, OPE_BUS_WR_VIOLATION_STATUS); + + dev_err_ratelimited(ope->dev, "constraint violation (clients=0x%x)\n", viol); + reset = true; + } + + if (status & OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_IMG_SZ_VIOL) { + u32 viol = ope_read_wr(ope, OPE_BUS_WR_IMAGE_SIZE_VIOLATION_STATUS); + + for (int i = 0; i < OPE_WR_CLIENT_MAX; i++) { + if (BIT(i) & viol) + dev_err_ratelimited(ope->dev, "WE%d: image size violation\n", i); + } + reset = true; + } + + if (status & OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_VIOL) { + u32 viol = ope_read_wr(ope, OPE_BUS_WR_VIOLATION_STATUS); + + dev_err_ratelimited(ope->dev, "fatal violation (status=0x%08x)\n", viol); + reset = true; + } + + if (reset) { + ope_write(ctx->ope, OPE_TOP_RESET_CMD, OPE_TOP_RESET_CMD_SW); + return true; + } + + if (status & OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_RUP_DONE) { + /* Register update done: program next stripe (double-buffered) */ + struct ope_stripe *stripe = ope_current_stripe(ctx); + + if (stripe && !ope_stripe_is_last(stripe)) + ope_prog_stripe(ctx, stripe + 1); + } + + return false; +} + + +static void __ope_irq_init(struct ope_dev *ope) +{ + ope_write(ope, OPE_TOP_IRQ_MASK, + OPE_TOP_IRQ_STATUS_RST_DONE | + OPE_TOP_IRQ_STATUS_WE | + OPE_TOP_IRQ_STATUS_FE | + OPE_TOP_IRQ_STATUS_VIOL | + OPE_TOP_IRQ_STATUS_IDLE); + ope_write_wr(ope, OPE_BUS_WR_INPUT_IF_IRQ_MASK_0, + OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_RUP_DONE | + OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_CONS_VIOL | + OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_VIOL | + OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_IMG_SZ_VIOL); + /* The fetch engine only needs to report bus errors */ + writel_relaxed(OPE_BUS_RD_INPUT_IF_IRQ_STATUS_CCIF_VIOL, + ope->base_rd + OPE_BUS_RD_INPUT_IF_IRQ_MASK); +} + +static irqreturn_t ope_irq(int irq, void *dev_id) +{ + struct ope_dev *ope = dev_id; + struct ope_ctx *ctx; + u32 status; + + /* + * The running job is safe to read here without a lock: ope_run_job() + * publishes it before calling ope_start(), so the hardware cannot raise + * an IRQ before it is visible. ope_job_finish() clears hw_running in IRQ + * context here, so the clear is serialised with this read by the IRQ + * itself. + */ + ctx = ope->hw_running ? ope->hw_ctx : NULL; + + status = ope_read(ope, OPE_TOP_IRQ_STATUS); + if (!status) + return IRQ_NONE; + + ope_write(ope, OPE_TOP_IRQ_CLEAR, status); + ope_write(ope, OPE_TOP_IRQ_CMD, OPE_TOP_IRQ_CMD_CLEAR); + + if (status & OPE_TOP_IRQ_STATUS_RST_DONE) { + dev_dbg(ope->dev, "reset done ctx=%p\n", ctx); + ope_glut_cache_invalidate(ope); + if (ctx) + ope_job_finish(ctx, VB2_BUF_STATE_ERROR); + + complete(&ope->reset_complete); + + return IRQ_HANDLED; + } + + if (status & OPE_TOP_IRQ_STATUS_VIOL) + dev_warn(ope->dev, "OPE violation: 0x%08x\n", + ope_read(ope, OPE_TOP_VIOLATION_STATUS)); + + if (status & OPE_TOP_IRQ_STATUS_FE) + ope_fe_irq(ope); + + if (status & OPE_TOP_IRQ_STATUS_WE) { + if (ope_we_irq(ope, ctx)) + return IRQ_HANDLED; + } + + if ((status & OPE_TOP_IRQ_STATUS_IDLE) && ctx) { + struct ope_stripe *stripe = ope_current_stripe(ctx); + + dev_dbg(ope->dev, "stripe %u done ctx=%p\n", ctx->current_stripe, ctx); + + if (unlikely(!stripe)) { + dev_err(ope->dev, "stripe index %u out of range\n", ctx->current_stripe); + ctx->current_stripe = 0; + ope_job_finish(ctx, VB2_BUF_STATE_ERROR); + } else if (ope_stripe_is_last(stripe)) { + ctx->current_stripe = 0; + ope_job_finish(ctx, VB2_BUF_STATE_DONE); + } else { + ctx->current_stripe++; + ope_start(ope); + } + } + + return IRQ_HANDLED; +} + +/* -------- vb2 queue private data -------- */ + +struct ope_vq_priv { + struct ope_ctx *ctx; + unsigned int queue_idx; + struct video_device *vdev; +}; + +static inline struct ope_ctx *ope_ctx_from_vq(struct vb2_queue *q) +{ + return ((struct ope_vq_priv *)vb2_get_drv_priv(q))->ctx; +} + +static inline unsigned int ope_idx_from_vq(struct vb2_queue *q) +{ + return ((struct ope_vq_priv *)vb2_get_drv_priv(q))->queue_idx; +} + +static inline struct video_device *ope_vdev_from_vq(struct vb2_queue *q) +{ + return ((struct ope_vq_priv *)vb2_get_drv_priv(q))->vdev; +} + +/* -------- vb2 ops -------- */ + +static int ope_queue_setup(struct vb2_queue *q, unsigned int *nbuffers, + unsigned int *nplanes, unsigned int sizes[], + struct device *alloc_devs[]) +{ + struct ope_ctx *ctx = ope_ctx_from_vq(q); + unsigned int idx = ope_idx_from_vq(q); + unsigned int size; + + if (idx == OPE_QUEUE_FRAME_IN) + size = ctx->fmt_in.sizeimage ? ctx->fmt_in.sizeimage : PAGE_SIZE; + else if (idx == OPE_QUEUE_DISP_OUT) + size = ctx->fmt_out.sizeimage ? ctx->fmt_out.sizeimage : PAGE_SIZE; + else + size = v4l2_isp_buffer_size(CAMSS_PARAMS_OPE_MAX_PAYLOAD); + + if (*nplanes) { + if (*nplanes != 1 || sizes[0] < size) + return -EINVAL; + } else { + *nplanes = 1; + sizes[0] = size; + } + + return 0; +} + +static int ope_buf_prepare(struct vb2_buffer *vb) +{ + struct ope_ctx *ctx = ope_ctx_from_vq(vb->vb2_queue); + unsigned int idx = ope_idx_from_vq(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + unsigned int sizeimage; + + if (idx == OPE_QUEUE_FRAME_IN) + sizeimage = ctx->fmt_in.sizeimage; + else if (idx == OPE_QUEUE_DISP_OUT) + sizeimage = ctx->fmt_out.sizeimage; + else + sizeimage = v4l2_isp_buffer_size(CAMSS_PARAMS_OPE_MAX_PAYLOAD); + + if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { + if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + if (vbuf->field == V4L2_FIELD_ANY) + vbuf->field = V4L2_FIELD_NONE; + if (vbuf->field != V4L2_FIELD_NONE) + return -EINVAL; + } + } + + if (vb2_plane_size(vb, 0) < sizeimage) + return -EINVAL; + + if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) + vb2_set_plane_payload(vb, 0, sizeimage); + + return 0; +} + +static void ope_buf_queue(struct vb2_buffer *vb) +{ + struct ope_ctx *ctx = ope_ctx_from_vq(vb->vb2_queue); + unsigned int idx = ope_idx_from_vq(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct ope_queue *q = &ctx->queues[idx]; + struct camss_isp_buf *buf = container_of(vbuf, struct camss_isp_buf, vb); + + guard(spinlock_irqsave)(&q->rdy_spinlock); + list_add_tail(&buf->list, &q->rdy_queue); + + ope_try_schedule(ctx); +} + +/* -------- Power scaling -------- */ + +static inline unsigned long ope_pixclk(const struct ope_fmt_state *fs, unsigned int fps) +{ + return (unsigned long)fs->width * fs->height * fps; +} + +static inline unsigned int ope_load_avg(const struct ope_fmt_state *fs, unsigned int fps) +{ + return mult_frac(ope_pixclk(fs, fps), fs->fmt->depth, 1000) / 8; +} + +static inline unsigned int ope_load_peak(const struct ope_fmt_state *fs, unsigned int fps) +{ + return ope_load_avg(fs, fps) * 2; +} + +static inline unsigned int ope_load_config(const struct ope_fmt_state *fs, unsigned int fps) +{ + unsigned int stripe_count = fs->width / OPE_STRIPE_MAX_W + 1; + + /* In worst case we have ~50 32-bit registers to write */ + return mult_frac(stripe_count * 50 * 4, fps, 1000); +} + +static void ope_adjust_power(struct ope_dev *ope) +{ + unsigned int loadavg = 0, loadpeak = 0, loadconfig = 0; + unsigned long pixclk = 0; + struct dev_pm_opp *opp; + struct ope_ctx *ctx; + int ret; + + if (unlikely(!ope_hw_available(ope))) + return; + + scoped_guard(spinlock, &ope->ctx_lock) { + list_for_each_entry(ctx, &ope->ctx_list, list) { + unsigned int fps; + + if (!ctx->started) + continue; + + fps = ctx->framerate ? ctx->framerate : DEFAULT_FRAMERATE; + + pixclk += ope_pixclk(&ctx->fmt_in, fps); + loadavg += ope_load_avg(&ctx->fmt_in, fps); + loadavg += ope_load_avg(&ctx->fmt_out, fps); + loadpeak += ope_load_peak(&ctx->fmt_in, fps); + loadpeak += ope_load_peak(&ctx->fmt_out, fps); + loadconfig += ope_load_config(&ctx->fmt_in, fps); + } + } + + /* 30% margin for overhead */ + pixclk = mult_frac(pixclk, 13, 10); + + dev_dbg(ope->dev, "adjust power: clk=%luHz avg=%uKBps peak=%uKBps cfg=%uKBps\n", + pixclk, loadavg, loadpeak, loadconfig); + + opp = dev_pm_opp_find_freq_ceil(ope->dev, &pixclk); + if (IS_ERR(opp)) + dev_warn(ope->dev, "Requested pixel clock %luHz exceeds hardware limit\n", pixclk); + else + dev_pm_opp_put(opp); + + ret = dev_pm_opp_set_rate(ope->dev, pixclk); + if (ret) + dev_warn(ope->dev, "Failed to set OPP rate: %d\n", ret); + + ret = icc_set_bw(ope->icc_data, loadavg, loadpeak); + if (ret) + dev_warn(ope->dev, "Failed to set data path BW: %d\n", ret); + + ret = icc_set_bw(ope->icc_config, loadconfig, loadconfig * 5); + if (ret) + dev_warn(ope->dev, "Failed to set config path BW: %d\n", ret); +} + +static int ope_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct ope_ctx *ctx = ope_ctx_from_vq(q); + struct video_device *vdev = ope_vdev_from_vq(q); + unsigned int idx = ope_idx_from_vq(q); + int ret; + + dev_dbg(ctx->ope->dev, "streaming start ctx=%p queue=%u\n", ctx, idx); + + if (!ope_hw_available(ctx->ope)) { + ret = -ENODEV; + goto err_drain; + } + + ret = video_device_pipeline_alloc_start(vdev); + if (ret) + goto err_drain; + + ret = pm_runtime_resume_and_get(ctx->ope->dev); + if (ret) { + dev_err(ctx->ope->dev, "resume failed (%d)\n", ret); + goto err_pipeline_stop; + } + + if (idx == OPE_QUEUE_FRAME_IN) { + ctx->fmt_in.sequence = 0; + ctx->started = true; + ope_adjust_power(ctx->ope); + __ope_irq_init(ctx->ope); + } + + ope_try_schedule(ctx); + + return 0; + +err_pipeline_stop: + video_device_pipeline_stop(vdev); +err_drain: + ope_queue_drain(ctx, idx, VB2_BUF_STATE_QUEUED); + return ret; +} + +static void ope_stop_streaming(struct vb2_queue *q) +{ + struct ope_ctx *ctx = ope_ctx_from_vq(q); + struct video_device *vdev = ope_vdev_from_vq(q); + unsigned int idx = ope_idx_from_vq(q); + + dev_dbg(ctx->ope->dev, "streaming stop ctx=%p queue=%u\n", ctx, idx); + + if (idx == OPE_QUEUE_FRAME_IN) { + ctx->started = false; + ope_adjust_power(ctx->ope); + } + + /* Drain with the scheduler held off, so no job can pick up a buffer */ + ope_sched_cancel(ctx); + ope_queue_drain(ctx, idx, VB2_BUF_STATE_ERROR); + ope_sched_resume(ctx); + + pm_runtime_put(ctx->ope->dev); + + if (video_device_pipeline(vdev)) + video_device_pipeline_stop(vdev); +} + +static const struct vb2_ops ope_vb2_ops = { + .queue_setup = ope_queue_setup, + .buf_prepare = ope_buf_prepare, + .buf_queue = ope_buf_queue, + .start_streaming = ope_start_streaming, + .stop_streaming = ope_stop_streaming, +}; + +static const unsigned int ope_queue_to_entity[] = { + [OPE_QUEUE_FRAME_IN] = OPE_ENTITY_FRAME_IN, + [OPE_QUEUE_DISP_OUT] = OPE_ENTITY_DISP_OUT, + [OPE_QUEUE_PARAMS] = OPE_ENTITY_PARAMS, +}; + +static int ope_init_vq(struct ope_ctx *ctx, unsigned int idx) +{ + struct ope_dev *ope = ctx->ope; + struct ope_vq_priv *qpriv; + struct vb2_queue *q = &ctx->queues[idx].vq; + int ret; + + qpriv = kzalloc_obj(*qpriv); + if (!qpriv) + return -ENOMEM; + + qpriv->ctx = ctx; + qpriv->queue_idx = idx; + qpriv->vdev = camss_isp_pipeline_get_vdev(ope->pipeline, ope_queue_to_entity[idx]); + q->drv_priv = qpriv; + q->ops = &ope_vb2_ops; + q->lock = &ctx->vbq_lock; + q->dev = ope->dev; + q->buf_struct_size = sizeof(struct camss_isp_buf); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + q->min_queued_buffers = (idx == OPE_QUEUE_PARAMS) ? 0 : 1; + + if (idx == OPE_QUEUE_PARAMS) { + q->type = V4L2_BUF_TYPE_META_OUTPUT; + q->mem_ops = &vb2_vmalloc_memops; + q->io_modes = VB2_MMAP | VB2_USERPTR; + } else if (idx == OPE_QUEUE_DISP_OUT) { + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + q->mem_ops = &vb2_dma_contig_memops; + q->io_modes = VB2_MMAP | VB2_DMABUF; + } else { + q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + q->mem_ops = &vb2_dma_contig_memops; + q->io_modes = VB2_MMAP | VB2_DMABUF; + } + + ret = vb2_queue_init(q); + if (ret) { + q->drv_priv = NULL; + kfree(qpriv); + } + + return ret; +} + +static void ope_deinit_vq(struct ope_ctx *ctx, unsigned int idx) +{ + struct vb2_queue *q = &ctx->queues[idx].vq; + + vb2_queue_release(q); + q->owner = NULL; + kfree(q->drv_priv); + q->drv_priv = NULL; +} + +/* -------- Format helpers -------- */ + +static const struct ope_fmt *ope_find_fmt(const struct ope_fmt *fmts, + unsigned int n, u32 fourcc) +{ + for (unsigned int i = 0; i < n; i++) + if (fmts[i].fourcc == fourcc) + return &fmts[i]; + + return NULL; +} + +static const struct ope_fmt *ope_fmt_try(struct ope_dev *ope, bool is_output, + struct v4l2_pix_format_mplane *pix) +{ + const struct ope_fmt *fmts = is_output ? ope_output_fmts : ope_input_fmts; + unsigned int n = is_output ? ARRAY_SIZE(ope_output_fmts) : ARRAY_SIZE(ope_input_fmts); + unsigned int max_w = OPE_MAX_W, max_h = OPE_MAX_H; + const struct ope_fmt *fmt; + unsigned int bytesperline; + unsigned int align; + + fmt = ope_find_fmt(fmts, n, pix->pixelformat); + if (!fmt) { + fmt = &fmts[0]; + pix->pixelformat = fmt->fourcc; + } + + v4l_bound_align_image(&pix->width, OPE_MIN_W, max_w, fmt->align, + &pix->height, OPE_MIN_H, max_h, 0, 0); + + pix->num_planes = 1; + pix->field = V4L2_FIELD_NONE; + if (!pix->colorspace) + pix->colorspace = is_output ? V4L2_COLORSPACE_SRGB : V4L2_COLORSPACE_RAW; + if (is_output) { + pix->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace); + pix->quantization = V4L2_QUANTIZATION_FULL_RANGE; + } + + /* + * Output formats are semi-planar or grey-scale (Y plane only) always + * using 1 byte per Y value. pix->bytesperline stores the Y-plane bpl. + * Depth tracks the total storage size including the second combined + * Cb + Cr plane which directly follows the Y plane and is used for + * sizeimage calculations rather then for bytesperline. + */ + if (is_output) + bytesperline = pix->width; + else + bytesperline = pix->width * fmt->depth / 8; + + if (pix->plane_fmt[0].bytesperline > bytesperline) + bytesperline = pix->plane_fmt[0].bytesperline; + + /* + * The WE requires the C plane base address to be 16-byte aligned. + * c_base = bpl * img_h + (compose_top / c_vsub) * c_stride where + * c_stride = bpl * 2 / c_hsub. To guarantee alignment for any + * compose_top, bpl must be a multiple of 16 / c_hsub: + * NV12/NV16 (c_hsub=2): bpl must be multiple of 8... but c_stride=bpl + * so we need bpl % 16 == 0. + * NV24/NV42 (c_hsub=1): c_stride=bpl*2, need bpl*2 % 16 == 0, + * so bpl must be a multiple of 8. + * GREY: no C plane, no constraint. + */ + if (is_output && fmt->fourcc != V4L2_PIX_FMT_GREY) + align = 8 * fmt->c_hsub; + else + align = 1; + + bytesperline = min(bytesperline, ALIGN_DOWN(OPE_MAX_STRIDE, align)); + bytesperline = ALIGN(bytesperline, align); + + pix->plane_fmt[0].bytesperline = bytesperline; + + if (is_output) + pix->plane_fmt[0].sizeimage = (u64)bytesperline * pix->height * fmt->depth / 8; + else + pix->plane_fmt[0].sizeimage = (u64)bytesperline * pix->height; + + return fmt; +} + +/* -------- ioctl helpers/ops -------- */ + +static inline unsigned int ope_queue_idx_from_file(struct file *file) +{ + return (unsigned int)(uintptr_t)video_get_drvdata(video_devdata(file)); +} + +static struct vb2_queue *ope_vq_from_file(struct file *file, struct ope_ctx *ctx) +{ + unsigned int idx = ope_queue_idx_from_file(file); + + if (idx >= OPE_QUEUE_COUNT) + return NULL; + + return &ctx->queues[idx].vq; +} + +static struct ope_ctx *ope_ctx_from_file(struct file *file) +{ + struct ope_dev *ope = container_of(video_devdata(file)->v4l2_dev, + struct ope_dev, v4l2_dev); + + return ope->shared_ctx; +} + +static int ope_querycap(struct file *file, void *priv, struct v4l2_capability *cap) +{ + strscpy(cap->driver, OPE_NAME, sizeof(cap->driver)); + strscpy(cap->card, "Qualcomm CAMSS OPE", sizeof(cap->card)); + + return 0; +} + +static int ope_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) +{ + unsigned int i, n = 0; + + for (i = 0; i < ARRAY_SIZE(ope_input_fmts); i++) { + if (f->mbus_code && ope_input_fmts[i].mbus_code != f->mbus_code) + continue; + if (n++ == f->index) { + f->pixelformat = ope_input_fmts[i].fourcc; + return 0; + } + } + + return -EINVAL; +} + +static int ope_g_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct ope_fmt_state *fs = &ctx->fmt_in; + struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; + + pix->pixelformat = fs->fmt->fourcc; + pix->width = fs->width; + pix->height = fs->height; + pix->num_planes = 1; + pix->field = V4L2_FIELD_NONE; + pix->colorspace = fs->colorspace; + pix->xfer_func = fs->xfer_func; + pix->ycbcr_enc = fs->ycbcr_enc; + pix->quantization = fs->quantization; + pix->plane_fmt[0].bytesperline = fs->bytesperline; + pix->plane_fmt[0].sizeimage = fs->sizeimage; + + return 0; +} + +static int ope_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + + ope_fmt_try(ctx->ope, false, &f->fmt.pix_mp); + + return 0; +} + +static int ope_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + const struct ope_fmt *fmt; + + if (vb2_is_busy(&ctx->queues[OPE_QUEUE_FRAME_IN].vq)) + return -EBUSY; + + fmt = ope_fmt_try(ctx->ope, false, &f->fmt.pix_mp); + ctx->fmt_in.fmt = fmt; + ctx->fmt_in.width = f->fmt.pix_mp.width; + ctx->fmt_in.height = f->fmt.pix_mp.height; + ctx->fmt_in.bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline; + ctx->fmt_in.sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage; + ctx->fmt_in.colorspace = f->fmt.pix_mp.colorspace; + ctx->fmt_in.xfer_func = f->fmt.pix_mp.xfer_func; + ctx->fmt_in.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + ctx->fmt_in.quantization = f->fmt.pix_mp.quantization; + + return 0; +} + +static int ope_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) +{ + unsigned int i, n = 0; + + for (i = 0; i < ARRAY_SIZE(ope_output_fmts); i++) { + if (f->mbus_code && ope_output_fmts[i].mbus_code != f->mbus_code) + continue; + if (n++ == f->index) { + f->pixelformat = ope_output_fmts[i].fourcc; + return 0; + } + } + + return -EINVAL; +} + +static int ope_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct ope_fmt_state *fs = &ctx->fmt_out; + struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; + + pix->pixelformat = fs->fmt->fourcc; + pix->width = fs->width; + pix->height = fs->height; + pix->num_planes = 1; + pix->field = V4L2_FIELD_NONE; + pix->colorspace = fs->colorspace; + pix->xfer_func = fs->xfer_func; + pix->ycbcr_enc = fs->ycbcr_enc; + pix->quantization = fs->quantization; + pix->plane_fmt[0].bytesperline = fs->bytesperline; + pix->plane_fmt[0].sizeimage = fs->sizeimage; + + return 0; +} + +static int ope_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + + ope_fmt_try(ctx->ope, true, &f->fmt.pix_mp); + + return 0; +} + +static int ope_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + const struct ope_fmt *fmt; + + if (vb2_is_busy(&ctx->queues[OPE_QUEUE_DISP_OUT].vq)) + return -EBUSY; + + fmt = ope_fmt_try(ctx->ope, true, &f->fmt.pix_mp); + + ctx->fmt_out.fmt = fmt; + ctx->fmt_out.width = f->fmt.pix_mp.width; + ctx->fmt_out.height = f->fmt.pix_mp.height; + ctx->fmt_out.bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline; + ctx->fmt_out.sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage; + ctx->fmt_out.colorspace = f->fmt.pix_mp.colorspace; + ctx->fmt_out.xfer_func = f->fmt.pix_mp.xfer_func; + ctx->fmt_out.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + ctx->fmt_out.quantization = f->fmt.pix_mp.quantization; + + return 0; +} + +static int ope_g_fmt_meta(struct file *file, void *priv, struct v4l2_format *f) +{ + f->fmt.meta.dataformat = V4L2_META_FMT_QCOM_ISP_PARAMS; + f->fmt.meta.buffersize = v4l2_isp_buffer_size(CAMSS_PARAMS_OPE_MAX_PAYLOAD); + + return 0; +} + +static int ope_enum_fmt_meta_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) +{ + if (f->index > 0) + return -EINVAL; + + f->pixelformat = V4L2_META_FMT_QCOM_ISP_PARAMS; + + return 0; +} + +static int ope_g_parm(struct file *file, void *priv, struct v4l2_streamparm *sp) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + + if (!V4L2_TYPE_IS_OUTPUT(sp->type)) + return -EINVAL; + + sp->parm.output.capability = V4L2_CAP_TIMEPERFRAME; + sp->parm.output.timeperframe = ctx->fmt_in.timeperframe; + + return 0; +} + +static int ope_s_parm(struct file *file, void *priv, struct v4l2_streamparm *sp) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct v4l2_fract *tpf = &sp->parm.output.timeperframe; + + if (!V4L2_TYPE_IS_OUTPUT(sp->type)) + return -EINVAL; + + if (vb2_is_busy(&ctx->queues[OPE_QUEUE_FRAME_IN].vq)) + return -EBUSY; + + if (!tpf->denominator) + tpf->denominator = 1; + if (!tpf->numerator) + tpf->numerator = 1; + + ctx->framerate = clamp(tpf->denominator / tpf->numerator, 1U, (u32)OPE_MAX_FRAMERATE); + tpf->numerator = 1; + tpf->denominator = ctx->framerate; + + ctx->fmt_in.timeperframe = *tpf; + sp->parm.output.capability = V4L2_CAP_TIMEPERFRAME; + + ope_adjust_power(ctx->ope); + + return 0; +} + +static int ope_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) +{ + unsigned int idx = ope_queue_idx_from_file(file); + const struct ope_fmt *fmts; + unsigned int n; + + if (idx == OPE_QUEUE_FRAME_IN) { + fmts = ope_input_fmts; + n = ARRAY_SIZE(ope_input_fmts); + } else { + fmts = ope_output_fmts; + n = ARRAY_SIZE(ope_output_fmts); + } + + if (fsize->index > 0 || !ope_find_fmt(fmts, n, fsize->pixel_format)) + return -EINVAL; + + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; + fsize->stepwise.min_width = OPE_MIN_W; + fsize->stepwise.max_width = OPE_MAX_W; + fsize->stepwise.step_width = 1; + fsize->stepwise.min_height = OPE_MIN_H; + fsize->stepwise.max_height = OPE_MAX_H; + fsize->stepwise.step_height = 1; + + return 0; +} + +static int ope_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *rb) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct vb2_queue *vq = ope_vq_from_file(file, ctx); + int ret; + + if (!vq) + return -EINVAL; + + if (vb2_queue_is_busy(vq, file)) + return -EBUSY; + + ret = vb2_reqbufs(vq, rb); + if (!ret) + vq->owner = rb->count ? file->private_data : NULL; + + return ret; +} + +static int ope_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct vb2_queue *vq = ope_vq_from_file(file, ctx); + + return vq ? vb2_querybuf(vq, buf) : -EINVAL; +} + +static int ope_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct video_device *vdev = video_devdata(file); + struct vb2_queue *vq = ope_vq_from_file(file, ctx); + + if (!vq) + return -EINVAL; + if (vb2_queue_is_busy(vq, file)) + return -EBUSY; + + return vb2_qbuf(vq, vdev->v4l2_dev->mdev, buf); +} + +static int ope_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct vb2_queue *vq = ope_vq_from_file(file, ctx); + + return vq ? vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK) : -EINVAL; +} + +static int ope_prepare_buf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct video_device *vdev = video_devdata(file); + struct vb2_queue *vq = ope_vq_from_file(file, ctx); + + if (!vq) + return -EINVAL; + if (vb2_queue_is_busy(vq, file)) + return -EBUSY; + + return vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf); +} + +static int ope_create_bufs(struct file *file, void *priv, struct v4l2_create_buffers *create) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct vb2_queue *vq = ope_vq_from_file(file, ctx); + int ret; + + if (!vq) + return -EINVAL; + if (vb2_queue_is_busy(vq, file)) + return -EBUSY; + ret = vb2_create_bufs(vq, create); + if (!ret && create->count) + vq->owner = file->private_data; + + return ret; +} + +static int ope_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *eb) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct vb2_queue *vq = ope_vq_from_file(file, ctx); + + if (!vq) + return -EINVAL; + if (vb2_queue_is_busy(vq, file)) + return -EBUSY; + + return vb2_expbuf(vq, eb); +} + +static int ope_streamon(struct file *file, void *priv, enum v4l2_buf_type type) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct vb2_queue *vq = ope_vq_from_file(file, ctx); + + if (!vq) + return -EINVAL; + if (vb2_queue_is_busy(vq, file)) + return -EBUSY; + + return vb2_streamon(vq, type); +} + +static int ope_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) +{ + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct vb2_queue *vq = ope_vq_from_file(file, ctx); + + if (!vq) + return -EINVAL; + + if (vb2_queue_is_busy(vq, file)) + return -EBUSY; + + return vb2_streamoff(vq, type); +} + +/* -------- proc subdev ops -------- */ + +static const struct v4l2_rect ope_sd_min_rect = { + .width = OPE_MIN_W, + .height = OPE_MIN_H, +}; + +static const struct ope_fmt *ope_fmt_from_mbus_code(const struct ope_fmt *fmts, + unsigned int num_fmts, u32 code) +{ + for (unsigned int i = 0; i < num_fmts; i++) + if (fmts[i].mbus_code == code) + return &fmts[i]; + + return NULL; +} + +static void ope_sd_adjust_crop_rect(struct v4l2_rect *crop, const struct v4l2_rect *bounds, + unsigned int halign, unsigned int valign) +{ + v4l2_rect_set_min_size(crop, &ope_sd_min_rect); + v4l2_rect_map_inside(crop, bounds); + + crop->width = ALIGN_DOWN(crop->width, halign); + crop->height = ALIGN_DOWN(crop->height, valign); + crop->left = ALIGN_DOWN(crop->left, halign); + crop->top = ALIGN_DOWN(crop->top, valign); +} + +static void ope_sd_adjust_crop(struct v4l2_rect *crop, const struct v4l2_mbus_framefmt *bounds) +{ + struct v4l2_rect crop_bounds = { + .left = 0, .top = 0, + .width = bounds->width, .height = bounds->height, + }; + const struct ope_fmt *fmt; + unsigned int halign = 2; + + /* Source packing unit, at least a Bayer pair */ + fmt = ope_fmt_from_mbus_code(ope_input_fmts, ARRAY_SIZE(ope_input_fmts), bounds->code); + if (fmt) + halign = max(2u, 1u << fmt->align); + + ope_sd_adjust_crop_rect(crop, &crop_bounds, halign, 2); +} + +static void ope_proc_adjust_src_compose(struct v4l2_subdev_state *state, struct v4l2_rect *compose) +{ + const struct v4l2_rect *sink_crop = + v4l2_subdev_state_get_crop(state, OPE_PROC_PAD_SINK_IN); + const struct v4l2_mbus_framefmt *src_fmt = + v4l2_subdev_state_get_format(state, OPE_PROC_PAD_SOURCE); + unsigned int halign = 1, valign = 1; + const struct ope_fmt *fmt; + struct v4l2_rect bounds; + + fmt = ope_fmt_from_mbus_code(ope_output_fmts, ARRAY_SIZE(ope_output_fmts), + src_fmt->code); + if (fmt) { + halign = fmt->c_hsub; + valign = fmt->c_vsub; + } + + bounds = (struct v4l2_rect){ 0, 0, sink_crop->width, sink_crop->height }; + ope_sd_adjust_crop_rect(compose, &bounds, halign, valign); +} + +static void ope_proc_set_src_fmt(struct v4l2_subdev_state *state, + struct v4l2_mbus_framefmt *format) +{ + struct v4l2_mbus_framefmt *src_fmt; + struct v4l2_rect *compose; + const struct ope_fmt *fmt; + + src_fmt = v4l2_subdev_state_get_format(state, OPE_PROC_PAD_SOURCE); + compose = v4l2_subdev_state_get_compose(state, OPE_PROC_PAD_SOURCE); + + fmt = ope_fmt_from_mbus_code(ope_output_fmts, ARRAY_SIZE(ope_output_fmts), format->code); + src_fmt->code = fmt ? fmt->mbus_code : MEDIA_BUS_FMT_YUYV8_1_5X8; + + ope_proc_adjust_src_compose(state, compose); + + src_fmt->width = compose->width; + src_fmt->height = compose->height; + src_fmt->field = V4L2_FIELD_NONE; + src_fmt->colorspace = V4L2_COLORSPACE_SRGB; + *format = *src_fmt; +} + +static void ope_proc_set_src_compose(struct v4l2_subdev_state *state, struct v4l2_rect *r) +{ + struct v4l2_rect *compose = v4l2_subdev_state_get_compose(state, OPE_PROC_PAD_SOURCE); + + *compose = *r; + ope_proc_adjust_src_compose(state, compose); + *r = *compose; + + /* Propagate to out format */ + ope_proc_set_src_fmt(state, v4l2_subdev_state_get_format(state, OPE_PROC_PAD_SOURCE)); +} + +static void ope_proc_set_sink_crop(struct v4l2_subdev_state *state, struct v4l2_rect *r) +{ + struct v4l2_rect *crop; + + crop = v4l2_subdev_state_get_crop(state, OPE_PROC_PAD_SINK_IN); + + *crop = *r; + ope_sd_adjust_crop(crop, v4l2_subdev_state_get_format(state, OPE_PROC_PAD_SINK_IN)); + *r = *crop; + + /* Propagate to out format */ + ope_proc_set_src_compose(state, v4l2_subdev_state_get_compose(state, OPE_PROC_PAD_SOURCE)); +} + +static void ope_proc_set_sink_fmt(struct v4l2_subdev_state *state, + struct v4l2_mbus_framefmt *format) +{ + struct v4l2_mbus_framefmt *sink_fmt; + const struct ope_fmt *fmt; + struct v4l2_rect *crop; + + sink_fmt = v4l2_subdev_state_get_format(state, OPE_PROC_PAD_SINK_IN); + crop = v4l2_subdev_state_get_crop(state, OPE_PROC_PAD_SINK_IN); + + fmt = ope_fmt_from_mbus_code(ope_input_fmts, ARRAY_SIZE(ope_input_fmts), format->code); + sink_fmt->code = fmt ? fmt->mbus_code : ope_input_fmts[0].mbus_code; + + sink_fmt->width = clamp(format->width, (u32)OPE_MIN_W, (u32)OPE_MAX_W); + sink_fmt->height = clamp(format->height, (u32)OPE_MIN_H, (u32)OPE_MAX_H); + sink_fmt->field = V4L2_FIELD_NONE; + sink_fmt->colorspace = V4L2_COLORSPACE_RAW; + *format = *sink_fmt; + + /* Propagate to in crop */ + ope_proc_set_sink_crop(state, crop); +} + +static int ope_proc_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + struct v4l2_mbus_framefmt fmt = { + .width = OPE_MIN_W, + .height = OPE_MIN_H, + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + }; + + /* Params sink: fixed format, width carries the payload size in bytes */ + *v4l2_subdev_state_get_format(state, OPE_PROC_PAD_SINK_PAR) = + (struct v4l2_mbus_framefmt){ + .code = MEDIA_BUS_FMT_FIXED, + .width = v4l2_isp_buffer_size(CAMSS_PARAMS_OPE_MAX_PAYLOAD), + .height = 1, + .field = V4L2_FIELD_NONE, + .colorspace = V4L2_COLORSPACE_DEFAULT, + }; + + /* Initialise source compose default before cascade */ + *v4l2_subdev_state_get_compose(state, OPE_PROC_PAD_SOURCE) = + (struct v4l2_rect){ 0, 0, OPE_MIN_W, OPE_MIN_H }; + v4l2_subdev_state_get_format(state, OPE_PROC_PAD_SOURCE)->code = + MEDIA_BUS_FMT_YUYV8_1_5X8; + + /* Drive the full cascade from sink-in fmt */ + ope_proc_set_sink_fmt(state, &fmt); + + return 0; +} + +static bool ope_state_is_busy(struct v4l2_subdev *sd, struct v4l2_subdev_state *state) +{ + struct ope_dev *ope = container_of(sd->v4l2_dev, struct ope_dev, v4l2_dev); + struct ope_ctx *ctx; + bool busy = false; + + if (state != sd->active_state) + return false; + + scoped_guard(spinlock, &ope->ctx_lock) + list_for_each_entry(ctx, &ope->ctx_list, list) + busy |= ctx->started; + + return busy; +} + +static int ope_proc_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *fmt) +{ + if (fmt->pad == OPE_PROC_PAD_SINK_PAR) + return v4l2_subdev_get_fmt(sd, state, fmt); + + if (ope_state_is_busy(sd, state)) + return -EBUSY; + + if (fmt->pad == OPE_PROC_PAD_SINK_IN) { + ope_proc_set_sink_fmt(state, &fmt->format); + return 0; + } + + ope_proc_set_src_fmt(state, &fmt->format); + + return 0; +} + +static int ope_proc_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_mbus_code_enum *code) +{ + const struct ope_fmt *fmts; + unsigned int nfmts; + unsigned int n = 0; + + if (code->pad == OPE_PROC_PAD_SINK_PAR) { + if (code->index) + return -EINVAL; + code->code = MEDIA_BUS_FMT_FIXED; + return 0; + } + + if (code->pad == OPE_PROC_PAD_SOURCE) { + fmts = ope_output_fmts; + nfmts = ARRAY_SIZE(ope_output_fmts); + } else { + fmts = ope_input_fmts; + nfmts = ARRAY_SIZE(ope_input_fmts); + } + + for (unsigned int i = 0; i < nfmts; i++) { + u32 mc = fmts[i].mbus_code; + bool seen = false; + + for (unsigned int j = 0; j < i; j++) { + if (fmts[j].mbus_code == mc) { + seen = true; + break; + } + } + if (!seen && n++ == code->index) { + code->code = mc; + return 0; + } + } + + return -EINVAL; +} + +static int ope_proc_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + if (sel->pad == OPE_PROC_PAD_SINK_IN) { + const struct v4l2_mbus_framefmt *sink_fmt = + v4l2_subdev_state_get_format(state, OPE_PROC_PAD_SINK_IN); + + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + sel->r = *v4l2_subdev_state_get_crop(state, OPE_PROC_PAD_SINK_IN); + return 0; + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + sel->r = (struct v4l2_rect){ 0, 0, sink_fmt->width, sink_fmt->height }; + return 0; + default: + return -EINVAL; + } + } + + if (sel->pad == OPE_PROC_PAD_SOURCE) { + const struct v4l2_rect *crop = + v4l2_subdev_state_get_crop(state, OPE_PROC_PAD_SINK_IN); + + switch (sel->target) { + case V4L2_SEL_TGT_COMPOSE: + sel->r = *v4l2_subdev_state_get_compose(state, OPE_PROC_PAD_SOURCE); + return 0; + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + sel->r = *crop; + return 0; + default: + return -EINVAL; + } + } + + return -EINVAL; +} + +static int ope_proc_set_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + if (ope_state_is_busy(sd, state)) + return -EBUSY; + + if (sel->pad == OPE_PROC_PAD_SINK_IN) { + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + ope_proc_set_sink_crop(state, &sel->r); + return 0; + } + + if (sel->pad == OPE_PROC_PAD_SOURCE) { + if (sel->target != V4L2_SEL_TGT_COMPOSE) + return -EINVAL; + ope_proc_set_src_compose(state, &sel->r); + return 0; + } + + return -EINVAL; +} + +static const struct v4l2_subdev_pad_ops ope_proc_pad_ops = { + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = ope_proc_set_fmt, + .enum_mbus_code = ope_proc_enum_mbus_code, + .get_selection = ope_proc_get_selection, + .set_selection = ope_proc_set_selection, +}; + +static const struct v4l2_subdev_internal_ops ope_proc_internal_ops = { + .init_state = ope_proc_init_state, +}; + +static const struct v4l2_subdev_ops ope_proc_ops = { + .pad = &ope_proc_pad_ops, +}; + +/* -------- disp subdev ops -------- */ + +static int ope_disp_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *pad_fmt; + u32 code = fmt->format.code; + + /* The disp subdev is pass-through: the source pad always mirrors the + * sink pad, so source format is read-only and derived from the sink. + */ + if (fmt->pad == OPE_DISP_PAD_SOURCE) + return v4l2_subdev_get_fmt(sd, state, fmt); + + if (ope_state_is_busy(sd, state)) + return -EBUSY; + + fmt->format.code = MEDIA_BUS_FMT_YUYV8_1_5X8; + for (unsigned int i = 0; i < ARRAY_SIZE(ope_output_fmts); i++) { + if (ope_output_fmts[i].mbus_code == code) { + fmt->format.code = code; + break; + } + } + + v4l_bound_align_image(&fmt->format.width, OPE_MIN_W, OPE_MAX_W, 0, + &fmt->format.height, OPE_MIN_H, OPE_MAX_H, 0, 0); + fmt->format.field = V4L2_FIELD_NONE; + fmt->format.colorspace = V4L2_COLORSPACE_SRGB; + + pad_fmt = v4l2_subdev_state_get_format(state, fmt->pad); + *pad_fmt = fmt->format; + + /* Propagate to source */ + *v4l2_subdev_state_get_format(state, OPE_DISP_PAD_SOURCE) = fmt->format; + + return 0; +} + +static int ope_disp_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + struct v4l2_mbus_framefmt def = { + .width = OPE_MIN_W, + .height = OPE_MIN_H, + .code = MEDIA_BUS_FMT_YUYV8_1_5X8, + .field = V4L2_FIELD_NONE, + .colorspace = V4L2_COLORSPACE_SRGB, + }; + + *v4l2_subdev_state_get_format(state, OPE_DISP_PAD_SINK) = def; + *v4l2_subdev_state_get_format(state, OPE_DISP_PAD_SOURCE) = def; + return 0; +} + +static const struct v4l2_subdev_pad_ops ope_disp_pad_ops = { + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = ope_disp_set_fmt, + .link_validate = v4l2_subdev_link_validate_default, +}; + +static const struct media_entity_operations ope_disp_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static const struct v4l2_subdev_internal_ops ope_disp_internal_ops = { + .init_state = ope_disp_init_state, +}; + +static const struct v4l2_subdev_ops ope_disp_ops = { + .pad = &ope_disp_pad_ops, +}; + +/* -------- disp-output video ops -------- */ + +static int ope_disp_output_link_validate(struct media_link *link) +{ + struct video_device *vdev = media_entity_to_video_device(link->sink->entity); + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(link->source->entity); + struct ope_dev *ope = container_of(vdev->v4l2_dev, struct ope_dev, v4l2_dev); + struct ope_ctx *ctx = ope->shared_ctx; + struct v4l2_subdev_state *sd_state; + struct v4l2_subdev_format sd_fmt = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .pad = link->source->index, + }; + int ret; + + if (!ctx) + return 0; + + sd_state = v4l2_subdev_lock_and_get_active_state(sd); + ret = v4l2_subdev_call(sd, pad, get_fmt, sd_state, &sd_fmt); + v4l2_subdev_unlock_state(sd_state); + if (ret) + return ret; + + if (ctx->fmt_out.fmt->mbus_code != sd_fmt.format.code) { + dev_dbg(ctx->ope->dev, "link validate: mbus 0x%04x incompatible with %p4cc\n", + sd_fmt.format.code, &ctx->fmt_out.fmt->fourcc); + return -EPIPE; + } + + if (sd_fmt.format.width > ctx->fmt_out.width || + sd_fmt.format.height > ctx->fmt_out.height) { + dev_dbg(ctx->ope->dev, + "link validate: compose %ux%u exceeds output buffer %ux%u\n", + sd_fmt.format.width, sd_fmt.format.height, + ctx->fmt_out.width, ctx->fmt_out.height); + return -EPIPE; + } + + /* Check compose rect (including offset) fits within output buffer */ + { + struct v4l2_subdev *proc_sd = + camss_isp_pipeline_get_subdev(ctx->ope->pipeline, + OPE_ENTITY_PROC); + struct v4l2_subdev_state *proc_state = + v4l2_subdev_lock_and_get_active_state(proc_sd); + const struct v4l2_rect *compose = + v4l2_subdev_state_get_compose(proc_state, + OPE_PROC_PAD_SOURCE); + + if (compose->left + compose->width > ctx->fmt_out.width || + compose->top + compose->height > ctx->fmt_out.height) { + dev_dbg(ctx->ope->dev, + "link: compose %ux%u+%u+%u overflows output buffer %ux%u\n", + compose->width, compose->height, + compose->left, compose->top, + ctx->fmt_out.width, ctx->fmt_out.height); + v4l2_subdev_unlock_state(proc_state); + return -EPIPE; + } + v4l2_subdev_unlock_state(proc_state); + } + + return 0; +} + +static const struct media_entity_operations ope_disp_output_entity_ops = { + .link_validate = ope_disp_output_link_validate, +}; + +static int ope_input_link_validate(struct media_link *link) +{ + struct video_device *vdev = media_entity_to_video_device(link->source->entity); + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(link->sink->entity); + struct ope_dev *ope = container_of(vdev->v4l2_dev, struct ope_dev, v4l2_dev); + struct ope_ctx *ctx = ope->shared_ctx; + struct v4l2_subdev_state *sd_state; + struct v4l2_subdev_format sd_fmt = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .pad = link->sink->index, + }; + int ret; + + if (!ctx) + return 0; + + sd_state = v4l2_subdev_lock_and_get_active_state(sd); + ret = v4l2_subdev_call(sd, pad, get_fmt, sd_state, &sd_fmt); + v4l2_subdev_unlock_state(sd_state); + if (ret) + return ret; + + if (ctx->fmt_in.fmt->mbus_code != sd_fmt.format.code || + ctx->fmt_in.width != sd_fmt.format.width || + ctx->fmt_in.height != sd_fmt.format.height) { + dev_dbg(ctx->ope->dev, + "link validate: input %dx%d/0x%04x != pad %dx%d/0x%04x\n", + ctx->fmt_in.width, ctx->fmt_in.height, + ctx->fmt_in.fmt->mbus_code, + sd_fmt.format.width, sd_fmt.format.height, + sd_fmt.format.code); + return -EPIPE; + } + + return 0; +} + +static const struct media_entity_operations ope_input_entity_ops = { + .link_validate = ope_input_link_validate, +}; + +static const struct v4l2_ioctl_ops ope_video_ioctl_ops = { + .vidioc_querycap = ope_querycap, + .vidioc_enum_fmt_vid_out = ope_enum_fmt_vid_out, + .vidioc_g_fmt_vid_out_mplane = ope_g_fmt_vid_out, + .vidioc_try_fmt_vid_out_mplane = ope_try_fmt_vid_out, + .vidioc_s_fmt_vid_out_mplane = ope_s_fmt_vid_out, + .vidioc_enum_fmt_vid_cap = ope_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap_mplane = ope_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap_mplane = ope_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap_mplane = ope_s_fmt_vid_cap, + .vidioc_enum_framesizes = ope_enum_framesizes, + .vidioc_g_parm = ope_g_parm, + .vidioc_s_parm = ope_s_parm, + .vidioc_reqbufs = ope_reqbufs, + .vidioc_querybuf = ope_querybuf, + .vidioc_qbuf = ope_qbuf, + .vidioc_dqbuf = ope_dqbuf, + .vidioc_prepare_buf = ope_prepare_buf, + .vidioc_create_bufs = ope_create_bufs, + .vidioc_expbuf = ope_expbuf, + .vidioc_streamon = ope_streamon, + .vidioc_streamoff = ope_streamoff, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static const struct v4l2_ioctl_ops ope_meta_ioctl_ops = { + .vidioc_querycap = ope_querycap, + .vidioc_enum_fmt_meta_out = ope_enum_fmt_meta_out, + .vidioc_g_fmt_meta_out = ope_g_fmt_meta, + .vidioc_s_fmt_meta_out = ope_g_fmt_meta, + .vidioc_try_fmt_meta_out = ope_g_fmt_meta, + .vidioc_reqbufs = ope_reqbufs, + .vidioc_querybuf = ope_querybuf, + .vidioc_qbuf = ope_qbuf, + .vidioc_dqbuf = ope_dqbuf, + .vidioc_prepare_buf = ope_prepare_buf, + .vidioc_create_bufs = ope_create_bufs, + .vidioc_expbuf = ope_expbuf, + .vidioc_streamon = ope_streamon, + .vidioc_streamoff = ope_streamoff, +}; + +/* -------- File/Context ops -------- */ + +static struct ope_ctx *ope_ctx_create(struct ope_dev *ope) +{ + struct v4l2_pix_format_mplane pix_in = { .pixelformat = ope_input_fmts[0].fourcc }; + struct v4l2_pix_format_mplane pix_out = { .pixelformat = ope_output_fmts[0].fourcc }; + struct ope_ctx *ctx; + unsigned int i; + int ret; + + lockdep_assert_held(&ope->mutex); + + ctx = kvzalloc_obj(*ctx); + if (!ctx) + return ERR_PTR(-ENOMEM); + + ctx->ope = ope; + + mutex_init(&ctx->vbq_lock); + + ctx->params_buf = kvzalloc(v4l2_isp_buffer_size(CAMSS_PARAMS_OPE_MAX_PAYLOAD), + GFP_KERNEL); + if (!ctx->params_buf) { + ret = -ENOMEM; + goto err_destroy_lock; + } + + ctx->config = ope_default_config; + + ctx->fmt_in.fmt = ope_fmt_try(ope, false, &pix_in); + ctx->fmt_in.width = pix_in.width; + ctx->fmt_in.height = pix_in.height; + ctx->fmt_in.bytesperline = pix_in.plane_fmt[0].bytesperline; + ctx->fmt_in.sizeimage = pix_in.plane_fmt[0].sizeimage; + ctx->fmt_in.colorspace = pix_in.colorspace; + ctx->fmt_in.xfer_func = pix_in.xfer_func; + ctx->fmt_in.ycbcr_enc = pix_in.ycbcr_enc; + ctx->fmt_in.quantization = pix_in.quantization; + ctx->fmt_in.timeperframe.numerator = 1; + ctx->fmt_in.timeperframe.denominator = DEFAULT_FRAMERATE; + + ctx->fmt_out.fmt = ope_fmt_try(ope, true, &pix_out); + ctx->fmt_out.width = pix_out.width; + ctx->fmt_out.height = pix_out.height; + ctx->fmt_out.bytesperline = pix_out.plane_fmt[0].bytesperline; + ctx->fmt_out.sizeimage = pix_out.plane_fmt[0].sizeimage; + ctx->fmt_out.colorspace = pix_out.colorspace; + ctx->fmt_out.xfer_func = pix_out.xfer_func; + ctx->fmt_out.ycbcr_enc = pix_out.ycbcr_enc; + ctx->fmt_out.quantization = pix_out.quantization; + + for (i = 0; i < OPE_QUEUE_COUNT; i++) { + INIT_LIST_HEAD(&ctx->queues[i].rdy_queue); + spin_lock_init(&ctx->queues[i].rdy_spinlock); + ret = ope_init_vq(ctx, i); + if (ret) + goto err_release_vq; + } + + INIT_LIST_HEAD(&ctx->list); + + scoped_guard(spinlock, &ope->ctx_lock) + list_add(&ctx->list, &ope->ctx_list); + + ope->shared_ctx = ctx; + + return ctx; + +err_release_vq: + while (i--) + ope_deinit_vq(ctx, i); + kvfree(ctx->params_buf); +err_destroy_lock: + mutex_destroy(&ctx->vbq_lock); + kvfree(ctx); + return ERR_PTR(ret); +} + +static void ope_queues_release(struct ope_ctx *ctx, struct v4l2_fh *fh) +{ + bool owned = false; + + for (unsigned int i = 0; i < OPE_QUEUE_COUNT; i++) + owned |= (ctx->queues[i].vq.owner == fh); + + if (!owned) + return; + + ope_sched_cancel(ctx); + + for (unsigned int i = 0; i < OPE_QUEUE_COUNT; i++) { + struct vb2_queue *vq = &ctx->queues[i].vq; + + if (vq->owner != fh) + continue; + + vb2_queue_release(vq); + vq->owner = NULL; + } + + ope_sched_resume(ctx); +} + +static void ope_ctx_destroy(struct ope_ctx *ctx) +{ + ctx->started = false; + + ope_sched_cancel(ctx); + + for (unsigned int i = 0; i < OPE_QUEUE_COUNT; i++) + ope_deinit_vq(ctx, i); + + ope_sched_resume(ctx); + + /* Do not leave the LUT cache pointing at a context about to be freed */ + ope_glut_cache_invalidate(ctx->ope); + + kvfree(ctx->params_buf); + mutex_destroy(&ctx->vbq_lock); + kvfree(ctx); +} + +static int ope_open(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct ope_dev *ope = container_of(vdev->v4l2_dev, struct ope_dev, v4l2_dev); + struct v4l2_fh *fh; + int ret = 0; + + fh = kzalloc_obj(*fh); + if (!fh) + return -ENOMEM; + + if (mutex_lock_interruptible(&ope->mutex)) { + kfree(fh); + return -ERESTARTSYS; + } + + v4l2_fh_init(fh, vdev); + v4l2_fh_add(fh, file); + + /* + * For now, only a single shared context is supported, + * until media multi-context support is available. + */ + if (!ope->shared_ctx) { + struct ope_ctx *ctx = ope_ctx_create(ope); + + if (IS_ERR(ctx)) { + ret = PTR_ERR(ctx); + goto err_fh_del; + } + } + + ope->open_count++; + mutex_unlock(&ope->mutex); + + return 0; + +err_fh_del: + v4l2_fh_del(fh, file); + v4l2_fh_exit(fh); + mutex_unlock(&ope->mutex); + kfree(fh); + return ret; +} + +static int ope_release(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_fh *fh = file_to_v4l2_fh(file); + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct ope_dev *ope = ctx->ope; + + scoped_guard(mutex, vdev->lock) + ope_queues_release(ctx, fh); + + v4l2_fh_del(fh, file); + v4l2_fh_exit(fh); + kfree(fh); + + scoped_guard(mutex, &ope->mutex) { + if (--ope->open_count != 0) + return 0; + ope->shared_ctx = NULL; + scoped_guard(spinlock, &ope->ctx_lock) + list_del(&ctx->list); + } + + ope_ctx_destroy(ctx); + + return 0; +} + +static __poll_t ope_poll(struct file *file, poll_table *wait) +{ + unsigned int idx = ope_queue_idx_from_file(file); + struct ope_ctx *ctx = ope_ctx_from_file(file); + struct v4l2_fh *fh = file_to_v4l2_fh(file); + struct vb2_queue *vq; + unsigned long flags; + __poll_t rc = 0; + + if (idx >= OPE_QUEUE_COUNT) + return EPOLLERR; + + vq = &ctx->queues[idx].vq; + + poll_wait(file, &vq->done_wq, wait); + poll_wait(file, &fh->wait, wait); + + spin_lock_irqsave(&vq->done_lock, flags); + if (!list_empty(&vq->done_list)) { + if (V4L2_TYPE_IS_OUTPUT(vq->type)) + rc |= EPOLLOUT | EPOLLWRNORM; + else + rc |= EPOLLIN | EPOLLRDNORM; + } + spin_unlock_irqrestore(&vq->done_lock, flags); + + if (v4l2_event_pending(fh)) + rc |= EPOLLPRI; + + return rc; +} + +static int ope_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned int idx = ope_queue_idx_from_file(file); + struct ope_ctx *ctx = ope_ctx_from_file(file); + + if (idx >= OPE_QUEUE_COUNT) + return -EINVAL; + + return vb2_mmap(&ctx->queues[idx].vq, vma); +} + +static const struct v4l2_file_operations ope_fops = { + .owner = THIS_MODULE, + .open = ope_open, + .release = ope_release, + .poll = ope_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = ope_mmap, +}; + +/* Pipeline descriptor */ +static const struct camss_isp_entity_desc ope_entity_descs[] = { + [OPE_ENTITY_FRAME_IN] = { + .name = "ope_input", + .obj_type = MEDIA_ENTITY_TYPE_VIDEO_DEVICE, + .function = MEDIA_ENT_F_IO_V4L, + .vdev.caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING, + .vdev.drvdata = (void *)(uintptr_t)OPE_QUEUE_FRAME_IN, + .vdev.fops = &ope_fops, + .vdev.ioctl_ops = &ope_video_ioctl_ops, + .vdev.entity_ops = &ope_input_entity_ops, + .pads = (const struct camss_isp_pad_desc[]) { + { MEDIA_PAD_FL_SOURCE, OPE_ENTITY_PROC, OPE_PROC_PAD_SINK_IN, 0 }, + { } + }, + }, + [OPE_ENTITY_DISP_OUT] = { + .name = "ope_disp_output", + .obj_type = MEDIA_ENTITY_TYPE_VIDEO_DEVICE, + .function = MEDIA_ENT_F_IO_V4L, + .vdev.caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING, + .vdev.drvdata = (void *)(uintptr_t)OPE_QUEUE_DISP_OUT, + .vdev.fops = &ope_fops, + .vdev.ioctl_ops = &ope_video_ioctl_ops, + .vdev.entity_ops = &ope_disp_output_entity_ops, + .pads = (const struct camss_isp_pad_desc[]) { + { MEDIA_PAD_FL_SINK, OPE_ENTITY_DISP, OPE_DISP_PAD_SOURCE, 0 }, + { } + }, + }, + [OPE_ENTITY_PARAMS] = { + .name = "ope_params", + .obj_type = MEDIA_ENTITY_TYPE_VIDEO_DEVICE, + .function = MEDIA_ENT_F_IO_V4L, + .vdev.caps = V4L2_CAP_META_OUTPUT | V4L2_CAP_STREAMING, + .vdev.drvdata = (void *)(uintptr_t)OPE_QUEUE_PARAMS, + .vdev.fops = &ope_fops, + .vdev.ioctl_ops = &ope_meta_ioctl_ops, + .pads = (const struct camss_isp_pad_desc[]) { + { MEDIA_PAD_FL_SOURCE, OPE_ENTITY_PROC, OPE_PROC_PAD_SINK_PAR, 0 }, + { } + }, + }, + [OPE_ENTITY_PROC] = { + .name = "ope_proc", + .obj_type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV, + .function = MEDIA_ENT_F_PROC_VIDEO_ISP, + .subdev.ops = &ope_proc_ops, + .subdev.internal_ops = &ope_proc_internal_ops, + .pads = (const struct camss_isp_pad_desc[]) { + { MEDIA_PAD_FL_SINK, OPE_ENTITY_FRAME_IN, 0, 0 }, + { MEDIA_PAD_FL_SINK, OPE_ENTITY_PARAMS, 0, 0 }, + { MEDIA_PAD_FL_SOURCE, OPE_ENTITY_DISP, OPE_DISP_PAD_SINK, + MEDIA_LNK_FL_ENABLED }, + { } + }, + }, + [OPE_ENTITY_DISP] = { + .name = "ope_disp", + .obj_type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV, + .function = MEDIA_ENT_F_PROC_VIDEO_SCALER, + .subdev.ops = &ope_disp_ops, + .subdev.internal_ops = &ope_disp_internal_ops, + .subdev.entity_ops = &ope_disp_entity_ops, + .pads = (const struct camss_isp_pad_desc[]) { + { MEDIA_PAD_FL_SINK, OPE_ENTITY_PROC, OPE_PROC_PAD_SOURCE, 0 }, + { MEDIA_PAD_FL_SOURCE, OPE_ENTITY_DISP_OUT, 0, 0 }, + { } + }, + }, +}; + +static void ope_v4l2_dev_release(struct v4l2_device *v4l2_dev) +{ + struct ope_dev *ope = container_of(v4l2_dev, struct ope_dev, v4l2_dev); + + /* Reached once the V4L2 core has released every video and subdev node */ + camss_isp_pipeline_free(ope->pipeline); + media_device_cleanup(&ope->mdev); + mutex_destroy(&ope->mutex); + kfree(ope); +} + +static int ope_v4l2_register(struct ope_dev *ope) +{ + int ret; + + ope->mdev.dev = ope->dev; + strscpy(ope->mdev.model, OPE_NAME, sizeof(ope->mdev.model)); + ope->mdev.hw_revision = ope->hw_version; + media_device_init(&ope->mdev); + ope->v4l2_dev.mdev = &ope->mdev; + ope->v4l2_dev.release = ope_v4l2_dev_release; + + ret = v4l2_device_register(ope->dev, &ope->v4l2_dev); + if (ret) { + /* No v4l2_device reference exists yet, so release @ope directly */ + ope_v4l2_dev_release(&ope->v4l2_dev); + return ret; + } + + ope->pipeline = camss_isp_pipeline_alloc(OPE_ENTITY_COUNT); + if (IS_ERR(ope->pipeline)) { + ret = PTR_ERR(ope->pipeline); + ope->pipeline = NULL; + goto err_v4l2; + } + + ret = camss_isp_pipeline_register(ope->pipeline, &ope->v4l2_dev, ope_entity_descs, + ARRAY_SIZE(ope_entity_descs)); + if (ret) + goto err_v4l2; + + /* Expose the graph to userspace only once every entity and link exists */ + ret = media_device_register(&ope->mdev); + if (ret) + goto err_pipeline; + + ope->pipeline->drv_priv = ope; + return 0; + +err_pipeline: + camss_isp_pipeline_unregister(ope->pipeline); +err_v4l2: + /* Rely on the v4l2_device release callback to free @ope */ + v4l2_device_unregister(&ope->v4l2_dev); + v4l2_device_put(&ope->v4l2_dev); + return ret; +} + +static void ope_unregister(struct ope_dev *ope) +{ + struct ope_ctx *ctx; + + disable_work_sync(&ope->run_work); + + scoped_guard(spinlock_irqsave, &ope->sched_lock) + ctx = ope->curr_ctx; + + if (ctx) { + if (ope_hw_reset_poll(ope)) + dev_err(ope->dev, "reset timeout on unbind\n"); + ope_job_finish(ctx, VB2_BUF_STATE_ERROR); + } + + if (ope->pipeline) + camss_isp_pipeline_unregister(ope->pipeline); + + media_device_unregister(&ope->mdev); + + /* Clears v4l2_dev.dev, after which no new job can reach the hardware */ + v4l2_device_unregister(&ope->v4l2_dev); + + /* + * Drops the reference this driver holds. @ope may be freed here, or + * later by the V4L2 core if userspace still has a node open. + * media_device_cleanup() is deferred to ope_v4l2_dev_release(). + */ + v4l2_device_put(&ope->v4l2_dev); +} + +static void ope_dump_pipeline(struct ope_dev *ope) +{ + static const struct { + const char *name; + u32 base; + } blocks[] = { + { "wb_gain", OPE_PP_WB_GAIN_BASE }, + { "demo", OPE_PP_DEMO_BASE }, + { "cc", OPE_PP_CC_BASE }, + { "glut", OPE_PP_GLUT_BASE }, + { "chroma_enhan", OPE_PP_CHROMA_ENHAN_BASE }, + { "ds_c_pre", OPE_PP_DOWNSCALE_MN_DS_C_PRE_BASE }, + { "ds_y_disp", OPE_PP_DOWNSCALE_MN_DS_Y_DISP_BASE }, + { "ds_c_disp", OPE_PP_DOWNSCALE_MN_DS_C_DISP_BASE }, + { "crop_y_disp", OPE_PP_CROP_RND_CLAMP_Y_DISP_BASE }, + { "crop_c_disp", OPE_PP_CROP_RND_CLAMP_C_DISP_BASE }, + }; + + for (unsigned int i = 0; i < ARRAY_SIZE(blocks); i++) { + u32 version = ope_read_pp(ope, OPE_PP_HW_VERSION(blocks[i].base)); + + dev_dbg(ope->dev, "pipeline %-13s HW version %u.%u.%u\n", + blocks[i].name, + OPE_HW_VERSION_GEN(version), + OPE_HW_VERSION_REV(version), + OPE_HW_VERSION_STEP(version)); + } +} + +static int ope_soft_reset(struct ope_dev *ope) +{ + u32 version; + int ret; + + ret = pm_runtime_resume_and_get(ope->dev); + if (ret) + return dev_err_probe(ope->dev, ret, "resume failed\n"); + + version = ope_read(ope, OPE_TOP_HW_VERSION); + ope->hw_version = version; + dev_dbg(ope->dev, "HW version %u.%u.%u\n", + OPE_HW_VERSION_GEN(version), + OPE_HW_VERSION_REV(version), + OPE_HW_VERSION_STEP(version)); + + ope_dump_pipeline(ope); + + ret = ope_hw_reset_poll(ope); + if (ret) + dev_err(ope->dev, "Reset timeout\n"); + + pm_runtime_put_sync(ope->dev); + + return ret; +} + +static const char * const ope_pds[] = { "camss" }; +static const char * const ope_opp_pds[] = { "cx" }; + +static const struct dev_pm_domain_attach_data ope_pd_data = { + .pd_names = ope_pds, + .num_pd_names = ARRAY_SIZE(ope_pds), +}; + +static const struct dev_pm_domain_attach_data ope_opp_pd_data = { + .pd_names = ope_opp_pds, + .num_pd_names = ARRAY_SIZE(ope_opp_pds), + .pd_flags = PD_FLAG_DEV_LINK_ON | PD_FLAG_REQUIRED_OPP, +}; + +static int ope_init_power(struct ope_dev *ope) +{ + struct device *dev = ope->dev; + struct dev_pm_domain_list *pmdomains; + struct dev_pm_domain_list *opp_pmdomains; + struct clk *axi_clk; + int ret; + + ope->icc_data = devm_of_icc_get(dev, "data"); + if (IS_ERR(ope->icc_data)) + return dev_err_probe(dev, PTR_ERR(ope->icc_data), + "failed to get interconnect data path\n"); + + ope->icc_config = devm_of_icc_get(dev, "config"); + if (IS_ERR(ope->icc_config)) + return dev_err_probe(dev, PTR_ERR(ope->icc_config), + "failed to get interconnect config path\n"); + + ret = devm_pm_domain_attach_list(dev, &ope_pd_data, &pmdomains); + if (ret < 0 && ret != -EEXIST) + return dev_err_probe(dev, ret, "failed to attach power domains\n"); + + ret = devm_pm_domain_attach_list(dev, &ope_opp_pd_data, &opp_pmdomains); + if (ret < 0 && ret != -EEXIST) + return dev_err_probe(dev, ret, "failed to attach OPP power domain\n"); + + axi_clk = devm_clk_get_optional(dev, "axi"); + if (IS_ERR(axi_clk)) + return dev_err_probe(dev, PTR_ERR(axi_clk), "failed to get AXI clock\n"); + + ret = clk_set_rate(axi_clk, OPE_AXI_CLK_RATE); + if (ret) + return dev_err_probe(dev, ret, "failed to set AXI clock rate\n"); + + ret = devm_pm_opp_set_clkname(dev, "core"); + if (ret) + return ret; + + ret = devm_pm_opp_of_add_table(dev); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "invalid OPP table\n"); + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + + ret = devm_pm_clk_create(dev); + if (ret) + return ret; + + ret = of_pm_clk_add_clks(dev); + if (ret < 0) + return ret; + + return 0; +} + +static int ope_init_mmio(struct ope_dev *ope) +{ + struct platform_device *pdev = to_platform_device(ope->dev); + + ope->base = devm_platform_ioremap_resource_byname(pdev, "top"); + if (IS_ERR(ope->base)) + return PTR_ERR(ope->base); + + ope->base_rd = devm_platform_ioremap_resource_byname(pdev, "bus_read"); + if (IS_ERR(ope->base_rd)) + return PTR_ERR(ope->base_rd); + + ope->base_wr = devm_platform_ioremap_resource_byname(pdev, "bus_write"); + if (IS_ERR(ope->base_wr)) + return PTR_ERR(ope->base_wr); + + ope->base_pp = devm_platform_ioremap_resource_byname(pdev, "pipeline"); + if (IS_ERR(ope->base_pp)) + return PTR_ERR(ope->base_pp); + + return 0; +} + +static int ope_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct ope_dev *ope; + int ret, irq; + + /* OPE lifetime is refcounted through the embedded v4l2_device */ + ope = kzalloc_obj(*ope); + if (!ope) + return -ENOMEM; + + ope->dev = dev; + init_completion(&ope->reset_complete); + mutex_init(&ope->mutex); + INIT_LIST_HEAD(&ope->ctx_list); + spin_lock_init(&ope->ctx_lock); + spin_lock_init(&ope->sched_lock); + INIT_WORK(&ope->run_work, ope_run_work); + + ret = dma_set_mask(dev, DMA_BIT_MASK(32)); + if (ret) { + ret = dev_err_probe(dev, ret, "Failed to set DMA mask\n"); + goto err_free; + } + + ret = ope_init_power(ope); + if (ret) { + ret = dev_err_probe(dev, ret, "Power init failed\n"); + goto err_free; + } + + ret = ope_init_mmio(ope); + if (ret) { + ret = dev_err_probe(dev, ret, "MMIO init failed\n"); + goto err_free; + } + + ret = ope_soft_reset(ope); + if (ret) + goto err_free; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + ret = dev_err_probe(dev, irq, "Unable to get IRQ\n"); + goto err_free; + } + + ope->irq = irq; + + ret = devm_request_irq(dev, ope->irq, ope_irq, IRQF_NO_AUTOEN, + "camss-ope", ope); + if (ret < 0) { + ret = dev_err_probe(dev, ret, "Requesting IRQ failed\n"); + goto err_free; + } + + /* ope ownership is transferred to ope_v4l2_register(), even on failure */ + ret = ope_v4l2_register(ope); + if (ret) + return dev_err_probe(dev, ret, "V4L2 registration failed\n"); + + platform_set_drvdata(pdev, ope); + + /* Everything @ope_irq() touches is in place, let interrupts in */ + enable_irq(ope->irq); + + return 0; + +err_free: + mutex_destroy(&ope->mutex); + kfree(ope); + return ret; +} + +static void ope_remove(struct platform_device *pdev) +{ + struct ope_dev *ope = platform_get_drvdata(pdev); + + disable_irq(ope->irq); + ope_unregister(ope); +} + +static const struct of_device_id ope_dt_ids[] = { + { .compatible = "qcom,qcm2290-camss-ope" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ope_dt_ids); + +static const struct dev_pm_ops ope_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static struct platform_driver ope_driver = { + .probe = ope_probe, + .remove = ope_remove, + .driver = { + .name = OPE_NAME, + .of_match_table = ope_dt_ids, + .pm = pm_ptr(&ope_pm_ops), + }, +}; + +module_platform_driver(ope_driver); + +MODULE_DESCRIPTION("CAMSS Offline Processing Engine"); +MODULE_AUTHOR("Loic Poulain "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/qcom/camss/ope/params.c b/drivers/media/platform/qcom/camss/ope/params.c new file mode 100644 index 0000000000000..55f9a9002e348 --- /dev/null +++ b/drivers/media/platform/qcom/camss/ope/params.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ope/params.c + * + * CAMSS ISP parameter buffer parser. + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include "params.h" + +int camss_isp_params_apply(struct device *dev, + struct vb2_buffer *vb, + struct v4l2_isp_params_buffer *scratch, + const struct v4l2_isp_params_block_type_info *type_info, + const camss_isp_params_handler_fn *handlers, + unsigned int num_handlers, + void *priv) +{ + const struct v4l2_isp_params_buffer *buf = scratch; + const void *src; + unsigned int remaining; + unsigned int offset = 0; + int ret; + + ret = v4l2_isp_params_validate_buffer_size(dev, vb, + v4l2_isp_buffer_size(CAMSS_PARAMS_OPE_MAX_PAYLOAD)); + if (ret) + return ret; + + src = vb2_plane_vaddr(vb, 0); + + if (!src) { + dev_dbg(dev, "params: buffer has no kernel mapping\n"); + return -EFAULT; + } + + /* + * The payload lives in a vmalloc'd buffer that userspace keeps mapped + * while the buffer is queued, so it must not be validated in place: + * copy it into kernel-only memory first, then work exclusively on the + * copy. See the v4l2_isp_params_validate_buffer() documentation. + */ + memcpy(scratch, src, vb2_get_plane_payload(vb, 0)); + + ret = v4l2_isp_params_validate_buffer(dev, vb, buf, type_info, num_handlers); + if (ret) + return ret; + + dev_dbg(dev, "params: version=%u data_size=%u\n", buf->version, buf->data_size); + + remaining = buf->data_size; + + while (remaining >= sizeof(struct v4l2_isp_params_block_header)) { + const union camss_isp_params_block *block = + (const union camss_isp_params_block *)&buf->data[offset]; + u16 type = block->header.type; + u32 bsize = block->header.size; + + if (type < num_handlers && handlers[type]) + handlers[type](priv, block); + else + dev_dbg(dev, "params: no handler for block type %u\n", type); + + offset += bsize; + remaining -= bsize; + } + + dev_dbg(dev, "params: buffer parsed successfully\n"); + + return 0; +} diff --git a/drivers/media/platform/qcom/camss/ope/params.h b/drivers/media/platform/qcom/camss/ope/params.h new file mode 100644 index 0000000000000..b3388b5ce2264 --- /dev/null +++ b/drivers/media/platform/qcom/camss/ope/params.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ope/params.h + * + * CAMSS ISP parameter buffer parser. + * + * Wraps the upstream v4l2_isp_params_validate_buffer() validation and adds + * a dispatch layer: after validation each block is forwarded to a + * driver-supplied handler. + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef CAMSS_PARAMS_H +#define CAMSS_PARAMS_H + +#include +#include +#include +#include + +#define CAMSS_ISP_PARAMS_FMT_INIT \ + { .fourcc = V4L2_META_FMT_QCOM_ISP_PARAMS, .depth = 8, .align = 0, .num_planes = 1 } + +#define CAMSS_ISP_PARAMS_FL_BLOCK_DIRTY (1U << V4L2_ISP_FL_DRIVER_FLAGS(0)) + +struct device; +struct vb2_buffer; +struct camss_isp_fmt; + +union camss_isp_params_block { + struct v4l2_isp_params_block_header header; + struct camss_params_wb_gain wb_gain; + struct camss_params_chroma_enhan chroma_enhan; + struct camss_params_color_correct color_correct; + struct camss_params_gamma gamma; +}; + +typedef void (*camss_isp_params_handler_fn)(void *priv, const union camss_isp_params_block *block); + +/** + * camss_isp_params_copy_block - copy one validated block into driver state + * + * @dst: destination block in the driver's shadow configuration + * @block: validated source block + * @size: size of the destination block + * + * Returns true if the payload was copied, false if only the header was. + */ +static inline bool camss_isp_params_copy_block(void *dst, + const union camss_isp_params_block *block, + size_t size) +{ + struct v4l2_isp_params_block_header *hdr = dst; + bool header_only = block->header.size == sizeof(block->header); + + if (header_only) + *hdr = block->header; + else + memcpy(dst, block, size); + + hdr->flags |= CAMSS_ISP_PARAMS_FL_BLOCK_DIRTY; + + return !header_only; +} + +/** + * camss_isp_params_apply - validate and dispatch a params buffer + * + * @dev: device for error logging + * @vb: the vb2 buffer (used for size validation) + * @scratch: kernel-only bounce buffer, at least + * v4l2_isp_buffer_size(CAMSS_PARAMS_OPE_MAX_PAYLOAD) bytes + * @type_info: per-block-type validation info, indexed by block type + * @handlers: per-block-type handlers, indexed by block type + * @num_handlers: number of entries in @type_info and @handlers + * @priv: opaque pointer forwarded to each handler + * + * Copies the buffer payload into @scratch, calls + * v4l2_isp_params_validate_buffer_size(), then + * v4l2_isp_params_validate_buffer(), then walks the validated block stream + * dispatching each block to its handler. Validation and dispatch operate + * only on @scratch, never on the userspace-visible mapping. + * + * Returns 0 on success, negative errno on validation failure. + */ +int camss_isp_params_apply(struct device *dev, + struct vb2_buffer *vb, + struct v4l2_isp_params_buffer *scratch, + const struct v4l2_isp_params_block_type_info *type_info, + const camss_isp_params_handler_fn *handlers, + unsigned int num_handlers, + void *priv); + +#endif /* CAMSS_PARAMS_H */ diff --git a/drivers/media/platform/qcom/camss/ope/pipeline.c b/drivers/media/platform/qcom/camss/ope/pipeline.c new file mode 100644 index 0000000000000..a888d5027fc78 --- /dev/null +++ b/drivers/media/platform/qcom/camss/ope/pipeline.c @@ -0,0 +1,405 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * CAMSS ISP pipeline helper — declarative MC topology builder + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +#include +#include +#include +#include +#include +#include "pipeline.h" + +/* -------- Internal helpers -------- */ + +static enum vfl_devnode_direction isp_caps_to_vfl_dir(u32 caps) +{ + if (caps & (V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE)) + return VFL_DIR_M2M; + if (caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_META_OUTPUT | V4L2_CAP_VBI_OUTPUT | V4L2_CAP_SDR_OUTPUT)) + return VFL_DIR_TX; + return VFL_DIR_RX; +} + +static unsigned int isp_count_pads(const struct camss_isp_pad_desc *pads) +{ + unsigned int n = 0; + + if (!pads) + return 0; + while (pads[n].flags) + n++; + return n; +} + +static struct media_entity *isp_pipeline_media_entity(struct camss_isp_pipeline *pipeline, + unsigned int idx) +{ + struct camss_isp_pipeline_entity *slot = &pipeline->entities[idx]; + + switch (slot->obj_type) { + case MEDIA_ENTITY_TYPE_VIDEO_DEVICE: + return &slot->vdev.entity; + case MEDIA_ENTITY_TYPE_V4L2_SUBDEV: + return &slot->subdev.entity; + default: + return &slot->entity; + } +} + +/* -------- Validation -------- */ + +static int isp_pipeline_validate(struct device *dev, + const struct camss_isp_entity_desc *descs, + unsigned int num_entities) +{ + unsigned int i, pi; + + for (i = 0; i < num_entities; i++) { + const struct camss_isp_pad_desc *pads = descs[i].pads; + unsigned int num_pads = isp_count_pads(pads); + + for (pi = 0; pi < num_pads; pi++) { + const struct camss_isp_pad_desc *pad = &pads[pi]; + const struct camss_isp_pad_desc *peer_pad; + unsigned int peer_num_pads; + int peer_ent = pad->peer_entity; + + if (peer_ent < 0) + continue; + + if ((unsigned int)peer_ent >= num_entities) { + dev_err(dev, "entity[%u].p%u: peer_entity %d out of range\n", + i, pi, peer_ent); + return -EINVAL; + } + + peer_num_pads = isp_count_pads(descs[peer_ent].pads); + if (pad->peer_pad >= peer_num_pads) { + dev_err(dev, "entity[%u].p%u: peer_pad %u out of range\n", + i, pi, pad->peer_pad); + return -EINVAL; + } + + peer_pad = &descs[peer_ent].pads[pad->peer_pad]; + + /* Links are SOURCE->SINK; reject SOURCE->SOURCE or SINK->SINK */ + if (((pad->flags & MEDIA_PAD_FL_SOURCE) && + (peer_pad->flags & MEDIA_PAD_FL_SOURCE)) || + ((pad->flags & MEDIA_PAD_FL_SINK) && + (peer_pad->flags & MEDIA_PAD_FL_SINK))) { + dev_err(dev, "entity[%u].p%u -> entity[%d].p%u: invalid\n", + i, pi, peer_ent, pad->peer_pad); + return -EINVAL; + } + + /* A link must be described symmetrically from both ends */ + if ((unsigned int)peer_pad->peer_entity != i || + peer_pad->peer_pad != pi) { + dev_err(dev, "entity[%u].p%u <-> entity[%d].p%u: mismatch\n", + i, pi, peer_ent, pad->peer_pad); + return -EINVAL; + } + } + } + + return 0; +} + +/* -------- Allocation / Release -------- */ + +struct camss_isp_pipeline *camss_isp_pipeline_alloc(unsigned int num_entities) +{ + struct camss_isp_pipeline *pipeline; + + pipeline = kzalloc(struct_size(pipeline, entities, num_entities), + GFP_KERNEL); + if (!pipeline) + return ERR_PTR(-ENOMEM); + + pipeline->num_entities = num_entities; + mutex_init(&pipeline->vdev_lock); + return pipeline; +} + +void camss_isp_pipeline_free(struct camss_isp_pipeline *pipeline) +{ + unsigned int i; + + if (!pipeline) + return; + + /* Release pads and subdevs state */ + for (i = 0; i < pipeline->num_entities; i++) { + struct camss_isp_pipeline_entity *slot = &pipeline->entities[i]; + + if (slot->obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV) + v4l2_subdev_cleanup(&slot->subdev); + + kfree(slot->pads); + slot->pads = NULL; + } + + mutex_destroy(&pipeline->vdev_lock); + kfree(pipeline); +} + +/* -------- Registration -------- */ + +void camss_isp_pipeline_unregister(struct camss_isp_pipeline *pipeline) +{ + int i; + + /* Unregister entities in reverse order. */ + for (i = (int)pipeline->num_entities - 1; i >= 0; i--) { + struct camss_isp_pipeline_entity *slot = &pipeline->entities[i]; + + if (slot->registered) { + switch (slot->obj_type) { + case MEDIA_ENTITY_TYPE_VIDEO_DEVICE: + if (video_device_pipeline(&slot->vdev)) + video_device_pipeline_stop(&slot->vdev); + video_unregister_device(&slot->vdev); + break; + case MEDIA_ENTITY_TYPE_V4L2_SUBDEV: + v4l2_device_unregister_subdev(&slot->subdev); + break; + case MEDIA_ENTITY_TYPE_BASE: + media_entity_remove_links(&slot->entity); + media_device_unregister_entity(&slot->entity); + slot->entity.name = NULL; + break; + } + + slot->registered = false; + } + } + + pipeline->v4l2_dev = NULL; +} + +static int isp_register_vdev(struct camss_isp_pipeline *pipeline, + struct camss_isp_pipeline_entity *slot, + const struct camss_isp_entity_desc *desc, + struct v4l2_device *v4l2_dev) +{ + struct video_device *vdev = &slot->vdev; + int ret; + + if (!desc->name || !desc->name[0] || !desc->vdev.fops) + return -EINVAL; + + strscpy(vdev->name, desc->name, sizeof(vdev->name)); + vdev->vfl_dir = isp_caps_to_vfl_dir(desc->vdev.caps); + vdev->v4l2_dev = v4l2_dev; + vdev->device_caps = desc->vdev.caps | V4L2_CAP_IO_MC; + vdev->release = video_device_release_empty; + vdev->fops = desc->vdev.fops; + vdev->lock = &pipeline->vdev_lock; + if (desc->vdev.ioctl_ops) + vdev->ioctl_ops = desc->vdev.ioctl_ops; + if (desc->vdev.entity_ops) + vdev->entity.ops = desc->vdev.entity_ops; + + vdev->entity.obj_type = MEDIA_ENTITY_TYPE_VIDEO_DEVICE; + vdev->entity.function = desc->function ? desc->function : MEDIA_ENT_F_IO_V4L; + + ret = media_entity_pads_init(&vdev->entity, slot->num_pads, slot->pads); + if (ret) + return ret; + + video_set_drvdata(vdev, desc->vdev.drvdata); + + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); + if (ret) + return ret; + + return 0; +} + +static int isp_register_subdev(struct camss_isp_pipeline_entity *slot, + const struct camss_isp_entity_desc *desc, + struct v4l2_device *v4l2_dev) +{ + struct v4l2_subdev *sd = &slot->subdev; + int ret; + + if (!desc->name || !desc->name[0] || !desc->subdev.ops) + return -EINVAL; + + v4l2_subdev_init(sd, desc->subdev.ops); + strscpy(sd->name, desc->name, sizeof(sd->name)); + sd->entity.function = desc->function ? + desc->function : MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; + /* Create a /dev/v4l-subdevN node so userspace can query pad formats */ + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + if (desc->subdev.internal_ops) + sd->internal_ops = desc->subdev.internal_ops; + if (desc->subdev.entity_ops) + sd->entity.ops = desc->subdev.entity_ops; + + ret = media_entity_pads_init(&sd->entity, slot->num_pads, slot->pads); + if (ret) + return ret; + + ret = v4l2_subdev_init_finalize(sd); + if (ret) + return ret; + + ret = v4l2_device_register_subdev(v4l2_dev, sd); + if (ret) { + v4l2_subdev_cleanup(sd); + return ret; + } + + return 0; +} + +static int isp_register_base_entity(struct camss_isp_pipeline_entity *slot, + const struct camss_isp_entity_desc *desc, + struct v4l2_device *v4l2_dev) +{ + struct media_entity *entity = &slot->entity; + int ret; + + if (!desc->name || !desc->name[0]) + return -EINVAL; + + entity->obj_type = MEDIA_ENTITY_TYPE_BASE; + entity->name = desc->name; + entity->function = desc->function; + + ret = media_entity_pads_init(entity, slot->num_pads, slot->pads); + if (ret) { + entity->name = NULL; + return ret; + } + + ret = media_device_register_entity(v4l2_dev->mdev, entity); + if (ret) { + entity->name = NULL; + return ret; + } + + return 0; +} + +static int isp_alloc_pads(struct camss_isp_pipeline_entity *slot, + const struct camss_isp_entity_desc *desc) +{ + unsigned int num_pads = isp_count_pads(desc->pads); + unsigned int i; + + if (!num_pads) + goto done; + + slot->pads = kcalloc(num_pads, sizeof(*slot->pads), GFP_KERNEL); + if (!slot->pads) + return -ENOMEM; + + for (i = 0; i < num_pads; i++) + slot->pads[i].flags = desc->pads[i].flags; +done: + slot->num_pads = num_pads; + return 0; +} + +int camss_isp_pipeline_register(struct camss_isp_pipeline *pipeline, + struct v4l2_device *v4l2_dev, + const struct camss_isp_entity_desc *descs, + unsigned int num_entities) +{ + unsigned int i, pi; + int ret; + + if (WARN_ON(num_entities != pipeline->num_entities)) + return -EINVAL; + + if (WARN_ON(!v4l2_dev || !v4l2_dev->mdev)) + return -EINVAL; + + ret = isp_pipeline_validate(v4l2_dev->dev, descs, num_entities); + if (ret) + return ret; + + pipeline->v4l2_dev = v4l2_dev; + + /* Register each entity */ + for (i = 0; i < num_entities; i++) { + const struct camss_isp_entity_desc *desc = &descs[i]; + struct camss_isp_pipeline_entity *slot = &pipeline->entities[i]; + + slot->obj_type = desc->obj_type; + + ret = isp_alloc_pads(slot, desc); + if (ret) + goto err_unregister; + + switch (desc->obj_type) { + case MEDIA_ENTITY_TYPE_VIDEO_DEVICE: + ret = isp_register_vdev(pipeline, slot, desc, v4l2_dev); + break; + case MEDIA_ENTITY_TYPE_V4L2_SUBDEV: + ret = isp_register_subdev(slot, desc, v4l2_dev); + break; + case MEDIA_ENTITY_TYPE_BASE: + default: + ret = isp_register_base_entity(slot, desc, v4l2_dev); + break; + } + if (ret) + goto err_unregister; + + slot->registered = true; + } + + /* Create links — only from SOURCE side to avoid duplicates */ + for (i = 0; i < num_entities; i++) { + const struct camss_isp_entity_desc *desc = &descs[i]; + unsigned int num_pads = isp_count_pads(desc->pads); + + for (pi = 0; pi < num_pads; pi++) { + const struct camss_isp_pad_desc *pad = &desc->pads[pi]; + struct media_entity *src_entity, *sink_entity; + unsigned int src_pad_idx, sink_pad_idx; + u32 lflags; + + if (!(pad->flags & MEDIA_PAD_FL_SOURCE)) + continue; + if (pad->peer_entity < 0) + continue; + + src_entity = isp_pipeline_media_entity(pipeline, i); + sink_entity = isp_pipeline_media_entity(pipeline, + (unsigned int)pad->peer_entity); + src_pad_idx = pi; + sink_pad_idx = pad->peer_pad; + + lflags = pad->link_flags ? + pad->link_flags : + (MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); + + ret = media_create_pad_link(src_entity, src_pad_idx, + sink_entity, sink_pad_idx, + lflags); + if (ret) + goto err_unregister; + } + } + + /* Create /dev/v4l-subdevN nodes for all registered subdevs */ + ret = v4l2_device_register_subdev_nodes(v4l2_dev); + if (ret) + goto err_unregister; + + return 0; + +err_unregister: + camss_isp_pipeline_unregister(pipeline); + return ret; +} diff --git a/drivers/media/platform/qcom/camss/ope/pipeline.h b/drivers/media/platform/qcom/camss/ope/pipeline.h new file mode 100644 index 0000000000000..f7d50734ed61f --- /dev/null +++ b/drivers/media/platform/qcom/camss/ope/pipeline.h @@ -0,0 +1,239 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * CAMSS ISP pipeline helper — declarative MC topology builder + * + * Drivers describe their entire media graph — entities (video devices, + * subdevs, or base entities), their pads, and the links between them — + * in a single static descriptor table. The builder validates the table, + * allocates and registers all entities, and creates all MC links. + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _CAMSS_PIPELINE_H +#define _CAMSS_PIPELINE_H + +#include +#include +#include +#include +#include +#include + +/** + * struct camss_isp_pad_desc - descriptor for one pad and its optional link + * + * @flags: Pad flags: MEDIA_PAD_FL_SINK, MEDIA_PAD_FL_SOURCE, + * MEDIA_PAD_FL_MUST_CONNECT. A zero @flags value acts as + * the sentinel that terminates the pad list. + * @peer_entity: Index of the peer entity in the descriptor array, or -1 + * if this pad has no link. + * @peer_pad: Pad index on the peer entity to link to. + * @link_flags: MC link flags (MEDIA_LNK_FL_*). Defaults to + * MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED when zero. + * + * Links are described from both sides (each endpoint references the other), + * but the builder only creates each link once — from the SOURCE side. + */ +struct camss_isp_pad_desc { + u32 flags; + int peer_entity; + unsigned int peer_pad; + u32 link_flags; +}; + +/** + * struct camss_isp_entity_desc - descriptor for one entity in the pipeline + * + * @name: Human-readable entity name (also used as video device name + * suffix when @obj_type is MEDIA_ENTITY_TYPE_VIDEO_DEVICE). + * Mandatory and must be non-empty. + * @obj_type: MEDIA_ENTITY_TYPE_VIDEO_DEVICE, MEDIA_ENTITY_TYPE_V4L2_SUBDEV, + * or MEDIA_ENTITY_TYPE_BASE. + * @function: MEDIA_ENT_F_* function identifier. + * @pads: Sentinel-terminated (flags == 0) array of pad descriptors. + * + * Fields used only for MEDIA_ENTITY_TYPE_VIDEO_DEVICE: + * @vdev.caps: V4L2_CAP_* device capabilities. + * The video device direction (VFL_DIR_RX/TX/M2M) is derived + * automatically from @caps by the builder. + * @vdev.drvdata: Opaque pointer set via video_set_drvdata() after registration. + * @vdev.fops: File operations (mandatory). + * @vdev.ioctl_ops: ioctl operations (may be NULL). + * + * Fields used only for MEDIA_ENTITY_TYPE_V4L2_SUBDEV: + * @subdev.ops: Subdev operations (mandatory). + * @subdev.internal_ops: Internal subdev operations (may be NULL). + */ +struct camss_isp_entity_desc { + const char *name; + u32 obj_type; + u32 function; + const struct camss_isp_pad_desc *pads; + + union { + /* MEDIA_ENTITY_TYPE_VIDEO_DEVICE */ + struct { + u32 caps; + void *drvdata; + const struct v4l2_file_operations *fops; + const struct v4l2_ioctl_ops *ioctl_ops; + const struct media_entity_operations *entity_ops; + } vdev; + /* MEDIA_ENTITY_TYPE_V4L2_SUBDEV */ + struct { + const struct v4l2_subdev_ops *ops; + const struct v4l2_subdev_internal_ops *internal_ops; + const struct media_entity_operations *entity_ops; + } subdev; + }; +}; + +/** + * struct camss_isp_pipeline_entity - one registered entity slot + * + * Internal to the pipeline; drivers access entities via the accessor helpers. + * + * @obj_type: mirrors the descriptor's @obj_type. + * @registered: set once the entity has been successfully registered, so that + * teardown only undoes what actually succeeded. + * @pads: allocated pad array for this entity. + * @num_pads: number of entries in @pads. + * @vdev: valid when @obj_type == MEDIA_ENTITY_TYPE_VIDEO_DEVICE. + * @subdev: valid when @obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV. + * @entity: valid when @obj_type == MEDIA_ENTITY_TYPE_BASE. + */ +struct camss_isp_pipeline_entity { + u32 obj_type; + bool registered; + struct media_pad *pads; + unsigned int num_pads; + union { + struct video_device vdev; + struct v4l2_subdev subdev; + struct media_entity entity; + }; +}; + +/** + * struct camss_isp_pipeline - registered ISP pipeline topology + * + * Allocate with camss_isp_pipeline_alloc(), register with + * camss_isp_pipeline_register(), tear down with + * camss_isp_pipeline_unregister(), free with camss_isp_pipeline_free(). + * + * @v4l2_dev: Pointer to the caller-provided V4L2 device. + * @drv_priv: Driver-private pointer; not touched by the framework. + * @vdev_lock: Pipeline-wide mutex assigned to video_device.lock of every + * registered video device, so the V4L2 core serialises ioctl2 + * handlers across all of the pipeline's video nodes. + * @num_entities: Number of entries in @entities. + * @entities: Per-entity state; flexible array. + */ +struct camss_isp_pipeline { + struct v4l2_device *v4l2_dev; + void *drv_priv; + struct mutex vdev_lock; + + unsigned int num_entities; + struct camss_isp_pipeline_entity entities[] __counted_by(num_entities); +}; + +/** + * camss_isp_pipeline_alloc() - allocate a pipeline for @num_entities entities + * + * Returns a pointer to the new pipeline or ERR_PTR on failure. + * Free with camss_isp_pipeline_free(). + */ +struct camss_isp_pipeline *camss_isp_pipeline_alloc(unsigned int num_entities); + +/** + * camss_isp_pipeline_free() - free a pipeline + * @pipeline: pipeline to free (may be NULL) + */ +void camss_isp_pipeline_free(struct camss_isp_pipeline *pipeline); + +/** + * camss_isp_pipeline_register() - validate descriptors and register the graph + * @pipeline: pipeline (allocated with camss_isp_pipeline_alloc()) + * @v4l2_dev: caller-owned and already-registered V4L2 device; its + * associated media_device (v4l2_dev->mdev) must also be + * initialised and registered before this call. + * @descs: array of @num_entities entity descriptors + * @num_entities: number of entities; must equal pipeline->num_entities + * + * Validates the descriptor table (link direction consistency, index bounds), + * then registers all entities into the provided v4l2_device / media_device + * and creates all MC pad links. + * + * Returns 0 on success or a negative error code. + */ +int camss_isp_pipeline_register(struct camss_isp_pipeline *pipeline, + struct v4l2_device *v4l2_dev, + const struct camss_isp_entity_desc *descs, + unsigned int num_entities); + +/** + * camss_isp_pipeline_unregister() - tear down a registered pipeline + * @pipeline: pipeline to unregister. + */ +void camss_isp_pipeline_unregister(struct camss_isp_pipeline *pipeline); + +/** + * camss_isp_pipeline_get_vdev() - return the video_device for entity @idx + * @pipeline: registered pipeline + * @idx: entity index (must be MEDIA_ENTITY_TYPE_VIDEO_DEVICE) + * + * Returns NULL if @idx is out of range or the entity is not a video device. + */ +static inline struct video_device * +camss_isp_pipeline_get_vdev(struct camss_isp_pipeline *pipeline, + unsigned int idx) +{ + if (WARN_ON(idx >= pipeline->num_entities)) + return NULL; + if (WARN_ON(pipeline->entities[idx].obj_type != + MEDIA_ENTITY_TYPE_VIDEO_DEVICE)) + return NULL; + return &pipeline->entities[idx].vdev; +} + +/** + * camss_isp_pipeline_get_subdev() - return the v4l2_subdev for entity @idx + * @pipeline: registered pipeline + * @idx: entity index (must be MEDIA_ENTITY_TYPE_V4L2_SUBDEV) + * + * Returns NULL if @idx is out of range or the entity is not a subdev. + */ +static inline struct v4l2_subdev * +camss_isp_pipeline_get_subdev(struct camss_isp_pipeline *pipeline, + unsigned int idx) +{ + if (WARN_ON(idx >= pipeline->num_entities)) + return NULL; + if (WARN_ON(pipeline->entities[idx].obj_type != + MEDIA_ENTITY_TYPE_V4L2_SUBDEV)) + return NULL; + return &pipeline->entities[idx].subdev; +} + +/** + * camss_isp_pipeline_get_entity() - return the media_entity for entity @idx + * @pipeline: registered pipeline + * @idx: entity index (must be MEDIA_ENTITY_TYPE_BASE) + * + * Returns NULL if @idx is out of range or the entity is not a base entity. + */ +static inline struct media_entity * +camss_isp_pipeline_get_entity(struct camss_isp_pipeline *pipeline, + unsigned int idx) +{ + if (WARN_ON(idx >= pipeline->num_entities)) + return NULL; + if (WARN_ON(pipeline->entities[idx].obj_type != + MEDIA_ENTITY_TYPE_BASE)) + return NULL; + return &pipeline->entities[idx].entity; +} + +#endif /* _CAMSS_PIPELINE_H */ From 2cefc093edb91049d82cd81afec4920485be80a7 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:31 +0800 Subject: [PATCH 0096/1133] FROMLIST: dt-bindings: media: Add qcom,x1p42100-camss Add bindings for the Camera Subsystem for X1P42100. The X1P42100 platform provides: - 2 x CSIPHY - 3 x TPG - 3 x CSID - 2 x CSID Lite - 1 x IFE - 2 x IFE Lite Link: https://lore.kernel.org/all/20260930-purwa_camss-v3-1-0fe2a5b11208@oss.qualcomm.com/ Signed-off-by: Wenmeng Liu --- .../bindings/media/qcom,x1p42100-camss.yaml | 263 ++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml new file mode 100644 index 0000000000000..c5ea7a7d9fe50 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml @@ -0,0 +1,263 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,x1p42100-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm X1P42100 Camera Subsystem (CAMSS) + +maintainers: + - Wenmeng Liu + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,x1p42100-camss + + reg: + maxItems: 12 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_wrapper + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 14 + + clock-names: + items: + - const: camnoc_rt_axi + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: gcc_axi_hf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + + interrupts: + maxItems: 8 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: vfe0 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + + iommus: + items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + + power-domains: + items: + - description: IFE0 GDSC - Image Front End, Global Distributed Switch Controller. + - description: Titan Top GDSC - Titan ISP Block, Global Distributed Switch Controller. + + power-domain-names: + items: + - const: ife0 + - const: top + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports, one per CSID. Each port receives the CSI data + decoded by the matching CSIPHY. + + patternProperties: + "^port@[01]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input port for receiving CSI data from a CSIPHY. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + - ports + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@acb7000 { + compatible = "qcom,x1p42100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0xf000>, + <0 0x0acc7000 0 0x1000>, + <0 0x0accb000 0 0x1000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + + clock-names = "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "gcc_axi_hf", + "vfe0", + "vfe0_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + + interconnect-names = "ahb", + "hf_mnoc"; + + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + + power-domain-names = "ife0", + "top"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + camss_csiphy0_ep: endpoint { + data-lanes = <1 2>; + remote-endpoint = <&csiphy0_out>; + }; + }; + }; + }; + }; From 72d0294a4f23f75a813a57c86fab425d58d08bfa Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:32 +0800 Subject: [PATCH 0097/1133] FROMLIST: media: qcom: camss: Add support for X1P42100 CAMSS Add CAMSS support for the Qualcomm X1P42100 (Purwa) SoC. The X1P42100 CAMSS is a cut-down variant of the X1E80100 (Hamoa) CAMSS. Compared to X1E80100 it has: - 2 x CSIPHY (CSIPHY0 and CSIPHY4) instead of 4 - 1 x IFE instead of 2 - only the ahb and hf_mnoc interconnect paths The CSID, CSID Lite, IFE Lite and TPG blocks are the same as on X1E80100, so reuse the existing CSID/VFE 680 ops and the X1E80100 TPG and CSID wrapper resources. The CSIPHYs are handled through the PHY API, so no CSIPHY resources other than the lane format are needed. Link: https://lore.kernel.org/all/20260930-purwa_camss-v3-2-0fe2a5b11208@oss.qualcomm.com/ Signed-off-by: Wenmeng Liu --- drivers/media/platform/qcom/camss/camss-vfe.c | 2 + drivers/media/platform/qcom/camss/camss.c | 195 ++++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 3 files changed, 198 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 2680a9914765f..c401d4d236702 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -354,6 +354,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_8650: case CAMSS_8775P: case CAMSS_X1E80100: + case CAMSS_X1P42100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: { @@ -2014,6 +2015,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_8650: case CAMSS_8775P: case CAMSS_X1E80100: + case CAMSS_X1P42100: ret = 16; break; default: diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index c54185c93a8a9..497ca82cf081e 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4452,6 +4452,186 @@ static const struct resources_wrapper csid_wrapper_res_x1e80100 = { .reg = "csid_wrapper", }; +static const struct camss_subdev_resources csid_res_x1p42100[] = { + /* CSID0 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "csid", "csid_csiphy_rx" }, + .clock_rate = { { 0 }, + { 64000000, 80000000 }, + { 80000000, 100000000, 200000000, + 300000000, 400000000 }, + { 300000000, 400000000, 480000000 }, + { 300000000, 400000000, 480000000 }, }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .hw_ops = &csid_ops_680, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + }, + }, + /* CSID1 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "csid", "csid_csiphy_rx" }, + .clock_rate = { { 0 }, + { 64000000, 80000000 }, + { 80000000, 100000000, 200000000, + 300000000, 400000000 }, + { 300000000, 400000000, 480000000 }, + { 300000000, 400000000, 480000000 }, }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .hw_ops = &csid_ops_680, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + }, + }, + /* CSID2 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "csid", "csid_csiphy_rx" }, + .clock_rate = { { 0 }, + { 64000000, 80000000 }, + { 80000000, 100000000, 200000000, + 300000000, 400000000 }, + { 300000000, 400000000, 480000000 }, + { 300000000, 400000000, 480000000 }, }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .hw_ops = &csid_ops_680, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + }, + }, + /* CSID_LITE0 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "csid", "csid_csiphy_rx" }, + .clock_rate = { { 0 }, + { 64000000, 80000000 }, + { 80000000, 100000000, 200000000, + 300000000, 400000000 }, + { 300000000, 400000000, 480000000 }, + { 300000000, 400000000, 480000000 }, }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_680, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE1 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "csid", "csid_csiphy_rx" }, + .clock_rate = { { 0 }, + { 64000000, 80000000 }, + { 80000000, 100000000, 200000000, + 300000000, 400000000 }, + { 300000000, 400000000, 480000000 }, + { 300000000, 400000000, 480000000 }, }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_680, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, +}; + +static const struct camss_subdev_resources vfe_res_x1p42100[] = { + /* IFE0 */ + { + .regulators = {}, + .clock = { "camnoc_rt_axi", "cpas_ahb", "cpas_fast_ahb", + "cpas_vfe0", "vfe0_fast_ahb", "vfe0" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 345600000, 432000000, 594000000, 675000000, + 727000000 }, }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 4, + .pd_name = "ife0", + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* IFE_LITE_0 */ + { + .regulators = {}, + .clock = { "camnoc_rt_axi", "cpas_ahb", "vfe_lite_ahb", + "cpas_vfe_lite", "vfe_lite", "vfe_lite_csid" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 266666667, 400000000, 480000000 }, }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* IFE_LITE_1 */ + { + .regulators = {}, + .clock = { "camnoc_rt_axi", "cpas_ahb", "vfe_lite_ahb", + "cpas_vfe_lite", "vfe_lite", "vfe_lite_csid" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 266666667, 400000000, 480000000 }, }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, +}; + +static const struct resources_icc icc_res_x1p42100[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + /* * camss_add_clock_margin - Add margin to clock frequency rate * @rate: Clock frequency rate @@ -5809,6 +5989,20 @@ static const struct camss_resources x1e80100_resources = { .vfe_num = ARRAY_SIZE(vfe_res_x1e80100), }; +static const struct camss_resources x1p42100_resources = { + .version = CAMSS_X1P42100, + .pd_name = "top", + .tpg_res = tpg_res_x1e80100, + .csid_res = csid_res_x1p42100, + .vfe_res = vfe_res_x1p42100, + .csid_wrapper_res = &csid_wrapper_res_x1e80100, + .icc_res = icc_res_x1p42100, + .icc_path_num = ARRAY_SIZE(icc_res_x1p42100), + .tpg_num = ARRAY_SIZE(tpg_res_x1e80100), + .csid_num = ARRAY_SIZE(csid_res_x1p42100), + .vfe_num = ARRAY_SIZE(vfe_res_x1p42100), +}; + static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, { .compatible = "qcom,msm8939-camss", .data = &msm8939_resources }, @@ -5829,6 +6023,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sm8650-camss", .data = &sm8650_resources }, { .compatible = "qcom,x1e80100-camss", .data = &x1e80100_resources }, { .compatible = "qcom,glymur-camss", .data = &x1e80100_resources }, + { .compatible = "qcom,x1p42100-camss", .data = &x1p42100_resources }, { } }; diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 7dc2fd9f03e0d..523050295209d 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -97,6 +97,7 @@ enum camss_version { CAMSS_8650, CAMSS_8775P, CAMSS_X1E80100, + CAMSS_X1P42100, }; enum icc_count { From 1c269439fd16dd2e2238e118ed809e2218efb0e4 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:13 -0700 Subject: [PATCH 0098/1133] FROMLIST: media: dt-bindings: Add CAMSS device for Kaanapali Add bindings for Camera Subsystem (CAMSS) on the Qualcomm Kaanapali platform. The Kaanapali platform provides: - 6 x CSIPHY (CSI Physical Layer) - 3 x TPG (Test Pattern Generator) - 3 x CSID (CSI Decoder) - 2 x CSID Lite - 3 x VFE (Video Front End), 5 RDI per VFE - 2 x VFE Lite, 4 RDI per VFE Lite Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-1-2541d8e55651@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Reviewed-by: Krzysztof Kozlowski Signed-off-by: Hangxiang Ma --- .../bindings/media/qcom,kaanapali-camss.yaml | 433 ++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml b/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml new file mode 100644 index 0000000000000..2f2bb682f32f4 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml @@ -0,0 +1,433 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,kaanapali-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Kaanapali Camera Subsystem (CAMSS) + +maintainers: + - Hangxiang Ma + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,kaanapali-camss + + reg: + maxItems: 19 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 35 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: cpas_vfe2 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy2 + - const: csiphy2_timer + - const: csiphy3 + - const: csiphy3_timer + - const: csiphy4 + - const: csiphy4_timer + - const: csiphy5 + - const: csiphy5_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe2 + - const: vfe2_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + - const: qdss_debug_xo + + interrupts: + maxItems: 16 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 4 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + - const: sf_icp_mnoc + + iommus: + maxItems: 1 + + power-domains: + items: + - description: + IFE0 GDSC - Global Distributed Switch Controller for IFE0. + - description: + IFE1 GDSC - Global Distributed Switch Controller for IFE1. + - description: + IFE2 GDSC - Global Distributed Switch Controller for IFE2. + - description: + Titan GDSC - Global Distributed Switch Controller for the entire camss. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: ife2 + - const: top + + vdd-csiphy0-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY0 core block. + + vdd-csiphy0-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY0 pll block. + + vdd-csiphy1-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY1 core block. + + vdd-csiphy1-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY1 pll block. + + vdd-csiphy2-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY2 core block. + + vdd-csiphy2-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY2 pll block. + + vdd-csiphy3-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY3 core block. + + vdd-csiphy3-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY3 pll block. + + vdd-csiphy4-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY4 core block. + + vdd-csiphy4-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY4 pll block. + + vdd-csiphy5-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY5 core block. + + vdd-csiphy5-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY5 pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-5]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input ports for receiving CSI data on CSIPHY 0-5. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@9253000 { + compatible = "qcom,kaanapali-camss"; + + reg = <0x0 0x09253000 0x0 0x5e80>, + <0x0 0x09263000 0x0 0x5e80>, + <0x0 0x09273000 0x0 0x5e80>, + <0x0 0x092d3000 0x0 0x3880>, + <0x0 0x092e7000 0x0 0x3880>, + <0x0 0x09523000 0x0 0x2000>, + <0x0 0x09525000 0x0 0x2000>, + <0x0 0x09527000 0x0 0x2000>, + <0x0 0x09529000 0x0 0x2000>, + <0x0 0x0952b000 0x0 0x2000>, + <0x0 0x0952d000 0x0 0x2000>, + <0x0 0x093fd000 0x0 0x400>, + <0x0 0x093fe000 0x0 0x400>, + <0x0 0x093ff000 0x0 0x400>, + <0x0 0x09151000 0x0 0x20000>, + <0x0 0x09171000 0x0 0x20000>, + <0x0 0x09191000 0x0 0x20000>, + <0x0 0x092dc000 0x0 0x9000>, + <0x0 0x092f0000 0x0 0x9000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + vdd-csiphy0-0p8-supply = <&vreg_0p8_supply>; + vdd-csiphy0-1p2-supply = <&vreg_1p2_supply>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy_ep0: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; From 8c8deb2f2b7017ab8d13ccf6adda805c9d9b9e15 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:14 -0700 Subject: [PATCH 0099/1133] FROMLIST: media: qcom: camss: Add Kaanapali compatible camss driver Add support for Kaanapali in the camss driver. Add high level resource information along with the bus bandwidth votes. Module level detailed resource information will be enumerated in the following patches of the series. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-2-2541d8e55651@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Signed-off-by: Hangxiang Ma --- drivers/media/platform/qcom/camss/camss.c | 22 ++++++++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 23 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 497ca82cf081e..2798fa1fd6217 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -38,6 +38,20 @@ static const struct parent_dev_ops vfe_parent_dev_ops; +static const struct resources_icc icc_res_kaanapali[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + /* Based on 4096 x 3072 30 FPS 2496 Mbps mode */ + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 471860, + .icc_bw_tbl.peak = 925857, + }, +}; + static const struct camss_subdev_resources csiphy_res_8x16[] = { /* CSIPHY0 */ { @@ -5756,6 +5770,13 @@ static void camss_remove(struct platform_device *pdev) camss_genpd_cleanup(camss); } +static const struct camss_resources kaanapali_resources = { + .version = CAMSS_KAANAPALI, + .pd_name = "top", + .icc_res = icc_res_kaanapali, + .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), +}; + static const struct camss_resources msm8916_resources = { .version = CAMSS_8x16, .csiphy_res = csiphy_res_8x16, @@ -6004,6 +6025,7 @@ static const struct camss_resources x1p42100_resources = { }; static const struct of_device_id camss_dt_match[] = { + { .compatible = "qcom,kaanapali-camss", .data = &kaanapali_resources }, { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, { .compatible = "qcom,msm8939-camss", .data = &msm8939_resources }, { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 523050295209d..50d68a6036846 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -96,6 +96,7 @@ enum camss_version { CAMSS_8550, CAMSS_8650, CAMSS_8775P, + CAMSS_KAANAPALI, CAMSS_X1E80100, CAMSS_X1P42100, }; From 562e4201c2bc15cef3e3bfe32965727b1d69edbb Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:15 -0700 Subject: [PATCH 0100/1133] FROMLIST: media: qcom: camss: csiphy: Add support for v2.4.0 two-phase CSIPHY Add more detailed resource information for CSIPHY devices in the camss driver along with the support for v2.4.0 in the 2 phase CSIPHY driver that is responsible for the PHY lane register configuration, module reset and interrupt handling. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-3-2541d8e55651@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Signed-off-by: Hangxiang Ma --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 124 +++++++++++++++++ drivers/media/platform/qcom/camss/camss.c | 125 ++++++++++++++++++ 2 files changed, 249 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index dac8d2ecf7995..795b333185e54 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -804,6 +804,123 @@ csiphy_lane_regs lane_regs_sm8650[] = { {0x0c10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, }; +/* 3nm 2PH v 2.4.0 2p5Gbps 4 lane DPHY mode */ +static const struct +csiphy_lane_regs lane_regs_2_4_0[] = { + /* LN 0 */ + {0x0094, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x00A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0090, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0098, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0094, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0094, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x005C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0060, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 2 */ + {0x0494, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x04A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0490, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0498, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0494, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0494, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x045C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0460, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 4 */ + {0x0894, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x08A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0890, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0898, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0894, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x082C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0814, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0804, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0820, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0808, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0894, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x085C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0860, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 6 */ + {0x0C94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0CA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C94, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0C30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C38, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C94, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x0C5C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0C60, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN CLK */ + {0x0E94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0EA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E90, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E94, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0E30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E28, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E00, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E0C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E38, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E08, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + /* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */ static const struct csiphy_lane_regs lane_regs_x1e80100[] = { @@ -1140,6 +1257,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_8550: case CAMSS_8650: case CAMSS_8775P: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: ret = true; break; @@ -1259,6 +1377,12 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sa8775p[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); break; + case CAMSS_KAANAPALI: + regs->lane_regs = &lane_regs_2_4_0[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_2_4_0); + regs->offset = 0x1000; + regs->common_status_offset = 0x138; + break; default: break; } diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 2798fa1fd6217..d8e4dad321ed0 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -38,6 +38,129 @@ static const struct parent_dev_ops vfe_parent_dev_ops; +static const struct camss_subdev_resources csiphy_res_kaanapali[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdd-csiphy0-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy0-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy0", "csiphy0_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdd-csiphy1-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy1-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy1", "csiphy1_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY2 */ + { + .regulators = { + { .supply = "vdd-csiphy2-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy2-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy2", "csiphy2_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY3 */ + { + .regulators = { + { .supply = "vdd-csiphy3-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy3-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy3", "csiphy3_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY4 */ + { + .regulators = { + { .supply = "vdd-csiphy4-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy4-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy4", "csiphy4_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY5 */ + { + .regulators = { + { .supply = "vdd-csiphy5-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy5-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy5", "csiphy5_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy5" }, + .interrupt = { "csiphy5" }, + .csiphy = { + .id = 5, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, +}; + static const struct resources_icc icc_res_kaanapali[] = { { .name = "ahb", @@ -5773,8 +5896,10 @@ static void camss_remove(struct platform_device *pdev) static const struct camss_resources kaanapali_resources = { .version = CAMSS_KAANAPALI, .pd_name = "top", + .csiphy_res = csiphy_res_kaanapali, .icc_res = icc_res_kaanapali, .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), + .csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali), }; static const struct camss_resources msm8916_resources = { From 5988992e68623503dd196c809f70e4448bb3de0a Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:16 -0700 Subject: [PATCH 0101/1133] FROMLIST: media: qcom: camss: csid: Add support for CSID gen4 Add more detailed resource information for CSID devices along with the driver for CSID gen4 that is responsible for CSID register configuration, module reset and IRQ handling for BUF_DONE events. And aggregate a common definition 'CSI2_RX_CFG0_PHY_SEL_BASE_IDX' into csid header file. In this CSID version, RUP and AUP update values are split into two registers along with a SET register. Accordingly, enhance the CSID interface to accommodate both the legacy combined reg_update and the split RUP and AUP updates. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-4-2541d8e55651@oss.qualcomm.com/ Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma --- drivers/media/platform/qcom/camss/Makefile | 1 + .../platform/qcom/camss/camss-csid-680.c | 1 - .../platform/qcom/camss/camss-csid-gen3.c | 1 - .../platform/qcom/camss/camss-csid-gen4.c | 376 ++++++++++++++++++ .../media/platform/qcom/camss/camss-csid.h | 11 +- drivers/media/platform/qcom/camss/camss.c | 75 ++++ 6 files changed, 462 insertions(+), 3 deletions(-) create mode 100644 drivers/media/platform/qcom/camss/camss-csid-gen4.c diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index b79c40626c401..8ae662db9c91d 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -10,6 +10,7 @@ qcom-camss-objs += \ camss-csid-680.o \ camss-csid-gen2.o \ camss-csid-gen3.o \ + camss-csid-gen4.o \ camss-csiphy.o \ camss-csiphy-2ph-1-0.o \ camss-csiphy-3ph-1-0.o \ diff --git a/drivers/media/platform/qcom/camss/camss-csid-680.c b/drivers/media/platform/qcom/camss/camss-csid-680.c index 345a67c8fb947..bf7164085ddb4 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-680.c +++ b/drivers/media/platform/qcom/camss/camss-csid-680.c @@ -101,7 +101,6 @@ #define CSI2_RX_CFG0_DL2_INPUT_SEL 12 #define CSI2_RX_CFG0_DL3_INPUT_SEL 16 #define CSI2_RX_CFG0_PHY_NUM_SEL 20 -#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 #define CSI2_RX_CFG0_PHY_TYPE_SEL 24 #define CSI2_RX_CFG0_TPG_MUX_EN BIT(27) #define CSI2_RX_CFG0_TPG_MUX_SEL GENMASK(29, 28) diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen3.c b/drivers/media/platform/qcom/camss/camss-csid-gen3.c index 0fdbf75fb27db..da9458cd178bd 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-gen3.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.c @@ -105,7 +105,6 @@ #define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ (0x34C + 0x100 * (rdi)) :\ (0x54C + 0x100 * (rdi))) -#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 static void __csid_configure_rx(struct csid_device *csid, struct csid_phy_config *phy, int vc) diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen4.c b/drivers/media/platform/qcom/camss/camss-csid-gen4.c new file mode 100644 index 0000000000000..41035352c4bb0 --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-gen4.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-csid-gen4.c + * + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include +#include +#include +#include + +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen3.h" + +/* Reset and Command Registers */ +#define CSID_RST_CFG 0x108 +#define RST_MODE BIT(0) +#define RST_LOCATION BIT(4) + +/* Reset and Command Registers */ +#define CSID_RST_CMD 0x10C +#define SELECT_HW_RST BIT(0) +#define SELECT_IRQ_RST BIT(2) +#define CSID_IRQ_CMD 0x110 +#define IRQ_CMD_CLEAR BIT(0) + +/* Register Update Commands, RUP/AUP */ +#define CSID_RUP_CMD 0x114 +#define CSID_AUP_CMD 0x118 +#define CSID_RUP_AUP_RDI(rdi) (BIT(8) << (rdi)) +#define CSID_RUP_AUP_CMD 0x11C +#define RUP_SET BIT(0) +#define MUP BIT(4) + +/* Top level interrupt registers */ +#define CSID_TOP_IRQ_STATUS 0x180 +#define CSID_TOP_IRQ_MASK 0x184 +#define CSID_TOP_IRQ_CLEAR 0x188 +#define INFO_RST_DONE BIT(0) +#define CSI2_RX_IRQ_STATUS BIT(2) +#define BUF_DONE_IRQ_STATUS BIT(3) + +/* Buffer done interrupt registers */ +#define CSID_BUF_DONE_IRQ_STATUS 0x1A0 +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET 16 +#define CSID_BUF_DONE_IRQ_MASK 0x1A4 +#define CSID_BUF_DONE_IRQ_CLEAR 0x1A8 +#define CSID_BUF_DONE_IRQ_SET 0x1AC + +/* CSI2 RX interrupt registers */ +#define CSID_CSI2_RX_IRQ_STATUS 0x1B0 +#define CSID_CSI2_RX_IRQ_MASK 0x1B4 +#define CSID_CSI2_RX_IRQ_CLEAR 0x1B8 +#define CSID_CSI2_RX_IRQ_SET 0x1BC + +/* CSI2 RX Configuration */ +#define CSID_CSI2_RX_CFG0 0x880 +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_DL0_INPUT_SEL 4 +#define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSID_CSI2_RX_CFG1 0x884 +#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_VC_MODE BIT(2) + +#define MSM_CSID_MAX_SRC_STREAMS_GEN4 (csid_is_lite(csid) ? 4 : 5) + +/* RDI Configuration */ +#define CSID_RDI_CFG0(rdi) \ + ((csid_is_lite(csid) ? 0x3080 : 0x5480) + 0x200 * (rdi)) +#define RDI_CFG0_RETIME_BS BIT(5) +#define RDI_CFG0_TIMESTAMP_EN BIT(6) +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) +#define RDI_CFG0_DECODE_FORMAT 12 +#define RDI_CFG0_DT 16 +#define RDI_CFG0_VC 22 +#define RDI_CFG0_EN BIT(31) + +/* RDI Control and Configuration */ +#define CSID_RDI_CTRL(rdi) \ + ((csid_is_lite(csid) ? 0x3088 : 0x5488) + 0x200 * (rdi)) +#define RDI_CTRL_START_CMD BIT(0) + +#define CSID_RDI_CFG1(rdi) \ + ((csid_is_lite(csid) ? 0x3094 : 0x5494) + 0x200 * (rdi)) +#define RDI_CFG1_DROP_H_EN BIT(5) +#define RDI_CFG1_DROP_V_EN BIT(6) +#define RDI_CFG1_CROP_H_EN BIT(7) +#define RDI_CFG1_CROP_V_EN BIT(8) +#define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) + +/* RDI Pixel Store Configuration */ +#define CSID_RDI_PIX_STORE_CFG0(rdi) (0x5498 + 0x200 * (rdi)) +#define RDI_PIX_STORE_CFG0_EN BIT(0) +#define RDI_PIX_STORE_CFG0_MIN_HBI 1 + +/* RDI IRQ Status in wrapper */ +#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) (0x224 + (0x10 * (rdi))) +#define CSID_CSI2_RDIN_IRQ_MASK(rdi) (0x228 + (0x10 * (rdi))) +#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) (0x22C + (0x10 * (rdi))) +#define INFO_RUP_DONE BIT(23) + +static void __csid_aup_rup_trigger(struct csid_device *csid) +{ + /* trigger SET in combined register */ + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD); +} + +static void __csid_aup_rup_clear(struct csid_device *csid, int port_id) +{ + /* Hardware clears the registers upon consuming the settings */ + csid->aup_update &= ~CSID_RUP_AUP_RDI(port_id); + csid->rup_update &= ~CSID_RUP_AUP_RDI(port_id); +} + +static void __csid_aup_update(struct csid_device *csid, int port_id) +{ + csid->aup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->aup_update, csid->base + CSID_AUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_reg_update(struct csid_device *csid, int port_id) +{ + csid->rup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->rup_update, csid->base + CSID_RUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy) +{ + int val; + + val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; + val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; + val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) + << CSI2_RX_CFG0_PHY_NUM_SEL; + writel(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_ECC_CORRECTION_EN; + writel(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_configure_rx_vc(struct csid_device *csid, int vc) +{ + int val; + + if (vc > 3) { + val = readl(csid->base + CSID_CSI2_RX_CFG1); + val |= CSI2_RX_CFG1_VC_MODE; + writel(val, csid->base + CSID_CSI2_RX_CFG1); + } +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + int val = 0; + + if (enable) + val = RDI_CTRL_START_CMD; + + writel(val, csid->base + CSID_RDI_CTRL(rdi)); +} + +static void __csid_configure_rdi_pix_store(struct csid_device *csid, u8 rdi) +{ + u32 val; + + /* + * Configure pixel store to allow absorption of hblanking or idle time. + * This helps with horizontal crop and prevents line buffer conflicts. + * Reset state is 0x8 which has MIN_HBI=4, we keep the default MIN_HBI + * and just enable the pixel store functionality. + */ + val = (4 << RDI_PIX_STORE_CFG0_MIN_HBI) | RDI_PIX_STORE_CFG0_EN; + writel(val, csid->base + CSID_RDI_PIX_STORE_CFG0(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc) +{ + u32 val; + u8 lane_cnt = csid->phy.lane_cnt; + + /* Source pads matching RDI channels on hardware. + * E.g. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. + */ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + + if (!lane_cnt) + lane_cnt = 4; + + val = RDI_CFG0_TIMESTAMP_EN; + val |= RDI_CFG0_TIMESTAMP_STB_SEL; + val |= RDI_CFG0_RETIME_BS; + + /* note: for non-RDI path, this should be format->decode_format */ + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; + val |= vc << RDI_CFG0_VC; + val |= format->data_type << RDI_CFG0_DT; + writel(val, csid->base + CSID_RDI_CFG0(port)); + + val = RDI_CFG1_PACKING_FORMAT_MIPI; + writel(val, csid->base + CSID_RDI_CFG1(port)); + + /* Configure pixel store using dedicated register in gen4 */ + if (!csid_is_lite(csid)) + __csid_configure_rdi_pix_store(csid, port); + + val = 0; + writel(val, csid->base + CSID_RDI_CTRL(port)); + + val = readl(csid->base + CSID_RDI_CFG0(port)); + + if (enable) + val |= RDI_CFG0_EN; + + writel(val, csid->base + CSID_RDI_CFG0(port)); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + u8 i, k; + + __csid_configure_rx(csid, &csid->phy); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i, 0); + __csid_configure_rx_vc(csid, 0); + + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++) + __csid_aup_update(csid, i); + + __csid_reg_update(csid, i); + + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return 0; +} + +static void csid_subdev_reg_update(struct csid_device *csid, int port_id, + bool clear) +{ + if (clear) + __csid_aup_rup_clear(csid, port_id); + else + __csid_aup_update(csid, port_id); +} + +/** + * csid_isr - CSID module interrupt service routine + * @irq: Interrupt line + * @dev: CSID device + * + * Return IRQ_HANDLED on success + */ +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val, buf_done_val; + u8 reset_done; + int i; + + val = readl(csid->base + CSID_TOP_IRQ_STATUS); + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + + reset_done = val & INFO_RST_DONE; + + buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS); + writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); + writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); + + if (val & INFO_RUP_DONE) + csid_subdev_reg_update(csid, i, true); + + if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) + camss_buf_done(csid->camss, csid->id, i); + } + } + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + if (reset_done) + complete(&csid->reset_complete); + + return IRQ_HANDLED; +} + +/** + * csid_reset - Trigger reset on CSID module and wait to complete + * @csid: CSID device + * + * Return 0 on success or a negative error code otherwise + */ +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + u32 val; + int i; + + reinit_completion(&csid->reset_complete); + + val = INFO_RST_DONE | BUF_DONE_IRQ_STATUS; + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + writel(val, csid->base + CSID_TOP_IRQ_MASK); + + val = 0; + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + /* + * Only need to clear buf done IRQ status here, + * RUP done IRQ status will be cleared once isr + * strobe generated by CSID_RST_CMD + */ + val |= BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i); + } + } + writel(val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + writel(val, csid->base + CSID_BUF_DONE_IRQ_MASK); + + /* Clear all IRQ status with CLEAR bits set */ + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + val = RST_LOCATION | RST_MODE; + writel(val, csid->base + CSID_RST_CFG); + + val = SELECT_HW_RST | SELECT_IRQ_RST; + writel(val, csid->base + CSID_RST_CMD); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + + if (!time) { + dev_err(csid->camss->dev, "CSID reset timeout\n"); + return -EIO; + } + + return 0; +} + +static void csid_subdev_init(struct csid_device *csid) +{ + csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; +} + +const struct csid_hw_ops csid_ops_gen4 = { + .configure_stream = csid_configure_stream, + .configure_testgen_pattern = csid_configure_testgen_pattern, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, + .reg_update = csid_subdev_reg_update, +}; diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index 5296b10f6bac8..e6590b2bd8be5 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -27,6 +27,8 @@ /* CSID hardware can demultiplex up to 4 outputs */ #define MSM_CSID_MAX_SRC_STREAMS 4 +/* CSIPHY to hardware PHY selector mapping */ +#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 #define CSID_RESET_TIMEOUT_MS 500 enum csid_testgen_mode { @@ -154,7 +156,13 @@ struct csid_device { void __iomem *base; u32 irq; char irq_name[30]; - u32 reg_update; + union { + u32 reg_update; + struct { + u32 rup_update; + u32 aup_update; + }; + }; struct camss_clock *clock; int nclocks; struct regulator_bulk_data *supplies; @@ -218,6 +226,7 @@ extern const struct csid_hw_ops csid_ops_340; extern const struct csid_hw_ops csid_ops_680; extern const struct csid_hw_ops csid_ops_gen2; extern const struct csid_hw_ops csid_ops_gen3; +extern const struct csid_hw_ops csid_ops_gen4; /* * csid_is_lite - Check if CSID is CSID lite. diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index d8e4dad321ed0..420b33459b258 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -161,6 +161,79 @@ static const struct camss_subdev_resources csiphy_res_kaanapali[] = { }, }; +static const struct camss_subdev_resources csid_res_kaanapali[] = { + /* CSID0 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE1 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + } +}; + static const struct resources_icc icc_res_kaanapali[] = { { .name = "ahb", @@ -5897,9 +5970,11 @@ static const struct camss_resources kaanapali_resources = { .version = CAMSS_KAANAPALI, .pd_name = "top", .csiphy_res = csiphy_res_kaanapali, + .csid_res = csid_res_kaanapali, .icc_res = icc_res_kaanapali, .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), .csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali), + .csid_num = ARRAY_SIZE(csid_res_kaanapali), }; static const struct camss_resources msm8916_resources = { From 778046468831fbcf95d92661d8a322a45ed7216c Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:17 -0700 Subject: [PATCH 0102/1133] FROMLIST: media: qcom: camss: vfe: Add support for VFE gen4 Add Video Front End (VFE) version gen4 as found on the Kaanapali SoC. The FULL front end modules in Kaanapali camera subsystem are called TFEs (Thin Front End), however, retaining the name VFE at places to maintain consistency and avoid unnecessary code changes. This change limits the VFE output lines to 3 for now as constrained by the CAMSS driver framework. Kaanapali architecture requires for the REG_UPDATE and AUP_UPDATE to be issued after all of the CSID configuration has been done. Additionally, the number of AUP_UPDATEs should match the number of buffers enqueued to the write master while it's being enabled. Although the real time data from TFE goes through the RT_CAMNOC, we are required to enable both the camnoc_rt_axi and camnoc_nrt_axi clocks for the PDX_NOC, that follows both the RT and NRT NOCs in this architecture, to ensure that both of the latter are idle after reset. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-5-2541d8e55651@oss.qualcomm.com/ Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma --- drivers/media/platform/qcom/camss/Makefile | 1 + .../platform/qcom/camss/camss-vfe-gen4.c | 197 ++++++++++++++++++ drivers/media/platform/qcom/camss/camss-vfe.c | 9 +- drivers/media/platform/qcom/camss/camss-vfe.h | 2 + drivers/media/platform/qcom/camss/camss.c | 138 ++++++++++++ 5 files changed, 345 insertions(+), 2 deletions(-) create mode 100644 drivers/media/platform/qcom/camss/camss-vfe-gen4.c diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index 8ae662db9c91d..3ecb13f644409 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -28,6 +28,7 @@ qcom-camss-objs += \ camss-vfe-680.o \ camss-vfe-gen1.o \ camss-vfe-gen3.o \ + camss-vfe-gen4.o \ camss-vfe-vbif.o \ camss-video.o diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c new file mode 100644 index 0000000000000..d73d70898710a --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-vfe-gen4.c + * + * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module gen4 + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include + +#include "camss.h" +#include "camss-vfe.h" + +/* VFE-gen4 Bus Register Base Addresses */ +#define BUS_REG_BASE (vfe_is_lite(vfe) ? 0x800 : 0x1000) + +#define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) +#define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) + +#define VFE_BUS_WM_TEST_BUS_CTRL (BUS_REG_BASE + 0x128) + +#define VFE_BUS_WM_CFG(n) (BUS_REG_BASE + 0x500 + (n) * 0x100) +#define WM_CFG_EN BIT(0) +#define WM_VIR_FRM_EN BIT(1) +#define WM_CFG_MODE BIT(16) +#define VFE_BUS_WM_IMAGE_ADDR(n) (BUS_REG_BASE + 0x504 + (n) * 0x100) +#define VFE_BUS_WM_FRAME_INCR(n) (BUS_REG_BASE + 0x508 + (n) * 0x100) +#define VFE_BUS_WM_IMAGE_CFG_0(n) (BUS_REG_BASE + 0x50C + (n) * 0x100) +#define WM_IMAGE_CFG_0_DEFAULT_WIDTH (0xFFFF) +#define VFE_BUS_WM_IMAGE_CFG_2(n) (BUS_REG_BASE + 0x514 + (n) * 0x100) +#define WM_IMAGE_CFG_2_DEFAULT_STRIDE (0xFFFF) +#define VFE_BUS_WM_PACKER_CFG(n) (BUS_REG_BASE + 0x518 + (n) * 0x100) + +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(n) (BUS_REG_BASE + 0x530 + (n) * 0x100) +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(n) (BUS_REG_BASE + 0x534 + (n) * 0x100) + +/* VFE lite has no such registers */ +#define VFE_BUS_WM_FRAMEDROP_PERIOD(n) (BUS_REG_BASE + 0x538 + (n) * 0x100) +#define VFE_BUS_WM_FRAMEDROP_PATTERN(n) (BUS_REG_BASE + 0x53C + (n) * 0x100) + +#define VFE_BUS_WM_MMU_PREFETCH_CFG(n) (BUS_REG_BASE + 0x560 + (n) * 0x100) +#define VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(n) (BUS_REG_BASE + 0x564 + (n) * 0x100) + +/* + * IFE write master client IDs + * + * VIDEO_FULL 0 + * VIDEO_DC4_Y 1 + * VIDEO_DC4_C 2 + * VIDEO_DC16_Y 3 + * VIDEO_DC16_C 4 + * DISPLAY_DS2_Y 5 + * DISPLAY_DS2_C 6 + * FD_Y 7 + * FD_C 8 + * PIXEL_RAW 9 + * STATS_AEC_BG 10 + * STATS_AEC_BHIST 11 + * STATS_TINTLESS_BG 12 + * STATS_AWB_BG 13 + * STATS_AWB_BFW 14 + * STATS_AF_BHIST 15 + * STATS_ALSC_BG 16 + * STATS_FLICKER_BAYERRS 17 + * STATS_TMC_BHIST 18 + * PDAF_0 19 + * PDAF_1 20 + * PDAF_2 21 + * PDAF_3 22 + * RDI0 23 + * RDI1 24 + * RDI2 25 + * RDI3 26 + * RDI4 27 + * + * IFE Lite write master client IDs + * + * RDI0 0 + * RDI1 1 + * RDI2 2 + * RDI3 3 + * GAMMA 4 + * STATES_BE 5 + */ +#define RDI_WM(n) ((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n)) + +static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) +{ + struct v4l2_pix_format_mplane *pix = + &line->video_out.active_fmt.fmt.pix_mp; + + wm = RDI_WM(wm); + + /* no clock gating at bus input */ + writel(WM_CGC_OVERRIDE_ALL, vfe->base + VFE_BUS_WM_CGC_OVERRIDE); + + writel(0x0, vfe->base + VFE_BUS_WM_TEST_BUS_CTRL); + + writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height >> 8, + vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); + writel((WM_IMAGE_CFG_0_DEFAULT_WIDTH & 0xFFFF), + vfe->base + VFE_BUS_WM_IMAGE_CFG_0(wm)); + writel(WM_IMAGE_CFG_2_DEFAULT_STRIDE, + vfe->base + VFE_BUS_WM_IMAGE_CFG_2(wm)); + writel(0, vfe->base + VFE_BUS_WM_PACKER_CFG(wm)); + + /* no dropped frames, one irq per frame */ + if (!vfe_is_lite(vfe)) { + writel(0, vfe->base + VFE_BUS_WM_FRAMEDROP_PERIOD(wm)); + writel(1, vfe->base + VFE_BUS_WM_FRAMEDROP_PATTERN(wm)); + } + + writel(0, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(wm)); + writel(1, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(wm)); + + writel(1, vfe->base + VFE_BUS_WM_MMU_PREFETCH_CFG(wm)); + writel(0xFFFFFFFF, vfe->base + VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(wm)); + + writel(WM_CFG_EN | WM_CFG_MODE, vfe->base + VFE_BUS_WM_CFG(wm)); +} + +static void vfe_wm_stop(struct vfe_device *vfe, u8 wm) +{ + wm = RDI_WM(wm); + writel(0, vfe->base + VFE_BUS_WM_CFG(wm)); +} + +static void vfe_wm_update(struct vfe_device *vfe, u8 wm, u32 addr, + struct vfe_line *line) +{ + wm = RDI_WM(wm); + writel(addr >> 8, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); + + dev_dbg(vfe->camss->dev, "wm:%d, image buf addr:0x%x\n", wm, addr); +} + +static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) +{ + int port_id = line_id; + + camss_reg_update(vfe->camss, vfe->id, port_id, false); +} + +static inline void vfe_reg_update_clear(struct vfe_device *vfe, + enum vfe_line_id line_id) +{ + int port_id = line_id; + + camss_reg_update(vfe->camss, vfe->id, port_id, true); +} + +static const struct camss_video_ops vfe_video_ops_gen4 = { + .queue_buffer = vfe_queue_buffer_v2, + .flush_buffers = vfe_flush_buffers, +}; + +static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) +{ + vfe->video_ops = vfe_video_ops_gen4; +} + +static void vfe_global_reset(struct vfe_device *vfe) +{ + vfe_isr_reset_ack(vfe); +} + +static irqreturn_t vfe_isr(int irq, void *dev) +{ + /* nop */ + return IRQ_HANDLED; +} + +static int vfe_halt(struct vfe_device *vfe) +{ + /* rely on vfe_disable_output() to stop the VFE */ + return 0; +} + +const struct vfe_hw_ops vfe_ops_gen4 = { + .global_reset = vfe_global_reset, + .hw_version = vfe_hw_version, + .isr = vfe_isr, + .pm_domain_off = vfe_pm_domain_off, + .pm_domain_on = vfe_pm_domain_on, + .reg_update = vfe_reg_update, + .reg_update_clear = vfe_reg_update_clear, + .subdev_init = vfe_subdev_init, + .vfe_disable = vfe_disable, + .vfe_enable = vfe_enable_v2, + .vfe_halt = vfe_halt, + .vfe_wm_start = vfe_wm_start, + .vfe_wm_stop = vfe_wm_stop, + .vfe_buf_done = vfe_buf_done, + .vfe_wm_update = vfe_wm_update, +}; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index c401d4d236702..2c246632ed18d 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -353,6 +353,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_8550: case CAMSS_8650: case CAMSS_8775P: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: case CAMSS_X1P42100: switch (sink_code) { @@ -526,7 +527,8 @@ int vfe_enable_output_v2(struct vfe_line *line) spin_lock_irqsave(&vfe->output_lock, flags); - ops->reg_update_clear(vfe, line->id); + if (ops->reg_update_clear) + ops->reg_update_clear(vfe, line->id); if (output->state > VFE_OUTPUT_RESERVED) { dev_err(vfe->camss->dev, @@ -553,7 +555,9 @@ int vfe_enable_output_v2(struct vfe_line *line) output->gen2.active_num++; ops->vfe_wm_update(vfe, output->wm_idx[0], output->buf[i]->addr[0], line); - ops->reg_update(vfe, line->id); + + if (!vfe->res->reg_update_after_csid_config) + ops->reg_update(vfe, line->id); } spin_unlock_irqrestore(&vfe->output_lock, flags); @@ -2014,6 +2018,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_8550: case CAMSS_8650: case CAMSS_8775P: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: case CAMSS_X1P42100: ret = 16; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h index ae9dad353a378..c402ef170c81b 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.h +++ b/drivers/media/platform/qcom/camss/camss-vfe.h @@ -133,6 +133,7 @@ struct vfe_isr_ops { struct vfe_subdev_resources { bool is_lite; + bool reg_update_after_csid_config; u8 line_num; bool has_pd; char *pd_name; @@ -249,6 +250,7 @@ extern const struct vfe_hw_ops vfe_ops_340; extern const struct vfe_hw_ops vfe_ops_480; extern const struct vfe_hw_ops vfe_ops_680; extern const struct vfe_hw_ops vfe_ops_gen3; +extern const struct vfe_hw_ops vfe_ops_gen4; int vfe_get(struct vfe_device *vfe); void vfe_put(struct vfe_device *vfe); diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 420b33459b258..d8ed597f4138e 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -234,6 +234,142 @@ static const struct camss_subdev_resources csid_res_kaanapali[] = { } }; +/* In Kaanapali, CAMNOC requires all CPAS_TFEX clocks + * to operate on any TFE Full. + */ +static const struct camss_subdev_resources vfe_res_kaanapali[] = { + /* VFE0 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe0_fast_ahb", "vfe0", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe1_fast_ahb", "vfe1", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe2_fast_ahb", "vfe2", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE3 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE4 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + static const struct resources_icc icc_res_kaanapali[] = { { .name = "ahb", @@ -5971,10 +6107,12 @@ static const struct camss_resources kaanapali_resources = { .pd_name = "top", .csiphy_res = csiphy_res_kaanapali, .csid_res = csid_res_kaanapali, + .vfe_res = vfe_res_kaanapali, .icc_res = icc_res_kaanapali, .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), .csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali), .csid_num = ARRAY_SIZE(csid_res_kaanapali), + .vfe_num = ARRAY_SIZE(vfe_res_kaanapali), }; static const struct camss_resources msm8916_resources = { From 8a7e59f8d5b720923da5176e41586acf1e4e2813 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:03 -0700 Subject: [PATCH 0103/1133] FROMLIST: media: dt-bindings: Add CAMSS device for SM8750 Add bindings for Camera Subsystem (CAMSS) on the Qualcomm SM8750 platform. The SM8750 platform provides: - 6 x CSIPHY (CSI Physical Layer) - 3 x TPG (Test Pattern Generator) - 3 x CSID (CSI Decoder) - 2 x CSID Lite - 3 x VFE (Video Front End), 5 RDI per VFE - 2 x VFE Lite, 4 RDI per VFE Lite Reviewed-by: Bryan O'Donoghue Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-1-fc6861a65c67@oss.qualcomm.com/ --- .../bindings/media/qcom,sm8750-camss.yaml | 433 ++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml b/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml new file mode 100644 index 0000000000000..fc0550899c074 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml @@ -0,0 +1,433 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,sm8750-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SM8750 Camera Subsystem (CAMSS) + +maintainers: + - Hangxiang Ma + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,sm8750-camss + + reg: + maxItems: 19 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 35 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: cpas_vfe2 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy2 + - const: csiphy2_timer + - const: csiphy3 + - const: csiphy3_timer + - const: csiphy4 + - const: csiphy4_timer + - const: csiphy5 + - const: csiphy5_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe2 + - const: vfe2_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + - const: qdss_debug_xo + + interrupts: + maxItems: 16 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 4 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + - const: sf_icp_mnoc + + iommus: + maxItems: 1 + + power-domains: + items: + - description: + IFE0 GDSC - Global Distributed Switch Controller for IFE0. + - description: + IFE1 GDSC - Global Distributed Switch Controller for IFE1. + - description: + IFE2 GDSC - Global Distributed Switch Controller for IFE2. + - description: + Titan GDSC - Global Distributed Switch Controller for the entire camss. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: ife2 + - const: top + + vdd-csiphy0-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY0 core block. + + vdd-csiphy0-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY0 pll block. + + vdd-csiphy1-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY1 core block. + + vdd-csiphy1-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY1 pll block. + + vdd-csiphy2-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY2 core block. + + vdd-csiphy2-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY2 pll block. + + vdd-csiphy3-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY3 core block. + + vdd-csiphy3-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY3 pll block. + + vdd-csiphy4-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY4 core block. + + vdd-csiphy4-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY4 pll block. + + vdd-csiphy5-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY5 core block. + + vdd-csiphy5-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY5 pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-5]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input ports for receiving CSI data on CSIPHY 0-5. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@ad27000 { + compatible = "qcom,sm8750-camss"; + + reg = <0x0 0x0ad27000 0x0 0x2b00>, + <0x0 0x0ad2a000 0x0 0x2b00>, + <0x0 0x0ad2d000 0x0 0x2b00>, + <0x0 0x0ad6d000 0x0 0xa00>, + <0x0 0x0ad72000 0x0 0xa00>, + <0x0 0x0ada9000 0x0 0x2000>, + <0x0 0x0adab000 0x0 0x2000>, + <0x0 0x0adad000 0x0 0x2000>, + <0x0 0x0adaf000 0x0 0x2000>, + <0x0 0x0adb1000 0x0 0x2000>, + <0x0 0x0adb3000 0x0 0x2000>, + <0x0 0x0ad8b000 0x0 0x400>, + <0x0 0x0ad8c000 0x0 0x400>, + <0x0 0x0ad8d000 0x0 0x400>, + <0x0 0x0ac86000 0x0 0x10000>, + <0x0 0x0ac96000 0x0 0x10000>, + <0x0 0x0aca6000 0x0 0x10000>, + <0x0 0x0ad6e000 0x0 0x3000>, + <0x0 0x0ad73000 0x0 0x3000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + vdd-csiphy0-0p9-supply = <&vreg_0p9_supply>; + vdd-csiphy0-1p2-supply = <&vreg_1p2_supply>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy_ep0: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; From 2a8fb9a7df3b6f3578c3700f67b3a8c4b2b0bc76 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Tue, 12 May 2026 21:49:27 -0700 Subject: [PATCH 0104/1133] FROMLIST: media: qcom: camss: Add SM8750 compatible camss driver Add SM8750 platform support to the CAMSS driver with ICC bandwidth resources and device tree match entry. Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-2-fc6861a65c67@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/camss.c | 22 ++++++++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 23 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index d8ed597f4138e..855e0dbc0f112 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4449,6 +4449,20 @@ static const struct resources_icc icc_res_sa8775p[] = { }, }; +static const struct resources_icc icc_res_sm8750[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + /* Based on 4096 x 3072 30 FPS 2496 Mbps mode */ + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 471860, + .icc_bw_tbl.peak = 925857, + }, +}; + static const struct camss_subdev_resources csiphy_res_x1e80100[] = { /* CSIPHY0 */ { @@ -6332,6 +6346,13 @@ static const struct camss_resources sm8650_resources = { .vfe_num = ARRAY_SIZE(vfe_res_sm8650), }; +static const struct camss_resources sm8750_resources = { + .version = CAMSS_8750, + .pd_name = "top", + .icc_res = icc_res_sm8750, + .icc_path_num = ARRAY_SIZE(icc_res_sm8750), +}; + static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", @@ -6381,6 +6402,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sm8250-camss", .data = &sm8250_resources }, { .compatible = "qcom,sm8550-camss", .data = &sm8550_resources }, { .compatible = "qcom,sm8650-camss", .data = &sm8650_resources }, + { .compatible = "qcom,sm8750-camss", .data = &sm8750_resources }, { .compatible = "qcom,x1e80100-camss", .data = &x1e80100_resources }, { .compatible = "qcom,glymur-camss", .data = &x1e80100_resources }, { .compatible = "qcom,x1p42100-camss", .data = &x1p42100_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 50d68a6036846..7914b636ad348 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -95,6 +95,7 @@ enum camss_version { CAMSS_845, CAMSS_8550, CAMSS_8650, + CAMSS_8750, CAMSS_8775P, CAMSS_KAANAPALI, CAMSS_X1E80100, From 5a51ff4c4d2ba5b5035e2d5c8c01126a1d978d0a Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:05 -0700 Subject: [PATCH 0105/1133] FROMLIST: media: qcom: camss: csiphy: Add support for v2.3.0 two-phase CSIPHY Add more detailed resource information for CSIPHY devices in the camss driver along with the support for v2.3.0 in the 2 phase CSIPHY driver that is responsible for the PHY lane register configuration, module reset and interrupt handling. Additionally, generalize the struct name for the lane configuration that had been added for Kaanapali and use it for SM8750 as well as they share the settings. Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-3-fc6861a65c67@oss.qualcomm.com/ --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 5 +- drivers/media/platform/qcom/camss/camss.c | 125 ++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index 795b333185e54..1c787036d47b3 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -804,7 +804,7 @@ csiphy_lane_regs lane_regs_sm8650[] = { {0x0c10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, }; -/* 3nm 2PH v 2.4.0 2p5Gbps 4 lane DPHY mode */ +/* 3nm 2PH v 2.3.0/2.4.0 2p5Gbps 4 lane DPHY mode */ static const struct csiphy_lane_regs lane_regs_2_4_0[] = { /* LN 0 */ @@ -1256,6 +1256,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: @@ -1377,7 +1378,9 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sa8775p[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); break; + case CAMSS_8750: case CAMSS_KAANAPALI: + /* CSPHY v2.4.0 is backward compatible with v2.3.0 settings */ regs->lane_regs = &lane_regs_2_4_0[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_2_4_0); regs->offset = 0x1000; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 855e0dbc0f112..5de6f1ef6340c 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4449,6 +4449,129 @@ static const struct resources_icc icc_res_sa8775p[] = { }, }; +static const struct camss_subdev_resources csiphy_res_8750[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdd-csiphy0-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy0-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy0", "csiphy0_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdd-csiphy1-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy1-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy1", "csiphy1_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY2 */ + { + .regulators = { + { .supply = "vdd-csiphy2-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy2-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy2", "csiphy2_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY3 */ + { + .regulators = { + { .supply = "vdd-csiphy3-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy3-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy3", "csiphy3_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY4 */ + { + .regulators = { + { .supply = "vdd-csiphy4-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy4-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy4", "csiphy4_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY5 */ + { + .regulators = { + { .supply = "vdd-csiphy5-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy5-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy5", "csiphy5_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy5" }, + .interrupt = { "csiphy5" }, + .csiphy = { + .id = 5, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, +}; + static const struct resources_icc icc_res_sm8750[] = { { .name = "ahb", @@ -6349,7 +6472,9 @@ static const struct camss_resources sm8650_resources = { static const struct camss_resources sm8750_resources = { .version = CAMSS_8750, .pd_name = "top", + .csiphy_res = csiphy_res_8750, .icc_res = icc_res_sm8750, + .csiphy_num = ARRAY_SIZE(csiphy_res_8750), .icc_path_num = ARRAY_SIZE(icc_res_sm8750), }; From 21fd69df507c1d963bc1c1f7f981350465847487 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:06 -0700 Subject: [PATCH 0106/1133] FROMLIST: media: qcom: camss: csid: Add support for CSID 980 Add more detailed resource information for CSID devices along with the driver for CSID 980 that is responsible for CSID register configuration, module reset and IRQ handling for BUF_DONE events. In SM8750, RUP and AUP updates for the CSID Full modules are split into two registers along with a SET register. However, CSID Lite modules still use a single register to update RUP and AUP without the additional SET register. Handled such differences in the driver. Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-4-fc6861a65c67@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/Makefile | 1 + .../platform/qcom/camss/camss-csid-980.c | 442 ++++++++++++++++++ .../media/platform/qcom/camss/camss-csid.h | 1 + drivers/media/platform/qcom/camss/camss.c | 75 +++ 4 files changed, 519 insertions(+) create mode 100644 drivers/media/platform/qcom/camss/camss-csid-980.c diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index 3ecb13f644409..247e78b0bc0d3 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -8,6 +8,7 @@ qcom-camss-objs += \ camss-csid-4-7.o \ camss-csid-340.o \ camss-csid-680.o \ + camss-csid-980.o \ camss-csid-gen2.o \ camss-csid-gen3.o \ camss-csid-gen4.o \ diff --git a/drivers/media/platform/qcom/camss/camss-csid-980.c b/drivers/media/platform/qcom/camss/camss-csid-980.c new file mode 100644 index 0000000000000..79eb063000b8d --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-980.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-csid-980.c + * + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include +#include +#include +#include +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen3.h" + +/* Reset and Command Registers */ +#define CSID_RST_CFG 0xC +#define RST_MODE BIT(0) +#define RST_LOCATION BIT(4) + +/* Reset and Command Registers */ +#define CSID_RST_CMD 0x10 +#define SELECT_HW_RST BIT(0) +#define SELECT_IRQ_RST BIT(2) +#define CSID_IRQ_CMD 0x14 +#define IRQ_CMD_CLEAR BIT(0) + +/* Register Update Commands, RUP/AUP */ +#define CSID_RUP_CMD 0x18 +#define CSID_AUP_CMD 0x1C +#define CSID_RUP_AUP_RDI(rdi) (BIT(8) << (rdi)) +#define CSID_RUP_AUP_CMD 0x20 +#define RUP_SET BIT(0) +#define MUP BIT(4) + +#define CSID_LITE_RUP_AUP_CMD 0x18 +#define CSID_LITE_RUP_RDI(rdi) (BIT(4) << (rdi)) +#define CSID_LITE_AUP_RDI(rdi) (BIT(20) << (rdi)) + +/* Top level interrupt registers */ +#define CSID_TOP_IRQ_STATUS (csid_is_lite(csid) ? 0x7C : 0x84) +#define CSID_TOP_IRQ_MASK (csid_is_lite(csid) ? 0x80 : 0x88) +#define CSID_TOP_IRQ_CLEAR (csid_is_lite(csid) ? 0x84 : 0x8C) +#define CSID_TOP_IRQ_SET (csid_is_lite(csid) ? 0x88 : 0x90) +#define INFO_RST_DONE BIT(0) +#define CSI2_RX_IRQ_STATUS BIT(2) +#define BUF_DONE_IRQ_STATUS BIT(csid_is_lite(csid) ? 13 : 3) + +/* Buffer done interrupt registers */ +#define CSID_BUF_DONE_IRQ_STATUS (csid_is_lite(csid) ? 0x8C : 0xA4) +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET (csid_is_lite(csid) ? 1 : 16) +#define CSID_BUF_DONE_IRQ_MASK (csid_is_lite(csid) ? 0x90 : 0xA8) +#define CSID_BUF_DONE_IRQ_CLEAR (csid_is_lite(csid) ? 0x94 : 0xAC) +#define CSID_BUF_DONE_IRQ_SET (csid_is_lite(csid) ? 0x98 : 0xB0) + +/* CSI2 RX interrupt registers */ +#define CSID_CSI2_RX_IRQ_STATUS (csid_is_lite(csid) ? 0x9C : 0xB4) +#define CSID_CSI2_RX_IRQ_MASK (csid_is_lite(csid) ? 0xA0 : 0xB8) +#define CSID_CSI2_RX_IRQ_CLEAR (csid_is_lite(csid) ? 0xA4 : 0xBC) +#define CSID_CSI2_RX_IRQ_SET (csid_is_lite(csid) ? 0xA8 : 0xC0) + +/* CSI2 RX Configuration */ +#define CSID_CSI2_RX_CFG0 (csid_is_lite(csid) ? 0x200 : 0x400) +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_DL0_INPUT_SEL 4 +#define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSID_CSI2_RX_CFG1 (csid_is_lite(csid) ? 0x204 : 0x404) +#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_VC_MODE BIT(2) + +#define MSM_CSID_MAX_SRC_STREAMS_980 (csid_is_lite(csid) ? 4 : 5) + +#define CSID_RDI_CFG0(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x500 + 0x100 * _rdi : \ + 0xE00 + 0x200 * _rdi; \ + }) +#define RDI_CFG0_RETIME_BS BIT(5) +#define RDI_CFG0_TIMESTAMP_EN BIT(6) +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) +#define RDI_CFG0_DECODE_FORMAT 12 +#define RDI_CFG0_DT 16 +#define RDI_CFG0_VC 22 +#define RDI_CFG0_DT_ID 27 +#define RDI_CFG0_EN BIT(31) + +/* RDI Control and Configuration */ +#define CSID_RDI_CTRL(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x504 + 0x100 * _rdi : \ + 0xE04 + 0x200 * _rdi; \ + }) +#define RDI_CTRL_START_CMD BIT(0) + +#define CSID_RDI_CFG1(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x510 + 0x100 * _rdi : \ + 0xE10 + 0x200 * _rdi; \ + }) +#define RDI_CFG1_DROP_H_EN BIT(5) +#define RDI_CFG1_DROP_V_EN BIT(6) +#define RDI_CFG1_CROP_H_EN BIT(7) +#define RDI_CFG1_CROP_V_EN BIT(8) +#define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) + +/* RDI Pixel Store Configuration */ +#define CSID_RDI_PIX_STORE_CFG0(rdi) (0xE14 + 0x200 * (rdi)) +#define RDI_PIX_STORE_CFG0_EN BIT(0) +#define RDI_PIX_STORE_CFG0_MIN_HBI 1 + +/* RDI IRQ Status in wrapper */ +#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) \ + (csid_is_lite(csid) ? 0xEC : 0x114 + 0x10 * (rdi)) +#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) \ + (csid_is_lite(csid) ? 0xF4 : 0x11C + 0x10 * (rdi)) +#define INFO_RUP_DONE BIT(23) + +static void __csid_full_aup_rup_trigger(struct csid_device *csid) +{ + /* trigger SET in combined register */ + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD); +} + +static void __csid_aup_update(struct csid_device *csid, int port_id) +{ + if (csid_is_lite(csid)) { + /* CSID Lites in v980 follow the legacy way of a combined RUP + * and AUP commands without an explicit SET register. + */ + csid->reg_update |= CSID_LITE_AUP_RDI(port_id); + writel(csid->reg_update, csid->base + CSID_LITE_RUP_AUP_CMD); + } else { + csid->aup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->aup_update, csid->base + CSID_AUP_CMD); + + /* CSID Fulls in v980 split AUP and RUP commands, which requires + * additional SET operation to make registers modification take + * effect. + */ + __csid_full_aup_rup_trigger(csid); + } +} + +static void __csid_rup_update(struct csid_device *csid, int port_id) +{ + if (csid_is_lite(csid)) { + /* CSID Lites in v980 follow the legacy way of a combined RUP + * and AUP commands without an explicit SET register. + */ + csid->reg_update |= CSID_LITE_RUP_RDI(port_id); + writel(csid->reg_update, csid->base + CSID_LITE_RUP_AUP_CMD); + } else { + csid->rup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->rup_update, csid->base + CSID_RUP_CMD); + + /* CSID Fulls in v980 split AUP and RUP commands, which requires + * additional SET operation to make registers modification take + * effect. + */ + __csid_full_aup_rup_trigger(csid); + } +} + +static void __csid_aup_rup_clear(struct csid_device *csid, int port_id) +{ + /* Hardware clears the registers upon consuming the settings */ + if (csid_is_lite(csid)) { + csid->reg_update &= ~CSID_LITE_RUP_RDI(port_id); + csid->reg_update &= ~CSID_LITE_AUP_RDI(port_id); + } else { + csid->aup_update &= ~CSID_RUP_AUP_RDI(port_id); + csid->rup_update &= ~CSID_RUP_AUP_RDI(port_id); + } +} + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy) +{ + int val; + + val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; + val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; + val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) + << CSI2_RX_CFG0_PHY_NUM_SEL; + writel(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_ECC_CORRECTION_EN; + writel(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_configure_rx_vc(struct csid_device *csid, int vc) +{ + int val; + + if (vc > 3) { + val = readl(csid->base + CSID_CSI2_RX_CFG1); + val |= CSI2_RX_CFG1_VC_MODE; + writel(val, csid->base + CSID_CSI2_RX_CFG1); + } +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + int val = 0; + u32 rdi_ctrl_offset = CSID_RDI_CTRL(rdi); + + if (enable) + val = RDI_CTRL_START_CMD; + + writel(val, csid->base + rdi_ctrl_offset); +} + +static void __csid_configure_rdi_pix_store(struct csid_device *csid, u8 rdi) +{ + u32 val; + + /* + * Configure pixel store to allow absorption of hblanking or idle time. + * This helps with horizontal crop and prevents line buffer conflicts. + * Reset state is 0x8 which has MIN_HBI=4, we keep the default MIN_HBI + * and just enable the pixel store functionality. + */ + val = (4 << RDI_PIX_STORE_CFG0_MIN_HBI) | RDI_PIX_STORE_CFG0_EN; + writel(val, csid->base + CSID_RDI_PIX_STORE_CFG0(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc) +{ + u32 val; + u8 lane_cnt = csid->phy.lane_cnt; + + /* Source pads matching RDI channels on hardware. + * E.g. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. + */ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + + if (!lane_cnt) + lane_cnt = 4; + + /* + * DT_ID is a two bit bitfield that is concatenated with + * the four least significant bits of the five bit VC + * bitfield to generate an internal CID value. + * + * CSID_RDI_CFG0(vc) + * DT_ID : 28:27 + * VC : 26:22 + * DT : 21:16 + * + * CID : VC 3:0 << 2 | DT_ID 1:0 + */ + u8 dt_id = vc & 0x03; + u32 rdi_cfg0_offset = CSID_RDI_CFG0(port); + u32 rdi_cfg1_offset = CSID_RDI_CFG1(port); + u32 rdi_ctrl_offset = CSID_RDI_CTRL(port); + + val = RDI_CFG0_TIMESTAMP_EN; + val |= RDI_CFG0_TIMESTAMP_STB_SEL; + val |= RDI_CFG0_RETIME_BS; + + /* note: for non-RDI path, this should be format->decode_format */ + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; + val |= vc << RDI_CFG0_VC; + val |= format->data_type << RDI_CFG0_DT; + val |= dt_id << RDI_CFG0_DT_ID; + writel(val, csid->base + rdi_cfg0_offset); + + val = RDI_CFG1_PACKING_FORMAT_MIPI; + writel(val, csid->base + rdi_cfg1_offset); + + /* Configure pixel store using dedicated register in 980 */ + if (!csid_is_lite(csid)) + __csid_configure_rdi_pix_store(csid, port); + + val = 0; + writel(val, csid->base + rdi_ctrl_offset); + + val = readl(csid->base + rdi_cfg0_offset); + + if (enable) + val |= RDI_CFG0_EN; + + writel(val, csid->base + rdi_cfg0_offset); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + u8 i, k; + + __csid_configure_rx(csid, &csid->phy); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i, 0); + __csid_configure_rx_vc(csid, 0); + + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++) { + __csid_aup_update(csid, i); + __csid_rup_update(csid, i); + } + + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return 0; +} + +static void csid_subdev_reg_update(struct csid_device *csid, int port_id, + bool clear) +{ + if (clear) + __csid_aup_rup_clear(csid, port_id); + else + __csid_aup_update(csid, port_id); +} + +/** + * csid_isr - CSID module interrupt service routine + * @irq: Interrupt line + * @dev: CSID device + * + * Return IRQ_HANDLED on success + */ +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val, buf_done_val; + u8 reset_done; + int i; + + val = readl(csid->base + CSID_TOP_IRQ_STATUS); + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + + reset_done = val & INFO_RST_DONE; + + buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS); + writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); + writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); + + if (val & INFO_RUP_DONE) + csid_subdev_reg_update(csid, i, true); + + if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) + camss_buf_done(csid->camss, csid->id, i); + } + } + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + if (reset_done) + complete(&csid->reset_complete); + + return IRQ_HANDLED; +} + +/** + * csid_reset - Trigger reset on CSID module and wait to complete + * @csid: CSID device + * + * Return 0 on success or a negative error code otherwise + */ +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + u32 val; + int i; + + reinit_completion(&csid->reset_complete); + + val = INFO_RST_DONE | BUF_DONE_IRQ_STATUS; + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + writel(val, csid->base + CSID_TOP_IRQ_MASK); + + val = 0; + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + /* + * Only need to clear buf done IRQ status here, + * RUP done IRQ status will be cleared once isr + * strobe generated by CSID_RST_CMD + */ + val |= BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i); + } + } + writel(val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + writel(val, csid->base + CSID_BUF_DONE_IRQ_MASK); + + /* Clear all IRQ status with CLEAR bits set */ + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + val = RST_LOCATION | RST_MODE; + writel(val, csid->base + CSID_RST_CFG); + + val = SELECT_HW_RST | SELECT_IRQ_RST; + writel(val, csid->base + CSID_RST_CMD); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + + if (!time) { + dev_err(csid->camss->dev, "CSID reset timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void csid_subdev_init(struct csid_device *csid) +{ + csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; +} + +const struct csid_hw_ops csid_ops_980 = { + .configure_stream = csid_configure_stream, + .configure_testgen_pattern = csid_configure_testgen_pattern, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, + .reg_update = csid_subdev_reg_update, +}; + diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index e6590b2bd8be5..dd9c0868e9c73 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -224,6 +224,7 @@ extern const struct csid_hw_ops csid_ops_4_1; extern const struct csid_hw_ops csid_ops_4_7; extern const struct csid_hw_ops csid_ops_340; extern const struct csid_hw_ops csid_ops_680; +extern const struct csid_hw_ops csid_ops_980; extern const struct csid_hw_ops csid_ops_gen2; extern const struct csid_hw_ops csid_ops_gen3; extern const struct csid_hw_ops csid_ops_gen4; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 5de6f1ef6340c..bf1a088968fca 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4572,6 +4572,79 @@ static const struct camss_subdev_resources csiphy_res_8750[] = { }, }; +static const struct camss_subdev_resources csid_res_8750[] = { + /* CSID0 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE1 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + } +}; + static const struct resources_icc icc_res_sm8750[] = { { .name = "ahb", @@ -6473,8 +6546,10 @@ static const struct camss_resources sm8750_resources = { .version = CAMSS_8750, .pd_name = "top", .csiphy_res = csiphy_res_8750, + .csid_res = csid_res_8750, .icc_res = icc_res_sm8750, .csiphy_num = ARRAY_SIZE(csiphy_res_8750), + .csid_num = ARRAY_SIZE(csid_res_8750), .icc_path_num = ARRAY_SIZE(icc_res_sm8750), }; From b1109982e1d7a7effcfa4baa4d2701085ee6cbde Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:07 -0700 Subject: [PATCH 0107/1133] FROMLIST: media: qcom: camss: vfe: Add support for VFE 980 Add support for Video Front End (VFE) that is on the SM8750 SoCs. VFE gen4 has support for VFE 980. This change limits SM8750 VFE output lines to 3 for now as constrained by the CAMSS driver framework. Reviewed-by: Bryan O'Donoghue Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-5-fc6861a65c67@oss.qualcomm.com/ --- .../platform/qcom/camss/camss-vfe-gen4.c | 10 +- drivers/media/platform/qcom/camss/camss-vfe.c | 2 + drivers/media/platform/qcom/camss/camss.c | 135 ++++++++++++++++++ 3 files changed, 144 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c index d73d70898710a..46d8e61b9bac0 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c @@ -13,8 +13,12 @@ #include "camss.h" #include "camss-vfe.h" -/* VFE-gen4 Bus Register Base Addresses */ -#define BUS_REG_BASE (vfe_is_lite(vfe) ? 0x800 : 0x1000) +#define IS_VFE_980(vfe) ((vfe)->camss->res->version == CAMSS_8750) + +#define BUS_REG_BASE_980 (vfe_is_lite(vfe) ? 0x200 : 0x800) +#define BUS_REG_BASE_1080 (vfe_is_lite(vfe) ? 0x800 : 0x1000) +#define BUS_REG_BASE \ + (IS_VFE_980(vfe) ? BUS_REG_BASE_980 : BUS_REG_BASE_1080) #define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) #define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) @@ -55,7 +59,7 @@ * DISPLAY_DS2_C 6 * FD_Y 7 * FD_C 8 - * PIXEL_RAW 9 + * RAW_OUT(1080)/IR_OUT(980) 9 * STATS_AEC_BG 10 * STATS_AEC_BHIST 11 * STATS_TINTLESS_BG 12 diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 2c246632ed18d..303a47cb51c9a 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -352,6 +352,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: @@ -2017,6 +2018,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index bf1a088968fca..520b5440f72f4 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4645,6 +4645,139 @@ static const struct camss_subdev_resources csid_res_8750[] = { } }; +static const struct camss_subdev_resources vfe_res_8750[] = { + /* VFE0 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe0_fast_ahb", "vfe0", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe1_fast_ahb", "vfe1", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe2_fast_ahb", "vfe2", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE0 */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE1 */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + } +}; + static const struct resources_icc icc_res_sm8750[] = { { .name = "ahb", @@ -6547,9 +6680,11 @@ static const struct camss_resources sm8750_resources = { .pd_name = "top", .csiphy_res = csiphy_res_8750, .csid_res = csid_res_8750, + .vfe_res = vfe_res_8750, .icc_res = icc_res_sm8750, .csiphy_num = ARRAY_SIZE(csiphy_res_8750), .csid_num = ARRAY_SIZE(csid_res_8750), + .vfe_num = ARRAY_SIZE(vfe_res_8750), .icc_path_num = ARRAY_SIZE(icc_res_sm8750), }; From 80c366505f598347d294100a2aa85da663f08ef3 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Thu, 3 Sep 2026 15:22:56 +0800 Subject: [PATCH 0108/1133] FROMLIST: dt-bindings: media: Add bindings for qcom,nord-camss Add bindings for the camera subsystem (CAMSS) on the Qualcomm Nord platform. The Nord platform provides: - 3 x TPG (Test Pattern Generator) - 3 x CSID (CSI Decoder) - 10 x CSID Lite - 3 x VFE (Video Front End) - 10 x VFE Lite Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/all/20260915-nord-v1-1-20db41a7f1ff@oss.qualcomm.com/ --- .../bindings/media/qcom,nord-camss.yaml | 393 ++++++++++++++++++ 1 file changed, 393 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,nord-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,nord-camss.yaml b/Documentation/devicetree/bindings/media/qcom,nord-camss.yaml new file mode 100644 index 0000000000000..93dbb55e1a974 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,nord-camss.yaml @@ -0,0 +1,393 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,nord-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Nord Camera Subsystem (CAMSS) + +maintainers: + - Wenmeng Liu + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,nord-camss + + reg: + maxItems: 29 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_lite2 + - const: csid_lite3 + - const: csid_lite4 + - const: csid_lite5 + - const: csid_lite6 + - const: csid_lite7 + - const: csid_lite8 + - const: csid_lite9 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + - const: vfe_lite2 + - const: vfe_lite3 + - const: vfe_lite4 + - const: vfe_lite5 + - const: vfe_lite6 + - const: vfe_lite7 + - const: vfe_lite8 + - const: vfe_lite9 + + clocks: + maxItems: 22 + + clock-names: + items: + - const: camnoc_rt_axi + - const: csid + - const: csid_csiphy_rx + - const: gcc_axi_hf + - const: top_ahb + - const: top_fast_ahb + - const: top_ife0 + - const: top_ife1 + - const: top_ife2 + - const: top_ife_lite + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe2 + - const: vfe2_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + - const: tpg_csiphy_rx + - const: qdss_debug_xo + + interrupts: + maxItems: 26 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_lite2 + - const: csid_lite3 + - const: csid_lite4 + - const: csid_lite5 + - const: csid_lite6 + - const: csid_lite7 + - const: csid_lite8 + - const: csid_lite9 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + - const: vfe_lite2 + - const: vfe_lite3 + - const: vfe_lite4 + - const: vfe_lite5 + - const: vfe_lite6 + - const: vfe_lite7 + - const: vfe_lite8 + - const: vfe_lite9 + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + + iommus: + maxItems: 2 + + power-domains: + items: + - description: IFE0 GDSC - Image Front End, Global Distributed Switch Controller. + - description: IFE1 GDSC - Image Front End, Global Distributed Switch Controller. + - description: IFE2 GDSC - Image Front End, Global Distributed Switch Controller. + - description: Titan Top GDSC - Titan ISP Block, Global Distributed Switch Controller. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: ife2 + - const: top + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-4]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + + description: + Input port for receiving CSI data. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@9b32000 { + compatible = "qcom,nord-camss"; + + reg = <0 0x09b32000 0 0x2000>, + <0 0x09b38800 0 0x2000>, + <0 0x09b3f000 0 0x2000>, + <0 0x09c32000 0 0x1000>, + <0 0x09c37000 0 0x1000>, + <0 0x09c3c000 0 0x1000>, + <0 0x09c41000 0 0x1000>, + <0 0x09c46000 0 0x1000>, + <0 0x09c4b000 0 0x1000>, + <0 0x09c50000 0 0x1000>, + <0 0x09c55000 0 0x1000>, + <0 0x09c5a000 0 0x1000>, + <0 0x09c5f000 0 0x1000>, + <0 0x09a92000 0 0x400>, + <0 0x09a93000 0 0x400>, + <0 0x09a94000 0 0x400>, + <0 0x09ab1000 0 0x4000>, + <0 0x09ad1000 0 0x4000>, + <0 0x09af1000 0 0x4000>, + <0 0x09c34000 0 0x2000>, + <0 0x09c39000 0 0x2000>, + <0 0x09c3e000 0 0x2000>, + <0 0x09c43000 0 0x2000>, + <0 0x09c48000 0 0x2000>, + <0 0x09c4d000 0 0x2000>, + <0 0x09c52000 0 0x2000>, + <0 0x09c57000 0 0x2000>, + <0 0x09c5c000 0 0x2000>, + <0 0x09c61000 0 0x2000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_lite2", + "csid_lite3", + "csid_lite4", + "csid_lite5", + "csid_lite6", + "csid_lite7", + "csid_lite8", + "csid_lite9", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1", + "vfe_lite2", + "vfe_lite3", + "vfe_lite4", + "vfe_lite5", + "vfe_lite6", + "vfe_lite7", + "vfe_lite8", + "vfe_lite9"; + + clocks = <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&nwgcc NW_GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_TOP_AHB_CLK>, + <&camcc CAM_CC_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_TOP_IFE_0_CLK>, + <&camcc CAM_CC_TOP_IFE_1_CLK>, + <&camcc CAM_CC_TOP_IFE_2_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_0_MAIN_CLK>, + <&camcc CAM_CC_IFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_MAIN_CLK>, + <&camcc CAM_CC_IFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_2_MAIN_CLK>, + <&camcc CAM_CC_IFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_TPG_CSIPHY_RX_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + + clock-names = "camnoc_rt_axi", + "csid", + "csid_csiphy_rx", + "gcc_axi_hf", + "top_ahb", + "top_fast_ahb", + "top_ife0", + "top_ife1", + "top_ife2", + "top_ife_lite", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "tpg_csiphy_rx", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_lite2", + "csid_lite3", + "csid_lite4", + "csid_lite5", + "csid_lite6", + "csid_lite7", + "csid_lite8", + "csid_lite9", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1", + "vfe_lite2", + "vfe_lite3", + "vfe_lite4", + "vfe_lite5", + "vfe_lite6", + "vfe_lite7", + "vfe_lite8", + "vfe_lite9"; + + interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + + interconnect-names = "ahb", + "hf_mnoc"; + + iommus = <&apps_smmu_2 0x1401 0x20>, + <&apps_smmu_2 0x1460 0x00>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_IFE_1_GDSC>, + <&camcc CAM_CC_IFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; From 207e72a4562f0d788e6ed1cde5a64d0c0c9624b5 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Thu, 3 Sep 2026 15:23:37 +0800 Subject: [PATCH 0109/1133] FROMLIST: media: qcom: camss: csid: Add support for CSID 900 Add a CSID driver for the "900" revision on the Nord SoC. It shares the CSI-2 RX helpers and the split RUP/AUP model of the gen3/980 lineage, but the register offsets differ across the map and the RUP/AUP command uses separate accumulator/trigger registers with a per-buffer AUP enqueue, so add a separate file rather than overload the gen3 offset macros with another SoC conditional. The write master buffers are enqueued to the CSID: for every enabled RDI an AUP_UPDATE is issued once per initial buffer, followed by a single RUP_UPDATE, matching the number of buffers handed to the write master when it is enabled. Nord has 3 CSID and 10 CSID Lite instances, all driven by csid_ops_900. Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/all/20260915-nord-v1-2-20db41a7f1ff@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/Makefile | 1 + .../platform/qcom/camss/camss-csid-900.c | 361 ++++++++++++++++++ .../media/platform/qcom/camss/camss-csid.h | 1 + 3 files changed, 363 insertions(+) create mode 100644 drivers/media/platform/qcom/camss/camss-csid-900.c diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index 247e78b0bc0d3..06b323d95f855 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -8,6 +8,7 @@ qcom-camss-objs += \ camss-csid-4-7.o \ camss-csid-340.o \ camss-csid-680.o \ + camss-csid-900.o \ camss-csid-980.o \ camss-csid-gen2.o \ camss-csid-gen3.o \ diff --git a/drivers/media/platform/qcom/camss/camss-csid-900.c b/drivers/media/platform/qcom/camss/camss-csid-900.c new file mode 100644 index 0000000000000..c7bb3783eddb7 --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-900.c @@ -0,0 +1,361 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-csid-900.c + * + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module 900 + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include +#include +#include +#include +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen3.h" + +#define CSID_RST_CFG 0xC +#define RST_MODE BIT(0) +#define RST_LOCATION BIT(4) + +#define CSID_RST_CMD 0x10 +#define SELECT_HW_RST BIT(0) +#define SELECT_IRQ_RST BIT(2) +#define CSID_IRQ_CMD 0x14 +#define IRQ_CMD_CLEAR BIT(0) + +#define CSID_RUP_CMD 0x18 +#define CSID_AUP_CMD 0x1C +#define CSID_RUP_AUP_RDI(rdi) (BIT(8) << (rdi)) +#define CSID_RUP_AUP_CMD 0x20 +#define RUP_SET BIT(0) +#define MUP BIT(4) + +#define CSID_TOP_IRQ_STATUS 0x84 +#define CSID_TOP_IRQ_MASK 0x88 +#define CSID_TOP_IRQ_CLEAR 0x8C +#define CSID_TOP_IRQ_SET 0x90 +#define INFO_RST_DONE BIT(0) +#define CSI2_RX_IRQ_STATUS BIT(2) +#define BUF_DONE_IRQ_STATUS BIT(3) + +#define CSID_BUF_DONE_IRQ_STATUS 0xA4 +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET 16 +#define CSID_BUF_DONE_IRQ_MASK 0xA8 +#define CSID_BUF_DONE_IRQ_CLEAR 0xAC +#define CSID_BUF_DONE_IRQ_SET 0xB0 + +#define CSID_CSI2_RX_IRQ_STATUS 0xB4 +#define CSID_CSI2_RX_IRQ_MASK 0xB8 +#define CSID_CSI2_RX_IRQ_CLEAR 0xBC +#define CSID_CSI2_RX_IRQ_SET 0xC0 + +#define CSID_CSI2_RX_CFG0 0x400 +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_DL0_INPUT_SEL 4 +#define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 +#define CSI2_RX_CFG0_TPG_MUX_EN BIT(27) +#define CSI2_RX_CFG0_TPG_MUX_SEL GENMASK(29, 28) +#define CSID_CSI2_RX_CFG1 0x404 +#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_VC_MODE BIT(2) + +#define MSM_CSID_MAX_SRC_STREAMS_900 (csid_is_lite(csid) ? 4 : 5) + +#define CSID_RDI_BASE (csid_is_lite(csid) ? 0x600 : 0x1300) +#define CSID_RDI_CFG0(rdi) (CSID_RDI_BASE + 0x0 + 0x200 * (rdi)) +#define RDI_CFG0_RETIME_DIS BIT(5) +#define RDI_CFG0_TIMESTAMP_EN BIT(6) +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) +#define RDI_CFG0_DECODE_FORMAT 12 +#define RDI_CFG0_DT 16 +#define RDI_CFG0_VC 22 +#define RDI_CFG0_DT_ID 27 +#define RDI_CFG0_EN BIT(31) + +#define CSID_RDI_CTRL(rdi) (CSID_RDI_BASE + 0x4 + 0x200 * (rdi)) +#define RDI_CTRL_START_CMD BIT(0) + +#define CSID_RDI_CFG1(rdi) (CSID_RDI_BASE + 0x10 + 0x200 * (rdi)) +#define RDI_CFG1_DROP_H_EN BIT(5) +#define RDI_CFG1_DROP_V_EN BIT(6) +#define RDI_CFG1_CROP_H_EN BIT(7) +#define RDI_CFG1_CROP_V_EN BIT(8) +#define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) + +#define CSID_RDI_PIX_STORE_CFG0(rdi) (CSID_RDI_BASE + 0x14 + 0x200 * (rdi)) +#define RDI_PIX_STORE_CFG0_EN BIT(0) +#define RDI_PIX_STORE_CFG0_MIN_HBI 1 + +#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) (0x114 + 0x10 * (rdi)) +#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) (0x11C + 0x10 * (rdi)) +#define INFO_RUP_DONE BIT(23) + +static void __csid_aup_rup_trigger(struct csid_device *csid) +{ + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD); +} + +static void __csid_aup_update(struct csid_device *csid, int port_id) +{ + csid->aup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->aup_update, csid->base + CSID_AUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_rup_update(struct csid_device *csid, int port_id) +{ + csid->rup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->rup_update, csid->base + CSID_RUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_aup_rup_clear(struct csid_device *csid, int port_id) +{ + csid->aup_update &= ~CSID_RUP_AUP_RDI(port_id); + csid->rup_update &= ~CSID_RUP_AUP_RDI(port_id); +} + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy) +{ + struct camss *camss = csid->camss; + int val; + + val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; + val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; + + if (camss->tpg && csid->tpg_linked && + camss->tpg[phy->csiphy_id].testgen.mode != TPG_PAYLOAD_MODE_DISABLED) { + val |= FIELD_PREP(CSI2_RX_CFG0_TPG_MUX_SEL, phy->csiphy_id + 1); + val |= CSI2_RX_CFG0_TPG_MUX_EN; + } else { + val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) + << CSI2_RX_CFG0_PHY_NUM_SEL; + } + writel(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_ECC_CORRECTION_EN; + writel(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_configure_rx_vc(struct csid_device *csid, int vc) +{ + int val; + + if (vc > 3) { + val = readl(csid->base + CSID_CSI2_RX_CFG1); + val |= CSI2_RX_CFG1_VC_MODE; + writel(val, csid->base + CSID_CSI2_RX_CFG1); + } +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + int val = 0; + u32 rdi_ctrl_offset = CSID_RDI_CTRL(rdi); + + if (enable) + val = RDI_CTRL_START_CMD; + + writel(val, csid->base + rdi_ctrl_offset); +} + +static void __csid_configure_rdi_pix_store(struct csid_device *csid, u8 rdi) +{ + u32 val; + + val = (4 << RDI_PIX_STORE_CFG0_MIN_HBI) | RDI_PIX_STORE_CFG0_EN; + writel(val, csid->base + CSID_RDI_PIX_STORE_CFG0(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc) +{ + u32 val; + u8 lane_cnt = csid->phy.lane_cnt; + + /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + + if (!lane_cnt) + lane_cnt = 4; + + /* + * DT_ID is a two bit bitfield that is concatenated with + * the four least significant bits of the five bit VC + * bitfield to generate an internal CID value. + * + * CSID_RDI_CFG0(vc) + * DT_ID : 28:27 + * VC : 26:22 + * DT : 21:16 + * + * CID : VC 3:0 << 2 | DT_ID 1:0 + */ + u8 dt_id = vc & 0x03; + u32 rdi_cfg0_offset = CSID_RDI_CFG0(port); + u32 rdi_cfg1_offset = CSID_RDI_CFG1(port); + u32 rdi_ctrl_offset = CSID_RDI_CTRL(port); + + val = RDI_CFG0_TIMESTAMP_EN; + val |= RDI_CFG0_TIMESTAMP_STB_SEL; + val |= RDI_CFG0_RETIME_DIS; + + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; + val |= vc << RDI_CFG0_VC; + val |= format->data_type << RDI_CFG0_DT; + val |= dt_id << RDI_CFG0_DT_ID; + writel(val, csid->base + rdi_cfg0_offset); + + val = RDI_CFG1_PACKING_FORMAT_MIPI; + writel(val, csid->base + rdi_cfg1_offset); + + if (!csid_is_lite(csid)) + __csid_configure_rdi_pix_store(csid, port); + + val = 0; + writel(val, csid->base + rdi_ctrl_offset); + + val = readl(csid->base + rdi_cfg0_offset); + + if (enable) + val |= RDI_CFG0_EN; + + writel(val, csid->base + rdi_cfg0_offset); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + u8 i, k; + + __csid_configure_rx(csid, &csid->phy); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_900; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i, 0); + __csid_configure_rx_vc(csid, 0); + + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++) + __csid_aup_update(csid, i); + + __csid_rup_update(csid, i); + + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return 0; +} + +static void csid_subdev_reg_update(struct csid_device *csid, int port_id, + bool clear) +{ + if (clear) + __csid_aup_rup_clear(csid, port_id); + else + __csid_aup_update(csid, port_id); +} + +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val, buf_done_val; + u8 reset_done; + int i; + + val = readl(csid->base + CSID_TOP_IRQ_STATUS); + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + + reset_done = val & INFO_RST_DONE; + + buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS); + writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_900; i++) { + if (csid->phy.en_vc & BIT(i)) { + val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); + writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); + + if (val & INFO_RUP_DONE) + csid_subdev_reg_update(csid, i, true); + + if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) + camss_buf_done(csid->camss, csid->id, i); + } + } + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + if (reset_done) + complete(&csid->reset_complete); + + return IRQ_HANDLED; +} + +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + u32 val; + int i; + + reinit_completion(&csid->reset_complete); + + val = INFO_RST_DONE | BUF_DONE_IRQ_STATUS; + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + writel(val, csid->base + CSID_TOP_IRQ_MASK); + + val = 0; + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_900; i++) { + if (csid->phy.en_vc & BIT(i)) + val |= BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i); + } + writel(val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + writel(val, csid->base + CSID_BUF_DONE_IRQ_MASK); + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + val = RST_LOCATION | RST_MODE; + writel(val, csid->base + CSID_RST_CFG); + + val = SELECT_HW_RST | SELECT_IRQ_RST; + writel(val, csid->base + CSID_RST_CMD); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + + if (!time) { + dev_err(csid->camss->dev, "CSID reset timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void csid_subdev_init(struct csid_device *csid) +{ + csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; +} + +const struct csid_hw_ops csid_ops_900 = { + .configure_stream = csid_configure_stream, + .configure_testgen_pattern = csid_configure_testgen_pattern, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, + .reg_update = csid_subdev_reg_update, +}; diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index dd9c0868e9c73..6b04ff77bf459 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -224,6 +224,7 @@ extern const struct csid_hw_ops csid_ops_4_1; extern const struct csid_hw_ops csid_ops_4_7; extern const struct csid_hw_ops csid_ops_340; extern const struct csid_hw_ops csid_ops_680; +extern const struct csid_hw_ops csid_ops_900; extern const struct csid_hw_ops csid_ops_980; extern const struct csid_hw_ops csid_ops_gen2; extern const struct csid_hw_ops csid_ops_gen3; From 1b7c3ca2736482f68102b78d43afaf533b312726 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 16 Sep 2026 17:20:06 +0800 Subject: [PATCH 0110/1133] FROMLIST: media: qcom: camss: vfe: Add support for VFE 900 The VFE on the Nord platform reuses the gen4 VFE driver but places its bus registers at a different base and does not implement the write master CGC override register. Add a VFE 900 variant to the gen4 driver to handle the different bus register base, the separate location of the test bus control register, and to skip the missing CGC override register. In addition, the v900 ADDR_IMAGE register takes a full byte address rather than the 256-byte-unit encoding used by the gen4 baseline, and the full IFE write master client map places the RDI clients at index 28 (the lite instances keep RDI0 at client 0). Convert the gen4 register layout from preprocessor macros to a table-driven vfe_gen4_hw_info, retaining the existing VFE 980 (SM8750) layout as a distinct table entry. Signed-off-by: Wenmeng Liu FROMLIST: https://lore.kernel.org/all/20260915-nord-v1-4-20db41a7f1ff@oss.qualcomm.com/ --- .../platform/qcom/camss/camss-vfe-gen4.c | 118 ++++++++++++++++-- drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 107 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c index 46d8e61b9bac0..5464be5a632b5 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c @@ -13,17 +13,89 @@ #include "camss.h" #include "camss-vfe.h" -#define IS_VFE_980(vfe) ((vfe)->camss->res->version == CAMSS_8750) +struct vfe_gen4_hw_info { + u32 bus_reg_base; + u32 bus_reg_base_lite; + s32 test_bus_ctrl_offset; /* relative to the bus register base */ + u8 rdi_wm_offset; + u8 rdi_wm_offset_lite; + u8 addr_shift; /* ADDR_IMAGE address unit */ + bool has_wm_cgc_override; +}; + +static const struct vfe_gen4_hw_info vfe_900_hw_info = { + .bus_reg_base = 0xA00, + .bus_reg_base_lite = 0x700, + .test_bus_ctrl_offset = -0x1BC, + .rdi_wm_offset = 0x1C, + .rdi_wm_offset_lite = 0x0, + .addr_shift = 0, + .has_wm_cgc_override = false, +}; + +static const struct vfe_gen4_hw_info vfe_980_hw_info = { + .bus_reg_base = 0x800, + .bus_reg_base_lite = 0x200, + .test_bus_ctrl_offset = 0x128, + .rdi_wm_offset = 0x17, + .rdi_wm_offset_lite = 0x0, + .addr_shift = 8, + .has_wm_cgc_override = true, +}; + +static const struct vfe_gen4_hw_info vfe_1080_hw_info = { + .bus_reg_base = 0x1000, + .bus_reg_base_lite = 0x800, + .test_bus_ctrl_offset = 0x128, + .rdi_wm_offset = 0x17, + .rdi_wm_offset_lite = 0x0, + .addr_shift = 8, + .has_wm_cgc_override = true, +}; + +static inline const struct vfe_gen4_hw_info * +vfe_gen4_get_hw_info(struct vfe_device *vfe) +{ + switch (vfe->camss->res->version) { + case CAMSS_NORD: + return &vfe_900_hw_info; + case CAMSS_8750: + return &vfe_980_hw_info; + default: + return &vfe_1080_hw_info; + } +} + +static inline u32 vfe_gen4_bus_reg_base(struct vfe_device *vfe) +{ + const struct vfe_gen4_hw_info *hw_info = vfe_gen4_get_hw_info(vfe); + + return vfe_is_lite(vfe) ? hw_info->bus_reg_base_lite : + hw_info->bus_reg_base; +} + +static inline u32 vfe_gen4_test_bus_ctrl(struct vfe_device *vfe) +{ + const struct vfe_gen4_hw_info *hw_info = vfe_gen4_get_hw_info(vfe); + + return vfe_gen4_bus_reg_base(vfe) + hw_info->test_bus_ctrl_offset; +} + +static inline u8 vfe_gen4_rdi_wm(struct vfe_device *vfe, u8 rdi) +{ + const struct vfe_gen4_hw_info *hw_info = vfe_gen4_get_hw_info(vfe); -#define BUS_REG_BASE_980 (vfe_is_lite(vfe) ? 0x200 : 0x800) -#define BUS_REG_BASE_1080 (vfe_is_lite(vfe) ? 0x800 : 0x1000) -#define BUS_REG_BASE \ - (IS_VFE_980(vfe) ? BUS_REG_BASE_980 : BUS_REG_BASE_1080) + return rdi + (vfe_is_lite(vfe) ? hw_info->rdi_wm_offset_lite : + hw_info->rdi_wm_offset); +} + +/* VFE-gen4 Bus Register Base Addresses */ +#define BUS_REG_BASE (vfe_gen4_bus_reg_base(vfe)) #define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) #define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) -#define VFE_BUS_WM_TEST_BUS_CTRL (BUS_REG_BASE + 0x128) +#define VFE_BUS_WM_TEST_BUS_CTRL (vfe_gen4_test_bus_ctrl(vfe)) #define VFE_BUS_WM_CFG(n) (BUS_REG_BASE + 0x500 + (n) * 0x100) #define WM_CFG_EN BIT(0) @@ -87,18 +159,36 @@ * RDI3 3 * GAMMA 4 * STATES_BE 5 + * + * v900 full IFE write master client map: the RDI clients start at 28, + * after the 28 image/stats clients (0-27): + * + * MAIN C0/C1/C2/UV 0-3 + * PIXEL_RAW 4 + * W_IR 5 + * AI_1 C0/C1/C2/UV 6-9 + * AI_2 C0/C1/C2/UV 10-13 + * HV_DS16 / HV_DS4 14-15 + * STATS BG_IR..BLTM 16-27 + * RDI0 28 + * RDI1 29 + * RDI2 30 + * ... RDI11 39 + * + * v900 IFE Lite matches the generic map above (RDI0 at client 0). */ -#define RDI_WM(n) ((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n)) static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) { struct v4l2_pix_format_mplane *pix = &line->video_out.active_fmt.fmt.pix_mp; - wm = RDI_WM(wm); + wm = vfe_gen4_rdi_wm(vfe, wm); /* no clock gating at bus input */ - writel(WM_CGC_OVERRIDE_ALL, vfe->base + VFE_BUS_WM_CGC_OVERRIDE); + if (vfe_gen4_get_hw_info(vfe)->has_wm_cgc_override) + writel(WM_CGC_OVERRIDE_ALL, + vfe->base + VFE_BUS_WM_CGC_OVERRIDE); writel(0x0, vfe->base + VFE_BUS_WM_TEST_BUS_CTRL); @@ -127,15 +217,19 @@ static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) static void vfe_wm_stop(struct vfe_device *vfe, u8 wm) { - wm = RDI_WM(wm); + wm = vfe_gen4_rdi_wm(vfe, wm); writel(0, vfe->base + VFE_BUS_WM_CFG(wm)); } static void vfe_wm_update(struct vfe_device *vfe, u8 wm, u32 addr, struct vfe_line *line) { - wm = RDI_WM(wm); - writel(addr >> 8, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); + const struct vfe_gen4_hw_info *hw_info = vfe_gen4_get_hw_info(vfe); + + wm = vfe_gen4_rdi_wm(vfe, wm); + + writel(addr >> hw_info->addr_shift, + vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); dev_dbg(vfe->camss->dev, "wm:%d, image buf addr:0x%x\n", wm, addr); } diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 7914b636ad348..b88fe51be44f0 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -98,6 +98,7 @@ enum camss_version { CAMSS_8750, CAMSS_8775P, CAMSS_KAANAPALI, + CAMSS_NORD, CAMSS_X1E80100, CAMSS_X1P42100, }; From 57e44ab7dccb3680e3d9ba13708da005dce98352 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Thu, 3 Sep 2026 16:15:50 +0800 Subject: [PATCH 0111/1133] FROMLIST: media: qcom: camss: tpg: Add support for TPG v2.5.0 Add support for TPG v2.5.0, which moves the stream enable bit out of TPG_CTRL into a dedicated command register (TPG_CTRL_CMD). Branch tpg_stream_on() on the runtime hw_version so the generator is enabled through the command register on v2.5.0 and through TPG_CTRL on earlier revisions; the reset bit is unchanged. Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/all/20260915-nord-v1-5-20db41a7f1ff@oss.qualcomm.com/ --- .../platform/qcom/camss/camss-tpg-gen1.c | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-tpg-gen1.c b/drivers/media/platform/qcom/camss/camss-tpg-gen1.c index d29de5f93c18e..0da5569e4b9a7 100644 --- a/drivers/media/platform/qcom/camss/camss-tpg-gen1.c +++ b/drivers/media/platform/qcom/camss/camss-tpg-gen1.c @@ -22,6 +22,7 @@ #define TPG_HW_VER_2_0_0 TPG_HW_VER(2, 0, 0) #define TPG_HW_VER_2_1_0 TPG_HW_VER(2, 1, 0) +#define TPG_HW_VER_2_5_0 TPG_HW_VER(2, 5, 0) #define TPG_HW_STATUS 0x4 @@ -33,7 +34,14 @@ # define TPG_CTRL_OVERLAP_SHDR_EN BIT(10) # define TPG_CTRL_NUM_ACTIVE_VC GENMASK(31, 30) -#define TPG_CLEAR 0x1F4 +/* + * Command register at 0x1F4. Earlier TPG revisions only expose HW_RESET[0] + * here; v2.5.0 adds TEST_EN[4], moving the generator enable out of TPG_CTRL. + * HW_RESET[0] is unchanged, so the reset path is revision-independent. + */ +#define TPG_CTRL_CMD 0x1F4 +# define TPG_CTRL_CMD_HW_RESET BIT(0) +# define TPG_CTRL_CMD_TEST_EN BIT(4) /* TPG VC-based registers */ #define TPG_VC_n_GAIN_CFG(n) (0x60 + (n) * 0x60) @@ -87,7 +95,9 @@ #define TPG_USER_SPECIFIED_PAYLOAD_DEFAULT 0xBE #define TPG_LFSR_SEED_DEFAULT 0x12345678 #define TPG_COLOR_BARS_CFG_STANDARD \ - FIELD_PREP(TPG_VC_n_COLOR_BARS_CFG_ROTATE_PERIOD, 0xA) + (FIELD_PREP(TPG_VC_n_COLOR_BARS_CFG_ROTATE_PERIOD, 0xA) | \ + FIELD_PREP(TPG_VC_n_COLOR_BARS_CFG_SIZE_X, 3) | \ + FIELD_PREP(TPG_VC_n_COLOR_BARS_CFG_SIZE_Y, 3)) static const char * const testgen_payload_modes[] = { [TPG_PAYLOAD_MODE_DISABLED] = "Disabled", @@ -164,18 +174,23 @@ static int tpg_stream_on(struct tpg_device *tpg) } /* Global TPG control */ - val = FIELD_PREP(TPG_CTRL_TEST_EN, 1) | - FIELD_PREP(TPG_CTRL_NUM_ACTIVE_LANES, lane_cnt - 1) | + val = FIELD_PREP(TPG_CTRL_NUM_ACTIVE_LANES, lane_cnt - 1) | FIELD_PREP(TPG_CTRL_NUM_ACTIVE_VC, last_vc); + if (tpg->hw_version < TPG_HW_VER_2_5_0) + val |= FIELD_PREP(TPG_CTRL_TEST_EN, 1); writel(val, tpg->base + TPG_CTRL); + /* v2.5.0 enables the generator through the command register */ + if (tpg->hw_version >= TPG_HW_VER_2_5_0) + writel(TPG_CTRL_CMD_TEST_EN, tpg->base + TPG_CTRL_CMD); + return 0; } static int tpg_reset(struct tpg_device *tpg) { writel(0, tpg->base + TPG_CTRL); - writel(1, tpg->base + TPG_CLEAR); + writel(TPG_CTRL_CMD_HW_RESET, tpg->base + TPG_CTRL_CMD); return 0; } From c56734a1d221fbc81f930f2c2104d6a4fdce6495 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Thu, 3 Sep 2026 16:16:00 +0800 Subject: [PATCH 0112/1133] FROMLIST: media: qcom: camss: Add support for Nord CAMSS Add support for the camera subsystem on the Qualcomm Nord platform. Enumerate the module-level resources (clocks, register regions, interrupts) and the bus bandwidth votes, and wire up the compatible. Nord exposes 3 TPG, 3 CSID plus 10 CSID Lite (driven by csid_ops_900) and 3 VFE plus 10 VFE Lite (driven by vfe_ops_gen4 with the VFE 900 variant). Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/all/20260915-nord-v1-6-20db41a7f1ff@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/camss-vfe.c | 2 + drivers/media/platform/qcom/camss/camss.c | 602 ++++++++++++++++++ 2 files changed, 604 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 303a47cb51c9a..a9fa526d560d7 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -355,6 +355,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_8750: case CAMSS_8775P: case CAMSS_KAANAPALI: + case CAMSS_NORD: case CAMSS_X1E80100: case CAMSS_X1P42100: switch (sink_code) { @@ -2021,6 +2022,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_8750: case CAMSS_8775P: case CAMSS_KAANAPALI: + case CAMSS_NORD: case CAMSS_X1E80100: case CAMSS_X1P42100: ret = 16; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 520b5440f72f4..65a7d94eb9339 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5321,6 +5321,594 @@ static const struct resources_icc icc_res_x1p42100[] = { }, }; +static const struct camss_subdev_resources tpg_res_nord[] = { + /* TPG0 */ + { + .clock = { "top_ahb", "tpg_csiphy_rx" }, + .clock_rate = { { 0 }, + { 400000000, 480000000 } }, + .reg = { "csitpg0" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, + /* TPG1 */ + { + .clock = { "top_ahb", "tpg_csiphy_rx" }, + .clock_rate = { { 0 }, + { 400000000, 480000000 } }, + .reg = { "csitpg1" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, + /* TPG2 */ + { + .clock = { "top_ahb", "tpg_csiphy_rx" }, + .clock_rate = { { 0 }, + { 400000000, 480000000 } }, + .reg = { "csitpg2" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, +}; + +static const struct camss_subdev_resources csid_res_nord[] = { + /* CSID0 */ + { + .clock = { "csid", "csid_csiphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .clock = { "csid", "csid_csiphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .clock = { "csid", "csid_csiphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE1 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE2 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite2" }, + .interrupt = { "csid_lite2" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE3 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite3" }, + .interrupt = { "csid_lite3" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE4 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite4" }, + .interrupt = { "csid_lite4" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE5 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite5" }, + .interrupt = { "csid_lite5" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE6 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite6" }, + .interrupt = { "csid_lite6" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE7 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite7" }, + .interrupt = { "csid_lite7" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE8 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite8" }, + .interrupt = { "csid_lite8" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE9 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite9" }, + .interrupt = { "csid_lite9" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + } +}; + +static const struct camss_subdev_resources vfe_res_nord[] = { + /* VFE0 - IFE Full */ + { + .clock = { "gcc_axi_hf", "vfe0_fast_ahb", "vfe0", + "top_ahb", "top_fast_ahb", + "top_ife0", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 - IFE Full */ + { + .clock = { "gcc_axi_hf", "vfe1_fast_ahb", "vfe1", + "top_ahb", "top_fast_ahb", + "top_ife1", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 - IFE Full */ + { + .clock = { "gcc_axi_hf", "vfe2_fast_ahb", "vfe2", + "top_ahb", "top_fast_ahb", + "top_ife2", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE0 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE1 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE2 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite2" }, + .interrupt = { "vfe_lite2" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE3 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite3" }, + .interrupt = { "vfe_lite3" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE4 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite4" }, + .interrupt = { "vfe_lite4" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE5 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite5" }, + .interrupt = { "vfe_lite5" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE6 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite6" }, + .interrupt = { "vfe_lite6" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE7 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite7" }, + .interrupt = { "vfe_lite7" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE8 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite8" }, + .interrupt = { "vfe_lite8" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE9 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite9" }, + .interrupt = { "vfe_lite9" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + } +}; + +static const struct resources_icc icc_res_nord[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + /* Based on 4096 x 3072 30 FPS 2496 Mbps mode */ + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 471860, + .icc_bw_tbl.peak = 925857, + }, +}; + /* * camss_add_clock_margin - Add margin to clock frequency rate * @rate: Clock frequency rate @@ -6504,6 +7092,19 @@ static const struct camss_resources msm8996_resources = { .vfe_num = ARRAY_SIZE(vfe_res_8x96), }; +static const struct camss_resources nord_resources = { + .version = CAMSS_NORD, + .pd_name = "top", + .tpg_res = tpg_res_nord, + .csid_res = csid_res_nord, + .vfe_res = vfe_res_nord, + .icc_res = icc_res_nord, + .icc_path_num = ARRAY_SIZE(icc_res_nord), + .tpg_num = ARRAY_SIZE(tpg_res_nord), + .csid_num = ARRAY_SIZE(csid_res_nord), + .vfe_num = ARRAY_SIZE(vfe_res_nord), +}; + static const struct camss_resources qcm2290_resources = { .version = CAMSS_2290, .pm_clks = { "top_ahb", "ahb", "axi" }, @@ -6724,6 +7325,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,msm8939-camss", .data = &msm8939_resources }, { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources }, { .compatible = "qcom,msm8996-camss", .data = &msm8996_resources }, + { .compatible = "qcom,nord-camss", .data = &nord_resources }, { .compatible = "qcom,qcm2290-camss", .data = &qcm2290_resources }, { .compatible = "qcom,qcs8300-camss", .data = &qcs8300_resources }, { .compatible = "qcom,sa8775p-camss", .data = &sa8775p_resources }, From d1eb62bd77ab73a839beb372e90be7376db986eb Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Sat, 3 Oct 2026 02:02:12 -0700 Subject: [PATCH 0113/1133] FROMLIST: dt-bindings: phy: qcom,x1e80100-csi2-phy: Add Kaanapali CSI2 PHY The Kaanapali CSI2 PHY is compatible with the existing x1e80100 CSI2 C-PHY/DPHY binding. Add the "qcom,kaanapali-csi2-phy" compatible. Reviewed-by: Bryan O'Donoghue Acked-by: Krzysztof Kozlowski Signed-off-by: Hangxiang Ma Upstream-Status: Submitted Link: https://lore.kernel.org/all/20261003-kaanapali-camss-v18-1-87ba4ebe0db1@oss.qualcomm.com/ --- .../devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml index 1f1e2a4993b2a..6e9eb8e265df9 100644 --- a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml @@ -17,7 +17,9 @@ description: properties: compatible: oneOf: - - const: qcom,x1e80100-csi2-phy + - enum: + - qcom,kaanapali-csi2-phy + - qcom,x1e80100-csi2-phy - items: - const: qcom,glymur-csi2-phy - const: qcom,x1e80100-csi2-phy From 1c2ecb30fcfb0fe57312171b2c42a34cbf756abe Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Sat, 3 Oct 2026 02:02:15 -0700 Subject: [PATCH 0114/1133] FROMLIST: phy: qcom-mipi-csi2: Parametrise the common status register offset The CSI2 PHY common status registers are not at a fixed offset from the common register block across SoCs: x1e80100 uses 0xb0 while other 3PH v2.4.0 parts differ. Replace the hard-coded 0xb0 in CSIPHY_3PH_CMN_CSI_COMMON_STATUSn() with a per-SoC common_status_offset field in struct mipi_csi2phy_device_regs, initialising x1e80100 to 0xb0 so behaviour is unchanged. This is a no-functional-change preparation for describing other SoC offsets. Signed-off-by: Hangxiang Ma Upstream-Status: Submitted Link: https://lore.kernel.org/all/20261003-kaanapali-camss-v18-4-87ba4ebe0db1@oss.qualcomm.com/ --- .../phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 16 +++++++++++----- drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 1 + 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c index 966d79c98f9b2..8cd331cfb4b32 100644 --- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c @@ -19,7 +19,8 @@ #define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B BIT(0) #define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID BIT(1) #define CSIPHY_3PH_CMN_CSI_COMMON_CTRL10_IRQ_CLEAR_CMD BIT(0) -#define CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(offset, n) ((offset) + 0xb0 + 0x4 * (n)) +#define CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(offset, common_status_offset, n) \ + ((offset) + (common_status_offset) + 0x4 * (n)) #define CSIPHY_2PH_LN_CSI_2PHASE_CTRL9n(n) ((0x200 * (n)) + 0x24) @@ -176,19 +177,23 @@ static void phy_qcom_mipi_csi2_hw_version_read(struct mipi_csi2phy_device *csi2p CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); tmp = readl_relaxed(csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 12)); + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, + regs->common_status_offset, 12)); csi2phy->hw_version = tmp; tmp = readl_relaxed(csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 13)); + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, + regs->common_status_offset, 13)); csi2phy->hw_version |= (tmp << 8) & 0xFF00; tmp = readl_relaxed(csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 14)); + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, + regs->common_status_offset, 14)); csi2phy->hw_version |= (tmp << 16) & 0xFF0000; tmp = readl_relaxed(csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 15)); + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, + regs->common_status_offset, 15)); csi2phy->hw_version |= (tmp << 24) & 0xFF000000; dev_dbg_once(csi2phy->dev, "CSIPHY 3PH HW Version = 0x%08x\n", csi2phy->hw_version); @@ -375,6 +380,7 @@ const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e = { .init_seq = lane_regs_x1e80100, .lane_array_size = ARRAY_SIZE(lane_regs_x1e80100), .common_regs_offset = 0x1000, + .common_status_offset = 0xb0, }, .supply_names = (const char **)x1e_supplies, .num_supplies = ARRAY_SIZE(x1e_supplies), diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h index 7e55ae0073704..d6366f809e510 100644 --- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h @@ -51,6 +51,7 @@ struct mipi_csi2phy_device_regs { const struct mipi_csi2phy_lane_regs *init_seq; const int lane_array_size; const u32 common_regs_offset; + const u32 common_status_offset; }; struct mipi_csi2_genpd { From d9a1b5294578812b35bf6d32e15fd223e227ffb4 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Wed, 7 Oct 2026 15:59:48 +0530 Subject: [PATCH 0115/1133] FROMLIST: media: qcom: camss: csiphy: Add support for v2.4.0 two-phase CSIPHY Add support for the v2.4.0 two-phase CSIPHY found on Kaanapali, where the PHY is driven by the standalone phy-qcom-mipi-csi2 DPHY driver rather than by CAMSS. Add the mipi_csi2_dphy_3nm_kaanapali configuration, which reuses the x1e80100 lane sequence, clocks and supplies but selects the v2.4.0 common status offset, adds Kaanapali power domain and register the "qcom,kaanapali-csi2-phy" compatible. Signed-off-by: Hangxiang Ma Upstream-Status: Submitted Link: https://lore.kernel.org/all/20261003-kaanapali-camss-v18-5-87ba4ebe0db1@oss.qualcomm.com/ --- .../phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 16 ++++++++++++++++ drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c | 1 + drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 1 + 3 files changed, 18 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c index 8cd331cfb4b32..658a39463104b 100644 --- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c @@ -389,3 +389,19 @@ const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e = { .genpds = x1e_genpds, .num_genpds = ARRAY_SIZE(x1e_genpds), }; + +const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_3nm_kaanapali = { + .ops = &phy_qcom_mipi_csi2_ops_3ph_1_0, + .reg_info = { + .init_seq = lane_regs_x1e80100, + .lane_array_size = ARRAY_SIZE(lane_regs_x1e80100), + .common_regs_offset = 0x1000, + .common_status_offset = 0x138, + }, + .supply_names = (const char **)x1e_supplies, + .num_supplies = ARRAY_SIZE(x1e_supplies), + .clk_names = (const char **)x1e_clks, + .num_clk = ARRAY_SIZE(x1e_clks), + .genpds = x1e_genpds, + .num_genpds = ARRAY_SIZE(x1e_genpds), +}; diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c index c0a4fa20eaf0c..aff9e66f0352e 100644 --- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c @@ -444,6 +444,7 @@ static int phy_qcom_mipi_csi2_probe(struct platform_device *pdev) static const struct of_device_id phy_qcom_mipi_csi2_of_match_table[] = { { .compatible = "qcom,x1e80100-csi2-phy", .data = &mipi_csi2_dphy_4nm_x1e }, + { .compatible = "qcom,kaanapali-csi2-phy", .data = &mipi_csi2_dphy_3nm_kaanapali }, { } }; MODULE_DEVICE_TABLE(of, phy_qcom_mipi_csi2_of_match_table); diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h index d6366f809e510..2355a1db9b941 100644 --- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h @@ -94,5 +94,6 @@ struct mipi_csi2phy_device { }; extern const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e; +extern const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_3nm_kaanapali; #endif /* __PHY_QCOM_MIPI_CSI2_H__ */ From c7cdacca035cd48105165cb6592b1754f0352b91 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Wed, 23 Sep 2026 16:32:32 +0530 Subject: [PATCH 0116/1133] FROMLIST: dt-bindings: i2c: qcom,i2c-cci: Add Hawi compatible Document the Camera Control Interface (CCI) compatible for the Qualcomm Hawi platform. Like other recent platforms it requires two clocks, so add it to the corresponding clocks constraint as well. Signed-off-by: Hangxiang Ma Signed-off-by: Nihal Kumar Gupta Upstream-Status: Submitted Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-1-cbbb42e534ef@oss.qualcomm.com/ --- Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml index 1e8def25ec0ec..b2b4d4bcf7807 100644 --- a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml +++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml @@ -27,6 +27,7 @@ properties: - items: - enum: - qcom,glymur-cci + - qcom,hawi-cci - qcom,kaanapali-cci - qcom,milos-cci - qcom,qcm2290-cci @@ -137,6 +138,7 @@ allOf: contains: enum: - qcom,glymur-cci + - qcom,hawi-cci - qcom,kaanapali-cci - qcom,qcm2290-cci - qcom,qcs8300-cci From ef30337ed04ce42457a6c99bff603473f0e8d09c Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Wed, 23 Sep 2026 16:32:33 +0530 Subject: [PATCH 0117/1133] FROMLIST: dt-bindings: phy: qcom,x1e80100-csi2-phy: Add Hawi and Maili compatibles Hawi and Maili integrate the same CSIPHY IP as Kaanapali with an identical register interface. Add qcom,hawi-csi2-phy and qcom,maili-csi2-phy falling back to qcom,kaanapali-csi2-phy. Signed-off-by: Nihal Kumar Gupta Upstream-Status: Submitted Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-2-cbbb42e534ef@oss.qualcomm.com/ --- .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml index 6e9eb8e265df9..a96f9d7daf3ca 100644 --- a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml @@ -17,13 +17,18 @@ description: properties: compatible: oneOf: - - enum: - - qcom,kaanapali-csi2-phy - - qcom,x1e80100-csi2-phy + - const: qcom,kaanapali-csi2-phy + - const: qcom,x1e80100-csi2-phy - items: - const: qcom,glymur-csi2-phy - const: qcom,x1e80100-csi2-phy + - items: + - enum: + - qcom,hawi-csi2-phy + - qcom,maili-csi2-phy + - const: qcom,kaanapali-csi2-phy + reg: maxItems: 1 From e52c38c0a655ba6e6fb522ea51bb77839ca13e13 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Wed, 23 Sep 2026 16:32:34 +0530 Subject: [PATCH 0118/1133] FROMLIST: dt-bindings: media: Add CAMSS device for Hawi Add bindings for Camera Subsystem (CAMSS) on the Qualcomm Hawi platform. The Hawi platform provides: - 6 x CSIPHY (CSI Physical Layer) - 3 x TPG (Test Pattern Generator) - 3 x CSID (CSI Decoder) - 2 x CSID Lite - 3 x VFE (Video Front End), 5 RDI per VFE - 2 x VFE Lite, 4 RDI per VFE Lite Signed-off-by: Hangxiang Ma Co-developed-by: Nihal Kumar Gupta Signed-off-by: Nihal Kumar Gupta Upstream-Status: Submitted Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-3-cbbb42e534ef@oss.qualcomm.com/ --- .../bindings/media/qcom,hawi-camss.yaml | 305 ++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,hawi-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,hawi-camss.yaml b/Documentation/devicetree/bindings/media/qcom,hawi-camss.yaml new file mode 100644 index 0000000000000..5bf0dca3d2462 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,hawi-camss.yaml @@ -0,0 +1,305 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,hawi-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Hawi Camera Subsystem (CAMSS) + +maintainers: + - Hangxiang Ma + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,hawi-camss + + reg: + maxItems: 13 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 26 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: camnoc_dcd_xo + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_mnoc_hf + - const: cpas_mnoc_sf + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: cpas_vfe2 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe2 + - const: vfe2_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + - const: qdss_debug_xo + + interrupts: + maxItems: 10 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + + iommus: + maxItems: 1 + + power-domains: + items: + - description: IFE0 GDSC - Global Distributed Switch Controller for IFE0. + - description: IFE1 GDSC - Global Distributed Switch Controller for IFE1. + - description: IFE2 GDSC - Global Distributed Switch Controller for IFE2. + - description: Titan GDSC - Global Distributed Switch Controller for the entire camss. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: ife2 + - const: top + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-5]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input ports for receiving CSI data on CSIPHY 0-5. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + - ports + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@9253000 { + compatible = "qcom,hawi-camss"; + + reg = <0x0 0x09253000 0x0 0x5e80>, + <0x0 0x09263000 0x0 0x5e80>, + <0x0 0x09273000 0x0 0x5e80>, + <0x0 0x092d3000 0x0 0x3880>, + <0x0 0x092e7000 0x0 0x3880>, + <0x0 0x093fd000 0x0 0x400>, + <0x0 0x093fe000 0x0 0x400>, + <0x0 0x093ff000 0x0 0x400>, + <0x0 0x09151000 0x0 0x20000>, + <0x0 0x09171000 0x0 0x20000>, + <0x0 0x09191000 0x0 0x20000>, + <0x0 0x092dc000 0x0 0x6800>, + <0x0 0x092f0000 0x0 0x6800>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_DCD_XO_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_TITAN_MNOC_HF_CLK>, + <&camcc CAM_CC_TITAN_MNOC_SF_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "camnoc_dcd_xo", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_mnoc_hf", + "cpas_mnoc_sf", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc"; + + iommus = <&apps_smmu 0x1800 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + camss_csiphy0_ep: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&csiphy0_out>; + }; + }; + }; + }; + }; From 4dc1a74f6b950bc9ef8562c313f0ee6ff87b437f Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Wed, 23 Sep 2026 16:32:35 +0530 Subject: [PATCH 0119/1133] FROMLIST: dt-bindings: media: Add CAMSS device for Maili Maili shares the same IP as Hawi. The only difference is Hawi has six CSIPHY while Maili has five. Signed-off-by: Nihal Kumar Gupta Upstream-Status: Submitted Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-4-cbbb42e534ef@oss.qualcomm.com/ --- .../devicetree/bindings/media/qcom,hawi-camss.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,hawi-camss.yaml b/Documentation/devicetree/bindings/media/qcom,hawi-camss.yaml index 5bf0dca3d2462..d1d53d6f024cb 100644 --- a/Documentation/devicetree/bindings/media/qcom,hawi-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,hawi-camss.yaml @@ -4,17 +4,22 @@ $id: http://devicetree.org/schemas/media/qcom,hawi-camss.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Qualcomm Hawi Camera Subsystem (CAMSS) +title: Qualcomm Hawi and Maili Camera Subsystem (CAMSS) maintainers: - Hangxiang Ma + - Nihal Kumar Gupta description: The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. properties: compatible: - const: qcom,hawi-camss + oneOf: + - const: qcom,hawi-camss + - items: + - const: qcom,maili-camss + - const: qcom,hawi-camss reg: maxItems: 13 From 5a76550bc74814d1a1abdef248a6c837637a9d7d Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Wed, 23 Sep 2026 16:32:36 +0530 Subject: [PATCH 0120/1133] FROMLIST: media: qcom: camss: Add Hawi compatible camss driver Add support for Hawi in the camss driver. Hawi reuses the CSIPHY resource table from Kaanapali and the TPG resource table from X1E80100. The CSID and VFE resource tables are Hawi-specific. Signed-off-by: Hangxiang Ma Signed-off-by: Nihal Kumar Gupta Upstream-Status: Submitted Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-5-cbbb42e534ef@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/camss.c | 259 ++++++++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 260 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 65a7d94eb9339..668d6d0cc6daf 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4449,6 +4449,249 @@ static const struct resources_icc icc_res_sa8775p[] = { }, }; +static const struct camss_subdev_resources vfe_res_hawi[] = { + /* VFE0 - TFE Full */ + { + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "vfe0_fast_ahb", "vfe0", "cpas_vfe0", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo", + "cpas_mnoc_hf", "cpas_mnoc_sf" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 238200000, 397000000, 440000000, 480000000, + 630000000, 750000000, 833000000 }, + { 0 }, + { 171428571, 240000000, 300000000, 400000000, + 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 - TFE Full */ + { + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "vfe1_fast_ahb", "vfe1", "cpas_vfe1", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo", + "cpas_mnoc_hf", "cpas_mnoc_sf" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 238200000, 397000000, 440000000, 480000000, + 630000000, 750000000, 833000000 }, + { 0 }, + { 171428571, 240000000, 300000000, 400000000, + 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 - TFE Full */ + { + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "vfe2_fast_ahb", "vfe2", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo", + "cpas_mnoc_hf", "cpas_mnoc_sf" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 238200000, 397000000, 440000000, 480000000, + 630000000, 750000000, 833000000 }, + { 0 }, + { 171428571, 240000000, 300000000, 400000000, + 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE3 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "vfe_lite_ahb", "vfe_lite", "cpas_vfe_lite", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo", + "cpas_mnoc_hf", "cpas_mnoc_sf" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 400000000, 480000000 }, + { 0 }, + { 171428571, 240000000, 300000000, 400000000, + 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE4 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "cpas_ahb", "cpas_fast_ahb", + "vfe_lite_ahb", "vfe_lite", "cpas_vfe_lite", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo", + "cpas_mnoc_hf", "cpas_mnoc_sf" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 400000000, 480000000 }, + { 0 }, + { 171428571, 240000000, 300000000, 400000000, + 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + +static const struct camss_subdev_resources csid_res_hawi[] = { + /* CSID0 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 480000000 }, + { 480000000 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 480000000 }, + { 480000000 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 480000000 }, + { 480000000 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 480000000 }, + { 480000000 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE1 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 480000000 }, + { 480000000 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + } +}; + +static const struct resources_icc icc_res_hawi[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, + }, + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + static const struct camss_subdev_resources csiphy_res_8750[] = { /* CSIPHY0 */ { @@ -7289,6 +7532,21 @@ static const struct camss_resources sm8750_resources = { .icc_path_num = ARRAY_SIZE(icc_res_sm8750), }; +static const struct camss_resources hawi_resources = { + .version = CAMSS_HAWI, + .pd_name = "top", + .csiphy_res = csiphy_res_kaanapali, + .tpg_res = tpg_res_x1e80100, + .csid_res = csid_res_hawi, + .vfe_res = vfe_res_hawi, + .icc_res = icc_res_hawi, + .icc_path_num = ARRAY_SIZE(icc_res_hawi), + .csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali), + .tpg_num = ARRAY_SIZE(tpg_res_x1e80100), + .csid_num = ARRAY_SIZE(csid_res_hawi), + .vfe_num = ARRAY_SIZE(vfe_res_hawi), +}; + static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", @@ -7342,6 +7600,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sm8750-camss", .data = &sm8750_resources }, { .compatible = "qcom,x1e80100-camss", .data = &x1e80100_resources }, { .compatible = "qcom,glymur-camss", .data = &x1e80100_resources }, + { .compatible = "qcom,hawi-camss", .data = &hawi_resources }, { .compatible = "qcom,x1p42100-camss", .data = &x1p42100_resources }, { } }; diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index b88fe51be44f0..8871270834e0d 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -97,6 +97,7 @@ enum camss_version { CAMSS_8650, CAMSS_8750, CAMSS_8775P, + CAMSS_HAWI, CAMSS_KAANAPALI, CAMSS_NORD, CAMSS_X1E80100, From f5d851d53dcaf2bdd2ba35f02202cc1d3e93b39d Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Wed, 23 Sep 2026 16:32:37 +0530 Subject: [PATCH 0121/1133] FROMLIST: media: qcom: camss: vfe: Add support for VFE 1190 Add support for the Video Front End (VFE) on Hawi SoC. VFE gen4 has support for VFE 1190. VFE 1190 uses a different bus write master register layout from the VFE 1080/980 variants: the per-write-master register block has a 0x200 stride based at 0x1000, and several individual registers sit at different offsets. Parameterize the bus register macros on the VFE version so the gen4 driver can serve VFE 1080, 980 and 1190. This change limits Hawi VFE output lines to 3 for now as constrained by the CAMSS driver framework. Signed-off-by: Hangxiang Ma Signed-off-by: Nihal Kumar Gupta Upstream-Status: Submitted Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-6-cbbb42e534ef@oss.qualcomm.com/ --- .../platform/qcom/camss/camss-vfe-gen4.c | 43 +++++++++++++------ drivers/media/platform/qcom/camss/camss-vfe.c | 2 + 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c index 5464be5a632b5..549582ce74eed 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c @@ -90,34 +90,49 @@ static inline u8 vfe_gen4_rdi_wm(struct vfe_device *vfe, u8 rdi) } /* VFE-gen4 Bus Register Base Addresses */ -#define BUS_REG_BASE (vfe_gen4_bus_reg_base(vfe)) +#define IS_VFE_1190(vfe) ((vfe)->camss->res->version == CAMSS_HAWI) +#define BUS_REG_BASE_1080 (vfe_is_lite(vfe) ? 0x800 : 0x1000) -#define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) +/* VFE-gen4 Bus Register Base Addresses */ +#define BUS_REG_BASE_1190 (0x800) +#define BUS_REG_BASE (IS_VFE_1190(vfe) ? BUS_REG_BASE_1190 : \ + BUS_REG_BASE_1080) + +#define BUS_REG_OFFSET_1080(n) (0x500 + (n) * 0x100) +#define BUS_REG_OFFSET_1190(n) (0x1000 + (n) * 0x200) +#define BUS_REG_OFFSET(n) (IS_VFE_1190(vfe) ? \ + BUS_REG_OFFSET_1190(n) : \ + BUS_REG_OFFSET_1080(n)) + +#define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + \ + (IS_VFE_1190(vfe) ? 0x4 : 0x8)) #define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) #define VFE_BUS_WM_TEST_BUS_CTRL (vfe_gen4_test_bus_ctrl(vfe)) -#define VFE_BUS_WM_CFG(n) (BUS_REG_BASE + 0x500 + (n) * 0x100) +#define VFE_BUS_WM_CFG(n) (BUS_REG_BASE + BUS_REG_OFFSET(n)) #define WM_CFG_EN BIT(0) #define WM_VIR_FRM_EN BIT(1) #define WM_CFG_MODE BIT(16) -#define VFE_BUS_WM_IMAGE_ADDR(n) (BUS_REG_BASE + 0x504 + (n) * 0x100) -#define VFE_BUS_WM_FRAME_INCR(n) (BUS_REG_BASE + 0x508 + (n) * 0x100) -#define VFE_BUS_WM_IMAGE_CFG_0(n) (BUS_REG_BASE + 0x50C + (n) * 0x100) +#define VFE_BUS_WM_IMAGE_ADDR(n) (BUS_REG_BASE + BUS_REG_OFFSET(n) + 0x4) +#define VFE_BUS_WM_FRAME_INCR(n) (BUS_REG_BASE + BUS_REG_OFFSET(n) + 0x8) +#define VFE_BUS_WM_IMAGE_CFG_0(n) (BUS_REG_BASE + BUS_REG_OFFSET(n) + 0xC) #define WM_IMAGE_CFG_0_DEFAULT_WIDTH (0xFFFF) -#define VFE_BUS_WM_IMAGE_CFG_2(n) (BUS_REG_BASE + 0x514 + (n) * 0x100) +#define VFE_BUS_WM_IMAGE_CFG_2(n) (BUS_REG_BASE + BUS_REG_OFFSET(n) + 0x14) #define WM_IMAGE_CFG_2_DEFAULT_STRIDE (0xFFFF) -#define VFE_BUS_WM_PACKER_CFG(n) (BUS_REG_BASE + 0x518 + (n) * 0x100) +#define VFE_BUS_WM_PACKER_CFG(n) (BUS_REG_BASE + BUS_REG_OFFSET(n) + 0x18) -#define VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(n) (BUS_REG_BASE + 0x530 + (n) * 0x100) -#define VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(n) (BUS_REG_BASE + 0x534 + (n) * 0x100) +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(n) (BUS_REG_BASE + BUS_REG_OFFSET(n) + 0x30) +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(n) (BUS_REG_BASE + BUS_REG_OFFSET(n) + 0x34) /* VFE lite has no such registers */ -#define VFE_BUS_WM_FRAMEDROP_PERIOD(n) (BUS_REG_BASE + 0x538 + (n) * 0x100) -#define VFE_BUS_WM_FRAMEDROP_PATTERN(n) (BUS_REG_BASE + 0x53C + (n) * 0x100) +#define VFE_BUS_WM_FRAMEDROP_PERIOD(n) (BUS_REG_BASE + BUS_REG_OFFSET(n) + 0x38) +#define VFE_BUS_WM_FRAMEDROP_PATTERN(n) (BUS_REG_BASE + BUS_REG_OFFSET(n) + 0x3C) -#define VFE_BUS_WM_MMU_PREFETCH_CFG(n) (BUS_REG_BASE + 0x560 + (n) * 0x100) -#define VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(n) (BUS_REG_BASE + 0x564 + (n) * 0x100) +#define VFE_BUS_WM_MMU_PREFETCH_CFG(n) (BUS_REG_BASE + BUS_REG_OFFSET(n) + \ + (IS_VFE_1190(vfe) ? 0x64 : 0x60)) +#define VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(n) (BUS_REG_BASE + BUS_REG_OFFSET(n) + \ + (IS_VFE_1190(vfe) ? 0x68 : 0x64)) /* * IFE write master client IDs diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index a9fa526d560d7..334135f5189ad 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -354,6 +354,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_8650: case CAMSS_8750: case CAMSS_8775P: + case CAMSS_HAWI: case CAMSS_KAANAPALI: case CAMSS_NORD: case CAMSS_X1E80100: @@ -2021,6 +2022,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_8650: case CAMSS_8750: case CAMSS_8775P: + case CAMSS_HAWI: case CAMSS_KAANAPALI: case CAMSS_NORD: case CAMSS_X1E80100: From 9436058db875e3625d37cb842711a9dca30701b7 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Thu, 30 Jul 2026 01:06:58 -0700 Subject: [PATCH 0122/1133] FROMLIST: dt-bindings: arm: Add support for Qualcomm 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 tgu.yaml file to describe the bindings required to define the TGU in the device trees. Link: https://lore.kernel.org/linux-arm-msm/20260730080704.2903540-2-songwei.chai@oss.qualcomm.com/ Reviewed-by: Rob Herring (Arm) Signed-off-by: Songwei Chai --- .../devicetree/bindings/arm/qcom,tgu.yaml | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/qcom,tgu.yaml diff --git a/Documentation/devicetree/bindings/arm/qcom,tgu.yaml b/Documentation/devicetree/bindings/arm/qcom,tgu.yaml new file mode 100644 index 0000000000000..76440f2497b97 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/qcom,tgu.yaml @@ -0,0 +1,71 @@ +# 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,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 identify the issue in time + once there is abnormal behavior in the subsystem. + +maintainers: + - Mao Jinlong + - Songwei Chai + +# Need a custom select here or 'arm,primecell' will match on lots of nodes +select: + properties: + compatible: + contains: + enum: + - qcom,tgu + required: + - compatible + +properties: + compatible: + items: + - const: qcom,tgu + - const: arm,primecell + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: apb_pclk + +required: + - compatible + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + tgu@10b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x10b0e000 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +... From ccfb88e654f63a7816f749515234916c892c085a Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Thu, 30 Jul 2026 01:06:59 -0700 Subject: [PATCH 0123/1133] FROMLIST: qcom-tgu: Add TGU driver Add driver to support 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/linux-arm-msm/20260730080704.2903540-3-songwei.chai@oss.qualcomm.com/ Signed-off-by: Songwei Chai Acked-by: Konrad Dybcio Reviewed-by: Jie Gan --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 9 + MAINTAINERS | 11 + drivers/Makefile | 1 + drivers/hwtracing/Kconfig | 2 + drivers/hwtracing/qcom/Kconfig | 20 ++ drivers/hwtracing/qcom/Makefile | 3 + drivers/hwtracing/qcom/tgu.c | 192 ++++++++++++++++++ drivers/hwtracing/qcom/tgu.h | 51 +++++ 8 files changed, 289 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-amba-devices-tgu create mode 100644 drivers/hwtracing/qcom/Kconfig create mode 100644 drivers/hwtracing/qcom/Makefile create mode 100644 drivers/hwtracing/qcom/tgu.c create mode 100644 drivers/hwtracing/qcom/tgu.h diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu new file mode 100644 index 0000000000000..36ab64f1e301d --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -0,0 +1,9 @@ +What: /sys/bus/amba/devices//enable_tgu +Date: August 2026 +KernelVersion: 7.2 +Contact: Jinlong Mao , Songwei Chai +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/MAINTAINERS b/MAINTAINERS index 93abbb315065d..81e9db074f888 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23174,6 +23174,17 @@ S: Maintained F: Documentation/tee/qtee.rst F: drivers/tee/qcomtee/ +QUALCOMM HARDWARETRACING DRIVER +M: Songwei Chai +M: Jie Gan +M: Suzuki K Poulose +L: linux-arm-msm@vger.kernel.org +S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux.git +F: Documentation/ABI/testing/sysfs-bus-amba-devices-tgu +F: Documentation/devicetree/bindings/arm/qcom,tgu.yaml +F: drivers/hwtracing/qcom/ + QUALCOMM TRUST ZONE MEMORY ALLOCATOR M: Bartosz Golaszewski L: linux-arm-msm@vger.kernel.org diff --git a/drivers/Makefile b/drivers/Makefile index 0841ea851847e..6a2cbe5b340f5 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -176,6 +176,7 @@ obj-$(CONFIG_RAS) += ras/ obj-$(CONFIG_USB4) += thunderbolt/ obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/ obj-y += hwtracing/intel_th/ +obj-y += hwtracing/qcom/ obj-$(CONFIG_STM) += hwtracing/stm/ obj-$(CONFIG_HISI_PTT) += hwtracing/ptt/ obj-y += android/ diff --git a/drivers/hwtracing/Kconfig b/drivers/hwtracing/Kconfig index 911ee977103c0..8a640218eed84 100644 --- a/drivers/hwtracing/Kconfig +++ b/drivers/hwtracing/Kconfig @@ -7,4 +7,6 @@ source "drivers/hwtracing/intel_th/Kconfig" source "drivers/hwtracing/ptt/Kconfig" +source "drivers/hwtracing/qcom/Kconfig" + endmenu diff --git a/drivers/hwtracing/qcom/Kconfig b/drivers/hwtracing/qcom/Kconfig new file mode 100644 index 0000000000000..5c94c75ffa396 --- /dev/null +++ b/drivers/hwtracing/qcom/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# QCOM specific hwtracing drivers +# +menu "Qualcomm specific hwtracing drivers" + +config QCOM_TGU + tristate "QCOM Trigger Generation Unit driver" + depends on ARCH_QCOM || COMPILE_TEST + depends on ARM_AMBA + 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. + +endmenu diff --git a/drivers/hwtracing/qcom/Makefile b/drivers/hwtracing/qcom/Makefile new file mode 100644 index 0000000000000..5a0a868c1ea0d --- /dev/null +++ b/drivers/hwtracing/qcom/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_QCOM_TGU) += tgu.o diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c new file mode 100644 index 0000000000000..9c7dd4a09f027 --- /dev/null +++ b/drivers/hwtracing/qcom/tgu.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tgu.h" + +static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) +{ + TGU_UNLOCK(drvdata->base); + /* Enable TGU to program the triggers */ + writel(1, drvdata->base + TGU_CONTROL); + TGU_LOCK(drvdata->base); +} + +static void tgu_enable(struct tgu_drvdata *drvdata) +{ + tgu_write_all_hw_regs(drvdata); + drvdata->enabled = true; +} + +static void tgu_disable(struct tgu_drvdata *drvdata) +{ + TGU_UNLOCK(drvdata->base); + writel(0, drvdata->base + TGU_CONTROL); + TGU_LOCK(drvdata->base); + + drvdata->enabled = false; +} + +static ssize_t enable_tgu_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + bool enabled; + + scoped_guard(mutex, &drvdata->lock) + enabled = drvdata->enabled; + + return sysfs_emit(buf, "%d\n", enabled); +} + +/* enable_tgu_store - Enable or disable the Trigger Generation Unit (TGU). */ +static ssize_t enable_tgu_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t size) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 0, &val); + if (ret || val > 1) + return -EINVAL; + + /* + * Hold the mutex across the whole check-and-act sequence: the check of + * drvdata->enabled, the PM runtime reference counting and the state + * update must be atomic, otherwise concurrent writers could each + * imbalance the PM runtime usage counter. + */ + guard(mutex)(&drvdata->lock); + + if (val) { + if (drvdata->enabled) + return -EBUSY; + + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + + tgu_enable(drvdata); + } else { + if (!drvdata->enabled) + return -EINVAL; + + tgu_disable(drvdata); + pm_runtime_put(dev); + } + + return size; +} +static DEVICE_ATTR_RW(enable_tgu); + +static struct attribute *tgu_common_attrs[] = { + &dev_attr_enable_tgu.attr, + NULL, +}; + +static const struct attribute_group tgu_common_grp = { + .attrs = tgu_common_attrs, +}; + +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) +{ + struct device *dev = &adev->dev; + struct tgu_drvdata *drvdata; + int ret; + + 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 (IS_ERR(drvdata->base)) + return PTR_ERR(drvdata->base); + + ret = devm_mutex_init(dev, &drvdata->lock); + if (ret) + return ret; + + drvdata->enabled = false; + + ret = sysfs_create_groups(&dev->kobj, tgu_attr_groups); + if (ret) { + dev_err(dev, "failed to create sysfs groups: %d\n", ret); + return ret; + } + + pm_runtime_put(&adev->dev); + + return 0; +} + +static void tgu_remove(struct amba_device *adev) +{ + struct device *dev = &adev->dev; + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + + sysfs_remove_groups(&dev->kobj, tgu_attr_groups); + + /* + * If the device is still enabled through sysfs, disable the hardware + * and drop the PM runtime reference taken in enable_tgu_store() so the + * usage counter stays balanced. Use the synchronous put: the driver core + * disables runtime PM right after ->remove() returns, and the barrier in + * pm_runtime_disable() would cancel a still-queued async idle/suspend, + * leaving the runtime-PM state inconsistent. + */ + scoped_guard(mutex, &drvdata->lock) { + if (drvdata->enabled) { + tgu_disable(drvdata); + pm_runtime_put_sync(dev); + } + } +} + +static const struct amba_id tgu_ids[] = { + { + .id = 0x000f0e00, + .mask = 0x000fffff, + }, + { 0, 0, NULL }, +}; + +MODULE_DEVICE_TABLE(amba, tgu_ids); + +static struct amba_driver tgu_driver = { + .drv = { + .name = "qcom-tgu", + .suppress_bind_attrs = true, + }, + .probe = tgu_probe, + .remove = tgu_remove, + .id_table = tgu_ids, +}; + +module_amba_driver(tgu_driver); + +MODULE_AUTHOR("Songwei Chai "); +MODULE_AUTHOR("Jinlong Mao "); +MODULE_DESCRIPTION("Qualcomm Trigger Generation Unit driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h new file mode 100644 index 0000000000000..ebba49402a20a --- /dev/null +++ b/drivers/hwtracing/qcom/tgu.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _QCOM_TGU_H +#define _QCOM_TGU_H + +/* Register addresses */ +#define TGU_CONTROL 0x0000 +#define TGU_LAR 0xfb0 +#define TGU_UNLOCK_OFFSET 0xc5acce55 + +static inline void TGU_LOCK(void __iomem *addr) +{ + do { + /* Wait for things to settle */ + mb(); + writel_relaxed(0x0, addr + TGU_LAR); + } while (0); +} + +static inline void TGU_UNLOCK(void __iomem *addr) +{ + do { + writel_relaxed(TGU_UNLOCK_OFFSET, addr + TGU_LAR); + /* Make sure everyone has seen this */ + mb(); + } while (0); +} + +/** + * struct tgu_drvdata - Data structure for a TGU (Trigger Generation Unit) + * @base: Memory-mapped base address of the TGU device + * @dev: Pointer to the associated device structure + * @lock: Mutex serialising enable/disable and the associated PM runtime + * reference counting against concurrent sysfs access + * @enabled: Flag indicating whether the TGU device is enabled + * + * This structure defines the data associated with a TGU device, + * including its base address, device pointer, the lock serialising + * enable/disable, and the enable status. + */ +struct tgu_drvdata { + void __iomem *base; + struct device *dev; + struct mutex lock; + bool enabled; +}; + +#endif From 63afa8bd6eb0e896654442655c7e91775ca19ae8 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Thu, 30 Jul 2026 01:07:00 -0700 Subject: [PATCH 0124/1133] FROMLIST: qcom-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/linux-arm-msm/20260730080704.2903540-4-songwei.chai@oss.qualcomm.com/ Reviewed-by: Jie Gan Signed-off-by: Songwei Chai --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 7 + drivers/hwtracing/qcom/tgu.c | 189 +++++++++++++++++- drivers/hwtracing/qcom/tgu.h | 133 ++++++++++++ 3 files changed, 328 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu index 36ab64f1e301d..7dd24314592d9 100644 --- a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-amba-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/amba/devices//step[0:7]_priority[0:3]/reg[0:17] +Date: August 2026 +KernelVersion: 7.2 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the sensed signal with specific step and priority for TGU. diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c index 9c7dd4a09f027..0e88b437f191f 100644 --- a/drivers/hwtracing/qcom/tgu.c +++ b/drivers/hwtracing/qcom/tgu.c @@ -15,14 +15,144 @@ #include "tgu.h" +static int calculate_array_location(struct tgu_drvdata *drvdata, + int step_index, int operation_index, + int reg_index) +{ + return operation_index * (drvdata->num_step) * (drvdata->num_reg) + + step_index * (drvdata->num_reg) + reg_index; +} + +static ssize_t tgu_dataset_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + struct tgu_attribute *tgu_attr = + container_of(attr, struct tgu_attribute, attr); + int index; + + index = calculate_array_location(drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num); + + /* + * Serialise against tgu_dataset_store() and tgu_enable(), which read + * and write the same priority array, so the value is not observed + * while being updated concurrently. + */ + guard(mutex)(&drvdata->lock); + + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->priority[index]); +} + +static ssize_t tgu_dataset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct tgu_drvdata *tgu_drvdata = dev_get_drvdata(dev); + struct tgu_attribute *tgu_attr = + container_of(attr, struct tgu_attribute, attr); + unsigned long val; + int index; + int ret; + + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; + + guard(mutex)(&tgu_drvdata->lock); + index = calculate_array_location(tgu_drvdata, tgu_attr->step_index, + tgu_attr->operation_index, + tgu_attr->reg_num); + + tgu_drvdata->value_table->priority[index] = 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); + 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->num_step) + return SYSFS_GROUP_INVISIBLE; + + if (tgu_attr->reg_num >= drvdata->num_reg) + return 0; + + return attr->mode; +} + static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) { + int i, j, k, index; + TGU_UNLOCK(drvdata->base); + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < MAX_PRIORITY; j++) { + for (k = 0; k < drvdata->num_reg; k++) { + index = calculate_array_location( + drvdata, i, j, k); + + writel(drvdata->value_table->priority[index], + drvdata->base + + PRIORITY_REG_STEP(i, j, k)); + } + } + } /* Enable TGU to program the triggers */ writel(1, drvdata->base + TGU_CONTROL); TGU_LOCK(drvdata->base); } +static void tgu_set_reg_number(struct tgu_drvdata *drvdata) +{ + int num_sense_input; + int num_reg; + u32 devid; + + devid = readl(drvdata->base + TGU_DEVID); + + num_sense_input = TGU_DEVID_SENSE_INPUT(devid); + num_reg = (num_sense_input * TGU_BITS_PER_SIGNAL) / LENGTH_REGISTER; + + if ((num_sense_input * TGU_BITS_PER_SIGNAL) % LENGTH_REGISTER) + num_reg++; + + if (num_reg > TGU_MAX_PRIORITY_REGS) { + dev_warn(drvdata->dev, + "DEVID reports %d priority regs, clamping to %d\n", + num_reg, TGU_MAX_PRIORITY_REGS); + num_reg = TGU_MAX_PRIORITY_REGS; + } + + drvdata->num_reg = num_reg; +} + +static void tgu_set_steps(struct tgu_drvdata *drvdata) +{ + u32 devid; + + devid = readl(drvdata->base + TGU_DEVID); + + drvdata->num_step = TGU_DEVID_STEPS(devid); + + if (drvdata->num_step > TGU_MAX_STEPS) { + dev_warn(drvdata->dev, + "DEVID reports %d steps, clamping to %d\n", + drvdata->num_step, TGU_MAX_STEPS); + drvdata->num_step = TGU_MAX_STEPS; + } +} + static void tgu_enable(struct tgu_drvdata *drvdata) { tgu_write_all_hw_regs(drvdata); @@ -104,6 +234,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, }; @@ -111,6 +273,8 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct tgu_drvdata *drvdata; + unsigned int *priority; + size_t priority_size; int ret; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); @@ -128,8 +292,31 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) if (ret) return ret; - drvdata->enabled = false; + 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; + priority_size = MAX_PRIORITY * drvdata->num_reg * drvdata->num_step; + + priority = devm_kcalloc(dev, priority_size, + sizeof(*drvdata->value_table->priority), + GFP_KERNEL); + if (!priority) + return -ENOMEM; + + drvdata->value_table->priority = priority; + + drvdata->enabled = false; + /* + * Create the sysfs groups only after the backing storage is fully + * allocated, otherwise userspace could open a priority attribute and + * have tgu_dataset_show() dereference an uninitialised value_table. + * This also keeps the error paths above free of sysfs teardown. + */ ret = sysfs_create_groups(&dev->kobj, tgu_attr_groups); if (ret) { dev_err(dev, "failed to create sysfs groups: %d\n", ret); diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h index ebba49402a20a..7a3e1161c4cfd 100644 --- a/drivers/hwtracing/qcom/tgu.h +++ b/drivers/hwtracing/qcom/tgu.h @@ -6,10 +6,137 @@ #ifndef _QCOM_TGU_H #define _QCOM_TGU_H +#include +#include + /* Register addresses */ #define TGU_CONTROL 0x0000 #define TGU_LAR 0xfb0 #define TGU_UNLOCK_OFFSET 0xc5acce55 +#define TGU_DEVID 0xfc8 + +#define TGU_DEVID_SENSE_INPUT(devid_val) \ + ((int)FIELD_GET(GENMASK(17, 10), devid_val)) +#define TGU_DEVID_STEPS(devid_val) \ + ((int)FIELD_GET(GENMASK(6, 3), devid_val)) +#define TGU_BITS_PER_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$ + * | registers | |---> |priority[3] |$ + * | | | |-------------|base+n*0x1D8+0x194$ + * | | | |priority[2] |$ + * |-------------------------| | |-------------|base+n*0x1D8+0x134$ + * | | | |priority[1] |$ + * | step[7] | | |-------------|base+n*0x1D8+0xD4$ + * |-------------------------|->base+0x40+7*0x1D8 | |priority[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 + +/* + * Upper bounds on the DEVID/DEVID2-derived per-region counts. The TGU register + * layout is fixed by the offset macros above and mirrored by the static sysfs + * attribute tables in tgu.c, so these are the largest counts the driver can + * both address within the mapped window and expose to userspace: + * + * TGU_MAX_STEPS static tables define step0..step7 + * TGU_MAX_PRIORITY_REGS STEP_PRIORITY_LIST defines reg0..reg17 + * + * A device whose DEVID reports counts above these bounds is clamped, so writes + * never fall outside the ioremap()'d window or spill into an adjacent region. + */ + +#define TGU_MAX_STEPS 8 +#define TGU_MAX_PRIORITY_REGS 18 + +/* 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; +}; static inline void TGU_LOCK(void __iomem *addr) { @@ -36,6 +163,9 @@ static inline void TGU_UNLOCK(void __iomem *addr) * @lock: Mutex serialising enable/disable and the associated PM runtime * reference counting against concurrent sysfs access * @enabled: Flag indicating whether the TGU device is enabled + * @value_table: Store given value based on relevant parameters + * @num_reg: Maximum number of registers + * @num_step: Maximum step size * * This structure defines the data associated with a TGU device, * including its base address, device pointer, the lock serialising @@ -46,6 +176,9 @@ struct tgu_drvdata { struct device *dev; struct mutex lock; bool enabled; + struct value_table *value_table; + int num_reg; + int num_step; }; #endif From e35fb94181baf5cc41e24bcad4ae5671c10e82f8 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Thu, 30 Jul 2026 01:07:01 -0700 Subject: [PATCH 0125/1133] FROMLIST: qcom-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/linux-arm-msm/20260730080704.2903540-5-songwei.chai@oss.qualcomm.com/ Reviewed-by: Jie Gan Signed-off-by: Songwei Chai --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 7 + drivers/hwtracing/qcom/tgu.c | 182 ++++++++++++++++-- drivers/hwtracing/qcom/tgu.h | 37 ++++ 3 files changed, 206 insertions(+), 20 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu index 7dd24314592d9..705e75c776d40 100644 --- a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -14,3 +14,10 @@ KernelVersion: 7.2 Contact: Jinlong Mao , Songwei Chai Description: (RW) Set/Get the sensed signal with specific step and priority for TGU. + +What: /sys/bus/amba/devices//step[0:7]_condition_decode/reg[0:3] +Date: August 2026 +KernelVersion: 7.2 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the decode mode with specific step for TGU. diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c index 0e88b437f191f..e83295217e7ab 100644 --- a/drivers/hwtracing/qcom/tgu.c +++ b/drivers/hwtracing/qcom/tgu.c @@ -19,8 +19,33 @@ static int calculate_array_location(struct tgu_drvdata *drvdata, int step_index, int operation_index, int reg_index) { - return operation_index * (drvdata->num_step) * (drvdata->num_reg) + - step_index * (drvdata->num_reg) + reg_index; + switch (operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + return operation_index * (drvdata->num_step) * + (drvdata->num_reg) + + step_index * (drvdata->num_reg) + reg_index; + case TGU_CONDITION_DECODE: + return step_index * (drvdata->num_condition_decode) + + reg_index; + default: + break; + } + + return -EINVAL; +} + +static int check_array_location(struct tgu_drvdata *drvdata, int step, + int ops, int reg) +{ + int result = calculate_array_location(drvdata, step, ops, reg); + + if (result == -EINVAL) + dev_err(drvdata->dev, "check array location - Fail\n"); + + return result; } static ssize_t tgu_dataset_show(struct device *dev, @@ -31,9 +56,11 @@ static ssize_t tgu_dataset_show(struct device *dev, container_of(attr, struct tgu_attribute, attr); int index; - index = calculate_array_location(drvdata, tgu_attr->step_index, - tgu_attr->operation_index, - tgu_attr->reg_num); + index = check_array_location(drvdata, tgu_attr->step_index, + tgu_attr->operation_index, tgu_attr->reg_num); + + if (index == -EINVAL) + return index; /* * Serialise against tgu_dataset_store() and tgu_enable(), which read @@ -42,8 +69,20 @@ static ssize_t tgu_dataset_show(struct device *dev, */ guard(mutex)(&drvdata->lock); - return sysfs_emit(buf, "0x%x\n", - drvdata->value_table->priority[index]); + 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[index]); + case TGU_CONDITION_DECODE: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->condition_decode[index]); + default: + break; + } + return -EINVAL; } static ssize_t tgu_dataset_store(struct device *dev, @@ -66,9 +105,27 @@ static ssize_t tgu_dataset_store(struct device *dev, tgu_attr->operation_index, tgu_attr->reg_num); - tgu_drvdata->value_table->priority[index] = val; + if (index == -EINVAL) + return index; + + switch (tgu_attr->operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + tgu_drvdata->value_table->priority[index] = val; + ret = size; + break; + case TGU_CONDITION_DECODE: + tgu_drvdata->value_table->condition_decode[index] = val; + ret = size; + break; + default: + ret = -EINVAL; + break; + } - return size; + return ret; } static umode_t tgu_node_visible(struct kobject *kobject, @@ -85,22 +142,41 @@ static umode_t tgu_node_visible(struct kobject *kobject, if (tgu_attr->step_index >= drvdata->num_step) return SYSFS_GROUP_INVISIBLE; - if (tgu_attr->reg_num >= drvdata->num_reg) - return 0; + switch (tgu_attr->operation_index) { + case TGU_PRIORITY0: + case TGU_PRIORITY1: + case TGU_PRIORITY2: + case TGU_PRIORITY3: + if (!drvdata->num_reg) + return SYSFS_GROUP_INVISIBLE; + if (tgu_attr->reg_num < drvdata->num_reg) + return attr->mode; + break; + case TGU_CONDITION_DECODE: + if (!drvdata->num_condition_decode) + return SYSFS_GROUP_INVISIBLE; + if (tgu_attr->reg_num < drvdata->num_condition_decode) + return attr->mode; + break; + default: + break; + } - return attr->mode; + return 0; } -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, index; + int i, j, k, index = 0; TGU_UNLOCK(drvdata->base); for (i = 0; i < drvdata->num_step; i++) { for (j = 0; j < MAX_PRIORITY; j++) { for (k = 0; k < drvdata->num_reg; k++) { - index = calculate_array_location( + index = check_array_location( drvdata, i, j, k); + if (index == -EINVAL) + goto exit; writel(drvdata->value_table->priority[index], drvdata->base + @@ -108,9 +184,23 @@ static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) } } } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_condition_decode; j++) { + index = check_array_location(drvdata, i, + TGU_CONDITION_DECODE, j); + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->condition_decode[index], + drvdata->base + CONDITION_DECODE_STEP(i, j)); + } + } /* Enable TGU to program the triggers */ writel(1, drvdata->base + TGU_CONTROL); +exit: TGU_LOCK(drvdata->base); + return index >= 0 ? 0 : -EINVAL; } static void tgu_set_reg_number(struct tgu_drvdata *drvdata) @@ -153,10 +243,31 @@ static void tgu_set_steps(struct tgu_drvdata *drvdata) } } -static void tgu_enable(struct tgu_drvdata *drvdata) +static int tgu_enable(struct tgu_drvdata *drvdata) { - tgu_write_all_hw_regs(drvdata); + int ret; + + ret = tgu_write_all_hw_regs(drvdata); + if (ret) + return ret; + drvdata->enabled = true; + return 0; +} + +static void tgu_set_conditions(struct tgu_drvdata *drvdata) +{ + u32 devid; + + devid = readl(drvdata->base + TGU_DEVID); + drvdata->num_condition_decode = TGU_DEVID_CONDITIONS(devid); + + if (drvdata->num_condition_decode > TGU_MAX_CONDITION_DECODE) { + dev_warn(drvdata->dev, + "DEVID reports %d condition decode regs, clamping to %d\n", + drvdata->num_condition_decode, TGU_MAX_CONDITION_DECODE); + drvdata->num_condition_decode = TGU_MAX_CONDITION_DECODE; + } } static void tgu_disable(struct tgu_drvdata *drvdata) @@ -210,7 +321,11 @@ static ssize_t enable_tgu_store(struct device *dev, if (ret) return ret; - tgu_enable(drvdata); + ret = tgu_enable(drvdata); + if (ret) { + pm_runtime_put(dev); + return ret; + } } else { if (!drvdata->enabled) return -EINVAL; @@ -266,6 +381,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, }; @@ -273,8 +396,9 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct tgu_drvdata *drvdata; - unsigned int *priority; - size_t priority_size; + unsigned int *priority, *condition; + size_t priority_size, condition_size; + int i, j; int ret; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); @@ -294,6 +418,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); @@ -310,6 +435,23 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) drvdata->value_table->priority = priority; + condition_size = drvdata->num_condition_decode * drvdata->num_step; + + condition = devm_kcalloc(dev, condition_size, + sizeof(*(drvdata->value_table->condition_decode)), + GFP_KERNEL); + if (!condition) + return -ENOMEM; + + drvdata->value_table->condition_decode = condition; + + /* Initialize all condition decode registers to NOT */ + for (i = 0; i < drvdata->num_step; i++) + for (j = 0; j < drvdata->num_condition_decode; j++) + condition[calculate_array_location( + drvdata, i, TGU_CONDITION_DECODE, j)] = + TGU_CONDITION_DECODE_NOT; + drvdata->enabled = false; /* * Create the sysfs groups only after the backing storage is fully diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h index 7a3e1161c4cfd..8b6a46995a5fd 100644 --- a/drivers/hwtracing/qcom/tgu.h +++ b/drivers/hwtracing/qcom/tgu.h @@ -19,6 +19,8 @@ ((int)FIELD_GET(GENMASK(17, 10), devid_val)) #define TGU_DEVID_STEPS(devid_val) \ ((int)FIELD_GET(GENMASK(6, 3), devid_val)) +#define TGU_DEVID_CONDITIONS(devid_val) \ + ((int)FIELD_GET(GENMASK(2, 0), devid_val)) #define TGU_BITS_PER_SIGNAL 4 #define LENGTH_REGISTER 32 @@ -52,6 +54,7 @@ */ #define STEP_OFFSET 0x1D8 #define PRIORITY_START_OFFSET 0x0074 +#define CONDITION_DECODE_OFFSET 0x0050 #define PRIORITY_OFFSET 0x60 #define REG_OFFSET 0x4 @@ -63,6 +66,7 @@ * * TGU_MAX_STEPS static tables define step0..step7 * TGU_MAX_PRIORITY_REGS STEP_PRIORITY_LIST defines reg0..reg17 + * TGU_MAX_CONDITION_DECODE decode region 0x50..0x5F holds 4 u32 registers * * A device whose DEVID reports counts above these bounds is clamped, so writes * never fall outside the ioremap()'d window or spill into an adjacent region. @@ -70,12 +74,16 @@ #define TGU_MAX_STEPS 8 #define TGU_MAX_PRIORITY_REGS 18 +#define TGU_MAX_CONDITION_DECODE 4 /* Calculate compare step addresses */ #define PRIORITY_REG_STEP(step, priority, reg)\ (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), \ @@ -87,6 +95,8 @@ #define STEP_PRIORITY(step_index, reg_num, priority) \ 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), \ @@ -110,6 +120,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),\ @@ -117,16 +135,32 @@ .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_CONDITION_DECODE, }; /* Maximum priority that TGU supports */ #define MAX_PRIORITY 4 +/* + * Neutral ('NOT') value for the condition decode registers. This is the + * driver's default so that, before userspace programs a real decode, an + * enabled step does not spuriously match. Used both when seeding the shadow + * table at probe and when clearing it via reset_tgu. + */ +#define TGU_CONDITION_DECODE_NOT 0x1000000 + struct tgu_attribute { struct device_attribute attr; u32 step_index; @@ -136,6 +170,7 @@ struct tgu_attribute { struct value_table { unsigned int *priority; + unsigned int *condition_decode; }; static inline void TGU_LOCK(void __iomem *addr) @@ -166,6 +201,7 @@ static inline void TGU_UNLOCK(void __iomem *addr) * @value_table: Store given value based on relevant parameters * @num_reg: Maximum number of registers * @num_step: Maximum step size + * @num_condition_decode: Maximum number of condition_decode * * This structure defines the data associated with a TGU device, * including its base address, device pointer, the lock serialising @@ -179,6 +215,7 @@ struct tgu_drvdata { struct value_table *value_table; int num_reg; int num_step; + int num_condition_decode; }; #endif From 7354886fc38cabe42ec35302d3c2c5be655d6f63 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Thu, 30 Jul 2026 01:07:02 -0700 Subject: [PATCH 0126/1133] FROMLIST: qcom-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/linux-arm-msm/20260730080704.2903540-6-songwei.chai@oss.qualcomm.com/ Reviewed-by: Jie Gan Signed-off-by: Songwei Chai --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 16 +++++ drivers/hwtracing/qcom/tgu.c | 68 ++++++++++++++++++- drivers/hwtracing/qcom/tgu.h | 41 +++++++++++ 3 files changed, 123 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu index 705e75c776d40..fa9e9083065e5 100644 --- a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -21,3 +21,19 @@ KernelVersion: 7.2 Contact: Jinlong Mao , Songwei Chai Description: (RW) Set/Get the decode mode with specific step for TGU. + +What: /sys/bus/amba/devices//step[0:7]_condition_select/reg[0:3] +Date: August 2026 +KernelVersion: 7.2 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the next action with specific step for TGU. + +What: /sys/bus/amba/devices//step[0:7]_condition_select/default +Date: August 2026 +KernelVersion: 7.2 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the default next action for a specific step of the + TGU. This is the last register of the condition select region + and is applied when none of the numbered select registers match. diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c index e83295217e7ab..7f0a74514e40f 100644 --- a/drivers/hwtracing/qcom/tgu.c +++ b/drivers/hwtracing/qcom/tgu.c @@ -30,6 +30,16 @@ static int calculate_array_location(struct tgu_drvdata *drvdata, case TGU_CONDITION_DECODE: return step_index * (drvdata->num_condition_decode) + reg_index; + case TGU_CONDITION_SELECT: + /* + * The 'default' register is the last one in the select region; + * it is exposed with a sentinel reg number, translated here to + * its actual position. + */ + if (reg_index == TGU_SELECT_DEFAULT_REG) + reg_index = drvdata->num_condition_select - 1; + return step_index * (drvdata->num_condition_select) + + reg_index; default: break; } @@ -79,6 +89,9 @@ static ssize_t tgu_dataset_show(struct device *dev, case TGU_CONDITION_DECODE: return sysfs_emit(buf, "0x%x\n", drvdata->value_table->condition_decode[index]); + case TGU_CONDITION_SELECT: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->condition_select[index]); default: break; } @@ -120,6 +133,10 @@ static ssize_t tgu_dataset_store(struct device *dev, tgu_drvdata->value_table->condition_decode[index] = val; ret = size; break; + case TGU_CONDITION_SELECT: + tgu_drvdata->value_table->condition_select[index] = val; + ret = size; + break; default: ret = -EINVAL; break; @@ -158,6 +175,17 @@ static umode_t tgu_node_visible(struct kobject *kobject, if (tgu_attr->reg_num < drvdata->num_condition_decode) return attr->mode; break; + case TGU_CONDITION_SELECT: + /* + * The next-action ('default') register is exposed as its own + * statically named attribute and is always present. The numbered + * data registers occupy the positions before it. + */ + if (tgu_attr->reg_num == TGU_SELECT_DEFAULT_REG) + return attr->mode; + if (tgu_attr->reg_num < drvdata->num_condition_select - 1) + return attr->mode; + break; default: break; } @@ -196,6 +224,18 @@ static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) drvdata->base + CONDITION_DECODE_STEP(i, j)); } } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_condition_select; j++) { + index = check_array_location(drvdata, i, + TGU_CONDITION_SELECT, j); + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->condition_select[index], + drvdata->base + CONDITION_SELECT_STEP(i, j)); + } + } /* Enable TGU to program the triggers */ writel(1, drvdata->base + TGU_CONTROL); exit: @@ -268,6 +308,12 @@ static void tgu_set_conditions(struct tgu_drvdata *drvdata) drvdata->num_condition_decode, TGU_MAX_CONDITION_DECODE); drvdata->num_condition_decode = TGU_MAX_CONDITION_DECODE; } + + /* select region has an additional 'default' register */ + drvdata->num_condition_select = TGU_DEVID_CONDITIONS(devid) + 1; + + if (drvdata->num_condition_select > TGU_MAX_CONDITION_SELECT) + drvdata->num_condition_select = TGU_MAX_CONDITION_SELECT; } static void tgu_disable(struct tgu_drvdata *drvdata) @@ -389,6 +435,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, }; @@ -396,8 +450,8 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct tgu_drvdata *drvdata; - unsigned int *priority, *condition; - size_t priority_size, condition_size; + unsigned int *priority, *condition, *select; + size_t priority_size, condition_size, select_size; int i, j; int ret; @@ -452,6 +506,16 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) drvdata, i, TGU_CONDITION_DECODE, j)] = TGU_CONDITION_DECODE_NOT; + select_size = drvdata->num_condition_select * drvdata->num_step; + + select = devm_kcalloc(dev, select_size, + sizeof(*(drvdata->value_table->condition_select)), + GFP_KERNEL); + if (!select) + return -ENOMEM; + + drvdata->value_table->condition_select = select; + drvdata->enabled = false; /* * Create the sysfs groups only after the backing storage is fully diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h index 8b6a46995a5fd..cee55f66f6292 100644 --- a/drivers/hwtracing/qcom/tgu.h +++ b/drivers/hwtracing/qcom/tgu.h @@ -55,6 +55,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 @@ -67,6 +68,8 @@ * TGU_MAX_STEPS static tables define step0..step7 * TGU_MAX_PRIORITY_REGS STEP_PRIORITY_LIST defines reg0..reg17 * TGU_MAX_CONDITION_DECODE decode region 0x50..0x5F holds 4 u32 registers + * TGU_MAX_CONDITION_SELECT select region 0x60..0x73 holds 5 u32 registers + * (the last one being the 'default' next-action) * * A device whose DEVID reports counts above these bounds is clamped, so writes * never fall outside the ioremap()'d window or spill into an adjacent region. @@ -75,6 +78,7 @@ #define TGU_MAX_STEPS 8 #define TGU_MAX_PRIORITY_REGS 18 #define TGU_MAX_CONDITION_DECODE 4 +#define TGU_MAX_CONDITION_SELECT 5 /* Calculate compare step addresses */ #define PRIORITY_REG_STEP(step, priority, reg)\ @@ -84,6 +88,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), \ @@ -97,6 +104,20 @@ reg_num) #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) + +/* + * The last register of the 'condition select' region is the next-action + * ('default') register. Its position depends on the runtime value of + * num_condition_select, so it is exposed as a dedicated statically named + * "default" attribute carrying a sentinel reg number, rather than renaming + * a shared static attribute at runtime. + */ +#define TGU_SELECT_DEFAULT_REG 0xffff +#define STEP_SELECT_DEFAULT(step_index) \ + tgu_dataset_rw(default, step_index, TGU_CONDITION_SELECT, \ + TGU_SELECT_DEFAULT_REG) #define STEP_PRIORITY_LIST(step_index, priority) \ {STEP_PRIORITY(step_index, 0, priority), \ @@ -128,6 +149,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_DEFAULT(n), \ + NULL \ + } + #define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\ (&(const struct attribute_group){\ .attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\ @@ -142,12 +172,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_SELECT, }; /* Maximum priority that TGU supports */ @@ -171,6 +209,7 @@ struct tgu_attribute { struct value_table { unsigned int *priority; unsigned int *condition_decode; + unsigned int *condition_select; }; static inline void TGU_LOCK(void __iomem *addr) @@ -202,6 +241,7 @@ static inline void TGU_UNLOCK(void __iomem *addr) * @num_reg: Maximum number of registers * @num_step: Maximum step size * @num_condition_decode: Maximum number of condition_decode + * @num_condition_select: Maximum number of condition_select * * This structure defines the data associated with a TGU device, * including its base address, device pointer, the lock serialising @@ -216,6 +256,7 @@ struct tgu_drvdata { int num_reg; int num_step; int num_condition_decode; + int num_condition_select; }; #endif From df81873e8e8281e5faeab0d24e319dd825f08153 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Thu, 30 Jul 2026 01:07:03 -0700 Subject: [PATCH 0127/1133] FROMLIST: qcom-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/linux-arm-msm/20260730080704.2903540-7-songwei.chai@oss.qualcomm.com/ Reviewed-by: Jie Gan Signed-off-by: Songwei Chai --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 14 +++ drivers/hwtracing/qcom/tgu.c | 117 +++++++++++++++++- drivers/hwtracing/qcom/tgu.h | 56 +++++++++ 3 files changed, 185 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu index fa9e9083065e5..a0cad2f163106 100644 --- a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -37,3 +37,17 @@ Description: (RW) Set/Get the default next action for a specific step of the TGU. This is the last register of the condition select region and is applied when none of the numbered select registers match. + +What: /sys/bus/amba/devices//step[0:7]_timer/reg[0:1] +Date: August 2026 +KernelVersion: 7.2 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the timer value with specific step for TGU. + +What: /sys/bus/amba/devices//step[0:7]_counter/reg[0:1] +Date: August 2026 +KernelVersion: 7.2 +Contact: Jinlong Mao , Songwei Chai +Description: + (RW) Set/Get the counter value with specific step for TGU. diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c index 7f0a74514e40f..ea83273a628c5 100644 --- a/drivers/hwtracing/qcom/tgu.c +++ b/drivers/hwtracing/qcom/tgu.c @@ -40,6 +40,10 @@ static int calculate_array_location(struct tgu_drvdata *drvdata, reg_index = drvdata->num_condition_select - 1; return step_index * (drvdata->num_condition_select) + reg_index; + case TGU_COUNTER: + return step_index * (drvdata->num_counter) + reg_index; + case TGU_TIMER: + return step_index * (drvdata->num_timer) + reg_index; default: break; } @@ -92,6 +96,12 @@ static ssize_t tgu_dataset_show(struct device *dev, case TGU_CONDITION_SELECT: return sysfs_emit(buf, "0x%x\n", drvdata->value_table->condition_select[index]); + case TGU_TIMER: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->timer[index]); + case TGU_COUNTER: + return sysfs_emit(buf, "0x%x\n", + drvdata->value_table->counter[index]); default: break; } @@ -137,6 +147,14 @@ static ssize_t tgu_dataset_store(struct device *dev, tgu_drvdata->value_table->condition_select[index] = val; ret = size; break; + case TGU_TIMER: + tgu_drvdata->value_table->timer[index] = val; + ret = size; + break; + case TGU_COUNTER: + tgu_drvdata->value_table->counter[index] = val; + ret = size; + break; default: ret = -EINVAL; break; @@ -186,6 +204,18 @@ static umode_t tgu_node_visible(struct kobject *kobject, if (tgu_attr->reg_num < drvdata->num_condition_select - 1) return attr->mode; break; + case TGU_COUNTER: + if (!drvdata->num_counter) + return SYSFS_GROUP_INVISIBLE; + if (tgu_attr->reg_num < drvdata->num_counter) + return attr->mode; + break; + case TGU_TIMER: + if (!drvdata->num_timer) + return SYSFS_GROUP_INVISIBLE; + if (tgu_attr->reg_num < drvdata->num_timer) + return attr->mode; + break; default: break; } @@ -236,6 +266,30 @@ static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) drvdata->base + CONDITION_SELECT_STEP(i, j)); } } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_timer; j++) { + index = check_array_location(drvdata, i, TGU_TIMER, j); + + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->timer[index], + drvdata->base + TIMER_COMPARE_STEP(i, j)); + } + } + + for (i = 0; i < drvdata->num_step; i++) { + for (j = 0; j < drvdata->num_counter; j++) { + index = check_array_location(drvdata, i, TGU_COUNTER, j); + + if (index == -EINVAL) + goto exit; + + writel(drvdata->value_table->counter[index], + drvdata->base + COUNTER_COMPARE_STEP(i, j)); + } + } /* Enable TGU to program the triggers */ writel(1, drvdata->base + TGU_CONTROL); exit: @@ -316,6 +370,27 @@ static void tgu_set_conditions(struct tgu_drvdata *drvdata) drvdata->num_condition_select = TGU_MAX_CONDITION_SELECT; } +static void tgu_set_timer_counter(struct tgu_drvdata *drvdata) +{ + int num_timers = 0, num_counters = 0; + u32 devid2; + + devid2 = readl(drvdata->base + CORESIGHT_DEVID2); + + if (TGU_DEVID2_TIMER0(devid2)) + num_timers++; + if (TGU_DEVID2_TIMER1(devid2)) + num_timers++; + + if (TGU_DEVID2_COUNTER0(devid2)) + num_counters++; + if (TGU_DEVID2_COUNTER1(devid2)) + num_counters++; + + drvdata->num_timer = num_timers; + drvdata->num_counter = num_counters; +} + static void tgu_disable(struct tgu_drvdata *drvdata) { TGU_UNLOCK(drvdata->base); @@ -443,6 +518,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, }; @@ -450,8 +541,8 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct tgu_drvdata *drvdata; - unsigned int *priority, *condition, *select; - size_t priority_size, condition_size, select_size; + unsigned int *priority, *condition, *select, *timer, *counter; + size_t priority_size, condition_size, select_size, timer_size, counter_size; int i, j; int ret; @@ -473,6 +564,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); @@ -516,7 +608,28 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id) drvdata->value_table->condition_select = select; + timer_size = drvdata->num_step * drvdata->num_timer; + + timer = devm_kcalloc(dev, timer_size, + sizeof(*(drvdata->value_table->timer)), + GFP_KERNEL); + if (!timer) + return -ENOMEM; + + drvdata->value_table->timer = timer; + + counter_size = drvdata->num_step * drvdata->num_counter; + + counter = devm_kcalloc(dev, counter_size, + sizeof(*(drvdata->value_table->counter)), + GFP_KERNEL); + if (!counter) + return -ENOMEM; + + drvdata->value_table->counter = counter; + drvdata->enabled = false; + /* * Create the sysfs groups only after the backing storage is fully * allocated, otherwise userspace could open a priority attribute and diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h index cee55f66f6292..12d2381bfbe0f 100644 --- a/drivers/hwtracing/qcom/tgu.h +++ b/drivers/hwtracing/qcom/tgu.h @@ -14,6 +14,7 @@ #define TGU_LAR 0xfb0 #define TGU_UNLOCK_OFFSET 0xc5acce55 #define TGU_DEVID 0xfc8 +#define CORESIGHT_DEVID2 0xfc0 #define TGU_DEVID_SENSE_INPUT(devid_val) \ ((int)FIELD_GET(GENMASK(17, 10), devid_val)) @@ -21,6 +22,15 @@ ((int)FIELD_GET(GENMASK(6, 3), devid_val)) #define TGU_DEVID_CONDITIONS(devid_val) \ ((int)FIELD_GET(GENMASK(2, 0), devid_val)) +#define TGU_DEVID2_TIMER0(devid_val) \ + ((int)FIELD_GET(GENMASK(23, 18), devid_val)) +#define TGU_DEVID2_TIMER1(devid_val) \ + ((int)FIELD_GET(GENMASK(17, 12), devid_val)) +#define TGU_DEVID2_COUNTER0(devid_val) \ + ((int)FIELD_GET(GENMASK(11, 6), devid_val)) +#define TGU_DEVID2_COUNTER1(devid_val) \ + ((int)FIELD_GET(GENMASK(5, 0), devid_val)) + #define TGU_BITS_PER_SIGNAL 4 #define LENGTH_REGISTER 32 @@ -56,6 +66,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 @@ -91,6 +103,12 @@ #define CONDITION_SELECT_STEP(step, select) \ (CONDITION_SELECT_OFFSET + REG_OFFSET * select + 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 tgu_dataset_rw(name, step_index, type, reg_num) \ (&((struct tgu_attribute[]){ { \ __ATTR(name, 0644, tgu_dataset_show, tgu_dataset_store), \ @@ -106,6 +124,10 @@ 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_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) /* * The last register of the 'condition select' region is the next-action @@ -158,6 +180,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),\ @@ -179,6 +213,20 @@ .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, @@ -186,6 +234,8 @@ enum operation_index { TGU_PRIORITY3, TGU_CONDITION_DECODE, TGU_CONDITION_SELECT, + TGU_TIMER, + TGU_COUNTER, }; /* Maximum priority that TGU supports */ @@ -210,6 +260,8 @@ struct value_table { unsigned int *priority; unsigned int *condition_decode; unsigned int *condition_select; + unsigned int *timer; + unsigned int *counter; }; static inline void TGU_LOCK(void __iomem *addr) @@ -242,6 +294,8 @@ static inline void TGU_UNLOCK(void __iomem *addr) * @num_step: Maximum step size * @num_condition_decode: Maximum number of condition_decode * @num_condition_select: Maximum number of condition_select + * @num_timer: Maximum number of timers + * @num_counter: Maximum number of counters * * This structure defines the data associated with a TGU device, * including its base address, device pointer, the lock serialising @@ -257,6 +311,8 @@ struct tgu_drvdata { int num_step; int num_condition_decode; int num_condition_select; + int num_timer; + int num_counter; }; #endif From 89e49d99dcbc2a5f15cc9f3309801931f1ce1f47 Mon Sep 17 00:00:00 2001 From: Songwei Chai Date: Thu, 30 Jul 2026 01:07:04 -0700 Subject: [PATCH 0128/1133] FROMLIST: qcom-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/linux-arm-msm/20260730080704.2903540-8-songwei.chai@oss.qualcomm.com/ Signed-off-by: Songwei Chai Reviewed-by: Jie Gan --- .../ABI/testing/sysfs-bus-amba-devices-tgu | 7 ++ drivers/hwtracing/qcom/tgu.c | 84 +++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu index a0cad2f163106..5c928a5fa0338 100644 --- a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -51,3 +51,10 @@ KernelVersion: 7.2 Contact: Jinlong Mao , Songwei Chai Description: (RW) Set/Get the counter value with specific step for TGU. + +What: /sys/bus/amba/devices//reset_tgu +Date: August 2026 +KernelVersion: 7.2 +Contact: Jinlong Mao , Songwei Chai +Description: + (Write) Write 1 to reset the dataset for TGU. diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c index ea83273a628c5..d65a68faa7418 100644 --- a/drivers/hwtracing/qcom/tgu.c +++ b/drivers/hwtracing/qcom/tgu.c @@ -228,6 +228,18 @@ static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) int i, j, k, index = 0; TGU_UNLOCK(drvdata->base); + + /* + * Quiesce the detection engine before mutating any comparison input. + * This function is also reached from reset_tgu_store() while the TGU is + * already running (TGU_CONTROL == 1); rewriting the priority/condition/ + * timer/counter registers register-by-register on a live engine could + * feed a transient, half-updated match into CTI/interrupt consumers. + * Programming with CONTROL == 0 and only re-enabling at the end keeps the + * program-then-enable ordering for every caller. + */ + writel(0, drvdata->base + TGU_CONTROL); + for (i = 0; i < drvdata->num_step; i++) { for (j = 0; j < MAX_PRIORITY; j++) { for (k = 0; k < drvdata->num_reg; k++) { @@ -459,8 +471,80 @@ static ssize_t enable_tgu_store(struct device *dev, } static DEVICE_ATTR_RW(enable_tgu); +static ssize_t reset_tgu_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + struct tgu_drvdata *drvdata = dev_get_drvdata(dev); + struct value_table *vt = drvdata->value_table; + unsigned long value; + int i, j, ret; + + if (kstrtoul(buf, 0, &value) || value != 1) + return -EINVAL; + + /* + * Hold the mutex across the whole sequence so it cannot race with + * enable_tgu_store()/tgu_dataset_store(): the enabled check and the + * hardware access stay consistent. No PM reference is taken or dropped + * here - the shadow tables are plain memory, and the hardware is only + * touched when the device is already resumed via the enable reference. + */ + guard(mutex)(&drvdata->lock); + + if (vt->priority) { + size_t bytes = MAX_PRIORITY * drvdata->num_step * + drvdata->num_reg * sizeof(unsigned int); + memset(vt->priority, 0, bytes); + } + + if (vt->condition_decode) { + size_t bytes = drvdata->num_condition_decode * + drvdata->num_step * sizeof(unsigned int); + memset(vt->condition_decode, 0, bytes); + + /* Initialize all condition decode registers to NOT (0x1000000) */ + for (i = 0; i < drvdata->num_step; i++) + for (j = 0; j < drvdata->num_condition_decode; j++) + vt->condition_decode[calculate_array_location( + drvdata, i, TGU_CONDITION_DECODE, j)] = + TGU_CONDITION_DECODE_NOT; + } + + if (vt->condition_select) { + size_t bytes = drvdata->num_condition_select * + drvdata->num_step * sizeof(unsigned int); + memset(vt->condition_select, 0, bytes); + } + + if (vt->timer) { + size_t bytes = drvdata->num_step * drvdata->num_timer * + sizeof(unsigned int); + memset(vt->timer, 0, bytes); + } + + if (vt->counter) { + size_t bytes = drvdata->num_step * drvdata->num_counter * + sizeof(unsigned int); + memset(vt->counter, 0, bytes); + } + + /* If the TGU is running, apply the cleared configuration immediately. */ + if (drvdata->enabled) { + ret = tgu_write_all_hw_regs(drvdata); + if (ret) + return ret; + } + + dev_dbg(dev, "Qualcomm-TGU reset complete\n"); + + return size; +} +static DEVICE_ATTR_WO(reset_tgu); + static struct attribute *tgu_common_attrs[] = { &dev_attr_enable_tgu.attr, + &dev_attr_reset_tgu.attr, NULL, }; From b98534213853ffafc29a9c0de5daf3f368e93052 Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Mon, 15 Jun 2026 20:32:29 +0800 Subject: [PATCH 0129/1133] FROMLIST: coresight: cti: Convert trigger usage fields to dynamic Replace the fixed-size u32 fields in the cti_config and cti_trig_grp structure with dynamically allocated bitmaps and arrays. This allows memory to be allocated based on the actual number of triggers during probe time, reducing memory footprint and improving scalability for platforms with varying trigger counts. Also add a bounds check in cti_allocate_trig_con() to ensure the caller does not pass in/out signal counts larger than nr_trig_max. Link: https://lore.kernel.org/all/20260615-extended_cti-v10-1-1c1694b6d8ed@oss.qualcomm.com/ Reviewed-by: Leo Yan Signed-off-by: Yingchao Deng --- .../hwtracing/coresight/coresight-cti-core.c | 70 +++++++++++++++---- .../coresight/coresight-cti-platform.c | 26 ++++--- .../hwtracing/coresight/coresight-cti-sysfs.c | 14 ++-- drivers/hwtracing/coresight/coresight-cti.h | 12 ++-- 4 files changed, 87 insertions(+), 35 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index b2c9a4db13b4e..572798ab504c8 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -161,8 +161,8 @@ void cti_write_intack(struct device *dev, u32 ackval) /* DEVID[19:16] - number of CTM channels */ #define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19)) -static void cti_set_default_config(struct device *dev, - struct cti_drvdata *drvdata) +static int cti_set_default_config(struct device *dev, + struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; u32 devid; @@ -181,6 +181,31 @@ static void cti_set_default_config(struct device *dev, config->nr_trig_max = CTIINOUTEN_MAX; } + config->trig_in_use = devm_bitmap_zalloc(dev, config->nr_trig_max, + GFP_KERNEL); + if (!config->trig_in_use) + return -ENOMEM; + + config->trig_out_use = devm_bitmap_zalloc(dev, config->nr_trig_max, + GFP_KERNEL); + if (!config->trig_out_use) + return -ENOMEM; + + config->trig_out_filter = devm_bitmap_zalloc(dev, config->nr_trig_max, + GFP_KERNEL); + if (!config->trig_out_filter) + return -ENOMEM; + + config->ctiinen = devm_kcalloc(dev, config->nr_trig_max, sizeof(u32), + GFP_KERNEL); + if (!config->ctiinen) + return -ENOMEM; + + config->ctiouten = devm_kcalloc(dev, config->nr_trig_max, sizeof(u32), + GFP_KERNEL); + if (!config->ctiouten) + return -ENOMEM; + config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid); /* Most regs default to 0 as zalloc'ed except...*/ @@ -189,6 +214,7 @@ static void cti_set_default_config(struct device *dev, config->enable_req_count = 0; config->asicctl_impl = !!FIELD_GET(GENMASK(4, 0), devid); + return 0; } /* @@ -219,8 +245,10 @@ int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata, cti_dev->nr_trig_con++; /* add connection usage bit info to overall info */ - drvdata->config.trig_in_use |= tc->con_in->used_mask; - drvdata->config.trig_out_use |= tc->con_out->used_mask; + bitmap_or(drvdata->config.trig_in_use, drvdata->config.trig_in_use, + tc->con_in->used_mask, drvdata->config.nr_trig_max); + bitmap_or(drvdata->config.trig_out_use, drvdata->config.trig_out_use, + tc->con_out->used_mask, drvdata->config.nr_trig_max); return 0; } @@ -231,6 +259,14 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs, { struct cti_trig_con *tc = NULL; struct cti_trig_grp *in = NULL, *out = NULL; + struct cti_drvdata *drvdata = dev_get_drvdata(dev); + int n_trigs = drvdata->config.nr_trig_max; + + if (in_sigs > n_trigs || out_sigs > n_trigs) { + dev_err(dev, "trigger signal is out of range: in=%d out=%d nr_max=%d\n", + in_sigs, out_sigs, n_trigs); + return NULL; + } tc = devm_kzalloc(dev, sizeof(struct cti_trig_con), GFP_KERNEL); if (!tc) @@ -242,12 +278,20 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs, if (!in) return NULL; + in->used_mask = devm_bitmap_zalloc(dev, n_trigs, GFP_KERNEL); + if (!in->used_mask) + return NULL; + out = devm_kzalloc(dev, offsetof(struct cti_trig_grp, sig_types[out_sigs]), GFP_KERNEL); if (!out) return NULL; + out->used_mask = devm_bitmap_zalloc(dev, n_trigs, GFP_KERNEL); + if (!out->used_mask) + return NULL; + tc->con_in = in; tc->con_out = out; tc->con_in->nr_sigs = in_sigs; @@ -263,7 +307,6 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata) { int ret = 0; int n_trigs = drvdata->config.nr_trig_max; - u32 n_trig_mask = GENMASK(n_trigs - 1, 0); struct cti_trig_con *tc = NULL; /* @@ -274,8 +317,8 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata) if (!tc) return -ENOMEM; - tc->con_in->used_mask = n_trig_mask; - tc->con_out->used_mask = n_trig_mask; + bitmap_fill(tc->con_in->used_mask, n_trigs); + bitmap_fill(tc->con_out->used_mask, n_trigs); ret = cti_add_connection_entry(dev, drvdata, tc, NULL, "default"); return ret; } @@ -288,7 +331,6 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, { struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *config = &drvdata->config; - u32 trig_bitmask; u32 chan_bitmask; u32 reg_value; int reg_offset; @@ -298,18 +340,16 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, (trigger_idx >= config->nr_trig_max)) return -EINVAL; - trig_bitmask = BIT(trigger_idx); - /* ensure registered triggers and not out filtered */ if (direction == CTI_TRIG_IN) { - if (!(trig_bitmask & config->trig_in_use)) + if (!(test_bit(trigger_idx, config->trig_in_use))) return -EINVAL; } else { - if (!(trig_bitmask & config->trig_out_use)) + if (!(test_bit(trigger_idx, config->trig_out_use))) return -EINVAL; if ((config->trig_filter_enable) && - (config->trig_out_filter & trig_bitmask)) + test_bit(trigger_idx, config->trig_out_filter)) return -EINVAL; } @@ -687,7 +727,9 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) raw_spin_lock_init(&drvdata->spinlock); /* initialise CTI driver config values */ - cti_set_default_config(dev, drvdata); + ret = cti_set_default_config(dev, drvdata); + if (ret) + return ret; pdata = coresight_cti_get_platform_data(dev); if (IS_ERR(pdata)) { diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c index d6d5388705c3e..ba5a7e4b6bff0 100644 --- a/drivers/hwtracing/coresight/coresight-cti-platform.c +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c @@ -136,8 +136,8 @@ static int cti_plat_create_v8_etm_connection(struct device *dev, goto create_v8_etm_out; /* build connection data */ - tc->con_in->used_mask = 0xF0; /* sigs <4,5,6,7> */ - tc->con_out->used_mask = 0xF0; /* sigs <4,5,6,7> */ + bitmap_set(tc->con_in->used_mask, 4, 4); /* sigs <4,5,6,7> */ + bitmap_set(tc->con_out->used_mask, 4, 4); /* sigs <4,5,6,7> */ /* * The EXTOUT type signals from the ETM are connected to a set of input @@ -194,10 +194,10 @@ static int cti_plat_create_v8_connections(struct device *dev, goto of_create_v8_out; /* Set the v8 PE CTI connection data */ - tc->con_in->used_mask = 0x3; /* sigs <0 1> */ + bitmap_set(tc->con_in->used_mask, 0, 2); /* sigs <0 1> */ tc->con_in->sig_types[0] = PE_DBGTRIGGER; tc->con_in->sig_types[1] = PE_PMUIRQ; - tc->con_out->used_mask = 0x7; /* sigs <0 1 2 > */ + bitmap_set(tc->con_out->used_mask, 0, 3); /* sigs <0 1 2 > */ tc->con_out->sig_types[0] = PE_EDBGREQ; tc->con_out->sig_types[1] = PE_DBGRESTART; tc->con_out->sig_types[2] = PE_CTIIRQ; @@ -213,7 +213,7 @@ static int cti_plat_create_v8_connections(struct device *dev, goto of_create_v8_out; /* filter pe_edbgreq - PE trigout sig <0> */ - drvdata->config.trig_out_filter |= 0x1; + set_bit(0, drvdata->config.trig_out_filter); of_create_v8_out: return ret; @@ -257,7 +257,7 @@ static int cti_plat_read_trig_group(struct cti_trig_grp *tgrp, if (!err) { /* set the signal usage mask */ for (idx = 0; idx < tgrp->nr_sigs; idx++) - tgrp->used_mask |= BIT(values[idx]); + set_bit(values[idx], tgrp->used_mask); } kfree(values); @@ -316,24 +316,34 @@ static int cti_plat_process_filter_sigs(struct cti_drvdata *drvdata, { struct cti_trig_grp *tg = NULL; int err = 0, nr_filter_sigs; + int nr_trigs = drvdata->config.nr_trig_max; nr_filter_sigs = cti_plat_count_sig_elements(fwnode, CTI_DT_FILTER_OUT_SIGS); if (nr_filter_sigs == 0) return 0; - if (nr_filter_sigs > drvdata->config.nr_trig_max) + if (nr_filter_sigs > nr_trigs) return -EINVAL; tg = kzalloc_obj(*tg); if (!tg) return -ENOMEM; + tg->used_mask = bitmap_zalloc(nr_trigs, GFP_KERNEL); + if (!tg->used_mask) { + kfree(tg); + return -ENOMEM; + } + tg->nr_sigs = nr_filter_sigs; err = cti_plat_read_trig_group(tg, fwnode, CTI_DT_FILTER_OUT_SIGS); if (!err) - drvdata->config.trig_out_filter |= tg->used_mask; + bitmap_or(drvdata->config.trig_out_filter, + drvdata->config.trig_out_filter, + tg->used_mask, nr_trigs); + bitmap_free(tg->used_mask); kfree(tg); return err; } diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index 2ed5d8eb1ddab..ee10f16984aaf 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -719,12 +719,12 @@ static ssize_t trigout_filtered_show(struct device *dev, struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *cfg = &drvdata->config; int nr_trig_max = cfg->nr_trig_max; - unsigned long mask = cfg->trig_out_filter; + unsigned long *mask = cfg->trig_out_filter; - if (mask == 0) + if (bitmap_empty(mask, nr_trig_max)) return 0; - return sysfs_emit(buf, "%*pbl\n", nr_trig_max, &mask); + return sysfs_emit(buf, "%*pbl\n", nr_trig_max, mask); } static DEVICE_ATTR_RO(trigout_filtered); @@ -931,9 +931,9 @@ static ssize_t trigin_sig_show(struct device *dev, struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *cfg = &drvdata->config; - unsigned long mask = con->con_in->used_mask; + unsigned long *mask = con->con_in->used_mask; - return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, &mask); + return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, mask); } static ssize_t trigout_sig_show(struct device *dev, @@ -945,9 +945,9 @@ static ssize_t trigout_sig_show(struct device *dev, struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *cfg = &drvdata->config; - unsigned long mask = con->con_out->used_mask; + unsigned long *mask = con->con_out->used_mask; - return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, &mask); + return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, mask); } /* convert a sig type id to a name */ diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index c5f9e79fabc60..ef079fc18b72a 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -68,7 +68,7 @@ struct fwnode_handle; */ struct cti_trig_grp { int nr_sigs; - u32 used_mask; + unsigned long *used_mask; int sig_types[]; }; @@ -145,17 +145,17 @@ struct cti_config { int enable_req_count; /* registered triggers and filtering */ - u32 trig_in_use; - u32 trig_out_use; - u32 trig_out_filter; + unsigned long *trig_in_use; + unsigned long *trig_out_use; + unsigned long *trig_out_filter; bool trig_filter_enable; u8 xtrig_rchan_sel; /* cti cross trig programmable regs */ u32 ctiappset; u8 ctiinout_sel; - u32 ctiinen[CTIINOUTEN_MAX]; - u32 ctiouten[CTIINOUTEN_MAX]; + u32 *ctiinen; + u32 *ctiouten; u32 ctigate; u32 asicctl; }; From 8d57e5b8997a9b8883111e9a9777ff70539c1374 Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Mon, 15 Jun 2026 20:32:30 +0800 Subject: [PATCH 0130/1133] FROMLIST: coresight: cti: use __reg_addr() helper for register access Introduce a static inline __reg_addr(drvdata, off, index) helper in coresight-cti.h to compute MMIO addresses from a base offset and a per-trigger index, replacing the function-like CTIINEN(n)/CTIOUTEN(n) macros with base offsets and explicit index arithmetic. Add reg_addr and reg_index_addr convenience macros for zero-index and indexed access respectively. Convert cti_read_single_reg() and cti_write_single_reg() to static inline wrappers in coresight-cti.h, and add indexed variants cti_read_single_reg_index() / cti_write_single_reg_index() for callers that need explicit bank selection. Extend cs_off_attribute with a u32 index field and update coresight_cti_reg_show/store to use the attribute's index field directly. Link: https://lore.kernel.org/all/20260615-extended_cti-v10-2-1c1694b6d8ed@oss.qualcomm.com/ Co-developed-by: Jinlong Mao Signed-off-by: Jinlong Mao Signed-off-by: Yingchao Deng --- .../hwtracing/coresight/coresight-cti-core.c | 36 ++++----------- .../hwtracing/coresight/coresight-cti-sysfs.c | 17 ++++--- drivers/hwtracing/coresight/coresight-cti.h | 46 +++++++++++++++++-- drivers/hwtracing/coresight/coresight-priv.h | 4 +- 4 files changed, 64 insertions(+), 39 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index 572798ab504c8..fa758c535ccbf 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -55,16 +55,17 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) /* write the CTI trigger registers */ for (i = 0; i < config->nr_trig_max; i++) { - writel_relaxed(config->ctiinen[i], drvdata->base + CTIINEN(i)); + writel_relaxed(config->ctiinen[i], + reg_index_addr(drvdata, CTIINEN, i)); writel_relaxed(config->ctiouten[i], - drvdata->base + CTIOUTEN(i)); + reg_index_addr(drvdata, CTIOUTEN, i)); } /* other regs */ - writel_relaxed(config->ctigate, drvdata->base + CTIGATE); + writel_relaxed(config->ctigate, reg_addr(drvdata, CTIGATE)); if (config->asicctl_impl) - writel_relaxed(config->asicctl, drvdata->base + ASICCTL); - writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET); + writel_relaxed(config->asicctl, reg_addr(drvdata, ASICCTL)); + writel_relaxed(config->ctiappset, reg_addr(drvdata, CTIAPPSET)); /* re-enable CTI */ writel_relaxed(1, drvdata->base + CTICONTROL); @@ -122,24 +123,6 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) return 0; } -u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset) -{ - int val; - - CS_UNLOCK(drvdata->base); - val = readl_relaxed(drvdata->base + offset); - CS_LOCK(drvdata->base); - - return val; -} - -void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value) -{ - CS_UNLOCK(drvdata->base); - writel_relaxed(value, drvdata->base + offset); - CS_LOCK(drvdata->base); -} - void cti_write_intack(struct device *dev, u32 ackval) { struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); @@ -333,7 +316,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, struct cti_config *config = &drvdata->config; u32 chan_bitmask; u32 reg_value; - int reg_offset; + u32 reg_offset; /* ensure indexes in range */ if ((channel_idx >= config->nr_ctm_channels) || @@ -355,8 +338,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, /* update the local register values */ chan_bitmask = BIT(channel_idx); - reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) : - CTIOUTEN(trigger_idx)); + reg_offset = (direction == CTI_TRIG_IN ? CTIINEN : CTIOUTEN); guard(raw_spinlock_irqsave)(&drvdata->spinlock); @@ -376,7 +358,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, /* write through if enabled */ if (cti_is_active(config)) - cti_write_single_reg(drvdata, reg_offset, reg_value); + cti_write_single_reg_index(drvdata, reg_offset, trigger_idx, reg_value); return 0; } diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index ee10f16984aaf..51409d4b868cb 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -171,7 +171,7 @@ static ssize_t coresight_cti_reg_show(struct device *dev, pm_runtime_get_sync(dev->parent); scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) - val = cti_read_single_reg(drvdata, cti_attr->off); + val = cti_read_single_reg_index(drvdata, cti_attr->off, cti_attr->index); pm_runtime_put_sync(dev->parent); return sysfs_emit(buf, "0x%x\n", val); @@ -192,7 +192,7 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, pm_runtime_get_sync(dev->parent); scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) - cti_write_single_reg(drvdata, cti_attr->off, val); + cti_write_single_reg_index(drvdata, cti_attr->off, cti_attr->index, val); pm_runtime_put_sync(dev->parent); return size; @@ -202,7 +202,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, (&((struct cs_off_attribute[]) { \ { \ __ATTR(name, 0444, coresight_cti_reg_show, NULL), \ - offset \ + offset, \ + 0 \ } \ })[0].attr.attr) @@ -211,7 +212,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, { \ __ATTR(name, 0644, coresight_cti_reg_show, \ coresight_cti_reg_store), \ - offset \ + offset, \ + 0 \ } \ })[0].attr.attr) @@ -219,7 +221,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, (&((struct cs_off_attribute[]) { \ { \ __ATTR(name, 0200, NULL, coresight_cti_reg_store), \ - offset \ + offset, \ + 0 \ } \ })[0].attr.attr) @@ -386,7 +389,7 @@ static ssize_t inen_store(struct device *dev, /* write through if enabled */ if (cti_is_active(config)) - cti_write_single_reg(drvdata, CTIINEN(index), val); + cti_write_single_reg_index(drvdata, CTIINEN, index, val); return size; } @@ -427,7 +430,7 @@ static ssize_t outen_store(struct device *dev, /* write through if enabled */ if (cti_is_active(config)) - cti_write_single_reg(drvdata, CTIOUTEN(index), val); + cti_write_single_reg_index(drvdata, CTIOUTEN, index, val); return size; } diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index ef079fc18b72a..634bdce5cdfd7 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -30,8 +30,8 @@ struct fwnode_handle; #define CTIAPPSET 0x014 #define CTIAPPCLEAR 0x018 #define CTIAPPPULSE 0x01C -#define CTIINEN(n) (0x020 + (4 * n)) -#define CTIOUTEN(n) (0x0A0 + (4 * n)) +#define CTIINEN 0x020 +#define CTIOUTEN 0x0A0 #define CTITRIGINSTATUS 0x130 #define CTITRIGOUTSTATUS 0x134 #define CTICHINSTATUS 0x138 @@ -217,8 +217,6 @@ int cti_enable(struct coresight_device *csdev, enum cs_mode mode, int cti_disable(struct coresight_device *csdev, struct coresight_path *path); void cti_write_all_hw_regs(struct cti_drvdata *drvdata); void cti_write_intack(struct device *dev, u32 ackval); -void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value); -u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset); int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, enum cti_trig_dir direction, u32 channel_idx, u32 trigger_idx); @@ -231,6 +229,46 @@ struct coresight_platform_data * coresight_cti_get_platform_data(struct device *dev); const char *cti_plat_get_node_name(struct fwnode_handle *fwnode); +static inline void __iomem *__reg_addr(struct cti_drvdata *drvdata, + u32 off, u32 index) +{ + return drvdata->base + off + index * sizeof(u32); +} + +#define reg_addr(drvdata, off) __reg_addr((drvdata), (off), 0) +#define reg_index_addr(drvdata, off, i) __reg_addr((drvdata), (off), (i)) + +static inline u32 cti_read_single_reg_index(struct cti_drvdata *drvdata, + u32 off, u32 index) +{ + u32 val; + + CS_UNLOCK(drvdata->base); + val = readl_relaxed(reg_index_addr(drvdata, off, index)); + CS_LOCK(drvdata->base); + + return val; +} + +static inline u32 cti_read_single_reg(struct cti_drvdata *drvdata, u32 off) +{ + return cti_read_single_reg_index(drvdata, off, 0); +} + +static inline void cti_write_single_reg_index(struct cti_drvdata *drvdata, + u32 off, u32 index, u32 value) +{ + CS_UNLOCK(drvdata->base); + writel_relaxed(value, reg_index_addr(drvdata, off, index)); + CS_LOCK(drvdata->base); +} + +static inline void cti_write_single_reg(struct cti_drvdata *drvdata, + u32 off, u32 value) +{ + cti_write_single_reg_index(drvdata, off, 0, value); +} + /* Check if a cti device is enabled */ static inline bool cti_is_active(struct cti_config *cfg) { diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index dddac946659fc..cb4736324c049 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -58,6 +58,7 @@ struct cs_pair_attribute { struct cs_off_attribute { struct device_attribute attr; u32 off; + u32 index; }; ssize_t coresight_simple_show32(struct device *_dev, struct device_attribute *attr, char *buf); @@ -67,7 +68,8 @@ ssize_t coresight_simple_show_pair(struct device *_dev, struct device_attribute (&((struct cs_off_attribute[]) { \ { \ __ATTR(name, 0444, coresight_simple_show32, NULL), \ - offset \ + offset, \ + 0 \ } \ })[0].attr.attr) From 2ccb95c30d488d7e1c1455c61cdddb479ee8d964 Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Mon, 15 Jun 2026 20:32:31 +0800 Subject: [PATCH 0131/1133] FROMLIST: coresight: cti: add Qualcomm extended CTI identification and quirks Qualcomm implements an extended variant of the ARM CoreSight CTI with a different register layout and vendor-specific behavior. While the programming model remains largely compatible, the register offsets differ from the standard ARM CTI and require explicit handling. Detect Qualcomm CTIs via the DEVARCH register and record this in the CTI driver data. Introduce a small mapping layer to translate standard CTI register offsets to Qualcomm-specific offsets, allowing the rest of the driver to use a common register access path. Additionally, handle a Qualcomm-specific quirk where the hardware does not implement the CoreSight Claim tag protocol. Instead of clearing the CLAIMSET register at probe time, bypass the claim/disclaim operations entirely for Qualcomm CTIs by wrapping coresight_claim_device(), coresight_disclaim_device_unlocked() and coresight_clear_self_claim_tag() in thin helpers that early-return when is_qcom_cti is set. No functional change is intended for standard ARM CTI devices. Link: https://lore.kernel.org/all/20260615-extended_cti-v10-3-1c1694b6d8ed@oss.qualcomm.com/ Co-developed-by: Jinlong Mao Signed-off-by: Jinlong Mao Signed-off-by: Yingchao Deng --- .../hwtracing/coresight/coresight-cti-core.c | 47 ++++++++++++-- drivers/hwtracing/coresight/coresight-cti.h | 64 ++++++++++++++++++- 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c index fa758c535ccbf..5b83dd4e603bd 100644 --- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -73,6 +73,35 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) CS_LOCK(drvdata->base); } +/* + * Qualcomm CTIs do not implement the CoreSight Claim tag protocol, so + * bypass coresight_clear_self_claim_tag() for them. + */ +static void cti_clear_self_claim_tag(struct cti_drvdata *drvdata, + struct csdev_access *csa) +{ + if (drvdata->is_qcom_cti) + return; + + coresight_clear_self_claim_tag(csa); +} + +static int cti_claim_device(struct cti_drvdata *drvdata) +{ + if (drvdata->is_qcom_cti) + return 0; + + return coresight_claim_device(drvdata->csdev); +} + +static void cti_unclaim_device_unlocked(struct cti_drvdata *drvdata) +{ + if (drvdata->is_qcom_cti) + return; + + coresight_disclaim_device_unlocked(drvdata->csdev); +} + /* write regs to hardware and enable */ static int cti_enable_hw(struct cti_drvdata *drvdata) { @@ -86,7 +115,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) goto cti_state_unchanged; /* claim the device */ - rc = coresight_claim_device(drvdata->csdev); + rc = cti_claim_device(drvdata); if (rc) return rc; @@ -101,7 +130,6 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) static int cti_disable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; - struct coresight_device *csdev = drvdata->csdev; guard(raw_spinlock_irqsave)(&drvdata->spinlock); @@ -118,7 +146,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) /* disable CTI */ writel_relaxed(0, drvdata->base + CTICONTROL); - coresight_disclaim_device_unlocked(csdev); + cti_unclaim_device_unlocked(drvdata); CS_LOCK(drvdata->base); return 0; } @@ -144,6 +172,9 @@ void cti_write_intack(struct device *dev, u32 ackval) /* DEVID[19:16] - number of CTM channels */ #define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19)) +/* DEVARCH[31:21] - ARCHITECT */ +#define CTI_DEVARCH_ARCHITECT(devarch_val) ((int)BMVAL(devarch_val, 21, 31)) + static int cti_set_default_config(struct device *dev, struct cti_drvdata *drvdata) { @@ -684,6 +715,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) struct coresight_desc cti_desc = { 0 }; struct coresight_platform_data *pdata = NULL; struct resource *res = &adev->res; + u32 devarch; /* driver data*/ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); @@ -708,6 +740,10 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) raw_spin_lock_init(&drvdata->spinlock); + devarch = readl_relaxed(drvdata->base + CORESIGHT_DEVARCH); + if (CTI_DEVARCH_ARCHITECT(devarch) == QCOM_ARCHITECT) + drvdata->is_qcom_cti = true; + /* initialise CTI driver config values */ ret = cti_set_default_config(dev, drvdata); if (ret) @@ -753,7 +789,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) cti_desc.groups = drvdata->ctidev.con_groups; cti_desc.dev = dev; - coresight_clear_self_claim_tag(&cti_desc.access); + cti_clear_self_claim_tag(drvdata, &cti_desc.access); drvdata->csdev = coresight_register(&cti_desc); if (IS_ERR(drvdata->csdev)) return PTR_ERR(drvdata->csdev); @@ -767,7 +803,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) /* all done - dec pm refcount */ pm_runtime_put(&adev->dev); - dev_info(&drvdata->csdev->dev, "CTI initialized\n"); + dev_info(&drvdata->csdev->dev, + "%sCTI initialized\n", drvdata->is_qcom_cti ? "QCOM " : ""); return 0; } diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index 634bdce5cdfd7..4b6fd6b551142 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -54,10 +54,36 @@ struct fwnode_handle; /* * CTI CSSoc 600 has a max of 32 trigger signals per direction. * CTI CSSoc 400 has 8 IO triggers - other CTIs can be impl def. + * QCOM CTI support up to 128 trigger signals per direction. * Max of in and out defined in the DEVID register. * - pick up actual number used from .dts parameters if present. */ -#define CTIINOUTEN_MAX 32 +#define CTIINOUTEN_MAX 128 + +/* QCOM CTI extension */ +#define QCOM_ARCHITECT 0x477 + +#define QCOM_CTIINTACK 0x020 +#define QCOM_CTIAPPSET 0x004 +#define QCOM_CTIAPPCLEAR 0x008 +#define QCOM_CTIAPPPULSE 0x00C +#define QCOM_CTIINEN 0x400 +#define QCOM_CTIOUTEN 0x800 +#define QCOM_CTITRIGINSTATUS 0x040 +#define QCOM_CTITRIGOUTSTATUS 0x060 +#define QCOM_CTICHINSTATUS 0x080 +#define QCOM_CTICHOUTSTATUS 0x084 +#define QCOM_CTIGATE 0x088 +#define QCOM_ASICCTL 0x08C +/* Integration test registers */ +#define QCOM_ITCHINACK 0xE70 +#define QCOM_ITTRIGINACK 0xE80 +#define QCOM_ITCHOUT 0xE74 +#define QCOM_ITTRIGOUT 0xEA0 +#define QCOM_ITCHOUTACK 0xE78 +#define QCOM_ITTRIGOUTACK 0xEC0 +#define QCOM_ITCHIN 0xE7C +#define QCOM_ITTRIGIN 0xEE0 /** * Group of related trigger signals @@ -168,6 +194,9 @@ struct cti_config { * @spinlock: Control data access to one at a time. * @config: Configuration data for this CTI device. * @node: List entry of this device in the list of CTI devices. + * @is_qcom_cti: True if this CTI is a Qualcomm vendor-specific + * variant that requires register offset translation + * via cti_qcom_reg_off(). */ struct cti_drvdata { void __iomem *base; @@ -176,6 +205,7 @@ struct cti_drvdata { raw_spinlock_t spinlock; struct cti_config config; struct list_head node; + bool is_qcom_cti; }; /* @@ -229,9 +259,41 @@ struct coresight_platform_data * coresight_cti_get_platform_data(struct device *dev); const char *cti_plat_get_node_name(struct fwnode_handle *fwnode); +static inline u32 cti_qcom_reg_off(u32 offset) +{ + switch (offset) { + case CTIINTACK: return QCOM_CTIINTACK; + case CTIAPPSET: return QCOM_CTIAPPSET; + case CTIAPPCLEAR: return QCOM_CTIAPPCLEAR; + case CTIAPPPULSE: return QCOM_CTIAPPPULSE; + case CTIINEN: return QCOM_CTIINEN; + case CTIOUTEN: return QCOM_CTIOUTEN; + case CTITRIGINSTATUS: return QCOM_CTITRIGINSTATUS; + case CTITRIGOUTSTATUS: return QCOM_CTITRIGOUTSTATUS; + case CTICHINSTATUS: return QCOM_CTICHINSTATUS; + case CTICHOUTSTATUS: return QCOM_CTICHOUTSTATUS; + case CTIGATE: return QCOM_CTIGATE; + case ASICCTL: return QCOM_ASICCTL; + case ITCHINACK: return QCOM_ITCHINACK; + case ITTRIGINACK: return QCOM_ITTRIGINACK; + case ITCHOUT: return QCOM_ITCHOUT; + case ITTRIGOUT: return QCOM_ITTRIGOUT; + case ITCHOUTACK: return QCOM_ITCHOUTACK; + case ITTRIGOUTACK: return QCOM_ITTRIGOUTACK; + case ITCHIN: return QCOM_ITCHIN; + case ITTRIGIN: return QCOM_ITTRIGIN; + + default: + return offset; + } +} + static inline void __iomem *__reg_addr(struct cti_drvdata *drvdata, u32 off, u32 index) { + if (unlikely(drvdata->is_qcom_cti)) + off = cti_qcom_reg_off(off); + return drvdata->base + off + index * sizeof(u32); } From df0d718619f3a95de6bd3c7f582d8c3e01a86620 Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Mon, 15 Jun 2026 20:32:32 +0800 Subject: [PATCH 0132/1133] FROMLIST: coresight: cti: expose banked sysfs registers for Qualcomm extended CTI Qualcomm extended CTI implements banked trigger status and integration registers, where each bank covers 32 triggers. Multiple instances of these registers are required to expose the full trigger space. Add coresight_cti_reg_index(), coresight_cti_reg_rw_index(), and coresight_cti_reg_wo_index() macros that carry the bank index in the cs_off_attribute.index field, keeping the base offset and index separate rather than encoding them together. Add static sysfs entries for the banked CTI registers and control their visibility based on the underlying hardware configuration. Visibility is determined by comparing the attribute's index against the number of banks implied by nr_trig_max (32 triggers per bank). Registers beyond the hardware capacity are hidden, preserving the existing ABI on standard ARM CTIs while exposing the full register set on Qualcomm CTIs. Link: https://lore.kernel.org/all/20260615-extended_cti-v10-4-1c1694b6d8ed@oss.qualcomm.com/ Reviewed-by: Leo Yan Signed-off-by: Yingchao Deng --- .../hwtracing/coresight/coresight-cti-sysfs.c | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index 51409d4b868cb..f7f6f22e4fb98 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -207,6 +207,15 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, } \ })[0].attr.attr) +#define coresight_cti_reg_index(name, offset, idx) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0444, coresight_cti_reg_show, NULL), \ + offset, \ + idx \ + } \ + })[0].attr.attr) + #define coresight_cti_reg_rw(name, offset) \ (&((struct cs_off_attribute[]) { \ { \ @@ -217,6 +226,16 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, } \ })[0].attr.attr) +#define coresight_cti_reg_rw_index(name, offset, idx) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0644, coresight_cti_reg_show, \ + coresight_cti_reg_store), \ + offset, \ + idx \ + } \ + })[0].attr.attr) + #define coresight_cti_reg_wo(name, offset) \ (&((struct cs_off_attribute[]) { \ { \ @@ -226,6 +245,15 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, } \ })[0].attr.attr) +#define coresight_cti_reg_wo_index(name, offset, idx) \ + (&((struct cs_off_attribute[]) { \ + { \ + __ATTR(name, 0200, NULL, coresight_cti_reg_store), \ + offset, \ + idx \ + } \ + })[0].attr.attr) + /* coresight management registers */ static struct attribute *coresight_cti_mgmt_attrs[] = { coresight_cti_reg(devaff0, CTIDEVAFF0), @@ -515,18 +543,36 @@ static struct attribute *coresight_cti_regs_attrs[] = { &dev_attr_appclear.attr, &dev_attr_apppulse.attr, coresight_cti_reg(triginstatus, CTITRIGINSTATUS), + coresight_cti_reg_index(triginstatus1, CTITRIGINSTATUS, 1), + coresight_cti_reg_index(triginstatus2, CTITRIGINSTATUS, 2), + coresight_cti_reg_index(triginstatus3, CTITRIGINSTATUS, 3), coresight_cti_reg(trigoutstatus, CTITRIGOUTSTATUS), + coresight_cti_reg_index(trigoutstatus1, CTITRIGOUTSTATUS, 1), + coresight_cti_reg_index(trigoutstatus2, CTITRIGOUTSTATUS, 2), + coresight_cti_reg_index(trigoutstatus3, CTITRIGOUTSTATUS, 3), coresight_cti_reg(chinstatus, CTICHINSTATUS), coresight_cti_reg(choutstatus, CTICHOUTSTATUS), #ifdef CONFIG_CORESIGHT_CTI_INTEGRATION_REGS coresight_cti_reg_rw(itctrl, CORESIGHT_ITCTRL), coresight_cti_reg(ittrigin, ITTRIGIN), + coresight_cti_reg_index(ittrigin1, ITTRIGIN, 1), + coresight_cti_reg_index(ittrigin2, ITTRIGIN, 2), + coresight_cti_reg_index(ittrigin3, ITTRIGIN, 3), coresight_cti_reg(itchin, ITCHIN), coresight_cti_reg_rw(ittrigout, ITTRIGOUT), + coresight_cti_reg_rw_index(ittrigout1, ITTRIGOUT, 1), + coresight_cti_reg_rw_index(ittrigout2, ITTRIGOUT, 2), + coresight_cti_reg_rw_index(ittrigout3, ITTRIGOUT, 3), coresight_cti_reg_rw(itchout, ITCHOUT), coresight_cti_reg(itchoutack, ITCHOUTACK), coresight_cti_reg(ittrigoutack, ITTRIGOUTACK), + coresight_cti_reg_index(ittrigoutack1, ITTRIGOUTACK, 1), + coresight_cti_reg_index(ittrigoutack2, ITTRIGOUTACK, 2), + coresight_cti_reg_index(ittrigoutack3, ITTRIGOUTACK, 3), coresight_cti_reg_wo(ittriginack, ITTRIGINACK), + coresight_cti_reg_wo_index(ittriginack1, ITTRIGINACK, 1), + coresight_cti_reg_wo_index(ittriginack2, ITTRIGINACK, 2), + coresight_cti_reg_wo_index(ittriginack3, ITTRIGINACK, 3), coresight_cti_reg_wo(itchinack, ITCHINACK), #endif NULL, @@ -537,10 +583,22 @@ static umode_t coresight_cti_regs_is_visible(struct kobject *kobj, { struct device *dev = kobj_to_dev(kobj); struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct device_attribute *dev_attr; + struct cs_off_attribute *cti_attr; + int max_bank; if (attr == &dev_attr_asicctl.attr && !drvdata->config.asicctl_impl) return 0; + dev_attr = container_of(attr, struct device_attribute, attr); + if (dev_attr->show == coresight_cti_reg_show || + dev_attr->store == coresight_cti_reg_store) { + cti_attr = container_of(dev_attr, struct cs_off_attribute, attr); + max_bank = DIV_ROUND_UP(drvdata->config.nr_trig_max, 32); + if (cti_attr->index >= max_bank) + return 0; + } + return attr->mode; } From 8022a581c4ab077645a97c7d6dda4f8b4996fb6f Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Mon, 15 Jun 2026 20:32:33 +0800 Subject: [PATCH 0133/1133] FROMLIST: coresight: cti: document banked and missing base CTI sysfs registers Document the new sysfs entries triginstatus[1-3], trigoutstatus[1-3], ittrigin[1-3], ittrigout[1-3], ittrigoutack[1-3] and ittriginack[1-3] in the coresight-cti ABI documentation. Also document the previously undocumented base integration test registers itctrl, itchin, itchinack, ittrigin, ittriginack, itchout, itchoutack, ittrigout and ittrigoutack, which were introduced in kernel version 5.7. Link: https://lore.kernel.org/all/20260615-extended_cti-v10-5-1c1694b6d8ed@oss.qualcomm.com/ Signed-off-by: Yingchao Deng --- .../testing/sysfs-bus-coresight-devices-cti | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti index a2aef7f5a6d74..9d7831ac455b8 100644 --- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti @@ -128,12 +128,102 @@ KernelVersion: 5.7 Contact: Mike Leach or Mathieu Poirier Description: (Read) read current status of input trigger signals +What: /sys/bus/coresight/devices//regs/triginstatus[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) read current status of QCOM extended input trigger signals. + What: /sys/bus/coresight/devices//regs/trigoutstatus Date: March 2020 KernelVersion: 5.7 Contact: Mike Leach or Mathieu Poirier Description: (Read) read current status of output trigger signals. +What: /sys/bus/coresight/devices//regs/trigoutstatus[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) read current status of QCOM extended output trigger signals. + +What: /sys/bus/coresight/devices//regs/itctrl +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (RW) Control integration mode. + +What: /sys/bus/coresight/devices//regs/itchin +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the values of the CTCHIN inputs. + +What: /sys/bus/coresight/devices//regs/itchinack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Write) Write the value of the CTCHINACK input. + +What: /sys/bus/coresight/devices//regs/ittrigin +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the values of the CTTRIGIN inputs. + +What: /sys/bus/coresight/devices//regs/ittrigin[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) Read the values of the QCOM extended CTTRIGIN inputs. + +What: /sys/bus/coresight/devices//regs/ittriginack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Write) Write the value of the CTTRIGINACK input. + +What: /sys/bus/coresight/devices//regs/ittriginack[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Write) Write the value of the QCOM extended CTTRIGINACK input. + +What: /sys/bus/coresight/devices//regs/itchout +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (RW) Read or write the value of the CTCHOUT outputs. + +What: /sys/bus/coresight/devices//regs/itchoutack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the value of the CTCHOUTACK input. + +What: /sys/bus/coresight/devices//regs/ittrigout +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (RW) Read or write the value of the CTTRIGOUT outputs. + +What: /sys/bus/coresight/devices//regs/ittrigout[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (RW) Read or write the value of the QCOM extended CTTRIGOUT outputs. + +What: /sys/bus/coresight/devices//regs/ittrigoutack +Date: March 2020 +KernelVersion: 5.7 +Contact: coresight@lists.linaro.org +Description: (Read) Read the value of the CTTRIGOUTACK input. + +What: /sys/bus/coresight/devices//regs/ittrigoutack[1-3] +Date: June 2026 +KernelVersion: 7.3 +Contact: Jinlong Mao +Description: (Read) Read the value of the QCOM extended CTTRIGOUTACK input. + What: /sys/bus/coresight/devices//channels/trigin_attach Date: March 2020 KernelVersion: 5.7 From 5d326152009b98b6d35388558acd597a71cb6aac Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Jul 2026 10:39:00 +0800 Subject: [PATCH 0134/1133] FROMLIST: dt-bindings: arm: coresight-tnoc: Bind on platform bus instead of AMBA The Aggregator TraceNoC hardware exposes CID registers, but the Component ID value returned by the hardware is 0x00000000 instead of a valid AMBA Component ID. As a result, the device cannot be identified on the AMBA bus. Describe the Aggregator TraceNoC with a dedicated single "qcom,coresight-tnoc" compatible instead of the two-string AMBA form "qcom,coresight-tnoc", "arm,primecell". This creates the device on the platform bus so it is bound by the platform driver through its compatible string rather than as an AMBA device. Link: https://lore.kernel.org/all/20260710-fix-tracenoc-probe-issue-v6-1-41eb36fef8d9@oss.qualcomm.com/ Signed-off-by: Jie Gan --- .../bindings/arm/qcom,coresight-tnoc.yaml | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tnoc.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tnoc.yaml index 37147124449e5..625801e3d3bb7 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-tnoc.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tnoc.yaml @@ -22,24 +22,12 @@ description: > Note this binding is specifically intended for Aggregator TNOC instances. -# Need a custom select here or 'arm,primecell' will match on lots of nodes -select: - properties: - compatible: - contains: - enum: - - qcom,coresight-tnoc - required: - - compatible - properties: $nodename: pattern: "^tn(@[0-9a-f]+)$" compatible: - items: - - const: qcom,coresight-tnoc - - const: arm,primecell + const: qcom,coresight-tnoc reg: maxItems: 1 @@ -83,7 +71,7 @@ additionalProperties: false examples: - | tn@109ab000 { - compatible = "qcom,coresight-tnoc", "arm,primecell"; + compatible = "qcom,coresight-tnoc"; reg = <0x109ab000 0x4200>; clocks = <&aoss_qmp>; From 0181c37beefad68f655fe4d0fe11d38eac69b539 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Jul 2026 10:39:01 +0800 Subject: [PATCH 0135/1133] FROMLIST: coresight: tnoc: Bind Aggregator TNOC on the platform bus The Aggregator TNOC is bound as an AMBA device through the "qcom,coresight-tnoc", "arm,primecell" compatible. The AMBA bus reads the peripheral and component ID registers to identify and probe the device. Although the Aggregator TNOC exposes the CID registers, the Component ID value returned by the hardware is 0x00000000 instead of a valid AMBA Component ID, so the AMBA match fails and the device never comes up. Bind the Aggregator TNOC on the platform bus instead, where the device is matched by its compatible string and no component-ID probing is performed. Add "qcom,coresight-tnoc" to the platform driver's match table, and rename the platform driver and its callbacks from the "itnoc"-specific names to generic "tnoc" names, since the driver now serves both the Interconnect and Aggregator TNOC. Update the platform driver name to "coresight-tnoc" accordingly. The ATID-unsupported handling keyed off dev_is_amba(), which disabled ATID allocation for every platform-bus device. With the Aggregator TNOC now on the platform bus, that check would wrongly disable its ATID, even though the Aggregator TNOC owns the ATID that tags the whole aggregation path. The Interconnect TNOC aggregates trace within its subsystem but carries no ATID of its own, because the downstream Aggregator TNOC already owns the ATID for the path. So base the check on the "qcom,coresight-itnoc" compatible and let every other form allocate a trace ID. Link: https://lore.kernel.org/all/20260710-fix-tracenoc-probe-issue-v6-2-41eb36fef8d9@oss.qualcomm.com/ Signed-off-by: Jie Gan --- drivers/hwtracing/coresight/coresight-tnoc.c | 37 +++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c index 929d316b4b363..6f3873cee3239 100644 --- a/drivers/hwtracing/coresight/coresight-tnoc.c +++ b/drivers/hwtracing/coresight/coresight-tnoc.c @@ -130,7 +130,7 @@ static int trace_noc_init_default_data(struct trace_noc_drvdata *drvdata) { int atid; - if (!dev_is_amba(drvdata->dev)) { + if (of_device_is_compatible(drvdata->dev->of_node, "qcom,coresight-itnoc")) { drvdata->atid = -EOPNOTSUPP; return 0; } @@ -278,7 +278,7 @@ static struct amba_driver trace_noc_driver = { .id_table = trace_noc_ids, }; -static int itnoc_probe(struct platform_device *pdev) +static int tnoc_platform_probe(struct platform_device *pdev) { struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); int ret; @@ -295,16 +295,18 @@ static int itnoc_probe(struct platform_device *pdev) return ret; } -static void itnoc_remove(struct platform_device *pdev) +static void tnoc_platform_remove(struct platform_device *pdev) { struct trace_noc_drvdata *drvdata = platform_get_drvdata(pdev); coresight_unregister(drvdata->csdev); pm_runtime_disable(&pdev->dev); + if (drvdata->atid > 0) + coresight_trace_id_put_system_id(drvdata->atid); } #ifdef CONFIG_PM -static int itnoc_runtime_suspend(struct device *dev) +static int tnoc_runtime_suspend(struct device *dev) { struct trace_noc_drvdata *drvdata = dev_get_drvdata(dev); @@ -313,7 +315,7 @@ static int itnoc_runtime_suspend(struct device *dev) return 0; } -static int itnoc_runtime_resume(struct device *dev) +static int tnoc_runtime_resume(struct device *dev) { struct trace_noc_drvdata *drvdata = dev_get_drvdata(dev); @@ -321,35 +323,36 @@ static int itnoc_runtime_resume(struct device *dev) } #endif -static const struct dev_pm_ops itnoc_dev_pm_ops = { - SET_RUNTIME_PM_OPS(itnoc_runtime_suspend, itnoc_runtime_resume, NULL) +static const struct dev_pm_ops tnoc_dev_pm_ops = { + SET_RUNTIME_PM_OPS(tnoc_runtime_suspend, tnoc_runtime_resume, NULL) }; -static const struct of_device_id itnoc_of_match[] = { +static const struct of_device_id tnoc_of_match[] = { { .compatible = "qcom,coresight-itnoc" }, + { .compatible = "qcom,coresight-tnoc" }, {} }; -MODULE_DEVICE_TABLE(of, itnoc_of_match); +MODULE_DEVICE_TABLE(of, tnoc_of_match); -static struct platform_driver itnoc_driver = { - .probe = itnoc_probe, - .remove = itnoc_remove, +static struct platform_driver tnoc_platform_driver = { + .probe = tnoc_platform_probe, + .remove = tnoc_platform_remove, .driver = { - .name = "coresight-itnoc", - .of_match_table = itnoc_of_match, + .name = "coresight-tnoc", + .of_match_table = tnoc_of_match, .suppress_bind_attrs = true, - .pm = &itnoc_dev_pm_ops, + .pm = &tnoc_dev_pm_ops, }, }; static int __init tnoc_init(void) { - return coresight_init_driver("tnoc", &trace_noc_driver, &itnoc_driver); + return coresight_init_driver("tnoc", &trace_noc_driver, &tnoc_platform_driver); } static void __exit tnoc_exit(void) { - coresight_remove_driver(&trace_noc_driver, &itnoc_driver); + coresight_remove_driver(&trace_noc_driver, &tnoc_platform_driver); } module_init(tnoc_init); module_exit(tnoc_exit); From e0f4bba8a7278df67b587f09f14db4f8a4cb8af7 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Sat, 20 Jun 2026 02:09:08 +0530 Subject: [PATCH 0136/1133] FROMLIST: dt-bindings: power: limits: Describe Qualcomm SPEL hardware The Qualcomm SoC Power and Electrical Limits (SPEL) provides hardware based power monitoring and limiting capabilities for various domains. Add a DeviceTree binding to describe the SPEL block on Qualcomm's SoC. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20260620-qcom_spel_driver_upstream-v2-1-a3ee6837c18f@oss.qualcomm.com --- .../bindings/power/limits/qcom,spel.yaml | 47 +++++++++++++++++++ MAINTAINERS | 6 +++ 2 files changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/limits/qcom,spel.yaml diff --git a/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml b/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml new file mode 100644 index 0000000000000..4c6e6cbfbfe40 --- /dev/null +++ b/Documentation/devicetree/bindings/power/limits/qcom,spel.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/limits/qcom,spel.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SoC Power and Electrical Limits (SPEL) + +maintainers: + - Manaf Meethalavalappu Pallikunhi + +description: + The Qualcomm SPEL (SoC Power and Electrical Limits) provides hardware-based + power monitoring and limiting capabilities for various power domains in + Qualcomm SoCs. + +properties: + compatible: + const: qcom,glymur-spel + + reg: + maxItems: 3 + + reg-names: + items: + - const: config + - const: constraints + - const: nodes + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + power-limits@ef3b000 { + compatible = "qcom,glymur-spel"; + reg = <0x0ef3b000 0x1000>, + <0x0ef3d000 0x1000>, + <0x0ef3e000 0x1000>; + reg-names = "config", + "constraints", + "nodes"; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 93abbb315065d..32b9bf521204d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23115,6 +23115,12 @@ S: Maintained F: Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml F: drivers/power/supply/qcom_smbx.c +QUALCOMM SPEL POWERCAP DRIVER +M: Manaf Meethalavalappu Pallikunhi +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/power/limits/qcom,spel.yaml + QUALCOMM PPE DRIVER M: Luo Jie L: netdev@vger.kernel.org From cebc0b637fdda077b160e7a2f2a0639bdaaec91a Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Sat, 20 Jun 2026 02:09:09 +0530 Subject: [PATCH 0137/1133] FROMLIST: powercap: qcom: Add SPEL powercap driver The Qualcomm SoC Power and Electrical Limits (SPEL) provides hardware based power monitoring and limiting capabilities for various power domains including System, SoC, CPU clusters, GPU, and various other subsystems. The driver integrates with the Linux powercap framework, exposing SPEL capabilities through powercap sysfs interfaces. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20260620-qcom_spel_driver_upstream-v2-2-a3ee6837c18f@oss.qualcomm.com --- MAINTAINERS | 1 + drivers/powercap/Kconfig | 13 + drivers/powercap/Makefile | 1 + drivers/powercap/qcom_spel.c | 776 +++++++++++++++++++++++++++++++++++ 4 files changed, 791 insertions(+) create mode 100644 drivers/powercap/qcom_spel.c diff --git a/MAINTAINERS b/MAINTAINERS index 32b9bf521204d..fc651c6eb6ce1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23120,6 +23120,7 @@ M: Manaf Meethalavalappu Pallikunhi L: linux-arm-msm@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/power/limits/qcom,spel.yaml +F: drivers/powercap/qcom_spel.c QUALCOMM PPE DRIVER M: Luo Jie diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig index 03c4c796d9931..e3a47c6534999 100644 --- a/drivers/powercap/Kconfig +++ b/drivers/powercap/Kconfig @@ -93,4 +93,17 @@ config DTPM_DEVFREQ help This enables support for device power limitation based on energy model. + +config QCOM_SPEL + tristate "Qualcomm SPEL Powercap driver" + depends on ARM64 || COMPILE_TEST + help + This enables support for the Qualcomm SoC Power and Electrical + Limits (SPEL) hardware, which allows power limits to be + enforced and monitored on Qualcomm SoCs. + + SPEL provides energy monitoring and power capping for multiple + domains including system, SoC, CPU clusters, GPU, and various + other subsystems. + endif diff --git a/drivers/powercap/Makefile b/drivers/powercap/Makefile index 5ab0dce565b9a..8235fb9d3df60 100644 --- a/drivers/powercap/Makefile +++ b/drivers/powercap/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_INTEL_RAPL) += intel_rapl_msr.o obj-$(CONFIG_INTEL_RAPL_TPMI) += intel_rapl_tpmi.o obj-$(CONFIG_IDLE_INJECT) += idle_inject.o obj-$(CONFIG_ARM_SCMI_POWERCAP) += arm_scmi_powercap.o +obj-$(CONFIG_QCOM_SPEL) += qcom_spel.o diff --git a/drivers/powercap/qcom_spel.c b/drivers/powercap/qcom_spel.c new file mode 100644 index 0000000000000..4dd91cf36ccca --- /dev/null +++ b/drivers/powercap/qcom_spel.c @@ -0,0 +1,776 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Qualcomm SPEL (SoC Power and Electrical Limits) Driver + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SPEL register bitmasks */ +#define ENERGY_STATUS_MASK GENMASK(31, 0) + +#define POWER_LIMIT_MASK GENMASK(14, 0) +#define POWER_LIMIT_ENABLE BIT(31) + +#define TIME_WINDOW_MASK_L GENMASK(14, 0) +#define TIME_WINDOW_MASK_H GENMASK(22, 16) +#define TIME_WINDOW_MAX ((FIELD_MAX(TIME_WINDOW_MASK_H) << 15) | \ + FIELD_MAX(TIME_WINDOW_MASK_L)) + +#define ENERGY_UNIT_MASK GENMASK(19, 16) +#define TIME_UNIT_MASK GENMASK(11, 8) +#define POWER_UNIT_MASK GENMASK(2, 0) + +#define LIMITS_CAPABILITY_OFFSET 0x20 +#define ENERGY_RPT_UNIT_OFFSET 0x04 + +#define ENERGY_UNIT_SCALE 1000 + +#define SPEL_DOMAIN_NAME_LENGTH 16 + +/* Domain types */ +enum spel_domain_type { + SPEL_DOMAIN_SYS, + SPEL_DOMAIN_SOC, + SPEL_DOMAIN_CL0, + SPEL_DOMAIN_CL1, + SPEL_DOMAIN_CL2, + SPEL_DOMAIN_IGPU, + SPEL_DOMAIN_DGPU, + SPEL_DOMAIN_NSP, + SPEL_DOMAIN_MMCX, + SPEL_DOMAIN_INFRA, + SPEL_DOMAIN_DRAM, + SPEL_DOMAIN_MDM, + SPEL_DOMAIN_WLAN, + SPEL_DOMAIN_USB1, + SPEL_DOMAIN_USB2, + SPEL_DOMAIN_USB3, + SPEL_DOMAIN_MAX, +}; + +/* Power limit IDs */ +enum spel_power_limit_id { + POWER_LIMIT1, + POWER_LIMIT2, + POWER_LIMIT3, + POWER_LIMIT4, + POWER_LIMITS_MAX, +}; + +/* Unit types for conversion */ +enum unit_type { + POWER_UNIT, + ENERGY_UNIT, + TIME_UNIT, +}; + +/* Power limit operation types */ +enum pl_ops_type { + PL_LIMIT, + PL_TIME_WINDOW, +}; + +static const char * const pl_names[] = { + [POWER_LIMIT1] = "pl1", + [POWER_LIMIT2] = "pl2", + [POWER_LIMIT3] = "pl3", + [POWER_LIMIT4] = "pl4", +}; + +/** + * struct spel_domain_info - Domain configuration + * @name: Domain name + * @offset: Register offset in node base + */ +struct spel_domain_info { + const char *name; + u32 offset; +}; + +/* Domain configuration */ +static const struct spel_domain_info domain_info[SPEL_DOMAIN_MAX] = { + [SPEL_DOMAIN_SYS] = { "sys", 0x40 }, + [SPEL_DOMAIN_SOC] = { "soc", 0x00 }, + [SPEL_DOMAIN_CL0] = { "cl0", 0x5c }, + [SPEL_DOMAIN_CL1] = { "cl1", 0x60 }, + [SPEL_DOMAIN_CL2] = { "cl2", 0x64 }, + [SPEL_DOMAIN_IGPU] = { "igpu", 0x08 }, + [SPEL_DOMAIN_DGPU] = { "dgpu", 0x44 }, + [SPEL_DOMAIN_NSP] = { "nsp", 0x0c }, + [SPEL_DOMAIN_MMCX] = { "mmcx", 0x10 }, + [SPEL_DOMAIN_INFRA] = { "infra", 0x18 }, + [SPEL_DOMAIN_DRAM] = { "dram", 0x1c }, + [SPEL_DOMAIN_MDM] = { "mdm", 0x48 }, + [SPEL_DOMAIN_WLAN] = { "wlan", 0x4c }, + [SPEL_DOMAIN_USB1] = { "usb1", 0x50 }, + [SPEL_DOMAIN_USB2] = { "usb2", 0x54 }, + [SPEL_DOMAIN_USB3] = { "usb3", 0x58 }, +}; + +/** + * struct spel_constraint_info - Power limit constraint information + * @limit_offset: Register offset for power limit value + * @time_window_offset: Register offset for time window + * @supported_mask: Bit mask in capability register + * @domain_id: Domain this constraint applies to + * @pl_id: Power limit ID (PL1, PL2, etc.) + */ +struct spel_constraint_info { + u32 limit_offset; + u32 time_window_offset; + u32 supported_mask; + enum spel_domain_type domain_id; + int pl_id; +}; + +/* Constraint configuration */ +static const struct spel_constraint_info constraints[] = { + /* SYS domain constraints */ + { 0x10, 0x70, BIT(0), SPEL_DOMAIN_SYS, POWER_LIMIT1 }, + { 0x14, 0x74, BIT(1), SPEL_DOMAIN_SYS, POWER_LIMIT2 }, + { 0x18, 0x78, BIT(2), SPEL_DOMAIN_SYS, POWER_LIMIT3 }, + { 0x1c, 0x7c, BIT(3), SPEL_DOMAIN_SYS, POWER_LIMIT4 }, + /* SoC domain constraints */ + { 0x00, 0x60, BIT(4), SPEL_DOMAIN_SOC, POWER_LIMIT1 }, + { 0x04, 0x64, BIT(5), SPEL_DOMAIN_SOC, POWER_LIMIT2 }, + { 0x08, 0x68, BIT(6), SPEL_DOMAIN_SOC, POWER_LIMIT3 }, + { 0x0c, 0x6c, BIT(7), SPEL_DOMAIN_SOC, POWER_LIMIT4 }, +}; + +/** + * struct spel_domain - SPEL power domain + * @power_zone: Powercap zone + * @lock: Mutex protecting register access + * @sp: Parent sys domain + * @status_reg: Energy counter register + * @name: Domain name + * @id: Domain type ID + */ +struct spel_domain { + struct powercap_zone power_zone; + struct mutex lock; /* Protects register read/write operations */ + void *sp; + void __iomem *status_reg; + char name[SPEL_DOMAIN_NAME_LENGTH]; + enum spel_domain_type id; +}; + +/** + * struct spel_system - SPEL system + * @domains: Array of domains + * @power_zone: Parent powercap zone + * @node_base: Base address for node registers + * @constraint_base: Base address for constraint registers + * @config_base: Base address for config registers + * @control_type: Powercap control type + * @dev: Device pointer for logging + * @limits: Supported power limits per domain + * @power_unit: Power unit in microWatts (common for all domains) + * @energy_unit: Energy unit in nanoJoules (common for all domains) + * @time_unit: Time unit in microseconds (common for all domains) + */ +struct spel_system { + struct spel_domain *domains; + struct powercap_zone *power_zone; + void __iomem *node_base; + void __iomem *constraint_base; + void __iomem *config_base; + struct powercap_control_type *control_type; + struct device *dev; + int limits[SPEL_DOMAIN_MAX]; + unsigned int power_unit; + unsigned int energy_unit; + unsigned int time_unit; +}; + +#define power_zone_to_spel_domain(_zone) \ + container_of(_zone, struct spel_domain, power_zone) + +static bool is_pl_valid(struct spel_domain *sd, int pl) +{ + struct spel_system *sp = sd->sp; + + return !!(sp->limits[sd->id] & BIT(pl)); +} + +static int get_pl_ops_offset(struct spel_domain *sd, int pl, enum pl_ops_type pl_op) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(constraints); i++) { + const struct spel_constraint_info *ci = &constraints[i]; + + if (ci->domain_id == sd->id && ci->pl_id == pl) { + switch (pl_op) { + case PL_LIMIT: + return ci->limit_offset; + case PL_TIME_WINDOW: + return ci->time_window_offset; + default: + return -EOPNOTSUPP; + } + } + } + + return -EOPNOTSUPP; +} + +static u64 spel_unit_xlate(struct spel_domain *sd, enum unit_type type, + u64 value, int to_raw) +{ + struct spel_system *sp = sd->sp; + u64 units, scale; + + switch (type) { + case POWER_UNIT: + units = sp->power_unit; + scale = 1; + break; + case ENERGY_UNIT: + units = sp->energy_unit; + scale = ENERGY_UNIT_SCALE; + break; + case TIME_UNIT: + units = sp->time_unit; + scale = 1; + break; + default: + return value; + } + + if (to_raw) + return DIV_ROUND_CLOSEST_ULL(value * scale, units); + + value *= units; + return div64_u64(value, scale); +} + +static int spel_read_pl_data(struct spel_domain *sd, int pl, + enum pl_ops_type pl_op, bool xlate, u64 *data) +{ + struct spel_system *sp = sd->sp; + void __iomem *reg_addr; + u64 value; + int offset; + + if (!is_pl_valid(sd, pl)) + return -EINVAL; + + offset = get_pl_ops_offset(sd, pl, pl_op); + if (offset < 0) + return offset; + + guard(mutex)(&sd->lock); + + reg_addr = sp->constraint_base + offset; + value = readl(reg_addr); + + switch (pl_op) { + case PL_LIMIT: + value = FIELD_GET(POWER_LIMIT_MASK, value); + if (xlate) + *data = spel_unit_xlate(sd, POWER_UNIT, value, 0); + else + *data = value; + break; + case PL_TIME_WINDOW: + /* Decode time window: bits [22:16] are upper 7 bits, [14:0] are lower 15 bits */ + value = (FIELD_GET(TIME_WINDOW_MASK_H, value) << 15) | + FIELD_GET(TIME_WINDOW_MASK_L, value); + if (xlate) + *data = spel_unit_xlate(sd, TIME_UNIT, value, 0); + else + *data = value; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int spel_write_pl_data(struct spel_domain *sd, int pl, + enum pl_ops_type pl_op, unsigned long long value) +{ + struct spel_system *sp = sd->sp; + void __iomem *reg_addr; + u64 reg_val, new_val; + int offset; + + if (!is_pl_valid(sd, pl)) + return -EINVAL; + + offset = get_pl_ops_offset(sd, pl, pl_op); + if (offset < 0) + return offset; + + guard(mutex)(&sd->lock); + + reg_addr = sp->constraint_base + offset; + reg_val = readl(reg_addr); + + switch (pl_op) { + case PL_LIMIT: + new_val = spel_unit_xlate(sd, POWER_UNIT, value, 1); + if (new_val > FIELD_MAX(POWER_LIMIT_MASK)) + return -EINVAL; + reg_val = (reg_val & ~POWER_LIMIT_MASK) | FIELD_PREP(POWER_LIMIT_MASK, new_val); + + /* + * Enable/Disable PL based on the value: + * - If value is 0, disable the PL (clear enable bit) + * - If value is non-zero, enable the PL (set enable bit) + */ + if (new_val == 0) + reg_val &= ~POWER_LIMIT_ENABLE; + else + reg_val |= POWER_LIMIT_ENABLE; + + writel(reg_val, reg_addr); + return 0; + + case PL_TIME_WINDOW: + /* + * Encode time window: upper 7 bits to [22:16], lower 15 bits to [14:0] + */ + new_val = spel_unit_xlate(sd, TIME_UNIT, value, 1); + if (new_val > TIME_WINDOW_MAX) + return -EINVAL; + /* Read-modify-write to preserve other bits */ + reg_val = (reg_val & ~(TIME_WINDOW_MASK_H | TIME_WINDOW_MASK_L)) | + FIELD_PREP(TIME_WINDOW_MASK_H, new_val >> 15) | + FIELD_PREP(TIME_WINDOW_MASK_L, new_val); + writel(reg_val, reg_addr); + + /* + * Time window register update doesn't trigger firmware interrupt. + * Write to the PL register with current value to trigger the interrupt. + */ + offset = get_pl_ops_offset(sd, pl, PL_LIMIT); + if (offset >= 0) { + reg_addr = sp->constraint_base + offset; + reg_val = readl(reg_addr); + writel(reg_val, reg_addr); + } + return 0; + + default: + return -EINVAL; + } +} + +static int spel_get_energy_counter(struct powercap_zone *power_zone, u64 *energy_raw) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + u64 value; + + value = readl(sd->status_reg); + + *energy_raw = spel_unit_xlate(sd, ENERGY_UNIT, value, 0); + + return 0; +} + +static int spel_get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy) +{ + struct spel_domain *sd = power_zone_to_spel_domain(pcd_dev); + + *energy = spel_unit_xlate(sd, ENERGY_UNIT, ENERGY_STATUS_MASK, 0); + + return 0; +} + +static int spel_release_zone(struct powercap_zone *power_zone) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + struct spel_system *sp = sd->sp; + + /* Free the domains array when the last zone (SYS domain) is released */ + if (sd->id == SPEL_DOMAIN_SYS) + kfree(sp->domains); + + return 0; +} + +static int spel_find_nr_power_limit(struct spel_domain *sd) +{ + int i, nr_pl = 0; + + for (i = 0; i < ARRAY_SIZE(pl_names); i++) { + if (is_pl_valid(sd, i)) + nr_pl++; + } + + return nr_pl; +} + +static const struct powercap_zone_ops zone_ops = { + .get_energy_uj = spel_get_energy_counter, + .get_max_energy_range_uj = spel_get_max_energy_counter, + .release = spel_release_zone, +}; + +static int spel_constraint_to_pl(struct spel_domain *sd, int cid) +{ + int i, id; + + for (i = 0, id = 0; i < ARRAY_SIZE(pl_names); i++) { + if (is_pl_valid(sd, i) && id++ == cid) + return i; + } + + return -EINVAL; +} + +static int spel_set_power_limit(struct powercap_zone *power_zone, int cid, + u64 power_limit) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + int id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + return spel_write_pl_data(sd, id, PL_LIMIT, power_limit); +} + +static int spel_get_power_limit(struct powercap_zone *power_zone, int cid, + u64 *data) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + u64 val; + int ret, id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + ret = spel_read_pl_data(sd, id, PL_LIMIT, true, &val); + if (!ret) + *data = val; + + return ret; +} + +static int spel_set_time_window(struct powercap_zone *power_zone, int cid, + u64 window) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + int id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + return spel_write_pl_data(sd, id, PL_TIME_WINDOW, window); +} + +static int spel_get_time_window(struct powercap_zone *power_zone, int cid, + u64 *data) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + u64 val; + int ret, id; + + id = spel_constraint_to_pl(sd, cid); + if (id < 0) + return id; + + ret = spel_read_pl_data(sd, id, PL_TIME_WINDOW, true, &val); + if (!ret) + *data = val; + + return ret; +} + +static const char *spel_get_constraint_name(struct powercap_zone *power_zone, + int cid) +{ + struct spel_domain *sd = power_zone_to_spel_domain(power_zone); + int id; + + id = spel_constraint_to_pl(sd, cid); + if (id >= 0 && id < ARRAY_SIZE(pl_names)) + return pl_names[id]; + + return NULL; +} + +static const struct powercap_zone_constraint_ops constraint_ops = { + .set_power_limit_uw = spel_set_power_limit, + .get_power_limit_uw = spel_get_power_limit, + .set_time_window_us = spel_set_time_window, + .get_time_window_us = spel_get_time_window, + .get_name = spel_get_constraint_name, +}; + +static void spel_init_domains(struct spel_system *sp) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(domain_info); i++) { + struct spel_domain *sd = &sp->domains[i]; + + sd->sp = sp; + snprintf(sd->name, SPEL_DOMAIN_NAME_LENGTH, "%s", + domain_info[i].name); + sd->id = i; + sd->status_reg = sp->node_base + domain_info[i].offset; + + /* PL1 is always supported (required for powercap registration) */ + sp->limits[i] = BIT(POWER_LIMIT1); + } +} + +static void spel_update_unit(struct spel_system *sp) +{ + u32 value, shift; + + /* Read power_unit and time_unit from offset 0x0 */ + value = readl(sp->config_base); + + /* + * Unit calculation: 1 / (2^shift) + * Masks limit: TIME_UNIT (4 bits, max 15), POWER_UNIT (3 bits, max 7). + */ + shift = FIELD_GET(POWER_UNIT_MASK, value); + sp->power_unit = 1000000 / (1 << shift); + + shift = FIELD_GET(TIME_UNIT_MASK, value); + /* + * Time window in register is in milliseconds. + */ + sp->time_unit = 1000 * (1 << shift); + + /* Read energy_unit from ENERGY_RPT_UNIT_OFFSET */ + value = readl(sp->config_base + ENERGY_RPT_UNIT_OFFSET); + + /* + * Unit calculation: 1 / (2^shift) + * Masks limit: ENERGY_UNIT (4 bits, max 15). + */ + shift = FIELD_GET(ENERGY_UNIT_MASK, value); + sp->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << shift); + + dev_dbg(sp->dev, "Units: energy=%dnJ, time=%dus, power=%duW\n", + sp->energy_unit, sp->time_unit, sp->power_unit); +} + +static void spel_detect_powerlimit(struct spel_domain *sd) +{ + struct spel_system *sp = sd->sp; + u32 capabilities; + int i, j; + + capabilities = readl(sp->config_base + LIMITS_CAPABILITY_OFFSET); + + /* + * Detect power limits from hardware capabilities. + * Start from index 1 (POWER_LIMIT2) since PL1 is always enabled in spel_init_domains(). + */ + for (i = 1; i < ARRAY_SIZE(pl_names); i++) { + for (j = 0; j < ARRAY_SIZE(constraints); j++) { + const struct spel_constraint_info *ci = &constraints[j]; + + if (ci->domain_id == sd->id && ci->pl_id == i) { + if (capabilities & ci->supported_mask) + sp->limits[sd->id] |= BIT(i); + break; + } + } + } +} + +static int spel_init_system(struct spel_system *sp, struct device *dev) +{ + int i, ret; + + /* Read unit configuration (common for all domains) */ + spel_update_unit(sp); + + sp->domains = kcalloc(ARRAY_SIZE(domain_info), + sizeof(struct spel_domain), GFP_KERNEL); + if (!sp->domains) + return -ENOMEM; + + spel_init_domains(sp); + + for (i = 0; i < ARRAY_SIZE(domain_info); i++) { + struct spel_domain *sd = &sp->domains[i]; + + ret = devm_mutex_init(dev, &sd->lock); + if (ret) { + dev_err(dev, "Failed to initialize mutex for domain %s\n", sd->name); + kfree(sp->domains); + return ret; + } + + spel_detect_powerlimit(sd); + } + + return 0; +} + +static int spel_register_powercap(struct spel_system *sp) +{ + struct spel_domain *sd; + struct powercap_zone *power_zone; + int nr_pl, ret, i; + + /* Register SYS domain as parent zone */ + sd = &sp->domains[SPEL_DOMAIN_SYS]; + nr_pl = spel_find_nr_power_limit(sd); + + power_zone = powercap_register_zone(&sd->power_zone, + sp->control_type, sd->name, + NULL, &zone_ops, nr_pl, + &constraint_ops); + if (IS_ERR(power_zone)) { + dev_err(sp->dev, "Failed to register power zone %s\n", + sd->name); + return PTR_ERR(power_zone); + } + sp->power_zone = power_zone; + + /* Register other domains as children */ + for (i = 0; i < ARRAY_SIZE(domain_info); i++) { + struct powercap_zone *parent; + + if (i == SPEL_DOMAIN_SYS) + continue; + + sd = &sp->domains[i]; + + /* SOC is child of SYS, others are children of SOC */ + if (i == SPEL_DOMAIN_SOC) + parent = sp->power_zone; + else + parent = &sp->domains[SPEL_DOMAIN_SOC].power_zone; + + nr_pl = spel_find_nr_power_limit(sd); + power_zone = powercap_register_zone(&sd->power_zone, + sp->control_type, + sd->name, parent, + &zone_ops, nr_pl, + &constraint_ops); + + if (IS_ERR(power_zone)) { + dev_err(sp->dev, "Failed to register power_zone %s\n", + sd->name); + ret = PTR_ERR(power_zone); + goto err_cleanup; + } + } + + return 0; + +err_cleanup: + /* Unregister in reverse order: children first, then SOC, then SYS */ + for (i = i - 1; i >= 0; i--) + powercap_unregister_zone(sp->control_type, &sp->domains[i].power_zone); + + return ret; +} + +static int spel_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct spel_system *sp; + int ret; + + sp = devm_kzalloc(dev, sizeof(*sp), GFP_KERNEL); + if (!sp) + return -ENOMEM; + + sp->dev = dev; + + /* Map config registers (units, capabilities) */ + sp->config_base = devm_platform_ioremap_resource_byname(pdev, "config"); + if (IS_ERR(sp->config_base)) + return PTR_ERR(sp->config_base); + + /* Map constraint registers (power limits) */ + sp->constraint_base = devm_platform_ioremap_resource_byname(pdev, "constraints"); + if (IS_ERR(sp->constraint_base)) + return PTR_ERR(sp->constraint_base); + + /* Map spel domain registers (energy counters) */ + sp->node_base = devm_platform_ioremap_resource_byname(pdev, "nodes"); + if (IS_ERR(sp->node_base)) + return PTR_ERR(sp->node_base); + + sp->control_type = powercap_register_control_type(NULL, "qcom-spel", + NULL); + if (IS_ERR(sp->control_type)) { + dev_err(dev, "Failed to register control type\n"); + return PTR_ERR(sp->control_type); + } + + /* Initialize system and domains */ + ret = spel_init_system(sp, dev); + if (ret) { + dev_err(dev, "Failed to initialize system\n"); + goto err_unregister_control; + } + + ret = spel_register_powercap(sp); + if (ret) { + dev_err(dev, "Failed to register powercap zones\n"); + if (!sp->power_zone) + kfree(sp->domains); + goto err_unregister_control; + } + + platform_set_drvdata(pdev, sp); + + return 0; + +err_unregister_control: + powercap_unregister_control_type(sp->control_type); + return ret; +} + +static void spel_remove(struct platform_device *pdev) +{ + struct spel_system *sp = platform_get_drvdata(pdev); + int i; + + /* Unregister in reverse order: children first, then SOC, then SYS */ + for (i = ARRAY_SIZE(domain_info) - 1; i >= 0; i--) + powercap_unregister_zone(sp->control_type, &sp->domains[i].power_zone); + + powercap_unregister_control_type(sp->control_type); +} + +static const struct of_device_id spel_of_match[] = { + { .compatible = "qcom,glymur-spel" }, + { } +}; +MODULE_DEVICE_TABLE(of, spel_of_match); + +static struct platform_driver spel_driver = { + .probe = spel_probe, + .remove = spel_remove, + .driver = { + .name = "qcom_spel", + .of_match_table = spel_of_match, + }, +}; + +module_platform_driver(spel_driver); + +MODULE_DESCRIPTION("Qualcomm SPEL Powercap Driver"); +MODULE_LICENSE("GPL"); From 3cc172621d514f14e3b02a1762ae099a0ff9dd51 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 17 Aug 2026 16:50:15 +0800 Subject: [PATCH 0138/1133] FROMLIST: coresight: fix trace ID search skipping pass-through NoC devices coresight_path_assign_trace_id() only treats a trace_id of 0 as "this device has no ID assignment, keep searching downstream". Pass-through NoC links such as itnoc (qcom,coresight-itnoc) intentionally return -EOPNOTSUPP from their .trace_id callback since they have no ATID register to program, but that negative value falls through to the IS_VALID_CS_TRACE_ID() check and is rejected, aborting the whole path with -EINVAL before the real trace ID owner further downstream is ever reached. This breaks enabling any source whose path traverses an itnoc, e.g. writing 1 to tpdm/enable_source for a TPDM fails with: sh: write error: Invalid argument Skip devices that return -EOPNOTSUPP the same way as devices that return 0, so the search continues to the next device on the path. Link: https://lore.kernel.org/all/20260817-fix-trace-id-assign-issue-v1-1-b2164e33f9fa@oss.qualcomm.com/ Fixes: f4526ffee6ff ("coresight: fix missing error code when trace ID is invalid") Signed-off-by: Jie Gan --- drivers/hwtracing/coresight/coresight-core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index d2f9c1fb77d98..d930232e893de 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -953,8 +953,12 @@ int coresight_path_assign_trace_id(struct coresight_path *path, /* Assign a trace ID to the path for the first device that wants to do it */ trace_id = coresight_get_trace_id(nd->csdev, mode, sink); - /* 0 means the device has no ID assignment, so keep searching */ - if (trace_id == 0) + /* + * 0 means the device has no ID assignment, and -EOPNOTSUPP + * means the device explicitly declines to assign one (e.g. a + * pass-through NoC) - in both cases keep searching downstream. + */ + if (trace_id == 0 || trace_id == -EOPNOTSUPP) continue; if (!IS_VALID_CS_TRACE_ID(trace_id)) From c7392eaac50685456c1fb42feb814444e7edd241 Mon Sep 17 00:00:00 2001 From: Yingchao Deng Date: Thu, 21 May 2026 21:14:24 +0800 Subject: [PATCH 0139/1133] FROMLIST: stm: class: Add MIPI OST protocol support Add MIPI OST (Open System Trace) protocol support for stm to format the traces. The OST Protocol abstracts the underlying layers from the sending and receiving applications, thus removing dependencies on the connection media and platform implementation. OST over STP packet consists of Header/Payload/End. Header is designed to include the information required by all OST packets. Information that is not shared by all packets is left to the higher layer protocols. Thus, the OST Protocol Header can be regarded as the first part of a complete OST Packet Header, while a higher layer header can be regarded as an extension designed for a specific purpose. +--------+--------+--------+--------+ | start |version |entity |protocol| +--------+--------+--------+--------+ | stm version | magic | +-----------------------------------+ | cpu | +-----------------------------------+ | timestamp | | | +-----------------------------------+ | tgid | | | +-----------------------------------+ | payload | +-----------------------------------+ | ... | end | +-----------------------------------+ In header, there will be STARTSIMPLE/VERSION/ENTITY/PROTOCOL. STARTSIMPLE is used to signal the beginning of a simplified OST protocol. The Version field is a one byte, unsigned number identifying the version of the OST Protocol. The Entity ID field is a one byte unsigned number that identifies the source. Entity ID values (0~239) are defined and controlled by the TS owner, and shall be unique for the whole TS. The configfs entity attribute allows the user to configure which Entity ID is associated with each policy node. The Protocol ID field is a one byte unsigned number identifying the higher layer protocol of the OST Packet, i.e. identifying the format of the data after the OST Protocol Header. OST Control Protocol ID value represents the common control protocol, the remaining Protocol ID values may be used by any higher layer protocols capable of being transported by the OST Protocol. Link: https://lore.kernel.org/all/20260521-stm_p_ost-v6-1-e557900b686b@oss.qualcomm.com/ Co-developed-by: Tingwei Zhang Signed-off-by: Tingwei Zhang Co-developed-by: Yuanfang Zhang Signed-off-by: Yuanfang Zhang Co-developed-by: Jinlong Mao Signed-off-by: Jinlong Mao Signed-off-by: Yingchao Deng --- .../ABI/testing/configfs-stp-policy-p_ost | 9 + Documentation/trace/index.rst | 1 + Documentation/trace/p_ost.rst | 39 +++ drivers/hwtracing/stm/Kconfig | 14 + drivers/hwtracing/stm/Makefile | 2 + drivers/hwtracing/stm/p_ost.c | 241 ++++++++++++++++++ 6 files changed, 306 insertions(+) create mode 100644 Documentation/ABI/testing/configfs-stp-policy-p_ost create mode 100644 Documentation/trace/p_ost.rst create mode 100644 drivers/hwtracing/stm/p_ost.c diff --git a/Documentation/ABI/testing/configfs-stp-policy-p_ost b/Documentation/ABI/testing/configfs-stp-policy-p_ost new file mode 100644 index 0000000000000..8fb160b50c40b --- /dev/null +++ b/Documentation/ABI/testing/configfs-stp-policy-p_ost @@ -0,0 +1,9 @@ +What: /config/stp-policy/:p_ost.//entity +Date: May 2026 +KernelVersion: 7.1 +Description: + Set the entity ID which identifies the trace source in the + OST packet header. Entity ID values (0~239) are defined by + the TS owner. Currently supported values are ftrace, console + and diag. RW. + diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst index f4058e8e92e3d..b4f5ecbda46a7 100644 --- a/Documentation/trace/index.rst +++ b/Documentation/trace/index.rst @@ -73,6 +73,7 @@ interactions and system performance. intel_th stm sys-t + p_ost coresight/index rv/index hisi-ptt diff --git a/Documentation/trace/p_ost.rst b/Documentation/trace/p_ost.rst new file mode 100644 index 0000000000000..2b92e22296539 --- /dev/null +++ b/Documentation/trace/p_ost.rst @@ -0,0 +1,39 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================== +MIPI OST over STP +=================== + +The OST (Open System Trace) driver is used with STM class devices to +generate standardized trace stream. Trace sources can be identified +by different entity IDs. + +CONFIG_STM_PROTO_OST is for p_ost driver enablement. Once this config +is enabled, you can select the p_ost protocol by command below: + +# mkdir /sys/kernel/config/stp-policy/stm0:p_ost.policy + +The policy name format is extended like this: + + :. + +With a coresight-stm device, it will look like "stm0:p_ost.policy". + +With the MIPI OST protocol driver, the attributes for each protocol node are: + +# mkdir /sys/kernel/config/stp-policy/stm0:p_ost.policy/default +# ls /sys/kernel/config/stp-policy/stm0:p_ost.policy/default +channels entity masters + +The entity here is the set of entities that p_ost supports. Currently +p_ost supports ftrace, console and diag entities. + +Set entity: +# echo 'ftrace' > /sys/kernel/config/stp-policy/stm0:p_ost.policy/default/entity + +Get available and currently selected (shown in square brackets) entity: +# cat /sys/kernel/config/stp-policy/stm0:p_ost.policy/default/entity +[ftrace] console diag + +See Documentation/ABI/testing/configfs-stp-policy-p_ost for more details. + diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig index cd7f0b0f3fbeb..4c83da5d95a05 100644 --- a/drivers/hwtracing/stm/Kconfig +++ b/drivers/hwtracing/stm/Kconfig @@ -40,6 +40,20 @@ config STM_PROTO_SYS_T If you don't know what this is, say N. +config STM_PROTO_OST + tristate "MIPI OST STM framing protocol driver" + default 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_DUMMY tristate "Dummy STM driver" help diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile index 1692fcd292779..d9c8615849b95 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..d2174872b7615 --- /dev/null +++ b/drivers/hwtracing/stm/p_ost.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * MIPI OST framing protocol for STM devices. + */ + +#include +#include +#include +#include +#include "stm.h" + +/* + * OST Base Protocol Header + * + * Position Bits Field Name + * 0 8 STARTSIMPLE + * 1 8 Version + * 2 8 Entity ID + * 3 8 Protocol ID + */ +#define OST_FIELD_STARTSIMPLE 0 +#define OST_FIELD_VERSION 8 +#define OST_FIELD_ENTITY 16 +#define OST_FIELD_PROTOCOL 24 + +#define OST_TOKEN_STARTSIMPLE 0x10 +#define OST_VERSION_MIPI1 0x10 + +/* entity id to identify the source */ +#define OST_ENTITY_FTRACE 0x01 +#define OST_ENTITY_CONSOLE 0x02 +#define OST_ENTITY_DIAG 0xEE + +#define OST_CONTROL_PROTOCOL 0x0 + +#define DATA_HEADER ((OST_TOKEN_STARTSIMPLE << OST_FIELD_STARTSIMPLE) | \ + (OST_VERSION_MIPI1 << OST_FIELD_VERSION) | \ + (OST_CONTROL_PROTOCOL << OST_FIELD_PROTOCOL)) + +#define STM_MAKE_VERSION(ma, mi) (((ma) << 8) | (mi)) +#define STM_HEADER_MAGIC (0x5953) + +enum ost_entity_type { + OST_ENTITY_TYPE_NONE, + OST_ENTITY_TYPE_FTRACE, + OST_ENTITY_TYPE_CONSOLE, + OST_ENTITY_TYPE_DIAG, +}; + +static const char * const str_ost_entity_type[] = { + [OST_ENTITY_TYPE_NONE] = "none", + [OST_ENTITY_TYPE_FTRACE] = "ftrace", + [OST_ENTITY_TYPE_CONSOLE] = "console", + [OST_ENTITY_TYPE_DIAG] = "diag", +}; + +static const u32 ost_entity_value[] = { + [OST_ENTITY_TYPE_NONE] = 0, + [OST_ENTITY_TYPE_FTRACE] = OST_ENTITY_FTRACE, + [OST_ENTITY_TYPE_CONSOLE] = OST_ENTITY_CONSOLE, + [OST_ENTITY_TYPE_DIAG] = OST_ENTITY_DIAG, +}; + +struct ost_policy_node { + enum ost_entity_type entity_type; +}; + +struct ost_output { + struct ost_policy_node node; +}; + +/* Set default entity type as none */ +static void ost_policy_node_init(void *priv) +{ + struct ost_policy_node *pn = priv; + + pn->entity_type = OST_ENTITY_TYPE_NONE; +} + +static int ost_output_open(void *priv, struct stm_output *output) +{ + struct ost_policy_node *pn = priv; + struct ost_output *opriv; + + opriv = kzalloc_obj(*opriv, GFP_ATOMIC); + if (!opriv) + return -ENOMEM; + + memcpy(&opriv->node, pn, sizeof(opriv->node)); + output->pdrv_private = opriv; + return 0; +} + +static void ost_output_close(struct stm_output *output) +{ + kfree(output->pdrv_private); +} + +static ssize_t ost_t_policy_entity_show(struct config_item *item, + char *page) +{ + struct ost_policy_node *pn = to_pdrv_policy_node(item); + ssize_t sz = 0; + int i; + + for (i = 1; i < ARRAY_SIZE(str_ost_entity_type); i++) { + if (i == pn->entity_type) + sz += sysfs_emit_at(page, sz, "[%s] ", str_ost_entity_type[i]); + else + sz += sysfs_emit_at(page, sz, "%s ", str_ost_entity_type[i]); + } + + sz += sysfs_emit_at(page, sz, "\n"); + return sz; +} + +static int entity_index(const char *str) +{ + int i; + + for (i = 1; i < ARRAY_SIZE(str_ost_entity_type); i++) { + if (sysfs_streq(str, str_ost_entity_type[i])) + return i; + } + + return 0; +} + +static ssize_t +ost_t_policy_entity_store(struct config_item *item, const char *page, + size_t count) +{ + struct mutex *mutexp = &item->ci_group->cg_subsys->su_mutex; + struct ost_policy_node *pn = to_pdrv_policy_node(item); + int i; + + i = entity_index(page); + if (i) { + mutex_lock(mutexp); + pn->entity_type = i; + mutex_unlock(mutexp); + } else { + return -EINVAL; + } + + return count; +} +CONFIGFS_ATTR(ost_t_policy_, entity); + +static struct configfs_attribute *ost_t_policy_attrs[] = { + &ost_t_policy_attr_entity, + NULL, +}; + +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) +{ + struct ost_output *op = output->pdrv_private; + unsigned int c = output->channel + chan; + unsigned int m = output->master; + const unsigned char nil = 0; + u32 header = DATA_HEADER; + struct trc_hdr { + u16 version; + u16 magic; + u32 cpu; + u64 timestamp; + u64 tgid; + } hdr; + ssize_t sz; + + /* + * Identify the source by entity type. + * If entity type is not set, return error value. + */ + if (op->node.entity_type) + header |= (ost_entity_value[op->node.entity_type] << OST_FIELD_ENTITY); + else + return -EINVAL; + + /* + * STP framing rules for OST frames: + * * the first packet of the OST frame is marked; + * * the last packet is a FLAG with timestamped tag. + */ + /* 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; + + /* DATA */ + hdr.version = STM_MAKE_VERSION(0, 3); + hdr.magic = STM_HEADER_MAGIC; + hdr.cpu = raw_smp_processor_id(); + hdr.timestamp = sched_clock(); + hdr.tgid = task_tgid_nr(current); + sz = stm_data_write(data, m, c, false, &hdr, sizeof(hdr)); + if (sz <= 0) + return sz; + + 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", + .priv_sz = sizeof(struct ost_policy_node), + .write = ost_write, + .policy_attr = ost_t_policy_attrs, + .output_open = ost_output_open, + .output_close = ost_output_close, + .policy_node_init = ost_policy_node_init, +}; + +static int ost_stm_init(void) +{ + return stm_register_protocol(&ost_pdrv); +} +module_init(ost_stm_init); + +static void ost_stm_exit(void) +{ + stm_unregister_protocol(&ost_pdrv); +} +module_exit(ost_stm_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MIPI Open System Trace STM framing protocol driver"); From 5a6e43760a6732a3f64ba64fbcf59cbc39155d65 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 7 Sep 2026 13:09:57 +0800 Subject: [PATCH 0140/1133] FROMLIST: coresight: Fix clock refcount imbalance on platform probe failure Each CoreSight platform_driver's probe() enables its clocks via coresight_get_enable_clocks() -> devm_clk_get_optional_enabled(), which registers a devm cleanup to run clk_disable_unprepare() on driver detach. The probe wrapper then unconditionally calls pm_runtime_put() regardless of whether the inner probe succeeded, so on failure this also fires runtime_suspend() and disables the same clocks a first time. The driver core then unwinds the failed probe and runs the devm cleanup, disabling them a second time and underflowing the refcount: coresight-etm4x etm0: probe with driver coresight-etm4x failed with error -22 ------------[ cut here ]------------ qdss_clk already disabled WARNING: CPU: 1 PID: 432 at drivers/clk/clk.c:1188 clk_core_disable+0x1d0/0x218 ... ------------[ cut here ]------------ Unpreparing enabled qdss_clk WARNING: CPU: 0 PID: 432 at drivers/clk/clk.c:1061 clk_core_unprepare+0x248/0x268 ... qdss_clk is shared by every CoreSight node, so the extra disable drives its refcount to 0 while sibling devices still expect it enabled. The next funnel to probe then touches unclocked hardware and panics: SError Interrupt on CPU1, code 0x00000000be000000 -- SError Kernel panic - not syncing: Asynchronous SError Interrupt ... coresight_clear_self_claim_tag+0x7c/0x1e0 [coresight] (P) funnel_probe+0x114/0x2e0 [coresight_funnel] dynamic_funnel_probe+0x24/0x70 [coresight_funnel] Use pm_runtime_put_noidle() instead of pm_runtime_put() on the failure path so it drops the usage count without invoking runtime_suspend(), leaving the devm cleanup as the sole disabler. Affects catu, ctcu, etm4x, funnel, replicator, stm, tmc, tpiu and tnoc, all of which share this probe skeleton. Link: https://lore.kernel.org/all/20260907-fix-clk-issue-v1-1-efe81fa2b697@oss.qualcomm.com/ Fixes: 1abc1b212eff ("coresight: Appropriately disable programming clocks") Signed-off-by: Jie Gan --- drivers/hwtracing/coresight/coresight-catu.c | 9 ++++++--- drivers/hwtracing/coresight/coresight-ctcu-core.c | 9 ++++++--- drivers/hwtracing/coresight/coresight-etm4x-core.c | 10 ++++++---- drivers/hwtracing/coresight/coresight-funnel.c | 9 ++++++--- drivers/hwtracing/coresight/coresight-replicator.c | 9 ++++++--- drivers/hwtracing/coresight/coresight-stm.c | 9 ++++++--- drivers/hwtracing/coresight/coresight-tmc-core.c | 9 ++++++--- drivers/hwtracing/coresight/coresight-tnoc.c | 9 ++++++--- drivers/hwtracing/coresight/coresight-tpiu.c | 9 ++++++--- 9 files changed, 54 insertions(+), 28 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index ad8dafea7d2fd..9a59a1f9e7fd8 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -632,11 +632,14 @@ static int catu_platform_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = __catu_probe(&pdev->dev, res); - pm_runtime_put(&pdev->dev); - if (ret) + if (ret) { + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + return ret; + } - return ret; + pm_runtime_put(&pdev->dev); + return 0; } static void catu_platform_remove(struct platform_device *pdev) diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c index 9043cad42f01e..ab02325375237 100644 --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c @@ -251,11 +251,14 @@ static int ctcu_platform_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = ctcu_probe(pdev); - pm_runtime_put(&pdev->dev); - if (ret) + if (ret) { + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + return ret; + } - return ret; + pm_runtime_put(&pdev->dev); + return 0; } static void ctcu_platform_remove(struct platform_device *pdev) diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index e21be6468e954..4e66510404a17 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -2373,12 +2373,14 @@ static int etm4_probe_platform_dev(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = etm4_probe(&pdev->dev); - - pm_runtime_put(&pdev->dev); - if (ret) + if (ret) { + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + return ret; + } - return ret; + pm_runtime_put(&pdev->dev); + return 0; } static int etm4_probe_cpu(unsigned int cpu) diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 0abc11f0690c5..d75f11fda72f4 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -319,11 +319,14 @@ static int funnel_platform_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = funnel_probe(&pdev->dev, res); - pm_runtime_put(&pdev->dev); - if (ret) + if (ret) { + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + return ret; + } - return ret; + pm_runtime_put(&pdev->dev); + return 0; } static void funnel_platform_remove(struct platform_device *pdev) diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 2f382de357ee4..3fe5eb5a7a0c4 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -298,11 +298,14 @@ static int replicator_platform_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = replicator_probe(&pdev->dev, res); - pm_runtime_put(&pdev->dev); - if (ret) + if (ret) { + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + return ret; + } - return ret; + pm_runtime_put(&pdev->dev); + return 0; } static void replicator_platform_remove(struct platform_device *pdev) diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 4e860519a73f6..5de0adf1d33a2 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -1011,11 +1011,14 @@ static int stm_platform_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = __stm_probe(&pdev->dev, res); - pm_runtime_put(&pdev->dev); - if (ret) + if (ret) { + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + return ret; + } - return ret; + pm_runtime_put(&pdev->dev); + return 0; } static void stm_platform_remove(struct platform_device *pdev) diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index bc5a133ada3e3..2481bae5c9f32 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -974,11 +974,14 @@ static int tmc_platform_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = __tmc_probe(&pdev->dev, res); - pm_runtime_put(&pdev->dev); - if (ret) + if (ret) { + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + return ret; + } - return ret; + pm_runtime_put(&pdev->dev); + return 0; } static void tmc_platform_remove(struct platform_device *pdev) diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c index 6f3873cee3239..3934cf507bdf9 100644 --- a/drivers/hwtracing/coresight/coresight-tnoc.c +++ b/drivers/hwtracing/coresight/coresight-tnoc.c @@ -288,11 +288,14 @@ static int tnoc_platform_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = _tnoc_probe(&pdev->dev, res); - pm_runtime_put(&pdev->dev); - if (ret) + if (ret) { + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + return ret; + } - return ret; + pm_runtime_put(&pdev->dev); + return 0; } static void tnoc_platform_remove(struct platform_device *pdev) diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 7b029d2eb3891..9ae94dc553d73 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -271,11 +271,14 @@ static int tpiu_platform_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = __tpiu_probe(&pdev->dev, res); - pm_runtime_put(&pdev->dev); - if (ret) + if (ret) { + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + return ret; + } - return ret; + pm_runtime_put(&pdev->dev); + return 0; } static void tpiu_platform_remove(struct platform_device *pdev) From 825e0769d6184876088c82e628b50c56f0fa8ca0 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Jul 2026 09:14:47 +0800 Subject: [PATCH 0141/1133] FROMLIST: coresight: Fix clock refcount imbalance on platform remove coresight_get_enable_clocks() enables the programming clock and the optional AT clock through devm_clk_get_optional_enabled(), which also registers a devm action to call clk_disable_unprepare() when the driver detaches. After probe, pm_runtime_put() allows the device to suspend and the runtime suspend callback disables the same clocks. During remove the device is left runtime suspended, so pm_runtime_disable() freezes it with the clocks already disabled. The devm cleanup that runs afterwards calls clk_disable_unprepare() a second time, underflowing the clock enable refcount. Resume the device with pm_runtime_get_sync() before tearing it down so the clocks are enabled again and balance the devm-managed disable. Then pm_runtime_set_suspended() and pm_runtime_put_noidle() leave the device in a coherent runtime PM state (suspended, usage count balanced) once the devm action has disabled the clocks. This affects all CoreSight platform drivers that obtain their clocks through coresight_get_enable_clocks(): catu, cpu-debug, ctcu, etm4x, funnel, replicator, stm, tmc and tpiu. Link: https://lore.kernel.org/all/20260710-fix-clock-refcount-unbalance-v3-1-a37a1fb17981@oss.qualcomm.com/ Fixes: 1abc1b212eff ("coresight: Appropriately disable programming clocks") Reviewed-by: Yeoreum Yun Reviewed-by: Leo Yan Signed-off-by: Jie Gan --- drivers/hwtracing/coresight/coresight-catu.c | 8 ++++++++ drivers/hwtracing/coresight/coresight-cpu-debug.c | 8 ++++++++ drivers/hwtracing/coresight/coresight-ctcu-core.c | 9 +++++++++ drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 +++++++++++-- drivers/hwtracing/coresight/coresight-funnel.c | 8 ++++++++ drivers/hwtracing/coresight/coresight-replicator.c | 8 ++++++++ drivers/hwtracing/coresight/coresight-stm.c | 8 ++++++++ drivers/hwtracing/coresight/coresight-tmc-core.c | 8 ++++++++ drivers/hwtracing/coresight/coresight-tpiu.c | 8 ++++++++ 9 files changed, 76 insertions(+), 2 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index 9a59a1f9e7fd8..e89f4929a9f9f 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -649,8 +649,16 @@ static void catu_platform_remove(struct platform_device *pdev) if (WARN_ON(!drvdata)) return; + /* + * Resume the device so its clocks are enabled again, balancing the + * clk_disable_unprepare() that devm runs when the driver detaches. + * Then mark it suspended and drop the usage count taken here. + */ + pm_runtime_get_sync(&pdev->dev); __catu_remove(&pdev->dev); pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); } #ifdef CONFIG_PM diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c index 3a806c1d50eaf..87b39874461e2 100644 --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c @@ -710,8 +710,16 @@ static void debug_platform_remove(struct platform_device *pdev) if (WARN_ON(!drvdata)) return; + /* + * Resume the device so its clocks are enabled again, balancing the + * clk_disable_unprepare() that devm runs when the driver detaches. + * Then mark it suspended and drop the usage count taken here. + */ + pm_runtime_get_sync(&pdev->dev); __debug_remove(&pdev->dev); pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); } #ifdef CONFIG_ACPI diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c index ab02325375237..6d66462a6225e 100644 --- a/drivers/hwtracing/coresight/coresight-ctcu-core.c +++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c @@ -268,8 +268,17 @@ static void ctcu_platform_remove(struct platform_device *pdev) if (WARN_ON(!drvdata)) return; + /* + * Resume the device so its clocks are enabled again, balancing the + * clk_disable_unprepare() that devm runs when the driver detaches. + * Then mark it suspended and drop the usage count taken here. + */ + pm_runtime_get_sync(&pdev->dev); + ctcu_remove(pdev); pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); } #ifdef CONFIG_PM diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index 4e66510404a17..012dc4cba1b8a 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -2470,9 +2470,18 @@ static void etm4_remove_platform_dev(struct platform_device *pdev) { struct etmv4_drvdata *drvdata = dev_get_drvdata(&pdev->dev); - if (drvdata) - etm4_remove_dev(drvdata); + if (WARN_ON(!drvdata)) + return; + /* + * Resume the device so its clocks are enabled again, balancing the + * clk_disable_unprepare() that devm runs when the driver detaches. + * Then mark it suspended and drop the usage count taken here. + */ + pm_runtime_get_sync(&pdev->dev); + etm4_remove_dev(drvdata); pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); } static const struct amba_id etm4_ids[] = { diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index d75f11fda72f4..452a277f1cba4 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -336,8 +336,16 @@ static void funnel_platform_remove(struct platform_device *pdev) if (WARN_ON(!drvdata)) return; + /* + * Resume the device so its clocks are enabled again, balancing the + * clk_disable_unprepare() that devm runs when the driver detaches. + * Then mark it suspended and drop the usage count taken here. + */ + pm_runtime_get_sync(&pdev->dev); funnel_remove(&pdev->dev); pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); } static const struct of_device_id funnel_match[] = { diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 3fe5eb5a7a0c4..fa706a0d52b36 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -315,8 +315,16 @@ static void replicator_platform_remove(struct platform_device *pdev) if (WARN_ON(!drvdata)) return; + /* + * Resume the device so its clocks are enabled again, balancing the + * clk_disable_unprepare() that devm runs when the driver detaches. + * Then mark it suspended and drop the usage count taken here. + */ + pm_runtime_get_sync(&pdev->dev); replicator_remove(&pdev->dev); pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); } #ifdef CONFIG_PM diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 5de0adf1d33a2..f4fe46cff13a2 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -1028,8 +1028,16 @@ static void stm_platform_remove(struct platform_device *pdev) if (WARN_ON(!drvdata)) return; + /* + * Resume the device so its clocks are enabled again, balancing the + * clk_disable_unprepare() that devm runs when the driver detaches. + * Then mark it suspended and drop the usage count taken here. + */ + pm_runtime_get_sync(&pdev->dev); __stm_remove(&pdev->dev); pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); } #ifdef CONFIG_ACPI diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c index 2481bae5c9f32..ed5ed53cf6bb3 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-core.c +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c @@ -991,8 +991,16 @@ static void tmc_platform_remove(struct platform_device *pdev) if (WARN_ON(!drvdata)) return; + /* + * Resume the device so its clocks are enabled again, balancing the + * clk_disable_unprepare() that devm runs when the driver detaches. + * Then mark it suspended and drop the usage count taken here. + */ + pm_runtime_get_sync(&pdev->dev); __tmc_remove(&pdev->dev); pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); } #ifdef CONFIG_PM diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 9ae94dc553d73..672c6a4300083 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -288,8 +288,16 @@ static void tpiu_platform_remove(struct platform_device *pdev) if (WARN_ON(!drvdata)) return; + /* + * Resume the device so its clocks are enabled again, balancing the + * clk_disable_unprepare() that devm runs when the driver detaches. + * Then mark it suspended and drop the usage count taken here. + */ + pm_runtime_get_sync(&pdev->dev); __tpiu_remove(&pdev->dev); pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); } #ifdef CONFIG_ACPI From 0e03ccc40e94e12957badd2d2efbc8e94a5424e9 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Jul 2026 09:14:48 +0800 Subject: [PATCH 0142/1133] FROMLIST: coresight: tnoc: Fix clock refcount imbalance on platform remove coresight_get_enable_clocks() enables the programming clock through devm_clk_get_optional_enabled(), which also registers a devm action to call clk_disable_unprepare() when the driver detaches. After probe, pm_runtime_put() allows the device to suspend and the runtime suspend callback disables the clock. During remove the device is left runtime suspended, so pm_runtime_disable() freezes it with the clock already disabled. The devm cleanup that runs afterwards calls clk_disable_unprepare() a second time, underflowing the clock enable refcount. Resume the device with pm_runtime_get_sync() before tearing it down so the clock is enabled again and balances the devm-managed disable. Then pm_runtime_set_suspended() and pm_runtime_put_noidle() leave the device in a coherent runtime PM state (suspended, usage count balanced) once the devm action has disabled the clock. Link: https://lore.kernel.org/all/20260710-fix-clock-refcount-unbalance-v3-2-a37a1fb17981@oss.qualcomm.com/ Fixes: 1abc1b212eff ("coresight: Appropriately disable programming clocks") Reviewed-by: Leo Yan Signed-off-by: Jie Gan --- drivers/hwtracing/coresight/coresight-tnoc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c index 3934cf507bdf9..6bae1a95496d9 100644 --- a/drivers/hwtracing/coresight/coresight-tnoc.c +++ b/drivers/hwtracing/coresight/coresight-tnoc.c @@ -302,8 +302,16 @@ static void tnoc_platform_remove(struct platform_device *pdev) { struct trace_noc_drvdata *drvdata = platform_get_drvdata(pdev); + /* + * Resume the device so its clocks are enabled again, balancing the + * clk_disable_unprepare() that devm runs when the driver detaches. + * Then mark it suspended and drop the usage count taken here. + */ + pm_runtime_get_sync(&pdev->dev); coresight_unregister(drvdata->csdev); pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); if (drvdata->atid > 0) coresight_trace_id_put_system_id(drvdata->atid); } From f7bba91bd0777bc4b9851b7d4e334bbac070c636 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Fri, 11 Sep 2026 03:28:52 -0700 Subject: [PATCH 0143/1133] FROMLIST: coresight: handle runtime PM resume failures When a CoreSight component's parent power domain, such as a CPU cluster genpd, fails to power on, runtime resume returns a negative error. Several call sites ignored that error and continued to access registers on an unpowered device, risking an external abort. Replace the remaining pm_runtime_get_sync() calls with pm_runtime_resume_and_get(), which restores the runtime PM usage count when resume fails. Abort before accessing hardware and propagate the error to the caller. In coresight_get_ref(), unwind the module and device references. In debug_enable_func(), roll back the CPUs that resumed successfully before the failure. Finally, release the mode acquired by stm_enable() if its runtime resume fails. Link: https://lore.kernel.org/all/20260911-b4-coresight-runtime-pm-failures-v1-1-acdf49756e11@qti.qualcomm.com/ Signed-off-by: Yuanfang Zhang --- drivers/hwtracing/coresight/coresight-core.c | 13 ++++++++++--- drivers/hwtracing/coresight/coresight-cpu-debug.c | 10 +++++----- drivers/hwtracing/coresight/coresight-cti-sysfs.c | 10 ++++++++-- drivers/hwtracing/coresight/coresight-etm3x-sysfs.c | 5 ++--- drivers/hwtracing/coresight/coresight-etm4x-sysfs.c | 5 ++++- drivers/hwtracing/coresight/coresight-funnel.c | 5 ++++- drivers/hwtracing/coresight/coresight-stm.c | 7 ++++++- drivers/hwtracing/coresight/coresight-sysfs.c | 11 +++++++++-- 8 files changed, 48 insertions(+), 18 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index d930232e893de..35f0985f20e42 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -822,14 +822,16 @@ struct coresight_device *coresight_get_sink_by_id(u32 id) * * @csdev: The coresight device to get a reference on. * - * Return true in successful case and power up the device. - * Return false when failed to get reference of module. + * Return true on success and power up the device. + * Return false if a reference cannot be obtained or the device cannot be + * powered up. */ static bool coresight_get_ref(struct coresight_device *csdev) { struct device *dev = &csdev->dev; struct device *parent = csdev->dev.parent; struct device_driver *drv; + int ret; /* Make sure csdev can't go away */ get_device(dev); @@ -843,9 +845,14 @@ static bool coresight_get_ref(struct coresight_device *csdev) goto err_module; /* Make sure the device is powered on */ - pm_runtime_get_sync(parent); + ret = pm_runtime_resume_and_get(parent); + if (ret < 0) + goto err_pm; + return true; +err_pm: + module_put(drv->owner); err_module: put_device(parent); put_device(dev); diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c index 87b39874461e2..edccbd2fa5e2c 100644 --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c @@ -429,19 +429,19 @@ static int debug_enable_func(void) if (!drvdata) continue; - ret = pm_runtime_get_sync(drvdata->dev); + ret = pm_runtime_resume_and_get(drvdata->dev); if (ret < 0) goto err; - else - cpumask_set_cpu(cpu, &mask); + + cpumask_set_cpu(cpu, &mask); } return 0; err: /* - * If pm_runtime_get_sync() has failed, need rollback on - * all the other CPUs that have been enabled before that. + * If runtime resume has failed, roll back all the other CPUs + * that have been enabled before that. */ for_each_cpu(cpu, &mask) { drvdata = per_cpu(debug_drvdata, cpu); diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index f7f6f22e4fb98..db1390b3c660a 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -167,8 +167,11 @@ static ssize_t coresight_cti_reg_show(struct device *dev, struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cs_off_attribute *cti_attr = container_of(attr, struct cs_off_attribute, attr); u32 val = 0; + int ret; - pm_runtime_get_sync(dev->parent); + ret = pm_runtime_resume_and_get(dev->parent); + if (ret < 0) + return ret; scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) val = cti_read_single_reg_index(drvdata, cti_attr->off, cti_attr->index); @@ -185,11 +188,14 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev, struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cs_off_attribute *cti_attr = container_of(attr, struct cs_off_attribute, attr); unsigned long val = 0; + int ret; if (kstrtoul(buf, 0, &val)) return -EINVAL; - pm_runtime_get_sync(dev->parent); + ret = pm_runtime_resume_and_get(dev->parent); + if (ret < 0) + return ret; scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) cti_write_single_reg_index(drvdata, cti_attr->off, cti_attr->index, val); diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c index d185fb8270e13..4a3f3a32b5caf 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c @@ -32,9 +32,9 @@ static int etm_readl_cslocked(struct etm_drvdata *drvdata, u32 off, int ret; struct etm_readl_cslocked_arg arg; - ret = pm_runtime_get_sync(drvdata->csdev->dev.parent); + ret = pm_runtime_resume_and_get(drvdata->csdev->dev.parent); if (ret < 0) - goto out; + return ret; arg.drvdata = drvdata; arg.off = off; @@ -43,7 +43,6 @@ static int etm_readl_cslocked(struct etm_drvdata *drvdata, u32 off, ret = smp_call_function_single(drvdata->cpu, etm_readl_cslocked_smp_call, (void *)&arg, 1); -out: pm_runtime_put(drvdata->csdev->dev.parent); return ret; } diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index db9e603f97ba8..f29e753245d3d 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -2498,10 +2498,13 @@ static ssize_t coresight_etm4x_reg_show(struct device *dev, { u32 val, offset; struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); + int ret; offset = coresight_etm4x_attr_to_offset(d_attr); - pm_runtime_get_sync(dev->parent); + ret = pm_runtime_resume_and_get(dev->parent); + if (ret < 0) + return ret; val = etmv4_cross_read(drvdata, offset); pm_runtime_put_sync(dev->parent); diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 452a277f1cba4..f166b17c73938 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -190,9 +190,12 @@ static ssize_t funnel_ctrl_show(struct device *dev, struct device_attribute *attr, char *buf) { u32 val; + int ret; struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent); - pm_runtime_get_sync(dev->parent); + ret = pm_runtime_resume_and_get(dev->parent); + if (ret < 0) + return ret; val = get_funnel_ctrl_hw(drvdata); diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index f4fe46cff13a2..6cbbf2ed47e84 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -196,6 +196,7 @@ static int stm_enable(struct coresight_device *csdev, struct perf_event *event, __maybe_unused struct coresight_path *path) { struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + int ret; if (mode != CS_MODE_SYSFS) return -EINVAL; @@ -205,7 +206,11 @@ static int stm_enable(struct coresight_device *csdev, struct perf_event *event, return -EBUSY; } - pm_runtime_get_sync(csdev->dev.parent); + ret = pm_runtime_resume_and_get(csdev->dev.parent); + if (ret < 0) { + coresight_set_mode(csdev, CS_MODE_DISABLED); + return ret; + } spin_lock(&drvdata->spinlock); stm_enable_hw(drvdata); diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c index 75000fe64fdac..2b18f7155aa1a 100644 --- a/drivers/hwtracing/coresight/coresight-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-sysfs.c @@ -17,8 +17,12 @@ ssize_t coresight_simple_show_pair(struct device *_dev, struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev); struct cs_pair_attribute *cs_attr = container_of(attr, struct cs_pair_attribute, attr); u64 val; + int ret; + + ret = pm_runtime_resume_and_get(_dev->parent); + if (ret < 0) + return ret; - pm_runtime_get_sync(_dev->parent); val = csdev_access_relaxed_read_pair(&csdev->access, cs_attr->lo_off, cs_attr->hi_off); pm_runtime_put_sync(_dev->parent); return sysfs_emit(buf, "0x%llx\n", val); @@ -31,8 +35,11 @@ ssize_t coresight_simple_show32(struct device *_dev, struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev); struct cs_off_attribute *cs_attr = container_of(attr, struct cs_off_attribute, attr); u64 val; + int ret; - pm_runtime_get_sync(_dev->parent); + ret = pm_runtime_resume_and_get(_dev->parent); + if (ret < 0) + return ret; val = csdev_access_relaxed_read32(&csdev->access, cs_attr->off); pm_runtime_put_sync(_dev->parent); return sysfs_emit(buf, "0x%llx\n", val); From f75378e1a65c23980a1ed07ca31e60fcaf65d891 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Mon, 5 Oct 2026 17:54:02 +0530 Subject: [PATCH 0144/1133] FROMLIST: dt-bindings: hwmon: Describe Qualcomm BCL hardware Qualcomm SPMI PMIC BCL (Battery Current Limiting) is a safety feature that monitors battery or system voltage and current to alert system for overcurrent or undervoltage conditions. It provides: - Real-time voltage and current monitoring - Configurable thresholds per channel - Hardware interrupts when thresholds are violated Add a devicetree binding to describe the BCL on Qualcomm's PMICs. Add sensor type to SPMI device list for BCL device. Signed-off-by: Manaf Meethalavalappu Pallikunhi Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20261005-qcom-bcl-hwmon-v4-1-50b9a8c730b7@oss.qualcomm.com --- .../bindings/hwmon/qcom,pm7250b-bcl.yaml | 69 +++++++++++++++++++ .../bindings/mfd/qcom,spmi-pmic.yaml | 4 ++ MAINTAINERS | 7 ++ 3 files changed, 80 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/qcom,pm7250b-bcl.yaml diff --git a/Documentation/devicetree/bindings/hwmon/qcom,pm7250b-bcl.yaml b/Documentation/devicetree/bindings/hwmon/qcom,pm7250b-bcl.yaml new file mode 100644 index 0000000000000..a9e3525cf0998 --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/qcom,pm7250b-bcl.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/hwmon/qcom,pm7250b-bcl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SPMI PMIC Battery Current Limiting (BCL) Hardware Monitor + +maintainers: + - Manaf Meethalavalappu Pallikunhi + +description: + SPMI PMIC Battery Current Limiting (BCL) hardware provides monitoring and + alarm functionality for battery overcurrent and battery or system under + voltage conditions. It monitors battery voltage and current, and + can trigger interrupts when configurable thresholds are exceeded. + +properties: + compatible: + enum: + - qcom,pm7250b-bcl + - qcom,pm7550-bcl + - qcom,pm7550ba-bcl + - qcom,pm8350c-bcl + - qcom,pm8550-bcl + - qcom,pmh0101-bcl + - qcom,pmih0108-bcl + - qcom,smb2360-bcl + - qcom,smb2370-bcl + + reg: + maxItems: 1 + + interrupts: + maxItems: 3 + + interrupt-names: + items: + - const: max-min + - const: critical + - const: emergency + +required: + - compatible + - reg + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + #include + + pmic { + #address-cells = <1>; + #size-cells = <0>; + + sensor@1d00 { + compatible = "qcom,pm7250b-bcl"; + reg = <0x1d00>; + interrupts = <0x2 0x1d 0x0 IRQ_TYPE_EDGE_RISING>, + <0x2 0x1d 0x1 IRQ_TYPE_EDGE_RISING>, + <0x2 0x1d 0x2 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "max-min", + "critical", + "emergency"; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index 7a889d8883835..2c3b604379826 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -197,6 +197,10 @@ patternProperties: type: object $ref: /schemas/rtc/qcom-pm8xxx-rtc.yaml# + "^sensor@[0-9a-f]+$": + type: object + $ref: /schemas/hwmon/qcom,pm7250b-bcl.yaml# + "^temp-alarm@[0-9a-f]+$": type: object $ref: /schemas/thermal/qcom,spmi-temp-alarm.yaml# diff --git a/MAINTAINERS b/MAINTAINERS index fc651c6eb6ce1..5fd24e613f4e8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22863,6 +22863,13 @@ S: Maintained F: Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml F: drivers/net/wwan/qcom_bam_dmux.c +QUALCOMM BCL HARDWARE MONITOR DRIVER +M: Manaf Meethalavalappu Pallikunhi +L: linux-hwmon@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/hwmon/qcom,pm7250b-bcl.yaml + QUALCOMM BLUETOOTH DRIVER M: Bartosz Golaszewski L: linux-arm-msm@vger.kernel.org From 000ea55a2de3fd3f37da06c7f080a2de60eedcb3 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Mon, 5 Oct 2026 17:54:03 +0530 Subject: [PATCH 0145/1133] FROMLIST: hwmon: Add Qualcomm PMIC BCL driver Add driver for Qualcomm SPMI PMIC Battery Current Limiting (BCL) hardware monitor. The driver exposes battery voltage and current monitoring through hwmon interface. The BCL driver provides - Real-time voltage and current readings - Configurable threshold-based alarms - Interrupt-driven notifications when thresholds are exceeded - Automatic threshold management with polling-based recovery - Hardware-specific scaling factors and threshold representations Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20261005-qcom-bcl-hwmon-v4-2-50b9a8c730b7@oss.qualcomm.com --- MAINTAINERS | 1 + drivers/hwmon/Kconfig | 11 + drivers/hwmon/Makefile | 1 + drivers/hwmon/qcom-bcl-hwmon.c | 1448 ++++++++++++++++++++++++++++++++ 4 files changed, 1461 insertions(+) create mode 100644 drivers/hwmon/qcom-bcl-hwmon.c diff --git a/MAINTAINERS b/MAINTAINERS index 5fd24e613f4e8..7e775b350b97a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22869,6 +22869,7 @@ L: linux-hwmon@vger.kernel.org L: linux-arm-msm@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/hwmon/qcom,pm7250b-bcl.yaml +F: drivers/hwmon/qcom-bcl-hwmon.c QUALCOMM BLUETOOTH DRIVER M: Bartosz Golaszewski diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 18c682e1a4756..8b5a490217c9a 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1999,6 +1999,17 @@ config SENSORS_PWM_FAN This driver can also be built as a module. If so, the module will be called pwm-fan. +config SENSORS_QCOM_SPMI_BCL + tristate "Qualcomm SPMI BCL hardware monitoring" + depends on SPMI + select REGMAP_SPMI + help + Say yes here to enable support for Qualcomm battery over current + and under voltage alarms monitor. + + This driver can also be built as a module. If so, the module + will be called qcom-bcl-hwmon. + config SENSORS_QNAP_MCU_HWMON tristate "QNAP MCU hardware monitoring" depends on MFD_QNAP_MCU diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d4c345ed7261f..ef19ddf527897 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -209,6 +209,7 @@ obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o obj-$(CONFIG_SENSORS_PROM21_XHCI) += prom21-xhci.o obj-$(CONFIG_SENSORS_PT5161L) += pt5161l.o obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o +obj-$(CONFIG_SENSORS_QCOM_SPMI_BCL) += qcom-bcl-hwmon.o obj-$(CONFIG_SENSORS_QNAP_MCU_HWMON) += qnap-mcu-hwmon.o obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o obj-$(CONFIG_SENSORS_SBTSI) += sbtsi_temp.o diff --git a/drivers/hwmon/qcom-bcl-hwmon.c b/drivers/hwmon/qcom-bcl-hwmon.c new file mode 100644 index 0000000000000..a883824949e6c --- /dev/null +++ b/drivers/hwmon/qcom-bcl-hwmon.c @@ -0,0 +1,1448 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Qualcomm pmic BCL driver for battery overcurrent and + * battery or system under voltage monitor + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BCL common regmap offset */ +#define REVISION1 0x0 +#define REVISION2 0x1 +#define STATUS 0x8 +#define INT_RT_STS 0x10 +#define EN_CTL1 0x46 + +/* BCL GEN1 regmap offsets */ +#define VADC_L0_THR 0x48 +#define VCMP_L1_THR 0x49 +#define VCMP_L2_THR 0x4a +#define IADC_H0_THR 0x4b +#define IADC_H1_THR 0x4c +#define VADC_DATA1 0x76 +#define IADC_DATA1 0x86 + +/* BCL GEN3 regmap offsets */ +#define VCMP_L0_THR 0x47 +#define IADC_H1_THR_GEN3 0x4d + +#define BCL_ALARM_POLLING_MS 50 + +/** + * enum bcl_limit_alarm - BCL alarm threshold levels + * @BCL_LIMIT_ALARM_LVL0: Level 0 alarm threshold + * @BCL_LIMIT_ALARM_LVL1: Level 1 alarm threshold + * @BCL_LIMIT_ALARM_LVL2: Level 2 alarm threshold + * @BCL_LIMIT_ALARM_MAX: sentinel value + * + * Defines the threshold levels for BCL monitoring. Each level corresponds + * to different severity of in or curr conditions. + */ +enum bcl_limit_alarm { + BCL_LIMIT_ALARM_LVL0, + BCL_LIMIT_ALARM_LVL1, + BCL_LIMIT_ALARM_LVL2, + + BCL_LIMIT_ALARM_MAX, +}; + +/** + * enum bcl_channel - BCL supported sensor channel type + * @CHANNEL_IN: in (voltage) channel + * @CHANNEL_CURR: curr (current) channel + * @CHANNEL_MAX: sentinel value + * + * Defines the supported channel types for bcl. + */ +enum bcl_channel { + CHANNEL_IN, + CHANNEL_CURR, + + CHANNEL_MAX, +}; + +/** + * enum bcl_thresh_type - voltage or current threshold representation type + * @THRESH_TYPE_ADC: Raw ADC value representation + * @THRESH_TYPE_INDEX: Index-based voltage or current representation + * + * Specifies how voltage or current thresholds are stored and interpreted in + * registers. Some PMICs use raw ADC values while others use indexed values. + */ +enum bcl_thresh_type { + THRESH_TYPE_ADC, + THRESH_TYPE_INDEX, +}; + +/** + * enum bcl_battery_config - Battery configuration types + * @BCL_BATT_1S: Single cell battery + * @BCL_BATT_2S: Two cells in series + * @BCL_BATT_3S: Three cells in series + */ +enum bcl_battery_config { + BCL_BATT_1S, + BCL_BATT_2S, + BCL_BATT_3S, +}; + +/** + * enum bcl_fields - BCL register field identifiers + * @F_V_MAJOR: Major revision info field + * @F_V_MINOR: Minor revision info field + * @F_CTL_EN: Monitor enable control field + * @F_LVL0_ALARM: Level 0 alarm status field + * @F_LVL1_ALARM: Level 1 alarm status field + * @F_LVL2_ALARM: Level 2 alarm status field + * @F_IN_L0_THR: voltage level 0 threshold field + * @F_IN_L1_THR: voltage level 1 threshold field + * @F_IN_L2_THR: voltage level 2 threshold field + * @F_IN_INPUT: voltage input data field (LSB for 16-bit data) + * @F_CURR_H0_THR: current level 0 threshold field + * @F_CURR_H1_THR: current level 1 threshold field + * @F_CURR_INPUT: current input data field (LSB for 16-bit data) + * @F_MAX_FIELDS: sentinel value + * + * Enumeration of all register fields used by the BCL driver for accessing + * registers through regmap fields. + */ +enum bcl_fields { + /* Common fields - present in all BCL variants */ + F_V_MAJOR, + F_V_MINOR, + F_CTL_EN, + F_LVL0_ALARM, + F_LVL1_ALARM, + F_LVL2_ALARM, + + /* Voltage monitoring fields */ + F_IN_L0_THR, + F_IN_L1_THR, + F_IN_L2_THR, + F_IN_INPUT, + + /* Current monitoring fields */ + F_CURR_H0_THR, + F_CURR_H1_THR, + F_CURR_INPUT, + + F_MAX_FIELDS +}; + +/** + * struct bcl_channel_cfg - BCL channel related configuration + * @default_scale_nu: Default scaling factor in nano unit + * @base_mu: Base threshold value in milli unit + * @max_mu: Maximum threshold value in milli unit + * @step_mu: step increment value between two indexed threshold value in milli unit + * @thresh_type: Array specifying threshold representation type for each alarm level + * + * Contains hardware-specific configuration and scaling parameters for different + * channels (voltage and current). + */ +struct bcl_channel_cfg { + u32 default_scale_nu; + u32 base_mu; + u32 max_mu; + u32 step_mu; + u8 thresh_type[BCL_LIMIT_ALARM_MAX]; +}; + +/** + * struct bcl_desc - BCL device descriptor + * @reg_fields: Array of register field definitions for this device variant + * @channel_cfg: Array of channel configurations indexed by battery config + * PMICs without battery detection: only [BCL_BATT_1S] is defined + * PMICs with battery detection: [BCL_BATT_2S], [BCL_BATT_3S] + * @battery_config_field: Register field for battery configuration detection + * NOTE: This is an ABSOLUTE address, not relative to BCL base + * Set to REG_FIELD(0, 0, 0) if not used + * @num_reg_fields: Number of register field definitions for this device variant + * @data_field_bits_size: data read register bit size + * @thresh_field_bits_size: lsb bit size those are not included in threshold register + * @in_mon_enabled: Voltage monitoring enabled at boot + * @in_input_enabled: Voltage input reading enabled at boot + * @curr_mon_enabled: Current monitoring enabled at boot + * + * Contains hardware-specific configuration and scaling parameters for different + * BCL variants. Each PMIC model may have different register layouts and + * conversion factors. + */ +struct bcl_desc { + const struct reg_field *reg_fields; + struct bcl_channel_cfg channel_cfg[BCL_BATT_3S + 1][CHANNEL_MAX]; + const struct reg_field battery_config_field; + u8 num_reg_fields; + u8 data_field_bits_size; + u8 thresh_field_bits_size; + bool in_mon_enabled; + bool in_input_enabled; + bool curr_mon_enabled; +}; + +/** + * struct bcl_alarm_data - BCL alarm interrupt data + * @irq: IRQ number assigned to this alarm + * @irq_enabled: Flag indicating if IRQ is enabled + * @irq_wake_enabled: Flag indicating if IRQ wake is enabled + * @shutting_down: Flag preventing work from re-enabling IRQ during teardown + * @type: Alarm level type (LVL0, or LVL1) + * @device: Pointer to parent BCL device structure + * @a_lock: Mutex for protecting alarm state + * @alarm_poll_work: delayed_work to poll alarm status + * + * Stores interrupt-related information for each alarm threshold level. + * Used by the IRQ handler to identify which alarm triggered. + */ +struct bcl_alarm_data { + int irq; + bool irq_enabled; + bool irq_wake_enabled; + bool shutting_down; + enum bcl_limit_alarm type; + void *device; + /* Protects alarm IRQ enable/disable state */ + struct mutex a_lock; + struct delayed_work alarm_poll_work; +}; + +/** + * struct bcl_device - Main BCL device structure + * @dev: Pointer to device structure + * @regmap: Regmap for accessing PMIC registers + * @base: the BCL regbase offset from regmap + * @fields: Array of regmap fields for register access + * @bcl_alarms: Array of alarm data structures for each threshold level + * @lock: Mutex for protecting concurrent hardware access + * @last_in_input: Last valid voltage input reading in millivolts + * @last_curr_input: Last valid current input reading in milliamps + * @last_in_updated: Timestamp of last voltage input update + * @last_curr_updated: Timestamp of last current input update + * @desc: Pointer to device descriptor with hardware-specific parameters + * @hwmon_dev: Pointer to registered hwmon device + * @hwmon_name: Sanitized name for hwmon device + * @batt_config: Detected battery configuration (only for SMB2360/2370) + * @batt_config_regfield: Regmap field for battery configuration register + * + * Main driver structure containing all state and configuration for a BCL + * monitoring instance. Manages voltage and current monitoring, thresholds, + * and alarm handling. + */ +struct bcl_device { + struct device *dev; + struct regmap *regmap; + u16 base; + struct regmap_field *fields[F_MAX_FIELDS]; + struct bcl_alarm_data bcl_alarms[BCL_LIMIT_ALARM_MAX]; + /* Protects hardware register access and device state */ + struct mutex lock; + u32 last_in_input; + s32 last_curr_input; + unsigned long last_in_updated; + unsigned long last_curr_updated; + const struct bcl_desc *desc; + struct device *hwmon_dev; + char *hwmon_name; + enum bcl_battery_config batt_config; + struct regmap_field *batt_config_regfield; +}; + +static const u8 in_attr_to_lvl_map[] = { + [hwmon_in_min] = BCL_LIMIT_ALARM_LVL0, + [hwmon_in_lcrit] = BCL_LIMIT_ALARM_LVL1, + [hwmon_in_lemergency] = BCL_LIMIT_ALARM_LVL2, + [hwmon_in_min_alarm] = BCL_LIMIT_ALARM_LVL0, + [hwmon_in_lcrit_alarm] = BCL_LIMIT_ALARM_LVL1, + [hwmon_in_lemergency_alarm] = BCL_LIMIT_ALARM_LVL2, +}; + +static const u8 in_lvl_to_attr_map[BCL_LIMIT_ALARM_MAX] = { + [BCL_LIMIT_ALARM_LVL0] = hwmon_in_min_alarm, + [BCL_LIMIT_ALARM_LVL1] = hwmon_in_lcrit_alarm, + [BCL_LIMIT_ALARM_LVL2] = hwmon_in_lemergency_alarm, +}; + +static const u8 curr_attr_to_lvl_map[] = { + [hwmon_curr_max] = BCL_LIMIT_ALARM_LVL0, + [hwmon_curr_crit] = BCL_LIMIT_ALARM_LVL1, + [hwmon_curr_max_alarm] = BCL_LIMIT_ALARM_LVL0, + [hwmon_curr_crit_alarm] = BCL_LIMIT_ALARM_LVL1, + [hwmon_curr_emergency_alarm] = BCL_LIMIT_ALARM_LVL2, +}; + +static const u8 curr_lvl_to_attr_map[BCL_LIMIT_ALARM_MAX] = { + [BCL_LIMIT_ALARM_LVL0] = hwmon_curr_max_alarm, + [BCL_LIMIT_ALARM_LVL1] = hwmon_curr_crit_alarm, + [BCL_LIMIT_ALARM_LVL2] = hwmon_curr_emergency_alarm, +}; + +/* Interrupt names for each alarm level */ +static const char * const bcl_int_names[BCL_LIMIT_ALARM_MAX] = { + [BCL_LIMIT_ALARM_LVL0] = "max-min", + [BCL_LIMIT_ALARM_LVL1] = "critical", + [BCL_LIMIT_ALARM_LVL2] = "emergency", +}; + +static const struct reg_field bcl_pm7250b_reg_fields[] = { + [F_V_MAJOR] = REG_FIELD(REVISION2, 0, 7), + [F_V_MINOR] = REG_FIELD(REVISION1, 0, 7), + [F_CTL_EN] = REG_FIELD(EN_CTL1, 7, 7), + [F_LVL0_ALARM] = REG_FIELD(STATUS, 0, 0), + [F_LVL1_ALARM] = REG_FIELD(STATUS, 1, 1), + [F_LVL2_ALARM] = REG_FIELD(STATUS, 2, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_L2_THR] = REG_FIELD(VCMP_L2_THR, 0, 5), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_pm7550ba_reg_fields[] = { + [F_V_MAJOR] = REG_FIELD(REVISION2, 0, 7), + [F_V_MINOR] = REG_FIELD(REVISION1, 0, 7), + [F_CTL_EN] = REG_FIELD(EN_CTL1, 7, 7), + [F_LVL0_ALARM] = REG_FIELD(STATUS, 0, 0), + [F_LVL1_ALARM] = REG_FIELD(STATUS, 1, 1), + [F_LVL2_ALARM] = REG_FIELD(STATUS, 2, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_L2_THR] = REG_FIELD(VCMP_L2_THR, 0, 5), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR_GEN3, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_pm8350c_reg_fields[] = { + [F_V_MAJOR] = REG_FIELD(REVISION2, 0, 7), + [F_V_MINOR] = REG_FIELD(REVISION1, 0, 7), + [F_CTL_EN] = REG_FIELD(EN_CTL1, 7, 7), + [F_LVL0_ALARM] = REG_FIELD(STATUS, 0, 0), + [F_LVL1_ALARM] = REG_FIELD(STATUS, 1, 1), + [F_LVL2_ALARM] = REG_FIELD(STATUS, 2, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_L2_THR] = REG_FIELD(VCMP_L2_THR, 0, 5), +}; + +static const struct reg_field bcl_pm8550_reg_fields[] = { + [F_V_MAJOR] = REG_FIELD(REVISION2, 0, 7), + [F_V_MINOR] = REG_FIELD(REVISION1, 0, 7), + [F_CTL_EN] = REG_FIELD(EN_CTL1, 7, 7), + [F_LVL0_ALARM] = REG_FIELD(STATUS, 0, 0), + [F_LVL1_ALARM] = REG_FIELD(STATUS, 1, 1), + [F_LVL2_ALARM] = REG_FIELD(STATUS, 2, 2), + [F_IN_L0_THR] = REG_FIELD(VCMP_L0_THR, 0, 5), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_L2_THR] = REG_FIELD(VCMP_L2_THR, 0, 5), +}; + +static const struct reg_field bcl_pmh0101_reg_fields[] = { + [F_V_MAJOR] = REG_FIELD(REVISION2, 0, 7), + [F_V_MINOR] = REG_FIELD(REVISION1, 0, 7), + [F_CTL_EN] = REG_FIELD(EN_CTL1, 7, 7), + [F_LVL0_ALARM] = REG_FIELD(STATUS, 0, 0), + [F_LVL1_ALARM] = REG_FIELD(STATUS, 1, 1), + [F_LVL2_ALARM] = REG_FIELD(STATUS, 2, 2), + [F_IN_L0_THR] = REG_FIELD(VCMP_L0_THR, 0, 6), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 6), + [F_IN_L2_THR] = REG_FIELD(VCMP_L2_THR, 0, 6), +}; + +static const struct reg_field bcl_pmih0108_reg_fields[] = { + [F_V_MAJOR] = REG_FIELD(REVISION2, 0, 7), + [F_V_MINOR] = REG_FIELD(REVISION1, 0, 7), + [F_CTL_EN] = REG_FIELD(EN_CTL1, 7, 7), + [F_LVL0_ALARM] = REG_FIELD(STATUS, 0, 0), + [F_LVL1_ALARM] = REG_FIELD(STATUS, 1, 1), + [F_LVL2_ALARM] = REG_FIELD(STATUS, 2, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_L2_THR] = REG_FIELD(VCMP_L2_THR, 0, 5), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR_GEN3, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_smb2360_reg_fields[] = { + [F_V_MAJOR] = REG_FIELD(REVISION2, 0, 7), + [F_V_MINOR] = REG_FIELD(REVISION1, 0, 7), + [F_CTL_EN] = REG_FIELD(EN_CTL1, 7, 7), + [F_LVL0_ALARM] = REG_FIELD(STATUS, 0, 0), + [F_LVL1_ALARM] = REG_FIELD(STATUS, 1, 1), + [F_LVL2_ALARM] = REG_FIELD(STATUS, 2, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_L2_THR] = REG_FIELD(VCMP_L2_THR, 0, 5), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR_GEN3, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct reg_field bcl_smb2370_reg_fields[] = { + [F_V_MAJOR] = REG_FIELD(REVISION2, 0, 7), + [F_V_MINOR] = REG_FIELD(REVISION1, 0, 7), + [F_CTL_EN] = REG_FIELD(EN_CTL1, 7, 7), + [F_LVL0_ALARM] = REG_FIELD(STATUS, 0, 0), + [F_LVL1_ALARM] = REG_FIELD(STATUS, 1, 1), + [F_LVL2_ALARM] = REG_FIELD(STATUS, 2, 2), + [F_IN_L0_THR] = REG_FIELD(VADC_L0_THR, 0, 7), + [F_IN_L1_THR] = REG_FIELD(VCMP_L1_THR, 0, 5), + [F_IN_L2_THR] = REG_FIELD(VCMP_L2_THR, 0, 5), + [F_IN_INPUT] = REG_FIELD(VADC_DATA1, 0, 7), + [F_CURR_H0_THR] = REG_FIELD(IADC_H0_THR, 0, 7), + [F_CURR_H1_THR] = REG_FIELD(IADC_H1_THR_GEN3, 0, 7), + [F_CURR_INPUT] = REG_FIELD(IADC_DATA1, 0, 7), +}; + +static const struct bcl_desc pm7250b_data = { + .reg_fields = bcl_pm7250b_reg_fields, + .num_reg_fields = F_CURR_INPUT + 1, + .data_field_bits_size = 8, + .thresh_field_bits_size = 7, + .battery_config_field = REG_FIELD(0, 0, 0), + .in_mon_enabled = true, + .in_input_enabled = true, + .curr_mon_enabled = true, + .channel_cfg[BCL_BATT_1S][CHANNEL_IN] = { + .base_mu = 2250, + .max_mu = 3600, + .step_mu = 25, + .default_scale_nu = 194637, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_INDEX, THRESH_TYPE_INDEX}, + }, + .channel_cfg[BCL_BATT_1S][CHANNEL_CURR] = { + .max_mu = 9918, + .default_scale_nu = 305180, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_ADC}, + }, +}; + +static const struct bcl_desc pm8350c_data = { + .reg_fields = bcl_pm8350c_reg_fields, + .num_reg_fields = F_IN_L2_THR + 1, + .data_field_bits_size = 0, + .thresh_field_bits_size = 8, + .battery_config_field = REG_FIELD(0, 0, 0), + .in_mon_enabled = true, + .in_input_enabled = false, + .curr_mon_enabled = false, + .channel_cfg[BCL_BATT_1S][CHANNEL_IN] = { + .base_mu = 2250, + .max_mu = 3600, + .step_mu = 25, + .default_scale_nu = 194637, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_INDEX, THRESH_TYPE_INDEX}, + }, +}; + +static const struct bcl_desc pm7550ba_data = { + .reg_fields = bcl_pm7550ba_reg_fields, + .num_reg_fields = F_CURR_INPUT + 1, + .data_field_bits_size = 8, + .thresh_field_bits_size = 8, + .battery_config_field = REG_FIELD(0, 0, 0), + .in_mon_enabled = true, + .in_input_enabled = true, + .curr_mon_enabled = true, + .channel_cfg[BCL_BATT_1S][CHANNEL_IN] = { + .base_mu = 2250, + .max_mu = 3600, + .step_mu = 25, + .default_scale_nu = 194637, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_INDEX, THRESH_TYPE_INDEX}, + }, + .channel_cfg[BCL_BATT_1S][CHANNEL_CURR] = { + .max_mu = 11901, + .default_scale_nu = 366220, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_ADC}, + }, +}; + +static const struct bcl_desc pm8550_data = { + .reg_fields = bcl_pm8550_reg_fields, + .num_reg_fields = F_IN_L2_THR + 1, + .data_field_bits_size = 0, + .thresh_field_bits_size = 6, + .battery_config_field = REG_FIELD(0, 0, 0), + .in_mon_enabled = true, + .in_input_enabled = false, + .curr_mon_enabled = false, + .channel_cfg[BCL_BATT_1S][CHANNEL_IN] = { + .base_mu = 2250, + .max_mu = 3600, + .step_mu = 25, + .thresh_type = {THRESH_TYPE_INDEX, THRESH_TYPE_INDEX, THRESH_TYPE_INDEX}, + }, +}; + +static const struct bcl_desc pmih0108_data = { + .reg_fields = bcl_pmih0108_reg_fields, + .num_reg_fields = F_CURR_INPUT + 1, + .data_field_bits_size = 16, + .thresh_field_bits_size = 8, + .battery_config_field = REG_FIELD(0, 0, 0), + .in_mon_enabled = true, + .in_input_enabled = true, + .curr_mon_enabled = true, + .channel_cfg[BCL_BATT_1S][CHANNEL_IN] = { + .base_mu = 2250, + .max_mu = 3600, + .step_mu = 25, + .default_scale_nu = 194637, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_INDEX, THRESH_TYPE_INDEX}, + }, + .channel_cfg[BCL_BATT_1S][CHANNEL_CURR] = { + .max_mu = 19836, + .default_scale_nu = 610370, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_ADC}, + }, +}; + +static const struct bcl_desc pmh0101_data = { + .reg_fields = bcl_pmh0101_reg_fields, + .num_reg_fields = F_IN_L2_THR + 1, + .thresh_field_bits_size = 7, + .battery_config_field = REG_FIELD(0, 0, 0), + .in_mon_enabled = true, + .in_input_enabled = false, + .curr_mon_enabled = false, + .channel_cfg[BCL_BATT_1S][CHANNEL_IN] = { + .base_mu = 1500, + .max_mu = 4000, + .step_mu = 25, + .thresh_type = {THRESH_TYPE_INDEX, THRESH_TYPE_INDEX, THRESH_TYPE_INDEX}, + }, +}; + +/* Register 0x2a50 mapping: 0 -> 2S, 1 -> 3S */ +static const struct bcl_desc smb2360_data = { + .reg_fields = bcl_smb2360_reg_fields, + .num_reg_fields = F_CURR_INPUT + 1, + .data_field_bits_size = 8, + .thresh_field_bits_size = 8, + .battery_config_field = REG_FIELD(0x2a50, 0, 1), + .in_mon_enabled = true, + .in_input_enabled = true, + .curr_mon_enabled = true, + .channel_cfg[BCL_BATT_2S][CHANNEL_IN] = { + .base_mu = 4500, + .max_mu = 8400, + .step_mu = 50, + .default_scale_nu = 432918, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_INDEX, THRESH_TYPE_INDEX}, + }, + .channel_cfg[BCL_BATT_2S][CHANNEL_CURR] = { + .max_mu = 17575, + .default_scale_nu = 540679, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_ADC}, + }, + .channel_cfg[BCL_BATT_3S][CHANNEL_IN] = { + .base_mu = 6750, + .max_mu = 12600, + .step_mu = 75, + .default_scale_nu = 648790, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_INDEX, THRESH_TYPE_INDEX}, + }, + .channel_cfg[BCL_BATT_3S][CHANNEL_CURR] = { + .max_mu = 17575, + .default_scale_nu = 540679, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_ADC}, + }, +}; + +static const struct bcl_desc smb2370_data = { + .reg_fields = bcl_smb2370_reg_fields, + .num_reg_fields = F_CURR_INPUT + 1, + .data_field_bits_size = 16, + .thresh_field_bits_size = 8, + .battery_config_field = REG_FIELD(0x2a50, 0, 1), + .in_mon_enabled = true, + .in_input_enabled = true, + .curr_mon_enabled = true, + .channel_cfg[BCL_BATT_2S][CHANNEL_IN] = { + .base_mu = 4500, + .max_mu = 8400, + .step_mu = 50, + .default_scale_nu = 432918, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_INDEX, THRESH_TYPE_INDEX}, + }, + .channel_cfg[BCL_BATT_2S][CHANNEL_CURR] = { + .max_mu = 46852, + .default_scale_nu = 1441603, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_ADC}, + }, + .channel_cfg[BCL_BATT_3S][CHANNEL_IN] = { + .base_mu = 6750, + .max_mu = 12600, + .step_mu = 75, + .default_scale_nu = 648790, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_INDEX, THRESH_TYPE_INDEX}, + }, + .channel_cfg[BCL_BATT_3S][CHANNEL_CURR] = { + .max_mu = 46852, + .default_scale_nu = 1441603, + .thresh_type = {THRESH_TYPE_ADC, THRESH_TYPE_ADC}, + }, +}; + +/** + * bcl_convert_raw_to_milliunit - Convert raw value to milli unit + * @bcl: BCL device structure + * @raw_val: Raw ADC value from hardware (signed for current, unsigned for voltage) + * @type: type of the channel, in or curr + * @field_width: bits size for data or threshold field + * + * Return: value in milli unit + */ +static int bcl_convert_raw_to_milliunit(const struct bcl_device *bcl, + s32 raw_val, + enum bcl_channel type, + u8 field_width) +{ + const struct bcl_desc *desc = bcl->desc; + u32 def_scale = desc->channel_cfg[bcl->batt_config][type].default_scale_nu; + u32 scaling_factor = (field_width > 8) ? def_scale : (def_scale << field_width); + + return DIV_S64_ROUND_CLOSEST((s64)raw_val * scaling_factor, 1000000); +} + +/** + * bcl_convert_milliunit_to_raw - Convert milli unit to raw value + * @bcl: BCL device structure + * @mval: threshold value in milli unit + * @type: type of the channel, in or curr + * @field_width: bits size for data or threshold field + * + * Return: Raw ADC value for hardware + */ +static unsigned int bcl_convert_milliunit_to_raw(const struct bcl_device *bcl, + int mval, + enum bcl_channel type, + u8 field_width) +{ + const struct bcl_desc *desc = bcl->desc; + u32 def_scale = desc->channel_cfg[bcl->batt_config][type].default_scale_nu; + u32 scaling_factor = (field_width > 8) ? def_scale : (def_scale << field_width); + + return DIV_ROUND_CLOSEST_ULL((u64)mval * 1000000, scaling_factor); +} + +/** + * bcl_convert_milliunit_to_index - Convert milliunit to in or curr index + * @bcl: BCL device structure + * @val: in or curr value in milli unit + * @type: type of the channel, in or curr + * + * Converts a value in milli unit to an index for BCL that use indexed thresholds. + * + * Return: Index value + */ +static unsigned int bcl_convert_milliunit_to_index(const struct bcl_device *bcl, + int val, + enum bcl_channel type) +{ + const struct bcl_desc *desc = bcl->desc; + const struct bcl_channel_cfg *cfg = &desc->channel_cfg[bcl->batt_config][type]; + u64 diff = (u64)val - cfg->base_mu; + + return DIV_ROUND_CLOSEST_ULL(diff, cfg->step_mu); +} + +/** + * bcl_convert_index_to_milliunit - Convert in or curr index to milli unit + * @bcl: BCL device structure + * @val: index value + * @type: type of the channel, in or curr + * + * Converts an index value to milli unit for BCL that use indexed thresholds. + * + * Return: Value in millivolts or milliamps + */ +static unsigned int bcl_convert_index_to_milliunit(const struct bcl_device *bcl, + int val, + enum bcl_channel type) +{ + const struct bcl_desc *desc = bcl->desc; + const struct bcl_channel_cfg *cfg = &desc->channel_cfg[bcl->batt_config][type]; + + return cfg->base_mu + val * cfg->step_mu; +} + +static int bcl_validate_threshold_fits(const struct bcl_device *bcl, + const struct reg_field *reg_field, + u32 raw_val, + long thresh, + const char *unit) +{ + unsigned int field_width; + unsigned int field_mask; + + if (WARN_ON(reg_field->msb < reg_field->lsb)) + return -EINVAL; + + field_width = reg_field->msb - reg_field->lsb + 1; + field_mask = GENMASK(field_width - 1, 0); + + if (raw_val > field_mask) { + dev_err(bcl->dev, + "Threshold value %ld %s (raw: %u) exceeds field capacity (max: %u)\n", + thresh, unit, raw_val, field_mask); + return -EINVAL; + } + + return 0; +} + +static int bcl_in_thresh_write(struct bcl_device *bcl, long value, enum bcl_limit_alarm lvl) +{ + const struct bcl_desc *desc = bcl->desc; + struct regmap_field *field = bcl->fields[F_IN_L0_THR + lvl]; + u32 raw_val; + int ret; + + int thresh = clamp_val(value, desc->channel_cfg[bcl->batt_config][CHANNEL_IN].base_mu, + desc->channel_cfg[bcl->batt_config][CHANNEL_IN].max_mu); + + if (desc->channel_cfg[bcl->batt_config][CHANNEL_IN].thresh_type[lvl] == THRESH_TYPE_ADC) + raw_val = bcl_convert_milliunit_to_raw(bcl, thresh, CHANNEL_IN, + desc->thresh_field_bits_size); + else + raw_val = bcl_convert_milliunit_to_index(bcl, thresh, CHANNEL_IN); + + ret = bcl_validate_threshold_fits(bcl, &desc->reg_fields[F_IN_L0_THR + lvl], + raw_val, thresh, "mV"); + if (ret) + return ret; + + return regmap_field_write(field, raw_val); +} + +static int bcl_curr_thresh_write(struct bcl_device *bcl, long value, enum bcl_limit_alarm lvl) +{ + const struct bcl_desc *desc = bcl->desc; + struct regmap_field *field = bcl->fields[F_CURR_H0_THR + lvl]; + u32 raw_val; + int ret; + + int thresh = clamp_val(value, 0, desc->channel_cfg[bcl->batt_config][CHANNEL_CURR].max_mu); + + if (desc->channel_cfg[bcl->batt_config][CHANNEL_CURR].thresh_type[lvl] == THRESH_TYPE_ADC) + raw_val = bcl_convert_milliunit_to_raw(bcl, thresh, CHANNEL_CURR, + desc->thresh_field_bits_size); + else + raw_val = bcl_convert_milliunit_to_index(bcl, thresh, CHANNEL_CURR); + + ret = bcl_validate_threshold_fits(bcl, &desc->reg_fields[F_CURR_H0_THR + lvl], + raw_val, thresh, "mA"); + if (ret) + return ret; + + return regmap_field_write(field, raw_val); +} + +static int bcl_in_thresh_read(struct bcl_device *bcl, enum bcl_limit_alarm lvl, long *out) +{ + int ret, thresh; + u32 raw_val = 0; + const struct bcl_desc *desc = bcl->desc; + + ret = regmap_field_read(bcl->fields[F_IN_L0_THR + lvl], &raw_val); + if (ret) + return ret; + + if (desc->channel_cfg[bcl->batt_config][CHANNEL_IN].thresh_type[lvl] == THRESH_TYPE_ADC) + thresh = bcl_convert_raw_to_milliunit(bcl, raw_val, CHANNEL_IN, + desc->thresh_field_bits_size); + else + thresh = bcl_convert_index_to_milliunit(bcl, raw_val, CHANNEL_IN); + + *out = thresh; + + return 0; +} + +static int bcl_curr_thresh_read(struct bcl_device *bcl, enum bcl_limit_alarm lvl, long *out) +{ + int ret, thresh; + u32 raw_val = 0; + const struct bcl_desc *desc = bcl->desc; + + ret = regmap_field_read(bcl->fields[F_CURR_H0_THR + lvl], &raw_val); + if (ret) + return ret; + + if (desc->channel_cfg[bcl->batt_config][CHANNEL_CURR].thresh_type[lvl] == THRESH_TYPE_ADC) + thresh = bcl_convert_raw_to_milliunit(bcl, raw_val, CHANNEL_CURR, + desc->thresh_field_bits_size); + else + thresh = bcl_convert_index_to_milliunit(bcl, raw_val, CHANNEL_CURR); + + *out = thresh; + + return 0; +} + +static int bcl_curr_input_read(struct bcl_device *bcl, long *out) +{ + int ret; + u32 raw_val = 0; + s32 signed_val; + const struct bcl_desc *desc = bcl->desc; + + /* Return cached value if read too soon after last update */ + if (bcl->last_curr_updated && + time_before(jiffies, bcl->last_curr_updated + HZ)) { + *out = bcl->last_curr_input; + return 0; + } + + if (desc->data_field_bits_size == 16) { + u8 buf[2]; + unsigned int reg = bcl->base + desc->reg_fields[F_CURR_INPUT].reg; + + /* + * Use a single bulk read for the LSB/MSB pair so the + * hardware returns both bytes from one bus transaction, + * avoiding a torn read if the ADC updates in between. + */ + ret = regmap_bulk_read(bcl->regmap, reg, buf, sizeof(buf)); + if (ret) + return ret; + raw_val = buf[0] | FIELD_PREP(GENMASK(15, 8), buf[1]); + } else { + ret = regmap_field_read(bcl->fields[F_CURR_INPUT], &raw_val); + if (ret) + return ret; + } + + /* + * Current ADC reading is in 2's complement form. + * Sign extend the value based on data field bit size. + */ + signed_val = sign_extend32(raw_val, desc->data_field_bits_size - 1); + + bcl->last_curr_input = + bcl_convert_raw_to_milliunit(bcl, signed_val, CHANNEL_CURR, + desc->data_field_bits_size); + bcl->last_curr_updated = jiffies; + + *out = bcl->last_curr_input; + + return 0; +} + +static int bcl_in_input_read(struct bcl_device *bcl, long *out) +{ + int ret; + u32 raw_val = 0; + const struct bcl_desc *desc = bcl->desc; + + /* Return cached value if read too soon after last update */ + if (bcl->last_in_updated && + time_before(jiffies, bcl->last_in_updated + HZ)) { + *out = bcl->last_in_input; + return 0; + } + + if (desc->data_field_bits_size == 16) { + u8 buf[2]; + unsigned int reg = bcl->base + desc->reg_fields[F_IN_INPUT].reg; + + /* + * Use a single bulk read for the LSB/MSB pair so the + * hardware returns both bytes from one bus transaction, + * avoiding a torn read if the ADC updates in between. + */ + ret = regmap_bulk_read(bcl->regmap, reg, buf, sizeof(buf)); + if (ret) + return ret; + raw_val = buf[0] | FIELD_PREP(GENMASK(15, 8), buf[1]); + } else { + ret = regmap_field_read(bcl->fields[F_IN_INPUT], &raw_val); + if (ret) + return ret; + } + + bcl->last_in_input = + bcl_convert_raw_to_milliunit(bcl, raw_val, CHANNEL_IN, + desc->data_field_bits_size); + bcl->last_in_updated = jiffies; + + *out = bcl->last_in_input; + + return 0; +} + +static int bcl_read_alarm_status(struct bcl_device *bcl, + enum bcl_limit_alarm lvl, long *status) +{ + int ret; + u32 raw_val = 0; + + ret = regmap_field_read(bcl->fields[F_LVL0_ALARM + lvl], &raw_val); + if (ret) + return ret; + + *status = raw_val; + + return 0; +} + +static unsigned int bcl_get_version_major(const struct bcl_device *bcl) +{ + u32 raw_val = 0; + + regmap_field_read(bcl->fields[F_V_MAJOR], &raw_val); + + return raw_val; +} + +static unsigned int bcl_get_version_minor(const struct bcl_device *bcl) +{ + u32 raw_val = 0; + + regmap_field_read(bcl->fields[F_V_MINOR], &raw_val); + + return raw_val; +} + +static void bcl_hwmon_notify_event(struct bcl_device *bcl, enum bcl_limit_alarm alarm) +{ + if (bcl->desc->in_mon_enabled) + hwmon_notify_event(bcl->hwmon_dev, hwmon_in, + in_lvl_to_attr_map[alarm], 0); + + if (bcl->desc->curr_mon_enabled) + hwmon_notify_event(bcl->hwmon_dev, hwmon_curr, + curr_lvl_to_attr_map[alarm], 0); +} + +static void bcl_alarm_enable_poll(struct work_struct *work) +{ + struct bcl_alarm_data *alarm = container_of(work, struct bcl_alarm_data, + alarm_poll_work.work); + struct bcl_device *bcl = (struct bcl_device *)alarm->device; + long status; + int ret; + + scoped_guard(mutex, &bcl->lock) + ret = bcl_read_alarm_status(bcl, alarm->type, &status); + + /* If read failed or shutting down, reschedule */ + if (ret || READ_ONCE(alarm->shutting_down)) { + if (!READ_ONCE(alarm->shutting_down)) + schedule_delayed_work(&alarm->alarm_poll_work, + msecs_to_jiffies(BCL_ALARM_POLLING_MS)); + return; + } + + /* Check if alarm cleared and IRQ needs re-enabling */ + scoped_guard(mutex, &alarm->a_lock) { + if (alarm->shutting_down) + return; + + if (!status && !alarm->irq_enabled) { + alarm->irq_enabled = true; + enable_irq(alarm->irq); + + if (!alarm->irq_wake_enabled && !enable_irq_wake(alarm->irq)) + alarm->irq_wake_enabled = true; + + bcl_hwmon_notify_event(bcl, alarm->type); + return; + } + } + + /* Alarm still active, reschedule polling */ + if (!READ_ONCE(alarm->shutting_down)) + schedule_delayed_work(&alarm->alarm_poll_work, + msecs_to_jiffies(BCL_ALARM_POLLING_MS)); +} + +static irqreturn_t bcl_handle_alarm(int irq, void *data) +{ + struct bcl_alarm_data *alarm = data; + struct bcl_device *bcl = (struct bcl_device *)alarm->device; + long status; + + if (READ_ONCE(alarm->shutting_down)) + return IRQ_HANDLED; + + guard(mutex)(&bcl->lock); + + if (bcl_read_alarm_status(bcl, alarm->type, &status) || !status) + return IRQ_HANDLED; + + bcl_hwmon_notify_event(bcl, alarm->type); + + guard(mutex)(&alarm->a_lock); + if (alarm->shutting_down) + return IRQ_HANDLED; + + if (alarm->irq_enabled) { + alarm->irq_enabled = false; + disable_irq_nosync(alarm->irq); + } + + if (alarm->irq_wake_enabled) { + disable_irq_wake(alarm->irq); + alarm->irq_wake_enabled = false; + } + + schedule_delayed_work(&alarm->alarm_poll_work, + msecs_to_jiffies(BCL_ALARM_POLLING_MS)); + + return IRQ_HANDLED; +} + +static umode_t bcl_hwmon_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int channel) +{ + const struct bcl_device *bcl = data; + + switch (type) { + case hwmon_in: + if (!bcl->desc->in_mon_enabled) + return 0; + + switch (attr) { + case hwmon_in_input: + return bcl->desc->in_input_enabled ? 0444 : 0; + case hwmon_in_min_alarm: + case hwmon_in_lcrit_alarm: + case hwmon_in_lemergency_alarm: + return 0444; + case hwmon_in_min: + case hwmon_in_lcrit: + case hwmon_in_lemergency: + return 0644; + default: + return 0; + } + case hwmon_curr: + if (!bcl->desc->curr_mon_enabled) + return 0; + + switch (attr) { + case hwmon_curr_input: + case hwmon_curr_max_alarm: + case hwmon_curr_crit_alarm: + case hwmon_curr_emergency_alarm: + return 0444; + case hwmon_curr_max: + case hwmon_curr_crit: + return 0644; + default: + return 0; + } + default: + return 0; + } +} + +static int bcl_hwmon_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + struct bcl_device *bcl = dev_get_drvdata(dev); + + guard(mutex)(&bcl->lock); + + switch (type) { + case hwmon_in: + switch (attr) { + case hwmon_in_min: + case hwmon_in_lcrit: + case hwmon_in_lemergency: + return bcl_in_thresh_write(bcl, val, in_attr_to_lvl_map[attr]); + default: + return -EOPNOTSUPP; + } + case hwmon_curr: + switch (attr) { + case hwmon_curr_max: + case hwmon_curr_crit: + return bcl_curr_thresh_write(bcl, val, curr_attr_to_lvl_map[attr]); + default: + return -EOPNOTSUPP; + } + default: + return -EOPNOTSUPP; + } +} + +static int bcl_in_read(struct bcl_device *bcl, u32 attr, long *value) +{ + guard(mutex)(&bcl->lock); + + switch (attr) { + case hwmon_in_input: + return bcl_in_input_read(bcl, value); + case hwmon_in_min: + case hwmon_in_lcrit: + case hwmon_in_lemergency: + return bcl_in_thresh_read(bcl, in_attr_to_lvl_map[attr], value); + case hwmon_in_min_alarm: + case hwmon_in_lcrit_alarm: + case hwmon_in_lemergency_alarm: + return bcl_read_alarm_status(bcl, in_attr_to_lvl_map[attr], value); + default: + return -EOPNOTSUPP; + } +} + +static int bcl_curr_read(struct bcl_device *bcl, u32 attr, long *value) +{ + guard(mutex)(&bcl->lock); + + switch (attr) { + case hwmon_curr_input: + return bcl_curr_input_read(bcl, value); + case hwmon_curr_max: + case hwmon_curr_crit: + return bcl_curr_thresh_read(bcl, curr_attr_to_lvl_map[attr], value); + case hwmon_curr_max_alarm: + case hwmon_curr_crit_alarm: + case hwmon_curr_emergency_alarm: + return bcl_read_alarm_status(bcl, curr_attr_to_lvl_map[attr], value); + default: + return -EOPNOTSUPP; + } +} + +static int bcl_hwmon_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *value) +{ + struct bcl_device *bcl = dev_get_drvdata(dev); + + switch (type) { + case hwmon_in: + return bcl_in_read(bcl, attr, value); + case hwmon_curr: + return bcl_curr_read(bcl, attr, value); + default: + return -EOPNOTSUPP; + } +} + +static const struct hwmon_ops bcl_hwmon_ops = { + .is_visible = bcl_hwmon_is_visible, + .read = bcl_hwmon_read, + .write = bcl_hwmon_write, +}; + +static const struct hwmon_channel_info * const bcl_hwmon_info[] = { + HWMON_CHANNEL_INFO(in, + HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_LCRIT | + HWMON_I_LEMERGENCY | + HWMON_I_MIN_ALARM | HWMON_I_LCRIT_ALARM | + HWMON_I_LEMERGENCY_ALARM), + HWMON_CHANNEL_INFO(curr, + HWMON_C_INPUT | HWMON_C_MAX | HWMON_C_CRIT | + HWMON_C_MAX_ALARM | HWMON_C_CRIT_ALARM | + HWMON_C_EMERGENCY_ALARM), + NULL +}; + +static const struct hwmon_chip_info bcl_chip_info = { + .ops = &bcl_hwmon_ops, + .info = bcl_hwmon_info, +}; + +static int bcl_detect_battery_config(struct bcl_device *bcl) +{ + u32 reg_val = 0; + int ret; + + ret = regmap_field_read(bcl->batt_config_regfield, ®_val); + if (ret) { + dev_err(bcl->dev, "Failed to read battery config register: %d\n", ret); + return ret; + } + + /* + * Map register value to battery configuration. + * As per hardware documentation: + * 0 -> 2S, 1 -> 3S, 2 -> 4S (unsupported) + */ + switch (reg_val) { + case 0: + bcl->batt_config = BCL_BATT_2S; + return 0; + case 1: + bcl->batt_config = BCL_BATT_3S; + return 0; + default: + dev_err(bcl->dev, "Unsupported battery configuration: 0x%x\n", + reg_val); + return -EINVAL; + } +} + +static int bcl_update_scaling_factors(struct bcl_device *bcl) +{ + const struct bcl_desc *desc = bcl->desc; + int ret; + + /* Check if battery detection is supported */ + if (desc->battery_config_field.reg == 0) { + /* No battery detection - use BCL_BATT_1S */ + bcl->batt_config = BCL_BATT_1S; + dev_dbg(bcl->dev, "Using default 1S battery configuration\n"); + return 0; + } + + bcl->batt_config_regfield = devm_regmap_field_alloc(bcl->dev, + bcl->regmap, + desc->battery_config_field); + if (IS_ERR(bcl->batt_config_regfield)) { + dev_err(bcl->dev, "Failed to allocate battery config regmap field\n"); + return PTR_ERR(bcl->batt_config_regfield); + } + + ret = bcl_detect_battery_config(bcl); + if (ret < 0) + return ret; + + dev_dbg(bcl->dev, + "%dS battery: BASE=%u mV,MAX=%u mV,STEP=%u mV,V_SCALE=%u nV, I_SCALE=%u nA\n", + bcl->batt_config + 1, + desc->channel_cfg[bcl->batt_config][CHANNEL_IN].base_mu, + desc->channel_cfg[bcl->batt_config][CHANNEL_IN].max_mu, + desc->channel_cfg[bcl->batt_config][CHANNEL_IN].step_mu, + desc->channel_cfg[bcl->batt_config][CHANNEL_IN].default_scale_nu, + desc->channel_cfg[bcl->batt_config][CHANNEL_CURR].default_scale_nu); + + return 0; +} + +static void bcl_alarm_work_cleanup_action(void *data) +{ + struct bcl_alarm_data *alarm = data; + + /* Set shutting_down flag to prevent work from being rescheduled */ + scoped_guard(mutex, &alarm->a_lock) + WRITE_ONCE(alarm->shutting_down, true); + + cancel_delayed_work_sync(&alarm->alarm_poll_work); +} + +static void bcl_alarm_wake_cleanup_action(void *data) +{ + struct bcl_alarm_data *alarm = data; + + guard(mutex)(&alarm->a_lock); + if (alarm->irq_wake_enabled) { + disable_irq_wake(alarm->irq); + alarm->irq_wake_enabled = false; + } +} + +static int bcl_alarm_irq_init(struct platform_device *pdev, + struct bcl_device *bcl) +{ + int ret, irq_num, i; + struct bcl_alarm_data *alarm; + + for (i = 0; i < ARRAY_SIZE(bcl->bcl_alarms); i++) { + alarm = &bcl->bcl_alarms[i]; + alarm->type = i; + alarm->device = bcl; + ret = devm_mutex_init(bcl->dev, &alarm->a_lock); + if (ret) + return ret; + + /* Initialize work before IRQ request */ + INIT_DELAYED_WORK(&alarm->alarm_poll_work, bcl_alarm_enable_poll); + + irq_num = platform_get_irq_byname(pdev, bcl_int_names[i]); + if (irq_num < 0) + return irq_num; + + alarm->irq = irq_num; + alarm->irq_enabled = true; + + ret = devm_request_threaded_irq(&pdev->dev, irq_num, NULL, + bcl_handle_alarm, IRQF_ONESHOT, + bcl_int_names[i], alarm); + if (ret) + return ret; + + /* + * Register the work cleanup action right after the IRQ is + * requested, before any other fallible step in this loop, so + * a delayed work scheduled by the IRQ handler is guaranteed to + * be canceled on teardown even if the wake cleanup registration + * below fails. Keeping it after the IRQ request also preserves + * safe devm LIFO teardown order. + */ + ret = devm_add_action_or_reset(&pdev->dev, bcl_alarm_work_cleanup_action, + alarm); + if (ret) + return ret; + + if (!enable_irq_wake(irq_num)) + alarm->irq_wake_enabled = true; + + ret = devm_add_action_or_reset(&pdev->dev, bcl_alarm_wake_cleanup_action, + alarm); + if (ret) + return ret; + } + + return 0; +} + +static int bcl_regmap_field_init(struct device *dev, struct bcl_device *bcl, + const struct bcl_desc *data) +{ + struct reg_field fields[F_MAX_FIELDS]; + int i; + + /* + * Note: We use a mutable local copy of struct reg_field (not const) + * because we need to modify the .reg field to add the BCL base offset. + */ + for (i = 0; i < data->num_reg_fields; i++) { + fields[i] = data->reg_fields[i]; + fields[i].reg += bcl->base; + } + + return devm_regmap_field_bulk_alloc(dev, bcl->regmap, bcl->fields, + fields, data->num_reg_fields); +} + +static int bcl_probe(struct platform_device *pdev) +{ + struct bcl_device *bcl; + int ret; + u32 reg; + + bcl = devm_kzalloc(&pdev->dev, sizeof(*bcl), GFP_KERNEL); + if (!bcl) + return -ENOMEM; + + bcl->dev = &pdev->dev; + bcl->desc = device_get_match_data(&pdev->dev); + if (!bcl->desc) + return dev_err_probe(&pdev->dev, -EINVAL, "Failed to get device match data\n"); + + ret = devm_mutex_init(bcl->dev, &bcl->lock); + if (ret) + return ret; + + bcl->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!bcl->regmap) + return dev_err_probe(&pdev->dev, -EINVAL, "Couldn't get parent's regmap\n"); + + ret = device_property_read_u32(&pdev->dev, "reg", ®); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "Failed to read 'reg' property\n"); + + bcl->base = reg; + + ret = bcl_regmap_field_init(bcl->dev, bcl, bcl->desc); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "Unable to allocate regmap fields\n"); + + ret = regmap_field_read(bcl->fields[F_CTL_EN], ®); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "Failed to read BCL enable status\n"); + + if (!reg) + return dev_err_probe(&pdev->dev, -ENODEV, "BCL is not enabled by bootloader\n"); + + ret = bcl_update_scaling_factors(bcl); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "Failed to update scaling factors\n"); + + dev_set_drvdata(&pdev->dev, bcl); + + bcl->hwmon_name = devm_hwmon_sanitize_name(&pdev->dev, + dev_name(bcl->dev)); + if (IS_ERR(bcl->hwmon_name)) + return PTR_ERR(bcl->hwmon_name); + + bcl->hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, + bcl->hwmon_name, + bcl, + &bcl_chip_info, + NULL); + if (IS_ERR(bcl->hwmon_dev)) + return dev_err_probe(&pdev->dev, PTR_ERR(bcl->hwmon_dev), + "Failed to register hwmon device\n"); + + ret = bcl_alarm_irq_init(pdev, bcl); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "Failed to initialize alarm IRQs\n"); + + dev_dbg(&pdev->dev, "BCL hwmon device with version: %u.%u registered\n", + bcl_get_version_major(bcl), bcl_get_version_minor(bcl)); + + return 0; +} + +static const struct of_device_id bcl_match[] = { + { + .compatible = "qcom,pm7250b-bcl", + .data = &pm7250b_data, + }, { + .compatible = "qcom,pm7550-bcl", + .data = &pm8550_data, + }, { + .compatible = "qcom,pm7550ba-bcl", + .data = &pm7550ba_data, + }, { + .compatible = "qcom,pm8350c-bcl", + .data = &pm8350c_data, + }, { + .compatible = "qcom,pm8550-bcl", + .data = &pm8550_data, + }, { + .compatible = "qcom,pmh0101-bcl", + .data = &pmh0101_data, + }, { + .compatible = "qcom,pmih0108-bcl", + .data = &pmih0108_data, + }, { + .compatible = "qcom,smb2360-bcl", + .data = &smb2360_data, + }, { + .compatible = "qcom,smb2370-bcl", + .data = &smb2370_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, bcl_match); + +static struct platform_driver bcl_driver = { + .probe = bcl_probe, + .driver = { + .name = "qcom-bcl-hwmon", + .of_match_table = bcl_match, + }, +}; + +module_platform_driver(bcl_driver); + +MODULE_DESCRIPTION("Qualcomm SPMI BCL HWMON driver"); +MODULE_LICENSE("GPL"); From 15f9a7ccbfa7e9d669e83bf5efec3344b69f8732 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 17 Oct 2026 12:58:14 +0800 Subject: [PATCH 0146/1133] FROMLIST: dt-bindings: clock: qcom,sm8450-videocc: Fix clock inputs for Glymur The schema describes exactly two clock inputs for every compatible it covers, a board XO and a video AHB clock from GCC. That does not match the video clock controller found on Glymur, Nord and SM8750. Per the hardware documentation, the controller on these SoCs has three clock inputs: the board XO, the active-only board XO that feeds its PLL reference, and the 32 kHz chip sleep clock that sources its sleep clock generator. It has no AHB clock input. The AHB clock the controller uses for itself is generated inside the block from the XO input. Because the schema stops at two items, the sleep clock input cannot be described in device tree at all, and the second item is described as a clock that is not routed into the controller. Describe three inputs for the Glymur, Nord and SM8750 compatibles and keep the existing two-input description for the remaining compatibles. Assisted-by: LLM Reviewed-by: Rob Herring (Arm) Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261017045817.1506961-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- .../bindings/clock/qcom,sm8450-videocc.yaml | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml index e985a450451d5..7ed5aeb050cd2 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-videocc.yaml @@ -42,9 +42,8 @@ properties: - qcom,x1p42100-videocc clocks: - items: - - description: Board XO source - - description: Video AHB clock from GCC + minItems: 2 + maxItems: 3 power-domains: description: @@ -79,6 +78,27 @@ allOf: then: required: - required-opps + - if: + properties: + compatible: + contains: + enum: + - qcom,glymur-videocc + - qcom,nord-videocc + - qcom,sm8750-videocc + then: + properties: + clocks: + items: + - description: Board XO source + - description: Board active-only XO source + - description: Sleep clock source + else: + properties: + clocks: + items: + - description: Board XO source + - description: Video AHB clock from GCC unevaluatedProperties: false From cdc21d4bb0476c02f229a0f185ac7c1a92993a09 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 17 Oct 2026 12:58:15 +0800 Subject: [PATCH 0147/1133] FROMLIST: arm64: dts: qcom: glymur: Add videocc sleep clock The video clock controller binding describes three clock inputs for Glymur: the board XO, the active-only board XO and the 32 kHz sleep clock. The videocc node passes only the first two. Pass the board sleep clock as the third input. No functional change, the video sleep clock keeps the rate left by the bootloader and has no rate consumer. Assisted-by: LLM Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261017045817.1506961-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/glymur.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index 65a398c0a9920..b389f953f97fb 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -5810,7 +5810,8 @@ compatible = "qcom,glymur-videocc"; reg = <0x0 0x0aaf0000 0x0 0x10000>; clocks = <&rpmhcc RPMH_CXO_CLK>, - <&rpmhcc RPMH_CXO_CLK_A>; + <&rpmhcc RPMH_CXO_CLK_A>, + <&sleep_clk>; power-domains = <&rpmhpd RPMHPD_MMCX>, <&rpmhpd RPMHPD_MXC>; From 5484b37f9c1dcb6297cc0ae225f69016a19ab6b8 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 17 Oct 2026 12:58:16 +0800 Subject: [PATCH 0148/1133] FROMLIST: arm64: dts: qcom: sm8750: Fix videocc clock inputs The video clock controller binding describes three clock inputs for SM8750: the board XO, the active-only board XO and the 32 kHz sleep clock. The videocc node instead passes the board XO and GCC_VIDEO_AHB_CLK, which is not an input of the controller. Pass bi_tcxo_ao_div2 and the board sleep clock in place of the AHB clock. No functional change, GCC_VIDEO_AHB_CLK is enabled independently of this node. Assisted-by: LLM Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261017045817.1506961-4-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index cf947acc57602..678e6e167bde6 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -3338,7 +3338,8 @@ compatible = "qcom,sm8750-videocc"; reg = <0x0 0x0aaf0000 0x0 0x10000>; clocks = <&bi_tcxo_div2>, - <&gcc GCC_VIDEO_AHB_CLK>; + <&bi_tcxo_ao_div2>, + <&sleep_clk>; power-domains = <&rpmhpd RPMHPD_MMCX>, <&rpmhpd RPMHPD_MXC>; required-opps = <&rpmhpd_opp_low_svs>, From 0128ea200837ea6b1aa2377350edb048dba5c49a Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 17 Oct 2026 12:58:17 +0800 Subject: [PATCH 0149/1133] FROMLIST: arm64: dts: qcom: nord: Fix videocc clock inputs The video clock controller binding describes three clock inputs for Nord: the board XO, the active-only board XO and the 32 kHz sleep clock. The videocc node instead passes the board XO and NW_GCC_VIDEO_AHB_CLK, which is not an input of the controller. Pass bi_tcxo_ao_div2 and the board sleep clock in place of the AHB clock. No functional change, NW_GCC_VIDEO_AHB_CLK is kept always on by the NW GCC driver. Assisted-by: LLM Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Tested-by: Bartosz Golaszewski Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261017045817.1506961-5-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 1ab7d9bc3cfed..62d14be558392 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -886,7 +886,8 @@ compatible = "qcom,nord-videocc"; reg = <0x0 0x0aaf0000 0x0 0x10000>; clocks = <&bi_tcxo_div2>, - <&nwgcc NW_GCC_VIDEO_AHB_CLK>; + <&bi_tcxo_ao_div2>, + <&sleep_clk>; power-domains = <&rpmhpd RPMHPD_MMCX>, <&rpmhpd RPMHPD_MXC>; required-opps = <&rpmhpd_opp_low_svs>, From 38e2daf4bfd3afbc822e2ebf6ea95fbbf8342a16 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 24 Sep 2026 14:10:03 +0200 Subject: [PATCH 0150/1133] FROMLIST: arm64: dts: qcom: nord: add GPI DMA controller nodes Add GPI DMA controller nodes for all three QUPv3 engines. Signed-off-by: Bartosz Golaszewski Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Reviewed-by: Mukesh Kumar Savaliya Link: https://lore.kernel.org/r/20260924-nord-gpi-dts-v3-1-74a85134699f@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/nord.dtsi | 64 ++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index fdbe290350ddd..8f189dc259d1e 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -3,6 +3,7 @@ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ +#include #include / { @@ -914,6 +915,27 @@ dma-ranges = <0 0 0 0 0x10 0>; ranges = <0 0 0 0 0x10 0>; + gpi_dma2: dma-controller@800000 { + compatible = "qcom,nord-gpi-dma", "qcom,sm6350-gpi-dma"; + reg = <0x0 0x00800000 0x0 0x60000>; + #dma-cells = <3>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + dma-channels = <12>; + dma-channel-mask = <0xfff>; + iommus = <&apps_smmu_0 0x15b6 0x0>; + }; + qupv3_2: geniqup@8c0000 { compatible = "qcom,geni-se-qup"; reg = <0x0 0x008c0000 0x0 0x2000>; @@ -1112,6 +1134,27 @@ }; }; + gpi_dma0: dma-controller@900000 { + compatible = "qcom,nord-gpi-dma", "qcom,sm6350-gpi-dma"; + reg = <0x0 0x00900000 0x0 0x60000>; + #dma-cells = <3>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + dma-channels = <12>; + dma-channel-mask = <0xfff>; + iommus = <&apps_smmu_2 0x1016 0x0>; + }; + qupv3_0: geniqup@9c0000 { compatible = "qcom,geni-se-qup"; reg = <0x0 0x009c0000 0x0 0x2000>; @@ -1283,6 +1326,27 @@ }; }; + gpi_dma1: dma-controller@a00000 { + compatible = "qcom,nord-gpi-dma", "qcom,sm6350-gpi-dma"; + reg = <0x0 0x00a00000 0x0 0x60000>; + #dma-cells = <3>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + dma-channels = <12>; + dma-channel-mask = <0xfff>; + iommus = <&apps_smmu_2 0x1056 0x0>; + }; + qupv3_1: geniqup@ac0000 { compatible = "qcom,geni-se-qup"; reg = <0x0 0x00ac0000 0x0 0x2000>; From f7de90ae94828090b1c1d6e61928baffc5f5958c Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 24 Sep 2026 14:10:04 +0200 Subject: [PATCH 0151/1133] FROMLIST: arm64: dts: qcom: nord: wire up GPI DMA for QUP I2C/SPI engines Add DMA phandles to I2C and SPI QUPv3 serial engine nodes. Signed-off-by: Bartosz Golaszewski Reviewed-by: Abel Vesa Reviewed-by: Shawn Guo Link: https://lore.kernel.org/r/20260924-nord-gpi-dts-v3-2-74a85134699f@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/nord.dtsi | 124 +++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 8f189dc259d1e..b5f2d3c0d069b 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -949,6 +949,10 @@ reg = <0x0 0x00880000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma2 0 0 QCOM_GPI_I2C>, + <&gpi_dma2 1 0 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -976,6 +980,10 @@ reg = <0x0 0x00884000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma2 0 1 QCOM_GPI_I2C>, + <&gpi_dma2 1 1 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1003,6 +1011,10 @@ reg = <0x0 0x00888000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma2 0 2 QCOM_GPI_I2C>, + <&gpi_dma2 1 2 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1030,6 +1042,10 @@ reg = <0x0 0x0088c000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma2 0 3 QCOM_GPI_I2C>, + <&gpi_dma2 1 3 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1057,6 +1073,10 @@ reg = <0x0 0x00890000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma2 0 4 QCOM_GPI_I2C>, + <&gpi_dma2 1 4 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1084,6 +1104,10 @@ reg = <0x0 0x00894000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma2 0 5 QCOM_GPI_I2C>, + <&gpi_dma2 1 5 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1111,6 +1135,10 @@ reg = <0x0 0x00898000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma2 0 6 QCOM_GPI_I2C>, + <&gpi_dma2 1 6 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1122,6 +1150,10 @@ reg = <0x0 0x00898000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma2 0 6 QCOM_GPI_SPI>, + <&gpi_dma2 1 6 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + status = "disabled"; }; @@ -1168,6 +1200,10 @@ reg = <0x0 0x00980000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>, + <&gpi_dma0 1 0 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1179,6 +1215,10 @@ reg = <0x0 0x00980000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma0 0 0 QCOM_GPI_SPI>, + <&gpi_dma0 1 0 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + status = "disabled"; }; @@ -1195,6 +1235,10 @@ reg = <0x0 0x00984000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>, + <&gpi_dma0 1 1 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1206,6 +1250,10 @@ reg = <0x0 0x00984000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma0 0 1 QCOM_GPI_SPI>, + <&gpi_dma0 1 1 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + status = "disabled"; }; @@ -1222,6 +1270,10 @@ reg = <0x0 0x00988000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>, + <&gpi_dma0 1 2 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1233,6 +1285,10 @@ reg = <0x0 0x00988000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma0 0 2 QCOM_GPI_SPI>, + <&gpi_dma0 1 2 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + status = "disabled"; }; @@ -1249,6 +1305,10 @@ reg = <0x0 0x0098c000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma0 0 3 QCOM_GPI_I2C>, + <&gpi_dma0 1 3 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1260,6 +1320,10 @@ reg = <0x0 0x0098c000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma0 0 3 QCOM_GPI_SPI>, + <&gpi_dma0 1 3 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + status = "disabled"; }; @@ -1276,6 +1340,10 @@ reg = <0x0 0x00990000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma0 0 4 QCOM_GPI_I2C>, + <&gpi_dma0 1 4 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1303,6 +1371,10 @@ reg = <0x0 0x00994000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>, + <&gpi_dma0 1 5 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1314,6 +1386,10 @@ reg = <0x0 0x00994000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma0 0 5 QCOM_GPI_SPI>, + <&gpi_dma0 1 5 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + status = "disabled"; }; @@ -1360,6 +1436,10 @@ reg = <0x0 0x00a80000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 0 QCOM_GPI_I2C>, + <&gpi_dma1 1 0 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1371,6 +1451,10 @@ reg = <0x0 0x00a80000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 0 QCOM_GPI_SPI>, + <&gpi_dma1 1 0 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + status = "disabled"; }; @@ -1387,6 +1471,10 @@ reg = <0x0 0x00a84000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 1 QCOM_GPI_I2C>, + <&gpi_dma1 1 1 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1398,6 +1486,10 @@ reg = <0x0 0x00a84000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 1 QCOM_GPI_SPI>, + <&gpi_dma1 1 1 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + status = "disabled"; }; @@ -1414,6 +1506,10 @@ reg = <0x0 0x00a88000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 2 QCOM_GPI_I2C>, + <&gpi_dma1 1 2 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1433,6 +1529,10 @@ reg = <0x0 0x00a8c000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 3 QCOM_GPI_I2C>, + <&gpi_dma1 1 3 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1452,6 +1552,10 @@ reg = <0x0 0x00a90000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 4 QCOM_GPI_I2C>, + <&gpi_dma1 1 4 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1463,6 +1567,10 @@ reg = <0x0 0x00a90000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 4 QCOM_GPI_SPI>, + <&gpi_dma1 1 4 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + status = "disabled"; }; @@ -1479,6 +1587,10 @@ reg = <0x0 0x00a94000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 5 QCOM_GPI_I2C>, + <&gpi_dma1 1 5 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1490,6 +1602,10 @@ reg = <0x0 0x00a94000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 5 QCOM_GPI_SPI>, + <&gpi_dma1 1 5 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + status = "disabled"; }; @@ -1506,6 +1622,10 @@ reg = <0x0 0x00a98000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 6 QCOM_GPI_I2C>, + <&gpi_dma1 1 6 QCOM_GPI_I2C>; + dma-names = "tx", "rx"; + #address-cells = <1>; #size-cells = <0>; @@ -1517,6 +1637,10 @@ reg = <0x0 0x00a98000 0x0 0x4000>; interrupts = ; + dmas = <&gpi_dma1 0 6 QCOM_GPI_SPI>, + <&gpi_dma1 1 6 QCOM_GPI_SPI>; + dma-names = "tx", "rx"; + status = "disabled"; }; From 7fb4545bf3301167ed308996719ae285d2c7534a Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Mon, 15 Jun 2026 16:26:43 +0200 Subject: [PATCH 0152/1133] firmware: qcom: pas: Expose the active PAS backend name Consumers may need to know which PAS backend is active, e.g. to decide whether SCM-specific calls apply. Add qcom_pas_get_backend() returning the active backend name (or NULL), and define QCOM_PAS_BACKEND_SCM/QCOM_PAS_BACKEND_TEE for consumers to match against. Use them in the SCM and OP-TEE backends too. Link: https://lore.kernel.org/all/20260911-video-optee-pas-v1-v1-1-7bbddaaac5ba@kernel.org/ Assisted-by: Copilot:claude-opus-4.8 Signed-off-by: Jorge Ramirez-Ortiz Co-developed-by: Sumit Garg Signed-off-by: Sumit Garg --- drivers/firmware/qcom/qcom_pas.c | 8 ++++++++ drivers/firmware/qcom/qcom_pas_tee.c | 2 +- drivers/firmware/qcom/qcom_scm.c | 2 +- include/linux/firmware/qcom/qcom_pas.h | 5 +++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/qcom/qcom_pas.c b/drivers/firmware/qcom/qcom_pas.c index 24485dd0fa10a..eb9e8ac858603 100644 --- a/drivers/firmware/qcom/qcom_pas.c +++ b/drivers/firmware/qcom/qcom_pas.c @@ -253,6 +253,14 @@ bool qcom_pas_supported(u32 pas_id) } EXPORT_SYMBOL_GPL(qcom_pas_supported); +const char *qcom_pas_get_backend(void) +{ + struct qcom_pas_ops *ops = ops_ptr; + + return ops ? ops->drv_name : NULL; +} +EXPORT_SYMBOL_GPL(qcom_pas_get_backend); + /** * qcom_pas_is_available() - Check if the peripheral authentication service is * available. Note that it is mandatory for any PAS diff --git a/drivers/firmware/qcom/qcom_pas_tee.c b/drivers/firmware/qcom/qcom_pas_tee.c index ac33a00687aa1..397f11aea3b4e 100644 --- a/drivers/firmware/qcom/qcom_pas_tee.c +++ b/drivers/firmware/qcom/qcom_pas_tee.c @@ -396,7 +396,7 @@ static void qcom_pas_tee_metadata_release(struct device *dev, } static struct qcom_pas_ops qcom_pas_ops_tee = { - .drv_name = "qcom-pas-tee", + .drv_name = QCOM_PAS_BACKEND_TEE, .supported = qcom_pas_tee_supported, .init_image = qcom_pas_tee_init_image, .mem_setup = qcom_pas_tee_mem_setup, diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 43e250faea75a..a7e6ea2847319 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -982,7 +982,7 @@ static bool qcom_scm_pas_supported(struct device *dev, u32 pas_id) } static struct qcom_pas_ops qcom_pas_ops_scm = { - .drv_name = "qcom_scm", + .drv_name = QCOM_PAS_BACKEND_SCM, .supported = qcom_scm_pas_supported, .init_image = qcom_scm_pas_init_image, .mem_setup = qcom_scm_pas_mem_setup, diff --git a/include/linux/firmware/qcom/qcom_pas.h b/include/linux/firmware/qcom/qcom_pas.h index fb2ec3be6a169..6e23b806259fc 100644 --- a/include/linux/firmware/qcom/qcom_pas.h +++ b/include/linux/firmware/qcom/qcom_pas.h @@ -13,6 +13,10 @@ #include #include +/* Names reported by qcom_pas_get_backend() for the active PAS backend. */ +#define QCOM_PAS_BACKEND_SCM "qcom_scm" +#define QCOM_PAS_BACKEND_TEE "qcom-pas-tee" + struct qcom_pas_context { struct device *dev; u32 pas_id; @@ -34,6 +38,7 @@ static inline void __iomem *qcom_pas_ctx_map(struct qcom_pas_context *ctx) return ptr; } +const char *qcom_pas_get_backend(void); bool qcom_pas_is_available(void); struct qcom_pas_context *devm_qcom_pas_context_alloc(struct device *dev, u32 pas_id, From 6c0433249d6f06d5a3ff3b2e1936d35b145b548f Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Tue, 6 Oct 2026 08:41:49 +0200 Subject: [PATCH 0153/1133] firmware: qcom: pas_tee: handle a NULL resource table Stopping a remote processor clears its cached resource table pointer but leaves the size set. On restart, qcom_pas_tee_get_rsc_table() copies from NULL when the firmware has no resource table: pc : __pi_memcpy_generic+0x110/0x22c lr : qcom_pas_tee_get_rsc_table+0xf0/0x244 Zero the input size when the table is NULL so the copy is skipped. Fixes: b6f7978da0c4 ("firmware: qcom: Add a PAS TEE service") Signed-off-by: Jorge Ramirez-Ortiz Tested-by: Harshal Dev on Shikra Reviewed-by: Sumit Garg --- drivers/firmware/qcom/qcom_pas_tee.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/qcom_pas_tee.c b/drivers/firmware/qcom/qcom_pas_tee.c index 397f11aea3b4e..c4309301a337b 100644 --- a/drivers/firmware/qcom/qcom_pas_tee.c +++ b/drivers/firmware/qcom/qcom_pas_tee.c @@ -230,12 +230,15 @@ static void *qcom_pas_tee_get_rsc_table(struct device *dev, }, [1] = { .attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT, - .u.memref.size = input_rt_size, } }; void *rt_buf = NULL; int ret; + if (!input_rt) + input_rt_size = 0; + param[1].u.memref.size = input_rt_size; + ret = tee_client_invoke_func(data->ctx, &inv_arg, param); if (ret < 0 || inv_arg.ret != 0) { dev_err(dev, "PAS get RT failed, pas_id: %d, ret: %d, err: 0x%x\n", From 05847a1a2cdfbcf69d336cb7d417337e1953415a Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 01:53:15 +0530 Subject: [PATCH 0154/1133] FROMLIST: dt-bindings: net: qcom,ethqos: add qcom,shikra-ethqos compatible Shikra's EMAC requires two additional clocks for NOC interconnect access (axi-noc, pcie-tile-axi-noc) beyond the standard four, and an OPP table with required-opps to vote VDD_CX to SVS when the NOC clocks are enabled. Add qcom,shikra-ethqos to the compatible enum and use an if/else block to constrain Shikra to exactly six clocks and require operating-points-v2, while leaving existing compatibles unchanged. Add the relevant compatible to the binding document for snps,dwmac as well. Link: https://lore.kernel.org/netdev/20260908-shikra_ethernet-v2-3-bbe3389d0652@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../devicetree/bindings/net/qcom,ethqos.yaml | 50 +++++++++++++++++-- .../devicetree/bindings/net/snps,dwmac.yaml | 2 + 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml index ef520f8105773..6b40ad4b4a817 100644 --- a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml +++ b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml @@ -14,9 +14,6 @@ description: dwmmac based Qualcomm ethernet devices which support Gigabit ethernet (version v2.3.0 and onwards). -allOf: - - $ref: snps,dwmac.yaml# - properties: compatible: oneOf: @@ -32,6 +29,7 @@ properties: - qcom,qcs404-ethqos - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos + - qcom,shikra-ethqos - qcom,sm8150-ethqos reg: @@ -57,9 +55,11 @@ properties: - const: sfty clocks: - maxItems: 4 + minItems: 4 + maxItems: 6 clock-names: + minItems: 4 items: - const: stmmaceth - const: pclk @@ -67,6 +67,8 @@ properties: - enum: - rgmii - phyaux + - const: axi-noc + - const: pcie-tile-axi-noc iommus: maxItems: 1 @@ -81,6 +83,11 @@ properties: - const: cpu-mac - const: mac-mem + operating-points-v2: true + + opp-table: + type: object + phys: true phy-names: @@ -95,6 +102,41 @@ required: - clock-names - reg-names +allOf: + - $ref: snps,dwmac.yaml# + + - if: + properties: + compatible: + contains: + const: qcom,shikra-ethqos + then: + properties: + clocks: + minItems: 6 + clock-names: + items: + - const: stmmaceth + - const: pclk + - const: ptp_ref + - const: rgmii + - const: axi-noc + - const: pcie-tile-axi-noc + required: + - operating-points-v2 + else: + properties: + clocks: + maxItems: 4 + clock-names: + items: + - const: stmmaceth + - const: pclk + - const: ptp_ref + - enum: + - rgmii + - phyaux + unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml index 2c4842404bf67..6dd64d46291bb 100644 --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml @@ -76,6 +76,7 @@ properties: - qcom,sa8255p-ethqos - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos + - qcom,shikra-ethqos - qcom,sm8150-ethqos - renesas,r9a06g032-gmac - renesas,r9a08g046-gbeth @@ -588,6 +589,7 @@ allOf: - qcom,sa8255p-ethqos - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos + - qcom,shikra-ethqos - qcom,sm8150-ethqos - snps,dwmac-4.00 - snps,dwmac-4.10a From 4f4949a3bfc9609b0ebe318933f7e27323f75d3d Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 01:53:16 +0530 Subject: [PATCH 0155/1133] FROMLIST: net: stmmac: qcom-ethqos: convert ethqos_rgmii_macro_init() to void The return value is never checked by its sole caller and the speed validation duplicates a check higher up the call stack. Convert to void and remove the dead code. Link: https://lore.kernel.org/netdev/20260908-shikra_ethernet-v2-4-bbe3389d0652@oss.qualcomm.com/ Reviewed-by: Maxime Chevallier Signed-off-by: Mohd Ayaan Anwar --- .../net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index d59be76a20916..c965c2d0c67de 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -411,9 +411,8 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) return 0; } -static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) +static void ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) { - struct device *dev = ðqos->pdev->dev; unsigned int prg_rclk_dly, loopback; unsigned int phase_shift; @@ -424,11 +423,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) /* Select RGMII, write 0 to interface select */ rgmii_clrmask(ethqos, RGMII_CONFIG_INTF_SEL, RGMII_IO_MACRO_CONFIG); - if (speed != SPEED_1000 && speed != SPEED_100 && speed != SPEED_10) { - dev_err(dev, "Invalid speed %d\n", speed); - return -EINVAL; - } - rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); if (speed == SPEED_1000) { @@ -519,8 +513,6 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, loopback, RGMII_IO_MACRO_CONFIG); - - return 0; } static void ethqos_fix_mac_speed_rgmii(void *bsp_priv, From 8ad9270e41c131962e9e02639911ab6d185d4eea Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Sat, 10 Oct 2026 15:28:22 +0800 Subject: [PATCH 0156/1133] FROMLIST: arm64: dts: qcom: nord: Add adreno SMMU nodes Add the Adreno GPU SMMMUs (MMU-500) for both GPU instances. Wire up the gpucc clock and power domain on both adreno SMMU nodes in nord-embedded.dtsi for embedded Nord variants where gpucc is available. Signed-off-by: Bibek Kumar Patro Reviewed-by: Bartosz Golaszewski Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20261010072823.3952417-1-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 13 ++++ arch/arm64/boot/dts/qcom/nord.dtsi | 74 +++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 62d14be558392..72e93552de247 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,18 @@ }; }; +&adreno_smmu_0 { + clocks = <&gpucc GPU_CC_GPU_SMMU_VOTE_CLK>; + clock-names = "hlos"; + power-domains = <&gpucc GPU_CC_CX_GDSC>; +}; + +&adreno_smmu_1 { + clocks = <&gpu2cc GPU_2_CC_GPU_SMMU_VOTE_CLK>; + clock-names = "hlos"; + power-domains = <&gpu2cc GPU_2_CC_CX_GDSC>; +}; + &crypto { interconnects = <&aggre1_noc_tile MASTER_CRYPTO_CORE0 QCOM_ICC_TAG_ALWAYS &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index b5f2d3c0d069b..6aa7815d72cbc 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -1711,6 +1711,80 @@ reg = <0x0 0x01f60000 0x0 0xa0000>; }; + adreno_smmu_0: iommu@3da0000 { + compatible = "qcom,nord-smmu-500", + "qcom,adreno-smmu", + "qcom,smmu-500", + "arm,mmu-500"; + reg = <0x0 0x03da0000 0x0 0x40000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + dma-coherent; + }; + + adreno_smmu_1: iommu@98a0000 { + compatible = "qcom,nord-smmu-500", + "qcom,adreno-smmu", + "qcom,smmu-500", + "arm,mmu-500"; + reg = <0x0 0x098a0000 0x0 0x40000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + dma-coherent; + }; + pdc: interrupt-controller@b220000 { compatible = "qcom,nord-pdc", "qcom,pdc"; From 688bbdd443807abcbb98f22878c52909d85e3086 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Thu, 24 Sep 2026 15:32:21 +0800 Subject: [PATCH 0157/1133] FROMLIST: dt-bindings: interconnect: qcom-bwmon: add nord cpu-bwmon compatible Document the qcom,nord-cpu-bwmon fallback compatible used by the CPU bandwidth monitors on Nord. Signed-off-by: Zhangfei Gao Acked-by: Krzysztof Kozlowski Acked-by: Georgi Djakov Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260924073222.1000666-2-shengchao.guo@oss.qualcomm.com --- .../devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml index f6969910bded9..3db61c38e2e73 100644 --- a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml +++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml @@ -30,6 +30,7 @@ properties: - qcom,hawi-cpu-bwmon - qcom,kaanapali-cpu-bwmon - qcom,maili-cpu-bwmon + - qcom,nord-cpu-bwmon - qcom,qcm2290-cpu-bwmon - qcom,qcs615-cpu-bwmon - qcom,qcs8300-cpu-bwmon From 125cfbbdb4a94a8024244a7573acd56a00bb17ab Mon Sep 17 00:00:00 2001 From: Pushpendra Singh Date: Thu, 24 Sep 2026 15:32:22 +0800 Subject: [PATCH 0158/1133] FROMLIST: arm64: dts: qcom: nord: Add bwmon node for Nord Add BWMON nodes and associated OPP tables to enable dynamic DDR/LLCC frequency scaling. The compatible is added in nord-embedded.dtsi rather than nord.dtsi, because Embedded variant specific 'interconnects' is required by the compatible. Co-developed-by: Zhangfei Gao Signed-off-by: Zhangfei Gao Signed-off-by: Pushpendra Singh Reviewed-by: Bartosz Golaszewski Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260924073222.1000666-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 21 +++++++ arch/arm64/boot/dts/qcom/nord.dtsi | 67 +++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 72e93552de247..6ccdeda5029cd 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -47,6 +47,27 @@ power-domains = <&gpu2cc GPU_2_CC_CX_GDSC>; }; +&bwmon_cluster0 { + compatible = "qcom,nord-cpu-bwmon", + "qcom,sdm845-bwmon"; + interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>; +}; + +&bwmon_cluster1 { + compatible = "qcom,nord-cpu-bwmon", + "qcom,sdm845-bwmon"; + interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>; +}; + +&bwmon_cluster2 { + compatible = "qcom,nord-cpu-bwmon", + "qcom,sdm845-bwmon"; + interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>; +}; + &crypto { interconnects = <&aggre1_noc_tile MASTER_CRYPTO_CORE0 QCOM_ICC_TAG_ALWAYS &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 6aa7815d72cbc..720d0b4504753 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -1653,6 +1653,73 @@ }; }; + bwmon_cluster2: pmu@1014400 { + reg = <0x0 0x01014400 0x0 0x500>; + interrupts = ; + operating-points-v2 = <&bwmon_cluster_opp_table>; + }; + + bwmon_cluster1: pmu@1015400 { + reg = <0x0 0x01015400 0x0 0x500>; + interrupts = ; + operating-points-v2 = <&bwmon_cluster_opp_table>; + }; + + bwmon_cluster0: pmu@1016400 { + reg = <0x0 0x01016400 0x0 0x500>; + interrupts = ; + + operating-points-v2 = <&bwmon_cluster_opp_table>; + + bwmon_cluster_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-0 { + opp-peak-kBps = <800000>; + }; + + opp-1 { + opp-peak-kBps = <2188800>; + }; + + opp-2 { + opp-peak-kBps = <5414400>; + }; + + opp-3 { + opp-peak-kBps = <6220800>; + }; + + opp-4 { + opp-peak-kBps = <6835200>; + }; + + opp-5 { + opp-peak-kBps = <7603200>; + }; + + opp-6 { + opp-peak-kBps = <8371200>; + }; + + opp-7 { + opp-peak-kBps = <9657600>; + }; + + opp-8 { + opp-peak-kBps = <10944000>; + }; + + opp-9 { + opp-peak-kBps = <12748800>; + }; + + opp-10 { + opp-peak-kBps = <14745600>; + }; + }; + }; + rng: rng@10c3000 { compatible = "qcom,nord-trng", "qcom,trng"; From 1364f3d30a440e39dfdff6cea58e01249616f42a Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Mon, 1 Jun 2026 16:59:22 +0800 Subject: [PATCH 0159/1133] FROMLIST: arm64: dts: qcom: kaanapali: add reboot-mode support Add PSCI SYSTEM_RESET2 reboot-modes for kaanapali-mtp and kaanapali-qrd for use by the psci-reboot-mode driver. The following modes are defined: - bootloader: reboot into fastboot mode for fastboot flashing. - edl: reboot into emergency download mode for image loading via the Firehose protocol. Link: https://lore.kernel.org/all/20260529-psci_sys_reset-dt-changes-for-pakala-v1-2-7c32161cf50b@oss.qualcomm.com/ Signed-off-by: Xin Liu Signed-off-by: Anurag Pateriya --- arch/arm64/boot/dts/qcom/kaanapali-mtp.dts | 7 +++++++ arch/arm64/boot/dts/qcom/kaanapali-qrd.dts | 7 +++++++ arch/arm64/boot/dts/qcom/kaanapali.dtsi | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts index 9eb02fd09dab6..c21f4edb0d18c 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts @@ -1113,6 +1113,13 @@ status = "okay"; }; +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; + &remoteproc_adsp { firmware-name = "qcom/kaanapali/adsp.mbn", "qcom/kaanapali/adsp_dtb.mbn"; diff --git a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts index f6b02223f4dfb..842a8b7f1d846 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts @@ -806,6 +806,13 @@ status = "okay"; }; +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; + &sdhc_2 { cd-gpios = <&tlmm 55 GPIO_ACTIVE_LOW>; diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index e48a179d07220..8f5b56c34c814 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -267,7 +267,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; From e5b9eb2ccefc56f797f6062aa8fae25f3e58b7ab Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:36:45 -0700 Subject: [PATCH 0160/1133] FROMLIST: arm64: dts: qcom: kaanapali: Add camss node Add node for the Kaanapali camera subsystem. Link: https://lore.kernel.org/all/20260508-knp-camera-v1-1-a18e289163fd@oss.qualcomm.com/ Signed-off-by: Hangxiang Ma --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 201 ++++++++++++++++++++++++ 1 file changed, 201 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 8f5b56c34c814..c547ec969f515 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -3597,6 +3597,207 @@ }; }; + camss: isp@9253000 { + compatible = "qcom,kaanapali-camss"; + + reg = <0x0 0x09253000 0x0 0x5e80>, + <0x0 0x09263000 0x0 0x5e80>, + <0x0 0x09273000 0x0 0x5e80>, + <0x0 0x092d3000 0x0 0x3880>, + <0x0 0x092e7000 0x0 0x3880>, + <0x0 0x09523000 0x0 0x2000>, + <0x0 0x09525000 0x0 0x2000>, + <0x0 0x09527000 0x0 0x2000>, + <0x0 0x09529000 0x0 0x2000>, + <0x0 0x0952b000 0x0 0x2000>, + <0x0 0x0952d000 0x0 0x2000>, + <0x0 0x093fd000 0x0 0x400>, + <0x0 0x093fe000 0x0 0x400>, + <0x0 0x093ff000 0x0 0x400>, + <0x0 0x09151000 0x0 0x20000>, + <0x0 0x09171000 0x0 0x20000>, + <0x0 0x09191000 0x0 0x20000>, + <0x0 0x092dc000 0x0 0x1300>, + <0x0 0x092f0000 0x0 0x1300>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + + port@1 { + reg = <1>; + }; + + port@2 { + reg = <2>; + }; + + port@3 { + reg = <3>; + }; + + port@4 { + reg = <4>; + }; + + port@5 { + reg = <5>; + }; + }; + }; + camcc: clock-controller@956d000 { compatible = "qcom,kaanapali-camcc"; reg = <0x0 0x0956d000 0x0 0x80000>; From de653acbae1e5fe3c03b381eeb782f2cb2a33b21 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:36:46 -0700 Subject: [PATCH 0161/1133] FROMLIST: arm64: dts: qcom: kaanapali: Add CCI definitions Qualcomm Kaanapali SoC has three Camera Control Interface (CCI). Each controller contains two I2C hosts. Reviewed-by: Vladimir Zapolskiy Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-knp-camera-v1-2-a18e289163fd@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 282 ++++++++++++++++++++++++ 1 file changed, 282 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index c547ec969f515..7aa635cf2f7da 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -3798,6 +3798,96 @@ }; }; + cci0: cci@941b000 { + compatible = "qcom,kaanapali-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941b000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci0_0_default &cci0_1_default>; + pinctrl-1 = <&cci0_0_sleep &cci0_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@941c000 { + compatible = "qcom,kaanapali-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941c000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci1_0_default &cci1_1_default>; + pinctrl-1 = <&cci1_0_sleep &cci1_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci2: cci@941d000 { + compatible = "qcom,kaanapali-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941d000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci2_0_default &cci2_1_default>; + pinctrl-1 = <&cci2_0_sleep &cci2_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci2_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci2_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + camcc: clock-controller@956d000 { compatible = "qcom,kaanapali-camcc"; reg = <0x0 0x0956d000 0x0 0x80000>; @@ -4358,6 +4448,198 @@ #interrupt-cells = <2>; wakeup-parent = <&pdc>; + cci0_0_default: cci0-0-default-state { + sda-pins { + pins = "gpio109"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio110"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_0_sleep: cci0-0-sleep-state { + sda-pins { + pins = "gpio109"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio110"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci0_1_default: cci0-1-default-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio112"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_1_sleep: cci0-1-sleep-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio112"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_0_default: cci1-0-default-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_0_sleep: cci1-0-sleep-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_1_default: cci1-1-default-state { + sda-pins { + pins = "gpio107"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio160"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_1_sleep: cci1-1-sleep-state { + sda-pins { + pins = "gpio107"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio160"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_0_default: cci2-0-default-state { + sda-pins { + pins = "gpio108"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio149"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_0_sleep: cci2-0-sleep-state { + sda-pins { + pins = "gpio108"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio149"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_1_default: cci2-1-default-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_1_sleep: cci2-1-sleep-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + hub_i2c0_data_clk: hub-i2c0-data-clk-state { /* SDA, SCL */ pins = "gpio66", "gpio67"; From 9fab68e6bb70cb6a24471dcb35ae0c99a1f6b773 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:36:47 -0700 Subject: [PATCH 0162/1133] FROMLIST: arm64: dts: qcom: kaanapali: Add camera MCLK pinctrl Define pinctrl definitions to enable camera master clocks on Kaanapali. Reviewed-by: Vladimir Zapolskiy Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-knp-camera-v1-3-a18e289163fd@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 56 +++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 7aa635cf2f7da..e3c51bfd336b3 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -4448,6 +4448,62 @@ #interrupt-cells = <2>; wakeup-parent = <&pdc>; + cam0_default: cam0-default-state { + pins = "gpio89"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam1_default: cam1-default-state { + pins = "gpio90"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam2_default: cam2-default-state { + pins = "gpio91"; + function = "cam_asc_mclk2"; + drive-strength = <2>; + bias-disable; + }; + + cam3_default: cam3-default-state { + pins = "gpio92"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam4_default: cam4-default-state { + pins = "gpio93"; + function = "cam_asc_mclk4"; + drive-strength = <2>; + bias-disable; + }; + + cam5_default: cam5-default-state { + pins = "gpio94"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam6_default: cam6-default-state { + pins = "gpio95"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam7_default: cam7-default-state { + pins = "gpio96"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + cci0_0_default: cci0-0-default-state { sda-pins { pins = "gpio109"; From 9af3d79bc0f00223093324f7c780f109048df2aa Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Jul 2026 10:39:02 +0800 Subject: [PATCH 0163/1133] FROMLIST: arm64: dts: qcom: kaanapali: bind traceNoC on the platform bus The traceNoC node used the "qcom,coresight-tnoc", "arm,primecell" compatible, which places the device on the AMBA bus. To bind an AMBA device, the bus reads the peripheral and component ID registers (PID/CID) at the top of the device's register block and matches them against the primecell ID. The traceNoC exposes the CID registers, but the Component ID value returned by the hardware is 0x00000000 instead of a valid AMBA Component ID, so the match never succeeds, the AMBA probe fails, and the device is left stuck in deferred probe indefinitely. Drop the "arm,primecell" entry and use the standalone "qcom,coresight-tnoc" compatible, which binds via the platform driver by compatible string and does not rely on the component ID register at all. This lets the device probe on hardware that does not return a valid CID, while remaining an Aggregator TNOC that retains ATID functionality. Link: https://lore.kernel.org/all/20260710-fix-tracenoc-probe-issue-v6-3-41eb36fef8d9@oss.qualcomm.com/ Fixes: f73959d86c15 ("arm64: dts: qcom: kaanapali: add coresight nodes") Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index e3c51bfd336b3..2b2027c47f2e1 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -5953,7 +5953,7 @@ }; tn@111b8000 { - compatible = "qcom,coresight-tnoc", "arm,primecell"; + compatible = "qcom,coresight-tnoc"; reg = <0x0 0x111b8000 0x0 0x4200>; clocks = <&aoss_qmp>; From 11a00803b8a26f1a10818dd261fb4a9589e4223f Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Wed, 22 Jul 2026 00:00:13 +0530 Subject: [PATCH 0164/1133] FROMLIST: arm64: dts: qcom: pmih0108-kaanapali: Enable BCL sensor node Add Battery Current Limiting (BCL) hardware monitor node for pmih0108 PMIC. The BCL monitors battery voltage and current, providing hardware interrupts when configurable thresholds are violated. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20260722-qcom-bcl-hwmon-v2-8-febe2805e17b@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/pmih0108-kaanapali.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pmih0108-kaanapali.dtsi b/arch/arm64/boot/dts/qcom/pmih0108-kaanapali.dtsi index b73b0e82c3d31..67b77272b0cf9 100644 --- a/arch/arm64/boot/dts/qcom/pmih0108-kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/pmih0108-kaanapali.dtsi @@ -49,6 +49,15 @@ #thermal-sensor-cells = <0>; }; + sensor@4700 { + compatible = "qcom,pmih0108-bcl"; + reg = <0x4700>; + interrupts = <0x7 0x47 0x0 IRQ_TYPE_EDGE_RISING>, + <0x7 0x47 0x1 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "max-min", + "critical"; + }; + pmih0108_e1_gpios: gpio@8800 { compatible = "qcom,pmih0108-gpio", "qcom,spmi-gpio"; reg = <0x8800>; From a0b6ce946fbce3c7a97b2da5caf0a74493d27629 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Wed, 5 Aug 2026 03:15:01 -0700 Subject: [PATCH 0165/1133] PENDING: arm64: dts: qcom: kaanapali-mtp: Add s5kjn5 image sensor on CSIPHY2 Enable the S5KJN5 image sensor which connected to cci0_i2c1 on Kaanapali MTP. The sensor appears on CCI pins connected to the CSIPHY2 interface in four lane mode. Signed-off-by: Hangxiang Ma --- arch/arm64/boot/dts/qcom/kaanapali-mtp.dts | 56 ++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts index c21f4edb0d18c..8a5b9892918da 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts @@ -1250,6 +1250,13 @@ <119 2>, /* SoCCP */ <144 4>; /* CXM UART */ + cam2_reset: cam2-reset-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + wlan_en: wlan-en-state { pins = "gpio16"; function = "gpio"; @@ -1350,6 +1357,55 @@ }; }; +&camss { + vdd-csiphy2-0p8-supply = <&vreg_l3d_0p8>; + vdd-csiphy2-1p2-supply = <&vreg_l1d_1p2>; + + status = "okay"; + + ports { + port@2 { + csiphy2_ep: endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&s5kjn5_ep>; + }; + }; + }; +}; + +&cci0 { + status = "okay"; +}; + +&cci0_i2c1 { + camera@10 { + compatible = "samsung,s5kjn5"; + reg = <0x10>; + + reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&cam2_default &cam2_reset>; + pinctrl-names = "default"; + + clocks = <&cambistmclkcc CAM_BIST_MCLK_CC_MCLK2_CLK>; + assigned-clocks = <&cambistmclkcc CAM_BIST_MCLK_CC_MCLK2_CLK>; + assigned-clock-rates = <19200000>; + + vddio-supply = <&vreg_l2n_1p2>; + vddd-supply = <&vreg_l1m_1p0>; + vdda-supply = <&vreg_l4m_2p2>; + vdda2-supply = <&vreg_l4n_1p8>; + afvdd-supply = <&vreg_l7m_2p8>; + + port { + s5kjn5_ep: endpoint { + link-frequencies = /bits/ 64 <1248000000>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&csiphy2_ep>; + }; + }; + }; +}; + &uart7 { status = "okay"; }; From 1832d466c25d72b8812f3853d9492f7513bf22aa Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Sun, 2 Aug 2026 16:57:41 +0800 Subject: [PATCH 0166/1133] FROMLIST: arm64: dts: qcom: Add INT2_GDSC to MDSS on Kaanapali and Glymur Kaanapali (SM8750) and Glymur use two display power domains. CORE_GDSC powers the main display hardware while INT2_GDSC powers a subset of SSPP blocks (VIG2/VIG3/DMA5/DMA6). Add DISP_CC_MDSS_CORE_INT2_GDSC alongside the existing CORE_GDSC reference in the MDSS node on both platforms and provide matching power-domain-names entries for the display power domains. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260720-msm_gdsc2-v1-3-4687866d6cb0@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/glymur.dtsi | 4 +++- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index 65a398c0a9920..be888eed2e7c0 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -5400,7 +5400,9 @@ interconnect-names = "mdp0-mem", "cpu-cfg"; - power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>; + power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>, + <&dispcc DISP_CC_MDSS_CORE_INT2_GDSC>; + power-domain-names = "core", "int2"; iommus = <&apps_smmu 0x1de0 0x2>; diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 2b2027c47f2e1..84f4c4b78a600 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -3927,7 +3927,9 @@ interconnect-names = "mdp0-mem", "cpu-cfg"; - power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>; + power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>, + <&dispcc DISP_CC_MDSS_CORE_INT2_GDSC>; + power-domain-names = "core", "int2"; iommus = <&apps_smmu 0x800 0x2>; From 17f3819fe49d4a587379752a687ddf4a7aa31e55 Mon Sep 17 00:00:00 2001 From: Jia Yang Date: Fri, 24 Jul 2026 12:48:15 +0530 Subject: [PATCH 0167/1133] FROMLIST: arm64: dts: qcom: kaanapali: Enable LLCC/DDR/DDR_QOS DVFS On Qualcomm Kaanapali SoCs, the memlat governor and the mechanism for controlling the LLCC and DDR/DDR_QOS frequencies run on the CPU Control Processor (CPUCP) and are exposed via the QCOM SCMI Generic Extension protocol. Add the CPUCP mailbox, the SCMI shared-memory regions and the CPUCP SCMI instance (scmi-1) with the Qualcomm vendor protocol@80 required for the QCOM SCMI Generic Extension protocol to probe and get functional bus DVFS on Kaanapali. Signed-off-by: Jia Yang Signed-off-by: Pragnesh Papaniya Signed-off-by: Yijie Yang Link: https://lore.kernel.org/r/20260724-rfc_v8_scmi_memlat-v1-10-cb732bcff1f4@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 84f4c4b78a600..201d04219b618 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -242,6 +242,20 @@ #power-domain-cells = <1>; }; }; + + cpucp_scmi: scmi-1 { + compatible = "arm,scmi"; + mboxes = <&cpucp_mbox 0>, <&cpucp_mbox 2>; + mbox-names = "tx", "rx"; + shmem = <&cpucp_scp_lpri0>, <&cpucp_scp_lpri1>; + + #address-cells = <1>; + #size-cells = <0>; + + scmi_vendor: protocol@80 { + reg = <0x80>; + }; + }; }; clk_virt: interconnect-0 { @@ -6585,6 +6599,13 @@ #mbox-cells = <1>; }; + cpucp_mbox: mailbox@17620000 { + compatible = "qcom,kaanapali-cpucp-mbox", "qcom,x1e80100-cpucp-mbox"; + reg = <0x0 0x17620000 0x0 0x8000>, <0x0 0x18830000 0x0 0x8000>; + interrupts = ; + #mbox-cells = <1>; + }; + timer@17810000 { compatible = "arm,armv7-timer-mem"; reg = <0x0 0x17810000 0x0 0x1000>; @@ -6794,6 +6815,26 @@ }; }; + cpucp_sram: sram@1d838000 { + compatible = "mmio-sram"; + reg = <0x0 0x1d838000 0x0 0x400>; + + #address-cells = <1>; + #size-cells = <1>; + + ranges = <0x0 0x0 0x1d838000 0x400>; + + cpucp_scp_lpri0: scp-sram-section@0 { + compatible = "arm,scmi-shmem"; + reg = <0x0 0x200>; + }; + + cpucp_scp_lpri1: scp-sram-section@200 { + compatible = "arm,scmi-shmem"; + reg = <0x200 0x200>; + }; + }; + efuse@221c8000 { compatible = "qcom,kaanapali-qfprom", "qcom,qfprom"; reg = <0x0 0x221c8000 0x0 0x1000>; From 4c9145193d9a59edd07f7182f7600fbeaa845ea5 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Fri, 31 Jul 2026 23:36:20 +0530 Subject: [PATCH 0168/1133] FROMLIST: arm64: dts: qcom: kaanapali: Add ADC support for Kaanapali boards Add the ADC channels under the PMK8850 ADC node for the other PMICS on the board with ADC peripherals. This includes die temperature and VPH power channels per PMIC and channels for available system thermistors. Add thermal zones corresponding to the thermistor channels to enable temperature monitoring. Also add io-channels and io-channel-names properties to the temp_alarm nodes so that they can get temperature reading from the newly added ADC die_temp channels. Link: https://lore.kernel.org/all/20260731-pmic5_gen4_adc-v1-7-9c49b2eea6f9@oss.qualcomm.com/ Signed-off-by: Jishnu Prakash --- arch/arm64/boot/dts/qcom/kaanapali-mtp.dts | 312 +++++++++++++++++++++ arch/arm64/boot/dts/qcom/kaanapali-qrd.dts | 312 +++++++++++++++++++++ 2 files changed, 624 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts index 8a5b9892918da..2d24494dceabf 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts @@ -8,8 +8,10 @@ #include #include #include +#include #include #include "kaanapali.dtsi" +#include "qcom-adc5-gen4.h" #include "pm8010-kaanapali.dtsi" /* SPMI1: SID-12/13 */ #include "pmd8028-kaanapali.dtsi" /* SPMI1: SID-4 */ @@ -206,6 +208,152 @@ }; }; + thermal-zones { + sys-0-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX1_THM_100K_PU(0, 0)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-1-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX1_THM_100K_PU(0, 1)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-2-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX2_THM_100K_PU(0, 1)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-3-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX3_THM_100K_PU(0, 1)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-4-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX4_THM_100K_PU(0, 1)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-5-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX6_THM_100K_PU(0, 1)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-6-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX4_THM_100K_PU(1, 7)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-7-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX4_GPIO_100K_PU(1, 7)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + }; + wcd939x: audio-codec { compatible = "qcom,wcd9395-codec", "qcom,wcd9390-codec"; @@ -1032,6 +1180,14 @@ }; }; +&pmh0101_gpios { + sys_therm_5_gpio3: sys-therm-5-gpio3-state { + pins = "gpio3"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; +}; + &pmh0101_pwm { status = "okay"; @@ -1059,6 +1215,11 @@ }; }; +&pmh0101_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 1)>; + io-channel-names = "thermal"; +}; + &pmh0104_j_e1_gpios { bt_default: bt-default-state { pins = "gpio5"; @@ -1089,6 +1250,11 @@ }; }; +&pmh0110_d_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 3)>; + io-channel-names = "thermal"; +}; + &pmh0110_f_e0_gpios { sde_disp0_rst_1p2_active: sde-disp0-rst-1p2-active-state { pins = "gpio9"; @@ -1107,6 +1273,152 @@ }; }; +&pmh0110_f_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 5)>; + io-channel-names = "thermal"; +}; + +&pmh0110_g_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 6)>; + io-channel-names = "thermal"; +}; + +&pmh0110_i_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 8)>; + io-channel-names = "thermal"; +}; + +&pmih0108_e1_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(1, 7)>; + io-channel-names = "thermal"; +}; + +&pmk8850_vadc { + pinctrl-0 = <&sys_therm_5_gpio3>; + pinctrl-names = "default"; + + channel@103 { + reg = ; + label = "pmh0101_die_temp"; + }; + + channel@18e { + reg = ; + label = "pmh0101_vph_pwr"; + }; + + channel@303 { + reg = ; + label = "pmh0110_3_die_temp"; + }; + + channel@38e { + reg = ; + label = "pmh0110_3_vph_pwr"; + }; + + channel@503 { + reg = ; + label = "pmh0110_5_die_temp"; + }; + + channel@58e { + reg = ; + label = "pmh0110_5_vph_pwr"; + }; + + channel@603 { + reg = ; + label = "pmh0110_6_die_temp"; + }; + + channel@68e { + reg = ; + label = "pmh0110_6_vph_pwr"; + }; + + channel@803 { + reg = ; + label = "pmh0110_8_die_temp"; + }; + + channel@88e { + reg = ; + label = "pmh0110_8_vph_pwr"; + }; + + channel@2703 { + reg = ; + label = "pmih0108_e1_die_temp"; + }; + + channel@278e { + reg = ; + label = "pmih0108_e1_vph_pwr"; + }; + + channel@278f { + reg = ; + label = "pmih0108_e1_vbat_sns_qbg"; + }; + + channel@144 { + reg = ; + label = "pmh0101_therm_1"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@145 { + reg = ; + label = "pmh0101_therm_2"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@146 { + reg = ; + label = "pmh0101_therm_3"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@147 { + reg = ; + label = "pmh0101_therm_4"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@149 { + reg = ; + label = "pmh0101_therm_5"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@2747 { + reg = ; + label = "pmih0108_e1_therm_6"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@274d { + reg = ; + label = "pmih0108_e1_therm_7"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; +}; + &pon_resin { linux,code = ; diff --git a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts index 842a8b7f1d846..8d590e44c5b19 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts @@ -8,8 +8,10 @@ #include #include #include +#include #include #include "kaanapali.dtsi" +#include "qcom-adc5-gen4.h" #include "pm8010-kaanapali.dtsi" /* SPMI1: SID-12/13 */ #include "pmd8028-kaanapali.dtsi" /* SPMI1: SID-4 */ @@ -81,6 +83,152 @@ }; }; + thermal-zones { + sys-0-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX1_THM_100K_PU(0, 0)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-1-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX1_THM_100K_PU(0, 1)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-2-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX2_THM_100K_PU(0, 1)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-3-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX3_THM_100K_PU(0, 1)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-4-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX4_THM_100K_PU(0, 1)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-5-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX6_THM_100K_PU(0, 1)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-6-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX4_THM_100K_PU(1, 7)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-7-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX4_GPIO_100K_PU(1, 7)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + }; + pmic-glink { compatible = "qcom,kaanapali-pmic-glink", "qcom,pmic-glink"; @@ -768,6 +916,14 @@ }; }; +&pmh0101_gpios { + sys_therm_5_gpio3: sys-therm-5-gpio3-state { + pins = "gpio3"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-high-impedance; + }; +}; + &pmh0101_pwm { status = "okay"; @@ -795,11 +951,167 @@ }; }; +&pmh0101_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 1)>; + io-channel-names = "thermal"; +}; + +&pmh0110_d_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 3)>; + io-channel-names = "thermal"; +}; + +&pmh0110_f_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 5)>; + io-channel-names = "thermal"; +}; + +&pmh0110_g_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 6)>; + io-channel-names = "thermal"; +}; + +&pmh0110_i_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 8)>; + io-channel-names = "thermal"; +}; + &pmih0108_e1_eusb2_repeater { vdd18-supply = <&vreg_l15b_1p8>; vdd3-supply = <&vreg_l5b_3p1>; }; +&pmih0108_e1_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(1, 7)>; + io-channel-names = "thermal"; +}; + +&pmk8850_vadc { + pinctrl-0 = <&sys_therm_5_gpio3>; + pinctrl-names = "default"; + + channel@103 { + reg = ; + label = "pmh0101_die_temp"; + }; + + channel@18e { + reg = ; + label = "pmh0101_vph_pwr"; + }; + + channel@303 { + reg = ; + label = "pmh0110_3_die_temp"; + }; + + channel@38e { + reg = ; + label = "pmh0110_3_vph_pwr"; + }; + + channel@503 { + reg = ; + label = "pmh0110_5_die_temp"; + }; + + channel@58e { + reg = ; + label = "pmh0110_5_vph_pwr"; + }; + + channel@603 { + reg = ; + label = "pmh0110_6_die_temp"; + }; + + channel@68e { + reg = ; + label = "pmh0110_6_vph_pwr"; + }; + + channel@803 { + reg = ; + label = "pmh0110_8_die_temp"; + }; + + channel@88e { + reg = ; + label = "pmh0110_8_vph_pwr"; + }; + + channel@2703 { + reg = ; + label = "pmih0108_e1_die_temp"; + }; + + channel@278e { + reg = ; + label = "pmih0108_e1_vph_pwr"; + }; + + channel@278f { + reg = ; + label = "pmih0108_e1_vbat_sns_qbg"; + }; + + channel@144 { + reg = ; + label = "pmh0101_therm_1"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@145 { + reg = ; + label = "pmh0101_therm_2"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@146 { + reg = ; + label = "pmh0101_therm_3"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@147 { + reg = ; + label = "pmh0101_therm_4"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@149 { + reg = ; + label = "pmh0101_therm_5"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@2747 { + reg = ; + label = "pmih0108_e1_therm_6"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@274d { + reg = ; + label = "pmih0108_e1_therm_7"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; +}; + &pon_resin { linux,code = ; From 7c07d4667d47df5102dc4db6d660cedbeea388e3 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Jul 2026 16:05:29 +0800 Subject: [PATCH 0169/1133] FROMLIST: arm64: dts: qcom: kaanapali: enable ETR and CTCU devices Embedded Trace Router(ETR) is working as a DDR memory sink to collect tracing data from source device and the CTCU device serves as the control unit for the ETR device. Link: https://lore.kernel.org/all/20260714-add-etr-ctcu-for-kaanapali-v1-1-be5cd7a3c656@oss.qualcomm.com/ Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 176 ++++++++++++++++++++++++ 1 file changed, 176 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 201d04219b618..e0667e4959526 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -5276,6 +5276,35 @@ }; }; + ctcu@10001000 { + compatible = "qcom,kaanapali-ctcu", "qcom,sa8775p-ctcu"; + reg = <0x0 0x10001000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ctcu_in0: endpoint { + remote-endpoint = <&tmc_etr_out>; + }; + }; + + port@1 { + reg = <1>; + + ctcu_in1: endpoint { + remote-endpoint = <&tmc_etr1_out>; + }; + }; + }; + }; + stm@10002000 { compatible = "arm,coresight-stm", "arm,primecell"; reg = <0x0 0x10002000 0x0 0x1000>, @@ -5415,6 +5444,121 @@ }; }; + replicator@10046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10046000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_qdss_in: endpoint { + remote-endpoint = <&replicator_swao_out0>; + }; + }; + }; + + out-ports { + port { + replicator_qdss_out: endpoint { + remote-endpoint = <&replicator_etr_in>; + }; + }; + }; + }; + + tmc@10048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x10048000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x04e0 0x0>; + arm,scatter-gather; + + in-ports { + port { + tmc_etr_in: endpoint { + remote-endpoint = <&replicator_etr_out0>; + }; + }; + }; + + out-ports { + port { + tmc_etr_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator@1004e000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1004e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_etr_in: endpoint { + remote-endpoint = <&replicator_qdss_out>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + replicator_etr_out0: endpoint { + remote-endpoint = <&tmc_etr_in>; + }; + }; + + port@1 { + reg = <1>; + + replicator_etr_out1: endpoint { + remote-endpoint = <&tmc_etr1_in>; + }; + }; + }; + }; + + tmc@1004f000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1004f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x0500 0x0>; + arm,scatter-gather; + + in-ports { + port { + tmc_etr1_in: endpoint { + remote-endpoint = <&replicator_etr_out1>; + }; + }; + }; + + out-ports { + port { + tmc_etr1_out: endpoint { + remote-endpoint = <&ctcu_in1>; + }; + }; + }; + }; + tpdm@11000000 { compatible = "qcom,coresight-tpdm", "arm,primecell"; reg = <0x0 0x11000000 0x0 0x1000>; @@ -6229,6 +6373,38 @@ }; }; }; + + out-ports { + port { + tmc_etf_out: endpoint { + remote-endpoint = <&replicator_swao_in>; + }; + }; + }; + }; + + replicator@11306000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x11306000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + replicator_swao_in: endpoint { + remote-endpoint = <&tmc_etf_out>; + }; + }; + }; + + out-ports { + port { + replicator_swao_out0: endpoint { + remote-endpoint = <&replicator_qdss_in>; + }; + }; + }; }; tpda@11308000 { From a672c1a5c8a3977e4c3daebd62dc5eb54a81ab61 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 22 Sep 2026 18:35:23 +0800 Subject: [PATCH 0170/1133] FROMLIST: arm64: dts: qcom: kaanapali: Add CoreSight nodes for APSS debug block The APSS debug block is built with CoreSight devices like ETE, replicator, funnel and TMC ETF. Add dt nodes for these devices to enable ETM trace. The replicator, funnel and TMC ETF nodes in this block are physically powered by the CPU cluster power rail rather than by a dedicated always-on rail. Add a power-domains property referencing the cluster_pd domain to each of these nodes, so their power state is tied to the CPU cluster domain and the runtime PM core can power the domain on before the devices are accessed and let it be powered off otherwise. Link: https://lore.kernel.org/all/20260922-add-etm-devices-for-multiple-qcom-platforms-v1-3-c2a8c3225a2e@oss.qualcomm.com/ Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 567 ++++++++++++++++++++++++ 1 file changed, 567 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index e0667e4959526..4d93dc530268e 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -219,6 +219,110 @@ }; }; + ete-0 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu0>; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + ete-1 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu1>; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + ete-2 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu2>; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + ete-3 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu3>; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + ete-4 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu4>; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc0_4_rep_in>; + }; + }; + }; + }; + + ete-5 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu5>; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc0_5_rep_in>; + }; + }; + }; + }; + + ete-6 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu6>; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + ete-7 { + compatible = "arm,embedded-trace-extension"; + cpu = <&cpu7>; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; + firmware { scm: scm { compatible = "qcom,scm-kaanapali", "qcom,scm"; @@ -6274,6 +6378,14 @@ remote-endpoint = <&tpdm_ipcc_cmb3_out>; }; }; + + port@36 { + reg = <0x36>; + + tn_ag_in54: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; }; out-ports { @@ -6591,6 +6703,43 @@ }; }; + funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in54>; + }; + }; + }; + }; + sram@14680000 { compatible = "qcom,kaanapali-imem", "mmio-sram"; reg = <0x0 0x14680000 0x0 0x1000>; @@ -7023,6 +7172,424 @@ }; }; + funnel@1d021000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x1d021000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@1d029000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1d029000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + funnel@1d081000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x1d081000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc0_1_funnel_in4: endpoint { + remote-endpoint = <&ncc0_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc0_1_funnel_in5: endpoint { + remote-endpoint = <&ncc0_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + replicator@1d090000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d090000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d0a0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d0a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@1d0b0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d0b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@1d0c0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d0c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + replicator@1d0d0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d0d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + port { + ncc0_4_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc0_4_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in4>; + }; + }; + }; + }; + + replicator@1d0e0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d0e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + port { + ncc0_5_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc0_5_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in5>; + }; + }; + }; + }; + + funnel@1d121000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x1d121000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@1d129000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1d129000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + funnel@1d181000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x1d181000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; + }; + }; + }; + }; + + replicator@1d190000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d190000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d1a0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d1a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd>; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm7_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; + nsp_noc: interconnect@260c0000 { compatible = "qcom,kaanapali-nsp-noc"; reg = <0x0 0x260c0000 0x0 0x21280>; From 4a64cf66ea36b9dfea85b9c8a5f53ddea9aa888f Mon Sep 17 00:00:00 2001 From: Balaji Kalkonda Date: Mon, 5 Oct 2026 12:54:28 +0530 Subject: [PATCH 0171/1133] FROMLIST: arm64: dts: qcom: kaanapali: Add DisplayPort controller Add device node for the DisplayPort controller, its OPP table, clocks and power domain, and connect it to the DPU and USB/DP QMP PHY. Signed-off-by: Balaji Kalkonda Signed-off-by: Mahadevan P Link: https://lore.kernel.org/all/20261005-kaanapali_dp-v1-3-6faeac3a6d59@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 87 ++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 4d93dc530268e..a738d5ad6a8f6 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -3683,6 +3683,7 @@ #clock-cells = <1>; #phy-cells = <1>; + mode-switch; orientation-switch; status = "disabled"; @@ -3710,6 +3711,7 @@ reg = <2>; usb_dp_qmpphy_dp_in: endpoint { + remote-endpoint = <&mdss_dp0_out>; }; }; }; @@ -4110,6 +4112,7 @@ reg = <2>; dpu_intf0_out: endpoint { + remote-endpoint = <&mdss_dp0_in>; }; }; }; @@ -4262,6 +4265,86 @@ status = "disabled"; }; + + mdss_dp0: displayport-controller@9ad2000 { + compatible = "qcom,kaanapali-dp"; + reg = <0x0 0x09ad2000 0x0 0x10c>, + <0x0 0x09ad2200 0x0 0xc8>, + <0x0 0x09ad3000 0x0 0x78>, + <0x0 0x09ad4000 0x0 0xa0>; + + interrupts-extended = <&mdss 12>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_DPTX0_AUX_CLK>, + <&dispcc DISP_CC_MDSS_DPTX0_LINK_CLK>, + <&dispcc DISP_CC_MDSS_DPTX0_LINK_INTF_CLK>, + <&dispcc DISP_CC_MDSS_DPTX0_PIXEL0_CLK>; + + clock-names = "core_iface", + "core_aux", + "ctrl_link", + "ctrl_link_iface", + "stream_pixel"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_DPTX0_LINK_CLK_SRC>, + <&dispcc DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC>; + assigned-clock-parents = + <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>, + <&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>; + + operating-points-v2 = <&dp_opp_table>; + + power-domains = <&rpmhpd RPMHPD_MX>; + + phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>; + phy-names = "dp"; + + #sound-dai-cells = <0>; + + status = "disabled"; + + dp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-270000000 { + opp-hz = /bits/ 64 <270000000>; + required-opps = <&rpmhpd_opp_low_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>; + }; + }; + + 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 { + data-lanes = <0 1 2 3>; + remote-endpoint = <&usb_dp_qmpphy_dp_in>; + }; + }; + }; + }; }; dispcc: clock-controller@9ba2000 { @@ -4271,8 +4354,8 @@ <&bi_tcxo_ao_div2>, <&gcc GCC_DISP_AHB_CLK>, <&sleep_clk>, - <0>, - <0>, + <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>, + <&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>, <0>, <0>, <0>, From 110a462d6dd03d4f177a3c15c9604aa7f8e3d2a2 Mon Sep 17 00:00:00 2001 From: Balaji Kalkonda Date: Mon, 5 Oct 2026 12:54:29 +0530 Subject: [PATCH 0172/1133] BACKPORT: arm64: dts: qcom: kaanapali-mtp: Enable USB headset and Type-C accessory mode MTP does not have audio jack connected and relies on USB mux (WCD9395). Add necessary nodes for proper audio headset support along with USB Type-C accessory mode and orientation. Signed-off-by: Balaji Kalkonda [mahadevan: resolved context conflict in kaanapali-mtp.dts, placed &qup_i2c3_data_clk after &psci as &pon_resin context differs] Signed-off-by: Mahadevan P Link: https://lore.kernel.org/all/20261005-kaanapali_dp-v1-4-6faeac3a6d59@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/kaanapali-mtp.dts | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts index 2d24494dceabf..5f8849bddbf1b 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts @@ -202,6 +202,7 @@ reg = <2>; pmic_glink_sbu: endpoint { + remote-endpoint = <&wcd_usbss_sbu_mux>; }; }; }; @@ -380,6 +381,15 @@ vdd-px-supply = <&vreg_l1g_1p2>; #sound-dai-cells = <1>; + + mode-switch; + orientation-switch; + + port { + wcd_codec_headset_in: endpoint { + remote-endpoint = <&wcd_usbss_headset_out>; + }; + }; }; wcn7850-pmu { @@ -1064,6 +1074,42 @@ firmware-name = "qcom/kaanapali/gen80200_zap.mbn"; }; +&i2c3 { + status = "okay"; + + wcd_usbss: typec-mux@e { + compatible = "qcom,wcd9395-usbss", "qcom,wcd9390-usbss"; + reg = <0xe>; + + vdd-supply = <&vreg_l15b_1p8>; + reset-gpios = <&tlmm 162 GPIO_ACTIVE_HIGH>; + + mode-switch; + orientation-switch; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + wcd_usbss_sbu_mux: endpoint { + remote-endpoint = <&pmic_glink_sbu>; + }; + }; + + port@1 { + reg = <1>; + + wcd_usbss_headset_out: endpoint { + remote-endpoint = <&wcd_codec_headset_in>; + }; + }; + }; + }; +}; + &lpass_vamacro { pinctrl-0 = <&dmic01_default>, <&dmic23_default>; pinctrl-names = "default"; @@ -1432,6 +1478,11 @@ }; }; +&qup_i2c3_data_clk { + /* Use internal I2C pull-up */ + bias-pull-up = <2200>; +}; + &remoteproc_adsp { firmware-name = "qcom/kaanapali/adsp.mbn", "qcom/kaanapali/adsp_dtb.mbn"; From 5a7838decacd68dd863455b0ca95f1a59b8e4406 Mon Sep 17 00:00:00 2001 From: Balaji Kalkonda Date: Mon, 5 Oct 2026 12:54:30 +0530 Subject: [PATCH 0173/1133] FROMLIST: arm64: dts: qcom: kaanapali-mtp: Enable DisplayPort over USB Hook up DisplayPort parts over Type-C USB on MTP. Signed-off-by: Balaji Kalkonda Signed-off-by: Mahadevan P Link: https://lore.kernel.org/all/20261005-kaanapali_dp-v1-5-6faeac3a6d59@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/kaanapali-mtp.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts index 5f8849bddbf1b..bbdd621e3ab6d 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts @@ -1163,6 +1163,14 @@ status = "okay"; }; +&mdss_dp0 { + status = "okay"; +}; + +&mdss_dp0_out { + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; +}; + &pcie0 { pinctrl-0 = <&pcie0_default_state>; pinctrl-names = "default"; From a8c6c009624b273fa8820a65a8fc79cfa3c7d9a4 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 1 Oct 2026 20:47:25 +0530 Subject: [PATCH 0174/1133] FROMLIST: arm64: dts: qcom: kaanapali: add iris video node Add iris video codec to kaanapali SoC, which comes with significantly different powering up sequence than previous iris generation, thus different clocks, power domains and resets. Link: https://lore.kernel.org/all/20261001-kaanapali-iris-v4-5-642f9ac5e699@oss.qualcomm.com Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 146 ++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index a738d5ad6a8f6..990d9c860594c 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -570,6 +570,10 @@ qcom,client-id = <1>; qcom,vmid = ; }; + + iris_resv: reservation-iris { + iommu-addresses = <&iris_non_pixel 0x0 0x25800000>; + }; }; smp2p-adsp { @@ -2783,6 +2787,148 @@ #reset-cells = <1>; }; + iris: video-codec@2000000 { + compatible = "qcom,kaanapali-iris"; + reg = <0x0 0x02000000 0x0 0xf0000>; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&gcc GCC_VIDEO_AXI1_CLK>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0B_CLK>, + <&videocc VIDEO_CC_MVS0_VPP0_CLK>, + <&videocc VIDEO_CC_MVS0_VPP1_CLK>, + <&videocc VIDEO_CC_MVS0A_CLK>; + clock-names = "iface", + "core", + "vcodec0_core", + "iface1", + "core_freerun", + "vcodec0_core_freerun", + "vcodec_bse", + "vcodec_vpp0", + "vcodec_vpp1", + "vcodec_apv"; + + dma-coherent; + + 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_MVP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + interrupts = ; + + memory-region = <&video_mem>; + + operating-points-v2 = <&iris_opp_table>; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc VIDEO_CC_MVS0_VPP0_GDSC>, + <&videocc VIDEO_CC_MVS0_VPP1_GDSC>, + <&videocc VIDEO_CC_MVS0A_GDSC>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vpp0", + "vpp1", + "apv"; + + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>, + <&gcc GCC_VIDEO_AXI1_CLK_ARES>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK_ARES>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK_ARES>; + reset-names = "bus0", + "bus1", + "core", + "vcodec0_core"; + + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0x0 0xffc00000>; + + status = "disabled"; + + iris_non_pixel: non-pixel { + iommus = <&apps_smmu 0x1940 0x0>, + <&apps_smmu 0x1944 0x0>, + <&apps_smmu 0x1a20 0x0>; + memory-region = <&iris_resv>; + }; + + pixel { + iommus = <&apps_smmu 0x1943 0x0>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000 240000000 + 240000000 360000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 + 338000000 507000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-420000000 { + opp-hz = /bits/ 64 <420000000 420000000 + 420000000 630000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 + 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-533000000 { + opp-hz = /bits/ 64 <533000000 533000000 + 533000000 800000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_nom>; + }; + + opp-630000000 { + opp-hz = /bits/ 64 <630000000 630000000 + 630000000 1104000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo>; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000 630000000 + 630000000 1260000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo_l0>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000 630000000 + 850000000 1260000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo_l1>; + }; + }; + }; + videocc: clock-controller@20f0000 { compatible = "qcom,kaanapali-videocc"; reg = <0x0 0x020f0000 0x0 0x10000>; From c78520e254b7f959a52cf91cdc8b6fe6555338c6 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 1 Oct 2026 20:47:26 +0530 Subject: [PATCH 0175/1133] FROMLIST: arm64: dts: qcom: kaanapali-mtp: enable iris video node on mtp board Enable the iris video codec on the kaanapali MTP reference board. Link: https://lore.kernel.org/all/20261001-kaanapali-iris-v4-6-642f9ac5e699@oss.qualcomm.com Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia --- arch/arm64/boot/dts/qcom/kaanapali-mtp.dts | 6 ++++++ arch/arm64/boot/dts/qcom/kaanapali-qrd.dts | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts index bbdd621e3ab6d..a4be2e14c5818 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-mtp.dts @@ -1066,6 +1066,12 @@ }; }; +&iris { + firmware-name = "qcom/vpu/vpu40_p2_s7.mbn"; + + status = "okay"; +}; + &gpu { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts index 8d590e44c5b19..81435cae964ee 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts +++ b/arch/arm64/boot/dts/qcom/kaanapali-qrd.dts @@ -884,6 +884,12 @@ }; }; +&iris { + firmware-name = "qcom/vpu/vpu40_p2_s7.mbn"; + + status = "okay"; +}; + &gpu { status = "okay"; }; From 8bbedffc8d13e0659ed787d3c664173978f84aa4 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 15 Oct 2026 09:38:26 +0800 Subject: [PATCH 0176/1133] FROMLIST: remoteproc: qcom: pas: Decide early_boot attach at probe time For early_boot subsystems, probe unconditionally marks the rproc RPROC_DETACHED and qcom_pas_attach() discovers from SMP2P whether the bootloader actually started the remote. If it did not, attach sets the state back to RPROC_OFFLINE and fails, expecting the core to boot the firmware instead. The core does not do that: rproc_boot() treats the attach failure as fatal and the remote is never started. This is hit on Nord with firmware where XBL no longer brings ADSP out of reset. The remote never publishes its inbound SMP2P entries, so the very first state read fails (debug print below) and the ADSP stays down: qcom_q6v5_pas 4c00000.remoteproc: Failed to get fatal_irq state: -19 remoteproc remoteproc0: can't attach to rproc adsp: -19 The ready, stop-ack and sysmon shutdown-ack signals cannot change while Linux has not yet interacted with the remote, so there is no reason to defer the decision to attach time. Check them in probe and only mark the rproc RPROC_DETACHED when the remote is up and has not been asked to stop; otherwise leave it RPROC_OFFLINE so the regular firmware boot path is taken. The ready state is read first so that a missing SMP2P entry -ENODEV is treated as "not running" before sysmon is queried. qcom_pas_attach() keeps only the fatal check, since that is the one signal that has to be acted upon once the rproc is attached. Assisted-by: LLM Fixes: 16472c99f469 ("remoteproc: qcom: pas: Add late attach support for subsystems") Cc: stable@vger.kernel.org Reviewed-by: Stephan Gerhold Reviewed-by: Bartosz Golaszewski Acked-by: Konrad Dybcio Link: https://lore.kernel.org/r/20261015013827.716465-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- drivers/remoteproc/qcom_q6v5_pas.c | 62 +++++++++++++++--------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index f37b77ae187e9..66bc4c6f004ec 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -550,9 +550,7 @@ static unsigned long qcom_pas_panic(struct rproc *rproc) static int qcom_pas_attach(struct rproc *rproc) { struct qcom_pas *pas = rproc->priv; - bool ready_state; bool crash_state; - bool stop_state; int ret; pas->q6v5.handover_issued = true; @@ -570,40 +568,44 @@ static int qcom_pas_attach(struct rproc *rproc) goto disable_running; } - ret = irq_get_irqchip_state(pas->q6v5.stop_irq, - IRQCHIP_STATE_LINE_LEVEL, &stop_state); - if (ret) - goto disable_running; + return 0; - if (stop_state || qcom_sysmon_shutdown_irq_state(pas->sysmon)) { - dev_info(pas->dev, "Subsystem found stop state set. Falling back to start.\n"); - goto unroll_attach; - } +disable_running: + pas->q6v5.running = false; + + return ret; +} + +/* + * The bootloader may or may not have started the subsystem. Inspect the + * SMP2P state, which is static until Linux interacts with the remote, to + * decide whether to attach or to load and start the firmware. + */ +static bool qcom_pas_is_running(struct qcom_pas *pas) +{ + bool ready_state; + bool stop_state; + int ret; + /* + * Check ready first: if the remote never published its SMP2P + * entries the state read fails with -ENODEV. + */ ret = irq_get_irqchip_state(pas->q6v5.ready_irq, IRQCHIP_STATE_LINE_LEVEL, &ready_state); - if (ret) - goto disable_running; - - if (unlikely(!ready_state)) { - /* - * The bootloader may not support early boot, mark the state as - * RPROC_OFFLINE so that the PAS driver can load the firmware and - * start the remoteproc. - */ - dev_err(pas->dev, "Failed to get subsystem ready interrupt\n"); - goto unroll_attach; + if (ret || !ready_state) { + dev_info(pas->dev, "Subsystem not running, not attaching\n"); + return false; } - return 0; - -unroll_attach: - pas->rproc->state = RPROC_OFFLINE; - ret = -EINVAL; -disable_running: - pas->q6v5.running = false; + ret = irq_get_irqchip_state(pas->q6v5.stop_irq, + IRQCHIP_STATE_LINE_LEVEL, &stop_state); + if (ret || stop_state || qcom_sysmon_shutdown_irq_state(pas->sysmon)) { + dev_info(pas->dev, "Subsystem has stop state set, not attaching\n"); + return false; + } - return ret; + return true; } static void qcom_pas_coredump(struct rproc *rproc) @@ -1024,7 +1026,7 @@ static int qcom_pas_probe(struct platform_device *pdev) if (pas->dtb_pas_id) pas->dtb_pas_ctx->use_tzmem = desc->needs_tzmem || rproc->has_iommu; - if (desc->early_boot) + if (desc->early_boot && qcom_pas_is_running(pas)) pas->rproc->state = RPROC_DETACHED; ret = qcom_pas_setup_tmd(pas, desc); From 2df5bba29da56c5cee882ea21a72916b5f254a44 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 15 Oct 2026 09:38:27 +0800 Subject: [PATCH 0177/1133] FROMLIST: remoteproc: qcom: pas: Don't fail attach if the remote has crashed When qcom_pas_attach() finds the fatal SMP2P bit already set, it reports a crash and then fails the attach. The core unwinds the attach while the crash work is queued: rproc_boot() drops the power refcount back to 0, and __rproc_attach()/rproc_attach() unprepare the subdevices, clean up the resource table and disable the IOMMU. Once rproc_boot() releases rproc->lock, the crash handler finds the rproc still RPROC_DETACHED, marks it RPROC_CRASHED and runs rproc_boot_recovery() on top of that torn-down state: - the subdevices are unprepared a second time by rproc_stop(), so SSR and sysmon notifiers see a duplicate shutdown; - qcom_pas_stop() and the subsequent rproc_start() operate on resources that rproc_attach() already released, e.g. iommu_unmap() on a disabled domain for rproc->has_iommu; - recovery leaves the rproc RPROC_RUNNING with power == 0. A later "stop" via sysfs takes power to -1 and returns success without stopping anything, so the remote stays running. A following "start" then boots the firmware again on the running remote and fails to re-add the still registered subdevices: sysfs: cannot create duplicate filename '.../qcom_common.pd-mapper.0' remoteproc remoteproc0: failed to prepare subdevices for adsp: -17 remoteproc remoteproc0: Boot failed: -17 A crash found at attach time is no different from one reported by the fatal interrupt right after attaching. Factor the crash handling out of q6v5_fatal_interrupt() into qcom_q6v5_report_fatal(), which logs the SMEM crash reason, clears q6v5.running and reports the crash, and call it from qcom_pas_attach() before letting the attach succeed. The core completes the attach with balanced bookkeeping, and the crash handler then recovers the subsystem through the regular RPROC_ATTACHED -> RPROC_CRASHED path. With running cleared, qcom_q6v5_request_stop() does not wait for a stop ack the dead remote cannot send, and handover_issued already prevents a spurious handover on stop. Assisted-by: LLM Fixes: 16472c99f469 ("remoteproc: qcom: pas: Add late attach support for subsystems") Cc: stable@vger.kernel.org Reviewed-by: Stephan Gerhold Reviewed-by: Bartosz Golaszewski Acked-by: Konrad Dybcio Link: https://lore.kernel.org/r/20261015013827.716465-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- drivers/remoteproc/qcom_q6v5.c | 22 +++++++++++++++++----- drivers/remoteproc/qcom_q6v5.h | 1 + drivers/remoteproc/qcom_q6v5_pas.c | 9 ++++++--- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index fe148b4b3775f..51b24cbd4336b 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -147,15 +147,18 @@ static irqreturn_t q6v5_wdog_interrupt(int irq, void *data) return IRQ_HANDLED; } -static irqreturn_t q6v5_fatal_interrupt(int irq, void *data) +/** + * qcom_q6v5_report_fatal() - report a fatal error of the remote processor + * @q6v5: reference to qcom_q6v5 context + * + * Log the crash reason published by the remote in SMEM, mark the remote as + * no longer running and report the crash to the remoteproc core. + */ +void qcom_q6v5_report_fatal(struct qcom_q6v5 *q6v5) { - struct qcom_q6v5 *q6v5 = data; size_t len; char *msg; - if (!q6v5->running) - return IRQ_HANDLED; - msg = qcom_smem_get(QCOM_SMEM_HOST_ANY, q6v5->crash_reason, &len); if (!IS_ERR(msg) && len > 0 && msg[0]) dev_err(q6v5->dev, "fatal error received: %s\n", msg); @@ -164,6 +167,15 @@ static irqreturn_t q6v5_fatal_interrupt(int irq, void *data) q6v5->running = false; rproc_report_crash(q6v5->rproc, RPROC_FATAL_ERROR); +} +EXPORT_SYMBOL_GPL(qcom_q6v5_report_fatal); + +static irqreturn_t q6v5_fatal_interrupt(int irq, void *data) +{ + struct qcom_q6v5 *q6v5 = data; + + if (q6v5->running) + qcom_q6v5_report_fatal(q6v5); return IRQ_HANDLED; } diff --git a/drivers/remoteproc/qcom_q6v5.h b/drivers/remoteproc/qcom_q6v5.h index 8991ff0905792..a0507860a21ce 100644 --- a/drivers/remoteproc/qcom_q6v5.h +++ b/drivers/remoteproc/qcom_q6v5.h @@ -56,5 +56,6 @@ int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5); int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5, struct qcom_sysmon *sysmon); int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout); unsigned long qcom_q6v5_panic(struct qcom_q6v5 *q6v5); +void qcom_q6v5_report_fatal(struct qcom_q6v5 *q6v5); #endif diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 66bc4c6f004ec..acd47c49af537 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -562,10 +562,13 @@ static int qcom_pas_attach(struct rproc *rproc) goto disable_running; if (crash_state) { + /* + * Complete the attach and let the crash handler recover the + * subsystem from the attached state, as for a crash reported + * by the fatal interrupt. + */ dev_err(pas->dev, "Subsystem has crashed before driver probe\n"); - rproc_report_crash(rproc, RPROC_FATAL_ERROR); - ret = -EINVAL; - goto disable_running; + qcom_q6v5_report_fatal(&pas->q6v5); } return 0; From 9aca5ed6f24583e67fdfccfa1f178c3e14a0dd25 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Thu, 14 May 2026 19:55:54 +0530 Subject: [PATCH 0178/1133] FROMLIST: arm64: dts: qcom: Add psci reboot-modes for talos boards Add PSCI SYSTEM_RESET2 reboot-modes for qcs615-ride, for use by the psci-reboot-mode driver. The following modes are defined: - bootloader: reboot into fastboot mode for fastboot flashing. - edl: reboot into emergency download mode for image loading via the Firehose protocol. Support for these modes is firmware dependent. Link: https://lore.kernel.org/all/20260514-arm-psci-system_reset2-vendor-reboots-v22-13-28a5bde07483@oss.qualcomm.com/ Reviewed-by: Bartosz Golaszewski Signed-off-by: Song Xue Signed-off-by: Shivendra Pratap --- arch/arm64/boot/dts/qcom/qcs615-ride.dts | 7 +++++++ arch/arm64/boot/dts/qcom/talos.dtsi | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride.dts b/arch/arm64/boot/dts/qcom/qcs615-ride.dts index 142dafb04324b..2fe6033f256f5 100644 --- a/arch/arm64/boot/dts/qcom/qcs615-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs615-ride.dts @@ -509,6 +509,13 @@ }; }; +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; + &qupv3_id_0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index 8ed6f2755705c..03da6400c5f25 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -581,7 +581,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; From f5e3adefff8bafa64296caabb7bf19c4d28f4a42 Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Wed, 29 Apr 2026 22:31:40 +0530 Subject: [PATCH 0179/1133] FROMLIST: arm64: dts: qcom: qcs615-ride: Enable QSPI and NOR flash The QCS615 Ride board has a SPI-NOR flash connected to the QSPI controller on CS0. Enable the QSPI controller and add the corresponding SPI-NOR flash node to allow the system to access it. Link: https://lore.kernel.org/all/20260429-spi-nor-v5-5-993016c9711e@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Viken Dadhaniya --- 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 2fe6033f256f5..e4a5cc383664f 100644 --- a/arch/arm64/boot/dts/qcom/qcs615-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs615-ride.dts @@ -516,6 +516,18 @@ }; }; +&qspi { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <25000000>; + spi-tx-bus-width = <2>; + spi-rx-bus-width = <2>; + }; +}; + &qupv3_id_0 { status = "okay"; }; From 24c5fe52d5fa611a01ac0f48e7e7ce0a670e9ee7 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:05:20 +0530 Subject: [PATCH 0180/1133] FROMLIST: arm64: dts: qcom: talos: Add GEM_NOC interconnect for adreno SMMU On Talos platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-6-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/talos.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index 03da6400c5f25..81c22bdca4caa 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -2101,6 +2101,8 @@ "iface"; power-domains = <&gpucc CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; stm@6002000 { From 65c0014e18c606426195670ebdcfba43ef755773 Mon Sep 17 00:00:00 2001 From: Renjiang Han Date: Thu, 30 Apr 2026 16:02:01 +0530 Subject: [PATCH 0181/1133] PENDING: arm64: dts: qcom: talos: enable video codec on Talos Enable video codec on Talos in the EL2 configuration and describe the firmware IOMMU mapping using the iommu-map property. Signed-off-by: Renjiang Han --- arch/arm64/boot/dts/qcom/talos-el2.dtso | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/talos-el2.dtso b/arch/arm64/boot/dts/qcom/talos-el2.dtso index f6818c058d724..08b5c9a537fb6 100644 --- a/arch/arm64/boot/dts/qcom/talos-el2.dtso +++ b/arch/arm64/boot/dts/qcom/talos-el2.dtso @@ -5,6 +5,8 @@ * Talos specific modifications required to boot in EL2. */ +#include + /dts-v1/; /plugin/; @@ -21,5 +23,6 @@ }; &venus { - status = "disabled"; + iommu-map = ; + status = "okay"; }; From 7681490b1101eea66e12f84a795fb477575e2ef0 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Sun, 9 Aug 2026 17:59:03 +0530 Subject: [PATCH 0182/1133] FROMLIST: arm64: dts: qcom: talos: Enable CDSP cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP does not throttle its speed automatically when it reaches high temperatures in talos. Set up CDSP cooling by throttling the cdsp, when it reaches 105°C. Add polling-delay-passive so the governor periodically evaluates the zone during passive cooling and steps up cooling levels when temperature stabilizes below the next trip. Link: https://lore.kernel.org/linux-devicetree/20260809-b4-qmi-tmd-v8-7-b15d47adc379@oss.qualcomm.com/ Reviewed-by: Daniel Lezcano Reviewed-by: Dmitry Baryshkov Signed-off-by: Gaurav Kohli Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/talos.dtsi | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index 81c22bdca4caa..92919759f3824 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -20,6 +20,7 @@ #include #include #include +#include #include / { @@ -3844,6 +3845,8 @@ qcom,smem-states = <&cdsp_smp2p_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <3>; + status = "disabled"; glink-edge { @@ -5505,15 +5508,31 @@ }; q6-hvx-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens0 10>; trips { + q6_hvx_alert0: trip-point0 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + q6-hvx-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&q6_hvx_alert0>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; mdm-core-thermal { From dfb609295bbeccbcda904169b83c6305dbe2f850 Mon Sep 17 00:00:00 2001 From: Nirmesh Kumar Singh Date: Fri, 28 Aug 2026 03:00:27 +0530 Subject: [PATCH 0183/1133] FROMLIST: dt-bindings: arm: qcom: Add Talos Lyra EVK board Add the qcom,talos-lyra-evk compatible string for the Talos Lyra EVK board, which pairs the Talos Lyra EVK SoM with a common carrier board. Signed-off-by: Avaneesh Kumar Dwivedi Signed-off-by: Nirmesh Kumar Singh Link: https://lore.kernel.org/all/20260901-lyra_upstreaming-v1-1-e3a76dc9e21c@oss.qualcomm.com/ --- 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 121ca557ce1ef..6aa0fe8f4e153 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -1092,6 +1092,13 @@ properties: - const: qcom,qcs615 - const: qcom,sm6150 + - items: + - enum: + - qcom,talos-lyra-evk + - const: qcom,talos-lyra-evk-som + - const: qcom,qcs615 + - const: qcom,sm6150 + - items: - enum: - sony,pdx213 From 3ed38cb131f1274d97872d70b0a2c90e7fedf6ca Mon Sep 17 00:00:00 2001 From: Nirmesh Kumar Singh Date: Fri, 28 Aug 2026 03:02:46 +0530 Subject: [PATCH 0184/1133] FROMLIST: arm64: dts: qcom: Add Talos Lyra EVK SoM platform Introduce the device tree for the QCS615-based Talos Lyra EVK SoM. Lyra EVK SoM a compact compute module integrating the QCS615 SoC, PMIC, and essential connectivity, designed to mount on carrier boards. The initial SoM device tree includes basic support for: - CPU and memory - PMIC and board-level regulators - UFS and SD card storage - QUPv3 (I2C/SPI/UART) instances - ADSP/CDSP remoteprocs - GPU Co-developed-by: Monish Chunara Signed-off-by: Monish Chunara Co-developed-by: Rakesh Kota Signed-off-by: Rakesh Kota Co-developed-by: Sayali Lokhande Signed-off-by: Sayali Lokhande Signed-off-by: Avaneesh Kumar Dwivedi Signed-off-by: Nirmesh Kumar Singh Link: https://lore.kernel.org/all/20260901-lyra_upstreaming-v1-2-e3a76dc9e21c@oss.qualcomm.com/ --- .../boot/dts/qcom/talos-lyra-evk-som.dtsi | 282 ++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi diff --git a/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi b/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi new file mode 100644 index 0000000000000..8c19f050d5b3e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include "talos.dtsi" +#include "pm8150.dtsi" +/ { + aliases { + mmc0 = &sdhc_1; + mmc1 = &sdhc_2; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + clocks { + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + clock-frequency = <32764>; + #clock-cells = <0>; + }; + + xo_board_clk: xo-board-clk { + compatible = "fixed-clock"; + clock-frequency = <38400000>; + #clock-cells = <0>; + }; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pm8150-rpmh-regulators"; + qcom,pmic-id = "a"; + + vreg_s3a: smps3 { + regulator-name = "vreg_s3a"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <650000>; + regulator-initial-mode = ; + }; + + vreg_s4a: smps4 { + regulator-name = "vreg_s4a"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1829000>; + regulator-initial-mode = ; + }; + + vreg_s5a: smps5 { + regulator-name = "vreg_s5a"; + regulator-min-microvolt = <1896000>; + regulator-max-microvolt = <2040000>; + regulator-initial-mode = ; + }; + + vreg_s6a: smps6 { + regulator-name = "vreg_s6a"; + regulator-min-microvolt = <1304000>; + regulator-max-microvolt = <1404000>; + regulator-initial-mode = ; + }; + + vreg_l1a: ldo1 { + regulator-name = "vreg_l1a"; + regulator-min-microvolt = <488000>; + regulator-max-microvolt = <852000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2a: ldo2 { + regulator-name = "vreg_l2a"; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <3100000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3a: ldo3 { + regulator-name = "vreg_l3a"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1248000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l5a: ldo5 { + regulator-name = "vreg_l5a"; + regulator-min-microvolt = <875000>; + regulator-max-microvolt = <975000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7a: ldo7 { + regulator-name = "vreg_l7a"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8a: ldo8 { + regulator-name = "vreg_l8a"; + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1350000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l10a: ldo10 { + regulator-name = "vreg_l10a"; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l11a: ldo11 { + regulator-name = "vreg_l11a"; + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l12a: ldo12 { + regulator-name = "vreg_l12a"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1890000>; + regulator-initial-mode = ; + }; + + vreg_l13a: ldo13 { + regulator-name = "vreg_l13a"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3230000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l15a: ldo15 { + regulator-name = "vreg_l15a"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1904000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l16a: ldo16 { + regulator-name = "vreg_l16a"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l17a: ldo17 { + regulator-name = "vreg_l17a"; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = ; + }; + }; +}; + +&gcc { + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&rpmhcc RPMH_CXO_CLK_A>, + <&sleep_clk>; +}; + +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/qcs615/a612_zap.mbn"; +}; + +&qupv3_id_0 { + status = "okay"; +}; + +&qupv3_id_1 { + 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>; +}; + +&sdhc_1 { + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + pinctrl-names = "default", "sleep"; + bus-width = <8>; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + vmmc-supply = <&vreg_l17a>; + vqmmc-supply = <&vreg_s4a>; + non-removable; + no-sd; + no-sdio; + + status = "okay"; +}; + +&sdhc_2 { + pinctrl-0 = <&sdc2_state_on>; + pinctrl-1 = <&sdc2_state_off>; + pinctrl-names = "default", "sleep"; + bus-width = <4>; + cd-gpios = <&tlmm 99 GPIO_ACTIVE_LOW>; + vmmc-supply = <&vreg_l10a>; + vqmmc-supply = <&vreg_s4a>; + + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&ufs_mem_hc { + reset-gpios = <&tlmm 123 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_l17a>; + vcc-max-microamp = <600000>; + vccq2-supply = <&vreg_s4a>; + vccq2-max-microamp = <600000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l12a>; + + status = "okay"; +}; From 391c338990e718940a12c881342dedd2e4a2c8f2 Mon Sep 17 00:00:00 2001 From: Nirmesh Kumar Singh Date: Fri, 28 Aug 2026 03:03:37 +0530 Subject: [PATCH 0185/1133] FROMLIST: arm64: dts: qcom: Add Talos Lyra EVK board Add the device tree for the Talos Lyra EVK platform which combines the Talos Lyra EVK SoM and Lyra carrier board. This device tree adds board-specific peripheral configuration on top of the SoM, including: - Native DisplayPort output - GPIO expanders on i2c5 - SPI-attached TPM (ST33) - USB host and peripheral controllers - Power and reset keys Co-developed-by: Akash Kumar Signed-off-by: Akash Kumar Co-developed-by: Khalid Faisal Ansari Signed-off-by: Khalid Faisal Ansari Co-developed-by: Vishnu Santhosh Signed-off-by: Vishnu Santhosh Signed-off-by: Avaneesh Kumar Dwivedi Signed-off-by: Nirmesh Kumar Singh Link: https://lore.kernel.org/all/20260901-lyra_upstreaming-v1-3-e3a76dc9e21c@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/talos-lyra-evk.dts | 138 ++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/talos-lyra-evk.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..8d2dd0b1bd0aa 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -460,6 +460,7 @@ dtb-$(CONFIG_ARCH_QCOM) += talos-evk.dtb talos-evk-el2-dtbs := talos-evk.dtb talos-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-lyra-evk.dtb talos-evk-usb1-peripheral-dtbs := talos-evk.dtb talos-evk-usb1-peripheral.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-usb1-peripheral.dtb dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camera-imx577.dtbo diff --git a/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts new file mode 100644 index 0000000000000..223158f2a861b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +/dts-v1/; + +#include "talos-lyra-evk-som.dtsi" + +/ { + model = "Qualcomm QCS615 Talos Lyra EVK"; + compatible = "qcom,talos-lyra-evk", "qcom,talos-lyra-evk-som", "qcom,qcs615", + "qcom,sm6150"; + chassis-type = "embedded"; + + dp0-connector { + compatible = "dp-connector"; + label = "DP0"; + type = "full-size"; + + hpd-gpios = <&tlmm 104 GPIO_ACTIVE_HIGH>; + + port { + dp0_connector_in: endpoint { + remote-endpoint = <&mdss_dp0_out>; + }; + }; + }; + +}; + +&i2c5 { + clock-frequency = <100000>; + + status = "okay"; + + expander0: gpio@20 { + compatible = "kinetic,kts1622", "ti,tcal6416"; + reg = <0x20>; + #gpio-cells = <2>; + gpio-controller; + }; + + expander1: gpio@21 { + compatible = "kinetic,kts1622", "ti,tcal6416"; + reg = <0x21>; + #gpio-cells = <2>; + gpio-controller; + }; + + expander2: gpio@38 { + compatible = "ti,tca9538"; + reg = <0x38>; + #gpio-cells = <2>; + gpio-controller; + }; + + expander3: gpio@3c { + compatible = "ti,tca9538"; + reg = <0x3c>; + #gpio-cells = <2>; + gpio-controller; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dp0 { + status = "okay"; +}; + +&mdss_dp0_out { + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000>; + remote-endpoint = <&dp0_connector_in>; +}; + +&pon_pwrkey { + status = "okay"; +}; + +&pon_resin { + linux,code = ; + + status = "okay"; +}; + +&spi6 { + status = "okay"; + + tpm@0 { + compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi"; + reg = <0>; + spi-max-frequency = <20000000>; + }; +}; + +&usb_1 { + dr_mode = "peripheral"; + + status = "okay"; +}; + +&usb_1_hsphy { + vdd-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l12a>; + vdda-phy-dpdm-supply = <&vreg_l13a>; + + status = "okay"; +}; + +&usb_2 { + dr_mode = "host"; + + status = "okay"; +}; + +&usb_2_hsphy { + vdd-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l12a>; + vdda-phy-dpdm-supply = <&vreg_l13a>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l12a>; + + status = "okay"; +}; + +&usb_qmpphy_2 { + vdda-phy-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l12a>; + + status = "okay"; +}; From 9313e2b844d80f048828a9859a73203c35344707 Mon Sep 17 00:00:00 2001 From: Abhishek Reddy Sudugu Date: Fri, 31 Jul 2026 16:46:16 +0530 Subject: [PATCH 0186/1133] PENDING: arm64: dts: qcom: talos-lyra-evk: Enable PCIe Support Enable PCIe support on Talos-Lyra-EVK Signed-off-by: Abhishek Reddy Sudugu --- .../boot/dts/qcom/talos-lyra-evk-som.dtsi | 47 ++++++++ arch/arm64/boot/dts/qcom/talos-lyra-evk.dts | 101 ++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi b/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi index 8c19f050d5b3e..4fed898226290 100644 --- a/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi @@ -31,6 +31,24 @@ #clock-cells = <0>; }; }; + + vreg_0p9: regulator-0v9 { + compatible = "regulator-fixed"; + regulator-name = "VREG_0P9"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-always-on; + regulator-boot-on; + }; + + vreg_1p8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VREG_1P8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; }; &apps_rsc { @@ -214,6 +232,35 @@ status = "okay"; }; +&i2c5 { + clock-frequency = <100000>; + + status = "okay"; +}; + +&pcie { + wake-gpios = <&tlmm 100 GPIO_ACTIVE_HIGH>; + + iommu-map = <0x0 &apps_smmu 0x400 0x1>, + <0x100 &apps_smmu 0x401 0x1>, + <0x208 &apps_smmu 0x402 0x1>, + <0x210 &apps_smmu 0x403 0x1>, + <0x218 &apps_smmu 0x404 0x1>, + <0x300 &apps_smmu 0x405 0x1>, + <0x400 &apps_smmu 0x406 0x1>, + <0x500 &apps_smmu 0x407 0x1>, + <0x501 &apps_smmu 0x408 0x1>; + + status = "okay"; +}; + +&pcie_phy { + vdda-phy-supply = <&vreg_l5a>; + vdda-pll-supply = <&vreg_l12a>; + + status = "okay"; +}; + &remoteproc_adsp { firmware-name = "qcom/qcs615/adsp.mbn"; diff --git a/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts index 223158f2a861b..b32baa85a0e3c 100644 --- a/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts +++ b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts @@ -75,6 +75,82 @@ remote-endpoint = <&dp0_connector_in>; }; +&pcie_port0 { + tc9563: pcie@0,0 { + compatible = "pci1179,0623"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + #gpio-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x2 0xff>; + + vddc-supply = <&vreg_0p9>; + vdd18-supply = <&vreg_1p8>; + vdd09-supply = <&vreg_0p9>; + vddio1-supply = <&vreg_1p8>; + vddio2-supply = <&vreg_1p8>; + vddio18-supply = <&vreg_1p8>; + + i2c-parent = <&i2c5 0x77>; + + resx-gpios = <&tlmm 89 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&tc9563_resx_state>; + 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>; + + ep-pwr-en-gpio = <&tc9563 2 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 5 GPIO_ACTIVE_HIGH>; + }; + + pcie@2,0 { + reg = <0x21000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x4 0xff>; + + ep-pwr-en-gpio = <&tc9563 4 GPIO_ACTIVE_HIGH>; + ep-reset-gpio = <&tc9563 3 GPIO_ACTIVE_HIGH>; + }; + + 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; + }; + }; + }; +}; + &pon_pwrkey { status = "okay"; }; @@ -95,6 +171,31 @@ }; }; +&tlmm { + pcie_default_state: pcie-default-state { + clkreq-pins { + pins = "gpio90"; + function = "pcie_clk_req"; + drive-strength = <2>; + bias-pull-up; + }; + + wake-pins { + pins = "gpio100"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + tc9563_resx_state: tc9563-resx-state { + pins = "gpio89"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; + &usb_1 { dr_mode = "peripheral"; From 64532910949fdff614ad3232c283b0e81817ccbf Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Tue, 8 Sep 2026 09:12:04 +0530 Subject: [PATCH 0187/1133] PENDING: arm64: dts: qcom: talos-lyra-evk: Enable M.2 Key-E QCC2072 WiFi/BT Add support for the M.2 Key-E QCC2072 wireless solution on the Talos Lyra EVK. The M.2 Key-E slot is connected via the QPS615 PCIe switch (TC9563) PCIe1 Downstream port for WiFi, and via SoC UART7 (GPIO10-13) for Bluetooth. - Add compatible = "pciclass,0604" and OF graph endpoint (tc9563_pcie1_ep) to the QPS615 PCIe1 Downstream port (pcie@1,0) to allow PCI subsystem DT node matching for pwrseq. This node now lives in talos-lyra-evk.dts since &pcie_port0 was moved here. - Add GPIO-controlled vreg_keye_3p3 regulator via expander3 GPIO6 - Add wifi-bt-connector (pcie-m2-e-connector) with vpcie3v3-supply, w-disable1 (GPIO51) for WiFi and w-disable2 (GPIO85) for BT - Wire endpoint cross-references via &tc9563_pcie1_ep and &uart7_ep Signed-off-by: Wei Deng --- arch/arm64/boot/dts/qcom/talos-lyra-evk.dts | 84 +++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts index b32baa85a0e3c..d4badf7a97b35 100644 --- a/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts +++ b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts @@ -12,6 +12,10 @@ "qcom,sm6150"; chassis-type = "embedded"; + aliases { + serial1 = &uart7; + }; + dp0-connector { compatible = "dp-connector"; label = "DP0"; @@ -26,6 +30,53 @@ }; }; + vreg_keye_3p3: regulator-keye-3p3 { + compatible = "regulator-fixed"; + regulator-name = "vreg_keye_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&expander3 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + }; + + wifi-bt-connector { + compatible = "pcie-m2-e-connector"; + vpcie3v3-supply = <&vreg_keye_3p3>; + + w-disable1-gpios = <&tlmm 51 GPIO_ACTIVE_LOW>; + w-disable2-gpios = <&tlmm 85 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&wcn_wlan_en>, <&wcn_bt_en>; + pinctrl-names = "default"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_pcie_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&tc9563_pcie1_ep>; + }; + }; + + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_uart_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&uart7_ep>; + }; + }; + }; + }; }; &i2c5 { @@ -104,12 +155,17 @@ reg = <0x20800 0x0 0x0 0x0 0x0>; #address-cells = <3>; #size-cells = <2>; + compatible = "pciclass,0604"; device_type = "pci"; ranges; bus-range = <0x3 0xff>; ep-pwr-en-gpio = <&tc9563 2 GPIO_ACTIVE_HIGH>; ep-reset-gpio = <&tc9563 5 GPIO_ACTIVE_HIGH>; + + port { + tc9563_pcie1_ep: endpoint {}; + }; }; pcie@2,0 { @@ -171,6 +227,10 @@ }; }; +&tc9563_pcie1_ep { + remote-endpoint = <&m2_e_pcie_ep>; +}; + &tlmm { pcie_default_state: pcie-default-state { clkreq-pins { @@ -194,6 +254,30 @@ drive-strength = <2>; bias-disable; }; + + wcn_wlan_en: wcn-wlan-en-state { + pins = "gpio51"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wcn_bt_en: wcn-bt-en-state { + pins = "gpio85"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; + +&uart7 { + status = "okay"; + + port { + uart7_ep: endpoint { + remote-endpoint = <&m2_e_uart_ep>; + }; + }; }; &usb_1 { From 909d83016664b56215df955afeff4a6ae107bb5b Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Tue, 8 Sep 2026 09:21:34 +0530 Subject: [PATCH 0188/1133] PENDING: arm64: dts: qcom: talos-lyra-evk: Add LT9611UXD HDMI bridge support Added LT9611UXD DSI to HDMI bridge node with dual DSI ports, regulators, reset GPIO, and IRQ on I2C2 at address 0x41. Signed-off-by: Mohit Dsor --- arch/arm64/boot/dts/qcom/talos-lyra-evk.dts | 94 +++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts index d4badf7a97b35..d2aa3612bcd8b 100644 --- a/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts +++ b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts @@ -4,6 +4,7 @@ */ /dts-v1/; +#include #include "talos-lyra-evk-som.dtsi" / { @@ -30,6 +31,28 @@ }; }; + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <<9611_out>; + }; + }; + }; + + vreg_lt9611_vcc: regulator-lt9611-vcc { + compatible = "regulator-fixed"; + regulator-name = "lt9611_vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&tlmm 3 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <<9611_vcc_pin>; + pinctrl-names = "default"; + }; + vreg_keye_3p3: regulator-keye-3p3 { compatible = "regulator-fixed"; regulator-name = "vreg_keye_3p3"; @@ -79,6 +102,43 @@ }; }; +&i2c2 { + status = "okay"; + + lt9611uxd: lt9611uxd@41 { + compatible = "lontium,lt9611uxd"; + reg = <0x41>; + interrupts-extended = <&tlmm 60 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&tlmm 61 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_lt9611_vcc>; + vdd-supply = <&vreg_s4a>; + + pinctrl-0 = <<9611_irq_pin <9611_rst_pin>; + pinctrl-names = "default"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9611_a: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9611_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; +}; + &i2c5 { clock-frequency = <100000>; @@ -126,6 +186,19 @@ remote-endpoint = <&dp0_connector_in>; }; +&mdss_dsi0 { + status = "okay"; +}; + +&mdss_dsi0_out { + remote-endpoint = <<9611_a>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; +}; + &pcie_port0 { tc9563: pcie@0,0 { compatible = "pci1179,0623"; @@ -232,6 +305,27 @@ }; &tlmm { + lt9611_irq_pin: lt9611-irq-state { + pins = "gpio60"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + lt9611_rst_pin: lt9611-rst-state { + pins = "gpio61"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + lt9611_vcc_pin: lt9611-vcc-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + pcie_default_state: pcie-default-state { clkreq-pins { pins = "gpio90"; From 154719db284402992508cb022156880349b054f5 Mon Sep 17 00:00:00 2001 From: Karthik S Date: Tue, 8 Sep 2026 09:32:22 +0530 Subject: [PATCH 0189/1133] PENDING: arm64: dts: qcom: talos-lyra-evk: enable audio support enable playback and capture over max98091 codec interfaces for talos-lyra-evk platform. Signed-off-by: Karthik S --- .../boot/dts/qcom/talos-lyra-evk-som.dtsi | 1 + arch/arm64/boot/dts/qcom/talos-lyra-evk.dts | 130 ++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi b/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi index 4fed898226290..6a24ca4431d9f 100644 --- a/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi @@ -5,6 +5,7 @@ #include #include +#include #include "talos.dtsi" #include "pm8150.dtsi" / { diff --git a/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts index d2aa3612bcd8b..6ddad8a0f4d13 100644 --- a/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts +++ b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts @@ -100,6 +100,46 @@ }; }; }; + + sound { + compatible = "qcom,talos-lyra-sndcard"; + model = "qcs615-snd-card"; + + pinctrl-names = "default"; + pinctrl-0 = <&lpi_spkr_i2s_mclk_a>, <&lpi_i2s1_clk>, <&lpi_i2s1_data>, <&lpi_i2s1_ws>; + + sec-mi2s-playback-dai-link { + link-name = "Secondary MI2S Playback"; + + cpu { + sound-dai = <&q6apmbedai SECONDARY_MI2S_RX>; + }; + + codec { + sound-dai = <&max98091>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + sec-mi2s-capture-dai-link { + link-name = "Secondary MI2S Capture"; + + cpu { + sound-dai = <&q6apmbedai SECONDARY_MI2S_TX>; + }; + + codec { + sound-dai = <&max98091>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; }; &i2c2 { @@ -171,6 +211,18 @@ #gpio-cells = <2>; gpio-controller; }; + + max98091: max98091@10 { + compatible = "maxim,max98091"; + reg = <0x10>; + #sound-dai-cells = <0>; + clock-names = "mclk"; + clocks = <&q6prmcc LPASS_CLK_ID_SPEAKER_I2S_OSR LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + interrupt-parent = <&tlmm>; + interrupts = <119 IRQ_TYPE_NONE>; + pinctrl-names = "default"; + pinctrl-0 = <&int_codec>; + }; }; &mdss { @@ -290,6 +342,79 @@ status = "okay"; }; +&soc { + lpass_tlmm: pinctrl@62B40000 { + compatible = "qcom,qcs615-lpass-lpi-pinctrl"; + reg = <0x0 0x62B40000 0x0 0x20000>, + <0x0 0x62B00000 0x0 0x10000>; + + clocks = <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "core"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&lpass_tlmm 0 0 32>; + }; +}; + +&lpass_tlmm { + lpi_spkr_i2s_mclk_a: lpi-spkr-i2s-mclk-a-state { + pins = "gpio19"; + function = "spkr_i2s_mclk_a"; + drive-strength = <16>; + bias-disable; + output-high; + }; + + lpi_i2s1_clk: lpi-i2s1-clk-state { + pins = "gpio8"; + function = "i2s1_clk"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + lpi_i2s1_clk_sleep: lpi-i2s1-clk-sleep-state { + pins = "gpio8"; + function = "i2s1_clk"; + drive-strength = <2>; + bias-pull-down; + input-enable; + }; + + lpi_i2s1_data: lpi-i2s1-data-state { + pins = "gpio10", "gpio11"; + function = "i2s1_data"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + lpi_i2s1_data_sleep: lpi-i2s1-data-sleep-state { + pins = "gpio10", "gpio11"; + function = "i2s1_data"; + drive-strength = <2>; + bias-pull-down; + input-enable; + }; + + lpi_i2s1_ws: lpi-i2s1-ws-state { + pins = "gpio9"; + function = "i2s1_ws"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + lpi_i2s1_ws_sleep: lpi-i2s1-ws-sleep-state { + pins = "gpio9"; + function = "i2s1_ws"; + drive-strength = <2>; + bias-pull-down; + input-enable; + }; +}; + &spi6 { status = "okay"; @@ -305,6 +430,11 @@ }; &tlmm { + int_codec: gpio-irq-state { + pins = "gpio119"; + function = "gpio"; + }; + lt9611_irq_pin: lt9611-irq-state { pins = "gpio60"; function = "gpio"; From cd579b275efd63d4b49fbfb2783da60ebf38f5a5 Mon Sep 17 00:00:00 2001 From: Ajinkya Inchure Date: Fri, 28 Aug 2026 18:20:16 +0530 Subject: [PATCH 0190/1133] PENDING: arm64: dts: qcom: talos-lyra-evk: add ethernet support Adding DTS changes for enabling ethernet on talos-lyra board with TI PHY being used. Signed-off-by: Ajinkya Inchure --- .../boot/dts/qcom/talos-lyra-evk-som.dtsi | 51 +++++++++++++++++++ arch/arm64/boot/dts/qcom/talos-lyra-evk.dts | 49 ++++++++++++++++++ arch/arm64/boot/dts/qcom/talos.dtsi | 34 +++++++++++++ 3 files changed, 134 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi b/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi index 6a24ca4431d9f..06d45c9044d83 100644 --- a/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-lyra-evk-som.dtsi @@ -211,6 +211,57 @@ }; }; +ð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: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rgmii_phy: ethernet-phy@7 { + compatible = "ethernet-phy-id2000.a231"; + reg = <0x7>; + + reset-gpios = <&tlmm 105 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>, diff --git a/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts index 6ddad8a0f4d13..8cdb995e496cb 100644 --- a/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts +++ b/arch/arm64/boot/dts/qcom/talos-lyra-evk.dts @@ -196,6 +196,13 @@ reg = <0x21>; #gpio-cells = <2>; gpio-controller; + + emac0_phy_en_hog: emac0-phy-en-hog { + gpio-hog; + gpios = <6 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "emac0-phy-en"; + }; }; expander2: gpio@38 { @@ -430,6 +437,48 @@ }; &tlmm { + ethernet_defaults: ethernet-defaults-state { + mdc-pins { + pins = "gpio113"; + function = "rgmii"; + bias-pull-up; + }; + + mdio-pins { + pins = "gpio114"; + function = "rgmii"; + bias-pull-up; + }; + + phy-intr-pins { + pins = "gpio121"; + function = "gpio"; + bias-disable; + drive-strength = <8>; + }; + + phy-reset-pins { + pins = "gpio105"; + function = "gpio"; + bias-pull-up; + drive-strength = <16>; + }; + + 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>; + }; + }; + int_codec: gpio-irq-state { pins = "gpio119"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index 92919759f3824..16b7ff8fd7aac 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -696,6 +696,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 b3750a5d4019427360635d7e627021dd5936c99a Mon Sep 17 00:00:00 2001 From: Nirmesh Kumar Singh Date: Thu, 24 Sep 2026 19:39:32 +0530 Subject: [PATCH 0191/1133] PENDING: arm64: dts: qcom: Add EL2 DTB support for Talos Lyra EVK Add the EL2 device tree configuration for Talos Lyra EVK to enable booting with KVM/EL2 virtualization support. Signed-off-by: Nirmesh Kumar Singh --- arch/arm64/boot/dts/qcom/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 8d2dd0b1bd0aa..b9dca863ead86 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -463,6 +463,11 @@ dtb-$(CONFIG_ARCH_QCOM) += talos-evk-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += talos-lyra-evk.dtb talos-evk-usb1-peripheral-dtbs := talos-evk.dtb talos-evk-usb1-peripheral.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-usb1-peripheral.dtb + +talos-lyra-evk-el2-dtbs := talos-lyra-evk.dtb talos-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += talos-lyra-evk-el2.dtb + dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camera-imx577.dtbo talos-evk-camera-imx577-dtbs := talos-evk.dtb talos-evk-camera-imx577.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camera-imx577.dtb From e9e241dce0db64f450b99d1cbba47a079138bca3 Mon Sep 17 00:00:00 2001 From: Jianping Li Date: Wed, 14 Oct 2026 16:03:39 +0800 Subject: [PATCH 0192/1133] FROMLIST: arm64: dts: qcom: talos: Make the ADSP remote heap no-map The ADSP remote heap is declared as a reusable CMA pool. FastRPC assigns the entire region to the DSP through qcom_scm_assign_mem() during probe without allocating the pages from CMA. Consequently, the pages remain available for movable HLOS allocations even after HLOS access to the region has been revoked. On Talos, GPU stress testing triggers a synchronous external abort when zram accesses pages within the ADSP remote heap. Replace reusable with no-map to prevent the region from being reused for normal kernel allocations and exclude it from the kernel's standard memory mapping. Fixes: b0b51a5f1911f ("arm64: dts: qcom: talos: Add memory-region for audio PD") Link: https://lore.kernel.org/all/20261014083820.468-1-jianping.li@oss.qualcomm.com/ Signed-off-by: Jianping Li --- arch/arm64/boot/dts/qcom/talos.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index 16b7ff8fd7aac..be5cb465d443a 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -683,7 +683,7 @@ adsp_rpc_remote_heap_mem: adsp-rpc-remote-heap { compatible = "shared-dma-pool"; alloc-ranges = <0x0 0x80000000 0x0 0x80000000>; - reusable; + no-map; alignment = <0x0 0x400000>; size = <0x0 0x800000>; }; From dbe132cf4a9f45b0b30d903d20d2dc39a521c575 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Fri, 9 Oct 2026 12:13:42 +0530 Subject: [PATCH 0193/1133] FROMLIST: arm64: dts: qcom: talos: Mark USB controllers as dma-coherent Mark the USB30_PRIM (usb@a600000) and USB20_SEC (usb@a800000) DWC3 controllers on Talos as dma-coherent. Without this, USB DMA transfers are incorrectly routed through the SWIOTLB bounce-buffer path causing a synchronous external abort during USB hub enumeration on boot. Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/all/20261021-talos-dma-coherent-usb-v1-1-df0400a2c64d@oss.qualcomm.com/ Signed-off-by: Krishna Kurapati Signed-off-by: Jeff Thomas Pampackal --- arch/arm64/boot/dts/qcom/talos.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index be5cb465d443a..6a1a6c1785bd9 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -5182,6 +5182,7 @@ phys = <&usb_1_hsphy>, <&usb_qmpphy>; phy-names = "usb2-phy", "usb3-phy"; + dma-coherent; power-domains = <&gcc USB30_PRIM_GDSC>; required-opps = <&rpmhpd_opp_nom>; @@ -5238,6 +5239,7 @@ phys = <&usb_2_hsphy>; phy-names = "usb2-phy"; + dma-coherent; power-domains = <&gcc USB20_SEC_GDSC>; required-opps = <&rpmhpd_opp_nom>; From d974b5e368111cd53400265d49a2208fb8425adb Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 8 Sep 2025 09:50:25 +0800 Subject: [PATCH 0194/1133] wifi: ath12k: Fix missing station power save configuration Commit afbab6e4e88d ("wifi: ath12k: modify ath12k_mac_op_bss_info_changed() for MLO") replaced the bss_info_changed() callback with vif_cfg_changed() and link_info_changed() to support Multi-Link Operation (MLO). As a result, the station power save configuration is no longer correctly applied in ath12k_mac_bss_info_changed(). Move the handling of 'BSS_CHANGED_PS' into ath12k_mac_op_vif_cfg_changed() to align with the updated callback structure introduced for MLO, ensuring proper power-save behavior for station interfaces. Tested-on: WCN7850 hw2.0 PCI WLAN.IOE_HMT.1.1-00011-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 Fixes: afbab6e4e88d ("wifi: ath12k: modify ath12k_mac_op_bss_info_changed() for MLO") Signed-off-by: Miaoqing Pan Link: https://lore.kernel.org/all/20250908015025.1301398-1-miaoqing.pan@oss.qualcomm.com/ Signed-off-by: Daizhuang Bai --- drivers/net/wireless/ath/ath12k/mac.c | 124 ++++++++++++++------------ 1 file changed, 68 insertions(+), 56 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 01f8c6572f657..595b649edfe2b 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -4441,12 +4441,68 @@ static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif, return ret; } +static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif) +{ + struct ath12k *ar = arvif->ar; + struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf; + enum wmi_sta_powersave_param param; + struct ieee80211_bss_conf *info; + enum wmi_sta_ps_mode psmode; + int ret; + int timeout; + bool enable_ps; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + + if (vif->type != NL80211_IFTYPE_STATION) + return; + + enable_ps = arvif->ahvif->ps; + if (enable_ps) { + psmode = WMI_STA_PS_MODE_ENABLED; + param = WMI_STA_PS_PARAM_INACTIVITY_TIME; + + timeout = conf->dynamic_ps_timeout; + if (timeout == 0) { + info = ath12k_mac_get_link_bss_conf(arvif); + if (!info) { + ath12k_warn(ar->ab, "unable to access bss link conf in setup ps for vif %pM link %u\n", + vif->addr, arvif->link_id); + return; + } + + /* firmware doesn't like 0 */ + timeout = ieee80211_tu_to_usec(info->beacon_int) / 1000; + } + + ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, + timeout); + if (ret) { + ath12k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n", + arvif->vdev_id, ret); + return; + } + } else { + psmode = WMI_STA_PS_MODE_DISABLED; + } + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d psmode %s\n", + arvif->vdev_id, psmode ? "enable" : "disable"); + + ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode); + if (ret) + ath12k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n", + psmode, arvif->vdev_id, ret); +} + void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 changed) { struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); unsigned long links = ahvif->links_map; + struct ieee80211_vif_cfg *vif_cfg; struct ieee80211_bss_conf *info; struct ath12k_link_vif *arvif; struct ieee80211_sta *sta; @@ -4510,63 +4566,26 @@ void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw, } } } -} -EXPORT_SYMBOL(ath12k_mac_op_vif_cfg_changed); - -static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif) -{ - struct ath12k *ar = arvif->ar; - struct ieee80211_vif *vif = arvif->ahvif->vif; - struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf; - enum wmi_sta_powersave_param param; - struct ieee80211_bss_conf *info; - enum wmi_sta_ps_mode psmode; - int ret; - int timeout; - bool enable_ps; - lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + if (changed & BSS_CHANGED_PS) { + links = ahvif->links_map; + vif_cfg = &vif->cfg; - if (vif->type != NL80211_IFTYPE_STATION) - return; + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); + if (!arvif || !arvif->ar) + continue; - enable_ps = arvif->ahvif->ps; - if (enable_ps) { - psmode = WMI_STA_PS_MODE_ENABLED; - param = WMI_STA_PS_PARAM_INACTIVITY_TIME; + ar = arvif->ar; - timeout = conf->dynamic_ps_timeout; - if (timeout == 0) { - info = ath12k_mac_get_link_bss_conf(arvif); - if (!info) { - ath12k_warn(ar->ab, "unable to access bss link conf in setup ps for vif %pM link %u\n", - vif->addr, arvif->link_id); - return; + if (ar->ab->hw_params->supports_sta_ps) { + ahvif->ps = vif_cfg->ps; + ath12k_mac_vif_setup_ps(arvif); } - - /* firmware doesn't like 0 */ - timeout = ieee80211_tu_to_usec(info->beacon_int) / 1000; - } - - ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, - timeout); - if (ret) { - ath12k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n", - arvif->vdev_id, ret); - return; } - } else { - psmode = WMI_STA_PS_MODE_DISABLED; } - - ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d psmode %s\n", - arvif->vdev_id, psmode ? "enable" : "disable"); - - ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode); - if (ret) - ath12k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n", - psmode, arvif->vdev_id, ret); } +EXPORT_SYMBOL(ath12k_mac_op_vif_cfg_changed); static bool ath12k_mac_supports_tpc(struct ath12k *ar, struct ath12k_vif *ahvif, const struct cfg80211_chan_def *chandef) @@ -4771,7 +4790,6 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, { struct ath12k_vif *ahvif = arvif->ahvif; struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); - struct ieee80211_vif_cfg *vif_cfg = &vif->cfg; struct ath12k_link_vif *tx_arvif; struct cfg80211_chan_def def; u32 param_id, param_value; @@ -5109,12 +5127,6 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, } ath12k_mac_fils_discovery(arvif, info); - - if (changed & BSS_CHANGED_PS && - ar->ab->hw_params->supports_sta_ps) { - ahvif->ps = vif_cfg->ps; - ath12k_mac_vif_setup_ps(arvif); - } } static struct ath12k_vif_cache *ath12k_ahvif_get_link_cache(struct ath12k_vif *ahvif, From cdf7a2675e703542acb4c1678f86f9063c669fb3 Mon Sep 17 00:00:00 2001 From: Hangtian Zhu Date: Fri, 21 Aug 2026 17:22:26 +0800 Subject: [PATCH 0195/1133] FROMLIST: wifi: ath12k: keep ML mgmt tx on active link Currently ath12k_mac_get_tx_link() may select an inactive link for ML management frame transmission. This happens when mac80211 passes IEEE80211_LINK_UNSPECIFIED and the resolved deflink is inactive. As a result, ML management frames such as deauthentication are sent on an inactive link and Tx fails (the frame gets dropped). Fix this by reselecting the Tx link only when the requested link is IEEE80211_LINK_UNSPECIFIED and the resolved deflink is inactive. Start from vif->active_links as the candidate set and prefer links that are both active on the vif and valid for the peer (sta->valid_links). If that intersection is empty, fall back to vif->active_links. Use __ffs() to pick deterministically from the candidate set. If mac80211 explicitly requests a link, keep that link and do not remap management Tx to another link. This change is limited to ML management frames. Data frames, HW-encap frames, and non-MLO paths are unchanged. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3 Signed-off-by: Hangtian Zhu Link: https://lore.kernel.org/all/20261020063719.3486519-1-hangtian.zhu@oss.qualcomm.com --- drivers/net/wireless/ath/ath12k/mac.c | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 595b649edfe2b..a413cd018b6be 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -9612,6 +9612,7 @@ u8 ath12k_mac_get_tx_link(struct ieee80211_sta *sta, struct ieee80211_vif *vif, struct ieee80211_link_sta *link_sta; struct ieee80211_bss_conf *bss_conf; struct ath12k_sta *ahsta; + bool req_unspecified_link = (link == IEEE80211_LINK_UNSPECIFIED); /* Use the link id passed or the default vif link */ if (!sta) { @@ -9657,6 +9658,33 @@ u8 ath12k_mac_get_tx_link(struct ieee80211_sta *sta, struct ieee80211_vif *vif, if (!ieee80211_is_mgmt(hdr->frame_control)) return link; + /* + * Keep ML management Tx on an active link only when mac80211 did + * not request a specific link and the selected link is inactive. + */ + if (req_unspecified_link && !(vif->active_links & BIT(link))) { + unsigned long tx_links = vif->active_links; + unsigned long peer_tx_links; + + if (!tx_links) + goto out_keep_link; + + peer_tx_links = tx_links & sta->valid_links; + + /* + * Prefer links that are both active on the vif and valid for + * this MLO peer. If no overlap exists, fall back to vif + * active links. + */ + if (peer_tx_links) + tx_links = peer_tx_links; + else + WARN_ON_ONCE(1); + + link = __ffs(tx_links); + } + +out_keep_link: /* Perform address conversion for ML STA Tx */ bss_conf = rcu_dereference(vif->link_conf[link]); link_sta = rcu_dereference(sta->link[link]); From afdab0d86e5254f0be362b0ef72e13121e0c56ac Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 22 Oct 2026 19:43:07 +0200 Subject: [PATCH 0196/1133] FROMLIST: net: qrtr: Allow the host QRTR to assign a unique node id Currently, QRTR identifies each remote node by the value of the 'src_node_id' field in the received packet and uses the node id as the key to store the node to the internal 'qrtr_nodes' radix tree. But this approach comes with a limitation. When more than one remote node share the same id, then QRTR can only add the first node to the radix tree and has to drop the successive nodes with the same node id as the 'key' in radix tree has to be unique. This prevents connecting identical Qcom PCIe WLAN devices to a single host at the same time. To fix this limitation, allow the host QRTR to use the node id (nid) received from the endpoint driver during qrtr_endpoint_register() as the unique node id and use it as the 'key' for the internal radix tree. Also, store the received 'src_id' in a new 'qrtr_node->ep_nid' field and replace the 'ep_nid' with the unique 'nid' in the QRTR control packets if both differ i.e., an endpoint driver has passed a unique 'nid' during qrtr_endpoint_register(). To maintain symmetry, replace the 'nid' with the 'ep_nid' while sending the packet back to the remote node if both differ. A node can also bridge other distant nodes, so the source id of an incoming packet is not always the id the endpoint advertises for itself. Keep adding such ids to the radix tree as additional keys for the same node, as it was done before this change. Otherwise the bridged nodes would lose their route and qrtr_sendmsg() would start failing with -ECONNRESET for them. Currently, all QRTR endpoint drivers pass 'QRTR_EP_NID_AUTO' as the 'nid' during qrtr_endpoint_register(). So 'ep_nid' and 'nid' are same and the routing behavior is not changed. Finally, since qrtr_node_rewrite_ctrl() dereferences the control packet for DEL_SERVER and DEL_CLIENT as well, extend the existing length check in qrtr_endpoint_post() to cover both types. Link: https://lore.kernel.org/r/20261022-qrtr-multi-ep-v4-1-c6fdb75fcd3e@oss.qualcomm.com Signed-off-by: Manivannan Sadhasivam --- net/qrtr/af_qrtr.c | 132 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 116 insertions(+), 16 deletions(-) diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index e7b3647424b8f..b95ffb98ec230 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -118,7 +118,8 @@ static DEFINE_XARRAY_ALLOC(qrtr_ports); * @ep_lock: lock for endpoint management and callbacks * @ep: endpoint * @ref: reference count for node - * @nid: node id + * @nid: node id assigned by the host QRTR + * @ep_nid: endpoint's own node id as received * @qrtr_tx_flow: xarray of qrtr_tx_flow, keyed by node << 32 | port * @qrtr_tx_lock: lock for qrtr_tx_flow inserts * @hello_sent: hello packet send successful @@ -131,6 +132,7 @@ struct qrtr_node { struct qrtr_endpoint *ep; struct kref ref; unsigned int nid; + unsigned int ep_nid; struct xarray qrtr_tx_flow; struct mutex qrtr_tx_lock; /* for qrtr_tx_flow */ @@ -347,6 +349,7 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb, { struct qrtr_hdr_v1 *hdr; size_t len = skb->len; + unsigned int dst_node; int rc, confirm_rx; mutex_lock(&node->ep_lock); @@ -369,10 +372,14 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb, hdr->src_node_id = cpu_to_le32(from->sq_node); hdr->src_port_id = cpu_to_le32(from->sq_port); if (to->sq_port == QRTR_PORT_CTRL) { - hdr->dst_node_id = cpu_to_le32(READ_ONCE(node->nid)); + hdr->dst_node_id = cpu_to_le32(READ_ONCE(node->ep_nid)); hdr->dst_port_id = cpu_to_le32(QRTR_PORT_CTRL); } else { - hdr->dst_node_id = cpu_to_le32(to->sq_node); + /* Put back the endpoint's own node id */ + dst_node = to->sq_node; + if (dst_node == READ_ONCE(node->nid)) + dst_node = READ_ONCE(node->ep_nid); + hdr->dst_node_id = cpu_to_le32(dst_node); hdr->dst_port_id = cpu_to_le32(to->sq_port); } @@ -422,23 +429,72 @@ static struct qrtr_node *qrtr_node_lookup(unsigned int nid) return node; } -/* Assign node id to node. +/* Add 'nid' as a lookup key for 'node', and adopt it as the node's own id if + * the node does not have one yet. + * + * Callers must hold 'qrtr_nodes_lock'. * - * This is mostly useful for automatic node id assignment, based on - * the source id in the incoming packet. + * Return: 0 on success; negative error code on failure */ -static void qrtr_node_assign(struct qrtr_node *node, unsigned int nid) +static int __qrtr_node_assign(struct qrtr_node *node, unsigned int nid) { - unsigned long flags; + int rc; if (nid == QRTR_EP_NID_AUTO) - return; + return 0; + + if (radix_tree_lookup(&qrtr_nodes, nid) == node) + return 0; + + rc = radix_tree_insert(&qrtr_nodes, nid, node); + if (rc) + return rc; - spin_lock_irqsave(&qrtr_nodes_lock, flags); - radix_tree_insert(&qrtr_nodes, nid, node); if (node->nid == QRTR_EP_NID_AUTO) WRITE_ONCE(node->nid, nid); + + return 0; +} + +/* Assign node id to node. + * + * Return: 0 on success; negative error code on failure + */ +static int qrtr_node_assign(struct qrtr_node *node, unsigned int nid) +{ + unsigned long flags; + int rc; + + spin_lock_irqsave(&qrtr_nodes_lock, flags); + rc = __qrtr_node_assign(node, nid); spin_unlock_irqrestore(&qrtr_nodes_lock, flags); + + return rc; +} + +/* Replace the node id in the control packet with 'node->nid', if both are + * different. + */ +static void qrtr_node_rewrite_ctrl(struct qrtr_node *node, unsigned int type, + struct sk_buff *skb) +{ + unsigned int ep_nid = READ_ONCE(node->ep_nid); + unsigned int host_nid = READ_ONCE(node->nid); + struct qrtr_ctrl_pkt *pkt; + __le32 *nid; + + if (host_nid == ep_nid) + return; + + pkt = (struct qrtr_ctrl_pkt *)skb->data; + if (type == QRTR_TYPE_DEL_CLIENT || type == QRTR_TYPE_RESUME_TX) + nid = &pkt->client.node; + else + nid = &pkt->server.node; + + /* Rewrite only the endpoint's node id, not those of bridged nodes */ + if (le32_to_cpu(*nid) == ep_nid) + *nid = cpu_to_le32(host_nid); } /** @@ -457,9 +513,12 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) struct qrtr_sock *ipc; struct sk_buff *skb; struct qrtr_cb *cb; + unsigned long flags; size_t size; unsigned int ver; + unsigned int nid; size_t hdrlen; + int rc = 0; if (len == 0 || len & 3) return -EINVAL; @@ -521,6 +580,8 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) goto err; if ((cb->type == QRTR_TYPE_NEW_SERVER || + cb->type == QRTR_TYPE_DEL_SERVER || + cb->type == QRTR_TYPE_DEL_CLIENT || cb->type == QRTR_TYPE_RESUME_TX) && size < sizeof(struct qrtr_ctrl_pkt)) goto err; @@ -531,16 +592,46 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) skb_put_data(skb, data + hdrlen, size); - qrtr_node_assign(node, cb->src_node); + nid = cb->src_node; + + spin_lock_irqsave(&qrtr_nodes_lock, flags); + + if (node->ep_nid == QRTR_EP_NID_AUTO) + WRITE_ONCE(node->ep_nid, nid); + + /* Add the source id to the lookup table only if 'node->nid' is auto + * assigned or the packet came from a bridged node. + */ + if (node->nid == QRTR_EP_NID_AUTO || nid != node->ep_nid) + rc = __qrtr_node_assign(node, nid); + + spin_unlock_irqrestore(&qrtr_nodes_lock, flags); + + if (rc) + goto err_nid; if (cb->type == QRTR_TYPE_NEW_SERVER) { /* Remote node endpoint can bridge other distant nodes */ - const struct qrtr_ctrl_pkt *pkt; + const struct qrtr_ctrl_pkt *pkt = data + hdrlen; + + nid = le32_to_cpu(pkt->server.node); - pkt = data + hdrlen; - qrtr_node_assign(node, le32_to_cpu(pkt->server.node)); + if (nid != READ_ONCE(node->ep_nid)) { + rc = qrtr_node_assign(node, nid); + if (rc) + goto err_nid; + } } + if (cb->src_node == READ_ONCE(node->ep_nid)) + cb->src_node = READ_ONCE(node->nid); + + if (cb->type == QRTR_TYPE_NEW_SERVER || + cb->type == QRTR_TYPE_DEL_SERVER || + cb->type == QRTR_TYPE_DEL_CLIENT || + cb->type == QRTR_TYPE_RESUME_TX) + qrtr_node_rewrite_ctrl(node, cb->type, skb); + if (cb->type == QRTR_TYPE_RESUME_TX) { qrtr_tx_resume(node, skb); } else { @@ -558,6 +649,8 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) return 0; +err_nid: + pr_err_ratelimited("qrtr: cannot route node id %u: %d\n", nid, rc); err: kfree_skb(skb); return -EINVAL; @@ -647,6 +740,7 @@ EXPORT_SYMBOL_GPL(qrtr_endpoint_hello); int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid) { struct qrtr_node *node; + int rc; if (!ep || !ep->xmit) return -EINVAL; @@ -659,6 +753,7 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid) mutex_init(&node->ep_lock); skb_queue_head_init(&node->rx_queue); node->nid = QRTR_EP_NID_AUTO; + node->ep_nid = QRTR_EP_NID_AUTO; node->ep = ep; node->hello_sent = false; @@ -667,7 +762,12 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid) xa_init(&node->qrtr_tx_flow); mutex_init(&node->qrtr_tx_lock); - qrtr_node_assign(node, nid); + rc = qrtr_node_assign(node, nid); + if (rc) { + pr_err("qrtr: cannot assign node id %u: %d\n", nid, rc); + kfree(node); + return rc; + } mutex_lock(&qrtr_node_lock); list_add(&node->item, &qrtr_all_nodes); From 46bc3a7b8f760ca99ab4ed841c4be5d911d2c9fb Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 22 Oct 2026 19:43:08 +0200 Subject: [PATCH 0197/1133] FROMLIST: net: qrtr: Assign unique node id for MHI endpoints Now that the QRTR driver allows using the unique node id for each device, which is different from the node id received from the remote node, compute a unique node id using a new API, qrtr_host_node_id(). This API takes the 'index' parameter and adds it to QRTR_NODE_HOST_BASE. The base is chosen well above the node ids in use by the remote nodes, so that the host assigned ids never collide with the pre-existing ones. Since the ids at and above the base now belong to the host, reject any packet carrying one as the source node id or as the node id of an announced server in qrtr_endpoint_post(). Finally, call the new API from MHI endpoint driver by passing the MHI controller index as the parameter. The MHI controller index is unique for each controller, thereby for each MHI endpoint device. Link: https://lore.kernel.org/r/20261022-qrtr-multi-ep-v4-2-c6fdb75fcd3e@oss.qualcomm.com Signed-off-by: Manivannan Sadhasivam --- MAINTAINERS | 1 + include/net/qrtr.h | 22 ++++++++++++++++++++++ net/qrtr/af_qrtr.c | 9 +++++++++ net/qrtr/mhi.c | 4 +++- 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 include/net/qrtr.h diff --git a/MAINTAINERS b/MAINTAINERS index 93abbb315065d..00c1b2fe9f8f4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23032,6 +23032,7 @@ QUALCOMM IPC ROUTER (QRTR) DRIVER M: Manivannan Sadhasivam L: linux-arm-msm@vger.kernel.org S: Maintained +F: include/net/qrtr.h F: include/trace/events/qrtr.h F: include/uapi/linux/qrtr.h F: net/qrtr/ diff --git a/include/net/qrtr.h b/include/net/qrtr.h new file mode 100644 index 0000000000000..6beefe89943b4 --- /dev/null +++ b/include/net/qrtr.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _NET_QRTR_H +#define _NET_QRTR_H + +#include + +/* Node ids at and above this base are reserved for the host and are never + * accepted from an endpoint. The base is well above the ids used by the + * remote nodes, so that pre-existing node ids stay untouched. + */ +#define QRTR_NODE_HOST_BASE 0x10000u + +/* Compute host node id from a per-device index. The index must be unique + * among the host assigned endpoints and smaller than QRTR_NODE_HOST_BASE. + */ +static inline unsigned int qrtr_host_node_id(unsigned int index) +{ + return QRTR_NODE_HOST_BASE + index; +} + +#endif /* _NET_QRTR_H */ diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index b95ffb98ec230..33df07fb836e5 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -11,6 +11,7 @@ #include #include +#include #include #include "qrtr.h" @@ -590,6 +591,12 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) cb->type != QRTR_TYPE_RESUME_TX) goto err; + /* Host assigned node ids are not supposed to overlap with + * remote node ids + */ + if (cb->src_node >= QRTR_NODE_HOST_BASE) + goto err; + skb_put_data(skb, data + hdrlen, size); nid = cb->src_node; @@ -615,6 +622,8 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) const struct qrtr_ctrl_pkt *pkt = data + hdrlen; nid = le32_to_cpu(pkt->server.node); + if (nid >= QRTR_NODE_HOST_BASE) + goto err; if (nid != READ_ONCE(node->ep_nid)) { rc = qrtr_node_assign(node, nid); diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c index e9a4bb92ce76f..b464231fa0c62 100644 --- a/net/qrtr/mhi.c +++ b/net/qrtr/mhi.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "qrtr.h" @@ -127,7 +128,8 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev, if (rc) return rc; - rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO); + rc = qrtr_endpoint_register(&qdev->ep, + qrtr_host_node_id(mhi_dev->mhi_cntrl->index)); if (rc) goto err_unprepare; From e65a74cac73c5b2f6971354ccdd9aa26b65b11bf Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 22 Oct 2026 19:43:09 +0200 Subject: [PATCH 0198/1133] FROMLIST: wifi: ath11k: Connect to the QMI server belonging to the device owned by this driver When two identical ath11k PCIe devices are connected to the same host, both advertise the WLFW service with the same service and instance id. The QMI lookup reports both servers to each device, so a device may connect to the firmware running on the other device. But now, QRTR provides each MHI endpoint a unique node id which is different from the node id announced by the device. So use the same id to pick the correct server. Add a get_qrtr_node_id() HIF callback that returns the node id derived from the MHI controller index and zero for transports that do not assign one. In the new_server callback, reject any service whose node id does not match. A node id of zero disables the check, so transports that do not assign one keep their current behavior. Link: https://lore.kernel.org/r/20261022-qrtr-multi-ep-v4-3-c6fdb75fcd3e@oss.qualcomm.com Signed-off-by: Manivannan Sadhasivam --- drivers/net/wireless/ath/ath11k/hif.h | 9 +++++++++ drivers/net/wireless/ath/ath11k/pci.c | 9 +++++++++ drivers/net/wireless/ath/ath11k/qmi.c | 10 ++++++++++ 3 files changed, 28 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/hif.h b/drivers/net/wireless/ath/ath11k/hif.h index 017fed1b4bd15..f432fa4890be7 100644 --- a/drivers/net/wireless/ath/ath11k/hif.h +++ b/drivers/net/wireless/ath/ath11k/hif.h @@ -32,6 +32,7 @@ struct ath11k_hif_ops { void (*ce_irq_disable)(struct ath11k_base *ab); void (*get_ce_msi_idx)(struct ath11k_base *ab, u32 ce_id, u32 *msi_idx); void (*coredump_download)(struct ath11k_base *ab); + unsigned int (*get_qrtr_node_id)(struct ath11k_base *ab); }; static inline void ath11k_hif_ce_irq_enable(struct ath11k_base *ab) @@ -159,4 +160,12 @@ static inline void ath11k_hif_coredump_download(struct ath11k_base *ab) ab->hif.ops->coredump_download(ab); } +static inline unsigned int ath11k_hif_get_qrtr_node_id(struct ath11k_base *ab) +{ + if (!ab->hif.ops->get_qrtr_node_id) + return 0; + + return ab->hif.ops->get_qrtr_node_id(ab); +} + #endif /* _HIF_H_ */ diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index a163168f36176..d40c057e130c4 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "pci.h" #include "core.h" @@ -900,6 +901,13 @@ static int ath11k_pci_start(struct ath11k_base *ab) return 0; } +static unsigned int ath11k_pci_get_qrtr_node_id(struct ath11k_base *ab) +{ + struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); + + return qrtr_host_node_id(ab_pci->mhi_ctrl->index); +} + static const struct ath11k_hif_ops ath11k_pci_hif_ops = { .start = ath11k_pci_start, .stop = ath11k_pcic_stop, @@ -921,6 +929,7 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = { #ifdef CONFIG_DEV_COREDUMP .coredump_download = ath11k_pci_coredump_download, #endif + .get_qrtr_node_id = ath11k_pci_get_qrtr_node_id, }; static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 *minor) diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index 7dc07339b9579..6d86e552038c2 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -3170,8 +3170,18 @@ static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl, struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle); struct ath11k_base *ab = qmi->ab; struct sockaddr_qrtr *sq = &qmi->sq; + unsigned int node_id; int ret; + /* Identical devices advertise the same QMI services, so connect only to + * the QMI server on this device's node. A node id of 0 means the + * transport has not assigned a unique node id, so accept the server + * unfiltered. + */ + node_id = ath11k_hif_get_qrtr_node_id(ab); + if (node_id && service->node != node_id) + return -EINVAL; + sq->sq_family = AF_QIPCRTR; sq->sq_node = service->node; sq->sq_port = service->port; From f439d7d2808dbcac391f0833cfad0a746cccc3b8 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 22 Oct 2026 19:43:10 +0200 Subject: [PATCH 0199/1133] FROMLIST: wifi: ath12k: Connect to the QMI server belonging to the device owned by this driver When two identical ath12k PCIe devices are connected to the same host, both advertise the WLFW service with the same service and instance id. The QMI lookup reports both servers to each device, so a device may connect to the firmware running on the other device. But now, QRTR provides each MHI endpoint a unique node id which is different from the node id announced by the device. So use the same id to pick the correct server. Add a get_qrtr_node_id() HIF callback that returns the node id derived from the MHI controller index and zero for transports that do not assign one. In the new_server callback, reject any service whose node id does not match. A node id of zero disables the check, so transports that do not assign one keep their current behavior. Link: https://lore.kernel.org/r/20261022-qrtr-multi-ep-v4-4-c6fdb75fcd3e@oss.qualcomm.com Signed-off-by: Manivannan Sadhasivam --- drivers/net/wireless/ath/ath12k/hif.h | 9 +++++++++ drivers/net/wireless/ath/ath12k/pci.c | 9 +++++++++ drivers/net/wireless/ath/ath12k/qmi.c | 11 +++++++++++ 3 files changed, 29 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/hif.h b/drivers/net/wireless/ath/ath12k/hif.h index aecdb0c5f2858..c2cfe9a754939 100644 --- a/drivers/net/wireless/ath/ath12k/hif.h +++ b/drivers/net/wireless/ath/ath12k/hif.h @@ -31,6 +31,7 @@ struct ath12k_hif_ops { void (*ce_irq_disable)(struct ath12k_base *ab); void (*get_ce_msi_idx)(struct ath12k_base *ab, u32 ce_id, u32 *msi_idx); void (*coredump_download)(struct ath12k_base *ab); + unsigned int (*get_qrtr_node_id)(struct ath12k_base *ab); }; static inline int ath12k_hif_map_service_to_pipe(struct ath12k_base *ab, u16 service_id, @@ -153,4 +154,12 @@ static inline void ath12k_hif_coredump_download(struct ath12k_base *ab) if (ab->hif.ops->coredump_download) ab->hif.ops->coredump_download(ab); } + +static inline unsigned int ath12k_hif_get_qrtr_node_id(struct ath12k_base *ab) +{ + if (!ab->hif.ops->get_qrtr_node_id) + return 0; + + return ab->hif.ops->get_qrtr_node_id(ab); +} #endif /* ATH12K_HIF_H */ diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index 12bbb75570f1f..e56f2f9d721e4 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "pci.h" #include "core.h" @@ -1493,6 +1494,13 @@ void ath12k_pci_power_down(struct ath12k_base *ab, bool is_suspend) ath12k_pci_sw_reset(ab_pci->ab, false); } +static unsigned int ath12k_pci_get_qrtr_node_id(struct ath12k_base *ab) +{ + struct ath12k_pci *ab_pci = ath12k_pci_priv(ab); + + return qrtr_host_node_id(ab_pci->mhi_ctrl->index); +} + static const struct ath12k_hif_ops ath12k_pci_hif_ops = { .start = ath12k_pci_start, .stop = ath12k_pci_stop, @@ -1513,6 +1521,7 @@ static const struct ath12k_hif_ops ath12k_pci_hif_ops = { #ifdef CONFIG_ATH12K_COREDUMP .coredump_download = ath12k_pci_coredump_download, #endif + .get_qrtr_node_id = ath12k_pci_get_qrtr_node_id, }; static enum ath12k_device_family diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index 817bd820623d2..0dc4421e89561 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -9,6 +9,7 @@ #include "qmi.h" #include "core.h" #include "debug.h" +#include "hif.h" #include #include #include @@ -3992,8 +3993,18 @@ static int ath12k_qmi_ops_new_server(struct qmi_handle *qmi_hdl, struct ath12k_qmi *qmi = container_of(qmi_hdl, struct ath12k_qmi, handle); struct ath12k_base *ab = qmi->ab; struct sockaddr_qrtr *sq = &qmi->sq; + unsigned int node_id; int ret; + /* Identical devices advertise the same QMI services, so connect only to + * the QMI server on this device's node. A node id of 0 means the + * transport has not assigned a unique node id, so accept the server + * unfiltered. + */ + node_id = ath12k_hif_get_qrtr_node_id(ab); + if (node_id && service->node != node_id) + return -EINVAL; + sq->sq_family = AF_QIPCRTR; sq->sq_node = service->node; sq->sq_port = service->port; From 5fed92542486681220eb0982f0d5046351c3ea28 Mon Sep 17 00:00:00 2001 From: Hangtian Zhu Date: Tue, 15 Sep 2026 05:51:17 +0000 Subject: [PATCH 0200/1133] FROMLIST: wifi: ath12k: set STA EHT MU mode before peer assoc Currently, ath12k_bss_assoc() sets HE MU mode with WMI_VDEV_PARAM_SET_HEMU_MODE before ath12k_wmi_send_peer_assoc_cmd(), but has no equivalent step for EHT. This means firmware can process peer assoc without EHT beamformee/OFDMA mode state matching the current peer and bandwidth, which can leave incorrect beamforming/OFDMA state for 11be links. Fix this by adding ath12k_mac_vif_recalc_sta_eht_txbf() to compute the EHT MU mode bitmask from local and peer EHT capabilities and link bandwidth, and sending WMI_VDEV_PARAM_SET_EHT_MU_MODE before peer assoc, mirroring the existing HE flow. Also send WMI_VDEV_PARAM_SET_EHT_MU_MODE with zero for non-EHT associations to clear stale EHT mode left from a previous association on the same vdev. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3 Link: https://lore.kernel.org/all/20260915055117.546723-1-hangtian.zhu@oss.qualcomm.com Signed-off-by: Hangtian Zhu --- drivers/net/wireless/ath/ath12k/mac.c | 91 +++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index a413cd018b6be..70ed852a2d0a2 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -3780,6 +3780,79 @@ static int ath12k_mac_vif_recalc_sta_he_txbf(struct ath12k *ar, return 0; } +static int ath12k_mac_vif_recalc_sta_eht_txbf(struct ath12k *ar, + struct ath12k_link_vif *arvif, + struct ieee80211_link_sta *link_sta, + u32 *ehtmode) +{ + const struct ieee80211_sta_eht_cap *peer_eht_cap; + const struct ieee80211_sta_eht_cap *own_eht_cap; + const struct ieee80211_sband_iftype_data *iftd; + struct ieee80211_vif *vif = arvif->ahvif->vif; + struct ieee80211_bss_conf *link_conf; + struct cfg80211_chan_def def; + enum nl80211_band band; + u8 mu_bformer; + + *ehtmode = 0; + + if (vif->type != NL80211_IFTYPE_STATION) + return -EINVAL; + + link_conf = ath12k_mac_get_link_bss_conf(arvif); + if (!link_conf) { + ath12k_warn(ar->ab, "unable to access bss link conf in recalc eht txbf conf\n"); + return -EINVAL; + } + + if (!link_conf->eht_support || !link_sta->eht_cap.has_eht) + return 0; + + if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def))) + return -EINVAL; + + band = def.chan->band; + iftd = ieee80211_get_sband_iftype_data(&ar->mac.sbands[band], vif->type); + if (!iftd) { + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "unable to access iftype data in recalc eht txbf conf\n"); + return 0; + } + + own_eht_cap = &iftd->eht_cap; + peer_eht_cap = &link_sta->eht_cap; + + if (!own_eht_cap->has_eht) + return 0; + + *ehtmode |= u32_encode_bits(EHT_DL_MUOFDMA_ENABLE, EHT_MODE_DL_OFDMA) | + u32_encode_bits(EHT_UL_MUOFDMA_ENABLE, EHT_MODE_UL_OFDMA); + + if ((own_eht_cap->eht_cap_elem.phy_cap_info[0] & + IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE) && + (peer_eht_cap->eht_cap_elem.phy_cap_info[0] & + IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER)) + *ehtmode |= u32_encode_bits(EHT_SU_BFEE_ENABLE, EHT_MODE_SU_TX_BFEE); + + switch (link_sta->bandwidth) { + case IEEE80211_STA_RX_BW_320: + mu_bformer = IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; + break; + case IEEE80211_STA_RX_BW_160: + mu_bformer = IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ; + break; + default: + mu_bformer = IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ; + break; + } + + if (u32_get_bits(*ehtmode, EHT_MODE_SU_TX_BFEE) && + (peer_eht_cap->eht_cap_elem.phy_cap_info[7] & mu_bformer)) + *ehtmode |= u32_encode_bits(EHT_MU_BFEE_ENABLE, EHT_MODE_MU_TX_BFEE); + + return 0; +} + static int ath12k_mac_set_eht_txbf_conf(struct ath12k_link_vif *arvif) { struct ath12k_vif *ahvif = arvif->ahvif; @@ -3923,6 +3996,7 @@ static void ath12k_bss_assoc(struct ath12k *ar, struct ath12k_sta *ahsta; struct ath12k_dp_link_peer *peer; bool is_auth = false; + u32 ehtmode = 0; u32 hemode = 0; int ret; struct ath12k_dp *dp = ath12k_ab_to_dp(ar->ab); @@ -3977,6 +4051,14 @@ static void ath12k_bss_assoc(struct ath12k *ar, return; } + ret = ath12k_mac_vif_recalc_sta_eht_txbf(ar, arvif, link_sta, &ehtmode); + if (ret) { + ath12k_warn(ar->ab, "failed to recalc eht txbf for vdev %i on bss %pM: %d\n", + arvif->vdev_id, bss_conf->bssid, ret); + rcu_read_unlock(); + return; + } + rcu_read_unlock(); /* keep this before ath12k_wmi_send_peer_assoc_cmd() */ @@ -3988,6 +4070,15 @@ static void ath12k_bss_assoc(struct ath12k *ar, return; } + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, + WMI_VDEV_PARAM_SET_EHT_MU_MODE, + ehtmode); + if (ret) { + ath12k_warn(ar->ab, "failed to submit vdev param eht txbf 0x%x: %d\n", + ehtmode, ret); + return; + } + peer_arg->is_assoc = true; ret = ath12k_mac_peer_assoc(ar, peer_arg); From c39e3e90a4a6a46c75319e50b7749864503eca01 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 2 Nov 2026 14:41:30 +0800 Subject: [PATCH 0201/1133] FROMLIST: wifi: ath12k: fix MLO 4-way handshake timeout on QCC2072 In MLO connections, ath12k_wifi7_dp_rx_set_link_id_wcn7850() attempts to resolve the IEEE 802.11 link ID for received frames by matching rxcb->peer_id against the link_peer->peer_id entries in dp_peer->link_peers[]. This fails for EAPOL frames because the firmware delivers them via the MLD peer path. In this case, rxcb->peer_id contains an MLD peer ID while link_peer->peer_id contains a link peer ID. The mismatch prevents status->link_valid from being set. When mac80211 receives a data frame with link_valid=0 for an MLO station, it calls link_sta_info_get_bss() with hdr->addr2 to resolve the link ID. If hdr->addr2 contains the AP MLD address rather than a link address, the lookup fails because link_sta_info_get_bss() indexes by link address, and the frame is dropped in __ieee80211_rx_handle_packet(). This is observed on QCC2072 where EAPOL M3 uses the MLD address, deauthenticated (Reason: 15=4WAY_HANDSHAKE_TIMEOUT) Fix this by resolving the link peer using the current operating frequency associated with each link peer. For 6 GHz links, the received frequency corresponds to the operating center frequency, while for other bands it corresponds to the primary channel frequency. Match the received frame against associated links using the appropriate frequency for each band. The frequency-based lookup is used only when exactly one associated link matches the received frequency. If multiple links share the same frequency, the match becomes ambiguous and no link ID is assigned. In that case, leave status->link_valid unset and let mac80211 fall back to its own link resolution logic. Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00228-QCACOLSWPL_V1_TO_SILICON-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3 Fixes: a2fe9dc70f3b ("wifi: ath12k: Fix low MLO RX throughput on WCN7850") Signed-off-by: Miaoqing Pan Link: https://lore.kernel.org/linux-wireless/20260815014329.3748059-1-miaoqing.pan@oss.qualcomm.com/ --- drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c index a32c804403e8a..5562c62b8945a 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c @@ -2362,19 +2362,63 @@ ath12k_wifi7_dp_rx_get_link_id_wcn7850(struct ath12k_dp_peer *dp_peer, struct ath12k_skb_rxcb *rxcb, struct ieee80211_rx_status *status) { - struct ath12k_dp_link_peer *link_peer; + struct ath12k_dp_link_peer *lp, *link_peer = NULL; + struct ieee80211_bss_conf *link_conf; + struct ieee80211_chanctx_conf *ctx; + struct ieee80211_vif *vif; + struct ath12k_sta *ahsta; unsigned long links_map; + int freq; int i; RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "ath12k set rx link id called without rcu lock"); + if (!status->freq) + return -1; + links_map = READ_ONCE(dp_peer->link_peers_map); for_each_set_bit(i, &links_map, ATH12K_NUM_MAX_LINKS) { - link_peer = rcu_dereference(dp_peer->link_peers[i]); - if (link_peer && link_peer->peer_id == rxcb->peer_id) - return link_peer->link_id; + lp = rcu_dereference(dp_peer->link_peers[i]); + if (!lp || !lp->sta) + continue; + + ahsta = ath12k_sta_to_ahsta(lp->sta); + if (unlikely(!ahsta->ahvif)) + continue; + + vif = ahsta->ahvif->vif; + link_conf = rcu_dereference(vif->link_conf[lp->link_id]); + if (!link_conf) + continue; + + ctx = rcu_dereference(link_conf->chanctx_conf); + if (!ctx) + continue; + + /* + * For 6 GHz, rx_status->freq contains the operating center frequency. + * For other bands, it contains the primary channel frequency. + */ + freq = status->band == NL80211_BAND_6GHZ ? + ctx->def.center_freq1 : ctx->def.chan->center_freq; + if (freq != status->freq) + continue; + + /* + * Skip freq-based lookup if multiple links share + * the same frequency; the match would be ambiguous. + */ + if (link_peer) { + link_peer = NULL; + break; + } + + link_peer = lp; } + if (likely(link_peer)) + return link_peer->link_id; + return -1; } From d9b4f13d4233d58c58d3d2acb1a7ca8d93ba2135 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 14 Oct 2026 14:39:46 +0800 Subject: [PATCH 0202/1133] FROMLIST: dt-bindings: rtc: qcom-pm8xxx: Document PMM8654AU RTC Document Qualcomm PMM8654AU PMIC RTC which is compatible with PMK8350 RTC. Reviewed-by: Bartosz Golaszewski Acked-by: Krzysztof Kozlowski Acked-by: Alexandre Belloni Link: https://lore.kernel.org/r/20261014063953.549379-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/rtc/qcom-pm8xxx-rtc.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/rtc/qcom-pm8xxx-rtc.yaml b/Documentation/devicetree/bindings/rtc/qcom-pm8xxx-rtc.yaml index 7497dc3ac5b20..78fa1d5ed0282 100644 --- a/Documentation/devicetree/bindings/rtc/qcom-pm8xxx-rtc.yaml +++ b/Documentation/devicetree/bindings/rtc/qcom-pm8xxx-rtc.yaml @@ -17,6 +17,9 @@ properties: - qcom,pm8921-rtc - qcom,pm8941-rtc - qcom,pmk8350-rtc + - items: + - const: qcom,pmm8654au-rtc + - const: qcom,pmk8350-rtc - items: - enum: - qcom,pm8018-rtc From 1a0fc9783aac8c57279fcc160aafd512567f3f32 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 14 Oct 2026 14:39:47 +0800 Subject: [PATCH 0203/1133] FROMLIST: arm64: dts: qcom: nord: Add support for ADSP and CDSPs Add device tree nodes to support ADSP (HPASS DSP) and CDSPs remoteproc on Nord SoC. This includes: - SMEM memory reservation used by the inter-processor communication infrastructure - IPCC mailbox controller for inter-processor signalling - AOSS QMP node for load state power management - SMP2P nodes providing stop control and fault/crash interrupt signals - Remoteproc nodes with a GLINK edge and FastRPC compute contexts for userspace offload The embedded variant specific power domains, XO clock, and interconnect paths are filled in nord-embedded.dtsi. Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261014063953.549379-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 63 ++ arch/arm64/boot/dts/qcom/nord-ipcc.h | 144 ++++ arch/arm64/boot/dts/qcom/nord.dtsi | 888 ++++++++++++++++++++ 3 files changed, 1095 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/nord-ipcc.h diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 6ccdeda5029cd..0269abdb277bd 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -401,6 +401,69 @@ "s-ahb"; }; +&remoteproc_adsp { + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + interconnects = <&hpass_ag_noc MASTER_HPASS_PROC_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MX>; + power-domain-names = "cx", + "mx"; +}; + +&remoteproc_cdsp0 { + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + interconnects = <&nsp_data_noc_0 MASTER_NSP0_PROC QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_NMXC>, + <&rpmhpd RPMHPD_NSP0>; + power-domain-names = "cx", + "mx", + "nsp"; +}; + +&remoteproc_cdsp1 { + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + interconnects = <&nsp_data_noc_1 MASTER_NSP1_PROC QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_NMXC>, + <&rpmhpd RPMHPD_NSP1>; + power-domain-names = "cx", + "mx", + "nsp"; +}; + +&remoteproc_cdsp2 { + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + interconnects = <&nsp_data_noc_2 MASTER_NSP2_PROC QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_NMXC>, + <&rpmhpd RPMHPD_NSP2>; + power-domain-names = "cx", + "mx", + "nsp"; +}; + +&remoteproc_cdsp3 { + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + interconnects = <&nsp_data_noc_3 MASTER_NSP3_PROC QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_NMXC>, + <&rpmhpd RPMHPD_NSP3>; + power-domain-names = "cx", + "mx", + "nsp"; +}; + &spi0 { clocks = <&segcc SE_GCC_QUPV3_WRAP0_S0_CLK>; clock-names = "se"; diff --git a/arch/arm64/boot/dts/qcom/nord-ipcc.h b/arch/arm64/boot/dts/qcom/nord-ipcc.h new file mode 100644 index 0000000000000..8bf9b0875b6d1 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/nord-ipcc.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __DTS_NORD_IPCC_H +#define __DTS_NORD_IPCC_H + +/* Physical client IDs */ +#define IPCC_MPROC_AOP 0 +#define IPCC_MPROC_TZ 1 +#define IPCC_MPROC_ADSP0 2 +#define IPCC_MPROC_NSP0 3 +#define IPCC_MPROC_NSP1 4 +#define IPCC_MPROC_NSP2 5 +#define IPCC_MPROC_NSP3 6 +#define IPCC_MPROC_APSS_NS0 7 +#define IPCC_MPROC_APSS_NS1 8 +#define IPCC_MPROC_APSS_NS2 9 +#define IPCC_MPROC_APSS_NS3 10 +#define IPCC_MPROC_ADSP1 11 +#define IPCC_MPROC_ADSP2 12 +#define IPCC_MPROC_APSS_NS4 13 +#define IPCC_MPROC_SOCCP 15 +#define IPCC_MPROC_CPUCP 16 +#define IPCC_MPROC_A78CSS 17 +#define IPCC_MPROC_TMESS 18 +#define IPCC_MPROC_SAIL0 19 +#define IPCC_MPROC_SAIL1 20 +#define IPCC_MPROC_SAIL2 21 +#define IPCC_MPROC_SAIL3 22 +#define IPCC_MPROC_SAIL4 23 +#define IPCC_MPROC_SAIL5 24 + +#define IPCC_COMPUTE_L0_ADSP0 0 +#define IPCC_COMPUTE_L0_NSP0 1 +#define IPCC_COMPUTE_L0_NSP1 2 +#define IPCC_COMPUTE_L0_NSP2 3 +#define IPCC_COMPUTE_L0_NSP3 4 +#define IPCC_COMPUTE_L0_APSS_NS0 5 +#define IPCC_COMPUTE_L0_GPU0 6 +#define IPCC_COMPUTE_L0_APSS_NS1 7 +#define IPCC_COMPUTE_L0_APSS_NS2 8 +#define IPCC_COMPUTE_L0_APSS_NS3 9 +#define IPCC_COMPUTE_L0_CVP 10 +#define IPCC_COMPUTE_L0_ICP0 11 +#define IPCC_COMPUTE_L0_ICP1 12 +#define IPCC_COMPUTE_L0_VPU 13 +#define IPCC_COMPUTE_L0_DPU0 14 +#define IPCC_COMPUTE_L0_DPU1 15 +#define IPCC_COMPUTE_L0_ADSP1 16 +#define IPCC_COMPUTE_L0_ADSP2 17 +#define IPCC_COMPUTE_L0_APSS_NS4 18 +#define IPCC_COMPUTE_L0_SOCCP 20 +#define IPCC_COMPUTE_L0_SAIL0 21 +#define IPCC_COMPUTE_L0_SAIL1 22 +#define IPCC_COMPUTE_L0_SAIL2 23 +#define IPCC_COMPUTE_L0_SAIL3 24 +#define IPCC_COMPUTE_L0_SAIL4 25 +#define IPCC_COMPUTE_L0_SAIL5 26 +#define IPCC_COMPUTE_L0_IPA 27 +#define IPCC_COMPUTE_L0_GPU1 28 + +#define IPCC_COMPUTE_L1_ADSP0 0 +#define IPCC_COMPUTE_L1_NSP0 1 +#define IPCC_COMPUTE_L1_NSP1 2 +#define IPCC_COMPUTE_L1_NSP2 3 +#define IPCC_COMPUTE_L1_NSP3 4 +#define IPCC_COMPUTE_L1_APSS_NS0 5 +#define IPCC_COMPUTE_L1_GPU0 6 +#define IPCC_COMPUTE_L1_APSS_NS1 7 +#define IPCC_COMPUTE_L1_APSS_NS2 8 +#define IPCC_COMPUTE_L1_APSS_NS3 9 +#define IPCC_COMPUTE_L1_CVP 10 +#define IPCC_COMPUTE_L1_ICP0 11 +#define IPCC_COMPUTE_L1_ICP1 12 +#define IPCC_COMPUTE_L1_VPU 13 +#define IPCC_COMPUTE_L1_DPU0 14 +#define IPCC_COMPUTE_L1_DPU1 15 +#define IPCC_COMPUTE_L1_ADSP1 16 +#define IPCC_COMPUTE_L1_ADSP2 17 +#define IPCC_COMPUTE_L1_APSS_NS4 18 +#define IPCC_COMPUTE_L1_SOCCP 20 +#define IPCC_COMPUTE_L1_SAIL0 21 +#define IPCC_COMPUTE_L1_SAIL1 22 +#define IPCC_COMPUTE_L1_SAIL2 23 +#define IPCC_COMPUTE_L1_SAIL3 24 +#define IPCC_COMPUTE_L1_SAIL4 25 +#define IPCC_COMPUTE_L1_SAIL5 26 +#define IPCC_COMPUTE_L1_IPA 27 +#define IPCC_COMPUTE_L1_GPU1 28 + +#define IPCC_PERIPH_ADSP0 0 +#define IPCC_PERIPH_NSP0 1 +#define IPCC_PERIPH_NSP1 2 +#define IPCC_PERIPH_NSP2 3 +#define IPCC_PERIPH_NSP3 4 +#define IPCC_PERIPH_APSS_NS0 5 +#define IPCC_PERIPH_PCIE0 6 +#define IPCC_PERIPH_PCIE1 7 +#define IPCC_PERIPH_APSS_NS1 8 +#define IPCC_PERIPH_APSS_NS2 9 +#define IPCC_PERIPH_APSS_NS3 10 +#define IPCC_PERIPH_ADSP1 11 +#define IPCC_PERIPH_ADSP2 12 +#define IPCC_PERIPH_APSS_NS4 13 + +#define IPCC_FENCE_ADSP0 0 +#define IPCC_FENCE_NSP0 1 +#define IPCC_FENCE_NSP1 2 +#define IPCC_FENCE_NSP2 3 +#define IPCC_FENCE_NSP3 4 +#define IPCC_FENCE_APSS_NS0 5 +#define IPCC_FENCE_GPU0 6 +#define IPCC_FENCE_APSS_NS1 7 +#define IPCC_FENCE_APSS_NS2 8 +#define IPCC_FENCE_APSS_NS3 9 +#define IPCC_FENCE_CVP 10 +#define IPCC_FENCE_ICP0 11 +#define IPCC_FENCE_ICP1 12 +#define IPCC_FENCE_CAM_ENG0 13 +#define IPCC_FENCE_CAM_ENG1 14 +#define IPCC_FENCE_CAM_ENG2 15 +#define IPCC_FENCE_CAM_ENG3 16 +#define IPCC_FENCE_CAM_ENG4 17 +#define IPCC_FENCE_CAM_ENG5 18 +#define IPCC_FENCE_CAM_ENG6 19 +#define IPCC_FENCE_CAM_ENG7 20 +#define IPCC_FENCE_CAM_ENG8 21 +#define IPCC_FENCE_CAM_ENG9 22 +#define IPCC_FENCE_CAM_ENG10 23 +#define IPCC_FENCE_CAM_ENG11 24 +#define IPCC_FENCE_CAM_ENG12 25 +#define IPCC_FENCE_VPU 26 +#define IPCC_FENCE_DPU0 27 +#define IPCC_FENCE_DPU1 28 +#define IPCC_FENCE_ADSP1 29 +#define IPCC_FENCE_ADSP2 30 +#define IPCC_FENCE_APSS_NS4 31 +#define IPCC_FENCE_SOCCP 33 +#define IPCC_FENCE_IPA 34 +#define IPCC_FENCE_GPU1 35 + +#endif diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 720d0b4504753..c4f38335c90ca 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -4,7 +4,11 @@ */ #include +#include #include +#include + +#include "nord-ipcc.h" / { interrupt-parent = <&intc>; @@ -691,6 +695,13 @@ no-map; }; + smem_mem: smem@89b00000 { + compatible = "qcom,smem"; + reg = <0x0 0x89b00000 0x0 0x400000>; + no-map; + hwlocks = <&tcsr_mutex 3>; + }; + global_sync_mem: global-sync-region@89f00000 { reg = <0x0 0x89f00000 0x0 0x400000>; no-map; @@ -908,6 +919,117 @@ }; }; + smp2p-adsp { + compatible = "qcom,smp2p"; + interrupts-extended = <&ipcc0 IPCC_MPROC_ADSP0 + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_ADSP0 + IPCC_MPROC_SIGNAL_SMP2P>; + qcom,smem = <443>, <429>; + qcom,local-pid = <0>; + qcom,remote-pid = <2>; + + smp2p_adsp_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_adsp_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-cdsp0 { + compatible = "qcom,smp2p"; + interrupts-extended = <&ipcc0 IPCC_MPROC_NSP0 + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_NSP0 IPCC_MPROC_SIGNAL_SMP2P>; + qcom,smem = <94>, <432>; + qcom,local-pid = <0>; + qcom,remote-pid = <5>; + + smp2p_cdsp0_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_cdsp0_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-cdsp1 { + compatible = "qcom,smp2p"; + interrupts-extended = <&ipcc0 IPCC_MPROC_NSP1 + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_NSP1 IPCC_MPROC_SIGNAL_SMP2P>; + qcom,smem = <617>, <616>; + qcom,local-pid = <0>; + qcom,remote-pid = <69>; + + smp2p_cdsp1_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_cdsp1_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-cdsp2 { + compatible = "qcom,smp2p"; + interrupts-extended = <&ipcc0 IPCC_MPROC_NSP2 + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_NSP2 IPCC_MPROC_SIGNAL_SMP2P>; + qcom,smem = <617>, <616>; + qcom,local-pid = <0>; + qcom,remote-pid = <133>; + + smp2p_cdsp2_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_cdsp2_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-cdsp3 { + compatible = "qcom,smp2p"; + interrupts-extended = <&ipcc0 IPCC_MPROC_NSP3 + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_NSP3 IPCC_MPROC_SIGNAL_SMP2P>; + qcom,smem = <617>, <616>; + qcom,local-pid = <0>; + qcom,remote-pid = <197>; + + smp2p_cdsp3_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_cdsp3_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + soc: soc@0 { compatible = "simple-bus"; #address-cells = <2>; @@ -1815,6 +1937,106 @@ dma-coherent; }; + remoteproc_adsp: remoteproc@4c00000 { + compatible = "qcom,nord-adsp-pas"; + reg = <0x0 0x04c00000 0x0 0x10000>; + + interrupts-extended = <&intc GIC_SPI 159 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + memory-region = <&hpass_dsp0_mem>, + <&hpass_dsp0_dtb_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_adsp_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc0 IPCC_MPROC_ADSP0 + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_ADSP0 + IPCC_MPROC_SIGNAL_GLINK_QMP>; + qcom,remote-pid = <2>; + label = "adsp"; + + fastrpc { + compatible = "qcom,nord-fastrpc", + "qcom,kaanapali-fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "adsp"; + memory-region = <&hpass_rpc_remote_heap_mem>; + qcom,vmids = ; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu_0 0x09e3 0x0000>, + <&apps_smmu_0 0x0a43 0x0020>, + <&apps_smmu_0 0x0a63 0x0020>, + <&apps_smmu_0 0x0a83 0x0000>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu_0 0x09e4 0x0000>, + <&apps_smmu_0 0x0a44 0x0020>, + <&apps_smmu_0 0x0a64 0x0020>, + <&apps_smmu_0 0x0a84 0x0000>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu_0 0x09e5 0x0000>, + <&apps_smmu_0 0x0a45 0x0020>, + <&apps_smmu_0 0x0a65 0x0020>, + <&apps_smmu_0 0x0a85 0x0000>; + dma-coherent; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu_0 0x09e6 0x0000>, + <&apps_smmu_0 0x0a46 0x0020>, + <&apps_smmu_0 0x0a66 0x0020>, + <&apps_smmu_0 0x0a86 0x0000>; + dma-coherent; + }; + }; + }; + }; + + ipcc0: mailbox@9007000 { + compatible = "qcom,nord-ipcc", + "qcom,ipcc"; + reg = <0x0 0x09007000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + }; + adreno_smmu_1: iommu@98a0000 { compatible = "qcom,nord-smmu-500", "qcom,adreno-smmu", @@ -1971,6 +2193,16 @@ #thermal-sensor-cells = <1>; }; + aoss_qmp: power-management@c300000 { + compatible = "qcom,nord-aoss-qmp", "qcom,aoss-qmp"; + reg = <0x0 0x0c300000 0x0 0x400>; + interrupts-extended = <&ipcc0 IPCC_MPROC_AOP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_AOP IPCC_MPROC_SIGNAL_GLINK_QMP>; + #clock-cells = <0>; + }; + tlmm: pinctrl@f100000 { compatible = "qcom,nord-tlmm"; reg = <0x0 0x0f100000 0x0 0xc0000>; @@ -2406,6 +2638,662 @@ interrupts = ; }; + remoteproc_cdsp0: remoteproc@1f300000 { + compatible = "qcom,nord-cdsp0-pas"; + reg = <0x0 0x1f300000 0x0 0x10000>; + + interrupts-extended = <&intc GIC_SPI 499 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp0_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp0_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp0_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp0_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp0_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + memory-region = <&cdsp0_mem>, + <&q6_cdsp0_dtb_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_cdsp0_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc0 IPCC_MPROC_NSP0 + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_NSP0 + IPCC_MPROC_SIGNAL_GLINK_QMP>; + qcom,remote-pid = <5>; + label = "cdsp"; + + fastrpc { + compatible = "qcom,nord-fastrpc", + "qcom,kaanapali-fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "cdsp"; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + iommus = <&apps_smmu_2 0x0301 0x0040>, + <&apps_smmu_2 0x0341 0x0040>, + <&apps_smmu_2 0x0361 0x0000>; + dma-coherent; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + iommus = <&apps_smmu_2 0x0302 0x0040>, + <&apps_smmu_2 0x0342 0x0040>, + <&apps_smmu_2 0x0362 0x0000>; + dma-coherent; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu_2 0x0303 0x0040>, + <&apps_smmu_2 0x0343 0x0040>, + <&apps_smmu_2 0x0363 0x0000>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu_2 0x0304 0x0040>, + <&apps_smmu_2 0x0344 0x0040>, + <&apps_smmu_2 0x0364 0x0000>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu_2 0x0305 0x0000>, + <&apps_smmu_2 0x0345 0x0020>, + <&apps_smmu_2 0x0365 0x0020>; + dma-coherent; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu_2 0x0306 0x0040>, + <&apps_smmu_2 0x0346 0x0040>, + <&apps_smmu_2 0x0366 0x0000>; + dma-coherent; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + iommus = <&apps_smmu_2 0x0307 0x0040>, + <&apps_smmu_2 0x0347 0x0040>, + <&apps_smmu_2 0x0367 0x0000>; + dma-coherent; + }; + + compute-cb@8 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <8>; + iommus = <&apps_smmu_2 0x0308 0x0040>, + <&apps_smmu_2 0x0348 0x0040>, + <&apps_smmu_2 0x0368 0x0000>; + dma-coherent; + }; + + compute-cb@9 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <9>; + iommus = <&apps_smmu_2 0x0309 0x0040>, + <&apps_smmu_2 0x0349 0x0040>, + <&apps_smmu_2 0x0369 0x0000>; + dma-coherent; + }; + + compute-cb@10 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <10>; + iommus = <&apps_smmu_2 0x030a 0x0040>, + <&apps_smmu_2 0x034a 0x0040>, + <&apps_smmu_2 0x036a 0x0000>; + dma-coherent; + }; + + compute-cb@11 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <11>; + iommus = <&apps_smmu_2 0x030b 0x0040>, + <&apps_smmu_2 0x034b 0x0040>, + <&apps_smmu_2 0x036b 0x0000>; + dma-coherent; + }; + + compute-cb@12 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <12>; + iommus = <&apps_smmu_2 0x030c 0x0040>, + <&apps_smmu_2 0x034c 0x0040>, + <&apps_smmu_2 0x036c 0x0000>; + dma-coherent; + }; + + compute-cb@13 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <13>; + iommus = <&apps_smmu_2 0x030d 0x0000>, + <&apps_smmu_2 0x034d 0x0020>, + <&apps_smmu_2 0x036d 0x0020>; + dma-coherent; + }; + }; + }; + }; + + remoteproc_cdsp1: remoteproc@1f700000 { + compatible = "qcom,nord-cdsp1-pas"; + reg = <0x0 0x1f700000 0x0 0x10000>; + + interrupts-extended = <&intc GIC_SPI 500 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp1_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp1_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp1_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp1_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp1_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + memory-region = <&cdsp1_mem>, + <&q6_cdsp1_dtb_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_cdsp1_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc0 IPCC_MPROC_NSP1 + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_NSP1 + IPCC_MPROC_SIGNAL_GLINK_QMP>; + qcom,remote-pid = <69>; + label = "cdsp"; + + fastrpc { + compatible = "qcom,nord-fastrpc", + "qcom,kaanapali-fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "cdsp1"; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + iommus = <&apps_smmu_2 0x0701 0x0040>, + <&apps_smmu_2 0x0741 0x0040>, + <&apps_smmu_2 0x0761 0x0000>; + dma-coherent; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + iommus = <&apps_smmu_2 0x0702 0x0040>, + <&apps_smmu_2 0x0742 0x0040>, + <&apps_smmu_2 0x0762 0x0000>; + dma-coherent; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu_2 0x0703 0x0040>, + <&apps_smmu_2 0x0743 0x0040>, + <&apps_smmu_2 0x0763 0x0000>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu_2 0x0704 0x0040>, + <&apps_smmu_2 0x0744 0x0040>, + <&apps_smmu_2 0x0764 0x0000>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu_2 0x0705 0x0000>, + <&apps_smmu_2 0x0745 0x0020>, + <&apps_smmu_2 0x0765 0x0020>; + dma-coherent; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu_2 0x0706 0x0040>, + <&apps_smmu_2 0x0746 0x0040>, + <&apps_smmu_2 0x0766 0x0000>; + dma-coherent; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + iommus = <&apps_smmu_2 0x0707 0x0040>, + <&apps_smmu_2 0x0747 0x0040>, + <&apps_smmu_2 0x0767 0x0000>; + dma-coherent; + }; + + compute-cb@8 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <8>; + iommus = <&apps_smmu_2 0x0708 0x0040>, + <&apps_smmu_2 0x0748 0x0040>, + <&apps_smmu_2 0x0768 0x0000>; + dma-coherent; + }; + + compute-cb@9 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <9>; + iommus = <&apps_smmu_2 0x0709 0x0040>, + <&apps_smmu_2 0x0749 0x0040>, + <&apps_smmu_2 0x0769 0x0000>; + dma-coherent; + }; + + compute-cb@10 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <10>; + iommus = <&apps_smmu_2 0x070a 0x0040>, + <&apps_smmu_2 0x074a 0x0040>, + <&apps_smmu_2 0x076a 0x0000>; + dma-coherent; + }; + + compute-cb@11 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <11>; + iommus = <&apps_smmu_2 0x070b 0x0040>, + <&apps_smmu_2 0x074b 0x0040>, + <&apps_smmu_2 0x076b 0x0000>; + dma-coherent; + }; + + compute-cb@12 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <12>; + iommus = <&apps_smmu_2 0x070c 0x0040>, + <&apps_smmu_2 0x074c 0x0040>, + <&apps_smmu_2 0x076c 0x0000>; + dma-coherent; + }; + + compute-cb@13 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <13>; + iommus = <&apps_smmu_2 0x070d 0x0000>, + <&apps_smmu_2 0x074d 0x0020>, + <&apps_smmu_2 0x076d 0x0020>; + dma-coherent; + }; + }; + }; + }; + + remoteproc_cdsp2: remoteproc@1fb00000 { + compatible = "qcom,nord-cdsp2-pas"; + reg = <0x0 0x1fb00000 0x0 0x10000>; + + interrupts-extended = <&intc GIC_SPI 501 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp2_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp2_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp2_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp2_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp2_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + memory-region = <&cdsp2_mem>, + <&q6_cdsp2_dtb_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_cdsp2_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc0 IPCC_MPROC_NSP2 + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_NSP2 + IPCC_MPROC_SIGNAL_GLINK_QMP>; + qcom,remote-pid = <133>; + label = "cdsp"; + + fastrpc { + compatible = "qcom,nord-fastrpc", + "qcom,kaanapali-fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "cdsp2"; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + iommus = <&apps_smmu_2 0x0b01 0x0040>, + <&apps_smmu_2 0x0b41 0x0040>, + <&apps_smmu_2 0x0b61 0x0000>; + dma-coherent; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + iommus = <&apps_smmu_2 0x0b02 0x0040>, + <&apps_smmu_2 0x0b42 0x0040>, + <&apps_smmu_2 0x0b62 0x0000>; + dma-coherent; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu_2 0x0b03 0x0040>, + <&apps_smmu_2 0x0b43 0x0040>, + <&apps_smmu_2 0x0b63 0x0000>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu_2 0x0b04 0x0040>, + <&apps_smmu_2 0x0b44 0x0040>, + <&apps_smmu_2 0x0b64 0x0000>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu_2 0x0b05 0x0000>, + <&apps_smmu_2 0x0b45 0x0020>, + <&apps_smmu_2 0x0b65 0x0020>; + dma-coherent; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu_2 0x0b06 0x0040>, + <&apps_smmu_2 0x0b46 0x0040>, + <&apps_smmu_2 0x0b66 0x0000>; + dma-coherent; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + iommus = <&apps_smmu_2 0x0b07 0x0040>, + <&apps_smmu_2 0x0b47 0x0040>, + <&apps_smmu_2 0x0b67 0x0000>; + dma-coherent; + }; + + compute-cb@8 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <8>; + iommus = <&apps_smmu_2 0x0b08 0x0040>, + <&apps_smmu_2 0x0b48 0x0040>, + <&apps_smmu_2 0x0b68 0x0000>; + dma-coherent; + }; + + compute-cb@9 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <9>; + iommus = <&apps_smmu_2 0x0b09 0x0040>, + <&apps_smmu_2 0x0b49 0x0040>, + <&apps_smmu_2 0x0b69 0x0000>; + dma-coherent; + }; + + compute-cb@10 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <10>; + iommus = <&apps_smmu_2 0x0b0a 0x0040>, + <&apps_smmu_2 0x0b4a 0x0040>, + <&apps_smmu_2 0x0b6a 0x0000>; + dma-coherent; + }; + + compute-cb@11 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <11>; + iommus = <&apps_smmu_2 0x0b0b 0x0040>, + <&apps_smmu_2 0x0b4b 0x0040>, + <&apps_smmu_2 0x0b6b 0x0000>; + dma-coherent; + }; + + compute-cb@12 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <12>; + iommus = <&apps_smmu_2 0x0b0c 0x0040>, + <&apps_smmu_2 0x0b4c 0x0040>, + <&apps_smmu_2 0x0b6c 0x0000>; + dma-coherent; + }; + + compute-cb@13 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <13>; + iommus = <&apps_smmu_2 0x0b0d 0x0000>, + <&apps_smmu_2 0x0b4d 0x0020>, + <&apps_smmu_2 0x0b6d 0x0020>; + dma-coherent; + }; + }; + }; + }; + + remoteproc_cdsp3: remoteproc@1ff00000 { + compatible = "qcom,nord-cdsp3-pas"; + reg = <0x0 0x1ff00000 0x0 0x10000>; + + interrupts-extended = <&intc GIC_SPI 505 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp3_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp3_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp3_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp3_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp3_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + memory-region = <&cdsp3_mem>, + <&q6_cdsp3_dtb_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_cdsp3_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc0 IPCC_MPROC_NSP3 + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_NSP3 + IPCC_MPROC_SIGNAL_GLINK_QMP>; + qcom,remote-pid = <197>; + label = "cdsp"; + + fastrpc { + compatible = "qcom,nord-fastrpc", + "qcom,kaanapali-fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "cdsp3"; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + iommus = <&apps_smmu_2 0x0f01 0x0040>, + <&apps_smmu_2 0x0f41 0x0040>, + <&apps_smmu_2 0x0f61 0x0000>; + dma-coherent; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + iommus = <&apps_smmu_2 0x0f02 0x0040>, + <&apps_smmu_2 0x0f42 0x0040>, + <&apps_smmu_2 0x0f62 0x0000>; + dma-coherent; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu_2 0x0f03 0x0040>, + <&apps_smmu_2 0x0f43 0x0040>, + <&apps_smmu_2 0x0f63 0x0000>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu_2 0x0f04 0x0040>, + <&apps_smmu_2 0x0f44 0x0040>, + <&apps_smmu_2 0x0f64 0x0000>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu_2 0x0f05 0x0000>, + <&apps_smmu_2 0x0f45 0x0020>, + <&apps_smmu_2 0x0f65 0x0020>; + dma-coherent; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu_2 0x0f06 0x0040>, + <&apps_smmu_2 0x0f46 0x0040>, + <&apps_smmu_2 0x0f66 0x0000>; + dma-coherent; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + iommus = <&apps_smmu_2 0x0f07 0x0040>, + <&apps_smmu_2 0x0f47 0x0040>, + <&apps_smmu_2 0x0f67 0x0000>; + dma-coherent; + }; + + compute-cb@8 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <8>; + iommus = <&apps_smmu_2 0x0f08 0x0040>, + <&apps_smmu_2 0x0f48 0x0040>, + <&apps_smmu_2 0x0f68 0x0000>; + dma-coherent; + }; + + compute-cb@9 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <9>; + iommus = <&apps_smmu_2 0x0f09 0x0040>, + <&apps_smmu_2 0x0f49 0x0040>, + <&apps_smmu_2 0x0f69 0x0000>; + dma-coherent; + }; + + compute-cb@10 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <10>; + iommus = <&apps_smmu_2 0x0f0a 0x0040>, + <&apps_smmu_2 0x0f4a 0x0040>, + <&apps_smmu_2 0x0f6a 0x0000>; + dma-coherent; + }; + + compute-cb@11 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <11>; + iommus = <&apps_smmu_2 0x0f0b 0x0040>, + <&apps_smmu_2 0x0f4b 0x0040>, + <&apps_smmu_2 0x0f6b 0x0000>; + dma-coherent; + }; + + compute-cb@12 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <12>; + iommus = <&apps_smmu_2 0x0f0c 0x0040>, + <&apps_smmu_2 0x0f4c 0x0040>, + <&apps_smmu_2 0x0f6c 0x0000>; + dma-coherent; + }; + + compute-cb@13 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <13>; + iommus = <&apps_smmu_2 0x0f0d 0x0000>, + <&apps_smmu_2 0x0f4d 0x0020>, + <&apps_smmu_2 0x0f6d 0x0020>; + dma-coherent; + }; + }; + }; + }; + llcc: system-cache-controller@21800000 { compatible = "qcom,nord-llcc"; reg = <0x0 0x21800000 0x0 0x100000>, From d33e3b306f573b833d85027e8fcfa512c67ba5f3 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 14 Oct 2026 14:39:48 +0800 Subject: [PATCH 0204/1133] FROMLIST: arm64: dts: qcom: nord-rrd: Enable ADSP and CDSPs Enable ADSP (HPASS DSP) and CDSPs remoteproc on the Nord RRD board. Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261014063953.549379-4-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index 3673003c8b213..0b0acd33a2e19 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -393,6 +393,41 @@ status = "okay"; }; +&remoteproc_adsp { + firmware-name = "qcom/nord/adsp.mbn", + "qcom/nord/adsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp0 { + firmware-name = "qcom/nord/cdsp.mbn", + "qcom/nord/cdsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp1 { + firmware-name = "qcom/nord/cdsp.mbn", + "qcom/nord/cdsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp2 { + firmware-name = "qcom/nord/cdsp.mbn", + "qcom/nord/cdsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp3 { + firmware-name = "qcom/nord/cdsp.mbn", + "qcom/nord/cdsp_dtb.mbn"; + + status = "okay"; +}; + &spi16 { status = "okay"; }; From ca57eebc7d14409c2c696572357b5ebcb222293d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 14 Oct 2026 14:39:49 +0800 Subject: [PATCH 0205/1133] FROMLIST: arm64: dts: qcom: nord: Add the SPMI PMIC arbiter Add the SPMI PMIC Arbiter node for the Nord platforms. Signed-off-by: Bartosz Golaszewski Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20261014063953.549379-5-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord.dtsi | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index c4f38335c90ca..41b4f0bde0ec5 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -2203,6 +2203,28 @@ #clock-cells = <0>; }; + spmi_bus: spmi@c400000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x0 0x0c400000 0x0 0x3000>, + <0x0 0x0c500000 0x0 0x400000>, + <0x0 0x0c440000 0x0 0x80000>, + <0x0 0x0c4c0000 0x0 0x10000>, + <0x0 0x0c42d000 0x0 0x4000>; + reg-names = "core", + "chnls", + "obsrvr", + "intr", + "cnfg"; + interrupts-extended = <&pdc 1 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "periph_irq"; + interrupt-controller; + #interrupt-cells = <4>; + #address-cells = <2>; + #size-cells = <0>; + qcom,channel = <0>; + qcom,ee = <0>; + }; + tlmm: pinctrl@f100000 { compatible = "qcom,nord-tlmm"; reg = <0x0 0x0f100000 0x0 0xc0000>; From 9c50138bd5569b9a9f59ca5afb3ec624a57e58aa Mon Sep 17 00:00:00 2001 From: Dhruvin Rajpura Date: Wed, 14 Oct 2026 14:39:50 +0800 Subject: [PATCH 0206/1133] FROMLIST: arm64: dts: qcom: nord: Add PMAU0102 and PMM8650AU PMIC support The Nord platform is supplied by two families of PMICs on the SPMI bus: eight PMAU0102 devices on USIDs 4 to 11, and one PMM8650AU on USID 0. Add one dtsi per PMIC type, following the established one-file-per-PMIC convention, and include both of them from nord-rrd.dts. The eight PMAU0102 instances are labelled pmau0102_e through pmau0102_l after their board designators. Each one provides a GPIO controller, an ADC, and an MBG (Master Bandgap) temperature monitor that reads its die temperature through a DIE_TEMP ADC channel. The monitors use the qcom,pmau0102-mbg-tm compatible with qcom,pm8775-mbg-tm as fallback, and each is hooked up to a thermal zone. PMM8650AU is the same die as PMM8654AU, so pmm8650au_a reuses the existing pmm8654au ompatibles while the file is named after the part actually populated on the board. It provides PON with a power key, a RTC, and a GPIO controller. The resin is described but left disabled, for boards that wire it up to enable. Signed-off-by: Dhruvin Rajpura Acked-by: Konrad Dybcio Reviewed-by: Abel Vesa Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261014063953.549379-6-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 2 + arch/arm64/boot/dts/qcom/pmau0102-nord.dtsi | 543 +++++++++++++++++++ arch/arm64/boot/dts/qcom/pmm8650au-nord.dtsi | 54 ++ 3 files changed, 599 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/pmau0102-nord.dtsi create mode 100644 arch/arm64/boot/dts/qcom/pmm8650au-nord.dtsi diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index 0b0acd33a2e19..47978df0af92d 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -9,6 +9,8 @@ #include #include "nord-embedded.dtsi" +#include "pmau0102-nord.dtsi" +#include "pmm8650au-nord.dtsi" / { model = "Qualcomm Technologies, Inc. IQ10 RRD"; diff --git a/arch/arm64/boot/dts/qcom/pmau0102-nord.dtsi b/arch/arm64/boot/dts/qcom/pmau0102-nord.dtsi new file mode 100644 index 0000000000000..47ea145f4abb1 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/pmau0102-nord.dtsi @@ -0,0 +1,543 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +#include "qcom-adc5-gen3.h" + +&spmi_bus { + pmau0102_e: pmic@4 { + compatible = "qcom,pmau0102", "qcom,spmi-pmic"; + reg = <0x4 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmau0102_e_mbg_temp: temperature-sensor@d700 { + compatible = "qcom,pmau0102-mbg-tm", "qcom,pm8775-mbg-tm"; + reg = <0xd700>; + interrupts-extended = <&spmi_bus 0x4 0xd7 0x0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pmau0102_e_adc ADC5_GEN3_DIE_TEMP(4)>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pmau0102_e_adc: adc@7200 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x7200>; + #address-cells = <1>; + #size-cells = <0>; + interrupts-extended = <&spmi_bus 0x4 0x72 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@400 { + reg = ; + label = "pmau0102_e_ref_gnd"; + qcom,pre-scaling = <1 1>; + }; + + channel@401 { + reg = ; + label = "pmau0102_e_vref_1p25"; + qcom,pre-scaling = <1 1>; + }; + + channel@403 { + reg = ; + label = "pmau0102_e_die_temp"; + qcom,pre-scaling = <1 1>; + }; + }; + + pmau0102_e_gpios: gpio@8800 { + compatible = "qcom,pmau0102-gpio", "qcom,spmi-gpio"; + reg = <0x8800>; + gpio-controller; + gpio-ranges = <&pmau0102_e_gpios 0 0 12>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + pmau0102_f: pmic@5 { + compatible = "qcom,pmau0102", "qcom,spmi-pmic"; + reg = <0x5 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmau0102_f_mbg_temp: temperature-sensor@d700 { + compatible = "qcom,pmau0102-mbg-tm", "qcom,pm8775-mbg-tm"; + reg = <0xd700>; + interrupts-extended = <&spmi_bus 0x5 0xd7 0x0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pmau0102_f_adc ADC5_GEN3_DIE_TEMP(5)>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pmau0102_f_adc: adc@7200 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x7200>; + #address-cells = <1>; + #size-cells = <0>; + interrupts-extended = <&spmi_bus 0x5 0x72 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@500 { + reg = ; + label = "pmau0102_f_ref_gnd"; + qcom,pre-scaling = <1 1>; + }; + + channel@501 { + reg = ; + label = "pmau0102_f_vref_1p25"; + qcom,pre-scaling = <1 1>; + }; + + channel@503 { + reg = ; + label = "pmau0102_f_die_temp"; + qcom,pre-scaling = <1 1>; + }; + }; + + pmau0102_f_gpios: gpio@8800 { + compatible = "qcom,pmau0102-gpio", "qcom,spmi-gpio"; + reg = <0x8800>; + gpio-controller; + gpio-ranges = <&pmau0102_f_gpios 0 0 12>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + pmau0102_g: pmic@6 { + compatible = "qcom,pmau0102", "qcom,spmi-pmic"; + reg = <0x6 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmau0102_g_mbg_temp: temperature-sensor@d700 { + compatible = "qcom,pmau0102-mbg-tm", "qcom,pm8775-mbg-tm"; + reg = <0xd700>; + interrupts-extended = <&spmi_bus 0x6 0xd7 0x0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pmau0102_g_adc ADC5_GEN3_DIE_TEMP(6)>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pmau0102_g_adc: adc@7200 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x7200>; + #address-cells = <1>; + #size-cells = <0>; + interrupts-extended = <&spmi_bus 0x6 0x72 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@600 { + reg = ; + label = "pmau0102_g_ref_gnd"; + qcom,pre-scaling = <1 1>; + }; + + channel@601 { + reg = ; + label = "pmau0102_g_vref_1p25"; + qcom,pre-scaling = <1 1>; + }; + + channel@603 { + reg = ; + label = "pmau0102_g_die_temp"; + qcom,pre-scaling = <1 1>; + }; + }; + + pmau0102_g_gpios: gpio@8800 { + compatible = "qcom,pmau0102-gpio", "qcom,spmi-gpio"; + reg = <0x8800>; + gpio-controller; + gpio-ranges = <&pmau0102_g_gpios 0 0 12>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + pmau0102_h: pmic@7 { + compatible = "qcom,pmau0102", "qcom,spmi-pmic"; + reg = <0x7 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmau0102_h_mbg_temp: temperature-sensor@d700 { + compatible = "qcom,pmau0102-mbg-tm", "qcom,pm8775-mbg-tm"; + reg = <0xd700>; + interrupts-extended = <&spmi_bus 0x7 0xd7 0x0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pmau0102_h_adc ADC5_GEN3_DIE_TEMP(7)>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pmau0102_h_adc: adc@7200 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x7200>; + #address-cells = <1>; + #size-cells = <0>; + interrupts-extended = <&spmi_bus 0x7 0x72 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@700 { + reg = ; + label = "pmau0102_h_ref_gnd"; + qcom,pre-scaling = <1 1>; + }; + + channel@701 { + reg = ; + label = "pmau0102_h_vref_1p25"; + qcom,pre-scaling = <1 1>; + }; + + channel@703 { + reg = ; + label = "pmau0102_h_die_temp"; + qcom,pre-scaling = <1 1>; + }; + }; + + pmau0102_h_gpios: gpio@8800 { + compatible = "qcom,pmau0102-gpio", "qcom,spmi-gpio"; + reg = <0x8800>; + gpio-controller; + gpio-ranges = <&pmau0102_h_gpios 0 0 12>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + pmau0102_i: pmic@8 { + compatible = "qcom,pmau0102", "qcom,spmi-pmic"; + reg = <0x8 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmau0102_i_mbg_temp: temperature-sensor@d700 { + compatible = "qcom,pmau0102-mbg-tm", "qcom,pm8775-mbg-tm"; + reg = <0xd700>; + interrupts-extended = <&spmi_bus 0x8 0xd7 0x0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pmau0102_i_adc ADC5_GEN3_DIE_TEMP(8)>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pmau0102_i_adc: adc@7200 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x7200>; + #address-cells = <1>; + #size-cells = <0>; + interrupts-extended = <&spmi_bus 0x8 0x72 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@800 { + reg = ; + label = "pmau0102_i_ref_gnd"; + qcom,pre-scaling = <1 1>; + }; + + channel@801 { + reg = ; + label = "pmau0102_i_vref_1p25"; + qcom,pre-scaling = <1 1>; + }; + + channel@803 { + reg = ; + label = "pmau0102_i_die_temp"; + qcom,pre-scaling = <1 1>; + }; + }; + + pmau0102_i_gpios: gpio@8800 { + compatible = "qcom,pmau0102-gpio", "qcom,spmi-gpio"; + reg = <0x8800>; + gpio-controller; + gpio-ranges = <&pmau0102_i_gpios 0 0 12>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + pmau0102_j: pmic@9 { + compatible = "qcom,pmau0102", "qcom,spmi-pmic"; + reg = <0x9 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmau0102_j_mbg_temp: temperature-sensor@d700 { + compatible = "qcom,pmau0102-mbg-tm", "qcom,pm8775-mbg-tm"; + reg = <0xd700>; + interrupts-extended = <&spmi_bus 0x9 0xd7 0x0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pmau0102_j_adc ADC5_GEN3_DIE_TEMP(9)>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pmau0102_j_adc: adc@7200 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x7200>; + #address-cells = <1>; + #size-cells = <0>; + interrupts-extended = <&spmi_bus 0x9 0x72 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@900 { + reg = ; + label = "pmau0102_j_ref_gnd"; + qcom,pre-scaling = <1 1>; + }; + + channel@901 { + reg = ; + label = "pmau0102_j_vref_1p25"; + qcom,pre-scaling = <1 1>; + }; + + channel@903 { + reg = ; + label = "pmau0102_j_die_temp"; + qcom,pre-scaling = <1 1>; + }; + }; + + pmau0102_j_gpios: gpio@8800 { + compatible = "qcom,pmau0102-gpio", "qcom,spmi-gpio"; + reg = <0x8800>; + gpio-controller; + gpio-ranges = <&pmau0102_j_gpios 0 0 12>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + pmau0102_k: pmic@a { + compatible = "qcom,pmau0102", "qcom,spmi-pmic"; + reg = <0xa SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmau0102_k_mbg_temp: temperature-sensor@d700 { + compatible = "qcom,pmau0102-mbg-tm", "qcom,pm8775-mbg-tm"; + reg = <0xd700>; + interrupts-extended = <&spmi_bus 0xa 0xd7 0x0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pmau0102_k_adc ADC5_GEN3_DIE_TEMP(0xa)>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pmau0102_k_adc: adc@7200 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x7200>; + #address-cells = <1>; + #size-cells = <0>; + interrupts-extended = <&spmi_bus 0xa 0x72 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@a00 { + reg = ; + label = "pmau0102_k_ref_gnd"; + qcom,pre-scaling = <1 1>; + }; + + channel@a01 { + reg = ; + label = "pmau0102_k_vref_1p25"; + qcom,pre-scaling = <1 1>; + }; + + channel@a03 { + reg = ; + label = "pmau0102_k_die_temp"; + qcom,pre-scaling = <1 1>; + }; + }; + + pmau0102_k_gpios: gpio@8800 { + compatible = "qcom,pmau0102-gpio", "qcom,spmi-gpio"; + reg = <0x8800>; + gpio-controller; + gpio-ranges = <&pmau0102_k_gpios 0 0 12>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + pmau0102_l: pmic@b { + compatible = "qcom,pmau0102", "qcom,spmi-pmic"; + reg = <0xb SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmau0102_l_mbg_temp: temperature-sensor@d700 { + compatible = "qcom,pmau0102-mbg-tm", "qcom,pm8775-mbg-tm"; + reg = <0xd700>; + interrupts-extended = <&spmi_bus 0xb 0xd7 0x0 IRQ_TYPE_EDGE_RISING>; + io-channels = <&pmau0102_l_adc ADC5_GEN3_DIE_TEMP(0xb)>; + io-channel-names = "thermal"; + #thermal-sensor-cells = <0>; + }; + + pmau0102_l_adc: adc@7200 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x7200>; + #address-cells = <1>; + #size-cells = <0>; + interrupts-extended = <&spmi_bus 0xb 0x72 0x1 IRQ_TYPE_EDGE_RISING>; + #io-channel-cells = <1>; + + channel@b00 { + reg = ; + label = "pmau0102_l_ref_gnd"; + qcom,pre-scaling = <1 1>; + }; + + channel@b01 { + reg = ; + label = "pmau0102_l_vref_1p25"; + qcom,pre-scaling = <1 1>; + }; + + channel@b03 { + reg = ; + label = "pmau0102_l_die_temp"; + qcom,pre-scaling = <1 1>; + }; + }; + + pmau0102_l_gpios: gpio@8800 { + compatible = "qcom,pmau0102-gpio", "qcom,spmi-gpio"; + reg = <0x8800>; + gpio-controller; + gpio-ranges = <&pmau0102_l_gpios 0 0 12>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; +}; + +/ { + thermal-zones { + pmau0102_e_thermal: pmau0102-e-thermal { + polling-delay-passive = <100>; + thermal-sensors = <&pmau0102_e_mbg_temp>; + + trips { + trip0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + }; + + pmau0102_f_thermal: pmau0102-f-thermal { + polling-delay-passive = <100>; + thermal-sensors = <&pmau0102_f_mbg_temp>; + + trips { + trip0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + }; + + pmau0102_g_thermal: pmau0102-g-thermal { + polling-delay-passive = <100>; + thermal-sensors = <&pmau0102_g_mbg_temp>; + + trips { + trip0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + }; + + pmau0102_h_thermal: pmau0102-h-thermal { + polling-delay-passive = <100>; + thermal-sensors = <&pmau0102_h_mbg_temp>; + + trips { + trip0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + }; + + pmau0102_i_thermal: pmau0102-i-thermal { + polling-delay-passive = <100>; + thermal-sensors = <&pmau0102_i_mbg_temp>; + + trips { + trip0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + }; + + pmau0102_j_thermal: pmau0102-j-thermal { + polling-delay-passive = <100>; + thermal-sensors = <&pmau0102_j_mbg_temp>; + + trips { + trip0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + }; + + pmau0102_k_thermal: pmau0102-k-thermal { + polling-delay-passive = <100>; + thermal-sensors = <&pmau0102_k_mbg_temp>; + + trips { + trip0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + }; + + pmau0102_l_thermal: pmau0102-l-thermal { + polling-delay-passive = <100>; + thermal-sensors = <&pmau0102_l_mbg_temp>; + + trips { + trip0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/pmm8650au-nord.dtsi b/arch/arm64/boot/dts/qcom/pmm8650au-nord.dtsi new file mode 100644 index 0000000000000..1282e5bae591d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/pmm8650au-nord.dtsi @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include + +&spmi_bus { + pmm8650au_a: pmic@0 { + compatible = "qcom,pmm8654au", "qcom,spmi-pmic"; + reg = <0x0 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmm8650au_a_pon: pon@1200 { + compatible = "qcom,pmm8654au-pon", "qcom,pmk8350-pon"; + reg = <0x1200>, <0x800>; + reg-names = "hlos", "pbs"; + + pmm8650au_a_pon_pwrkey: pwrkey { + compatible = "qcom,pmm8654au-pwrkey", "qcom,pmk8350-pwrkey"; + interrupts-extended = <&spmi_bus 0x0 0x12 0x7 IRQ_TYPE_EDGE_BOTH>; + linux,code = ; + debounce = <15625>; + }; + + pmm8650au_a_pon_resin: resin { + compatible = "qcom,pmm8654au-resin", "qcom,pmk8350-resin"; + interrupts-extended = <&spmi_bus 0x0 0x12 0x6 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + status = "disabled"; + }; + }; + + pmm8650au_a_rtc: rtc@6100 { + compatible = "qcom,pmm8654au-rtc", "qcom,pmk8350-rtc"; + reg = <0x6100>, <0x6200>; + reg-names = "rtc", "alarm"; + interrupts-extended = <&spmi_bus 0x0 0x62 0x1 IRQ_TYPE_EDGE_RISING>; + }; + + pmm8650au_a_gpios: gpio@8800 { + compatible = "qcom,pmm8654au-gpio", "qcom,spmi-gpio"; + reg = <0x8800>; + gpio-controller; + gpio-ranges = <&pmm8650au_a_gpios 0 0 12>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; +}; From 55113ec19e19ee8164d8485a644878deaad78674 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 14 Oct 2026 14:39:51 +0800 Subject: [PATCH 0207/1133] FROMLIST: dt-bindings: arm: qcom: Document Nord Ride Embedded board Document qcom,sa8797p-ride-embedded, the Embedded variant of the Nord SA8797P Ride board. Signed-off-by: Bartosz Golaszewski Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20261014063953.549379-7-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/qcom.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 121ca557ce1ef..7557efa4e1688 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -434,6 +434,7 @@ properties: - enum: - qcom,iq10-rrd - qcom,sa8797p-ride + - qcom,sa8797p-ride-embedded - const: qcom,nord - description: Qualcomm Technologies, Inc. Robotics RB1 From 9fe9cf2c0016d7b4bed818bacaaef9051beaac2d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 14 Oct 2026 14:39:52 +0800 Subject: [PATCH 0208/1133] FROMLIST: arm64: dts: qcom: Add initial support for Nord Ride Embedded board Add the initial device tree for the Nord Ride Embedded board, the non-SCMI variant of the SA8797P automotive Ride board. Enable the debug UART, UFS storage, the ADSP and CDSP remote processors, and describe the board regulators supplied by the on-board PMICs. Signed-off-by: Bartosz Golaszewski Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20261014063953.549379-8-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/Makefile | 1 + .../boot/dts/qcom/nord-ride-embedded.dts | 442 ++++++++++++++++++ 2 files changed, 443 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/nord-ride-embedded.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..b77bbc5030d8c 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -174,6 +174,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-maple.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-poplar.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8998-xiaomi-sagit.dtb dtb-$(CONFIG_ARCH_QCOM) += nord-ride.dtb +dtb-$(CONFIG_ARCH_QCOM) += nord-ride-embedded.dtb dtb-$(CONFIG_ARCH_QCOM) += nord-rrd.dtb dtb-$(CONFIG_ARCH_QCOM) += purwa-iot-evk.dtb diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts new file mode 100644 index 0000000000000..49635695f832e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include +#include + +#include "nord-embedded.dtsi" +#include "pmau0102-nord.dtsi" +#include "pmm8650au-nord.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SA8797P Ride"; + compatible = "qcom,sa8797p-ride-embedded", "qcom,nord"; + + aliases { + serial0 = &uart15; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + clocks { + xo_board: xo-board-clk { + compatible = "fixed-clock"; + clock-frequency = <38400000>; + #clock-cells = <0>; + }; + + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + clock-frequency = <32000>; + #clock-cells = <0>; + }; + + bi_tcxo_div2: bi-tcxo-div2-clk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-mult = <1>; + clock-div = <2>; + }; + + bi_tcxo_ao_div2: bi-tcxo-ao-div2-clk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clocks = <&rpmhcc RPMH_CXO_CLK_A>; + clock-mult = <1>; + clock-div = <2>; + }; + }; +}; + +&apps_rsc { + /* PMIC A - Kobra_MM (PMM8650AU) - SID 0x0, Bus E0 */ + regulators-0 { + compatible = "qcom,pmm8654au-rpmh-regulators"; + qcom,pmic-id = "A_E0"; + + vreg_l4a_1p2: ldo4 { + regulator-name = "vreg_l4a_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l6a_1p2: ldo6 { + regulator-name = "vreg_l6a_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7a_1p2: ldo7 { + regulator-name = "vreg_l7a_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l8a_1p8: ldo8 { + regulator-name = "vreg_l8a_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_s1a_vdd2h_l: smps1 { + regulator-name = "vreg_s1a_vdd2h_l"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1100000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + }; + + vreg_s3a_1p8: smps3 { + regulator-name = "vreg_s3a_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + }; + + vreg_s5a_mv: smps5 { + regulator-name = "vreg_s5a_mv"; + regulator-min-microvolt = <1328000>; + regulator-max-microvolt = <1370000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + }; + + vreg_s6a_vddq_l: smps6 { + regulator-name = "vreg_s6a_vddq_l"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <570000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + /* PMIC E - Kai_MV - SID 0x4, Bus E0 */ + regulators-1 { + compatible = "qcom,pmau0102-rpmh-regulators"; + qcom,pmic-id = "E_E0"; + + vreg_l1e_0p9: ldo1 { + regulator-name = "vreg_l1e_0p9"; + regulator-min-microvolt = <936000>; + regulator-max-microvolt = <936000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2e_0p9: ldo2 { + regulator-name = "vreg_l2e_0p9"; + regulator-min-microvolt = <936000>; + regulator-max-microvolt = <936000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3e_1p8: ldo3 { + regulator-name = "vreg_l3e_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + /* PMIC F - Kai_MV - SID 0x5, Bus E0 */ + regulators-2 { + compatible = "qcom,pmau0102-rpmh-regulators"; + qcom,pmic-id = "F_E0"; + + vreg_l1f_vdd2l: ldo1 { + regulator-name = "vreg_l1f_vdd2l"; + regulator-min-microvolt = <904000>; + regulator-max-microvolt = <904000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3f_vdd1: ldo3 { + regulator-name = "vreg_l3f_vdd1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_s7f_lv_sub: smps7 { + regulator-name = "vreg_s7f_lv_sub"; + regulator-min-microvolt = <1036000>; + regulator-max-microvolt = <1136000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + }; + + vreg_s8f_vddq_h: smps8 { + regulator-name = "vreg_s8f_vddq_h"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <570000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + /* PMIC G - Kai_MV - SID 0x6, Bus E0 */ + regulators-3 { + compatible = "qcom,pmau0102-rpmh-regulators"; + qcom,pmic-id = "G_E0"; + + vreg_l2g_0p7: ldo2 { + regulator-name = "vreg_l2g_0p7"; + regulator-min-microvolt = <752000>; + regulator-max-microvolt = <752000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_s5g_vdd2h_h: smps5 { + regulator-name = "vreg_s5g_vdd2h_h"; + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <1150000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + }; + }; + + /* PMIC H - Kai_MV - SID 0x7, Bus E0 */ + regulators-4 { + compatible = "qcom,pmau0102-rpmh-regulators"; + qcom,pmic-id = "H_E0"; + + vreg_l1h_0p9: ldo1 { + regulator-name = "vreg_l1h_0p9"; + regulator-min-microvolt = <904000>; + regulator-max-microvolt = <904000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2h_1p2: ldo2 { + regulator-name = "vreg_l2h_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + }; + + /* PMIC I - Kai_MV - SID 0x8, Bus E0 */ + regulators-5 { + compatible = "qcom,pmau0102-rpmh-regulators"; + qcom,pmic-id = "I_E0"; + + vreg_l1i_0p9: ldo1 { + regulator-name = "vreg_l1i_0p9"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <912000>; + regulator-initial-mode = ; + }; + + vreg_l2i_1p2: ldo2 { + regulator-name = "vreg_l2i_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3i_2p5: ldo3 { + regulator-name = "vreg_l3i_2p5"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <2504000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + /* PMIC K - Kai_MV - SID 0xA, Bus E0 */ + regulators-6 { + compatible = "qcom,pmau0102-rpmh-regulators"; + qcom,pmic-id = "K_E0"; + + vreg_l1k_vdd2l: ldo1 { + regulator-name = "vreg_l1k_vdd2l"; + regulator-min-microvolt = <904000>; + regulator-max-microvolt = <904000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2k_0p9: ldo2 { + regulator-name = "vreg_l2k_0p9"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <880000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3k_vdd1: ldo3 { + regulator-name = "vreg_l3k_vdd1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-always-on; + regulator-boot-on; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + /* PMIC L - Kai_MV - SID 0xB, Bus E0 */ + regulators-7 { + compatible = "qcom,pmau0102-rpmh-regulators"; + qcom,pmic-id = "L_E0"; + + vreg_l3l_1p8: ldo3 { + regulator-name = "vreg_l3l_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; +}; + +&qupv3_0 { + firmware-name = "qcom/nord/qupv3fw.elf"; + + status = "okay"; +}; + +&qupv3_1 { + firmware-name = "qcom/nord/qupv3fw.elf"; + + status = "okay"; +}; + +&qupv3_2 { + firmware-name = "qcom/nord/qupv3fw.elf"; + + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/nord/adsp.mbn", + "qcom/nord/adsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp0 { + firmware-name = "qcom/nord/cdsp.mbn", + "qcom/nord/cdsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp1 { + firmware-name = "qcom/nord/cdsp.mbn", + "qcom/nord/cdsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp2 { + firmware-name = "qcom/nord/cdsp.mbn", + "qcom/nord/cdsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp3 { + firmware-name = "qcom/nord/cdsp.mbn", + "qcom/nord/cdsp_dtb.mbn"; + + status = "okay"; +}; + +&uart15 { + status = "okay"; +}; + +&ufs_mem_hc { + reset-gpios = <&tlmm 181 GPIO_ACTIVE_LOW>; + + vcc-supply = <&vreg_l3i_2p5>; + vcc-max-microamp = <1300000>; + vccq-supply = <&vreg_l2i_1p2>; + vccq-max-microamp = <1200000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l1i_0p9>; + vdda-pll-supply = <&vreg_l2h_1p2>; + + status = "okay"; +}; From 7b54d5444fb872e0b037a610bba99160276e0d90 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Sun, 1 Nov 2026 11:09:02 +0800 Subject: [PATCH 0209/1133] FROMLIST: iio: adc: qcom-spmi-adc5-gen3: Reuse IIO device ID for ADC_TM aux device adc5_gen3_add_aux_tm_device() never sets the auxiliary device id, so every ADC5 Gen3 instance with at least one qcom,adc-tm channel tries to register the same device name. With ADC_TM channels on more than one PMIC, the second instance to probe fails: sysfs: cannot create duplicate filename '/bus/auxiliary/devices/qcom_spmi_adc5_gen3.adc5_tm_gen3.0' ... auxiliary qcom_spmi_adc5_gen3.adc5_tm_gen3.0: adding auxiliary device failed!: -17 qcom-spmi-adc5-gen3 c400000.spmi:pmic@8:adc@7200: error -EEXIST: Failed to add auxiliary TM device The ADC probe then fails as a whole, so that PMIC loses both its IIO channels and its thermal zones. This shows up on Nord, which has thermistor channels on two PMAU0102 PMICs. Each ADC instance already has a unique IIO device ID. Use it as the auxiliary device id instead of allocating one from a separate driver-wide IDA, which removes the custom ID allocation and release handling. The ADC_TM driver matches on the device name only, so the instance number does not affect binding. Fixes: baff45179e90 ("iio: adc: Add support for QCOM PMIC5 Gen3 ADC") Signed-off-by: Loic Poulain Link: https://lore.kernel.org/r/20261101030902.1387122-1-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- drivers/iio/adc/qcom-spmi-adc5-gen3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/qcom-spmi-adc5-gen3.c b/drivers/iio/adc/qcom-spmi-adc5-gen3.c index c68c6c5f6aca0..a23eb5c9096d7 100644 --- a/drivers/iio/adc/qcom-spmi-adc5-gen3.c +++ b/drivers/iio/adc/qcom-spmi-adc5-gen3.c @@ -610,7 +610,7 @@ static void adc5_gen3_delete_aux(void *data) static void adc5_gen3_aux_device_release(struct device *dev) {} -static int adc5_gen3_add_aux_tm_device(struct adc5_chip *adc) +static int adc5_gen3_add_aux_tm_device(struct adc5_chip *adc, int id) { struct tm5_aux_dev_wrapper *aux_device; int i, ret, i_tm = 0; @@ -620,6 +620,7 @@ static int adc5_gen3_add_aux_tm_device(struct adc5_chip *adc) return -ENOMEM; aux_device->aux_dev.name = "adc5_tm_gen3"; + aux_device->aux_dev.id = id; aux_device->aux_dev.dev.parent = adc->dev; aux_device->aux_dev.dev.release = adc5_gen3_aux_device_release; @@ -799,7 +800,7 @@ static int adc5_gen3_probe(struct platform_device *pdev) return ret; if (adc->n_tm_channels > 0) { - ret = adc5_gen3_add_aux_tm_device(adc); + ret = adc5_gen3_add_aux_tm_device(adc, iio_device_id(indio_dev)); if (ret) dev_err_probe(dev, ret, "Failed to add auxiliary TM device\n"); From 7bcd4e5713e9d6035d12770045c1675f4a0df613 Mon Sep 17 00:00:00 2001 From: Dhruvin Rajpura Date: Wed, 28 Oct 2026 23:01:03 +0800 Subject: [PATCH 0210/1133] FROMLIST: arm64: dts: qcom: nord: add ADC-TM thermistor channels for Nord PMICs PMAU0102 (Kai_MV) and PMM8650AU's Kobra_MM ADC5 Gen3 controllers only expose REF_GND/1P25VREF/DIE_TEMP calibration channels; none of their AMUX thermistor pins are wired up, so none of the board thermistor rails feed the thermal framework. Only 3 AMUX pins are actually wired to thermistors on Nord, all on Kai and none on Kobra: Kai instance E's AMUX1 (SDRAM3 THERM) and Kai instance I's AMUX1/AMUX2 (SDRAM1 THERM, UFS THERM). Kai's other AMUX pins are either DO_NOT_USE or wired to voltage-rail monitors, not thermistors, so add only these 3 channels. Add #thermal-sensor-cells = <1> to the two Kai adc@ nodes that gain a channel, the new AMUX1[/AMUX2]_THM channel(s) with qcom,adc-tm, and a per-channel thermal-zone for each, following the existing Gen3/Gen4 board pattern of a direct thermal-sensors phandle into the ADC channel. Signed-off-by: Dhruvin Rajpura Acked-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261028150103.520428-1-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/pmau0102-nord.dtsi | 80 +++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pmau0102-nord.dtsi b/arch/arm64/boot/dts/qcom/pmau0102-nord.dtsi index 47ea145f4abb1..6230fed2374ce 100644 --- a/arch/arm64/boot/dts/qcom/pmau0102-nord.dtsi +++ b/arch/arm64/boot/dts/qcom/pmau0102-nord.dtsi @@ -31,6 +31,7 @@ #size-cells = <0>; interrupts-extended = <&spmi_bus 0x4 0x72 0x1 IRQ_TYPE_EDGE_RISING>; #io-channel-cells = <1>; + #thermal-sensor-cells = <1>; channel@400 { reg = ; @@ -49,6 +50,14 @@ label = "pmau0102_e_die_temp"; qcom,pre-scaling = <1 1>; }; + + channel@444 { + reg = ; + label = "pmau0102_e_sdram3_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; }; pmau0102_e_gpios: gpio@8800 { @@ -243,6 +252,7 @@ #size-cells = <0>; interrupts-extended = <&spmi_bus 0x8 0x72 0x1 IRQ_TYPE_EDGE_RISING>; #io-channel-cells = <1>; + #thermal-sensor-cells = <1>; channel@800 { reg = ; @@ -261,6 +271,22 @@ label = "pmau0102_i_die_temp"; qcom,pre-scaling = <1 1>; }; + + channel@844 { + reg = ; + label = "pmau0102_i_sdram1_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + channel@845 { + reg = ; + label = "pmau0102_i_ufs_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; }; pmau0102_i_gpios: gpio@8800 { @@ -449,6 +475,24 @@ }; }; + pmau0102_e_sdram3_thermal: pm-e-sdram3-thermal { + thermal-sensors = <&pmau0102_e_adc ADC5_GEN3_AMUX1_THM_100K_PU(4)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + pmau0102_f_thermal: pmau0102-f-thermal { polling-delay-passive = <100>; thermal-sensors = <&pmau0102_f_mbg_temp>; @@ -501,6 +545,42 @@ }; }; + pmau0102_i_sdram1_thermal: pm-i-sdram1-thermal { + thermal-sensors = <&pmau0102_i_adc ADC5_GEN3_AMUX1_THM_100K_PU(8)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + pmau0102_i_ufs_thermal: pm-i-ufs-thermal { + thermal-sensors = <&pmau0102_i_adc ADC5_GEN3_AMUX2_THM_100K_PU(8)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + pmau0102_j_thermal: pmau0102-j-thermal { polling-delay-passive = <100>; thermal-sensors = <&pmau0102_j_mbg_temp>; From fc1c2787407165d4d26ab342e0014ce0181f13fe Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Wed, 14 Oct 2026 17:16:09 +0530 Subject: [PATCH 0211/1133] FROMLIST: dt-bindings: remoteproc: qcom,kaanapali-soccp-pas: Add Nord SoCCP The SoCCP (SoC Control Processor) on Nord handles hardware fencing for display and other use cases. It shares interrupts, SMP2P states, power domains, and clock with Kaanapali SoCCP, except that it ships firmware without a separate devicetree image, so it cannot use the Kaanapali compatible as fallback. Add qcom,nord-soccp-pas as a standalone compatible with a single firmware-name/memory-region pair, while existing SoCs keep requiring two. Reviewed-by: Rob Herring (Arm) Reviewed-by: Shawn Guo Signed-off-by: Anurag Pateriya Link: https://lore.kernel.org/r/20261014-soccp_driver_dtbinding-v2-1-09d9c1378e9e@oss.qualcomm.com --- .../remoteproc/qcom,kaanapali-soccp-pas.yaml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml index e6c78d621d17c..c1911124e0738 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml @@ -26,6 +26,7 @@ properties: - enum: - qcom,glymur-soccp-pas - qcom,kaanapali-soccp-pas + - qcom,nord-soccp-pas reg: maxItems: 1 @@ -49,11 +50,13 @@ properties: - const: mx firmware-name: + minItems: 1 items: - description: Firmware name of the SoC Control Processor - description: Firmware name of the SoCCP Devicetree memory-region: + minItems: 1 items: - description: Memory region for main Firmware authentication - description: Memory region for Devicetree Firmware authentication @@ -93,6 +96,23 @@ required: allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# + - if: + properties: + compatible: + contains: + const: qcom,nord-soccp-pas + then: + properties: + firmware-name: + maxItems: 1 + memory-region: + maxItems: 1 + else: + properties: + firmware-name: + minItems: 2 + memory-region: + minItems: 2 unevaluatedProperties: false From 9481cd8b282ae4382b0100dec00fcca888d5edf5 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Wed, 14 Oct 2026 17:16:10 +0530 Subject: [PATCH 0212/1133] FROMLIST: remoteproc: qcom_q6v5_pas: Add remoteproc support for SOCCP on Nord The SoC Control Processor (SoCCP) is a dedicated control processor that handles hardware fencing for display and other use cases on Nord based devices. For Nord, SoCCP firmware ships without a separate SoCCP devicetree image. Therefore, it takes a single firmware-name and memory-region. Add support for SoCCP PAS loader on Nord platform. Signed-off-by: Anurag Pateriya Reviewed-by: Shawn Guo Acked-by: Konrad Dybcio Link: https://lore.kernel.org/r/20261014-soccp_driver_dtbinding-v2-2-09d9c1378e9e@oss.qualcomm.com --- drivers/remoteproc/qcom_q6v5_pas.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index acd47c49af537..913253762f456 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -1684,6 +1684,20 @@ static const struct qcom_pas_data nord_cdsp3_resource = { .smem_host_id = 197, }; +static const struct qcom_pas_data nord_soccp_resource = { + .crash_reason_smem = 656, + .firmware_name = "soccp.mbn", + .pas_id = 51, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + NULL + }, + .ssr_name = "soccp", + .sysmon_name = "soccp", + .auto_boot = true, +}; + static const struct qcom_pas_data sm8450_mpss_resource = { .crash_reason_smem = 421, .firmware_name = "modem.mdt", @@ -2017,6 +2031,7 @@ static const struct of_device_id qcom_pas_of_match[] = { { .compatible = "qcom,nord-cdsp1-pas", .data = &nord_cdsp1_resource }, { .compatible = "qcom,nord-cdsp2-pas", .data = &nord_cdsp2_resource }, { .compatible = "qcom,nord-cdsp3-pas", .data = &nord_cdsp3_resource }, + { .compatible = "qcom,nord-soccp-pas", .data = &nord_soccp_resource }, { .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init }, { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init }, { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init }, From 6a3450435018632fa825cd40090e7d324984768a Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 22 Oct 2026 17:27:01 +0530 Subject: [PATCH 0213/1133] FROMLIST: arm64: dts: qcom: nord: Add SoCCP remoteproc DT support for Nord Add the SoCCP (System on Chip Control Processor) remoteproc node and its SMP2P configuration at the SoC level in nord.dtsi, and wire up the clock and power-domain dependencies shared by all Nord embedded variants in nord-embedded.dtsi. Move the SoCCP compatible to nord-embedded.dtsi to fix binding errors reported for the Ride board. Signed-off-by: Anurag Pateriya Reviewed-by: Shawn Guo Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20261022-nord-soccp-dt-v3-1-1a69a4d54c42@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 10 ++++ arch/arm64/boot/dts/qcom/nord.dtsi | 56 +++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 0269abdb277bd..3bb346cfb65f4 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -464,6 +464,16 @@ "nsp"; }; +&remoteproc_soccp { + compatible = "qcom,nord-soccp-pas"; + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MX>; + power-domain-names = "cx", + "mx"; +}; + &spi0 { clocks = <&segcc SE_GCC_QUPV3_WRAP0_S0_CLK>; clock-names = "se"; diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 41b4f0bde0ec5..de36f161f25b9 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -1030,6 +1030,28 @@ }; }; + smp2p-soccp { + compatible = "qcom,smp2p"; + interrupts-extended = <&ipcc0 IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_SOCCP IPCC_MPROC_SIGNAL_SMP2P>; + qcom,smem = <617>, <616>; + qcom,local-pid = <0>; + qcom,remote-pid = <19>; + + smp2p_soccp_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_soccp_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + soc: soc@0 { compatible = "simple-bus"; #address-cells = <2>; @@ -1842,6 +1864,40 @@ }; }; + remoteproc_soccp: remoteproc@d00000 { + reg = <0x0 0x00d00000 0x0 0x200000>; + + interrupts-extended = <&intc GIC_SPI 167 IRQ_TYPE_EDGE_RISING>, + <&smp2p_soccp_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_soccp_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_soccp_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_soccp_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_soccp_in 9 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "pong"; + + memory-region = <&soccp_mem>; + + qcom,smem-states = <&smp2p_soccp_out 0>, + <&smp2p_soccp_out 8>; + qcom,smem-state-names = "stop", + "ping"; + + glink-edge { + interrupts-extended = <&ipcc0 IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc0 IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP>; + qcom,remote-pid = <19>; + label = "soccp"; + }; + }; + rng: rng@10c3000 { compatible = "qcom,nord-trng", "qcom,trng"; From 9bf86b4eef79e968f182f72dc724e7cddb26e619 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 22 Oct 2026 17:27:02 +0530 Subject: [PATCH 0214/1133] FROMLIST: arm64: dts: qcom: nord: Add SoCCP on RRD board Add the SoCCP remoteproc node with its firmware path on the Nord RRD board. Signed-off-by: Anurag Pateriya Reviewed-by: Abel Vesa Reviewed-by: Shawn Guo Link: https://lore.kernel.org/r/20261022-nord-soccp-dt-v3-2-1a69a4d54c42@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index 47978df0af92d..6bed47b8c913a 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -430,6 +430,10 @@ status = "okay"; }; +&remoteproc_soccp { + firmware-name = "qcom/nord/soccp.mbn"; +}; + &spi16 { status = "okay"; }; From 3833986f30e06d9042f7fbde55cbd8d3b0e507f1 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 22 Oct 2026 17:27:03 +0530 Subject: [PATCH 0215/1133] FROMLIST: arm64: dts: qcom: nord: Add SoCCP on Ride-Embedded board Add the SoCCP remoteproc node with its firmware path on the Nord Ride Embedded board. Reviewed-by: Abel Vesa Signed-off-by: Anurag Pateriya Reviewed-by: Shawn Guo Link: https://lore.kernel.org/r/20261022-nord-soccp-dt-v3-3-1a69a4d54c42@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/nord-ride-embedded.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index 49635695f832e..1aa3ed4c1e459 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -419,6 +419,10 @@ status = "okay"; }; +&remoteproc_soccp { + firmware-name = "qcom/nord/soccp.mbn"; +}; + &uart15 { status = "okay"; }; From f42b336c308c532179b3f5c209eb37d2f305ed6f Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 28 Oct 2026 15:49:33 +0800 Subject: [PATCH 0216/1133] FROMLIST: dt-bindings: arm: qcom,coresight-ctcu: add Nord The CTCU device for nord shares the same configurations as SA8775p. Add a fallback to enable the CTCU for nord to utilize the compatible of the SA8775p. Signed-off-by: Jie Gan Acked-by: Krzysztof Kozlowski Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261028075044.431228-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml index 335a8e1a5a9eb..1d5bf79f49840 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-ctcu.yaml @@ -31,6 +31,7 @@ properties: - enum: - qcom,glymur-ctcu - qcom,kaanapali-ctcu + - qcom,nord-ctcu - qcom,qcs8300-ctcu - qcom,shikra-ctcu - qcom,sm8750-ctcu From 1ebdcad3f703f47b2cf9ea50abe5a7e59fda8857 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 28 Oct 2026 15:49:34 +0800 Subject: [PATCH 0217/1133] FROMLIST: arm64: dts: qcom: nord: add CoreSight debug nodes Add the CoreSight trace topology for the Qualcomm Nord SoC: CTCU, STM, TPDM/TPDA sources and aggregators, funnels, replicators, TMC ETR/ETF sinks, TNoC/ITNoC nodes and per-subsystem CTIs. This wires up trace sources for SOCCP, BCV/IMH/DPM, GCC, QM, DL_NOC, the CDSP NSP0-3 clusters, DLMM, EVA, MDSS0/1, LPASS and the AOSS SWAO priority TPDMs, plus the DDR0-3 channel and LLCC TPDMs, all funneled through the tn_ag aggregator into the main CoreSight funnel and out to the AOSS sink. Signed-off-by: Jie Gan Link: https://lore.kernel.org/r/20261028075044.431228-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord.dtsi | 3540 ++++++++++++++++++++++++++-- 1 file changed, 3314 insertions(+), 226 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index de36f161f25b9..22fced605ba54 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -347,6 +347,18 @@ }; }; + eud-sink { + compatible = "arm,coresight-dummy-sink"; + + in-ports { + port { + eud_in: endpoint { + remote-endpoint = <&aoss_rep0_out1>; + }; + }; + }; + }; + firmware: firmware { scm { compatible = "qcom,scm-nord", @@ -374,6 +386,20 @@ }; }; + hpass-stm { + compatible = "arm,coresight-dummy-source"; + label = "hpass_stm"; + arm,static-trace-id = <25>; + + out-ports { + port { + lpass_stm_out: endpoint { + remote-endpoint = <&lpass_tn_in18>; + }; + }; + }; + }; + memory@80000000 { device_type = "memory"; /* Size will be updated by bootloader */ @@ -2293,236 +2319,3178 @@ wakeup-parent = <&pdc>; }; - apps_smmu_0: iommu@15a00000 { - compatible = "qcom,nord-smmu-500", - "qcom,smmu-500", - "arm,mmu-500"; - reg = <0x0 0x15a00000 0x0 0x100000>; - #iommu-cells = <2>; - #global-interrupts = <1>; - dma-coherent; - interrupts = , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - ; + ctcu@10001000 { + compatible = "qcom,nord-ctcu", "qcom,sa8775p-ctcu"; + reg = <0x0 0x10001000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ctcu_in0: endpoint { + remote-endpoint = <&qdss_etr0_out_ctcu>; + }; + }; + + port@1 { + reg = <1>; + + ctcu_in1: endpoint { + remote-endpoint = <&qdss_etr1_out_ctcu>; + }; + }; + }; }; - apps_smmu_1: iommu@15c00000 { - compatible = "qcom,nord-smmu-500", - "qcom,smmu-500", - "arm,mmu-500"; - reg = <0x0 0x15c00000 0x0 0x100000>; - #iommu-cells = <2>; - #global-interrupts = <1>; - dma-coherent; - interrupts = , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - ; + stm@10002000 { + compatible = "arm,coresight-stm", "arm,primecell"; + reg = <0x0 0x10002000 0x0 0x1000>, + <0x0 0x16000000 0x0 0x180000>; + reg-names = "stm-base", + "stm-stimulus-base"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + out-ports { + port { + qdss_stm_out: endpoint { + remote-endpoint = <&qdss_funnel_in7>; + }; + }; + }; }; - apps_smmu_2: iommu@15e00000 { - compatible = "qcom,nord-smmu-500", - "qcom,smmu-500", - "arm,mmu-500"; - reg = <0x0 0x15e00000 0x0 0x100000>; - #iommu-cells = <2>; - #global-interrupts = <1>; - dma-coherent; - interrupts = , - , - , - , - , - , - , - , + tpda@10004000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x10004000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + qdss_tpda_in1: endpoint { + remote-endpoint = <&qdss_tpdm1_out>; + }; + }; + }; + + out-ports { + port { + qdss_tpda_out: endpoint { + remote-endpoint = <&qdss_funnel_in6>; + }; + }; + }; + }; + + tpdm@1000f000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1000f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_spdm"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + qdss_tpdm1_out: endpoint { + remote-endpoint = <&qdss_tpda_in1>; + }; + }; + }; + }; + + funnel@10041000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x10041000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + qdss_funnel_in0: endpoint { + remote-endpoint = <&tn_ag_out>; + }; + }; + + port@6 { + reg = <6>; + + qdss_funnel_in6: endpoint { + remote-endpoint = <&qdss_tpda_out>; + }; + }; + + port@7 { + reg = <7>; + + qdss_funnel_in7: endpoint { + remote-endpoint = <&qdss_stm_out>; + }; + }; + }; + + out-ports { + port { + qdss_funnel_out: endpoint { + remote-endpoint = <&aoss_funnel_in7>; + }; + }; + }; + }; + + replicator@10046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10046000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + qdss_rep0_in: endpoint { + remote-endpoint = <&aoss_rep1_out>; + }; + }; + }; + + out-ports { + port { + qdss_rep0_out: endpoint { + remote-endpoint = <&qdss_rep1_in>; + }; + }; + }; + }; + + tmc@10048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x10048000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + iommus = <&apps_smmu_0 0x1860 0x0>; + + arm,scatter-gather; + + in-ports { + port { + qdss_etr0_in: endpoint { + remote-endpoint = <&qdss_rep1_out0>; + }; + }; + }; + + out-ports { + port { + qdss_etr0_out_ctcu: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator@1004e000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1004e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + qdss_rep1_in: endpoint { + remote-endpoint = <&qdss_rep0_out>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + qdss_rep1_out0: endpoint { + remote-endpoint = <&qdss_etr0_in>; + }; + }; + + port@1 { + reg = <1>; + + qdss_rep1_out1: endpoint { + remote-endpoint = <&qdss_etr1_in>; + }; + }; + }; + }; + + tmc@1004f000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1004f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + iommus = <&apps_smmu_0 0x1880 0x0>; + + arm,scatter-gather; + + in-ports { + port { + qdss_etr1_in: endpoint { + remote-endpoint = <&qdss_rep1_out1>; + }; + }; + }; + + out-ports { + port { + qdss_etr1_out_ctcu: endpoint { + remote-endpoint = <&ctcu_in1>; + }; + }; + }; + }; + + itnoc@11500000 { + compatible = "qcom,coresight-itnoc"; + reg = <0x0 0x11500000 0x0 0x3400>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + port { + soccp_tn_in: endpoint { + remote-endpoint = <&soccp_tpdm_out>; + }; + }; + }; + + out-ports { + port { + soccp_tn_out: endpoint { + remote-endpoint = <&tn_ag_in75>; + }; + }; + }; + }; + + tpdm@11504000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11504000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_soccp"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + soccp_tpdm_out: endpoint { + remote-endpoint = <&soccp_tn_in>; + }; + }; + }; + }; + + tpdm@11528000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11528000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_bcv"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + mm_rscc_tpdm0_out: endpoint { + remote-endpoint = <&mm_rscc_tpda_in0>; + }; + }; + }; + }; + + tpdm@11529000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11529000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_imh"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + mm_rscc_tpdm1_out: endpoint { + remote-endpoint = <&mm_rscc_tpda_in1>; + }; + }; + }; + }; + + tpdm@1152a000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1152a000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_dpm"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + mm_rscc_tpdm2_out: endpoint { + remote-endpoint = <&mm_rscc_tpda_in2>; + }; + }; + }; + }; + + tpda@1152b000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x1152b000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + mm_rscc_tpda_in0: endpoint { + remote-endpoint = <&mm_rscc_tpdm0_out>; + }; + }; + + port@1 { + reg = <1>; + + mm_rscc_tpda_in1: endpoint { + remote-endpoint = <&mm_rscc_tpdm1_out>; + }; + }; + + port@2 { + reg = <2>; + + mm_rscc_tpda_in2: endpoint { + remote-endpoint = <&mm_rscc_tpdm2_out>; + }; + }; + }; + + out-ports { + port { + mm_rscc_tpda_out: endpoint { + remote-endpoint = <&tn_ag_in8>; + }; + }; + }; + }; + + tpdm@1153c000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1153c000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_gcc"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + gcc_tpdm_out: endpoint { + remote-endpoint = <&tn_ag_in56>; + }; + }; + }; + }; + + tpdm@115a5000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115a5000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_0"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm0_out: endpoint { + remote-endpoint = <&tn_ag_in0>; + }; + }; + }; + }; + + tpdm@115a6000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115a6000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_1"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm1_out: endpoint { + remote-endpoint = <&tn_ag_in1>; + }; + }; + }; + }; + + tpdm@115a7000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115a7000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_2"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm2_out: endpoint { + remote-endpoint = <&tn_ag_in37>; + }; + }; + }; + }; + + tpdm@115a8000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115a8000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_3"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm3_out: endpoint { + remote-endpoint = <&tn_ag_in44>; + }; + }; + }; + }; + + tpdm@115a9000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115a9000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_4"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm4_out: endpoint { + remote-endpoint = <&tn_ag_in47>; + }; + }; + }; + }; + + tpdm@115aa000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115aa000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_5"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm5_out: endpoint { + remote-endpoint = <&tn_ag_in51>; + }; + }; + }; + }; + + tpdm@115ab000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115ab000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_6"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm6_out: endpoint { + remote-endpoint = <&tn_ag_in65>; + }; + }; + }; + }; + + tpdm@115ac000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115ac000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_7"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm7_out: endpoint { + remote-endpoint = <&tn_ag_in66>; + }; + }; + }; + }; + + tpdm@115ad000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115ad000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_8"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm8_out: endpoint { + remote-endpoint = <&tn_ag_in67>; + }; + }; + }; + }; + + tpdm@115ae000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115ae000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_9"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm9_out: endpoint { + remote-endpoint = <&tn_ag_in68>; + }; + }; + }; + }; + + tpdm@115af000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115af000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_10"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm10_out: endpoint { + remote-endpoint = <&tn_ag_in69>; + }; + }; + }; + }; + + tpdm@115b0000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_11"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm11_out: endpoint { + remote-endpoint = <&tn_ag_in70>; + }; + }; + }; + }; + + tpdm@115b1000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115b1000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_12"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm12_out: endpoint { + remote-endpoint = <&tn_ag_in71>; + }; + }; + }; + }; + + tpdm@115b2000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115b2000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_13"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm13_out: endpoint { + remote-endpoint = <&tn_ag_in130>; + }; + }; + }; + }; + + tpdm@115b3000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115b3000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_14"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm14_out: endpoint { + remote-endpoint = <&tn_ag_in131>; + }; + }; + }; + }; + + tpdm@115b4000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115b4000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_15"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm15_out: endpoint { + remote-endpoint = <&tn_ag_in135>; + }; + }; + }; + }; + + tpdm@115b5000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115b5000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_16"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm16_out: endpoint { + remote-endpoint = <&tn_ag_in136>; + }; + }; + }; + }; + + tpdm@115b6000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x115b6000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_tn_ag_17"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + tn_ag_tpdm17_out: endpoint { + remote-endpoint = <&tn_ag_in149>; + }; + }; + }; + }; + + tn@115bc000 { + compatible = "qcom,coresight-tnoc"; + reg = <0x0 0x115bc000 0x0 0x3c00>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tn_ag_in0: endpoint { + remote-endpoint = <&tn_ag_tpdm0_out>; + }; + }; + + port@1 { + reg = <1>; + + tn_ag_in1: endpoint { + remote-endpoint = <&tn_ag_tpdm1_out>; + }; + }; + + port@2 { + reg = <2>; + + tn_ag_in2: endpoint { + remote-endpoint = <&dlmm_funnel_out>; + }; + }; + + port@8 { + reg = <8>; + + tn_ag_in8: endpoint { + remote-endpoint = <&mm_rscc_tpda_out>; + }; + }; + + port@a { + reg = <0xa>; + + tn_ag_in10: endpoint { + remote-endpoint = <&ddr0_tn_out>; + }; + }; + + port@1f { + reg = <0x1f>; + + tn_ag_in31: endpoint { + remote-endpoint = <&dlnoc_funnel_out>; + }; + }; + + port@25 { + reg = <0x25>; + + tn_ag_in37: endpoint { + remote-endpoint = <&tn_ag_tpdm2_out>; + }; + }; + + port@26 { + reg = <0x26>; + + tn_ag_in38: endpoint { + remote-endpoint = <&lpass_tn_out>; + }; + }; + + port@2c { + reg = <0x2c>; + + tn_ag_in44: endpoint { + remote-endpoint = <&tn_ag_tpdm3_out>; + }; + }; + + port@2f { + reg = <0x2f>; + + tn_ag_in47: endpoint { + remote-endpoint = <&tn_ag_tpdm4_out>; + }; + }; + + port@33 { + reg = <0x33>; + + tn_ag_in51: endpoint { + remote-endpoint = <&tn_ag_tpdm5_out>; + }; + }; + + port@38 { + reg = <0x38>; + + tn_ag_in56: endpoint { + remote-endpoint = <&gcc_tpdm_out>; + }; + }; + + port@3d { + reg = <0x3d>; + + tn_ag_in61: endpoint { + remote-endpoint = <&nsp1_funnel_out>; + }; + }; + + port@3e { + reg = <0x3e>; + + tn_ag_in62: endpoint { + remote-endpoint = <&nsp2_funnel_out>; + }; + }; + + port@3f { + reg = <0x3f>; + + tn_ag_in63: endpoint { + remote-endpoint = <&nsp3_funnel_out>; + }; + }; + + port@41 { + reg = <0x41>; + + tn_ag_in65: endpoint { + remote-endpoint = <&tn_ag_tpdm6_out>; + }; + }; + + port@42 { + reg = <0x42>; + + tn_ag_in66: endpoint { + remote-endpoint = <&tn_ag_tpdm7_out>; + }; + }; + + port@43 { + reg = <0x43>; + + tn_ag_in67: endpoint { + remote-endpoint = <&tn_ag_tpdm8_out>; + }; + }; + + port@44 { + reg = <0x44>; + + tn_ag_in68: endpoint { + remote-endpoint = <&tn_ag_tpdm9_out>; + }; + }; + + port@45 { + reg = <0x45>; + + tn_ag_in69: endpoint { + remote-endpoint = <&tn_ag_tpdm10_out>; + }; + }; + + port@46 { + reg = <0x46>; + + tn_ag_in70: endpoint { + remote-endpoint = <&tn_ag_tpdm11_out>; + }; + }; + + port@47 { + reg = <0x47>; + + tn_ag_in71: endpoint { + remote-endpoint = <&tn_ag_tpdm12_out>; + }; + }; + + port@48 { + reg = <0x48>; + + tn_ag_in72: endpoint { + remote-endpoint = <&qm_tpdm_out>; + }; + }; + + port@4b { + reg = <0x4b>; + + tn_ag_in75: endpoint { + remote-endpoint = <&soccp_tn_out>; + }; + }; + + port@59 { + reg = <0x59>; + + tn_ag_in89: endpoint { + remote-endpoint = <&ddr1_tn_out>; + }; + }; + + port@6b { + reg = <0x6b>; + + tn_ag_in107: endpoint { + remote-endpoint = <&ddr2_tn_out>; + }; + }; + + port@82 { + reg = <0x82>; + + tn_ag_in130: endpoint { + remote-endpoint = <&tn_ag_tpdm13_out>; + }; + }; + + port@83 { + reg = <0x83>; + + tn_ag_in131: endpoint { + remote-endpoint = <&tn_ag_tpdm14_out>; + }; + }; + + port@87 { + reg = <0x87>; + + tn_ag_in135: endpoint { + remote-endpoint = <&tn_ag_tpdm15_out>; + }; + }; + + port@88 { + reg = <0x88>; + + tn_ag_in136: endpoint { + remote-endpoint = <&tn_ag_tpdm16_out>; + }; + }; + + port@89 { + reg = <0x89>; + + tn_ag_in137: endpoint { + remote-endpoint = <&nsp0_funnel_out>; + }; + }; + + port@95 { + reg = <0x95>; + + tn_ag_in149: endpoint { + remote-endpoint = <&tn_ag_tpdm17_out>; + }; + }; + + port@9f { + reg = <0x9f>; + + tn_ag_in159: endpoint { + remote-endpoint = <&ddr3_tn_out>; + }; + }; + }; + + out-ports { + port { + tn_ag_out: endpoint { + remote-endpoint = <&qdss_funnel_in0>; + }; + }; + }; + }; + + tpdm@11684000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11684000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_qm"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + qm_tpdm_out: endpoint { + remote-endpoint = <&tn_ag_in72>; + }; + }; + }; + }; + + tpdm@116f0000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x116f0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_dl_noc_0"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + dlnoc_tpdm0_out: endpoint { + remote-endpoint = <&dlnoc_tpda_in27>; + }; + }; + }; + }; + + tpdm@116f1000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x116f1000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_dl_noc_1"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + dlnoc_tpdm1_out: endpoint { + remote-endpoint = <&dlnoc_tpda_in28>; + }; + }; + }; + }; + + tpda@116f4000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x116f4000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1b { + reg = <0x1b>; + + dlnoc_tpda_in27: endpoint { + remote-endpoint = <&dlnoc_tpdm0_out>; + }; + }; + + port@1c { + reg = <0x1c>; + + dlnoc_tpda_in28: endpoint { + remote-endpoint = <&dlnoc_tpdm1_out>; + }; + }; + }; + + out-ports { + port { + dlnoc_tpda_out: endpoint { + remote-endpoint = <&dlnoc_funnel_in>; + }; + }; + }; + }; + + funnel@116f5000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x116f5000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + dlnoc_funnel_in: endpoint { + remote-endpoint = <&dlnoc_tpda_out>; + }; + }; + }; + + out-ports { + port { + dlnoc_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in31>; + }; + }; + }; + }; + + tpda@117c8000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x117c8000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + nsp0_tpda_in0: endpoint { + remote-endpoint = <&nsp0_tpdm0_out>; + }; + }; + + port@1 { + reg = <1>; + + nsp0_tpda_in1: endpoint { + remote-endpoint = <&nsp0_tpdm1_out>; + }; + }; + }; + + out-ports { + port { + nsp0_tpda_out: endpoint { + remote-endpoint = <&nsp0_funnel_in>; + }; + }; + }; + }; + + funnel@117c9000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x117c9000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + nsp0_funnel_in: endpoint { + remote-endpoint = <&nsp0_tpda_out>; + }; + }; + }; + + out-ports { + port { + nsp0_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in137>; + }; + }; + }; + }; + + cti@117d3000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x117d3000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "cti_nsp0"; + }; + + tpda@117e8000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x117e8000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + nsp1_tpda_in0: endpoint { + remote-endpoint = <&nsp1_tpdm0_out>; + }; + }; + + port@1 { + reg = <1>; + + nsp1_tpda_in1: endpoint { + remote-endpoint = <&nsp1_tpdm1_out>; + }; + }; + }; + + out-ports { + port { + nsp1_tpda_out: endpoint { + remote-endpoint = <&nsp1_funnel_in>; + }; + }; + }; + }; + + funnel@117e9000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x117e9000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + nsp1_funnel_in: endpoint { + remote-endpoint = <&nsp1_tpda_out>; + }; + }; + }; + + out-ports { + port { + nsp1_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in61>; + }; + }; + }; + }; + + cti@117f3000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x117f3000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "cti_nsp1"; + }; + + tpdm@11800000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11800000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_dlmm_dsb"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + dlmm_tpdm0_out: endpoint { + remote-endpoint = <&dlmm_tpda_in27>; + }; + }; + }; + }; + + tpdm@11801000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11801000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_dlmm_cmb"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + dlmm_tpdm1_out: endpoint { + remote-endpoint = <&dlmm_tpda_in28>; + }; + }; + }; + }; + + tpda@11804000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x11804000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + dlmm_tpda_in2: endpoint { + remote-endpoint = <&mdss1_funnel_out>; + }; + }; + + port@8 { + reg = <8>; + + dlmm_tpda_in8: endpoint { + remote-endpoint = <&eva_funnel_out>; + }; + }; + + port@e { + reg = <0xe>; + + dlmm_tpda_in14: endpoint { + remote-endpoint = <&mdss0_funnel_out>; + }; + }; + + port@1b { + reg = <0x1b>; + + dlmm_tpda_in27: endpoint { + remote-endpoint = <&dlmm_tpdm0_out>; + }; + }; + + port@1c { + reg = <0x1c>; + + dlmm_tpda_in28: endpoint { + remote-endpoint = <&dlmm_tpdm1_out>; + }; + }; + }; + + out-ports { + port { + dlmm_tpda_out: endpoint { + remote-endpoint = <&dlmm_funnel_in>; + }; + }; + }; + }; + + funnel@11805000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x11805000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + dlmm_funnel_in: endpoint { + remote-endpoint = <&dlmm_tpda_out>; + }; + }; + }; + + out-ports { + port { + dlmm_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in2>; + }; + }; + }; + }; + + tpdm@11810000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11810000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_eva"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + eva_tpdm0_out: endpoint { + remote-endpoint = <&eva_funnel_in0>; + }; + }; + }; + }; + + funnel@11813000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x11813000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + eva_funnel_in0: endpoint { + remote-endpoint = <&eva_tpdm0_out>; + }; + }; + }; + + out-ports { + port { + eva_funnel_out: endpoint { + remote-endpoint = <&dlmm_tpda_in8>; + }; + }; + }; + }; + + tpdm@11860000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11860000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_mdss1"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + mdss1_tpdm0_out: endpoint { + remote-endpoint = <&mdss1_funnel_in0>; + }; + }; + }; + }; + + funnel@11864000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x11864000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + mdss1_funnel_in0: endpoint { + remote-endpoint = <&mdss1_tpdm0_out>; + }; + }; + }; + + out-ports { + port { + mdss1_funnel_out: endpoint { + remote-endpoint = <&dlmm_tpda_in2>; + }; + }; + }; + }; + + tpdm@11870000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11870000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_mdss0"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + mdss0_tpdm0_out: endpoint { + remote-endpoint = <&mdss0_funnel_in0>; + }; + }; + }; + }; + + funnel@11874000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x11874000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + mdss0_funnel_in0: endpoint { + remote-endpoint = <&mdss0_tpdm0_out>; + }; + }; + }; + + out-ports { + port { + mdss0_funnel_out: endpoint { + remote-endpoint = <&dlmm_tpda_in14>; + }; + }; + }; + }; + + tpda@118c8000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x118c8000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + nsp2_tpda_in0: endpoint { + remote-endpoint = <&nsp2_tpdm0_out>; + }; + }; + + port@1 { + reg = <1>; + + nsp2_tpda_in1: endpoint { + remote-endpoint = <&nsp2_tpdm1_out>; + }; + }; + }; + + out-ports { + port { + nsp2_tpda_out: endpoint { + remote-endpoint = <&nsp2_funnel_in>; + }; + }; + }; + }; + + funnel@118c9000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x118c9000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + nsp2_funnel_in: endpoint { + remote-endpoint = <&nsp2_tpda_out>; + }; + }; + }; + + out-ports { + port { + nsp2_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in62>; + }; + }; + }; + }; + + tpda@118e8000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x118e8000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + nsp3_tpda_in0: endpoint { + remote-endpoint = <&nsp3_tpdm0_out>; + }; + }; + + port@1 { + reg = <1>; + + nsp3_tpda_in1: endpoint { + remote-endpoint = <&nsp3_tpdm1_out>; + }; + }; + }; + + out-ports { + port { + nsp3_tpda_out: endpoint { + remote-endpoint = <&nsp3_funnel_in>; + }; + }; + }; + }; + + funnel@118e9000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x118e9000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + nsp3_funnel_in: endpoint { + remote-endpoint = <&nsp3_tpda_out>; + }; + }; + }; + + out-ports { + port { + nsp3_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in63>; + }; + }; + }; + }; + + itnoc@11980000 { + compatible = "qcom,coresight-itnoc"; + reg = <0x0 0x11980000 0x0 0x3080>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@12 { + reg = <0x12>; + + lpass_tn_in18: endpoint { + remote-endpoint = <&lpass_stm_out>; + }; + }; + }; + + out-ports { + port { + lpass_tn_out: endpoint { + remote-endpoint = <&tn_ag_in38>; + }; + }; + }; + }; + + tpdm@11a03000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11a03000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_swao_prio_4"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + aoss_tpdm4_out: endpoint { + remote-endpoint = <&aoss_tpda_in4>; + }; + }; + }; + }; + + funnel@11a04000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x11a04000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@6 { + reg = <6>; + + aoss_funnel_in6: endpoint { + remote-endpoint = <&aoss_tpda_out>; + }; + }; + + port@7 { + reg = <7>; + + aoss_funnel_in7: endpoint { + remote-endpoint = <&qdss_funnel_out>; + }; + }; + }; + + out-ports { + port { + aoss_funnel_out: endpoint { + remote-endpoint = <&aoss_etf_in>; + }; + }; + }; + }; + + tmc@11a05000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x11a05000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + aoss_etf_in: endpoint { + remote-endpoint = <&aoss_funnel_out>; + }; + }; + }; + + out-ports { + port { + aoss_etf_out: endpoint { + remote-endpoint = <&aoss_rep0_in>; + }; + }; + }; + }; + + replicator@11a06000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x11a06000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + aoss_rep0_in: endpoint { + remote-endpoint = <&aoss_etf_out>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + aoss_rep0_out0: endpoint { + remote-endpoint = <&aoss_rep1_in>; + }; + }; + + port@1 { + reg = <1>; + + aoss_rep0_out1: endpoint { + remote-endpoint = <&eud_in>; + }; + }; + }; + }; + + replicator@11a07000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x11a07000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + aoss_rep1_in: endpoint { + remote-endpoint = <&aoss_rep0_out0>; + }; + }; + }; + + out-ports { + port { + aoss_rep1_out: endpoint { + remote-endpoint = <&qdss_rep0_in>; + }; + }; + }; + }; + + tpda@11a08000 { + compatible = "qcom,coresight-tpda", "arm,primecell"; + reg = <0x0 0x11a08000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + aoss_tpda_in0: endpoint { + remote-endpoint = <&aoss_tpdm0_out>; + }; + }; + + port@1 { + reg = <1>; + + aoss_tpda_in1: endpoint { + remote-endpoint = <&aoss_tpdm1_out>; + }; + }; + + port@2 { + reg = <2>; + + aoss_tpda_in2: endpoint { + remote-endpoint = <&aoss_tpdm2_out>; + }; + }; + + port@3 { + reg = <3>; + + aoss_tpda_in3: endpoint { + remote-endpoint = <&aoss_tpdm3_out>; + }; + }; + + port@4 { + reg = <4>; + + aoss_tpda_in4: endpoint { + remote-endpoint = <&aoss_tpdm4_out>; + }; + }; + + port@5 { + reg = <5>; + + aoss_tpda_in5: endpoint { + remote-endpoint = <&aoss_tpdm5_out>; + }; + }; + }; + + out-ports { + port { + aoss_tpda_out: endpoint { + remote-endpoint = <&aoss_funnel_in6>; + }; + }; + }; + }; + + tpdm@11a09000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11a09000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_swao_prio_0"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + aoss_tpdm0_out: endpoint { + remote-endpoint = <&aoss_tpda_in0>; + }; + }; + }; + }; + + tpdm@11a0a000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11a0a000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_swao_prio_1"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + aoss_tpdm1_out: endpoint { + remote-endpoint = <&aoss_tpda_in1>; + }; + }; + }; + }; + + tpdm@11a0b000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11a0b000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_swao_prio_2"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + aoss_tpdm2_out: endpoint { + remote-endpoint = <&aoss_tpda_in2>; + }; + }; + }; + }; + + tpdm@11a0c000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11a0c000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_swao_prio_3"; + + qcom,cmb-element-bits = <64>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + aoss_tpdm3_out: endpoint { + remote-endpoint = <&aoss_tpda_in3>; + }; + }; + }; + }; + + tpdm@11a0d000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x11a0d000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_swao1"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + aoss_tpdm5_out: endpoint { + remote-endpoint = <&aoss_tpda_in5>; + }; + }; + }; + }; + + cti@11a21000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0x0 0x11a21000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "cti_aoss"; + }; + + itnoc@12000000 { + compatible = "qcom,coresight-itnoc"; + reg = <0x0 0x12000000 0x0 0x2e80>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@7 { + reg = <7>; + + ddr0_tn_in7: endpoint { + remote-endpoint = <&ddr0_tpdm0_out>; + }; + }; + + port@8 { + reg = <8>; + + ddr0_tn_in8: endpoint { + remote-endpoint = <&ddr0_tpdm1_out>; + }; + }; + + port@9 { + reg = <9>; + + ddr0_tn_in9: endpoint { + remote-endpoint = <&ddr0_tpdm2_out>; + }; + }; + + port@a { + reg = <0xa>; + + ddr0_tn_in10: endpoint { + remote-endpoint = <&ddr0_tpdm3_out>; + }; + }; + + port@b { + reg = <0xb>; + + ddr0_tn_in11: endpoint { + remote-endpoint = <&ddr0_tpdm4_out>; + }; + }; + + port@f { + reg = <0xf>; + + ddr0_tn_in15: endpoint { + remote-endpoint = <&ddr0_tpdm8_out>; + }; + }; + + port@10 { + reg = <0x10>; + + ddr0_tn_in16: endpoint { + remote-endpoint = <&ddr0_tpdm9_out>; + }; + }; + + }; + + out-ports { + port { + ddr0_tn_out: endpoint { + remote-endpoint = <&tn_ag_in10>; + }; + }; + }; + }; + + tpdm@12003000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12003000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr0_shrm2"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr0_tpdm4_out: endpoint { + remote-endpoint = <&ddr0_tn_in11>; + }; + }; + }; + }; + + tpdm@12009000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12009000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr0_ch02"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr0_tpdm8_out: endpoint { + remote-endpoint = <&ddr0_tn_in15>; + }; + }; + }; + }; + + tpdm@1200c000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1200c000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr0_ch13"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr0_tpdm9_out: endpoint { + remote-endpoint = <&ddr0_tn_in16>; + }; + }; + }; + }; + + tpdm@1200e000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1200e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr0_llcc_0"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr0_tpdm0_out: endpoint { + remote-endpoint = <&ddr0_tn_in7>; + }; + }; + }; + }; + + tpdm@1200f000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1200f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr0_llcc_1"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr0_tpdm1_out: endpoint { + remote-endpoint = <&ddr0_tn_in8>; + }; + }; + }; + }; + + tpdm@12010000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12010000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr0_llcc_2"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr0_tpdm2_out: endpoint { + remote-endpoint = <&ddr0_tn_in9>; + }; + }; + }; + }; + + tpdm@12011000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12011000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr0_llcc_3"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr0_tpdm3_out: endpoint { + remote-endpoint = <&ddr0_tn_in10>; + }; + }; + }; + }; + + itnoc@12200000 { + compatible = "qcom,coresight-itnoc"; + reg = <0x0 0x12200000 0x0 0x2e80>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@7 { + reg = <7>; + + ddr1_tn_in7: endpoint { + remote-endpoint = <&ddr1_tpdm0_out>; + }; + }; + + port@8 { + reg = <8>; + + ddr1_tn_in8: endpoint { + remote-endpoint = <&ddr1_tpdm1_out>; + }; + }; + + port@9 { + reg = <9>; + + ddr1_tn_in9: endpoint { + remote-endpoint = <&ddr1_tpdm2_out>; + }; + }; + + port@a { + reg = <0xa>; + + ddr1_tn_in10: endpoint { + remote-endpoint = <&ddr1_tpdm3_out>; + }; + }; + + port@b { + reg = <0xb>; + + ddr1_tn_in11: endpoint { + remote-endpoint = <&ddr1_tpdm4_out>; + }; + }; + + port@f { + reg = <0xf>; + + ddr1_tn_in15: endpoint { + remote-endpoint = <&ddr1_tpdm8_out>; + }; + }; + + port@10 { + reg = <0x10>; + + ddr1_tn_in16: endpoint { + remote-endpoint = <&ddr1_tpdm9_out>; + }; + }; + + }; + + out-ports { + port { + ddr1_tn_out: endpoint { + remote-endpoint = <&tn_ag_in89>; + }; + }; + }; + }; + + tpdm@12203000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12203000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr1_shrm2"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr1_tpdm4_out: endpoint { + remote-endpoint = <&ddr1_tn_in11>; + }; + }; + }; + }; + + tpdm@12209000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12209000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr1_ch02"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr1_tpdm8_out: endpoint { + remote-endpoint = <&ddr1_tn_in15>; + }; + }; + }; + }; + + tpdm@1220c000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1220c000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr1_ch13"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr1_tpdm9_out: endpoint { + remote-endpoint = <&ddr1_tn_in16>; + }; + }; + }; + }; + + tpdm@1220e000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1220e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr1_llcc_0"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr1_tpdm0_out: endpoint { + remote-endpoint = <&ddr1_tn_in7>; + }; + }; + }; + }; + + tpdm@1220f000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1220f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr1_llcc_1"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr1_tpdm1_out: endpoint { + remote-endpoint = <&ddr1_tn_in8>; + }; + }; + }; + }; + + tpdm@12210000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12210000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr1_llcc_2"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr1_tpdm2_out: endpoint { + remote-endpoint = <&ddr1_tn_in9>; + }; + }; + }; + }; + + tpdm@12211000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12211000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr1_llcc_3"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr1_tpdm3_out: endpoint { + remote-endpoint = <&ddr1_tn_in10>; + }; + }; + }; + }; + + itnoc@12400000 { + compatible = "qcom,coresight-itnoc"; + reg = <0x0 0x12400000 0x0 0x2e80>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@7 { + reg = <7>; + + ddr2_tn_in7: endpoint { + remote-endpoint = <&ddr2_tpdm0_out>; + }; + }; + + port@8 { + reg = <8>; + + ddr2_tn_in8: endpoint { + remote-endpoint = <&ddr2_tpdm1_out>; + }; + }; + + port@9 { + reg = <9>; + + ddr2_tn_in9: endpoint { + remote-endpoint = <&ddr2_tpdm2_out>; + }; + }; + + port@a { + reg = <0xa>; + + ddr2_tn_in10: endpoint { + remote-endpoint = <&ddr2_tpdm3_out>; + }; + }; + + port@b { + reg = <0xb>; + + ddr2_tn_in11: endpoint { + remote-endpoint = <&ddr2_tpdm4_out>; + }; + }; + + port@f { + reg = <0xf>; + + ddr2_tn_in15: endpoint { + remote-endpoint = <&ddr2_tpdm8_out>; + }; + }; + + port@10 { + reg = <0x10>; + + ddr2_tn_in16: endpoint { + remote-endpoint = <&ddr2_tpdm9_out>; + }; + }; + + }; + + out-ports { + port { + ddr2_tn_out: endpoint { + remote-endpoint = <&tn_ag_in107>; + }; + }; + }; + }; + + tpdm@12403000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12403000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr2_shrm2"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr2_tpdm4_out: endpoint { + remote-endpoint = <&ddr2_tn_in11>; + }; + }; + }; + }; + + tpdm@12409000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12409000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr2_ch02"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr2_tpdm8_out: endpoint { + remote-endpoint = <&ddr2_tn_in15>; + }; + }; + }; + }; + + tpdm@1240c000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1240c000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr2_ch13"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr2_tpdm9_out: endpoint { + remote-endpoint = <&ddr2_tn_in16>; + }; + }; + }; + }; + + tpdm@1240e000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1240e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr2_llcc_0"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr2_tpdm0_out: endpoint { + remote-endpoint = <&ddr2_tn_in7>; + }; + }; + }; + }; + + tpdm@1240f000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1240f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr2_llcc_1"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr2_tpdm1_out: endpoint { + remote-endpoint = <&ddr2_tn_in8>; + }; + }; + }; + }; + + tpdm@12410000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12410000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr2_llcc_2"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr2_tpdm2_out: endpoint { + remote-endpoint = <&ddr2_tn_in9>; + }; + }; + }; + }; + + tpdm@12411000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12411000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr2_llcc_3"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr2_tpdm3_out: endpoint { + remote-endpoint = <&ddr2_tn_in10>; + }; + }; + }; + }; + + itnoc@12600000 { + compatible = "qcom,coresight-itnoc"; + reg = <0x0 0x12600000 0x0 0x2e80>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@7 { + reg = <7>; + + ddr3_tn_in7: endpoint { + remote-endpoint = <&ddr3_tpdm0_out>; + }; + }; + + port@8 { + reg = <8>; + + ddr3_tn_in8: endpoint { + remote-endpoint = <&ddr3_tpdm1_out>; + }; + }; + + port@9 { + reg = <9>; + + ddr3_tn_in9: endpoint { + remote-endpoint = <&ddr3_tpdm2_out>; + }; + }; + + port@a { + reg = <0xa>; + + ddr3_tn_in10: endpoint { + remote-endpoint = <&ddr3_tpdm3_out>; + }; + }; + + port@b { + reg = <0xb>; + + ddr3_tn_in11: endpoint { + remote-endpoint = <&ddr3_tpdm4_out>; + }; + }; + + port@f { + reg = <0xf>; + + ddr3_tn_in15: endpoint { + remote-endpoint = <&ddr3_tpdm8_out>; + }; + }; + + port@10 { + reg = <0x10>; + + ddr3_tn_in16: endpoint { + remote-endpoint = <&ddr3_tpdm9_out>; + }; + }; + + }; + + out-ports { + port { + ddr3_tn_out: endpoint { + remote-endpoint = <&tn_ag_in159>; + }; + }; + }; + }; + + tpdm@12603000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12603000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr3_shrm2"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr3_tpdm4_out: endpoint { + remote-endpoint = <&ddr3_tn_in11>; + }; + }; + }; + }; + + tpdm@12609000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12609000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr3_ch02"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr3_tpdm8_out: endpoint { + remote-endpoint = <&ddr3_tn_in15>; + }; + }; + }; + }; + + tpdm@1260c000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1260c000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr3_ch13"; + + qcom,dsb-element-bits = <32>; + qcom,dsb-msrs-num = <32>; + + out-ports { + port { + ddr3_tpdm9_out: endpoint { + remote-endpoint = <&ddr3_tn_in16>; + }; + }; + }; + }; + + tpdm@1260e000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1260e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr3_llcc_0"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr3_tpdm0_out: endpoint { + remote-endpoint = <&ddr3_tn_in7>; + }; + }; + }; + }; + + tpdm@1260f000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x1260f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr3_llcc_1"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr3_tpdm1_out: endpoint { + remote-endpoint = <&ddr3_tn_in8>; + }; + }; + }; + }; + + tpdm@12610000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12610000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr3_llcc_2"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr3_tpdm2_out: endpoint { + remote-endpoint = <&ddr3_tn_in9>; + }; + }; + }; + }; + + tpdm@12611000 { + compatible = "qcom,coresight-tpdm", "arm,primecell"; + reg = <0x0 0x12611000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + label = "tpdm_ddr3_llcc_3"; + + qcom,cmb-element-bits = <32>; + qcom,cmb-msrs-num = <32>; + + out-ports { + port { + ddr3_tpdm3_out: endpoint { + remote-endpoint = <&ddr3_tn_in10>; + }; + }; + }; + }; + + apps_smmu_0: iommu@15a00000 { + compatible = "qcom,nord-smmu-500", + "qcom,smmu-500", + "arm,mmu-500"; + reg = <0x0 0x15a00000 0x0 0x100000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + dma-coherent; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; + + apps_smmu_1: iommu@15c00000 { + compatible = "qcom,nord-smmu-500", + "qcom,smmu-500", + "arm,mmu-500"; + reg = <0x0 0x15c00000 0x0 0x100000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + dma-coherent; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; + + apps_smmu_2: iommu@15e00000 { + compatible = "qcom,nord-smmu-500", + "qcom,smmu-500", + "arm,mmu-500"; + reg = <0x0 0x15e00000 0x0 0x100000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + dma-coherent; + interrupts = , + , + , + , + , + , + , + , , , , @@ -3413,6 +6381,126 @@ }; }; + tpdm-nsp0-cdsp-llm { + compatible = "qcom,coresight-static-tpdm"; + label = "tpdm_nsp0_cdsp_llm"; + + qcom,cmb-element-bits = <32>; + + out-ports { + port { + nsp0_tpdm0_out: endpoint { + remote-endpoint = <&nsp0_tpda_in0>; + }; + }; + }; + }; + + tpdm-nsp0-cdsp-llm2 { + compatible = "qcom,coresight-static-tpdm"; + label = "tpdm_nsp0_cdsp_llm2"; + + qcom,cmb-element-bits = <32>; + + out-ports { + port { + nsp0_tpdm1_out: endpoint { + remote-endpoint = <&nsp0_tpda_in1>; + }; + }; + }; + }; + + tpdm-nsp1-cdsp-llm { + compatible = "qcom,coresight-static-tpdm"; + label = "tpdm_nsp1_cdsp_llm"; + + qcom,cmb-element-bits = <32>; + + out-ports { + port { + nsp1_tpdm0_out: endpoint { + remote-endpoint = <&nsp1_tpda_in0>; + }; + }; + }; + }; + + tpdm-nsp1-cdsp-llm2 { + compatible = "qcom,coresight-static-tpdm"; + label = "tpdm_nsp1_cdsp_llm2"; + + qcom,cmb-element-bits = <32>; + + out-ports { + port { + nsp1_tpdm1_out: endpoint { + remote-endpoint = <&nsp1_tpda_in1>; + }; + }; + }; + }; + + tpdm-nsp2-cdsp-llm { + compatible = "qcom,coresight-static-tpdm"; + label = "tpdm_nsp2_cdsp_llm"; + + qcom,cmb-element-bits = <32>; + + out-ports { + port { + nsp2_tpdm0_out: endpoint { + remote-endpoint = <&nsp2_tpda_in0>; + }; + }; + }; + }; + + tpdm-nsp2-cdsp-llm2 { + compatible = "qcom,coresight-static-tpdm"; + label = "tpdm_nsp2_cdsp_llm2"; + + qcom,cmb-element-bits = <32>; + + out-ports { + port { + nsp2_tpdm1_out: endpoint { + remote-endpoint = <&nsp2_tpda_in1>; + }; + }; + }; + }; + + tpdm-nsp3-cdsp-llm { + compatible = "qcom,coresight-static-tpdm"; + label = "tpdm_nsp3_cdsp_llm"; + + qcom,cmb-element-bits = <32>; + + out-ports { + port { + nsp3_tpdm0_out: endpoint { + remote-endpoint = <&nsp3_tpda_in0>; + }; + }; + }; + }; + + tpdm-nsp3-cdsp-llm2 { + compatible = "qcom,coresight-static-tpdm"; + label = "tpdm_nsp3_cdsp_llm2"; + + qcom,cmb-element-bits = <32>; + + out-ports { + port { + nsp3_tpdm1_out: endpoint { + remote-endpoint = <&nsp3_tpda_in1>; + }; + }; + }; + }; + arch_timer: timer { compatible = "arm,armv8-timer"; interrupts = , From 749c6bae7e21507957c7baf93f159674bf1ec047 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 16 Sep 2026 21:59:17 +0800 Subject: [PATCH 0218/1133] FROMLIST: dt-bindings: usb: Add onsemi FUSB15201 Type-C and PD controller The FUSB15201 is an autonomous dual-port USB Type-C and Power Delivery controller. It runs the Type-C state machine and the Power Delivery policy engine on an integrated microcontroller, and exposes only a status and command interface over I2C, so it is not a TCPC. Describe the two ports as addressed connector child nodes, so that a board which wires up only one of them can describe just that one. Assisted-by: LLM Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260916135918.1017527-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- .../bindings/usb/onnn,fusb15201.yaml | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/onnn,fusb15201.yaml diff --git a/Documentation/devicetree/bindings/usb/onnn,fusb15201.yaml b/Documentation/devicetree/bindings/usb/onnn,fusb15201.yaml new file mode 100644 index 0000000000000..09f2e964d3ef3 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/onnn,fusb15201.yaml @@ -0,0 +1,152 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/onnn,fusb15201.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: onsemi FUSB15201 dual-port Type-C and Power Delivery controller + +maintainers: + - Shawn Guo + +description: + The FUSB15201 is an autonomous dual-port USB Type-C and Power Delivery + controller. It runs the Type-C state machine and the Power Delivery policy + engine on an integrated microcontroller, so the host is not involved in + Power Delivery messaging. Over I2C it reports the attach state, CC + orientation, data and power roles, faults and the VBUS voltage of each of + its two ports, and accepts commands to initiate data and power role swaps. + + The two ports are described as connector child nodes, addressed 0 for port A + and 1 for port B. A board that wires up only one of the two ports describes + only the corresponding connector. + +properties: + compatible: + const: onnn,fusb15201 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + description: + Interrupt line shared by both ports, driven by the I2C_INT pin. The pin + is active low and stays asserted until every pending interrupt has been + cleared, so it has to be described as level triggered. + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + +patternProperties: + '^connector@[01]$': + type: object + $ref: /schemas/connector/usb-connector.yaml# + unevaluatedProperties: false + + properties: + compatible: + const: usb-c-connector + + reg: + maximum: 1 + description: + 0 for port A, 1 for port B. + + required: + - reg + +required: + - compatible + - reg + - interrupts + - '#address-cells' + - '#size-cells' + +anyOf: + - required: [connector@0] + - required: [connector@1] + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + typec@50 { + compatible = "onnn,fusb15201"; + reg = <0x50>; + interrupts-extended = <&pmic_gpios 8 IRQ_TYPE_LEVEL_LOW>; + + #address-cells = <1>; + #size-cells = <0>; + + connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + label = "USB-C0"; + power-role = "dual"; + data-role = "dual"; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + endpoint { + remote-endpoint = <&usb_0_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + endpoint { + remote-endpoint = <&usb_0_qmpphy_ss>; + }; + }; + }; + }; + + connector@1 { + compatible = "usb-c-connector"; + reg = <1>; + label = "USB-C1"; + power-role = "dual"; + data-role = "dual"; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + endpoint { + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + endpoint { + remote-endpoint = <&usb_1_qmpphy_ss>; + }; + }; + }; + }; + }; + }; +... From 3e473a2f19f7d5a7401ba5adbfd5814270a257a0 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 16 Sep 2026 21:59:18 +0800 Subject: [PATCH 0219/1133] FROMLIST: usb: typec: Add onsemi FUSB15201 driver The FUSB15201 is a dual-port USB Type-C and Power Delivery controller which runs the Type-C state machine and the PD policy engine on an integrated microcontroller. The host only observes the resulting state and may ask for role swaps, so this is a plain Type-C class driver rather than a TCPC driven by the Type-C Port Manager. Register a Type-C port for each connector described in firmware, report attach and detach, orientation, power and data roles and the PD capability of the partner, and drive the USB role switch of the attached USB controller so that OTG role switching works. Data and power role swaps requested through sysfs are forwarded to the controller, which performs them asynchronously and reports the outcome as a port status interrupt. The controller exposes a per-port VBUS ADC reading, but the Type-C class has no VBUS attribute and nothing needs the value, so it is not read. PD messages, PDOs and alternate modes are not exposed by the hardware at all. The chip-wide MASTER_RESET command would drop both ports at once and has no caller, so it is left alone as well. Assisted-by: LLM Reviewed-by: Bartosz Golaszewski Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20260916135918.1017527-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- drivers/usb/typec/Kconfig | 17 + drivers/usb/typec/Makefile | 1 + drivers/usb/typec/fusb15201.c | 580 ++++++++++++++++++++++++++++++++++ 3 files changed, 598 insertions(+) create mode 100644 drivers/usb/typec/fusb15201.c diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index 2f80c2792dbda..e21854cb89d42 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -64,6 +64,23 @@ config TYPEC_ANX7411 If you choose to build this driver as a dynamically linked module, the module will be called anx7411.ko. +config TYPEC_FUSB15201 + tristate "onsemi FUSB15201 Type-C and Power Delivery controller driver" + depends on I2C + depends on USB_ROLE_SWITCH + select REGMAP_I2C + help + Say Y or M here if your system has an onsemi FUSB15201 dual-port USB + Type-C and Power Delivery controller. + + The FUSB15201 handles Type-C detection and Power Delivery negotiation + autonomously. This driver reports the resulting state to the Type-C + class, drives the USB role switch of the attached USB controller, and + allows data and power role swaps to be requested. + + If you choose to build this driver as a dynamically linked module, the + module will be called fusb15201.ko. + config TYPEC_RT1719 tristate "Richtek RT1719 Sink Only Type-C controller driver" depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile index 8a6a1c663eb69..9f3a156d9c9fc 100644 --- a/drivers/usb/typec/Makefile +++ b/drivers/usb/typec/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_TYPEC_TCPM) += tcpm/ obj-$(CONFIG_TYPEC_UCSI) += ucsi/ obj-$(CONFIG_TYPEC_TPS6598X) += tipd/ obj-$(CONFIG_TYPEC_ANX7411) += anx7411.o +obj-$(CONFIG_TYPEC_FUSB15201) += fusb15201.o obj-$(CONFIG_TYPEC_HD3SS3220) += hd3ss3220.o obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o obj-$(CONFIG_TYPEC_RT1719) += rt1719.o diff --git a/drivers/usb/typec/fusb15201.c b/drivers/usb/typec/fusb15201.c new file mode 100644 index 0000000000000..ab3b07368bdf1 --- /dev/null +++ b/drivers/usb/typec/fusb15201.c @@ -0,0 +1,580 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Driver for the onsemi FUSB15201 dual-port USB Type-C and Power Delivery + * controller. + * + * The FUSB15201 runs the Type-C state machine and the Power Delivery policy + * engine on an integrated microcontroller. The host only observes the + * resulting state and may ask for role swaps, so this is a plain Type-C class + * driver rather than a TCPC on the Type-C Port Manager. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FUSB15201_NUM_PORTS 2 + +#define FUSB15201_REG_VENDID 0x00 +#define FUSB15201_REG_PRODID 0x01 +#define FUSB15201_REG_DEVID 0x02 +#define FUSB15201_REG_HWVER 0x03 +#define FUSB15201_REG_FWVER 0x04 + +#define FUSB15201_VENDID 0xaa +#define FUSB15201_PRODID 0x65 +#define FUSB15201_DEVID 0x01 + +/* Per-port status block, port A at 0x06 and port B at 0x0c */ +#define FUSB15201_PORT_BASE(p) (0x06 + (p) * 0x06) +#define FUSB15201_REG_STATUS(p) (FUSB15201_PORT_BASE(p) + 0x02) +#define FUSB15201_REG_RESET_STATUS(p) (FUSB15201_PORT_BASE(p) + 0x03) +#define FUSB15201_REG_FAULT_STATUS(p) (FUSB15201_PORT_BASE(p) + 0x04) + +#define FUSB15201_STATUS_ATTACHED BIT(0) +#define FUSB15201_STATUS_USBPD BIT(1) +#define FUSB15201_STATUS_CC2 BIT(2) +#define FUSB15201_STATUS_DFP BIT(3) +#define FUSB15201_STATUS_SINK BIT(4) + +#define FUSB15201_RESET_ERR_RECOVERY BIT(2) + +#define FUSB15201_FAULT_VBUS_OVP BIT(0) +#define FUSB15201_FAULT_OTP BIT(1) +#define FUSB15201_FAULT_CC_OVP BIT(2) +#define FUSB15201_FAULT_VCONN_OCP BIT(3) + +/* Per-port command block, port A at 0x11 and port B at 0x13 */ +#define FUSB15201_REG_COMMANDS(p) (0x11 + (p) * 0x02) +#define FUSB15201_REG_INT_MASK(p) (0x12 + (p) * 0x02) + +/* + * The swap command bits are named after the role the port is in when the swap + * is requested, not the role it ends up in. + */ +#define FUSB15201_CMD_UFP_TO_DFP BIT(4) +#define FUSB15201_CMD_DFP_TO_UFP BIT(5) +#define FUSB15201_CMD_SINK_TO_SOURCE BIT(6) +#define FUSB15201_CMD_SOURCE_TO_SINK BIT(7) + +#define FUSB15201_REG_MASTER_CONTROL 0x15 +#define FUSB15201_MASTER_DRP_DISABLE BIT(1) + +/* Per-port interrupt status, write one to clear */ +#define FUSB15201_REG_INTERRUPT(p) (0x16 + (p)) +#define FUSB15201_INT_FAULT BIT(0) +#define FUSB15201_INT_RESET_STATUS BIT(1) +#define FUSB15201_INT_PORT_STATUS BIT(2) +#define FUSB15201_INT_ALL (FUSB15201_INT_FAULT | \ + FUSB15201_INT_RESET_STATUS | \ + FUSB15201_INT_PORT_STATUS) + +#define FUSB15201_REG_MAX FUSB15201_REG_INTERRUPT(1) + +struct fusb15201; + +struct fusb15201_port { + struct fusb15201 *chip; + unsigned int index; + struct typec_port *port; + struct typec_partner *partner; + struct usb_role_switch *role_sw; + struct typec_capability cap; + unsigned int status; +}; + +struct fusb15201 { + struct device *dev; + struct regmap *regmap; + struct mutex lock; /* serialises access to the shared registers */ + struct fusb15201_port ports[FUSB15201_NUM_PORTS]; +}; + +static enum typec_role fusb15201_default_pwr_role(struct fusb15201_port *port) +{ + switch (port->cap.type) { + case TYPEC_PORT_SRC: + return TYPEC_SOURCE; + case TYPEC_PORT_SNK: + return TYPEC_SINK; + default: + if (is_source(port->cap.prefer_role)) + return TYPEC_SOURCE; + return TYPEC_SINK; + } +} + +static void fusb15201_set_roles(struct fusb15201_port *port, + enum typec_role pwr_role, + enum typec_data_role data_role, bool attached) +{ + typec_set_pwr_role(port->port, pwr_role); + typec_set_vconn_role(port->port, pwr_role); + typec_set_data_role(port->port, data_role); + + if (!port->role_sw) + return; + + if (!attached) + usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE); + else if (data_role == TYPEC_HOST) + usb_role_switch_set_role(port->role_sw, USB_ROLE_HOST); + else + usb_role_switch_set_role(port->role_sw, USB_ROLE_DEVICE); +} + +static void fusb15201_hw_update(struct fusb15201_port *port) +{ + struct fusb15201 *chip = port->chip; + enum typec_data_role data_role = TYPEC_DEVICE; + enum typec_role pwr_role; + unsigned int status; + int ret; + + ret = regmap_read(chip->regmap, FUSB15201_REG_STATUS(port->index), &status); + if (ret) { + dev_warn(chip->dev, "port%u: failed to read status: %d\n", + port->index, ret); + return; + } + + if (!(status & FUSB15201_STATUS_ATTACHED)) { + if (port->partner) { + typec_unregister_partner(port->partner); + port->partner = NULL; + } + + /* + * None of the remaining status bits are valid while detached, + * so fall back to what the port is configured to do. + */ + typec_set_orientation(port->port, TYPEC_ORIENTATION_NONE); + typec_set_pwr_opmode(port->port, TYPEC_PWR_MODE_USB); + + pwr_role = fusb15201_default_pwr_role(port); + if (is_source(pwr_role)) + data_role = TYPEC_HOST; + + fusb15201_set_roles(port, pwr_role, data_role, false); + + port->status = status; + return; + } + + if (!(port->status & FUSB15201_STATUS_ATTACHED)) { + struct typec_partner_desc desc = { + .usb_pd = !!(status & FUSB15201_STATUS_USBPD), + }; + + port->partner = typec_register_partner(port->port, &desc); + if (IS_ERR(port->partner)) { + dev_err(chip->dev, + "port%u: failed to register partner: %pe\n", + port->index, port->partner); + port->partner = NULL; + } + } + + typec_set_orientation(port->port, status & FUSB15201_STATUS_CC2 ? + TYPEC_ORIENTATION_REVERSE : + TYPEC_ORIENTATION_NORMAL); + + /* + * The controller only tells us whether the partner is PD capable. The + * Type-C current advertisement is not reported, so 1.5A and 3.0A + * operation cannot be distinguished from the default. + */ + typec_set_pwr_opmode(port->port, status & FUSB15201_STATUS_USBPD ? + TYPEC_PWR_MODE_PD : TYPEC_PWR_MODE_USB); + + pwr_role = status & FUSB15201_STATUS_SINK ? TYPEC_SINK : TYPEC_SOURCE; + data_role = status & FUSB15201_STATUS_DFP ? TYPEC_HOST : TYPEC_DEVICE; + fusb15201_set_roles(port, pwr_role, data_role, true); + + port->status = status; +} + +static void fusb15201_report_faults(struct fusb15201_port *port) +{ + struct fusb15201 *chip = port->chip; + unsigned int fault; + int ret; + + ret = regmap_read(chip->regmap, FUSB15201_REG_FAULT_STATUS(port->index), &fault); + if (ret) + return; + + /* + * The controller protects itself, so there is nothing to do here + * beyond making the fault visible. + */ + if (fault & FUSB15201_FAULT_VBUS_OVP) + dev_warn_ratelimited(chip->dev, "port%u: VBUS overvoltage\n", + port->index); + if (fault & FUSB15201_FAULT_OTP) + dev_warn_ratelimited(chip->dev, "port%u: over temperature\n", + port->index); + if (fault & FUSB15201_FAULT_CC_OVP) + dev_warn_ratelimited(chip->dev, "port%u: CC overvoltage\n", + port->index); + if (fault & FUSB15201_FAULT_VCONN_OCP) + dev_warn_ratelimited(chip->dev, "port%u: VCONN overcurrent\n", + port->index); +} + +static void fusb15201_report_reset(struct fusb15201_port *port) +{ + struct fusb15201 *chip = port->chip; + unsigned int reset; + int ret; + + ret = regmap_read(chip->regmap, FUSB15201_REG_RESET_STATUS(port->index), &reset); + if (ret) + return; + + dev_dbg(chip->dev, "port%u: reset status 0x%02x\n", port->index, reset); + + if (reset & FUSB15201_RESET_ERR_RECOVERY) + dev_warn_ratelimited(chip->dev, + "port%u: entered error recovery\n", + port->index); +} + +static irqreturn_t fusb15201_irq(int irq, void *data) +{ + struct fusb15201 *chip = data; + irqreturn_t ret = IRQ_NONE; + unsigned int i; + + guard(mutex)(&chip->lock); + + for (i = 0; i < FUSB15201_NUM_PORTS; i++) { + struct fusb15201_port *port = &chip->ports[i]; + unsigned int pending; + + if (!port->port) + continue; + + if (regmap_read(chip->regmap, FUSB15201_REG_INTERRUPT(i), &pending)) + continue; + + pending &= FUSB15201_INT_ALL; + if (!pending) + continue; + + /* Write one to clear */ + regmap_write(chip->regmap, FUSB15201_REG_INTERRUPT(i), pending); + + if (pending & FUSB15201_INT_PORT_STATUS) + fusb15201_hw_update(port); + if (pending & FUSB15201_INT_FAULT) + fusb15201_report_faults(port); + if (pending & FUSB15201_INT_RESET_STATUS) + fusb15201_report_reset(port); + + ret = IRQ_HANDLED; + } + + return ret; +} + +/* + * Role swaps are asynchronous: the command only asks the controller to start + * the swap, and the outcome arrives later as a port status interrupt. + */ +static int fusb15201_command(struct fusb15201_port *port, unsigned int cmd) +{ + struct fusb15201 *chip = port->chip; + + guard(mutex)(&chip->lock); + + if (!(port->status & FUSB15201_STATUS_ATTACHED)) + return -ENOTCONN; + + return regmap_write(chip->regmap, FUSB15201_REG_COMMANDS(port->index), cmd); +} + +static int fusb15201_dr_set(struct typec_port *p, enum typec_data_role role) +{ + struct fusb15201_port *port = typec_get_drvdata(p); + unsigned int cmd = FUSB15201_CMD_DFP_TO_UFP; + + if (role == TYPEC_HOST) + cmd = FUSB15201_CMD_UFP_TO_DFP; + + return fusb15201_command(port, cmd); +} + +static int fusb15201_pr_set(struct typec_port *p, enum typec_role role) +{ + struct fusb15201_port *port = typec_get_drvdata(p); + unsigned int cmd = FUSB15201_CMD_SOURCE_TO_SINK; + + if (is_source(role)) + cmd = FUSB15201_CMD_SINK_TO_SOURCE; + + return fusb15201_command(port, cmd); +} + +static const struct typec_operations fusb15201_typec_ops = { + .dr_set = fusb15201_dr_set, + .pr_set = fusb15201_pr_set, +}; + +/* + * Nearly every register is either volatile or write-only, and the interrupt + * registers are write-one-to-clear, so the register map is not cached. + */ +static const struct regmap_config fusb15201_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = FUSB15201_REG_MAX, +}; + +static void fusb15201_unregister_port(void *data) +{ + struct fusb15201_port *port = data; + + if (port->partner) + typec_unregister_partner(port->partner); + typec_unregister_port(port->port); +} + +static void fusb15201_put_role_sw(void *data) +{ + usb_role_switch_put(data); +} + +static int fusb15201_check_id(struct fusb15201 *chip) +{ + static const struct { + unsigned int reg; + unsigned int expected; + const char *name; + } ids[] = { + { FUSB15201_REG_VENDID, FUSB15201_VENDID, "vendor" }, + { FUSB15201_REG_PRODID, FUSB15201_PRODID, "product" }, + { FUSB15201_REG_DEVID, FUSB15201_DEVID, "device" }, + }; + unsigned int val, hwver, fwver; + int ret, i; + + for (i = 0; i < ARRAY_SIZE(ids); i++) { + ret = regmap_read(chip->regmap, ids[i].reg, &val); + if (ret) + return dev_err_probe(chip->dev, ret, + "failed to read %s id\n", + ids[i].name); + + if (val != ids[i].expected) + return dev_err_probe(chip->dev, -ENODEV, + "bad %s id 0x%02x, expected 0x%02x\n", + ids[i].name, val, ids[i].expected); + } + + /* + * The register semantics are defined by the firmware image, so record + * the versions to make mismatches easier to spot. + */ + if (!regmap_read(chip->regmap, FUSB15201_REG_HWVER, &hwver) && + !regmap_read(chip->regmap, FUSB15201_REG_FWVER, &fwver)) + dev_dbg(chip->dev, "hardware version %u, firmware version %u\n", + hwver, fwver); + + return 0; +} + +static int fusb15201_register_port(struct fusb15201 *chip, + struct fwnode_handle *fwnode) +{ + struct fusb15201_port *port; + unsigned int index; + int ret; + + ret = fwnode_property_read_u32(fwnode, "reg", &index); + if (ret) + return dev_err_probe(chip->dev, ret, + "missing reg property of %pfwP\n", fwnode); + + if (index >= FUSB15201_NUM_PORTS) + return dev_err_probe(chip->dev, -EINVAL, + "invalid connector index %u\n", index); + + port = &chip->ports[index]; + if (port->port) + return dev_err_probe(chip->dev, -EINVAL, + "duplicate connector for port %u\n", index); + + port->chip = chip; + port->index = index; + + ret = typec_get_fw_cap(&port->cap, fwnode); + if (ret) + return dev_err_probe(chip->dev, ret, + "port%u: failed to get capabilities\n", + index); + + port->cap.revision = USB_TYPEC_REV_2_0; + port->cap.orientation_aware = true; + port->cap.driver_data = port; + port->cap.ops = &fusb15201_typec_ops; + + port->port = typec_register_port(chip->dev, &port->cap); + if (IS_ERR(port->port)) { + ret = PTR_ERR(port->port); + port->port = NULL; + return dev_err_probe(chip->dev, ret, + "port%u: failed to register\n", index); + } + + ret = devm_add_action_or_reset(chip->dev, fusb15201_unregister_port, port); + if (ret) + return ret; + + port->role_sw = fwnode_usb_role_switch_get(fwnode); + if (IS_ERR(port->role_sw)) + return dev_err_probe(chip->dev, PTR_ERR(port->role_sw), + "port%u: failed to get role switch\n", + index); + + if (port->role_sw) { + ret = devm_add_action_or_reset(chip->dev, fusb15201_put_role_sw, + port->role_sw); + if (ret) + return ret; + } + + return 0; +} + +static int fusb15201_hw_init(struct fusb15201 *chip) +{ + bool source_only = true; + unsigned int i; + int ret; + + for (i = 0; i < FUSB15201_NUM_PORTS; i++) { + struct fusb15201_port *port = &chip->ports[i]; + + if (!port->port) { + /* Nothing describes this port, keep it quiet. */ + ret = regmap_write(chip->regmap, + FUSB15201_REG_INT_MASK(i), + FUSB15201_INT_ALL); + if (ret) + return ret; + + continue; + } + + if (port->cap.type != TYPEC_PORT_SRC) + source_only = false; + + ret = regmap_write(chip->regmap, FUSB15201_REG_INT_MASK(i), 0); + if (ret) + return ret; + + /* Discard anything that happened before we got here */ + ret = regmap_write(chip->regmap, FUSB15201_REG_INTERRUPT(i), + FUSB15201_INT_ALL); + if (ret) + return ret; + } + + /* + * Dual role toggling is the only configurable part of the Type-C state + * machine, and it is chip wide rather than per port, which is why it is + * set up here instead of from a port_type_set() callback. + */ + ret = regmap_update_bits(chip->regmap, FUSB15201_REG_MASTER_CONTROL, + FUSB15201_MASTER_DRP_DISABLE, + source_only ? FUSB15201_MASTER_DRP_DISABLE : 0); + if (ret) + return ret; + + /* Seed the Type-C class with the current state before arming the IRQ */ + for (i = 0; i < FUSB15201_NUM_PORTS; i++) { + if (chip->ports[i].port) + fusb15201_hw_update(&chip->ports[i]); + } + + return 0; +} + +static int fusb15201_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct fusb15201 *chip; + unsigned int nports = 0; + int ret; + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->dev = dev; + i2c_set_clientdata(client, chip); + + ret = devm_mutex_init(dev, &chip->lock); + if (ret) + return ret; + + chip->regmap = devm_regmap_init_i2c(client, &fusb15201_regmap_config); + if (IS_ERR(chip->regmap)) + return dev_err_probe(dev, PTR_ERR(chip->regmap), + "failed to initialise register map\n"); + + ret = fusb15201_check_id(chip); + if (ret) + return ret; + + device_for_each_child_node_scoped(dev, fwnode) { + ret = fusb15201_register_port(chip, fwnode); + if (ret) + return ret; + + nports++; + } + + if (!nports) + return dev_err_probe(dev, -ENODEV, "no connector described\n"); + + ret = fusb15201_hw_init(chip); + if (ret) + return dev_err_probe(dev, ret, "failed to initialise\n"); + + ret = devm_request_threaded_irq(dev, client->irq, NULL, fusb15201_irq, + IRQF_ONESHOT, dev_name(dev), chip); + if (ret) + return dev_err_probe(dev, ret, "failed to request irq\n"); + + return 0; +} + +static const struct of_device_id fusb15201_of_match[] = { + { .compatible = "onnn,fusb15201" }, + { } +}; +MODULE_DEVICE_TABLE(of, fusb15201_of_match); + +static struct i2c_driver fusb15201_driver = { + .driver = { + .name = "fusb15201", + .of_match_table = fusb15201_of_match, + }, + .probe = fusb15201_probe, +}; +module_i2c_driver(fusb15201_driver); + +MODULE_AUTHOR("Shawn Guo "); +MODULE_DESCRIPTION("onsemi FUSB15201 Type-C and Power Delivery controller"); +MODULE_LICENSE("GPL"); From 470f8337de6f628807c368066e3e023b2e63113f Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 8 Oct 2026 09:50:15 +0800 Subject: [PATCH 0220/1133] FROMLIST: dt-bindings: phy: qcom,sc8280xp-qmp-usb43dp-phy: Add Nord cfg_ahb clock On Nord, the USB3-DP PHY registers are reached through the AHB2PHY_0 bridge, which is gated by NE_GCC_AHB2PHY_CLK. Describe the bridge clock as a fifth "cfg_ahb" clock for Nord, using the same clock list as SC7180 and SDM845. Link: https://lore.kernel.org/r/20261008015017.3359804-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- .../devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml index 13e64fe510b8f..809bd4e1090a7 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml @@ -209,6 +209,7 @@ allOf: compatible: contains: enum: + - qcom,nord-qmp-usb3-dp-phy - qcom,sc7180-qmp-usb3-dp-phy - qcom,sdm845-qmp-usb3-dp-phy then: @@ -229,6 +230,7 @@ allOf: compatible: contains: enum: + - qcom,nord-qmp-usb3-dp-phy - qcom,x1e80100-qmp-usb3-dp-phy - qcom,sc7180-qmp-usb3-dp-phy - qcom,sdm845-qmp-usb3-dp-phy From 2b115c06c00cee034f2d9709d65ec16ba759ad50 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 8 Oct 2026 09:50:16 +0800 Subject: [PATCH 0221/1133] FROMLIST: dt-bindings: phy: qcom,snps-eusb2-phy: Add Nord bus clock On Nord, the eUSB2 PHY registers are reached through the AHB2PHY_0 bridge, which is gated by NE_GCC_AHB2PHY_CLK. Allow an optional second "bus" clock for the AHB2PHY bridge, require it for qcom,nord-snps-eusb2-phy, and keep other compatibles at the single "ref" clock. Link: https://lore.kernel.org/r/20261008015017.3359804-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- .../bindings/phy/qcom,snps-eusb2-phy.yaml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml index 931cd0e7d297e..67f2a587e65cc 100644 --- a/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,snps-eusb2-phy.yaml @@ -34,12 +34,16 @@ properties: const: 0 clocks: + minItems: 1 items: - description: ref + - description: AHB2PHY bridge clock for register access clock-names: + minItems: 1 items: - const: ref + - const: bus resets: maxItems: 1 @@ -77,6 +81,24 @@ allOf: required: - resets + - if: + properties: + compatible: + contains: + const: qcom,nord-snps-eusb2-phy + then: + properties: + clocks: + minItems: 2 + clock-names: + minItems: 2 + else: + properties: + clocks: + maxItems: 1 + clock-names: + maxItems: 1 + additionalProperties: false examples: From b15164f58ed512f3aa2605f1ca0a76e4f98f9caa Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 8 Oct 2026 09:50:17 +0800 Subject: [PATCH 0222/1133] FROMLIST: phy: phy-snps-eusb2: Enable AHB2PHY bus clock on Nord On Nord, the eUSB2 PHY registers sit behind the AHB2PHY_0 bridge, gated by NE_GCC_AHB2PHY_CLK. The Nord PHY currently matches the sm8550 fallback, which only requests the "ref" clock, so the bridge clock is never enabled by the PHY. When nothing else holds it, e.g. on boards where only the USB20-only controller is in use, clk_disable_unused() gates the bridge and PHY init accesses go nowhere: xhci-hcd xhci-hcd.2.auto: can't setup: -110 Add Nord-specific match data that requests both "ref" and "bus" clocks, reusing the existing Qualcomm init sequence. The bus clock is enabled and disabled together with the ref clock in phy init/exit. Reviewed-by: Bartosz Golaszewski Tested-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20261008015017.3359804-4-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- drivers/phy/phy-snps-eusb2.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/phy/phy-snps-eusb2.c b/drivers/phy/phy-snps-eusb2.c index af4fa17ac6cbc..8429599f428b9 100644 --- a/drivers/phy/phy-snps-eusb2.c +++ b/drivers/phy/phy-snps-eusb2.c @@ -452,6 +452,16 @@ static const struct snps_eusb2_phy_drvdata sm8550_snps_eusb2_phy = { .num_clks = ARRAY_SIZE(qcom_eusb2_hsphy_clock_names), }; +static const char * const nord_eusb2_hsphy_clock_names[] = { + "ref", "bus", +}; + +static const struct snps_eusb2_phy_drvdata nord_snps_eusb2_phy = { + .phy_init = qcom_snps_eusb2_hsphy_init, + .clk_names = nord_eusb2_hsphy_clock_names, + .num_clks = ARRAY_SIZE(nord_eusb2_hsphy_clock_names), +}; + static int snps_eusb2_hsphy_init(struct phy *p) { struct snps_eusb2_hsphy *phy = phy_get_drvdata(p); @@ -608,6 +618,9 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev) static const struct of_device_id snps_eusb2_hsphy_of_match_table[] = { { + .compatible = "qcom,nord-snps-eusb2-phy", + .data = &nord_snps_eusb2_phy, + }, { .compatible = "qcom,sm8550-snps-eusb2-phy", .data = &sm8550_snps_eusb2_phy, }, { From 7e217767b92e014d200648623f4c1afe3405947d Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 17 Sep 2026 14:20:28 +0100 Subject: [PATCH 0223/1133] FROMLIST: arm64: dts: qcom: x1e80100: Add CCI definitions Add in two CCI buses. One bus has two CCI bus master pinouts: cci_i2c_sda0 = gpio101 cci_i2c_scl0 = gpio102 cci_i2c_sda1 = gpio103 cci_i2c_scl1 = gpio104 The second bus has two CCI bus master pinouts: cci_i2c_sda2 = gpio105 cci_i2c_scl2 = gpio106 aon_cci_i2c_sda3 = gpio235 aon_cci_i2c_scl3 = gpio236 Link: https://lore.kernel.org/all/20260917-x1e-camss-csi2-phy-dtsi-v7-3-1a63eb35838b@linaro.org/ Reviewed-by: Konrad Dybcio Reviewed-by: Vladimir Zapolskiy Signed-off-by: Bryan O'Donoghue Tested-by: Liviu Nicoara # Dell XPS 13 9345 --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 150 ++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 48f47aa6ba3c7..66042a98c0b39 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -5534,6 +5534,84 @@ #power-domain-cells = <1>; }; + cci0: cci@ac15000 { + compatible = "qcom,x1e80100-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac15000 0 0x1000>; + + interrupts = ; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + pinctrl-0 = <&cci0_default>; + pinctrl-1 = <&cci0_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@ac16000 { + compatible = "qcom,x1e80100-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac16000 0 0x1000>; + + interrupts = ; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + pinctrl-0 = <&cci1_default>; + pinctrl-1 = <&cci1_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + camcc: clock-controller@ade0000 { compatible = "qcom,x1e80100-camcc"; reg = <0x0 0x0ade0000 0x0 0x20000>; @@ -6131,6 +6209,78 @@ gpio-ranges = <&tlmm 0 0 239>; wakeup-parent = <&pdc>; + cci0_default: cci0-default-state { + cci0_i2c0_default: cci0-i2c0-default-pins { + /* cci_i2c_sda0, cci_i2c_scl0 */ + pins = "gpio101", "gpio102"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + + cci0_i2c1_default: cci0-i2c1-default-pins { + /* cci_i2c_sda1, cci_i2c_scl1 */ + pins = "gpio103", "gpio104"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_sleep: cci0-sleep-state { + cci0_i2c0_sleep: cci0-i2c0-sleep-pins { + /* cci_i2c_sda0, cci_i2c_scl0 */ + pins = "gpio101", "gpio102"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + + cci0_i2c1_sleep: cci0-i2c1-sleep-pins { + /* cci_i2c_sda1, cci_i2c_scl1 */ + pins = "gpio103", "gpio104"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_default: cci1-default-state { + cci1_i2c0_default: cci1-i2c0-default-pins { + /* cci_i2c_sda2, cci_i2c_scl2 */ + pins = "gpio105", "gpio106"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + + cci1_i2c1_default: cci1-i2c1-default-pins { + /* aon_cci_i2c_sda3, aon_cci_i2c_scl3 */ + pins = "gpio235", "gpio236"; + function = "aon_cci"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_sleep: cci1-sleep-state { + cci1_i2c0_sleep: cci1-i2c0-sleep-pins { + /* cci_i2c_sda2, cci_i2c_scl2 */ + pins = "gpio105", "gpio106"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + + cci1_i2c1_sleep: cci1-i2c1-sleep-pins { + /* aon_cci_i2c_sda3, aon_cci_i2c_scl3 */ + pins = "gpio235", "gpio236"; + function = "aon_cci"; + drive-strength = <2>; + bias-pull-down; + }; + }; + edp0_hpd_default: edp0-hpd-default-state { pins = "gpio119"; function = "edp0_hot"; From 0e9226f6c187406cbe8668f268ed8c4313baa664 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 17 Sep 2026 14:20:29 +0100 Subject: [PATCH 0224/1133] FROMLIST: arm64: dts: qcom: x1e80100: Add CAMSS block definition Add dtsi to describe the x1e80100 CAMSS block 4 x CSIPHY 3 x TPG 2 x CSID 2 x CSID Lite 2 x IFE 2 x IFE Lite Link: https://lore.kernel.org/all/20260917-x1e-camss-csi2-phy-dtsi-v7-4-1a63eb35838b@linaro.org/ Signed-off-by: Bryan O'Donoghue Tested-by: Liviu Nicoara # Dell XPS 13 9345 --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 370 ++++++++++++++++++++++++++++ 1 file changed, 370 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 66042a98c0b39..400534b29f0ad 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -667,6 +667,50 @@ }; }; + csiphy_mxc_opp_table: opp-table-mxc { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + + csiphy_mxa_opp_table: opp-table-mxa { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs_d1>; + }; + }; + qup_opp_table_100mhz: opp-table-qup100mhz { compatible = "operating-points-v2"; @@ -5612,6 +5656,332 @@ }; }; + camss: isp@acb7000 { + compatible = "qcom,x1e80100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0ace4000 0 0x2000>, + <0 0x0ace6000 0 0x2000>, + <0 0x0ace8000 0 0x2000>, + <0 0x0acec000 0 0x2000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0xf000>, + <0 0x0ac71000 0 0xf000>, + <0 0x0acc7000 0 0x2000>, + <0 0x0accb000 0 0x2000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe_lite", + "cphy_rx_clk_src", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy4", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>, + <&apps_smmu 0x840 0x60>, + <&apps_smmu 0x860 0x60>, + <&apps_smmu 0x18a0 0x0>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_IFE_1_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "top"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + camss_csiphy0_in_port: port@0 { + reg = <0>; + }; + + camss_csiphy1_in_port: port@1 { + reg = <1>; + }; + + camss_csiphy2_in_port: port@2 { + reg = <2>; + }; + + camss_csiphy4_in_port: port@3 { + reg = <3>; + }; + }; + }; + + csiphy0: phy@ace4000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace4000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + csiphy0_in_port: port@0 { + reg = <0>; + }; + + csiphy0_out_port: port@1 { + reg = <1>; + }; + }; + }; + + csiphy1: phy@ace6000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace6000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + csiphy1_in_port: port@0 { + reg = <0>; + }; + + csiphy1_out_port: port@1 { + reg = <1>; + }; + }; + }; + + csiphy2: phy@ace8000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace8000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + csiphy2_in_port: port@0 { + reg = <0>; + }; + + csiphy2_out_port: port@1 { + reg = <1>; + }; + }; + }; + + csiphy4: phy@acec000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0acec000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + operating-points-v2 = <&csiphy_mxa_opp_table>; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + csiphy4_in_port: port@0 { + reg = <0>; + }; + + csiphy4_out_port: port@1 { + reg = <1>; + }; + }; + }; + camcc: clock-controller@ade0000 { compatible = "qcom,x1e80100-camcc"; reg = <0x0 0x0ade0000 0x0 0x20000>; From 18a3669b4730644da124c7351a7112dc523f3440 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 17 Sep 2026 14:20:30 +0100 Subject: [PATCH 0225/1133] FROMLIST: arm64: dts: qcom: x1e80100-crd: Add pm8010 CRD pmic,id=m regulators Add pmic,id = m rpmh to regulator definitions. This regulator set provides vreg_l3m_1p8 the regulator for the ov08x40 RGB sensor on the CRD. Link: https://lore.kernel.org/all/20260917-x1e-camss-csi2-phy-dtsi-v7-5-1a63eb35838b@linaro.org/ Reviewed-by: Konrad Dybcio Tested-by: Daniel J Blueman # Lenovo Slim 7x X1E80100 Signed-off-by: Bryan O'Donoghue Reviewed-by: Christopher Obbard --- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1-crd.dtsi b/arch/arm64/boot/dts/qcom/x1-crd.dtsi index fcd7cef6660fd..71c819aa2d43c 100644 --- a/arch/arm64/boot/dts/qcom/x1-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-crd.dtsi @@ -897,6 +897,36 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p9: ldo7 { + regulator-name = "vreg_l7m_2p9"; + regulator-min-microvolt = <2912000>; + regulator-max-microvolt = <2912000>; + regulator-initial-mode = ; + }; + }; }; &gpu { From bc39ecb5978dc912782b101c6cb8bb785245d8ba Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 17 Sep 2026 14:20:31 +0100 Subject: [PATCH 0226/1133] FROMLIST: arm64: dts: qcom: x1e80100-crd: Add ov08x40 RGB sensor on CSIPHY4 Define ov08x40 on cci1_i2c1. The RGB sensor appears on the AON CCI pins connected to CSIPHY4 in four lane mode. Link: https://lore.kernel.org/all/20260917-x1e-camss-csi2-phy-dtsi-v7-6-1a63eb35838b@linaro.org/ Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 82 ++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1-crd.dtsi b/arch/arm64/boot/dts/qcom/x1-crd.dtsi index 71c819aa2d43c..5f66e23e694db 100644 --- a/arch/arm64/boot/dts/qcom/x1-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-crd.dtsi @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include @@ -933,6 +935,70 @@ status = "okay"; }; +&camss { + status = "okay"; +}; + +&camss_csiphy4_in_port { + camss_csiphy4_inep: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&csiphy4_out_ep>; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov08x40"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&cam_rgb_default>; + pinctrl-names = "default"; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = ; + + avdd-supply = <&vreg_l7b_2p8>; + dovdd-supply = <&vreg_l3m_1p8>; + + port { + ov08x40_out_ep: endpoint { + data-lanes = <1 2 3 4>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&csiphy4_in_ep>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + +&csiphy4_in_port { + csiphy4_in_ep: endpoint { + bus-type = ; + data-lanes = <1 2 3 4>; + remote-endpoint = <&ov08x40_out_ep>; + }; +}; + +&csiphy4_out_port { + csiphy4_out_ep: endpoint { + remote-endpoint = <&camss_csiphy4_inep>; + }; +}; + &i2c0 { clock-frequency = <400000>; @@ -1585,6 +1651,22 @@ <65 1>, /* EC reset */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + ec_int_n_default: ec-int-n-state { pins = "gpio66"; function = "gpio"; From 0d8820881cf29386e62f6822a0aa284e6fb75db3 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 17 Sep 2026 14:20:32 +0100 Subject: [PATCH 0227/1133] FROMLIST: arm64: dts: qcom: x1e80100-t14s: Add pm8010 camera PMIC with voltage levels for IR and RGB camera Add the PM8010 PMIC providing the following voltage rails: vreg_l1m_r @ 1v2 IR sensor vreg_l2m_r @ 1v2 RGB sensor vreg_l3m_r @ 1v8 IR sensor vreg_l4m_r @ 1v8 RGB sensor vreg_l5m_r @ 2v8 IR sensor vreg_l7m_r @ 2v8 RGB sensor Link: https://lore.kernel.org/all/20260917-x1e-camss-csi2-phy-dtsi-v7-7-1a63eb35838b@linaro.org/ Reviewed-by: Christopher Obbard Tested-by: Christopher Obbard Tested-by: Daniel J Blueman # Lenovo Slim 7x X1E80100 Signed-off-by: Bryan O'Donoghue --- .../qcom/x1e78100-lenovo-thinkpad-t14s.dtsi | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi index 93c7e3a02041c..96d48b13f37c8 100644 --- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi @@ -562,6 +562,13 @@ regulator-initial-mode = ; }; + vreg_l7b_2p8: ldo7 { + regulator-name = "vreg_l7b_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-initial-mode = ; + }; + vreg_l8b_3p0: ldo8 { regulator-name = "vreg_l8b_3p0"; regulator-min-microvolt = <3072000>; @@ -805,6 +812,58 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p2: ldo1 { + regulator-name = "vreg_l1m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p2: ldo2 { + regulator-name = "vreg_l2m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l5m_2p8: ldo5 { + regulator-name = "vreg_l5m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p8: ldo7 { + regulator-name = "vreg_l7m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + }; + }; &gpu { From 835741ea77612bd7c8ad5e7fec89aed724da3269 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 17 Sep 2026 14:20:33 +0100 Subject: [PATCH 0228/1133] FROMLIST: arm64: dts: qcom: x1e80100-t14s: Add on ov02c10 RGB sensor on CSIPHY4 Switch on the ov02c10 RGB sensor on CSIPHY4. Link: https://lore.kernel.org/all/20260917-x1e-camss-csi2-phy-dtsi-v7-8-1a63eb35838b@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../qcom/x1e78100-lenovo-thinkpad-t14s.dtsi | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi index 96d48b13f37c8..bc492e0ff2b74 100644 --- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include @@ -866,6 +868,71 @@ }; +&camss { + status = "okay"; +}; + +&camss_csiphy4_in_port { + camss_csiphy4_inep: endpoint { + data-lanes = <1 2>; + remote-endpoint = <&csiphy4_out_ep>; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov02c10"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = ; + + avdd-supply = <&vreg_l7m_2p8>; + dvdd-supply = <&vreg_l2m_1p2>; + dovdd-supply = <&vreg_l4m_1p8>; + + port { + ov02c10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&csiphy4_in_ep>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + +&csiphy4_in_port { + csiphy4_in_ep: endpoint { + bus-type = ; + data-lanes = <1 2>; + remote-endpoint = <&ov02c10_ep>; + }; +}; + +&csiphy4_out_port { + csiphy4_out_ep: endpoint { + remote-endpoint = <&camss_csiphy4_inep>; + }; +}; + &gpu { status = "okay"; }; @@ -1469,6 +1536,22 @@ <72 2>, /* Secure EC I2C connection (?) */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + ec_int_n_default: ec-int-n-state { pins = "gpio66"; function = "gpio"; From 645a5448c411eeabcf11e7872d36b52050f1e921 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 17 Sep 2026 14:20:34 +0100 Subject: [PATCH 0229/1133] FROMLIST: arm64: dts: qcom: x1e80100-lenovo-yoga-slim7x: Add pm8010 camera PMIC with voltage levels for IR and RGB camera Add voltage regulators-8 for Camera on slim7x including: - vreg_l1m_1p2 - vreg_l3m_1p8 Link: https://lore.kernel.org/all/20260917-x1e-camss-csi2-phy-dtsi-v7-9-1a63eb35838b@linaro.org/ Tested-by: Daniel J Blueman # Lenovo Slim 7x X1E80100 Signed-off-by: Bryan O'Donoghue Reviewed-by: Christopher Obbard --- .../dts/qcom/x1e80100-lenovo-yoga-slim7x.dts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index a807744d1750b..5ce1a7755c97b 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -795,6 +795,57 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p2: ldo1 { + regulator-name = "vreg_l1m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p2: ldo2 { + regulator-name = "vreg_l2m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l5m_2p8: ldo5 { + regulator-name = "vreg_l5m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p8: ldo7 { + regulator-name = "vreg_l7m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + }; }; &gpu { From 9d0d943a59d6a015b8cb57dc0a7b408cdf01e15e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 17 Sep 2026 14:20:35 +0100 Subject: [PATCH 0230/1133] FROMLIST: arm64: dts: qcom: x1e80100-lenovo-yoga-slim7x: Add l7b_2p8 voltage regulator for RGB camera Some sleuthing work by Aleksandrs Vinarskis in the bowels of the ACPI tables for this part shows we need l7b_2p8 for the avdd supply. Link: https://lore.kernel.org/all/20260917-x1e-camss-csi2-phy-dtsi-v7-10-1a63eb35838b@linaro.org/ Suggested-by: Aleksandrs Vinarskis Tested-by: Daniel J Blueman # Lenovo Slim 7x X1E80100 Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index 5ce1a7755c97b..a1629b0824e01 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -552,6 +552,13 @@ regulator-initial-mode = ; }; + vreg_l7b_2p8: ldo7 { + regulator-name = "vreg_l7b_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-initial-mode = ; + }; + vreg_l8b_3p0: ldo8 { regulator-name = "vreg_l8b_3p0"; regulator-min-microvolt = <3072000>; From dd35864c65f9442d9b255308ad641d2e59ee902c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 17 Sep 2026 14:20:36 +0100 Subject: [PATCH 0231/1133] FROMLIST: arm64: dts: qcom: x1e80100-lenovo-yoga-slim7x: Add ov02c10 RGB sensor on CSIPHY4 Add in the RGB sensor on CSIPHY4. Link: https://lore.kernel.org/all/20260917-x1e-camss-csi2-phy-dtsi-v7-11-1a63eb35838b@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../dts/qcom/x1e80100-lenovo-yoga-slim7x.dts | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index a1629b0824e01..68864a294b2d8 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -7,6 +7,8 @@ #include #include +#include +#include #include #include "hamoa.dtsi" @@ -863,6 +865,71 @@ firmware-name = "qcom/x1e80100/LENOVO/83ED/qcdxkmsuc8380.mbn"; }; +&camss { + status = "okay"; +}; + +&camss_csiphy4_in_port { + camss_csiphy4_inep: endpoint { + data-lanes = <1 2>; + remote-endpoint = <&csiphy4_out_ep>; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov02c10"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = ; + + avdd-supply = <&vreg_l7b_2p8>; + dvdd-supply = <&vreg_l1m_1p2>; + dovdd-supply = <&vreg_l3m_1p8>; + + port { + ov02c10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&csiphy4_in_ep>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + +&csiphy4_in_port { + csiphy4_in_ep: endpoint { + bus-type = ; + data-lanes = <1 2>; + remote-endpoint = <&ov02c10_ep>; + }; +}; + +&csiphy4_out_port { + csiphy4_out_ep: endpoint { + remote-endpoint = <&camss_csiphy4_inep>; + }; +}; + &i2c0 { clock-frequency = <400000>; @@ -1448,6 +1515,22 @@ <65 1>, /* EC reset */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + ec_int_n_default: ec-int-n-state { pins = "gpio66"; function = "gpio"; From 1b0722b3bf0ba165d427b127e80689354baf27dc Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 17 Sep 2026 14:20:37 +0100 Subject: [PATCH 0232/1133] FROMLIST: arm64: dts: qcom: x1e80100-dell-inspiron14-7441: Switch on CAMSS RGB sensor Inspiron14 has a ov02e10 sensor on CSIPHY4. Enable the list of dependencies now. Link: Link: https://lore.kernel.org/all/20260917-x1e-camss-csi2-phy-dtsi-v7-12-1a63eb35838b@linaro.org/ Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi | 67 +++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi index f00feb3ca85c6..cdfe1c8b396c1 100644 --- a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include "hamoa-pmics.dtsi" @@ -794,6 +796,71 @@ }; }; +&camss { + status = "okay"; +}; + +&camss_csiphy4_in_port { + camss_csiphy4_inep: endpoint { + data-lanes = <1 2>; + remote-endpoint = <&csiphy4_out_ep>; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@10 { + compatible = "ovti,ov02e10"; + reg = <0x10>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = ; + + avdd-supply = <&vreg_l7b_2p8>; + dvdd-supply = <&vreg_l7b_2p8>; + dovdd-supply = <&vreg_cam_1p8>; + + port { + ov02e10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <360000000>; + remote-endpoint = <&csiphy4_in_ep>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + +&csiphy4_in_port { + csiphy4_in_ep: endpoint { + bus-type = ; + data-lanes = <1 2>; + remote-endpoint = <&ov02e10_ep>; + }; +}; + +&csiphy4_out_port { + csiphy4_out_ep: endpoint { + remote-endpoint = <&camss_csiphy4_inep>; + }; +}; + &i2c0 { clock-frequency = <400000>; From f9ab10f0dd6f99cbb55b4acd9e6242154aab0abc Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Thu, 12 Mar 2026 21:26:35 +0530 Subject: [PATCH 0233/1133] FROMLIST: arm64: dts: qcom: x1e80100: Remove interconnect from SCM device Interconnect from SCM device are optional and were added to get additional performance benefit. These nodes however delays the SCM firmware device probe due to dependency on interconnect and results in NULL pointer dereference for the users of SCM device driver APIs, such as PDC driver. Remove them from the scm device to unblock the user. Link: https://lore.kernel.org/r/20260312-hamoa_pdc-v1-1-760c8593ce50@oss.qualcomm.com Signed-off-by: Maulik Shah Signed-off-by: Sneh Mankad --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 400534b29f0ad..e84900294fc92 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -329,8 +329,7 @@ firmware { scm: scm { compatible = "qcom,scm-x1e80100", "qcom,scm"; - interconnects = <&aggre2_noc MASTER_CRYPTO QCOM_ICC_TAG_ALWAYS - &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + /* TODO: add interconnects */ qcom,dload-mode = <&tcsr 0x19000>; }; From 1649179715c52decfedb6d9dc8c8491df888ff7c Mon Sep 17 00:00:00 2001 From: Renjiang Han Date: Thu, 4 Jun 2026 13:50:54 +0530 Subject: [PATCH 0234/1133] PENDING: arm64: dts: enable iris driver for hamoa kvm Add video firmware node to enable video kvm on the hamoa. Signed-off-by: Renjiang Han --- arch/arm64/boot/dts/qcom/x1-el2.dtso | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/x1-el2.dtso b/arch/arm64/boot/dts/qcom/x1-el2.dtso index ee006742d6f3b..8bbe5e61402b0 100644 --- a/arch/arm64/boot/dts/qcom/x1-el2.dtso +++ b/arch/arm64/boot/dts/qcom/x1-el2.dtso @@ -17,8 +17,10 @@ }; &iris { - /* TODO: Add video-firmware iommus to start IRIS from EL2 */ - status = "disabled"; + status = "okay"; + video-firmware { + iommus = <&apps_smmu 0x1942 0x0>; + }; }; /* From e81d780e74ac6c64274eedeb00dccbe5ac9cf293 Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Wed, 1 Jul 2026 14:14:36 +0800 Subject: [PATCH 0235/1133] FROMLIST: arm64: dts: qcom: hamoa: Enable CDSP cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP does not throttle its speed automatically when it reaches high temperatures in hamoa. Set up CDSP cooling by throttling the cdsp, when it reaches 95°C. Add polling-delay-passive so the governor periodically evaluates the zone during passive cooling and steps up cooling levels when temperature stabilizes below the next trip. Update the NSP passive trip thresholds to 105°C to align with the higher temperature specification for Hamoa IOT. Link: https://lore.kernel.org/all/20260809-b4-qmi-tmd-v8-9-b15d47adc379@oss.qualcomm.com/ Reviewed-by: Abel Vesa Reviewed-by: Dmitry Baryshkov Signed-off-by: Dipa Ramesh Mantre Signed-off-by: Gaurav Kohli --- arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts | 16 ++++++ arch/arm64/boot/dts/qcom/hamoa.dtsi | 63 ++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts index d0433cc3623fe..0d5cd1130f71f 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts @@ -1650,3 +1650,19 @@ }; }; }; + +&nsp0_alert0 { + temperature = <105000>; +}; + +&nsp1_alert0 { + temperature = <105000>; +}; + +&nsp2_alert0 { + temperature = <105000>; +}; + +&nsp3_alert0 { + temperature = <105000>; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index e84900294fc92..5e29d6cca5d60 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -22,6 +22,7 @@ #include #include #include +#include #include / { @@ -9522,6 +9523,8 @@ status = "disabled"; + #cooling-cells = <3>; + glink-edge { interrupts-extended = <&ipcc IPCC_CLIENT_CDSP IPCC_MPROC_SIGNAL_GLINK_QMP @@ -10109,6 +10112,7 @@ }; thermal_nsp0: nsp0-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 1>; trips { @@ -10118,15 +10122,30 @@ type = "hot"; }; + nsp0_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp0-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp0_alert0>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_nsp1: nsp1-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 2>; trips { @@ -10136,15 +10155,30 @@ type = "hot"; }; + nsp1_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp1-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp1_alert0>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_nsp2: nsp2-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 3>; trips { @@ -10154,15 +10188,30 @@ type = "hot"; }; + nsp2_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp2-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp2_alert0>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_nsp3: nsp3-thermal { + polling-delay-passive = <200>; thermal-sensors = <&tsens3 4>; trips { @@ -10172,12 +10221,26 @@ type = "hot"; }; + nsp3_alert0: trip-point1 { + temperature = <95000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp3-critical { temperature = <115000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp3_alert0>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; thermal_gpuss_0: gpuss-0-thermal { From 62b8e677158874a97599c0ce3df6b3b8599e1649 Mon Sep 17 00:00:00 2001 From: Anvesh Jain P Date: Fri, 3 Jul 2026 15:23:42 +0530 Subject: [PATCH 0236/1133] FROMLIST: arm64: dts: qcom: purwa-iot-evk: Add Embedded controller node Add embedded controller node for Purwa IOT EVK boards which adds fan control, temperature sensors, access to EC internal state changes and suspend entry/exit notifications to the EC. Link: https://lore.kernel.org/all/20260703-ec_support_for_purwa_evk-v2-2-c59aac5c6aac@oss.qualcomm.com/ Tested-by: Yushan Li Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Anvesh Jain P --- arch/arm64/boot/dts/qcom/purwa-iot-evk.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts index a811d8ca2dbf3..60b70d059aeda 100644 --- a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts @@ -841,6 +841,16 @@ pinctrl-0 = <&eusb6_reset_n>; pinctrl-names = "default"; }; + + embedded-controller@76 { + compatible = "qcom,purwa-iot-evk-ec", "qcom,hamoa-crd-ec"; + reg = <0x76>; + + interrupts-extended = <&tlmm 66 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-0 = <&ec_int_n_default>; + pinctrl-names = "default"; + }; }; &i2c7 { @@ -1351,6 +1361,12 @@ }; &tlmm { + ec_int_n_default: ec-int-n-state { + pins = "gpio66"; + function = "gpio"; + bias-disable; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; From 9077c52dc6002264b907d286e9ab83a916e39082 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Mon, 5 Oct 2026 17:54:04 +0530 Subject: [PATCH 0237/1133] FROMLIST: arm64: dts: qcom: hamoa-pmic: Enable BCL sensor node Add Battery Current Limiting (BCL) hardware monitor node for hamoa-pmic. The BCL monitors battery voltage and current, providing hardware interrupts when configurable thresholds are violated. Reviewed-by: Abel Vesa Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/all/20261005-qcom-bcl-hwmon-v4-3-50b9a8c730b7@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi b/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi index 7fad4a9b92fa2..6b17d568188e9 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-pmics.dtsi @@ -426,6 +426,17 @@ io-channel-names = "thermal"; }; + sensor@4700 { + compatible = "qcom,pm8550-bcl"; + reg = <0x4700>; + interrupts = <0x1 0x47 0x0 IRQ_TYPE_EDGE_RISING>, + <0x1 0x47 0x1 IRQ_TYPE_EDGE_RISING>, + <0x1 0x47 0x2 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "max-min", + "critical", + "emergency"; + }; + pm8550_gpios: gpio@8800 { compatible = "qcom,pm8550-gpio", "qcom,spmi-gpio"; reg = <0x8800>; @@ -674,6 +685,17 @@ status = "disabled"; + sensor@4700 { + compatible = "qcom,smb2360-bcl"; + reg = <0x4700>; + interrupts = <0x7 0x47 0x0 IRQ_TYPE_EDGE_RISING>, + <0x7 0x47 0x1 IRQ_TYPE_EDGE_RISING>, + <0x7 0x47 0x2 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "max-min", + "critical", + "emergency"; + }; + smb2360_0_eusb2_repeater: phy@fd00 { compatible = "qcom,smb2360-eusb2-repeater"; reg = <0xfd00>; From ed2db86860d4b3b2c1c743b70fd0622cf3521712 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 9 Jul 2026 18:05:53 +0530 Subject: [PATCH 0238/1133] FROMLIST: arm64: dts: qcom: hamoa: Move Iris IOMMUs to sub nodes The Iris VPU has separate streams with different IOVA constraints. The non-pixel stream must be limited to the 0-600 MB IOVA range, while the pixel stream can use the full IOVA space. Using a single set of IOMMU entries for the Iris node does not describe these per-stream limits and can allow accesses outside the supported range, which may lead to device crashes. One such issue was reported at: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Add non-pixel and pixel child nodes, move each stream ID to its corresponding child node, and add a reserved IOVA range for the non-pixel stream. Link: https://lore.kernel.org/all/20260709-vpu_iommu_iova_handling-v1-7-72bb62cb2dfd@oss.qualcomm.com Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Tested-by: Daniel J Blueman --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 5e29d6cca5d60..6b7260ab982db 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -665,6 +665,10 @@ hwlocks = <&tcsr_mutex 3>; no-map; }; + + iris_resv: reservation-iris { + iommu-addresses = <&iris_non_pixel 0x0 0x0 0x0 0x25800000>; + }; }; csiphy_mxc_opp_table: opp-table-mxc { @@ -5512,10 +5516,11 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x1940 0>, - <&apps_smmu 0x1947 0>; dma-coherent; + #address-cells = <2>; + #size-cells = <2>; + /* * IRIS firmware is signed by vendors, only * enable on boards where the proper signed firmware @@ -5523,6 +5528,15 @@ */ status = "disabled"; + iris_non_pixel: non-pixel { + iommus = <&apps_smmu 0x1940 0x0>; + memory-region = <&iris_resv>; + }; + + iris_pixel: pixel { + iommus = <&apps_smmu 0x1947 0x0>; + }; + iris_opp_table: opp-table { compatible = "operating-points-v2"; From cd50909f0076961c4fe855574c2a1cc611f91b28 Mon Sep 17 00:00:00 2001 From: Wenjia Zhang Date: Wed, 22 Jul 2026 18:14:03 +0800 Subject: [PATCH 0239/1133] FROMLIST: hamoa: Add ICE node for UFS inline encryption Add the Inline Crypto Engine (ICE) device node to describe the hardware-accelerated inline encryption for UFS storage on the Hamoa IoT EVK board (Qualcomm X1E80100 SoC). Link: https://lore.kernel.org/all/20260728-hamoa_ufs_ice_change-v3-2-293c7c6c2ae5@oss.qualcomm.com/ Signed-off-by: Wenjia Zhang --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 6b7260ab982db..d6f96077a5217 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -3975,6 +3975,8 @@ phys = <&ufs_mem_phy>; phy-names = "ufsphy"; + qcom,ice = <&ice>; + #reset-cells = <1>; status = "disabled"; @@ -4020,6 +4022,17 @@ }; }; + ice: crypto@1d88000 { + compatible = "qcom,x1e80100-inline-crypto-engine", + "qcom,inline-crypto-engine"; + reg = <0x0 0x01d88000 0x0 0x18000>; + clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>, + <&gcc GCC_UFS_PHY_AHB_CLK>; + clock-names = "core", + "iface"; + power-domains = <&gcc GCC_UFS_PHY_GDSC>; + }; + cryptobam: dma-controller@1dc4000 { compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; reg = <0x0 0x01dc4000 0x0 0x28000>; From c08bcce9284bc03d632b78349fb5b51809870874 Mon Sep 17 00:00:00 2001 From: Tingguo Cheng Date: Mon, 28 Sep 2026 16:50:28 +0800 Subject: [PATCH 0240/1133] PENDING: arm64: dts: qcom: hamoa-iot-som: Add pm8010 camera PMIC regulators Add the PM8010 PMIC providing the following voltage rails: - vreg_l1m_1p1 @ 1v1 camera core (DVDD) - vreg_l2m_1p15 @ 1v15 camera core (DVDD) - vreg_l3m_1p8 @ 1v8 camera analog/IO (AVDD2, DOVDD) - vreg_l4m_1p8 @ 1v8 camera IO (DOVDD) - vreg_l5m_3p0 @ 3v0 camera VCM - vreg_l6m_1p8 @ 1v8 camera analog (AVDD2) - vreg_l7m_2p9 @ 2v9 camera analog (AVDD) Signed-off-by: Tingguo Cheng Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi | 61 +++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi b/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi index f139f3adb9335..8b557455defa7 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-som.dtsi @@ -376,6 +376,67 @@ regulator-initial-mode = ; }; }; + + /* PM8010_M */ + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l5-supply = <&vreg_bob1>; + vdd-l6-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p1: ldo1 { + regulator-name = "vreg_l1m_1p1"; + regulator-min-microvolt = <1056000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p15: ldo2 { + regulator-name = "vreg_l2m_1p15"; + regulator-min-microvolt = <1152000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l5m_3p0: ldo5 { + regulator-name = "vreg_l5m_3p0"; + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + }; + + vreg_l6m_1p8: ldo6 { + regulator-name = "vreg_l6m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p9: ldo7 { + regulator-name = "vreg_l7m_2p9"; + regulator-min-microvolt = <2912000>; + regulator-max-microvolt = <2912000>; + regulator-initial-mode = ; + }; + }; }; &iris { From 08eb5d5fd31a6821470c994eefb46f43007201d6 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Mon, 28 Sep 2026 17:00:36 +0800 Subject: [PATCH 0241/1133] PENDING: arm64: dts: qcom: hamoa-iot-evk-camera-imx577: Add DT overlay Enable IMX577 via CCI on Hamoa EVK Core Kit. The Hamoa EVK board does not include a camera sensor by default. This DTSO enables the Arducam 12.3MP IMX577 Mini Camera Module on the CSI-1 interface. The module is powered from a 3.3V supply enabled via TLMM GPIO19. Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/Makefile | 4 + .../dts/qcom/hamoa-iot-evk-camera-imx577.dtso | 88 +++++++++++++++++++ arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts | 16 ++++ 3 files changed, 108 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/hamoa-iot-evk-camera-imx577.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..b6190d9fb6474 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -25,6 +25,10 @@ dtb-$(CONFIG_ARCH_QCOM) += glymur-qcb.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-advantech-som-db5830.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk.dtb +dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk-camera-imx577.dtbo +hamoa-iot-evk-camera-imx577-dtbs := hamoa-iot-evk.dtb hamoa-iot-evk-camera-imx577.dtbo +dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk-camera-imx577.dtb + hamoa-iot-evk-el2-dtbs := hamoa-iot-evk.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk-el2.dtb diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk-camera-imx577.dtso b/arch/arm64/boot/dts/qcom/hamoa-iot-evk-camera-imx577.dtso new file mode 100644 index 0000000000000..96d20deee6b83 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk-camera-imx577.dtso @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include + +&{/} { + vreg_cam1_3p3: regulator-cam1 { + compatible = "regulator-fixed"; + regulator-name = "vreg_cam1_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <1000>; + enable-active-high; + gpio = <&tlmm 19 GPIO_ACTIVE_HIGH>; + }; +}; + +&camss { + status = "okay"; +}; + +&camss_csiphy1_in_port { + camss_csiphy1_ep: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&csiphy1_out_ep>; + }; +}; + +&cci0 { + status = "okay"; +}; + +&cci0_i2c1 { + #address-cells = <1>; + #size-cells = <0>; + + camera@1a { + compatible = "sony,imx577"; + reg = <0x1a>; + + reset-gpios = <&tlmm 110 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&cam1_default>; + pinctrl-names = "default"; + + clocks = <&camcc CAM_CC_MCLK1_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK1_CLK>; + assigned-clock-rates = <24000000>; + + avdd-supply = <&vreg_cam1_3p3>; + dovdd-supply = <&vreg_l4m_1p8>; + + port { + imx577_ep: endpoint { + link-frequencies = /bits/ 64 <600000000>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&csiphy1_in_ep>; + }; + }; + }; +}; + +&csiphy1 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + +&csiphy1_in_port { + csiphy1_in_ep: endpoint { + bus-type = ; + data-lanes = <1 2 3 4>; + remote-endpoint = <&imx577_ep>; + }; +}; + +&csiphy1_out_port { + csiphy1_out_ep: endpoint { + remote-endpoint = <&camss_csiphy1_ep>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts index 0d5cd1130f71f..ed6c68955fb99 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts @@ -1349,6 +1349,22 @@ }; &tlmm { + cam1_default: cam1-default-state { + mclk-pins { + pins = "gpio97"; + function = "cam_mclk"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio110"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + ec_int_n_default: ec-int-n-state { pins = "gpio66"; function = "gpio"; From efed4420ae418e4e24189132159c333b1be607f9 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:33 +0800 Subject: [PATCH 0242/1133] PENDING: arm64: dts: qcom: purwa: Add camss node Add node for the X1P42100 camera subsystem. Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/purwa.dtsi | 106 ++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi index 4348dd3d1dc59..5188a3a219ac5 100644 --- a/arch/arm64/boot/dts/qcom/purwa.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa.dtsi @@ -9,6 +9,9 @@ #include /delete-node/ &bwmon_cluster0; +/delete-node/ &camss_csiphy1_in_port; +/delete-node/ &camss_csiphy2_in_port; +/delete-node/ &camss_csiphy4_in_port; /delete-node/ &cluster_pd2; /delete-node/ &cpu_map_cluster2; /delete-node/ &cpu8; @@ -19,6 +22,8 @@ /delete-node/ &cpu_pd9; /delete-node/ &cpu_pd10; /delete-node/ &cpu_pd11; +/delete-node/ &csiphy1; +/delete-node/ &csiphy2; /delete-node/ &gpu_opp_table; /delete-node/ &gpu_speed_bin; /delete-node/ &iris_opp_table; @@ -39,6 +44,107 @@ /delete-node/ &thermal_gpuss_6; /delete-node/ &thermal_gpuss_7; +&camss { + compatible = "qcom,x1p42100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0xf000>, + <0 0x0acc7000 0 0x1000>, + <0 0x0accb000 0 0x1000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + interrupts = , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + + clock-names = "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "gcc_axi_hf", + "vfe0", + "vfe0_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc"; + + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "top"; + + status = "disabled"; + + ports { + camss_csiphy4_in_port: port@1 { + reg = <1>; + }; + }; +}; + &camcc { compatible = "qcom,x1p42100-camcc"; }; From 2b54e0de63eabd38d8db747bb81a613caeb16fa5 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:34 +0800 Subject: [PATCH 0243/1133] PENDING: arm64: dts: qcom: purwa-iot-evk: Add camss node enable camss node for purwa iot evk board camss tpg support. Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/purwa-iot-evk.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts index 60b70d059aeda..f62e6d9044f89 100644 --- a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts @@ -738,6 +738,10 @@ }; }; +&camss { + status = "okay"; +}; + &i2c3 { clock-frequency = <400000>; From a5c560a7a26b0e168cf3bccde00fb09253f440b8 Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Mon, 31 Aug 2026 18:22:16 +0800 Subject: [PATCH 0244/1133] FROMLIST: arm64: dts: qcom: hamoa: Add PSCI SYSTEM_RESET2 types Add support for SYSTEM_RESET2 vendor-specific resets as reboot-modes in the psci node. Describe the resets: "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/all/20260901075552.3558150-2-xin.liu@oss.qualcomm.com/ Signed-off-by: Xin Liu --- arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts | 7 +++++++ arch/arm64/boot/dts/qcom/hamoa.dtsi | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts index ed6c68955fb99..a63d3e28273bd 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts @@ -1190,6 +1190,13 @@ status = "okay"; }; +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; + &sdhc_2 { cd-gpios = <&tlmm 71 GPIO_ACTIVE_LOW>; diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index d6f96077a5217..d795fd7ba8b0d 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -373,7 +373,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; From 341fc09044b2ac5408f035595405207e4dd5951c Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Mon, 31 Aug 2026 18:22:16 +0800 Subject: [PATCH 0245/1133] FROMLIST: arm64: dts: qcom: purwa: Add PSCI SYSTEM_RESET2 types Add support for SYSTEM_RESET2 vendor-specific resets as reboot-modes in the psci node. Describe the resets: "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/all/20260901075552.3558150-3-xin.liu@oss.qualcomm.com/ Signed-off-by: Xin Liu --- arch/arm64/boot/dts/qcom/purwa-iot-evk.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts index f62e6d9044f89..21a598321d592 100644 --- a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts @@ -1187,6 +1187,13 @@ status = "okay"; }; +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; + &sdhc_2 { cd-gpios = <&tlmm 71 GPIO_ACTIVE_LOW>; From 0e10c226cb6228c60b962311ac18cf77b7df4868 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 22 Sep 2026 18:35:21 +0800 Subject: [PATCH 0246/1133] FROMLIST: arm64: dts: qcom: hamoa: Add CoreSight nodes for APSS debug block The APSS debug block is built with CoreSight devices like ETM, replicator, funnel and TMC ETF. Add dt nodes for these devices to enable ETM trace. The replicator, funnel and TMC ETF nodes in this block are physically powered by the CPU cluster power rail rather than by a dedicated always-on rail. Add a power-domains property referencing the corresponding cluster_pdN domain to each of these nodes, so their power state is tied to the CPU cluster domain and the runtime PM core can power the domain on before the devices are accessed and let it be powered off otherwise. Link: https://lore.kernel.org/all/20260922-add-etm-devices-for-multiple-qcom-platforms-v1-1-c2a8c3225a2e@oss.qualcomm.com/ Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 884 ++++++++++++++++++++++++++++ arch/arm64/boot/dts/qcom/purwa.dtsi | 12 + 2 files changed, 896 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index d795fd7ba8b0d..48cc6c89b541a 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -327,6 +327,210 @@ }; }; + etm-0 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + etm-1 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + etm-2 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + etm-3 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + etm-4 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu4>; + qcom,skip-power-up; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + etm-5 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu5>; + qcom,skip-power-up; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; + + etm-6 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu6>; + qcom,skip-power-up; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_2_rep_in>; + }; + }; + }; + }; + + etm-7 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu7>; + qcom,skip-power-up; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_3_rep_in>; + }; + }; + }; + }; + + etm8: etm-8 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu8>; + qcom,skip-power-up; + + out-ports { + port { + etm8_out: endpoint { + remote-endpoint = <&ncc2_0_rep_in>; + }; + }; + }; + }; + + etm9: etm-9 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu9>; + qcom,skip-power-up; + + out-ports { + port { + etm9_out: endpoint { + remote-endpoint = <&ncc2_1_rep_in>; + }; + }; + }; + }; + + etm10: etm-10 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu10>; + qcom,skip-power-up; + + out-ports { + port { + etm10_out: endpoint { + remote-endpoint = <&ncc2_2_rep_in>; + }; + }; + }; + }; + + etm11: etm-11 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu11>; + qcom,skip-power-up; + + out-ports { + port { + etm11_out: endpoint { + remote-endpoint = <&ncc2_3_rep_in>; + }; + }; + }; + }; + firmware { scm: scm { compatible = "qcom,scm-x1e80100", "qcom,scm"; @@ -7533,6 +7737,14 @@ }; }; + port@4 { + reg = <4>; + + funnel1_in4: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; + port@5 { reg = <5>; @@ -8980,6 +9192,678 @@ }; }; + funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + + port@2 { + reg = <2>; + + apss_funnel_in2: endpoint { + remote-endpoint = <&ncc2_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&funnel1_in4>; + }; + }; + }; + }; + + funnel@13401000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x13401000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@13409000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x13409000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + replicator@13490000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x13490000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@134a0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x134a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@134b0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x134b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@134c0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x134c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + funnel@134d0000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x134d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd0>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + funnel@13901000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x13901000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@13909000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x13909000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + replicator@13990000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x13990000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@139a0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x139a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; + + replicator@139b0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x139b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + + in-ports { + port { + ncc1_2_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in2>; + }; + }; + }; + }; + + replicator@139c0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x139c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + + in-ports { + port { + ncc1_3_rep_in: endpoint { + remote-endpoint = <&etm7_out>; + }; + }; + }; + + out-ports { + port { + ncc1_3_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in3>; + }; + }; + }; + }; + + funnel@139d0000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x139d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd1>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc1_1_funnel_in2: endpoint { + remote-endpoint = <&ncc1_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc1_1_funnel_in3: endpoint { + remote-endpoint = <&ncc1_3_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; + }; + }; + }; + }; + + cluster2_funnel_l2: funnel@13e01000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x13e01000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc2_2_funnel_in2: endpoint { + remote-endpoint = <&ncc2_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc2_2_funnel_out: endpoint { + remote-endpoint = <&ncc2_etf_in>; + }; + }; + }; + }; + + cluster2_etf: tmc@13e09000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x13e09000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + + in-ports { + port { + ncc2_etf_in: endpoint { + remote-endpoint = <&ncc2_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc2_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in2>; + }; + }; + }; + }; + + cluster2_rep_2_0: replicator@13e90000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x13e90000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + + in-ports { + port { + ncc2_0_rep_in: endpoint { + remote-endpoint = <&etm8_out>; + }; + }; + }; + + out-ports { + port { + ncc2_0_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in0>; + }; + }; + }; + }; + + cluster2_rep_2_1: replicator@13ea0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x13ea0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + + in-ports { + port { + ncc2_1_rep_in: endpoint { + remote-endpoint = <&etm9_out>; + }; + }; + }; + + out-ports { + port { + ncc2_1_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in1>; + }; + }; + }; + }; + + cluster2_rep_2_2: replicator@13eb0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x13eb0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + + in-ports { + port { + ncc2_2_rep_in: endpoint { + remote-endpoint = <&etm10_out>; + }; + }; + }; + + out-ports { + port { + ncc2_2_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in2>; + }; + }; + }; + }; + + cluster2_rep_2_3: replicator@13ec0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x13ec0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + + in-ports { + port { + ncc2_3_rep_in: endpoint { + remote-endpoint = <&etm11_out>; + }; + }; + }; + + out-ports { + port { + ncc2_3_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in3>; + }; + }; + }; + }; + + cluster2_funnel_l1: funnel@13ed0000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x13ed0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster_pd2>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc2_1_funnel_in0: endpoint { + remote-endpoint = <&ncc2_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc2_1_funnel_in1: endpoint { + remote-endpoint = <&ncc2_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc2_1_funnel_in2: endpoint { + remote-endpoint = <&ncc2_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc2_1_funnel_in3: endpoint { + remote-endpoint = <&ncc2_3_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc2_1_funnel_out: endpoint { + remote-endpoint = <&ncc2_2_funnel_in2>; + }; + }; + }; + }; + apps_smmu: iommu@15000000 { compatible = "qcom,x1e80100-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0 0x15000000 0 0x100000>; diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi index 5188a3a219ac5..fbc5716924d64 100644 --- a/arch/arm64/boot/dts/qcom/purwa.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa.dtsi @@ -8,10 +8,18 @@ #include +/delete-node/ &apss_funnel_in2; /delete-node/ &bwmon_cluster0; /delete-node/ &camss_csiphy1_in_port; /delete-node/ &camss_csiphy2_in_port; /delete-node/ &camss_csiphy4_in_port; +/delete-node/ &cluster2_etf; +/delete-node/ &cluster2_funnel_l1; +/delete-node/ &cluster2_funnel_l2; +/delete-node/ &cluster2_rep_2_0; +/delete-node/ &cluster2_rep_2_1; +/delete-node/ &cluster2_rep_2_2; +/delete-node/ &cluster2_rep_2_3; /delete-node/ &cluster_pd2; /delete-node/ &cpu_map_cluster2; /delete-node/ &cpu8; @@ -24,6 +32,10 @@ /delete-node/ &cpu_pd11; /delete-node/ &csiphy1; /delete-node/ &csiphy2; +/delete-node/ &etm8; +/delete-node/ &etm9; +/delete-node/ &etm10; +/delete-node/ &etm11; /delete-node/ &gpu_opp_table; /delete-node/ &gpu_speed_bin; /delete-node/ &iris_opp_table; From e430db8448217b38177fa56e7d63cb5c8c144694 Mon Sep 17 00:00:00 2001 From: Le Qi Date: Fri, 9 Oct 2026 10:56:25 +0800 Subject: [PATCH 0247/1133] FROMLIST: arm64: dts: qcom: hamoa-iot-evk: add missing DP2 audio link The DP2 DAI link is missing from the sound card definition, preventing audio playback over the third DisplayPort interface. Add the required codec, CPU, and platform DAI configuration. Audio playback over DP2 has been verified with this change. Link: https://lore.kernel.org/all/20261009025831.1476396-1-le.qi@oss.qualcomm.com/ Signed-off-by: Le Qi --- arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts index a63d3e28273bd..ba45e87c79105 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/hamoa-iot-evk.dts @@ -647,6 +647,22 @@ sound-dai = <&q6apm>; }; }; + + dp2-dai-link { + link-name = "DP2 Playback"; + + codec { + sound-dai = <&mdss_dp2>; + }; + + cpu { + sound-dai = <&q6apmbedai DISPLAY_PORT_RX_2>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; }; wifi-bt-connector { From 67828dd022cf208ebd87e6ffdfcb4a221c720c21 Mon Sep 17 00:00:00 2001 From: Le Qi Date: Fri, 9 Oct 2026 11:02:24 +0800 Subject: [PATCH 0248/1133] FROMLIST: arm64: dts: qcom: purwa-iot-evk: add missing DP2 audio link The DP2 DAI link is missing from the sound card definition, preventing audio playback over the third DisplayPort interface. Add the required codec, CPU, and platform DAI configuration to enable audio playback over DP2. Link: https://lore.kernel.org/all/20261009030404.1981995-1-le.qi@oss.qualcomm.com/ Signed-off-by: Le Qi --- arch/arm64/boot/dts/qcom/purwa-iot-evk.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts index 21a598321d592..ac4242ca2bbd8 100644 --- a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts @@ -641,6 +641,22 @@ sound-dai = <&q6apm>; }; }; + + dp2-dai-link { + link-name = "DP2 Playback"; + + codec { + sound-dai = <&mdss_dp2>; + }; + + cpu { + sound-dai = <&q6apmbedai DISPLAY_PORT_RX_2>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; }; wifi-bt-connector { From d6676e85e9cc14fff02e136013ffb707c4da9337 Mon Sep 17 00:00:00 2001 From: Yuanjie Yang Date: Thu, 29 Oct 2026 07:38:20 +0000 Subject: [PATCH 0249/1133] FROMLIST: arm64: dts: qcom: hamoa: Add EL2 overlay for hamoa-advantech-som-db5830 Add support for building an EL2 combined DTB for the hamoa-advantech-som-db5830 in the Qualcomm DTS Makefile. The new hamoa-advantech-som-db5830-el2.dtb is generated by combining the base hamoa-advantech-som-db5830.dtb with the x1-el2.dtbo overlay, enabling EL2-specific configurations required by the platform. Link: https://lore.kernel.org/lkml/20261029-come_kvm-v1-1-576afbde32c4@oss.qualcomm.com/ Signed-off-by: Yuanjie Yang --- arch/arm64/boot/dts/qcom/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index b6190d9fb6474..7fb2b1979c2b5 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -23,6 +23,10 @@ dtb-$(CONFIG_ARCH_QCOM) += glymur-hp-elitebook-x-g2q.dtb dtb-$(CONFIG_ARCH_QCOM) += glymur-lenovo-yoga-slim7x.dtb dtb-$(CONFIG_ARCH_QCOM) += glymur-qcb.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-advantech-som-db5830.dtb + +hamoa-advantech-som-db5830-el2-dtbs := hamoa-advantech-som-db5830.dtb x1-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += hamoa-advantech-som-db5830-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-iot-evk-camera-imx577.dtbo From 209f13260ad831deb6a2647e906d14db9cd56728 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 13 Oct 2026 13:34:46 +0200 Subject: [PATCH 0250/1133] FROMLIST: arm64: dts: qcom: nord: Add the USB controller nodes Add the base nodes for the three DWC3 USB controllers. These carry only the SoC-invariant properties and are disabled by default. The extension for the embedded Nord variant and relevant board files will add the platform resources and enable them. USB_2 has no SuperSpeed PHY and no 'ss_phy_irq' on this SoC, so it is capped to high-speed and told to use UTMI as its pipe clock. Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261013-nord-usb-dwc-dts-v3-1-bcaaf3faae24@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord.dtsi | 100 +++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 22fced605ba54..7cace7e2ef521 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -2156,6 +2156,106 @@ dma-coherent; }; + usb_2: usb@a200000 { + compatible = "qcom,nord-dwc3", + "qcom,snps-dwc3"; + reg = <0x0 0x0a200000 0x0 0xfc100>; + + interrupts-extended = <&intc GIC_SPI 910 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 907 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 908 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 8 IRQ_TYPE_EDGE_BOTH>, + <&pdc 7 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "dwc_usb3", + "pwr_event", + "hs_phy_irq", + "dp_hs_phy_irq", + "dm_hs_phy_irq"; + + iommus = <&apps_smmu_0 0x14e0 0x0>; + + dma-coherent; + wakeup-source; + usb-role-switch; + + snps,dis-u1-entry-quirk; + snps,dis-u2-entry-quirk; + snps,dis_u2_susphy_quirk; + snps,dis_u3_susphy_quirk; + snps,dis_enblslpm_quirk; + qcom,select-utmi-as-pipe-clk; + + maximum-speed = "high-speed"; + + status = "disabled"; + }; + + usb_1: usb@a400000 { + compatible = "qcom,nord-dwc3", + "qcom,snps-dwc3"; + reg = <0x0 0x0a400000 0x0 0xfc100>; + + interrupts-extended = <&intc GIC_SPI 917 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 918 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 919 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 13 IRQ_TYPE_EDGE_BOTH>, + <&pdc 12 IRQ_TYPE_EDGE_BOTH>, + <&pdc 41 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "dwc_usb3", + "pwr_event", + "hs_phy_irq", + "dp_hs_phy_irq", + "dm_hs_phy_irq", + "ss_phy_irq"; + + iommus = <&apps_smmu_0 0x15c0 0x0>; + + dma-coherent; + wakeup-source; + usb-role-switch; + + snps,dis-u1-entry-quirk; + snps,dis-u2-entry-quirk; + snps,dis_u2_susphy_quirk; + snps,dis_u3_susphy_quirk; + snps,dis_enblslpm_quirk; + + status = "disabled"; + }; + + usb_0: usb@a600000 { + compatible = "qcom,nord-dwc3", + "qcom,snps-dwc3"; + reg = <0x0 0x0a600000 0x0 0xfc100>; + + interrupts-extended = <&intc GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 14 IRQ_TYPE_EDGE_BOTH>, + <&pdc 15 IRQ_TYPE_EDGE_BOTH>, + <&pdc 17 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "dwc_usb3", + "pwr_event", + "hs_phy_irq", + "dp_hs_phy_irq", + "dm_hs_phy_irq", + "ss_phy_irq"; + + iommus = <&apps_smmu_0 0x1500 0x0>; + + dma-coherent; + wakeup-source; + usb-role-switch; + + snps,dis-u1-entry-quirk; + snps,dis-u2-entry-quirk; + snps,dis_u2_susphy_quirk; + snps,dis_u3_susphy_quirk; + snps,dis_enblslpm_quirk; + + status = "disabled"; + }; + pdc: interrupt-controller@b220000 { compatible = "qcom,nord-pdc", "qcom,pdc"; From ffaa675c86669654389b483a9ac0a5493c0d4b60 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 13 Oct 2026 13:34:47 +0200 Subject: [PATCH 0251/1133] FROMLIST: arm64: dts: qcom: nord-embedded: Add USB resources and PHYs Add the platform resources for the three USB controllers on the embedded Nord variant: clocks, resets, power domains and interconnect paths. Add the eUSB2 PHY for each of the three controllers, plus the QMP combo PHYs for USB_0 and USB_1, and feed the two QMP USB3 pipe clocks back into negcc, which so far carried placeholder zeros in their place. The eUSB2 PHY of instance 2 gets no 'resets': the SoC provides only two QUSB2PHY block resets, belonging to instances 0 and 1. Instance 2 comes out of reset with the rest of the USB20 tile, driven by the controller. Reviewed-by: Abel Vesa Co-developed-by: Shawn Guo Reviewed-by: Konrad Dybcio Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261013-nord-usb-dwc-dts-v3-2-bcaaf3faae24@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 311 +++++++++++++++++++- 1 file changed, 309 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 3bb346cfb65f4..80c345f83fa05 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -901,6 +902,161 @@ qcom,bcm-voters = <&apps_bcm_voter>; }; + usb_2_hsphy: phy@88e0000 { + compatible = "qcom,nord-snps-eusb2-phy", + "qcom,sm8550-snps-eusb2-phy"; + reg = <0x0 0x088e0000 0x0 0x154>; + + clocks = <&tcsrcc TCSR_USB2_2_CLKREF_EN>, + <&negcc NE_GCC_AHB2PHY_CLK>; + clock-names = "ref", + "bus"; + + resets = <&negcc NE_GCC_QUSB2PHY_PRIM_BCR>; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_0_qmpphy: phy@88e1000 { + compatible = "qcom,nord-qmp-usb3-dp-phy"; + reg = <0x0 0x088e1000 0x0 0x3000>; + + clocks = <&negcc NE_GCC_USB3_PRIM_PHY_AUX_CLK>, + <&tcsrcc TCSR_USB3_0_CLKREF_EN>, + <&negcc NE_GCC_USB3_PRIM_PHY_COM_AUX_CLK>, + <&negcc NE_GCC_USB3_PRIM_PHY_PIPE_CLK>, + <&negcc NE_GCC_AHB2PHY_CLK>; + clock-names = "aux", + "ref", + "com_aux", + "usb3_pipe", + "cfg_ahb"; + + power-domains = <&negcc NE_GCC_USB3_PHY_GDSC>; + + resets = <&negcc NE_GCC_USB3_PHY_PRIM_BCR>, + <&negcc NE_GCC_USB3_DP_PHY_PRIM_BCR>; + reset-names = "phy", + "common"; + + #clock-cells = <1>; + #phy-cells = <1>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + #address-cells = <1>; + #size-cells = <0>; + + usb_0_qmpphy_usb_ss_out: endpoint@1 { + reg = <1>; + data-lanes = <1 0>; + }; + }; + + port@1 { + reg = <1>; + + usb_0_qmpphy_usb_ss_in: endpoint { + remote-endpoint = <&usb_0_dwc3_ss>; + }; + }; + }; + }; + + usb_1_qmpphy: phy@88e4000 { + compatible = "qcom,nord-qmp-usb3-dp-phy"; + reg = <0x0 0x088e4000 0x0 0x3000>; + + clocks = <&negcc NE_GCC_USB3_SEC_PHY_AUX_CLK>, + <&tcsrcc TCSR_USB3_1_CLKREF_EN>, + <&negcc NE_GCC_USB3_SEC_PHY_COM_AUX_CLK>, + <&negcc NE_GCC_USB3_SEC_PHY_PIPE_CLK>, + <&negcc NE_GCC_AHB2PHY_CLK>; + clock-names = "aux", + "ref", + "com_aux", + "usb3_pipe", + "cfg_ahb"; + + power-domains = <&negcc NE_GCC_USB3_SEC_PHY_GDSC>; + + resets = <&negcc NE_GCC_USB3_PHY_SEC_BCR>, + <&negcc NE_GCC_USB3_DP_PHY_SEC_BCR>; + reset-names = "phy", + "common"; + + #clock-cells = <1>; + #phy-cells = <1>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + #address-cells = <1>; + #size-cells = <0>; + + usb_1_qmpphy_usb_ss_out: endpoint@1 { + reg = <1>; + data-lanes = <1 0>; + }; + }; + + port@1 { + reg = <1>; + + usb_1_qmpphy_usb_ss_in: endpoint { + remote-endpoint = <&usb_1_dwc3_ss>; + }; + }; + }; + }; + + usb_0_hsphy: phy@88ea000 { + compatible = "qcom,nord-snps-eusb2-phy", + "qcom,sm8550-snps-eusb2-phy"; + reg = <0x0 0x088ea000 0x0 0x154>; + + clocks = <&tcsrcc TCSR_USB2_0_CLKREF_EN>, + <&negcc NE_GCC_AHB2PHY_CLK>; + clock-names = "ref", + "bus"; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_1_hsphy: phy@88eb000 { + compatible = "qcom,nord-snps-eusb2-phy", + "qcom,sm8550-snps-eusb2-phy"; + reg = <0x0 0x088eb000 0x0 0x154>; + + clocks = <&tcsrcc TCSR_USB2_1_CLKREF_EN>, + <&negcc NE_GCC_AHB2PHY_CLK>; + clock-names = "ref", + "bus"; + + resets = <&negcc NE_GCC_QUSB2PHY_SEC_BCR>; + + #phy-cells = <0>; + + status = "disabled"; + }; + negcc: clock-controller@8900000 { compatible = "qcom,nord-negcc"; reg = <0x0 0x08900000 0x0 0xf4200>; @@ -909,8 +1065,8 @@ <0>, <0>, <0>, - <0>, - <0>; + <&usb_1_qmpphy QMP_USB43DP_USB3_PIPE_CLK>, + <&usb_0_qmpphy QMP_USB43DP_USB3_PIPE_CLK>; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; @@ -2034,3 +2190,154 @@ }; }; }; + +&usb_0 { + clocks = <&negcc NE_GCC_CNOC_USB3_PRIM_AXI_CLK>, + <&negcc NE_GCC_USB31_PRIM_MASTER_CLK>, + <&negcc NE_GCC_AGGRE_NOC_USB3_PRIM_AXI_CLK>, + <&negcc NE_GCC_USB31_PRIM_SLEEP_CLK>, + <&negcc NE_GCC_USB31_PRIM_MOCK_UTMI_CLK>, + <&tcsrcc TCSR_USB3_0_CLKREF_EN>; + clock-names = "cfg_noc", + "core", + "iface", + "sleep", + "mock_utmi", + "xo"; + + assigned-clocks = <&negcc NE_GCC_USB31_PRIM_MOCK_UTMI_CLK>, + <&negcc NE_GCC_USB31_PRIM_MASTER_CLK>; + assigned-clock-rates = <19200000>, <200000000>; + + power-domains = <&negcc NE_GCC_USB31_PRIM_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + resets = <&negcc NE_GCC_USB31_PRIM_BCR>; + + interconnects = <&aggre1_noc_tile MASTER_USB3_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_USB3_0 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "usb-ddr", + "apps-usb"; + + phys = <&usb_0_hsphy>, + <&usb_0_qmpphy QMP_USB43DP_USB3_PHY>; + phy-names = "usb2-phy", + "usb3-phy"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_0_dwc3_hs: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_0_dwc3_ss: endpoint { + remote-endpoint = <&usb_0_qmpphy_usb_ss_in>; + }; + }; + }; +}; + +&usb_1 { + clocks = <&negcc NE_GCC_CNOC_USB3_SEC_AXI_CLK>, + <&negcc NE_GCC_USB31_SEC_MASTER_CLK>, + <&negcc NE_GCC_AGGRE_NOC_USB3_SEC_AXI_CLK>, + <&negcc NE_GCC_USB31_SEC_SLEEP_CLK>, + <&negcc NE_GCC_USB31_SEC_MOCK_UTMI_CLK>, + <&tcsrcc TCSR_USB3_1_CLKREF_EN>; + clock-names = "cfg_noc", + "core", + "iface", + "sleep", + "mock_utmi", + "xo"; + + assigned-clocks = <&negcc NE_GCC_USB31_SEC_MOCK_UTMI_CLK>, + <&negcc NE_GCC_USB31_SEC_MASTER_CLK>; + assigned-clock-rates = <19200000>, <200000000>; + + power-domains = <&negcc NE_GCC_USB31_SEC_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + resets = <&negcc NE_GCC_USB31_SEC_BCR>; + + interconnects = <&aggre1_noc_tile MASTER_USB3_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_USB3_1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "usb-ddr", + "apps-usb"; + + phys = <&usb_1_hsphy>, + <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>; + phy-names = "usb2-phy", + "usb3-phy"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_1_dwc3_hs: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_1_dwc3_ss: endpoint { + remote-endpoint = <&usb_1_qmpphy_usb_ss_in>; + }; + }; + }; +}; + +&usb_2 { + clocks = <&negcc NE_GCC_CNOC_USB2_AXI_CLK>, + <&negcc NE_GCC_USB20_MASTER_CLK>, + <&negcc NE_GCC_AGGRE_NOC_USB2_AXI_CLK>, + <&negcc NE_GCC_USB20_SLEEP_CLK>, + <&negcc NE_GCC_USB20_MOCK_UTMI_CLK>, + <&tcsrcc TCSR_USB2_2_CLKREF_EN>; + clock-names = "cfg_noc", + "core", + "iface", + "sleep", + "mock_utmi", + "xo"; + + assigned-clocks = <&negcc NE_GCC_USB20_MOCK_UTMI_CLK>, + <&negcc NE_GCC_USB20_MASTER_CLK>; + assigned-clock-rates = <19200000>, <120000000>; + + power-domains = <&negcc NE_GCC_USB20_PRIM_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + resets = <&negcc NE_GCC_USB20_PRIM_BCR>; + + interconnects = <&aggre1_noc_tile MASTER_USB2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_USB2 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "usb-ddr", + "apps-usb"; + + phys = <&usb_2_hsphy>; + phy-names = "usb2-phy"; + + port { + usb_2_dwc3_hs: endpoint { + }; + }; +}; From aa78eb905e6e254c00bc772e5ef1863994ddc6db Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 13 Oct 2026 13:34:48 +0200 Subject: [PATCH 0252/1133] FROMLIST: arm64: dts: qcom: nord-rrd: Enable USB ports Describe the RRD USB topology. Enable i2c9 and add the two NXP PTN3222 eUSB2 repeaters for USB_0 and USB_1, supplied from vreg_l3l_1p8 and a new fixed 3.3 V pre-regulator, and reset through pmau0102_i GPIOs 9 and 10. Add the onsemi FUSB15201 Type-C controller at 0x50 with its interrupt and pinctrl state on pmau0102_i gpio8. Unlike RIDE, only port A of the controller is wired on this board, to USB_0, so a single usb-c-connector is described and port B is left out. USB_0 is configured for OTG with usb-role-switch and its HS and SS endpoints are linked to the dwc3 HS endpoint and the QMP combo PHY SS output. USB_1 is a fixed host port feeding an on-board Genesys Logic GL3590 USB 3.1 hub. Add the HS and SS hub pair as children of USB_1, linked with peer-hub, with the HS half reset via TLMM GPIO 170 and the SS half additionally supplied by a fixed 1.2 V rail. Reviewed-by: Abel Vesa Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Co-developed-by: Bartosz Golaszewski Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261013-nord-usb-dwc-dts-v3-3-bcaaf3faae24@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 166 ++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index 6bed47b8c913a..c9122905758f6 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include #include "nord-embedded.dtsi" @@ -53,6 +54,22 @@ clock-div = <2>; }; }; + + vreg_hub_1p2: regulator-hub-1p2 { + compatible = "regulator-fixed"; + regulator-name = "vreg_hub_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + vreg_per_3p3: regulator-per-3p3 { + compatible = "regulator-fixed"; + regulator-name = "vreg_per_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; }; &apps_rsc { @@ -377,6 +394,86 @@ }; }; +&i2c9 { + clock-frequency = <400000>; + + status = "okay"; + + usb0_repeater: redriver@43 { + compatible = "nxp,ptn3222"; + reg = <0x43>; + #phy-cells = <0>; + vdd1v8-supply = <&vreg_l3l_1p8>; + vdd3v3-supply = <&vreg_per_3p3>; + reset-gpios = <&pmau0102_i_gpios 9 GPIO_ACTIVE_LOW>; + }; + + usb1_repeater: redriver@4f { + compatible = "nxp,ptn3222"; + reg = <0x4f>; + #phy-cells = <0>; + vdd1v8-supply = <&vreg_l3l_1p8>; + vdd3v3-supply = <&vreg_per_3p3>; + reset-gpios = <&pmau0102_i_gpios 10 GPIO_ACTIVE_LOW>; + }; + + typec@50 { + compatible = "onnn,fusb15201"; + reg = <0x50>; + interrupts-extended = <&pmau0102_i_gpios 8 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-0 = <&usb_pd_int_default>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + /* + * Only port A of the controller is wired up on this board, to + * USB_0. Port B is left unconnected. + */ + connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + label = "USB-C0"; + power-role = "dual"; + data-role = "dual"; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_0_con_hs: endpoint { + remote-endpoint = <&usb_0_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + usb_0_con_ss: endpoint { + remote-endpoint = <&usb_0_qmpphy_usb_ss_out>; + }; + }; + }; + }; + }; +}; + +&pmau0102_i_gpios { + usb_pd_int_default: usb-pd-int-state { + pins = "gpio8"; + function = "normal"; + input-enable; + bias-pull-up; + power-source = <0>; + }; +}; + &qupv3_0 { firmware-name = "qcom/nord/qupv3fw.elf"; @@ -463,3 +560,72 @@ status = "okay"; }; + +&usb_0 { + status = "okay"; +}; + +&usb_0_dwc3_hs { + remote-endpoint = <&usb_0_con_hs>; +}; + +&usb_0_hsphy { + vdd-supply = <&vreg_l1h_0p9>; + vdda12-supply = <&vreg_l2h_1p2>; + + phys = <&usb0_repeater>; + + status = "okay"; +}; + +&usb_0_qmpphy { + vdda-phy-supply = <&vreg_l2k_0p9>; + vdda-pll-supply = <&vreg_l2h_1p2>; + + status = "okay"; +}; + +&usb_0_qmpphy_usb_ss_out { + remote-endpoint = <&usb_0_con_ss>; +}; + +&usb_1 { + dr_mode = "host"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "okay"; + + hub_hs: hub@1 { + compatible = "usb5e3,610"; + reg = <1>; + reset-gpios = <&tlmm 170 GPIO_ACTIVE_LOW>; + vdd-supply = <&vreg_per_3p3>; + peer-hub = <&hub_ss>; + }; + + hub_ss: hub@2 { + compatible = "usb5e3,625"; + reg = <2>; + vdd-supply = <&vreg_per_3p3>; + vdd12-supply = <&vreg_hub_1p2>; + peer-hub = <&hub_hs>; + }; +}; + +&usb_1_hsphy { + vdd-supply = <&vreg_l1h_0p9>; + vdda12-supply = <&vreg_l2h_1p2>; + + phys = <&usb1_repeater>; + + status = "okay"; +}; + +&usb_1_qmpphy { + vdda-phy-supply = <&vreg_l2k_0p9>; + vdda-pll-supply = <&vreg_l2h_1p2>; + + status = "okay"; +}; From 4e9fc4f9d6c0b00a0593ce95e575a6770b1a69c1 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 13 Oct 2026 13:34:49 +0200 Subject: [PATCH 0253/1133] FROMLIST: arm64: dts: qcom: nord-ride-embedded: Enable USB ports Wire up the board specific pieces for USB ports. Enable i2c9 and add the three NXP PTN3222 eUSB2 repeaters (one per USB port) with their 1.8 V supply and reset GPIOs on the PMIC GPIO expanders. Add the onsemi FUSB15201 dual port Type-C controller at 0x50, with its interrupt and pinctrl state on pmau0102_i gpio8. Both controller ports are wired on this board, so describe two usb-c-connector children and cross-link their HS and SS endpoints to the dwc3 HS endpoint and the QMP combo PHY SS output of USB_0 and USB_1. Both controllers therefore run in OTG mode with usb-role-switch. USB_2 has no Type-C connector, so it is configured as a fixed host port. Its VBUS is supplied by a fixed regulator gated by pmau0102_h gpio3, kept always-on since nothing switches it at runtime. Reviewed-by: Abel Vesa Co-developed-by: Bartosz Golaszewski Signed-off-by: Bartosz Golaszewski Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20261013-nord-usb-dwc-dts-v3-4-bcaaf3faae24@oss.qualcomm.com Signed-off-by: Shawn Guo --- .../boot/dts/qcom/nord-ride-embedded.dts | 222 ++++++++++++++++++ 1 file changed, 222 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index 1aa3ed4c1e459..82a8aa1c6451f 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include #include "nord-embedded.dtsi" @@ -53,6 +54,37 @@ clock-div = <2>; }; }; + + vreg_per_3p3: regulator-per-3p3 { + compatible = "regulator-fixed"; + regulator-name = "vreg_per_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + usb2_vbus: regulator-usb2-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb2_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&pmau0102_h_gpios 3 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; + + usb2-connector { + compatible = "usb-a-connector"; + label = "USB-2-Type-A"; + power-role = "source"; + + vbus-supply = <&usb2_vbus>; + + port { + usb2_con_hs: endpoint { + remote-endpoint = <&usb_2_dwc3_hs>; + }; + }; + }; }; &apps_rsc { @@ -366,6 +398,121 @@ }; }; +&i2c9 { + clock-frequency = <400000>; + + status = "okay"; + + usb0_repeater: redriver@43 { + compatible = "nxp,ptn3222"; + reg = <0x43>; + #phy-cells = <0>; + vdd1v8-supply = <&vreg_l3l_1p8>; + vdd3v3-supply = <&vreg_per_3p3>; + reset-gpios = <&pmau0102_i_gpios 9 GPIO_ACTIVE_LOW>; + }; + + usb2_repeater: redriver@47 { + compatible = "nxp,ptn3222"; + reg = <0x47>; + #phy-cells = <0>; + vdd1v8-supply = <&vreg_l3l_1p8>; + vdd3v3-supply = <&vreg_per_3p3>; + reset-gpios = <&pmau0102_l_gpios 3 GPIO_ACTIVE_LOW>; + }; + + usb1_repeater: redriver@4f { + compatible = "nxp,ptn3222"; + reg = <0x4f>; + #phy-cells = <0>; + vdd1v8-supply = <&vreg_l3l_1p8>; + vdd3v3-supply = <&vreg_per_3p3>; + reset-gpios = <&pmau0102_i_gpios 10 GPIO_ACTIVE_LOW>; + }; + + typec@50 { + compatible = "onnn,fusb15201"; + reg = <0x50>; + interrupts-extended = <&pmau0102_i_gpios 8 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-0 = <&usb_pd_int_default>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + label = "USB-C0"; + power-role = "dual"; + data-role = "dual"; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_0_con_hs: endpoint { + remote-endpoint = <&usb_0_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + usb_0_con_ss: endpoint { + remote-endpoint = <&usb_0_qmpphy_usb_ss_out>; + }; + }; + }; + }; + + connector@1 { + compatible = "usb-c-connector"; + reg = <1>; + label = "USB-C1"; + power-role = "dual"; + data-role = "dual"; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_1_con_hs: endpoint { + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + usb_1_con_ss: endpoint { + remote-endpoint = <&usb_1_qmpphy_usb_ss_out>; + }; + }; + }; + }; + }; +}; + +&pmau0102_i_gpios { + usb_pd_int_default: usb-pd-int-state { + pins = "gpio8"; + function = "normal"; + input-enable; + bias-pull-up; + power-source = <0>; + }; +}; + &qupv3_0 { firmware-name = "qcom/nord/qupv3fw.elf"; @@ -444,3 +591,78 @@ status = "okay"; }; + +&usb_0 { + status = "okay"; +}; + +&usb_0_dwc3_hs { + remote-endpoint = <&usb_0_con_hs>; +}; + +&usb_0_hsphy { + vdd-supply = <&vreg_l1h_0p9>; + vdda12-supply = <&vreg_l2h_1p2>; + + phys = <&usb0_repeater>; + + status = "okay"; +}; + +&usb_0_qmpphy { + vdda-phy-supply = <&vreg_l2k_0p9>; + vdda-pll-supply = <&vreg_l2h_1p2>; + + status = "okay"; +}; + +&usb_0_qmpphy_usb_ss_out { + remote-endpoint = <&usb_0_con_ss>; +}; + +&usb_1 { + status = "okay"; +}; + +&usb_1_dwc3_hs { + remote-endpoint = <&usb_1_con_hs>; +}; + +&usb_1_hsphy { + vdd-supply = <&vreg_l1h_0p9>; + vdda12-supply = <&vreg_l2h_1p2>; + + phys = <&usb1_repeater>; + + status = "okay"; +}; + +&usb_1_qmpphy { + vdda-phy-supply = <&vreg_l2k_0p9>; + vdda-pll-supply = <&vreg_l2h_1p2>; + + status = "okay"; +}; + +&usb_1_qmpphy_usb_ss_out { + remote-endpoint = <&usb_1_con_ss>; +}; + +&usb_2 { + dr_mode = "host"; + + status = "okay"; +}; + +&usb_2_dwc3_hs { + remote-endpoint = <&usb2_con_hs>; +}; + +&usb_2_hsphy { + vdd-supply = <&vreg_l1h_0p9>; + vdda12-supply = <&vreg_l2h_1p2>; + + phys = <&usb2_repeater>; + + status = "okay"; +}; From 4be83334f215895a53cfcdf3441e1fdc4d7d9c8f Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 11 Sep 2026 15:45:42 +0800 Subject: [PATCH 0254/1133] PENDING: arm64: defconfig: Enable FUSB15201 Type-C controller driver Enable onsemi FUSB15201 Type-C controller driver which is needed by Qualcomm Nord Ride and RRD reference design boards. Signed-off-by: Shawn Guo --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7b4985b29b21c..6fb1c9b7a024c 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1273,6 +1273,7 @@ CONFIG_TYPEC_TCPCI=m CONFIG_TYPEC_RT1711H=m CONFIG_TYPEC_MT6360=m CONFIG_TYPEC_TCPCI_MAXIM=m +CONFIG_TYPEC_FUSB15201=m CONFIG_TYPEC_FUSB302=m CONFIG_TYPEC_QCOM_PMIC=m CONFIG_TYPEC_UCSI=m From d2abc3e6708be3d32179343391cd14904b7b3afc Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 31 Oct 2026 16:23:18 +0800 Subject: [PATCH 0255/1133] FROMLIST: ASoC: qcom: sc8280xp: Derive TDM channels from DT mask Derive the backend channel count of TDM DAIs from the cpu DAI TDM slot mask in the DT, using the same DAI ID ranges and tx/rx mask selection as q6tdm_set_tdm_slot(), so the channel count always matches the number of slots programmed into the DSP. Each board then gets the channel count its dai-link describes, e.g. 4/4 on Nord RRD, 6/4 on RIDE. Keep the default of two when the link has no TDM slot description, and fail the fixup on an invalid one. Link: https://lore.kernel.org/r/20261031082318.1146398-1-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- sound/soc/qcom/sc8280xp.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 9aae6aadd43da..8cc75a7ad866d 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -303,6 +303,26 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, channels->min = 2; channels->max = 2; switch (cpu_dai->id) { + case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: + case AIF_TDM_RX_0 ... AIF_TDM_TX_12: { + struct qcom_snd_tdm_slot_cfg cpu_cfg, codec_cfg; + unsigned int mask; + int ret; + + ret = qcom_snd_get_dai_tdm_slots(rtd, &cpu_cfg, &codec_cfg); + if (ret == -ENOENT) + break; + if (ret) + return ret; + + /* Same slot mask selection as q6tdm_set_tdm_slot() */ + mask = (cpu_dai->id & 0x1) ? cpu_cfg.tx_mask : cpu_cfg.rx_mask; + if (mask) { + channels->min = hweight32(mask); + channels->max = channels->min; + } + break; + } case TX_CODEC_DMA_TX_0: case TX_CODEC_DMA_TX_1: case TX_CODEC_DMA_TX_2: From ec7c5afc107689a513ba8b3a7c7bcd73d07614fb Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 21 Oct 2026 11:12:28 +0800 Subject: [PATCH 0256/1133] FROMLIST: ASoC: codec: pcm1681: Acquire sck when bound to a card The sck clock is taken once at i2c probe and held for the lifetime of the device. On Qualcomm boards it is an LPASS clock exported by the q6prm clock controller, which lives on the DSP and is unregistered and registered anew whenever the ADSP is stopped and restarted. fw_devlink cannot tie pcm1681 to that provider, since the provider node only gets a device once the DSP is up, so it falls back to the remoteproc device, which stays bound across a DSP restart. pcm1681 is therefore never unbound and keeps a clk handle to the dead provider. After an ADSP restart the first runtime resume fails with: pcm1681 0-004c: Failed to enable sck: -6 and there is no playback through the DAC. Even with a fresh handle the DAC stays silent: the new provider registers its clocks at their default rate (19.2 MHz), while assigned-clock-rates (12.288 MHz) was only applied by the i2c core at probe time. The sound card, however, is torn down and re-created on a DSP restart. Move sck handling into the component probe/remove callbacks: get the clock, re-apply the assigned clock rates and enable it each time the component is bound, and release it on removal. The i2c probe now only sets up supplies and the regmap, keeping the cache in cache-only mode until the clock is running, and the cache is synced once sck is up. Runtime PM is enabled and disabled together with the clock. Fixes: 8987e9a24f45 ("ASoC: codec: pcm1681: Add optional SCK clock and runtime PM support") Link: https://lore.kernel.org/r/20261021031228.2074402-1-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- sound/soc/codecs/pcm1681.c | 122 ++++++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 34 deletions(-) diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 6002da3a56669..2cc34561aa83b 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -321,7 +322,87 @@ static const struct regmap_config pcm1681_regmap = { .cache_type = REGCACHE_MAPLE, }; +/* + * sck may come from a DSP-hosted clock controller that is torn down and + * re-registered when the DSP restarts, which also rebinds the card. A clk + * handle kept across that would point at the dead provider, so only hold + * sck while the component is bound to a card. + */ +static int pcm1681_component_probe(struct snd_soc_component *component) +{ + struct pcm1681_private *priv = snd_soc_component_get_drvdata(component); + struct device *dev = component->dev; + int ret; + + priv->sck = clk_get_optional(dev, "sck"); + if (IS_ERR(priv->sck)) { + ret = PTR_ERR(priv->sck); + priv->sck = NULL; + return dev_err_probe(dev, ret, "Failed to get sck\n"); + } + + /* + * A re-registered provider comes back at its default rate, and the + * driver core applied assigned-clock-rates only once, at i2c probe. + */ + ret = of_clk_set_defaults(dev->of_node, false); + if (ret) { + dev_err(dev, "Failed to set assigned clock rates: %d\n", ret); + goto err_put; + } + + ret = clk_prepare_enable(priv->sck); + if (ret) { + dev_err(dev, "Failed to enable sck: %d\n", ret); + goto err_put; + } + + pcm1681_sck_settle(priv); + + /* The DAC lost its state if sck went away while unbound */ + regcache_cache_only(priv->regmap, false); + regcache_mark_dirty(priv->regmap); + ret = regcache_sync(priv->regmap); + if (ret) { + dev_err(dev, "Failed to sync regcache: %d\n", ret); + goto err_disable; + } + + /* The clock is on, so hand the now-active device over to runtime PM */ + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_idle(dev); + + return 0; + +err_disable: + clk_disable_unprepare(priv->sck); +err_put: + clk_put(priv->sck); + priv->sck = NULL; + return ret; +} + +static void pcm1681_component_remove(struct snd_soc_component *component) +{ + struct pcm1681_private *priv = snd_soc_component_get_drvdata(component); + struct device *dev = component->dev; + + pm_runtime_disable(dev); + /* Runtime PM may already have gated the clock */ + if (!pm_runtime_status_suspended(dev)) { + regcache_cache_only(priv->regmap, true); + clk_disable_unprepare(priv->sck); + } + pm_runtime_set_suspended(dev); + + clk_put(priv->sck); + priv->sck = NULL; +} + static const struct snd_soc_component_driver soc_component_dev_pcm1681 = { + .probe = pcm1681_component_probe, + .remove = pcm1681_component_remove, .controls = pcm1681_controls, .num_controls = ARRAY_SIZE(pcm1681_controls), .dapm_widgets = pcm1681_dapm_widgets, @@ -359,11 +440,6 @@ static int pcm1681_i2c_probe(struct i2c_client *client) return dev_err_probe(dev, ret, "Failed to enable supplies\n"); - priv->sck = devm_clk_get_optional(dev, "sck"); - if (IS_ERR(priv->sck)) - return dev_err_probe(dev, PTR_ERR(priv->sck), - "Failed to get sck\n"); - priv->regmap = devm_regmap_init_i2c(client, &pcm1681_regmap); if (IS_ERR(priv->regmap)) { ret = PTR_ERR(priv->regmap); @@ -371,53 +447,31 @@ static int pcm1681_i2c_probe(struct i2c_client *client) return ret; } + /* No sck until the component is bound, serve access from the cache */ + regcache_cache_only(priv->regmap, true); + /* Must be set before runtime PM is enabled, the callbacks use it */ i2c_set_clientdata(client, priv); - ret = clk_prepare_enable(priv->sck); - if (ret) - return dev_err_probe(dev, ret, "Failed to enable sck\n"); - - pcm1681_sck_settle(priv); - - /* The clock is on, so hand the now-active device over to runtime PM */ + /* Runtime PM is enabled from component probe, once sck is running */ pm_runtime_set_autosuspend_delay(dev, 100); pm_runtime_use_autosuspend(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - pm_runtime_idle(dev); ret = devm_snd_soc_register_component(dev, &soc_component_dev_pcm1681, &pcm1681_dai, 1); if (ret) { dev_err(dev, "Failed to register component: %d\n", ret); - goto err_pm; + pm_runtime_dont_use_autosuspend(dev); + return ret; } return 0; - -err_pm: - pm_runtime_dont_use_autosuspend(dev); - pm_runtime_disable(dev); - if (!pm_runtime_status_suspended(dev)) - clk_disable_unprepare(priv->sck); - pm_runtime_set_suspended(dev); - - return ret; } static void pcm1681_i2c_remove(struct i2c_client *client) { - struct pcm1681_private *priv = i2c_get_clientdata(client); - struct device *dev = &client->dev; - - pm_runtime_dont_use_autosuspend(dev); - pm_runtime_disable(dev); - /* Runtime PM may already have gated the clock */ - if (!pm_runtime_status_suspended(dev)) - clk_disable_unprepare(priv->sck); - pm_runtime_set_suspended(dev); + pm_runtime_dont_use_autosuspend(&client->dev); } static int pcm1681_runtime_suspend(struct device *dev) From 141710f79f8b5954167bad05f565c3d2055fe526 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Wed, 28 Oct 2026 10:47:20 +0800 Subject: [PATCH 0257/1133] FROMLIST: ASoC: qcom: audioreach: support multichannel PCM formats AudioReach currently rejects PCM streams with more than four channels in the PCM and shared-memory media format paths. This prevents TDM links that expose more channels, such as the 6-channel playback path used on SA8797P Ride, from being configured. Reuse q6dsp_map_channels() to support multichannel PCM formats and use the common PCM channel limit definition. Signed-off-by: Zhangfei Gao Reviewed-by: Prasad Kumpatla Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20261028024720.981971-1-zhangfei.gao@oss.qualcomm.com --- sound/soc/qcom/qdsp6/audioreach.c | 36 ++++--------------------- sound/soc/qcom/qdsp6/audioreach.h | 5 ++-- sound/soc/qcom/qdsp6/q6apm-dai.c | 12 ++++++--- sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 11 +++++--- 4 files changed, 24 insertions(+), 40 deletions(-) diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c index d2dc5d37bccf8..e6f077a5b750f 100644 --- a/sound/soc/qcom/qdsp6/audioreach.c +++ b/sound/soc/qcom/qdsp6/audioreach.c @@ -306,22 +306,6 @@ void *audioreach_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t token } EXPORT_SYMBOL_GPL(audioreach_alloc_apm_cmd_pkt); -void audioreach_set_default_channel_mapping(u8 *ch_map, int num_channels) -{ - if (num_channels == 1) { - ch_map[0] = PCM_CHANNEL_FL; - } else if (num_channels == 2) { - ch_map[0] = PCM_CHANNEL_FL; - ch_map[1] = PCM_CHANNEL_FR; - } else if (num_channels == 4) { - ch_map[0] = PCM_CHANNEL_FL; - ch_map[1] = PCM_CHANNEL_FR; - ch_map[2] = PCM_CHANNEL_LS; - ch_map[3] = PCM_CHANNEL_RS; - } -} -EXPORT_SYMBOL_GPL(audioreach_set_default_channel_mapping); - static void apm_populate_container_config(struct apm_container_obj *cfg, const struct audioreach_container *cont) { @@ -760,7 +744,7 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph, intf_cfg->cfg.intf_index = module->hw_interface_idx; intf_cfg->cfg.active_channels_mask = 0; /* Convert the physical channel mapping into a bit field */ - for (i = 0; i < AR_PCM_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_MAX_NUM_CHANNEL; i++) if (cfg->channel_map[i]) intf_cfg->cfg.active_channels_mask |= BIT(i); @@ -883,7 +867,7 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph, media_format->bit_width = cfg->bit_width; media_format->num_channels = cfg->num_channels; /* Convert the physical mapping to a logical mapping of the channels */ - for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) { + for (i = 0, j = 0; i < PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) { if (!cfg->channel_map[i]) continue; media_format->channel_mapping[j++] = cfg->channel_map[i]; @@ -1185,11 +1169,6 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph, int payload_size; int i, j; - if (num_channels > 4) { - dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels); - return -EINVAL; - } - payload_size = APM_PCM_MODULE_FMT_CMD_PSIZE(num_channels); struct gpr_pkt *pkt __free(kfree) = @@ -1218,7 +1197,7 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph, media_cfg->q_factor = mcfg->bit_width - 1; media_cfg->bits_per_sample = mcfg->bit_width; /* Convert the physical mapping to a logical mapping of the channels */ - for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < mcfg->num_channels; i++) { + for (i = 0, j = 0; i < PCM_MAX_NUM_CHANNEL && j < mcfg->num_channels; i++) { if (!mcfg->channel_map[i]) continue; media_cfg->channel_mapping[j++] = mcfg->channel_map[i]; @@ -1275,11 +1254,6 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph, int i, j; void *p; - if (num_channels > 4) { - dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels); - return -EINVAL; - } - payload_size = APM_SHMEM_FMT_CFG_PSIZE(num_channels) + APM_MODULE_PARAM_DATA_SIZE; struct gpr_pkt *pkt __free(kfree) = @@ -1313,7 +1287,7 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph, cfg->endianness = PCM_LITTLE_ENDIAN; cfg->num_channels = mcfg->num_channels; /* Convert the physical mapping to a logical mapping of the channels */ - for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) { + for (i = 0, j = 0; i < PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) { if (!mcfg->channel_map[i]) continue; cfg->channel_mapping[j++] = mcfg->channel_map[i]; @@ -1436,7 +1410,7 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph, cm_cfg->cfg.num_channels = num_channels * 2; /* Convert the physical mapping to a logical mapping of the channels */ - for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < num_channels; i++) { + for (i = 0, j = 0; i < PCM_MAX_NUM_CHANNEL && j < num_channels; i++) { if (!mcfg->channel_map[i]) continue; /* diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h index 587f14ce71d23..9f4166ebdc107 100644 --- a/sound/soc/qcom/qdsp6/audioreach.h +++ b/sound/soc/qcom/qdsp6/audioreach.h @@ -6,6 +6,7 @@ #include #include #include +#include "q6dsp-common.h" struct q6apm; struct q6apm_graph; @@ -805,7 +806,6 @@ struct param_id_hw_ep_power_mode_cfg { #define PARAM_ID_HW_EP_DMA_DATA_ALIGN 0x08001233 #define AR_HW_EP_DMA_DATA_ALIGN_MSB 0 #define AR_HW_EP_DMA_DATA_ALIGN_LSB 1 -#define AR_PCM_MAX_NUM_CHANNEL 8 struct param_id_hw_ep_dma_data_align { uint32_t dma_data_align; @@ -998,7 +998,7 @@ struct audioreach_module_config { u16 nslots_per_frame; u16 slot_width; struct snd_codec codec; - u8 channel_map[AR_PCM_MAX_NUM_CHANNEL]; + u8 channel_map[PCM_MAX_NUM_CHANNEL]; }; /* Packet Allocation routines */ @@ -1009,7 +1009,6 @@ static inline u16 audioreach_gpr_dest_domain(gpr_device_t *gdev) void *audioreach_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t token); -void audioreach_set_default_channel_mapping(u8 *ch_map, int num_channels); void *audioreach_alloc_cmd_pkt(int payload_size, uint32_t opcode, uint32_t token, uint32_t src_port, uint32_t dest_port); diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 58beaf906b9ff..83594b693569e 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -21,6 +21,7 @@ #include #include #include "q6apm.h" +#include "q6dsp-common.h" #define DRV_NAME "q6apm-dai" #define POS_BUFFER_BYTES 4096 @@ -344,7 +345,10 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, cfg.num_channels = runtime->channels; cfg.bit_width = prtd->bits_per_sample; cfg.fmt = SND_AUDIOCODEC_PCM; - audioreach_set_default_channel_mapping(cfg.channel_map, runtime->channels); + ret = q6dsp_map_channels(cfg.channel_map, runtime->channels); + if (ret) + return ret; + if (prtd->state) { /* clear the previous setup if any */ q6apm_graph_stop(prtd->graph); @@ -1007,8 +1011,10 @@ static int q6apm_dai_compr_set_params(struct snd_soc_component *component, cfg.num_channels = 2; cfg.bit_width = prtd->bits_per_sample; cfg.fmt = codec->id; - audioreach_set_default_channel_mapping(cfg.channel_map, - cfg.num_channels); + ret = q6dsp_map_channels(cfg.channel_map, cfg.num_channels); + if (ret) + return ret; + memcpy(&cfg.codec, codec, sizeof(*codec)); ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg); diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c index 83f2711bceeaa..9a3994a4f4754 100644 --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c @@ -94,7 +94,7 @@ static int q6dma_set_channel_map(struct snd_soc_dai *dai, return -EINVAL; } - if (tx_num > AR_PCM_MAX_NUM_CHANNEL) { + if (tx_num > PCM_MAX_NUM_CHANNEL) { dev_err(dai->dev, "invalid tx num %d\n", tx_num); return -EINVAL; @@ -147,7 +147,9 @@ static int q6hdmi_hw_params(struct snd_pcm_substream *substream, cfg->bit_width = params_width(params); cfg->sample_rate = params_rate(params); cfg->num_channels = channels; - audioreach_set_default_channel_mapping(cfg->channel_map, channels); + ret = q6dsp_map_channels(cfg->channel_map, channels); + if (ret) + return ret; switch (dai->id) { case DISPLAY_PORT_RX_0: @@ -173,11 +175,14 @@ static int q6dma_hw_params(struct snd_pcm_substream *substream, struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); struct audioreach_module_config *cfg = &dai_data->module_config[dai->id]; int channels = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max; + int ret; cfg->bit_width = params_width(params); cfg->sample_rate = params_rate(params); cfg->num_channels = channels; - audioreach_set_default_channel_mapping(cfg->channel_map, channels); + ret = q6dsp_map_channels(cfg->channel_map, channels); + if (ret) + return ret; return 0; } From 64e954f643cb55558df4321970a2261462e38a7e Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Wed, 21 Oct 2026 15:36:29 +0800 Subject: [PATCH 0258/1133] FROMLIST: soc: qcom: pd-mapper: Add support for Nord Add support for the Qualcomm Nord SoC to the protection domain mapper. Signed-off-by: Mohammad Rafi Shaik Link: https://lore.kernel.org/r/20261021073633.2163128-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- drivers/soc/qcom/qcom_pd_mapper.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index 64ca99d7fad92..6dace16a3b8c1 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -277,6 +277,12 @@ static const struct qcom_pdm_domain_data adsp_root_pd = { .services = { NULL }, }; +static const struct qcom_pdm_domain_data adsp1_root_pd = { + .domain = "msm/adsp1/root_pd", + .instance_id = 123, + .services = { NULL }, +}; + static const struct qcom_pdm_domain_data adsp_root_pd_pdr = { .domain = "msm/adsp/root_pd", .instance_id = 74, @@ -414,6 +420,13 @@ static const struct qcom_pdm_domain_data *msm8998_domains[] = { NULL, }; +static const struct qcom_pdm_domain_data *nord_domains[] = { + &adsp_audio_pd, + &adsp_root_pd, + &adsp1_root_pd, + &cdsp_root_pd, +}; + static const struct qcom_pdm_domain_data *qcm2290_domains[] = { &adsp_audio_pd, &adsp_root_pd, @@ -634,6 +647,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,msm8974", .data = NULL, }, { .compatible = "qcom,msm8996", .data = msm8996_domains, }, { .compatible = "qcom,msm8998", .data = msm8998_domains, }, + { .compatible = "qcom,nord", .data = nord_domains, }, { .compatible = "qcom,qcm2290", .data = qcm2290_domains, }, { .compatible = "qcom,qcm6490", .data = sc7280_domains, }, { .compatible = "qcom,qcs404", .data = qcs404_domains, }, From ee62ba3cb8d1424418b9914796bea8a5daa48589 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Wed, 21 Oct 2026 15:36:30 +0800 Subject: [PATCH 0259/1133] FROMLIST: arm64: dts: qcom: nord: Add gpr node Add the GPR (Generic Packet Router) node to the nord SoC DTSI along with the APM (Audio Process Manager) and PRM (Proxy Resource Manager) audio services. These nodes are required by the Q6APM audio stack to route audio packets between the application processor and the DSP. Signed-off-by: Mohammad Rafi Shaik Link: https://lore.kernel.org/r/20261021073633.2163128-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord.dtsi | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 7cace7e2ef521..32f7a7ae687a7 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -7,6 +7,7 @@ #include #include #include +#include #include "nord-ipcc.h" @@ -2106,6 +2107,45 @@ dma-coherent; }; }; + + 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"; + + q6apmbedai: bedais { + compatible = "qcom,q6apm-lpass-dais"; + #sound-dai-cells = <1>; + }; + + q6apmdai: dais { + compatible = "qcom,q6apm-dais"; + iommus = <&apps_smmu_0 0x09e1 0x0400>; + }; + }; + + 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>; + }; + }; + }; }; }; From f0ef42f539d42f799b11f47eafd559b2b7c5a9c3 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 21 Oct 2026 15:36:31 +0800 Subject: [PATCH 0260/1133] FROMLIST: arm64: dts: qcom: nord-embedded: Raise i2c18 pad drive strength The i2c18 pins (gpio154/155) are configured for 2 mA. That is not enough on nord-ride-embedded, where i2c18 is the audio control bus carrying the TCA6408 expander, ADAU1979 ADC and PCM1681 DAC behind TXS0102 level shifters. Transfers intermittently fail with arbitration loss and unexpected start/stop conditions: geni_i2c 890000.i2c: Bus arbitration lost, clock line undriveable geni_i2c 890000.i2c: Bus proto err, noisy/unexpected start/stop adau1977 0-0031: probe with driver adau1977 failed with error -11 reg-fixed-voltage regulator-5p0-dac: setup of GPIO (default) failed: -11 The failure became much more frequent with commit 8cb5c17be3a2 ("i2c: qcom-geni: Restore the source-clock selection policy"), which moves the i2c18 serial engine clock from 32 MHz to 19.2 MHz. That commit only changes how often the marginal signalling shows up: reverting it, or lowering the bus to 100 kHz, still leaves occasional failures in a codec unbind/bind loop. With 4 mA the loop passes reliably at either source clock rate. nord-rrd uses the same level shifters and has not shown the failure at 2 mA, but that appears to be margin rather than a guarantee. Since this audio I2C arrangement is the reference design that customer boards will likely follow, raise the default in the shared dtsi instead of overriding it per board. Link: https://lore.kernel.org/r/20261021073633.2163128-4-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 80c345f83fa05..d6555f70a1e74 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -1422,7 +1422,7 @@ qup_i2c18_default: qup-i2c18-default-state { pins = "gpio154", "gpio155"; function = "qup2_se4"; - drive-strength = <2>; + drive-strength = <4>; bias-pull-up; }; From 067910284ad04ef91da7ab82909c61734a67a97d Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Wed, 21 Oct 2026 15:36:32 +0800 Subject: [PATCH 0261/1133] FROMLIST: arm64: dts: qcom: nord-ride-embedded: Add sound support Enable audio on the nord-ride-embedded board. Add a soundcard node using the qcom,nord-sndcard compatible. Add PCM1681/ADAU1979 codec nodes on I2C18, with the PCM1681 system clock supplied via MCLK0. The DAC control lines come off a TCA6408 I/O expander on the same bus. Describe DAC_ENABLE as the enable of two regulator-fixed supplies (3.3V and 5V load switches) feeding the PCM1681, and the three MAX9892 click-and-pop suppressors as one simple-audio-amplifier on CLICK_POP_MUTE_N, routed after VOUT1..6, so DAPM controls the mute. Signed-off-by: Mohammad Rafi Shaik Link: https://lore.kernel.org/r/20261021073633.2163128-5-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 30 ++++ .../boot/dts/qcom/nord-ride-embedded.dts | 159 ++++++++++++++++++ 2 files changed, 189 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index d6555f70a1e74..4c337b2e829a8 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -1307,6 +1307,36 @@ }; &tlmm { + aud_intfc8_mi2s_active: aud-intfc8-mi2s-active-state { + data-pins { + pins = "gpio75", "gpio76"; + function = "aud_intfc8_data"; + drive-strength = <8>; + bias-disable; + }; + + sclk-pins { + pins = "gpio73"; + function = "aud_intfc8_clk"; + drive-strength = <8>; + bias-disable; + }; + + ws-pins { + pins = "gpio74"; + function = "aud_intfc8_ws"; + drive-strength = <8>; + bias-disable; + }; + }; + + aud_mclk0_mira_active: aud-mclk0-mira-active-state { + pins = "gpio99"; + function = "aud_mclk0_mira"; + drive-strength = <8>; + bias-disable; + }; + qup_i2c0_default: qup-i2c0-default-state { pins = "gpio111", "gpio112"; function = "qup0_se0"; diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index 82a8aa1c6451f..80fcf2430c8d4 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -8,6 +8,7 @@ #include #include #include +#include #include "nord-embedded.dtsi" #include "pmau0102-nord.dtsi" @@ -55,6 +56,100 @@ }; }; + /* + * MAX9892 click-and-pop suppressors on the PCM1681 line outputs. All + * three parts are muted by a single CLICK_POP_MUTE_N line, so describe + * them as one amplifier. + */ + lineout_amp: amplifier { + compatible = "simple-audio-amplifier"; + sound-name-prefix = "LineOut"; + enable-gpios = <&expander0 5 GPIO_ACTIVE_HIGH>; + VCC-supply = <&vreg_per_3p3>; + }; + + sound { + compatible = "qcom,nord-sndcard"; + model = "NORD-RIDE"; + + aux-devs = <&lineout_amp>; + audio-routing = "LineOut INL", "VOUT1", + "LineOut INR", "VOUT2", + "LineOut INL", "VOUT3", + "LineOut INR", "VOUT4", + "LineOut INL", "VOUT5", + "LineOut INR", "VOUT6"; + + pinctrl-0 = <&aud_intfc8_mi2s_active>; + pinctrl-names = "default"; + + aud-intfc8-tdm-playback-dai-link { + link-name = "PCM1681 Playback"; + + codec { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1 1 1 1 1>; + sound-dai = <&pcm1681>; + }; + + cpu { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-tx-mask = <1 1 1 1 1 1>; + sound-dai = <&q6apmbedai AIF_TDM_RX_8>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + aud-intfc8-tdm-capture-dai-link { + link-name = "ADAU1979 Capture"; + + codec { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1 1 1>; + sound-dai = <&adau1979>; + }; + + cpu { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1 1 1>; + sound-dai = <&q6apmbedai AIF_TDM_TX_8>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + + /* + * DAC_ENABLE gates two load switches feeding the PCM1681, one for the + * analog and one for the digital supply. + */ + vreg_3p3_dac: regulator-3p3-dac { + compatible = "regulator-fixed"; + regulator-name = "vreg_3p3_dac"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&expander0 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vreg_5p0_dac: regulator-5p0-dac { + compatible = "regulator-fixed"; + regulator-name = "vreg_5p0_dac"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&expander0 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + vreg_per_3p3: regulator-per-3p3 { compatible = "regulator-fixed"; regulator-name = "vreg_per_3p3"; @@ -503,6 +598,53 @@ }; }; +&i2c18 { + clock-frequency = <400000>; + + status = "okay"; + + expander0: gpio@20 { + compatible = "ti,tca6408"; + reg = <0x20>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&pmau0102_l_gpios 6 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&pmau0102_l_gpios 5 GPIO_ACTIVE_LOW>; + vcc-supply =<&vreg_per_3p3>; + }; + + /* ADI ADAU1979 - 4-channel 24-bit ADC */ + adau1979: adau1979@31 { + compatible = "adi,adau1979"; + reg = <0x31>; + + AVDD-supply = <&vreg_per_3p3>; + #sound-dai-cells = <0>; + }; + + /* PCM1681 DAC */ + pcm1681: pcm1681@4c { + compatible = "ti,pcm1681"; + reg = <0x4c>; + + pinctrl-0 = <&aud_mclk0_mira_active>; + pinctrl-names = "default"; + + clocks = <&q6prmcc LPASS_CLK_ID_MCLK_1 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "sck"; + assigned-clocks = <&q6prmcc LPASS_CLK_ID_MCLK_1 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <12288000>; + + VCC1-supply = <&vreg_5p0_dac>; + VCC2-supply = <&vreg_5p0_dac>; + VDD-supply = <&vreg_3p3_dac>; + + #sound-dai-cells = <0>; + }; +}; + &pmau0102_i_gpios { usb_pd_int_default: usb-pd-int-state { pins = "gpio8"; @@ -513,6 +655,23 @@ }; }; +&q6apmbedai { + #address-cells = <1>; + #size-cells = <0>; + + dai@195 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_QAIF_IF8_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; + + dai@196 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_QAIF_IF8_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; +}; + &qupv3_0 { firmware-name = "qcom/nord/qupv3fw.elf"; From f445aa0d65a4026a42d69044452a60504e62dc65 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 21 Oct 2026 15:36:33 +0800 Subject: [PATCH 0262/1133] FROMLIST: arm64: dts: qcom: nord-rrd: Add sound support Enable audio on the nord-rrd board. Add a soundcard node using the qcom,nord-sndcard compatible. Add PCM1681/ADAU1979 codec nodes on I2C18, with the PCM1681 system clock supplied via MCLK0. Describe DAC_ENABLE as the enable of two regulator-fixed supplies (3.3V and 5V load switches) feeding the PCM1681, and the two MAX9892 click-and-pop suppressors as one simple-audio-amplifier on CLICK_POP_MUTE_N, routed after VOUT1..4, so DAPM controls the mute. Link: https://lore.kernel.org/r/20261021073633.2163128-6-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 145 ++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index c9122905758f6..526ef4db4d072 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -8,6 +8,7 @@ #include #include #include +#include #include "nord-embedded.dtsi" #include "pmau0102-nord.dtsi" @@ -55,6 +56,98 @@ }; }; + /* + * MAX9892 click-and-pop suppressors on the PCM1681 line outputs. Both + * parts are muted by a single CLICK_POP_MUTE_N line, so describe them + * as one amplifier. + */ + lineout_amp: amplifier { + compatible = "simple-audio-amplifier"; + sound-name-prefix = "LineOut"; + enable-gpios = <&tlmm 42 GPIO_ACTIVE_HIGH>; + VCC-supply = <&vreg_per_3p3>; + }; + + sound { + compatible = "qcom,nord-sndcard"; + model = "NORD-RRD"; + + aux-devs = <&lineout_amp>; + audio-routing = "LineOut INL", "VOUT1", + "LineOut INR", "VOUT2", + "LineOut INL", "VOUT3", + "LineOut INR", "VOUT4"; + + pinctrl-0 = <&aud_intfc8_mi2s_active>; + pinctrl-names = "default"; + + aud-intfc8-tdm-playback-dai-link { + link-name = "PCM1681 Playback"; + + codec { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1 1 1>; + sound-dai = <&pcm1681>; + }; + + cpu { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-tx-mask = <1 1 1 1>; + sound-dai = <&q6apmbedai AIF_TDM_RX_8>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + aud-intfc8-tdm-capture-dai-link { + link-name = "ADAU1979 Capture"; + + codec { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1 1 1>; + sound-dai = <&adau1979>; + }; + + cpu { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1 1 1>; + sound-dai = <&q6apmbedai AIF_TDM_TX_8>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + + /* + * DAC_ENABLE gates two load switches feeding the PCM1681, one for the + * analog and one for the digital supply. + */ + vreg_3p3_dac: regulator-3p3-dac { + compatible = "regulator-fixed"; + regulator-name = "vreg_3p3_dac"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&tlmm 41 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vreg_5p0_dac: regulator-5p0-dac { + compatible = "regulator-fixed"; + regulator-name = "vreg_5p0_dac"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&tlmm 41 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + vreg_hub_1p2: regulator-hub-1p2 { compatible = "regulator-fixed"; regulator-name = "vreg_hub_1p2"; @@ -464,6 +557,41 @@ }; }; +&i2c18 { + clock-frequency = <400000>; + + status = "okay"; + + /* ADI ADAU1979 - 4-channel 24-bit ADC */ + adau1979: adau1979@31 { + compatible = "adi,adau1979"; + reg = <0x31>; + + AVDD-supply = <&vreg_per_3p3>; + #sound-dai-cells = <0>; + }; + + /* PCM1681 DAC */ + pcm1681: pcm1681@4c { + compatible = "ti,pcm1681"; + reg = <0x4c>; + + pinctrl-0 = <&aud_mclk0_mira_active>; + pinctrl-names = "default"; + + clocks = <&q6prmcc LPASS_CLK_ID_MCLK_1 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "sck"; + assigned-clocks = <&q6prmcc LPASS_CLK_ID_MCLK_1 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <12288000>; + + VCC1-supply = <&vreg_5p0_dac>; + VCC2-supply = <&vreg_5p0_dac>; + VDD-supply = <&vreg_3p3_dac>; + + #sound-dai-cells = <0>; + }; +}; + &pmau0102_i_gpios { usb_pd_int_default: usb-pd-int-state { pins = "gpio8"; @@ -474,6 +602,23 @@ }; }; +&q6apmbedai { + #address-cells = <1>; + #size-cells = <0>; + + dai@195 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_QAIF_IF8_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; + + dai@196 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_QAIF_IF8_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; +}; + &qupv3_0 { firmware-name = "qcom/nord/qupv3fw.elf"; From 73ceeb617a183bb63d51af18ffd2c3951626bda1 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 8 Oct 2026 18:10:57 +0530 Subject: [PATCH 0263/1133] PENDING: arm64: defconfig: Enable PCM1681 and ADAU1977-I2C drivers Qualcomm NORD RIDE and RRD boards use the PCM1681 audio codec for playback and the ADAU1977 codec for Capture. Enable both drivers as modules in arm64_defconfig so that audio functionality is available on these boards with the default arm64 configuration. Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 6fb1c9b7a024c..db99aff2b28d4 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1093,6 +1093,7 @@ CONFIG_SND_USB_AUDIO=m CONFIG_SND_USB_AUDIO_QMI=m CONFIG_SND_SOC=m CONFIG_SND_SOC_USB=m +CONFIG_SND_SOC_ADAU1977_I2C=m CONFIG_SND_SOC_APPLE_MCA=m CONFIG_SND_BCM2835_SOC_I2S=m CONFIG_SND_SOC_FSL_ASRC=m @@ -1113,6 +1114,7 @@ CONFIG_SND_SOC_MT8195=m CONFIG_SND_SOC_MT8195_MT6359=m CONFIG_SND_SOC_MT8365=m CONFIG_SND_SOC_MT8365_MT6357=m +CONFIG_SND_SOC_PCM1681=m CONFIG_SND_MESON_AXG_SOUND_CARD=m CONFIG_SND_MESON_GX_SOUND_CARD=m CONFIG_SND_SOC_QCOM=m From bac7ef17c30976e11c37c303559ef0789b0c010d Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Thu, 29 Oct 2026 11:40:16 +0530 Subject: [PATCH 0264/1133] FROMLIST: dt-bindings: pci: qcom: add Nord PCIe controller compatible Add the qcom,nord-pcie compatible string to the Qualcomm PCIe controller binding. The Nord PCIe controller is compatible with the SA8775P PCIe controller implementation and reuses the same binding definition. Acked-by: Krzysztof Kozlowski Reviewed-by: Shawn Guo Signed-off-by: Krishna Chaitanya Chundru Link: https://lore.kernel.org/r/20261029-nord-v5-1-1a13c214e89d@oss.qualcomm.com --- Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml index 63630a814f287..b8ba2c4449b7f 100644 --- a/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml +++ b/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml @@ -20,6 +20,7 @@ properties: - const: qcom,pcie-sa8775p - items: - enum: + - qcom,nord-pcie - qcom,pcie-qcs8300 - const: qcom,pcie-sa8775p From 3e82c05b6b8c5d2573018c8377f9c8fb4760bea4 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Thu, 29 Oct 2026 11:40:17 +0530 Subject: [PATCH 0265/1133] FROMLIST: PCI: qcom: Add Nord PCIe controller support Add the Nord PCIe controller configuration and the platform-specific settings required for correct operation. Nord requires the NO_SNOOP override and L0s to be disabled. It also requires a clock-gating-control (CGC) workaround to address a PCIe power-domain timing-convergence issue. Set the CORE_CLK_CGC_DIS and AUX_PWR_DET bits in PARF_SYS_CTRL after controller initialization. The SLV_ACLK_CGC_DIS bit is already configured by hardware reset. This behavior is documented in the private QCTDD11972446 erratum, which is not publicly available. Reviewed-by: Konrad Dybcio Reviewed-by: Shawn Guo Tested-by: Shawn Guo Signed-off-by: Krishna Chaitanya Chundru Link: https://lore.kernel.org/r/20261029-nord-v5-2-1a13c214e89d@oss.qualcomm.com --- drivers/pci/controller/dwc/pcie-qcom.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index d903f10211c23..c62abfc7a446c 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -300,6 +300,7 @@ struct qcom_pcie_cfg { bool override_no_snoop; bool firmware_managed; bool no_l0s; + bool disable_cgc; }; struct qcom_pcie_perst { @@ -1138,11 +1139,18 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie) static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie) { const struct qcom_pcie_cfg *pcie_cfg = pcie->cfg; + u32 val; if (pcie_cfg->override_no_snoop) writel(WR_NO_SNOOP_OVERRIDE_EN | RD_NO_SNOOP_OVERRIDE_EN, pcie->parf + PARF_NO_SNOOP_OVERRIDE); + if (pcie_cfg->disable_cgc) { + val = readl(pcie->parf + PARF_SYS_CTRL); + val |= CORE_CLK_CGC_DIS | AUX_PWR_DET; + writel(val, pcie->parf + PARF_SYS_CTRL); + } + qcom_pcie_set_slot_cap(pcie->pci); qcom_pcie_init_outbound_blocker(pcie); @@ -1725,6 +1733,13 @@ static const struct qcom_pcie_cfg cfg_2_9_0 = { .ops = &ops_2_9_0, }; +static const struct qcom_pcie_cfg cfg_nord = { + .ops = &ops_1_9_0, + .override_no_snoop = true, + .no_l0s = true, + .disable_cgc = true, +}; + static const struct qcom_pcie_cfg cfg_sc8280xp = { .ops = &ops_1_21_0, .no_l0s = true, @@ -2586,6 +2601,7 @@ static int qcom_pcie_resume_noirq(struct device *dev) static const struct of_device_id qcom_pcie_match[] = { { .compatible = "qcom,hawi-pcie", .data = &cfg_1_9_0 }, + { .compatible = "qcom,nord-pcie", .data = &cfg_nord }, { .compatible = "qcom,pcie-apq8064", .data = &cfg_2_1_0 }, { .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 }, { .compatible = "qcom,pcie-ipq4019", .data = &cfg_2_4_0 }, From e1abf56bde71e76893283d70793920d6e8fda0de Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 31 Oct 2026 22:24:27 +0800 Subject: [PATCH 0266/1133] FROMLIST: arm64: dts: qcom: nord: Add PCIe PHY and controller nodes Nord has four PCIe controllers backed by a single quadfurcated Gen5 QMP PHY with four ports (A/B/C/D) and a common PCIe SMMU. The ports can be ganged into x16, x8+x8, x8+x4+x4 or x8+x4+x2+x2 topologies; the topology in effect is selected by firmware through the TCSR link-config mode register, which the PHY driver reads at probe time. Describe the x8+x4+x2+x2 topology, i.e. all four controllers usable, as that is the configuration the boards ship with. Add the controller and SMMU nodes to nord.dtsi, and the PHY node along with the per-controller clocks, resets, GDSCs, interconnects, OPP tables and TLMM pin states to nord-embedded.dtsi. The four PCIe pipe clocks also become available now, so hook them up as GCC parents in place of the <0> placeholders. The controllers and the PHY are left disabled here and enabled per board. Signed-off-by: Krishna Chaitanya Chundru Reviewed-by: Abel Vesa Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261031142433.1212809-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 926 +++++++++++++++++++- arch/arm64/boot/dts/qcom/nord.dtsi | 297 +++++++ 2 files changed, 1219 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 4c337b2e829a8..1f639b898e3d3 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -381,6 +381,738 @@ pinctrl-names = "default"; }; +&pcie0 { + clocks = <&gcc GCC_PCIE_A_AUX_CLK>, + <&gcc GCC_PCIE_A_CFG_AHB_CLK>, + <&gcc GCC_PCIE_A_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_A_SLV_AXI_CLK>, + <&gcc GCC_PCIE_A_SLV_Q2A_AXI_CLK>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a"; + + assigned-clocks = <&gcc GCC_PCIE_A_AUX_CLK>; + assigned-clock-rates = <19200000>; + + interconnects = <&pcie_data_inbound MASTER_PCIE_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_PCIE_0 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "pcie-mem", + "cpu-pcie"; + + power-domains = <&gcc GCC_PCIE_A_GDSC>; + + resets = <&gcc GCC_PCIE_A_BCR>, + <&gcc GCC_PCIE_A_LINK_DOWN_BCR>; + reset-names = "pci", + "link_down"; + + pinctrl-0 = <&pcie0_default>; + pinctrl-names = "default"; + + operating-points-v2 = <&pcie0_opp_table>; + + pcie0_opp_table: opp-table { + compatible = "operating-points-v2"; + + /* GEN 1 x1 */ + opp-2500000-1 { + opp-hz = /bits/ 64 <2500000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* GEN 1 x2 */ + opp-5000000-1 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <500000 1>; + opp-level = <1>; + }; + + /* GEN 1 x4 */ + opp-10000000-1 { + opp-hz = /bits/ 64 <10000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1000000 1>; + opp-level = <1>; + }; + + /* GEN 1 x8 */ + opp-20000000-1 { + opp-hz = /bits/ 64 <20000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <2000000 1>; + opp-level = <1>; + }; + + /* GEN 1 x16 */ + opp-40000000-1 { + opp-hz = /bits/ 64 <40000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <4000000 1>; + opp-level = <1>; + }; + + /* GEN 2 x1 */ + opp-5000000-2 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + + /* GEN 2 x2 */ + opp-10000000-2 { + opp-hz = /bits/ 64 <10000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1000000 1>; + opp-level = <2>; + }; + + /* GEN 2 x4 */ + opp-20000000-2 { + opp-hz = /bits/ 64 <20000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <2000000 1>; + opp-level = <2>; + }; + + /* GEN 2 x8 */ + opp-40000000-2 { + opp-hz = /bits/ 64 <40000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <4000000 1>; + opp-level = <2>; + }; + + /* GEN 2 x16 */ + opp-80000000-2 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <8000000 1>; + opp-level = <2>; + }; + + /* GEN 3 x1 */ + opp-8000000-3 { + opp-hz = /bits/ 64 <8000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <984500 1>; + opp-level = <3>; + }; + + /* GEN 3 x2 */ + opp-16000000-3 { + opp-hz = /bits/ 64 <16000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1969000 1>; + opp-level = <3>; + }; + + /* GEN 3 x4 */ + opp-32000000-3 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <3938000 1>; + opp-level = <3>; + }; + + /* GEN 3 x8 */ + opp-64000000-3 { + opp-hz = /bits/ 64 <64000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <7876000 1>; + opp-level = <3>; + }; + + /* GEN 3 x16 */ + opp-128000000-3 { + opp-hz = /bits/ 64 <128000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <15753000 1>; + opp-level = <3>; + }; + + /* GEN 4 x1 */ + opp-16000000-4 { + opp-hz = /bits/ 64 <16000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <1969000 1>; + opp-level = <4>; + }; + + /* GEN 4 x2 */ + opp-32000000-4 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <3938000 1>; + opp-level = <4>; + }; + + /* GEN 4 x4 */ + opp-64000000-4 { + opp-hz = /bits/ 64 <64000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <7876000 1>; + opp-level = <4>; + }; + + /* GEN 4 x8 */ + opp-128000000-4 { + opp-hz = /bits/ 64 <128000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <15753000 1>; + opp-level = <4>; + }; + + /* GEN 4 x16 */ + opp-256000000-4 { + opp-hz = /bits/ 64 <256000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <31506000 1>; + opp-level = <4>; + }; + + /* GEN 5 x1 */ + opp-32000000-5 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <3938000 1>; + opp-level = <5>; + }; + + /* GEN 5 x2 */ + opp-64000000-5 { + opp-hz = /bits/ 64 <64000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <7876000 1>; + opp-level = <5>; + }; + + /* GEN 5 x4 */ + opp-128000000-5 { + opp-hz = /bits/ 64 <128000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <15753000 1>; + opp-level = <5>; + }; + + /* GEN 5 x8 */ + opp-256000000-5 { + opp-hz = /bits/ 64 <256000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <31506000 1>; + opp-level = <5>; + }; + + /* GEN 5 x16 */ + opp-512000000-5 { + opp-hz = /bits/ 64 <512000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <63012000 1>; + opp-level = <5>; + }; + }; +}; + +&pcie0_port0 { + phys = <&pcie_phy 0>; +}; + +&pcie1 { + clocks = <&gcc GCC_PCIE_B_AUX_CLK>, + <&gcc GCC_PCIE_B_CFG_AHB_CLK>, + <&gcc GCC_PCIE_B_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_B_SLV_AXI_CLK>, + <&gcc GCC_PCIE_B_SLV_Q2A_AXI_CLK>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a"; + + assigned-clocks = <&gcc GCC_PCIE_B_AUX_CLK>; + assigned-clock-rates = <19200000>; + + interconnects = <&pcie_data_inbound MASTER_PCIE_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_PCIE_1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "pcie-mem", + "cpu-pcie"; + + power-domains = <&gcc GCC_PCIE_B_GDSC>; + + resets = <&gcc GCC_PCIE_B_BCR>, + <&gcc GCC_PCIE_B_LINK_DOWN_BCR>; + reset-names = "pci", + "link_down"; + + pinctrl-0 = <&pcie1_default>; + pinctrl-names = "default"; + + operating-points-v2 = <&pcie1_opp_table>; + + pcie1_opp_table: opp-table { + compatible = "operating-points-v2"; + + /* GEN 1 x1 */ + opp-2500000-1 { + opp-hz = /bits/ 64 <2500000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* GEN 1 x2 */ + opp-5000000-1 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <500000 1>; + opp-level = <1>; + }; + + /* GEN 1 x4 */ + opp-10000000-1 { + opp-hz = /bits/ 64 <10000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1000000 1>; + opp-level = <1>; + }; + + /* GEN 1 x8 */ + opp-20000000-1 { + opp-hz = /bits/ 64 <20000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <2000000 1>; + opp-level = <1>; + }; + + /* GEN 2 x1 */ + opp-5000000-2 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + + /* GEN 2 x2 */ + opp-10000000-2 { + opp-hz = /bits/ 64 <10000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1000000 1>; + opp-level = <2>; + }; + + /* GEN 2 x4 */ + opp-20000000-2 { + opp-hz = /bits/ 64 <20000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <2000000 1>; + opp-level = <2>; + }; + + /* GEN 2 x8 */ + opp-40000000-2 { + opp-hz = /bits/ 64 <40000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <4000000 1>; + opp-level = <2>; + }; + + /* GEN 3 x1 */ + opp-8000000-3 { + opp-hz = /bits/ 64 <8000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <984500 1>; + opp-level = <3>; + }; + + /* GEN 3 x2 */ + opp-16000000-3 { + opp-hz = /bits/ 64 <16000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1969000 1>; + opp-level = <3>; + }; + + /* GEN 3 x4 */ + opp-32000000-3 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <3938000 1>; + opp-level = <3>; + }; + + /* GEN 3 x8 */ + opp-64000000-3 { + opp-hz = /bits/ 64 <64000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <7876000 1>; + opp-level = <3>; + }; + + /* GEN 4 x1 */ + opp-16000000-4 { + opp-hz = /bits/ 64 <16000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <1969000 1>; + opp-level = <4>; + }; + + /* GEN 4 x2 */ + opp-32000000-4 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <3938000 1>; + opp-level = <4>; + }; + + /* GEN 4 x4 */ + opp-64000000-4 { + opp-hz = /bits/ 64 <64000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <7876000 1>; + opp-level = <4>; + }; + + /* GEN 4 x8 */ + opp-128000000-4 { + opp-hz = /bits/ 64 <128000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <15753000 1>; + opp-level = <4>; + }; + + /* GEN 5 x1 */ + opp-32000000-5 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <3938000 1>; + opp-level = <5>; + }; + + /* GEN 5 x2 */ + opp-64000000-5 { + opp-hz = /bits/ 64 <64000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <7876000 1>; + opp-level = <5>; + }; + + /* GEN 5 x4 */ + opp-128000000-5 { + opp-hz = /bits/ 64 <128000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <15753000 1>; + opp-level = <5>; + }; + + /* GEN 5 x8 */ + opp-256000000-5 { + opp-hz = /bits/ 64 <256000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <31506000 1>; + opp-level = <5>; + }; + }; +}; + +&pcie1_port0 { + phys = <&pcie_phy 1>; +}; + +&pcie2 { + clocks = <&gcc GCC_PCIE_C_AUX_CLK>, + <&gcc GCC_PCIE_C_CFG_AHB_CLK>, + <&gcc GCC_PCIE_C_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_C_SLV_AXI_CLK>, + <&gcc GCC_PCIE_C_SLV_Q2A_AXI_CLK>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a"; + + assigned-clocks = <&gcc GCC_PCIE_C_AUX_CLK>; + assigned-clock-rates = <19200000>; + + interconnects = <&pcie_data_inbound MASTER_PCIE_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_PCIE_2 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "pcie-mem", + "cpu-pcie"; + + power-domains = <&gcc GCC_PCIE_C_GDSC>; + + resets = <&gcc GCC_PCIE_C_BCR>, + <&gcc GCC_PCIE_C_LINK_DOWN_BCR>; + reset-names = "pci", + "link_down"; + + pinctrl-0 = <&pcie2_default>; + pinctrl-names = "default"; + + operating-points-v2 = <&pcie2_opp_table>; + + pcie2_opp_table: opp-table { + compatible = "operating-points-v2"; + + /* GEN 1 x1 */ + opp-2500000-1 { + opp-hz = /bits/ 64 <2500000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* GEN 1 x2 */ + opp-5000000-1 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <500000 1>; + opp-level = <1>; + }; + + /* GEN 1 x4 */ + opp-10000000-1 { + opp-hz = /bits/ 64 <10000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1000000 1>; + opp-level = <1>; + }; + + /* GEN 2 x1 */ + opp-5000000-2 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + + /* GEN 2 x2 */ + opp-10000000-2 { + opp-hz = /bits/ 64 <10000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1000000 1>; + opp-level = <2>; + }; + + /* GEN 2 x4 */ + opp-20000000-2 { + opp-hz = /bits/ 64 <20000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <2000000 1>; + opp-level = <2>; + }; + + /* GEN 3 x1 */ + opp-8000000-3 { + opp-hz = /bits/ 64 <8000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <984500 1>; + opp-level = <3>; + }; + + /* GEN 3 x2 */ + opp-16000000-3 { + opp-hz = /bits/ 64 <16000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1969000 1>; + opp-level = <3>; + }; + + /* GEN 3 x4 */ + opp-32000000-3 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <3938000 1>; + opp-level = <3>; + }; + + /* GEN 4 x1 */ + opp-16000000-4 { + opp-hz = /bits/ 64 <16000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <1969000 1>; + opp-level = <4>; + }; + + /* GEN 4 x2 */ + opp-32000000-4 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <3938000 1>; + opp-level = <4>; + }; + + /* GEN 4 x4 */ + opp-64000000-4 { + opp-hz = /bits/ 64 <64000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <7876000 1>; + opp-level = <4>; + }; + + /* GEN 5 x1 */ + opp-32000000-5 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <3938000 1>; + opp-level = <5>; + }; + + /* GEN 5 x2 */ + opp-64000000-5 { + opp-hz = /bits/ 64 <64000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <7876000 1>; + opp-level = <5>; + }; + + /* GEN 5 x4 */ + opp-128000000-5 { + opp-hz = /bits/ 64 <128000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <15753000 1>; + opp-level = <5>; + }; + }; +}; + +&pcie2_port0 { + phys = <&pcie_phy 2>; +}; + +&pcie3 { + clocks = <&gcc GCC_PCIE_D_AUX_CLK>, + <&gcc GCC_PCIE_D_CFG_AHB_CLK>, + <&gcc GCC_PCIE_D_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_D_SLV_AXI_CLK>, + <&gcc GCC_PCIE_D_SLV_Q2A_AXI_CLK>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a"; + + assigned-clocks = <&gcc GCC_PCIE_D_AUX_CLK>; + assigned-clock-rates = <19200000>; + + interconnects = <&pcie_data_inbound MASTER_PCIE_3 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_PCIE_3 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "pcie-mem", + "cpu-pcie"; + + power-domains = <&gcc GCC_PCIE_D_GDSC>; + + resets = <&gcc GCC_PCIE_D_BCR>, + <&gcc GCC_PCIE_D_LINK_DOWN_BCR>; + reset-names = "pci", + "link_down"; + + pinctrl-0 = <&pcie3_default>; + pinctrl-names = "default"; + + operating-points-v2 = <&pcie3_opp_table>; + + pcie3_opp_table: opp-table { + compatible = "operating-points-v2"; + + /* GEN 1 x1 */ + opp-2500000-1 { + opp-hz = /bits/ 64 <2500000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* GEN 1 x2 */ + opp-5000000-1 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <500000 1>; + opp-level = <1>; + }; + + /* GEN 2 x1 */ + opp-5000000-2 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + + /* GEN 2 x2 */ + opp-10000000-2 { + opp-hz = /bits/ 64 <10000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1000000 1>; + opp-level = <2>; + }; + + /* GEN 3 x1 */ + opp-8000000-3 { + opp-hz = /bits/ 64 <8000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <984500 1>; + opp-level = <3>; + }; + + /* GEN 3 x2 */ + opp-16000000-3 { + opp-hz = /bits/ 64 <16000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1969000 1>; + opp-level = <3>; + }; + + /* GEN 4 x1 */ + opp-16000000-4 { + opp-hz = /bits/ 64 <16000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <1969000 1>; + opp-level = <4>; + }; + + /* GEN 4 x2 */ + opp-32000000-4 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <3938000 1>; + opp-level = <4>; + }; + + /* GEN 5 x1 */ + opp-32000000-5 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <3938000 1>; + opp-level = <5>; + }; + + /* GEN 5 x2 */ + opp-64000000-5 { + opp-hz = /bits/ 64 <64000000>; + required-opps = <&rpmhpd_opp_nom>; + opp-peak-kBps = <7876000 1>; + opp-level = <5>; + }; + }; +}; + +&pcie3_port0 { + phys = <&pcie_phy 3>; +}; + &qupv3_0 { clocks = <&segcc SE_GCC_QUPV3_WRAP0_M_AHB_CLK>, <&segcc SE_GCC_QUPV3_WRAP0_S_AHB_CLK>; @@ -753,10 +1485,10 @@ reg = <0x0 0x00100000 0x0 0x1f4200>; clocks = <&bi_tcxo_div2>, <&sleep_clk>, - <0>, - <0>, - <0>, - <0>; + <&pcie_phy 0>, + <&pcie_phy 1>, + <&pcie_phy 2>, + <&pcie_phy 3>; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; @@ -823,6 +1555,100 @@ qcom,bcm-voters = <&apps_bcm_voter>; }; + pcie_phy: phy@1b00000 { + compatible = "qcom,nord-qmp-gen5x16-pcie-phy"; + + reg = <0x0 0x01b00000 0x0 0x10000>, + <0x0 0x01b10000 0x0 0x10000>, + <0x0 0x01b20000 0x0 0x10000>, + <0x0 0x01b30000 0x0 0x10000>; + reg-names = "port_a", + "port_b", + "port_c", + "port_d"; + + clocks = <&gcc GCC_PCIE_A_PHY_AUX_CLK>, + <&gcc GCC_PCIE_A_CFG_AHB_CLK>, + <&tcsrcc TCSR_PCIE_CLKREF_EN>, + <&gcc GCC_PCIE_A_PHY_RCHNG_CLK>, + <&gcc GCC_PCIE_A_PIPE_CLK>, + <&gcc GCC_PCIE_B_PHY_AUX_CLK>, + <&gcc GCC_PCIE_B_CFG_AHB_CLK>, + <&gcc GCC_PCIE_B_PHY_RCHNG_CLK>, + <&gcc GCC_PCIE_B_PIPE_CLK>, + <&gcc GCC_PCIE_C_PHY_AUX_CLK>, + <&gcc GCC_PCIE_C_CFG_AHB_CLK>, + <&gcc GCC_PCIE_C_PHY_RCHNG_CLK>, + <&gcc GCC_PCIE_C_PIPE_CLK>, + <&gcc GCC_PCIE_D_PHY_AUX_CLK>, + <&gcc GCC_PCIE_D_CFG_AHB_CLK>, + <&gcc GCC_PCIE_D_PHY_RCHNG_CLK>, + <&gcc GCC_PCIE_D_PIPE_CLK>; + clock-names = "aux_a", + "cfg_ahb_a", + "ref", + "rchng_a", + "pipe_a", + "aux_b", + "cfg_ahb_b", + "rchng_b", + "pipe_b", + "aux_c", + "cfg_ahb_c", + "rchng_c", + "pipe_c", + "aux_d", + "cfg_ahb_d", + "rchng_d", + "pipe_d"; + + assigned-clocks = <&gcc GCC_PCIE_A_PHY_RCHNG_CLK>, + <&gcc GCC_PCIE_B_PHY_RCHNG_CLK>, + <&gcc GCC_PCIE_C_PHY_RCHNG_CLK>, + <&gcc GCC_PCIE_D_PHY_RCHNG_CLK>; + assigned-clock-rates = <100000000>, + <100000000>, + <100000000>, + <100000000>; + + power-domains = <&gcc GCC_PCIE_A_PHY_GDSC>, + <&gcc GCC_PCIE_B_PHY_GDSC>, + <&gcc GCC_PCIE_C_PHY_GDSC>, + <&gcc GCC_PCIE_D_PHY_GDSC>; + power-domain-names = "port_a", + "port_b", + "port_c", + "port_d"; + + resets = <&gcc GCC_PCIE_A_PHY_COM_BCR>, + <&gcc GCC_PCIE_A_NOCSR_COM_PHY_BCR>, + <&gcc GCC_PCIE_B_PHY_COM_BCR>, + <&gcc GCC_PCIE_B_NOCSR_COM_PHY_BCR>, + <&gcc GCC_PCIE_C_PHY_COM_BCR>, + <&gcc GCC_PCIE_C_NOCSR_COM_PHY_BCR>, + <&gcc GCC_PCIE_D_PHY_COM_BCR>, + <&gcc GCC_PCIE_D_NOCSR_COM_PHY_BCR>; + reset-names = "port_a", + "port_a_nocsr", + "port_b", + "port_b_nocsr", + "port_c", + "port_c_nocsr", + "port_d", + "port_d_nocsr"; + + qcom,link-mode = <&tcsr 0x71050>; + + #clock-cells = <1>; + clock-output-names = "pcie_a_pipe_clk", + "pcie_b_pipe_clk", + "pcie_c_pipe_clk", + "pcie_d_pipe_clk"; + #phy-cells = <1>; + + status = "disabled"; + }; + pcie_cfg: interconnect@1ba0000 { compatible = "qcom,nord-pcie-cfg"; reg = <0x0 0x01ba0000 0x0 0x7200>; @@ -1337,6 +2163,98 @@ bias-disable; }; + pcie0_default: pcie0-default-state { + wake-pins { + pins = "gpio0"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio1"; + function = "pcie0_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio2"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + + pcie1_default: pcie1-default-state { + wake-pins { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio4"; + function = "pcie1_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio5"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + + pcie2_default: pcie2-default-state { + wake-pins { + pins = "gpio6"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio7"; + function = "pcie2_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio8"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + + pcie3_default: pcie3-default-state { + wake-pins { + pins = "gpio9"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clkreq-pins { + pins = "gpio10"; + function = "pcie3_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-pins { + pins = "gpio11"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + qup_i2c0_default: qup-i2c0-default-state { pins = "gpio111", "gpio112"; function = "qup0_se0"; diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 32f7a7ae687a7..4f288613464d3 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -1931,6 +1931,290 @@ reg = <0x0 0x010c3000 0x0 0x1000>; }; + pcie0: pci@1b80000 { + compatible = "qcom,nord-pcie", "qcom,pcie-sa8775p"; + + reg = <0x00 0x01b80000 0x00 0x00004000>, + <0x00 0x40000000 0x00 0x00000f20>, + <0x00 0x40000f20 0x00 0x000000a8>, + <0x00 0x40010000 0x00 0x00020000>, + <0x00 0x40100000 0x00 0x00100000>, + <0x00 0x01b84000 0x00 0x00001000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + + ranges = <0x01000000 0x0 0x00000000 0x0 0x40200000 0x0 0x100000>, + <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0xfd00000>; + + bus-range = <0x00 0xff>; + device_type = "pci"; + linux,pci-domain = <0>; + num-lanes = <8>; + + #address-cells = <3>; + #size-cells = <2>; + + dma-coherent; + + 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 0 0 0 149 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 0 150 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 0 151 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 0 152 IRQ_TYPE_LEVEL_HIGH>; + + iommu-map = <0x0 &pcie_smmu 0x0000 0x10000>; + + msi-map = <0x0 &gic_its 0x80000 0x10000>; + + status = "disabled"; + + pcie0_port0: pcie@0 { + compatible = "pciclass,0604"; + reg = <0 0 0 0 0>; + bus-range = <0x01 0xff>; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; + }; + + pcie1: pci@1b88000 { + compatible = "qcom,nord-pcie", "qcom,pcie-sa8775p"; + + reg = <0x00 0x01b88000 0x00 0x00004000>, + <0x00 0x50000000 0x00 0x00000f20>, + <0x00 0x50000f20 0x00 0x000000a8>, + <0x00 0x50010000 0x00 0x00010000>, + <0x00 0x50100000 0x00 0x00100000>, + <0x00 0x01b8c000 0x00 0x00001000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + + ranges = <0x01000000 0x0 0x00000000 0x0 0x50200000 0x0 0x100000>, + <0x02000000 0x0 0x50300000 0x0 0x50300000 0x0 0xfd00000>; + + bus-range = <0x00 0xff>; + device_type = "pci"; + linux,pci-domain = <1>; + num-lanes = <4>; + + #address-cells = <3>; + #size-cells = <2>; + + dma-coherent; + + 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 0 0 0 835 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 0 351 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 0 830 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 0 348 IRQ_TYPE_LEVEL_HIGH>; + + msi-map = <0x0 &gic_its 0x90000 0x10000>; + + iommu-map = <0x0 &pcie_smmu 0x10000 0x10000>; + + status = "disabled"; + + pcie1_port0: pcie@0 { + device_type = "pci"; + compatible = "pciclass,0604"; + reg = <0 0 0 0 0>; + bus-range = <0x01 0xff>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; + }; + + pcie2: pci@1b90000 { + compatible = "qcom,nord-pcie", "qcom,pcie-sa8775p"; + + reg = <0x00 0x01b90000 0x00 0x00004000>, + <0x00 0x60000000 0x00 0x00000f20>, + <0x00 0x60000f20 0x00 0x000000a8>, + <0x00 0x60010000 0x00 0x00010000>, + <0x00 0x60100000 0x00 0x00100000>, + <0x00 0x01b94000 0x00 0x00001000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + + ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>, + <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0xfd00000>; + + bus-range = <0x00 0xff>; + device_type = "pci"; + linux,pci-domain = <2>; + num-lanes = <2>; + + #address-cells = <3>; + #size-cells = <2>; + + dma-coherent; + + 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 0 0 0 263 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 0 154 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 0 110 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 0 258 IRQ_TYPE_LEVEL_HIGH>; + + iommu-map = <0x0 &pcie_smmu 0x20000 0x10000>; + + msi-map = <0x0 &gic_its 0xa0000 0x10000>; + + status = "disabled"; + + pcie2_port0: pcie@0 { + device_type = "pci"; + compatible = "pciclass,0604"; + reg = <0 0 0 0 0>; + bus-range = <0x01 0xff>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; + }; + + pcie3: pci@1b98000 { + compatible = "qcom,nord-pcie", "qcom,pcie-sa8775p"; + + reg = <0x00 0x01b98000 0x00 0x00004000>, + <0x00 0x70000000 0x00 0x00000f20>, + <0x00 0x70000f20 0x00 0x000000a8>, + <0x00 0x70010000 0x00 0x00010000>, + <0x00 0x70100000 0x00 0x00100000>, + <0x00 0x01b9c000 0x00 0x00001000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + + ranges = <0x01000000 0x0 0x00000000 0x0 0x70200000 0x0 0x100000>, + <0x02000000 0x0 0x70300000 0x0 0x70300000 0x0 0xfd00000>; + + bus-range = <0x00 0xff>; + device_type = "pci"; + linux,pci-domain = <3>; + num-lanes = <2>; + + #address-cells = <3>; + #size-cells = <2>; + + dma-coherent; + + 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 0 0 0 111 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 0 246 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 0 239 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 0 234 IRQ_TYPE_LEVEL_HIGH>; + + msi-map = <0x0 &gic_its 0xb0000 0x10000>; + + iommu-map = <0x0 &pcie_smmu 0x30000 0x10000>; + + status = "disabled"; + + pcie3_port0: pcie@0 { + device_type = "pci"; + compatible = "pciclass,0604"; + reg = <0 0 0 0 0>; + bus-range = <0x01 0xff>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; + }; + ufs_mem_hc: ufshc@1d44000 { compatible = "qcom,nord-ufshc", "qcom,ufshc", @@ -2196,6 +2480,19 @@ dma-coherent; }; + pcie_smmu: iommu@9980000 { + compatible = "arm,smmu-v3"; + reg = <0x0 0x09980000 0x0 0x20000>; + interrupts = , + , + ; + interrupt-names = "eventq", + "cmdq-sync", + "gerror"; + dma-coherent; + #iommu-cells = <1>; + }; + usb_2: usb@a200000 { compatible = "qcom,nord-dwc3", "qcom,snps-dwc3"; From 89838516703203cb9e1bb29b7eae444d3e5db504 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 31 Oct 2026 22:24:28 +0800 Subject: [PATCH 0267/1133] FROMLIST: arm64: dts: qcom: nord-rrd: Enable PCIe controllers and PHY The Nord Robotics Reference Design board routes all four PCIe links, so enable pcie0-pcie3 and the QMP PHY, supply the per-port PHY and PLL rails, and describe the PERST# and WAKE# lines of each root port. Signed-off-by: Krishna Chaitanya Chundru Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261031142433.1212809-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 49 +++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index 526ef4db4d072..243b2d6eb479f 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -619,6 +619,55 @@ }; }; +&pcie_phy { + vdda-phy-a-supply = <&vreg_l6a_1p2>; + vdda-phy-b-supply = <&vreg_l4a_1p2>; + vdda-phy-c-supply = <&vreg_l4a_1p2>; + vdda-phy-d-supply = <&vreg_l4a_1p2>; + vdda-pll-a-supply = <&vreg_l1e_0p9>; + vdda-pll-b-supply = <&vreg_l2e_0p9>; + vdda-pll-c-supply = <&vreg_l2e_0p9>; + vdda-pll-d-supply = <&vreg_l2e_0p9>; + + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; + +&pcie0_port0 { + reset-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; +}; + +&pcie1 { + status = "okay"; +}; + +&pcie1_port0 { + reset-gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; +}; + +&pcie2 { + status = "okay"; +}; + +&pcie2_port0 { + reset-gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; +}; + +&pcie3 { + status = "okay"; +}; + +&pcie3_port0 { + reset-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; +}; + &qupv3_0 { firmware-name = "qcom/nord/qupv3fw.elf"; From 6898115708b0079f97ed70c5dc7e1a98a0ec587a Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 31 Oct 2026 22:24:29 +0800 Subject: [PATCH 0268/1133] FROMLIST: arm64: dts: qcom: nord-ride-embedded: Enable PCIe controllers and PHY The Nord Ride Embedded board routes all four PCIe links, so enable pcie0-pcie3 and the QMP PHY, supply the per-port PHY and PLL rails, and describe the PERST# and WAKE# lines of each root port. Signed-off-by: Krishna Chaitanya Chundru Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261031142433.1212809-4-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- .../boot/dts/qcom/nord-ride-embedded.dts | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index 80fcf2430c8d4..bd02ae2a3dc2c 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -672,6 +672,55 @@ }; }; +&pcie_phy { + vdda-phy-a-supply = <&vreg_l6a_1p2>; + vdda-phy-b-supply = <&vreg_l4a_1p2>; + vdda-phy-c-supply = <&vreg_l4a_1p2>; + vdda-phy-d-supply = <&vreg_l4a_1p2>; + vdda-pll-a-supply = <&vreg_l1e_0p9>; + vdda-pll-b-supply = <&vreg_l2e_0p9>; + vdda-pll-c-supply = <&vreg_l2e_0p9>; + vdda-pll-d-supply = <&vreg_l2e_0p9>; + + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; + +&pcie0_port0 { + reset-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; +}; + +&pcie1 { + status = "okay"; +}; + +&pcie1_port0 { + reset-gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; +}; + +&pcie2 { + status = "okay"; +}; + +&pcie2_port0 { + reset-gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; +}; + +&pcie3 { + status = "okay"; +}; + +&pcie3_port0 { + reset-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; +}; + &qupv3_0 { firmware-name = "qcom/nord/qupv3fw.elf"; From f3361e42862828da037c6947523e5723d6a6024f Mon Sep 17 00:00:00 2001 From: "Yu Zhang(Yuriy)" Date: Sat, 31 Oct 2026 22:24:30 +0800 Subject: [PATCH 0269/1133] FROMLIST: arm64: dts: qcom: nord-ride-embedded: Add WCN7850 WLAN support The Nord Ride Embedded board carries a QCA6797AQ (WCN7850) LGA module on a connectivity adapter card hanging off PCIe2. Two PMIC GPIOs gate the module supplies: PWR_CORE (pmau0102_e GPIO6) enables the DBU_CORE_VL, DBU_CORE_VM and DBU_CORE_VH regulators feeding VDD_CORE_VL/VM/VH, and PWR_CTRL1 (pmau0102_e GPIO8) enables DBU4, which produces the 3.3 V rail. PWR_CTRL2 drives DBU3, which is not populated, so it is left alone. Describe those rails, the WCN7850 PMU that derives the chip supplies from them, and the PCIe endpoint node consuming the PMU outputs. Signed-off-by: Yu Zhang (Yuriy) Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261031142433.1212809-5-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- .../boot/dts/qcom/nord-ride-embedded.dts | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index bd02ae2a3dc2c..df710b8a97b71 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -180,6 +180,102 @@ }; }; }; + + vreg_wcn_3p3: regulator-wcn-3p3 { + compatible = "regulator-fixed"; + regulator-name = "vreg_wcn_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pmau0102_e_gpios 8 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vreg_wcn_1p9: regulator-wcn-1p9 { + compatible = "regulator-fixed"; + regulator-name = "vreg_wcn_1p9"; + regulator-min-microvolt = <1900000>; + regulator-max-microvolt = <1900000>; + gpio = <&pmau0102_e_gpios 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vreg_wcn_core_vl_0p95: regulator-wcn-core-vl-0p95 { + compatible = "regulator-fixed"; + regulator-name = "vreg_wcn_core_vl_0p95"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <950000>; + gpio = <&pmau0102_e_gpios 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vreg_wcn_core_vm_1p35: regulator-wcn-core-vm-1p35 { + compatible = "regulator-fixed"; + regulator-name = "vreg_wcn_core_vm_1p35"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + gpio = <&pmau0102_e_gpios 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vreg_wcn_core_vh_1p95: regulator-wcn-core-vh-1p95 { + compatible = "regulator-fixed"; + regulator-name = "vreg_wcn_core_vh_1p95"; + regulator-min-microvolt = <1950000>; + regulator-max-microvolt = <1950000>; + gpio = <&pmau0102_e_gpios 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + wcn7850-pmu { + compatible = "qcom,wcn7850-pmu"; + + wlan-enable-gpios = <&pmau0102_e_gpios 10 GPIO_ACTIVE_HIGH>; + + vdd-supply = <&vreg_wcn_3p3>; + vddio-supply = <&vreg_s3a_1p8>; + vddaon-supply = <&vreg_wcn_core_vl_0p95>; + vdddig-supply = <&vreg_wcn_1p9>; + vddrfa1p2-supply = <&vreg_wcn_core_vm_1p35>; + vddrfa1p8-supply = <&vreg_wcn_core_vh_1p95>; + + 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_rfa_0p8: ldo5 { + regulator-name = "vreg_pmu_rfa_0p8"; + }; + + vreg_pmu_rfa_1p2: ldo6 { + regulator-name = "vreg_pmu_rfa_1p2"; + }; + + vreg_pmu_rfa_1p8: ldo7 { + regulator-name = "vreg_pmu_rfa_1p8"; + }; + + vreg_pmu_pcie_0p9: ldo8 { + regulator-name = "vreg_pmu_pcie_0p9"; + }; + + vreg_pmu_pcie_1p8: ldo9 { + regulator-name = "vreg_pmu_pcie_1p8"; + }; + }; + }; }; &apps_rsc { @@ -710,6 +806,21 @@ &pcie2_port0 { reset-gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; wake-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; + + wifi@0 { + compatible = "pci17cb,1107"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>; + }; }; &pcie3 { From 074fa1e3f0c27cf5bca675f0c9bcf56ad73f4a46 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Sat, 31 Oct 2026 22:24:31 +0800 Subject: [PATCH 0270/1133] FROMLIST: arm64: dts: qcom: nord-ride-embedded: Add WCN7850 Bluetooth support The WCN7850 module on the connectivity adapter card exposes its HCI interface on UART17, and BT_EN is routed to pmau0102_e GPIO9. Hook that GPIO up to the WCN7850 PMU, enable uart17 as serial1, and describe the Bluetooth controller consuming the PMU outputs. Signed-off-by: Shuai Zhang Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261031142433.1212809-6-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- .../boot/dts/qcom/nord-ride-embedded.dts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index df710b8a97b71..906c3b0bd12a6 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -20,6 +20,7 @@ aliases { serial0 = &uart15; + serial1 = &uart17; }; chosen { @@ -229,6 +230,7 @@ wcn7850-pmu { compatible = "qcom,wcn7850-pmu"; + bt-enable-gpios = <&pmau0102_e_gpios 9 GPIO_ACTIVE_HIGH>; wlan-enable-gpios = <&pmau0102_e_gpios 10 GPIO_ACTIVE_HIGH>; vdd-supply = <&vreg_wcn_3p3>; @@ -893,6 +895,23 @@ status = "okay"; }; +&uart17 { + status = "okay"; + + bluetooth { + compatible = "qcom,wcn7850-bt"; + max-speed = <3200000>; + + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + }; +}; + &ufs_mem_hc { reset-gpios = <&tlmm 181 GPIO_ACTIVE_LOW>; From 59cb3bad5af63562e07d5ce6e9e7dfe117eb2849 Mon Sep 17 00:00:00 2001 From: "Yu Zhang(Yuriy)" Date: Sat, 31 Oct 2026 22:24:32 +0800 Subject: [PATCH 0271/1133] FROMLIST: arm64: dts: qcom: nord-rrd: Add WCN7850 WLAN support The Nord RRD carries a QCA6797AQ (WCN7850) LGA module on a connectivity adapter card hanging off PCIe2. Three PMIC GPIOs gate the module supplies: PWR_CORE (pmau0102_e GPIO6) enables the DBU_CORE_VL, DBU_CORE_VM and DBU_CORE_VH regulators feeding VDD_CORE_VL/VM/VH, PWR_CTRL1 (pmau0102_e GPIO8) enables DBU4, which produces the 3.3 V rail, and PWR_CTRL2 (pmau0102_e GPIO7) enables the 1.9 V rail. Describe those rails, the WCN7850 PMU that derives the chip supplies from them, and the PCIe endpoint node consuming the PMU outputs. Signed-off-by: Yu Zhang (Yuriy) Link: https://lore.kernel.org/r/20261031142433.1212809-7-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 111 ++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index 243b2d6eb479f..827bc21218286 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -163,6 +163,102 @@ regulator-max-microvolt = <3300000>; regulator-always-on; }; + + vreg_wcn_3p3: regulator-wcn-3p3 { + compatible = "regulator-fixed"; + regulator-name = "vreg_wcn_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pmau0102_e_gpios 8 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vreg_wcn_1p9: regulator-wcn-1p9 { + compatible = "regulator-fixed"; + regulator-name = "vreg_wcn_1p9"; + regulator-min-microvolt = <1900000>; + regulator-max-microvolt = <1900000>; + gpio = <&pmau0102_e_gpios 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vreg_wcn_core_vl_0p95: regulator-wcn-core-vl-0p95 { + compatible = "regulator-fixed"; + regulator-name = "vreg_wcn_core_vl_0p95"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <950000>; + gpio = <&pmau0102_e_gpios 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vreg_wcn_core_vm_1p35: regulator-wcn-core-vm-1p35 { + compatible = "regulator-fixed"; + regulator-name = "vreg_wcn_core_vm_1p35"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + gpio = <&pmau0102_e_gpios 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vreg_wcn_core_vh_1p95: regulator-wcn-core-vh-1p95 { + compatible = "regulator-fixed"; + regulator-name = "vreg_wcn_core_vh_1p95"; + regulator-min-microvolt = <1950000>; + regulator-max-microvolt = <1950000>; + gpio = <&pmau0102_e_gpios 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + wcn7850-pmu { + compatible = "qcom,wcn7850-pmu"; + + wlan-enable-gpios = <&pmau0102_e_gpios 10 GPIO_ACTIVE_HIGH>; + + vdd-supply = <&vreg_wcn_3p3>; + vddio-supply = <&vreg_s3a_1p8>; + vddaon-supply = <&vreg_wcn_core_vl_0p95>; + vdddig-supply = <&vreg_wcn_1p9>; + vddrfa1p2-supply = <&vreg_wcn_core_vm_1p35>; + vddrfa1p8-supply = <&vreg_wcn_core_vh_1p95>; + + 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_rfa_0p8: ldo5 { + regulator-name = "vreg_pmu_rfa_0p8"; + }; + + vreg_pmu_rfa_1p2: ldo6 { + regulator-name = "vreg_pmu_rfa_1p2"; + }; + + vreg_pmu_rfa_1p8: ldo7 { + regulator-name = "vreg_pmu_rfa_1p8"; + }; + + vreg_pmu_pcie_0p9: ldo8 { + regulator-name = "vreg_pmu_pcie_0p9"; + }; + + vreg_pmu_pcie_1p8: ldo9 { + regulator-name = "vreg_pmu_pcie_1p8"; + }; + }; + }; }; &apps_rsc { @@ -657,6 +753,21 @@ &pcie2_port0 { reset-gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; wake-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; + + wifi@0 { + compatible = "pci17cb,1107"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>; + }; }; &pcie3 { From 2be854356ba3d776c99216228d410c993c4c690d Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Sat, 31 Oct 2026 22:24:33 +0800 Subject: [PATCH 0272/1133] FROMLIST: arm64: dts: qcom: nord-rrd: Add WCN7850 Bluetooth support Enable Bluetooth for the WCN7850 module on the Nord RRD: route the BT UART (uart17) as serial1, add the bt-enable GPIO (pmau0102_e GPIO9) to the WCN7850 PMU and describe the bluetooth node with its supplies. Signed-off-by: Shuai Zhang Link: https://lore.kernel.org/r/20261031142433.1212809-8-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index 827bc21218286..597c5b9cf6364 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -20,6 +20,7 @@ aliases { serial0 = &uart15; + serial1 = &uart17; }; chosen { @@ -212,6 +213,7 @@ wcn7850-pmu { compatible = "qcom,wcn7850-pmu"; + bt-enable-gpios = <&pmau0102_e_gpios 9 GPIO_ACTIVE_HIGH>; wlan-enable-gpios = <&pmau0102_e_gpios 10 GPIO_ACTIVE_HIGH>; vdd-supply = <&vreg_wcn_3p3>; @@ -848,6 +850,23 @@ status = "okay"; }; +&uart17 { + status = "okay"; + + bluetooth { + compatible = "qcom,wcn7850-bt"; + max-speed = <3200000>; + + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + }; +}; + &ufs_mem_hc { reset-gpios = <&tlmm 181 GPIO_ACTIVE_LOW>; From 170623131b671c23c5beb6a44ee281c5e315885d Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 01:53:17 +0530 Subject: [PATCH 0273/1133] FROMLIST: net: stmmac: qcom-ethqos: fix RGMII_ID mode to use DLL bypass When "rgmii-id" is selected the PHY supplies both TX and RX delays, so the MAC must not add its own. The driver currently falls through to the generic DLL initialisation path which programs it to add a delay. Power down the DLL and set DDR bypass mode for RGMII_ID, then program the IO_MACRO via a new ethqos_rgmii_id_macro_init() helper. Also fix ethqos_set_clk_tx_rate() to not double the clock rate in bypass mode at 100M/10M, and remove RGMII_ID from the phase-shift suppression in ethqos_rgmii_macro_init() since RGMII_ID no longer reaches that path. Link: https://lore.kernel.org/netdev/20260908-shikra_ethernet-v2-5-bbe3389d0652@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 67 ++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index c965c2d0c67de..bee316c5ba734 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -68,6 +68,9 @@ /* SDC4_STATUS bits */ #define SDC4_STATUS_DLL_LOCK BIT(7) +/* SDCC_USR_CTL bits */ +#define SDCC_USR_CTL_DDR_BYPASS BIT(30) + /* RGMII_IO_MACRO_CONFIG2 fields */ #define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17) #define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16) @@ -189,7 +192,15 @@ static int ethqos_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i, if (rate < 0) return rate; - return clk_set_rate(ethqos->link_clk, rate * 2); + /* Clock Rate Requirements: + * MAC added delay: 250/50/5 Mhz for 1G/100M/10M + * No MAC delay (DLL bypass): 250/25/2.5 Mhz for 1G/100M/10M + */ + if (ethqos->phy_mode != PHY_INTERFACE_MODE_RGMII_ID || + speed == SPEED_1000) + rate *= 2; + + return clk_set_rate(ethqos->link_clk, rate); } static void @@ -445,8 +456,7 @@ static void ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) RGMII_IO_MACRO_CONFIG2); /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */ - if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID || - ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) + if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) phase_shift = 0; else phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN; @@ -515,6 +525,42 @@ static void ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos, int speed) RGMII_IO_MACRO_CONFIG); } +static void ethqos_rgmii_id_macro_init(struct qcom_ethqos *ethqos, int speed) +{ + rgmii_clrmask(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, + RGMII_IO_MACRO_CONFIG2); + + if (speed == SPEED_1000) + rgmii_setmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + else + rgmii_clrmask(ethqos, RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + rgmii_setmask(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, RGMII_IO_MACRO_CONFIG); + rgmii_clrmask(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, RGMII_IO_MACRO_CONFIG); + rgmii_clrmask(ethqos, RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG); + + if (ethqos->data->has_emac_ge_3) + rgmii_clrmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + RGMII_IO_MACRO_CONFIG2); + else + rgmii_setmask(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + RGMII_IO_MACRO_CONFIG2); + + rgmii_clrmask(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_IO_MACRO_CONFIG2); + + if (speed == SPEED_1000) + rgmii_clrmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, RGMII_IO_MACRO_CONFIG2); + else + rgmii_setmask(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, RGMII_IO_MACRO_CONFIG2); + + if (ethqos->data->rgmii_config_loopback_en) + rgmii_setmask(ethqos, RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); + else + rgmii_clrmask(ethqos, RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); + + rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); +} + static void ethqos_fix_mac_speed_rgmii(void *bsp_priv, phy_interface_t interface, int speed, unsigned int mode) @@ -533,6 +579,21 @@ static void ethqos_fix_mac_speed_rgmii(void *bsp_priv, ethqos_set_func_clk_en(ethqos); + /* For rgmii-id mode, the PHY should add the required delays. + * Therefore, power down the DLL and program it in bypass mode. + * Program the IO_MACRO as per the settings recommended by the + * programming guide for bypass mode. This will ensure that the + * MAC core doesn't add any additional delays. + */ + if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID) { + rgmii_setmask(ethqos, SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG); + rgmii_setmask(ethqos, SDCC_USR_CTL_DDR_BYPASS, SDCC_USR_CTL); + + ethqos_rgmii_id_macro_init(ethqos, speed); + + return; + } + /* Initialize the DLL first */ /* Set DLL_RST */ From b689d9c4936c9c49ef6da1d8e104febe8c614df8 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 01:53:18 +0530 Subject: [PATCH 0274/1133] FROMLIST: net: stmmac: qcom-ethqos: warn about legacy RGMII PHY modes The qcom-ethqos driver is moving towards using "rgmii-id" together with PHY-provided delays. However, existing DTBs use "rgmii" and "rgmii-txid" and must remain supported for backwards compatibility. Warn when either of these legacy PHY modes is used to encourage users to migrate to updated DTBs using "rgmii-id". Link: https://lore.kernel.org/netdev/20260908-shikra_ethernet-v2-6-bbe3389d0652@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index bee316c5ba734..ad34abbd36b7c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -951,9 +951,11 @@ static int qcom_ethqos_probe(struct platform_device *pdev) switch (ethqos->phy_mode) { case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: + dev_warn(dev, "legacy RGMII phy-mode detected; consider upgrading to a newer DTB\n"); + fallthrough; + case PHY_INTERFACE_MODE_RGMII_ID: break; case PHY_INTERFACE_MODE_2500BASEX: case PHY_INTERFACE_MODE_SGMII: From 10a9d7b32fcbe30ee5720d70fbc9aa28ca0d0688 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 01:53:19 +0530 Subject: [PATCH 0275/1133] FROMLIST: net: stmmac: qcom-ethqos: set initial RGMII link clock to lowest speed On probe the RGMII link clock is initialised at SPEED_1000, which translates to a 250 MHz source clock even when no PHY link is present, drawing unnecessary power. Initialise at SPEED_10 instead; fix_mac_speed updates the rate once a link is established. Link: https://lore.kernel.org/netdev/20260908-shikra_ethernet-v2-7-bbe3389d0652@oss.qualcomm.com/ Reviewed-by: Maxime Chevallier Signed-off-by: Mohd Ayaan Anwar --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index ad34abbd36b7c..97ce8f2c11fae 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -819,7 +819,7 @@ static int ethqos_hlos_setup(struct qcom_ethqos *ethqos, if (ret) return ret; - ethqos_set_clk_tx_rate(ethqos, NULL, plat_dat->phy_interface, SPEED_1000); + ethqos_set_clk_tx_rate(ethqos, NULL, plat_dat->phy_interface, SPEED_10); qcom_ethqos_set_sgmii_loopback(ethqos, true); ethqos_set_func_clk_en(ethqos); From 129e31630e7d42d6b91c50f54df3a21f49d2689b Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 01:53:20 +0530 Subject: [PATCH 0276/1133] FROMLIST: net: stmmac: qcom-ethqos: add per-platform NOC clock voting Some SoCs gate the EMAC's path to the System NOC behind dedicated clocks that must be enabled before the DMA can reach memory. Add ethqos_noc_clk_cfg and the corresponding fields in the driver-data and runtime structs so each compatible can declare its own set with per-clock rates. The clocks are acquired during probe and enabled/disabled alongside the existing link clock in ethqos_clks_config(). No functional change for existing compatibles. This will help us when we add support for Shikra. Link: https://lore.kernel.org/netdev/20260908-shikra_ethernet-v2-8-bbe3389d0652@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 97ce8f2c11fae..24fd6eda1dfd2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "stmmac.h" #include "stmmac_platform.h" @@ -85,6 +86,8 @@ #define SGMII_10M_RX_CLK_DVDR 0x31 +#define ETHQOS_MAX_NOC_CLKS 3 + struct qcom_ethqos; struct ethqos_emac_por { @@ -92,6 +95,11 @@ struct ethqos_emac_por { unsigned int value; }; +struct ethqos_noc_clk_cfg { + const char *id; + unsigned long rate; +}; + struct ethqos_emac_driver_data { const struct ethqos_emac_por *rgmii_por; unsigned int num_rgmii_por; @@ -101,6 +109,8 @@ struct ethqos_emac_driver_data { const char *link_clk_name; struct dwmac4_addrs dwmac4_addrs; bool needs_sgmii_loopback; + const struct ethqos_noc_clk_cfg *noc_clk_cfg; + unsigned int num_noc_clks; /* Fixed PTP reference clock rate, used on SCMI platforms where * firmware does not implement the clock protocol allowing linux to * query it. @@ -116,6 +126,9 @@ struct qcom_ethqos { struct clk *link_clk; struct phy *serdes_phy; phy_interface_t phy_mode; + struct clk_bulk_data noc_clks[ETHQOS_MAX_NOC_CLKS]; + unsigned long noc_clk_rates[ETHQOS_MAX_NOC_CLKS]; + int num_noc_clks; struct dev_pm_domain_list *pds; const struct ethqos_emac_driver_data *data; }; @@ -747,15 +760,51 @@ static int ethqos_mac_finish_serdes(struct net_device *ndev, void *priv, static int ethqos_clks_config(void *priv, bool enabled) { struct qcom_ethqos *ethqos = priv; + unsigned int i; int ret = 0; if (enabled) { + if (ethqos->num_noc_clks) { + ret = dev_pm_opp_set_rate(ðqos->pdev->dev, + ethqos->noc_clk_rates[0]); + if (ret) { + dev_err(ðqos->pdev->dev, + "NOC OPP rate set failed: %d\n", ret); + return ret; + } + + for (i = 1; i < ethqos->num_noc_clks; i++) { + ret = clk_set_rate(ethqos->noc_clks[i].clk, + ethqos->noc_clk_rates[i]); + if (ret) { + dev_err(ðqos->pdev->dev, + "NOC clock rate set failed: %d\n", ret); + dev_pm_opp_set_rate(ðqos->pdev->dev, 0); + return ret; + } + } + } + ret = clk_prepare_enable(ethqos->link_clk); if (ret) { dev_err(ðqos->pdev->dev, "link_clk enable failed\n"); + if (ethqos->num_noc_clks) + dev_pm_opp_set_rate(ðqos->pdev->dev, 0); return ret; } + if (ethqos->num_noc_clks) { + ret = clk_bulk_prepare_enable(ethqos->num_noc_clks, + ethqos->noc_clks); + if (ret) { + dev_err(ðqos->pdev->dev, + "NOC clocks enable failed: %d\n", ret); + clk_disable_unprepare(ethqos->link_clk); + dev_pm_opp_set_rate(ðqos->pdev->dev, 0); + return ret; + } + } + /* Enable functional clock to prevent DMA reset to timeout due * to lacking PHY clock after the hardware block has been power * cycled. The actual configuration will be adjusted once @@ -764,7 +813,12 @@ static int ethqos_clks_config(void *priv, bool enabled) qcom_ethqos_set_sgmii_loopback(ethqos, true); ethqos_set_func_clk_en(ethqos); } else { + if (ethqos->num_noc_clks) + clk_bulk_disable_unprepare(ethqos->num_noc_clks, + ethqos->noc_clks); clk_disable_unprepare(ethqos->link_clk); + if (ethqos->num_noc_clks) + dev_pm_opp_set_rate(ðqos->pdev->dev, 0); } return ret; @@ -775,6 +829,51 @@ static void ethqos_clks_disable(void *data) ethqos_clks_config(data, false); } +static void qcom_ethqos_noc_opp_cleanup(void *dev) +{ + dev_pm_opp_set_rate(dev, 0); +} + +/* Some SoCs gate NOC access behind dedicated clocks. Acquire them here + * so ethqos_clks_config() can enable/disable them at runtime. The OPP + * table is used to propagate the required VDD_CX performance state via + * dev_pm_opp_set_rate(). + */ +static int qcom_ethqos_init_noc_clks(struct qcom_ethqos *ethqos, + const struct ethqos_emac_driver_data *data) +{ + struct device *dev = ðqos->pdev->dev; + unsigned int i; + int ret; + + if (!data->num_noc_clks) + return 0; + + for (i = 0; i < data->num_noc_clks; i++) { + ethqos->noc_clks[i].id = data->noc_clk_cfg[i].id; + ethqos->noc_clk_rates[i] = data->noc_clk_cfg[i].rate; + } + ethqos->num_noc_clks = data->num_noc_clks; + + ret = devm_clk_bulk_get(dev, ethqos->num_noc_clks, ethqos->noc_clks); + if (ret) + return dev_err_probe(dev, ret, "Failed to get NOC clocks\n"); + + ret = devm_pm_opp_set_clkname(dev, data->noc_clk_cfg[0].id); + if (ret) + return dev_err_probe(dev, ret, "Failed to set OPP clock name\n"); + + ret = devm_pm_opp_of_add_table(dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to add OPP table\n"); + + ret = dev_pm_opp_set_rate(dev, data->noc_clk_cfg[0].rate); + if (ret) + return dev_err_probe(dev, ret, "Failed to set initial NOC OPP rate\n"); + + return devm_add_action_or_reset(dev, qcom_ethqos_noc_opp_cleanup, dev); +} + static void ethqos_ptp_clk_freq_config(struct stmmac_priv *priv) { struct plat_stmmacenet_data *plat_dat = priv->plat; @@ -974,6 +1073,12 @@ static int qcom_ethqos_probe(struct platform_device *pdev) if (WARN_ON(!data->setup)) return -EINVAL; + if (data->num_noc_clks) { + ret = qcom_ethqos_init_noc_clks(ethqos, data); + if (ret) + return ret; + } + ret = data->setup(ethqos, plat_dat); if (ret) return ret; From 8a5edaf688bd7a33a1b33739c7758647afe05c22 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:04 +0200 Subject: [PATCH 0277/1133] FROMLIST: dmaengine: qcom: bam_dma: free interrupt before the clock in error path The BAM interrupt is requested with a devres helper and so on error it's freed after probe() returns. We disable the clock before freeing or masking it so it may still fire and we may end up reading BAM registers with clock disabled. Stop using devres for interrupts as we free it in remove() manually anyway. Add an appropriate label and free the interrupt before disabling the clock in error path and in remove(). Fixes: e7c0fe2a5c84 ("dmaengine: add Qualcomm BAM dma driver") Closes: https://sashiko.dev/#/patchset/20260427-qcom-qce-cmd-descr-v16-0-945fd1cafbbc%40oss.qualcomm.com?part=2 Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-2-56f67da84c05@oss.qualcomm.com --- drivers/dma/qcom/bam_dma.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index f67a93a37d48c..6847785bd25d8 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -1404,6 +1404,9 @@ static void bam_dma_remove(struct platform_device *pdev) u32 i; pm_runtime_dont_use_autosuspend(&pdev->dev); + + free_irq(bdev->irq, bdev); + pm_runtime_force_suspend(&pdev->dev); of_dma_controller_free(pdev->dev.of_node); From 9c15e9ea93eaab98338ff5fac231596d916b19ed Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:05 +0200 Subject: [PATCH 0278/1133] FROMLIST: dmaengine: qcom: bam_dma: convert tasklet to a BH workqueue BH workqueues are a modern mechanism, aiming to replace legacy tasklets. Let's convert the BAM DMA driver to using the high-priority variant of the BH workqueue. [Vinod: suggested using the BG workqueue instead of the regular one running in process context] Suggested-by: Vinod Koul Reviewed-by: Dmitry Baryshkov Reviewed-by: Bjorn Andersson Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-3-56f67da84c05@oss.qualcomm.com --- drivers/dma/qcom/bam_dma.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 6847785bd25d8..600b6d9361e57 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "../dmaengine.h" #include "../virt-dma.h" @@ -426,8 +427,8 @@ struct bam_device { struct clk *bamclk; int irq; - /* dma start transaction tasklet */ - struct tasklet_struct task; + /* dma start transaction workqueue */ + struct work_struct work; }; /** @@ -892,7 +893,7 @@ static u32 process_channel_irqs(struct bam_device *bdev) /* * if complete, process cookie. Otherwise * push back to front of desc_issued so that - * it gets restarted by the tasklet + * it gets restarted by the work queue. */ if (!async_desc->num_desc) { vchan_cookie_complete(&async_desc->vd); @@ -922,9 +923,9 @@ static irqreturn_t bam_dma_irq(int irq, void *data) srcs |= process_channel_irqs(bdev); - /* kick off tasklet to start next dma transfer */ + /* kick off the work queue to start next dma transfer */ if (srcs & P_IRQ) - tasklet_schedule(&bdev->task); + queue_work(system_bh_highpri_wq, &bdev->work); ret = pm_runtime_get_sync(bdev->dev); if (ret < 0) @@ -1120,14 +1121,14 @@ static void bam_start_dma(struct bam_chan *bchan) } /** - * dma_tasklet - DMA IRQ tasklet - * @t: tasklet argument (bam controller structure) + * bam_dma_work() - DMA interrupt work queue callback + * @work: work queue struct embedded in the BAM controller device struct * * Sets up next DMA operation and then processes all completed transactions */ -static void dma_tasklet(struct tasklet_struct *t) +static void bam_dma_work(struct work_struct *work) { - struct bam_device *bdev = from_tasklet(bdev, t, task); + struct bam_device *bdev = from_work(bdev, work, work); struct bam_chan *bchan; unsigned int i; @@ -1140,14 +1141,13 @@ static void dma_tasklet(struct tasklet_struct *t) if (!list_empty(&bchan->vc.desc_issued) && !IS_BUSY(bchan)) bam_start_dma(bchan); } - } /** * bam_issue_pending - starts pending transactions * @chan: dma channel * - * Calls tasklet directly which in turn starts any pending transactions + * Calls work queue directly which in turn starts any pending transactions */ static void bam_issue_pending(struct dma_chan *chan) { @@ -1316,14 +1316,14 @@ static int bam_dma_probe(struct platform_device *pdev) if (ret) goto err_disable_clk; - tasklet_setup(&bdev->task, dma_tasklet); + INIT_WORK(&bdev->work, bam_dma_work); bdev->channels = devm_kcalloc(bdev->dev, bdev->num_channels, sizeof(*bdev->channels), GFP_KERNEL); if (!bdev->channels) { ret = -ENOMEM; - goto err_tasklet_kill; + goto err_workqueue_cancel; } /* allocate and initialize channels */ @@ -1390,8 +1390,8 @@ static int bam_dma_probe(struct platform_device *pdev) err_bam_channel_exit: for (i = 0; i < bdev->num_channels; i++) tasklet_kill(&bdev->channels[i].vc.task); -err_tasklet_kill: - tasklet_kill(&bdev->task); +err_workqueue_cancel: + cancel_work_sync(&bdev->work); err_disable_clk: clk_disable_unprepare(bdev->bamclk); @@ -1429,7 +1429,7 @@ static void bam_dma_remove(struct platform_device *pdev) bdev->channels[i].fifo_phys); } - tasklet_kill(&bdev->task); + cancel_work_sync(&bdev->work); clk_disable_unprepare(bdev->bamclk); } From c8f2516e2883b41f56d19892c910970ae1b3ca2f Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:06 +0200 Subject: [PATCH 0279/1133] FROMLIST: dmaengine: qcom: bam_dma: Extend the driver's device match data In preparation for supporting the pipe locking feature flag, extend the amount of information we can carry in device match data: create a separate structure and make the register information one of its fields. This way, in subsequent patches, it will be just a matter of adding a new field to the device data. Reviewed-by: Dmitry Baryshkov Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-4-56f67da84c05@oss.qualcomm.com --- drivers/dma/qcom/bam_dma.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 600b6d9361e57..febc78772ee34 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -113,6 +113,10 @@ struct reg_offset_data { unsigned int pipe_mult, evnt_mult, ee_mult; }; +struct bam_device_data { + const struct reg_offset_data *reg_info; +}; + static const struct reg_offset_data bam_v1_3_reg_info[] = { [BAM_CTRL] = { 0x0F80, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x0F84, 0x00, 0x00, 0x00 }, @@ -142,6 +146,10 @@ static const struct reg_offset_data bam_v1_3_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0x1020, 0x00, 0x40, 0x00 }, }; +static const struct bam_device_data bam_v1_3_data = { + .reg_info = bam_v1_3_reg_info, +}; + static const struct reg_offset_data bam_v1_4_reg_info[] = { [BAM_CTRL] = { 0x0000, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x0004, 0x00, 0x00, 0x00 }, @@ -171,6 +179,10 @@ static const struct reg_offset_data bam_v1_4_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0x1820, 0x00, 0x1000, 0x00 }, }; +static const struct bam_device_data bam_v1_4_data = { + .reg_info = bam_v1_4_reg_info, +}; + static const struct reg_offset_data bam_v1_7_reg_info[] = { [BAM_CTRL] = { 0x00000, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x01000, 0x00, 0x00, 0x00 }, @@ -200,6 +212,10 @@ static const struct reg_offset_data bam_v1_7_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0x13820, 0x00, 0x1000, 0x00 }, }; +static const struct bam_device_data bam_v1_7_data = { + .reg_info = bam_v1_7_reg_info, +}; + static const struct reg_offset_data bam_v2_0_reg_info[] = { [BAM_CTRL] = { 0x0000, 0x00, 0x00, 0x00 }, [BAM_REVISION] = { 0x1000, 0x00, 0x00, 0x00 }, @@ -229,6 +245,10 @@ static const struct reg_offset_data bam_v2_0_reg_info[] = { [BAM_P_FIFO_SIZES] = { 0xC820, 0x00, 0x1000, 0x00 }, }; +static const struct bam_device_data bam_v2_0_data = { + .reg_info = bam_v2_0_reg_info, +}; + /* BAM CTRL */ #define BAM_SW_RST BIT(0) #define BAM_EN BIT(1) @@ -422,7 +442,7 @@ struct bam_device { bool powered_remotely; u32 active_channels; - const struct reg_offset_data *layout; + const struct bam_device_data *dev_data; struct clk *bamclk; int irq; @@ -440,7 +460,7 @@ struct bam_device { static inline void __iomem *bam_addr(struct bam_device *bdev, u32 pipe, enum bam_reg reg) { - const struct reg_offset_data r = bdev->layout[reg]; + const struct reg_offset_data r = bdev->dev_data->reg_info[reg]; return bdev->regs + r.base_offset + r.pipe_mult * pipe + @@ -1234,10 +1254,10 @@ static void bam_channel_init(struct bam_device *bdev, struct bam_chan *bchan, } static const struct of_device_id bam_of_match[] = { - { .compatible = "qcom,bam-v1.3.0", .data = &bam_v1_3_reg_info }, - { .compatible = "qcom,bam-v1.4.0", .data = &bam_v1_4_reg_info }, - { .compatible = "qcom,bam-v1.7.0", .data = &bam_v1_7_reg_info }, - { .compatible = "qcom,bam-v2.0.0", .data = &bam_v2_0_reg_info }, + { .compatible = "qcom,bam-v1.3.0", .data = &bam_v1_3_data }, + { .compatible = "qcom,bam-v1.4.0", .data = &bam_v1_4_data }, + { .compatible = "qcom,bam-v1.7.0", .data = &bam_v1_7_data }, + { .compatible = "qcom,bam-v2.0.0", .data = &bam_v2_0_data }, {} }; @@ -1261,7 +1281,7 @@ static int bam_dma_probe(struct platform_device *pdev) return -ENODEV; } - bdev->layout = match->data; + bdev->dev_data = match->data; bdev->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(bdev->regs)) From 926dd7f1ac798f76af23a19711901878d8b4601f Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:07 +0200 Subject: [PATCH 0280/1133] FROMLIST: dmaengine: qcom: bam_dma: Add pipe_lock_supported flag support Extend the device match data with a flag indicating whether the IP supports the BAM lock/unlock feature. Set it to true on BAM IP versions 1.4.0 and above. Signed-off-by: Bartosz Golaszewski Reviewed-by: Dmitry Baryshkov Acked-by: Manivannan Sadhasivam Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-5-56f67da84c05@oss.qualcomm.com --- drivers/dma/qcom/bam_dma.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index febc78772ee34..bb24b538fec77 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -115,6 +115,7 @@ struct reg_offset_data { struct bam_device_data { const struct reg_offset_data *reg_info; + bool pipe_lock_supported; }; static const struct reg_offset_data bam_v1_3_reg_info[] = { @@ -181,6 +182,7 @@ static const struct reg_offset_data bam_v1_4_reg_info[] = { static const struct bam_device_data bam_v1_4_data = { .reg_info = bam_v1_4_reg_info, + .pipe_lock_supported = true, }; static const struct reg_offset_data bam_v1_7_reg_info[] = { @@ -214,6 +216,7 @@ static const struct reg_offset_data bam_v1_7_reg_info[] = { static const struct bam_device_data bam_v1_7_data = { .reg_info = bam_v1_7_reg_info, + .pipe_lock_supported = true, }; static const struct reg_offset_data bam_v2_0_reg_info[] = { @@ -247,6 +250,7 @@ static const struct reg_offset_data bam_v2_0_reg_info[] = { static const struct bam_device_data bam_v2_0_data = { .reg_info = bam_v2_0_reg_info, + .pipe_lock_supported = true, }; /* BAM CTRL */ From 2ba3a9ac01c8c7d18ddc27b99de189341b13414e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:08 +0200 Subject: [PATCH 0281/1133] FROMLIST: dmaengine: qcom: bam_dma: add support for BAM locking Add support for BAM pipe locking. To that end: when starting DMA on an RX channel - prepend the existing queue of issued descriptors with an additional "dummy" command descriptor with the LOCK bit set. Once the transaction is done (no more issued descriptors), issue one more dummy descriptor with the UNLOCK bit. We *must* wait until the transaction is signalled as done because we must not perform any writes into config registers while the engine is busy. The dummy writes must be issued into a scratchpad register of the client so provide a mechanism to communicate the right address via descriptor metadata. Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-6-56f67da84c05@oss.qualcomm.com --- drivers/dma/qcom/bam_dma.c | 189 +++++++++++++++++++++++++++++-- include/linux/dma/qcom_bam_dma.h | 14 +++ 2 files changed, 196 insertions(+), 7 deletions(-) diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index bb24b538fec77..aaa282cb2b7b6 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -28,11 +28,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -60,6 +62,8 @@ struct bam_desc_hw { #define DESC_FLAG_EOB BIT(13) #define DESC_FLAG_NWD BIT(12) #define DESC_FLAG_CMD BIT(11) +#define DESC_FLAG_LOCK BIT(10) +#define DESC_FLAG_UNLOCK BIT(9) struct bam_async_desc { struct virt_dma_desc vd; @@ -72,6 +76,10 @@ struct bam_async_desc { struct bam_desc_hw *curr_desc; + /* BAM locking infrastructure */ + struct scatterlist lock_sg; + struct bam_cmd_element lock_ce; + /* list node for the desc in the bam_chan list of descriptors */ struct list_head desc_node; enum dma_transfer_direction dir; @@ -425,6 +433,11 @@ struct bam_chan { struct list_head desc_list; struct list_head node; + + /* BAM locking infrastructure */ + phys_addr_t scratchpad_addr; + enum dma_transfer_direction direction; + bool bam_locked; }; static inline struct bam_chan *to_bam_chan(struct dma_chan *common) @@ -638,8 +651,10 @@ static void bam_free_chan(struct dma_chan *chan) goto err; } - scoped_guard(spinlock_irqsave, &bchan->vc.lock) + scoped_guard(spinlock_irqsave, &bchan->vc.lock) { bam_reset_channel(bchan); + bchan->bam_locked = false; + } dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, bchan->fifo_virt, bchan->fifo_phys); @@ -686,6 +701,35 @@ static int bam_slave_config(struct dma_chan *chan, return 0; } +static int bam_metadata_attach(struct dma_async_tx_descriptor *desc, void *data, size_t len) +{ + struct bam_chan *bchan = to_bam_chan(desc->chan); + const struct bam_device_data *bdata = bchan->bdev->dev_data; + struct bam_desc_metadata *metadata = data; + + if (!data) + return -EINVAL; + + if (!bdata->pipe_lock_supported) + /* + * The client wants to use locking but this BAM version doesn't + * support it. Don't return an error here as this will stop the + * client from using DMA at all for no reason. + */ + return 0; + + guard(spinlock_irqsave)(&bchan->vc.lock); + + bchan->scratchpad_addr = metadata->scratchpad_addr; + bchan->direction = metadata->direction; + + return 0; +} + +static const struct dma_descriptor_metadata_ops bam_metadata_ops = { + .attach = bam_metadata_attach, +}; + /** * bam_prep_slave_sg - Prep slave sg transaction * @@ -702,6 +746,7 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, void *context) { struct bam_chan *bchan = to_bam_chan(chan); + struct dma_async_tx_descriptor *tx_desc; struct bam_device *bdev = bchan->bdev; struct bam_async_desc *async_desc; struct scatterlist *sg; @@ -757,7 +802,10 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, } while (remainder > 0); } - return vchan_tx_prep(&bchan->vc, &async_desc->vd, flags); + tx_desc = vchan_tx_prep(&bchan->vc, &async_desc->vd, flags); + tx_desc->metadata_ops = &bam_metadata_ops; + + return tx_desc; } /** @@ -802,6 +850,7 @@ static int bam_dma_terminate_all(struct dma_chan *chan) } vchan_get_all_descriptors(&bchan->vc, &head); + bchan->bam_locked = false; } vchan_dma_desc_free_list(&bchan->vc, &head); @@ -859,6 +908,15 @@ static int bam_resume(struct dma_chan *chan) return 0; } +static void bam_dma_free_lock_desc(struct virt_dma_desc *vd) +{ + struct bam_async_desc *async_desc = container_of(vd, struct bam_async_desc, vd); + struct dma_chan *chan = vd->tx.chan; + + dma_unmap_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE); + kfree(async_desc); +} + /** * process_channel_irqs - processes the channel interrupts * @bdev: bam controller @@ -919,13 +977,23 @@ static u32 process_channel_irqs(struct bam_device *bdev) * push back to front of desc_issued so that * it gets restarted by the work queue. */ + + list_del(&async_desc->desc_node); if (!async_desc->num_desc) { - vchan_cookie_complete(&async_desc->vd); + struct bam_desc_hw *hdesc = async_desc->desc; + u16 flags = le16_to_cpu(hdesc->flags); + + if (flags & (DESC_FLAG_LOCK | DESC_FLAG_UNLOCK)) { + if (flags & DESC_FLAG_UNLOCK) + bchan->bam_locked = false; + bam_dma_free_lock_desc(&async_desc->vd); + } else { + vchan_cookie_complete(&async_desc->vd); + } } else { list_add(&async_desc->vd.node, &bchan->vc.desc_issued); } - list_del(&async_desc->desc_node); } } @@ -1046,13 +1114,101 @@ static void bam_apply_new_config(struct bam_chan *bchan, bchan->reconfigure = 0; } +static struct bam_async_desc * +bam_make_lock_desc(struct bam_chan *bchan, unsigned long flag) +{ + struct dma_chan *chan = &bchan->vc.chan; + struct bam_async_desc *async_desc; + struct bam_desc_hw *desc; + struct virt_dma_desc *vd; + struct virt_dma_chan *vc; + unsigned int mapped; + + async_desc = kzalloc_flex(*async_desc, desc, 1, GFP_NOWAIT); + if (!async_desc) { + dev_err(bchan->bdev->dev, "failed to allocate the BAM lock descriptor\n"); + return ERR_PTR(-ENOMEM); + } + + sg_init_table(&async_desc->lock_sg, 1); + + async_desc->num_desc = 1; + async_desc->curr_desc = async_desc->desc; + async_desc->dir = DMA_MEM_TO_DEV; + + desc = async_desc->desc; + + bam_prep_ce_le32(&async_desc->lock_ce, bchan->scratchpad_addr, BAM_WRITE_COMMAND, 0); + sg_set_buf(&async_desc->lock_sg, &async_desc->lock_ce, sizeof(async_desc->lock_ce)); + + mapped = dma_map_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE); + if (!mapped) { + kfree(async_desc); + return ERR_PTR(-ENOMEM); + } + + desc->flags |= cpu_to_le16(DESC_FLAG_CMD | flag); + desc->addr = sg_dma_address(&async_desc->lock_sg); + desc->size = cpu_to_le16(sizeof(struct bam_cmd_element)); + + vc = &bchan->vc; + vd = &async_desc->vd; + + dma_async_tx_descriptor_init(&vd->tx, &vc->chan); + vd->tx.flags = DMA_PREP_CMD; + vd->tx_result.result = DMA_TRANS_NOERROR; + vd->tx_result.residue = 0; + + return async_desc; +} + +static int bam_setup_pipe_lock(struct bam_chan *bchan) +{ + const struct bam_device_data *bdata = bchan->bdev->dev_data; + struct bam_async_desc *lock_desc, *unlock_desc; + + lockdep_assert_held(&bchan->vc.lock); + + if (!bdata->pipe_lock_supported || !bchan->scratchpad_addr || + bchan->direction != DMA_MEM_TO_DEV) + return 0; + + /* + * Allocate both the LOCK and the UNLOCK descriptors up-front so the + * operation is all-or-nothing: if either allocation fails we free both + * and run the sequence unlocked rather than leave the pipe locked with + * no matching UNLOCK. + * + * Both are queued in-band around the currently issued work: the LOCK is + * prepended so it enters the FIFO first, the UNLOCK is appended so it is + * the last descriptor of the sequence. They are loaded together with the + * payload in a single operation so the engine executes LOCK, the work + * and UNLOCK as one ordered batch. + */ + lock_desc = bam_make_lock_desc(bchan, DESC_FLAG_LOCK); + if (IS_ERR(lock_desc)) + return PTR_ERR(lock_desc); + + unlock_desc = bam_make_lock_desc(bchan, DESC_FLAG_UNLOCK); + if (IS_ERR(unlock_desc)) { + bam_dma_free_lock_desc(&lock_desc->vd); + return PTR_ERR(unlock_desc); + } + + list_add(&lock_desc->vd.node, &bchan->vc.desc_issued); + list_add_tail(&unlock_desc->vd.node, &bchan->vc.desc_issued); + bchan->bam_locked = true; + + return 0; +} + /** * bam_start_dma - start next transaction * @bchan: bam dma channel */ static void bam_start_dma(struct bam_chan *bchan) { - struct virt_dma_desc *vd = vchan_next_desc(&bchan->vc); + struct virt_dma_desc *vd; struct bam_device *bdev = bchan->bdev; struct bam_async_desc *async_desc = NULL; struct bam_desc_hw *desc; @@ -1064,9 +1220,23 @@ static void bam_start_dma(struct bam_chan *bchan) lockdep_assert_held(&bchan->vc.lock); + vd = vchan_next_desc(&bchan->vc); if (!vd) return; + /* + * Wrap the issued work with a LOCK/UNLOCK pair exactly once, at the + * start of a fresh sequence and only when there is real work to lock + * around. On a re-entry after a full FIFO, we see the BAM is locked + * and must not add another pair we simply continue loading the + * remainder of the same locked sequence. + */ + if (!bchan->bam_locked) { + ret = bam_setup_pipe_lock(bchan); + if (ret == 0 && bchan->bam_locked) + vd = vchan_next_desc(&bchan->vc); + } + ret = pm_runtime_get_sync(bdev->dev); if (ret < 0) return; @@ -1191,8 +1361,12 @@ static void bam_issue_pending(struct dma_chan *chan) */ static void bam_dma_free_desc(struct virt_dma_desc *vd) { - struct bam_async_desc *async_desc = container_of(vd, - struct bam_async_desc, vd); + struct bam_async_desc *async_desc = container_of(vd, struct bam_async_desc, vd); + struct bam_desc_hw *desc = async_desc->desc; + struct dma_chan *chan = vd->tx.chan; + + if (le16_to_cpu(desc->flags) & (DESC_FLAG_LOCK | DESC_FLAG_UNLOCK)) + dma_unmap_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE); kfree(async_desc); } @@ -1385,6 +1559,7 @@ static int bam_dma_probe(struct platform_device *pdev) bdev->common.device_terminate_all = bam_dma_terminate_all; bdev->common.device_issue_pending = bam_issue_pending; bdev->common.device_tx_status = bam_tx_status; + bdev->common.desc_metadata_modes = DESC_METADATA_CLIENT; bdev->common.dev = bdev->dev; ret = dma_async_device_register(&bdev->common); diff --git a/include/linux/dma/qcom_bam_dma.h b/include/linux/dma/qcom_bam_dma.h index d9d07a9ab3132..728500f6555b9 100644 --- a/include/linux/dma/qcom_bam_dma.h +++ b/include/linux/dma/qcom_bam_dma.h @@ -6,6 +6,8 @@ #ifndef _QCOM_BAM_DMA_H #define _QCOM_BAM_DMA_H +#include + #include /* @@ -37,6 +39,18 @@ enum bam_command_type { BAM_READ_COMMAND, }; +/** + * struct bam_desc_metadata - DMA descriptor metadata specific to the BAM driver. + * + * @scratchpad_addr: Physical address to use for dummy write operations when + * queuing command descriptors with LOCK/UNLOCK bits set. + * @direction: Transfer direction of this channel. + */ +struct bam_desc_metadata { + phys_addr_t scratchpad_addr; + enum dma_transfer_direction direction; +}; + /* * prep_bam_ce_le32 - Wrapper function to prepare a single BAM command * element with the data already in le32 format. From 4e87c9c3ccfcbc0326f4bbe88c037df1e37ce45c Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:09 +0200 Subject: [PATCH 0282/1133] FROMLIST: crypto: qce - Cancel work on device detach The workqueue is setup in probe() but never cancelled on error or in remove(). Set up a devres action to clean it up. We need to move the initialization earlier as we don't want to cancel the work before any outstanding DMA transfer is terminated. Make sure we do terminate all transfers in qce_dma_release() devres action. Fixes: eb7986e5e14d ("crypto: qce - convert tasklet to workqueue") Closes: https://sashiko.dev/#/patchset/20260427-qcom-qce-cmd-descr-v16-0-945fd1cafbbc%40oss.qualcomm.com?part=7 Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-7-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/core.c | 13 ++++++++++++- drivers/crypto/qce/dma.c | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index bf3c1bc3ba7bd..fab276f260b1b 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -190,6 +190,13 @@ static int qce_check_version(struct qce_device *qce) return 0; } +static void qce_cancel_work(void *data) +{ + struct work_struct *work = data; + + cancel_work_sync(work); +} + static int qce_crypto_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -241,6 +248,11 @@ static int qce_crypto_probe(struct platform_device *pdev) if (ret) return ret; + INIT_WORK(&qce->done_work, qce_req_done_work); + ret = devm_add_action_or_reset(dev, qce_cancel_work, &qce->done_work); + if (ret) + return ret; + ret = devm_qce_dma_request(qce->dev, &qce->dma); if (ret) return ret; @@ -253,7 +265,6 @@ static int qce_crypto_probe(struct platform_device *pdev) if (ret) return ret; - INIT_WORK(&qce->done_work, qce_req_done_work); crypto_init_queue(&qce->queue, QCE_QUEUE_LENGTH); qce->async_req_enqueue = qce_async_request_enqueue; diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index 68cafd4741ad3..7ec9d72fd690f 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -13,6 +13,8 @@ static void qce_dma_release(void *data) { struct qce_dma_data *dma = data; + dmaengine_terminate_sync(dma->txchan); + dmaengine_terminate_sync(dma->rxchan); dma_release_channel(dma->txchan); dma_release_channel(dma->rxchan); kfree(dma->result_buf); From 96d8e2e130f2de2cf550160d09f1b112b9772b07 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:10 +0200 Subject: [PATCH 0283/1133] FROMLIST: crypto: qce - Include algapi.h in the core.h header The header defines a struct embedding struct crypto_queue whose size needs to be known and which is defined in crypto/algapi.h. Move the inclusion from core.c to core.h. Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-8-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/core.c | 1 - drivers/crypto/qce/core.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index fab276f260b1b..1076d397dd523 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include "core.h" diff --git a/drivers/crypto/qce/core.h b/drivers/crypto/qce/core.h index eb6fa7a8b64a8..f092ce2d3b04a 100644 --- a/drivers/crypto/qce/core.h +++ b/drivers/crypto/qce/core.h @@ -8,6 +8,7 @@ #include #include +#include #include "dma.h" From 81f13f02e005aecf000ed1c4b47994641f43bd1c Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:11 +0200 Subject: [PATCH 0284/1133] FROMLIST: crypto: qce - Remove unused ignore_buf It's unclear what the purpose of this field is. It has been here since the initial commit but without any explanation. The driver works fine without it. We still keep allocating more space in the result buffer, we just don't need to store its address. While at it: move the QCE_IGNORE_BUF_SZ definition into dma.c as it's not used outside of this compilation unit. Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-9-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/dma.c | 4 ++-- drivers/crypto/qce/dma.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index 7ec9d72fd690f..d1daa229361aa 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -9,6 +9,8 @@ #include "dma.h" +#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) + static void qce_dma_release(void *data) { struct qce_dma_data *dma = data; @@ -43,8 +45,6 @@ int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma) goto error_nomem; } - dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ; - return devm_add_action_or_reset(dev, qce_dma_release, dma); error_nomem: diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h index 31629185000e1..fc337c435cd14 100644 --- a/drivers/crypto/qce/dma.h +++ b/drivers/crypto/qce/dma.h @@ -23,7 +23,6 @@ struct qce_result_dump { u32 status2; }; -#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) #define QCE_RESULT_BUF_SZ \ ALIGN(sizeof(struct qce_result_dump), QCE_BAM_BURST_SIZE) @@ -31,7 +30,6 @@ struct qce_dma_data { struct dma_chan *txchan; struct dma_chan *rxchan; struct qce_result_dump *result_buf; - void *ignore_buf; }; int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma); From 8234d5af1f2e9086a50fecc7757b07cc55b6e4fd Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:12 +0200 Subject: [PATCH 0285/1133] FROMLIST: crypto: qce - Simplify arguments of devm_qce_dma_request() This function can extract all the information it needs from struct qce_device alone so simplify its arguments. This is done in preparation for adding support for register I/O over DMA which will require accessing even more fields from struct qce_device. Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-10-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/core.c | 2 +- drivers/crypto/qce/dma.c | 5 ++++- drivers/crypto/qce/dma.h | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index 1076d397dd523..db29b4d92af7e 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -252,7 +252,7 @@ static int qce_crypto_probe(struct platform_device *pdev) if (ret) return ret; - ret = devm_qce_dma_request(qce->dev, &qce->dma); + ret = devm_qce_dma_request(qce); if (ret) return ret; diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index d1daa229361aa..d60efb5c26d88 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -7,6 +7,7 @@ #include #include +#include "core.h" #include "dma.h" #define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) @@ -22,8 +23,10 @@ static void qce_dma_release(void *data) kfree(dma->result_buf); } -int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma) +int devm_qce_dma_request(struct qce_device *qce) { + struct qce_dma_data *dma = &qce->dma; + struct device *dev = qce->dev; int ret; dma->txchan = dma_request_chan(dev, "tx"); diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h index fc337c435cd14..483789d9fa98e 100644 --- a/drivers/crypto/qce/dma.h +++ b/drivers/crypto/qce/dma.h @@ -8,6 +8,8 @@ #include +struct qce_device; + /* maximum data transfer block size between BAM and CE */ #define QCE_BAM_BURST_SIZE 64 @@ -32,7 +34,7 @@ struct qce_dma_data { struct qce_result_dump *result_buf; }; -int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma); +int devm_qce_dma_request(struct qce_device *qce); int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *sg_in, int in_ents, struct scatterlist *sg_out, int out_ents, dma_async_tx_callback cb, void *cb_param); From 7062e51f6f88931af84eff4f97e7b4c933b0a794 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:13 +0200 Subject: [PATCH 0286/1133] FROMLIST: crypto: qce - Use existing devres APIs in devm_qce_dma_request() Switch to devm_kmalloc() and devm_dma_alloc_chan() in devm_qce_dma_request(). This allows us to drop two labels and shrink the function. Signed-off-by: Bartosz Golaszewski Reviewed-by: Konrad Dybcio Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-11-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/dma.c | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index d60efb5c26d88..26347e9fc078a 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -12,49 +12,34 @@ #define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) -static void qce_dma_release(void *data) +static void qce_dma_terminate(void *data) { struct qce_dma_data *dma = data; dmaengine_terminate_sync(dma->txchan); dmaengine_terminate_sync(dma->rxchan); - dma_release_channel(dma->txchan); - dma_release_channel(dma->rxchan); - kfree(dma->result_buf); } int devm_qce_dma_request(struct qce_device *qce) { struct qce_dma_data *dma = &qce->dma; struct device *dev = qce->dev; - int ret; - dma->txchan = dma_request_chan(dev, "tx"); + dma->result_buf = devm_kmalloc(dev, QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ, GFP_KERNEL); + if (!dma->result_buf) + return -ENOMEM; + + dma->txchan = devm_dma_request_chan(dev, "tx"); if (IS_ERR(dma->txchan)) return dev_err_probe(dev, PTR_ERR(dma->txchan), "Failed to get TX DMA channel\n"); - dma->rxchan = dma_request_chan(dev, "rx"); - if (IS_ERR(dma->rxchan)) { - ret = dev_err_probe(dev, PTR_ERR(dma->rxchan), - "Failed to get RX DMA channel\n"); - goto error_rx; - } - - dma->result_buf = kmalloc(QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ, - GFP_KERNEL); - if (!dma->result_buf) { - ret = -ENOMEM; - goto error_nomem; - } - - return devm_add_action_or_reset(dev, qce_dma_release, dma); + dma->rxchan = devm_dma_request_chan(dev, "rx"); + if (IS_ERR(dma->rxchan)) + return dev_err_probe(dev, PTR_ERR(dma->rxchan), + "Failed to get RX DMA channel\n"); -error_nomem: - dma_release_channel(dma->rxchan); -error_rx: - dma_release_channel(dma->txchan); - return ret; + return devm_add_action_or_reset(dev, qce_dma_terminate, dma); } struct scatterlist * From 345bb04ad8eaa5246aee10cbcf82ce588895d08a Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:14 +0200 Subject: [PATCH 0287/1133] FROMLIST: crypto: qce - Map crypto memory for DMA As the first step in converting the driver to using DMA for register I/O, let's map the crypto memory range. Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-12-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/core.c | 25 +++++++++++++++++++++++-- drivers/crypto/qce/core.h | 6 ++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index db29b4d92af7e..a2b739c663877 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -196,10 +196,19 @@ static void qce_cancel_work(void *data) cancel_work_sync(work); } +static void qce_crypto_unmap_dma(void *data) +{ + struct qce_device *qce = data; + + dma_unmap_resource(qce->dev, qce->base_dma, qce->dma_size, + DMA_BIDIRECTIONAL, 0); +} + static int qce_crypto_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct qce_device *qce; + struct resource *res; int ret; qce = devm_kzalloc(dev, sizeof(*qce), GFP_KERNEL); @@ -209,7 +218,7 @@ static int qce_crypto_probe(struct platform_device *pdev) qce->dev = dev; platform_set_drvdata(pdev, qce); - qce->base = devm_platform_ioremap_resource(pdev, 0); + qce->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(qce->base)) return PTR_ERR(qce->base); @@ -278,7 +287,19 @@ static int qce_crypto_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(dev); pm_runtime_mark_last_busy(dev); - return 0; + qce->dma_size = resource_size(res); + qce->base_dma = dma_map_resource(dev, res->start, qce->dma_size, + DMA_BIDIRECTIONAL, 0); + qce->base_phys = res->start; + ret = dma_mapping_error(dev, qce->base_dma); + if (ret) + return ret; + + ret = devm_add_action_or_reset(qce->dev, qce_crypto_unmap_dma, qce); + if (ret) + return ret; + + return devm_qce_register_algs(qce); } static int qce_runtime_suspend(struct device *dev) diff --git a/drivers/crypto/qce/core.h b/drivers/crypto/qce/core.h index f092ce2d3b04a..a80e12eac6c87 100644 --- a/drivers/crypto/qce/core.h +++ b/drivers/crypto/qce/core.h @@ -27,6 +27,9 @@ * @dma: pointer to dma data * @burst_size: the crypto burst size * @pipe_pair_id: which pipe pair id the device using + * @base_dma: base DMA address + * @base_phys: base physical address + * @dma_size: size of memory mapped for DMA * @async_req_enqueue: invoked by every algorithm to enqueue a request * @async_req_done: invoked by every algorithm to finish its request */ @@ -43,6 +46,9 @@ struct qce_device { struct qce_dma_data dma; int burst_size; unsigned int pipe_pair_id; + dma_addr_t base_dma; + phys_addr_t base_phys; + size_t dma_size; int (*async_req_enqueue)(struct qce_device *qce, struct crypto_async_request *req); void (*async_req_done)(struct qce_device *qce, int ret); From 210e95fdef817fa598d622f44504c46d1b066336 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:15 +0200 Subject: [PATCH 0288/1133] FROMLIST: crypto: qce - Add BAM DMA support for crypto register I/O Switch to using BAM DMA for register I/O in addition to passing data. To that end: provide the necessary infrastructure in the driver, modify the ordering of operations as required and replace all direct register writes with wrappers queueing DMA command descriptors. Signed-off-by: Bartosz Golaszewski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-13-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/aead.c | 10 +-- drivers/crypto/qce/common.c | 20 +++--- drivers/crypto/qce/dma.c | 120 ++++++++++++++++++++++++++++++++-- drivers/crypto/qce/dma.h | 5 ++ drivers/crypto/qce/sha.c | 10 +-- drivers/crypto/qce/skcipher.c | 10 +-- 6 files changed, 144 insertions(+), 31 deletions(-) diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index e0061bfab2168..5f2736f09746f 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -461,17 +461,17 @@ qce_aead_async_req_handle(struct crypto_async_request *async_req) src_nents = dst_nents - 1; } - ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, rctx->dst_sg, dst_nents, - qce_aead_done, async_req); + ret = qce_start(async_req, tmpl->crypto_alg_type); if (ret) goto error_unmap_src; - qce_dma_issue_pending(&qce->dma); - - ret = qce_start(async_req, tmpl->crypto_alg_type); + ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, rctx->dst_sg, dst_nents, + qce_aead_done, async_req); if (ret) goto error_terminate; + qce_dma_issue_pending(&qce->dma); + return 0; error_terminate: diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c index 3081d765a0f2c..5930933412e94 100644 --- a/drivers/crypto/qce/common.c +++ b/drivers/crypto/qce/common.c @@ -24,7 +24,7 @@ static inline u32 qce_read(struct qce_device *qce, u32 offset) static inline void qce_write(struct qce_device *qce, u32 offset, u32 val) { - writel(val, qce->base + offset); + qce_write_dma(qce, offset, val); } static inline void qce_write_array(struct qce_device *qce, u32 offset, @@ -81,6 +81,8 @@ static void qce_setup_config(struct qce_device *qce) { u32 config; + qce_clear_bam_transaction(qce); + /* get big endianness */ config = qce_config_reg(qce, 0); @@ -89,12 +91,14 @@ static void qce_setup_config(struct qce_device *qce) qce_write(qce, REG_CONFIG, config); } -static inline void qce_crypto_go(struct qce_device *qce, bool result_dump) +static inline int qce_crypto_go(struct qce_device *qce, bool result_dump) { if (result_dump) qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); else qce_write(qce, REG_GOPROC, BIT(GO_SHIFT)); + + return qce_submit_cmd_desc(qce); } #if defined(CONFIG_CRYPTO_DEV_QCE_SHA) || defined(CONFIG_CRYPTO_DEV_QCE_AEAD) @@ -220,9 +224,7 @@ static int qce_setup_regs_ahash(struct crypto_async_request *async_req) config = qce_config_reg(qce, 1); qce_write(qce, REG_CONFIG, config); - qce_crypto_go(qce, true); - - return 0; + return qce_crypto_go(qce, true); } #endif @@ -364,9 +366,7 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) config = qce_config_reg(qce, 1); qce_write(qce, REG_CONFIG, config); - qce_crypto_go(qce, true); - - return 0; + return qce_crypto_go(qce, true); } #endif @@ -504,9 +504,7 @@ static int qce_setup_regs_aead(struct crypto_async_request *async_req) qce_write(qce, REG_CONFIG, config); /* Start the process */ - qce_crypto_go(qce, !IS_CCM(flags)); - - return 0; + return qce_crypto_go(qce, !IS_CCM(flags)); } #endif diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index 26347e9fc078a..1b43c56503334 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -4,6 +4,8 @@ */ #include +#include +#include #include #include @@ -11,6 +13,96 @@ #include "dma.h" #define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) +#define QCE_BAM_CMD_SGL_SIZE 128 +#define QCE_BAM_CMD_ELEMENT_SIZE 128 + +struct qce_desc_info { + struct dma_async_tx_descriptor *dma_desc; + enum dma_data_direction dir; +}; + +struct qce_bam_transaction { + struct bam_cmd_element bam_ce[QCE_BAM_CMD_ELEMENT_SIZE]; + struct scatterlist wr_sgl[QCE_BAM_CMD_SGL_SIZE]; + struct qce_desc_info *desc; + u32 bam_ce_idx; + u32 pre_bam_ce_idx; + u32 wr_sgl_cnt; +}; + +void qce_clear_bam_transaction(struct qce_device *qce) +{ + struct qce_bam_transaction *bam_txn = qce->dma.bam_txn; + + bam_txn->bam_ce_idx = 0; + bam_txn->wr_sgl_cnt = 0; + bam_txn->pre_bam_ce_idx = 0; +} + +int qce_submit_cmd_desc(struct qce_device *qce) +{ + struct qce_desc_info *qce_desc = qce->dma.bam_txn->desc; + struct qce_bam_transaction *bam_txn = qce->dma.bam_txn; + struct dma_async_tx_descriptor *dma_desc; + struct dma_chan *chan = qce->dma.rxchan; + unsigned long attrs = DMA_PREP_CMD; + dma_cookie_t cookie; + unsigned int mapped; + int ret; + + mapped = dma_map_sg(qce->dev, bam_txn->wr_sgl, bam_txn->wr_sgl_cnt, DMA_TO_DEVICE); + if (!mapped) + return -ENOMEM; + + dma_desc = dmaengine_prep_slave_sg(chan, bam_txn->wr_sgl, mapped, DMA_MEM_TO_DEV, attrs); + if (!dma_desc) { + ret = -ENOMEM; + goto err_unmap_sg; + } + + qce_desc->dma_desc = dma_desc; + cookie = dmaengine_submit(qce_desc->dma_desc); + + ret = dma_submit_error(cookie); + if (ret) + goto err_unmap_sg; + + return 0; + +err_unmap_sg: + dma_unmap_sg(qce->dev, bam_txn->wr_sgl, bam_txn->wr_sgl_cnt, DMA_TO_DEVICE); + return ret; +} + +static void qce_prep_dma_cmd_desc(struct qce_device *qce, struct qce_dma_data *dma, + unsigned int addr, void *buf) +{ + struct qce_bam_transaction *bam_txn = dma->bam_txn; + struct bam_cmd_element *bam_ce_buf; + int bam_ce_size, cnt, idx; + + idx = bam_txn->bam_ce_idx; + bam_ce_buf = &bam_txn->bam_ce[idx]; + bam_prep_ce_le32(bam_ce_buf, addr, BAM_WRITE_COMMAND, *((__le32 *)buf)); + + bam_ce_buf = &bam_txn->bam_ce[bam_txn->pre_bam_ce_idx]; + bam_txn->bam_ce_idx++; + bam_ce_size = (bam_txn->bam_ce_idx - bam_txn->pre_bam_ce_idx) * sizeof(*bam_ce_buf); + + cnt = bam_txn->wr_sgl_cnt; + + sg_set_buf(&bam_txn->wr_sgl[cnt], bam_ce_buf, bam_ce_size); + + ++bam_txn->wr_sgl_cnt; + bam_txn->pre_bam_ce_idx = bam_txn->bam_ce_idx; +} + +void qce_write_dma(struct qce_device *qce, unsigned int offset, u32 val) +{ + unsigned int reg_addr = ((unsigned int)(qce->base_phys) + offset); + + qce_prep_dma_cmd_desc(qce, &qce->dma, reg_addr, &val); +} static void qce_dma_terminate(void *data) { @@ -39,6 +131,16 @@ int devm_qce_dma_request(struct qce_device *qce) return dev_err_probe(dev, PTR_ERR(dma->rxchan), "Failed to get RX DMA channel\n"); + dma->bam_txn = devm_kzalloc(dev, sizeof(*dma->bam_txn), GFP_KERNEL); + if (!dma->bam_txn) + return -ENOMEM; + + dma->bam_txn->desc = devm_kzalloc(dev, sizeof(*dma->bam_txn->desc), GFP_KERNEL); + if (!dma->bam_txn->desc) + return -ENOMEM; + + sg_init_table(dma->bam_txn->wr_sgl, QCE_BAM_CMD_SGL_SIZE); + return devm_add_action_or_reset(dev, qce_dma_terminate, dma); } @@ -98,28 +200,36 @@ int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *rx_sg, { struct dma_chan *rxchan = dma->rxchan; struct dma_chan *txchan = dma->txchan; - unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; + unsigned long txflags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; + unsigned long rxflags = txflags | DMA_PREP_FENCE; int ret; - ret = qce_dma_prep_sg(rxchan, rx_sg, rx_nents, flags, DMA_MEM_TO_DEV, + ret = qce_dma_prep_sg(rxchan, rx_sg, rx_nents, rxflags, DMA_MEM_TO_DEV, NULL, NULL); if (ret) return ret; - return qce_dma_prep_sg(txchan, tx_sg, tx_nents, flags, DMA_DEV_TO_MEM, + return qce_dma_prep_sg(txchan, tx_sg, tx_nents, txflags, DMA_DEV_TO_MEM, cb, cb_param); } void qce_dma_issue_pending(struct qce_dma_data *dma) { - dma_async_issue_pending(dma->rxchan); dma_async_issue_pending(dma->txchan); + dma_async_issue_pending(dma->rxchan); } int qce_dma_terminate_all(struct qce_dma_data *dma) { + struct qce_device *qce = container_of(dma, struct qce_device, dma); + struct qce_bam_transaction *bam_txn = dma->bam_txn; int ret; ret = dmaengine_terminate_all(dma->rxchan); - return ret ?: dmaengine_terminate_all(dma->txchan); + if (ret) + return ret; + + dma_unmap_sg(qce->dev, bam_txn->wr_sgl, bam_txn->wr_sgl_cnt, DMA_TO_DEVICE); + + return dmaengine_terminate_all(dma->txchan); } diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h index 483789d9fa98e..f05dfa9e6b25b 100644 --- a/drivers/crypto/qce/dma.h +++ b/drivers/crypto/qce/dma.h @@ -8,6 +8,7 @@ #include +struct qce_bam_transaction; struct qce_device; /* maximum data transfer block size between BAM and CE */ @@ -32,6 +33,7 @@ struct qce_dma_data { struct dma_chan *txchan; struct dma_chan *rxchan; struct qce_result_dump *result_buf; + struct qce_bam_transaction *bam_txn; }; int devm_qce_dma_request(struct qce_device *qce); @@ -43,5 +45,8 @@ int qce_dma_terminate_all(struct qce_dma_data *dma); struct scatterlist * qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, unsigned int max_len); +void qce_write_dma(struct qce_device *qce, unsigned int offset, u32 val); +int qce_submit_cmd_desc(struct qce_device *qce); +void qce_clear_bam_transaction(struct qce_device *qce); #endif /* _DMA_H_ */ diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c index b67d749db05f2..ced9c8596fc6b 100644 --- a/drivers/crypto/qce/sha.c +++ b/drivers/crypto/qce/sha.c @@ -105,17 +105,17 @@ static int qce_ahash_async_req_handle(struct crypto_async_request *async_req) goto error_unmap_src; } - ret = qce_dma_prep_sgs(&qce->dma, req->src, rctx->src_nents, - &rctx->result_sg, 1, qce_ahash_done, async_req); + ret = qce_start(async_req, tmpl->crypto_alg_type); if (ret) goto error_unmap_dst; - qce_dma_issue_pending(&qce->dma); - - ret = qce_start(async_req, tmpl->crypto_alg_type); + ret = qce_dma_prep_sgs(&qce->dma, req->src, rctx->src_nents, + &rctx->result_sg, 1, qce_ahash_done, async_req); if (ret) goto error_terminate; + qce_dma_issue_pending(&qce->dma); + return 0; error_terminate: diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index 03a3cec2bb90e..50d8c8c3d4ad1 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -141,18 +141,18 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req) src_nents = dst_nents - 1; } + ret = qce_start(async_req, tmpl->crypto_alg_type); + if (ret) + goto error_unmap_src; + ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, rctx->dst_sg, dst_nents, qce_skcipher_done, async_req); if (ret) - goto error_unmap_src; + goto error_terminate; qce_dma_issue_pending(&qce->dma); - ret = qce_start(async_req, tmpl->crypto_alg_type); - if (ret) - goto error_terminate; - return 0; error_terminate: From 4445e09df979378abc8893068dc92a2fbbbd0268 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2026 12:01:16 +0200 Subject: [PATCH 0289/1133] FROMLIST: crypto: qce - Communicate the base physical address to the dmaengine In order to communicate to the BAM DMA engine which address should be used as a scratchpad for dummy writes related to BAM pipe locking, fill out and attach the provided metadata struct to the descriptor. Reviewed-by: Manivannan Sadhasivam Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260629-qcom-qce-cmd-descr-v20-14-56f67da84c05@oss.qualcomm.com --- drivers/crypto/qce/dma.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c index 1b43c56503334..6410f8dc5bcf5 100644 --- a/drivers/crypto/qce/dma.c +++ b/drivers/crypto/qce/dma.c @@ -11,6 +11,7 @@ #include "core.h" #include "dma.h" +#include "regs-v5.h" #define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) #define QCE_BAM_CMD_SGL_SIZE 128 @@ -41,6 +42,10 @@ void qce_clear_bam_transaction(struct qce_device *qce) int qce_submit_cmd_desc(struct qce_device *qce) { + struct bam_desc_metadata meta = { + .scratchpad_addr = qce->base_phys + REG_VERSION, + .direction = DMA_MEM_TO_DEV, + }; struct qce_desc_info *qce_desc = qce->dma.bam_txn->desc; struct qce_bam_transaction *bam_txn = qce->dma.bam_txn; struct dma_async_tx_descriptor *dma_desc; @@ -60,15 +65,21 @@ int qce_submit_cmd_desc(struct qce_device *qce) goto err_unmap_sg; } + ret = dmaengine_desc_attach_metadata(dma_desc, &meta, sizeof(meta)); + if (ret) + goto err_free_desc; + qce_desc->dma_desc = dma_desc; cookie = dmaengine_submit(qce_desc->dma_desc); ret = dma_submit_error(cookie); if (ret) - goto err_unmap_sg; + goto err_free_desc; return 0; +err_free_desc: + dmaengine_desc_free(dma_desc); err_unmap_sg: dma_unmap_sg(qce->dev, bam_txn->wr_sgl, bam_txn->wr_sgl_cnt, DMA_TO_DEVICE); return ret; From abe65a7597ff2720d0b7b1473432ca97620eee2f Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:16 +0200 Subject: [PATCH 0290/1133] FROMLIST: crypto: qce - Fix HMAC self-test failures for empty messages BAM DMA cannot process zero-length transfers, so the driver always holds back at least one byte to submit to the engine and only ever finalizes with an empty buffer when nothing is left to submit. For plain hashes this was handled by returning the precomputed hash of the empty message (tmpl->hash_zero), but HMAC's result depends on the key and cannot be constant, so hmac(sha256) produced an incorrect digest for an empty message and the crypto self-tests failed. A zero pending buffer at finalization time does not necessarily mean the message itself is empty, though: the caller can also reach it by importing a state that already reflects some hashed data with nothing currently buffered (crypto_ahash_import() followed directly by finalization). Special-casing only a genuinely empty message would silently compute the wrong result for an imported state in that scenario. Handle every zero-length finalization consistently through the software fallback ahash instead. When nothing has been processed yet, let the fallback compute the result from scratch using the key already propagated to it via setkey(). Otherwise, reconstruct the fallback's running hash state from the state kept by the driver and finalize from there, accounting for the HMAC ipad block that the engine absorbs internally and that never goes through update(). Cc: stable@vger.kernel.org Fixes: ec8f5d8f6f76 ("crypto: qce - Qualcomm crypto engine driver") Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-1-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- drivers/crypto/qce/common.h | 1 - drivers/crypto/qce/sha.c | 58 +++++++++++++++++++++++++++---------- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/qce/common.h b/drivers/crypto/qce/common.h index 9cd2e6ed8bbb0..587d349da91d1 100644 --- a/drivers/crypto/qce/common.h +++ b/drivers/crypto/qce/common.h @@ -82,7 +82,6 @@ struct qce_alg_template { struct aead_alg aead; } alg; struct qce_device *qce; - const u8 *hash_zero; const u32 digest_size; }; diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c index ced9c8596fc6b..66016fe98a82b 100644 --- a/drivers/crypto/qce/sha.c +++ b/drivers/crypto/qce/sha.c @@ -249,18 +249,53 @@ static int qce_ahash_update(struct ahash_request *req) return qce->async_req_enqueue(tmpl->qce, &req->base); } +/* + * BAM DMA cannot handle zero-length transfers, so the driver always holds + * back at least one byte to submit to the engine. A zero rctx->buflen at + * finalization time does not necessarily mean the message is empty: the + * caller may have imported a state that already reflects some hashed data + * with nothing currently buffered. Handle both cases through the software + * fallback: reconstruct the running state when there is one instead of + * assuming the message is empty. + */ +static int qce_ahash_finalize_zero(struct ahash_request *req) +{ + struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req); + HASH_FBREQ_ON_STACK(fbreq, req); + struct __sha256_ctx core; + struct scatterlist sg; + int ret; + + sg_init_one(&sg, NULL, 0); + ahash_request_set_crypt(fbreq, &sg, req->result, 0); + + if (rctx->first_blk) { + ret = crypto_ahash_init(fbreq) ?: crypto_ahash_finup(fbreq); + } else { + core = (struct __sha256_ctx){ + .bytecount = rctx->count, + }; + + memcpy(&core.state, rctx->digest, sizeof(core.state)); + if (IS_SHA_HMAC(rctx->flags)) + core.bytecount += SHA256_BLOCK_SIZE; + + ret = crypto_ahash_import_core(fbreq, &core) ?: + crypto_ahash_finup(fbreq); + } + + HASH_REQUEST_ZERO(fbreq); + return ret; +} + static int qce_ahash_final(struct ahash_request *req) { struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req); struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm); struct qce_device *qce = tmpl->qce; - if (!rctx->buflen) { - if (tmpl->hash_zero) - memcpy(req->result, tmpl->hash_zero, - tmpl->alg.ahash.halg.digestsize); - return 0; - } + if (!rctx->buflen) + return qce_ahash_finalize_zero(req); rctx->last_blk = true; @@ -292,12 +327,8 @@ static int qce_ahash_digest(struct ahash_request *req) rctx->first_blk = true; rctx->last_blk = true; - if (!rctx->nbytes_orig) { - if (tmpl->hash_zero) - memcpy(req->result, tmpl->hash_zero, - tmpl->alg.ahash.halg.digestsize); - return 0; - } + if (!rctx->nbytes_orig) + return qce_ahash_finalize_zero(req); return qce->async_req_enqueue(tmpl->qce, &req->base); } @@ -431,9 +462,6 @@ static int qce_ahash_register_one(const struct qce_ahash_def *def, alg->halg.digestsize = def->digestsize; alg->halg.statesize = def->statesize; - if (IS_SHA256(def->flags)) - tmpl->hash_zero = sha256_zero_message_hash; - base = &alg->halg.base; base->cra_blocksize = def->blocksize; base->cra_priority = 175; From 2e5070fee74101a262944b1154edad6acf4a50cf Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:17 +0200 Subject: [PATCH 0291/1133] FROMLIST: crypto: qce - Reject empty messages for AES-XTS XTS is not defined for an empty plaintext: it requires at least one full block of data. The driver treated a zero-length request as a successful no-op, so the crypto self-tests "unexpectedly succeeded" when -EINVAL was expected. Return -EINVAL for empty XTS requests while keeping the no-op behavior for the other ciphers, which the crypto engine simply cannot process due to its DMA not supporting zero-length transfers. Cc: stable@vger.kernel.org Fixes: f08789462255 ("crypto: qce - Return error for zero length messages") Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-2-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- drivers/crypto/qce/skcipher.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index 50d8c8c3d4ad1..c2f5bec2cc83c 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -222,8 +222,12 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; /* CE does not handle 0 length messages */ - if (!req->cryptlen) + if (!req->cryptlen) { + /* XTS requires at least one full block of data */ + if (IS_XTS(rctx->flags)) + return -EINVAL; return 0; + } /* * ECB and CBC algorithms require message lengths to be From d03a92ccadb4201da607f68a66273136fa81aabd Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 22 Sep 2026 14:57:18 +0200 Subject: [PATCH 0292/1133] FROMLIST: crypto: qce - Fix CTR-AES for partial block requests In CTR mode, the IV acts as the initial counter block. APer NIST SP 800-38A, after a CTR mode operation the next unused counter value is: IV_next = IV_in + ceil(cryptlen / AES_BLOCK_SIZE) The skcipher requires req->iv to hold this updated counter on completion, ensuring chained requests produce correct results. Referring to Crypto6.0 documentation, Section 2.2.5 says: "The count value increments automatically once per block of data (in AES, a block is 16 bytes) based on the value in the CRYPTO_ENCR_CNTR_MASK registers." QCE increments internal counter register once per full 16-byte block(for ctr-aes) is processed. In case of partial request length, the hardware uses the current counter to generate keystreams but does not increment the counter register afterwards. So the counter value written in CRYPTO_ENCR_CNTRn_IVn later once read by software is one less than the expected value. Crypto selftest framework capture this scenario with test vector 4 comprising of a 499-byte payload (31 full blocks + 3 partial bytes). Error: [ 5.606169] alg: skcipher: ctr-aes-qce encryption test failed (wrong output IV) on test vector 4, cfg="in-place (one sglist)" [ 5.606176] 00000000: e7 82 1d b8 53 11 ac 47 e2 7d 18 d6 71 0c a7 61 [ 5.606192] alg: self-tests for ctr(aes) using ctr-aes-qce failed (rc=-22) Expected iv_out: 0x62 (iv_in + 32) Obtained iv_out: 0x61 (iv_in + 31, partial block not counted) To fix this, just increase the counter value for partial block requests by 1 and for the full block size requests, don't take any action as expected value is already returned by the hardware. Cc: stable@vger.kernel.org Fixes: 3e806a12d10a ("crypto: qce - update the skcipher IV") Signed-off-by: Kuldeep Singh Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-3-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- drivers/crypto/qce/skcipher.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index c2f5bec2cc83c..d73b836d68e76 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -33,6 +33,7 @@ static void qce_skcipher_done(void *data) struct qce_device *qce = tmpl->qce; struct qce_result_dump *result_buf = qce->dma.result_buf; enum dma_data_direction dir_src, dir_dst; + unsigned int blocks; u32 status; int error; bool diff_dst; @@ -56,7 +57,21 @@ static void qce_skcipher_done(void *data) if (error < 0) dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); - memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); + if (IS_CTR(rctx->flags)) { + /* + * QCE hardware does not increment the counter for a partial + * final block. Increment it in software so that iv_out + * reflects the correct next counter value expected by the CTR + * mode. + */ + blocks = DIV_ROUND_UP(rctx->cryptlen, AES_BLOCK_SIZE); + + while (blocks--) + crypto_inc(rctx->iv, rctx->ivsize); + } else { + memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); + } + qce->async_req_done(tmpl->qce, error); } From 72e6a1ae191490b04bdcadac72e6fc423e5b44dd Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:19 +0200 Subject: [PATCH 0293/1133] FROMLIST: crypto: qce - Use a fallback for AES-CTR with a partial final block ctr(aes) is registered with a block size of 1, so the crypto API hands the driver requests whose length is not a multiple of the AES block size. The crypto engine, however, stalls waiting for a full block of input in that case, leaving the operation incomplete and failing the request (and the crypto self-tests) with a hardware operation error. Route AES-CTR requests with a partial final block to the software fallback, which already handles the other cases the engine cannot. Cc: stable@vger.kernel.org Fixes: bb5c863b3d3c ("crypto: qce - fix ctr-aes-qce block, chunk sizes") Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-4-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- drivers/crypto/qce/skcipher.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index d73b836d68e76..77febb3a5fa22 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -259,9 +259,12 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) * AES-XTS request with len > QCE_SECTOR_SIZE and * is not a multiple of it.(Revisit this condition to check if it is * needed in all versions of CE) + * AES-CTR with a partial final block (the CE stalls waiting for a full + * block of input). */ if (IS_AES(rctx->flags) && ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || + (IS_CTR(rctx->flags) && !IS_ALIGNED(req->cryptlen, AES_BLOCK_SIZE)) || (IS_XTS(rctx->flags) && ((req->cryptlen <= aes_sw_max_len) || (req->cryptlen > QCE_SECTOR_SIZE && req->cryptlen % QCE_SECTOR_SIZE))))) { From d8666377d1a0229936b35fc09a4662ff8f420c11 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:20 +0200 Subject: [PATCH 0294/1133] FROMLIST: crypto: qce - Use fallback for fragmented skcipher payloads The crypto engine reliably processes AES requests only when the payload is a single contiguous buffer. A payload split across multiple scatterlist entries makes the engine stall waiting for input, failing the request with a hardware operation error. This was uncovered by the crypto self-tests, which feed the algorithms randomly fragmented buffers. Detect a payload that spans more than one scatterlist entry, in either the source or the destination, and route the request to the software fallback. Cc: stable@vger.kernel.org Fixes: 25b71d61d631 ("crypto: qce - Improve the conditions for requesting AES fallback cipher") Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-5-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- drivers/crypto/qce/skcipher.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index 77febb3a5fa22..f7c60efc8b842 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -261,13 +261,17 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) * needed in all versions of CE) * AES-CTR with a partial final block (the CE stalls waiting for a full * block of input). + * A payload fragmented across more than one scatterlist entry (the CE + * stalls waiting for input in that case too). */ if (IS_AES(rctx->flags) && ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || (IS_CTR(rctx->flags) && !IS_ALIGNED(req->cryptlen, AES_BLOCK_SIZE)) || (IS_XTS(rctx->flags) && ((req->cryptlen <= aes_sw_max_len) || (req->cryptlen > QCE_SECTOR_SIZE && - req->cryptlen % QCE_SECTOR_SIZE))))) { + req->cryptlen % QCE_SECTOR_SIZE))) || + sg_nents_for_len(req->src, req->cryptlen) > 1 || + sg_nents_for_len(req->dst, req->cryptlen) > 1)) { skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback); skcipher_request_set_callback(&rctx->fallback_req, req->base.flags, From bfd0405ca5d3ce48a6186ec73f152e76b222b501 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 22 Sep 2026 14:57:21 +0200 Subject: [PATCH 0295/1133] FROMLIST: crypto: qce - Fix xts-aes-qce for weak keys The QCE hardware does not support AES XTS mode when key1 and key2 are equal. The driver was handling this by unconditionally rejecting the keys with -ENOKEY(-126), regardless of whether FIPS mode is active or the FORBID_WEAK_KEYS flag is set. [ 5.599170] alg: skcipher: xts-aes-qce setkey failed on test vector 0; expected_error=0, actual_error=-126, flags=0x1 [ 5.599184] alg: self-tests for xts(aes) using xts-aes-qce failed (rc=-126) In general for weak keys, - If FIPS mode is active or FORBID_WEAK_KEYS is set: return -EINVAL. - In non-FIPS mode, Accept the key and encrypt successfully. Since QCE was returning -ENOKEY for non-FIPS mode whereas the expectation is to encrypt content and return success, the selftest saw a mismatch and failed. There are two problems in QCE behavior: * -ENOKEY is returned instead of -EINVAL for the FIPS/weak-key rejection case. * key1 == key2 is rejected even in non-FIPS mode Fix xts-aes-qce behavior by using generic helper xts_verify_key() to reject keys early with -EINVAL for FIPS mode active(or FORBID_WEAK_KEYS set). For non-FIPS mode, since QCE hardware cannot accept the keys, use software fallback mechanism to encrypt the data. Cc: stable@vger.kernel.org Fixes: f0d078dd6c49 ("crypto: qce - Return unsupported if key1 and key 2 are same for AES XTS algorithm") Signed-off-by: Kuldeep Singh Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-6-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- drivers/crypto/qce/cipher.h | 1 + drivers/crypto/qce/skcipher.c | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/qce/cipher.h b/drivers/crypto/qce/cipher.h index 850f257d00f3a..daea07551118d 100644 --- a/drivers/crypto/qce/cipher.h +++ b/drivers/crypto/qce/cipher.h @@ -14,6 +14,7 @@ struct qce_cipher_ctx { u8 enc_key[QCE_MAX_KEY_SIZE]; unsigned int enc_keylen; + bool use_fallback; struct crypto_skcipher *fallback; }; diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index f7c60efc8b842..83c75a6fa64f6 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "cipher.h" @@ -194,14 +195,17 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, if (!key || !keylen) return -EINVAL; - /* - * AES XTS key1 = key2 not supported by crypto engine. - * Revisit to request a fallback cipher in this case. - */ if (IS_XTS(flags)) { + ret = xts_verify_key(ablk, key, keylen); + if (ret) + return ret; __keylen = keylen >> 1; - if (!memcmp(key, key + __keylen, __keylen)) - return -ENOKEY; + /* + * QCE does not support key1 == key2 for XTS. + * Use fallback cipher in this case. + */ + ctx->use_fallback = !crypto_memneq(key, key + __keylen, + __keylen); } else { __keylen = keylen; } @@ -261,6 +265,7 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) * needed in all versions of CE) * AES-CTR with a partial final block (the CE stalls waiting for a full * block of input). + * AES-XTS with key1 == key2 (not supported by the CE). * A payload fragmented across more than one scatterlist entry (the CE * stalls waiting for input in that case too). */ @@ -270,6 +275,7 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) (IS_XTS(rctx->flags) && ((req->cryptlen <= aes_sw_max_len) || (req->cryptlen > QCE_SECTOR_SIZE && req->cryptlen % QCE_SECTOR_SIZE))) || + (IS_XTS(rctx->flags) && ctx->use_fallback) || sg_nents_for_len(req->src, req->cryptlen) > 1 || sg_nents_for_len(req->dst, req->cryptlen) > 1)) { skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback); From 9b7274dfb961cf3921400c93dc321fccd4146e95 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:22 +0200 Subject: [PATCH 0296/1133] FROMLIST: crypto: qce - Use a fallback for CCM with a partial final block CCM builds on AES-CTR for encryption, and the crypto engine stalls on a partial final block just as it does for plain ctr(aes): a payload whose length is not a multiple of the AES block size leaves the operation incomplete and fails with a hardware operation error. This was caught by the ccm(aes) crypto self-tests. Force the software fallback for CCM requests whose message length is not block aligned, reusing the driver's existing need_fallback mechanism. Cc: stable@vger.kernel.org Fixes: 9363efb4181c ("crypto: qce - Add support for AEAD algorithms") Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-7-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- drivers/crypto/qce/aead.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index 5f2736f09746f..611f68b480593 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -514,6 +514,14 @@ static int qce_aead_crypt(struct aead_request *req, int encrypt) ctx->need_fallback = true; } + /* + * CCM uses AES-CTR internally and the CE stalls on a partial final + * block, so a payload that is not a multiple of the block size has to + * be handled by the fallback. + */ + if (IS_CCM(rctx->flags) && !IS_ALIGNED(rctx->cryptlen, AES_BLOCK_SIZE)) + ctx->need_fallback = true; + /* If fallback is needed, schedule and exit */ if (ctx->need_fallback) { /* Reset need_fallback in case the same ctx is used for another transaction */ From 6724176ab84611b2f43aaf072504d21e5590d814 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:23 +0200 Subject: [PATCH 0297/1133] FROMLIST: crypto: qce - Use fallback for CCM with a fragmented payload The crypto engine reliably processes CCM only when the message payload is a single contiguous buffer. The associated data is already linearized into a bounce buffer before being submitted, but when the payload itself is split across multiple scatterlist entries the engine stalls waiting for input and the request fails with a hardware operation error. This was uncovered by the crypto self-tests, which feed the algorithms randomly fragmented buffers. Detect a payload that spans more than one scatterlist entry (in either the source or the destination, skipping past the associated data) and route the request to the software fallback. Cc: stable@vger.kernel.org Fixes: 9363efb4181c ("crypto: qce - Add support for AEAD algorithms") Tested-by: Kuldeep Singh Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-8-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- drivers/crypto/qce/aead.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index 611f68b480593..83edf19d11360 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -498,7 +498,8 @@ static int qce_aead_crypt(struct aead_request *req, int encrypt) struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req); struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); struct qce_alg_template *tmpl = to_aead_tmpl(tfm); - unsigned int blocksize = crypto_aead_blocksize(tfm); + unsigned int blocksize = crypto_aead_blocksize(tfm), authsize; + struct scatterlist __sg[2], *msg_sg; rctx->flags = tmpl->alg_flags; rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; @@ -522,6 +523,27 @@ static int qce_aead_crypt(struct aead_request *req, int encrypt) if (IS_CCM(rctx->flags) && !IS_ALIGNED(rctx->cryptlen, AES_BLOCK_SIZE)) ctx->need_fallback = true; + /* + * The CE reliably processes CCM only when the message payload is a + * single contiguous buffer. The associated data is linearized into a + * bounce buffer before being handed to the engine, but a fragmented + * payload makes the engine stall waiting for input, so route those + * requests to the fallback. + */ + if (IS_CCM(rctx->flags) && rctx->cryptlen) { + authsize = ctx->authsize; + + msg_sg = scatterwalk_ffwd(__sg, req->src, req->assoclen); + if (sg_nents_for_len(msg_sg, rctx->cryptlen + + (encrypt ? 0 : authsize)) > 1) + ctx->need_fallback = true; + + msg_sg = scatterwalk_ffwd(__sg, req->dst, req->assoclen); + if (sg_nents_for_len(msg_sg, rctx->cryptlen + + (encrypt ? authsize : 0)) > 1) + ctx->need_fallback = true; + } + /* If fallback is needed, schedule and exit */ if (ctx->need_fallback) { /* Reset need_fallback in case the same ctx is used for another transaction */ From 3aa97b078038ecd48b4f3aa87d3777df4b9cdd06 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:24 +0200 Subject: [PATCH 0298/1133] FROMLIST: crypto: qce - Only register algos if the user really wants it This driver's crypto algorithms still have a few issues that need addressing which don't currently trigger any self-test failures. For that reason: don't register the algorithms unless the user really wants it. Add a module parameter to the QCE driver that by default causes the driver to *not* register the crypto algorithms. It will only be one if the user explicitly passes the do_register_algos argument as true. The power-management part of the driver is kept as is to allow scaling down of interconnects gating of clocks by runtime PM. Cc: stable@vger.kernel.org Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-9-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- drivers/crypto/qce/core.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index a2b739c663877..786a9f3572d9c 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,9 @@ #include "sha.h" #include "aead.h" +static bool do_register_algos; +module_param(do_register_algos, bool, 0444); + #define QCE_QUEUE_LENGTH 1 #define QCE_DEFAULT_MEM_BANDWIDTH 393600 @@ -278,9 +282,11 @@ static int qce_crypto_probe(struct platform_device *pdev) qce->async_req_enqueue = qce_async_request_enqueue; qce->async_req_done = qce_async_request_done; - ret = devm_qce_register_algs(qce); - if (ret) - return ret; + if (do_register_algos) { + ret = devm_qce_register_algs(qce); + if (ret) + return ret; + } /* Configure autosuspend after successful init */ pm_runtime_set_autosuspend_delay(dev, 100); From bc20dac5cbddea0c304469c5990aaf7307148a4c Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:25 +0200 Subject: [PATCH 0299/1133] FROMLIST: Revert "crypto: qce - Mark QCE as BROKEN" The self-tests for this driver have been fixed. The crypto algorithms are only registered if the user explicitly requests it with the provided module parameter defaulting to false. There's no reason to further keep it unbuildable with the BROKEN label. While at it: update the Kconfig description by saying this is an "offloader" and not an "accelerator". Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-10-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- arch/arm/configs/multi_v7_defconfig | 1 + arch/arm64/configs/defconfig | 1 + drivers/crypto/Kconfig | 22 +++++++++++++--------- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 069d5a49f01cb..d611e85c62e93 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -1315,6 +1315,7 @@ CONFIG_CRYPTO_DEV_ATMEL_AES=m CONFIG_CRYPTO_DEV_ATMEL_TDES=m CONFIG_CRYPTO_DEV_ATMEL_SHA=m CONFIG_CRYPTO_DEV_MARVELL_CESA=m +CONFIG_CRYPTO_DEV_QCE=m CONFIG_CRYPTO_DEV_ROCKCHIP=m CONFIG_CRYPTO_DEV_STM32_HASH=m CONFIG_CRYPTO_DEV_STM32_CRYP=m diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7b4985b29b21c..52654d3b97c8e 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1845,6 +1845,7 @@ CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_CRYPTO_DEV_SUN8I_CE=m CONFIG_CRYPTO_DEV_FSL_CAAM=m CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=m +CONFIG_CRYPTO_DEV_QCE=m CONFIG_CRYPTO_DEV_TEGRA=m CONFIG_CRYPTO_DEV_ZYNQMP_AES=m CONFIG_CRYPTO_DEV_ZYNQMP_SHA3=m diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 0189dfdcbbe11..adcbe15851899 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -527,17 +527,21 @@ source "drivers/crypto/marvell/Kconfig" source "drivers/crypto/intel/Kconfig" config CRYPTO_DEV_QCE - tristate "Qualcomm crypto engine accelerator" - depends on (BROKEN && ARCH_QCOM) || COMPILE_TEST + tristate "Qualcomm crypto engine offloader" + depends on ARCH_QCOM || COMPILE_TEST depends on HAS_IOMEM help - This driver supports Qualcomm crypto engine accelerator - hardware. To compile this driver as a module, choose M here. The - module will be called qcrypto. - - This driver does not have exclusive access to the - hardware, causing races with the secure world. It - is also slower than the CPU. + This driver supports Qualcomm crypto engine offloader hardware. To + compile this driver as a module, choose M here. The module will be + called qcrypto. + + NOTE: With qcrypto.do_register_algos module parameter set to true, + this driver does not have exclusive access to the hardware, and may + cause races with the secure world. It is also *slower* than the + CPU for the same algorithms. By default it will not register crypto + algorithms and only scale down the interconnect bandwidth and disable + the relevant clocks. Use qcrypto.do_register_algos=1 at your own + risk! config CRYPTO_DEV_QCE_SKCIPHER bool From 1832d35e718d41e80fe9f02fa9cc5b31d7d8f999 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:26 +0200 Subject: [PATCH 0300/1133] FROMLIST: crypto: qce - convert to auxiliary bus This driver is disabled in arm64 defconfig but one of its functionalities - scaling down the interconnect votes to 0 when unused - will be moved to an always-enabled core qce driver. This upcoming core driver will also be in charge of registering the qcrypto device on the auxiliary bus so that it may be enabled if desired. As the first step: convert the driver to using the auxiliary bus and remove the interconnect management from the code. Update the power management as required and make sure to use the parent struct device for DMA. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-11-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- drivers/crypto/Kconfig | 2 + drivers/crypto/qce/aead.c | 12 ++--- drivers/crypto/qce/core.c | 94 ++++++++++++++++------------------- drivers/crypto/qce/core.h | 5 +- drivers/crypto/qce/sha.c | 12 ++--- drivers/crypto/qce/skcipher.c | 12 ++--- 6 files changed, 66 insertions(+), 71 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index adcbe15851899..b3fa1f6135bce 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -530,6 +530,8 @@ config CRYPTO_DEV_QCE tristate "Qualcomm crypto engine offloader" depends on ARCH_QCOM || COMPILE_TEST depends on HAS_IOMEM + depends on PM + select AUXILIARY_BUS help This driver supports Qualcomm crypto engine offloader hardware. To compile this driver as a module, choose M here. The module will be diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index 83edf19d11360..deda5ede81592 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -44,9 +44,9 @@ static void qce_aead_done(void *data) dev_dbg(qce->dev, "aead dma termination error (%d)\n", error); if (diff_dst) - dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); + dma_unmap_sg(qce->dma_dev, rctx->src_sg, rctx->src_nents, dir_src); - dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); + dma_unmap_sg(qce->dma_dev, rctx->dst_sg, rctx->dst_nents, dir_dst); if (IS_CCM(rctx->flags)) { if (req->assoclen) { @@ -442,14 +442,14 @@ qce_aead_async_req_handle(struct crypto_async_request *async_req) if (ret) return ret; - dst_nents = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); + dst_nents = dma_map_sg(qce->dma_dev, rctx->dst_sg, rctx->dst_nents, dir_dst); if (!dst_nents) { ret = -EIO; goto error_free; } if (diff_dst) { - src_nents = dma_map_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); + src_nents = dma_map_sg(qce->dma_dev, rctx->src_sg, rctx->src_nents, dir_src); if (src_nents < 0) { ret = src_nents; goto error_unmap_dst; @@ -478,9 +478,9 @@ qce_aead_async_req_handle(struct crypto_async_request *async_req) qce_dma_terminate_all(&qce->dma); error_unmap_src: if (diff_dst) - dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); + dma_unmap_sg(qce->dma_dev, req->src, rctx->src_nents, dir_src); error_unmap_dst: - dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); + dma_unmap_sg(qce->dma_dev, rctx->dst_sg, rctx->dst_nents, dir_dst); error_free: if (IS_CCM(rctx->flags) && rctx->assoclen) { sg_free_table(&rctx->src_tbl); diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c index 786a9f3572d9c..d4353e6afbc45 100644 --- a/drivers/crypto/qce/core.c +++ b/drivers/crypto/qce/core.c @@ -3,15 +3,16 @@ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. */ +#include #include #include #include +#include #include -#include #include #include #include -#include +#include #include #include #include @@ -27,8 +28,6 @@ module_param(do_register_algos, bool, 0444); #define QCE_QUEUE_LENGTH 1 -#define QCE_DEFAULT_MEM_BANDWIDTH 393600 - static const struct qce_algo_ops *qce_ops[] = { #ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER &skcipher_ops, @@ -92,11 +91,6 @@ static int qce_handle_queue(struct qce_device *qce, struct crypto_async_request *async_req, *backlog; int ret, err; - PM_RUNTIME_ACQUIRE_AUTOSUSPEND(qce->dev, pm); - ret = PM_RUNTIME_ACQUIRE_ERR(&pm); - if (ret) - return ret; - scoped_guard(mutex, &qce->lock) { if (req) ret = crypto_enqueue_request(&qce->queue, req); @@ -119,8 +113,21 @@ static int qce_handle_queue(struct qce_device *qce, crypto_request_complete(backlog, -EINPROGRESS); } + /* + * Hold the device resumed across that whole window instead of just + * across this function, or autosuspend could gate the engine clocks + * while the DMA is still in flight. + */ + err = pm_runtime_resume_and_get(qce->dev); + if (err) { + qce->result = err; + schedule_work(&qce->done_work); + return ret; + } + err = qce_handle_request(async_req); if (err) { + pm_runtime_put_autosuspend(qce->dev); qce->result = err; schedule_work(&qce->done_work); } @@ -153,6 +160,7 @@ static int qce_async_request_enqueue(struct qce_device *qce, static void qce_async_request_done(struct qce_device *qce, int ret) { + pm_runtime_put_autosuspend(qce->dev); qce->result = ret; schedule_work(&qce->done_work); } @@ -208,11 +216,13 @@ static void qce_crypto_unmap_dma(void *data) DMA_BIDIRECTIONAL, 0); } -static int qce_crypto_probe(struct platform_device *pdev) +static int qce_crypto_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *id) { - struct device *dev = &pdev->dev; + struct device *dev = &auxdev->dev; struct qce_device *qce; struct resource *res; + struct resource res; int ret; qce = devm_kzalloc(dev, sizeof(*qce), GFP_KERNEL); @@ -220,13 +230,17 @@ static int qce_crypto_probe(struct platform_device *pdev) return -ENOMEM; qce->dev = dev; - platform_set_drvdata(pdev, qce); + qce->dma_dev = dev->parent; + auxiliary_set_drvdata(auxdev, qce); - qce->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + ret = of_address_to_resource(dev->of_node, 0, &res); + if (ret) + return ret; + qce->base = devm_ioremap_resource(dev, &res); if (IS_ERR(qce->base)) return PTR_ERR(qce->base); - ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + ret = dma_set_mask_and_coherent(qce->dma_dev, DMA_BIT_MASK(32)); if (ret < 0) return ret; @@ -242,10 +256,6 @@ static int qce_crypto_probe(struct platform_device *pdev) if (IS_ERR(qce->bus)) return PTR_ERR(qce->bus); - qce->mem_path = devm_of_icc_get(dev, "memory"); - if (IS_ERR(qce->mem_path)) - return PTR_ERR(qce->mem_path); - /* * Enable runtime PM after clocks and ICC path are acquired so that * the resume callback can enable clocks and apply the ICC bandwidth @@ -255,7 +265,10 @@ static int qce_crypto_probe(struct platform_device *pdev) if (ret) return ret; - PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm); + pm_runtime_set_autosuspend_delay(dev, 100); + pm_runtime_use_autosuspend(dev); + + PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(dev, pm); ret = PM_RUNTIME_ACQUIRE_ERR(&pm); if (ret) return ret; @@ -288,11 +301,6 @@ static int qce_crypto_probe(struct platform_device *pdev) return ret; } - /* Configure autosuspend after successful init */ - pm_runtime_set_autosuspend_delay(dev, 100); - pm_runtime_use_autosuspend(dev); - pm_runtime_mark_last_busy(dev); - qce->dma_size = resource_size(res); qce->base_dma = dma_map_resource(dev, res->start, qce->dma_size, DMA_BIDIRECTIONAL, 0); @@ -305,26 +313,17 @@ static int qce_crypto_probe(struct platform_device *pdev) if (ret) return ret; - return devm_qce_register_algs(qce); + return 0; } static int qce_runtime_suspend(struct device *dev) { struct qce_device *qce = dev_get_drvdata(dev); - int ret; clk_disable_unprepare(qce->core); clk_disable_unprepare(qce->iface); clk_disable_unprepare(qce->bus); - ret = icc_set_bw(qce->mem_path, 0, 0); - if (ret) { - clk_prepare_enable(qce->bus); - clk_prepare_enable(qce->iface); - clk_prepare_enable(qce->core); - return ret; - } - return 0; } @@ -333,14 +332,9 @@ static int qce_runtime_resume(struct device *dev) struct qce_device *qce = dev_get_drvdata(dev); int ret; - ret = icc_set_bw(qce->mem_path, QCE_DEFAULT_MEM_BANDWIDTH, - QCE_DEFAULT_MEM_BANDWIDTH); - if (ret) - return ret; - ret = clk_prepare_enable(qce->core); if (ret) - goto err_core; + return ret; ret = clk_prepare_enable(qce->iface); if (ret) @@ -356,8 +350,7 @@ static int qce_runtime_resume(struct device *dev) clk_disable_unprepare(qce->iface); err_iface: clk_disable_unprepare(qce->core); -err_core: - icc_set_bw(qce->mem_path, 0, 0); + return ret; } @@ -366,25 +359,22 @@ static const struct dev_pm_ops qce_crypto_pm_ops = { SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; -static const struct of_device_id qce_crypto_of_match[] = { - { .compatible = "qcom,crypto-v5.1", }, - { .compatible = "qcom,crypto-v5.4", }, - { .compatible = "qcom,qce", }, +static const struct auxiliary_device_id qce_crypto_ids[] = { + { .name = "qce.crypto", }, {} }; -MODULE_DEVICE_TABLE(of, qce_crypto_of_match); +MODULE_DEVICE_TABLE(auxiliary, qce_crypto_ids); -static struct platform_driver qce_crypto_driver = { +static struct auxiliary_driver qce_crypto_driver = { .probe = qce_crypto_probe, + .id_table = qce_crypto_ids, .driver = { - .name = KBUILD_MODNAME, - .of_match_table = qce_crypto_of_match, + .name = "qce-crypto", .pm = pm_ptr(&qce_crypto_pm_ops), }, }; -module_platform_driver(qce_crypto_driver); +module_auxiliary_driver(qce_crypto_driver); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Qualcomm crypto engine driver"); -MODULE_ALIAS("platform:" KBUILD_MODNAME); MODULE_AUTHOR("The Linux Foundation"); diff --git a/drivers/crypto/qce/core.h b/drivers/crypto/qce/core.h index a80e12eac6c87..f912ece4bc7de 100644 --- a/drivers/crypto/qce/core.h +++ b/drivers/crypto/qce/core.h @@ -21,6 +21,9 @@ * @result: result of current transform * @base: virtual IO base * @dev: pointer to device structure + * @dma_dev: pointer to the device to use for DMA mapping calls; this is the + * auxiliary bus device's parent, which is the one that actually + * went through DMA/IOMMU configuration * @core: core device clock * @iface: interface clock * @bus: bus clock @@ -41,8 +44,8 @@ struct qce_device { int result; void __iomem *base; struct device *dev; + struct device *dma_dev; struct clk *core, *iface, *bus; - struct icc_path *mem_path; struct qce_dma_data dma; int burst_size; unsigned int pipe_pair_id; diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c index 66016fe98a82b..023f236cc8179 100644 --- a/drivers/crypto/qce/sha.c +++ b/drivers/crypto/qce/sha.c @@ -47,8 +47,8 @@ static void qce_ahash_done(void *data) if (error) dev_dbg(qce->dev, "ahash dma termination error (%d)\n", error); - dma_unmap_sg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE); - dma_unmap_sg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE); + dma_unmap_sg(qce->dma_dev, req->src, rctx->src_nents, DMA_TO_DEVICE); + dma_unmap_sg(qce->dma_dev, &rctx->result_sg, 1, DMA_FROM_DEVICE); memcpy(rctx->digest, result->auth_iv, digestsize); if (req->result && rctx->last_blk) @@ -93,13 +93,13 @@ static int qce_ahash_async_req_handle(struct crypto_async_request *async_req) return rctx->src_nents; } - ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE); + ret = dma_map_sg(qce->dma_dev, req->src, rctx->src_nents, DMA_TO_DEVICE); if (!ret) return -EIO; sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); - ret = dma_map_sg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE); + ret = dma_map_sg(qce->dma_dev, &rctx->result_sg, 1, DMA_FROM_DEVICE); if (!ret) { ret = -EIO; goto error_unmap_src; @@ -121,9 +121,9 @@ static int qce_ahash_async_req_handle(struct crypto_async_request *async_req) error_terminate: qce_dma_terminate_all(&qce->dma); error_unmap_dst: - dma_unmap_sg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE); + dma_unmap_sg(qce->dma_dev, &rctx->result_sg, 1, DMA_FROM_DEVICE); error_unmap_src: - dma_unmap_sg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE); + dma_unmap_sg(qce->dma_dev, req->src, rctx->src_nents, DMA_TO_DEVICE); return ret; } diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index 83c75a6fa64f6..bc1ddf6ef225e 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -49,8 +49,8 @@ static void qce_skcipher_done(void *data) error); if (diff_dst) - dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); - dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); + dma_unmap_sg(qce->dma_dev, rctx->src_sg, rctx->src_nents, dir_src); + dma_unmap_sg(qce->dma_dev, rctx->dst_sg, rctx->dst_nents, dir_dst); sg_free_table(&rctx->dst_tbl); @@ -139,14 +139,14 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req) sg_mark_end(sg); rctx->dst_sg = rctx->dst_tbl.sgl; - dst_nents = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); + dst_nents = dma_map_sg(qce->dma_dev, rctx->dst_sg, rctx->dst_nents, dir_dst); if (!dst_nents) { ret = -EIO; goto error_free; } if (diff_dst) { - src_nents = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); + src_nents = dma_map_sg(qce->dma_dev, req->src, rctx->src_nents, dir_src); if (!src_nents) { ret = -EIO; goto error_unmap_dst; @@ -175,9 +175,9 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req) qce_dma_terminate_all(&qce->dma); error_unmap_src: if (diff_dst) - dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); + dma_unmap_sg(qce->dma_dev, req->src, rctx->src_nents, dir_src); error_unmap_dst: - dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); + dma_unmap_sg(qce->dma_dev, rctx->dst_sg, rctx->dst_nents, dir_dst); error_free: sg_free_table(&rctx->dst_tbl); return ret; From 56c56748809fe31079e2cc517d78a97a8a8144b3 Mon Sep 17 00:00:00 2001 From: Yijie Yang Date: Tue, 22 Sep 2026 16:19:58 -0700 Subject: [PATCH 0301/1133] FROMLIST: dt-bindings: arm: qcom: Document Maili SoC and its reference board Document the Maili SoC binding and the board which use it. Signed-off-by: Jingyi Wang Signed-off-by: Yijie Yang Link: https://lore.kernel.org/r/20260922-maili-dts-v1-1-ac2b1b76bfd9@oss.qualcomm.com --- Documentation/devicetree/bindings/arm/qcom.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 121ca557ce1ef..360bf529d0d5b 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -201,6 +201,11 @@ properties: - const: lenovo,thinkpad-t14s-gen7 - const: qcom,mahua + - items: + - enum: + - qcom,maili-mtp + - const: qcom,maili + - description: Sierra Wireless MangOH Green with WP8548 Module items: - const: swir,mangoh-green-wp8548 From 39c119d8fc59ec4bf595112d84cad7bb43ab53a4 Mon Sep 17 00:00:00 2001 From: Chunkai Deng Date: Tue, 22 Sep 2026 16:19:59 -0700 Subject: [PATCH 0302/1133] FROMLIST: arm64: dts: qcom: Add header file for IPCC physical client IDs Physical client IDs are used on Maili Inter Process Communication Controller (IPCC), add a corresponding header file. Signed-off-by: Chunkai Deng Signed-off-by: Jingyi Wang Signed-off-by: Yijie Yang Link: https://lore.kernel.org/r/20260922-maili-dts-v1-2-ac2b1b76bfd9@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/maili-ipcc.h | 62 +++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/maili-ipcc.h diff --git a/arch/arm64/boot/dts/qcom/maili-ipcc.h b/arch/arm64/boot/dts/qcom/maili-ipcc.h new file mode 100644 index 0000000000000..7cf66d20e9c13 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/maili-ipcc.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __DTS_MAILI_MAILBOX_IPCC_H +#define __DTS_MAILI_MAILBOX_IPCC_H + +/* Physical client IDs */ +#define IPCC_MPROC_AOP 0 +#define IPCC_MPROC_TZ 1 +#define IPCC_MPROC_MPSS 2 +#define IPCC_MPROC_LPASS 3 +#define IPCC_MPROC_SDC 4 +#define IPCC_MPROC_CDSP 5 +#define IPCC_MPROC_APSS 6 +#define IPCC_MPROC_SOCCP 12 +#define IPCC_MPROC_DCP 13 +#define IPCC_MPROC_QECP 14 +#define IPCC_MPROC_SPSS 15 +#define IPCC_MPROC_TME 16 +#define IPCC_MPROC_WPSS 17 + +#define IPCC_COMPUTE_L0_LPASS 1 +#define IPCC_COMPUTE_L0_CDSP 2 +#define IPCC_COMPUTE_L0_APSS 3 +#define IPCC_COMPUTE_L0_GPU 4 +#define IPCC_COMPUTE_L0_CVP 8 +#define IPCC_COMPUTE_L0_CAM 9 +#define IPCC_COMPUTE_L0_CAM1 10 +#define IPCC_COMPUTE_L0_DCP 11 +#define IPCC_COMPUTE_L0_VPU 12 +#define IPCC_COMPUTE_L0_SOCCP 16 + +#define IPCC_COMPUTE_L1_LPASS 1 +#define IPCC_COMPUTE_L1_CDSP 2 +#define IPCC_COMPUTE_L1_APSS 3 +#define IPCC_COMPUTE_L1_GPU 4 +#define IPCC_COMPUTE_L1_CVP 8 +#define IPCC_COMPUTE_L1_CAM 9 +#define IPCC_COMPUTE_L1_CAM1 10 +#define IPCC_COMPUTE_L1_DCP 11 +#define IPCC_COMPUTE_L1_VPU 12 +#define IPCC_COMPUTE_L1_SOCCP 16 + +#define IPCC_PERIPH_CDSP 2 +#define IPCC_PERIPH_APSS 3 +#define IPCC_PERIPH_PCIE0 4 +#define IPCC_PERIPH_PCIE1 15 + +#define IPCC_FENCE_LPASS 1 +#define IPCC_FENCE_CDSP 2 +#define IPCC_FENCE_APSS 3 +#define IPCC_FENCE_GPU 4 +#define IPCC_FENCE_CVP 8 +#define IPCC_FENCE_CAM 9 +#define IPCC_FENCE_CAM1 10 +#define IPCC_FENCE_DCP 11 +#define IPCC_FENCE_VPU 20 +#define IPCC_FENCE_SOCCP 24 + +#endif From 08a92d6e460ab9b236e98de4eccd87dfae731325 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 22 Sep 2026 16:20:00 -0700 Subject: [PATCH 0303/1133] FROMLIST: arm64: dts: qcom: Introduce Maili SoC Maili is Snapdragon SoC from Qualcomm. Features added in this patch: - CPUs with PSCI idle states and cpufreq - Interrupt-controller with PDC wakeup support - Timers, TCSR Clock Controllers - Reserved Shared memory - GCC and RPMHCC - TLMM - Interconnect - QuP with UART - SMMU - RPMHPD - UFS with Inline Crypto Engine - Watchdog - remoteprocs with smp2p and fastrpc - QUPv3 serial engine protocols - IPCC - PCIe - SPMI PMIC - USB - SD Card - videocc and gpucc - Adreno SMMU - BWMONs - LLCC - Temperature Sensor (TSENS) Written with help from Raviteja Laggyshetty (added interconnect nodes), Taniya Das (added Clock Controllers and cpufreq), Fenglin Wu (added RPMhPD and PMICs), Nitin Rawat (added UFS and SD Card), Kyle Deng (added IPCC and smp2p), Kumari Pallavi (added fastrpc), Vivek Pernamitta (added PCIe), Jyothi Kumar Seerapu(added QUPv3), Krishna Kurapati PSSNV(added USB) and Haritha S K (added TSENS). Co-developed-by: Yijie Yang Signed-off-by: Jingyi Wang Signed-off-by: Yijie Yang Link: https://lore.kernel.org/r/20260922-maili-dts-v1-3-ac2b1b76bfd9@oss.qualcomm.com Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/maili.dtsi | 6956 +++++++++++++++++++++++++++ 1 file changed, 6956 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/maili.dtsi diff --git a/arch/arm64/boot/dts/qcom/maili.dtsi b/arch/arm64/boot/dts/qcom/maili.dtsi new file mode 100644 index 0000000000000..886d307e536be --- /dev/null +++ b/arch/arm64/boot/dts/qcom/maili.dtsi @@ -0,0 +1,6956 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "maili-ipcc.h" + +/ { + interrupt-parent = <&intc>; + + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu6: cpu@0 { + device_type = "cpu"; + compatible = "qcom,oryon-3-0"; + reg = <0x0 0x0>; + enable-method = "psci"; + next-level-cache = <&l2_0>; + power-domains = <&cpu_pd6>, <&scmi_perf 0>; + power-domain-names = "psci", "perf"; + #cooling-cells = <2>; + }; + + cpu7: cpu@100 { + device_type = "cpu"; + compatible = "qcom,oryon-3-0"; + reg = <0x0 0x100>; + enable-method = "psci"; + next-level-cache = <&l2_0>; + power-domains = <&cpu_pd7>, <&scmi_perf 0>; + power-domain-names = "psci", "perf"; + #cooling-cells = <2>; + }; + + cpu3: cpu@200 { + device_type = "cpu"; + compatible = "qcom,oryon-3-1"; + reg = <0x0 0x200>; + enable-method = "psci"; + next-level-cache = <&l2_0>; + power-domains = <&cpu_pd3>, <&scmi_perf 2>; + power-domain-names = "psci", "perf"; + #cooling-cells = <2>; + }; + + cpu0: cpu@300 { + device_type = "cpu"; + compatible = "qcom,oryon-3-2"; + reg = <0x0 0x300>; + enable-method = "psci"; + next-level-cache = <&l2_0>; + power-domains = <&cpu_pd0>, <&scmi_perf 1>; + power-domain-names = "psci", "perf"; + #cooling-cells = <2>; + + l2_0: l2-cache { + compatible = "cache"; + cache-level = <2>; + cache-unified; + }; + }; + + cpu4: cpu@400 { + device_type = "cpu"; + compatible = "qcom,oryon-3-1"; + reg = <0x0 0x400>; + enable-method = "psci"; + next-level-cache = <&l2_0>; + power-domains = <&cpu_pd4>, <&scmi_perf 2>; + power-domain-names = "psci", "perf"; + #cooling-cells = <2>; + }; + + cpu1: cpu@500 { + device_type = "cpu"; + compatible = "qcom,oryon-3-2"; + reg = <0x0 0x500>; + enable-method = "psci"; + next-level-cache = <&l2_0>; + power-domains = <&cpu_pd1>, <&scmi_perf 1>; + power-domain-names = "psci", "perf"; + #cooling-cells = <2>; + }; + + cpu5: cpu@600 { + device_type = "cpu"; + compatible = "qcom,oryon-3-1"; + reg = <0x0 0x600>; + enable-method = "psci"; + next-level-cache = <&l2_0>; + power-domains = <&cpu_pd5>, <&scmi_perf 2>; + power-domain-names = "psci", "perf"; + #cooling-cells = <2>; + }; + + cpu2: cpu@700 { + device_type = "cpu"; + compatible = "qcom,oryon-3-2"; + reg = <0x0 0x700>; + enable-method = "psci"; + next-level-cache = <&l2_0>; + power-domains = <&cpu_pd2>, <&scmi_perf 1>; + power-domain-names = "psci", "perf"; + #cooling-cells = <2>; + }; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + + core1 { + cpu = <&cpu1>; + }; + + core2 { + cpu = <&cpu2>; + }; + }; + + cluster1 { + core0 { + cpu = <&cpu3>; + }; + + core1 { + cpu = <&cpu4>; + }; + + core2 { + cpu = <&cpu5>; + }; + }; + + cluster2 { + core0 { + cpu = <&cpu6>; + }; + + core1 { + cpu = <&cpu7>; + }; + }; + }; + + domain-idle-states { + cluster_cl5: cluster-sleep-0 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x01000054>; + entry-latency-us = <2150>; + exit-latency-us = <1983>; + min-residency-us = <17845>; + }; + + domain_ss3: domain-sleep-0 { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x0200c354>; + entry-latency-us = <2800>; + exit-latency-us = <4400>; + min-residency-us = <19012>; + }; + }; + + idle-states { + entry-method = "psci"; + + cluster0_1_c4: cpu-sleep-0 { + compatible = "arm,idle-state"; + idle-state-name = "retention"; + arm,psci-suspend-param = <0x00000004>; + entry-latency-us = <93>; + exit-latency-us = <129>; + min-residency-us = <1925>; + }; + + cluster2_c4: cpu-sleep-1 { + compatible = "arm,idle-state"; + idle-state-name = "retention"; + arm,psci-suspend-param = <0x00000004>; + entry-latency-us = <172>; + exit-latency-us = <130>; + min-residency-us = <2356>; + }; + }; + }; + + firmware { + scm { + compatible = "qcom,scm-maili", "qcom,scm"; + qcom,dload-mode = <&tcsr 0x2000>; + interconnects = <&aggre_noc MASTER_CRYPTO QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + }; + + scmi { + compatible = "arm,scmi"; + mboxes = <&pdp0_mbox 0>, <&pdp0_mbox 1>; + mbox-names = "tx", "rx"; + shmem = <&pdp_tx>, <&pdp_rx>; + + #address-cells = <1>; + #size-cells = <0>; + + scmi_perf: protocol@13 { + reg = <0x13>; + #power-domain-cells = <1>; + }; + }; + }; + + clk_virt: interconnect-0 { + compatible = "qcom,maili-clk-virt"; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + mc_virt: interconnect-1 { + compatible = "qcom,maili-mc-virt"; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + memory@a0000000 { + device_type = "memory"; + /* We expect the bootloader to fill in the size */ + reg = <0x0 0xa0000000 0x0 0x0>; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + + cpu_pd0: power-domain-cpu0 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&cluster0_1_c4>; + }; + + cpu_pd1: power-domain-cpu1 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&cluster0_1_c4>; + }; + + cpu_pd2: power-domain-cpu2 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&cluster0_1_c4>; + }; + + cpu_pd3: power-domain-cpu3 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&cluster0_1_c4>; + }; + + cpu_pd4: power-domain-cpu4 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&cluster0_1_c4>; + }; + + cpu_pd5: power-domain-cpu5 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&cluster0_1_c4>; + }; + + cpu_pd6: power-domain-cpu6 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&cluster2_c4>; + }; + + cpu_pd7: power-domain-cpu7 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&cluster2_c4>; + }; + + cluster_pd: power-domain-cluster { + #power-domain-cells = <0>; + domain-idle-states = <&cluster_cl5>, + <&domain_ss3>; + }; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + cpucp_slc_mem_sub: cpucp@81230000 { + reg = <0x0 0x81230000 0x0 0x1000>; + no-map; + }; + + aop_cmd_db_mem: aop-cmd-db@81c60000 { + compatible = "qcom,cmd-db"; + reg = <0x0 0x81c60000 0x0 0x20000>; + no-map; + }; + + pdp_ns_shared_mem: pdp-ns-shared@81f00000 { + reg = <0x0 0x81f00000 0x0 0x100000>; + no-map; + }; + + smem_mem: smem@82700000 { + compatible = "qcom,smem"; + reg = <0x0 0x82700000 0x0 0x400000>; + hwlocks = <&tcsr_mutex 3>; + no-map; + }; + + dsm_partition_1_mem: dsm-partition-1@83500000 { + reg = <0x0 0x83500000 0x0 0x5180000>; + no-map; + }; + + dsm_partition_2_mem: dsm-partition-2@88680000 { + reg = <0x0 0x88680000 0x0 0x1700000>; + no-map; + }; + + mpss_mem: mpss@89e00000 { + reg = <0x0 0x89e00000 0x0 0x10400000>; + no-map; + }; + + q6_mpss_dtb_mem: q6-mpss-dtb@98400000 { + reg = <0x0 0x98400000 0x0 0x80000>; + no-map; + }; + + ipa_fw_mem: ipa-fw@99580000 { + reg = <0x0 0x99580000 0x0 0x10000>; + no-map; + }; + + ipa_gsi_mem: ipa-gsi@99590000 { + reg = <0x0 0x99590000 0x0 0xc000>; + no-map; + }; + + gpu_microcode_mem: gpu-microcode@9959c000 { + reg = <0x0 0x9959c000 0x0 0x4000>; + no-map; + }; + + camera_mem: camera@99600000 { + reg = <0x0 0x99600000 0x0 0x800000>; + no-map; + }; + + camera_2_mem: camera-2@99e00000 { + reg = <0x0 0x99e00000 0x0 0x800000>; + no-map; + }; + + video_mem: video@9a600000 { + reg = <0x0 0x9a600000 0x0 0x800000>; + no-map; + }; + + cvp_mem: cvp@9ae00000 { + reg = <0x0 0x9ae00000 0x0 0x800000>; + no-map; + }; + + cdsp_mem: cdsp@9b900000 { + reg = <0x0 0x9b900000 0x0 0x1900000>; + no-map; + }; + + q6_cdsp_dtb_mem: q6-cdsp-dtb@9d200000 { + reg = <0x0 0x9d200000 0x0 0x80000>; + no-map; + }; + + soccp_mem: soccp@a0480000 { + reg = <0x0 0xa0480000 0x0 0x500000>; + no-map; + }; + + soccp_dtb_mem: soccp-dtb@a0980000 { + reg = <0x0 0xa0980000 0x0 0x50000>; + no-map; + }; + + q6_adsp_dtb_mem: q6-adsp-dtb@a1380000 { + reg = <0x0 0xa1380000 0x0 0x80000>; + no-map; + }; + + adspslpi_mem: adspslpi@a1400000 { + reg = <0x0 0xa1400000 0x0 0x4600000>; + no-map; + }; + + mpss_crashdump_overlay_mem: mpss-crashdump-overlay@bd500000 { + reg = <0x0 0xbd500000 0x0 0xf00000>; + no-map; + }; + }; + + smp2p-adsp { + compatible = "qcom,smp2p"; + + interrupts-extended = <&ipcc IPCC_MPROC_LPASS + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + + mboxes = <&ipcc IPCC_MPROC_LPASS + IPCC_MPROC_SIGNAL_SMP2P>; + + qcom,smem = <443>, <429>; + qcom,local-pid = <0>; + qcom,remote-pid = <2>; + + smp2p_adsp_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_adsp_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-cdsp { + compatible = "qcom,smp2p"; + + interrupts-extended = <&ipcc IPCC_MPROC_CDSP + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + + mboxes = <&ipcc IPCC_MPROC_CDSP + IPCC_MPROC_SIGNAL_SMP2P>; + + qcom,smem = <94>, <432>; + qcom,local-pid = <0>; + qcom,remote-pid = <5>; + + smp2p_cdsp_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_cdsp_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-modem { + compatible = "qcom,smp2p"; + + interrupts-extended = <&ipcc IPCC_MPROC_MPSS + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + + mboxes = <&ipcc IPCC_MPROC_MPSS + IPCC_MPROC_SIGNAL_SMP2P>; + + qcom,smem = <435>, <428>; + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + + smp2p_modem_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_modem_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smp2p-soccp { + compatible = "qcom,smp2p"; + + interrupts-extended = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_SMP2P + IRQ_TYPE_EDGE_RISING>; + + mboxes = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_SMP2P>; + + qcom,smem = <617>, <616>; + qcom,local-pid = <0>; + qcom,remote-pid = <19>; + + smp2p_soccp_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,smem-state-cells = <1>; + }; + + smp2p_soccp_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + soc@0 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0 0 0 0x10 0>; + dma-ranges = <0 0 0 0 0x10 0>; + + gcc: clock-controller@100000 { + compatible = "qcom,maili-gcc"; + reg = <0x0 0x00100000 0x0 0x1f4200>; + + clocks = <&bi_tcxo_div2>, + <&bi_tcxo_ao_div2>, + <&sleep_clk>, + <&pcie0_phy>, + <&pcie1_phy>, + <&ufs_mem_phy 0>, + <&ufs_mem_phy 1>, + <&ufs_mem_phy 2>, + <&usb_dp_qmpphy QMP_USB43DP_USB3_PIPE_CLK>; + + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + gpi_dma2: dma-controller@800000 { + compatible = "qcom,maili-gpi-dma", "qcom,sm6350-gpi-dma"; + reg = <0x0 0x00800000 0x0 0x60000>; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + + dma-channels = <12>; + dma-channel-mask = <0x1f>; + #dma-cells = <3>; + + iommus = <&apps_smmu 0x36 0x0>; + dma-coherent; + }; + + qupv3_2: geniqup@8c0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x008c0000 0x0 0x2000>; + + clocks = <&gcc GCC_QUPV3_WRAP_2_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_2_S_AHB_CLK>; + clock-names = "m-ahb", + "s-ahb"; + + iommus = <&apps_smmu 0x23 0x0>; + + dma-coherent; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + i2c8: i2c@880000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00880000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma2 0 0 QCOM_GPI_I2C>, + <&gpi_dma2 1 0 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c8_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart8: serial@880000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x00880000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart8_default>, <&qup_uart8_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi8: spi@880000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00880000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma2 0 0 QCOM_GPI_SPI>, + <&gpi_dma2 1 0 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi8_data_clk>, <&qup_spi8_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c9: i2c@884000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00884000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma2 0 1 QCOM_GPI_I2C>, + <&gpi_dma2 1 1 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c9_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart9: serial@884000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x00884000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart9_default>, <&qup_uart9_cts_rts>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + spi9: spi@884000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00884000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma2 0 1 QCOM_GPI_SPI>, + <&gpi_dma2 1 1 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi9_data_clk>, <&qup_spi9_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c10: i2c@888000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00888000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma2 0 2 QCOM_GPI_I2C>, + <&gpi_dma2 1 2 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c10_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart10: serial@888000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x00888000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart10_default>, <&qup_uart10_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi10: spi@888000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00888000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma2 0 2 QCOM_GPI_SPI>, + <&gpi_dma2 1 2 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi10_data_clk>, <&qup_spi10_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c11: i2c@88c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x0088c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma2 0 3 QCOM_GPI_I2C>, + <&gpi_dma2 1 3 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c11_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart11: serial@88c000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x0088c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart11_default>, <&qup_uart11_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi11: spi@88c000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x0088c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma2 0 3 QCOM_GPI_SPI>, + <&gpi_dma2 1 3 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi11_data_clk>, <&qup_spi11_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c12: i2c@890000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00890000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_2 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma2 0 4 QCOM_GPI_I2C>, + <&gpi_dma2 1 4 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c12_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart12: serial@890000 { + compatible = "qcom,geni-debug-uart"; + reg = <0x0 0x00890000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP2_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart12_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + }; + + i2c_master_hub: geniqup@9c0000 { + compatible = "qcom,geni-se-i2c-master-hub"; + reg = <0x0 0x009c0000 0x0 0x2000>; + + clocks = <&gcc GCC_QUPV3_I2C_S_AHB_CLK>; + clock-names = "s-ahb"; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + i2c_hub_0: i2c@980000 { + compatible = "qcom,geni-i2c-master-hub"; + reg = <0x0 0x00980000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_I2C_S0_CLK>, + <&gcc GCC_QUPV3_I2C_CORE_CLK>; + clock-names = "se", + "core"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_I2C QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&hub_i2c0_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c_hub_1: i2c@984000 { + compatible = "qcom,geni-i2c-master-hub"; + reg = <0x0 0x00984000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_I2C_S1_CLK>, + <&gcc GCC_QUPV3_I2C_CORE_CLK>; + clock-names = "se", + "core"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_I2C QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&hub_i2c1_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c_hub_2: i2c@988000 { + compatible = "qcom,geni-i2c-master-hub"; + reg = <0x0 0x00988000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_I2C_S2_CLK>, + <&gcc GCC_QUPV3_I2C_CORE_CLK>; + clock-names = "se", + "core"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_I2C QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&hub_i2c2_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c_hub_3: i2c@98c000 { + compatible = "qcom,geni-i2c-master-hub"; + reg = <0x0 0x0098c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_I2C_S3_CLK>, + <&gcc GCC_QUPV3_I2C_CORE_CLK>; + clock-names = "se", + "core"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_I2C QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&hub_i2c3_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c_hub_4: i2c@990000 { + compatible = "qcom,geni-i2c-master-hub"; + reg = <0x0 0x00990000 0x0 0x4000>; + + interrupts = ; + clocks = <&gcc GCC_QUPV3_I2C_S4_CLK>, + <&gcc GCC_QUPV3_I2C_CORE_CLK>; + clock-names = "se", + "core"; + + interconnects = <&clk_virt MASTER_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_0 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_I2C QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&hub_i2c4_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + }; + + gpi_dma1: dma-controller@a00000 { + compatible = "qcom,maili-gpi-dma", "qcom,sm6350-gpi-dma"; + reg = <0x0 0x00a00000 0x0 0x60000>; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + + dma-channels = <16>; + dma-channel-mask = <0x7f>; + #dma-cells = <3>; + + iommus = <&apps_smmu 0xb6 0x0>; + dma-coherent; + }; + + qupv3_1: geniqup@ac0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x00ac0000 0x0 0x2000>; + + clocks = <&gcc GCC_QUPV3_WRAP_1_M_AXI_CLK>, + <&gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>; + clock-names = "m-ahb", "s-ahb"; + + iommus = <&apps_smmu 0xa3 0x0>; + + dma-coherent; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + i2c0: i2c@a80000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma1 0 0 QCOM_GPI_I2C>, + <&gpi_dma1 1 0 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c0_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart0: serial@a80000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x00a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart0_default>, <&qup_uart0_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi0: spi@a80000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma1 0 0 QCOM_GPI_SPI>, + <&gpi_dma1 1 0 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi0_data_clk>, <&qup_spi0_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c1: i2c@a84000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00a84000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma1 0 1 QCOM_GPI_I2C>, + <&gpi_dma1 1 1 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c1_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart1: serial@a84000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x00a84000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart1_default>, <&qup_uart1_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi1: spi@a84000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00a84000 0x0 0x4000>; + + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma1 0 1 QCOM_GPI_SPI>, + <&gpi_dma1 1 1 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi1_data_clk>, <&qup_spi1_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c2: i2c@a88000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00a88000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma1 0 2 QCOM_GPI_I2C>, + <&gpi_dma1 1 2 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c2_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart2: serial@a88000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x00a88000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart2_default>, <&qup_uart2_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi2: spi@a88000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00a88000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma1 0 2 QCOM_GPI_SPI>, + <&gpi_dma1 1 2 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi2_data_clk>, <&qup_spi2_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c3: i2c@a8c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00a8c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma1 0 3 QCOM_GPI_I2C>, + <&gpi_dma1 1 3 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c3_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart3: serial@a8c000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x00a8c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart3_default>, <&qup_uart3_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi3: spi@a8c000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00a8c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma1 0 3 QCOM_GPI_SPI>, + <&gpi_dma1 1 3 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi3_data_clk>, <&qup_spi3_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c4: i2c@a90000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00a90000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma1 0 4 QCOM_GPI_I2C>, + <&gpi_dma1 1 4 QCOM_GPI_I2C>; + + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c4_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart4: serial@a90000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x00a90000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart4_default>, <&qup_uart4_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi4: spi@a90000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00a90000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma1 0 4 QCOM_GPI_SPI>, + <&gpi_dma1 1 4 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi4_data_clk>, <&qup_spi4_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c5: i2c@a94000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00a94000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma1 0 5 QCOM_GPI_I2C>, + <&gpi_dma1 1 5 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c5_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart5: serial@a94000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x00a94000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart5_default>, <&qup_uart5_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi5: spi@a94000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00a94000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma1 0 5 QCOM_GPI_SPI>, + <&gpi_dma1 1 5 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi5_data_clk>, <&qup_spi5_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c6: i2c@a98000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00a98000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S6_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma1 0 6 QCOM_GPI_I2C>, + <&gpi_dma1 1 6 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c6_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart6: serial@a98000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x00a98000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S6_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart6_default>, <&qup_uart6_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi6: spi@a98000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00a98000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S6_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma1 0 6 QCOM_GPI_SPI>, + <&gpi_dma1 1 6 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi6_data_clk>, <&qup_spi6_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c7: i2c@a9c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x00a9c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S7_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma1 0 7 QCOM_GPI_I2C>, + <&gpi_dma1 1 7 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c7_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart7: serial@a9c000 { + compatible = "qcom,geni-debug-uart"; + reg = <0x0 0x00a9c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S7_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart7_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi7: spi@a9c000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x00a9c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP1_S7_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma1 0 7 QCOM_GPI_SPI>, + <&gpi_dma1 1 7 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi7_data_clk>, <&qup_spi7_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + }; + + remoteproc_soccp: remoteproc@d00000 { + compatible = "qcom,maili-soccp-pas", "qcom,kaanapali-soccp-pas"; + reg = <0x0 0x00d00000 0x0 0x200000>; + + interrupts-extended = <&intc GIC_ESPI 231 IRQ_TYPE_EDGE_RISING>, + <&smp2p_soccp_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_soccp_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_soccp_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_soccp_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_soccp_in 9 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "pong"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MX>; + power-domain-names = "cx", + "mx"; + + memory-region = <&soccp_mem>, + <&soccp_dtb_mem>; + + qcom,smem-states = <&smp2p_soccp_out 0>, + <&smp2p_soccp_out 8>; + qcom,smem-state-names = "stop", + "ping"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + + mboxes = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "soccp"; + qcom,remote-pid = <19>; + }; + }; + + aggre_noc: interconnect@f00000 { + compatible = "qcom,maili-aggre-noc"; + reg = <0x0 0x00f00000 0x0 0x56200>; + #interconnect-cells = <2>; + clocks = <&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>, + <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>, + <&rpmhcc RPMH_IPA_CLK>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + usb_hsphy: phy@fe3000 { + compatible = "qcom,maili-m31-eusb2-phy", "qcom,sm8750-m31-eusb2-phy"; + reg = <0x0 0x00fe3000 0x0 0x29c>; + + clocks = <&tcsrcc TCSR_USB2_CLKREF_EN>; + clock-names = "ref"; + + resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_dp_qmpphy: phy@fe8000 { + compatible = "qcom,maili-qmp-usb3-dp-phy", "qcom,hawi-qmp-usb3-dp-phy"; + reg = <0x0 0x00fe8000 0x0 0x4000>; + + clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, + <&tcsrcc TCSR_USB3_CLKREF_EN>, + <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>, + <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; + clock-names = "aux", + "ref", + "com_aux", + "usb3_pipe"; + + resets = <&gcc GCC_USB3_PHY_PRIM_BCR>, + <&gcc GCC_USB3_DP_PHY_PRIM_BCR>; + reset-names = "phy", + "common"; + + power-domains = <&gcc GCC_USB3_PHY_GDSC>; + + #clock-cells = <1>; + #phy-cells = <1>; + + orientation-switch; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_dp_qmpphy_out: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_dp_qmpphy_usb_ss_in: endpoint { + remote-endpoint = <&usb_dwc3_ss>; + }; + }; + + port@2 { + reg = <2>; + + usb_dp_qmpphy_dp_in: endpoint { + }; + }; + }; + }; + + rng@10c3000 { + compatible = "qcom,maili-trng", "qcom,trng"; + reg = <0x0 0x010c3000 0x0 0x1000>; + }; + + ipcc: mailbox@1106000 { + compatible = "qcom,maili-ipcc", "qcom,ipcc"; + reg = <0x0 0x01106000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + }; + + cnoc_main: interconnect@1500000 { + compatible = "qcom,maili-cnoc-main"; + reg = <0x0 0x01500000 0x0 0x20000>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + system_noc: interconnect@1680000 { + compatible = "qcom,maili-system-noc"; + reg = <0x0 0x01680000 0x0 0x20080>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + pcie_anoc: interconnect@16c0000 { + compatible = "qcom,maili-pcie-anoc"; + reg = <0x0 0x016c0000 0x0 0x12400>; + #interconnect-cells = <2>; + clocks = <&gcc GCC_AGGRE_NOC_PCIE_AXI_CLK>, + <&gcc GCC_CFG_NOC_PCIE_ANOC_AHB_CLK>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + mmss_noc: interconnect@1780000 { + compatible = "qcom,maili-mmss-noc"; + reg = <0x0 0x01780000 0x0 0x5f800>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + gpi_dma3: dma-controller@1900000 { + compatible = "qcom,maili-gpi-dma", "qcom,sm6350-gpi-dma"; + reg = <0x0 0x01900000 0x0 0x60000>; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + + dma-channels = <12>; + dma-channel-mask = <0x1f>; + #dma-cells = <3>; + + iommus = <&apps_smmu 0xd6 0x0>; + dma-coherent; + }; + + qupv3_3: geniqup@19c0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x019c0000 0x0 0x2000>; + + clocks = <&gcc GCC_QUPV3_WRAP_3_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_3_S_AHB_CLK>; + clock-names = "m-ahb", + "s-ahb"; + + iommus = <&apps_smmu 0xc3 0x0>; + + dma-coherent; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + i2c13: i2c@1980000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x01980000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_3 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma3 0 0 QCOM_GPI_I2C>, + <&gpi_dma3 1 0 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c13_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart13: serial@1980000 { + compatible = "qcom,geni-debug-uart"; + reg = <0x0 0x01980000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart13_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi13: spi@1980000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x01980000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma3 0 0 QCOM_GPI_SPI>, + <&gpi_dma3 1 0 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi13_data_clk>, <&qup_spi13_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c14: i2c@1984000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x01984000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_3 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma3 0 1 QCOM_GPI_I2C>, + <&gpi_dma3 1 1 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c14_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart14: serial@1984000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x01984000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart14_default>, <&qup_uart14_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi14: spi@1984000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x01984000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma3 0 1 QCOM_GPI_SPI>, + <&gpi_dma3 1 1 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi14_data_clk>, <&qup_spi14_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c15: i2c@1988000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x01988000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_3 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma3 0 2 QCOM_GPI_I2C>, + <&gpi_dma3 1 2 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c15_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart15: serial@1988000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x01988000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart15_default>, <&qup_uart15_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi15: spi@1988000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x01988000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma3 0 2 QCOM_GPI_SPI>, + <&gpi_dma3 1 2 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi15_data_clk>, <&qup_spi15_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c16: i2c@198c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x0198c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_3 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma3 0 3 QCOM_GPI_I2C>, + <&gpi_dma3 1 3 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c16_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart16: serial@198c000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x0198c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart16_default>, <&qup_uart16_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi16: spi@198c000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x0198c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma3 0 3 QCOM_GPI_SPI>, + <&gpi_dma3 1 3 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi16_data_clk>, <&qup_spi16_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c17: i2c@1990000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x01990000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_3 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma3 0 4 QCOM_GPI_I2C>, + <&gpi_dma3 1 4 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c17_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart17: serial@1990000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x01990000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart17_default>, <&qup_uart17_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi17: spi@1990000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x01990000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma3 0 4 QCOM_GPI_SPI>, + <&gpi_dma3 1 4 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi17_data_clk>, <&qup_spi17_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c18: i2c@1994000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x01994000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_3 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma3 0 5 QCOM_GPI_I2C>, + <&gpi_dma3 1 5 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c18_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart18: serial@1994000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x01994000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart18_default>, <&qup_uart18_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi18: spi@1994000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x01994000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP3_S5_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_3 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma3 0 5 QCOM_GPI_SPI>, + <&gpi_dma3 1 5 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi18_data_clk>, <&qup_spi18_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + }; + + gpi_dma4: dma-controller@1a00000 { + compatible = "qcom,maili-gpi-dma", "qcom,sm6350-gpi-dma"; + reg = <0x0 0x01a00000 0x0 0x60000>; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + ; + + dma-channels = <12>; + dma-channel-mask = <0x1f>; + #dma-cells = <3>; + + iommus = <&apps_smmu 0x136 0x0>; + dma-coherent; + }; + + qupv3_4: geniqup@1ac0000 { + compatible = "qcom,geni-se-qup"; + reg = <0x0 0x01ac0000 0x0 0x2000>; + + clocks = <&gcc GCC_QUPV3_WRAP_4_M_AHB_CLK>, + <&gcc GCC_QUPV3_WRAP_4_S_AHB_CLK>; + clock-names = "m-ahb", + "s-ahb"; + + iommus = <&apps_smmu 0x123 0x0>; + + dma-coherent; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + i2c19: i2c@1a80000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x01a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_4 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma4 0 0 QCOM_GPI_I2C>, + <&gpi_dma4 1 0 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c19_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart19: serial@1a80000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x01a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart19_default>, <&qup_uart19_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi19: spi@1a80000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x01a80000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S0_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma4 0 0 QCOM_GPI_SPI>, + <&gpi_dma4 1 0 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi19_data_clk>, <&qup_spi19_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c20: i2c@1a84000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x01a84000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_4 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma4 0 1 QCOM_GPI_I2C>, + <&gpi_dma4 1 1 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c20_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart20: serial@1a84000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x01a84000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart20_default>, <&qup_uart20_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi20: spi@1a84000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x01a84000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S1_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma4 0 1 QCOM_GPI_SPI>, + <&gpi_dma4 1 1 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi20_data_clk>, <&qup_spi20_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c21: i2c@1a88000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x01a88000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_4 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma4 0 2 QCOM_GPI_I2C>, + <&gpi_dma4 1 2 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c21_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart21: serial@1a88000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x01a88000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart21_default>, <&qup_uart21_cts_rts>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + spi21: spi@1a88000 { + compatible = "qcom,geni-spi"; + reg = <0x0 0x01a88000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S2_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + dmas = <&gpi_dma4 0 2 QCOM_GPI_SPI>, + <&gpi_dma4 1 2 QCOM_GPI_SPI>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_spi21_data_clk>, <&qup_spi21_cs>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + i2c22: i2c@1a8c000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x01a8c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_4 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma4 0 3 QCOM_GPI_I2C>, + <&gpi_dma4 1 3 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c22_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart22: serial@1a8c000 { + compatible = "qcom,geni-debug-uart"; + reg = <0x0 0x01a8c000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S3_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart22_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + + i2c23: i2c@1a90000 { + compatible = "qcom,geni-i2c"; + reg = <0x0 0x01a90000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>, + <&aggre_noc MASTER_QUP_4 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "qup-core", + "qup-config", + "qup-memory"; + + dmas = <&gpi_dma4 0 4 QCOM_GPI_I2C>, + <&gpi_dma4 1 4 QCOM_GPI_I2C>; + dma-names = "tx", + "rx"; + + pinctrl-0 = <&qup_i2c23_data_clk>; + pinctrl-names = "default"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + uart23: serial@1a90000 { + compatible = "qcom,geni-debug-uart"; + reg = <0x0 0x01a90000 0x0 0x4000>; + + interrupts = ; + + clocks = <&gcc GCC_QUPV3_WRAP4_S4_CLK>; + clock-names = "se"; + + interconnects = <&clk_virt MASTER_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS + &clk_virt SLAVE_QUP_CORE_4 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_QUP_4 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "qup-core", + "qup-config"; + + pinctrl-0 = <&qup_uart23_default>; + pinctrl-names = "default"; + + status = "disabled"; + }; + }; + + pcie0: pcie@1c00000 { + device_type = "pci"; + compatible = "qcom,maili-pcie", "qcom,hawi-pcie"; + reg = <0x0 0x01c00000 0x0 0x3000>, + <0x0 0x40000000 0x0 0xf1d>, + <0x0 0x40000f20 0x0 0xa8>, + <0x0 0x40001000 0x0 0x1000>, + <0x0 0x40100000 0x0 0x100000>, + <0x0 0x01c03000 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 0x3d00000>; + + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "msi0", + "msi1", + "msi2", + "msi3", + "msi4", + "msi5", + "msi6", + "msi7", + "global"; + + clocks = <&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>, + <&gcc GCC_AGGRE_NOC_PCIE_AXI_CLK>, + <&gcc GCC_CNOC_PCIE_SF_AXI_CLK>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "noc_aggr", + "cnoc_sf_axi"; + + resets = <&gcc GCC_PCIE_0_BCR>, + <&gcc GCC_PCIE_0_LINK_DOWN_BCR>; + reset-names = "pci", + "link_down"; + + interconnects = <&pcie_anoc MASTER_PCIE_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &cnoc_main SLAVE_PCIE_0 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "pcie-mem", + "cpu-pcie"; + + power-domains = <&gcc GCC_PCIE_0_GDSC>; + + eq-presets-8gts = /bits/ 16 <0x5555 0x5555>; + + operating-points-v2 = <&pcie0_opp_table>; + + iommu-map = <0x0 &apps_smmu 0x1000 0x1>, + <0x100 &apps_smmu 0x1001 0x1>; + + interrupt-map = <0 0 0 1 &intc 0 0 GIC_ESPI 149 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 GIC_ESPI 150 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 GIC_ESPI 151 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 GIC_ESPI 152 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 0x7>; + #interrupt-cells = <1>; + + msi-map = <0x0 &gic_its 0x1000 0x1>, + <0x100 &gic_its 0x1001 0x1>; + msi-map-mask = <0xff00>; + + linux,pci-domain = <0>; + bus-range = <0x00 0xff>; + + pinctrl-0 = <&pcie0_default_state>; + pinctrl-names = "default"; + + dma-coherent; + + status = "disabled"; + + pcie0_opp_table: opp-table { + compatible = "operating-points-v2"; + + /* 2.5 GT/s x1 */ + opp-2500000-1 { + opp-hz = /bits/ 64 <2500000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* 2.5 GT/s x2 */ + opp-5000000-1 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + opp-peak-kBps = <500000 1>; + opp-level = <1>; + }; + + /* 5.0 GT/s x1 */ + opp-5000000-2 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + + /* 8.0 GT/s x1 */ + opp-8000000-3 { + opp-hz = /bits/ 64 <8000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <984500 1>; + opp-level = <3>; + }; + + /* 5.0 GT/s x2 */ + opp-10000000-2 { + opp-hz = /bits/ 64 <10000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + opp-peak-kBps = <1000000 1>; + opp-level = <2>; + }; + + /* 8.0 GT/s x2 */ + opp-16000000-3 { + opp-hz = /bits/ 64 <16000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1969000 1>; + opp-level = <3>; + }; + }; + + pcie_port0: pcie@0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + bus-range = <0x01 0xff>; + + #address-cells = <3>; + #size-cells = <2>; + ranges; + phys = <&pcie0_phy>; + }; + }; + + pcie0_phy: phy@1c06000 { + compatible = "qcom,maili-qmp-gen3x2-pcie-phy", + "qcom,hawi-qmp-gen3x2-pcie-phy"; + reg = <0x0 0x01c06000 0x0 0x2000>; + + clocks = <&gcc GCC_PCIE_0_PHY_AUX_CLK>, + <&gcc GCC_PCIE_0_CFG_AHB_CLK>, + <&tcsrcc TCSR_PCIE_0_CLKREF_EN>, + <&gcc GCC_PCIE_0_PHY_RCHNG_CLK>, + <&gcc GCC_PCIE_0_PIPE_CLK>, + <&gcc GCC_PCIE_0_PIPE_DIV2_CLK>; + clock-names = "aux", + "cfg_ahb", + "ref", + "rchng", + "pipe", + "pipediv2"; + + assigned-clocks = <&gcc GCC_PCIE_0_PHY_RCHNG_CLK>; + assigned-clock-rates = <100000000>; + + resets = <&gcc GCC_PCIE_0_PHY_BCR>, + <&gcc GCC_PCIE_0_NOCSR_COM_PHY_BCR>; + reset-names = "phy", + "phy_nocsr"; + + power-domains = <&gcc GCC_PCIE_0_PHY_GDSC>; + + #clock-cells = <0>; + clock-output-names = "pcie0_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + + pcie1: pcie@1c18000 { + device_type = "pci"; + compatible = "qcom,maili-pcie", "qcom,hawi-pcie"; + reg = <0x0 0x01c18000 0x0 0x3000>, + <0x0 0x64000000 0x0 0xf1d>, + <0x0 0x64000f20 0x0 0xa8>, + <0x0 0x64001000 0x0 0x1000>, + <0x0 0x64100000 0x0 0x100000>, + <0x0 0x01c1b000 0x0 0x1000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x01000000 0x0 0x00000000 0x0 0x64200000 0x0 0x100000>, + <0x02000000 0x0 0x64300000 0x0 0x64300000 0x0 0x1bd00000>; + + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "msi0", "msi1", "msi2", "msi3", + "msi4", "msi5", "msi6", "msi7", "global"; + + clocks = <&gcc GCC_PCIE_1_AUX_CLK>, + <&gcc GCC_PCIE_1_CFG_AHB_CLK>, + <&gcc GCC_PCIE_1_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_1_SLV_AXI_CLK>, + <&gcc GCC_PCIE_1_SLV_Q2A_AXI_CLK>, + <&gcc GCC_AGGRE_NOC_PCIE_AXI_CLK>, + <&gcc GCC_CNOC_PCIE_SF_AXI_CLK>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "noc_aggr", + "cnoc_sf_axi"; + + resets = <&gcc GCC_PCIE_1_BCR>, + <&gcc GCC_PCIE_1_LINK_DOWN_BCR>; + reset-names = "pci", + "link_down"; + + interconnects = <&pcie_anoc MASTER_PCIE_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &cnoc_main SLAVE_PCIE_1 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "pcie-mem", + "cpu-pcie"; + + power-domains = <&gcc GCC_PCIE_1_GDSC>; + + eq-presets-8gts = /bits/ 16 <0x5555 0x5555>; + + operating-points-v2 = <&pcie1_opp_table>; + + iommu-map = <0x0 &apps_smmu 0x1080 0x1>, + <0x100 &apps_smmu 0x1081 0x1>; + + interrupt-map = <0 0 0 1 &intc 0 0 GIC_ESPI 42 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 GIC_ESPI 43 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 GIC_ESPI 44 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 GIC_ESPI 45 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 0x7>; + #interrupt-cells = <1>; + + msi-map = <0x0 &gic_its 0x1080 0x1>, + <0x100 &gic_its 0x1081 0x1>; + msi-map-mask = <0xff00>; + linux,pci-domain = <1>; + bus-range = <0x00 0xff>; + + pinctrl-0 = <&pcie1_default_state>; + pinctrl-names = "default"; + + dma-coherent; + + status = "disabled"; + + pcie1_opp_table: opp-table { + compatible = "operating-points-v2"; + + /* 2.5 GT/s x1 */ + opp-2500000-1 { + opp-hz = /bits/ 64 <2500000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* 2.5 GT/s x2 */ + opp-5000000-1 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + opp-peak-kBps = <500000 1>; + opp-level = <1>; + }; + + /* 5.0 GT/s x1 */ + opp-5000000-2 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + + /* 8.0 GT/s x1 */ + opp-8000000-3 { + opp-hz = /bits/ 64 <8000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <984500 1>; + opp-level = <3>; + }; + + /* 5.0 GT/s x2 */ + opp-10000000-2 { + opp-hz = /bits/ 64 <10000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + opp-peak-kBps = <1000000 1>; + opp-level = <2>; + }; + + /* 8.0 GT/s x2 */ + opp-16000000-3 { + opp-hz = /bits/ 64 <16000000>; + required-opps = <&rpmhpd_opp_low_svs>; + opp-peak-kBps = <1969000 1>; + opp-level = <3>; + }; + + /* 16.0 GT/s x1 */ + opp-16000000-4 { + opp-hz = /bits/ 64 <16000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <1969000 1>; + opp-level = <4>; + }; + + /* 16.0 GT/s x2 */ + opp-32000000-3 { + opp-hz = /bits/ 64 <32000000>; + required-opps = <&rpmhpd_opp_svs>; + opp-peak-kBps = <3938000 1>; + opp-level = <4>; + }; + }; + + pcie_port1: pcie@0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + bus-range = <0x01 0xff>; + + #address-cells = <3>; + #size-cells = <2>; + ranges; + phys = <&pcie1_phy>; + }; + }; + + pcie1_phy: phy@1c1e000 { + compatible = "qcom,maili-qmp-gen4x1-pcie-phy", + "qcom,hawi-qmp-gen4x1-pcie-phy"; + reg = <0x0 0x01c1e000 0x0 0x2000>; + + clocks = <&gcc GCC_PCIE_1_PHY_AUX_CLK>, + <&gcc GCC_PCIE_1_CFG_AHB_CLK>, + <&tcsrcc TCSR_PCIE_1_CLKREF_EN>, + <&gcc GCC_PCIE_1_PHY_RCHNG_CLK>, + <&gcc GCC_PCIE_1_PIPE_CLK>, + <&gcc GCC_PCIE_1_PIPE_DIV2_CLK>; + clock-names = "aux", + "cfg_ahb", + "ref", + "rchng", + "pipe", + "pipediv2"; + + assigned-clocks = <&gcc GCC_PCIE_1_PHY_RCHNG_CLK>; + assigned-clock-rates = <100000000>; + + resets = <&gcc GCC_PCIE_1_PHY_BCR>, + <&gcc GCC_PCIE_1_NOCSR_COM_PHY_BCR>; + reset-names = "phy", + "phy_nocsr"; + + power-domains = <&gcc GCC_PCIE_1_PHY_GDSC>; + + #clock-cells = <0>; + clock-output-names = "pcie1_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + + sdhc_2: mmc@1c44000 { + compatible = "qcom,maili-sdhci", "qcom,sdhci-msm-v5"; + reg = <0x0 0x01c44000 0x0 0x1000>; + + interrupts = , + ; + interrupt-names = "hc_irq", "pwr_irq"; + + clocks = <&gcc GCC_SDCC2_AHB_CLK>, + <&gcc GCC_SDCC2_APPS_CLK>, + <&rpmhcc RPMH_CXO_CLK>; + + clock-names = "iface", "core", "xo"; + + interconnects = <&aggre_noc MASTER_SDCC_2 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_SDCC_2 QCOM_ICC_TAG_ACTIVE_ONLY>; + + interconnect-names = "sdhc-ddr", "cpu-sdhc"; + + power-domains = <&rpmhpd RPMHPD_CX>; + operating-points-v2 = <&sdhc2_opp_table>; + + qcom,dll-config = <0x0007442c>; + qcom,ddr-config = <0x80040868>; + + iommus = <&apps_smmu 0x140 0x0>; + dma-coherent; + + bus-width = <4>; + max-sd-hs-hz = <37500000>; + + resets = <&gcc GCC_SDCC2_BCR>; + status = "disabled"; + + sdhc2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-peak-kBps = <160000 100000>; + opp-avg-kBps = <50000 0>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-202000000 { + opp-hz = /bits/ 64 <202000000>; + opp-peak-kBps = <200000 120000>; + opp-avg-kBps = <104000 0>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + + }; + + ufs_mem_phy: phy@1d80000 { + compatible = "qcom,maili-qmp-ufs-phy", "qcom,hawi-qmp-ufs-phy"; + reg = <0x0 0x01d80000 0x0 0x4000>; + + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_UFS_PHY_PHY_AUX_CLK>, + <&tcsrcc TCSR_UFS_CLKREF_EN>; + + clock-names = "ref", + "ref_aux", + "qref"; + + resets = <&ufs_mem_hc 0>; + reset-names = "ufsphy"; + + power-domains = <&gcc GCC_UFS_MEM_PHY_GDSC>; + + #clock-cells = <1>; + #phy-cells = <0>; + + status = "disabled"; + }; + + ufs_mem_hc: ufshc@1d84000 { + compatible = "qcom,maili-ufshc", + "qcom,ufshc", + "jedec,ufs-2.0"; + reg = <0x0 0x01d84000 0x0 0x3000>, + <0x0 0x01da0000 0x0 0x15000>; + + reg-names = "std", + "mcq"; + + interrupts = ; + + clocks = <&gcc GCC_UFS_PHY_AXI_CLK>, + <&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>, + <&gcc GCC_UFS_PHY_AHB_CLK>, + <&gcc GCC_UFS_PHY_UNIPRO_5_CORE_CLK>, + <&rpmhcc RPMH_LN_BB_CLK3>, + <&gcc GCC_UFS_PHY_TX_SYMBOL_0_CLK>, + <&gcc GCC_UFS_PHY_RX_SYMBOL_0_CLK>, + <&gcc GCC_UFS_PHY_RX_SYMBOL_1_CLK>; + + clock-names = "core_clk", + "bus_aggr_clk", + "iface_clk", + "core_clk_unipro", + "ref_clk", + "tx_lane0_sync_clk", + "rx_lane0_sync_clk", + "rx_lane1_sync_clk"; + + operating-points-v2 = <&ufs_opp_table>; + + resets = <&gcc GCC_UFS_PHY_BCR>; + reset-names = "rst"; + + interconnects = <&aggre_noc MASTER_UFS_MEM 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_UFS_MEM_CFG QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "ufs-ddr", + "cpu-ufs"; + + power-domains = <&gcc GCC_UFS_PHY_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + iommus = <&apps_smmu 0x60 0x0>; + dma-coherent; + + msi-parent = <&gic_its 0x60>; + + lanes-per-direction = <2>; + limit-hs-gear = <5>; + + phys = <&ufs_mem_phy>; + phy-names = "ufsphy"; + + qcom,ice = <&ice>; + + #reset-cells = <1>; + + status = "disabled"; + + ufs_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <100000000>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <0>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-403000000 { + opp-hz = /bits/ 64 <403000000>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <403000000>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <0>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + ice: crypto@1d88000 { + compatible = "qcom,maili-inline-crypto-engine", + "qcom,inline-crypto-engine"; + reg = <0x0 0x01d88000 0x0 0x18000>; + + clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>, + <&gcc GCC_UFS_PHY_AHB_CLK>; + clock-names = "core", + "iface"; + + power-domains = <&gcc GCC_UFS_PHY_GDSC>; + }; + + videocc: clock-controller@20f0000 { + compatible = "qcom,maili-videocc"; + reg = <0x0 0x020f0000 0x0 0x10000>; + + clocks = <&bi_tcxo_div2>, + <&gcc GCC_VIDEO_AHB_CLK>; + + power-domains = <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + required-opps = <&rpmhpd_opp_low_svs_d2>, + <&rpmhpd_opp_low_svs_d2>; + + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + apps_smmu: iommu@2e00000 { + compatible = "qcom,maili-smmu-500", "qcom,smmu-500", "arm,mmu-500"; + reg = <0x0 0x02e00000 0x0 0x100000>; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + + #iommu-cells = <2>; + #global-interrupts = <1>; + + dma-coherent; + }; + + stdst_noc: interconnect@3000000 { + compatible = "qcom,maili-stdst-main"; + reg = <0x0 0x03000000 0x0 0xf9000>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + tcsr: syscon@3a70000 { + compatible = "qcom,maili-tcsr", "syscon"; + reg = <0x0 0x03a70000 0x0 0x10000>; + }; + + tcsr_mutex: hwlock@3ad3000 { + compatible = "qcom,tcsr-mutex"; + reg = <0x0 0x03ad3000 0x0 0x20000>; + #hwlock-cells = <1>; + }; + + tcsrcc: clock-controller@3b13040 { + compatible = "qcom,maili-tcsrcc", "qcom,hawi-tcsrcc", "syscon"; + reg = <0x0 0x03b13040 0x0 0x50>; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + + #clock-cells = <1>; + #reset-cells = <1>; + }; + + gxclkctl: clock-controller@3d64000 { + compatible = "qcom,maili-gxclkctl", "qcom,kaanapali-gxclkctl"; + reg = <0x0 0x03d64000 0x0 0x6000>; + + power-domains = <&rpmhpd RPMHPD_GFX>, + <&rpmhpd RPMHPD_GMXC>, + <&gpucc GPU_CC_CX_GDSC>; + + #power-domain-cells = <1>; + }; + + gpucc: clock-controller@3d90000 { + compatible = "qcom,maili-gpucc"; + reg = <0x0 0x03d90000 0x0 0x9800>; + + clocks = <&bi_tcxo_div2>, + <&gcc GCC_GPU_GPLL0_CLK_SRC>, + <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MX>, + <&rpmhpd RPMHPD_GMXC>; + required-opps = <&rpmhpd_opp_low_svs_d3>, + <&rpmhpd_opp_low_svs_d3>, + <&rpmhpd_opp_low_svs_d3>; + + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + adreno_smmu: iommu@3da0000 { + compatible = "qcom,maili-smmu-500", "qcom,adreno-smmu", + "qcom,smmu-500", "arm,mmu-500"; + reg = <0x0 0x03da0000 0x0 0x40000>; + #iommu-cells = <2>; + #global-interrupts = <1>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + clocks = <&gpucc GPU_CC_GPU_SMMU_VOTE_CLK>; + clock-names = "hlos"; + power-domains = <&gpucc GPU_CC_CX_GDSC>; + dma-coherent; + }; + + remoteproc_mpss: remoteproc@4000000 { + compatible = "qcom,maili-mpss-pas", "qcom,sm8650-mpss-pas"; + reg = <0x0 0x04000000 0x0 0x10000>; + + interrupts-extended = <&intc GIC_ESPI 328 IRQ_TYPE_EDGE_RISING>, + <&smp2p_modem_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_modem_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_modem_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_modem_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_modem_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + interconnects = <&mc_virt MASTER_LLCC QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MSS>; + power-domain-names = "cx", + "mss"; + + memory-region = <&mpss_mem>, <&q6_mpss_dtb_mem>, + <&dsm_partition_1_mem>, <&dsm_partition_2_mem>, + <&mpss_crashdump_overlay_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_modem_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_MPROC_MPSS + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + + mboxes = <&ipcc IPCC_MPROC_MPSS + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "mpss"; + qcom,remote-pid = <1>; + }; + }; + + remoteproc_adsp: remoteproc@7000000 { + compatible = "qcom,maili-adsp-pas", "qcom,sm8550-adsp-pas"; + reg = <0x0 0x07000000 0x0 0x10000>; + + interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + interconnects = <&lpass_lpicx_noc MASTER_LPASS_PROC QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + + power-domains = <&rpmhpd RPMHPD_LCX>, + <&rpmhpd RPMHPD_LMX>; + power-domain-names = "lcx", + "lmx"; + + memory-region = <&adspslpi_mem>, <&q6_adsp_dtb_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_adsp_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_MPROC_LPASS + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + + mboxes = <&ipcc IPCC_MPROC_LPASS + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "lpass"; + qcom,remote-pid = <2>; + + fastrpc { + compatible = "qcom,maili-fastrpc", "qcom,kaanapali-fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "adsp"; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + + iommus = <&apps_smmu 0x0c03 0x80>, + <&apps_smmu 0x0c43 0x20>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + + iommus = <&apps_smmu 0x0c04 0x80>, + <&apps_smmu 0x0c44 0x20>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + + iommus = <&apps_smmu 0x0c05 0x80>, + <&apps_smmu 0x0c45 0x20>; + dma-coherent; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + + iommus = <&apps_smmu 0x0c06 0x80>, + <&apps_smmu 0x0c46 0x20>; + dma-coherent; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + + iommus = <&apps_smmu 0x0c07 0x80>, + <&apps_smmu 0x0c47 0x20>; + dma-coherent; + }; + + compute-cb@8 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <8>; + + iommus = <&apps_smmu 0x0c08 0x80>, + <&apps_smmu 0x0c48 0x20>; + dma-coherent; + }; + }; + }; + }; + + lpass_lpiaon_noc: interconnect@7c00000 { + compatible = "qcom,maili-lpass-lpiaon-noc"; + reg = <0x0 0x07c00000 0x0 0x19080>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + lpass_lpicx_noc: interconnect@7c20000 { + compatible = "qcom,maili-lpass-lpicx-noc"; + reg = <0x0 0x07c20000 0x0 0x46080>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + llclpi_noc: interconnect@7cd0000 { + compatible = "qcom,maili-llclpi-noc"; + reg = <0x0 0x07cd0000 0x0 0x17200>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + lpass_ag_noc: interconnect@8f40000 { + compatible = "qcom,maili-lpass-ag-noc"; + reg = <0x0 0x08f40000 0x0 0xc080>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + usb: usb@a600000 { + compatible = "qcom,maili-dwc3", "qcom,snps-dwc3"; + reg = <0x0 0x0a600000 0x0 0xfc100>; + clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>, + <&gcc GCC_AGGRE_STARDUSTNOC_USB3_PRIM_AXI_CLK>, + <&gcc GCC_USB30_PRIM_SLEEP_CLK>, + <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>; + clock-names = "cfg_noc", + "core", + "iface", + "sleep", + "mock_utmi"; + + assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, + <&gcc GCC_USB30_PRIM_MASTER_CLK>; + assigned-clock-rates = <19200000>, <200000000>; + + interrupts-extended = <&intc GIC_ESPI 196 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_ESPI 194 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_ESPI 195 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 14 IRQ_TYPE_EDGE_BOTH>, + <&pdc 15 IRQ_TYPE_EDGE_BOTH>, + <&pdc 17 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "dwc_usb3", + "pwr_event", + "hs_phy_irq", + "dp_hs_phy_irq", + "dm_hs_phy_irq", + "ss_phy_irq"; + + power-domains = <&gcc GCC_USB30_PRIM_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + resets = <&gcc GCC_USB30_PRIM_BCR>; + + interconnects = <&aggre_noc MASTER_USB3 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_USB3 QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "usb-ddr", + "apps-usb"; + iommus = <&apps_smmu 0x40 0x0>; + + phys = <&usb_hsphy>, <&usb_dp_qmpphy QMP_USB43DP_USB3_PHY>; + phy-names = "usb2-phy", "usb3-phy"; + + snps,hird-threshold = /bits/ 8 <0x0>; + snps,usb2-gadget-lpm-disable; + snps,dis_u2_susphy_quirk; + snps,dis_enblslpm_quirk; + snps,dis-u1-entry-quirk; + snps,dis-u2-entry-quirk; + snps,is-utmi-l1-suspend; + snps,usb3_lpm_capable; + snps,usb2-lpm-disable; + snps,has-lpm-erratum; + tx-fifo-resize; + dma-coherent; + + usb-role-switch; + wakeup-source; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb_dwc3_hs: endpoint { + }; + }; + + port@1 { + reg = <1>; + + usb_dwc3_ss: endpoint { + remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>; + }; + }; + }; + }; + + pdc: interrupt-controller@b220000 { + compatible = "qcom,maili-pdc", "qcom,pdc"; + reg = <0x0 0x0b220000 0x0 0x10000>, + <0x0 0x179600f0 0x0 0xf4>; + interrupt-parent = <&intc>; + #interrupt-cells = <2>; + interrupt-controller; + qcom,pdc-ranges = <0 288 202>; + }; + + tsens0: thermal-sensor@c22b000 { + compatible = "qcom,maili-tsens", "qcom,tsens-v2"; + reg = <0x0 0x0c22b000 0x0 0x1000>, + <0x0 0x0c222000 0x0 0x1000>; + interrupts = , + ; + interrupt-names = "uplow", + "critical"; + #qcom,sensors = <12>; + #thermal-sensor-cells = <1>; + }; + + tsens1: thermal-sensor@c22c000 { + compatible = "qcom,maili-tsens", "qcom,tsens-v2"; + reg = <0x0 0x0c22c000 0x0 0x1000>, + <0x0 0x0c223000 0x0 0x1000>; + interrupts = , + ; + interrupt-names = "uplow", + "critical"; + #qcom,sensors = <7>; + #thermal-sensor-cells = <1>; + }; + + tsens2: thermal-sensor@c22d000 { + compatible = "qcom,maili-tsens", "qcom,tsens-v2"; + reg = <0x0 0x0c22d000 0x0 0x1000>, + <0x0 0x0c224000 0x0 0x1000>; + interrupts = , + ; + interrupt-names = "uplow", + "critical"; + #qcom,sensors = <6>; + #thermal-sensor-cells = <1>; + }; + + tsens3: thermal-sensor@c22e000 { + compatible = "qcom,maili-tsens", "qcom,tsens-v2"; + reg = <0x0 0x0c22e000 0x0 0x1000>, + <0x0 0x0c225000 0x0 0x1000>; + interrupts = , + ; + interrupt-names = "uplow", + "critical"; + #qcom,sensors = <7>; + #thermal-sensor-cells = <1>; + }; + + tsens4: thermal-sensor@c22f000 { + compatible = "qcom,maili-tsens", "qcom,tsens-v2"; + reg = <0x0 0x0c22f000 0x0 0x1000>, + <0x0 0x0c226000 0x0 0x1000>; + interrupts = , + ; + interrupt-names = "uplow", + "critical"; + #qcom,sensors = <9>; + #thermal-sensor-cells = <1>; + }; + + tsens5: thermal-sensor@c230000 { + compatible = "qcom,maili-tsens", "qcom,tsens-v2"; + reg = <0x0 0x0c230000 0x0 0x1000>, + <0x0 0x0c227000 0x0 0x1000>; + interrupts = , + ; + interrupt-names = "uplow", + "critical"; + #qcom,sensors = <11>; + #thermal-sensor-cells = <1>; + }; + + tsens6: thermal-sensor@c231000 { + compatible = "qcom,maili-tsens", "qcom,tsens-v2"; + reg = <0x0 0x0c231000 0x0 0x1000>, + <0x0 0x0c228000 0x0 0x1000>; + interrupts = , + ; + interrupt-names = "uplow", + "critical"; + #qcom,sensors = <8>; + #thermal-sensor-cells = <1>; + }; + + aoss_qmp: power-management@c300000 { + compatible = "qcom,maili-aoss-qmp", "qcom,aoss-qmp"; + reg = <0x0 0x0c300000 0x0 0x400>; + interrupts-extended = <&ipcc IPCC_MPROC_AOP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_MPROC_AOP + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + #clock-cells = <0>; + }; + + arbiter@c400000 { + compatible = "qcom,maili-spmi-pmic-arb", + "qcom,glymur-spmi-pmic-arb"; + reg = <0x0 0x0c400000 0x0 0x3000>, + <0x0 0x0c900000 0x0 0x400000>, + <0x0 0x0c4c0000 0x0 0x400000>, + <0x0 0x0c403000 0x0 0x8000>; + reg-names = "core", + "chnls", + "obsrvr", + "chnl_map"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + qcom,channel = <0>; + qcom,ee = <0>; + + spmi_bus0: spmi@c426000 { + reg = <0x0 0x0c426000 0x0 0x4000>, + <0x0 0x0c8c0000 0x0 0x10000>, + <0x0 0x0c42a000 0x0 0x8000>; + reg-names = "cnfg", + "intr", + "chnl_owner"; + interrupts-extended = <&pdc 1 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "periph_irq"; + interrupt-controller; + #interrupt-cells = <4>; + #address-cells = <2>; + #size-cells = <0>; + }; + + spmi_bus1: spmi@c437000 { + reg = <0x0 0x0c437000 0x0 0x4000>, + <0x0 0x0c8d0000 0x0 0x10000>, + <0x0 0x0c43b000 0x0 0x8000>; + reg-names = "cnfg", + "intr", + "chnl_owner"; + interrupts-extended = <&pdc 3 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "periph_irq"; + interrupt-controller; + #interrupt-cells = <4>; + #address-cells = <2>; + #size-cells = <0>; + }; + }; + + tlmm: pinctrl@f100000 { + compatible = "qcom,maili-tlmm"; + reg = <0x0 0x0f100000 0x0 0x102000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&tlmm 0 0 227>; + interrupt-controller; + #interrupt-cells = <2>; + wakeup-parent = <&pdc>; + + qup_i2c8_data_clk: qup-i2c8-data-clk-state { + /* SDA, SCL */ + pins = "gpio0", "gpio1"; + function = "qup2_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi8_data_clk: qup-spi8-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio0", "gpio1", "gpio2"; + function = "qup2_se0"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart8_cts_rts: qup-uart8-cts-rts-state { + /* CTS, RTS */ + pins = "gpio0", "gpio1"; + function = "qup2_se0"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart8_default: qup-uart8-default-state { + /* TX, RX */ + pins = "gpio2", "gpio3"; + function = "qup2_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi8_cs: qup-spi8-cs-state { + pins = "gpio3"; + function = "qup2_se0"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c9_data_clk: qup-i2c9-data-clk-state { + /* SDA, SCL */ + pins = "gpio4", "gpio5"; + function = "qup2_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi9_data_clk: qup-spi9-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio4", "gpio5", "gpio6"; + function = "qup2_se1"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart9_cts_rts: qup-uart9-cts-rts-state { + /* CTS, RTS */ + pins = "gpio4", "gpio5"; + function = "qup2_se1"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart9_default: qup-uart9-default-state { + /* TX, RX */ + pins = "gpio6", "gpio7"; + function = "qup2_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi9_cs: qup-spi9-cs-state { + pins = "gpio7"; + function = "qup2_se1"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c14_data_clk: qup-i2c14-data-clk-state { + /* SDA, SCL */ + pins = "gpio8", "gpio9"; + function = "qup3_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi14_data_clk: qup-spi14-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio8", "gpio9", "gpio10"; + function = "qup3_se1"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart14_cts_rts: qup-uart14-cts-rts-state { + /* CTS, RTS */ + pins = "gpio8", "gpio9"; + function = "qup3_se1"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart14_default: qup-uart14-default-state { + /* TX, RX */ + pins = "gpio10", "gpio11"; + function = "qup3_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi14_cs: qup-spi14-cs-state { + pins = "gpio11"; + function = "qup3_se1"; + drive-strength = <6>; + bias-pull-up; + }; + + qup_i2c15_data_clk: qup-i2c15-data-clk-state { + /* SDA, SCL */ + pins = "gpio12", "gpio13"; + function = "qup3_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi15_data_clk: qup-spi15-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio12", "gpio13", "gpio14"; + function = "qup3_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart15_cts_rts: qup-uart15-cts-rts-state { + /* CTS, RTS */ + pins = "gpio12", "gpio13"; + function = "qup3_se2"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart15_default: qup-uart15-default-state { + /* TX, RX */ + pins = "gpio14", "gpio15"; + function = "qup3_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi15_cs: qup-spi15-cs-state { + pins = "gpio15"; + function = "qup3_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c16_data_clk: qup-i2c16-data-clk-state { + /* SDA, SCL */ + pins = "gpio16", "gpio17"; + function = "qup3_se3"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi16_data_clk: qup-spi16-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio16", "gpio17", "gpio18"; + function = "qup3_se3"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart16_cts_rts: qup-uart16-cts-rts-state { + /* CTS, RTS */ + pins = "gpio16", "gpio17"; + function = "qup3_se3"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart16_default: qup-uart16-default-state { + /* TX, RX */ + pins = "gpio18", "gpio19"; + function = "qup3_se3"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi16_cs: qup-spi16-cs-state { + pins = "gpio19"; + function = "qup3_se3"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c17_data_clk: qup-i2c17-data-clk-state { + /* SDA, SCL */ + pins = "gpio20", "gpio21"; + function = "qup3_se4"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi17_data_clk: qup-spi17-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio20", "gpio21", "gpio22"; + function = "qup3_se4"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart17_cts_rts: qup-uart17-cts-rts-state { + /* CTS, RTS */ + pins = "gpio20", "gpio21"; + function = "qup3_se4"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart17_default: qup-uart17-default-state { + /* TX, RX */ + pins = "gpio22", "gpio23"; + function = "qup3_se4"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi17_cs: qup-spi17-cs-state { + pins = "gpio23"; + function = "qup3_se4"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c18_data_clk: qup-i2c18-data-clk-state { + /* SDA, SCL */ + pins = "gpio24", "gpio25"; + function = "qup3_se5"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi18_data_clk: qup-spi18-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio24", "gpio25", "gpio26"; + function = "qup3_se5"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart18_cts_rts: qup-uart18-cts-rts-state { + /* CTS, RTS */ + pins = "gpio24", "gpio25"; + function = "qup3_se5"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart18_default: qup-uart18-default-state { + /* TX, RX */ + pins = "gpio26", "gpio27"; + function = "qup3_se5"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi18_cs: qup-spi18-cs-state { + pins = "gpio27"; + function = "qup3_se5"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c20_data_clk: qup-i2c20-data-clk-state { + /* SDA, SCL */ + pins = "gpio28", "gpio29"; + function = "qup4_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi20_data_clk: qup-spi20-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio28", "gpio29", "gpio30"; + function = "qup4_se1"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart20_cts_rts: qup-uart20-cts-rts-state { + /* CTS, RTS */ + pins = "gpio28", "gpio29"; + function = "qup4_se1"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart20_default: qup-uart20-default-state { + /* TX, RX */ + pins = "gpio30", "gpio31"; + function = "qup4_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi20_cs: qup-spi20-cs-state { + pins = "gpio31"; + function = "qup4_se1"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c21_data_clk: qup-i2c21-data-clk-state { + /* SDA, SCL */ + pins = "gpio32", "gpio33"; + function = "qup4_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi21_data_clk: qup-spi21-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio32", "gpio33", "gpio34"; + function = "qup4_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart21_cts_rts: qup-uart21-cts-rts-state { + /* CTS, RTS */ + pins = "gpio32", "gpio33"; + function = "qup4_se2"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart21_default: qup-uart21-default-state { + /* TX, RX */ + pins = "gpio34", "gpio35"; + function = "qup4_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi21_cs: qup-spi21-cs-state { + pins = "gpio35"; + function = "qup4_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c4_data_clk: qup-i2c4-data-clk-state { + /* SDA, SCL */ + pins = "gpio36", "gpio37"; + function = "qup1_se4"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi4_data_clk: qup-spi4-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio36", "gpio37", "gpio38"; + function = "qup1_se4"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart4_cts_rts: qup-uart4-cts-rts-state { + /* CTS, RTS */ + pins = "gpio36", "gpio37"; + function = "qup1_se4"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart4_default: qup-uart4-default-state { + /* TX, RX */ + pins = "gpio38", "gpio39"; + function = "qup1_se4"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi4_cs: qup-spi4-cs-state { + pins = "gpio39"; + function = "qup1_se4"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c2_data_clk: qup-i2c2-data-clk-state { + /* SDA, SCL */ + pins = "gpio40", "gpio41"; + function = "qup1_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi2_data_clk: qup-spi2-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio40", "gpio41", "gpio42"; + function = "qup1_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart2_cts_rts: qup-uart2-cts-rts-state { + /* CTS, RTS */ + pins = "gpio40", "gpio41"; + function = "qup1_se2"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart2_default: qup-uart2-default-state { + /* TX, RX */ + pins = "gpio42", "gpio43"; + function = "qup1_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi2_cs: qup-spi2-cs-state { + pins = "gpio43"; + function = "qup1_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c3_data_clk: qup-i2c3-data-clk-state { + /* SDA, SCL */ + pins = "gpio44", "gpio45"; + function = "qup1_se3"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi3_data_clk: qup-spi3-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio44", "gpio45", "gpio46"; + function = "qup1_se3"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart3_cts_rts: qup-uart3-cts-rts-state { + /* CTS, RTS */ + pins = "gpio44", "gpio45"; + function = "qup1_se3"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart3_default: qup-uart3-default-state { + /* TX, RX */ + pins = "gpio46", "gpio47"; + function = "qup1_se3"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi3_cs: qup-spi3-cs-state { + pins = "gpio47"; + function = "qup1_se3"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c19_data_clk: qup-i2c19-data-clk-state { + /* SDA, SCL */ + pins = "gpio48", "gpio49"; + function = "qup4_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi19_data_clk: qup-spi19-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio48", "gpio49", "gpio50"; + function = "qup4_se0"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart19_cts_rts: qup-uart19-cts-rts-state { + /* CTS, RTS */ + pins = "gpio48", "gpio49"; + function = "qup4_se0"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart19_default: qup-uart19-default-state { + /* TX, RX */ + pins = "gpio50", "gpio51"; + function = "qup4_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi19_cs: qup-spi19-cs-state { + pins = "gpio51"; + function = "qup4_se0"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c5_data_clk: qup-i2c5-data-clk-state { + /* SDA, SCL */ + pins = "gpio52", "gpio53"; + function = "qup1_se5"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi5_data_clk: qup-spi5-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio52", "gpio53", "gpio54"; + function = "qup1_se5"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart5_cts_rts: qup-uart5-cts-rts-state { + /* CTS, RTS */ + pins = "gpio52", "gpio53"; + function = "qup1_se5"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart5_default: qup-uart5-default-state { + /* TX, RX */ + pins = "gpio54", "gpio55"; + function = "qup1_se5"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi5_cs: qup-spi5-cs-state { + pins = "gpio55"; + function = "qup1_se5"; + drive-strength = <6>; + bias-disable; + }; + + sdc2_default: sdc2-default-state { + card-detect-pins { + pins = "gpio55"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clk-pins { + pins = "gpio56"; + function = "sdc2_clk"; + drive-strength = <16>; + bias-disable; + }; + + cmd-pins { + pins = "gpio57"; + function = "sdc2_cmd"; + drive-strength = <10>; + bias-pull-up; + }; + + data-pins { + pins = "gpio74", "gpio75", "gpio76", "gpio77"; + function = "sdc2_data"; + drive-strength = <10>; + bias-pull-up; + }; + }; + + sdc2_sleep: sdc2-sleep-state { + card-detect-pins { + pins = "gpio55"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + clk-pins { + pins = "gpio56"; + function = "sdc2_clk"; + drive-strength = <2>; + bias-disable; + }; + + cmd-pins { + pins = "gpio57"; + function = "sdc2_cmd"; + drive-strength = <2>; + bias-pull-up; + }; + + data-pins { + pins = "gpio74", "gpio75", "gpio76", "gpio77"; + function = "sdc2_data"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + qup_i2c6_data_clk: qup-i2c6-data-clk-state { + /* SDA, SCL */ + pins = "gpio56", "gpio57"; + function = "qup1_se6"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi6_data_clk: qup-spi6-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio56", "gpio57", "gpio58"; + function = "qup1_se6"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart6_cts_rts: qup-uart6-cts-rts-state { + /* CTS, RTS */ + pins = "gpio56", "gpio57"; + function = "qup1_se6"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart6_default: qup-uart6-default-state { + /* TX, RX */ + pins = "gpio58", "gpio59"; + function = "qup1_se6"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi6_cs: qup-spi6-cs-state { + pins = "gpio59"; + function = "qup1_se6"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c7_data_clk: qup-i2c7-data-clk-state { + /* SDA, SCL */ + pins = "gpio60", "gpio61"; + function = "qup1_se7"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi7_data_clk: qup-spi7-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio60", "gpio61", "gpio62"; + function = "qup1_se7"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart7_default: qup-uart7-state { + /* TX, RX */ + pins = "gpio62", "gpio63"; + function = "qup1_se7"; + drive-strength = <2>; + bias-disable; + }; + + qup_spi7_cs: qup-spi7-cs-state { + pins = "gpio63"; + function = "qup1_se7"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c13_data_clk: qup-i2c13-data-clk-state { + /* SDA, SCL */ + pins = "gpio64", "gpio65"; + function = "qup3_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi13_data_clk: qup-spi13-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio64", "gpio65", "gpio66"; + function = "qup3_se0"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart13_cts_rts: qup-uart13-cts-rts-state { + /* CTS, RTS */ + pins = "gpio64", "gpio65"; + function = "qup3_se0"; + drive-strength = <2>; + bias-pull-down; + }; + + hub_i2c0_data_clk: hub-i2c0-data-clk-state { + /* SDA, SCL */ + pins = "gpio66", "gpio67"; + function = "i2chub0_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart13_default: qup-uart13-default-state { + /* TX, RX */ + pins = "gpio66", "gpio67"; + function = "qup3_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi13_cs: qup-spi13-cs-state { + pins = "gpio67"; + function = "qup3_se0"; + drive-strength = <6>; + bias-pull-up; + }; + + hub_i2c2_data_clk: hub-i2c2-data-clk-state { + /* SDA, SCL */ + pins = "gpio68", "gpio69"; + function = "i2chub0_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + hub_i2c3_data_clk: hub-i2c3-data-clk-state { + /* SDA, SCL */ + pins = "gpio70", "gpio71"; + function = "i2chub0_se3"; + drive-strength = <2>; + bias-pull-up; + }; + + hub_i2c4_data_clk: hub-i2c4-data-clk-state { + /* SDA, SCL */ + pins = "gpio72", "gpio73"; + function = "i2chub0_se4"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c1_data_clk: qup-i2c1-data-clk-state { + /* SDA, SCL */ + pins = "gpio74", "gpio75"; + function = "qup1_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi1_data_clk: qup-spi1-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio74", "gpio75", "gpio76"; + function = "qup1_se1"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart1_cts_rts: qup-uart1-cts-rts-state { + /* CTS, RTS */ + pins = "gpio74", "gpio75"; + function = "qup1_se1"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart1_default: qup-uart1-default-state { + /* TX, RX */ + pins = "gpio76", "gpio77"; + function = "qup1_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi1_cs: qup-spi1-cs-state { + pins = "gpio77"; + function = "qup1_se1"; + drive-strength = <6>; + bias-disable; + }; + + hub_i2c1_data_clk: hub-i2c1-data-clk-state { + /* SDA, SCL */ + pins = "gpio78", "gpio79"; + function = "i2chub0_se1"; + drive-strength = <2>; + bias-pull-up; + }; + + pcie1_default_state: pcie1-default-state { + wake-n-pins { + pins = "gpio80"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio220"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + clkreq-n-pins { + pins = "gpio221"; + function = "pcie1_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie0_default_state: pcie0-default-state { + perst-n-pins { + pins = "gpio102"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + clkreq-n-pins { + pins = "gpio103"; + function = "pcie0_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + wake-n-pins { + pins = "gpio104"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + qup_i2c10_data_clk: qup-i2c10-data-clk-state { + /* SDA, SCL */ + pins = "gpio117", "gpio118"; + function = "qup2_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi10_data_clk: qup-spi10-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio117", "gpio118", "gpio119"; + function = "qup2_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart10_cts_rts: qup-uart10-cts-rts-state { + /* CTS, RTS */ + pins = "gpio117", "gpio118"; + function = "qup2_se2"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart10_default: qup-uart10-default-state { + /* TX, RX */ + pins = "gpio119", "gpio120"; + function = "qup2_se2"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi10_cs: qup-spi10-cs-state { + pins = "gpio120"; + function = "qup2_se2"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c22_data_clk: qup-i2c22-data-clk-state { + /* SDA, SCL */ + pins = "gpio121", "gpio84"; + function = "qup4_se3_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart22_default: qup-uart22-default-state { + /* TX, RX */ + pins = "gpio121", "gpio98"; + function = "qup4_se3_23"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c11_data_clk: qup-i2c11-data-clk-state { + /* SDA, SCL */ + pins = "gpio122", "gpio123"; + function = "qup2_se3"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi11_data_clk: qup-spi11-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio122", "gpio123", "gpio124"; + function = "qup2_se3"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart11_cts_rts: qup-uart11-cts-rts-state { + /* CTS, RTS */ + pins = "gpio122", "gpio123"; + function = "qup2_se3"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart11_default: qup-uart11-default-state { + /* TX, RX */ + pins = "gpio124", "gpio125"; + function = "qup2_se3"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi11_cs: qup-spi11-cs-state { + pins = "gpio125"; + function = "qup2_se3"; + drive-strength = <6>; + bias-disable; + }; + + qup_i2c23_data_clk: qup-i2c23-data-clk-state { + /* SDA, SCL */ + pins = "gpio161", "gpio162"; + function = "qup4_se4_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart23_default: qup-uart23-default-state { + /* TX, RX */ + pins = "gpio161", "gpio162"; + function = "qup4_se4_23"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c12_data_clk: qup-i2c12-data-clk-state { + /* SDA, SCL */ + pins = "gpio208", "gpio209"; + function = "qup2_se4_01"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_uart12_default: qup-uart12-default-state { + /* TX, RX */ + pins = "gpio208", "gpio209"; + function = "qup2_se4_23"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_i2c0_data_clk: qup-i2c0-data-clk-state { + /* SDA, SCL */ + pins = "gpio222", "gpio223"; + function = "qup1_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi0_data_clk: qup-spi0-data-clk-state { + /* MISO, MOSI, CLK */ + pins = "gpio222", "gpio223", "gpio224"; + function = "qup1_se0"; + drive-strength = <6>; + bias-disable; + }; + + qup_uart0_cts_rts: qup-uart0-cts-rts-state { + /* CTS, RTS */ + pins = "gpio222", "gpio223"; + function = "qup1_se0"; + drive-strength = <2>; + bias-pull-down; + }; + + qup_uart0_default: qup-uart0-default-state { + /* TX, RX */ + pins = "gpio224", "gpio225"; + function = "qup1_se0"; + drive-strength = <2>; + bias-pull-up; + }; + + qup_spi0_cs: qup-spi0-cs-state { + pins = "gpio225"; + function = "qup1_se0"; + drive-strength = <6>; + bias-disable; + }; + + }; + + sram@14680000 { + compatible = "qcom,maili-imem", "mmio-sram"; + reg = <0x0 0x14680000 0x0 0x1000>; + ranges = <0x0 0x0 0x14680000 0x1000>; + + no-memory-wc; + + #address-cells = <1>; + #size-cells = <1>; + + pil-sram@94c { + compatible = "qcom,pil-reloc-info"; + reg = <0x94c 0xc8>; + }; + }; + + intc: interrupt-controller@17000000 { + compatible = "arm,gic-v3"; + reg = <0x0 0x17000000 0x0 0x10000>, + <0x0 0x17080000 0x0 0x200000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupts = ; + #interrupt-cells = <3>; + interrupt-controller; + #redistributor-regions = <1>; + + gic_its: msi-controller@17040000 { + compatible = "arm,gic-v3-its"; + reg = <0x0 0x17040000 0x0 0x20000>; + msi-controller; + #msi-cells = <1>; + }; + }; + + watchdog@17600000 { + compatible = "qcom,apss-wdt-maili", "qcom,kpss-wdt"; + reg = <0x0 0x17600000 0x0 0x1000>; + clocks = <&sleep_clk>; + interrupts = ; + }; + + pdp0_mbox: mailbox@17610000 { + compatible = "qcom,maili-cpucp-mbox", "qcom,x1e80100-cpucp-mbox"; + reg = <0x0 0x17610000 0x0 0x8000>, <0x0 0x19990000 0x0 0x8000>; + interrupts = ; + #mbox-cells = <1>; + }; + + timer@17810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x17810000 0x0 0x1000>; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0x0 0x0 0x0 0x0 0x20000000>; + + frame@17811000 { + reg = <0x0 0x17811000 0x1000>, + <0x0 0x17812000 0x1000>; + frame-number = <0>; + interrupts = , + ; + }; + + frame@17813000 { + reg = <0x0 0x17813000 0x1000>; + frame-number = <1>; + interrupts = ; + status = "disabled"; + }; + + frame@17815000 { + reg = <0x0 0x17815000 0x1000>; + frame-number = <2>; + interrupts = ; + status = "disabled"; + }; + + frame@17817000 { + reg = <0x0 0x17817000 0x1000>; + frame-number = <3>; + interrupts = ; + status = "disabled"; + }; + + frame@17819000 { + reg = <0x0 0x17819000 0x1000>; + frame-number = <4>; + interrupts = ; + status = "disabled"; + }; + + frame@1781b000 { + reg = <0x0 0x1781b000 0x1000>; + frame-number = <5>; + interrupts = ; + status = "disabled"; + }; + + frame@1781d000 { + reg = <0x0 0x1781d000 0x1000>; + frame-number = <6>; + interrupts = ; + status = "disabled"; + }; + }; + + apps_rsc: rsc@18900000 { + compatible = "qcom,rpmh-rsc"; + reg = <0x0 0x18900000 0x0 0x10000>, + <0x0 0x18910000 0x0 0x10000>, + <0x0 0x18920000 0x0 0x10000>; + reg-names = "drv-0", "drv-1", "drv-2"; + interrupts = , + , + ; + + power-domains = <&cluster_pd>; + label = "apps_rsc"; + qcom,drv-id = <2>; + qcom,tcs-config = , + , + , + ; + qcom,tcs-offset = <0xd00>; + + apps_bcm_voter: bcm-voter { + compatible = "qcom,bcm-voter"; + }; + + rpmhcc: clock-controller { + compatible = "qcom,maili-rpmh-clk", "qcom,hawi-rpmh-clk"; + #clock-cells = <1>; + clock-names = "xo"; + clocks = <&xo_board>; + }; + + rpmhpd: power-controller { + compatible = "qcom,maili-rpmhpd", "qcom,hawi-rpmhpd"; + + operating-points-v2 = <&rpmhpd_opp_table>; + + #power-domain-cells = <1>; + + rpmhpd_opp_table: opp-table { + compatible = "operating-points-v2"; + + rpmhpd_opp_ret: opp-16 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_d3_0: opp-49 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_d3: opp-50 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_d2_1: opp-51 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_d2: opp-52 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_d1_1: opp-54 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_d1_0: opp-55 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_d1: opp-56 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_d0_0: opp-59 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_d0: opp-60 { + opp-level = ; + }; + + rpmhpd_opp_low_svs: opp-64 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_l0: opp-76 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_l1: opp-80 { + opp-level = ; + }; + + rpmhpd_opp_low_svs_l2: opp-96 { + opp-level = ; + }; + + rpmhpd_opp_svs: opp-128 { + opp-level = ; + }; + + rpmhpd_opp_svs_l0: opp-144 { + opp-level = ; + }; + + rpmhpd_opp_svs_l1: opp-192 { + opp-level = ; + }; + + rpmhpd_opp_svs_l2: opp-224 { + opp-level = ; + }; + + rpmhpd_opp_svs_l2_0: opp-225 { + opp-level = ; + }; + + rpmhpd_opp_nom: opp-256 { + opp-level = ; + }; + + rpmhpd_opp_nom_l1: opp-320 { + opp-level = ; + }; + + rpmhpd_opp_nom_l2: opp-336 { + opp-level = ; + }; + + rpmhpd_opp_turbo: opp-384 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l0: opp-400 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l1: opp-416 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l1_0: opp-417 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l1_1: opp-418 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l1_2: opp-419 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l2: opp-432 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l3: opp-448 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l3_0: opp-449 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l3_1: opp-450 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l3_2: opp-451 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l4: opp-452 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l5: opp-456 { + opp-level = ; + }; + + rpmhpd_opp_super_turbo_no_cpr: opp-480 { + opp-level = ; + }; + }; + }; + }; + + efuse@221c8000 { + compatible = "qcom,maili-qfprom", "qcom,qfprom"; + reg = <0x0 0x221c8000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + gpu_speed_bin: gpu-speed-bin@142 { + reg = <0x142 0x2>; + bits = <3 9>; + }; + }; + + nsp_noc: interconnect@260c0000 { + compatible = "qcom,maili-nsp-noc"; + reg = <0x0 0x260c0000 0x0 0x21280>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + remoteproc_cdsp: remoteproc@26300000 { + compatible = "qcom,maili-cdsp-pas", "qcom,hawi-cdsp-pas"; + reg = <0x0 0x26300000 0x0 0x10000>; + + interrupts-extended = <&intc GIC_ESPI 642 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_cdsp_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + interconnects = <&nsp_noc MASTER_CDSP_PROC QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_NSP>; + power-domain-names = "cx", + "mxc", + "nsp"; + + memory-region = <&cdsp_mem>, <&q6_cdsp_dtb_mem>; + + qcom,qmp = <&aoss_qmp>; + + qcom,smem-states = <&smp2p_cdsp_out 0>; + qcom,smem-state-names = "stop"; + + status = "disabled"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_MPROC_CDSP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + + mboxes = <&ipcc IPCC_MPROC_CDSP + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "cdsp"; + qcom,remote-pid = <5>; + + fastrpc { + compatible = "qcom,maili-fastrpc", "qcom,kaanapali-fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "cdsp"; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + + iommus = <&apps_smmu 0x0801 0x40>, + <&apps_smmu 0x15c1 0x0>; + dma-coherent; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + + iommus = <&apps_smmu 0x0802 0x40>, + <&apps_smmu 0x15c2 0x0>; + dma-coherent; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + + iommus = <&apps_smmu 0x0803 0x40>, + <&apps_smmu 0x15c3 0x0>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + + iommus = <&apps_smmu 0x0804 0x40>, + <&apps_smmu 0x15c4 0x0>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + + iommus = <&apps_smmu 0x0805 0x40>, + <&apps_smmu 0x15c5 0x0>; + dma-coherent; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + + iommus = <&apps_smmu 0x0806 0x40>, + <&apps_smmu 0x15c6 0x0>; + dma-coherent; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + + iommus = <&apps_smmu 0x0807 0x40>, + <&apps_smmu 0x15c7 0x0>; + dma-coherent; + }; + + compute-cb@8 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <8>; + + iommus = <&apps_smmu 0x0808 0x40>, + <&apps_smmu 0x15c8 0x0>; + dma-coherent; + }; + + compute-cb@12 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <12>; + + iommus = <&apps_smmu 0x080c 0x40>, + <&apps_smmu 0x15cc 0x0>; + dma-coherent; + }; + }; + }; + }; + + pmu@310b7400 { + compatible = "qcom,maili-cpu-bwmon", "qcom,sdm845-bwmon"; + reg = <0x0 0x310b7400 0x0 0x600>; + + interrupts = ; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>; + + operating-points-v2 = <&cpu_bwmon_opp_table>; + + cpu_bwmon_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-0 { + opp-peak-kBps = <2188000>; + }; + + opp-1 { + opp-peak-kBps = <5412000>; + }; + + opp-2 { + opp-peak-kBps = <6220000>; + }; + + opp-3 { + opp-peak-kBps = <6832000>; + }; + + opp-4 { + opp-peak-kBps = <8368000>; + }; + + opp-5 { + opp-peak-kBps = <10944000>; + }; + + opp-6 { + opp-peak-kBps = <12748000>; + }; + + opp-7 { + opp-peak-kBps = <14744000>; + }; + + opp-8 { + opp-peak-kBps = <16896000>; + }; + + opp-9 { + opp-peak-kBps = <19120000>; + }; + + opp-10 { + opp-peak-kBps = <21332000>; + }; + }; + }; + + gem_noc: interconnect@31100000 { + compatible = "qcom,maili-gem-noc"; + reg = <0x0 0x31100000 0x0 0x160200>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + config_noc: stdst_cfg: interconnect@313c0000 { + compatible = "qcom,maili-stdst-cfg"; + reg = <0x0 0x313c0000 0x0 0x9000>; + #interconnect-cells = <2>; + qcom,bcm-voters = <&apps_bcm_voter>; + }; + + system-cache-controller@31800000 { + compatible = "qcom,maili-llcc", "qcom,hawi-llcc"; + reg = <0x0 0x31800000 0x0 0x200000>, + <0x0 0x32800000 0x0 0x200000>, + <0x0 0x31c00000 0x0 0x200000>, + <0x0 0x32c00000 0x0 0x200000>, + <0x0 0x34800000 0x0 0x200000>, + <0x0 0x34c00000 0x0 0x200000>; + reg-names = "llcc0_base", + "llcc1_base", + "llcc2_base", + "llcc3_base", + "llcc_broadcast_base", + "llcc_broadcast_and_base"; + + interrupts = ; + memory-region = <&cpucp_slc_mem_sub>; + }; + + sram: sram@81f08000 { + compatible = "mmio-sram"; + reg = <0x0 0x81f08000 0x0 0x200>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x81f08000 0x200>; + + pdp_rx: scp-sram-section@0 { + compatible = "arm,scmi-shmem"; + reg = <0x0 0x80>; + }; + + pdp_tx: scp-sram-section@80 { + compatible = "arm,scmi-shmem"; + reg = <0x80 0x80>; + }; + }; + }; + + thermal-zones { + camera-0-thermal { + thermal-sensors = <&tsens6 4>; + + trips { + camera-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + camera-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + camera-1-thermal { + thermal-sensors = <&tsens6 5>; + + trips { + camera-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + camera-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-0-0-thermal { + thermal-sensors = <&tsens2 0>; + + trips { + cpu-0-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-0-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-0-1-thermal { + thermal-sensors = <&tsens2 1>; + + trips { + cpu-0-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-0-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-0-2-thermal { + thermal-sensors = <&tsens2 2>; + + trips { + cpu-0-2-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-0-2-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-1-0-thermal { + thermal-sensors = <&tsens2 3>; + + trips { + cpu-1-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-1-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-1-1-thermal { + thermal-sensors = <&tsens2 4>; + + trips { + cpu-1-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-1-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-1-2-thermal { + thermal-sensors = <&tsens2 5>; + + trips { + cpu-1-2-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-1-2-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-2-0-thermal { + thermal-sensors = <&tsens0 6>; + + trips { + cpu-2-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-2-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-2-1-thermal { + thermal-sensors = <&tsens0 7>; + + trips { + cpu-2-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-2-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-3-0-thermal { + thermal-sensors = <&tsens0 0>; + + trips { + cpu-3-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-3-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-3-1-thermal { + thermal-sensors = <&tsens0 1>; + + trips { + cpu-3-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-3-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-4-0-thermal { + thermal-sensors = <&tsens0 8>; + + trips { + cpu-4-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-4-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-4-1-thermal { + thermal-sensors = <&tsens0 9>; + + trips { + cpu-4-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-4-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-5-0-thermal { + thermal-sensors = <&tsens0 2>; + + trips { + cpu-5-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-5-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-5-1-thermal { + thermal-sensors = <&tsens0 3>; + + trips { + cpu-5-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-5-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-6-0-thermal { + thermal-sensors = <&tsens0 10>; + + trips { + cpu-6-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-6-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-6-1-thermal { + thermal-sensors = <&tsens0 11>; + + trips { + cpu-6-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-6-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-7-0-thermal { + thermal-sensors = <&tsens0 4>; + + trips { + cpu-7-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-7-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpu-7-1-thermal { + thermal-sensors = <&tsens0 5>; + + trips { + cpu-7-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpu-7-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpullc-0-thermal { + thermal-sensors = <&tsens1 0>; + + trips { + cpullc-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpullc-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + cpullc-1-thermal { + thermal-sensors = <&tsens1 1>; + + trips { + cpullc-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + cpullc-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + ddr-thermal { + thermal-sensors = <&tsens6 7>; + + trips { + ddr-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + ddr-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpu-0-0-thermal { + thermal-sensors = <&tsens5 0>; + + trips { + gpu-0-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpu-0-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpu-0-1-thermal { + thermal-sensors = <&tsens5 1>; + + trips { + gpu-0-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpu-0-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpu-0-2-thermal { + thermal-sensors = <&tsens5 2>; + + trips { + gpu-0-2-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpu-0-2-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpu-1-0-thermal { + thermal-sensors = <&tsens5 3>; + + trips { + gpu-1-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpu-1-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpu-1-1-thermal { + thermal-sensors = <&tsens5 4>; + + trips { + gpu-1-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpu-1-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpu-1-2-thermal { + thermal-sensors = <&tsens5 5>; + + trips { + gpu-1-2-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpu-1-2-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpu-2-0-thermal { + thermal-sensors = <&tsens5 6>; + + trips { + gpu-2-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpu-2-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpu-2-1-thermal { + thermal-sensors = <&tsens5 7>; + + trips { + gpu-2-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpu-2-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpu-2-2-thermal { + thermal-sensors = <&tsens5 8>; + + trips { + gpu-2-2-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpu-2-2-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpuss-0-thermal { + thermal-sensors = <&tsens5 9>; + + trips { + gpuss-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpuss-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + gpuss-1-thermal { + thermal-sensors = <&tsens5 10>; + + trips { + gpuss-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + gpuss-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + mdmss-0-thermal { + thermal-sensors = <&tsens6 0>; + + trips { + mdmss-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + mdmss-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + mdmss-1-thermal { + thermal-sensors = <&tsens6 1>; + + trips { + mdmss-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + mdmss-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + mdmss-2-thermal { + thermal-sensors = <&tsens6 2>; + + trips { + mdmss-2-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + mdmss-2-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + mdmss-3-thermal { + thermal-sensors = <&tsens6 3>; + + trips { + mdmss-3-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + mdmss-3-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspllv-0-0-thermal { + thermal-sensors = <&tsens3 3>; + + trips { + nspllv-0-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspllv-0-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspllv-0-1-thermal { + thermal-sensors = <&tsens3 4>; + + trips { + nspllv-0-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspllv-0-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspllv-1-0-thermal { + thermal-sensors = <&tsens3 5>; + + trips { + nspllv-1-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspllv-1-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspllv-1-1-thermal { + thermal-sensors = <&tsens3 6>; + + trips { + nspllv-1-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspllv-1-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspmxu0-0-0-thermal { + thermal-sensors = <&tsens4 1>; + + trips { + nspmxu0-0-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspmxu0-0-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspmxu0-0-1-thermal { + thermal-sensors = <&tsens4 2>; + + trips { + nspmxu0-0-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspmxu0-0-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspmxu0-1-0-thermal { + thermal-sensors = <&tsens4 3>; + + trips { + nspmxu0-1-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspmxu0-1-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspmxu0-1-1-thermal { + thermal-sensors = <&tsens4 4>; + + trips { + nspmxu0-1-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspmxu0-1-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspmxu1-0-0-thermal { + thermal-sensors = <&tsens4 5>; + + trips { + nspmxu1-0-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspmxu1-0-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspmxu1-0-1-thermal { + thermal-sensors = <&tsens4 6>; + + trips { + nspmxu1-0-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspmxu1-0-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspmxu1-1-0-thermal { + thermal-sensors = <&tsens4 7>; + + trips { + nspmxu1-1-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspmxu1-1-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspmxu1-1-1-thermal { + thermal-sensors = <&tsens4 8>; + + trips { + nspmxu1-1-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspmxu1-1-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspmxutop-thermal { + thermal-sensors = <&tsens4 0>; + + trips { + nspmxutop-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspmxutop-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspq6-thermal { + thermal-sensors = <&tsens3 0>; + + trips { + nspq6-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspq6-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspvxu-0-thermal { + thermal-sensors = <&tsens3 1>; + + trips { + nspvxu-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspvxu-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + nspvxu-1-thermal { + thermal-sensors = <&tsens3 2>; + + trips { + nspvxu-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + nspvxu-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + qmx-0-thermal { + thermal-sensors = <&tsens1 2>; + + trips { + qmx-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + qmx-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + qmx-1-thermal { + thermal-sensors = <&tsens1 3>; + + trips { + qmx-1-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + qmx-1-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + qmx-2-thermal { + thermal-sensors = <&tsens1 4>; + + trips { + qmx-2-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + qmx-2-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + qmx-3-thermal { + thermal-sensors = <&tsens1 5>; + + trips { + qmx-3-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + qmx-3-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + qmx-4-thermal { + thermal-sensors = <&tsens1 6>; + + trips { + qmx-4-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + qmx-4-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + + video-thermal { + thermal-sensors = <&tsens6 6>; + + trips { + video-0-hot { + temperature = <120000>; + hysteresis = <5000>; + type = "hot"; + }; + + video-0-critical { + temperature = <125000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; +}; From 0ff6882e9ef5bbad6d2397ca0047b2328f315c67 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Tue, 22 Sep 2026 16:20:01 -0700 Subject: [PATCH 0304/1133] FROMLIST: arm64: dts: qcom: Add PMIC support for Maili platforms Add PMIC files for pmic-arbiter device used on Maili QRD and MTP boards. Only one PMH0104 chip is used on SPMI bus-0 with SID 0x2 which is a new usage, hence add a new pmh0104-maili.dtsi. Also, add a new pmg1110.dtsi to support PMG1110 usage. Signed-off-by: Fenglin Wu Signed-off-by: Jingyi Wang Signed-off-by: Yijie Yang Link: https://lore.kernel.org/r/20260922-maili-dts-v1-4-ac2b1b76bfd9@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/pmg1110.dtsi | 57 +++++++++++++++++++++ arch/arm64/boot/dts/qcom/pmh0104-maili.dtsi | 57 +++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/pmg1110.dtsi create mode 100644 arch/arm64/boot/dts/qcom/pmh0104-maili.dtsi diff --git a/arch/arm64/boot/dts/qcom/pmg1110.dtsi b/arch/arm64/boot/dts/qcom/pmg1110.dtsi new file mode 100644 index 0000000000000..31b05003b843a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/pmg1110.dtsi @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +/ { + thermal-zones { + pmg1110-thermal { + polling-delay-passive = <100>; + + thermal-sensors = <&pmg1110_k_e1_temp_alarm>; + + trips { + trip0 { + temperature = <95000>; + hysteresis = <0>; + type = "passive"; + }; + + trip1 { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; + }; + }; +}; + +&spmi_bus1 { + pmg1110_k_e1: pmic@9 { + compatible = "qcom,pmg1110", "qcom,spmi-pmic"; + reg = <0x9 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmg1110_k_e1_temp_alarm: temp-alarm@a00 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0xa00>; + interrupts = <0x9 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; + #thermal-sensor-cells = <0>; + }; + + pmg1110_k_e1_gpios: gpio@8800 { + compatible = "qcom,pmg1110-gpio", "qcom,spmi-gpio"; + reg = <0x8800>; + gpio-controller; + gpio-ranges = <&pmg1110_k_e1_gpios 0 0 4>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/pmh0104-maili.dtsi b/arch/arm64/boot/dts/qcom/pmh0104-maili.dtsi new file mode 100644 index 0000000000000..2f3906ccaa73d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/pmh0104-maili.dtsi @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +/ { + thermal-zones { + pmh0104-c-thermal { + polling-delay-passive = <100>; + + thermal-sensors = <&pmh0104_c_e0_temp_alarm>; + + trips { + trip0 { + temperature = <95000>; + hysteresis = <0>; + type = "passive"; + }; + + trip1 { + temperature = <115000>; + hysteresis = <0>; + type = "hot"; + }; + }; + }; + }; +}; + +&spmi_bus0 { + pmh0104_c_e0: pmic@2 { + compatible = "qcom,pmh0104", "qcom,spmi-pmic"; + reg = <0x2 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pmh0104_c_e0_temp_alarm: temp-alarm@a00 { + compatible = "qcom,spmi-temp-alarm"; + reg = <0xa00>; + interrupts = <0x2 0xa 0x0 IRQ_TYPE_EDGE_BOTH>; + #thermal-sensor-cells = <0>; + }; + + pmh0104_c_e0_gpios: gpio@8800 { + compatible = "qcom,pmh0104-gpio", "qcom,spmi-gpio"; + reg = <0x8800>; + gpio-controller; + gpio-ranges = <&pmh0104_c_e0_gpios 0 0 8>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; +}; From 9220154fd1275e4d126ccccbf65fbd914b3aff78 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 22 Sep 2026 16:20:02 -0700 Subject: [PATCH 0305/1133] FROMLIST: arm64: dts: qcom: maili: Add base MTP board Add initial support for Qualcomm Maili MTP board which enables booting to shell with UART console and features including UFS, remoteprocs, USB, PCIe, SD Card, PMICs and devices for keys and LEDs. Written with help from Fenglin Wu (added RPMhPD nodes and PMICs), Nitin Rawat (Added UFS and SD Card), Krishna Kurapati PSSNV(added USB) and Vivek Pernamitta(added PCIe). Co-developed-by: Yijie Yang Signed-off-by: Jingyi Wang Signed-off-by: Yijie Yang Link: https://lore.kernel.org/r/20260922-maili-dts-v1-5-ac2b1b76bfd9@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/maili-mtp.dts | 960 +++++++++++++++++++++++++ 2 files changed, 961 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/maili-mtp.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..2bacae76f1e4e 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -65,6 +65,7 @@ lemans-evk-ifp-mezzanine-dtbs := lemans-evk.dtb lemans-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-ifp-mezzanine.dtb dtb-$(CONFIG_ARCH_QCOM) += mahua-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += mahua-lenovo-thinkpad-t14s-gen7-lcd.dtb +dtb-$(CONFIG_ARCH_QCOM) += maili-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-fairphone-fp6.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-nothing-asteroids.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza.dtb diff --git a/arch/arm64/boot/dts/qcom/maili-mtp.dts b/arch/arm64/boot/dts/qcom/maili-mtp.dts new file mode 100644 index 0000000000000..1fdc91e03271c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/maili-mtp.dts @@ -0,0 +1,960 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include +#include +#include +#include +#include +#include "maili.dtsi" +#include "pm8010-kaanapali.dtsi" /* SPMI1: SID-C/D */ +#include "pmd8028-kaanapali.dtsi" /* SPMI1: SID-4 */ +#include "pmg1110.dtsi" /* SPMI1: SID-9 */ +#include "pmh0101.dtsi" /* SPMI0: SID-1 */ +#include "pmh0104-maili.dtsi" /* SPMI0: SID-2 */ +#include "pmh0110-kaanapali.dtsi" /* SPMI0: SID-3/5/6/8 */ +#include "pmih0108-kaanapali.dtsi" /* SPMI1: SID-7 */ +#include "pmk8850.dtsi" /* SPMI0: SID-0 */ +#include "pmr735d-kaanapali.dtsi" /* SPMI1: SID-A */ + +/ { + model = "Qualcomm Technologies, Inc. Maili MTP"; + compatible = "qcom,maili-mtp", "qcom,maili"; + chassis-type = "handset"; + + aliases { + serial0 = &uart7; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + clocks { + bi_tcxo_ao_div2: bi-tcxo-ao-div2-clk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clocks = <&rpmhcc RPMH_CXO_CLK_A>; + clock-mult = <1>; + clock-div = <2>; + }; + + bi_tcxo_div2: bi-tcxo-div2-clk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-mult = <1>; + clock-div = <2>; + }; + + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + clock-frequency = <32764>; + #clock-cells = <0>; + }; + + xo_board: xo-board { + compatible = "fixed-clock"; + clock-frequency = <76800000>; + #clock-cells = <0>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&volume_up_n>; + pinctrl-names = "default"; + + key-volume-up { + label = "Volume Up"; + linux,code = ; + gpios = <&pmh0110_i_e0_gpios 13 GPIO_ACTIVE_LOW>; + debounce-interval = <15>; + linux,can-disable; + wakeup-source; + }; + }; + + pmic-glink { + compatible = "qcom,maili-pmic-glink", + "qcom,kaanapali-pmic-glink", + "qcom,pmic-glink"; + + #address-cells = <1>; + #size-cells = <0>; + + connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + pmic_glink_hs_in: endpoint { + remote-endpoint = <&usb_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + pmic_glink_ss_in: endpoint { + remote-endpoint = <&usb_dp_qmpphy_out>; + }; + }; + + port@2 { + reg = <2>; + + pmic_glink_dp_out: endpoint { + + }; + }; + }; + }; + }; + + sdcard_vdd_3p0: sdcard-vdd-3p0 { + compatible = "regulator-fixed"; + + regulator-name = "sdc-vdd123"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-enable-ramp-delay = <1500>; + + gpio = <&pmh0104_c_e0_gpios 5 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&sd_card_eldo_en>; + pinctrl-names = "default"; + + vin-supply = <&vreg_bob1>; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pmh0101-rpmh-regulators"; + qcom,pmic-id = "B_E0"; + + vreg_bob1: bob1 { + regulator-name = "vreg_bob1"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <4224000>; + regulator-initial-mode = ; + }; + + vreg_bob2: bob2 { + regulator-name = "vreg_bob2"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <3616000>; + regulator-initial-mode = ; + }; + + vreg_l1b_1p8: ldo1 { + regulator-name = "vreg_l1b_1p8"; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2b_3p0: ldo2 { + regulator-name = "vreg_l2b_3p0"; + regulator-min-microvolt = <2600000>; + regulator-max-microvolt = <3544000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4b_1p8: ldo4 { + regulator-name = "vreg_l4b_1p8"; + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <1980000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l5b_3p1: ldo5 { + regulator-name = "vreg_l5b_3p1"; + regulator-min-microvolt = <2300000>; + regulator-max-microvolt = <3544000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l6b_1p8: ldo6 { + regulator-name = "vreg_l6b_1p8"; + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7b_1p8: ldo7 { + regulator-name = "vreg_l7b_1p8"; + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l9b_2p5: ldo9 { + regulator-name = "vreg_l9b_2p5"; + regulator-min-microvolt = <2400000>; + regulator-max-microvolt = <2700000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l10b_1p8: ldo10 { + regulator-name = "vreg_l10b_1p8"; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l11b_1p2: ldo11 { + regulator-name = "vreg_l11b_1p2"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1950000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l12b_1p8: ldo12 { + regulator-name = "vreg_l12b_1p8"; + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l13b_3p0: ldo13 { + regulator-name = "vreg_l13b_3p0"; + regulator-min-microvolt = <2650000>; + regulator-max-microvolt = <3544000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l14b_3p2: ldo14 { + regulator-name = "vreg_l14b_3p2"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3544000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l15b_1p8: ldo15 { + regulator-name = "vreg_l15b_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1980000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l16b_2p9: ldo16 { + regulator-name = "vreg_l16b_2p9"; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <3544000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l17b_2p5: ldo17 { + regulator-name = "vreg_l17b_2p5"; + regulator-min-microvolt = <2400000>; + regulator-max-microvolt = <2700000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l18b_1p2: ldo18 { + regulator-name = "vreg_l18b_1p2"; + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + regulators-1 { + compatible = "qcom,pmh0104-rpmh-regulators"; + qcom,pmic-id = "C_E0"; + + vreg_s3c_1p2: smps3 { + regulator-name = "vreg_s3c_1p2"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <2100000>; + regulator-initial-mode = ; + }; + + vreg_s4c_1p8: smps4 { + regulator-name = "vreg_s4c_1p8"; + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <2040000>; + regulator-initial-mode = ; + }; + }; + + regulators-2 { + compatible = "qcom,pmh0110-rpmh-regulators"; + qcom,pmic-id = "D_E0"; + + vreg_s7d_0p7: smps7 { + regulator-name = "vreg_s7d_0p7"; + regulator-min-microvolt = <713000>; + regulator-max-microvolt = <765000>; + regulator-initial-mode = ; + }; + + vreg_s8d_1p0: smps8 { + regulator-name = "vreg_s8d_1p0"; + regulator-min-microvolt = <1010000>; + regulator-max-microvolt = <1120000>; + regulator-initial-mode = ; + }; + + vreg_s9d_1p0: smps9 { + regulator-name = "vreg_s9d_1p0"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <1372000>; + regulator-initial-mode = ; + }; + + vreg_l1d_0p9: ldo1 { + regulator-name = "vreg_l1d_0p9"; + regulator-min-microvolt = <830000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2d_1p8: ldo2 { + regulator-name = "vreg_l2d_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3d_0p9: ldo3 { + regulator-name = "vreg_l3d_0p9"; + regulator-min-microvolt = <830000>; + regulator-max-microvolt = <950000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4d_0p9: ldo4 { + regulator-name = "vreg_l4d_0p9"; + regulator-min-microvolt = <830000>; + regulator-max-microvolt = <950000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + regulators-3 { + compatible = "qcom,pmh0110-rpmh-regulators"; + qcom,pmic-id = "F_E0"; + + vreg_l3f_1p2: ldo3 { + regulator-name = "vreg_l3f_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4f_1p0: ldo4 { + regulator-name = "vreg_l4f_1p0"; + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <1320000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + regulators-4 { + compatible = "qcom,pmh0110-rpmh-regulators"; + qcom,pmic-id = "G_E0"; + + vreg_s7g_1p2: smps7 { + regulator-name = "vreg_s7g_1p2"; + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1372000>; + regulator-initial-mode = ; + }; + + vreg_l1g_1p2: ldo1 { + regulator-name = "vreg_l1g_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2g_1p2: ldo2 { + regulator-name = "vreg_l2g_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3g_1p2: ldo3 { + regulator-name = "vreg_l3g_1p2"; + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <1320000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4g_1p2: ldo4 { + regulator-name = "vreg_l4g_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1980000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + regulators-5 { + compatible = "qcom,pmh0110-rpmh-regulators"; + qcom,pmic-id = "I_E0"; + + vreg_s1i_0p5: smps1 { + regulator-name = "vreg_s1i_0p5"; + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <570000>; + regulator-initial-mode = ; + }; + + vreg_s4i_0p9: smps4 { + regulator-name = "vreg_s4i_0p9"; + regulator-min-microvolt = <870000>; + regulator-max-microvolt = <970000>; + regulator-initial-mode = ; + }; + + vreg_s10i_1p0: smps10 { + regulator-name = "vreg_s10i_1p0"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1300000>; + regulator-initial-mode = ; + }; + + vreg_l1i_0p8: ldo1 { + regulator-name = "vreg_l1i_0p8"; + regulator-min-microvolt = <720000>; + regulator-max-microvolt = <950000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3i_0p9: ldo3 { + regulator-name = "vreg_l3i_0p9"; + regulator-min-microvolt = <825000>; + regulator-max-microvolt = <925000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4i_0p9: ldo4 { + regulator-name = "vreg_l4i_0p9"; + regulator-min-microvolt = <866000>; + regulator-max-microvolt = <958000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + regulators-6 { + compatible = "qcom,pmg1110-rpmh-regulators"; + qcom,pmic-id = "J_E1"; + + vreg_s1j_0p8: smps1 { + regulator-name = "vreg_s1j_0p8"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1352000>; + regulator-initial-mode = ; + }; + }; + + regulators-7 { + compatible = "qcom,pmr735d-rpmh-regulators"; + qcom,pmic-id = "K_E1"; + + vreg_l1k_0p7: ldo1 { + regulator-name = "vreg_l1k_0p7"; + regulator-min-microvolt = <713000>; + regulator-max-microvolt = <765000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2k_0p8: ldo2 { + regulator-name = "vreg_l2k_0p8"; + regulator-min-microvolt = <831000>; + regulator-max-microvolt = <892000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3k_1p2: ldo3 { + regulator-name = "vreg_l3k_1p2"; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l4k_1p0: ldo4 { + regulator-name = "vreg_l4k_1p0"; + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l5k_0p9: ldo5 { + regulator-name = "vreg_l5k_0p9"; + regulator-min-microvolt = <915000>; + regulator-max-microvolt = <970000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l6k_1p0: ldo6 { + regulator-name = "vreg_l6k_1p0"; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l7k_0p7: ldo7 { + regulator-name = "vreg_l7k_0p7"; + regulator-min-microvolt = <713000>; + regulator-max-microvolt = <765000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "M_E1"; + + vreg_l1m_1p0: ldo1 { + regulator-name = "vreg_l1m_1p0"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1100000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2m_1p0: ldo2 { + regulator-name = "vreg_l2m_1p0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3m_2p8: ldo3 { + regulator-name = "vreg_l3m_2p8"; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <2900000>; + regulator-initial-mode = ; + }; + + vreg_l5m_2p8: ldo5 { + regulator-name = "vreg_l5m_2p8"; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3000000>; + regulator-initial-mode = ; + }; + + vreg_l6m_2p8: ldo6 { + regulator-name = "vreg_l6m_2p8"; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <2900000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p2: ldo7 { + regulator-name = "vreg_l7m_2p2"; + regulator-min-microvolt = <2100000>; + regulator-max-microvolt = <2300000>; + regulator-initial-mode = ; + }; + }; + + regulators-9 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "N_E1"; + + vreg_l1n_0p8: ldo1 { + regulator-name = "vreg_l1n_0p8"; + regulator-min-microvolt = <720000>; + regulator-max-microvolt = <900000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l2n_1p2: ldo2 { + regulator-name = "vreg_l2n_1p2"; + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <1544000>; + regulator-initial-mode = ; + regulator-allow-set-load; + regulator-allowed-modes = ; + }; + + vreg_l3n_1p8: ldo3 { + regulator-name = "vreg_l3n_1p8"; + regulator-min-microvolt = <1792000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l4n_1p8: ldo4 { + regulator-name = "vreg_l4n_1p8"; + regulator-min-microvolt = <1792000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = ; + }; + + vreg_l5n_3p3: ldo5 { + regulator-name = "vreg_l5n_3p3"; + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3544000>; + regulator-initial-mode = ; + }; + + vreg_l6n_2p8: ldo6 { + regulator-name = "vreg_l6n_2p8"; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <2900000>; + regulator-initial-mode = ; + }; + + vreg_l7n_3p3: ldo7 { + regulator-name = "vreg_l7n_3p3"; + regulator-min-microvolt = <3130000>; + regulator-max-microvolt = <3470000>; + regulator-initial-mode = ; + }; + }; +}; + +&pcie0 { + status = "okay"; +}; + +&pcie0_phy { + vdda-phy-supply = <&vreg_l1d_0p9>; + vdda-pll-supply = <&vreg_l3g_1p2>; + + status = "okay"; +}; + +&pcie_port0 { + wake-gpios = <&tlmm 104 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 102 GPIO_ACTIVE_LOW>; +}; + +&pcie1 { + status = "okay"; +}; + +&pcie1_phy { + vdda-phy-supply = <&vreg_l1d_0p9>; + vdda-pll-supply = <&vreg_l3g_1p2>; + + status = "okay"; +}; + +&pcie_port1 { + wake-gpios = <&tlmm 80 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 220 GPIO_ACTIVE_LOW>; +}; + +&pmh0101_flash { + status = "okay"; + + led-0 { + function = LED_FUNCTION_FLASH; + function-enumerator = <0>; + color = ; + led-sources = <1>, <4>; + led-max-microamp = <500000>; + flash-max-microamp = <2000000>; + flash-max-timeout-us = <1280000>; + }; + + led-1 { + function = LED_FUNCTION_FLASH; + function-enumerator = <1>; + color = ; + led-sources = <2>, <3>; + led-max-microamp = <500000>; + flash-max-microamp = <2000000>; + flash-max-timeout-us = <1280000>; + }; +}; + +&pmh0104_c_e0_gpios { + sd_card_eldo_en: sd-card-eldo-en-state { + pins = "gpio5"; + function = "normal"; + qcom,drive-strength = ; + input-disable; + output-low; + power-source = <0>; + }; +}; + +&pmh0110_i_e0_gpios { + volume_up_n: volume-up-n-state { + pins = "gpio13"; + function = "normal"; + bias-pull-up; + input-enable; + power-source = <1>; + }; +}; + +&pmh0101_pwm { + status = "okay"; + + multi-led { + color = ; + function = LED_FUNCTION_STATUS; + + #address-cells = <1>; + #size-cells = <0>; + + led@1 { + reg = <1>; + color = ; + }; + + led@2 { + reg = <2>; + color = ; + }; + + led@3 { + reg = <3>; + color = ; + }; + }; +}; + +&pmih0108_e1_eusb2_repeater { + vdd18-supply = <&vreg_l15b_1p8>; + vdd3-supply = <&vreg_l5b_3p1>; +}; + +&pon_resin { + linux,code = ; + + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/maili/adsp.mbn", + "qcom/maili/adsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/maili/cdsp.mbn", + "qcom/maili/cdsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_mpss { + firmware-name = "qcom/maili/modem.mbn", + "qcom/maili/modem_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_soccp { + firmware-name = "qcom/maili/soccp.mbn", + "qcom/maili/soccp_dtb.mbn"; +}; + +&sdhc_2 { + cd-gpios = <&tlmm 55 GPIO_ACTIVE_LOW>; + + vmmc-supply = <&sdcard_vdd_3p0>; + vqmmc-supply = <&vreg_l16b_2p9>; + + bus-width = <4>; + no-sdio; + no-mmc; + + pinctrl-0 = <&sdc2_default>; + pinctrl-1 = <&sdc2_sleep>; + pinctrl-names = "default", "sleep"; + + status = "okay"; +}; + +&tlmm { + gpio-reserved-ranges = <36 4>, /* NFC eSE SPI */ + <119 2>, /* SoCCP */ + <144 2>, /* CXM UART */ + <211 1>; /* NFC Secure IO */ +}; + +&uart7 { + status = "okay"; +}; + +&ufs_mem_hc { + reset-gpios = <&tlmm 226 GPIO_ACTIVE_LOW>; + + vcc-supply = <&vreg_l17b_2p5>; + vcc-max-microamp = <1200000>; + + vccq-supply = <&vreg_l1g_1p2>; + vccq-max-microamp = <1200000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l4i_0p9>; + vdda-pll-supply = <&vreg_l3g_1p2>; + + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_dp_qmpphy { + vdda-phy-supply = <&vreg_l3g_1p2>; + vdda-pll-supply = <&vreg_l3i_0p9>; + + status = "okay"; +}; + +&usb_dp_qmpphy_out { + remote-endpoint = <&pmic_glink_ss_in>; +}; + +&usb_dwc3_hs { + remote-endpoint = <&pmic_glink_hs_in>; +}; + +&usb_hsphy { + vdd-supply = <&vreg_l3i_0p9>; + vdda12-supply = <&vreg_l3g_1p2>; + + phys = <&pmih0108_e1_eusb2_repeater>; + + status = "okay"; +}; From 49f7dd224e5b6952f376814c011b0f45e7f46017 Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Wed, 23 Sep 2026 14:16:25 +0530 Subject: [PATCH 0306/1133] FROMLIST: arm64: dts: qcom: maili: add LPASS audio subsystem nodes Add the Low Power Audio SubSystem (LPASS) device tree infrastructure for Maili, mirroring the Hawi SoC, so the ADSP-based audio pipeline can be described by boards. This adds under the ADSP GLINK edge the GPR (Generic Packet Router) node with the q6apm and q6prm services, and on the SoC bus the RX, TX and VA Bolero macro codecs, their RX/TX SoundWire controllers, the VA CSR heartbeat clock provider, and the LPASS LPI TLMM pinctrl node with the DMIC, I2S and SoundWire pin states used by the audio blocks. The SoundWire controllers are left status = "disabled" here; boards enable them once the attached codecs are described. Link: https://lore.kernel.org/lkml/20260923084627.748920-7-prasad.kumpatla@oss.qualcomm.com/ Signed-off-by: Prasad Kumpatla Signed-off-by: Mukesh Ojha --- arch/arm64/boot/dts/qcom/maili.dtsi | 291 ++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/maili.dtsi b/arch/arm64/boot/dts/qcom/maili.dtsi index 886d307e536be..5540a7630c3ad 100644 --- a/arch/arm64/boot/dts/qcom/maili.dtsi +++ b/arch/arm64/boot/dts/qcom/maili.dtsi @@ -20,6 +20,8 @@ #include #include "maili-ipcc.h" +#include +#include / { interrupt-parent = <&intc>; @@ -4006,6 +4008,295 @@ dma-coherent; }; }; + + 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"; + + q6apmbedai: bedais { + compatible = "qcom,q6apm-lpass-dais"; + #address-cells = <1>; + #size-cells = <0>; + #sound-dai-cells = <1>; + }; + + q6apmdai: dais { + compatible = "qcom,q6apm-dais"; + iommus = <&apps_smmu 0x0c01 0x80>, + <&apps_smmu 0x0c41 0x20>; + }; + }; + + 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>; + }; + }; + }; + }; + }; + + lpass_rxmacro: codec@72c0000 { + compatible = "qcom,maili-lpass-rx-macro", "qcom,hawi-lpass-rx-macro"; + reg = <0x0 0x072c0000 0x0 0x1000>; + clocks = <&q6prmcc LPASS_CLK_ID_RX_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_LPR_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&lpass_vamacro>; + clock-names = "mclk", "lpr", "dcodec", "fsgen"; + + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + swr1: soundwire@72d0000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x0 0x072d0000 0x0 0x10000>; + interrupts = ; + clocks = <&lpass_rxmacro>; + clock-names = "iface"; + label = "RX"; + + pinctrl-0 = <&rx_swr_active>; + pinctrl-names = "default"; + + qcom,din-ports = <1>; + qcom,dout-ports = <11>; + qcom,ports-sinterval = /bits/ 16 <0x03 0x3f 0x1f 0x07 0x00 0x18f 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0b 0x01 0x00 0x00 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0b 0x00 0x00 0x00 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-hstart = /bits/ 8 <0xff 0x03 0xff 0xff 0xff 0x08 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0x06 0xff 0xff 0xff 0x08 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04 0xff 0xff 0x0f 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0x00 0x01 0xff 0xff 0x00 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0x00 0x00 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00 0x00 0x00 0xff 0xff 0xff 0xff 0xff 0xff>; + + #address-cells = <2>; + #size-cells = <0>; + #sound-dai-cells = <1>; + + status = "disabled"; + }; + + lpass_txmacro: codec@72e0000 { + compatible = "qcom,maili-lpass-tx-macro", "qcom,hawi-lpass-tx-macro"; + reg = <0x0 0x72e0000 0x0 0x1000>; + clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_LPR_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&lpass_vamacro>; + clock-names = "mclk", "lpr", "dcodec", "fsgen"; + + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + swr2: soundwire@7e90000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x0 0x7e90000 0x0 0x10000>; + interrupts = , + ; + interrupt-names = "core", "wakeup"; + clocks = <&lpass_txmacro>; + clock-names = "iface"; + label = "TX"; + + pinctrl-0 = <&tx_swr_active>; + pinctrl-names = "default"; + + qcom,din-ports = <4>; + qcom,dout-ports = <0>; + qcom,ports-sinterval-low = /bits/ 8 <0x01 0x01 0x01 0x03>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x00 0x01>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0xff 0x00 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0xff 0x0f 0xff>; + qcom,ports-word-length = /bits/ 8 <0xff 0x00 0x00 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0x00 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0x00 0xff>; + qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x01 0x00>; + + #address-cells = <2>; + #size-cells = <0>; + #sound-dai-cells = <1>; + + status = "disabled"; + }; + + lpass_vamacro: codec@7ec0000 { + compatible = "qcom,maili-lpass-va-macro", "qcom,hawi-lpass-va-macro"; + reg = <0x0 0x07ec0000 0x0 0x2000>; + clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_LPR_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&lpass_va_csr>; + clock-names = "mclk", "lpr", "dcodec", "heartbeatpulse"; + + #clock-cells = <0>; + clock-output-names = "fsgen"; + #sound-dai-cells = <1>; + }; + + lpass_va_csr: va-csr@7ee0000 { + compatible = "qcom,hawi-lpass-va-csr"; + reg = <0x0 0x07ee0000 0x0 0xe000>; + clocks = <&q6prmcc LPASS_HW_LPR_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "lpr", "audio"; + #clock-cells = <0>; + }; + + lpass_tlmm: pinctrl@7f60000 { + compatible = "qcom,hawi-lpass-lpi-pinctrl"; + reg = <0x0 0x07f60000 0x0 0x20000>; + + clocks = <&q6prmcc LPASS_HW_LPR_VOTE + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "lpr", "audio"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&lpass_tlmm 0 0 23>; + + dmic01_default: dmic01-default-state { + clk-pins { + pins = "gpio6"; + function = "dmic1_clk"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio7"; + function = "dmic1_data"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic23_default: dmic23-default-state { + clk-pins { + pins = "gpio8"; + function = "dmic2_clk"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio9"; + function = "dmic2_data"; + drive-strength = <8>; + input-enable; + }; + }; + + lpi_i2s1_active: lpi-i2s1-active-state { + clk-pins { + pins = "gpio10"; + function = "i2s1_clk"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + ws-pins { + pins = "gpio11"; + function = "i2s1_ws"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + data-pins { + pins = "gpio15", "gpio16"; + function = "i2s1_data"; + drive-strength = <8>; + bias-disable; + output-high; + }; + }; + + lpi_i2s1_sleep: lpi-i2s1-sleep-state { + clk-pins { + pins = "gpio10"; + function = "i2s1_clk"; + drive-strength = <2>; + bias-pull-down; + input-enable; + }; + + ws-pins { + pins = "gpio11"; + function = "i2s1_ws"; + drive-strength = <2>; + bias-pull-down; + input-enable; + }; + + data-pins { + pins = "gpio15", "gpio16"; + function = "i2s1_data"; + drive-strength = <2>; + bias-pull-down; + input-enable; + }; + }; + + rx_swr_active: rx-swr-active-state { + clk-pins { + pins = "gpio3"; + function = "swr_rx_clk"; + drive-strength = <2>; + slew-rate = <1>; + bias-disable; + }; + + data-pins { + pins = "gpio4", "gpio5"; + function = "swr_rx_data"; + drive-strength = <2>; + slew-rate = <1>; + bias-bus-hold; + }; + }; + + tx_swr_active: tx-swr-active-state { + clk-pins { + pins = "gpio0"; + function = "swr_tx_clk"; + drive-strength = <2>; + slew-rate = <1>; + bias-disable; + }; + + data-pins { + pins = "gpio1", "gpio2", "gpio14"; + function = "swr_tx_data"; + drive-strength = <2>; + slew-rate = <1>; + bias-bus-hold; + }; }; }; From 36a1a002af611f75b287dda908cf1202c03c5d66 Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Wed, 23 Sep 2026 14:16:26 +0530 Subject: [PATCH 0307/1133] FROMLIST: arm64: dts: qcom: maili-mtp: enable audio playback and capture Wire up the audio use cases on the Maili MTP board on top of the LPASS nodes added to the SoC dtsi, mirroring the Maili QRD board. Add the sound card with the TDM playback, WCD playback/capture and VA DMIC capture DAI links and the associated audio routing. Describe the WCD9395 codec, enable the RX and TX SoundWire controllers with their WCD RX/TX satellite ports, and add the WSA8855 speaker amplifier on i2c3. Configure the VA macro DMIC supply and the required TLMM pin states (WCD reset, WSA IRQ, WSA shutdown). The MTP and QRD boards share the same SoC and PMIC rails, so the same regulators (vreg_l2d_1p8, vreg_l4g_1p2, vreg_l15b_1p8, vreg_bob1, vreg_l1g_1p2, vreg_l10b_1p8) and the pmh0110_f_e0_gpios speaker shutdown GPIO from the shared pmh0110-kaanapali.dtsi apply unchanged. Link: https://lore.kernel.org/lkml/20260923084627.748920-8-prasad.kumpatla@oss.qualcomm.com/ Signed-off-by: Prasad Kumpatla Signed-off-by: Mukesh Ojha --- arch/arm64/boot/dts/qcom/maili-mtp.dts | 206 +++++++++++++++++++++++++ 1 file changed, 206 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/maili-mtp.dts b/arch/arm64/boot/dts/qcom/maili-mtp.dts index 1fdc91e03271c..31192a01e70e3 100644 --- a/arch/arm64/boot/dts/qcom/maili-mtp.dts +++ b/arch/arm64/boot/dts/qcom/maili-mtp.dts @@ -7,9 +7,11 @@ #include #include +#include #include #include #include +#include #include "maili.dtsi" #include "pm8010-kaanapali.dtsi" /* SPMI1: SID-C/D */ #include "pmd8028-kaanapali.dtsi" /* SPMI1: SID-4 */ @@ -126,6 +128,122 @@ }; }; + maili_sound: sound { + compatible = "qcom,maili-sndcard", "qcom,sm8450-sndcard"; + model = "MAILI-MTP"; + + audio-routing = "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2", + "VA DMIC0", "MIC BIAS1", + "VA DMIC1", "MIC BIAS1", + "VA DMIC2", "MIC BIAS3", + "VA DMIC3", "MIC BIAS3", + "TX SWR_INPUT", "ADC2_OUTPUT"; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&lpi_i2s1_active>; + pinctrl-1 = <&lpi_i2s1_sleep>; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + + codec { + sound-dai = <&lpass_vamacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-capture-dai-link { + link-name = "WCD Capture"; + + codec { + sound-dai = <&wcd939x 1>, <&swr2 0>, <&lpass_txmacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-playback-dai-link { + link-name = "WCD Playback"; + + codec { + sound-dai = <&wcd939x 0>, <&swr1 0>, <&lpass_rxmacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wsa-playback-dai-link { + link-name = "WSA Playback"; + + codec { + sound-dai = <&wsa885x>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; + }; + + cpu { + sound-dai = <&q6apmbedai AIF_TDM_RX_1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + + wcd939x: audio-codec { + compatible = "qcom,wcd9395-codec", "qcom,wcd9390-codec"; + + pinctrl-0 = <&wcd_default>; + pinctrl-names = "default"; + + qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 + 500000 500000 500000 500000>; + qcom,mbhc-headphone-vthreshold-microvolt = <50000>; + qcom,mbhc-headset-vthreshold-microvolt = <1700000>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + qcom,micbias4-microvolt = <1800000>; + qcom,rx-device = <&wcd_rx>; + qcom,tx-device = <&wcd_tx>; + + reset-gpios = <&tlmm 161 GPIO_ACTIVE_LOW>; + + vdd-buck-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l15b_1p8>; + vdd-mic-bias-supply = <&vreg_bob1>; + vdd-px-supply = <&vreg_l3f_1p2>; + vdd-rxtx-supply = <&vreg_l15b_1p8>; + + #sound-dai-cells = <1>; + }; + sdcard_vdd_3p0: sdcard-vdd-3p0 { compatible = "regulator-fixed"; @@ -743,6 +861,70 @@ }; }; +&i2c3 { + + status = "okay"; + + wsa885x: speaker@c { + compatible = "qcom,wsa8855"; + reg = <0x0c>; + + interrupt-parent = <&tlmm>; + interrupts = <98 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-0 = <&wsa885x_spkr_sd_n &wsa885x_irq_gpio>; + pinctrl-names = "default"; + + powerdown-gpios = <&pmh0110_f_e0_gpios 11 GPIO_ACTIVE_LOW>; + + vdd-1p8-supply = <&vreg_l2d_1p8>; + vdd-io-supply = <&vreg_l4g_1p2>; + + qcom,battery-config = "1s"; + + #sound-dai-cells = <0>; + + status = "okay"; + }; +}; + +&lpass_vamacro { + pinctrl-0 = <&dmic01_default>, <&dmic23_default>; + pinctrl-names = "default"; + + vdd-micb-supply = <&vreg_l10b_1p8>; + qcom,dmic-sample-rate = <4800000>; +}; + +&q6apmbedai { + dai@40 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_QAIF_IF1_IBIT + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; +}; + +&swr1 { + status = "okay"; + wcd_rx: codec@0,4 { + compatible = "sdw20217010e00"; + reg = <0 4>; + + qcom,rx-port-mapping = <1 2 3 4 5 9>; + }; +}; + +&swr2 { + status = "okay"; + + wcd_tx: codec@0,3 { + compatible = "sdw20217010e00"; + reg = <0 3>; + qcom,tx-port-mapping = <3 3 3 4>; + }; +}; + &pcie0 { status = "okay"; }; @@ -820,6 +1002,16 @@ }; }; +&pmh0110_f_e0_gpios { + wsa885x_spkr_sd_n: wsa885x-spkr-sd-n-state { + pins = "gpio11"; + function = "normal"; + input-disable; + output-enable; + power-source = <1>; /* 1.8V */ + }; +}; + &pmh0101_pwm { status = "okay"; @@ -906,6 +1098,20 @@ <119 2>, /* SoCCP */ <144 2>, /* CXM UART */ <211 1>; /* NFC Secure IO */ + + wcd_default: wcd-reset-n-active-state { + pins = "gpio161"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + wsa885x_irq_gpio: wsa885x-irq-state { + pins = "gpio98"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; }; &uart7 { From 7e69935d20024227763eb9ac174a154ff98a4b83 Mon Sep 17 00:00:00 2001 From: Bhaskar Reddy Valluru Date: Wed, 23 Sep 2026 15:55:54 +0530 Subject: [PATCH 0308/1133] FROMLIST: arm64: dts: qcom: maili: Add GPU support Add the GPU and GMU nodes describing the register maps, interrupts, clocks, power domains, IOMMU, interconnect paths and the OPP tables. The GPU node is left disabled here and is enabled by the board devicetrees. Link: https://lore.kernel.org/lkml/20260923-hawi-gpu-v1-14-0c3c79a1a470@oss.qualcomm.com/ Signed-off-by: Bhaskar Reddy Valluru Signed-off-by: Akhil P Oommen Signed-off-by: Mukesh Ojha --- arch/arm64/boot/dts/qcom/maili.dtsi | 309 ++++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/maili.dtsi b/arch/arm64/boot/dts/qcom/maili.dtsi index 5540a7630c3ad..7c74d9e4834cd 100644 --- a/arch/arm64/boot/dts/qcom/maili.dtsi +++ b/arch/arm64/boot/dts/qcom/maili.dtsi @@ -3778,6 +3778,250 @@ #reset-cells = <1>; }; + gpu: gpu@3d00000 { + compatible = "qcom,adreno-44041400", "qcom,adreno"; + reg = <0x0 0x03d00000 0x0 0x6c000>, + <0x0 0x03d9e000 0x0 0x2000>; + reg-names = "kgsl_3d0_reg_memory", + "cx_mem"; + + interrupts = ; + + iommus = <&adreno_smmu 0 0x0>, + <&adreno_smmu 1 0x0>; + + operating-points-v2 = <&gpu_opp_table>; + + qcom,gmu = <&gmu>; + #cooling-cells = <2>; + + nvmem-cells = <&gpu_speed_bin>; + nvmem-cell-names = "speed_bin"; + + interconnects = <&gem_noc MASTER_GFX3D QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "gfx-mem"; + + status = "disabled"; + + gpu_zap_shader: zap-shader { + memory-region = <&gpu_microcode_mem>; + }; + + gpu_opp_table: opp-table { + compatible = "operating-points-v2-adreno", + "operating-points-v2"; + + opp-1450000000 { + opp-hz = /bits/ 64 <1450000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x88295ffd>; + }; + + opp-1400000000 { + opp-hz = /bits/ 64 <1400000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x88295ffd>; + }; + + opp-1350000000 { + opp-hz = /bits/ 64 <1350000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa8295ffd>; + }; + + opp-1275000000 { + opp-hz = /bits/ 64 <1275000000>; + opp-level = ; + opp-peak-kBps = <18671875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82a5ffd>; + }; + + opp-1201000000 { + opp-hz = /bits/ 64 <1201000000>; + opp-level = ; + opp-peak-kBps = <18671875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82b5ffd>; + }; + + opp-1126000000 { + opp-hz = /bits/ 64 <1126000000>; + opp-level = ; + opp-peak-kBps = <16500000>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82b5ffd>; + }; + + opp-1025000000 { + opp-hz = /bits/ 64 <1025000000>; + opp-level = ; + opp-peak-kBps = <16500000>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82b5ffd>; + }; + + opp-951000000 { + opp-hz = /bits/ 64 <951000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82b5ffd>; + }; + + opp-843000000 { + opp-hz = /bits/ 64 <843000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82c5ffd>; + }; + + opp-801000000 { + opp-hz = /bits/ 64 <801000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x882d5ffd>; + }; + + opp-759000000 { + opp-hz = /bits/ 64 <759000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82d5ffd>; + }; + + opp-693000000 { + opp-hz = /bits/ 64 <693000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x882e5ffd>; + }; + + opp-636000000 { + opp-hz = /bits/ 64 <636000000>; + opp-level = ; + opp-peak-kBps = <10687500>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x882f5ffd>; + }; + + opp-578000000 { + opp-hz = /bits/ 64 <578000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe02a5ffd>; + }; + + opp-539000000 { + opp-hz = /bits/ 64 <539000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xc02c5ffd>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xc02d5ffd>; + }; + + opp-461000000 { + opp-hz = /bits/ 64 <461000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xc02e5ffd>; + }; + + opp-422000000 { + opp-hz = /bits/ 64 <422000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82f5ffd>; + }; + + opp-390000000 { + opp-hz = /bits/ 64 <390000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82f5ffd>; + }; + + opp-357000000 { + opp-hz = /bits/ 64 <357000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82f5ffd>; + }; + + opp-325000000 { + opp-hz = /bits/ 64 <325000000>; + opp-level = ; + opp-peak-kBps = <5285156>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82f5ffd>; + }; + + opp-274000000 { + opp-hz = /bits/ 64 <274000000>; + opp-level = ; + opp-peak-kBps = <5285156>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82f5ffd>; + }; + + opp-222000000 { + opp-hz = /bits/ 64 <222000000>; + opp-level = ; + opp-peak-kBps = <2136718>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82f5ffd>; + }; + + opp-190000000 { + opp-hz = /bits/ 64 <190000000>; + opp-level = ; + opp-peak-kBps = <2136718>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82f5ffd>; + }; + + opp-157000000 { + opp-hz = /bits/ 64 <157000000>; + opp-level = ; + opp-peak-kBps = <2136718>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82f5ffd>; + }; + + opp-125000000 { + opp-hz = /bits/ 64 <125000000>; + opp-level = ; + opp-peak-kBps = <2136718>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82f5ffd>; + }; + }; + }; + gxclkctl: clock-controller@3d64000 { compatible = "qcom,maili-gxclkctl", "qcom,kaanapali-gxclkctl"; reg = <0x0 0x03d64000 0x0 0x6000>; @@ -3789,6 +4033,71 @@ #power-domain-cells = <1>; }; + gmu: gmu@3d6c000 { + compatible = "qcom,adreno-gmu-845.0", "qcom,adreno-gmu"; + reg = <0x0 0x03d6c000 0x0 0x32000>; + reg-names = "gmu"; + + interrupts = , + ; + interrupt-names = "hfi", "gmu"; + + clocks = <&gpucc GPU_CC_CX_GMU_CLK>, + <&gpucc GPU_CC_CXO_CLK>, + <&gpucc GPU_CC_GPU_SMMU_VOTE_CLK>, + <&gpucc GPU_CC_AHB_CLK>, + <&gpucc GPU_CC_MXG_AHB_CLK>, + <&gpucc GPU_CC_HUB_CX_INT_CLK>; + clock-names = "gmu", + "cxo", + "smmu_vote", + "ahb", + "mxg_ahb", + "hub"; + + power-domains = <&gpucc GPU_CC_CX_GDSC>, + <&gxclkctl GX_CLKCTL_GX_GDSC>, + <&gpucc GPU_CC_MXG_GDSC>; + power-domain-names = "cx", + "gx", + "gmu_mx"; + + iommus = <&adreno_smmu 5 0x0>; + + qcom,qmp = <&aoss_qmp>; + + operating-points-v2 = <&gmu_opp_table>; + + gmu_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-556000000 { + opp-hz = /bits/ 64 <556000000>; + opp-level = ; + }; + + opp-788000000 { + opp-hz = /bits/ 64 <788000000>; + opp-level = ; + }; + + opp-825000000 { + opp-hz = /bits/ 64 <825000000>; + opp-level = ; + }; + + opp-880000000 { + opp-hz = /bits/ 64 <880000000>; + opp-level = ; + }; + + opp-917000000 { + opp-hz = /bits/ 64 <917000000>; + opp-level = ; + }; + }; + }; + gpucc: clock-controller@3d90000 { compatible = "qcom,maili-gpucc"; reg = <0x0 0x03d90000 0x0 0x9800>; From 737dbe2795f342aded1793c9cc7570c18f5a71d9 Mon Sep 17 00:00:00 2001 From: Bhaskar Reddy Valluru Date: Wed, 23 Sep 2026 15:55:55 +0530 Subject: [PATCH 0309/1133] FROMLIST: arm64: dts: qcom: maili-mtp: Enable GPU Add the secure firmware name property and enable GPU support on Maili MTP device. Link: https://lore.kernel.org/lkml/20260923-hawi-gpu-v1-15-0c3c79a1a470@oss.qualcomm.com/ Signed-off-by: Bhaskar Reddy Valluru Signed-off-by: Akhil P Oommen Signed-off-by: Mukesh Ojha --- arch/arm64/boot/dts/qcom/maili-mtp.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/maili-mtp.dts b/arch/arm64/boot/dts/qcom/maili-mtp.dts index 31192a01e70e3..b7ed4a88a6900 100644 --- a/arch/arm64/boot/dts/qcom/maili-mtp.dts +++ b/arch/arm64/boot/dts/qcom/maili-mtp.dts @@ -1114,6 +1114,14 @@ }; }; +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/maili/gen81100_zap.mbn"; +}; + &uart7 { status = "okay"; }; From fe042d700a7ff0f709572370b999050df193c3d5 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Wed, 23 Sep 2026 16:32:42 +0530 Subject: [PATCH 0310/1133] FROMLIST: arm64: dts: qcom: maili: Add support for cambistmclkcc and camcc Add the device nodes for the cambistmclkcc and camcc on Qualcomm Maili SoC. Signed-off-by: Taniya Das Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-11-cbbb42e534ef@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/maili.dtsi | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/maili.dtsi b/arch/arm64/boot/dts/qcom/maili.dtsi index 7c74d9e4834cd..69c827f3528b1 100644 --- a/arch/arm64/boot/dts/qcom/maili.dtsi +++ b/arch/arm64/boot/dts/qcom/maili.dtsi @@ -3,9 +3,11 @@ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ +#include #include #include #include +#include #include #include #include @@ -2040,6 +2042,25 @@ qcom,bcm-voters = <&apps_bcm_voter>; }; + cambistmclkcc: clock-controller@1760000 { + compatible = "qcom,maili-cambistmclkcc", + "qcom,kaanapali-cambistmclkcc"; + reg = <0x0 0x01760000 0x0 0x6000>; + + clocks = <&gcc GCC_CAM_BIST_MCLK_AHB_CLK>, + <&bi_tcxo_div2>, + <&bi_tcxo_ao_div2>, + <&sleep_clk>; + + power-domains = <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MX>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + + #clock-cells = <1>; + #reset-cells = <1>; + }; + mmss_noc: interconnect@1780000 { compatible = "qcom,maili-mmss-noc"; reg = <0x0 0x01780000 0x0 0x5f800>; @@ -4637,6 +4658,28 @@ qcom,bcm-voters = <&apps_bcm_voter>; }; + camcc: clock-controller@956d000 { + compatible = "qcom,maili-camcc"; + reg = <0x0 0x0956d000 0x0 0x80000>; + + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&bi_tcxo_div2>, + <&bi_tcxo_ao_div2>, + <&sleep_clk>; + + power-domains = <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + + interconnects = <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mmss_noc SLAVE_MNOC_HF_MEM_NOC QCOM_ICC_TAG_ALWAYS>; + + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + usb: usb@a600000 { compatible = "qcom,maili-dwc3", "qcom,snps-dwc3"; reg = <0x0 0x0a600000 0x0 0xfc100>; From 75646f5bd654ffd23a7c5fe0c42a0999411ac89d Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Wed, 23 Sep 2026 16:32:43 +0530 Subject: [PATCH 0311/1133] FROMLIST: arm64: dts: qcom: maili: Add CAMSS and CSIPHY nodes for Maili Maili uses the same CAMSS IP as Hawi with five CSIPHY instances instead of six. Add CAMSS and CSIPHY nodes reusing the Hawi-compatible driver. 5 x CSIPHY 3 x TPG 3 x CSID 2 x CSID Lite 3 x IFE 2 x IFE Lite Acked-by: Konrad Dybcio Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-12-cbbb42e534ef@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/maili.dtsi | 412 ++++++++++++++++++++++++++++ 1 file changed, 412 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/maili.dtsi b/arch/arm64/boot/dts/qcom/maili.dtsi index 69c827f3528b1..e027d32b7e9cd 100644 --- a/arch/arm64/boot/dts/qcom/maili.dtsi +++ b/arch/arm64/boot/dts/qcom/maili.dtsi @@ -539,6 +539,28 @@ }; }; + csiphy_mxc_opp_table: opp-table-mxc { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs_d1_1>, + <&rpmhpd_opp_low_svs_d1_1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d0>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_nom>; + }; + }; + soc@0 { compatible = "simple-bus"; #address-cells = <2>; @@ -4658,6 +4680,396 @@ qcom,bcm-voters = <&apps_bcm_voter>; }; + camss: isp@9253000 { + compatible = "qcom,maili-camss", "qcom,hawi-camss"; + + reg = <0x0 0x09253000 0x0 0x5e80>, + <0x0 0x09263000 0x0 0x5e80>, + <0x0 0x09273000 0x0 0x5e80>, + <0x0 0x092d3000 0x0 0x3880>, + <0x0 0x092e7000 0x0 0x3880>, + <0x0 0x093fd000 0x0 0x400>, + <0x0 0x093fe000 0x0 0x400>, + <0x0 0x093ff000 0x0 0x400>, + <0x0 0x09151000 0x0 0x20000>, + <0x0 0x09171000 0x0 0x20000>, + <0x0 0x09191000 0x0 0x20000>, + <0x0 0x092dc000 0x0 0x6800>, + <0x0 0x092f0000 0x0 0x6800>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_DCD_XO_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_TITAN_MNOC_HF_CLK>, + <&camcc CAM_CC_TITAN_MNOC_SF_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "camnoc_dcd_xo", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_mnoc_hf", + "cpas_mnoc_sf", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc"; + + iommus = <&apps_smmu 0x1800 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + camss_csiphy0_inep: endpoint { + remote-endpoint = <&csiphy0_out_ep>; + }; + }; + + port@1 { + reg = <1>; + + camss_csiphy1_inep: endpoint { + remote-endpoint = <&csiphy1_out_ep>; + }; + }; + + port@2 { + reg = <2>; + + camss_csiphy2_inep: endpoint { + remote-endpoint = <&csiphy2_out_ep>; + }; + }; + + port@3 { + reg = <3>; + + camss_csiphy3_inep: endpoint { + remote-endpoint = <&csiphy3_out_ep>; + }; + }; + + port@4 { + reg = <4>; + + camss_csiphy4_inep: endpoint { + remote-endpoint = <&csiphy4_out_ep>; + }; + }; + }; + }; + + csiphy0: phy@9523000 { + compatible = "qcom,maili-csi2-phy", "qcom,kaanapali-csi2-phy"; + reg = <0x0 0x09523000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy0_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy0_out_ep: endpoint { + remote-endpoint = <&camss_csiphy0_inep>; + }; + }; + }; + }; + + csiphy1: phy@9525000 { + compatible = "qcom,maili-csi2-phy", "qcom,kaanapali-csi2-phy"; + reg = <0x0 0x09525000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy1_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy1_out_ep: endpoint { + remote-endpoint = <&camss_csiphy1_inep>; + }; + }; + }; + }; + + csiphy2: phy@9527000 { + compatible = "qcom,maili-csi2-phy", "qcom,kaanapali-csi2-phy"; + reg = <0x0 0x09527000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy2_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy2_out_ep: endpoint { + remote-endpoint = <&camss_csiphy2_inep>; + }; + }; + }; + }; + + csiphy3: phy@9529000 { + compatible = "qcom,maili-csi2-phy", "qcom,kaanapali-csi2-phy"; + reg = <0x0 0x09529000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy3_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy3_out_ep: endpoint { + remote-endpoint = <&camss_csiphy3_inep>; + }; + }; + }; + }; + + csiphy4: phy@952b000 { + compatible = "qcom,maili-csi2-phy", "qcom,kaanapali-csi2-phy"; + reg = <0x0 0x0952b000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy4_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy4_out_ep: endpoint { + remote-endpoint = <&camss_csiphy4_inep>; + }; + }; + }; + }; + camcc: clock-controller@956d000 { compatible = "qcom,maili-camcc"; reg = <0x0 0x0956d000 0x0 0x80000>; From f9c9abace4bc1b35f1f91faebe956fcfdc3f828b Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Wed, 23 Sep 2026 16:32:44 +0530 Subject: [PATCH 0312/1133] FROMLIST: arm64: dts: qcom: maili: Add camera MCLK pinctrl for Maili Define pinctrl definitions to enable camera master clocks on Maili. Reviewed-by: Konrad Dybcio Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-13-cbbb42e534ef@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/maili.dtsi | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/maili.dtsi b/arch/arm64/boot/dts/qcom/maili.dtsi index e027d32b7e9cd..bd9181031b37c 100644 --- a/arch/arm64/boot/dts/qcom/maili.dtsi +++ b/arch/arm64/boot/dts/qcom/maili.dtsi @@ -6348,6 +6348,48 @@ bias-disable; }; + mclk0_default: mclk0-default-state { + pins = "gpio95"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + mclk1_default: mclk1-default-state { + pins = "gpio90"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + mclk2_default: mclk2-default-state { + pins = "gpio91"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + mclk3_default: mclk3-default-state { + pins = "gpio92"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + mclk4_default: mclk4-default-state { + pins = "gpio93"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + mclk5_default: mclk5-default-state { + pins = "gpio94"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + }; sram@14680000 { From 0036d733f336b62c1b3265a456c00371b63b4030 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Wed, 23 Sep 2026 16:32:45 +0530 Subject: [PATCH 0313/1133] FROMLIST: arm64: dts: qcom: maili-mtp: Enable S5KJN5 camera for Maili MTP Qualcomm Maili MTP carries a Samsung S5KJN5 rear camera sensor on QUP I2C9, connected to CSIPHY2 via 4-lane CSI-2 D-PHY. Reviewed-by: Konrad Dybcio Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-14-cbbb42e534ef@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/maili-mtp.dts | 64 ++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/maili-mtp.dts b/arch/arm64/boot/dts/qcom/maili-mtp.dts index b7ed4a88a6900..a7d5e007155d9 100644 --- a/arch/arm64/boot/dts/qcom/maili-mtp.dts +++ b/arch/arm64/boot/dts/qcom/maili-mtp.dts @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -861,6 +862,28 @@ }; }; +&camss { + status = "okay"; +}; + +&camss_csiphy2_inep { + data-lanes = <1 2 3 4>; +}; + +&csiphy2 { + vdda-0p9-supply = <&vreg_l1d_0p9>; + vdda-1p2-supply = <&vreg_l3g_1p2>; + + status = "okay"; +}; + +&csiphy2_in_ep { + bus-type = ; + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&s5kjn5_ep>; +}; + &i2c3 { status = "okay"; @@ -888,6 +911,40 @@ }; }; +&i2c9 { + clock-frequency = <400000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + status = "okay"; + + camera@10 { + compatible = "samsung,s5kjn5"; + reg = <0x10>; + + reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&mclk2_default &cam2_reset_default>; + pinctrl-names = "default"; + + clocks = <&cambistmclkcc CAM_BIST_MCLK_CC_MCLK2_CLK>; + assigned-clocks = <&cambistmclkcc CAM_BIST_MCLK_CC_MCLK2_CLK>; + assigned-clock-rates = <19200000>; + + afvdd-supply = <&vreg_l5m_2p8>; + vdda-supply = <&vreg_l7m_2p2>; + vddd-supply = <&vreg_l1m_1p0>; + vddio-supply = <&vreg_l4n_1p8>; + vddio1p2-supply = <&vreg_l2n_1p2>; + + port { + s5kjn5_ep: endpoint { + link-frequencies = /bits/ 64 <1248000000>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&csiphy2_in_ep>; + }; + }; + }; +}; + &lpass_vamacro { pinctrl-0 = <&dmic01_default>, <&dmic23_default>; pinctrl-names = "default"; @@ -1099,6 +1156,13 @@ <144 2>, /* CXM UART */ <211 1>; /* NFC Secure IO */ + cam2_reset_default: cam2-reset-default-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + wcd_default: wcd-reset-n-active-state { pins = "gpio161"; function = "gpio"; From fb0c1fca6809c66a965ef609e1870b749f4578b5 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 10:41:15 +0800 Subject: [PATCH 0314/1133] FROMLIST: arm64: dts: qcom: maili: add iris video codec node Add the iris video codec device node for the maili SoC, describing the register space, interrupt, five power domains, eight clocks, two interconnect paths for CPU config and video memory bandwidth, IOMMU Mappings, and the operating point table covering 240 MHz to 1000 MHz. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_maili-v2-5-7223738e330d@oss.qualcomm.com/ Signed-off-by: Wangao Wang --- arch/arm64/boot/dts/qcom/maili.dtsi | 129 ++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/maili.dtsi b/arch/arm64/boot/dts/qcom/maili.dtsi index bd9181031b37c..ba5b453e3de4e 100644 --- a/arch/arm64/boot/dts/qcom/maili.dtsi +++ b/arch/arm64/boot/dts/qcom/maili.dtsi @@ -433,6 +433,10 @@ reg = <0x0 0xbd500000 0x0 0xf00000>; no-map; }; + + iris_resv: reservation-iris { + iommu-addresses = <&iris_non_pixel 0x0 0x0 0x0 0x25800000>; + }; }; smp2p-adsp { @@ -3636,6 +3640,131 @@ power-domains = <&gcc GCC_UFS_PHY_GDSC>; }; + iris: video-codec@2000000 { + compatible = "qcom,maili-iris"; + reg = <0x0 0x02000000 0x0 0xf0000>; + + interrupts = ; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc VIDEO_CC_MVS0_VPP0_GDSC>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vpp0"; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&gcc GCC_VIDEO_AXI0C_CLK>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0B_CLK>, + <&videocc VIDEO_CC_MVS0_VPP0_CLK>; + clock-names = "iface", + "core", + "vcodec0_core", + "iface1", + "core_freerun", + "vcodec0_core_freerun", + "vcodec_bse", + "vcodec_vpp0"; + + operating-points-v2 = <&iris_opp_table>; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_IRIS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_VIDEO_MVP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + memory-region = <&video_mem>; + + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>, + <&gcc GCC_VIDEO_AXI0C_CLK_ARES>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK_ARES>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK_ARES>; + reset-names = "bus0", + "bus1", + "core", + "vcodec0_core"; + + dma-coherent; + + #address-cells = <2>; + #size-cells = <2>; + + status = "disabled"; + + iris_non_pixel: non-pixel { + iommus = <&apps_smmu 0x1540 0x0000>, + <&apps_smmu 0x1620 0x0000>, + <&apps_smmu 0x1544 0x0000>; + memory-region = <&iris_resv>; + }; + + iris_pixel: pixel { + iommus = <&apps_smmu 0x1543 0x0000>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000 240000000 360000000>; + required-opps = <&rpmhpd_opp_low_svs_d2>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 507000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs>; + }; + + opp-420000000 { + opp-hz = /bits/ 64 <420000000 420000000 630000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000 533000000 800000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_nom>; + }; + + opp-630000000 { + opp-hz = /bits/ 64 <630000000 630000000 1104000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo>; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000 630000000 1260000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo_l1>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000 800000000 1260000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo_l3>; + }; + }; + }; + videocc: clock-controller@20f0000 { compatible = "qcom,maili-videocc"; reg = <0x0 0x020f0000 0x0 0x10000>; From f0918ec84bc1db199ca8674b741b4c14d6a0e205 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 10:41:16 +0800 Subject: [PATCH 0315/1133] FROMLIST: arm64: dts: qcom: maili: enable iris on mtp board Enable the iris video codec on the maili MTP reference board. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_maili-v2-6-7223738e330d@oss.qualcomm.com/ Signed-off-by: Wangao Wang --- arch/arm64/boot/dts/qcom/maili-mtp.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/maili-mtp.dts b/arch/arm64/boot/dts/qcom/maili-mtp.dts index a7d5e007155d9..f8b7f7202a617 100644 --- a/arch/arm64/boot/dts/qcom/maili-mtp.dts +++ b/arch/arm64/boot/dts/qcom/maili-mtp.dts @@ -945,6 +945,10 @@ }; }; +&iris { + status = "okay"; +}; + &lpass_vamacro { pinctrl-0 = <&dmic01_default>, <&dmic23_default>; pinctrl-names = "default"; From fe8e90e2eea572e2445f1260c411c6d595f28233 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:27 +0200 Subject: [PATCH 0316/1133] FROMLIST: soc: qcom: add core driver for the Qualcomm Crypto Engine Add the core driver for the Qualcomm crypto engine. Its task is to bind to the qce DT node, set up runtime PM for interconnect down-scaling and register the auxiliary device using the crypto offloader driver. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-12-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- drivers/soc/qcom/Kconfig | 11 +++++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/qce-core.c | 92 +++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 drivers/soc/qcom/qce-core.c diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 535c8619197b3..67d54d5211ff2 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -121,6 +121,17 @@ config QCOM_PMIC_GLINK Say yes here to support USB-C and battery status on modern Qualcomm platforms. +config QCOM_CRYPTO_CORE + tristate "Qualcomm Crypto Engine core driver" + depends on PM + select AUXILIARY_BUS + help + Core driver for the Qualcomm Crypto Engine. Say yes here to enable + the top-level driver that binds to the devicetree node representing + the QCE, registers the sub-devices implementing actual QCE + functionalities and sets up runtime PM allowing the interconnects to + scale down. + config QCOM_RAMP_CTRL tristate "Qualcomm Ramp Controller driver" help diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index bddd6f0a58367..9ef0f11d01585 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o CFLAGS_pmic_pdcharger_ulog.o := -I$(src) obj-$(CONFIG_QCOM_QMI_TMD) += qmi_tmd.o +obj-$(CONFIG_QCOM_CRYPTO_CORE) += qce-core.o obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o qmi_helpers-y += qmi_encdec.o qmi_interface.o obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o diff --git a/drivers/soc/qcom/qce-core.c b/drivers/soc/qcom/qce-core.c new file mode 100644 index 0000000000000..8a9d070935cc8 --- /dev/null +++ b/drivers/soc/qcom/qce-core.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2026 Qualcomm Technologies, Inc. and/or its subsidiaries + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define QCE_DEFAULT_MEM_BANDWIDTH 393600 + +static const char *const qce_core_aux_devs[] = { "crypto", NULL }; + +static int qce_core_probe(struct platform_device *pdev) +{ + static const char *const *subdev; + struct auxiliary_device *auxdev; + struct device *dev = &pdev->dev; + struct icc_path *mem_path; + int ret; + + mem_path = devm_of_icc_get(&pdev->dev, "memory"); + if (IS_ERR(mem_path)) + return PTR_ERR(mem_path); + + dev_set_drvdata(dev, mem_path); + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + + PM_RUNTIME_ACQUIRE(dev, pm); + ret = PM_RUNTIME_ACQUIRE_ERR(&pm); + if (ret) + return ret; + + for (subdev = qce_core_aux_devs; *subdev; subdev++) { + auxdev = __devm_auxiliary_device_create(dev, "qce", *subdev, NULL, 0); + if (IS_ERR(auxdev)) + return PTR_ERR(auxdev); + } + + return 0; +} + +static int qce_core_runtime_suspend(struct device *dev) +{ + struct icc_path *mem_path = dev_get_drvdata(dev); + + return icc_set_bw(mem_path, 0, 0); +} + +static int qce_core_runtime_resume(struct device *dev) +{ + struct icc_path *mem_path = dev_get_drvdata(dev); + + return icc_set_bw(mem_path, QCE_DEFAULT_MEM_BANDWIDTH, + QCE_DEFAULT_MEM_BANDWIDTH); +} + +static const struct dev_pm_ops qce_core_pm_ops = { + RUNTIME_PM_OPS(qce_core_runtime_suspend, qce_core_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) +}; + +static const struct of_device_id qce_core_of_match[] = { + { .compatible = "qcom,crypto-v5.1" }, + { .compatible = "qcom,crypto-v5.4" }, + { .compatible = "qcom,qce" }, + { } +}; +MODULE_DEVICE_TABLE(of, qce_core_of_match); + +static struct platform_driver qce_core_driver = { + .probe = qce_core_probe, + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = qce_core_of_match, + .pm = pm_ptr(&qce_core_pm_ops), + }, +}; +module_platform_driver(qce_core_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm crypto engine core driver"); +MODULE_ALIAS("platform:" KBUILD_MODNAME); +MODULE_AUTHOR("Bartosz Golaszewski "); From a9a60cfdc2eb513d1b0c0bc0c9f1e2437be88a7b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:28 +0200 Subject: [PATCH 0317/1133] FROMLIST: arm64: defconfig: enable the Qualcomm Crypto Engine core driver The QCE core driver should be enabled by default as it binds to the qce device node and scales down the interconnects if no child auxiliary driver is using the IP. Add it to the arm64 defconfig. Disable the crypto part of the driver by default. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-13-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- arch/arm64/configs/defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 52654d3b97c8e..22f5e669aa010 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1559,6 +1559,7 @@ CONFIG_QCOM_SMD_RPM=y CONFIG_QCOM_SMP2P=y CONFIG_QCOM_SMSM=y CONFIG_QCOM_SOCINFO=m +CONFIG_QCOM_CRYPTO_CORE=m CONFIG_QCOM_SPM=m CONFIG_QCOM_STATS=m CONFIG_QCOM_WCNSS_CTRL=m @@ -1845,7 +1846,6 @@ CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_CRYPTO_DEV_SUN8I_CE=m CONFIG_CRYPTO_DEV_FSL_CAAM=m CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=m -CONFIG_CRYPTO_DEV_QCE=m CONFIG_CRYPTO_DEV_TEGRA=m CONFIG_CRYPTO_DEV_ZYNQMP_AES=m CONFIG_CRYPTO_DEV_ZYNQMP_SHA3=m From 973a3815c26105147c2957fe2ad61d589392d261 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Sep 2026 14:57:29 +0200 Subject: [PATCH 0318/1133] FROMLIST: arm: multi_v7_defconfig: enable the Qualcomm Crypto Engine core driver The QCE core driver should be enabled by default as it binds to the qce device node and scales down the interconnects if no child auxiliary driver is using the IP. Add it to the multi_v7_defconfig. Disable the crypto part of the driver by default. Signed-off-by: Bartosz Golaszewski Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260922-qce-fix-self-tests-v9-14-b1aa742e79af@oss.qualcomm.com Signed-off-by: Udit Tiwari --- arch/arm/configs/multi_v7_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index d611e85c62e93..690904df74d2f 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -1142,6 +1142,7 @@ CONFIG_QCOM_SMD_RPM=y CONFIG_QCOM_SMP2P=y CONFIG_QCOM_SMSM=y CONFIG_QCOM_SOCINFO=m +CONFIG_QCOM_CRYPTO_CORE=m CONFIG_QCOM_STATS=m CONFIG_QCOM_WCNSS_CTRL=m CONFIG_ROCKCHIP_IODOMAIN=y @@ -1315,7 +1316,6 @@ CONFIG_CRYPTO_DEV_ATMEL_AES=m CONFIG_CRYPTO_DEV_ATMEL_TDES=m CONFIG_CRYPTO_DEV_ATMEL_SHA=m CONFIG_CRYPTO_DEV_MARVELL_CESA=m -CONFIG_CRYPTO_DEV_QCE=m CONFIG_CRYPTO_DEV_ROCKCHIP=m CONFIG_CRYPTO_DEV_STM32_HASH=m CONFIG_CRYPTO_DEV_STM32_CRYP=m From 9f825efa583b7a9fff3be10a55e6ba5be551bae1 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 01:53:21 +0530 Subject: [PATCH 0319/1133] FROMLIST: net: stmmac: qcom-ethqos: add Shikra EMAC support Shikra integrates two Qualcomm ETHQOS controllers based on the Synopsys GMAC IP, similar to previous platforms. Register qcom,shikra-ethqos backed by a new shikra_data descriptor that enables the three NOC clocks required for DMA memory access (axi-noc, pcie-tile-axi-noc, stmmaceth) all at 120 MHz, and the 36-bit DMA address width. As part of the NOC clock voting logic, the qcom-ethqos glue driver takes a second enable reference on the "stmmaceth" clock, which is already enabled by the stmmac core. All three clocks in shikra_noc_clks[] must run at 120 MHz for NOC access, and managing "stmmaceth" through the same clk_bulk path keeps the rate-setting and enable/disable together. Link: https://lore.kernel.org/netdev/20260908-shikra_ethernet-v2-9-bbe3389d0652@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 24fd6eda1dfd2..ddb714d7e2749 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -367,6 +367,37 @@ static const struct ethqos_emac_driver_data emac_v4_0_0_scmi_data = { .setup = ethqos_scmi_setup, }; +static const struct ethqos_noc_clk_cfg shikra_noc_clks[] = { + { "axi-noc", 120000000 }, + { "pcie-tile-axi-noc", 120000000 }, + { "stmmaceth", 120000000 }, +}; + +static const struct ethqos_emac_driver_data shikra_data = { + .dma_addr_width = 36, + .has_emac_ge_3 = true, + .noc_clk_cfg = shikra_noc_clks, + .num_noc_clks = ARRAY_SIZE(shikra_noc_clks), + .rgmii_config_loopback_en = false, + .dwmac4_addrs = { + .dma_chan = 0x00008100, + .dma_chan_offset = 0x1000, + .mtl_chan = 0x00008000, + .mtl_chan_offset = 0x1000, + .mtl_ets_ctrl = 0x00008010, + .mtl_ets_ctrl_offset = 0x1000, + .mtl_txq_weight = 0x00008018, + .mtl_txq_weight_offset = 0x1000, + .mtl_send_slp_cred = 0x0000801c, + .mtl_send_slp_cred_offset = 0x1000, + .mtl_high_cred = 0x00008020, + .mtl_high_cred_offset = 0x1000, + .mtl_low_cred = 0x00008024, + .mtl_low_cred_offset = 0x1000, + }, + .setup = ethqos_hlos_setup, +}; + static int ethqos_dll_configure(struct qcom_ethqos *ethqos) { struct device *dev = ðqos->pdev->dev; @@ -1124,6 +1155,7 @@ static const struct of_device_id qcom_ethqos_match[] = { { .compatible = "qcom,sa8255p-ethqos", .data = &emac_v4_0_0_scmi_data}, { .compatible = "qcom,sa8775p-ethqos", .data = &emac_v4_0_0_data}, { .compatible = "qcom,sc8280xp-ethqos", .data = &emac_v3_0_0_data}, + { .compatible = "qcom,shikra-ethqos", .data = &shikra_data}, { .compatible = "qcom,sm8150-ethqos", .data = &emac_v2_1_0_data}, { } }; From 2db660a869d5887c461da27d94ef4f050ef0d234 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 23 Sep 2026 02:40:44 +0530 Subject: [PATCH 0320/1133] FROMLIST: dt-bindings: net: pcs: add Qualcomm Nord XPCS Document the Qualcomm Nord integrated DesignWare XPCS compatible. The XPCS resides in an Ethernet power domain and requires its CSR clock for register access, so require the clock and power-domain resources for this compatible. Link: https://lore.kernel.org/netdev/20260923-qcom_xpcs_nord_emac-v1-1-4b1c682af70f@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../bindings/net/pcs/snps,dw-xpcs.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml b/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml index e77eec9ac9ee0..68bb941cbb290 100644 --- a/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml +++ b/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml @@ -22,6 +22,17 @@ description: by means of the APB3/MCI interfaces. In the later case the XPCS can be mapped right to the system IO memory space. +allOf: + - if: + properties: + compatible: + const: qcom,nord-dw-xpcs + then: + required: + - clocks + - clock-names + - power-domains + properties: compatible: oneOf: @@ -41,6 +52,8 @@ properties: const: snps,dw-xpcs-gen5-10g - description: Synopsys DesignWare XPCS with Consumer Gen5 12G PMA const: snps,dw-xpcs-gen5-12g + - description: Qualcomm Nord integrated DesignWare XPCS + const: qcom,nord-dw-xpcs reg: items: @@ -98,6 +111,10 @@ properties: - enum: [core, pad] - const: pad + power-domains: + description: Power domain containing the integrated PCS registers + maxItems: 1 + required: - compatible - reg From c34c13967455e2955866c42ed5428a14d371e7d0 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 16 Sep 2026 15:24:07 +0530 Subject: [PATCH 0321/1133] FROMLIST: net: pcs: xpcs: add USXGMII Clause 37 autoneg support Add the Clause 37 USXGMII configuration and state handling required by XPCS variants which use Clause 37 framing for USXGMII. Link: https://lore.kernel.org/netdev/20260923-qcom_xpcs_nord_emac-v1-2-4b1c682af70f@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- drivers/net/pcs/pcs-xpcs.c | 113 +++++++++++++++++++++++++++++++++++ drivers/net/pcs/pcs-xpcs.h | 15 +++++ include/linux/pcs/pcs-xpcs.h | 1 + 3 files changed, 129 insertions(+) diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 6466e0ff2a98b..17d6f34c7afcf 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -283,6 +283,7 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs, switch (compat->an_mode) { case DW_AN_C73: case DW_10GBASER: + case DW_AN_C37_USXGMII: dev = MDIO_MMD_PCS; break; case DW_AN_C37_SGMII: @@ -355,6 +356,54 @@ static int xpcs_read_fault_c73(struct dw_xpcs *xpcs, return 0; } +static int xpcs_config_aneg_c37_usxgmii(struct dw_xpcs *xpcs) +{ + u16 mask, val; + int ret; + + /* Select BASE-R PCS mode. */ + ret = xpcs_modify(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, + DW_PCS_TYPE_SEL, MDIO_PCS_CTRL2_10GBR); + if (ret < 0) + return ret; + + /* Enable USXGMII before accessing the MII MMD registers. */ + ret = xpcs_modify_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, + DW_USXGMII_EN, DW_USXGMII_EN); + if (ret < 0) + return ret; + + /* Select single-port 10G-SXGMII mode. */ + ret = xpcs_modify_vpcs(xpcs, DW_VR_XS_PCS_KR_CTRL, + DW_USXG_MODE_SEL, + FIELD_PREP(DW_USXG_MODE_SEL, + DW_USXG_MODE_10G_SXGMII)); + if (ret < 0) + return ret; + + /* Disable Clause 37 AN before changing its configuration. */ + ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR, + BMCR_ANENABLE, 0); + if (ret < 0) + return ret; + + /* Configure USXGMII per XPCS databook section 7.6. */ + mask = DW_VR_MII_AN_CTRL_8BIT | DW_VR_MII_SGMII_LINK_STS | + DW_VR_MII_TX_CONFIG_MASK | DW_VR_MII_PCS_MODE_MASK | + DW_VR_MII_AN_INTR_EN; + val = FIELD_PREP(DW_VR_MII_TX_CONFIG_MASK, + DW_VR_MII_TX_CONFIG_PHY_SIDE_SGMII) | + DW_VR_MII_SGMII_LINK_STS; + + ret = xpcs_modify(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, + mask, val); + if (ret < 0) + return ret; + + return xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR, + BMCR_ANENABLE, BMCR_ANENABLE); +} + static void xpcs_link_up_usxgmii(struct dw_xpcs *xpcs, int speed) { int ret, speed_sel; @@ -687,6 +736,7 @@ static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs, case DW_10GBASER: case DW_2500BASEX: + case DW_AN_C37_USXGMII: return LINK_INBAND_DISABLE; default: @@ -964,6 +1014,11 @@ static int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface, if (ret) return ret; break; + case DW_AN_C37_USXGMII: + ret = xpcs_config_aneg_c37_usxgmii(xpcs); + if (ret) + return ret; + break; case DW_2500BASEX: ret = xpcs_config_2500basex(xpcs); if (ret) @@ -1181,6 +1236,58 @@ static int xpcs_get_state_2500basex(struct dw_xpcs *xpcs, return 0; } +static int xpcs_get_state_c37_usxgmii(struct dw_xpcs *xpcs, + struct phylink_link_state *state) +{ + int ret; + u16 speed; + + state->link = false; + state->an_complete = false; + state->speed = SPEED_UNKNOWN; + state->duplex = DUPLEX_UNKNOWN; + state->pause = 0; + + ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS); + if (ret < 0) + return ret; + + state->an_complete = !!(ret & DW_VR_MII_AN_STS_C37_ANCMPLT_INTR); + state->link = !!(ret & DW_VR_MII_USXG_LINK); + if (!state->link) + return 0; + + speed = FIELD_GET(DW_VR_MII_USXG_SPEED, ret); + switch (speed) { + case DW_VR_MII_USXG_SPEED_10: + state->speed = SPEED_10; + break; + case DW_VR_MII_USXG_SPEED_100: + state->speed = SPEED_100; + break; + case DW_VR_MII_USXG_SPEED_1000: + state->speed = SPEED_1000; + break; + case DW_VR_MII_USXG_SPEED_10000: + state->speed = SPEED_10000; + break; + case DW_VR_MII_USXG_SPEED_2500: + state->speed = SPEED_2500; + break; + case DW_VR_MII_USXG_SPEED_5000: + state->speed = SPEED_5000; + break; + default: + state->link = false; + return 0; + } + + state->duplex = ret & DW_VR_MII_USXG_FULL ? + DUPLEX_FULL : DUPLEX_HALF; + + return 0; +} + static void xpcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode, struct phylink_link_state *state) { @@ -1214,6 +1321,12 @@ static void xpcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode, dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n", "xpcs_get_state_c37_1000basex", ERR_PTR(ret)); break; + case DW_AN_C37_USXGMII: + ret = xpcs_get_state_c37_usxgmii(xpcs, state); + if (ret) + dev_err(&xpcs->mdiodev->dev, "%s returned %pe\n", + "xpcs_get_state_c37_usxgmii", ERR_PTR(ret)); + break; case DW_2500BASEX: ret = xpcs_get_state_2500basex(xpcs, state); if (ret) diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h index 929fa238445ed..cbf583ff55ba0 100644 --- a/drivers/net/pcs/pcs-xpcs.h +++ b/drivers/net/pcs/pcs-xpcs.h @@ -13,6 +13,7 @@ #define DW_VENDOR BIT(15) /* VR_XS_PCS */ +#define DW_PCS_TYPE_SEL GENMASK(3, 0) #define DW_USXGMII_RST BIT(10) #define DW_USXGMII_EN BIT(9) #define DW_VR_XS_PCS_DIG_CTRL1 0x0000 @@ -20,6 +21,9 @@ #define DW_EN_VSMMD1 BIT(13) #define DW_CL37_BP BIT(12) #define DW_VR_XS_PCS_DIG_STS 0x0010 +#define DW_VR_XS_PCS_KR_CTRL 0x0007 +#define DW_USXG_MODE_SEL GENMASK(12, 10) +#define DW_USXG_MODE_10G_SXGMII 0 #define DW_RXFIFO_ERR GENMASK(6, 5) #define DW_PSEQ_ST GENMASK(4, 2) #define DW_PSEQ_ST_GOOD FIELD_PREP(GENMASK(4, 2), 0x4) @@ -68,6 +72,7 @@ #define DW_VR_MII_PCS_MODE_C37_1000BASEX 0x0 #define DW_VR_MII_PCS_MODE_C37_SGMII 0x2 #define DW_VR_MII_AN_INTR_EN BIT(0) +#define DW_VR_MII_SGMII_LINK_STS BIT(4) #define DW_VR_MII_AN_INTR_STS 0x8002 #define DW_VR_MII_AN_STS_C37_ANCMPLT_INTR BIT(0) @@ -78,6 +83,16 @@ #define DW_VR_MII_C37_ANSGM_SP_1000 0x2 #define DW_VR_MII_C37_ANSGM_SP_LNKSTS BIT(4) +#define DW_VR_MII_USXG_LINK BIT(14) +#define DW_VR_MII_USXG_FULL BIT(13) +#define DW_VR_MII_USXG_SPEED GENMASK(12, 10) +#define DW_VR_MII_USXG_SPEED_10 0 +#define DW_VR_MII_USXG_SPEED_100 1 +#define DW_VR_MII_USXG_SPEED_1000 2 +#define DW_VR_MII_USXG_SPEED_10000 3 +#define DW_VR_MII_USXG_SPEED_2500 4 +#define DW_VR_MII_USXG_SPEED_5000 5 + #define DW_VR_MII_EEE_MCTRL0 0x8006 #define DW_VR_MII_EEE_LTX_EN BIT(0) /* LPI Tx Enable */ #define DW_VR_MII_EEE_LRX_EN BIT(1) /* LPI Rx Enable */ diff --git a/include/linux/pcs/pcs-xpcs.h b/include/linux/pcs/pcs-xpcs.h index 36073f7b6bb40..4ea995b70150e 100644 --- a/include/linux/pcs/pcs-xpcs.h +++ b/include/linux/pcs/pcs-xpcs.h @@ -20,6 +20,7 @@ #define DW_2500BASEX 3 #define DW_AN_C37_1000BASEX 4 #define DW_10GBASER 5 +#define DW_AN_C37_USXGMII 6 enum dw_xpcs_pcs_id { DW_XPCS_ID_NATIVE = 0, From 99d098481e11bb6b27a4e6945fcb14f615da7f25 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 23 Sep 2026 02:43:21 +0530 Subject: [PATCH 0322/1133] FROMLIST: net: pcs: xpcs: add custom platform register accessors Some XPCS integrations do not expose the standard direct or indirect register layout. Allow the platform driver to use optional register read and write callbacks for both Clause 22 and Clause 45 accesses, while retaining the existing access paths when no callbacks are supplied. Link: https://lore.kernel.org/netdev/20260923-qcom_xpcs_nord_emac-v1-3-4b1c682af70f@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- drivers/net/pcs/pcs-xpcs-plat.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/net/pcs/pcs-xpcs-plat.c b/drivers/net/pcs/pcs-xpcs-plat.c index c4404500bac60..6d2277594c6df 100644 --- a/drivers/net/pcs/pcs-xpcs-plat.c +++ b/drivers/net/pcs/pcs-xpcs-plat.c @@ -24,8 +24,16 @@ /* Page select register for the indirect MMIO CSRs access */ #define DW_VR_CSR_VIEWPORT 0xff +struct dw_xpcs_plat_ops { + int (*reg_read)(struct platform_device *pdev, void __iomem *reg_base, + int dev, int reg); + int (*reg_write)(struct platform_device *pdev, void __iomem *reg_base, + int dev, int reg, u16 val); +}; + struct dw_xpcs_plat { struct platform_device *pdev; + const struct dw_xpcs_plat_ops *ops; struct mii_bus *bus; bool reg_indir; int reg_width; @@ -169,6 +177,10 @@ static int xpcs_mmio_read_c22(struct mii_bus *bus, int addr, int reg) if (addr != 0) return -ENODEV; + if (pxpcs->ops) + return pxpcs->ops->reg_read(pxpcs->pdev, pxpcs->reg_base, + MDIO_MMD_VEND2, reg); + if (pxpcs->reg_indir) return xpcs_mmio_read_reg_indirect(pxpcs, MDIO_MMD_VEND2, reg); else @@ -182,6 +194,10 @@ static int xpcs_mmio_write_c22(struct mii_bus *bus, int addr, int reg, u16 val) if (addr != 0) return -ENODEV; + if (pxpcs->ops) + return pxpcs->ops->reg_write(pxpcs->pdev, pxpcs->reg_base, + MDIO_MMD_VEND2, reg, val); + if (pxpcs->reg_indir) return xpcs_mmio_write_reg_indirect(pxpcs, MDIO_MMD_VEND2, reg, val); else @@ -195,6 +211,10 @@ static int xpcs_mmio_read_c45(struct mii_bus *bus, int addr, int dev, int reg) if (addr != 0) return -ENODEV; + if (pxpcs->ops) + return pxpcs->ops->reg_read(pxpcs->pdev, pxpcs->reg_base, + dev, reg); + if (pxpcs->reg_indir) return xpcs_mmio_read_reg_indirect(pxpcs, dev, reg); else @@ -209,6 +229,10 @@ static int xpcs_mmio_write_c45(struct mii_bus *bus, int addr, int dev, if (addr != 0) return -ENODEV; + if (pxpcs->ops) + return pxpcs->ops->reg_write(pxpcs->pdev, pxpcs->reg_base, + dev, reg, val); + if (pxpcs->reg_indir) return xpcs_mmio_write_reg_indirect(pxpcs, dev, reg, val); else From bd65ffeff6705c8746d7585ec5cc952a0c2e343f Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Thu, 30 Apr 2026 10:12:18 +0530 Subject: [PATCH 0323/1133] FROMLIST: pci: quirks: Advertise D3cold capability for UPD720201 PCIe-to-USB bridge UPD720201 does not advertise D3cold support until firmware is loaded post pci enumeration. This results in upd blocking D3cold entry during system suspend and causing overall failure to enter XO shutdown. Hence, add a quirk to advertise D3cold PME capability since the HW actually supports and advertises it post firmware loading. Link: https://lore.kernel.org/all/20260430-d3cold_support-v1-1-6734f280c481@oss.qualcomm.com/ Signed-off-by: Sushrut Shree Trivedi --- drivers/pci/quirks.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 7f1f47ea2ee41..76c7d253369a0 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -6595,3 +6595,13 @@ static void pci_mask_replay_timer_timeout(struct pci_dev *pdev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_GLI, 0x9750, pci_mask_replay_timer_timeout); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_GLI, 0x9755, pci_mask_replay_timer_timeout); #endif + +/* + * Renesas PCIe-to-USB bridge UPD720201 does not advertise D3cold + * capability by default until firmware is loaded post-enumeration. + */ +static void quirk_enable_d3cold(struct pci_dev *dev) +{ + dev->pme_support = dev->pme_support | (1 << PCI_D3cold); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_RENESAS, 0x0014, quirk_enable_d3cold); From 8fe1a3525cc2888cac18072d35394fa4ef4d9e7c Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 19 May 2026 14:26:02 +0530 Subject: [PATCH 0324/1133] FROMLIST: Bluetooth: hci_qca: Add M.2 Bluetooth device support using pwrseq Power supply to the M.2 Bluetooth device attached to the host using M.2 connector is controlled using the 'uart' pwrseq device. So add support for getting the pwrseq device if the OF graph link is present. Once obtained, the existing pwrseq APIs can be used to control the power supplies of the M.2 card. Link: https://lore.kernel.org/r/20260519-pwrseq-m2-bt-v3-7-b39dc2ae3966@oss.qualcomm.com Tested-by: Wei Deng Reviewed-by: Bartosz Golaszewski Reviewed-by: Dmitry Baryshkov Signed-off-by: Manivannan Sadhasivam --- drivers/bluetooth/hci_qca.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 7089e9b639b2a..e249fc6e44479 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -2454,6 +2455,18 @@ static int qca_serdev_probe(struct serdev_device *serdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + /* + * OF graph link is only present for BT devices attached through + * the M.2 Key E connector. + */ + if (of_graph_is_present(dev_of_node(&serdev->ctrl->dev))) { + qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->ctrl->dev, + "uart"); + if (IS_ERR(qcadev->bt_power->pwrseq)) + return PTR_ERR(qcadev->bt_power->pwrseq); + break; + } + if (!device_property_present(&serdev->dev, "enable-gpios")) { /* * Backward compatibility with old DT sources. If the From 61a09ea506cb1d11620dee055bcd1e2ba6d52bd3 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 19 May 2026 14:26:03 +0530 Subject: [PATCH 0325/1133] FROMLIST: Bluetooth: hci_qca: Rename 'power_ctrl_enabled' to 'bt_en_available' 'power_ctrl_enabled' flag is used to indicate the availability of the BT_EN GPIO in devicetree. But the naming causes confusion with the new pwrctrl framework. So rename it to 'bt_en_available' to make it clear and explicit. Link: https://lore.kernel.org/r/20260519-pwrseq-m2-bt-v3-8-b39dc2ae3966@oss.qualcomm.com Tested-by: Wei Deng Reviewed-by: Dmitry Baryshkov Reviewed-by: Bartosz Golaszewski Signed-off-by: Manivannan Sadhasivam --- drivers/bluetooth/hci_qca.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index e249fc6e44479..f53f95601693d 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2402,7 +2402,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) struct hci_dev *hdev; const struct qca_device_data *data; int err; - bool power_ctrl_enabled = true; + bool bt_en_available = true; qcadev = devm_kzalloc(&serdev->dev, sizeof(*qcadev), GFP_KERNEL); if (!qcadev) @@ -2510,7 +2510,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855 || data->soc_type == QCA_WCN7850)) - power_ctrl_enabled = false; + bt_en_available = false; qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", GPIOD_IN); @@ -2548,7 +2548,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) } if (!qcadev->bt_en) - power_ctrl_enabled = false; + bt_en_available = false; qcadev->susclk = devm_clk_get_optional_enabled_with_rate( &serdev->dev, NULL, SUSCLK_RATE_32KHZ); @@ -2566,7 +2566,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) hdev = qcadev->serdev_hu.hdev; - if (power_ctrl_enabled) { + if (bt_en_available) { hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); hdev->shutdown = qca_hci_shutdown; } From c51b39e70a80a6689e4d10a4bd9e3a8933877775 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 19 May 2026 14:26:04 +0530 Subject: [PATCH 0326/1133] FROMLIST: Bluetooth: hci_qca: Set 'bt_en_available' based on W_DISABLE2# presence in M.2 connector Check if the M.2 connector supports the W_DISABLE2# property or not by querying the pwrseq provider's DT node. If not available, then set 'bt_en_available' flag to 'false'. This flag is used to set the HCI_QUIRK_NON_PERSISTENT_SETUP HCI quirk, which informs the HCI layer whether the shutdown() callback for the device can be triggered or not. Link: https://lore.kernel.org/r/20260519-pwrseq-m2-bt-v3-9-b39dc2ae3966@oss.qualcomm.com Tested-by: Wei Deng Reviewed-by: Bartosz Golaszewski Signed-off-by: Manivannan Sadhasivam --- drivers/bluetooth/hci_qca.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index f53f95601693d..765d5c3ecb27a 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2460,10 +2460,17 @@ static int qca_serdev_probe(struct serdev_device *serdev) * the M.2 Key E connector. */ if (of_graph_is_present(dev_of_node(&serdev->ctrl->dev))) { + struct device *dev; + qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->ctrl->dev, "uart"); if (IS_ERR(qcadev->bt_power->pwrseq)) return PTR_ERR(qcadev->bt_power->pwrseq); + + dev = pwrseq_to_device(qcadev->bt_power->pwrseq); + if (!device_property_present(dev, "w-disable2-gpios")) + bt_en_available = false; + break; } From 3a7b8c846cfe6d06fd63b4306c9e4d60c7c5ff74 Mon Sep 17 00:00:00 2001 From: Saikiran Date: Wed, 28 Jan 2026 00:32:10 +0530 Subject: [PATCH 0327/1133] FROMLIST: dt-bindings: regulator: qcom,rpmh: Allow regulator-off-on-delay-us Add the standard 'regulator-off-on-delay-us' property to the list of allowed properties for RPMh regulators. This property is required for platforms where specific rails (like camera LDOs) rely on passive discharge and need a mandatory off-time constraint enforced by the regulator core. Link: https://lore.kernel.org/all/20260127190211.14312-2-bjsaikiran@gmail.com/ Signed-off-by: Saikiran --- .../devicetree/bindings/regulator/qcom,rpmh-regulator.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml index 9115885e7985b..31d2330d8422a 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml @@ -135,6 +135,8 @@ properties: $ref: regulator.yaml# unevaluatedProperties: false description: BOB regulator node. + properties: + regulator-off-on-delay-us: true dependencies: regulator-allow-set-load: [ regulator-allowed-modes ] @@ -144,6 +146,8 @@ patternProperties: $ref: regulator.yaml# unevaluatedProperties: false description: smps/ldo regulator nodes(s). + properties: + regulator-off-on-delay-us: true dependencies: regulator-allow-set-load: [ regulator-allowed-modes ] From 72074529646c4d4fb394bd0855db6e743a813472 Mon Sep 17 00:00:00 2001 From: Saikiran Date: Wed, 28 Jan 2026 00:32:11 +0530 Subject: [PATCH 0328/1133] FROMLIST: regulator: qcom-rpmh: Add support for regulator-off-on-delay-us The core regulator framework supports enforcing a physical off-time via standard properties, but the `qcom-rpmh-regulator` driver currently ignores them. The issue is platform-specific: The Lenovo Yoga Slim 7x (Snapdragon X Elite) has large bulk capacitors on the camera rails (LDO1, LDO3, LDO7). When these regulators are disabled, the voltage decays very slowly (passive discharge). If the rail is re-enabled before this discharge completes, the sensor experiences a brownout and fails to initialize. Add support for parsing the 'regulator-off-on-delay-us' property from the device tree to enforce this physical constraint. Link: https://lore.kernel.org/all/20260127190211.14312-3-bjsaikiran@gmail.com/ Signed-off-by: Saikiran --- drivers/regulator/qcom-rpmh-regulator.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 4c90d206e63bc..02c513960fece 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -552,6 +552,9 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev, vreg->always_wait_for_ack = of_property_read_bool(node, "qcom,always-wait-for-ack"); + of_property_read_u32(node, "regulator-off-on-delay-us", + &vreg->rdesc.off_on_delay); + vreg->rdesc.owner = THIS_MODULE; vreg->rdesc.type = REGULATOR_VOLTAGE; vreg->rdesc.ops = vreg->hw_data->ops; From 6b98b624288c240a318ac58007c311861046fddd Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Fri, 31 Jul 2026 23:36:14 +0530 Subject: [PATCH 0329/1133] FROMLIST: dt-bindings: iio: adc: Add support for QCOM PMIC5 Gen4 ADC PMIC5 Gen4 ADC is similar to PMIC5 Gen3 ADC, with several changes made for improved performance, mostly at the hardware level. The main differences are increased ratiometric conversion resolution (from 14 bits to 16 bits) and increased bit field width for PMIC SID (to allow communication with an increased number of PMICs, supported on latest SoCs). Link: https://lore.kernel.org/all/20260731-pmic5_gen4_adc-v1-1-9c49b2eea6f9@oss.qualcomm.com/ Signed-off-by: Jishnu Prakash --- .../bindings/iio/adc/qcom,spmi-adc5-gen3.yaml | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-adc5-gen3.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-adc5-gen3.yaml index 149f4af8f4b8b..e79ddc2acca06 100644 --- a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-adc5-gen3.yaml +++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-adc5-gen3.yaml @@ -21,9 +21,14 @@ description: | All boards using a particular (SOC + master PMIC) combination will have the same number of ADC SDAMs supported on that PMIC. + PMIC5 Gen4 ADC is similar to Gen3 ADC, with some differences such as + improved ratiometric conversion resolution. + properties: compatible: - const: qcom,spmi-adc5-gen3 + enum: + - qcom,spmi-adc5-gen3 + - qcom,spmi-adc5-gen4 reg: items: @@ -83,6 +88,46 @@ patternProperties: This property indicates ADC_TM monitoring is done on this channel. type: boolean + qcom,adc5-gen4: + description: + Indicates channel is of type ADC5 Gen4. This may be needed in cases where the + master PMIC has an ADC peripheral of type Gen3, but some of the other PMICs it + communicates with have ADC peripherals of type Gen4, so channels of those PMICs + need to be marked as Gen4 to ensure their conversions are handled correctly. + type: boolean + + qcom,adc5-gen3: + description: + Indicates channel is of type ADC5 Gen3. This may be needed in cases where the + master PMIC has an ADC peripheral of type Gen4, but some of the other PMICs + under it have ADC peripherals of type Gen3. + type: boolean + +allOf: + - if: + properties: + compatible: + contains: + const: qcom,spmi-adc5-gen4 + + then: + patternProperties: + "^channel@[0-9a-f]+$": + properties: + qcom,adc5-gen4: false + + - if: + properties: + compatible: + contains: + const: qcom,spmi-adc5-gen3 + + then: + patternProperties: + "^channel@[0-9a-f]+$": + properties: + qcom,adc5-gen3: false + required: - compatible - reg From d58601563f92bcdb39de2bc648dbe004d644a30d Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Fri, 31 Jul 2026 23:36:15 +0530 Subject: [PATCH 0330/1133] FROMLIST: iio: adc: qcom-spmi-adc5-gen3: Add support for QCOM PMIC5 Gen4 ADC PMIC5 Gen4 ADC is similar to PMIC5 Gen3 ADC, with several changes made for improved performance, mostly at the hardware level. One significant software change is that ratiometric conversion resolution has been increased from 14 bits to 16 bits, so the maximum value of these measurements needs to be updated for Gen4. Add a new scaling function for thermistor channels which use this type of conversion. In the latest PMIC arbiter version (v8), there can be up to 4 buses under the PMIC arbiter and 32 PMICs under each bus. In order to support communication between ADC on the master PMIC and ADCs on any of the other PMICs, a field of width 2 bits is added for bus index and the bits for SID are extended from 4 to 5 bits, in the SID register. Add support for this. In addition, it is possible that the master PMIC has ADC of one generation and it needs to communicate with another PMIC with ADC of a different generation. Add new DT properties "qcom,adc5-gen3" and "qcom,adc5-gen4", to distinguish Gen3 channels under a Gen4 master and Gen4 channels under a Gen3 master respectively, to ensure that their conversions are handled correctly. Link: https://lore.kernel.org/all/20260731-pmic5_gen4_adc-v1-2-9c49b2eea6f9@oss.qualcomm.com/ Co-developed-by: Anjelique Melendez Signed-off-by: Anjelique Melendez Signed-off-by: Jishnu Prakash --- drivers/iio/adc/qcom-spmi-adc5-gen3.c | 165 +++++++++++++----- drivers/iio/adc/qcom-vadc-common.c | 32 ++++ include/linux/iio/adc/qcom-adc5-gen3-common.h | 44 ++++- include/linux/iio/adc/qcom-vadc-common.h | 4 + 4 files changed, 195 insertions(+), 50 deletions(-) diff --git a/drivers/iio/adc/qcom-spmi-adc5-gen3.c b/drivers/iio/adc/qcom-spmi-adc5-gen3.c index c68c6c5f6aca0..810d25b665b13 100644 --- a/drivers/iio/adc/qcom-spmi-adc5-gen3.c +++ b/drivers/iio/adc/qcom-spmi-adc5-gen3.c @@ -86,7 +86,9 @@ int adc5_gen3_write(struct adc5_device_data *adc, unsigned int sdam_index, } EXPORT_SYMBOL_NS_GPL(adc5_gen3_write, "QCOM_SPMI_ADC5_GEN3"); -static int adc5_gen3_read_voltage_data(struct adc5_chip *adc, u16 *data) +static int adc5_gen3_read_voltage_data(struct adc5_chip *adc, + struct adc5_channel_common_prop *prop, + u16 *data) { u8 rslt[2]; int ret; @@ -99,8 +101,10 @@ static int adc5_gen3_read_voltage_data(struct adc5_chip *adc, u16 *data) *data = get_unaligned_le16(rslt); if (*data == ADC5_USR_DATA_CHECK) { - dev_err(adc->dev, "Invalid data:%#x\n", *data); - return -EINVAL; + if (!(prop->generation == ADC5_GEN4 && prop->cal_method == ADC5_RATIOMETRIC_CAL)) { + dev_err(adc->dev, "Invalid data:%#x\n", *data); + return -EINVAL; + } } dev_dbg(adc->dev, "voltage raw code:%#x\n", *data); @@ -131,8 +135,9 @@ static int adc5_gen3_configure(struct adc5_chip *adc, if (ret) return ret; - /* Write SID */ - buf[0] = FIELD_PREP(ADC5_GEN3_SID_MASK, prop->sid); + /* Write SID and bus_id*/ + buf[0] = FIELD_PREP(ADC5_GEN4_BUS_INDEX_MASK, prop->bus_index) | + FIELD_PREP(ADC5_GEN4_SID_MASK, prop->sid); /* * Use channel 0 by default for immediate conversion and to indicate @@ -268,7 +273,7 @@ static int adc5_gen3_do_conversion(struct adc5_chip *adc, return -ETIMEDOUT; } - ret = adc5_gen3_read_voltage_data(adc, data_volt); + ret = adc5_gen3_read_voltage_data(adc, prop, data_volt); if (ret) return ret; @@ -325,7 +330,7 @@ static int adc5_gen3_fwnode_xlate(struct iio_dev *indio_dev, int i, v_channel; for (i = 0; i < adc->nchannels; i++) { - v_channel = ADC5_GEN3_V_CHAN(adc->chan_props[i].common_props); + v_channel = ADC5_GEN4_V_CHAN(adc->chan_props[i].common_props); if (v_channel == iiospec->args[0]) return i; } @@ -351,7 +356,7 @@ static int adc5_gen3_read_raw(struct iio_dev *indio_dev, return ret; ret = qcom_adc5_hw_scale(prop->scale_fn_type, prop->prescale, - adc->data, adc_code_volt, val); + prop->data, adc_code_volt, val); if (ret) return ret; @@ -433,15 +438,89 @@ static const struct adc5_channels adc5_gen3_chans_pmic[ADC5_MAX_CHANNEL] = { SCALE_HW_CALIB_THERM_100K_PU_PM7) }; +static const struct adc5_channels adc5_gen4_chans_pmic[ADC5_MAX_CHANNEL] = { + [ADC5_GEN4_OFFSET_REF] = ADC5_CHAN_VOLT(0, + SCALE_HW_CALIB_DEFAULT) + [ADC5_GEN4_1P25VREF] = ADC5_CHAN_VOLT(0, + SCALE_HW_CALIB_DEFAULT) + [ADC5_GEN4_VPH_PWR] = ADC5_CHAN_VOLT(1, + SCALE_HW_CALIB_DEFAULT) + [ADC5_GEN4_VBAT_SNS_QBG] = ADC5_CHAN_VOLT(1, + SCALE_HW_CALIB_DEFAULT) + [ADC5_GEN4_DIE_TEMP] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_PMIC_THERM_PM7) + [ADC5_GEN4_AMUX1_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_GEN4) + [ADC5_GEN4_AMUX2_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_GEN4) + [ADC5_GEN4_AMUX3_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_GEN4) + [ADC5_GEN4_AMUX4_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_GEN4) + [ADC5_GEN4_AMUX5_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_GEN4) + [ADC5_GEN4_AMUX6_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_GEN4) + [ADC5_GEN4_AMUX1_GPIO_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_GEN4) + [ADC5_GEN4_AMUX2_GPIO_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_GEN4) + [ADC5_GEN4_AMUX3_GPIO_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_GEN4) + [ADC5_GEN4_AMUX4_GPIO_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_GEN4) + [ADC5_GEN4_AMUX5_GPIO_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_GEN4) +}; + +static const struct adc5_data adc5_gen3_data_pmic = { + .full_scale_code_volt = 0x70e4, + .adc_chans = adc5_gen3_chans_pmic, + .info = &adc5_gen3_info, + .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX]) + { 85, 340, 1360 }, + .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX]) + { 15, 100, 200, 300, + 400, 500, 600, 700, + 1000, 2000, 4000, 8000, + 16000, 32000, 64000, 128000 }, +}; + +static const struct adc5_data adc5_gen4_data_pmic = { + .full_scale_code_volt = 0x70e4, + .adc_chans = adc5_gen4_chans_pmic, + .info = &adc5_gen3_info, + .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX]) + { 85, 340, 1360 }, + .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX]) + { 15, 100, 200, 300, + 400, 500, 600, 700, + 1000, 2000, 4000, 8000, + 16000, 32000, 64000, 128000 }, +}; + +static const struct of_device_id adc5_match_table[] = { + { + .compatible = "qcom,spmi-adc5-gen3", + .data = &adc5_gen3_data_pmic, + }, + { + .compatible = "qcom,spmi-adc5-gen4", + .data = &adc5_gen4_data_pmic, + }, + { } +}; +MODULE_DEVICE_TABLE(of, adc5_match_table); + static int adc5_gen3_get_fw_channel_data(struct adc5_chip *adc, struct adc5_channel_prop *prop, struct fwnode_handle *fwnode) { const char *name = fwnode_get_name(fwnode); - const struct adc5_data *data = adc->data; + const struct adc5_data *data; + u32 chan, value, sid, bus_index; struct device *dev = adc->dev; const char *channel_name; - u32 chan, value, sid; u32 varr[2]; int ret; @@ -452,27 +531,46 @@ static int adc5_gen3_get_fw_channel_data(struct adc5_chip *adc, /* * Value read from "reg" is virtual channel number - * virtual channel number = sid << 8 | channel number + * virtual channel number = bus index << 13 | sid << 8 | channel number + * For ADC5 GEN3 channels, bus index = 0 */ - sid = FIELD_GET(ADC5_GEN3_VIRTUAL_SID_MASK, chan); - chan = FIELD_GET(ADC5_GEN3_CHANNEL_MASK, chan); + bus_index = FIELD_GET(ADC5_GEN4_V_CHAN_BUS_INDEX_MASK, chan); + sid = FIELD_GET(ADC5_GEN4_V_CHAN_SID_MASK, chan); + chan = FIELD_GET(ADC5_GEN4_V_CHAN_CHANNEL_MASK, chan); if (chan >= ADC5_MAX_CHANNEL) return dev_err_probe(dev, -EINVAL, "%s invalid channel number %d\n", name, chan); + prop->common_props.bus_index = bus_index; prop->common_props.channel = chan; prop->common_props.sid = sid; - if (!adc->data->adc_chans[chan].info_mask) + if (fwnode_property_read_bool(fwnode, "qcom,adc5-gen4")) { + prop->common_props.generation = ADC5_GEN4; + data = &adc5_gen4_data_pmic; + } else if (fwnode_property_read_bool(fwnode, "qcom,adc5-gen3")) { + prop->common_props.generation = ADC5_GEN3; + data = &adc5_gen3_data_pmic; + } else { + prop->common_props.generation = (adc->data == &adc5_gen3_data_pmic) ? + ADC5_GEN3 : ADC5_GEN4; + data = adc->data; + } + prop->common_props.data = data; + + if (!data->adc_chans[chan].info_mask) return dev_err_probe(dev, -EINVAL, "Channel %#x not supported\n", chan); channel_name = name; fwnode_property_read_string(fwnode, "label", &channel_name); prop->common_props.label = channel_name; - value = data->decimation[ADC5_DECIMATION_DEFAULT]; + if (prop->common_props.generation == ADC5_GEN3) + value = data->decimation[ADC5_DECIMATION_DEFAULT]; + else + value = data->decimation[ADC5_GEN4_DECIMATION_DEFAULT]; fwnode_property_read_u32(fwnode, "qcom,decimation", &value); ret = qcom_adc5_decimation_from_dt(value, data->decimation); if (ret < 0) @@ -480,7 +578,7 @@ static int adc5_gen3_get_fw_channel_data(struct adc5_chip *adc, chan, value); prop->common_props.decimation = ret; - prop->common_props.prescale = adc->data->adc_chans[chan].prescale_index; + prop->common_props.prescale = data->adc_chans[chan].prescale_index; ret = fwnode_property_read_u32_array(fwnode, "qcom,pre-scaling", varr, 2); if (!ret) { ret = qcom_adc5_prescaling_from_dt(varr[0], varr[1]); @@ -526,34 +624,13 @@ static int adc5_gen3_get_fw_channel_data(struct adc5_chip *adc, return 0; } -static const struct adc5_data adc5_gen3_data_pmic = { - .full_scale_code_volt = 0x70e4, - .adc_chans = adc5_gen3_chans_pmic, - .info = &adc5_gen3_info, - .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX]) - { 85, 340, 1360 }, - .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX]) - { 15, 100, 200, 300, - 400, 500, 600, 700, - 1000, 2000, 4000, 8000, - 16000, 32000, 64000, 128000 }, -}; - -static const struct of_device_id adc5_match_table[] = { - { - .compatible = "qcom,spmi-adc5-gen3", - .data = &adc5_gen3_data_pmic, - }, - { } -}; -MODULE_DEVICE_TABLE(of, adc5_match_table); - static int adc5_get_fw_data(struct adc5_chip *adc) { const struct adc5_channels *adc_chan; struct adc5_channel_prop *chan_props; struct iio_chan_spec *iio_chan; struct device *dev = adc->dev; + const struct adc5_data *data; unsigned int index = 0; int ret; @@ -582,10 +659,11 @@ static int adc5_get_fw_data(struct adc5_chip *adc) return ret; chan_props->chip = adc; - adc_chan = &adc->data->adc_chans[chan_props->common_props.channel]; + data = chan_props->common_props.data; + adc_chan = &data->adc_chans[chan_props->common_props.channel]; chan_props->common_props.scale_fn_type = adc_chan->scale_fn_type; - iio_chan->channel = ADC5_GEN3_V_CHAN(chan_props->common_props); + iio_chan->channel = ADC5_GEN4_V_CHAN(chan_props->common_props); iio_chan->info_mask_separate = adc_chan->info_mask; iio_chan->type = adc_chan->type; iio_chan->address = index; @@ -697,7 +775,7 @@ int adc5_gen3_get_scaled_reading(struct device *dev, return qcom_adc5_hw_scale(common_props->scale_fn_type, common_props->prescale, - adc->data, adc_code_volt, val); + common_props->data, adc_code_volt, val); } EXPORT_SYMBOL_NS_GPL(adc5_gen3_get_scaled_reading, "QCOM_SPMI_ADC5_GEN3"); @@ -705,12 +783,9 @@ int adc5_gen3_therm_code_to_temp(struct device *dev, struct adc5_channel_common_prop *common_props, u16 code, int *val) { - struct iio_dev *indio_dev = dev_get_drvdata(dev->parent); - struct adc5_chip *adc = iio_priv(indio_dev); - return qcom_adc5_hw_scale(common_props->scale_fn_type, common_props->prescale, - adc->data, code, val); + common_props->data, code, val); } EXPORT_SYMBOL_NS_GPL(adc5_gen3_therm_code_to_temp, "QCOM_SPMI_ADC5_GEN3"); diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c index b03cf584b1657..cb23d0d178c74 100644 --- a/drivers/iio/adc/qcom-vadc-common.c +++ b/drivers/iio/adc/qcom-vadc-common.c @@ -301,6 +301,10 @@ static const struct u32_fract adc5_prescale_ratios[] = { { .numerator = 1, .denominator = 16 }, }; +static int qcom_adc5_gen4_scale_hw_calib_therm( + const struct u32_fract *prescale, + const struct adc5_data *data, + u16 adc_code, int *result_mdec); static int qcom_vadc_scale_hw_calib_volt( const struct u32_fract *prescale, const struct adc5_data *data, @@ -341,6 +345,8 @@ static const struct qcom_adc5_scale_type scale_adc5_fn[] = { qcom_vadc7_scale_hw_calib_die_temp}, [SCALE_HW_CALIB_PM5_CHG_TEMP] = {qcom_vadc_scale_hw_chg5_temp}, [SCALE_HW_CALIB_PM5_SMB_TEMP] = {qcom_vadc_scale_hw_smb_temp}, + [SCALE_HW_CALIB_THERM_100K_PU_GEN4] = { + qcom_adc5_gen4_scale_hw_calib_therm}, }; static int qcom_vadc_map_voltage_temp(const struct vadc_map_pt *pts, @@ -556,6 +562,32 @@ static int qcom_vadc7_scale_hw_calib_therm( return 0; } +static int qcom_adc5_gen4_scale_hw_calib_therm( + const struct u32_fract *prescale, + const struct adc5_data *data, + u16 adc_code, int *result_mdec) +{ + s64 resistance = adc_code; + int ret, result; + + if (adc_code >= RATIO_MAX_ADC5_GEN4) + return -EINVAL; + + /* (ADC code * R_PULLUP (100Kohm)) / (full_scale_code - ADC code)*/ + resistance *= R_PU_100K; + resistance = div64_s64(resistance, RATIO_MAX_ADC5_GEN4 - adc_code); + + ret = qcom_vadc_map_voltage_temp(adcmap7_100k, + ARRAY_SIZE(adcmap7_100k), + resistance, &result); + if (ret) + return ret; + + *result_mdec = result; + + return 0; +} + static int qcom_vadc_scale_hw_calib_volt( const struct u32_fract *prescale, const struct adc5_data *data, diff --git a/include/linux/iio/adc/qcom-adc5-gen3-common.h b/include/linux/iio/adc/qcom-adc5-gen3-common.h index b3e2c2f50e8f5..6b15f8c97529e 100644 --- a/include/linux/iio/adc/qcom-adc5-gen3-common.h +++ b/include/linux/iio/adc/qcom-adc5-gen3-common.h @@ -40,7 +40,8 @@ #define ADC5_GEN3_CONV_ERR_CLR_REQ BIT(0) #define ADC5_GEN3_SID 0x4f -#define ADC5_GEN3_SID_MASK GENMASK(3, 0) +#define ADC5_GEN4_SID_MASK GENMASK(4, 0) +#define ADC5_GEN4_BUS_INDEX_MASK GENMASK(6, 5) #define ADC5_GEN3_PERPH_CH 0x50 #define ADC5_GEN3_CHAN_CONV_REQ BIT(7) @@ -51,6 +52,7 @@ #define ADC5_GEN3_DIG_PARAM 0x52 #define ADC5_GEN3_DIG_PARAM_CAL_SEL_MASK GENMASK(5, 4) #define ADC5_GEN3_DIG_PARAM_DEC_RATIO_SEL_MASK GENMASK(3, 2) +#define ADC5_GEN4_DECIMATION_DEFAULT 1 #define ADC5_GEN3_FAST_AVG 0x53 #define ADC5_GEN3_FAST_AVG_CTL_EN BIT(7) @@ -75,10 +77,13 @@ #define ADC5_GEN3_CONV_REQ 0xe5 #define ADC5_GEN3_CONV_REQ_REQ BIT(0) -#define ADC5_GEN3_VIRTUAL_SID_MASK GENMASK(15, 8) -#define ADC5_GEN3_CHANNEL_MASK GENMASK(7, 0) -#define ADC5_GEN3_V_CHAN(x) \ - (FIELD_PREP(ADC5_GEN3_VIRTUAL_SID_MASK, (x).sid) | (x).channel) +#define ADC5_GEN4_V_CHAN_BUS_INDEX_MASK GENMASK(14, 13) +#define ADC5_GEN4_V_CHAN_SID_MASK GENMASK(12, 8) +#define ADC5_GEN4_V_CHAN_CHANNEL_MASK GENMASK(7, 0) +#define ADC5_GEN4_V_CHAN(x) \ + (FIELD_PREP(ADC5_GEN4_V_CHAN_BUS_INDEX_MASK, (x).bus_index) | \ + FIELD_PREP(ADC5_GEN4_V_CHAN_SID_MASK, (x).sid) | \ + FIELD_PREP(ADC5_GEN4_V_CHAN_CHANNEL_MASK, (x).channel)) /* ADC channels for PMIC5 Gen3 */ #define ADC5_GEN3_REF_GND 0x00 @@ -102,6 +107,27 @@ #define ADC5_MAX_CHANNEL 0xc0 +/* ADC channels for PMIC5 Gen4 */ +#define ADC5_GEN4_OFFSET_REF 0x00 +#define ADC5_GEN4_1P25VREF 0x01 +#define ADC5_GEN4_DIE_TEMP 0x03 +#define ADC5_GEN4_USB_SNS_DIV20 0x11 +#define ADC5_GEN4_VIN_DIV20_MUX 0x12 +#define ADC5_GEN4_VPH_PWR 0x8e +#define ADC5_GEN4_VBAT_SNS_QBG 0x8f +/* 100k pull-up channels */ +#define ADC5_GEN4_AMUX1_THM_100K_PU 0x44 +#define ADC5_GEN4_AMUX2_THM_100K_PU 0x45 +#define ADC5_GEN4_AMUX3_THM_100K_PU 0x46 +#define ADC5_GEN4_AMUX4_THM_100K_PU 0x47 +#define ADC5_GEN4_AMUX5_THM_100K_PU 0x48 +#define ADC5_GEN4_AMUX6_THM_100K_PU 0x49 +#define ADC5_GEN4_AMUX1_GPIO_100K_PU 0x4a +#define ADC5_GEN4_AMUX2_GPIO_100K_PU 0x4b +#define ADC5_GEN4_AMUX3_GPIO_100K_PU 0x4c +#define ADC5_GEN4_AMUX4_GPIO_100K_PU 0x4d +#define ADC5_GEN4_AMUX5_GPIO_100K_PU 0x5e + enum adc5_cal_method { ADC5_NO_CAL = 0, ADC5_RATIOMETRIC_CAL, @@ -117,6 +143,11 @@ enum adc5_time_select { MEAS_INT_NONE, }; +enum adc_generation { + ADC5_GEN3 = 0, + ADC5_GEN4, +}; + /** * struct adc5_sdam_data - data per SDAM allocated for adc usage * @base_addr: base address for the ADC SDAM peripheral. @@ -166,6 +197,9 @@ struct adc5_channel_common_prop { unsigned int hw_settle_time_us; unsigned int avg_samples; enum vadc_scale_fn_type scale_fn_type; + enum adc_generation generation; + unsigned int bus_index; + const struct adc5_data *data; }; /** diff --git a/include/linux/iio/adc/qcom-vadc-common.h b/include/linux/iio/adc/qcom-vadc-common.h index 3bf4c49726a73..4be6820838434 100644 --- a/include/linux/iio/adc/qcom-vadc-common.h +++ b/include/linux/iio/adc/qcom-vadc-common.h @@ -54,6 +54,7 @@ #define R_PU_100K 100000 #define RATIO_MAX_ADC7 BIT(14) +#define RATIO_MAX_ADC5_GEN4 0xffff /* * VADC_CALIB_ABSOLUTE: uses the 625mV and 1.25V as reference channels. @@ -105,6 +106,8 @@ struct vadc_linear_graph { * charger temperature. * @SCALE_HW_CALIB_PM5_SMB_TEMP: Returns result in millidegrees for PMIC5 * SMB1390 temperature. + * @SCALE_HW_CALIB_THERM_100K_PU_GEN4: Returns temperature in millidegC using + * lookup table for PMIC5 Gen4 ADC. The hardware applies offset/slope to adc code. */ enum vadc_scale_fn_type { SCALE_DEFAULT = 0, @@ -120,6 +123,7 @@ enum vadc_scale_fn_type { SCALE_HW_CALIB_PMIC_THERM_PM7, SCALE_HW_CALIB_PM5_CHG_TEMP, SCALE_HW_CALIB_PM5_SMB_TEMP, + SCALE_HW_CALIB_THERM_100K_PU_GEN4, /* private: */ SCALE_HW_CALIB_INVALID, }; From 7b43864e77bdc896023f137250a400dc22331837 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Fri, 31 Jul 2026 23:36:16 +0530 Subject: [PATCH 0331/1133] FROMLIST: thermal: qcom: qcom-spmi-adc-tm5-gen3: Add support for QCOM PMIC5 Gen4 ADC PMIC5 Gen4 ADC is similar to PMIC5 Gen3 ADC, with several changes made for improved performance, mostly at the hardware level. One significant software change is that ratiometric conversion resolution has been increased from 14 bits to 16 bits. Add a reverse scaling function for Gen4 ADC thermistor channels. In the latest PMIC arbiter version (v8), there can be up to 4 buses under the PMIC arbiter and 32 PMICs under each bus. In order to support communication between ADC on the master PMIC and ADCs on any of the other PMICs, a field of width 2 bits is added for bus index and the bits for SID are extended from 4 to 5 bits, in the SID register. Add support for this. Link: https://lore.kernel.org/all/20260731-pmic5_gen4_adc-v1-3-9c49b2eea6f9@oss.qualcomm.com/ Co-developed-by: Anjelique Melendez Signed-off-by: Anjelique Melendez Signed-off-by: Jishnu Prakash --- drivers/iio/adc/qcom-vadc-common.c | 11 +++++++++++ drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c | 19 ++++++++++++++----- include/linux/iio/adc/qcom-vadc-common.h | 2 ++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c index cb23d0d178c74..25bd4622c3898 100644 --- a/drivers/iio/adc/qcom-vadc-common.c +++ b/drivers/iio/adc/qcom-vadc-common.c @@ -720,6 +720,17 @@ u16 qcom_adc_tm5_gen2_temp_res_scale(int temp) } EXPORT_SYMBOL(qcom_adc_tm5_gen2_temp_res_scale); +u16 qcom_adc_tm5_gen4_temp_res_scale(int temp) +{ + s64 resistance; + + resistance = qcom_vadc_map_temp_voltage(adcmap7_100k, + ARRAY_SIZE(adcmap7_100k), temp); + + return div64_s64(resistance * RATIO_MAX_ADC5_GEN4, resistance + R_PU_100K); +} +EXPORT_SYMBOL(qcom_adc_tm5_gen4_temp_res_scale); + int qcom_adc5_hw_scale(enum vadc_scale_fn_type scaletype, unsigned int prescale_ratio, const struct adc5_data *data, diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c index 9cf552d368684..80e820b6dc4b2 100644 --- a/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c +++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c @@ -207,15 +207,23 @@ static int adc_tm5_gen3_disable_channel(struct adc_tm5_gen3_channel_props *prop) ADC5_GEN3_CONV_REQ, &val, sizeof(val)); } +typedef u16 (*temp_res_scale)(int temp); + static int adc_tm5_gen3_configure(struct adc_tm5_gen3_channel_props *prop, int low_temp, int high_temp) { struct adc_tm5_gen3_chip *adc_tm5 = prop->chip; u8 buf[ADC_TM5_GEN3_CONFIG_REGS]; + temp_res_scale tm_scal_fn; u8 conv_req; u16 adc_code; int ret; + if (prop->common_props.generation == ADC5_GEN4) + tm_scal_fn = qcom_adc_tm5_gen4_temp_res_scale; + else + tm_scal_fn = qcom_adc_tm5_gen2_temp_res_scale; + ret = adc5_gen3_poll_wait_hs(adc_tm5->dev_data, prop->sdam_index); if (ret < 0) return ret; @@ -225,8 +233,9 @@ static int adc_tm5_gen3_configure(struct adc_tm5_gen3_channel_props *prop, if (ret < 0) return ret; - /* Write SID */ - buf[0] = FIELD_PREP(ADC5_GEN3_SID_MASK, prop->common_props.sid); + /* Write SID and bus_id*/ + buf[0] = FIELD_PREP(ADC5_GEN4_BUS_INDEX_MASK, prop->common_props.bus_index) | + FIELD_PREP(ADC5_GEN4_SID_MASK, prop->common_props.sid); /* Select TM channel and indicate there is an actual conversion request */ buf[1] = ADC5_GEN3_CHAN_CONV_REQ | prop->tm_chan_index; @@ -252,7 +261,7 @@ static int adc_tm5_gen3_configure(struct adc_tm5_gen3_channel_props *prop, /* High temperature corresponds to low voltage threshold */ prop->low_thr_en = (high_temp != INT_MAX); if (prop->low_thr_en) { - adc_code = qcom_adc_tm5_gen2_temp_res_scale(high_temp); + adc_code = tm_scal_fn(high_temp); put_unaligned_le16(adc_code, &buf[8]); buf[7] |= ADC5_GEN3_LOW_THR_INT_EN; } @@ -260,7 +269,7 @@ static int adc_tm5_gen3_configure(struct adc_tm5_gen3_channel_props *prop, /* Low temperature corresponds to high voltage threshold */ prop->high_thr_en = (low_temp != -INT_MAX); if (prop->high_thr_en) { - adc_code = qcom_adc_tm5_gen2_temp_res_scale(low_temp); + adc_code = tm_scal_fn(low_temp); put_unaligned_le16(adc_code, &buf[10]); buf[7] |= ADC5_GEN3_HIGH_THR_INT_EN; } @@ -306,7 +315,7 @@ static int adc_tm5_register_tzd(struct adc_tm5_gen3_chip *adc_tm5) int ret; for (int i = 0; i < adc_tm5->nchannels; i++) { - channel = ADC5_GEN3_V_CHAN(adc_tm5->chan_props[i].common_props); + channel = ADC5_GEN4_V_CHAN(adc_tm5->chan_props[i].common_props); tzd = devm_thermal_of_zone_register(adc_tm5->dev, channel, &adc_tm5->chan_props[i], &adc_tm_ops); diff --git a/include/linux/iio/adc/qcom-vadc-common.h b/include/linux/iio/adc/qcom-vadc-common.h index 4be6820838434..55efad27ed73e 100644 --- a/include/linux/iio/adc/qcom-vadc-common.h +++ b/include/linux/iio/adc/qcom-vadc-common.h @@ -159,6 +159,8 @@ u16 qcom_adc_tm5_temp_volt_scale(unsigned int prescale_ratio, u16 qcom_adc_tm5_gen2_temp_res_scale(int temp); +u16 qcom_adc_tm5_gen4_temp_res_scale(int temp); + int qcom_adc5_prescaling_from_dt(u32 num, u32 den); int qcom_adc5_hw_settle_time_from_dt(u32 value, const unsigned int *hw_settle); From 16f93ce95fc4b7868ca8b893780c9780321055a7 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Fri, 31 Jul 2026 23:36:17 +0530 Subject: [PATCH 0332/1133] FROMLIST: arm64: dts: qcom: Add header file for ADC5 Gen4 channel macros Add macro definitions for virtual channels (combination of ADC channel number, PMIC SID number and PMIC bus ID number), to be used in devicetree by clients of ADC5 GEN4 device and in the "reg" property of ADC channels. Link: https://lore.kernel.org/all/20260731-pmic5_gen4_adc-v1-4-9c49b2eea6f9@oss.qualcomm.com/ Signed-off-by: Jishnu Prakash --- arch/arm64/boot/dts/qcom/qcom-adc5-gen4.h | 96 +++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcom-adc5-gen4.h diff --git a/arch/arm64/boot/dts/qcom/qcom-adc5-gen4.h b/arch/arm64/boot/dts/qcom/qcom-adc5-gen4.h new file mode 100644 index 0000000000000..cf94e3185e211 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcom-adc5-gen4.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __DTS_ARM64_QCOM_ADC5_GEN4_H__ +#define __DTS_ARM64_QCOM_ADC5_GEN4_H__ + +/* ADC channels for PMIC5 Gen4 */ + +#define ADC5_GEN4_VIRT_CHAN(bus_id, sid, chan) ((bus_id) << 13 | (sid) << 8 | (chan)) + +#define ADC5_GEN4_OFFSET_REF(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x00) +#define ADC5_GEN4_1P25VREF(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x01) +#define ADC5_GEN4_VREF_VADC(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x02) +#define ADC5_GEN4_DIE_TEMP(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x03) + +#define ADC5_GEN4_AMUX1_THM(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x04) +#define ADC5_GEN4_AMUX2_THM(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x05) +#define ADC5_GEN4_AMUX3_THM(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x06) +#define ADC5_GEN4_AMUX4_THM(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x07) +#define ADC5_GEN4_AMUX5_THM(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x08) +#define ADC5_GEN4_AMUX6_THM(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x09) +#define ADC5_GEN4_AMUX1_GPIO(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x0a) +#define ADC5_GEN4_AMUX2_GPIO(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x0b) +#define ADC5_GEN4_AMUX3_GPIO(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x0c) +#define ADC5_GEN4_AMUX4_GPIO(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x0d) +#define ADC5_GEN4_AMUX5_GPIO(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x1e) + +#define ADC5_GEN4_CHG_TEMP(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x10) +#define ADC5_GEN4_USB_SNS_DIV20(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x11) +#define ADC5_GEN4_VIN_DIV20_MUX(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x12) +#define ADC5_GEN4_USBC_MUX(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x13) +#define ADC5_GEN4_VREF_BAT_THERM(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x15) +#define ADC5_GEN4_IIN(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x17) + +#define ADC5_GEN4_VREF_BAT2_THERM(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x1a) +#define ADC5_GEN4_ATEST1(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x1b) +#define ADC5_GEN4_ATEST2(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x1c) +#define ADC5_GEN4_VBAT_2S_MID_CHGR(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x1d) + +/* 10k pull-up1 */ +#define ADC5_GEN4_AMUX1_THM_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x24) +#define ADC5_GEN4_AMUX2_THM_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x25) +#define ADC5_GEN4_AMUX3_THM_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x26) +#define ADC5_GEN4_AMUX4_THM_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x27) +#define ADC5_GEN4_AMUX5_THM_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x28) +#define ADC5_GEN4_AMUX6_THM_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x29) +#define ADC5_GEN4_AMUX1_GPIO_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x2a) +#define ADC5_GEN4_AMUX2_GPIO_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x2b) +#define ADC5_GEN4_AMUX3_GPIO_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x2c) +#define ADC5_GEN4_AMUX4_GPIO_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x2d) +#define ADC5_GEN4_USBC_MUX_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x33) +#define ADC5_GEN4_AMUX5_GPIO_10K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x3e) + +/* 100k pull-up2 */ +#define ADC5_GEN4_AMUX1_THM_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x44) +#define ADC5_GEN4_AMUX2_THM_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x45) +#define ADC5_GEN4_AMUX3_THM_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x46) +#define ADC5_GEN4_AMUX4_THM_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x47) +#define ADC5_GEN4_AMUX5_THM_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x48) +#define ADC5_GEN4_AMUX6_THM_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x49) +#define ADC5_GEN4_AMUX1_GPIO_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x4a) +#define ADC5_GEN4_AMUX2_GPIO_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x4b) +#define ADC5_GEN4_AMUX3_GPIO_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x4c) +#define ADC5_GEN4_AMUX4_GPIO_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x4d) +#define ADC5_GEN4_USBC_MUX_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x53) +#define ADC5_GEN4_AMUX5_GPIO_100K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x5e) + +/* 400k pull-up3 */ +#define ADC5_GEN4_AMUX1_THM_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x64) +#define ADC5_GEN4_AMUX2_THM_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x65) +#define ADC5_GEN4_AMUX3_THM_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x66) +#define ADC5_GEN4_AMUX4_THM_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x67) +#define ADC5_GEN4_AMUX5_THM_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x68) +#define ADC5_GEN4_AMUX6_THM_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x69) +#define ADC5_GEN4_AMUX1_GPIO_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x6a) +#define ADC5_GEN4_AMUX2_GPIO_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x6b) +#define ADC5_GEN4_AMUX3_GPIO_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x6c) +#define ADC5_GEN4_AMUX4_GPIO_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x6d) +#define ADC5_GEN4_USBC_MUX_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x73) +#define ADC5_GEN4_AMUX5_GPIO_400K_PU(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x7e) + +/* 1/3 Divider */ +#define ADC5_GEN4_AMUX1_GPIO_DIV3(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x8a) +#define ADC5_GEN4_VPH_PWR(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x8e) +#define ADC5_GEN4_VBAT_SNS_QBG(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x8f) +#define ADC5_GEN4_VBAT_SNS_CHG(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x94) +#define ADC5_GEN4_VBAT_2S_MID_QBG(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x96) +#define ADC5_GEN4_VPH2_PWR(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x99) +#define ADC5_GEN4_VBAT_2S_MID_CHGR_DIV3(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x9d) +#define ADC5_GEN4_VBAT_2S_MID2(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0x9f) + +#define ADC5_GEN4_ICHG_FB(bus_id, sid) ADC5_GEN4_VIRT_CHAN(bus_id, sid, 0xa1) + +#endif /* __DTS_ARM64_QCOM_ADC5_GEN4_H__ */ From 9232e2fe5b100461e79b0aa452b0fe8c0c2c4e66 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Fri, 31 Jul 2026 23:36:18 +0530 Subject: [PATCH 0333/1133] FROMLIST: arm64: dts: qcom: pmk8850: Add ADC5 Gen4 peripheral PMK8850 has an ADC5 Gen4 peripheral that acts as the master ADC for the platform, communicating with ADC peripherals on other PMICs on the system. Add the ADC peripheral node with PMK8850 die_temp and xo_therm channel nodes under it initially. Link: https://lore.kernel.org/all/20260731-pmic5_gen4_adc-v1-5-9c49b2eea6f9@oss.qualcomm.com/ Signed-off-by: Jishnu Prakash --- arch/arm64/boot/dts/qcom/pmk8850.dtsi | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pmk8850.dtsi b/arch/arm64/boot/dts/qcom/pmk8850.dtsi index c7ba72fd48bc8..44d1d1957f8a9 100644 --- a/arch/arm64/boot/dts/qcom/pmk8850.dtsi +++ b/arch/arm64/boot/dts/qcom/pmk8850.dtsi @@ -7,6 +7,7 @@ #include #include #include +#include "qcom-adc5-gen4.h" &spmi_bus0 { pmic@0 { @@ -45,6 +46,30 @@ #interrupt-cells = <2>; }; + pmk8850_vadc: adc@9000 { + compatible = "qcom,spmi-adc5-gen4"; + reg = <0x9000>, <0x9100>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x0 0x90 0x1 IRQ_TYPE_EDGE_RISING>, + <0x0 0x91 0x1 IRQ_TYPE_EDGE_RISING>; + #thermal-sensor-cells = <1>; + #io-channel-cells = <1>; + + channel@3 { + reg = ; + label = "pmk8850_die_temp"; + }; + + channel@44 { + reg = ; + label = "pmk8850_therm_0"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + }; + pmk8850_rtc: rtc@6100 { compatible = "qcom,pmk8350-rtc"; reg = <0x6100>, From ca24a11cd96958e206bfcd07f1c17ba47b93cb12 Mon Sep 17 00:00:00 2001 From: Kamal Wadhwa Date: Fri, 7 Aug 2026 02:26:30 +0530 Subject: [PATCH 0334/1133] FROMLIST: dt-bindings: soc: qcom: qcom,pmic-glink: Document RTC client properties The pmic_glink driver can now register an RTC auxiliary device on glymur, whose PMIC exposes an RTC over GLINK (see rtc-glink driver). Document the allow-set-time flag it consumes from the parent pmic-glink node. Link: https://lore.kernel.org/all/20260807-rtc-glink-cleanup-v1-1-7801e4d69c4f@oss.qualcomm.com/ Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Raj Aryan Signed-off-by: Kamal Wadhwa --- .../devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml index 16ad4f5698fc3..38db1ff473c01 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml @@ -79,6 +79,11 @@ properties: - const: charge_limit_end - const: charge_limit_delta + allow-set-time: + $ref: /schemas/types.yaml#/definitions/flag + description: + Indicates that the setting of RTC time is allowed by the host CPU. + patternProperties: '^connector@\d$': $ref: /schemas/connector/usb-connector.yaml# From b90d01991e562432f8e1daedfc765fd039d0f4f9 Mon Sep 17 00:00:00 2001 From: Kamal Wadhwa Date: Fri, 7 Aug 2026 02:26:31 +0530 Subject: [PATCH 0335/1133] FROMLIST: rtc: qcom: rtc-glink: Add PMIC GLINK RTC driver and extend pmic_glink Add a new RTC driver that communicates with the PMIC firmware over the GLINK transport layer. The driver supports reading time and alarm functionality via GET_PROPERTY and SET_PROPERTY opcodes. Time is read via GET_PROPERTY (opcode 0x62) using QCOM_RTC_GLINK_TIME property (0x00). Alarm set and enable are handled via SET_PROPERTY (opcode 0x63) using QCOM_RTC_GLINK_ALARM and QCOM_RTC_GLINK_ALARM_ENABLE properties respectively. GET_PROPERTY and SET_PROPERTY responses share the same firmware message layout, with the firmware echoing back the property value. Both opcodes are handled by a common callback path accordingly. Also extend pmic_glink to register the RTC as a PMIC GLINK client and add PMIC GLINK RTC client support for glymur. Link: https://lore.kernel.org/all/20260807-rtc-glink-cleanup-v1-2-7801e4d69c4f@oss.qualcomm.com/ Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Raj Aryan Signed-off-by: Kamal Wadhwa --- MAINTAINERS | 7 + drivers/rtc/Kconfig | 10 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-qcom-glink.c | 690 ++++++++++++++++++++++++++++ drivers/soc/qcom/pmic_glink.c | 22 +- include/linux/soc/qcom/pmic_glink.h | 1 + 6 files changed, 730 insertions(+), 1 deletion(-) create mode 100644 drivers/rtc/rtc-qcom-glink.c diff --git a/MAINTAINERS b/MAINTAINERS index 93abbb315065d..fb0e732de622f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23115,6 +23115,13 @@ S: Maintained F: Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml F: drivers/power/supply/qcom_smbx.c +QUALCOMM PMIC GLINK RTC DRIVER +M: Kamal Wadhwa +L: linux-rtc@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: drivers/rtc/rtc-qcom-glink.c + QUALCOMM PPE DRIVER M: Luo Jie L: netdev@vger.kernel.org diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 73ec9230edfd0..41ace94550ed2 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1863,6 +1863,16 @@ config RTC_DRV_PM8XXX To compile this driver as a module, choose M here: the module will be called rtc-pm8xxx. +config RTC_DRV_QCOM_GLINK + tristate "Qualcomm PMIC GLINK RTC" + depends on QCOM_PMIC_GLINK + help + Say Y here to enable support for the RTC exposed by the PMIC + over the GLINK transport on Qualcomm platforms. + + This driver can also be built as a module. If so, the module + will be called rtc-qcom-glink. + config RTC_DRV_TEGRA tristate "NVIDIA Tegra Internal RTC driver" depends on ARCH_TEGRA || COMPILE_TEST diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 46f1a0fc24165..a01803a69ad7d 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o obj-$(CONFIG_RTC_DRV_FSL_FTM_ALARM) += rtc-fsl-ftm-alarm.o obj-$(CONFIG_RTC_DRV_FTRTC010) += rtc-ftrtc010.o obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o +obj-$(CONFIG_RTC_DRV_QCOM_GLINK) += rtc-qcom-glink.o obj-$(CONFIG_RTC_DRV_GOLDFISH) += rtc-goldfish.o obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o diff --git a/drivers/rtc/rtc-qcom-glink.c b/drivers/rtc/rtc-qcom-glink.c new file mode 100644 index 0000000000000..611f06a3cc5ca --- /dev/null +++ b/drivers/rtc/rtc-qcom-glink.c @@ -0,0 +1,690 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RTC_GLINK_SET_PROPERTY 0x63 +#define RTC_GLINK_GET_PROPERTY 0x65 +#define RTC_GLINK_GET_RTC_TICKS 0x67 +#define RTC_GLINK_GET_REAL_TIME 0x68 +#define RTC_GLINK_SET_REAL_TIME 0x69 +#define RTC_GLINK_ALARM_EXPIRED 0x6A + +enum qcom_rtc_glink_properties { + QCOM_RTC_GLINK_TIME = 0, + QCOM_RTC_GLINK_ALARM_TIME, + QCOM_RTC_GLINK_ALARM_ENABLE, +}; + +struct qcom_rtc_glink_msg { + struct pmic_glink_hdr hdr; + __le32 property; + __le32 value; +}; + +struct qcom_rtc_glink_generic_req { + struct pmic_glink_hdr hdr; +}; + +struct qcom_rtc_glink_status_resp { + struct pmic_glink_hdr hdr; + __le32 return_status; +}; + +struct qcom_rtc_glink_ticks_resp { + struct pmic_glink_hdr hdr; + __le32 return_status; + __le32 rtc_ticks; +}; + +struct qcom_rtc_glink_real_time_resp { + struct pmic_glink_hdr hdr; + __le32 return_status; + __le32 real_time_data[4]; +}; + +struct qcom_rtc_glink_set_real_time_req { + struct pmic_glink_hdr hdr; + __le32 real_time_data[4]; +}; + +struct qcom_rtc_glink { + struct device *dev; + struct pmic_glink_client *client; + struct rtc_device *rtc; + + /* Serializes requests: only one may be in flight at a time */ + struct mutex lock; + struct completion ack; + struct work_struct alarm_work; + + /* Protects service_up and request_pending across callback contexts */ + spinlock_t state_lock; + bool service_up; + bool request_pending; + + int error; + u32 resp_value; + u32 offset; + struct rtc_time resp_tm; + bool resp_valid; + bool allow_set_time; +}; + +static int qcom_rtc_glink_request(struct qcom_rtc_glink *rtc_glink, + void *data, size_t len) +{ + unsigned long flags; + unsigned long left; + int ret; + + /* + * Reinit the completion before request_pending becomes visible to + * qcom_rtc_glink_pdr_tify(), so a concurrent SSR down-transition + * can't complete() a stale completion that gets wiped out by + * reinit_completion() right after. + */ + reinit_completion(&rtc_glink->ack); + rtc_glink->error = 0; + rtc_glink->resp_valid = false; + + spin_lock_irqsave(&rtc_glink->state_lock, flags); + if (!rtc_glink->service_up) { + spin_unlock_irqrestore(&rtc_glink->state_lock, flags); + return -ECONNRESET; + } + rtc_glink->request_pending = true; + spin_unlock_irqrestore(&rtc_glink->state_lock, flags); + + ret = pmic_glink_send(rtc_glink->client, data, len); + if (ret < 0) { + spin_lock_irqsave(&rtc_glink->state_lock, flags); + rtc_glink->request_pending = false; + spin_unlock_irqrestore(&rtc_glink->state_lock, flags); + return ret; + } + + left = wait_for_completion_timeout(&rtc_glink->ack, HZ); + spin_lock_irqsave(&rtc_glink->state_lock, flags); + rtc_glink->request_pending = false; + spin_unlock_irqrestore(&rtc_glink->state_lock, flags); + if (!left) + return -ETIMEDOUT; + + return rtc_glink->error; +} + +static int qcom_rtc_glink_set_property(struct qcom_rtc_glink *rtc_glink, + u32 property, u32 value) +{ + struct qcom_rtc_glink_msg msg = { + .hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_RTC), + .hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP), + .hdr.opcode = cpu_to_le32(RTC_GLINK_SET_PROPERTY), + .property = cpu_to_le32(property), + .value = cpu_to_le32(value), + }; + int ret; + + dev_dbg(rtc_glink->dev, + "TX opcode=0x%x property=%u value=%u\n", + RTC_GLINK_SET_PROPERTY, property, value); + mutex_lock(&rtc_glink->lock); + ret = qcom_rtc_glink_request(rtc_glink, &msg, sizeof(msg)); + mutex_unlock(&rtc_glink->lock); + return ret; +} + +static int qcom_rtc_glink_get_property(struct qcom_rtc_glink *rtc_glink, + u32 property, u32 *value) +{ + struct qcom_rtc_glink_msg msg = { + .hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_RTC), + .hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP), + .hdr.opcode = cpu_to_le32(RTC_GLINK_GET_PROPERTY), + .property = cpu_to_le32(property), + }; + int ret; + + dev_dbg(rtc_glink->dev, + "TX opcode=0x%x property=%u\n", + RTC_GLINK_GET_PROPERTY, property); + mutex_lock(&rtc_glink->lock); + ret = qcom_rtc_glink_request(rtc_glink, &msg, sizeof(msg)); + if (!ret) { + if (!rtc_glink->resp_valid) + ret = -EIO; + else + *value = rtc_glink->resp_value; + } + mutex_unlock(&rtc_glink->lock); + return ret; +} + +static int qcom_rtc_glink_get_ticks(struct qcom_rtc_glink *rtc_glink, + u32 *ticks) +{ + struct qcom_rtc_glink_generic_req msg = { + .hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_RTC), + .hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP), + .hdr.opcode = cpu_to_le32(RTC_GLINK_GET_RTC_TICKS), + }; + int ret; + + dev_dbg(rtc_glink->dev, "TX opcode=0x%x\n", RTC_GLINK_GET_RTC_TICKS); + mutex_lock(&rtc_glink->lock); + ret = qcom_rtc_glink_request(rtc_glink, &msg, sizeof(msg)); + if (!ret) { + if (!rtc_glink->resp_valid) + ret = -EIO; + else + *ticks = rtc_glink->resp_value; + } + mutex_unlock(&rtc_glink->lock); + return ret; +} + +static int qcom_rtc_glink_get_real_time(struct qcom_rtc_glink *rtc_glink, + struct rtc_time *tm) +{ + struct qcom_rtc_glink_generic_req msg = { + .hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_RTC), + .hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP), + .hdr.opcode = cpu_to_le32(RTC_GLINK_GET_REAL_TIME), + }; + int ret; + + dev_dbg(rtc_glink->dev, "TX opcode=0x%x\n", RTC_GLINK_GET_REAL_TIME); + mutex_lock(&rtc_glink->lock); + ret = qcom_rtc_glink_request(rtc_glink, &msg, sizeof(msg)); + if (!ret) { + if (!rtc_glink->resp_valid) + ret = -EIO; + else + *tm = rtc_glink->resp_tm; + } + mutex_unlock(&rtc_glink->lock); + return ret; +} + +static int qcom_rtc_glink_set_real_time(struct qcom_rtc_glink *rtc_glink, + struct rtc_time *tm) +{ + struct qcom_rtc_glink_set_real_time_req msg = {}; + u32 w0, w1; + int ret; + + w0 = ((tm->tm_year + 1900) & 0xffff) | + (((tm->tm_mon + 1) & 0xff) << 16) | + ((tm->tm_mday & 0xff) << 24); + w1 = (tm->tm_hour & 0xff) | + ((tm->tm_min & 0xff) << 8) | + ((tm->tm_sec & 0xff) << 16) | + (1U << 24); + msg.hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_RTC); + msg.hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP); + msg.hdr.opcode = cpu_to_le32(RTC_GLINK_SET_REAL_TIME); + msg.real_time_data[0] = cpu_to_le32(w0); + msg.real_time_data[1] = cpu_to_le32(w1); + msg.real_time_data[2] = 0; + msg.real_time_data[3] = 0; + dev_dbg(rtc_glink->dev, + "TX opcode=0x%x data=%08x %08x\n", + RTC_GLINK_SET_REAL_TIME, w0, w1); + mutex_lock(&rtc_glink->lock); + ret = qcom_rtc_glink_request(rtc_glink, &msg, sizeof(msg)); + mutex_unlock(&rtc_glink->lock); + return ret; +} + +static int qcom_rtc_glink_get_time(struct qcom_rtc_glink *rtc_glink, + struct rtc_time *time) +{ + u32 ticks; + int ret; + + ret = qcom_rtc_glink_get_real_time(rtc_glink, time); + if (!ret) + return 0; + dev_warn(rtc_glink->dev, "0x68 failed (%d), falling back\n", ret); + + ret = qcom_rtc_glink_get_ticks(rtc_glink, &ticks); + if (!ret) { + rtc_time64_to_tm((time64_t)ticks + rtc_glink->offset, time); + return 0; + } + + ret = qcom_rtc_glink_get_property(rtc_glink, QCOM_RTC_GLINK_TIME, + &ticks); + if (!ret && ticks != U32_MAX) { + rtc_time64_to_tm((time64_t)ticks + rtc_glink->offset, time); + return 0; + } + + dev_err(rtc_glink->dev, "all time sources failed\n"); + return -EIO; +} + +static int qcom_rtc_glink_set_time(struct qcom_rtc_glink *rtc_glink, + struct rtc_time *time) +{ + time64_t t = rtc_tm_to_time64(time); + u32 ticks; + int ret; + + if (!rtc_glink->allow_set_time) + return -EOPNOTSUPP; + + ret = qcom_rtc_glink_set_real_time(rtc_glink, time); + if (ret) + dev_warn(rtc_glink->dev, "0x69 failed (%d)\n", ret); + + ret = qcom_rtc_glink_set_property(rtc_glink, QCOM_RTC_GLINK_TIME, (u32)t); + if (ret) + return ret; + + ret = qcom_rtc_glink_get_ticks(rtc_glink, &ticks); + if (!ret && ticks != U32_MAX) { + rtc_glink->offset = (u32)t - ticks; + } else { + dev_warn(rtc_glink->dev, "no tick source for offset\n"); + return -EIO; + } + + return 0; +} + +static int qcom_rtc_glink_set_alarm_en(struct qcom_rtc_glink *rtc_glink, + int enabled) +{ + return qcom_rtc_glink_set_property(rtc_glink, + QCOM_RTC_GLINK_ALARM_ENABLE, + enabled); +} + +static int qcom_rtc_glink_set_alarm(struct qcom_rtc_glink *rtc_glink, + struct rtc_wkalrm *alarm) +{ + time64_t alarm_t = rtc_tm_to_time64(&alarm->time); + struct rtc_time now_tm; + time64_t now_real, secs_until_alarm; + u32 fw_current, fw_alarm; + int ret; + + ret = qcom_rtc_glink_get_time(rtc_glink, &now_tm); + if (ret) + return ret; + now_real = rtc_tm_to_time64(&now_tm); + secs_until_alarm = alarm_t - now_real; + dev_dbg(rtc_glink->dev, + "set_alarm: now_real=%lld alarm_t=%lld delta=%lld\n", + now_real, alarm_t, secs_until_alarm); + if (secs_until_alarm < 0) + return -EINVAL; + if (secs_until_alarm > U32_MAX) + return -ERANGE; + + ret = qcom_rtc_glink_get_property(rtc_glink, QCOM_RTC_GLINK_TIME, + &fw_current); + if (ret) + return ret; + if (fw_current == U32_MAX) + fw_current = 0; + fw_alarm = fw_current + (u32)secs_until_alarm; + dev_dbg(rtc_glink->dev, + "set_alarm: fw_current=%u fw_alarm=%u\n", + fw_current, fw_alarm); + + ret = qcom_rtc_glink_set_alarm_en(rtc_glink, 0); + if (ret) + return ret; + + ret = qcom_rtc_glink_set_property(rtc_glink, + QCOM_RTC_GLINK_ALARM_TIME, fw_alarm); + if (ret) + return ret; + + return qcom_rtc_glink_set_alarm_en(rtc_glink, alarm->enabled); +} + +static int qcom_rtc_glink_get_alarm(struct qcom_rtc_glink *rtc_glink, + struct rtc_wkalrm *alarm) +{ + u32 fw_alarm_time, fw_current, alarm_en; + struct rtc_time now_tm; + time64_t now_real, secs_until_alarm, alarm_real; + int ret; + + ret = qcom_rtc_glink_get_property(rtc_glink, + QCOM_RTC_GLINK_ALARM_TIME, + &fw_alarm_time); + if (ret) + return ret; + + ret = qcom_rtc_glink_get_property(rtc_glink, QCOM_RTC_GLINK_TIME, + &fw_current); + if (ret) + return ret; + + ret = qcom_rtc_glink_get_property(rtc_glink, + QCOM_RTC_GLINK_ALARM_ENABLE, + &alarm_en); + if (ret) + return ret; + if (fw_current == U32_MAX) + fw_current = 0; + + ret = qcom_rtc_glink_get_time(rtc_glink, &now_tm); + if (ret) + return ret; + now_real = rtc_tm_to_time64(&now_tm); + secs_until_alarm = (time64_t)fw_alarm_time - (time64_t)fw_current; + alarm_real = now_real + secs_until_alarm; + dev_dbg(rtc_glink->dev, + "get_alarm: now_real=%lld fw_current=%u fw_alarm=%u delta=%lld\n", + now_real, fw_current, fw_alarm_time, secs_until_alarm); + rtc_time64_to_tm(alarm_real, &alarm->time); + alarm->enabled = !!alarm_en; + return 0; +} + +static void qcom_rtc_glink_alarm_work(struct work_struct *work) +{ + struct qcom_rtc_glink *rtc_glink = + container_of(work, struct qcom_rtc_glink, alarm_work); + int ret; + + ret = qcom_rtc_glink_set_alarm_en(rtc_glink, 0); + if (ret) + dev_err(rtc_glink->dev, + "failed to disable alarm after expiry (%d)\n", ret); + rtc_update_irq(rtc_glink->rtc, 1, RTC_IRQF | RTC_AF); +} + +static void qcom_rtc_glink_callback(const void *data, size_t len, void *priv) +{ + struct qcom_rtc_glink *rtc_glink = priv; + const struct pmic_glink_hdr *hdr = data; + unsigned long flags; + bool pending; + + if (len < sizeof(*hdr)) + return; + + dev_dbg(rtc_glink->dev, + "RX opcode=0x%x type=0x%x owner=0x%x len=%zu\n", + le32_to_cpu(hdr->opcode), le32_to_cpu(hdr->type), + le32_to_cpu(hdr->owner), len); + + if (le32_to_cpu(hdr->opcode) == RTC_GLINK_ALARM_EXPIRED) { + dev_info(rtc_glink->dev, "alarm expired\n"); + schedule_work(&rtc_glink->alarm_work); + return; + } + + /* + * Hold state_lock across the pending check and the response fields + * below: qcom_rtc_glink_pdr_notify() writes the same error/resp_* + * fields under this lock when it force-completes a request on an + * SSR down-transition, and the two must not race. Dropping the + * response here if !pending also covers requests that already + * timed out or were aborted; qcom_rtc_glink_request() will call + * reinit_completion() again before this response could be mistaken + * for a later request's. + */ + spin_lock_irqsave(&rtc_glink->state_lock, flags); + pending = rtc_glink->request_pending; + + if (!pending) { + spin_unlock_irqrestore(&rtc_glink->state_lock, flags); + dev_dbg(rtc_glink->dev, + "dropping stale response opcode=0x%x\n", + le32_to_cpu(hdr->opcode)); + return; + } + + switch (le32_to_cpu(hdr->opcode)) { + case RTC_GLINK_GET_PROPERTY: + fallthrough; + case RTC_GLINK_SET_PROPERTY: { + const struct qcom_rtc_glink_msg *msg = data; + + if (len < sizeof(struct pmic_glink_hdr) + sizeof(__le32)) { + rtc_glink->error = -EINVAL; + break; + } + rtc_glink->resp_value = le32_to_cpu(msg->property); + rtc_glink->resp_valid = true; + rtc_glink->error = 0; + dev_dbg(rtc_glink->dev, "ACK opcode=0x%x resp_value=%u\n", + le32_to_cpu(hdr->opcode), rtc_glink->resp_value); + break; + } + + case RTC_GLINK_GET_RTC_TICKS: { + const struct qcom_rtc_glink_ticks_resp *resp = data; + + if (len < sizeof(*resp)) { + rtc_glink->error = -EINVAL; + break; + } + if (le32_to_cpu(resp->return_status)) { + rtc_glink->error = -EIO; + break; + } + rtc_glink->resp_value = le32_to_cpu(resp->rtc_ticks); + rtc_glink->resp_valid = true; + rtc_glink->error = 0; + dev_dbg(rtc_glink->dev, "ACK opcode=0x%x ticks=%u\n", + RTC_GLINK_GET_RTC_TICKS, rtc_glink->resp_value); + break; + } + + case RTC_GLINK_GET_REAL_TIME: { + const struct qcom_rtc_glink_real_time_resp *resp = data; + u32 w0, w1; + + if (len < sizeof(*resp)) { + rtc_glink->error = -EINVAL; + break; + } + if (le32_to_cpu(resp->return_status)) { + rtc_glink->error = -EIO; + break; + } + w0 = le32_to_cpu(resp->real_time_data[0]); + w1 = le32_to_cpu(resp->real_time_data[1]); + rtc_glink->resp_tm.tm_year = (w0 & 0xffff) - 1900; + rtc_glink->resp_tm.tm_mon = ((w0 >> 16) & 0xff) - 1; + rtc_glink->resp_tm.tm_mday = (w0 >> 24) & 0xff; + rtc_glink->resp_tm.tm_hour = w1 & 0xff; + rtc_glink->resp_tm.tm_min = (w1 >> 8) & 0xff; + rtc_glink->resp_tm.tm_sec = (w1 >> 16) & 0xff; + rtc_glink->resp_valid = true; + rtc_glink->error = 0; + dev_dbg(rtc_glink->dev, + "ACK opcode=0x%x %04d-%02d-%02d %02d:%02d:%02d\n", + RTC_GLINK_GET_REAL_TIME, + rtc_glink->resp_tm.tm_year + 1900, + rtc_glink->resp_tm.tm_mon + 1, + rtc_glink->resp_tm.tm_mday, + rtc_glink->resp_tm.tm_hour, + rtc_glink->resp_tm.tm_min, + rtc_glink->resp_tm.tm_sec); + break; + } + + case RTC_GLINK_SET_REAL_TIME: { + const struct qcom_rtc_glink_status_resp *resp = data; + + if (len < sizeof(*resp)) { + rtc_glink->error = -EINVAL; + break; + } + rtc_glink->error = le32_to_cpu(resp->return_status) ? -EIO : 0; + dev_dbg(rtc_glink->dev, "ACK opcode=0x%x status=%u\n", + RTC_GLINK_SET_REAL_TIME, + le32_to_cpu(resp->return_status)); + break; + } + + default: + spin_unlock_irqrestore(&rtc_glink->state_lock, flags); + dev_warn(rtc_glink->dev, + "unhandled RX opcode=0x%x len=%zu\n", + le32_to_cpu(hdr->opcode), len); + return; + } + + spin_unlock_irqrestore(&rtc_glink->state_lock, flags); + complete(&rtc_glink->ack); +} + +static void qcom_rtc_glink_pdr_notify(void *priv, int state) +{ + struct qcom_rtc_glink *rtc_glink = priv; + unsigned long flags; + bool up = (state == SERVREG_SERVICE_STATE_UP); + + spin_lock_irqsave(&rtc_glink->state_lock, flags); + rtc_glink->service_up = up; + if (!up && rtc_glink->request_pending) { + rtc_glink->error = -ECONNRESET; + rtc_glink->resp_valid = false; + complete(&rtc_glink->ack); + } + spin_unlock_irqrestore(&rtc_glink->state_lock, flags); +} + +static int qcom_rtc_glink_read_time(struct device *dev, struct rtc_time *tm) +{ + return qcom_rtc_glink_get_time(dev_get_drvdata(dev), tm); +} + +static int qcom_rtc_glink_set_time_dev(struct device *dev, struct rtc_time *tm) +{ + return qcom_rtc_glink_set_time(dev_get_drvdata(dev), tm); +} + +static int qcom_rtc_glink_read_alarm(struct device *dev, + struct rtc_wkalrm *alrm) +{ + return qcom_rtc_glink_get_alarm(dev_get_drvdata(dev), alrm); +} + +static int qcom_rtc_glink_set_alarm_dev(struct device *dev, + struct rtc_wkalrm *alrm) +{ + return qcom_rtc_glink_set_alarm(dev_get_drvdata(dev), alrm); +} + +static int qcom_rtc_glink_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + return qcom_rtc_glink_set_alarm_en(dev_get_drvdata(dev), enabled); +} + +static const struct rtc_class_ops qcom_rtc_glink_rtc_ops = { + .read_time = qcom_rtc_glink_read_time, + .set_time = qcom_rtc_glink_set_time_dev, + .read_alarm = qcom_rtc_glink_read_alarm, + .set_alarm = qcom_rtc_glink_set_alarm_dev, + .alarm_irq_enable = qcom_rtc_glink_alarm_irq_enable, +}; + +static const struct of_device_id qcom_rtc_glink_of_variants[] = { + { .compatible = "qcom,glymur-pmic-glink" }, + {} +}; + +static int qcom_rtc_glink_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct device *dev = &adev->dev; + struct qcom_rtc_glink *rtc_glink; + + if (!of_match_device(qcom_rtc_glink_of_variants, dev->parent)) + return -ENXIO; + + rtc_glink = devm_kzalloc(dev, sizeof(*rtc_glink), GFP_KERNEL); + if (!rtc_glink) + return -ENOMEM; + + rtc_glink->dev = dev; + rtc_glink->allow_set_time = device_property_read_bool(dev->parent, + "allow-set-time"); + + mutex_init(&rtc_glink->lock); + spin_lock_init(&rtc_glink->state_lock); + init_completion(&rtc_glink->ack); + INIT_WORK(&rtc_glink->alarm_work, qcom_rtc_glink_alarm_work); + dev_set_drvdata(dev, rtc_glink); + + rtc_glink->client = devm_pmic_glink_client_alloc(dev, + PMIC_GLINK_OWNER_RTC, + qcom_rtc_glink_callback, + qcom_rtc_glink_pdr_notify, + rtc_glink); + if (IS_ERR(rtc_glink->client)) + return dev_err_probe(dev, PTR_ERR(rtc_glink->client), + "failed to allocate glink client\n"); + + pmic_glink_client_register(rtc_glink->client); + + device_init_wakeup(dev, true); + + rtc_glink->rtc = devm_rtc_allocate_device(dev); + if (IS_ERR(rtc_glink->rtc)) + return dev_err_probe(dev, PTR_ERR(rtc_glink->rtc), + "failed to allocate RTC device\n"); + + rtc_glink->rtc->ops = &qcom_rtc_glink_rtc_ops; + rtc_glink->rtc->range_min = 0; + rtc_glink->rtc->range_max = U32_MAX; + + return devm_rtc_register_device(rtc_glink->rtc); +} + +static void qcom_rtc_glink_remove(struct auxiliary_device *adev) +{ + struct qcom_rtc_glink *rtc_glink = dev_get_drvdata(&adev->dev); + /* + * Nothing left to arm alarm_work after this returns: the glink + * client (and its callback/pdr_notify) is torn down by devm after + * .remove() returns, and rtc_update_irq() below still targets a + * live devm-managed rtc device. + */ + cancel_work_sync(&rtc_glink->alarm_work); +} + +static const struct auxiliary_device_id qcom_rtc_glink_id_table[] = { + { .name = "pmic_glink.rtc-glink" }, + {} +}; + +MODULE_DEVICE_TABLE(auxiliary, qcom_rtc_glink_id_table); + +static struct auxiliary_driver qcom_rtc_glink_driver = { + .name = "qcom_pmic_rtc_glink", + .id_table = qcom_rtc_glink_id_table, + .probe = qcom_rtc_glink_probe, + .remove = qcom_rtc_glink_remove, +}; + +module_auxiliary_driver(qcom_rtc_glink_driver); +MODULE_DESCRIPTION("Qualcomm PMIC GLINK RTC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index 84fd0c82c0c4d..715ba8eac560b 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -21,6 +21,7 @@ enum { PMIC_GLINK_CLIENT_BATT = 0, PMIC_GLINK_CLIENT_ALTMODE, PMIC_GLINK_CLIENT_UCSI, + PMIC_GLINK_CLIENT_RTC, }; struct pmic_glink_data { @@ -40,6 +41,7 @@ struct pmic_glink { struct auxiliary_device altmode_aux; struct auxiliary_device ps_aux; struct auxiliary_device ucsi_aux; + struct auxiliary_device rtc_aux; /* serializing client_state and pdr_state updates */ struct mutex state_lock; @@ -342,6 +344,12 @@ static int pmic_glink_probe(struct platform_device *pdev) goto out_release_altmode_aux; } + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_RTC)) { + ret = pmic_glink_add_aux_device(pg, &pg->rtc_aux, "rtc-glink"); + if (ret) + goto out_release_ps_aux; + } + if (pg->data->charger_pdr_service_name && pg->data->charger_pdr_service_path) { service = pdr_add_lookup(pg->pdr, pg->data->charger_pdr_service_name, pg->data->charger_pdr_service_path); @@ -359,6 +367,9 @@ static int pmic_glink_probe(struct platform_device *pdev) return 0; out_release_aux_devices: + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_RTC)) + pmic_glink_del_aux_device(pg, &pg->rtc_aux); +out_release_ps_aux: if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) pmic_glink_del_aux_device(pg, &pg->ps_aux); out_release_altmode_aux: @@ -385,11 +396,20 @@ static void pmic_glink_remove(struct platform_device *pdev) pmic_glink_del_aux_device(pg, &pg->altmode_aux); if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) pmic_glink_del_aux_device(pg, &pg->ucsi_aux); + if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_RTC)) + pmic_glink_del_aux_device(pg, &pg->rtc_aux); guard(mutex)(&__pmic_glink_lock); __pmic_glink = NULL; } +static const struct pmic_glink_data pmic_glink_glymur_data = { + .client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | + BIT(PMIC_GLINK_CLIENT_ALTMODE) | + BIT(PMIC_GLINK_CLIENT_UCSI) | + BIT(PMIC_GLINK_CLIENT_RTC), +}; + static const struct pmic_glink_data pmic_glink_adsp_data = { .client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | BIT(PMIC_GLINK_CLIENT_ALTMODE) | @@ -405,7 +425,7 @@ static const struct pmic_glink_data pmic_glink_soccp_data = { }; static const struct of_device_id pmic_glink_of_match[] = { - { .compatible = "qcom,glymur-pmic-glink", .data = &pmic_glink_soccp_data }, + { .compatible = "qcom,glymur-pmic-glink", .data = &pmic_glink_glymur_data }, { .compatible = "qcom,kaanapali-pmic-glink", .data = &pmic_glink_soccp_data }, { .compatible = "qcom,pmic-glink", .data = &pmic_glink_adsp_data }, {} diff --git a/include/linux/soc/qcom/pmic_glink.h b/include/linux/soc/qcom/pmic_glink.h index 7cddf10277528..11031b06b810d 100644 --- a/include/linux/soc/qcom/pmic_glink.h +++ b/include/linux/soc/qcom/pmic_glink.h @@ -11,6 +11,7 @@ struct pmic_glink_client; #define PMIC_GLINK_OWNER_BATTMGR 32778 #define PMIC_GLINK_OWNER_USBC 32779 #define PMIC_GLINK_OWNER_USBC_PAN 32780 +#define PMIC_GLINK_OWNER_RTC 32784 #define PMIC_GLINK_REQ_RESP 1 #define PMIC_GLINK_NOTIFY 2 From 3dc641edd6e541209f787b3c72df5a2ab7b8b63b Mon Sep 17 00:00:00 2001 From: Kamal Wadhwa Date: Thu, 6 Aug 2026 20:36:11 +0530 Subject: [PATCH 0336/1133] FROMLIST: power: supply: qcom_battmgr: Add multi-port USB-C power supply support Extend the qcom_battmgr driver to report up to MAX_USB_PORTS (3) USB-C power supply ports on the X1E80100 & Glymur platform, which exposes more than one charger port to firmware. At firmware-enable time, query USB_NUM_PORTS over the existing BATTMGR_USB_PROPERTY_GET opcode to discover how many ports the firmware actually reports, and register the additional "qcom-battmgr-usb2"/"qcom-battmgr-usb3" power supplies only when the firmware confirms a second/third port. Each additional port is polled independently via new BATTMGR_USB2_PROPERTY_GET/SET (0xC0/0xC1) and BATTMGR_USB3_PROPERTY_GET/SET (0xC2/0xC3) opcodes so its properties are not aliased to the primary port's state. X1E80100 ports report their USB-C adapter type on USB_ADAP_TYPE rather than the SM8350/SC8280XP USB_TYPE property, so add a dedicated x1e80100_usb_prop_map[] mapping POWER_SUPPLY_PROP_USB_TYPE to USB_ADAP_TYPE, and use it for all three X1E80100 USB ports. Give the primary X1E80100 USB port its own update/get_property callback (qcom_battmgr_usb_x1e80100_update()/ qcom_battmgr_usb_x1e80100_get_property()) instead of routing it through the SC8280XP battery-status update path, mirroring the pattern already used for the usb2/usb3 ports. Also add the POWER_SUPPLY_PROP_CAPACITY entry to x1e80100_bat_props[]. Link: https://lore.kernel.org/all/20260806-b4-battmgr-multiport-usb-v2-1-1a6dd1e06cc2@oss.qualcomm.com/ Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Kamal Wadhwa --- drivers/power/supply/qcom_battmgr.c | 482 +++++++++++++++++++++++++++- 1 file changed, 470 insertions(+), 12 deletions(-) diff --git a/drivers/power/supply/qcom_battmgr.c b/drivers/power/supply/qcom_battmgr.c index 636d6f6acecc5..f65ab7a10d830 100644 --- a/drivers/power/supply/qcom_battmgr.c +++ b/drivers/power/supply/qcom_battmgr.c @@ -27,6 +27,8 @@ enum qcom_battmgr_variant { QCOM_BATTMGR_X1E80100, }; +#define MAX_USB_PORTS 3 + #define BATTMGR_BAT_STATUS 0x1 #define BATTMGR_REQUEST_NOTIFICATION 0x4 @@ -77,6 +79,10 @@ enum qcom_battmgr_variant { #define BATTMGR_USB_PROPERTY_GET 0x32 #define BATTMGR_USB_PROPERTY_SET 0x33 +#define BATTMGR_USB2_PROPERTY_GET 0xC0 +#define BATTMGR_USB2_PROPERTY_SET 0xC1 +#define BATTMGR_USB3_PROPERTY_GET 0xC2 +#define BATTMGR_USB3_PROPERTY_SET 0xC3 #define USB_ONLINE 0 #define USB_VOLT_NOW 1 #define USB_VOLT_MAX 2 @@ -87,6 +93,13 @@ enum qcom_battmgr_variant { #define USB_ADAP_TYPE 7 #define USB_MOISTURE_DET_EN 8 #define USB_MOISTURE_DET_STS 9 +#define USB_CONNECTOR_TEMP 10 +#define USB_REAL_TYPE 11 +#define USB_TYPEC_COMPLIANT 12 +#define USB_SCOPE 13 +#define USB_CONNECTOR_TYPE 14 +#define USB_F_ACTIVE 15 +#define USB_NUM_PORTS 16 #define BATTMGR_WLS_PROPERTY_GET 0x34 #define BATTMGR_WLS_PROPERTY_SET 0x35 @@ -298,6 +311,7 @@ struct qcom_battmgr_usb { unsigned int current_max; unsigned int current_limit; unsigned int usb_type; + unsigned int num_ports; }; struct qcom_battmgr_wireless { @@ -317,6 +331,8 @@ struct qcom_battmgr { struct power_supply *ac_psy; struct power_supply *bat_psy; struct power_supply *usb_psy; + struct power_supply *usb2_psy; + struct power_supply *usb3_psy; struct power_supply *wls_psy; enum qcom_battmgr_unit unit; @@ -330,8 +346,12 @@ struct qcom_battmgr { struct qcom_battmgr_status status; struct qcom_battmgr_ac ac; struct qcom_battmgr_usb usb; + struct qcom_battmgr_usb usb2; + struct qcom_battmgr_usb usb3; struct qcom_battmgr_wireless wireless; + struct power_supply_config usb_psy_cfg; + struct work_struct enable_work; /* @@ -979,6 +999,16 @@ static const u8 sm8350_usb_prop_map[] = { [POWER_SUPPLY_PROP_USB_TYPE] = USB_ADAP_TYPE, }; +static const u8 x1e80100_usb_prop_map[] = { + [POWER_SUPPLY_PROP_ONLINE] = USB_ONLINE, + [POWER_SUPPLY_PROP_VOLTAGE_NOW] = USB_VOLT_NOW, + [POWER_SUPPLY_PROP_VOLTAGE_MAX] = USB_VOLT_MAX, + [POWER_SUPPLY_PROP_CURRENT_NOW] = USB_CURR_NOW, + [POWER_SUPPLY_PROP_CURRENT_MAX] = USB_CURR_MAX, + [POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT] = USB_INPUT_CURR_LIMIT, + [POWER_SUPPLY_PROP_USB_TYPE] = USB_ADAP_TYPE, +}; + static int qcom_battmgr_usb_sm8350_update(struct qcom_battmgr *battmgr, enum power_supply_property psp) { @@ -997,6 +1027,24 @@ static int qcom_battmgr_usb_sm8350_update(struct qcom_battmgr *battmgr, return ret; } +static int qcom_battmgr_usb_x1e80100_update(struct qcom_battmgr *battmgr, + enum power_supply_property psp) +{ + unsigned int prop; + int ret; + + if (psp >= ARRAY_SIZE(x1e80100_usb_prop_map)) + return -EINVAL; + + prop = x1e80100_usb_prop_map[psp]; + + mutex_lock(&battmgr->lock); + ret = qcom_battmgr_request_property(battmgr, BATTMGR_USB_PROPERTY_GET, prop, 0); + mutex_unlock(&battmgr->lock); + + return ret; +} + static int qcom_battmgr_usb_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -1007,8 +1055,7 @@ static int qcom_battmgr_usb_get_property(struct power_supply *psy, if (!battmgr->service_up) return -EAGAIN; - if (battmgr->variant == QCOM_BATTMGR_SC8280XP || - battmgr->variant == QCOM_BATTMGR_X1E80100) + if (battmgr->variant == QCOM_BATTMGR_SC8280XP) ret = qcom_battmgr_bat_sc8280xp_update(battmgr, psp); else ret = qcom_battmgr_usb_sm8350_update(battmgr, psp); @@ -1044,8 +1091,179 @@ static int qcom_battmgr_usb_get_property(struct power_supply *psy, return 0; } +static int qcom_battmgr_usb_x1e80100_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct qcom_battmgr *battmgr = power_supply_get_drvdata(psy); + int ret; + + if (!battmgr->service_up) + return -EAGAIN; + + ret = qcom_battmgr_usb_x1e80100_update(battmgr, psp); + if (ret) + return ret; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + val->intval = battmgr->usb.online; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = battmgr->usb.voltage_now; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + val->intval = battmgr->usb.voltage_max; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = battmgr->usb.current_now; + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval = battmgr->usb.current_max; + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + val->intval = battmgr->usb.current_limit; + break; + case POWER_SUPPLY_PROP_USB_TYPE: + val->intval = battmgr->usb.usb_type; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int qcom_battmgr_usb2_x1e80100_update(struct qcom_battmgr *battmgr, + enum power_supply_property psp) +{ + unsigned int prop; + int ret; + + if (psp >= ARRAY_SIZE(x1e80100_usb_prop_map)) + return -EINVAL; + + prop = x1e80100_usb_prop_map[psp]; + + mutex_lock(&battmgr->lock); + ret = qcom_battmgr_request_property(battmgr, BATTMGR_USB2_PROPERTY_GET, prop, 0); + mutex_unlock(&battmgr->lock); + + return ret; +} + +static int qcom_battmgr_usb3_x1e80100_update(struct qcom_battmgr *battmgr, + enum power_supply_property psp) +{ + unsigned int prop; + int ret; + + if (psp >= ARRAY_SIZE(x1e80100_usb_prop_map)) + return -EINVAL; + + prop = x1e80100_usb_prop_map[psp]; + + mutex_lock(&battmgr->lock); + ret = qcom_battmgr_request_property(battmgr, BATTMGR_USB3_PROPERTY_GET, prop, 0); + mutex_unlock(&battmgr->lock); + + return ret; +} + +static int qcom_battmgr_usb2_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct qcom_battmgr *battmgr = power_supply_get_drvdata(psy); + int ret; + + if (!battmgr->service_up) + return -EAGAIN; + + ret = qcom_battmgr_usb2_x1e80100_update(battmgr, psp); + if (ret) + return ret; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + val->intval = battmgr->usb2.online; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = battmgr->usb2.voltage_now; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + val->intval = battmgr->usb2.voltage_max; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = battmgr->usb2.current_now; + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval = battmgr->usb2.current_max; + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + val->intval = battmgr->usb2.current_limit; + break; + case POWER_SUPPLY_PROP_USB_TYPE: + val->intval = battmgr->usb2.usb_type; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int qcom_battmgr_usb3_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct qcom_battmgr *battmgr = power_supply_get_drvdata(psy); + int ret; + + if (!battmgr->service_up) + return -EAGAIN; + + ret = qcom_battmgr_usb3_x1e80100_update(battmgr, psp); + if (ret) + return ret; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + val->intval = battmgr->usb3.online; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = battmgr->usb3.voltage_now; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + val->intval = battmgr->usb3.voltage_max; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = battmgr->usb3.current_now; + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval = battmgr->usb3.current_max; + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + val->intval = battmgr->usb3.current_limit; + break; + case POWER_SUPPLY_PROP_USB_TYPE: + val->intval = battmgr->usb3.usb_type; + break; + default: + return -EINVAL; + } + + return 0; +} + static const enum power_supply_property sc8280xp_usb_props[] = { POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, + POWER_SUPPLY_PROP_USB_TYPE, }; static const struct power_supply_desc sc8280xp_usb_psy_desc = { @@ -1066,6 +1284,60 @@ static const struct power_supply_desc sc8280xp_usb_psy_desc = { BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID), }; +static const struct power_supply_desc x1e80100_usb_psy_desc = { + .name = "qcom-battmgr-usb", + .type = POWER_SUPPLY_TYPE_USB, + .properties = sc8280xp_usb_props, + .num_properties = ARRAY_SIZE(sc8280xp_usb_props), + .get_property = qcom_battmgr_usb_x1e80100_get_property, + .usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) | + BIT(POWER_SUPPLY_USB_TYPE_SDP) | + BIT(POWER_SUPPLY_USB_TYPE_DCP) | + BIT(POWER_SUPPLY_USB_TYPE_CDP) | + BIT(POWER_SUPPLY_USB_TYPE_ACA) | + BIT(POWER_SUPPLY_USB_TYPE_C) | + BIT(POWER_SUPPLY_USB_TYPE_PD) | + BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) | + BIT(POWER_SUPPLY_USB_TYPE_PD_PPS) | + BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID), +}; + +static const struct power_supply_desc x1e80100_usb2_psy_desc = { + .name = "qcom-battmgr-usb2", + .type = POWER_SUPPLY_TYPE_USB, + .properties = sc8280xp_usb_props, + .num_properties = ARRAY_SIZE(sc8280xp_usb_props), + .get_property = qcom_battmgr_usb2_get_property, + .usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) | + BIT(POWER_SUPPLY_USB_TYPE_SDP) | + BIT(POWER_SUPPLY_USB_TYPE_DCP) | + BIT(POWER_SUPPLY_USB_TYPE_CDP) | + BIT(POWER_SUPPLY_USB_TYPE_ACA) | + BIT(POWER_SUPPLY_USB_TYPE_C) | + BIT(POWER_SUPPLY_USB_TYPE_PD) | + BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) | + BIT(POWER_SUPPLY_USB_TYPE_PD_PPS) | + BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID), +}; + +static const struct power_supply_desc x1e80100_usb3_psy_desc = { + .name = "qcom-battmgr-usb3", + .type = POWER_SUPPLY_TYPE_USB, + .properties = sc8280xp_usb_props, + .num_properties = ARRAY_SIZE(sc8280xp_usb_props), + .get_property = qcom_battmgr_usb3_get_property, + .usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) | + BIT(POWER_SUPPLY_USB_TYPE_SDP) | + BIT(POWER_SUPPLY_USB_TYPE_DCP) | + BIT(POWER_SUPPLY_USB_TYPE_CDP) | + BIT(POWER_SUPPLY_USB_TYPE_ACA) | + BIT(POWER_SUPPLY_USB_TYPE_C) | + BIT(POWER_SUPPLY_USB_TYPE_PD) | + BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) | + BIT(POWER_SUPPLY_USB_TYPE_PD_PPS) | + BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID), +}; + static const enum power_supply_property sm8350_usb_props[] = { POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_VOLTAGE_NOW, @@ -1214,6 +1486,10 @@ static void qcom_battmgr_notification(struct qcom_battmgr *battmgr, break; case NOTIF_USB_PROPERTY: power_supply_changed(battmgr->usb_psy); + if (battmgr->usb2_psy) + power_supply_changed(battmgr->usb2_psy); + if (battmgr->usb3_psy) + power_supply_changed(battmgr->usb3_psy); break; case NOTIF_WLS_PROPERTY: power_supply_changed(battmgr->wls_psy); @@ -1280,6 +1556,7 @@ static void qcom_battmgr_sc8280xp_callback(struct qcom_battmgr *battmgr, unsigned int power_state; unsigned int source; unsigned int state; + unsigned int property; size_t payload_len = len - sizeof(struct pmic_glink_hdr); if (payload_len < sizeof(__le32)) { @@ -1383,6 +1660,124 @@ static void qcom_battmgr_sc8280xp_callback(struct qcom_battmgr *battmgr, case BATTMGR_CHG_CTRL_LIMIT_EN: battmgr->error = 0; break; + case BATTMGR_USB_PROPERTY_GET: + property = le32_to_cpu(resp->intval.property); + if (payload_len != sizeof(resp->intval)) { + dev_warn(battmgr->dev, + "invalid payload length for %#x request: %zd\n", + property, payload_len); + battmgr->error = -ENODATA; + return; + } + + switch (property) { + case USB_ONLINE: + battmgr->usb.online = le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_NOW: + battmgr->usb.voltage_now = le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_MAX: + battmgr->usb.voltage_max = le32_to_cpu(resp->intval.value); + break; + case USB_CURR_NOW: + battmgr->usb.current_now = le32_to_cpu(resp->intval.value); + break; + case USB_CURR_MAX: + battmgr->usb.current_max = le32_to_cpu(resp->intval.value); + break; + case USB_INPUT_CURR_LIMIT: + battmgr->usb.current_limit = le32_to_cpu(resp->intval.value); + break; + case USB_TYPE: + case USB_ADAP_TYPE: + battmgr->usb.usb_type = le32_to_cpu(resp->intval.value); + break; + case USB_NUM_PORTS: + battmgr->usb.num_ports = le32_to_cpu(resp->intval.value); + break; + default: + dev_warn(battmgr->dev, "unknown property %#x\n", property); + break; + } + break; + + case BATTMGR_USB2_PROPERTY_GET: + property = le32_to_cpu(resp->intval.property); + if (payload_len != sizeof(resp->intval)) { + dev_warn(battmgr->dev, + "invalid payload length for %#x request: %zd\n", + property, payload_len); + battmgr->error = -ENODATA; + return; + } + + switch (property) { + case USB_ONLINE: + battmgr->usb2.online = le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_NOW: + battmgr->usb2.voltage_now = le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_MAX: + battmgr->usb2.voltage_max = le32_to_cpu(resp->intval.value); + break; + case USB_CURR_NOW: + battmgr->usb2.current_now = le32_to_cpu(resp->intval.value); + break; + case USB_CURR_MAX: + battmgr->usb2.current_max = le32_to_cpu(resp->intval.value); + break; + case USB_INPUT_CURR_LIMIT: + battmgr->usb2.current_limit = le32_to_cpu(resp->intval.value); + break; + case USB_TYPE: + case USB_ADAP_TYPE: + battmgr->usb2.usb_type = le32_to_cpu(resp->intval.value); + break; + default: + dev_warn(battmgr->dev, "unknown property %#x\n", property); + break; + } + break; + case BATTMGR_USB3_PROPERTY_GET: + property = le32_to_cpu(resp->intval.property); + if (payload_len != sizeof(resp->intval)) { + dev_warn(battmgr->dev, + "invalid payload length for %#x request: %zd\n", + property, payload_len); + battmgr->error = -ENODATA; + return; + } + + switch (property) { + case USB_ONLINE: + battmgr->usb3.online = le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_NOW: + battmgr->usb3.voltage_now = le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_MAX: + battmgr->usb3.voltage_max = le32_to_cpu(resp->intval.value); + break; + case USB_CURR_NOW: + battmgr->usb3.current_now = le32_to_cpu(resp->intval.value); + break; + case USB_CURR_MAX: + battmgr->usb3.current_max = le32_to_cpu(resp->intval.value); + break; + case USB_INPUT_CURR_LIMIT: + battmgr->usb3.current_limit = le32_to_cpu(resp->intval.value); + break; + case USB_TYPE: + case USB_ADAP_TYPE: + battmgr->usb3.usb_type = le32_to_cpu(resp->intval.value); + break; + default: + dev_warn(battmgr->dev, "unknown property %#x\n", property); + break; + } + break; default: dev_warn(battmgr->dev, "unknown message %#x\n", opcode); break; @@ -1611,6 +2006,8 @@ static void qcom_battmgr_callback(const void *data, size_t len, void *priv) qcom_battmgr_sm8350_callback(battmgr, data, len); } +static char *qcom_battmgr_battery[] = { "battery" }; + static void qcom_battmgr_enable_worker(struct work_struct *work) { struct qcom_battmgr *battmgr = container_of(work, struct qcom_battmgr, enable_work); @@ -1619,11 +2016,53 @@ static void qcom_battmgr_enable_worker(struct work_struct *work) .hdr.type = cpu_to_le32(PMIC_GLINK_NOTIFY), .hdr.opcode = cpu_to_le32(BATTMGR_REQUEST_NOTIFICATION), }; + struct power_supply *psy; int ret; + int num_ports_fw = 0; ret = qcom_battmgr_request(battmgr, &req, sizeof(req)); if (ret) dev_err(battmgr->dev, "failed to request power notifications\n"); + + if (battmgr->variant == QCOM_BATTMGR_X1E80100) { + mutex_lock(&battmgr->lock); + ret = qcom_battmgr_request_property(battmgr, BATTMGR_USB_PROPERTY_GET, + USB_NUM_PORTS, 0); + mutex_unlock(&battmgr->lock); + if (ret < 0) { + dev_dbg(battmgr->dev, "Failed to read USB_NUM_PORTS from SoCCP, rc=%d\n", + ret); + } else { + num_ports_fw = battmgr->usb.num_ports; + if (num_ports_fw > MAX_USB_PORTS) { + dev_err(battmgr->dev, "USB ports reported by SoCCP: %d exceeds max %d\n", + num_ports_fw, MAX_USB_PORTS); + num_ports_fw = MAX_USB_PORTS; + } + } + + if (num_ports_fw >= 2 && !battmgr->usb2_psy) { + psy = devm_power_supply_register(battmgr->dev, &x1e80100_usb2_psy_desc, + &battmgr->usb_psy_cfg); + if (IS_ERR(psy)) { + dev_err(battmgr->dev, "failed to register USB port-1 power supply: %ld\n", + PTR_ERR(psy)); + } else { + battmgr->usb2_psy = psy; + } + } + + if (num_ports_fw >= 3 && !battmgr->usb3_psy) { + psy = devm_power_supply_register(battmgr->dev, &x1e80100_usb3_psy_desc, + &battmgr->usb_psy_cfg); + if (IS_ERR(psy)) { + dev_err(battmgr->dev, "failed to register USB port-2 power supply: %ld\n", + PTR_ERR(psy)); + } else { + battmgr->usb3_psy = psy; + } + } + } } static void qcom_battmgr_pdr_notify(void *priv, int state) @@ -1649,8 +2088,6 @@ static const struct of_device_id qcom_battmgr_of_variants[] = { {} }; -static char *qcom_battmgr_battery[] = { "battery" }; - static int qcom_battmgr_probe(struct auxiliary_device *adev, const struct auxiliary_device_id *id) { @@ -1676,6 +2113,8 @@ static int qcom_battmgr_probe(struct auxiliary_device *adev, psy_cfg_supply.supplied_to = qcom_battmgr_battery; psy_cfg_supply.num_supplicants = 1; + battmgr->usb_psy_cfg = psy_cfg_supply; + mutex_init(&battmgr->lock); init_completion(&battmgr->ack); @@ -1690,14 +2129,9 @@ static int qcom_battmgr_probe(struct auxiliary_device *adev, return dev_err_probe(dev, ret, "failed to init battery charge control thresholds\n"); - if (battmgr->variant == QCOM_BATTMGR_SC8280XP || - battmgr->variant == QCOM_BATTMGR_X1E80100) { - if (battmgr->variant == QCOM_BATTMGR_X1E80100) - psy_desc = &x1e80100_bat_psy_desc; - else - psy_desc = &sc8280xp_bat_psy_desc; - - battmgr->bat_psy = devm_power_supply_register(dev, psy_desc, &psy_cfg); + if (battmgr->variant == QCOM_BATTMGR_SC8280XP) { + battmgr->bat_psy = devm_power_supply_register(dev, &sc8280xp_bat_psy_desc, + &psy_cfg); if (IS_ERR(battmgr->bat_psy)) return dev_err_probe(dev, PTR_ERR(battmgr->bat_psy), "failed to register battery power supply\n"); @@ -1712,6 +2146,30 @@ static int qcom_battmgr_probe(struct auxiliary_device *adev, return dev_err_probe(dev, PTR_ERR(battmgr->usb_psy), "failed to register USB power supply\n"); + battmgr->wls_psy = devm_power_supply_register(dev, &sc8280xp_wls_psy_desc, + &psy_cfg_supply); + if (IS_ERR(battmgr->wls_psy)) + return dev_err_probe(dev, PTR_ERR(battmgr->wls_psy), + "failed to register wireless charing power supply\n"); + } else if (battmgr->variant == QCOM_BATTMGR_X1E80100) { + battmgr->bat_psy = devm_power_supply_register(dev, &x1e80100_bat_psy_desc, + &psy_cfg); + if (IS_ERR(battmgr->bat_psy)) + return dev_err_probe(dev, PTR_ERR(battmgr->bat_psy), + "failed to register battery power supply\n"); + + battmgr->ac_psy = devm_power_supply_register(dev, &sc8280xp_ac_psy_desc, + &psy_cfg_supply); + if (IS_ERR(battmgr->ac_psy)) + return dev_err_probe(dev, PTR_ERR(battmgr->ac_psy), + "failed to register AC power supply\n"); + + battmgr->usb_psy = devm_power_supply_register(dev, &x1e80100_usb_psy_desc, + &psy_cfg_supply); + if (IS_ERR(battmgr->usb_psy)) + return dev_err_probe(dev, PTR_ERR(battmgr->usb_psy), + "failed to register USB power supply\n"); + battmgr->wls_psy = devm_power_supply_register(dev, &sc8280xp_wls_psy_desc, &psy_cfg_supply); if (IS_ERR(battmgr->wls_psy)) return dev_err_probe(dev, PTR_ERR(battmgr->wls_psy), From 0ab2485e6c3f2c095879285191a46895ab8f8da4 Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Wed, 8 Jul 2026 16:07:22 +0530 Subject: [PATCH 0337/1133] FROMLIST: power: sequencing: pcie-m2: Deassert W_DISABLE2# when no UART serdev is created The pwrseq_m2_pci_ids[] table lists PCIe BT devices that use UART as the BT transport and need a UART serdev created by the driver. When a PCIe device under the M.2 connector does not match any entry in this table, no UART serdev is created. However, the BT subsystem of such a device may still require W_DISABLE2# to be deasserted to power up. Rather than adding every possible non-UART BT device ID to the table, add an else branch that deasserts W_DISABLE2# whenever a PCIe device is detected under the connector but does not match a UART BT entry. This allows any BT interface on the card (USB or other) to enumerate without requiring explicit knowledge of its device ID. The primary use case is USB BT variants of combo chips that share the same PCIe device ID as their UART counterpart (e.g. WCN7851 NCM865 USB, sub 0x3378, vs NCM865A UART, sub 0x337c): no UART serdev is needed, but W_DISABLE2# must be deasserted so the USB BT device can enumerate. Reassert W_DISABLE2# symmetrically when the PCIe device is removed. Validated on Hamoa EVK (IQ-X7181-EVK) with WCN7851 NCM865 USB card (sub 0x3378): without this change GPIO116 (W_DISABLE2#) stays low and no BT interface appears; with this change GPIO116 is driven high and the USB BT device enumerates and comes up via btusb. Signed-off-by: Wei Deng Link: https://lore.kernel.org/all/20260709-fix-hamoa-m2-w-disable2-v1-3-5e725091266a@oss.qualcomm.com/ --- drivers/power/sequencing/pwrseq-pcie-m2.c | 33 ++++++++++++++++------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c index 56c5d51293c10..33425e386d795 100644 --- a/drivers/power/sequencing/pwrseq-pcie-m2.c +++ b/drivers/power/sequencing/pwrseq-pcie-m2.c @@ -444,11 +444,23 @@ static int pwrseq_pcie_m2_notify(struct notifier_block *nb, unsigned long action ret = pwrseq_pcie_m2_create_serdev_one(ctx, pdev); if (ret) return notifier_from_errno(ret); + } else if (ctx->w_disable2_gpio) { + /* + * PCIe device not in the UART BT table. This covers + * USB BT variants of the same combo chip (same PCIe + * device ID, different sub-system ID, BT exposed over + * USB instead of UART). No UART serdev is needed, but + * W_DISABLE2# must be deasserted to enable the BT + * subsystem so the USB BT interface can enumerate. + */ + gpiod_set_value_cansleep(ctx->w_disable2_gpio, 0); } break; case BUS_NOTIFY_REMOVED_DEVICE: if (pci_match_id(pwrseq_m2_pci_ids, pdev)) pwrseq_pcie_m2_remove_serdev(ctx, pdev); + else if (ctx->w_disable2_gpio) + gpiod_set_value_cansleep(ctx->w_disable2_gpio, 1); break; } @@ -512,16 +524,17 @@ static int pwrseq_pcie_m2_create_serdev(struct pwrseq_pcie_m2_ctx *ctx) if (!pwrseq_pcie_m2_pci_parent_matches(pdev, pci_parent)) continue; - if (!pci_match_id(pwrseq_m2_pci_ids, pdev)) - continue; - - ret = pwrseq_pcie_m2_create_serdev_one(ctx, pdev); - if (ret) { - dev_err_probe(ctx->dev, ret, - "Failed to create serdev for PCI device (%s)\n", - pci_name(pdev)); - pci_dev_put(pdev); - goto err_remove_serdev; + if (pci_match_id(pwrseq_m2_pci_ids, pdev)) { + ret = pwrseq_pcie_m2_create_serdev_one(ctx, pdev); + if (ret) { + dev_err_probe(ctx->dev, ret, + "Failed to create serdev for PCI device (%s)\n", + pci_name(pdev)); + pci_dev_put(pdev); + goto err_remove_serdev; + } + } else if (ctx->w_disable2_gpio) { + gpiod_set_value_cansleep(ctx->w_disable2_gpio, 0); } } From db1a43f3f98c7e34e722907cc8d8643134d00d55 Mon Sep 17 00:00:00 2001 From: Hariharan Sreedhar Date: Wed, 7 Oct 2026 09:41:53 +0000 Subject: [PATCH 0338/1133] FROMLIST: phy: qcom: qmp-pcie: Add vdda-refgen supplies for QCS8300 and SA8775p The PCIe QMP PHYs on Monaco (QCS8300) require stable reference voltage provided by refgen and reference clock provided by qref. The refgen and qref require power supplies. Add a new sa8775p_qmp_phy_vreg_l list with vdda-qref and vdda-refgen supplies, and use it for qcs8300_qmp_gen4x2, sa8775p_qmp_gen4x2 and sa8775p_qmp_gen4x4 PCIe PHY configurations Link: https://lore.kernel.org/all/20260916102023.2054761-3-ziyue.zhang@oss.qualcomm.com/ Signed-off-by: Ziyue Zhang Signed-off-by: Hariharan Sreedhar --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index 9cfabf474fd63..c7aeebd037f59 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -4106,6 +4106,10 @@ static const char * const sm8550_qmp_phy_vreg_l[] = { "vdda-phy", "vdda-pll", "vdda-qref", }; +static const char * const sa8775p_qmp_phy_vreg_l[] = { + "vdda-phy", "vdda-pll", "vdda-qref", "vdda-refgen", "refgen" +}; + /* list of resets */ static const char * const ipq8074_pciephy_reset_l[] = { "phy", "common", @@ -4597,8 +4601,8 @@ static const struct qmp_phy_cfg qcs8300_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -5362,8 +5366,8 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -5403,8 +5407,8 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, From c8d25cb6f9f3c5544aa6ecfc9e74614ece0e33d8 Mon Sep 17 00:00:00 2001 From: krishnachaitanya-linux Date: Tue, 13 Oct 2026 10:19:25 +0530 Subject: [PATCH 0339/1133] =?UTF-8?q?Revert=20"FROMLIST:=20phy:=20qcom:=20?= =?UTF-8?q?qmp-pcie:=20Add=20vdda-refgen=20supplies=20for=20QCS8300=20a?= =?UTF-8?q?=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 95ba1c6b04db3a87b6fe82922c1fa34402e14bb7. --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index c7aeebd037f59..9cfabf474fd63 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -4106,10 +4106,6 @@ static const char * const sm8550_qmp_phy_vreg_l[] = { "vdda-phy", "vdda-pll", "vdda-qref", }; -static const char * const sa8775p_qmp_phy_vreg_l[] = { - "vdda-phy", "vdda-pll", "vdda-qref", "vdda-refgen", "refgen" -}; - /* list of resets */ static const char * const ipq8074_pciephy_reset_l[] = { "phy", "common", @@ -4601,8 +4597,8 @@ static const struct qmp_phy_cfg qcs8300_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = sa8775p_qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -5366,8 +5362,8 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = sa8775p_qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -5407,8 +5403,8 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = sa8775p_qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, From c2e1c1843540509d801ae7ed37eb5f1bd623b73a Mon Sep 17 00:00:00 2001 From: Hariharan Sreedhar Date: Wed, 7 Oct 2026 09:41:53 +0000 Subject: [PATCH 0340/1133] FROMLIST: phy: qcom: qmp-pcie: Add vdda-refgen supplies for QCS8300 and SA8775p The PCIe QMP PHYs on Monaco (QCS8300) require stable reference voltage provided by refgen and reference clock provided by qref. The refgen and qref require power supplies. Add a new sa8775p_qmp_phy_vreg_l list with vdda-qref and vdda-refgen supplies, and use it for qcs8300_qmp_gen4x2, sa8775p_qmp_gen4x2 and sa8775p_qmp_gen4x4 PCIe PHY configurations Link: https://lore.kernel.org/all/20260916102023.2054761-3-ziyue.zhang@oss.qualcomm.com/ Signed-off-by: Ziyue Zhang Signed-off-by: Hariharan Sreedhar --- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index 9cfabf474fd63..c7aeebd037f59 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -4106,6 +4106,10 @@ static const char * const sm8550_qmp_phy_vreg_l[] = { "vdda-phy", "vdda-pll", "vdda-qref", }; +static const char * const sa8775p_qmp_phy_vreg_l[] = { + "vdda-phy", "vdda-pll", "vdda-qref", "vdda-refgen", "refgen" +}; + /* list of resets */ static const char * const ipq8074_pciephy_reset_l[] = { "phy", "common", @@ -4597,8 +4601,8 @@ static const struct qmp_phy_cfg qcs8300_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -5362,8 +5366,8 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x2_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, @@ -5403,8 +5407,8 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = { .reset_list = sdm845_pciephy_reset_l, .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), - .vreg_list = qmp_phy_vreg_l, - .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .vreg_list = sa8775p_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sa8775p_qmp_phy_vreg_l), .regs = pciephy_v5_regs_layout, .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, From 1126804d7ff6f2f9b837ed22db6da4c5ae0e14e0 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Wed, 8 Jul 2026 16:30:16 +0200 Subject: [PATCH 0341/1133] FROMLIST: PCI/ASPM: Add pci_force_enable_link_state() API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pci_enable_link_state() and pci_enable_link_state_locked() APIs only enable the ASPM states that were not previously disabled via pci_disable_link_state*() API or blacklisted during init (e.g. the pre-1.1 device blacklist, which is only meant to be overridden with 'pcie_aspm=force'). This is an intentional behavior as these APIs must not silently re-enable states that were deliberately disabled, since doing so could enable ASPM on a link where it is known to be unsafe. However, some drivers (e.g. the atheros WLAN drivers) save the currently enabled ASPM states, disable all ASPM states before firmware download, and then try to restore exactly the states that were enabled before. Restoring those states requires re-enabling states that were just disabled via pci_disable_link_state() API. But, this cannot be achieved using the existing APIs. Hence, add pci_force_enable_link_state() API for such callers. Unlike pci_enable_link_state(), it re-enables the requested states even if they were previously disabled via pci_disable_link_state() or disabled during init. The caller is therefore responsible for only enabling states the device actually supports, typically the ones previously reported by pcie_aspm_enabled(). This API is implemented by adding a 'force' parameter to the shared __pci_enable_link_state() helper. When 'force' is true, the requested states are cleared from 'link->aspm_disable' before enabling. Suggested-by: Ilpo Järvinen Signed-off-by: Manivannan Sadhasivam Signed-off-by: Hariharan Sreedhar --- drivers/pci/pcie/aspm.c | 37 ++++++++++++++++++++++++++++++++++--- include/linux/pci.h | 3 +++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index b039b57f8466b..a3fd948b66ba1 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -1561,7 +1561,8 @@ int pci_disable_link_state(struct pci_dev *pdev, int state) } EXPORT_SYMBOL(pci_disable_link_state); -static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked) +static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked, + bool force) { struct pcie_link_state *link = pcie_aspm_get_link(pdev); @@ -1582,6 +1583,10 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked) down_read(&pci_bus_sem); mutex_lock(&aspm_lock); link->aspm_default = pci_calc_aspm_enable_mask(state); + + /* Force enable states that were previously disabled */ + if (force) + link->aspm_disable &= ~link->aspm_default; pcie_config_aspm_link(link, policy_to_aspm_state(link)); link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0; @@ -1608,7 +1613,7 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked) */ int pci_enable_link_state(struct pci_dev *pdev, int state) { - return __pci_enable_link_state(pdev, state, false); + return __pci_enable_link_state(pdev, state, false, false); } EXPORT_SYMBOL(pci_enable_link_state); @@ -1631,10 +1636,36 @@ int pci_enable_link_state_locked(struct pci_dev *pdev, int state) { lockdep_assert_held_read(&pci_bus_sem); - return __pci_enable_link_state(pdev, state, true); + return __pci_enable_link_state(pdev, state, true, false); } EXPORT_SYMBOL(pci_enable_link_state_locked); +/** + * pci_force_enable_link_state - Force enable device link state + * @pdev: PCI device + * @state: Mask of ASPM link states to enable + * + * Enable device link state, so the link will enter the specified states. + * Unlike pci_enable_link_state(), this also re-enables states previously + * disabled by pci_disable_link_state() and overrides the ASPM states disabled + * during init (e.g., the pre-1.1 device blacklist). The caller is therefore + * responsible for only enabling states the device supports, typically the ones + * previously reported by pcie_aspm_enabled(). + * + * Note that if the BIOS didn't grant ASPM control to the OS, this does nothing + * because we can't touch the LNKCTL register. + * + * Note: Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per + * PCIe r6.0, sec 5.5.4. + * + * Return: 0 on success, a negative errno otherwise. + */ +int pci_force_enable_link_state(struct pci_dev *pdev, int state) +{ + return __pci_enable_link_state(pdev, state, false, true); +} +EXPORT_SYMBOL(pci_force_enable_link_state); + void pcie_aspm_remove_cap(struct pci_dev *pdev, u32 lnkcap) { if (lnkcap & PCI_EXP_LNKCAP_ASPM_L0S) diff --git a/include/linux/pci.h b/include/linux/pci.h index aa3765a20a96c..c8b94abcb64ea 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1957,6 +1957,7 @@ int pci_disable_link_state(struct pci_dev *pdev, int state); int pci_disable_link_state_locked(struct pci_dev *pdev, int state); int pci_enable_link_state(struct pci_dev *pdev, int state); int pci_enable_link_state_locked(struct pci_dev *pdev, int state); +int pci_force_enable_link_state(struct pci_dev *pdev, int state); void pcie_no_aspm(void); bool pcie_aspm_support_enabled(void); bool pcie_aspm_enabled(struct pci_dev *pdev); @@ -1969,6 +1970,8 @@ static inline int pci_enable_link_state(struct pci_dev *pdev, int state) { return 0; } static inline int pci_enable_link_state_locked(struct pci_dev *pdev, int state) { return 0; } +static inline int pci_force_enable_link_state(struct pci_dev *pdev, int state) +{ return 0; } static inline void pcie_no_aspm(void) { } static inline bool pcie_aspm_support_enabled(void) { return false; } static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; } From d727741391a204983ad1dddcd99456a3cedf4444 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Wed, 8 Jul 2026 16:30:17 +0200 Subject: [PATCH 0342/1133] FROMLIST: PCI/ASPM: Transition the device to D0 (if required) when enabling ASPM link states Per PCIe spec r6.0, sec 5.5.4: "If setting either or both of the enable bits for PCI-PM L1 PM Substates, both ports must be configured as described in this section while in D0." Currently, the callers of pci_enable_link_state_locked() (vmd, pcie-qcom) transition the device to D0 themselves before enabling the link state. But this is easy to get wrong and has to be duplicated by every caller. Move the D0 transition into the shared __pci_enable_link_state() helper so that all three APIs pci_enable_link_state(), pci_enable_link_state_locked() and pci_force_enable_link_state() perform it, and only when the PCI-PM L1 PM Substates are getting enabled. Now that the helper handles the transition, drop the redundant D0 transition from the vmd and pcie-qcom callers. Signed-off-by: Manivannan Sadhasivam Signed-off-by: Hariharan Sreedhar --- drivers/pci/controller/dwc/pcie-qcom.c | 5 ----- drivers/pci/controller/vmd.c | 5 ----- drivers/pci/pcie/aspm.c | 23 +++++++++++++++++------ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index d903f10211c23..503cd356e6cca 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -1152,11 +1152,6 @@ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie) static int qcom_pcie_enable_aspm(struct pci_dev *pdev, void *userdata) { - /* - * Downstream devices need to be in D0 state before enabling PCI PM - * substates. - */ - pci_set_power_state_locked(pdev, PCI_D0); pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); return 0; diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c index 9d97a832785ee..af09ff976613f 100644 --- a/drivers/pci/controller/vmd.c +++ b/drivers/pci/controller/vmd.c @@ -945,11 +945,6 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata) pci_info(pdev, "VMD: Default LTR value set by driver\n"); out_state_change: - /* - * Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per - * PCIe r6.0, sec 5.5.4. - */ - pci_set_power_state_locked(pdev, PCI_D0); pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); return 0; } diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index a3fd948b66ba1..8b579704514f5 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -1579,6 +1579,17 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked, return -EPERM; } + /* + * Ensure the device is in D0 before enabling PCI-PM L1 PM Substates, per + * PCIe r6.0, sec 5.5.4. + */ + if (state & PCIE_LINK_STATE_L1_SS_PCIPM) { + if (locked) + pci_set_power_state_locked(pdev, PCI_D0); + else + pci_set_power_state(pdev, PCI_D0); + } + if (!locked) down_read(&pci_bus_sem); mutex_lock(&aspm_lock); @@ -1605,8 +1616,8 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked, * touch the LNKCTL register. Also note that this does not enable states * disabled by pci_disable_link_state(). Return 0 or a negative errno. * - * Note: Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per - * PCIe r6.0, sec 5.5.4. + * Note: The device will be transitioned to D0 state if the PCI-PM L1 Substates + * are getting enabled. * * @pdev: PCI device * @state: Mask of ASPM link states to enable @@ -1624,8 +1635,8 @@ EXPORT_SYMBOL(pci_enable_link_state); * can't touch the LNKCTL register. Also note that this does not enable states * disabled by pci_disable_link_state(). Return 0 or a negative errno. * - * Note: Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per - * PCIe r6.0, sec 5.5.4. + * Note: The device will be transitioned to D0 state if the PCI-PM L1 Substates + * are getting enabled. * * @pdev: PCI device * @state: Mask of ASPM link states to enable @@ -1655,8 +1666,8 @@ EXPORT_SYMBOL(pci_enable_link_state_locked); * Note that if the BIOS didn't grant ASPM control to the OS, this does nothing * because we can't touch the LNKCTL register. * - * Note: Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per - * PCIe r6.0, sec 5.5.4. + * Note: The device will be transitioned to D0 state if the PCI-PM L1 Substates + * are getting enabled. * * Return: 0 on success, a negative errno otherwise. */ From 093ddde68f60c6934744905785049f36c41f3936 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Wed, 8 Jul 2026 16:30:18 +0200 Subject: [PATCH 0343/1133] FROMLIST: PCI/ASPM: Improve the kernel-doc for pci_{enable,disable}_link_state*() APIs Add kernel-doc for pci_disable_link_state_locked() API and fix the kernel-doc for pci_disable_link_state() API. Also convert the kernel-doc of pci_enable_link_state() and pci_enable_link_state_locked() APIs to the standard format and mention that pci_force_enable_link_state() should be used to re-enable the states disabled by pci_disable_link_state(). Signed-off-by: Manivannan Sadhasivam Signed-off-by: Hariharan Sreedhar --- drivers/pci/pcie/aspm.c | 47 ++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 8b579704514f5..886c2485bad99 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -1538,6 +1538,17 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool locked return 0; } +/** + * pci_disable_link_state_locked - Disable device's link state + * @pdev: PCI device + * @state: ASPM link state to disable + * + * Disable device's link state so the link will never enter specific states. + * + * Context: Caller holds pci_bus_sem read lock. + * + * Return: 0 on success, a negative errno otherwise. + */ int pci_disable_link_state_locked(struct pci_dev *pdev, int state) { lockdep_assert_held_read(&pci_bus_sem); @@ -1610,17 +1621,20 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked, } /** - * pci_enable_link_state - Clear and set the default device link state so that - * the link may be allowed to enter the specified states. Note that if the - * BIOS didn't grant ASPM control to the OS, this does nothing because we can't - * touch the LNKCTL register. Also note that this does not enable states - * disabled by pci_disable_link_state(). Return 0 or a negative errno. + * pci_enable_link_state - Enable device's link state + * @pdev: PCI device + * @state: Mask of ASPM link states to enable + * + * Enable device's link state, so the link will enter the specified states. + * Note that if the BIOS didn't grant ASPM control to the OS, this does + * nothing because we can't touch the LNKCTL register. Also note that this + * does not enable states disabled by pci_disable_link_state(). Use + * pci_force_enable_link_state() for that. * * Note: The device will be transitioned to D0 state if the PCI-PM L1 Substates * are getting enabled. * - * @pdev: PCI device - * @state: Mask of ASPM link states to enable + * Return: 0 on success, a negative errno otherwise. */ int pci_enable_link_state(struct pci_dev *pdev, int state) { @@ -1629,19 +1643,22 @@ int pci_enable_link_state(struct pci_dev *pdev, int state) EXPORT_SYMBOL(pci_enable_link_state); /** - * pci_enable_link_state_locked - Clear and set the default device link state - * so that the link may be allowed to enter the specified states. Note that if - * the BIOS didn't grant ASPM control to the OS, this does nothing because we - * can't touch the LNKCTL register. Also note that this does not enable states - * disabled by pci_disable_link_state(). Return 0 or a negative errno. + * pci_enable_link_state_locked - Enable device's link state + * @pdev: PCI device + * @state: Mask of ASPM link states to enable + * + * Enable device's link state, so the link will enter the specified states. + * Note that if the BIOS didn't grant ASPM control to the OS, this does + * nothing because we can't touch the LNKCTL register. Also note that this + * does not enable states disabled by pci_disable_link_state(). Use + * pci_force_enable_link_state() for that. * * Note: The device will be transitioned to D0 state if the PCI-PM L1 Substates * are getting enabled. * - * @pdev: PCI device - * @state: Mask of ASPM link states to enable - * * Context: Caller holds pci_bus_sem read lock. + * + * Return: 0 on success, a negative errno otherwise. */ int pci_enable_link_state_locked(struct pci_dev *pdev, int state) { From b8c897e021963a3716ee7363b4da5550c33a38ac Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Wed, 8 Jul 2026 16:30:19 +0200 Subject: [PATCH 0344/1133] FROMLIST: PCI/ASPM: Return enabled ASPM states from pcie_aspm_enabled() API pcie_aspm_enabled() returns 'pcie_link_state::aspm_enabled' parameter which contains the enabled states. But the API currently returns the 'bool' type which is used by the callers to decide if ASPM is enabled or not. To allow the future callers to also make use of the enabled ASPM states, return the actual type of 'pcie_link_state::aspm_enabled' parameter, 'u32'. Existing callers can still treat the return value as a 'bool' as the C11 standard guarantees the behavior (this API relied on the same behavior before as well). Signed-off-by: Manivannan Sadhasivam Signed-off-by: Hariharan Sreedhar --- drivers/pci/pcie/aspm.c | 6 ++++-- include/linux/pci.h | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 886c2485bad99..f8e64971c6c3d 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -1749,15 +1749,17 @@ module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy, NULL, 0644); /** - * pcie_aspm_enabled - Check if PCIe ASPM has been enabled for a device. + * pcie_aspm_enabled - Get the enabled PCIe ASPM states for a device. * @pdev: Target device. * * Relies on the upstream bridge's link_state being valid. The link_state * is deallocated only when the last child of the bridge (i.e., @pdev or a * sibling) is removed, and the caller should be holding a reference to * @pdev, so this should be safe. + * + * Return: Enabled PCIe ASPM states. 0 if ASPM is disabled. */ -bool pcie_aspm_enabled(struct pci_dev *pdev) +u32 pcie_aspm_enabled(struct pci_dev *pdev) { struct pcie_link_state *link = pcie_aspm_get_link(pdev); diff --git a/include/linux/pci.h b/include/linux/pci.h index c8b94abcb64ea..9cbcadd08f3d3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1960,7 +1960,7 @@ int pci_enable_link_state_locked(struct pci_dev *pdev, int state); int pci_force_enable_link_state(struct pci_dev *pdev, int state); void pcie_no_aspm(void); bool pcie_aspm_support_enabled(void); -bool pcie_aspm_enabled(struct pci_dev *pdev); +u32 pcie_aspm_enabled(struct pci_dev *pdev); #else static inline int pci_disable_link_state(struct pci_dev *pdev, int state) { return 0; } @@ -1974,7 +1974,7 @@ static inline int pci_force_enable_link_state(struct pci_dev *pdev, int state) { return 0; } static inline void pcie_no_aspm(void) { } static inline bool pcie_aspm_support_enabled(void) { return false; } -static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; } +static inline u32 pcie_aspm_enabled(struct pci_dev *pdev) { return 0; } #endif #ifdef CONFIG_HOTPLUG_PCI From 2e3b872e8cbd1036bd92d86dba17b5719d7fbfa2 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Wed, 8 Jul 2026 16:30:20 +0200 Subject: [PATCH 0345/1133] FROMLIST: wifi: ath12k: Use pci_{enable/disable}_link_state() APIs to enable/disable ASPM states It is not recommended to enable/disable the ASPM states on the back of the PCI core directly using the LNKCTL register. It will break the PCI core's knowledge about the device ASPM states. So use the APIs exposed by the PCI core to enable/disable ASPM states. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Reported-by: Qiang Yu Signed-off-by: Manivannan Sadhasivam Signed-off-by: Hariharan Sreedhar --- drivers/net/wireless/ath/ath12k/Kconfig | 2 +- drivers/net/wireless/ath/ath12k/pci.c | 19 +++---------------- drivers/net/wireless/ath/ath12k/pci.h | 4 +++- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/Kconfig b/drivers/net/wireless/ath/ath12k/Kconfig index 0d5d1c55bfc13..4662d38c88c0c 100644 --- a/drivers/net/wireless/ath/ath12k/Kconfig +++ b/drivers/net/wireless/ath/ath12k/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause-Clear config ATH12K tristate "Qualcomm Wi-Fi 7 support (ath12k)" - depends on MAC80211 && HAS_DMA && PCI + depends on MAC80211 && HAS_DMA && PCI && PCIEASPM select QCOM_QMI_HELPERS select MHI_BUS select QRTR diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index 12bbb75570f1f..7009f1259a0bd 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -908,19 +908,9 @@ static void ath12k_pci_free_region(struct ath12k_pci *ab_pci) static void ath12k_pci_aspm_disable(struct ath12k_pci *ab_pci) { - struct ath12k_base *ab = ab_pci->ab; - - pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL, - &ab_pci->link_ctl); - - ath12k_dbg(ab, ATH12K_DBG_PCI, "pci link_ctl 0x%04x L0s %d L1 %d\n", - ab_pci->link_ctl, - u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S), - u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1)); + ab_pci->aspm_states = pcie_aspm_enabled(ab_pci->pdev); - /* disable L0s and L1 */ - pcie_capability_clear_word(ab_pci->pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_ASPMC); + pci_disable_link_state(ab_pci->pdev, PCIE_LINK_STATE_ASPM_ALL); set_bit(ATH12K_PCI_ASPM_RESTORE, &ab_pci->flags); } @@ -949,10 +939,7 @@ static void ath12k_pci_aspm_restore(struct ath12k_pci *ab_pci) { if (ab_pci->ab->hw_params->supports_aspm && test_and_clear_bit(ATH12K_PCI_ASPM_RESTORE, &ab_pci->flags)) - pcie_capability_clear_and_set_word(ab_pci->pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_ASPMC, - ab_pci->link_ctl & - PCI_EXP_LNKCTL_ASPMC); + pci_force_enable_link_state(ab_pci->pdev, ab_pci->aspm_states); } static void ath12k_pci_cancel_workqueue(struct ath12k_base *ab) diff --git a/drivers/net/wireless/ath/ath12k/pci.h b/drivers/net/wireless/ath/ath12k/pci.h index 0e0e2020c6ae5..409ef063cd69a 100644 --- a/drivers/net/wireless/ath/ath12k/pci.h +++ b/drivers/net/wireless/ath/ath12k/pci.h @@ -128,7 +128,9 @@ struct ath12k_pci { /* enum ath12k_pci_flags */ unsigned long flags; - u16 link_ctl; + + /* Cached PCIe ASPM states */ + u32 aspm_states; unsigned long irq_flags; const struct ath12k_pci_ops *pci_ops; u32 qmi_instance; From 6d6daeab1498cf48d78f26b1b274aaa8b1a9ed6a Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Wed, 8 Jul 2026 16:30:21 +0200 Subject: [PATCH 0346/1133] FROMLIST: wifi: ath11k: Use pci_{enable/disable}_link_state() APIs to enable/disable ASPM states It is not recommended to enable/disable the ASPM states on the back of the PCI core directly using the LNKCTL register. It will break the PCI core's knowledge about the device ASPM states. So use the APIs exposed by the PCI core to enable/disable ASPM states. Signed-off-by: Manivannan Sadhasivam Signed-off-by: Hariharan Sreedhar --- drivers/net/wireless/ath/ath11k/Kconfig | 2 +- drivers/net/wireless/ath/ath11k/pci.c | 19 +++---------------- drivers/net/wireless/ath/ath11k/pci.h | 3 ++- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/Kconfig b/drivers/net/wireless/ath/ath11k/Kconfig index 44b520d2e66ee..ac398246d530a 100644 --- a/drivers/net/wireless/ath/ath11k/Kconfig +++ b/drivers/net/wireless/ath/ath11k/Kconfig @@ -22,7 +22,7 @@ config ATH11K_AHB config ATH11K_PCI tristate "Atheros ath11k PCI support" - depends on ATH11K && PCI + depends on ATH11K && PCI && PCIEASPM select MHI_BUS select QRTR select QRTR_MHI diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index a163168f36176..32dbb844a47b8 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -608,19 +608,9 @@ static void ath11k_pci_free_region(struct ath11k_pci *ab_pci) static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci) { - struct ath11k_base *ab = ab_pci->ab; - - pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL, - &ab_pci->link_ctl); - - ath11k_dbg(ab, ATH11K_DBG_PCI, "link_ctl 0x%04x L0s %d L1 %d\n", - ab_pci->link_ctl, - u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S), - u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1)); + ab_pci->aspm_states = pcie_aspm_enabled(ab_pci->pdev); - /* disable L0s and L1 */ - pcie_capability_clear_word(ab_pci->pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_ASPMC); + pci_disable_link_state(ab_pci->pdev, PCIE_LINK_STATE_ASPM_ALL); set_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags); } @@ -628,10 +618,7 @@ static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci) static void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci) { if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags)) - pcie_capability_clear_and_set_word(ab_pci->pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_ASPMC, - ab_pci->link_ctl & - PCI_EXP_LNKCTL_ASPMC); + pci_force_enable_link_state(ab_pci->pdev, ab_pci->aspm_states); } #ifdef CONFIG_DEV_COREDUMP diff --git a/drivers/net/wireless/ath/ath11k/pci.h b/drivers/net/wireless/ath/ath11k/pci.h index 1e3005a4b64c6..474c187414187 100644 --- a/drivers/net/wireless/ath/ath11k/pci.h +++ b/drivers/net/wireless/ath/ath11k/pci.h @@ -72,7 +72,8 @@ struct ath11k_pci { /* enum ath11k_pci_flags */ unsigned long flags; - u16 link_ctl; + /* Cached PCIe ASPM states */ + u32 aspm_states; u64 dma_mask; }; From 5572d7fdf35f22f1902700016e372e6160d10472 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Wed, 8 Jul 2026 16:30:22 +0200 Subject: [PATCH 0347/1133] FROMLIST: wifi: ath10k: Use pci_{enable/disable}_link_state() APIs to enable/disable ASPM states It is not recommended to enable/disable the ASPM states on the back of the PCI core directly using the LNKCTL register. It will break the PCI core's knowledge about the device ASPM states. So use the APIs exposed by the PCI core to enable/disable ASPM states. Signed-off-by: Manivannan Sadhasivam Signed-off-by: Hariharan Sreedhar --- drivers/net/wireless/ath/ath10k/Kconfig | 2 +- drivers/net/wireless/ath/ath10k/pci.c | 11 ++++------- drivers/net/wireless/ath/ath10k/pci.h | 5 ++--- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index efb9f022d8c66..eac3ec5a4e78f 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -17,7 +17,7 @@ config ATH10K_CE config ATH10K_PCI tristate "Atheros ath10k PCI support" - depends on ATH10K && PCI + depends on ATH10K && PCI && PCIEASPM help This module adds support for PCIE bus diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 335bc7c488e41..2e27a70065cce 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1965,9 +1965,7 @@ static int ath10k_pci_hif_start(struct ath10k *ar) ath10k_pci_irq_enable(ar); ath10k_pci_rx_post(ar); - pcie_capability_clear_and_set_word(ar_pci->pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_ASPMC, - ar_pci->link_ctl & PCI_EXP_LNKCTL_ASPMC); + pci_force_enable_link_state(ar_pci->pdev, ar_pci->aspm_states); return 0; } @@ -2822,10 +2820,9 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar, ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n"); - pcie_capability_read_word(ar_pci->pdev, PCI_EXP_LNKCTL, - &ar_pci->link_ctl); - pcie_capability_clear_word(ar_pci->pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_ASPMC); + ar_pci->aspm_states = pcie_aspm_enabled(ar_pci->pdev); + + pci_disable_link_state(ar_pci->pdev, PCIE_LINK_STATE_ASPM_ALL); /* * Bring the target up cleanly. diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index d114778edb417..122e365b7cdd8 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -128,10 +128,9 @@ struct ath10k_pci { struct timer_list rx_post_retry; /* Due to HW quirks it is recommended to disable ASPM during device - * bootup. To do that the original PCI-E Link Control is stored before - * device bootup is executed and re-programmed later. + * bootup. To do that the ASPM states are saved and re-programmed later. */ - u16 link_ctl; + u32 aspm_states; /* Protects ps_awake and ps_wake_refcount */ spinlock_t ps_lock; From d73a1e3c0beecb2f207c1a947a53aee90a9891c9 Mon Sep 17 00:00:00 2001 From: Vivek Pernamitta Date: Thu, 17 Sep 2026 12:38:02 +0530 Subject: [PATCH 0348/1133] FROMLIST: bus: mhi: host: Add support to read MHI capabilities As per MHI spec v1.2,sec 6.6, MHI has capability registers which are located after the ERDB array. The location of this group of registers is indicated by the MISCOFF register. Each capability has a capability ID to determine which functionality is supported and each capability will point to the next capability supported. Add a basic function to read those capabilities offsets. Signed-off-by: Vivek Pernamitta Signed-off-by: Sivareddy Surasani Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Hariharan Sreedhar --- drivers/bus/mhi/common.h | 11 +++++++++++ drivers/bus/mhi/host/init.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/drivers/bus/mhi/common.h b/drivers/bus/mhi/common.h index dda340aaed95a..4c316f3d5a68b 100644 --- a/drivers/bus/mhi/common.h +++ b/drivers/bus/mhi/common.h @@ -16,6 +16,7 @@ #define MHICFG 0x10 #define CHDBOFF 0x18 #define ERDBOFF 0x20 +#define MISCOFF 0x24 #define BHIOFF 0x28 #define BHIEOFF 0x2c #define DEBUGOFF 0x30 @@ -113,6 +114,9 @@ #define MHISTATUS_MHISTATE_MASK GENMASK(15, 8) #define MHISTATUS_SYSERR_MASK BIT(2) #define MHISTATUS_READY_MASK BIT(0) +#define MISC_CAP_MASK GENMASK(31, 0) +#define CAP_CAPID_MASK GENMASK(31, 24) +#define CAP_NEXT_CAP_MASK GENMASK(23, 12) /* Command Ring Element macros */ /* No operation command */ @@ -204,6 +208,13 @@ #define MHI_RSCTRE_DATA_DWORD1 cpu_to_le32(FIELD_PREP(GENMASK(23, 16), \ MHI_PKT_TYPE_COALESCING)) +#define MHI_CAP_ID_INTX 0x1 +#define MHI_CAP_ID_TIME_SYNC 0x2 +#define MHI_CAP_ID_BW_SCALE 0x3 +#define MHI_CAP_ID_TSC_TIME_SYNC 0x4 +#define MHI_CAP_ID_MAX_TRB_LEN 0x5 +#define MHI_CAP_ID_MAX 0x6 + enum mhi_pkt_type { MHI_PKT_TYPE_INVALID = 0x0, MHI_PKT_TYPE_NOOP_CMD = 0x1, diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c index fd3050889412d..7ca2fe48c9ac0 100644 --- a/drivers/bus/mhi/host/init.c +++ b/drivers/bus/mhi/host/init.c @@ -465,6 +465,38 @@ static int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl) return ret; } +static int mhi_find_capability(struct mhi_controller *mhi_cntrl, u32 capability) +{ + u32 val, cur_cap, next_offset, cur_offset; + int ret; + + /* Get the first supported capability offset */ + ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, MISCOFF, MISC_CAP_MASK, &cur_offset); + if (ret) + return 0; + + do { + if (cur_offset >= mhi_cntrl->reg_len) + return 0; + + ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, cur_offset, &val); + if (ret) + return 0; + + cur_cap = FIELD_GET(CAP_CAPID_MASK, val); + next_offset = FIELD_GET(CAP_NEXT_CAP_MASK, val); + if (cur_cap >= MHI_CAP_ID_MAX) + return 0; + + if (cur_cap == capability) + return cur_offset; + + cur_offset = next_offset; + } while (next_offset); + + return 0; +} + int mhi_init_mmio(struct mhi_controller *mhi_cntrl) { u32 val; From d634f3b4d6eb04c96ed2c9d023bf2ccb45cc0d96 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 19 Aug 2026 18:55:52 +0530 Subject: [PATCH 0349/1133] FROMLIST: PCI/bwctrl: Set host bridge OPP and optionally disable ASPM around link retraining PCIe host bridge controllers may need their operating point raised before retraining to a higher link speed so that hardware resources (e.g., RPMh votes on Qualcomm platforms) are available at the requested data rate. After retraining, the operating point must be updated to reflect the actual negotiated speed. Add pcie_set_opp() to look up an OPP on the host bridge parent device using a key of (per-lane frequency in kHz, LNKCTL2 Target Link Speed level). Keying by generation rather than total bandwidth lets OPP tables remain width-independent. In pcie_set_target_speed(), call pcie_set_opp() before retraining only when upscaling (speed_req > cur_bus_speed), since only raising the operating point requires pre-staging hardware. After retraining, call pcie_set_opp() unconditionally with the actual cur_bus_speed to settle the votes. Both calls are skipped for downstream ports of PCIe switches, as those are outside the host controller's scope. Some controllers also require ASPM to be disabled around link retraining. Add a disable_aspm_for_retrain flag to pci_host_bridge; when set, pcie_set_target_speed() saves the child device's ASPM state, disables all ASPM link states before retraining, and restores them afterward. Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Hariharan Sreedhar --- drivers/pci/pcie/bwctrl.c | 63 ++++++++++++++++++++++++++++++++++++++- include/linux/pci.h | 1 + 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pcie/bwctrl.c b/drivers/pci/pcie/bwctrl.c index d48021bfd8448..81d125b65bc01 100644 --- a/drivers/pci/pcie/bwctrl.c +++ b/drivers/pci/pcie/bwctrl.c @@ -28,9 +28,11 @@ #include #include #include +#include #include #include #include +#include #include "../pci.h" #include "portdrv.h" @@ -98,6 +100,38 @@ static int pcie_bwctrl_change_speed(struct pci_dev *port, u16 target_speed, bool return pcie_retrain_link(port, use_lt); } +static int pcie_set_opp(struct pci_dev *pdev, struct pci_host_bridge *host, + enum pci_bus_speed speed) +{ + struct device *dev = host->dev.parent; + struct dev_pm_opp_key key = {}; + int ret, freq_mbps, width; + unsigned long freq_kbps; + struct dev_pm_opp *opp; + u16 lnksta; + + pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta); + width = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta); + + freq_mbps = pcie_dev_speed_mbps(speed); + if (freq_mbps < 0) + return -EINVAL; + + freq_kbps = freq_mbps * KILO; + key.freq = freq_kbps; + key.level = pci_bus_speed2lnkctl2(speed); + key.bw = 0; + opp = dev_pm_opp_find_key_exact(dev, &key, true); + if (!IS_ERR(opp)) { + ret = dev_pm_opp_set_opp(dev, opp); + if (ret) + dev_err(dev, "Failed to set OPP for freq (%lu): %d\n", + freq_kbps * width, ret); + dev_pm_opp_put(opp); + } + return 0; +} + /** * pcie_set_target_speed - Set downstream Link Speed for PCIe Port * @port: PCIe Port @@ -118,9 +152,12 @@ static int pcie_bwctrl_change_speed(struct pci_dev *port, u16 target_speed, bool int pcie_set_target_speed(struct pci_dev *port, enum pci_bus_speed speed_req, bool use_lt) { + struct pci_host_bridge *host = pci_find_host_bridge(port->bus); + bool is_rootbus = pci_is_root_bus(port->bus); struct pci_bus *bus = port->subordinate; + struct pci_dev *child = NULL; + int aspm_state = 0, ret; u16 target_speed; - int ret; if (WARN_ON_ONCE(!pcie_valid_speed(speed_req))) return -EINVAL; @@ -130,6 +167,24 @@ int pcie_set_target_speed(struct pci_dev *port, enum pci_bus_speed speed_req, target_speed = pcie_bwctrl_select_speed(port, speed_req); + /* + * The host bridge driver may need to be scaled for targeted speed + * otherwise link might not come up at requested speed. + */ + if (is_rootbus && host && bus) { + /* Get function 0 of downstream device */ + list_for_each_entry(child, &bus->devices, bus_list) + if (PCI_FUNC(child->devfn) == 0) + break; + + if (child && host->disable_aspm_for_retrain) { + aspm_state = pcie_aspm_enabled(child); + pci_disable_link_state_locked(child, PCIE_LINK_STATE_ALL); + } + if (speed_req > bus->cur_bus_speed) + pcie_set_opp(port, host, speed_req); + } + scoped_guard(rwsem_read, &pcie_bwctrl_setspeed_rwsem) { struct pcie_bwctrl_data *data = port->link_bwctrl; @@ -154,6 +209,12 @@ int pcie_set_target_speed(struct pci_dev *port, enum pci_bus_speed speed_req, !list_empty(&bus->devices)) ret = -EAGAIN; + if (bus && is_rootbus && host) { + if (child && host->disable_aspm_for_retrain) + pci_force_enable_link_state(child, aspm_state); + pcie_set_opp(port, host, bus->cur_bus_speed); + } + return ret; } diff --git a/include/linux/pci.h b/include/linux/pci.h index 9cbcadd08f3d3..352079393edbc 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -673,6 +673,7 @@ struct pci_host_bridge { unsigned int msi_domain:1; /* Bridge wants MSI domain */ unsigned int broken_l1ss_resume:1; /* Resuming from L1SS during system suspend is broken */ + unsigned int disable_aspm_for_retrain:1; /* Disable ASPM before link retain */ /* Resource alignment requirements */ resource_size_t (*align_resource)(struct pci_dev *dev, From 7ebfe9999c974ee4d0c284836491d932f75617d0 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 19 Aug 2026 18:55:53 +0530 Subject: [PATCH 0350/1133] FROMLIST: PCI: Export pci_set_target_speed() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Export pci_set_target_speed() so that other kernel drivers can use it to change the PCIe data rate. Link: https://lore.kernel.org/all/20260819-bwscale-v5-0-6dea79786b37@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru Acked-by: Ilpo Järvinen Acked-by: Manivannan Sadhasivam Signed-off-by: Hariharan Sreedhar --- drivers/pci/pcie/bwctrl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/pcie/bwctrl.c b/drivers/pci/pcie/bwctrl.c index 81d125b65bc01..be6f6d1fe37a1 100644 --- a/drivers/pci/pcie/bwctrl.c +++ b/drivers/pci/pcie/bwctrl.c @@ -217,6 +217,7 @@ int pcie_set_target_speed(struct pci_dev *port, enum pci_bus_speed speed_req, return ret; } +EXPORT_SYMBOL_GPL(pcie_set_target_speed); static void pcie_bwnotif_enable(struct pcie_device *srv) { From f0e81055e28f3aa1bdc364569d439f55b4ab40f4 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 19 Aug 2026 18:55:54 +0530 Subject: [PATCH 0351/1133] FROMLIST: PCI: Add pci_lnkctl2_bus_speed() to convert lnkctl2speed to pci_bus_speed Add a exported function to convert lnkctl2speed to enum pci_bus_speed, so that other kernel drivers can use it. Link: https://lore.kernel.org/all/20260819-bwscale-v5-0-6dea79786b37@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Hariharan Sreedhar --- drivers/pci/pci.c | 15 +++++++++++++++ include/linux/pci.h | 1 + 2 files changed, 16 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7c6f2aba81443..1ab4094fe8772 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -6056,6 +6056,21 @@ int pcie_link_bandwidth_mbps(struct pci_dev *pdev) } EXPORT_SYMBOL(pcie_link_bandwidth_mbps); +/** + * pci_lnkctl2_bus_speed - convert Link Control 2 Target Link Speed to pci_bus_speed + * @speed: Target Link Speed (TLS) value from Link Control 2 register (0-4 for Gen1-Gen5) + * + * Convert the Target Link Speed (TLS) field value from the Link Control 2 register + * to the corresponding enum pci_bus_speed. + * + * Return: pci_bus_speed corresponding to the TLS value + */ +enum pci_bus_speed pci_lnkctl2_bus_speed(u32 speed) +{ + return pcie_link_speed[speed]; +} +EXPORT_SYMBOL(pci_lnkctl2_bus_speed); + /** * pcie_bandwidth_available - determine minimum link settings of a PCIe * device and its bandwidth limitation diff --git a/include/linux/pci.h b/include/linux/pci.h index 352079393edbc..d12875c95491c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1739,6 +1739,7 @@ int pci_cfg_space_size(struct pci_dev *dev); unsigned char pci_bus_max_busnr(struct pci_bus *bus); resource_size_t pcibios_window_alignment(struct pci_bus *bus, unsigned long type); +enum pci_bus_speed pci_lnkctl2_bus_speed(u32 speed); #define PCI_VGA_STATE_CHANGE_BRIDGE (1 << 0) #define PCI_VGA_STATE_CHANGE_DECODES (1 << 1) From 0f458865ecc2bc7b3904447bc4b3420052a878b9 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 19 Aug 2026 18:55:55 +0530 Subject: [PATCH 0352/1133] FROMLIST: bus: mhi: host: Add support for Bandwidth scale As per MHI spec v1.2, sec 14, MHI supports bandwidth scaling to reduce power consumption. MHI bandwidth scaling is advertised by devices that contain the bandwidth scaling capability registers. If enabled, the device aggregates bandwidth requirements and sends them to the host through dedicated mhi event ring. After the host performs the bandwidth switch, it sends an acknowledgment by ringing a doorbell. if the host supports bandwidth scaling events, then it must set BW_CFG.ENABLED bit, set BW_CFG.DB_CHAN_ID to the channel ID to the doorbell that will be used by the host to communicate the bandwidth scaling status and BW_CFG.ER_INDEX to the index for the event ring to which the device should send bandwidth scaling request in the bandwidth scaling capability register. As part of mmio init check if the bw scale capability is present or not, if present advertise host supports bw scale by setting all the required fields. MHI layer will only forward the bw scaling request to the controller driver since MHI doesn't have any idea about transport layer used by the controller, it is responsibility of the controller driver to do actual bw scaling and then pass status to the MHI. MHI will response back to the device based up on the status of the bw scale received. Add a new get_misc_doorbell() to get doorbell for misc capabilities to use the doorbell with mhi events like MHI BW scale etc. Use workqueue & mutex for the bw scale events as the pci_set_target_speed() which will called by the mhi controller driver can sleep. Link: https://lore.kernel.org/all/20260819-bwscale-v5-0-6dea79786b37@oss.qualcomm.com/ Co-developed-by: Qiang Yu Signed-off-by: Qiang Yu Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Hariharan Sreedhar --- drivers/bus/mhi/common.h | 13 ++++ drivers/bus/mhi/host/init.c | 94 ++++++++++++++++++++++++-- drivers/bus/mhi/host/internal.h | 5 ++ drivers/bus/mhi/host/main.c | 113 +++++++++++++++++++++++++++++++- drivers/bus/mhi/host/pm.c | 9 ++- drivers/bus/mhi/host/trace.h | 7 ++ include/linux/mhi.h | 12 ++++ 7 files changed, 247 insertions(+), 6 deletions(-) diff --git a/drivers/bus/mhi/common.h b/drivers/bus/mhi/common.h index 4c316f3d5a68b..267260901a411 100644 --- a/drivers/bus/mhi/common.h +++ b/drivers/bus/mhi/common.h @@ -215,6 +215,19 @@ #define MHI_CAP_ID_MAX_TRB_LEN 0x5 #define MHI_CAP_ID_MAX 0x6 +/* MHI Bandwidth scaling offsets */ +#define MHI_BW_SCALE_CFG_OFFSET 0x4 +#define MHI_BW_SCALE_CAP_ID (3) +#define MHI_BW_SCALE_DB_CHAN_ID GENMASK(31, 25) +#define MHI_BW_SCALE_ENABLED BIT(24) +#define MHI_BW_SCALE_ER_INDEX GENMASK(23, 19) + +#define MHI_TRE_GET_EV_BW_REQ_SEQ(tre) FIELD_GET(GENMASK(15, 8), (MHI_TRE_GET_DWORD(tre, 0))) + +#define MHI_BW_SCALE_RESULT(status, seq) (FIELD_PREP(GENMASK(11, 8), status) | \ + FIELD_PREP(GENMASK(7, 0), seq)) +#define MHI_BW_SCALE_NACK 0xF + enum mhi_pkt_type { MHI_PKT_TYPE_INVALID = 0x0, MHI_PKT_TYPE_NOOP_CMD = 0x1, diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c index 7ca2fe48c9ac0..77ee51ee86ebb 100644 --- a/drivers/bus/mhi/host/init.c +++ b/drivers/bus/mhi/host/init.c @@ -497,10 +497,66 @@ static int mhi_find_capability(struct mhi_controller *mhi_cntrl, u32 capability) return 0; } +static int mhi_get_er_index(struct mhi_controller *mhi_cntrl, + enum mhi_er_data_type type) +{ + struct mhi_event *mhi_event = mhi_cntrl->mhi_event; + int i; + + /* Find event ring for requested type */ + for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { + if (mhi_event->data_type == type) + return mhi_event->er_index; + } + + return -ENOENT; +} + +static int mhi_init_bw_scale(struct mhi_controller *mhi_cntrl, + int bw_scale_db) +{ + struct device *dev = &mhi_cntrl->mhi_dev->dev; + struct mhi_event *mhi_event; + u32 bw_cfg_offset, val; + int er_index, i; + + bw_cfg_offset = mhi_find_capability(mhi_cntrl, MHI_BW_SCALE_CAP_ID); + if (!bw_cfg_offset) + return 0; + + er_index = mhi_get_er_index(mhi_cntrl, MHI_ER_BW_SCALE); + if (er_index < 0) + return er_index; + + /* Initialize BW scale event ring resources */ + mhi_event = mhi_cntrl->mhi_event; + for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { + if (mhi_event->data_type == MHI_ER_BW_SCALE) { + INIT_WORK(&mhi_event->work, mhi_process_ev_work); + mutex_init(&mhi_event->mutex); + break; + } + } + + bw_cfg_offset += MHI_BW_SCALE_CFG_OFFSET; + + /* Advertise host support */ + val = FIELD_PREP(MHI_BW_SCALE_DB_CHAN_ID, bw_scale_db) | + FIELD_PREP(MHI_BW_SCALE_ER_INDEX, er_index) | + MHI_BW_SCALE_ENABLED; + + mhi_write_reg(mhi_cntrl, mhi_cntrl->regs, bw_cfg_offset, val); + + dev_dbg(dev, "Bandwidth scaling setup complete with event ring: %d\n", + er_index); + + return 0; +} + int mhi_init_mmio(struct mhi_controller *mhi_cntrl) { - u32 val; - int i, ret; + u32 val, chdb_offset; + int i, ret, doorbell = 0; struct mhi_chan *mhi_chan; struct mhi_event *mhi_event; void __iomem *base = mhi_cntrl->regs; @@ -581,6 +637,8 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl) return -ERANGE; } + chdb_offset = val; + /* Setup wake db */ mhi_cntrl->wake_db = base + val + (8 * MHI_DEV_WAKE_DB); mhi_cntrl->wake_set = false; @@ -634,6 +692,17 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl) return ret; } + if (mhi_cntrl->get_misc_doorbell) + doorbell = mhi_cntrl->get_misc_doorbell(mhi_cntrl, MHI_ER_BW_SCALE); + + if (doorbell > 0) { + ret = mhi_init_bw_scale(mhi_cntrl, doorbell); + if (!ret) + mhi_cntrl->bw_scale_db = base + chdb_offset + (8 * doorbell); + else + dev_warn(dev, "Failed to setup bandwidth scaling: %d\n", ret); + } + return 0; } @@ -778,6 +847,9 @@ static int parse_ev_cfg(struct mhi_controller *mhi_cntrl, case MHI_ER_CTRL: mhi_event->process_event = mhi_process_ctrl_ev_ring; break; + case MHI_ER_BW_SCALE: + mhi_event->process_event = mhi_process_bw_scale_ev_ring; + break; default: dev_err(dev, "Event Ring type not supported\n"); goto error_ev_cfg; @@ -1001,12 +1073,15 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl, mhi_event->mhi_cntrl = mhi_cntrl; spin_lock_init(&mhi_event->lock); - if (mhi_event->data_type == MHI_ER_CTRL) + if (mhi_event->data_type == MHI_ER_CTRL) { tasklet_init(&mhi_event->task, mhi_ctrl_ev_task, (ulong)mhi_event); - else + } else if (mhi_event->data_type == MHI_ER_BW_SCALE) { + /* BW scale resources will be initialized in mhi_init_mmio() if capability exists */ + } else { tasklet_init(&mhi_event->task, mhi_ev_task, (ulong)mhi_event); + } } mhi_chan = mhi_cntrl->mhi_chan; @@ -1094,6 +1169,7 @@ void mhi_unregister_controller(struct mhi_controller *mhi_cntrl) { struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; struct mhi_chan *mhi_chan = mhi_cntrl->mhi_chan; + struct mhi_event *mhi_event; unsigned int i; mhi_deinit_free_irq(mhi_cntrl); @@ -1103,6 +1179,16 @@ void mhi_unregister_controller(struct mhi_controller *mhi_cntrl) sysfs_remove_file(&mhi_dev->dev.kobj, &dev_attr_trigger_edl.attr); destroy_workqueue(mhi_cntrl->hiprio_wq); + + /* Clean up BW scale resources */ + mhi_event = mhi_cntrl->mhi_event; + for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { + if (mhi_event->data_type == MHI_ER_BW_SCALE) { + cancel_work_sync(&mhi_event->work); + mutex_destroy(&mhi_event->mutex); + } + } + kfree(mhi_cntrl->mhi_cmd); kfree(mhi_cntrl->mhi_event); diff --git a/drivers/bus/mhi/host/internal.h b/drivers/bus/mhi/host/internal.h index 7b0ee5e3a12dd..85f778478765d 100644 --- a/drivers/bus/mhi/host/internal.h +++ b/drivers/bus/mhi/host/internal.h @@ -250,6 +250,8 @@ struct mhi_event { struct mhi_ring ring; struct db_cfg db_cfg; struct tasklet_struct task; + struct work_struct work; + struct mutex mutex; /* serializes bw_scale event processing */ spinlock_t lock; int (*process_event)(struct mhi_controller *mhi_cntrl, struct mhi_event *mhi_event, @@ -403,6 +405,8 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl, int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl, struct mhi_event *mhi_event, u32 event_quota); void mhi_uevent_notify(struct mhi_controller *mhi_cntrl, enum mhi_ee_type ee); +int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl, + struct mhi_event *mhi_event, u32 event_quota); /* ISR handlers */ irqreturn_t mhi_irq_handler(int irq_number, void *dev); @@ -419,5 +423,6 @@ void mhi_unmap_single_no_bb(struct mhi_controller *mhi_cntrl, struct mhi_buf_info *buf_info); void mhi_unmap_single_use_bb(struct mhi_controller *mhi_cntrl, struct mhi_buf_info *buf_info); +void mhi_process_ev_work(struct work_struct *work); #endif /* _MHI_INT_H */ diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c index 4d458396233ab..0fbbd9b258d6b 100644 --- a/drivers/bus/mhi/host/main.c +++ b/drivers/bus/mhi/host/main.c @@ -478,7 +478,10 @@ irqreturn_t mhi_irq_handler(int irq_number, void *dev) if (mhi_dev) mhi_notify(mhi_dev, MHI_CB_PENDING_DATA); } else { - tasklet_schedule(&mhi_event->task); + if (mhi_event->data_type == MHI_ER_BW_SCALE) + queue_work(mhi_cntrl->hiprio_wq, &mhi_event->work); + else + tasklet_schedule(&mhi_event->task); } return IRQ_HANDLED; @@ -1049,6 +1052,114 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl, return count; } +int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl, + struct mhi_event *mhi_event, u32 event_quota) +{ + struct mhi_event_ctxt *er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index]; + struct device *dev = &mhi_cntrl->mhi_dev->dev; + struct mhi_ring *ev_ring = &mhi_event->ring; + dma_addr_t ptr = le64_to_cpu(er_ctxt->rp); + u32 response = MHI_BW_SCALE_NACK; + struct mhi_ring_element *dev_rp; + struct mhi_link_info link_info; + bool dev_wake_held = false; + int ret = 0; + + if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state))) + return -EIO; + + if (!MHI_IN_MISSION_MODE(mhi_cntrl->ee)) + return -EINVAL; + + if (!is_valid_ring_ptr(ev_ring, ptr)) { + dev_err(dev, + "Event ring rp points outside of the event ring\n"); + return -EIO; + } + + dev_rp = mhi_to_virtual(ev_ring, ptr); + if (ev_ring->rp == dev_rp) + return 0; + + /* If rp points to base, we need to wrap it around */ + if (dev_rp == ev_ring->base) + dev_rp = ev_ring->base + ev_ring->len; + dev_rp--; + + /* Fast forward to currently processed element and recycle er */ + ev_ring->rp = dev_rp; + ev_ring->wp = dev_rp - 1; + if (ev_ring->wp < ev_ring->base) + ev_ring->wp = ev_ring->base + ev_ring->len - ev_ring->el_size; + mhi_recycle_ev_ring_element(mhi_cntrl, ev_ring); + + if (WARN_ON(MHI_TRE_GET_EV_TYPE(dev_rp) != MHI_PKT_TYPE_BW_REQ_EVENT)) { + dev_err(dev, "Unexpected event type for BW scale event ring\n"); + return -EINVAL; + } + + trace_mhi_bw_scale_event(mhi_cntrl, dev_rp); + + link_info.target_link_speed = MHI_TRE_GET_EV_LINKSPEED(dev_rp); + link_info.target_link_width = MHI_TRE_GET_EV_LINKWIDTH(dev_rp); + link_info.sequence_num = MHI_TRE_GET_EV_BW_REQ_SEQ(dev_rp); + + dev_dbg(dev, "Received BW_REQ with seq:%d link speed:0x%x width:0x%x\n", + link_info.sequence_num, + link_info.target_link_speed, + link_info.target_link_width); + + read_lock_bh(&mhi_cntrl->pm_lock); + if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl))) + mhi_ring_er_db(mhi_event); + read_unlock_bh(&mhi_cntrl->pm_lock); + + /* Bring host and device out of suspended states */ + ret = mhi_device_get_sync(mhi_cntrl->mhi_dev); + if (ret) + goto send_bw_scale_resp; + + mhi_cntrl->runtime_get(mhi_cntrl); + dev_wake_held = true; + + ret = mhi_cntrl->bw_scale(mhi_cntrl, &link_info); + if (!ret) + response = 0; + +send_bw_scale_resp: + response = MHI_BW_SCALE_RESULT(response, link_info.sequence_num); + + if (ret) + dev_err(dev, "BW_REQ seq:%d speed:0x%x width:0x%x NACKed, err:%d\n", + link_info.sequence_num, link_info.target_link_speed, + link_info.target_link_width, ret); + + write_lock_bh(&mhi_cntrl->pm_lock); + mhi_write_reg(mhi_cntrl, mhi_cntrl->bw_scale_db, 0, response); + write_unlock_bh(&mhi_cntrl->pm_lock); + + if (dev_wake_held) { + mhi_cntrl->runtime_put(mhi_cntrl); + mhi_device_put(mhi_cntrl->mhi_dev); + } + + return ret; +} + +void mhi_process_ev_work(struct work_struct *work) +{ + struct mhi_event *mhi_event = container_of(work, struct mhi_event, + work); + + struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl; + + if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state))) + return; + + guard(mutex)(&mhi_event->mutex); + mhi_event->process_event(mhi_cntrl, mhi_event, U32_MAX); +} + void mhi_ev_task(unsigned long data) { struct mhi_event *mhi_event = (struct mhi_event *)data; diff --git a/drivers/bus/mhi/host/pm.c b/drivers/bus/mhi/host/pm.c index ced83fbb1a51d..19143aa42f3bd 100644 --- a/drivers/bus/mhi/host/pm.c +++ b/drivers/bus/mhi/host/pm.c @@ -525,6 +525,10 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, continue; disable_irq(mhi_cntrl->irq[mhi_event->irq]); tasklet_kill(&mhi_event->task); + if (mhi_event->data_type == MHI_ER_BW_SCALE) + cancel_work_sync(&mhi_event->work); + else + tasklet_kill(&mhi_event->task); } /* Release lock and wait for all pending threads to complete */ @@ -681,7 +685,10 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl) for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { if (mhi_event->offload_ev) continue; - tasklet_kill(&mhi_event->task); + if (mhi_event->data_type == MHI_ER_BW_SCALE) + cancel_work_sync(&mhi_event->work); + else + tasklet_kill(&mhi_event->task); } /* Release lock and wait for all pending threads to complete */ diff --git a/drivers/bus/mhi/host/trace.h b/drivers/bus/mhi/host/trace.h index 3e0c41777429e..f7cc3470bcdb3 100644 --- a/drivers/bus/mhi/host/trace.h +++ b/drivers/bus/mhi/host/trace.h @@ -212,6 +212,13 @@ DEFINE_EVENT(mhi_process_event_ring, mhi_ctrl_event, TP_ARGS(mhi_cntrl, rp) ); +DEFINE_EVENT(mhi_process_event_ring, mhi_bw_scale_event, + + TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_ring_element *rp), + + TP_ARGS(mhi_cntrl, rp) +); + DECLARE_EVENT_CLASS(mhi_update_channel_state, TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, int state, diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 65e8a397cc50b..71fa5fdaacb3b 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -119,10 +119,12 @@ struct image_info { * struct mhi_link_info - BW requirement * @target_link_speed: Link speed as defined by TLS bits in LinkControl reg * @target_link_width: Link width as defined by NLW bits in LinkStatus reg + * sequence_num - used by device to track bw requests sent to host */ struct mhi_link_info { unsigned int target_link_speed; unsigned int target_link_width; + int sequence_num; }; /** @@ -201,10 +203,12 @@ enum mhi_ch_ee_mask { * enum mhi_er_data_type - Event ring data types * @MHI_ER_DATA: Only client data over this ring * @MHI_ER_CTRL: MHI control data and client data + * @MHI_ER_BW_SCALE: MHI controller bandwidth scale functionality */ enum mhi_er_data_type { MHI_ER_DATA, MHI_ER_CTRL, + MHI_ER_BW_SCALE, }; /** @@ -315,6 +319,7 @@ struct mhi_controller_config { * @bhi: Points to base of MHI BHI register space * @bhie: Points to base of MHI BHIe register space * @wake_db: MHI WAKE doorbell register address + * @bw_scale_db: MHI BW_SCALE doorbell register address * @iova_start: IOMMU starting address for data (required) * @iova_stop: IOMMU stop address for data (required) * @fw_image: Firmware image name for normal booting (optional) @@ -373,6 +378,8 @@ struct mhi_controller_config { * @write_reg: Write a MHI register via the physical link (required) * @reset: Controller specific reset function (optional) * @edl_trigger: CB function to trigger EDL mode (optional) + * @get_misc_doobell: function to get doorbell used for MISC feature like BW scale etc (optional) + * @bw_scale: CB function for passing BW scale info (optional) * @buffer_len: Bounce buffer length * @index: Index of the MHI controller instance * @bounce_buf: Use of bounce buffer @@ -395,6 +402,7 @@ struct mhi_controller { void __iomem *bhi; void __iomem *bhie; void __iomem *wake_db; + void __iomem *bw_scale_db; dma_addr_t iova_start; dma_addr_t iova_stop; @@ -458,6 +466,10 @@ struct mhi_controller { u32 val); void (*reset)(struct mhi_controller *mhi_cntrl); int (*edl_trigger)(struct mhi_controller *mhi_cntrl); + int (*get_misc_doorbell)(struct mhi_controller *mhi_cntrl, + enum mhi_er_data_type type); + int (*bw_scale)(struct mhi_controller *mhi_cntrl, + struct mhi_link_info *link_info); size_t buffer_len; int index; From abe6dee5f933e8c2a6bc0c62475a2ceef9909da0 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Wed, 19 Aug 2026 18:55:56 +0530 Subject: [PATCH 0353/1133] FROMLIST: wifi: ath11k: Add support for MHI bandwidth scaling Add support for MHI bandwidth scaling, which will reduce power consumption if WLAN operates with lower bandwidth. This feature is only enabled for QCA6390. Bandwidth scaling is initiated by the endpoint firmware based upon the bandwidth requirements, if there is high bandwidth data endpoint requests for higher data rates or if there is less bandwidth they request for lower data rates to reduce power. Endpoint initiates this through MHI protocol. Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04546-QCAHSPSWPL_V1_V2_SILICONZ_IOE-1 Link: https://lore.kernel.org/all/20260819-bwscale-v5-0-6dea79786b37@oss.qualcomm.com/ Signed-off-by: Miaoqing Pan Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Hariharan Sreedhar --- drivers/net/wireless/ath/ath11k/mhi.c | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c index a6c9ff112c68f..9bff4c4bca3b3 100644 --- a/drivers/net/wireless/ath/ath11k/mhi.c +++ b/drivers/net/wireless/ath/ath11k/mhi.c @@ -20,6 +20,7 @@ #define MHI_TIMEOUT_DEFAULT_MS 20000 #define RDDM_DUMP_SIZE 0x420000 #define MHI_CB_INVALID 0xff +#define MHI_BW_SCALE_CHAN_DB 126 static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = { { @@ -71,6 +72,17 @@ static struct mhi_event_config ath11k_mhi_events_qca6390[] = { .client_managed = false, .offload_channel = false, }, + { + .num_elements = 8, + .irq_moderation_ms = 0, + .irq = 1, + .mode = MHI_DB_BRST_DISABLE, + .data_type = MHI_ER_BW_SCALE, + .priority = 2, + .hardware_event = false, + .client_managed = false, + .offload_channel = false, + }, }; static const struct mhi_controller_config ath11k_mhi_config_qca6390 = { @@ -311,6 +323,30 @@ static void ath11k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl, writel(val, addr); } +static int ath11k_mhi_op_get_misc_doorbell(struct mhi_controller *mhi_cntrl, + enum mhi_er_data_type type) +{ + if (type == MHI_ER_BW_SCALE) + return MHI_BW_SCALE_CHAN_DB; + + return -EOPNOTSUPP; +} + +static int ath11k_mhi_op_bw_scale(struct mhi_controller *mhi_cntrl, + struct mhi_link_info *link_info) +{ + enum pci_bus_speed speed = pci_lnkctl2_bus_speed(link_info->target_link_speed); + struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev); + struct pci_dev *pci_dev = to_pci_dev(ab->dev); + struct pci_dev *pdev; + + pdev = pci_upstream_bridge(pci_dev); + if (!pdev) + return -ENODEV; + + return pcie_set_target_speed(pdev, speed, true); +} + static int ath11k_mhi_read_addr_from_dt(struct mhi_controller *mhi_ctrl) { struct device_node *np; @@ -387,6 +423,8 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci) mhi_ctrl->status_cb = ath11k_mhi_op_status_cb; mhi_ctrl->read_reg = ath11k_mhi_op_read_reg; mhi_ctrl->write_reg = ath11k_mhi_op_write_reg; + mhi_ctrl->bw_scale = ath11k_mhi_op_bw_scale; + mhi_ctrl->get_misc_doorbell = ath11k_mhi_op_get_misc_doorbell; switch (ab->hw_rev) { case ATH11K_HW_QCN9074_HW10: From 316efbe38371ea621f2f4bf46855f04f9298ed81 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 19 Aug 2026 18:55:57 +0530 Subject: [PATCH 0354/1133] FROMLIST: PCI: qcom: Enable ASPM disabling during link retraining Set the disable_aspm_for_retrain flag in qcom_pcie_host_init() to ensure ASPM is disabled during link retraining operations. This prevents potential issues with link state transitions during bandwidth scaling on Qualcomm PCIe controllers. Link: https://lore.kernel.org/all/20260819-bwscale-v5-0-6dea79786b37@oss.qualcomm.com/ Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Hariharan Sreedhar --- drivers/pci/controller/dwc/pcie-qcom.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 503cd356e6cca..a6f63ce233717 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -1514,6 +1514,8 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp) qcom_pcie_perst_deassert(pcie); + pp->bridge->disable_aspm_for_retrain = true; + if (pcie->cfg->ops->config_sid) { ret = pcie->cfg->ops->config_sid(pcie); if (ret) From e304ec9070a72f24075d53c79bc02fda5d691cd0 Mon Sep 17 00:00:00 2001 From: Hariharan Sreedhar Date: Tue, 6 Oct 2026 17:58:05 +0530 Subject: [PATCH 0355/1133] FROMLIST: wifi: ath12k: Add support for MHI bandwidth scaling Add support for MHI bandwidth scaling, which will reduce power consumption if WLAN operates with lower bandwidth. Bandwidth scaling is initiated by the endpoint firmware based upon the bandwidth requirements, if there is high bandwidth data endpoint requests for higher data rates or if there is less bandwidth they request for lower data rates to reduce power. Endpoint initiates this through MHI protocol Link: https://lore.kernel.org/all/20260819-bwscale-v5-0-6dea79786b37@oss.qualcomm.com/ Signed-off-by: Hariharan Sreedhar --- drivers/net/wireless/ath/ath12k/mhi.c | 27 +++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wifi7/mhi.c | 11 +++++++++ 2 files changed, 38 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c index ee87f00bc5de9..b977ed5c4211e 100644 --- a/drivers/net/wireless/ath/ath12k/mhi.c +++ b/drivers/net/wireless/ath/ath12k/mhi.c @@ -17,6 +17,7 @@ #define OTP_INVALID_BOARD_ID 0xFFFF #define OTP_VALID_DUALMAC_BOARD_ID_MASK 0x1000 #define MHI_CB_INVALID 0xff +#define MHI_BW_SCALE_CHAN_DB 126 void ath12k_mhi_set_mhictrl_reset(struct ath12k_base *ab) { @@ -184,6 +185,30 @@ static void ath12k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl, writel(val, addr); } +static int ath12k_mhi_op_get_misc_doorbell(struct mhi_controller *mhi_cntrl, + enum mhi_er_data_type type) +{ + if (type == MHI_ER_BW_SCALE) + return MHI_BW_SCALE_CHAN_DB; + + return -EOPNOTSUPP; +} + +static int ath12k_mhi_op_bw_scale(struct mhi_controller *mhi_cntrl, + struct mhi_link_info *link_info) +{ + enum pci_bus_speed speed = pci_lnkctl2_bus_speed(link_info->target_link_speed); + struct ath12k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev); + struct pci_dev *pci_dev = to_pci_dev(ab->dev); + struct pci_dev *pdev; + + pdev = pci_upstream_bridge(pci_dev); + if (!pdev) + return -ENODEV; + + return pcie_set_target_speed(pdev, speed, true); +} + int ath12k_mhi_register(struct ath12k_pci *ab_pci) { struct ath12k_base *ab = ab_pci->ab; @@ -261,6 +286,8 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci) mhi_ctrl->status_cb = ath12k_mhi_op_status_cb; mhi_ctrl->read_reg = ath12k_mhi_op_read_reg; mhi_ctrl->write_reg = ath12k_mhi_op_write_reg; + mhi_ctrl->bw_scale = ath12k_mhi_op_bw_scale; + mhi_ctrl->get_misc_doorbell = ath12k_mhi_op_get_misc_doorbell; ret = mhi_register_controller(mhi_ctrl, ab->hw_params->mhi_config); if (ret) { diff --git a/drivers/net/wireless/ath/ath12k/wifi7/mhi.c b/drivers/net/wireless/ath/ath12k/wifi7/mhi.c index 988affafcfd1b..7d915c1399a16 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/mhi.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/mhi.c @@ -120,6 +120,17 @@ static struct mhi_event_config ath12k_wifi7_mhi_events_wcn7850[] = { .client_managed = false, .offload_channel = false, }, + { + .num_elements = 8, + .irq_moderation_ms = 0, + .irq = 1, + .mode = MHI_DB_BRST_DISABLE, + .data_type = MHI_ER_BW_SCALE, + .priority = 2, + .hardware_event = false, + .client_managed = false, + .offload_channel = false, + } }; const struct mhi_controller_config ath12k_wifi7_mhi_config_wcn7850 = { From ba9248f548ab15cdbc441a5a8a0d9887affff25e Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Fri, 9 Oct 2026 18:25:27 +0530 Subject: [PATCH 0356/1133] FROMLIST: PCI: qcom: Disable halting feature The PARF write, read and BDF halt features make the controller wait for earlier AXI transactions to complete before issuing new ones. This is needed on SoCs whose NoC cannot preserve the ordering of inbound transactions from the controller. On newer SoCs, the NoC preserves this ordering on its own. Halting at the controller adds no correctness benefit and reduces inbound DMA bandwidth. Add a noc_ensures_ordering flag to struct qcom_pcie_cfg. Clear all three halt features on SoCs that set it. Other SoCs keep enabling write halt as before. Link: https://patch.msgid.link/20261009-halt-v1-1-4a2d7899d91f@oss.qualcomm.com Signed-off-by: Krishna Chaitanya Chundru --- drivers/pci/controller/dwc/pcie-qcom.c | 37 +++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index a6f63ce233717..68f888917ee46 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -54,6 +54,7 @@ #define PARF_SLV_ADDR_SPACE_SIZE 0x16c #define PARF_MHI_CLOCK_RESET_CTRL 0x174 #define PARF_AXI_MSTR_WR_ADDR_HALT 0x178 +#define PARF_AXI_MSTR_RD_HALT_NO_WRITES 0x1a4 #define PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1a8 #define PARF_Q2A_FLUSH 0x1ac #define PARF_LTSSM 0x1b0 @@ -68,6 +69,7 @@ #define PARF_SLV_ADDR_SPACE_SIZE_V2 0x358 #define PARF_SLV_ADDR_SPACE_SIZE_V2_HI 0x35c #define PARF_NO_SNOOP_OVERRIDE 0x3d4 +#define PARF_AXI_MSTR_WR_NS_BDF_HALT 0x4a0 #define PARF_ATU_BASE_ADDR 0x634 #define PARF_ATU_BASE_ADDR_HI 0x638 #define PARF_DEVICE_TYPE 0x1000 @@ -153,6 +155,9 @@ /* PARF_AXI_MSTR_WR_ADDR_HALT register fields */ #define EN BIT(31) +/* PARF_AXI_MSTR_RD_HALT_NO_WRITES */ +#define RD_HALT_NO_WRITES_EN BIT(0) + /* PARF_LTSSM register fields */ #define LTSSM_EN BIT(8) #define PARF_LTSSM_STATE_MASK GENMASK(5, 0) @@ -168,6 +173,9 @@ #define WR_NO_SNOOP_OVERRIDE_EN BIT(1) #define RD_NO_SNOOP_OVERRIDE_EN BIT(3) +/* PARF_AXI_MSTR_WR_NS_BDF_HALT */ +#define BDF_CHANGE_HALT_EN BIT(0) + /* PARF_DEVICE_TYPE register fields */ #define DEVICE_TYPE_RC 0x4 @@ -294,12 +302,16 @@ struct qcom_pcie_ops { * @override_no_snoop: Override NO_SNOOP attribute in TLP to enable cache * snooping * @firmware_managed: Set if the Root Complex is firmware managed + * @no_l0s: Set if the Root Complex does not support L0s + * @noc_ensures_ordering: Set if the NoC preserves the ordering of inbound + * transactions from the controller. */ struct qcom_pcie_cfg { const struct qcom_pcie_ops *ops; bool override_no_snoop; bool firmware_managed; bool no_l0s; + bool noc_ensures_ordering; }; struct qcom_pcie_perst { @@ -1122,9 +1134,23 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie) pci->l1ss_support = true; - val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); - val |= EN; - writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + if (pcie->cfg->noc_ensures_ordering) { + val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + val &= ~EN; + writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + + val = readl(pcie->parf + PARF_AXI_MSTR_RD_HALT_NO_WRITES); + val &= ~RD_HALT_NO_WRITES_EN; + writel(val, pcie->parf + PARF_AXI_MSTR_RD_HALT_NO_WRITES); + + val = readl(pcie->parf + PARF_AXI_MSTR_WR_NS_BDF_HALT); + val &= ~BDF_CHANGE_HALT_EN; + writel(val, pcie->parf + PARF_AXI_MSTR_WR_NS_BDF_HALT); + } else { + val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + val |= EN; + writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + } return 0; err_disable_clocks: @@ -1689,12 +1715,14 @@ static const struct qcom_pcie_cfg cfg_1_0_0 = { static const struct qcom_pcie_cfg cfg_1_9_0 = { .ops = &ops_1_9_0, + .noc_ensures_ordering = true, }; static const struct qcom_pcie_cfg cfg_1_34_0 = { .ops = &ops_1_9_0, .override_no_snoop = true, .no_l0s = true, + .noc_ensures_ordering = true, }; static const struct qcom_pcie_cfg cfg_2_1_0 = { @@ -1716,15 +1744,18 @@ static const struct qcom_pcie_cfg cfg_2_4_0 = { static const struct qcom_pcie_cfg cfg_2_7_0 = { .ops = &ops_2_7_0, + .noc_ensures_ordering = true, }; static const struct qcom_pcie_cfg cfg_2_9_0 = { .ops = &ops_2_9_0, + .noc_ensures_ordering = true, }; static const struct qcom_pcie_cfg cfg_sc8280xp = { .ops = &ops_1_21_0, .no_l0s = true, + .noc_ensures_ordering = true, }; static const struct qcom_pcie_cfg cfg_fw_managed = { From 7a54598f1752ff986854aba02218d536c36c6d11 Mon Sep 17 00:00:00 2001 From: Liao Xuan Date: Thu, 24 Sep 2026 14:15:11 +0800 Subject: [PATCH 0357/1133] FROMLIST: nvme: Add adaptive PCIe link rate switching function Add support for dynamically adjusting the PCIe link rate of NVMe devices based on I/O activity. The link is downgraded to a configurable minimum rate during periods of low activity to save power, and upgraded to the maximum supported rate as soon as the workload exceeds a computed threshold, so that peak performance is maintained under load. The amount of transferred data is accumulated on the I/O submission path and aggregated by a per-controller timer. The threshold is derived from the bandwidth of the minimum and maximum rates such that the extra time required to transfer the data at the minimum rate does not exceed the estimated link retraining time. The feature is currently only supported on Hygon platforms. Four NVMe devices were tested on the link with this patch. The power benefit was measured by sampling the voltage and current of the power monitor every 1 second, each run lasted 3 minutes and the test was repeated 5 times. Test run Power Benefit(w) 1 5.3236 2 5.2285 3 5.4176 4 5.4538 5 5.3444 Average 5.3536 The adaptive link rate switching saves about 5.3w of system power on average. The feature was tested with Gen1 as the minimum link rate. The workload runs 10 seconds of random read followed by 0.5 seconds of idle, repeated 100 times. Avg IOPS (k) Avg BW (GiB/s) Avg clat (us) With speed switching 2671.2 10.19 378.1 Without speed switching 2681.5 10.23 377.0 The differences are within measurement noise (< 0.5%), which shows that the adaptive link rate switching does not degrade the baseline performance and keeps the I/O stable. In summary, the adaptive link rate switching keeps the I/O performance essentially unchanged (the differences in IOPS, bandwidth and latency are all within 0.5% measurement noise) while saving about 5w of system power, providing an effective way to reduce the platform power consumption under light I/O without sacrificing throughput or latency. Signed-off-by: Liao Xuan Signed-off-by: Zheng Tan Link: https://patch.msgid.link/9e99e007bf05a608b1b82da740c2b33935a27175.1790222172.git.liaoxuan@hygon.cn Signed-off-by: Hariharan Sreedhar --- drivers/nvme/host/Kconfig | 10 + drivers/nvme/host/Makefile | 1 + drivers/nvme/host/core.c | 4 + drivers/nvme/host/nvme.h | 42 ++++ drivers/nvme/host/pci.c | 4 + drivers/nvme/host/speed_switch.c | 365 +++++++++++++++++++++++++++++++ 6 files changed, 426 insertions(+) create mode 100644 drivers/nvme/host/speed_switch.c diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig index 31974c7dd20c9..ef03494eb601d 100644 --- a/drivers/nvme/host/Kconfig +++ b/drivers/nvme/host/Kconfig @@ -134,3 +134,13 @@ config NVME_APPLE To compile this driver as a module, choose M here: the module will be called nvme-apple. + +config NVME_SPEED_SWITCH + bool "NVMe adaptive PCIe link rate switching" + depends on BLK_DEV_NVME + help + This provides support for dynamic PCIe link rate switching for NVMe + devices. When enabled, the NVMe driver can dynamically adjust the + PCIe link speed and width based on workload requirement. + + If unsure, say N. diff --git a/drivers/nvme/host/Makefile b/drivers/nvme/host/Makefile index 8288b986d7131..3f2a0fe068ef9 100644 --- a/drivers/nvme/host/Makefile +++ b/drivers/nvme/host/Makefile @@ -19,6 +19,7 @@ nvme-core-$(CONFIG_BLK_DEV_ZONED) += zns.o nvme-core-$(CONFIG_FAULT_INJECTION_DEBUG_FS) += fault_inject.o nvme-core-$(CONFIG_NVME_HWMON) += hwmon.o nvme-core-$(CONFIG_NVME_HOST_AUTH) += auth.o +nvme-core-$(CONFIG_NVME_SPEED_SWITCH) += speed_switch.o nvme-y += pci.o nvme-$(CONFIG_DMA_SHARED_BUFFER) += pci-dmabuf.o diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index a7a4d09644c13..b097564bcc43e 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -4714,6 +4714,7 @@ static void nvme_scan_work(struct work_struct *work) /* Re-read the ANA log page to not miss updates */ queue_work(nvme_wq, &ctrl->ana_work); #endif + nvme_speed_switch_start(ctrl); } /* @@ -5138,6 +5139,7 @@ EXPORT_SYMBOL_GPL(nvme_remove_io_tag_set); void nvme_stop_ctrl(struct nvme_ctrl *ctrl) { + nvme_speed_switch_exit(ctrl); nvme_mpath_stop(ctrl); nvme_auth_stop(ctrl); nvme_stop_failfast_work(ctrl); @@ -5338,6 +5340,8 @@ int nvme_add_ctrl(struct nvme_ctrl *ctrl) nvme_fault_inject_init(&ctrl->fault_inject, dev_name(ctrl->device)); nvme_get_ctrl(ctrl); + nvme_speed_switch_init(ctrl); + return 0; } EXPORT_SYMBOL_GPL(nvme_add_ctrl); diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 2d8f681079e85..2ac9dddc0d48a 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -339,6 +339,33 @@ enum nvme_ctrl_flags { NVME_CTRL_FROZEN = 6, }; +#ifdef CONFIG_NVME_SPEED_SWITCH +struct nvme_speed_switch_stats { + u64 read_bytes; + u64 write_bytes; +}; + +struct nvme_speed_switch { + bool initialized; + bool enabled; + u8 max_speed; + u8 cur_speed; + u8 target_speed; + u8 min_speed; + u32 monitor_interval; /* ms */ + u32 threshold; /* KB */ + struct timer_list timer; + struct work_struct work; + struct nvme_speed_switch_stats __percpu *stats; + atomic_t timer_active; +}; + +enum nvme_speed_timer_state { + NVME_SPEED_TIMER_INACTIVE, + NVME_SPEED_TIMER_ACTIVE, +}; +#endif + struct nvme_ctrl { bool comp_seen; bool identified; @@ -480,8 +507,23 @@ struct nvme_ctrl { enum nvme_dctype dctype; u16 awupf; /* 0's based value. */ +#ifdef CONFIG_NVME_SPEED_SWITCH + struct nvme_speed_switch speed_switch; +#endif }; +#ifdef CONFIG_NVME_SPEED_SWITCH +void nvme_update_io_stats(struct nvme_ctrl *ctrl, struct request *req); +void nvme_speed_switch_start(struct nvme_ctrl *ctrl); +void nvme_speed_switch_init(struct nvme_ctrl *ctrl); +void nvme_speed_switch_exit(struct nvme_ctrl *ctrl); +#else +static inline void nvme_update_io_stats(struct nvme_ctrl *ctrl, struct request *req) {} +static inline void nvme_speed_switch_start(struct nvme_ctrl *ctrl) {} +static inline void nvme_speed_switch_init(struct nvme_ctrl *ctrl) {} +static inline void nvme_speed_switch_exit(struct nvme_ctrl *ctrl) {} +#endif + static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl) { return READ_ONCE(ctrl->state); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 019a1e3cc0a2d..67a9960289eee 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1682,6 +1682,9 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx, ret = nvme_prep_rq(req); if (unlikely(ret)) return ret; + + nvme_update_io_stats(&dev->ctrl, req); + spin_lock(&nvmeq->sq_lock); nvme_sq_copy_cmd(nvmeq, &iod->cmd); nvme_write_sq_db(nvmeq, bd->last); @@ -1700,6 +1703,7 @@ static void nvme_submit_cmds(struct nvme_queue *nvmeq, struct rq_list *rqlist) while ((req = rq_list_pop(rqlist))) { struct nvme_iod *iod = blk_mq_rq_to_pdu(req); + nvme_update_io_stats(&nvmeq->dev->ctrl, req); nvme_sq_copy_cmd(nvmeq, &iod->cmd); } nvme_write_sq_db(nvmeq, true); diff --git a/drivers/nvme/host/speed_switch.c b/drivers/nvme/host/speed_switch.c new file mode 100644 index 0000000000000..ffee140ff8c81 --- /dev/null +++ b/drivers/nvme/host/speed_switch.c @@ -0,0 +1,365 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NVMe link speed switch driver + * + * Adjusts the PCIe link rate of NVMe devices dynamically based on the I/O + * workload: the link is downgraded to a configurable minimum rate during + * periods of low activity to save power, and upgraded to the maximum + * supported rate as soon as the workload requires it. + * + * Copyright (c) 2026 Hygon Information Technology Co., Ltd. + * Copyright (c) 2026 Kylin Software Co., Ltd. + * + */ + +#include +#include +#include +#include +#include + +#include "nvme.h" + +/* + * PCIe link bandwidth in KB/s for each generation (rows, Gen1..Gen5) and + * lane width (columns, x1..x16). The table is used to derive the I/O + * threshold exceed/below which the link can be upgraded/downgraded. + */ +static const u32 nvme_speed_table[][5] = { + { 312, 625, 1250, 2500, 5000 }, /* Gen1 */ + { 625, 1250, 2500, 5000, 10000 }, /* Gen2 */ + { 1000, 2000, 4000, 8000, 16000 }, /* Gen3 */ + { 2000, 4000, 8000, 16000, 32000 }, /* Gen4 */ + { 4000, 8000, 16000, 32000, 64000 },/* Gen5 */ +}; + +static int nvme_bandwidth_index(enum pcie_link_width width) +{ + switch (width) { + case PCIE_LNK_X1: + return 0; + case PCIE_LNK_X2: + return 1; + case PCIE_LNK_X4: + return 2; + case PCIE_LNK_X8: + return 3; + case PCIE_LNK_X16: + return 4; + default: + return -EINVAL; + } +} + +/* + * Read the maximum supported link rate of the upstream port from the Link + * Capability register. + */ +static int nvme_get_max_link_speed(struct pci_dev *pdev) +{ + u16 linkcap; + + pcie_capability_read_word(pdev, PCI_EXP_LNKCAP, &linkcap); + + return linkcap & PCI_EXP_LNKCAP_SLS; +} + +static enum pci_bus_speed nvme_speed_to_bus_speed(u8 gen) +{ + return gen + PCIE_SPEED_2_5GT - 1; +} + +/* + * Work item that actually changes the link rate. The queues are frozen + * before retraining to quiesce I/O and resumed once the switch completed. + */ +static void nvme_speed_switch_work(struct work_struct *work) +{ + struct nvme_speed_switch *sw = container_of(work, struct nvme_speed_switch, work); + struct nvme_ctrl *ctrl = container_of(sw, struct nvme_ctrl, speed_switch); + struct pci_dev *pdev = to_pci_dev(ctrl->dev); + struct pci_dev *bridge = pdev->bus->self; + u8 cur_speed = READ_ONCE(sw->cur_speed); + int ret; + + if (nvme_ctrl_state(ctrl) != NVME_CTRL_LIVE) + return; + + /* Freeze I/O to avoid timeouts during link retraining. */ + nvme_start_freeze(ctrl); + nvme_wait_freeze(ctrl); + + ret = pcie_set_target_speed(bridge, nvme_speed_to_bus_speed(sw->target_speed), + true); + if (ret) { + dev_warn(ctrl->device, + "failed to set target rate Gen%u (%d), trying rollback to Gen%u\n", + sw->target_speed, ret, cur_speed); + ret = pcie_set_target_speed(bridge, nvme_speed_to_bus_speed(cur_speed), + true); + if (ret) { + dev_err(ctrl->device, + "rollback to Gen%u failed (%d), disabling speed switch\n", + cur_speed, ret); + WRITE_ONCE(sw->enabled, false); + nvme_unfreeze(ctrl); + return; + } + } else { + WRITE_ONCE(sw->cur_speed, sw->target_speed); + } + + nvme_unfreeze(ctrl); + dev_dbg(ctrl->device, "link rate changed to Gen%u\n", + READ_ONCE(sw->cur_speed)); +} + +/* + * Compute the I/O threshold (in KB) for a monitoring window. + * + * The threshold is derived from the following constraint: for the link + * speed to be upgraded, the transfer time of the data at the minimum + * speed must be greater than the sum of the transfer time at maximum + * speed and the link retraining time (100us): + * + * data / min_bw >= data / max_bw + 100us + * + * which yields data <= min_bw * max_bw * 0.1ms / (max_bw - min_bw). + * The bandwidths are taken from the link capability of the upstream port + * and the link width capability of the device. + */ +static u32 nvme_calc_speed_threshold(struct nvme_speed_switch *sw, + enum pcie_link_width max_width) +{ + struct nvme_ctrl *ctrl = container_of(sw, struct nvme_ctrl, speed_switch); + int bw_idx, min_gen = sw->min_speed, max_gen = sw->max_speed; + u64 min_bw, max_bw, x, y; + u32 threshold; + + if (min_gen < 1 || min_gen > 5 || max_gen < 1 || max_gen > 5) { + dev_warn(ctrl->device, + "invalid link rate range for threshold: min=Gen%d, max=Gen%d\n", + min_gen, max_gen); + return 0; + } + + bw_idx = nvme_bandwidth_index(max_width); + if (bw_idx < 0) { + dev_warn(ctrl->device, + "unsupported link width (%d) for threshold calculation\n", + max_width); + return 0; + } + + min_bw = nvme_speed_table[min_gen - 1][bw_idx]; + max_bw = nvme_speed_table[max_gen - 1][bw_idx]; + if (min_bw >= max_bw) { + dev_warn(ctrl->device, + "invalid bandwidth for threshold: min=%llu KB/s, max=%llu KB/s\n", + min_bw, max_bw); + return 0; + } + + x = min_bw * max_bw; + y = 10ULL * (max_bw - min_bw); + threshold = div64_u64(x + (y >> 1), y); + + dev_dbg(ctrl->device, + "I/O threshold: %u KB (min=Gen%d, max=Gen%d, width=x%d)\n", + threshold, min_gen, max_gen, max_width); + + return threshold; +} + +/* Called on the I/O submission path to accumulate the transferred bytes. */ +void nvme_update_io_stats(struct nvme_ctrl *ctrl, struct request *req) +{ + struct nvme_speed_switch *sw = &ctrl->speed_switch; + struct nvme_speed_switch_stats *stat; + enum req_op op = req_op(req); + unsigned int bytes = blk_rq_bytes(req); + + if (!READ_ONCE(sw->enabled)) + return; + + if (op != REQ_OP_READ && op != REQ_OP_WRITE) + return; + + if (!sw->stats) { + dev_dbg(ctrl->device, "I/O statistics not allocated, skip accounting\n"); + return; + } + + stat = get_cpu_ptr(sw->stats); + if (op == REQ_OP_READ) + stat->read_bytes += bytes; + else + stat->write_bytes += bytes; + put_cpu_ptr(sw->stats); + + if (atomic_cmpxchg(&sw->timer_active, NVME_SPEED_TIMER_INACTIVE, + NVME_SPEED_TIMER_ACTIVE) != NVME_SPEED_TIMER_INACTIVE) + return; + + /* First I/O of the activity period: compute the threshold and arm the timer. */ + WRITE_ONCE(sw->threshold, nvme_calc_speed_threshold(sw, + pcie_get_width_cap(to_pci_dev(ctrl->dev)))); + if (!READ_ONCE(sw->threshold)) { + dev_warn(ctrl->device, + "failed to compute speed switch threshold, keeping current rate\n"); + atomic_set(&sw->timer_active, NVME_SPEED_TIMER_INACTIVE); + return; + } + mod_timer(&sw->timer, jiffies + msecs_to_jiffies(READ_ONCE(sw->monitor_interval))); +} +EXPORT_SYMBOL_GPL(nvme_update_io_stats); + +static void nvme_clear_io_stats(struct nvme_speed_switch *sw) +{ + int cpu; + + for_each_possible_cpu(cpu) { + struct nvme_speed_switch_stats *stat = per_cpu_ptr(sw->stats, cpu); + + stat->read_bytes = 0; + stat->write_bytes = 0; + } +} + +/* + * Aggregate the per-CPU I/O counters of the last monitoring window and + * decide the target rate: the maximum rate if the window exceeded the + * threshold, the minimum rate otherwise. + */ +static int nvme_check_io_and_decide_speed(struct nvme_speed_switch *sw) +{ + struct nvme_ctrl *ctrl = container_of(sw, struct nvme_ctrl, speed_switch); + u64 read_bytes = 0, write_bytes = 0; + unsigned long read_kb, write_kb; + int cpu; + + for_each_possible_cpu(cpu) { + struct nvme_speed_switch_stats *stat = per_cpu_ptr(sw->stats, cpu); + + read_bytes += stat->read_bytes; + write_bytes += stat->write_bytes; + stat->read_bytes = 0; + stat->write_bytes = 0; + } + + read_kb = read_bytes / 1024; + write_kb = write_bytes / 1024; + dev_dbg(ctrl->device, + "I/O in window: read=%lu KB, write=%lu KB, threshold=%u KB\n", + read_kb, write_kb, READ_ONCE(sw->threshold)); + + if (read_kb >= sw->threshold || write_kb >= sw->threshold) + return sw->max_speed; + + return sw->min_speed; +} + +static void nvme_speed_switch_timer_fn(struct timer_list *t) +{ + struct nvme_speed_switch *sw = container_of(t, struct nvme_speed_switch, timer); + + if (!READ_ONCE(sw->enabled)) { + atomic_set(&sw->timer_active, NVME_SPEED_TIMER_INACTIVE); + return; + } + + sw->target_speed = nvme_check_io_and_decide_speed(sw); + if (sw->target_speed != READ_ONCE(sw->cur_speed)) + schedule_work(&sw->work); + + mod_timer(t, jiffies + msecs_to_jiffies(READ_ONCE(sw->monitor_interval))); +} + +static void nvme_speed_switch_params_init(struct nvme_speed_switch *sw) +{ + sw->monitor_interval = 100; + sw->min_speed = PCI_EXP_LNKSTA_CLS_2_5GB; +} + +void nvme_speed_switch_init(struct nvme_ctrl *ctrl) +{ + struct nvme_speed_switch *sw = &ctrl->speed_switch; + struct pci_dev *pdev; + int max_speed; + + if (!dev_is_pci(ctrl->dev)) { + dev_err(ctrl->device, "link rate switching requires a PCI device\n"); + return; + } + + pdev = to_pci_dev(ctrl->dev); + if (!pdev->bus->self) { + dev_err(ctrl->device, + "link rate switching requires a PCIe upstream port\n"); + return; + } + + nvme_speed_switch_params_init(sw); + + max_speed = nvme_get_max_link_speed(pdev->bus->self); + if (max_speed <= sw->min_speed) { + dev_err(ctrl->device, + "invalid link rate range: min=Gen%u, max=Gen%d\n", + sw->min_speed, max_speed); + return; + } + sw->max_speed = max_speed; + + sw->stats = alloc_percpu(struct nvme_speed_switch_stats); + if (!sw->stats) { + dev_err(ctrl->device, "failed to allocate per-CPU I/O statistics\n"); + return; + } + nvme_clear_io_stats(sw); + + WRITE_ONCE(sw->cur_speed, sw->max_speed); + WRITE_ONCE(sw->threshold, nvme_calc_speed_threshold(sw, pcie_get_width_cap(pdev))); + if (!READ_ONCE(sw->threshold)) { + dev_err(ctrl->device, "failed to compute speed switch threshold\n"); + free_percpu(sw->stats); + sw->stats = NULL; + return; + } + + INIT_WORK(&sw->work, nvme_speed_switch_work); + timer_setup(&sw->timer, nvme_speed_switch_timer_fn, 0); + atomic_set(&sw->timer_active, NVME_SPEED_TIMER_INACTIVE); + WRITE_ONCE(sw->enabled, true); + sw->initialized = true; + + dev_info(ctrl->device, + "NVMe link rate switching initialized (min Gen%u, max Gen%d)\n", + sw->min_speed, sw->max_speed); +} + +void nvme_speed_switch_start(struct nvme_ctrl *ctrl) +{ + struct nvme_speed_switch *sw = &ctrl->speed_switch; + + if (!READ_ONCE(sw->enabled)) + return; + + atomic_set(&sw->timer_active, NVME_SPEED_TIMER_ACTIVE); + mod_timer(&sw->timer, jiffies + msecs_to_jiffies(READ_ONCE(sw->monitor_interval))); +} + +void nvme_speed_switch_exit(struct nvme_ctrl *ctrl) +{ + struct nvme_speed_switch *sw = &ctrl->speed_switch; + + if (!sw->initialized) + return; + + sw->initialized = false; + WRITE_ONCE(sw->enabled, false); + timer_delete_sync(&sw->timer); + cancel_work_sync(&sw->work); + + free_percpu(sw->stats); + sw->stats = NULL; +} From 7a333e19c7d3f864fb728e253ebe42bb7c65a6e5 Mon Sep 17 00:00:00 2001 From: Liao Xuan Date: Thu, 24 Sep 2026 14:15:12 +0800 Subject: [PATCH 0358/1133] FROMLIST: nvme: Add hysteresis and idle detection to link rate switching The rate switching decision currently toggles the link rate in every monitoring window based on the I/O of that window alone, which can cause excessive rate switching when the workload fluctuates around the threshold. Add counters that require the threshold to be exceeded for a consecutive number of windows before the rate is upgraded, and to stay below the threshold for a consecutive number of windows before it is downgraded. The upgrade happens immediately (threshold 0 by default) so that latency is not sacrificed, while the downgrade requires 10 consecutive windows. Monitoring is stopped after 10 seconds of inactivity and is re-armed by the next I/O. Signed-off-by: Liao Xuan Link: https://patch.msgid.link/de23e8b9699b5a7a77e7ee215e8e4c9f530ce5da.1790222172.git.liaoxuan@hygon.cn Signed-off-by: Hariharan Sreedhar --- drivers/nvme/host/nvme.h | 5 +++ drivers/nvme/host/speed_switch.c | 52 ++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 2ac9dddc0d48a..0a2640a887cd3 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -354,6 +354,11 @@ struct nvme_speed_switch { u8 min_speed; u32 monitor_interval; /* ms */ u32 threshold; /* KB */ + u32 up_cnt; + u32 down_cnt; + u32 up_threshold; + u32 down_threshold; + u32 idle_cnt; struct timer_list timer; struct work_struct work; struct nvme_speed_switch_stats __percpu *stats; diff --git a/drivers/nvme/host/speed_switch.c b/drivers/nvme/host/speed_switch.c index ffee140ff8c81..c9821d9560b9f 100644 --- a/drivers/nvme/host/speed_switch.c +++ b/drivers/nvme/host/speed_switch.c @@ -228,10 +228,15 @@ static void nvme_clear_io_stats(struct nvme_speed_switch *sw) /* * Aggregate the per-CPU I/O counters of the last monitoring window and - * decide the target rate: the maximum rate if the window exceeded the - * threshold, the minimum rate otherwise. + * decide the target rate. Hysteresis counters are used to avoid + * excessive rate switching when the workload fluctuates around the + * threshold: the rate is only upgraded after the threshold was exceeded + * for a number of consecutive windows, and only downgraded after it + * stayed below the threshold for a number of consecutive windows. When + * no I/O was observed for 10 seconds the monitoring is stopped. */ -static int nvme_check_io_and_decide_speed(struct nvme_speed_switch *sw) +static int nvme_check_io_and_decide_speed(struct nvme_speed_switch *sw, + bool *io_activity) { struct nvme_ctrl *ctrl = container_of(sw, struct nvme_ctrl, speed_switch); u64 read_bytes = 0, write_bytes = 0; @@ -247,31 +252,62 @@ static int nvme_check_io_and_decide_speed(struct nvme_speed_switch *sw) stat->write_bytes = 0; } + if (read_bytes || write_bytes) { + *io_activity = true; + sw->idle_cnt = 0; + } else { + sw->idle_cnt++; + } + + /* Stop monitoring after 10 seconds of inactivity (100 windows of 100ms). */ + if (sw->idle_cnt >= 100) + *io_activity = false; + read_kb = read_bytes / 1024; write_kb = write_bytes / 1024; dev_dbg(ctrl->device, "I/O in window: read=%lu KB, write=%lu KB, threshold=%u KB\n", read_kb, write_kb, READ_ONCE(sw->threshold)); - if (read_kb >= sw->threshold || write_kb >= sw->threshold) + if (read_kb >= sw->threshold || write_kb >= sw->threshold) { + sw->up_cnt++; + sw->down_cnt = 0; + } else { + sw->down_cnt++; + sw->up_cnt = 0; + } + + if (sw->up_cnt > READ_ONCE(sw->up_threshold)) { + sw->up_cnt = 0; return sw->max_speed; + } + + if (sw->down_cnt > READ_ONCE(sw->down_threshold) || !*io_activity) { + sw->down_cnt = 0; + return sw->min_speed; + } - return sw->min_speed; + return READ_ONCE(sw->cur_speed); } static void nvme_speed_switch_timer_fn(struct timer_list *t) { struct nvme_speed_switch *sw = container_of(t, struct nvme_speed_switch, timer); + bool io_activity = true; if (!READ_ONCE(sw->enabled)) { atomic_set(&sw->timer_active, NVME_SPEED_TIMER_INACTIVE); return; } - sw->target_speed = nvme_check_io_and_decide_speed(sw); + sw->target_speed = nvme_check_io_and_decide_speed(sw, &io_activity); if (sw->target_speed != READ_ONCE(sw->cur_speed)) schedule_work(&sw->work); + if (!io_activity) { + atomic_set(&sw->timer_active, NVME_SPEED_TIMER_INACTIVE); + return; + } mod_timer(t, jiffies + msecs_to_jiffies(READ_ONCE(sw->monitor_interval))); } @@ -279,6 +315,10 @@ static void nvme_speed_switch_params_init(struct nvme_speed_switch *sw) { sw->monitor_interval = 100; sw->min_speed = PCI_EXP_LNKSTA_CLS_2_5GB; + /* Upgrade immediately once the threshold is exceeded. */ + sw->up_threshold = 0; + /* Downgrade after 10 consecutive below-threshold windows. */ + sw->down_threshold = 10; } void nvme_speed_switch_init(struct nvme_ctrl *ctrl) From bac721abd20da6481fe78ad2353b04f828903cc9 Mon Sep 17 00:00:00 2001 From: Liao Xuan Date: Thu, 24 Sep 2026 14:15:13 +0800 Subject: [PATCH 0359/1133] FROMLIST: nvme: Expose link rate switching tunables via sysfs Add a speed attribute group under /sys/class/nvme/nvmeX/ that exposes the adaptive link rate switching parameters for runtime tuning: enable - toggle the feature on/off (0/1) monitor_interval - I/O monitoring window in milliseconds (>= 100) min_speed - minimum PCIe generation to downgrade to (1-5) up_threshold - windows above the threshold needed to upgrade down_threshold - windows below the threshold needed to downgrade The attributes are read/write and are removed when the controller is torn down. Signed-off-by: Liao Xuan Link: https://patch.msgid.link/be224cd8385a5c28a20db65d635000a7be4da91a.1790222172.git.liaoxuan@hygon.cn Signed-off-by: Hariharan Sreedhar --- drivers/nvme/host/nvme.h | 3 + drivers/nvme/host/speed_switch.c | 15 +++- drivers/nvme/host/sysfs.c | 143 +++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 0a2640a887cd3..6b6e19111b394 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -1096,6 +1096,9 @@ extern const struct attribute_group nvme_dev_attrs_group; extern const struct attribute_group nvme_dev_diag_attrs_group; extern const struct attribute_group *nvme_subsys_attrs_groups[]; extern const struct attribute_group *nvme_dev_attr_groups[]; +#ifdef CONFIG_NVME_SPEED_SWITCH +extern const struct attribute_group nvme_speed_attr_group; +#endif extern const struct block_device_operations nvme_bdev_ops; void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl); diff --git a/drivers/nvme/host/speed_switch.c b/drivers/nvme/host/speed_switch.c index c9821d9560b9f..6cacac1ff6925 100644 --- a/drivers/nvme/host/speed_switch.c +++ b/drivers/nvme/host/speed_switch.c @@ -325,7 +325,7 @@ void nvme_speed_switch_init(struct nvme_ctrl *ctrl) { struct nvme_speed_switch *sw = &ctrl->speed_switch; struct pci_dev *pdev; - int max_speed; + int max_speed, ret; if (!dev_is_pci(ctrl->dev)) { dev_err(ctrl->device, "link rate switching requires a PCI device\n"); @@ -370,6 +370,18 @@ void nvme_speed_switch_init(struct nvme_ctrl *ctrl) timer_setup(&sw->timer, nvme_speed_switch_timer_fn, 0); atomic_set(&sw->timer_active, NVME_SPEED_TIMER_INACTIVE); WRITE_ONCE(sw->enabled, true); + + ret = sysfs_create_group(&ctrl->device->kobj, &nvme_speed_attr_group); + if (ret) { + dev_err(ctrl->device, + "failed to create link rate switching sysfs group (%d)\n", + ret); + timer_delete_sync(&sw->timer); + free_percpu(sw->stats); + sw->stats = NULL; + WRITE_ONCE(sw->enabled, false); + return; + } sw->initialized = true; dev_info(ctrl->device, @@ -399,6 +411,7 @@ void nvme_speed_switch_exit(struct nvme_ctrl *ctrl) WRITE_ONCE(sw->enabled, false); timer_delete_sync(&sw->timer); cancel_work_sync(&sw->work); + sysfs_remove_group(&ctrl->device->kobj, &nvme_speed_attr_group); free_percpu(sw->stats); sw->stats = NULL; diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c index 10018c6356b62..25be8e01c0ac7 100644 --- a/drivers/nvme/host/sysfs.c +++ b/drivers/nvme/host/sysfs.c @@ -1313,3 +1313,146 @@ const struct attribute_group *nvme_subsys_attrs_groups[] = { &nvme_subsys_attrs_group, NULL, }; + +#ifdef CONFIG_NVME_SPEED_SWITCH +enum nvme_speed_attr_id { + NVME_SPEED_ATTR_ENABLE, + NVME_SPEED_ATTR_MONITOR_INTERVAL, + NVME_SPEED_ATTR_MIN_SPEED, + NVME_SPEED_ATTR_UP_THRESHOLD, + NVME_SPEED_ATTR_DOWN_THRESHOLD, +}; + +struct nvme_speed_attr { + struct device_attribute attr; + enum nvme_speed_attr_id id; +}; + +static ssize_t nvme_speed_attr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + struct nvme_speed_switch *sw = &ctrl->speed_switch; + struct nvme_speed_attr *sa = + container_of(attr, struct nvme_speed_attr, attr); + u32 val; + + switch (sa->id) { + case NVME_SPEED_ATTR_ENABLE: + val = READ_ONCE(sw->enabled); + break; + case NVME_SPEED_ATTR_MONITOR_INTERVAL: + val = READ_ONCE(sw->monitor_interval); + break; + case NVME_SPEED_ATTR_MIN_SPEED: + val = READ_ONCE(sw->min_speed); + break; + case NVME_SPEED_ATTR_UP_THRESHOLD: + val = READ_ONCE(sw->up_threshold); + break; + case NVME_SPEED_ATTR_DOWN_THRESHOLD: + val = READ_ONCE(sw->down_threshold); + break; + default: + return -EINVAL; + } + + return sysfs_emit(buf, "%u\n", val); +} + +static ssize_t nvme_speed_attr_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + struct nvme_speed_switch *sw = &ctrl->speed_switch; + struct nvme_speed_attr *sa = + container_of(attr, struct nvme_speed_attr, attr); + u32 val; + int ret; + + ret = kstrtou32(buf, 10, &val); + if (ret) + return ret; + + switch (sa->id) { + case NVME_SPEED_ATTR_ENABLE: + if (val > 1) + return -EINVAL; + if (!val && READ_ONCE(sw->enabled)) { + WRITE_ONCE(sw->enabled, false); + timer_delete_sync(&sw->timer); + cancel_work_sync(&sw->work); + atomic_set(&sw->timer_active, NVME_SPEED_TIMER_INACTIVE); + } else + WRITE_ONCE(sw->enabled, val); + break; + case NVME_SPEED_ATTR_MONITOR_INTERVAL: + if (val < 100) + return -EINVAL; + WRITE_ONCE(sw->monitor_interval, val); + break; + case NVME_SPEED_ATTR_MIN_SPEED: + if (val < 1 || val > 5) + return -EINVAL; + if (val > sw->max_speed) + val = sw->max_speed; + WRITE_ONCE(sw->min_speed, val); + break; + case NVME_SPEED_ATTR_UP_THRESHOLD: + WRITE_ONCE(sw->up_threshold, val); + break; + case NVME_SPEED_ATTR_DOWN_THRESHOLD: + WRITE_ONCE(sw->down_threshold, val); + break; + default: + return -EINVAL; + } + + return count; +} + +static struct nvme_speed_attr nvme_speed_attr_enable = { + .attr = __ATTR(enable, 0644, + nvme_speed_attr_show, nvme_speed_attr_store), + .id = NVME_SPEED_ATTR_ENABLE, +}; + +static struct nvme_speed_attr nvme_speed_attr_monitor_interval = { + .attr = __ATTR(monitor_interval, 0644, + nvme_speed_attr_show, nvme_speed_attr_store), + .id = NVME_SPEED_ATTR_MONITOR_INTERVAL, +}; + +static struct nvme_speed_attr nvme_speed_attr_min_speed = { + .attr = __ATTR(min_speed, 0644, + nvme_speed_attr_show, nvme_speed_attr_store), + .id = NVME_SPEED_ATTR_MIN_SPEED, +}; + +static struct nvme_speed_attr nvme_speed_attr_up_threshold = { + .attr = __ATTR(up_threshold, 0644, + nvme_speed_attr_show, nvme_speed_attr_store), + .id = NVME_SPEED_ATTR_UP_THRESHOLD, +}; + +static struct nvme_speed_attr nvme_speed_attr_down_threshold = { + .attr = __ATTR(down_threshold, 0644, + nvme_speed_attr_show, nvme_speed_attr_store), + .id = NVME_SPEED_ATTR_DOWN_THRESHOLD, +}; + +static struct attribute *nvme_speed_attrs[] = { + &nvme_speed_attr_enable.attr.attr, + &nvme_speed_attr_monitor_interval.attr.attr, + &nvme_speed_attr_min_speed.attr.attr, + &nvme_speed_attr_up_threshold.attr.attr, + &nvme_speed_attr_down_threshold.attr.attr, + NULL, +}; + +const struct attribute_group nvme_speed_attr_group = { + .name = "speed", + .attrs = nvme_speed_attrs, +}; +#endif /* CONFIG_NVME_SPEED_SWITCH */ From 0fa94eddb25a09bcd5102ff472a97ec337f298b2 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Mon, 5 Oct 2026 17:23:04 +0530 Subject: [PATCH 0360/1133] FROMLIST: PCI: qcom: Enable Link Bandwidth Notification capability The Qualcomm PCIe controller hardwires the Link Bandwidth Notification Capability (LBNC) bit to 0, even though the Root Port supports retraining the link to the speeds advertised in LNKCAP2. The PCIe port bandwidth controller relies on this capability to determine whether link bandwidth control is supported. With LBNC cleared, the bandwidth controller is not registered and link speed cannot be managed through the associated thermal cooling device. Override the read-only LNKCAP register through the DBI RO write interface and set PCI_EXP_LNKCAP_LBNC during controller initialization. This allows the PCIe bandwidth controller to bind to the Root Port and enables link speed scaling through the thermal framework. Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Hariharan Sreedhar --- drivers/pci/controller/dwc/pcie-qcom.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 68f888917ee46..4b73b3a37b758 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -408,6 +408,26 @@ static void qcom_pcie_clear_aspm_l0s(struct dw_pcie *pci) dw_pcie_dbi_ro_wr_dis(pci); } +static void qcom_pcie_set_link_bw_notif_cap(struct dw_pcie *pci) +{ + u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + u32 val; + + dw_pcie_dbi_ro_wr_en(pci); + + /* + * The controller hardwires Link Bandwidth Notification Capability to 0, + * even though the Root Port can retrain to any of the speeds advertised + * in LNKCAP2. Set the bit so that the PCIe port driver binds bwctrl and + * registers the link speed thermal cooling device. + */ + val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP); + val |= PCI_EXP_LNKCAP_LBNC; + writel(val, pci->dbi_base + offset + PCI_EXP_LNKCAP); + + dw_pcie_dbi_ro_wr_dis(pci); +} + static void qcom_pcie_set_slot_cap(struct dw_pcie *pci) { u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); @@ -1170,6 +1190,7 @@ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie) pcie->parf + PARF_NO_SNOOP_OVERRIDE); qcom_pcie_set_slot_cap(pcie->pci); + qcom_pcie_set_link_bw_notif_cap(pcie->pci); qcom_pcie_init_outbound_blocker(pcie); From e8ce609e00b97948f92baf492fada5d08b99d991 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Sat, 5 Sep 2026 06:59:29 +0530 Subject: [PATCH 0361/1133] FROMLIST: PCI: qcom: Add register dump support for PCIe Link Down events When the PCIe link goes down unexpectedly, being able to inspect the state of key controller registers at the time of failure is valuable for root-causing the issue. If a storage endpoint is present downstream, the dump is printed directly via dev_err() so it is visible in dmesg immediately, since a devcoredump read from userspace could otherwise race with a storage failure. Otherwise, the buffer is handed to the devcoredump framework so it can be collected from /sys/class/devcoredump/ for offline analysis. To keep the dump readable given the number of registers involved, entries are packed as "offset: value" pairs, QCOM_PCIE_DUMP_REGS_PER_LINE (4) per dmesg line, with a section header ("DBI registers:", "PARF registers:", "MHI registers:") identifying each register group. Also expose the same dump on demand via a new "regdump" debugfs file under the existing per-controller debugfs directory, so the register state can be inspected without needing an actual Link Down event. Signed-off-by: Krishna Chaitanya Chundru Link: https://lore.kernel.org/r/20260905-regdump-v2-1-f7d34f9d4f46@oss.qualcomm.com --- drivers/pci/controller/dwc/pcie-designware.h | 6 + drivers/pci/controller/dwc/pcie-qcom.c | 351 ++++++++++++++++++- include/uapi/linux/pci_regs.h | 2 + 3 files changed, 355 insertions(+), 4 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 6d788aa000117..1d50aecef380f 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -288,6 +288,12 @@ #define RAS_DES_EVENT_COUNTER_DATA 0xc +/* SD-EQ (Gen5 32 GT/s per-lane pre/post cursor equalization) registers */ +#define PCIE_RAS_DES_SD_EQ_CONTROL1 0xd0 +#define PCIE_RAS_DES_SD_EQ_CONTROL1_LANE_SEL GENMASK(3, 0) +#define PCIE_RAS_DES_SD_EQ_STATUS2 0xe4 +#define PCIE_RAS_DES_SD_EQ_STATUS3 0xe8 + /* PTM register definitions */ #define PTM_RES_REQ_CTRL 0x8 #define PTM_RES_CCONTEXT_VALID BIT(0) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 4b73b3a37b758..803da92704bb1 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -34,8 +35,10 @@ #include #include #include +#include #include #include +#include #include "../../pci.h" #include "../pci-host-common.h" @@ -45,6 +48,8 @@ /* PARF registers */ #define PARF_SYS_CTRL 0x00 #define PARF_PM_CTRL 0x20 +#define PARF_PM_STTS 0x24 +#define PARF_PM_STTS_1 0x28 #define PARF_PCS_DEEMPH 0x34 #define PARF_PCS_SWING 0x38 #define PARF_PHY_CTRL 0x40 @@ -64,12 +69,18 @@ #define PARF_STATUS 0x230 #define PARF_SID_OFFSET 0x234 #define PARF_BDF_TRANSLATE_CFG 0x24c +#define PARF_CLKREQ_OVERRIDE 0x2b0 #define PARF_DBI_BASE_ADDR_V2 0x350 #define PARF_DBI_BASE_ADDR_V2_HI 0x354 #define PARF_SLV_ADDR_SPACE_SIZE_V2 0x358 #define PARF_SLV_ADDR_SPACE_SIZE_V2_HI 0x35c #define PARF_NO_SNOOP_OVERRIDE 0x3d4 +#define PARF_CORE_ERRORS 0x3c0 #define PARF_AXI_MSTR_WR_NS_BDF_HALT 0x4a0 +#define PARF_L1SS_SLEEP_MODE_HANDLER_STATUS 0x4d0 +#define PARF_L1SS_SLEEP_MODE_HANDLER_CFG 0x4d4 +#define PARF_INT_ALL_2_STATUS 0x500 +#define PARF_LINK_DOWN_AXI_ECAM_BLOCK_STATUS 0x630 #define PARF_ATU_BASE_ADDR 0x634 #define PARF_ATU_BASE_ADDR_HI 0x638 #define PARF_DEVICE_TYPE 0x1000 @@ -103,8 +114,12 @@ /* MHI registers */ #define PARF_DEBUG_CNT_PM_LINKST_IN_L2 0xc04 +#define PARF_DEBUG_CNT_PM_LINKST_IN_L1SUB 0xc08 #define PARF_DEBUG_CNT_PM_LINKST_IN_L1 0xc0c #define PARF_DEBUG_CNT_PM_LINKST_IN_L0S 0xc10 +#define PARF_DEBUG_CNT_AUX_CLK_APP_REQ_EXIT_L1 0xc14 +#define PARF_DEBUG_CNT_AUX_CLK_APP_READY_ENTER_L23 0xc18 +#define PARF_DEBUG_CNT_AUX_CLK_APP_READY_ENTER_L1 0xc1c #define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1 0xc84 #define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2 0xc88 @@ -215,11 +230,48 @@ #define PERST_DELAY_US 1000 #define FLUSH_TIMEOUT_US 100 +/* Dump buffer size for the link-down register dump */ +#define QCOM_PCIE_DUMP_BUF_SIZE SZ_8K + #define QCOM_PCIE_CRC8_POLYNOMIAL (BIT(2) | BIT(1) | BIT(0)) #define QCOM_PCIE_LINK_SPEED_TO_BW(speed) \ Mbps_to_icc(PCIE_SPEED2MBS_ENC(pcie_get_link_speed(speed))) +#define QCOM_PCIE_DUMP_REGS_PER_LINE 4 + +static const u32 qcom_pcie_parf_dump_regs[] = { + PARF_LTSSM, + PARF_INT_ALL_STATUS, + PARF_SYS_CTRL, +}; + +static const u32 qcom_pcie_ext_parf_dump_regs[] = { + PARF_PM_STTS, + PARF_PM_STTS_1, + PARF_INT_ALL_STATUS, + PARF_INT_ALL_2_STATUS, + PARF_CLKREQ_OVERRIDE, + PARF_L1SS_SLEEP_MODE_HANDLER_STATUS, + PARF_L1SS_SLEEP_MODE_HANDLER_CFG, + PARF_CORE_ERRORS, + PARF_LINK_DOWN_AXI_ECAM_BLOCK_STATUS, + PARF_STATUS, + PARF_SYS_CTRL, +}; + +static const u32 qcom_pcie_mhi_dump_regs[] = { + PARF_DEBUG_CNT_PM_LINKST_IN_L2, + PARF_DEBUG_CNT_PM_LINKST_IN_L1SUB, + PARF_DEBUG_CNT_PM_LINKST_IN_L1, + PARF_DEBUG_CNT_PM_LINKST_IN_L0S, + PARF_DEBUG_CNT_AUX_CLK_APP_REQ_EXIT_L1, + PARF_DEBUG_CNT_AUX_CLK_APP_READY_ENTER_L23, + PARF_DEBUG_CNT_AUX_CLK_APP_READY_ENTER_L1, + PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1, + PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2, +}; + struct qcom_pcie_resources_1_0_0 { struct clk_bulk_data *clks; int num_clks; @@ -305,6 +357,8 @@ struct qcom_pcie_ops { * @no_l0s: Set if the Root Complex does not support L0s * @noc_ensures_ordering: Set if the NoC preserves the ordering of inbound * transactions from the controller. + * @has_ext_parf_regs: Set if the PARF block implements the extended + * register set used by qcom_pcie_dump_regs(). */ struct qcom_pcie_cfg { const struct qcom_pcie_ops *ops; @@ -312,6 +366,7 @@ struct qcom_pcie_cfg { bool firmware_managed; bool no_l0s; bool noc_ensures_ordering; + bool has_ext_parf_regs; }; struct qcom_pcie_perst { @@ -1737,6 +1792,7 @@ static const struct qcom_pcie_cfg cfg_1_0_0 = { static const struct qcom_pcie_cfg cfg_1_9_0 = { .ops = &ops_1_9_0, .noc_ensures_ordering = true, + .has_ext_parf_regs = true, }; static const struct qcom_pcie_cfg cfg_1_34_0 = { @@ -1744,6 +1800,7 @@ static const struct qcom_pcie_cfg cfg_1_34_0 = { .override_no_snoop = true, .no_l0s = true, .noc_ensures_ordering = true, + .has_ext_parf_regs = true, }; static const struct qcom_pcie_cfg cfg_2_1_0 = { @@ -1766,6 +1823,7 @@ static const struct qcom_pcie_cfg cfg_2_4_0 = { static const struct qcom_pcie_cfg cfg_2_7_0 = { .ops = &ops_2_7_0, .noc_ensures_ordering = true, + .has_ext_parf_regs = true, }; static const struct qcom_pcie_cfg cfg_2_9_0 = { @@ -1777,6 +1835,7 @@ static const struct qcom_pcie_cfg cfg_sc8280xp = { .ops = &ops_1_21_0, .no_l0s = true, .noc_ensures_ordering = true, + .has_ext_parf_regs = true, }; static const struct qcom_pcie_cfg cfg_fw_managed = { @@ -1904,6 +1963,287 @@ static int qcom_pcie_set_max_opp(struct device *dev) return ret; } +static int qcom_pcie_has_storage_ep_cb(struct pci_dev *pdev, void *data) +{ + bool *found = data; + + if (pdev->class >> 16 == PCI_BASE_CLASS_STORAGE) { + *found = true; + return 1; + } + + return 0; +} + +static bool qcom_pcie_has_storage_ep(struct qcom_pcie *pcie) +{ + struct dw_pcie_rp *pp = &pcie->pci->pp; + bool found = false; + + pci_walk_bus(pp->bridge->bus, qcom_pcie_has_storage_ep_cb, &found); + + return found; +} + +/* + * qcom_pcie_dump_advance_col - advance @col and append a separator to @buf. + * + * @col tracks the current column within the active section and must be + * reset to 0 by the caller at the start of each new section; a newline is + * emitted every QCOM_PCIE_DUMP_REGS_PER_LINE entries to keep the dump + * compact in dmesg. + */ +static size_t qcom_pcie_dump_advance_col(char *buf, size_t buf_size, int *col) +{ + *col += 1; + + return scnprintf(buf, buf_size, + (*col % QCOM_PCIE_DUMP_REGS_PER_LINE) ? " " : "\n"); +} + +static size_t qcom_pcie_dump_reg_val(char *buf, size_t buf_size, int *col, + u32 offset, u32 val) +{ + size_t len; + + len = scnprintf(buf, buf_size, "0x%03x: 0x%08x", offset, val); + len += qcom_pcie_dump_advance_col(buf + len, buf_size - len, col); + + return len; +} + +/* Same as qcom_pcie_dump_reg_val(), but tags the entry with a lane number + * since the RAS-DES SD-EQ status registers are read once per lane at a + * fixed offset, so the offset alone can't tell entries apart. + */ +static size_t qcom_pcie_dump_lane_reg_val(char *buf, size_t buf_size, int *col, + int lane, u32 offset, u32 val) +{ + size_t len; + + len = scnprintf(buf, buf_size, "L%d/0x%03x: 0x%08x", lane, offset, val); + len += qcom_pcie_dump_advance_col(buf + len, buf_size - len, col); + + return len; +} + +static size_t qcom_pcie_dump_reg_table(void __iomem *base, const u32 *regs, + int nregs, char *buf, size_t buf_size) +{ + size_t len = 0; + int col = 0; + int i; + + for (i = 0; i < nregs; i++) + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + regs[i], readl_relaxed(base + regs[i])); + + if (col % QCOM_PCIE_DUMP_REGS_PER_LINE) + len += scnprintf(buf + len, buf_size - len, "\n"); + + return len; +} + +/* + * qcom_pcie_fill_dump_buf - fill @buf with key PCIe register values captured + * at Link Down time. + * + * Returns the number of bytes written into @buf. + */ +static size_t qcom_pcie_fill_dump_buf(struct qcom_pcie *pcie, char *buf, + size_t buf_size) +{ + struct dw_pcie *pci = pcie->pci; + u16 exp_cap, aer_cap, l1ss_cap, secpci_cap, pl16gt_cap, pl32gt_cap; + size_t len = 0; + int col = 0; + u32 val; + + len += scnprintf(buf + len, buf_size - len, "DBI registers:\n"); + + exp_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + if (exp_cap) { + val = dw_pcie_readl_dbi(pci, exp_cap + PCI_EXP_LNKCAP); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + exp_cap + PCI_EXP_LNKCAP, val); + + val = dw_pcie_readl_dbi(pci, exp_cap + PCI_EXP_LNKCTL); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + exp_cap + PCI_EXP_LNKCTL, val); + + val = dw_pcie_readl_dbi(pci, exp_cap + PCI_EXP_LNKCTL2); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + exp_cap + PCI_EXP_LNKCTL2, val); + } + + aer_cap = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_ERR); + if (aer_cap) { + val = dw_pcie_readl_dbi(pci, aer_cap + PCI_ERR_UNCOR_STATUS); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + aer_cap + PCI_ERR_UNCOR_STATUS, val); + + val = dw_pcie_readl_dbi(pci, aer_cap + PCI_ERR_COR_STATUS); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + aer_cap + PCI_ERR_COR_STATUS, val); + } + + l1ss_cap = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_L1SS); + if (l1ss_cap) { + val = dw_pcie_readl_dbi(pci, l1ss_cap + PCI_L1SS_CTL1); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + l1ss_cap + PCI_L1SS_CTL1, val); + } + + secpci_cap = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_SECPCI); + if (secpci_cap) { + val = dw_pcie_readl_dbi(pci, secpci_cap + PCI_SECPCI_LE_CTRL); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + secpci_cap + PCI_SECPCI_LE_CTRL, val); + + val = dw_pcie_readl_dbi(pci, secpci_cap + PCI_SECPCI_LE_CTRL + 4); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + secpci_cap + PCI_SECPCI_LE_CTRL + 4, val); + } + + pl16gt_cap = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_PL_16GT); + if (pl16gt_cap) { + val = dw_pcie_readl_dbi(pci, pl16gt_cap + PCI_PL_16GT_LE_CTRL); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + pl16gt_cap + PCI_PL_16GT_LE_CTRL, val); + + val = dw_pcie_readl_dbi(pci, pl16gt_cap + PCI_PL_16GT_STATUS); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + pl16gt_cap + PCI_PL_16GT_STATUS, val); + } + + pl32gt_cap = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_PL_32GT); + if (pl32gt_cap) { + val = dw_pcie_readl_dbi(pci, pl32gt_cap + PCI_PL_32GT_LE_CTRL); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + pl32gt_cap + PCI_PL_32GT_LE_CTRL, val); + + val = dw_pcie_readl_dbi(pci, pl32gt_cap + PCI_PL_32GT_STATUS); + len += qcom_pcie_dump_reg_val(buf + len, buf_size - len, &col, + pl32gt_cap + PCI_PL_32GT_STATUS, val); + } + + /* + * Gen5 (32 GT/s) local/remote pre/post cursor status, read through the + * SD-EQ registers inside the DWC RAS-DES vendor-specific extended + * capability. For each lane, write the lane selector into + * PCIE_RAS_DES_SD_EQ_CONTROL1 then read back + * PCIE_RAS_DES_SD_EQ_STATUS2/3, which carry the local/remote pre/post + * cursor values. + */ + if (pcie_get_link_speed(pci->max_link_speed) == PCIE_SPEED_32_0GT) { + u16 rasdes_cap = dw_pcie_find_rasdes_capability(pci); + + if (rasdes_cap) { + int num_lanes = dw_pcie_link_get_max_link_width(pci); + int lane; + + for (lane = 0; lane < num_lanes; lane++) { + dw_pcie_writel_dbi(pci, + rasdes_cap + PCIE_RAS_DES_SD_EQ_CONTROL1, + lane & PCIE_RAS_DES_SD_EQ_CONTROL1_LANE_SEL); + + val = dw_pcie_readl_dbi(pci, + rasdes_cap + PCIE_RAS_DES_SD_EQ_STATUS2); + len += qcom_pcie_dump_lane_reg_val(buf + len, buf_size - len, &col, + lane, + rasdes_cap + PCIE_RAS_DES_SD_EQ_STATUS2, + val); + + val = dw_pcie_readl_dbi(pci, + rasdes_cap + PCIE_RAS_DES_SD_EQ_STATUS3); + len += qcom_pcie_dump_lane_reg_val(buf + len, buf_size - len, &col, + lane, + rasdes_cap + PCIE_RAS_DES_SD_EQ_STATUS3, + val); + } + } + } + + if (col % QCOM_PCIE_DUMP_REGS_PER_LINE) + len += scnprintf(buf + len, buf_size - len, "\n"); + + len += scnprintf(buf + len, buf_size - len, "\nPARF registers:\n"); + if (pcie->cfg->has_ext_parf_regs) + len += qcom_pcie_dump_reg_table(pcie->parf, qcom_pcie_ext_parf_dump_regs, + ARRAY_SIZE(qcom_pcie_ext_parf_dump_regs), + buf + len, buf_size - len); + else + len += qcom_pcie_dump_reg_table(pcie->parf, qcom_pcie_parf_dump_regs, + ARRAY_SIZE(qcom_pcie_parf_dump_regs), + buf + len, buf_size - len); + + if (!pcie->mhi) + return len; + + len += scnprintf(buf + len, buf_size - len, "\nMHI registers:\n"); + len += qcom_pcie_dump_reg_table(pcie->mhi, qcom_pcie_mhi_dump_regs, + ARRAY_SIZE(qcom_pcie_mhi_dump_regs), + buf + len, buf_size - len); + + return len; +} + +/* + * qcom_pcie_dump_regs - capture a PCIe register dump on Link Down. + * + * If a storage endpoint is present downstream, print the dump directly to + * dmesg via dev_err() so it is immediately visible even if userspace is not + * available to read a devcoredump after a storage failure. Otherwise hand + * the buffer to the devcoredump framework so it is accessible under + * /sys/class/devcoredump/ for offline analysis. + */ +static void qcom_pcie_dump_regs(struct qcom_pcie *pcie) +{ + struct device *dev = pcie->pci->dev; + bool storage_ep = qcom_pcie_has_storage_ep(pcie); + char *buf, *line, *pos; + size_t len; + + buf = vmalloc(QCOM_PCIE_DUMP_BUF_SIZE); + if (!buf) + return; + + len = qcom_pcie_fill_dump_buf(pcie, buf, QCOM_PCIE_DUMP_BUF_SIZE); + + if (storage_ep) { + /* + * printk() truncates messages longer than LOG_LINE_MAX, so + * print the dump one line at a time instead of as a single + * dev_err() call. + */ + dev_err(dev, "PCIe Link Down register dump:\n"); + pos = buf; + while ((line = strsep(&pos, "\n"))) + dev_err(dev, "%s\n", line); + vfree(buf); + } else { + dev_coredumpv(dev, buf, len, GFP_KERNEL); + } +} + +static int qcom_pcie_regdump_show(struct seq_file *s, void *data) +{ + struct qcom_pcie *pcie = (struct qcom_pcie *)dev_get_drvdata(s->private); + char *buf; + size_t len; + + buf = vmalloc(QCOM_PCIE_DUMP_BUF_SIZE); + if (!buf) + return -ENOMEM; + + len = qcom_pcie_fill_dump_buf(pcie, buf, QCOM_PCIE_DUMP_BUF_SIZE); + seq_write(s, buf, len); + + vfree(buf); + + return 0; +} + /* * Qcom PCIe controllers only support one Root Port per controller instance. So * this function ignores the 'pci_dev' associated with the Root Port and just @@ -2011,8 +2351,11 @@ static void qcom_pcie_init_debugfs(struct qcom_pcie *pcie) return; pcie->debugfs = debugfs_create_dir(name, NULL); - debugfs_create_devm_seqfile(dev, "link_transition_count", pcie->debugfs, - qcom_pcie_link_transition_count); + if (pcie->mhi) + debugfs_create_devm_seqfile(dev, "link_transition_count", pcie->debugfs, + qcom_pcie_link_transition_count); + debugfs_create_devm_seqfile(dev, "regdump", pcie->debugfs, + qcom_pcie_regdump_show); } static irqreturn_t qcom_pcie_global_irq_thread(int irq, void *data) @@ -2032,6 +2375,7 @@ static irqreturn_t qcom_pcie_global_irq_thread(int irq, void *data) qcom_pcie_enable_outbound_blocker(pcie); mutex_unlock(&pcie->reset_lock); + qcom_pcie_dump_regs(pcie); for_each_pci_bridge(port, pp->bridge->bus) { if (pci_pcie_type(port) == PCI_EXP_TYPE_ROOT_PORT) pci_host_handle_link_down(port); @@ -2479,8 +2823,7 @@ static int qcom_pcie_probe(struct platform_device *pdev) qcom_pcie_icc_opp_update(pcie); - if (pcie->mhi) - qcom_pcie_init_debugfs(pcie); + qcom_pcie_init_debugfs(pcie); return 0; diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index facaa324bd86a..0e82d89e747a2 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -1176,12 +1176,14 @@ #define PCI_SECPCI_LE_CTRL 0x0c /* Lane Equalization Control Register */ /* Physical Layer 16.0 GT/s */ +#define PCI_PL_16GT_STATUS 0x0c /* 16.0 GT/s Status Register */ #define PCI_PL_16GT_LE_CTRL 0x20 /* Lane Equalization Control Register */ #define PCI_PL_16GT_LE_CTRL_DSP_TX_PRESET_MASK 0x0000000F #define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK 0x000000F0 #define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_SHIFT 4 /* Physical Layer 32.0 GT/s */ +#define PCI_PL_32GT_STATUS 0x0c /* 32.0 GT/s Status Register */ #define PCI_PL_32GT_LE_CTRL 0x20 /* Lane Equalization Control Register */ /* Physical Layer 64.0 GT/s */ From ede4dcc2837961ffc2187778540e13cd85c12354 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 21 Oct 2026 19:21:22 +0530 Subject: [PATCH 0362/1133] FROMLIST: dt-bindings: connector: Add PCIe M.2 Mechanical Key B connector Add the devicetree binding for PCIe M.2 Mechanical Key B connector defined in the PCI Express M.2 Specification, r4.2, sec 3.2.19.1. This connector is used to attach WWAN Adapters to the host machine over interfaces such as PCIe, USB3.1 Gen1, SSIC, or USB 2.0, selected by the Adapter's configuration pins. The connector provides a primary power supply of 3.3V/VBAT, along with optional GPIO signals for WWAN-specific power/radio control: FULL_CARD_POWER_OFF#, RESET#, W_DISABLE1#/2#, WAKE_ON_WWAN#, and DPR. Link: https://patch.msgid.link/20261021-pcie6_fix-v1-1-ad37134c35a3@oss.qualcomm.com Signed-off-by: Krishna Chaitanya Chundru --- .../connector/pcie-m2-b-connector.yaml | 146 ++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 147 insertions(+) create mode 100644 Documentation/devicetree/bindings/connector/pcie-m2-b-connector.yaml diff --git a/Documentation/devicetree/bindings/connector/pcie-m2-b-connector.yaml b/Documentation/devicetree/bindings/connector/pcie-m2-b-connector.yaml new file mode 100644 index 0000000000000..a7f4bcbc51199 --- /dev/null +++ b/Documentation/devicetree/bindings/connector/pcie-m2-b-connector.yaml @@ -0,0 +1,146 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/connector/pcie-m2-b-connector.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: PCIe M.2 Mechanical Key B Connector + +maintainers: + - Krishna Chaitanya Chundru + +description: + A PCIe M.2 B connector node represents a physical PCIe M.2 Mechanical Key B + connector. Mechanical Key B connectors are used to connect WWAN devices to + the host machine over interfaces like PCIe, USB3.1 Gen1, SSIC, or USB 2.0, + selected by the Adapter's configuration pins. + +properties: + compatible: + const: pcie-m2-b-connector + + vpcie3v3-supply: + description: A phandle to the regulator for the 3.3v/VBAT supply. + + full-card-power-off-gpios: + description: GPIO output to FULL_CARD_POWER_OFF# signal. This signal is + used by the host system to turn off the entire Adapter. Refer, PCI + Express M.2 Specification r4.0, sec 3.2.13.1 for more details. + maxItems: 1 + + reset-gpios: + description: GPIO output to RESET# signal. This signal is used by the + host system to place the WWAN Adapter into a power-on reset condition. + Refer, PCI Express M.2 Specification r4.0, sec 3.2.13.2 for more + details. + maxItems: 1 + + w-disable1-gpios: + description: GPIO output to W_DISABLE1# signal. This signal is used by + the host system to disable the WWAN radio on the Adapter. Refer, PCI + Express M.2 Specification r4.0, sec 3.1.12.3 for more details. + maxItems: 1 + + w-disable2-gpios: + description: GPIO output to W_DISABLE2# signal (default function of + GPIO_10). This signal is used by the host system to disable a second + radio on the Adapter. Refer, PCI Express M.2 Specification r4.0, + sec 3.1.12.3 for more details. + maxItems: 1 + + wowwan-gpios: + description: GPIO input to WAKE_ON_WWAN# (WoWWAN#) signal. The Adapter + asserts this signal to wake up the host system. Refer, PCI Express M.2 + Specification r4.0, sec 3.2.13.3.6 for more details. + maxItems: 1 + + dpr-gpios: + description: GPIO output to the Dynamic Power Reduction (DPR) signal. + This signal is provided by a host system proximity sensor to the + Adapter to trigger a reduction in the radio transmit output power to + meet regulatory SAR requirements. Refer, PCI Express M.2 Specification + r4.0, sec 3.2.13.4 for more details. + maxItems: 1 + + clocks: + description: 32.768 KHz Suspend Clock (SUSCLK) input from the host system to + the M.2 card. Refer, PCI Express M.2 Specification r4.0, sec 3.1.12.1 for + more details. + maxItems: 1 + + ports: + $ref: /schemas/graph.yaml#/properties/ports + description: OF graph bindings modeling the interfaces exposed on the + connector. Since a single connector can have multiple interfaces, every + interface has an assigned OF graph port number as described below. + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: PCIe interface for WWAN + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: SSIC interface for WWAN + + port@2: + $ref: /schemas/graph.yaml#/properties/port + description: USB 2.0 interface for WWAN + + port@3: + $ref: /schemas/graph.yaml#/properties/port + description: USB3.1 Gen1 interface for WWAN + + anyOf: + - required: + - port@0 + - required: + - port@1 + - required: + - port@3 + +required: + - compatible + - vpcie3v3-supply + +additionalProperties: false + +examples: + # PCI M.2 Key B connector for WWAN with PCIe interface + - | + #include + + connector { + compatible = "pcie-m2-b-connector"; + vpcie3v3-supply = <&vreg_wwan>; + full-card-power-off-gpios = <&tlmm 121 GPIO_ACTIVE_LOW>; + w-disable1-gpios = <&tlmm 122 GPIO_ACTIVE_LOW>; + wowwan-gpios = <&tlmm 123 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + endpoint@0 { + reg = <0>; + remote-endpoint = <&pcie6_port0_ep>; + }; + }; + + port@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + + endpoint@0 { + reg = <0>; + remote-endpoint = <&usb_hs_ep>; + }; + }; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 93abbb315065d..b9db9686dac54 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22255,6 +22255,7 @@ PCIE M.2 POWER SEQUENCING M: Manivannan Sadhasivam L: linux-pci@vger.kernel.org S: Maintained +F: Documentation/devicetree/bindings/connector/pcie-m2-b-connector.yaml F: Documentation/devicetree/bindings/connector/pcie-m2-e-connector.yaml F: Documentation/devicetree/bindings/connector/pcie-m2-m-connector.yaml F: drivers/power/sequencing/pwrseq-pcie-m2.c From ec882233b58fda2b20c82a17d108466f5fd0d7f6 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 21 Oct 2026 19:21:23 +0530 Subject: [PATCH 0363/1133] FROMLIST: power: sequencing: pcie-m2: Add support for PCIe M.2 Key B connectors Add support for handling the power sequence of the PCIe M.2 Key B connectors. These connectors are used to attach WWAN Adapters to the host machine over interfaces such as PCIe, USB3.1 Gen1, SSIC, or USB 2.0. Currently, this driver only supports driving the 3.3V/VBAT power supply along with the FULL_CARD_POWER_OFF#, RESET#, and W_DISABLE1#/2# GPIOs as a single "pcie" target, since Key B Adapters expose only a discoverable PCIe/USB interface and no non-discoverable bus (unlike Key E's UART-attached Bluetooth device), so no serdev creation is needed. The optional WAKE_ON_WWAN# and DPR signals are not currently supported. Link: https://patch.msgid.link/20261021-pcie6_fix-v1-2-ad37134c35a3@oss.qualcomm.com Signed-off-by: Krishna Chaitanya Chundru --- drivers/power/sequencing/pwrseq-pcie-m2.c | 82 +++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c index 33425e386d795..7842d252d6dd6 100644 --- a/drivers/power/sequencing/pwrseq-pcie-m2.c +++ b/drivers/power/sequencing/pwrseq-pcie-m2.c @@ -39,6 +39,8 @@ struct pwrseq_pcie_m2_ctx { struct notifier_block nb; struct gpio_desc *w_disable1_gpio; struct gpio_desc *w_disable2_gpio; + struct gpio_desc *full_card_power_off_gpio; + struct gpio_desc *reset_gpio; struct device *dev; struct list_head pci_devices; struct mutex list_lock; @@ -135,6 +137,53 @@ static const struct pwrseq_unit_data pwrseq_pcie_m2_e_pcie_unit_data = { .disable = pwrseq_pci_m2_e_pcie_disable, }; +static int pwrseq_pci_m2_b_pcie_enable(struct pwrseq_device *pwrseq) +{ + struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); + int ret; + + ret = gpiod_set_value_cansleep(ctx->full_card_power_off_gpio, 0); + if (ret) + return ret; + + ret = gpiod_set_value_cansleep(ctx->reset_gpio, 0); + if (ret) + return ret; + + ret = gpiod_set_value_cansleep(ctx->w_disable1_gpio, 0); + if (ret) + return ret; + + return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 0); +} + +static int pwrseq_pci_m2_b_pcie_disable(struct pwrseq_device *pwrseq) +{ + struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); + int ret; + + ret = gpiod_set_value_cansleep(ctx->w_disable2_gpio, 1); + if (ret) + return ret; + + ret = gpiod_set_value_cansleep(ctx->w_disable1_gpio, 1); + if (ret) + return ret; + + ret = gpiod_set_value_cansleep(ctx->reset_gpio, 1); + if (ret) + return ret; + + return gpiod_set_value_cansleep(ctx->full_card_power_off_gpio, 1); +} + +static const struct pwrseq_unit_data pwrseq_pcie_m2_b_pcie_unit_data = { + .name = "pcie-enable", + .deps = pwrseq_pcie_m2_unit_deps, + .enable = pwrseq_pci_m2_b_pcie_enable, + .disable = pwrseq_pci_m2_b_pcie_disable, +}; + static const struct pwrseq_unit_data pwrseq_pcie_m2_m_pcie_unit_data = { .name = "pcie-enable", .deps = pwrseq_pcie_m2_unit_deps, @@ -166,6 +215,11 @@ static const struct pwrseq_target_data pwrseq_pcie_m2_e_pcie_target_data = { .is_controllable = pwrseq_pci_m2_e_pcie_is_controllable, }; +static const struct pwrseq_target_data pwrseq_pcie_m2_b_pcie_target_data = { + .name = "pcie", + .unit = &pwrseq_pcie_m2_b_pcie_unit_data, +}; + static const struct pwrseq_target_data pwrseq_pcie_m2_m_pcie_target_data = { .name = "pcie", .unit = &pwrseq_pcie_m2_m_pcie_unit_data, @@ -177,6 +231,11 @@ static const struct pwrseq_target_data *pwrseq_pcie_m2_e_targets[] = { NULL }; +static const struct pwrseq_target_data *pwrseq_pcie_m2_b_targets[] = { + &pwrseq_pcie_m2_b_pcie_target_data, + NULL +}; + static const struct pwrseq_target_data *pwrseq_pcie_m2_m_targets[] = { &pwrseq_pcie_m2_m_pcie_target_data, NULL @@ -186,6 +245,10 @@ static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_e_of_data = { .targets = pwrseq_pcie_m2_e_targets, }; +static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_b_of_data = { + .targets = pwrseq_pcie_m2_b_targets, +}; + static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_m_of_data = { .targets = pwrseq_pcie_m2_m_targets, }; @@ -590,6 +653,21 @@ static int pwrseq_pcie_m2_probe(struct platform_device *pdev) goto err_free_regulators; } + ctx->full_card_power_off_gpio = devm_gpiod_get_optional(dev, "full-card-power-off", + GPIOD_OUT_HIGH); + if (IS_ERR(ctx->full_card_power_off_gpio)) { + ret = dev_err_probe(dev, PTR_ERR(ctx->full_card_power_off_gpio), + "Failed to get the FULL_CARD_POWER_OFF# GPIO\n"); + goto err_free_regulators; + } + + ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->reset_gpio)) { + ret = dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), + "Failed to get the RESET# GPIO\n"); + goto err_free_regulators; + } + config.parent = dev; config.owner = THIS_MODULE; config.drvdata = ctx; @@ -654,6 +732,10 @@ static const struct of_device_id pwrseq_pcie_m2_of_match[] = { .compatible = "pcie-m2-e-connector", .data = &pwrseq_pcie_m2_e_of_data, }, + { + .compatible = "pcie-m2-b-connector", + .data = &pwrseq_pcie_m2_b_of_data, + }, { } }; MODULE_DEVICE_TABLE(of, pwrseq_pcie_m2_of_match); From 6008f5093e5eed42ca0aac6ffdcc2176981a91e0 Mon Sep 17 00:00:00 2001 From: Raj Aryan Date: Wed, 19 Aug 2026 16:04:00 +0530 Subject: [PATCH 0364/1133] PENDING: ARM: config: Enable ADC and RTC_GLINK defconfigs This is a patch which enables ADC and RTC_GLINK defconfigs probe for temp-alarm and rtc-glink depend on these defconfigs. Signed-off-by: Raj Aryan --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7b4985b29b21c..8061a3cbba43d 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -90,6 +90,7 @@ CONFIG_NUMA=y CONFIG_XEN=y CONFIG_COMPAT=y CONFIG_RANDOMIZE_BASE=y +CONFIG_RTC_DRV_QCOM_GLINK=m CONFIG_HIBERNATION=y CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y CONFIG_ENERGY_MODEL=y @@ -810,6 +811,7 @@ CONFIG_GENERIC_ADC_THERMAL=m CONFIG_QCOM_TSENS=y CONFIG_QCOM_SPMI_ADC_TM5=m CONFIG_QCOM_SPMI_ADC_TM5_GEN3=m +CONFIG_QCOM_SPMI_ADC5_GEN3=m CONFIG_QCOM_SPMI_TEMP_ALARM=m CONFIG_QCOM_LMH=m CONFIG_UNIPHIER_THERMAL=y From 5be6dffa01f2ac99cbcf827057e2dfab32659a24 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 18 Sep 2026 22:12:45 +0530 Subject: [PATCH 0365/1133] FROMLIST: dt-bindings: mfd: pm8008: Add qcom,pm8010-i2c compatible The PM8010 can communicate over both SPMI and I2C, based on whether GPIO1 is pulled high or low respectively. Since the qcom,pm8010 compatible is already taken in the SPMI PMIC bindings and that set of properties is heavily tailored towards SPMI, introduce a secondary compatible to handle the I2C case. Link: https://lore.kernel.org/all/20260918-pm8010_i2c_support-v1-1-de33d78fad9d@oss.qualcomm.com/ Signed-off-by: Konrad Dybcio Signed-off-by: Jishnu Prakash Acked-by: Rob Herring (Arm) Tested-by: Oleg Keri # Lenovo Yoga Slim 7x Gen 11 (Glymur) --- Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml b/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml index 0c6e1870db1dc..2701aa755f310 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml @@ -16,7 +16,9 @@ description: | properties: compatible: - const: qcom,pm8008 + enum: + - qcom,pm8008 + - qcom,pm8010-i2c reg: maxItems: 1 From 16f2f179add0d64b258b3e2bb3d0f7ac17ba2b57 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 18 Sep 2026 22:12:46 +0530 Subject: [PATCH 0366/1133] FROMLIST: regulator: pm8008: Add PM8010 support PM8010 is effectively the next generation of PM8008. Like PM8008, PM8010 also has 7 LDOs under it which are used to power camera sensors. The PM8010 LDO are of different types from the PM8008 ones and have different voltage dropout values. PM8010 LDOs do not have a voltage step rate configuration register. Add the necessary changes to support PM8010 LDOs. Link: https://lore.kernel.org/all/20260918-pm8010_i2c_support-v1-2-de33d78fad9d@oss.qualcomm.com/ Signed-off-by: Konrad Dybcio Co-developed-by: Dhruvin Rajpura Signed-off-by: Dhruvin Rajpura Co-developed-by: Jishnu Prakash Signed-off-by: Jishnu Prakash Tested-by: Oleg Keri # Lenovo Yoga Slim 7x Gen 11 (Glymur) --- drivers/regulator/qcom-pm8008-regulator.c | 109 +++++++++++++++++----- 1 file changed, 85 insertions(+), 24 deletions(-) diff --git a/drivers/regulator/qcom-pm8008-regulator.c b/drivers/regulator/qcom-pm8008-regulator.c index 9c9b8be2e15a4..b484c0f73eeac 100644 --- a/drivers/regulator/qcom-pm8008-regulator.c +++ b/drivers/regulator/qcom-pm8008-regulator.c @@ -39,24 +39,59 @@ struct pm8008_regulator_data { unsigned int base; int min_dropout_uV; const struct linear_range *voltage_range; + int n_linear_ranges; }; -static const struct linear_range nldo_ranges[] = { +struct pm8008_match_data { + const bool has_stepper_ctl_reg; + const struct pm8008_regulator_data *regulator_data; + const int num_regulators; +}; + +static const struct linear_range pm8008_nldo_ranges[] = { REGULATOR_LINEAR_RANGE(528000, 0, 122, 8000), }; -static const struct linear_range pldo_ranges[] = { +static const struct linear_range pm8008_pldo_ranges[] = { REGULATOR_LINEAR_RANGE(1504000, 0, 237, 8000), }; +static const struct linear_range pm8010_nldo_ranges[] = { + REGULATOR_LINEAR_RANGE(528000, 0, 127, 8000), +}; + +static const struct linear_range pm8010_pldo_ranges[] = { + REGULATOR_LINEAR_RANGE(1504000, 0, 255, 8000), +}; + +static const struct linear_range pm8010_pldo_lv_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0, 2, 200000), + REGULATOR_LINEAR_RANGE(2608000, 3, 28, 16000), + REGULATOR_LINEAR_RANGE(3104000, 29, 30, 96000), + REGULATOR_LINEAR_RANGE(3312000, 31, 31, 0), +}; + +#define PM8008_REGULATOR(_name, _supply, _base, _dropout, _range) \ + { _name, _supply, _base, _dropout, _range, ARRAY_SIZE(_range) } + static const struct pm8008_regulator_data pm8008_reg_data[] = { - { "ldo1", "vdd-l1-l2", 0x4000, 225000, nldo_ranges, }, - { "ldo2", "vdd-l1-l2", 0x4100, 225000, nldo_ranges, }, - { "ldo3", "vdd-l3-l4", 0x4200, 300000, pldo_ranges, }, - { "ldo4", "vdd-l3-l4", 0x4300, 300000, pldo_ranges, }, - { "ldo5", "vdd-l5", 0x4400, 200000, pldo_ranges, }, - { "ldo6", "vdd-l6", 0x4500, 200000, pldo_ranges, }, - { "ldo7", "vdd-l7", 0x4600, 200000, pldo_ranges, }, + PM8008_REGULATOR("ldo1", "vdd-l1-l2", 0x4000, 225000, pm8008_nldo_ranges), + PM8008_REGULATOR("ldo2", "vdd-l1-l2", 0x4100, 225000, pm8008_nldo_ranges), + PM8008_REGULATOR("ldo3", "vdd-l3-l4", 0x4200, 300000, pm8008_pldo_ranges), + PM8008_REGULATOR("ldo4", "vdd-l3-l4", 0x4300, 300000, pm8008_pldo_ranges), + PM8008_REGULATOR("ldo5", "vdd-l5", 0x4400, 200000, pm8008_pldo_ranges), + PM8008_REGULATOR("ldo6", "vdd-l6", 0x4500, 200000, pm8008_pldo_ranges), + PM8008_REGULATOR("ldo7", "vdd-l7", 0x4600, 200000, pm8008_pldo_ranges), +}; + +static const struct pm8008_regulator_data pm8010_reg_data[] = { + PM8008_REGULATOR("ldo1", "vdd-l1-l2", 0x4000, 172000, pm8010_nldo_ranges), + PM8008_REGULATOR("ldo2", "vdd-l1-l2", 0x4100, 172000, pm8010_nldo_ranges), + PM8008_REGULATOR("ldo3", "vdd-l3-l4", 0x4200, 80000, pm8010_pldo_lv_ranges), + PM8008_REGULATOR("ldo4", "vdd-l3-l4", 0x4300, 80000, pm8010_pldo_lv_ranges), + PM8008_REGULATOR("ldo5", "vdd-l5", 0x4400, 296000, pm8010_pldo_ranges), + PM8008_REGULATOR("ldo6", "vdd-l6", 0x4500, 80000, pm8010_pldo_lv_ranges), + PM8008_REGULATOR("ldo7", "vdd-l7", 0x4600, 296000, pm8010_pldo_ranges), }; static int pm8008_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) @@ -100,7 +135,7 @@ static int pm8008_regulator_get_voltage_sel(struct regulator_dev *rdev) } static const struct regulator_ops pm8008_regulator_ops = { - .list_voltage = regulator_list_voltage_linear, + .list_voltage = regulator_list_voltage_linear_range, .set_voltage_sel = pm8008_regulator_set_voltage_sel, .get_voltage_sel = pm8008_regulator_get_voltage_sel, .enable = regulator_enable_regmap, @@ -110,8 +145,10 @@ static const struct regulator_ops pm8008_regulator_ops = { static int pm8008_regulator_probe(struct platform_device *pdev) { + const struct pm8008_match_data *match_data; const struct pm8008_regulator_data *data; struct regulator_config config = {}; + const struct platform_device_id *id; struct device *dev = &pdev->dev; struct pm8008_regulator *preg; struct regulator_desc *desc; @@ -120,12 +157,20 @@ static int pm8008_regulator_probe(struct platform_device *pdev) unsigned int val; int ret, i; + id = platform_get_device_id(pdev); + if (!id) + return dev_err_probe(dev, -ENODEV, "Missing platform device id\n"); + + match_data = (const struct pm8008_match_data *)id->driver_data; + if (!match_data) + return dev_err_probe(dev, -ENODATA, "Missing driver match data\n"); + regmap = dev_get_regmap(dev->parent, "secondary"); if (!regmap) return -EINVAL; - for (i = 0; i < ARRAY_SIZE(pm8008_reg_data); i++) { - data = &pm8008_reg_data[i]; + for (i = 0; i < match_data->num_regulators; i++) { + data = &match_data->regulator_data[i]; preg = devm_kzalloc(dev, sizeof(*preg), GFP_KERNEL); if (!preg) @@ -145,18 +190,21 @@ static int pm8008_regulator_probe(struct platform_device *pdev) desc->owner = THIS_MODULE; desc->linear_ranges = data->voltage_range; - desc->n_linear_ranges = 1; - desc->uV_step = desc->linear_ranges[0].step; - desc->min_uV = desc->linear_ranges[0].min; - desc->n_voltages = linear_range_values_in_range(&desc->linear_ranges[0]); - - ret = regmap_read(regmap, preg->base + LDO_STEPPER_CTL_REG, &val); - if (ret < 0) { - dev_err(dev, "failed to read step rate: %d\n", ret); - return ret; + desc->n_linear_ranges = data->n_linear_ranges; + desc->n_voltages = linear_range_values_in_range_array(desc->linear_ranges, + desc->n_linear_ranges); + + if (match_data->has_stepper_ctl_reg) { + ret = regmap_read(regmap, preg->base + LDO_STEPPER_CTL_REG, &val); + if (ret < 0) { + dev_err(dev, "failed to read step rate: %d\n", ret); + return ret; + } + val &= STEP_RATE_MASK; + desc->ramp_delay = DEFAULT_VOLTAGE_STEPPER_RATE >> val; + } else { + desc->ramp_delay = DEFAULT_VOLTAGE_STEPPER_RATE; } - val &= STEP_RATE_MASK; - desc->ramp_delay = DEFAULT_VOLTAGE_STEPPER_RATE >> val; desc->min_dropout_uV = data->min_dropout_uV; @@ -179,8 +227,21 @@ static int pm8008_regulator_probe(struct platform_device *pdev) return 0; } +static const struct pm8008_match_data pm8008_data = { + .has_stepper_ctl_reg = true, + .regulator_data = pm8008_reg_data, + .num_regulators = ARRAY_SIZE(pm8008_reg_data), +}; + +static const struct pm8008_match_data pm8010_data = { + .has_stepper_ctl_reg = false, + .regulator_data = pm8010_reg_data, + .num_regulators = ARRAY_SIZE(pm8010_reg_data), +}; + static const struct platform_device_id pm8008_regulator_id_table[] = { - { .name = "pm8008-regulator" }, + { .name = "pm8008-regulator", .driver_data = (kernel_ulong_t)&pm8008_data }, + { .name = "pm8010-regulator", .driver_data = (kernel_ulong_t)&pm8010_data }, { } }; MODULE_DEVICE_TABLE(platform, pm8008_regulator_id_table); From 6ac5a3aa7536a71aaef9021bcb5dd9822c6eeca7 Mon Sep 17 00:00:00 2001 From: Dhruvin Rajpura Date: Fri, 18 Sep 2026 22:12:47 +0530 Subject: [PATCH 0367/1133] FROMLIST: regulator: qcom-pm8008: Add PM8010 mode support Implement set_mode/get_mode support for PM8010 LDOs using the mode control and status registers to allow clients to vote for LDO modes. Mode voting is not supported in the PM8008 LDOs. Link: https://lore.kernel.org/all/20260918-pm8010_i2c_support-v1-3-de33d78fad9d@oss.qualcomm.com/ Signed-off-by: Dhruvin Rajpura Signed-off-by: Jishnu Prakash Tested-by: Oleg Keri # Lenovo Yoga Slim 7x Gen 11 (Glymur) --- drivers/regulator/qcom-pm8008-regulator.c | 75 ++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/qcom-pm8008-regulator.c b/drivers/regulator/qcom-pm8008-regulator.c index b484c0f73eeac..9758809a6322d 100644 --- a/drivers/regulator/qcom-pm8008-regulator.c +++ b/drivers/regulator/qcom-pm8008-regulator.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -24,9 +25,19 @@ #define LDO_VSET_LB_REG 0x40 +#define LDO_MODE_CTL1_REG 0x45 +#define MODE_PRIMARY_MASK GENMASK(2, 0) +#define LDO_MODE_NPM 7 +#define LDO_MODE_LPM 4 + #define LDO_ENABLE_REG 0x46 #define ENABLE_BIT BIT(7) +#define LDO_STATUS1_REG 0x08 +#define MODE_STATE_MASK GENMASK(1, 0) +#define MODE_STATE_NPM 3 +#define MODE_STATE_LPM 2 + struct pm8008_regulator { struct regmap *regmap; struct regulator_desc desc; @@ -134,6 +145,51 @@ static int pm8008_regulator_get_voltage_sel(struct regulator_dev *rdev) return regulator_map_voltage_linear_range(rdev, uV, INT_MAX); } +static int pm8010_regulator_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct pm8008_regulator *preg = rdev_get_drvdata(rdev); + unsigned int val; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val = LDO_MODE_NPM; + break; + case REGULATOR_MODE_IDLE: + val = LDO_MODE_LPM; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(preg->regmap, preg->base + LDO_MODE_CTL1_REG, + MODE_PRIMARY_MASK, val); +} + +static unsigned int pm8010_regulator_get_mode(struct regulator_dev *rdev) +{ + struct pm8008_regulator *preg = rdev_get_drvdata(rdev); + unsigned int val; + int ret; + + ret = regmap_read(preg->regmap, preg->base + LDO_STATUS1_REG, &val); + if (ret < 0) + return REGULATOR_MODE_INVALID; + + return (val & MODE_STATE_MASK) == MODE_STATE_NPM ? + REGULATOR_MODE_NORMAL : REGULATOR_MODE_IDLE; +} + +static unsigned int pm8010_regulator_of_map_mode(unsigned int mode) +{ + switch (mode) { + case REGULATOR_MODE_NORMAL: + case REGULATOR_MODE_IDLE: + return mode; + default: + return REGULATOR_MODE_INVALID; + } +} + static const struct regulator_ops pm8008_regulator_ops = { .list_voltage = regulator_list_voltage_linear_range, .set_voltage_sel = pm8008_regulator_set_voltage_sel, @@ -143,6 +199,17 @@ static const struct regulator_ops pm8008_regulator_ops = { .is_enabled = regulator_is_enabled_regmap, }; +static const struct regulator_ops pm8010_regulator_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = pm8008_regulator_set_voltage_sel, + .get_voltage_sel = pm8008_regulator_get_voltage_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_mode = pm8010_regulator_set_mode, + .get_mode = pm8010_regulator_get_mode, +}; + static int pm8008_regulator_probe(struct platform_device *pdev) { const struct pm8008_match_data *match_data; @@ -155,6 +222,7 @@ static int pm8008_regulator_probe(struct platform_device *pdev) struct regulator_dev *rdev; struct regmap *regmap; unsigned int val; + bool is_pm8010; int ret, i; id = platform_get_device_id(pdev); @@ -169,6 +237,9 @@ static int pm8008_regulator_probe(struct platform_device *pdev) if (!regmap) return -EINVAL; + is_pm8010 = of_device_is_compatible(to_i2c_client(dev->parent)->dev.of_node, + "qcom,pm8010-i2c"); + for (i = 0; i < match_data->num_regulators; i++) { data = &match_data->regulator_data[i]; @@ -185,7 +256,9 @@ static int pm8008_regulator_probe(struct platform_device *pdev) desc->supply_name = data->supply_name; desc->of_match = data->name; desc->regulators_node = of_match_ptr("regulators"); - desc->ops = &pm8008_regulator_ops; + desc->ops = is_pm8010 ? &pm8010_regulator_ops : &pm8008_regulator_ops; + if (is_pm8010) + desc->of_map_mode = pm8010_regulator_of_map_mode; desc->type = REGULATOR_VOLTAGE; desc->owner = THIS_MODULE; From 564360f8a6bc3e57964f1ea9893dfdda4fa4d423 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 18 Sep 2026 22:12:48 +0530 Subject: [PATCH 0368/1133] FROMLIST: mfd: qcom-pm8008: Add PM8010 support PM8010 is effectively the next generation of PM8008. The device is generally designed to serve the exact same function - power camera sensors and the associated supporting hardware. PM8010 supports both I2C and SPMI communications. The latter case is already handled, since it reuses the same peripherals as other PMICs. The I2C front-end is more less the same to the one of PM8008. Plumb in the necessary changes to support it. Link: https://lore.kernel.org/all/20260918-pm8010_i2c_support-v1-4-de33d78fad9d@oss.qualcomm.com/ Signed-off-by: Konrad Dybcio Co-developed-by: Dhruvin Rajpura Signed-off-by: Dhruvin Rajpura Co-developed-by: Jishnu Prakash Signed-off-by: Jishnu Prakash Tested-by: Oleg Keri # Lenovo Yoga Slim 7x Gen 11 (Glymur) --- drivers/mfd/qcom-pm8008.c | 67 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c index 60204cc9a2dc6..ed656f0d6df25 100644 --- a/drivers/mfd/qcom-pm8008.c +++ b/drivers/mfd/qcom-pm8008.c @@ -34,6 +34,7 @@ enum { PM8008_GPIO1, PM8008_GPIO2, PM8008_NUM_PERIPHS, + PM8010_NUM_PERIPHS = 2, }; #define PM8008_PERIPH_0_BASE 0x900 @@ -55,6 +56,10 @@ enum { #define PM8008_IRQ_GPIO1 6 #define PM8008_IRQ_GPIO2 7 +#define PM8010_IRQ_MISC_MBG_FAULT 0 +/* 1-3 are unused */ +#define PM8010_IRQ_MISC_LDO_OCP 4 + enum { SET_TYPE_INDEX, POLARITY_HI_INDEX, @@ -88,6 +93,12 @@ static const struct regmap_irq pm8008_irqs[] = { _IRQ(PM8008_IRQ_GPIO2, PM8008_GPIO2, BIT(0), IRQ_TYPE_SENSE_MASK), }; +static const struct regmap_irq pm8010_irqs[] = { + _IRQ(PM8010_IRQ_MISC_MBG_FAULT, PM8008_MISC, BIT(0), IRQ_TYPE_EDGE_RISING), + _IRQ(PM8010_IRQ_MISC_LDO_OCP, PM8008_MISC, BIT(4), IRQ_TYPE_EDGE_RISING), + _IRQ(PM8008_IRQ_TEMP_ALARM, PM8008_TEMP_ALARM, BIT(0), IRQ_TYPE_SENSE_MASK), +}; + static const unsigned int pm8008_periph_base[] = { PM8008_PERIPH_0_BASE, PM8008_PERIPH_1_BASE, @@ -158,6 +169,25 @@ static const struct regmap_irq_chip pm8008_irq_chip = { .get_irq_reg = pm8008_get_irq_reg, }; +static const struct regmap_irq_chip pm8010_irq_chip = { + .name = "pm8010", + .main_status = I2C_INTR_STATUS_BASE, + .num_main_regs = 1, + .irqs = pm8010_irqs, + .num_irqs = ARRAY_SIZE(pm8010_irqs), + .num_regs = PM8010_NUM_PERIPHS, + .status_base = INT_LATCHED_STS_OFFSET, + .mask_base = INT_EN_CLR_OFFSET, + .unmask_base = INT_EN_SET_OFFSET, + .mask_unmask_non_inverted = true, + .ack_base = INT_LATCHED_CLR_OFFSET, + .config_base = pm8008_config_regs, + .num_config_bases = ARRAY_SIZE(pm8008_config_regs), + .num_config_regs = PM8010_NUM_PERIPHS, + .set_type_config = pm8008_set_type_config, + .get_irq_reg = pm8008_get_irq_reg, +}; + static const struct regmap_config qcom_mfd_regmap_cfg = { .name = "primary", .reg_bits = 16, @@ -183,6 +213,17 @@ static const struct mfd_cell pm8008_cells[] = { MFD_CELL_NAME("pm8008-gpio"), }; +static const struct mfd_cell pm8010_cells[] = { + MFD_CELL_NAME("pm8010-regulator"), + MFD_CELL_RES("qpnp-temp-alarm", pm8008_temp_res), +}; + +struct pm8008_match_data { + const struct regmap_irq_chip *irq_chip_desc; + const struct mfd_cell *mfd_cells; + int num_mfd_cells; +}; + static void devm_irq_domain_fwnode_release(void *data) { struct fwnode_handle *fwnode = data; @@ -193,6 +234,7 @@ static void devm_irq_domain_fwnode_release(void *data) static int pm8008_probe(struct i2c_client *client) { struct regmap_irq_chip_data *irq_data; + const struct pm8008_match_data *data; struct device *dev = &client->dev; struct regmap *regmap, *regmap2; struct fwnode_handle *fwnode; @@ -201,6 +243,10 @@ static int pm8008_probe(struct i2c_client *client) char *name; int ret; + data = device_get_match_data(dev); + if (!data) + return dev_err_probe(dev, -ENODATA, "Missing driver match data\n"); + dummy = devm_i2c_new_dummy_device(dev, client->adapter, client->addr + 1); if (IS_ERR(dummy)) { ret = PTR_ERR(dummy); @@ -246,7 +292,7 @@ static int pm8008_probe(struct i2c_client *client) return ret; ret = devm_regmap_add_irq_chip_fwnode(dev, fwnode, regmap, client->irq, - IRQF_SHARED, 0, &pm8008_irq_chip, &irq_data); + IRQF_SHARED, 0, data->irq_chip_desc, &irq_data); if (ret) { dev_err(dev, "failed to add IRQ chip: %d\n", ret); return ret; @@ -255,13 +301,26 @@ static int pm8008_probe(struct i2c_client *client) /* Needed by GPIO driver. */ dev_set_drvdata(dev, regmap_irq_get_domain(irq_data)); - return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, pm8008_cells, - ARRAY_SIZE(pm8008_cells), NULL, 0, + return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, data->mfd_cells, + data->num_mfd_cells, NULL, 0, regmap_irq_get_domain(irq_data)); } +static const struct pm8008_match_data pm8008_data = { + .irq_chip_desc = &pm8008_irq_chip, + .mfd_cells = pm8008_cells, + .num_mfd_cells = ARRAY_SIZE(pm8008_cells), +}; + +static const struct pm8008_match_data pm8010_data = { + .irq_chip_desc = &pm8010_irq_chip, + .mfd_cells = pm8010_cells, + .num_mfd_cells = ARRAY_SIZE(pm8010_cells), +}; + static const struct of_device_id pm8008_match[] = { - { .compatible = "qcom,pm8008", }, + { .compatible = "qcom,pm8008", .data = &pm8008_data }, + { .compatible = "qcom,pm8010-i2c", .data = &pm8010_data }, { }, }; MODULE_DEVICE_TABLE(of, pm8008_match); From 1d40e08823906c94a556d359c6a71a11f8c7ae1d Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 18 Sep 2026 22:12:49 +0530 Subject: [PATCH 0369/1133] FROMLIST: dt-bindings: mfd: pm8008: Make interrupts optional Some designs integrate the PMIC with the interrupt pin left unconnected, deliberately. That of course compromises some functionality, but the core function of programming the voltage regulators remains there. Link: https://lore.kernel.org/all/20260918-pm8010_i2c_support-v1-5-de33d78fad9d@oss.qualcomm.com/ Signed-off-by: Konrad Dybcio Co-developed-by: Jishnu Prakash Signed-off-by: Jishnu Prakash Acked-by: Rob Herring (Arm) Tested-by: Oleg Keri # Lenovo Yoga Slim 7x Gen 11 (Glymur) --- Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml b/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml index 2701aa755f310..3c0febc8152b1 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml @@ -90,7 +90,6 @@ properties: required: - compatible - reg - - interrupts - vdd-l1-l2-supply - vdd-l3-l4-supply - vdd-l5-supply @@ -99,10 +98,11 @@ required: - gpio-controller - "#gpio-cells" - gpio-ranges - - interrupt-controller - - "#interrupt-cells" - "#thermal-sensor-cells" +dependencies: + interrupt-controller: [ interrupts, "#interrupt-cells" ] + additionalProperties: false examples: From 6455a0b1ee79be3cb57efac7c91773652b5a9fb9 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 18 Sep 2026 22:12:50 +0530 Subject: [PATCH 0370/1133] FROMLIST: mfd: qcom-pm8008: Tolerate missing interrupt PM8010 is often wired up with the interrupt pin tied to ground. Only register the IRQ infrastructure if we have a parent irq. Link: https://lore.kernel.org/all/20260918-pm8010_i2c_support-v1-6-de33d78fad9d@oss.qualcomm.com/ Signed-off-by: Konrad Dybcio Co-developed-by: Dhruvin Rajpura Signed-off-by: Dhruvin Rajpura Co-developed-by: Jishnu Prakash Signed-off-by: Jishnu Prakash Tested-by: Oleg Keri # Lenovo Yoga Slim 7x Gen 11 (Glymur) --- drivers/mfd/qcom-pm8008.c | 45 +++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c index ed656f0d6df25..77e4f6c04ac7a 100644 --- a/drivers/mfd/qcom-pm8008.c +++ b/drivers/mfd/qcom-pm8008.c @@ -233,7 +233,7 @@ static void devm_irq_domain_fwnode_release(void *data) static int pm8008_probe(struct i2c_client *client) { - struct regmap_irq_chip_data *irq_data; + struct regmap_irq_chip_data *irq_data = NULL; const struct pm8008_match_data *data; struct device *dev = &client->dev; struct regmap *regmap, *regmap2; @@ -277,33 +277,36 @@ static int pm8008_probe(struct i2c_client *client) */ usleep_range(1000, 2000); - name = devm_kasprintf(dev, GFP_KERNEL, "%pOF-internal", dev->of_node); - if (!name) - return -ENOMEM; + if (client->irq) { + name = devm_kasprintf(dev, GFP_KERNEL, "%pOF-internal", dev->of_node); + if (!name) + return -ENOMEM; - name = strreplace(name, '/', ':'); + name = strreplace(name, '/', ':'); - fwnode = irq_domain_alloc_named_fwnode(name); - if (!fwnode) - return -ENOMEM; + fwnode = irq_domain_alloc_named_fwnode(name); + if (!fwnode) + return -ENOMEM; - ret = devm_add_action_or_reset(dev, devm_irq_domain_fwnode_release, fwnode); - if (ret) - return ret; + ret = devm_add_action_or_reset(dev, devm_irq_domain_fwnode_release, fwnode); + if (ret) + return ret; - ret = devm_regmap_add_irq_chip_fwnode(dev, fwnode, regmap, client->irq, - IRQF_SHARED, 0, data->irq_chip_desc, &irq_data); - if (ret) { - dev_err(dev, "failed to add IRQ chip: %d\n", ret); - return ret; - } + ret = devm_regmap_add_irq_chip_fwnode(dev, fwnode, regmap, client->irq, + IRQF_SHARED, 0, data->irq_chip_desc, + &irq_data); + if (ret) { + dev_err(dev, "failed to add IRQ chip: %d\n", ret); + return ret; + } - /* Needed by GPIO driver. */ - dev_set_drvdata(dev, regmap_irq_get_domain(irq_data)); + /* Needed by GPIO driver. */ + dev_set_drvdata(dev, regmap_irq_get_domain(irq_data)); + } return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, data->mfd_cells, - data->num_mfd_cells, NULL, 0, - regmap_irq_get_domain(irq_data)); + data->num_mfd_cells, NULL, 0, + regmap_irq_get_domain(irq_data)); } static const struct pm8008_match_data pm8008_data = { From 308c7f9ce807688e1e02a38fec7ea53a2842291e Mon Sep 17 00:00:00 2001 From: Raj Aryan Date: Mon, 24 Aug 2026 20:19:13 +0530 Subject: [PATCH 0371/1133] FROMLIST: arm64: dts: qcom: Add PMIC thermal support for Agatti QRB2210-RB1 platform Add ADC channels for msm, quiet and xo thermistors along with their ADC thermal bridge nodes and thermal zones for PMIC thermal mitigation. Link: https://lore.kernel.org/all/20260824-pm4125-adc-thermal-v1-1-3b67ef2eccb2@oss.qualcomm.com/ Signed-off-by: Raj Aryan --- arch/arm64/boot/dts/qcom/qrb2210-rb1.dts | 91 ++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts index bf6fb12ad9906..c4038c1f1e886 100644 --- a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts +++ b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts @@ -7,6 +7,7 @@ #include #include +#include #include "agatti.dtsi" #include "pm4125.dtsi" @@ -33,6 +34,68 @@ }; }; + msm_therm_bridge: msm-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM3_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; + + quiet_therm_bridge: quiet-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_AMUX_THM2_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; + + xo_therm_bridge: xo-therm-bridge { + compatible = "generic-adc-thermal"; + io-channels = <&pm4125_adc ADC5_XO_THERM_100K_PU>; + io-channel-names = "sensor-channel"; + #thermal-sensor-cells = <0>; + }; + + thermal-zones { + sys-1-thermal { + polling-delay-passive = <2000>; + thermal-sensors = <&msm_therm_bridge>; + + trips { + active-config0 { + temperature = <80000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-2-thermal { + polling-delay-passive = <2000>; + thermal-sensors = <&quiet_therm_bridge>; + + trips { + active-config0 { + temperature = <80000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + + sys-3-thermal { + polling-delay-passive = <2000>; + thermal-sensors = <&xo_therm_bridge>; + + trips { + active-config0 { + temperature = <80000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + }; + gpio-keys { compatible = "gpio-keys"; label = "gpio-keys"; @@ -333,6 +396,34 @@ }; }; +&pm4125_adc { + status = "okay"; + + channel@4c { + reg = ; + label = "xo_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4e { + reg = ; + label = "quiet_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; + + channel@4f { + reg = ; + label = "msm_therm"; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,pre-scaling = <1 1>; + }; +}; + &i2c2_gpio { clock-frequency = <400000>; status = "okay"; From 7c750e6cb657e3c5d87642349975099e2a79228c Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Thu, 1 Oct 2026 19:03:56 +0530 Subject: [PATCH 0372/1133] FROMLIST: regulator: dt-bindings: Add 'regulator-off-on-delay-us' property Add a new property 'regulator-off-on-delay-us' to specify a minimum delay between disabling and re-enabling a regulator. This is useful in cases where a regulator discharges slowly and needs significant time to reach a safe reset level, and re-enabling it too early may lead to a brownout event. Link: https://lore.kernel.org/all/20261001-regulator-off-on-delay-v4-1-258ba9612da8@oss.qualcomm.com/ Suggested-by: Saikiran Signed-off-by: Jishnu Prakash --- Documentation/devicetree/bindings/regulator/regulator.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/regulator.yaml b/Documentation/devicetree/bindings/regulator/regulator.yaml index 019aeb664caec..73e1bea87adbf 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/regulator.yaml @@ -243,6 +243,11 @@ properties: description: Maximum difference between current and target voltages that can be changed safely in a single step. + regulator-off-on-delay-us: + description: Specifies a minimum delay in microseconds between disabling and + re-enabling the regulator. This is needed for regulators that discharge + slowly and require a significant delay to drop below brownout thresholds. + patternProperties: ".*-supply$": description: Input supply phandle(s) for this node From 5a0936f8e34fcfe41b31ed4668a800a706aac28c Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Thu, 1 Oct 2026 19:03:56 +0530 Subject: [PATCH 0373/1133] FROMLIST: regulator: dt-bindings: qcom,rpmh-regulator: Add debounce delay property Add 'qcom,regulator-off-debounce-delay-us' to describe the time to wait for an enable vote after a disable vote, before actually sending the disable request to RPMh. Some consumers toggle a regulator off and back on in quick succession as part of their normal operation, a behavior this driver has no control over. The appropriate debounce window to absorb this varies by which consumer(s) are wired to a given rail and how they use it, so it is exposed as a per-regulator property rather than a fixed value. It is placed in the qcom,rpmh-regulator binding and vendor-prefixed because the underlying deferred-disable mechanism is specific to this driver's RPMh command handling. Link: https://lore.kernel.org/all/20261001-regulator-off-on-delay-v4-3-258ba9612da8@oss.qualcomm.com/ Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Jishnu Prakash --- .../bindings/regulator/qcom,rpmh-regulator.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml index 31d2330d8422a..b16ca27c3b8a1 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml @@ -137,6 +137,14 @@ properties: description: BOB regulator node. properties: regulator-off-on-delay-us: true + qcom,regulator-off-debounce-delay-us: + description: + Time in microseconds to wait for an enable vote after a disable + vote, before actually disabling the regulator in hardware. This is + needed for consumers that may toggle a regulator off and back on + in quick succession as part of their normal operation, a behavior + this driver has no control over, so as to avoid needlessly + power-cycling the regulator in hardware. dependencies: regulator-allow-set-load: [ regulator-allowed-modes ] @@ -148,6 +156,14 @@ patternProperties: description: smps/ldo regulator nodes(s). properties: regulator-off-on-delay-us: true + qcom,regulator-off-debounce-delay-us: + description: + Time in microseconds to wait for an enable vote after a disable + vote, before actually disabling the regulator in hardware. This is + needed for consumers that may toggle a regulator off and back on + in quick succession as part of their normal operation, a behavior + this driver has no control over, so as to avoid needlessly + power-cycling the regulator in hardware. dependencies: regulator-allow-set-load: [ regulator-allowed-modes ] From 5771e49317c22aac63a7428f683b9e8ef77aa1fd Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Thu, 1 Oct 2026 19:03:56 +0530 Subject: [PATCH 0374/1133] FROMLIST: regulator: qcom-rpmh: Add debounce delay before disabling regulator Some consumers rapidly toggle a regulator off and back on again, for example a driver that disables its supply on -EPROBE_DEFER and re-enables it on the next probe attempt. Sending the disable request to RPMh immediately in this case causes needless power cycling of the rail, and in some cases the driver instead avoids calling regulator_disable() altogether to sidestep this, at the cost of leaving the regulator enabled and triggering the core's "unbalanced disables" and late-cleanup warnings. Add support for a new 'qcom,regulator-off-debounce-delay-us' property. When set, a disable vote is not sent to RPMh immediately; instead a cancelable delayed work item is queued to send it after the configured delay. If an enable vote arrives before the delay expires, the pending work is canceled and the rail is left untouched, avoiding the unnecessary disable/enable bounce. If no enable vote arrives, the disable request is sent once the delay elapses. This complements the existing 'regulator-off-on-delay-us' handling: that property enforces a minimum time the rail must stay physically off before it can be safely re-enabled (a hardware discharge/POR constraint), whereas this new delay defers sending the disable request in the first place, absorbing quick bounces before they ever reach the hardware. The two have no dependency on each other and can be used together. The deferred disable work item can run after the regulator has been registered, so cache the regulator_dev pointer in struct rpmh_vreg and thread it explicitly through _rpmh_regulator_set_enable_state() rather than relying on the regulator_dev argument that was previously only available at the regulator core's enable()/disable() call sites. Link: https://lore.kernel.org/all/20261001-regulator-off-on-delay-v4-4-258ba9612da8@oss.qualcomm.com/ Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Jishnu Prakash --- drivers/regulator/qcom-rpmh-regulator.c | 114 ++++++++++++++++++++++-- 1 file changed, 108 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 02c513960fece..9e105f3736e9b 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -5,8 +5,10 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ #include +#include #include #include +#include #include #include #include @@ -15,6 +17,7 @@ #include #include #include +#include #include #include @@ -160,6 +163,27 @@ struct rpmh_vreg_hw_data { * @voltage_selector: Selector used for get_voltage_sel() and * set_voltage_sel() callbacks * @mode: RPMh VRM regulator current framework mode + * @rdev: Regulator device pointer registered for this + * regulator + * @delayed_off_work: Delayed worker used to defer sending a disable + * request to RPMh, so that a quick subsequent + * enable vote can cancel it instead of causing a + * disable/enable bounce on the rail + * @debounce_delay: Time in microseconds to wait for an enable vote + * after a disable vote, before actually sending + * the disable request to RPMh + * @off_on_delay: Minimum time in microseconds to wait after the + * disable request for this regulator has actually + * been sent to RPMh, before allowing it to be + * enabled again. This is tracked locally instead + * of via rdesc.off_on_delay whenever + * debounce_delay is configured so that it can be + * measured from the real disable time instead of + * from the time the debounced disable request was + * merely queued. + * @last_off: Time at which the disable request for this + * regulator was last actually sent to RPMh. Only + * used when debounce_delay is configured. */ struct rpmh_vreg { struct device *dev; @@ -172,6 +196,11 @@ struct rpmh_vreg { bool bypassed; int voltage_selector; unsigned int mode; + struct regulator_dev *rdev; + struct delayed_work delayed_off_work; + unsigned int debounce_delay; + unsigned int off_on_delay; + ktime_t last_off; }; /** @@ -293,10 +322,9 @@ static int rpmh_regulator_is_enabled(struct regulator_dev *rdev) return vreg->enabled; } -static int rpmh_regulator_set_enable_state(struct regulator_dev *rdev, - bool enable) +static int _rpmh_regulator_set_enable_state(struct rpmh_vreg *vreg, + struct regulator_dev *rdev, bool enable) { - struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); struct tcs_cmd cmd = { .addr = vreg->addr + RPMH_REGULATOR_REG_ENABLE, .data = enable, @@ -306,7 +334,8 @@ static int rpmh_regulator_set_enable_state(struct regulator_dev *rdev, if (vreg->enabled == -EINVAL && vreg->voltage_selector != -ENOTRECOVERABLE) { ret = _rpmh_regulator_vrm_set_voltage_sel(rdev, - vreg->voltage_selector, true); + vreg->voltage_selector, + true); if (ret < 0) return ret; } @@ -318,13 +347,54 @@ static int rpmh_regulator_set_enable_state(struct regulator_dev *rdev, return ret; } +static int rpmh_regulator_set_enable_state(struct regulator_dev *rdev, + bool enable) +{ + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); + + return _rpmh_regulator_set_enable_state(vreg, rdev, enable); +} + +static void rpmh_delayed_off_work(struct work_struct *work) +{ + struct rpmh_vreg *vreg = container_of(work, + struct rpmh_vreg, delayed_off_work.work); + + if (!_rpmh_regulator_set_enable_state(vreg, vreg->rdev, false)) + vreg->last_off = ktime_get_boottime(); +} + static int rpmh_regulator_enable(struct regulator_dev *rdev) { + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); + s64 remaining; + + if (vreg->debounce_delay) { + if (cancel_delayed_work_sync(&vreg->delayed_off_work)) + return 0; + + if (vreg->off_on_delay) { + remaining = ktime_us_delta(ktime_add_us(vreg->last_off, + vreg->off_on_delay), + ktime_get_boottime()); + if (remaining > 0) + fsleep(remaining); + } + } + return rpmh_regulator_set_enable_state(rdev, true); } static int rpmh_regulator_disable(struct regulator_dev *rdev) { + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); + + if (vreg->debounce_delay) { + queue_delayed_work(system_percpu_wq, &vreg->delayed_off_work, + usecs_to_jiffies(vreg->debounce_delay)); + return 0; + } + return rpmh_regulator_set_enable_state(rdev, false); } @@ -481,6 +551,13 @@ static const struct regulator_ops rpmh_regulator_xob_ops = { .is_enabled = rpmh_regulator_is_enabled, }; +static void rpmh_regulator_cancel_delayed_off_work(void *data) +{ + struct rpmh_vreg *vreg = data; + + cancel_delayed_work_sync(&vreg->delayed_off_work); +} + /** * rpmh_regulator_init_vreg() - initialize all attributes of an rpmh-regulator * @vreg: Pointer to the individual rpmh-regulator resource @@ -504,6 +581,7 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev, const struct rpmh_vreg_init_data *rpmh_data; struct regulator_init_data *init_data; struct regulator_dev *rdev; + u32 off_on_delay = 0; int ret; vreg->dev = dev; @@ -552,8 +630,24 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev, vreg->always_wait_for_ack = of_property_read_bool(node, "qcom,always-wait-for-ack"); - of_property_read_u32(node, "regulator-off-on-delay-us", - &vreg->rdesc.off_on_delay); + of_property_read_u32(node, "regulator-off-on-delay-us", &off_on_delay); + + of_property_read_u32(node, "qcom,regulator-off-debounce-delay-us", + &vreg->debounce_delay); + + if (vreg->debounce_delay) { + /* + * The disable request to RPMh is deferred until the debounce + * delay elapses, so off_on_delay must be measured from that + * point rather than from when disable() returns. Enforce it + * locally instead of delegating to the regulator core. + */ + vreg->off_on_delay = off_on_delay; + + INIT_DELAYED_WORK(&vreg->delayed_off_work, rpmh_delayed_off_work); + } else { + vreg->rdesc.off_on_delay = off_on_delay; + } vreg->rdesc.owner = THIS_MODULE; vreg->rdesc.type = REGULATOR_VOLTAGE; @@ -583,6 +677,14 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev, node, ret); return ret; } + vreg->rdev = rdev; + + if (vreg->debounce_delay) { + ret = devm_add_action_or_reset(dev, rpmh_regulator_cancel_delayed_off_work, + vreg); + if (ret) + return ret; + } dev_dbg(dev, "%pOFn regulator registered for RPMh resource %s @ 0x%05X\n", node, rpmh_resource_name, vreg->addr); From 1a79b72a0cc7403223bfcc05d6a44e7b817baf78 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Thu, 1 Oct 2026 19:03:56 +0530 Subject: [PATCH 0375/1133] Revert "FROMLIST: dt-bindings: regulator: qcom,rpmh: Allow regulator-off-on-delay-us" This reverts commit e4ae86bcb1e5543b48e8fe28ddbd8738d548b114. The 'regulator-off-on-delay-us' property is now documented in the common regulator.yaml schema (see "regulator: dt-bindings: Add 'regulator-off-on-delay-us' property"), which qcom,rpmh-regulator.yaml already references via $ref: regulator.yaml#. The explicit per-node allow-list entries added here are therefore redundant. Signed-off-by: Jishnu Prakash --- .../devicetree/bindings/regulator/qcom,rpmh-regulator.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml index b16ca27c3b8a1..68afc22e5d72f 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml @@ -136,7 +136,6 @@ properties: unevaluatedProperties: false description: BOB regulator node. properties: - regulator-off-on-delay-us: true qcom,regulator-off-debounce-delay-us: description: Time in microseconds to wait for an enable vote after a disable @@ -155,7 +154,6 @@ patternProperties: unevaluatedProperties: false description: smps/ldo regulator nodes(s). properties: - regulator-off-on-delay-us: true qcom,regulator-off-debounce-delay-us: description: Time in microseconds to wait for an enable vote after a disable From d517c3e1ca6db876b9d2c1946971c27fcae3649f Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Wed, 22 Jul 2026 21:42:07 +0530 Subject: [PATCH 0376/1133] usb: typec: ucsi: ucsi_glink: Prevent suspend during UCSI notification handling When the system is suspended and a UCSI event arrives (such as USB plug-in), the GLINK interrupt (with IRQF_NO_SUSPEND flag) fires and it eventually calls the pmic_glink_ucsi_callback(), which schedules notify_work to handle the connector change. However, since no wakeup source is held, the system can re-enter suspend soon after the interrupt handler returns, before notify_work has completed running, and the USB plug-in event would not be handled. There was an earlier attempt to address this at the GLINK driver level, by making the GLINK interrupt wakeup-capable, ("rpmsg: glink: Make glink smem interrupt wakeup capable") [1], but upstream reviewers suggested a different approach, preferring wakeup logic to be handled in the client driver. To avoid losing UCSI notifications in this way, register ucsi_glink as a wakeup-capable device in the probe, and call pm_wakeup_dev_event() with hard=true before scheduling notify_work. The hard wakeup aborts any in-progress suspend, and the timed wakeup source keeps the system awake long enough for the notify_work call to run. [1] https://lore.kernel.org/all/20240603073648.3475123-1-quic_deesin@quicinc.com/ Link: https://patch.msgid.link/20260722-ucsi_glink_wakeup-v2-1-b43dee56df24@oss.qualcomm.com Signed-off-by: Jishnu Prakash --- drivers/usb/typec/ucsi/ucsi_glink.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c index 1db0c88d817e6..d74065cdb1459 100644 --- a/drivers/usb/typec/ucsi/ucsi_glink.c +++ b/drivers/usb/typec/ucsi/ucsi_glink.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,12 @@ #define UC_UCSI_WRITE_BUF_REQ 0x12 #define UC_UCSI_USBC_NOTIFY_IND 0x13 +/* + * Wakeup timeout to allow USB event notification processing to + * complete before device suspends. + */ +#define UCSI_GLINK_WAKEUP_TIMEOUT_MS 50 + struct ucsi_read_buf_req_msg { struct pmic_glink_hdr hdr; }; @@ -342,6 +349,7 @@ static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv) pmic_glink_ucsi_write_ack(ucsi, data, len); break; case UC_UCSI_USBC_NOTIFY_IND: + pm_wakeup_dev_event(ucsi->dev, UCSI_GLINK_WAKEUP_TIMEOUT_MS, true); schedule_work(&ucsi->notify_work); break; } @@ -405,6 +413,8 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, ucsi->dev = dev; dev_set_drvdata(dev, ucsi); + device_init_wakeup(dev, true); + INIT_WORK(&ucsi->notify_work, pmic_glink_ucsi_notify); INIT_WORK(&ucsi->register_work, pmic_glink_ucsi_register); init_completion(&ucsi->read_ack); From 3f984fc657d88659eb1a8cf9f3aac9d4c578aaef Mon Sep 17 00:00:00 2001 From: Anandu Krishnan E Date: Fri, 26 Jun 2026 21:42:48 +0530 Subject: [PATCH 0377/1133] WORKAROUND: misc: fastrpc: use dev_dbg for absent remote heap memory On platforms where remote heap memory is not present, dev_err() can flood the kernel log. Use dev_dbg() instead to reduce log verbosity in this expected condition. Signed-off-by: Anandu Krishnan E --- drivers/misc/fastrpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index af18ff1992eed..b251c3b5a8b86 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1470,7 +1470,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, if (!cctx->remote_heap_addr || !cctx->remote_heap_size) { err = -ENOMEM; - dev_err(fl->sctx->dev, + dev_dbg(fl->sctx->dev, "remote heap memory region is not added\n"); return err; } From 134b05efd759adb3434c80dc428516647fe0a321 Mon Sep 17 00:00:00 2001 From: Jianping Li Date: Thu, 25 Jun 2026 11:30:44 +0800 Subject: [PATCH 0378/1133] FROMLIST: misc: fastrpc: avoid duplicate DMA mappings in fastrpc_create_maps() DMA handles passed as invoke arguments (scalars beyond nbufs) may refer to the same dma_buf fd as an input/output buffer argument. Taking an extra reference for such DMA handle maps leads to duplicate mappings and an unbalanced reference count, since DMA handle maps are released separately when the DSP returns the fd through the fdlist. Fix this by not taking an extra reference for DMA handle arguments (take_ref = false) and tagging them with FASTRPC_MAP_DMA_HANDLE. As these maps are borrowed references, fastrpc_get_args() re-validates the map via fastrpc_map_lookup() before dereferencing it, so it is not used after being freed. fastrpc_put_args() only releases maps flagged as FASTRPC_MAP_DMA_HANDLE and clears the flag to guarantee the map is freed exactly once. Link: https://lore.kernel.org/all/20260914104019.492-1-jianping.li@oss.qualcomm.com/ Fixes: 10df039834f84 ("misc: fastrpc: Skip reference for DMA handles") Cc: stable@kernel.org Signed-off-by: Jianping Li --- drivers/misc/fastrpc.c | 56 +++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index b251c3b5a8b86..a223e9f70fe71 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -52,6 +52,9 @@ #define FASTRPC_CTXID_SEQ_SHIFT 16 #define FASTRPC_CTXID_SEQ_MASK GENMASK_ULL(63, 16) +/* Map the DMA handle in the invoke call for backward compatibility */ +#define FASTRPC_MAP_DMA_HANDLE 0x20000 + /* * Newer DSP firmware implements a PD (Protection Domain) notification * framework that sends PD state notifications upon request. The PD exit @@ -251,6 +254,7 @@ struct fastrpc_map { u64 len; u64 raddr; u32 attr; + u32 flags; struct kref refcount; }; @@ -881,7 +885,7 @@ static dma_addr_t fastrpc_compute_dma_addr(struct fastrpc_user *fl, dma_addr_t s } static int fastrpc_map_attach(struct fastrpc_user *fl, int fd, - u64 len, u32 attr, struct fastrpc_map **ppmap) + u64 len, u32 attr, struct fastrpc_map **ppmap, int mflags) { struct fastrpc_session_ctx *sess = fl->sctx; struct fastrpc_map *map = NULL; @@ -898,6 +902,7 @@ static int fastrpc_map_attach(struct fastrpc_user *fl, int fd, map->fl = fl; map->fd = fd; + map->flags = mflags; map->buf = dma_buf_get(fd); if (IS_ERR(map->buf)) { err = PTR_ERR(map->buf); @@ -972,13 +977,13 @@ static int fastrpc_map_attach(struct fastrpc_user *fl, int fd, return err; } -static int fastrpc_map_create(struct fastrpc_user *fl, int fd, - u64 len, u32 attr, struct fastrpc_map **ppmap) +static int fastrpc_map_create(struct fastrpc_user *fl, int fd, u64 len, u32 attr, + struct fastrpc_map **ppmap, bool take_ref, int mflags) { - if (!fastrpc_map_lookup(fl, fd, ppmap, true)) + if (!fastrpc_map_lookup(fl, fd, ppmap, take_ref)) return 0; - return fastrpc_map_attach(fl, fd, len, attr, ppmap); + return fastrpc_map_attach(fl, fd, len, attr, ppmap, mflags); } /* @@ -1049,23 +1054,25 @@ static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx) int i, err; for (i = 0; i < ctx->nscalars; ++i) { + bool take_ref = i < ctx->nbufs; + int mflags = 0; if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1 || ctx->args[i].length == 0) continue; - if (i < ctx->nbufs) - err = fastrpc_map_create(ctx->fl, ctx->args[i].fd, - ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]); - else - err = fastrpc_map_attach(ctx->fl, ctx->args[i].fd, - ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]); + /* Set the DMA handle mapping flag for DMA handles */ + if (i >= ctx->nbufs) + mflags = FASTRPC_MAP_DMA_HANDLE; + + err = fastrpc_map_create(ctx->fl, ctx->args[i].fd, ctx->args[i].length, + ctx->args[i].attr, &ctx->maps[i], take_ref, mflags); if (err) { dev_err(dev, "Error Creating map %d\n", err); return -EINVAL; } - } + return 0; } @@ -1197,6 +1204,16 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) list[i].num = ctx->args[i].length ? 1 : 0; list[i].pgidx = i; if (ctx->maps[i]) { + /* It is possible that map is created with + * mflags FASTRPC_MAP_DMA_HANDLE and take_ref + * is false. Check if map still exists or is + * being freed as take_ref is false + */ + if (fastrpc_map_lookup(ctx->fl, ctx->args[i].fd, + &ctx->maps[i], false)) { + ctx->maps[i] = NULL; + return -EINVAL; + } pages[i].addr = ctx->maps[i]->dma_addr; pages[i].size = ctx->maps[i]->size; } @@ -1246,8 +1263,17 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx, for (i = 0; i < FASTRPC_MAX_FDLIST; i++) { if (!fdlist[i]) break; - if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap, false)) + /* + * DMA handle maps are released when the DSP returns the corresponding fd in + * fdlist. The DSP is expected to return a specific fd only once in fdlist, + * so no two fastrpc_put_args() paths should clear the DMA_HANDLE flag for + * the same map concurrently. + */ + if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap, false) && + mmap->flags == FASTRPC_MAP_DMA_HANDLE) { + mmap->flags = 0; fastrpc_map_put(mmap); + } } return ret; @@ -1608,7 +1634,7 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl, fl->pd = USER_PD; if (init.filelen && init.filefd) { - err = fastrpc_map_create(fl, init.filefd, init.filelen, 0, &map); + err = fastrpc_map_create(fl, init.filefd, init.filelen, 0, &map, true, 0); if (err) goto err; } @@ -2214,7 +2240,7 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp) return -EFAULT; /* create SMMU mapping */ - err = fastrpc_map_create(fl, req.fd, req.length, 0, &map); + err = fastrpc_map_create(fl, req.fd, req.length, 0, &map, true, 0); if (err) { dev_err(dev, "failed to map buffer, fd = %d\n", req.fd); return err; From ed70458b165d458b8d286f644c15df5faf75a03a Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Wed, 23 Sep 2026 14:09:33 +0530 Subject: [PATCH 0379/1133] FROMLIST: misc: fastrpc: iterate CB nodes manually instead of of_platform_populate of_platform_populate() only guarantees that child devices are registered, not that their probes have completed before it returns. This creates a window where fastrpc_cb_init() may not have run for all context bank nodes, leaving the channel context partially initialised. Introduce fastrpc_cb_devices_create() to iterate over child DT nodes directly and call fastrpc_cb_init() synchronously for each qcom,fastrpc-compute-cb node. This ensures all context banks are fully initialised before fastrpc_rpmsg_probe() returns. Introduce fastrpc_cb_devices_destroy() as the symmetric counterpart. Before destroying the CB platform devices, invalidate all sessions under the channel lock so that any fastrpc_user still holding a reference to the channel context cannot acquire a new session backed by a destroyed device. Since fastrpc_cb_driver is no longer needed as an independent platform driver, remove it along with its match table and remove callback. Use module_rpmsg_driver() now that only a single driver registration remains. Link: https://lore.kernel.org/all/20260923-dup-sessions-v5-1-e953133a1827@oss.qualcomm.com/ Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 104 ++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index a223e9f70fe71..a36d2011bdc30 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -2359,7 +2359,7 @@ static const struct file_operations fastrpc_fops = { .compat_ioctl = fastrpc_device_ioctl, }; -static int fastrpc_cb_probe(struct platform_device *pdev) +static int fastrpc_cb_init(struct platform_device *pdev) { struct fastrpc_channel_ctx *cctx; struct fastrpc_session_ctx *sess; @@ -2381,7 +2381,7 @@ static int fastrpc_cb_probe(struct platform_device *pdev) spin_lock_irqsave(&cctx->lock, flags); if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) { spin_unlock_irqrestore(&cctx->lock, flags); - dev_err(&pdev->dev, "too many sessions\n"); + dev_err(dev, "too many sessions\n"); return -ENOSPC; } dma_bits = cctx->soc_data->dma_addr_bits_default; @@ -2415,37 +2415,63 @@ static int fastrpc_cb_probe(struct platform_device *pdev) return 0; } -static void fastrpc_cb_remove(struct platform_device *pdev) +static void fastrpc_cb_devices_destroy(struct rpmsg_device *rpdev) { - struct fastrpc_channel_ctx *cctx = dev_get_drvdata(pdev->dev.parent); - struct fastrpc_session_ctx *sess = dev_get_drvdata(&pdev->dev); + struct fastrpc_channel_ctx *cctx = dev_get_drvdata(&rpdev->dev); + struct device *rdev = &rpdev->dev; + struct platform_device *pdev; + struct device_node *np; unsigned long flags; int i; spin_lock_irqsave(&cctx->lock, flags); - for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) { - if (cctx->session[i].sid == sess->sid) { - cctx->session[i].valid = false; - cctx->sesscount--; + for (i = 0; i < cctx->sesscount; i++) + cctx->session[i].valid = false; + spin_unlock_irqrestore(&cctx->lock, flags); + + for_each_available_child_of_node(rdev->of_node, np) { + if (!of_device_is_compatible(np, "qcom,fastrpc-compute-cb")) { + of_node_put(np); + continue; } + + pdev = of_find_device_by_node(np); + of_node_put(np); + if (pdev) + of_platform_device_destroy(&pdev->dev, NULL); } - spin_unlock_irqrestore(&cctx->lock, flags); } -static const struct of_device_id fastrpc_match_table[] = { - { .compatible = "qcom,fastrpc-compute-cb" }, - { } -}; +static int fastrpc_cb_devices_create(struct rpmsg_device *rpdev) +{ + struct device *rdev = &rpdev->dev; + struct platform_device *pdev; + struct device_node *np; + int err; -static struct platform_driver fastrpc_cb_driver = { - .probe = fastrpc_cb_probe, - .remove = fastrpc_cb_remove, - .driver = { - .name = "qcom,fastrpc-cb", - .of_match_table = fastrpc_match_table, - .suppress_bind_attrs = true, - }, -}; + for_each_available_child_of_node(rdev->of_node, np) { + if (!of_device_is_compatible(np, "qcom,fastrpc-compute-cb")) { + of_node_put(np); + continue; + } + + pdev = of_platform_device_create(np, NULL, rdev); + if (!pdev) { + of_node_put(np); + fastrpc_cb_devices_destroy(rpdev); + return -EINVAL; + } + + err = fastrpc_cb_init(pdev); + if (err) { + of_node_put(np); + fastrpc_cb_devices_destroy(rpdev); + return err; + } + } + + return 0; +} static int fastrpc_device_register(struct device *dev, struct fastrpc_channel_ctx *cctx, bool is_secured, const char *domain) @@ -2665,7 +2691,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) data->rpdev = rpdev; dev_set_drvdata(&rpdev->dev, data); - err = of_platform_populate(rdev->of_node, NULL, NULL, rdev); + err = fastrpc_cb_devices_create(rpdev); if (err) goto err_deregister_fdev; @@ -2737,7 +2763,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) &cctx->remote_heap_addr, cctx->remote_heap_size, err); } - of_platform_depopulate(&rpdev->dev); + fastrpc_cb_devices_destroy(rpdev); fastrpc_channel_ctx_put(cctx); } @@ -2824,33 +2850,7 @@ static struct rpmsg_driver fastrpc_driver = { }, }; -static int fastrpc_init(void) -{ - int ret; - - ret = platform_driver_register(&fastrpc_cb_driver); - if (ret < 0) { - pr_err("fastrpc: failed to register cb driver\n"); - return ret; - } - - ret = register_rpmsg_driver(&fastrpc_driver); - if (ret < 0) { - pr_err("fastrpc: failed to register rpmsg driver\n"); - platform_driver_unregister(&fastrpc_cb_driver); - return ret; - } - - return 0; -} -module_init(fastrpc_init); - -static void fastrpc_exit(void) -{ - platform_driver_unregister(&fastrpc_cb_driver); - unregister_rpmsg_driver(&fastrpc_driver); -} -module_exit(fastrpc_exit); +module_rpmsg_driver(fastrpc_driver); MODULE_DESCRIPTION("Qualcomm FastRPC"); MODULE_LICENSE("GPL v2"); From 1db0daf09db8a2707af148a7611cd7c424c3a92c Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Wed, 23 Sep 2026 14:09:34 +0530 Subject: [PATCH 0380/1133] FROMLIST: misc: fastrpc: move ADSP duplicate session creation to the driver For ADSP, only a limited number of FastRPC context banks (CBs) are available. Each CB supports a single session, which means only a few processes can run on ADSP simultaneously. If all sessions are consumed by fastrpc daemons, no session remains available when a user application starts, causing the application to fail. To work around this, qcom,nsessions = <5> was set in DT to duplicate sessions inline during fastrpc_cb_init(). This policy does not belong in DT and should be handled at the driver level instead. Remove the qcom,nsessions DT property read and the per-CB duplication logic from fastrpc_cb_init(). After all context banks have been initialised in fastrpc_rpmsg_probe(), append FASTRPC_DUP_SESSIONS (4) copies of the last session for the ADSP domain. Link: https://lore.kernel.org/all/20260923-dup-sessions-v5-2-e953133a1827@oss.qualcomm.com/ Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index a36d2011bdc30..eea35f292c4b9 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -34,6 +34,7 @@ #define CDSP_DOMAIN_ID (3) #define GDSP_DOMAIN_ID (4) #define FASTRPC_MAX_SESSIONS 14 +#define FASTRPC_DUP_SESSIONS 4 #define FASTRPC_MAX_VMIDS 16 #define FASTRPC_ALIGN 128 #define FASTRPC_MAX_FDLIST 16 @@ -2364,7 +2365,6 @@ static int fastrpc_cb_init(struct platform_device *pdev) struct fastrpc_channel_ctx *cctx; struct fastrpc_session_ctx *sess; struct device *dev = &pdev->dev; - int i, sessions = 0; unsigned long flags; u32 dma_bits; u32 sid = 0; @@ -2374,7 +2374,6 @@ static int fastrpc_cb_init(struct platform_device *pdev) if (!cctx) return -EINVAL; - of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions); if (of_property_read_u32(dev->of_node, "reg", &sid)) dev_info(dev, "FastRPC Session ID not specified in DT\n"); @@ -2395,16 +2394,6 @@ static int fastrpc_cb_init(struct platform_device *pdev) if (cctx->domain_id == CDSP_DOMAIN_ID) dma_bits = cctx->soc_data->dma_addr_bits_cdsp; - if (sessions > 0) { - struct fastrpc_session_ctx *dup_sess; - - for (i = 1; i < sessions; i++) { - if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) - break; - dup_sess = &cctx->session[cctx->sesscount++]; - memcpy(dup_sess, sess, sizeof(*dup_sess)); - } - } spin_unlock_irqrestore(&cctx->lock, flags); rc = dma_set_mask(dev, DMA_BIT_MASK(dma_bits)); if (rc) { @@ -2695,6 +2684,22 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) if (err) goto err_deregister_fdev; + if (data->domain_id == ADSP_DOMAIN_ID && data->sesscount > 0) { + struct fastrpc_session_ctx *last_sess; + struct fastrpc_session_ctx *dup_sess; + unsigned long flags; + + spin_lock_irqsave(&data->lock, flags); + last_sess = &data->session[data->sesscount - 1]; + for (i = 0; i < FASTRPC_DUP_SESSIONS; i++) { + if (data->sesscount >= FASTRPC_MAX_SESSIONS) + break; + dup_sess = &data->session[data->sesscount++]; + memcpy(dup_sess, last_sess, sizeof(*dup_sess)); + } + spin_unlock_irqrestore(&data->lock, flags); + } + return 0; err_deregister_fdev: From 44c3282ae7ea8aab345148fb9c3d1d4a4d3dd05f Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Wed, 23 Sep 2026 14:09:35 +0530 Subject: [PATCH 0381/1133] FROMLIST: dt-bindings: misc: qcom,fastrpc: deprecate qcom,nsessions The qcom,nsessions property was used to duplicate FastRPC sessions inline during context bank initialisation. Session duplication is now handled at the driver level, making this DT property redundant. Mark it deprecated. Link: https://lore.kernel.org/all/20260923-dup-sessions-v5-3-e953133a1827@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Vinayak Katoch --- Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml b/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml index 49d2a5e8ba39f..e945c8ba75e30 100644 --- a/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml +++ b/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml @@ -101,8 +101,10 @@ patternProperties: qcom,nsessions: $ref: /schemas/types.yaml#/definitions/uint32 default: 1 + deprecated: true description: > A value indicating how many sessions can share this context bank. + Session duplication is now handled by the driver. required: - compatible From f0a6f29c9d69c1fe17ab19122e0daaa7f24caafc Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Thu, 1 Oct 2026 16:31:25 +0530 Subject: [PATCH 0382/1133] FROMLIST: misc: fastrpc: fix NULL rpdev dereference when session alloc fails When a fastrpc client process dies abnormally without closing its file descriptor, fastrpc_device_release() is never called and the compute-cb session slot is never freed. The abnormal client death on the DSP side triggers a glink channel teardown which propagates up through the rpmsg bus and calls fastrpc_rpmsg_remove(). fastrpc_rpmsg_remove() nulls cctx->rpdev before calling misc_deregister(). If a concurrent open() enters fastrpc_device_open() in this window and fastrpc_session_alloc() returns NULL (sessions exhausted by the leaked slot), the error path dereferences cctx->rpdev->dev causing a NULL pointer dereference: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 pc : fastrpc_device_open+0x1b8/0x258 [fastrpc] Call trace: fastrpc_device_open+0x1b8/0x258 [fastrpc] (P) misc_open+0xd8/0x1a0 Fix by moving misc_deregister() before rpdev = NULL. misc_open() and misc_deregister() both take misc_mtx, so misc_deregister() will either block until fastrpc_device_open() completes or prevent new opens from entering it entirely. Link: https://lore.kernel.org/all/20261001-fastrpc-probe-fixes-v1-1-1376d93b8b3e@oss.qualcomm.com/ Fixes: 7c11df42d0c7 ("misc: fastrpc: Fix device_open when no session is available") Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index eea35f292c4b9..184e91c1c06f9 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -2732,6 +2732,12 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) struct fastrpc_user *user; unsigned long flags; + if (cctx->fdevice) + misc_deregister(&cctx->fdevice->miscdev); + + if (cctx->secure_fdevice) + misc_deregister(&cctx->secure_fdevice->miscdev); + /* No invocations past this point */ spin_lock_irqsave(&cctx->lock, flags); cctx->rpdev = NULL; @@ -2739,12 +2745,6 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) fastrpc_notify_users(user); spin_unlock_irqrestore(&cctx->lock, flags); - if (cctx->fdevice) - misc_deregister(&cctx->fdevice->miscdev); - - if (cctx->secure_fdevice) - misc_deregister(&cctx->secure_fdevice->miscdev); - list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node) list_del(&buf->node); From 13417cf2cd6a246a45d0a4b835699a900c3dd44c Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Thu, 1 Oct 2026 16:31:26 +0530 Subject: [PATCH 0383/1133] FROMLIST: misc: fastrpc: fix init ordering race in rpmsg probe fastrpc_device_register() calls misc_register() which makes the device node visible to userspace. However, kref_init(), spin_lock_init(), INIT_LIST_HEAD(), dev_set_drvdata() and fastrpc_cb_devices_create() were all called after the switch/misc_register block, leaving a window where userspace can open the device and call fastrpc_device_open() on a partially initialised channel context. On a concurrent open(), fastrpc_channel_ctx_get() calls kref_get() on a kzalloc-zeroed, never kref_init()'d refcount of 0, triggering: refcount_t: addition on 0; use-after-free. Call trace: refcount_warn_saturate+0x120/0x148 (P) fastrpc_device_open+0x204/0x258 [fastrpc] misc_open+0xd8/0x1a0 Additionally, fastrpc_cb_devices_create() not having run means sesscount is still 0, so fastrpc_session_alloc() returns NULL and fastrpc_device_open() hits the error path which calls fastrpc_channel_ctx_put() on the already-bogus refcount. This triggers the free callback, kfree()-ing the channel context. A subsequent IRQ-path fastrpc_rpmsg_callback() then dereferences the freed spinlock: Unable to handle kernel paging request at virtual address ffffcd5841510ca0 Internal error: Oops: 0000000096000047 [#1] SMP Call trace: queued_spin_lock_slowpath+0x414/0x5e0 (P) _raw_spin_lock_irqsave+0x74/0x90 fastrpc_rpmsg_callback+0x4c/0xf0 [fastrpc] qcom_glink_native_rx+0x6c4/0xf10 qcom_glink_smem_intr+0x1c/0x38 [qcom_glink_smem] Kernel panic - not syncing: Oops: Fatal exception in interrupt Fix by moving all channel context initialisation (kref_init, spin_lock_init, INIT_LIST_HEAD, idr_init, dev_set_drvdata) and fastrpc_cb_devices_create() before fastrpc_device_register(), ensuring the struct is fully ready before the device node is visible to userspace. Add err_depopulate label in the error path since fastrpc_cb_devices_create() now runs before misc_register(); a fastrpc_device_register() failure must call fastrpc_cb_devices_destroy() to clean up the compute-cb children before freeing data. Link: https://lore.kernel.org/all/20261001-fastrpc-probe-fixes-v1-2-1376d93b8b3e@oss.qualcomm.com/ Fixes: 3abe3ab3cdab ("misc: fastrpc: add secure domain support") Signed-off-by: Vinayak Katoch --- drivers/misc/fastrpc.c | 43 ++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 184e91c1c06f9..eca4c15a623e0 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -2640,6 +2640,23 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) data->poll_mode_supported = soc_data->poll_mode_supported || of_machine_get_match(fastrpc_poll_supported_machines); + kref_init(&data->refcount); + atomic_set(&data->ctx_seq, 0); + + 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->invoke_interrupted_mmaps); + spin_lock_init(&data->lock); + idr_init(&data->ctx_idr); + data->domain_id = domain_id; + data->rpdev = rpdev; + dev_set_drvdata(&rpdev->dev, data); + + err = fastrpc_cb_devices_create(rpdev); + if (err) + goto err_free_data; + switch (domain_id) { case ADSP_DOMAIN_ID: case MDSP_DOMAIN_ID: @@ -2648,7 +2665,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) data->unsigned_support = false; err = fastrpc_device_register(rdev, data, secure_dsp, domain); if (err) - goto err_free_data; + goto err_depopulate; break; case CDSP_DOMAIN_ID: case GDSP_DOMAIN_ID: @@ -2656,7 +2673,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) /* Create both device nodes so that we can allow both Signed and Unsigned PD */ err = fastrpc_device_register(rdev, data, true, domain); if (err) - goto err_free_data; + goto err_depopulate; err = fastrpc_device_register(rdev, data, false, domain); if (err) @@ -2664,26 +2681,9 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) break; default: err = -EINVAL; - goto err_free_data; + goto err_depopulate; } - kref_init(&data->refcount); - atomic_set(&data->ctx_seq, 0); - - 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->invoke_interrupted_mmaps); - spin_lock_init(&data->lock); - idr_init(&data->ctx_idr); - data->domain_id = domain_id; - data->rpdev = rpdev; - dev_set_drvdata(&rpdev->dev, data); - - err = fastrpc_cb_devices_create(rpdev); - if (err) - goto err_deregister_fdev; - if (data->domain_id == ADSP_DOMAIN_ID && data->sesscount > 0) { struct fastrpc_session_ctx *last_sess; struct fastrpc_session_ctx *dup_sess; @@ -2708,6 +2708,9 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) if (data->secure_fdevice) misc_deregister(&data->secure_fdevice->miscdev); +err_depopulate: + fastrpc_cb_devices_destroy(rpdev); + err_free_data: kfree(data); return err; From 6d256cabf13ce0817eb7546d0ee379cfcc3c3760 Mon Sep 17 00:00:00 2001 From: Abhinav Parihar Date: Thu, 24 Sep 2026 11:22:39 +0530 Subject: [PATCH 0384/1133] FROMLIST: misc: fastrpc: Add cache maintenance for non-coherent platforms Some platforms using fastrpc do not support DMA coherency on HLOS. On such systems, explicit cache maintenance is required to ensure data consistency for RPC argument buffers. Add cache maintenance for argument buffers when operating on non-coherent platforms: - Flush input buffers before invoking RPC to ensure CPU writes are visible to the DSP - Invalidate output buffers after RPC completion to ensure DSP writes are visible to the CPU Introduce helper functions fastrpc_flush_args() and fastrpc_inv_args() to perform the required dma-buf cache operations. These are invoked only when the device is not marked as DMA coherent. The coherency capability is determined using the "dma-coherent" device tree property and stored per session context. This ensures correct data synchronization on platforms lacking DMA coherency, while avoiding unnecessary overhead on coherent systems. Link: https://lore.kernel.org/all/20260916185850.3686010-1-abhinav.parihar@oss.qualcomm.com/ Signed-off-by: Abhinav Parihar --- drivers/misc/fastrpc.c | 77 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index eca4c15a623e0..86c6c63b842f5 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -219,6 +219,7 @@ struct fastrpc_buf_overlap { u64 mstart; u64 mend; u64 offset; + bool do_cmo; }; struct fastrpc_buf { @@ -295,6 +296,7 @@ struct fastrpc_session_ctx { int sid; bool used; bool valid; + bool coherent; }; struct fastrpc_soc_data { @@ -662,7 +664,9 @@ static int olaps_cmp(const void *a, const void *b) static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) { u64 max_end = 0; + int max_raix = -1; int i; + int inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); for (i = 0; i < ctx->nbufs; ++i) { ctx->olaps[i].start = ctx->args[i].ptr; @@ -682,6 +686,9 @@ static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) if (ctx->olaps[i].end > max_end) { max_end = ctx->olaps[i].end; } else { + if ((max_raix < inbufs && ctx->olaps[i].raix + 1 > inbufs) || + (ctx->olaps[i].raix < inbufs && max_raix + 1 > inbufs)) + ctx->olaps[i].do_cmo = true; ctx->olaps[i].mend = 0; ctx->olaps[i].mstart = 0; } @@ -691,6 +698,7 @@ static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) ctx->olaps[i].mstart = ctx->olaps[i].start; ctx->olaps[i].offset = 0; max_end = ctx->olaps[i].end; + max_raix = ctx->olaps[i].raix; } } } @@ -710,6 +718,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( INIT_LIST_HEAD(&ctx->node); ctx->fl = user; + ctx->sc = sc; ctx->nscalars = REMOTE_SCALARS_LENGTH(sc); ctx->nbufs = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc); @@ -735,7 +744,6 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( /* Take a reference to user, released in fastrpc_context_free() */ fastrpc_user_get(user); - ctx->sc = sc; ctx->retval = -1; ctx->pid = current->pid; ctx->client_id = user->client_id; @@ -1077,6 +1085,64 @@ static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx) return 0; } +static void fastrpc_flush_args(struct fastrpc_invoke_ctx *ctx) +{ + union fastrpc_remote_arg *rpra = ctx->rpra; + int i, inbufs, outbufs; + + inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); + outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); + + for (i = 0; i < inbufs + outbufs; ++i) { + int raix = ctx->olaps[i].raix; + struct fastrpc_map *map = ctx->maps[raix]; + + if (raix + 1 > inbufs) + continue; + if (!map || !map->buf) + continue; + + if (rpra[raix].buf.len && (ctx->olaps[i].mstart || ctx->olaps[i].do_cmo)) { + dma_buf_begin_cpu_access(map->buf, DMA_TO_DEVICE); + dma_buf_end_cpu_access(map->buf, DMA_TO_DEVICE); + } + } +} + +static void fastrpc_inv_args(struct fastrpc_invoke_ctx *ctx) +{ + union fastrpc_remote_arg *rpra = ctx->rpra; + int i, inbufs, outbufs; + + inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); + outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); + + for (i = 0; i < inbufs + outbufs; ++i) { + int raix = ctx->olaps[i].raix; + struct fastrpc_map *map = ctx->maps[raix]; + + if (raix + 1 <= inbufs) + continue; + if (!rpra[raix].buf.len) + continue; + if (!map || !map->buf) + continue; + + /* + * Skip invalidation if the argument overlaps with the + * RPC control header page. + */ + if (((uintptr_t)rpra & PAGE_MASK) == + ((uintptr_t)rpra[raix].buf.pv & PAGE_MASK)) + continue; + + if (ctx->olaps[i].mstart || ctx->olaps[i].do_cmo) { + dma_buf_begin_cpu_access(map->buf, DMA_FROM_DEVICE); + dma_buf_end_cpu_access(map->buf, DMA_FROM_DEVICE); + } + } +} + static struct fastrpc_invoke_buf *fastrpc_invoke_buf_start(union fastrpc_remote_arg *pra, int len) { return (struct fastrpc_invoke_buf *)(&pra[len]); @@ -1201,6 +1267,9 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) } } + if (!ctx->fl->sctx->coherent) + fastrpc_flush_args(ctx); + for (i = ctx->nbufs; i < ctx->nscalars; ++i) { list[i].num = ctx->args[i].length ? 1 : 0; list[i].pgidx = i; @@ -1405,6 +1474,8 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, if (err) goto bail; + if (!fl->sctx->coherent) + fastrpc_inv_args(ctx); /* make sure that all CPU memory writes are seen by DSP */ dma_wmb(); /* Send invoke buffer to remote dsp */ @@ -1425,6 +1496,9 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, /* make sure that all memory writes by DSP are seen by CPU */ dma_rmb(); + if (!fl->sctx->coherent) + fastrpc_inv_args(ctx); + /* populate all the output buffers with results */ err = fastrpc_put_args(ctx, kernel); if (err) @@ -2388,6 +2462,7 @@ static int fastrpc_cb_init(struct platform_device *pdev) sess->used = false; sess->valid = true; sess->dev = dev; + sess->coherent = of_property_read_bool(dev->of_node, "dma-coherent"); dev_set_drvdata(dev, sess); sess->sid = sid; From e808ccd13031b5c166064e9593d04384e03881b6 Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Mon, 2 Nov 2026 14:57:08 +0530 Subject: [PATCH 0385/1133] FROMLIST: misc: fastrpc: map ADSP remote heap into remoteproc IOMMU domain On Qualcomm platforms without Gunyah/QHEE, the kernel runs at EL2 without a separate hypervisor to manage inter-VM memory access control. In this configuration the remoteproc is assigned its own IOMMU domain, and any memory carveout the DSP must access requires an explicit mapping into that domain before the DSP can reach it. The existing code calls qcom_scm_assign_mem() to transfer ownership of the ADSP remote heap carveout from HLOS to the DSP VM. This SCM call is only meaningful when a separate hypervisor (e.g. Gunyah) is present to enforce inter-VM memory access control. On platforms without such a hypervisor, the carveout must instead be mapped into the remoteproc's IOMMU domain via an identity mapping (IOVA == PA) using iommu_map(). Without this mapping the DSP triggers an SMMU translation fault when accessing the remote heap during audio PD static process creation. Detect whether the remoteproc has an IOMMU by checking for the "iommus" property on the remoteproc DT node and store the result in a new use_iommu_map flag in fastrpc_channel_ctx. When the flag is set, map the carveout into the remoteproc's IOMMU domain instead of calling qcom_scm_assign_mem(). Introduce fastrpc_remote_heap_map() and fastrpc_remote_heap_unmap() helpers to encapsulate the IOMMU domain lookup and map/unmap operations, and a shared fastrpc_remote_heap_release() helper that tears the mapping (or SCM assignment) back down, used both from fastrpc_rpmsg_remove() and from fastrpc_rpmsg_probe()'s error path. Link: https://lore.kernel.org/all/20261027-fastrpc-kvm-iommu-v3-v3-1-f3cd5c030c78@oss.qualcomm.com/ Signed-off-by: Anandu Krishnan E Signed-off-by: Ekansh Gupta --- drivers/misc/fastrpc.c | 152 +++++++++++++++++++++++++++++++++++------ 1 file changed, 132 insertions(+), 20 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 86c6c63b842f5..8961b4fdb04e9 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -324,6 +325,8 @@ struct fastrpc_channel_ctx { /* Audio PD reserved remote heap region */ phys_addr_t remote_heap_addr; u64 remote_heap_size; + /* set when remoteproc has an IOMMU; use iommu_map instead of hyp_assign */ + bool use_iommu_map; u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES]; struct fastrpc_device *secure_fdevice; struct fastrpc_device *fdevice; @@ -2619,9 +2622,120 @@ static const struct of_device_id fastrpc_poll_supported_machines[] __maybe_unuse {}, }; +static struct device_node *fastrpc_get_rproc_node(struct device_node *node) +{ + struct device_node *parent, *rproc_node; + + parent = of_get_parent(node); + if (!parent) + return NULL; + + rproc_node = of_get_parent(parent); + of_node_put(parent); + + return rproc_node; +} + +static int fastrpc_remote_heap_map(struct device *rdev, + struct device_node *rproc_node, + phys_addr_t addr, u64 size) +{ + struct platform_device *rproc_pdev; + struct iommu_domain *domain; + int ret; + + rproc_pdev = of_find_device_by_node(rproc_node); + if (!rproc_pdev) { + dev_err(rdev, "failed to find remoteproc platform device\n"); + return -ENODEV; + } + + domain = iommu_get_domain_for_dev(&rproc_pdev->dev); + if (!domain) { + put_device(&rproc_pdev->dev); + dev_err(rdev, "no IOMMU domain for remoteproc\n"); + return -ENODEV; + } + + ret = iommu_map(domain, addr, addr, size, IOMMU_READ | IOMMU_WRITE, GFP_KERNEL); + if (ret) + dev_err(rdev, "failed to map remote heap phys=0x%llx size=0x%llx err=%d\n", + (u64)addr, size, ret); + + put_device(&rproc_pdev->dev); + return ret; +} + +static void fastrpc_remote_heap_unmap(struct rpmsg_device *rpdev, + phys_addr_t addr, u64 size) +{ + struct device_node *rproc_node; + struct platform_device *rproc_pdev; + struct iommu_domain *domain; + size_t unmapped; + + rproc_node = fastrpc_get_rproc_node(rpdev->dev.of_node); + if (!rproc_node) { + dev_warn(&rpdev->dev, "failed to find remoteproc node for heap unmap\n"); + return; + } + + rproc_pdev = of_find_device_by_node(rproc_node); + of_node_put(rproc_node); + if (!rproc_pdev) { + dev_warn(&rpdev->dev, "failed to find remoteproc platform device for heap unmap\n"); + return; + } + + domain = iommu_get_domain_for_dev(&rproc_pdev->dev); + if (!domain) { + dev_warn(&rpdev->dev, "no IOMMU domain for remoteproc during heap unmap\n"); + put_device(&rproc_pdev->dev); + return; + } + + unmapped = iommu_unmap(domain, addr, size); + if (unmapped != size) + dev_warn(&rpdev->dev, "partial/failed heap unmap: requested=0x%llx unmapped=0x%zx\n", + size, unmapped); + + put_device(&rproc_pdev->dev); +} + +static void fastrpc_remote_heap_release(struct fastrpc_channel_ctx *cctx, + struct rpmsg_device *rpdev) +{ + if (!cctx->remote_heap_size) + return; + + if (cctx->use_iommu_map) { + fastrpc_remote_heap_unmap(rpdev, cctx->remote_heap_addr, + cctx->remote_heap_size); + } else if (cctx->vmcount) { + u64 src_perms = 0; + int err, i; + struct qcom_scm_vmperm dst_perms; + + 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(cctx->remote_heap_addr, + cctx->remote_heap_size, &src_perms, + &dst_perms, 1); + if (err) + dev_err(&rpdev->dev, + "Failed to assign memory back to HLOS: addr %pa size %#llx err %d\n", + &cctx->remote_heap_addr, cctx->remote_heap_size, err); + } +} + static int fastrpc_init_reserved_mem(struct fastrpc_channel_ctx *cctx, struct device *rdev, u32 domain_id) { + struct device_node *rproc_node; struct resource res; u64 src_perms; int err; @@ -2648,6 +2762,19 @@ static int fastrpc_init_reserved_mem(struct fastrpc_channel_ctx *cctx, if (domain_id == ADSP_DOMAIN_ID) { cctx->remote_heap_addr = res.start; cctx->remote_heap_size = resource_size(&res); + + rproc_node = fastrpc_get_rproc_node(rdev->of_node); + if (rproc_node) + cctx->use_iommu_map = of_property_present(rproc_node, "iommus"); + + if (cctx->use_iommu_map) { + err = fastrpc_remote_heap_map(rdev, rproc_node, res.start, + resource_size(&res)); + of_node_put(rproc_node); + return err; + } + + of_node_put(rproc_node); } if (!cctx->vmcount) @@ -2730,7 +2857,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) err = fastrpc_cb_devices_create(rpdev); if (err) - goto err_free_data; + goto err_unmap_heap; switch (domain_id) { case ADSP_DOMAIN_ID: @@ -2786,6 +2913,9 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) err_depopulate: fastrpc_cb_devices_destroy(rpdev); +err_unmap_heap: + fastrpc_remote_heap_release(data, rpdev); + err_free_data: kfree(data); return err; @@ -2826,25 +2956,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_size && cctx->vmcount) { - u64 src_perms = 0; - int err, i; - struct qcom_scm_vmperm dst_perms; - - 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(cctx->remote_heap_addr, - cctx->remote_heap_size, &src_perms, - &dst_perms, 1); - if (err) - dev_err(&rpdev->dev, - "Failed to assign memory back to HLOS: addr %pa size %#llx err %d\n", - &cctx->remote_heap_addr, cctx->remote_heap_size, err); - } + fastrpc_remote_heap_release(cctx, rpdev); fastrpc_cb_devices_destroy(rpdev); From e4cb3e5daf9fb73577903b4df14995c74401d18a Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 23 Sep 2026 02:44:50 +0530 Subject: [PATCH 0386/1133] FROMLIST: net: pcs: xpcs: add Qualcomm Nord platform support Qualcomm Nord exposes the DesignWare XPCS register blocks through separate direct-MMIO windows instead of the standard contiguous MMD/register layout. Add accessors that translate MMD accesses to the Nord windows: MMD 3 (PCS), standard registers: SR_XS at 0x0000 MMD 3 (PCS), vendor registers: VR_XS at 0x2000 MMD 1 (PMA/PMD): SR_PMA at 0x3000 MMD 31 (VEND2), standard regs: SR_MII at 0x4000 MMD 31 (VEND2), vendor registers: VR_MII at 0x5000 Each register uses a 32-bit MMIO stride. The vendor bit is removed from the register index before calculating a vendor-window offset. Select these accessors using the Nord synthetic XPCS ID, allow its smaller direct-MMIO resource, and add the Nord USXGMII Clause 37 compatibility. Link: https://lore.kernel.org/netdev/20260923-qcom_xpcs_nord_emac-v1-4-4b1c682af70f@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- drivers/net/pcs/Makefile | 5 +- drivers/net/pcs/pcs-xpcs-plat.c | 17 ++++++- drivers/net/pcs/pcs-xpcs-qcom.c | 86 +++++++++++++++++++++++++++++++++ drivers/net/pcs/pcs-xpcs-qcom.h | 16 ++++++ drivers/net/pcs/pcs-xpcs.c | 13 +++++ include/linux/pcs/pcs-xpcs.h | 1 + 6 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 drivers/net/pcs/pcs-xpcs-qcom.c create mode 100644 drivers/net/pcs/pcs-xpcs-qcom.h diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile index f9f6cf2578d72..17a71182a4276 100644 --- a/drivers/net/pcs/Makefile +++ b/drivers/net/pcs/Makefile @@ -1,10 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 # Makefile for Linux PCS drivers -pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs.o pcs-xpcs-nxp.o pcs-xpcs-wx.o +pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs.o pcs-xpcs-plat.o \ + pcs-xpcs-nxp.o pcs-xpcs-qcom.o \ + pcs-xpcs-wx.o obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o -obj-$(CONFIG_PCS_XPCS_PLATFORM) += pcs-xpcs-plat.o obj-$(CONFIG_PCS_XPCS_ROCKCHIP) += pcs-xpcs-rk.o obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o diff --git a/drivers/net/pcs/pcs-xpcs-plat.c b/drivers/net/pcs/pcs-xpcs-plat.c index 6d2277594c6df..7175c96b77ac9 100644 --- a/drivers/net/pcs/pcs-xpcs-plat.c +++ b/drivers/net/pcs/pcs-xpcs-plat.c @@ -20,6 +20,7 @@ #include #include "pcs-xpcs.h" +#include "pcs-xpcs-qcom.h" /* Page select register for the indirect MMIO CSRs access */ #define DW_VR_CSR_VIEWPORT 0xff @@ -239,8 +240,14 @@ static int xpcs_mmio_write_c45(struct mii_bus *bus, int addr, int dev, return xpcs_mmio_write_reg_direct(pxpcs, dev, reg, val); } +static const struct dw_xpcs_plat_ops xpcs_qcom_ops = { + .reg_read = xpcs_qcom_reg_read, + .reg_write = xpcs_qcom_reg_write, +}; + static struct dw_xpcs_plat *xpcs_plat_create_data(struct platform_device *pdev) { + const struct dw_xpcs_info *info; struct dw_xpcs_plat *pxpcs; pxpcs = devm_kzalloc(&pdev->dev, sizeof(*pxpcs), GFP_KERNEL); @@ -248,6 +255,12 @@ static struct dw_xpcs_plat *xpcs_plat_create_data(struct platform_device *pdev) return ERR_PTR(-ENOMEM); pxpcs->pdev = pdev; + info = device_get_match_data(&pdev->dev); + if (!info) + return ERR_PTR(-EINVAL); + + if (info->pcs == QCOM_NORD_XPCS_ID) + pxpcs->ops = &xpcs_qcom_ops; dev_set_drvdata(&pdev->dev, pxpcs); @@ -285,7 +298,7 @@ static int xpcs_plat_init_res(struct dw_xpcs_plat *pxpcs) else spc_size = pxpcs->reg_width * SZ_2M; - if (resource_size(res) < spc_size) { + if (!pxpcs->ops && resource_size(res) < spc_size) { dev_err(dev, "Invalid reg-space size\n"); return -EINVAL; } @@ -496,8 +509,10 @@ DW_XPCS_INFO_DECLARE(xpcs_pma_gen4_3g, DW_XPCS_ID_NATIVE, DW_XPCS_PMA_GEN4_3G_ID DW_XPCS_INFO_DECLARE(xpcs_pma_gen4_6g, DW_XPCS_ID_NATIVE, DW_XPCS_PMA_GEN4_6G_ID); DW_XPCS_INFO_DECLARE(xpcs_pma_gen5_10g, DW_XPCS_ID_NATIVE, DW_XPCS_PMA_GEN5_10G_ID); DW_XPCS_INFO_DECLARE(xpcs_pma_gen5_12g, DW_XPCS_ID_NATIVE, DW_XPCS_PMA_GEN5_12G_ID); +DW_XPCS_INFO_DECLARE(xpcs_qcom_nord, QCOM_NORD_XPCS_ID, DW_XPCS_PMA_ID_NATIVE); static const struct of_device_id xpcs_of_ids[] = { + { .compatible = "qcom,nord-dw-xpcs", .data = &xpcs_qcom_nord }, { .compatible = "snps,dw-xpcs", .data = &xpcs_generic }, { .compatible = "snps,dw-xpcs-gen1-3g", .data = &xpcs_pma_gen1_3g }, { .compatible = "snps,dw-xpcs-gen2-3g", .data = &xpcs_pma_gen2_3g }, diff --git a/drivers/net/pcs/pcs-xpcs-qcom.c b/drivers/net/pcs/pcs-xpcs-qcom.c new file mode 100644 index 0000000000000..63c95c9514548 --- /dev/null +++ b/drivers/net/pcs/pcs-xpcs-qcom.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm DesignWare XPCS platform helpers + * + * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include + +#include "pcs-xpcs.h" +#include "pcs-xpcs-qcom.h" + +/* Qualcomm Nord direct MMIO XPCS windows. */ +#define QCOM_XPCS_SR_XS_BASE 0x0000 +#define QCOM_XPCS_VR_XS_BASE 0x2000 +#define QCOM_XPCS_SR_PMA_BASE 0x3000 +#define QCOM_XPCS_SR_MII_BASE 0x4000 +#define QCOM_XPCS_VR_MII_BASE 0x5000 + +static int xpcs_qcom_reg_offset(int dev, int reg) +{ + switch (dev) { + case MDIO_MMD_PCS: + if (reg & DW_VENDOR) + return QCOM_XPCS_VR_XS_BASE + + ((reg & ~DW_VENDOR) << 2); + + return QCOM_XPCS_SR_XS_BASE + (reg << 2); + + case MDIO_MMD_PMAPMD: + return QCOM_XPCS_SR_PMA_BASE + (reg << 2); + + case MDIO_MMD_VEND2: + if (reg >= DW_VENDOR) + return QCOM_XPCS_VR_MII_BASE + + ((reg - DW_VENDOR) << 2); + + return QCOM_XPCS_SR_MII_BASE + (reg << 2); + + default: + return -EOPNOTSUPP; + } +} + +int xpcs_qcom_reg_read(struct platform_device *pdev, void __iomem *reg_base, + int dev, int reg) +{ + int offset, ret; + + offset = xpcs_qcom_reg_offset(dev, reg); + if (offset < 0) + return offset; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) + return ret; + + ret = readl(reg_base + offset) & 0xffff; + + pm_runtime_put(&pdev->dev); + + return ret; +} + +int xpcs_qcom_reg_write(struct platform_device *pdev, void __iomem *reg_base, + int dev, int reg, u16 val) +{ + int offset, ret; + + offset = xpcs_qcom_reg_offset(dev, reg); + if (offset < 0) + return offset; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) + return ret; + + writel(val, reg_base + offset); + + pm_runtime_put(&pdev->dev); + + return 0; +} diff --git a/drivers/net/pcs/pcs-xpcs-qcom.h b/drivers/net/pcs/pcs-xpcs-qcom.h new file mode 100644 index 0000000000000..a1084f6a10a96 --- /dev/null +++ b/drivers/net/pcs/pcs-xpcs-qcom.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __PCS_XPCS_QCOM_H +#define __PCS_XPCS_QCOM_H + +#include +#include + +struct platform_device; + +int xpcs_qcom_reg_read(struct platform_device *pdev, void __iomem *reg_base, + int dev, int reg); +int xpcs_qcom_reg_write(struct platform_device *pdev, void __iomem *reg_base, + int dev, int reg, u16 val); + +#endif /* __PCS_XPCS_QCOM_H */ diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 17d6f34c7afcf..40e80ab7d0c40 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -1594,6 +1594,15 @@ static const struct dw_xpcs_compat nxp_sja1110_xpcs_compat[] = { } }; +static const struct dw_xpcs_compat qcom_nord_xpcs_compat[] = { + { + .interface = PHY_INTERFACE_MODE_USXGMII, + .supported = xpcs_usxgmii_features, + .an_mode = DW_AN_C37_USXGMII, + }, { + } +}; + static const struct dw_xpcs_desc xpcs_desc_list[] = { { .id = DW_XPCS_ID, @@ -1607,6 +1616,10 @@ static const struct dw_xpcs_desc xpcs_desc_list[] = { .id = NXP_SJA1110_XPCS_ID, .mask = DW_XPCS_ID_MASK, .compat = nxp_sja1110_xpcs_compat, + }, { + .id = QCOM_NORD_XPCS_ID, + .mask = DW_XPCS_ID_MASK, + .compat = qcom_nord_xpcs_compat, }, }; diff --git a/include/linux/pcs/pcs-xpcs.h b/include/linux/pcs/pcs-xpcs.h index 4ea995b70150e..0f69e14b2a4c8 100644 --- a/include/linux/pcs/pcs-xpcs.h +++ b/include/linux/pcs/pcs-xpcs.h @@ -26,6 +26,7 @@ enum dw_xpcs_pcs_id { DW_XPCS_ID_NATIVE = 0, NXP_SJA1105_XPCS_ID = 0x00000010, NXP_SJA1110_XPCS_ID = 0x00000020, + QCOM_NORD_XPCS_ID = 0x00000030, DW_XPCS_ID = 0x7996ced0, DW_XPCS_ID_MASK = 0xffffffff, }; From 8dca2cbde09741689929ffa55968c2616d415642 Mon Sep 17 00:00:00 2001 From: Jitendra Vegiraju Date: Thu, 2 Apr 2026 14:36:26 -0700 Subject: [PATCH 0387/1133] FROMLIST: net: stmmac: Add DW25GMAC support in stmmac core driver The DW25GMAC introduced a new DMA architecture called Hyper-DMA (HDMA) for virtualization scalability. This is realized by decoupling physical DMA channels(PDMA) from potentially large number of virtual DMA channels(VDMA). The VDMAs provide software abstraction to driver that map to PDMAs for frame transmission and reception. Since 25GMAC is a derivative of XGMAC, majority of IP is common to both. To add support for the HDMA in 25GMAC, a new instance of dma_ops, dw25gmac400_dma_ops is introduced. To support the current needs, a simple one-to-one mapping of dw25gmac's logical VDMA (channel) to TC to PDMAs is used. Most of the other dma operation functions in existing dwxgamc2_dma.c file are reused whereever applicable. Added setup function for DW25GMAC's stmmac_hwif_entry in stmmac core. Link: https://lore.kernel.org/netdev/20260402213629.1996133-2-jitendra.vegiraju@broadcom.com/ Signed-off-by: Jitendra Vegiraju Signed-off-by: Mohd Ayaan Anwar --- drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- drivers/net/ethernet/stmicro/stmmac/common.h | 12 +- .../net/ethernet/stmicro/stmmac/dw25gmac.c | 161 ++++++++++++++++++ .../net/ethernet/stmicro/stmmac/dw25gmac.h | 92 ++++++++++ .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 1 + .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 59 ++++--- .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 51 ++++++ drivers/net/ethernet/stmicro/stmmac/hwif.h | 1 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 17 +- include/linux/stmmac.h | 1 + 10 files changed, 371 insertions(+), 26 deletions(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dw25gmac.c create mode 100644 drivers/net/ethernet/stmicro/stmmac/dw25gmac.h diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index b16a456b730ec..e0a41307dd0a1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \ stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \ - stmmac_xdp.o stmmac_est.o stmmac_fpe.o stmmac_vlan.o \ + stmmac_xdp.o stmmac_est.o stmmac_fpe.o stmmac_vlan.o dw25gmac.o \ stmmac_pcs.o $(stmmac-y) stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index c74bc7c9750e9..cec0f9db4ebc5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -42,13 +42,18 @@ #define DWXGMAC_CORE_2_20 0x22 #define DWXLGMAC_CORE_2_00 0x20 +#define DW25GMAC_CORE_3_20 0x32 +#define DW25GMAC_CORE_4_00 0x40 + /* Device ID */ #define DWXGMAC_ID 0x76 +#define DW25GMAC_ID 0x55 #define DWXLGMAC_ID 0x27 static inline bool dwmac_is_xmac(enum dwmac_core_type core_type) { - return core_type == DWMAC_CORE_GMAC4 || core_type == DWMAC_CORE_XGMAC; + return core_type == DWMAC_CORE_GMAC4 || core_type == DWMAC_CORE_XGMAC || + core_type == DWMAC_CORE_25GMAC; } #define STMMAC_CHAN0 0 /* Always supported and default for all chips */ @@ -324,6 +329,9 @@ struct stmmac_safety_stats { #define PHY_INTF_GMII 0 #define PHY_INTF_RGMII 1 +/* DW25GMAC uses different encoding - defaults to XGMII */ +#define PHY_INTF_DW25GMAC_XGMII 0 + /* MSI defines */ #define STMMAC_MSI_VEC_MAX 32 @@ -594,6 +602,7 @@ struct mac_link { u32 speed2500; u32 speed5000; u32 speed10000; + u32 speed25000; } xgmii; struct { u32 speed25000; @@ -655,6 +664,7 @@ int dwmac100_setup(struct stmmac_priv *priv); int dwmac1000_setup(struct stmmac_priv *priv); int dwmac4_setup(struct stmmac_priv *priv); int dwxgmac2_setup(struct stmmac_priv *priv); +int dw25gmac_setup(struct stmmac_priv *priv); int dwxlgmac2_setup(struct stmmac_priv *priv); void stmmac_set_mac_addr(void __iomem *ioaddr, const u8 addr[6], diff --git a/drivers/net/ethernet/stmicro/stmmac/dw25gmac.c b/drivers/net/ethernet/stmicro/stmmac/dw25gmac.c new file mode 100644 index 0000000000000..82eb22bff73e0 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dw25gmac.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024-2026 Broadcom Corporation + */ +#include "stmmac.h" +#include "dwxgmac2.h" +#include "dw25gmac.h" + +u32 dw25gmac_decode_vdma_count(u32 regval) +{ + /* compressed encoding for vdma count */ + if (regval < 16) /* Direct mapping */ + return regval + 1; + else if (regval < 20) /* 20, 24, 28, 32 */ + return 20 + (regval - 16) * 4; + else if (regval < 24) /* 40, 48, 56, 64 */ + return 40 + (regval - 20) * 8; + else if (regval < 28) /* 80, 96, 112, 128 */ + return 80 + (regval - 24) * 16; + else /* not defined */ + return 0; +} + +static int rd_dma_ch_ind(void __iomem *ioaddr, u8 mode, u32 channel) +{ + u32 reg_val = 0; + + reg_val |= FIELD_PREP(XXVGMAC_MODE_SELECT, mode); + reg_val |= FIELD_PREP(XXVGMAC_ADDR_OFFSET, channel); + reg_val |= XXVGMAC_CMD_TYPE | XXVGMAC_OB; + writel(reg_val, ioaddr + XXVGMAC_DMA_CH_IND_CONTROL); + return readl(ioaddr + XXVGMAC_DMA_CH_IND_DATA); +} + +static void wr_dma_ch_ind(void __iomem *ioaddr, u8 mode, u32 channel, u32 val) +{ + u32 reg_val = 0; + + writel(val, ioaddr + XXVGMAC_DMA_CH_IND_DATA); + reg_val |= FIELD_PREP(XXVGMAC_MODE_SELECT, mode); + reg_val |= FIELD_PREP(XXVGMAC_ADDR_OFFSET, channel); + reg_val |= XGMAC_OB; + writel(reg_val, ioaddr + XXVGMAC_DMA_CH_IND_CONTROL); +} + +void dw25gmac_dma_init(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg) +{ + u32 tx_pdmas, rx_pdmas; + u32 hw_cap; + u32 value; + u32 i; + + value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE); + value &= ~(XGMAC_AAL | XGMAC_EAME); + if (dma_cfg->aal) + value |= XGMAC_AAL; + if (dma_cfg->eame) + value |= XGMAC_EAME; + writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE); + + /* Get PDMA counts from HW */ + hw_cap = readl(ioaddr + XGMAC_HW_FEATURE2); + tx_pdmas = FIELD_GET(XGMAC_HWFEAT_TXQCNT, hw_cap) + 1; + rx_pdmas = FIELD_GET(XGMAC_HWFEAT_RXQCNT, hw_cap) + 1; + + /* Initialize all PDMAs with burst length fields */ + for (i = 0; i < tx_pdmas; i++) { + value = rd_dma_ch_ind(ioaddr, MODE_TXEXTCFG, i); + value &= ~(XXVGMAC_TXPBL | XXVGMAC_TPBLX8_MODE); + if (dma_cfg->pblx8) + value |= XXVGMAC_TPBLX8_MODE; + value |= FIELD_PREP(XXVGMAC_TXPBL, dma_cfg->pbl); + wr_dma_ch_ind(ioaddr, MODE_TXEXTCFG, i, value); + } + + for (i = 0; i < rx_pdmas; i++) { + value = rd_dma_ch_ind(ioaddr, MODE_RXEXTCFG, i); + value &= ~(XXVGMAC_RXPBL | XXVGMAC_RPBLX8_MODE); + if (dma_cfg->pblx8) + value |= XXVGMAC_RPBLX8_MODE; + value |= FIELD_PREP(XXVGMAC_RXPBL, dma_cfg->pbl); + wr_dma_ch_ind(ioaddr, MODE_RXEXTCFG, i, value); + } +} + +void dw25gmac_dma_init_tx_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + dma_addr_t dma_addr, u32 chan) +{ + u32 value; + u32 tc; + + /* Descriptor cache size and prefetch threshold size */ + value = rd_dma_ch_ind(ioaddr, MODE_TXDESCCTRL, chan); + value &= ~XXVGMAC_TXDCSZ; + value |= FIELD_PREP(XXVGMAC_TXDCSZ, + XXVGMAC_TXDCSZ_256BYTES); + value &= ~XXVGMAC_TDPS; + value |= FIELD_PREP(XXVGMAC_TDPS, XXVGMAC_TDPS_HALF); + wr_dma_ch_ind(ioaddr, MODE_TXDESCCTRL, chan, value); + + /* Use one-to-one mapping between VDMA, TC, and PDMA. */ + tc = chan; + + /* 1-to-1 PDMA to TC mapping */ + value = rd_dma_ch_ind(ioaddr, MODE_TXEXTCFG, chan); + value &= ~XXVGMAC_TP2TCMP; + value |= FIELD_PREP(XXVGMAC_TP2TCMP, tc); + wr_dma_ch_ind(ioaddr, MODE_TXEXTCFG, chan, value); + + /* 1-to-1 VDMA to TC mapping */ + value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + value &= ~XXVGMAC_TVDMA2TCMP; + value |= FIELD_PREP(XXVGMAC_TVDMA2TCMP, tc); + writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + + writel(upper_32_bits(dma_addr), + ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(chan)); + writel(lower_32_bits(dma_addr), + ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(chan)); +} + +void dw25gmac_dma_init_rx_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + dma_addr_t dma_addr, u32 chan) +{ + u32 value; + u32 tc; + + /* Descriptor cache size and prefetch threshold size */ + value = rd_dma_ch_ind(ioaddr, MODE_RXDESCCTRL, chan); + value &= ~XXVGMAC_RXDCSZ; + value |= FIELD_PREP(XXVGMAC_RXDCSZ, + XXVGMAC_RXDCSZ_256BYTES); + value &= ~XXVGMAC_RDPS; + value |= FIELD_PREP(XXVGMAC_RDPS, XXVGMAC_RDPS_HALF); + wr_dma_ch_ind(ioaddr, MODE_RXDESCCTRL, chan, value); + + /* Use one-to-one mapping between VDMA, TC, and PDMA. */ + tc = chan; + + /* 1-to-1 PDMA to TC mapping */ + value = rd_dma_ch_ind(ioaddr, MODE_RXEXTCFG, chan); + value &= ~XXVGMAC_RP2TCMP; + value |= FIELD_PREP(XXVGMAC_RP2TCMP, tc); + wr_dma_ch_ind(ioaddr, MODE_RXEXTCFG, chan, value); + + /* 1-to-1 VDMA to TC mapping */ + value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + value &= ~XXVGMAC_RVDMA2TCMP; + value |= FIELD_PREP(XXVGMAC_RVDMA2TCMP, tc); + writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + + writel(upper_32_bits(dma_addr), + ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(chan)); + writel(lower_32_bits(dma_addr), + ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(chan)); +} diff --git a/drivers/net/ethernet/stmicro/stmmac/dw25gmac.h b/drivers/net/ethernet/stmicro/stmmac/dw25gmac.h new file mode 100644 index 0000000000000..b2eee66f04d58 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dw25gmac.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2024-2026 Broadcom Corporation + * DW25GMAC definitions. + */ +#ifndef __STMMAC_DW25GMAC_H__ +#define __STMMAC_DW25GMAC_H__ + +/* Hardware features */ +#define XXVGMAC_HWFEAT_VDMA_RXCNT GENMASK(16, 12) +#define XXVGMAC_HWFEAT_VDMA_TXCNT GENMASK(22, 18) + +/* DMA Indirect Registers*/ +#define XXVGMAC_DMA_CH_IND_CONTROL 0x00003080 +#define XXVGMAC_MODE_SELECT GENMASK(27, 24) +enum dma_ch_ind_modes { + MODE_TXEXTCFG = 0x0, /* Tx Extended Config */ + MODE_RXEXTCFG = 0x1, /* Rx Extended Config */ + MODE_TXDBGSTS = 0x2, /* Tx Debug Status */ + MODE_RXDBGSTS = 0x3, /* Rx Debug Status */ + MODE_TXDESCCTRL = 0x4, /* Tx Descriptor control */ + MODE_RXDESCCTRL = 0x5, /* Rx Descriptor control */ +}; + +#define XXVGMAC_ADDR_OFFSET GENMASK(14, 8) +#define XXVGMAC_AUTO_INCR GENMASK(5, 4) +#define XXVGMAC_CMD_TYPE BIT(1) +#define XXVGMAC_OB BIT(0) +#define XXVGMAC_DMA_CH_IND_DATA 0x00003084 + +/* TX Config definitions */ +#define XXVGMAC_TXPBL GENMASK(29, 24) +#define XXVGMAC_TPBLX8_MODE BIT(19) +#define XXVGMAC_TP2TCMP GENMASK(18, 16) +#define XXVGMAC_ORRQ GENMASK(13, 8) + +/* RX Config definitions */ +#define XXVGMAC_RXPBL GENMASK(29, 24) +#define XXVGMAC_RPBLX8_MODE BIT(19) +#define XXVGMAC_RP2TCMP GENMASK(18, 16) +#define XXVGMAC_OWRQ GENMASK(13, 8) + +/* Tx Descriptor control */ +#define XXVGMAC_TXDCSZ GENMASK(2, 0) +#define XXVGMAC_TXDCSZ_0BYTES 0 +#define XXVGMAC_TXDCSZ_64BYTES 1 +#define XXVGMAC_TXDCSZ_128BYTES 2 +#define XXVGMAC_TXDCSZ_256BYTES 3 +#define XXVGMAC_TDPS GENMASK(5, 3) +#define XXVGMAC_TDPS_ZERO 0 +#define XXVGMAC_TDPS_1_8TH 1 +#define XXVGMAC_TDPS_1_4TH 2 +#define XXVGMAC_TDPS_HALF 3 +#define XXVGMAC_TDPS_3_4TH 4 + +/* Rx Descriptor control */ +#define XXVGMAC_RXDCSZ GENMASK(2, 0) +#define XXVGMAC_RXDCSZ_0BYTES 0 +#define XXVGMAC_RXDCSZ_64BYTES 1 +#define XXVGMAC_RXDCSZ_128BYTES 2 +#define XXVGMAC_RXDCSZ_256BYTES 3 +#define XXVGMAC_RDPS GENMASK(5, 3) +#define XXVGMAC_RDPS_ZERO 0 +#define XXVGMAC_RDPS_1_8TH 1 +#define XXVGMAC_RDPS_1_4TH 2 +#define XXVGMAC_RDPS_HALF 3 +#define XXVGMAC_RDPS_3_4TH 4 + +/* DWCXG_DMA_CH(#i) Registers*/ +#define XXVGMAC_DSL GENMASK(20, 18) +#define XXVGMAC_MSS GENMASK(13, 0) +#define XXVGMAC_TFSEL GENMASK(30, 29) +#define XXVGMAC_TQOS GENMASK(27, 24) +#define XXVGMAC_IPBL BIT(15) +#define XXVGMAC_TVDMA2TCMP GENMASK(6, 4) +#define XXVGMAC_RPF BIT(31) +#define XXVGMAC_RVDMA2TCMP GENMASK(30, 28) +#define XXVGMAC_RQOS GENMASK(27, 24) + +u32 dw25gmac_decode_vdma_count(u32 regval); + +void dw25gmac_dma_init(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg); + +void dw25gmac_dma_init_tx_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + dma_addr_t dma_addr, u32 chan); +void dw25gmac_dma_init_rx_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + dma_addr_t dma_addr, u32 chan); +#endif /* __STMMAC_DW25GMAC_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index f8ab347f7b5b9..7616227ebb71a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -17,6 +17,7 @@ #define XGMAC_CONFIG_SS_OFF 29 #define XGMAC_CONFIG_SS_MASK GENMASK(31, 29) #define XGMAC_CONFIG_SS_10000 (0x0 << XGMAC_CONFIG_SS_OFF) +#define XGMAC_CONFIG_SS_25000 (0x1 << XGMAC_CONFIG_SS_OFF) #define XGMAC_CONFIG_SS_2500_GMII (0x2 << XGMAC_CONFIG_SS_OFF) #define XGMAC_CONFIG_SS_1000_GMII (0x3 << XGMAC_CONFIG_SS_OFF) #define XGMAC_CONFIG_SS_100_MII (0x4 << XGMAC_CONFIG_SS_OFF) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 1a88cbaed70ca..1539ad2a0864c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -13,6 +13,7 @@ #include "stmmac_vlan.h" #include "dwxlgmac2.h" #include "dwxgmac2.h" +#include "dw25gmac.h" static void dwxgmac2_core_init(struct mac_device_info *hw, struct net_device *dev) @@ -1505,11 +1506,11 @@ const struct stmmac_ops dwxlgmac2_ops = { .fpe_map_preemption_class = dwxgmac3_fpe_map_preemption_class, }; -int dwxgmac2_setup(struct stmmac_priv *priv) +static void dwxgmac2_common_setup(struct stmmac_priv *priv, char *mac_name) { struct mac_device_info *mac = priv->hw; - dev_info(priv->device, "\tXGMAC2\n"); + dev_info(priv->device, "\t%s\n", mac_name); priv->dev->priv_flags |= IFF_UNICAST_FLT; mac->pcsr = priv->ioaddr; @@ -1520,6 +1521,19 @@ int dwxgmac2_setup(struct stmmac_priv *priv) if (mac->multicast_filter_bins) mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + mac->mii.addr = XGMAC_MDIO_ADDR; + mac->mii.data = XGMAC_MDIO_DATA; + mac->mii.addr_mask = GENMASK_U32(20, 16); + mac->mii.reg_mask = GENMASK_U32(15, 0); + mac->mii.clk_csr_mask = GENMASK_U32(21, 19); +} + +int dwxgmac2_setup(struct stmmac_priv *priv) +{ + struct mac_device_info *mac = priv->hw; + + dwxgmac2_common_setup(priv, "XGMAC2"); + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD | MAC_5000FD | MAC_10000FD; @@ -1533,30 +1547,37 @@ int dwxgmac2_setup(struct stmmac_priv *priv) mac->link.xgmii.speed10000 = XGMAC_CONFIG_SS_10000; mac->link.speed_mask = XGMAC_CONFIG_SS_MASK; - mac->mii.addr = XGMAC_MDIO_ADDR; - mac->mii.data = XGMAC_MDIO_DATA; - mac->mii.addr_mask = GENMASK_U32(20, 16); - mac->mii.reg_mask = GENMASK_U32(15, 0); - mac->mii.clk_csr_mask = GENMASK_U32(21, 19); mac->num_vlan = stmmac_get_num_vlan(priv->ioaddr); return 0; } -int dwxlgmac2_setup(struct stmmac_priv *priv) +int dw25gmac_setup(struct stmmac_priv *priv) { struct mac_device_info *mac = priv->hw; - dev_info(priv->device, "\tXLGMAC\n"); + dwxgmac2_common_setup(priv, "DW25GMAC"); - priv->dev->priv_flags |= IFF_UNICAST_FLT; - mac->pcsr = priv->ioaddr; - mac->multicast_filter_bins = priv->plat->multicast_filter_bins; - mac->unicast_filter_entries = priv->plat->unicast_filter_entries; - mac->mcast_bits_log2 = 0; + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_1000FD | MAC_2500FD | MAC_5000FD | + MAC_10000FD | MAC_25000FD; + mac->link.duplex = 0; + mac->link.speed1000 = XGMAC_CONFIG_SS_1000_GMII; + mac->link.speed2500 = XGMAC_CONFIG_SS_2500_GMII; + mac->link.xgmii.speed2500 = XGMAC_CONFIG_SS_2500; + mac->link.xgmii.speed5000 = XGMAC_CONFIG_SS_5000; + mac->link.xgmii.speed10000 = XGMAC_CONFIG_SS_10000; + mac->link.xgmii.speed25000 = XGMAC_CONFIG_SS_25000; + mac->link.speed_mask = XGMAC_CONFIG_SS_MASK; - if (mac->multicast_filter_bins) - mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + return 0; +} + +int dwxlgmac2_setup(struct stmmac_priv *priv) +{ + struct mac_device_info *mac = priv->hw; + + dwxgmac2_common_setup(priv, "XLGMAC"); mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_1000FD | MAC_2500FD | MAC_5000FD | @@ -1573,11 +1594,5 @@ int dwxlgmac2_setup(struct stmmac_priv *priv) mac->link.xlgmii.speed100000 = XLGMAC_CONFIG_SS_100G; mac->link.speed_mask = XLGMAC_CONFIG_SS; - mac->mii.addr = XGMAC_MDIO_ADDR; - mac->mii.data = XGMAC_MDIO_DATA; - mac->mii.addr_mask = GENMASK_U32(20, 16); - mac->mii.reg_mask = GENMASK_U32(15, 0); - mac->mii.clk_csr_mask = GENMASK_U32(21, 19); - return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index 0a6e82a155c0e..078e7c1c58ca8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -7,6 +7,7 @@ #include #include "stmmac.h" #include "dwxgmac2.h" +#include "dw25gmac.h" static int dwxgmac2_dma_reset(void __iomem *ioaddr) { @@ -480,6 +481,26 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, return 0; } +static int dw25gmac_get_hw_feature(void __iomem *ioaddr, + struct dma_features *dma_cap) +{ + u32 hw_cap; + int ret; + + ret = dwxgmac2_get_hw_feature(ioaddr, dma_cap); + + /* For DW25GMAC VDMA channel count is channel count */ + hw_cap = readl(ioaddr + XGMAC_HW_FEATURE2); + dma_cap->number_tx_channel = + dw25gmac_decode_vdma_count(FIELD_GET(XXVGMAC_HWFEAT_VDMA_TXCNT, + hw_cap)); + dma_cap->number_rx_channel = + dw25gmac_decode_vdma_count(FIELD_GET(XXVGMAC_HWFEAT_VDMA_RXCNT, + hw_cap)); + + return ret; +} + static void dwxgmac2_rx_watchdog(struct stmmac_priv *priv, void __iomem *ioaddr, u32 riwt, u32 queue) { @@ -621,3 +642,33 @@ const struct stmmac_dma_ops dwxgmac210_dma_ops = { .enable_sph = dwxgmac2_enable_sph, .enable_tbs = dwxgmac2_enable_tbs, }; + +const struct stmmac_dma_ops dw25gmac400_dma_ops = { + .reset = dwxgmac2_dma_reset, + .init = dw25gmac_dma_init, + .init_chan = dwxgmac2_dma_init_chan, + .init_rx_chan = dw25gmac_dma_init_rx_chan, + .init_tx_chan = dw25gmac_dma_init_tx_chan, + .axi = dwxgmac2_dma_axi, + .dump_regs = dwxgmac2_dma_dump_regs, + .dma_rx_mode = dwxgmac2_dma_rx_mode, + .dma_tx_mode = dwxgmac2_dma_tx_mode, + .enable_dma_irq = dwxgmac2_enable_dma_irq, + .disable_dma_irq = dwxgmac2_disable_dma_irq, + .start_tx = dwxgmac2_dma_start_tx, + .stop_tx = dwxgmac2_dma_stop_tx, + .start_rx = dwxgmac2_dma_start_rx, + .stop_rx = dwxgmac2_dma_stop_rx, + .dma_interrupt = dwxgmac2_dma_interrupt, + .get_hw_feature = dw25gmac_get_hw_feature, + .rx_watchdog = dwxgmac2_rx_watchdog, + .set_rx_ring_len = dwxgmac2_set_rx_ring_len, + .set_tx_ring_len = dwxgmac2_set_tx_ring_len, + .set_rx_tail_ptr = dwxgmac2_set_rx_tail_ptr, + .set_tx_tail_ptr = dwxgmac2_set_tx_tail_ptr, + .enable_tso = dwxgmac2_enable_tso, + .qmode = dwxgmac2_qmode, + .set_bfsize = dwxgmac2_set_bfsize, + .enable_sph = dwxgmac2_enable_sph, + .enable_tbs = dwxgmac2_enable_tbs, +}; diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index b2e5577888038..3943aedf1ac23 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -690,6 +690,7 @@ extern const struct stmmac_dma_ops dwmac410_dma_ops; extern const struct stmmac_ops dwmac510_ops; extern const struct stmmac_tc_ops dwmac4_tc_ops; extern const struct stmmac_tc_ops dwmac510_tc_ops; +extern const struct stmmac_dma_ops dw25gmac400_dma_ops; #define GMAC_VERSION 0x00000020 /* GMAC CORE Version */ #define GMAC4_VERSION 0x00000110 /* GMAC4+ CORE Version */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 9ded31150fbe6..ebccd0009092c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -144,6 +144,10 @@ static const char *stmmac_dwxgmac_phyif[4] = { [PHY_INTF_RGMII] = "RGMII", }; +static const char *stmmac_dw25gmac_phyif[2] = { + [PHY_INTF_DW25GMAC_XGMII] = "XGMII", +}; + static irqreturn_t stmmac_interrupt(int irq, void *dev_id); /* For MSI interrupts handling */ static irqreturn_t stmmac_mac_interrupt(int irq, void *dev_id); @@ -1126,7 +1130,10 @@ static void stmmac_mac_link_up(struct phylink_config *config, ctrl |= priv->hw->link.xlgmii.speed40000; break; case SPEED_25000: - ctrl |= priv->hw->link.xlgmii.speed25000; + if (interface == PHY_INTERFACE_MODE_XGMII) + ctrl |= priv->hw->link.xgmii.speed25000; + else + ctrl |= priv->hw->link.xlgmii.speed25000; break; case SPEED_10000: ctrl |= priv->hw->link.xgmii.speed10000; @@ -1135,7 +1142,8 @@ static void stmmac_mac_link_up(struct phylink_config *config, ctrl |= priv->hw->link.xgmii.speed5000; break; case SPEED_2500: - if (interface == PHY_INTERFACE_MODE_USXGMII) + if (interface == PHY_INTERFACE_MODE_USXGMII || + interface == PHY_INTERFACE_MODE_XGMII) ctrl |= priv->hw->link.xgmii.speed2500; else ctrl |= priv->hw->link.speed2500; @@ -7521,6 +7529,11 @@ static void stmmac_print_actphyif(struct stmmac_priv *priv) phyif_table = stmmac_dwxgmac_phyif; phyif_table_size = ARRAY_SIZE(stmmac_dwxgmac_phyif); break; + + case DWMAC_CORE_25GMAC: + phyif_table = stmmac_dw25gmac_phyif; + phyif_table_size = ARRAY_SIZE(stmmac_dw25gmac_phyif); + break; } if (priv->dma_cap.actphyif < phyif_table_size) diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 00be2df63d220..7976c0597f395 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -193,6 +193,7 @@ enum dwmac_core_type { DWMAC_CORE_GMAC, DWMAC_CORE_GMAC4, DWMAC_CORE_XGMAC, + DWMAC_CORE_25GMAC, }; #define STMMAC_FLAG_SPH_DISABLE BIT(1) From c62145d93dee615519e965f2658b2c34a91976c6 Mon Sep 17 00:00:00 2001 From: Jitendra Vegiraju Date: Thu, 2 Apr 2026 14:36:27 -0700 Subject: [PATCH 0388/1133] FROMLIST: net: stmmac: Integrate dw25gmac into hwif handling Integrate dw25gmac support into stmmac hardware interface handling. Added a new entry to the stmmac_hw table in hwif.c. Link: https://lore.kernel.org/netdev/20260402213629.1996133-3-jitendra.vegiraju@broadcom.com/ Signed-off-by: Jitendra Vegiraju Signed-off-by: Mohd Ayaan Anwar --- drivers/net/ethernet/stmicro/stmmac/hwif.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c index 265671170bf6e..4bea373a881c7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c @@ -287,6 +287,26 @@ static const struct stmmac_hwif_entry { .mmc = &dwxgmac_mmc_ops, .est = &dwmac510_est_ops, .setup = dwxlgmac2_setup, + }, { + .core_type = DWMAC_CORE_25GMAC, + .min_id = DW25GMAC_CORE_3_20, + .regs = { + .ptp_off = PTP_XGMAC_OFFSET, + .mmc_off = MMC_XGMAC_OFFSET, + .est_off = EST_XGMAC_OFFSET, + }, + .desc = &dwxgmac210_desc_ops, + .dma = &dw25gmac400_dma_ops, + .mac = &dwxgmac210_ops, + .vlan = &dwxgmac210_vlan_ops, + .hwtimestamp = &stmmac_ptp, + .ptp = &stmmac_ptp_clock_ops, + .mode = NULL, + .tc = &dwmac510_tc_ops, + .mmc = &dwxgmac_mmc_ops, + .est = &dwmac510_est_ops, + .setup = dw25gmac_setup, + .quirks = NULL, }, }; From e08c0c213057c852afb3f70adc0832461d6a9d49 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 23 Sep 2026 00:34:19 +0530 Subject: [PATCH 0389/1133] FROMLIST: dt-bindings: net: qcom,ethqos: add Qualcomm Nord Qualcomm Nord integrates two ETHQOS controllers based on the Synopsys DesignWare XGMAC IP. Each controller has five clocks, one power domain, and ten SMMU stream mappings. Due to a hardware quirk, PCS link-up depends on the EEE clock being enabled. Add the Nord compatible to the common DWMAC schema exceptions used by Qualcomm ETHQOS platforms. Link: https://lore.kernel.org/netdev/20260923-qcom_xpcs_nord_emac-v1-6-4b1c682af70f@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../devicetree/bindings/net/qcom,ethqos.yaml | 58 +++++++++++++++++-- .../devicetree/bindings/net/snps,dwmac.yaml | 2 + 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml index 6b40ad4b4a817..1a977dd9e0deb 100644 --- a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml +++ b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml @@ -11,8 +11,8 @@ maintainers: - Konrad Dybcio description: - dwmmac based Qualcomm ethernet devices which support Gigabit - ethernet (version v2.3.0 and onwards). + DWMAC and XGMAC based Qualcomm Ethernet devices supporting Gigabit and + multi-gigabit Ethernet. properties: compatible: @@ -27,6 +27,7 @@ properties: - const: qcom,sa8775p-ethqos - enum: - qcom,qcs404-ethqos + - qcom,nord-ethqos - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos - qcom,shikra-ethqos @@ -67,11 +68,14 @@ properties: - enum: - rgmii - phyaux - - const: axi-noc + - enum: + - axi-noc + - eee - const: pcie-tile-axi-noc iommus: - maxItems: 1 + minItems: 1 + maxItems: 10 dma-coherent: true @@ -105,6 +109,38 @@ required: allOf: - $ref: snps,dwmac.yaml# + - if: + properties: + compatible: + contains: + const: qcom,nord-ethqos + then: + properties: + clocks: + minItems: 5 + maxItems: 5 + clock-names: + minItems: 5 + maxItems: 5 + items: + - const: stmmaceth + - const: pclk + - const: ptp_ref + - const: phyaux + - const: eee + description: | + Due to a hardware quirk, PCS link-up depends on the EEE + clock being enabled. + iommus: + minItems: 10 + maxItems: 10 + required: + - power-domains + else: + properties: + iommus: + maxItems: 1 + - if: properties: compatible: @@ -124,7 +160,19 @@ allOf: - const: pcie-tile-axi-noc required: - operating-points-v2 - else: + + - if: + not: + anyOf: + - properties: + compatible: + contains: + const: qcom,shikra-ethqos + - properties: + compatible: + contains: + const: qcom,nord-ethqos + then: properties: clocks: maxItems: 4 diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml index 6dd64d46291bb..82d8a7ab7b68a 100644 --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml @@ -73,6 +73,7 @@ properties: - nuvoton,ma35d1-dwmac - nxp,s32g2-dwmac - qcom,qcs404-ethqos + - qcom,nord-ethqos - qcom,sa8255p-ethqos - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos @@ -586,6 +587,7 @@ allOf: - ingenic,x1830-mac - ingenic,x2000-mac - qcom,qcs404-ethqos + - qcom,nord-ethqos - qcom,sa8255p-ethqos - qcom,sa8775p-ethqos - qcom,sc8280xp-ethqos From f5a7e0905e4813b69dad1526e806cc67d3d0ab4b Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 23 Sep 2026 03:27:15 +0530 Subject: [PATCH 0390/1133] FROMLIST: net: stmmac: support custom XGMAC register layouts Some XGMAC integrations place their MTL queues and DMA channels at different offsets from the standard register layout. Allow platform data to override these addresses while retaining the standard layout by default. This follows the approach used by commit 33719b57f52e ("net: stmmac: dwmac4: Allow platforms to specify some DMA/MTL offsets"). Qualcomm XGMAC hardware similarly uses differently aligned queue and channel registers. Also allow platforms to override the timestamp register base. Link: https://lore.kernel.org/netdev/20260923-qcom_xpcs_nord_emac-v1-7-4b1c682af70f@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- drivers/net/ethernet/stmicro/stmmac/common.h | 1 + .../ethernet/stmicro/stmmac/dwmac-socfpga.c | 2 +- .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 94 +++++++++---- .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 34 +++-- .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 128 +++++++++++------- drivers/net/ethernet/stmicro/stmmac/hwif.c | 5 +- .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 5 +- .../net/ethernet/stmicro/stmmac/stmmac_fpe.c | 15 +- include/linux/stmmac.h | 11 ++ 9 files changed, 193 insertions(+), 102 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index cec0f9db4ebc5..9ce9489d1f3bd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -630,6 +630,7 @@ struct mac_device_info { const struct stmmac_mmc_ops *mmc; const struct stmmac_est_ops *est; const struct stmmac_vlan_ops *vlan; + const struct dwxgmac_addrs *dwxgmac_addrs; struct dw_xpcs *xpcs; struct phylink_pcs *phylink_pcs; struct mii_regs mii; /* MII register Addresses */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 6d4bc1fe8f751..a28c08247ef1f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -365,7 +365,7 @@ static int smtg_crosststamp(ktime_t *device, struct system_counterval_t *system, }; num_snapshot = FIELD_GET(XGMAC_TIMESTAMP_ATSNS_MASK, - readl(ioaddr + XGMAC_TIMESTAMP_STATUS)); + readl(ioaddr + XGMAC_TIMESTAMP_STATUS(NULL))); /* Repeat until the timestamps are from the FIFO last segment */ for (i = 0; i < num_snapshot; i++) { diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index 7616227ebb71a..c99b790401ab9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -221,12 +221,21 @@ #define XGMAC_CT BIT(1) #define XGMAC_OB BIT(0) #define XGMAC_RSS_DATA 0x00000c8c -#define XGMAC_TIMESTAMP_STATUS 0x00000d20 + +/* Timestamp registers */ +#define XGMAC_TIMESTAMP_BASE_ADDR 0x00000d00 + +static inline u32 xgmac_timestamp_base_addr(const struct dwxgmac_addrs *addrs) +{ + return addrs ? addrs->timestamp_base : XGMAC_TIMESTAMP_BASE_ADDR; +} + +#define XGMAC_TIMESTAMP_STATUS(a) (xgmac_timestamp_base_addr(a) + 0x20) #define XGMAC_TIMESTAMP_ATSNS_MASK GENMASK(29, 25) #define XGMAC_TXTSC BIT(15) -#define XGMAC_TXTIMESTAMP_NSEC 0x00000d30 +#define XGMAC_TXTIMESTAMP_NSEC(a) (xgmac_timestamp_base_addr(a) + 0x30) #define XGMAC_TXTSSTSLO GENMASK(30, 0) -#define XGMAC_TXTIMESTAMP_SEC 0x00000d34 +#define XGMAC_TXTIMESTAMP_SEC(a) (xgmac_timestamp_base_addr(a) + 0x34) #define XGMAC_PPS_CONTROL 0x00000d70 #define XGMAC_PPS_MAXIDX(x) ((((x) + 1) * 8) - 1) #define XGMAC_PPS_MINIDX(x) ((x) * 8) @@ -286,37 +295,49 @@ #define XGMAC_MTL_ECC_INT_STATUS 0x000010cc #define XGMAC_MTL_DPP_CONTROL 0x000010e0 #define XGMAC_DPP_DISABLE BIT(0) -#define XGMAC_MTL_TXQ_OPMODE(x) (0x00001100 + (0x80 * (x))) + +/* MTL per-queue registers — address-aware to support custom queue offsets. */ +#define XGMAC_MTL_CHAN_BASE_ADDR 0x00001100 +#define XGMAC_MTL_CHAN_OFFSET 0x80 + +static inline u32 +xgmac_mtl_chanx_base_addr(const struct dwxgmac_addrs *addrs, u32 x) +{ + return addrs ? addrs->mtl_chan_base + x * addrs->mtl_chan_offset + : XGMAC_MTL_CHAN_BASE_ADDR + x * XGMAC_MTL_CHAN_OFFSET; +} + +#define XGMAC_MTL_TXQ_OPMODE(a, x) xgmac_mtl_chanx_base_addr(a, x) #define XGMAC_TQS GENMASK(25, 16) #define XGMAC_Q2TCMAP GENMASK(10, 8) #define XGMAC_TTC GENMASK(6, 4) #define XGMAC_TXQEN GENMASK(3, 2) #define XGMAC_TSF BIT(1) -#define XGMAC_MTL_TCx_ETS_CONTROL(x) (0x00001110 + (0x80 * (x))) -#define XGMAC_MTL_TCx_QUANTUM_WEIGHT(x) (0x00001118 + (0x80 * (x))) -#define XGMAC_MTL_TCx_SENDSLOPE(x) (0x0000111c + (0x80 * (x))) -#define XGMAC_MTL_TCx_HICREDIT(x) (0x00001120 + (0x80 * (x))) -#define XGMAC_MTL_TCx_LOCREDIT(x) (0x00001124 + (0x80 * (x))) +#define XGMAC_MTL_TCx_ETS_CONTROL(a, x) (xgmac_mtl_chanx_base_addr(a, x) + 0x10) +#define XGMAC_MTL_TCx_QUANTUM_WEIGHT(a, x) (xgmac_mtl_chanx_base_addr(a, x) + 0x18) +#define XGMAC_MTL_TCx_SENDSLOPE(a, x) (xgmac_mtl_chanx_base_addr(a, x) + 0x1c) +#define XGMAC_MTL_TCx_HICREDIT(a, x) (xgmac_mtl_chanx_base_addr(a, x) + 0x20) +#define XGMAC_MTL_TCx_LOCREDIT(a, x) (xgmac_mtl_chanx_base_addr(a, x) + 0x24) #define XGMAC_CC BIT(3) #define XGMAC_TSA GENMASK(1, 0) #define XGMAC_SP (0x0 << 0) #define XGMAC_CBS (0x1 << 0) #define XGMAC_ETS (0x2 << 0) -#define XGMAC_MTL_RXQ_OPMODE(x) (0x00001140 + (0x80 * (x))) +#define XGMAC_MTL_RXQ_OPMODE(a, x) (xgmac_mtl_chanx_base_addr(a, x) + 0x40) #define XGMAC_RQS GENMASK(25, 16) #define XGMAC_EHFC BIT(7) #define XGMAC_RSF BIT(5) #define XGMAC_RTC GENMASK(1, 0) -#define XGMAC_MTL_RXQ_FLOW_CONTROL(x) (0x00001150 + (0x80 * (x))) +#define XGMAC_MTL_RXQ_FLOW_CONTROL(a, x) (xgmac_mtl_chanx_base_addr(a, x) + 0x50) #define XGMAC_RFD GENMASK(31, 17) #define XGMAC_RFA GENMASK(15, 1) -#define XGMAC_MTL_QINTEN(x) (0x00001170 + (0x80 * (x))) +#define XGMAC_MTL_QINTEN(a, x) (xgmac_mtl_chanx_base_addr(a, x) + 0x70) #define XGMAC_RXOIE BIT(16) -#define XGMAC_MTL_QINT_STATUS(x) (0x00001174 + (0x80 * (x))) +#define XGMAC_MTL_QINT_STATUS(a, x) (xgmac_mtl_chanx_base_addr(a, x) + 0x74) #define XGMAC_RXOVFIS BIT(16) #define XGMAC_ABPSIS BIT(1) #define XGMAC_TXUNFIS BIT(0) -#define XGMAC_MAC_REGSIZE (XGMAC_MTL_QINT_STATUS(15) / 4) +#define XGMAC_MAC_REGSIZE(a) (XGMAC_MTL_QINT_STATUS(a, 15) / 4) /* DMA Registers */ #define XGMAC_DMA_MODE 0x00003000 @@ -354,28 +375,43 @@ #define XGMAC_TCEIE BIT(0) #define XGMAC_DMA_ECC_INT_STATUS 0x0000306c #define XGMAC_DMA_DPP_INT_STATUS 0x00003074 -#define XGMAC_DMA_CH_CONTROL(x) (0x00003100 + (0x80 * (x))) + +/* DMA per-channel registers */ +#define XGMAC_DMA_CHAN_BASE_ADDR 0x00003100 +#define XGMAC_DMA_CHAN_OFFSET 0x80 + +static inline u32 +xgmac_dma_chanx_base_addr(const struct dwxgmac_addrs *addrs, u32 x) +{ + if (addrs && (x & 1)) + return addrs->dma_odd_chan_base + x * addrs->dma_chan_offset; + if (addrs) + return addrs->dma_even_chan_base + x * addrs->dma_chan_offset; + return XGMAC_DMA_CHAN_BASE_ADDR + x * XGMAC_DMA_CHAN_OFFSET; +} + +#define XGMAC_DMA_CH_CONTROL(a, x) (xgmac_dma_chanx_base_addr(a, x)) #define XGMAC_SPH BIT(24) #define XGMAC_PBLx8 BIT(16) -#define XGMAC_DMA_CH_TX_CONTROL(x) (0x00003104 + (0x80 * (x))) +#define XGMAC_DMA_CH_TX_CONTROL(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x04) #define XGMAC_EDSE BIT(28) #define XGMAC_TxPBL GENMASK(21, 16) #define XGMAC_TSE BIT(12) #define XGMAC_OSP BIT(4) #define XGMAC_TXST BIT(0) -#define XGMAC_DMA_CH_RX_CONTROL(x) (0x00003108 + (0x80 * (x))) +#define XGMAC_DMA_CH_RX_CONTROL(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x08) #define XGMAC_RxPBL GENMASK(21, 16) #define XGMAC_RBSZ GENMASK(14, 1) #define XGMAC_RXST BIT(0) -#define XGMAC_DMA_CH_TxDESC_HADDR(x) (0x00003110 + (0x80 * (x))) -#define XGMAC_DMA_CH_TxDESC_LADDR(x) (0x00003114 + (0x80 * (x))) -#define XGMAC_DMA_CH_RxDESC_HADDR(x) (0x00003118 + (0x80 * (x))) -#define XGMAC_DMA_CH_RxDESC_LADDR(x) (0x0000311c + (0x80 * (x))) -#define XGMAC_DMA_CH_TxDESC_TAIL_LPTR(x) (0x00003124 + (0x80 * (x))) -#define XGMAC_DMA_CH_RxDESC_TAIL_LPTR(x) (0x0000312c + (0x80 * (x))) -#define XGMAC_DMA_CH_TxDESC_RING_LEN(x) (0x00003130 + (0x80 * (x))) -#define XGMAC_DMA_CH_RxDESC_RING_LEN(x) (0x00003134 + (0x80 * (x))) -#define XGMAC_DMA_CH_INT_EN(x) (0x00003138 + (0x80 * (x))) +#define XGMAC_DMA_CH_TxDESC_HADDR(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x10) +#define XGMAC_DMA_CH_TxDESC_LADDR(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x14) +#define XGMAC_DMA_CH_RxDESC_HADDR(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x18) +#define XGMAC_DMA_CH_RxDESC_LADDR(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x1c) +#define XGMAC_DMA_CH_TxDESC_TAIL_LPTR(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x24) +#define XGMAC_DMA_CH_RxDESC_TAIL_LPTR(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x2c) +#define XGMAC_DMA_CH_TxDESC_RING_LEN(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x30) +#define XGMAC_DMA_CH_RxDESC_RING_LEN(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x34) +#define XGMAC_DMA_CH_INT_EN(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x38) #define XGMAC_NIE BIT(15) #define XGMAC_AIE BIT(14) #define XGMAC_RBUE BIT(7) @@ -386,9 +422,9 @@ XGMAC_RIE | XGMAC_TIE) #define XGMAC_DMA_INT_DEFAULT_RX (XGMAC_RIE) #define XGMAC_DMA_INT_DEFAULT_TX (XGMAC_TIE) -#define XGMAC_DMA_CH_Rx_WATCHDOG(x) (0x0000313c + (0x80 * (x))) +#define XGMAC_DMA_CH_Rx_WATCHDOG(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x3c) #define XGMAC_RWT GENMASK(7, 0) -#define XGMAC_DMA_CH_STATUS(x) (0x00003160 + (0x80 * (x))) +#define XGMAC_DMA_CH_STATUS(a, x) (xgmac_dma_chanx_base_addr(a, x) + 0x60) #define XGMAC_NIS BIT(15) #define XGMAC_AIS BIT(14) #define XGMAC_FBE BIT(12) @@ -397,7 +433,7 @@ #define XGMAC_TBU BIT(2) #define XGMAC_TPS BIT(1) #define XGMAC_TI BIT(0) -#define XGMAC_REGSIZE ((0x0000317c + (0x80 * 15)) / 4) +#define XGMAC_REGSIZE(a) ((xgmac_dma_chanx_base_addr(a, 15) + 0x7c) / 4) #define XGMAC_DMA_STATUS_MSK_COMMON (XGMAC_NIS | XGMAC_AIS | XGMAC_FBE) #define XGMAC_DMA_STATUS_MSK_RX (XGMAC_RBU | XGMAC_RI | \ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 1539ad2a0864c..0b00d880fd305 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -235,11 +235,11 @@ static void dwxgmac2_prog_mtl_tx_algorithms(struct mac_device_info *hw, /* Set ETS if desired */ for (i = 0; i < MTL_MAX_TX_QUEUES; i++) { - value = readl(ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(i)); + value = readl(ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(hw->dwxgmac_addrs, i)); value &= ~XGMAC_TSA; if (ets) value |= XGMAC_ETS; - writel(value, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(i)); + writel(value, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(hw->dwxgmac_addrs, i)); } } @@ -247,9 +247,10 @@ static void dwxgmac2_set_mtl_tx_queue_weight(struct stmmac_priv *priv, struct mac_device_info *hw, u32 weight, u32 queue) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; void __iomem *ioaddr = hw->pcsr; - writel(weight, ioaddr + XGMAC_MTL_TCx_QUANTUM_WEIGHT(queue)); + writel(weight, ioaddr + XGMAC_MTL_TCx_QUANTUM_WEIGHT(addrs, queue)); } static void dwxgmac2_map_mtl_to_dma(struct mac_device_info *hw, u32 queue, @@ -274,18 +275,19 @@ static void dwxgmac2_config_cbs(struct stmmac_priv *priv, u32 send_slope, u32 idle_slope, u32 high_credit, u32 low_credit, u32 queue) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; void __iomem *ioaddr = hw->pcsr; u32 value; - writel(send_slope, ioaddr + XGMAC_MTL_TCx_SENDSLOPE(queue)); - writel(idle_slope, ioaddr + XGMAC_MTL_TCx_QUANTUM_WEIGHT(queue)); - writel(high_credit, ioaddr + XGMAC_MTL_TCx_HICREDIT(queue)); - writel(low_credit, ioaddr + XGMAC_MTL_TCx_LOCREDIT(queue)); + writel(send_slope, ioaddr + XGMAC_MTL_TCx_SENDSLOPE(addrs, queue)); + writel(idle_slope, ioaddr + XGMAC_MTL_TCx_QUANTUM_WEIGHT(addrs, queue)); + writel(high_credit, ioaddr + XGMAC_MTL_TCx_HICREDIT(addrs, queue)); + writel(low_credit, ioaddr + XGMAC_MTL_TCx_LOCREDIT(addrs, queue)); - value = readl(ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(queue)); + value = readl(ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(addrs, queue)); value &= ~XGMAC_TSA; value |= XGMAC_CC | XGMAC_CBS; - writel(value, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(queue)); + writel(value, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(addrs, queue)); } static void dwxgmac2_dump_regs(struct mac_device_info *hw, u32 *reg_space) @@ -293,7 +295,7 @@ static void dwxgmac2_dump_regs(struct mac_device_info *hw, u32 *reg_space) void __iomem *ioaddr = hw->pcsr; int i; - for (i = 0; i < XGMAC_MAC_REGSIZE; i++) + for (i = 0; i < XGMAC_MAC_REGSIZE(hw->dwxgmac_addrs); i++) reg_space[i] = readl(ioaddr + i * 4); } @@ -337,18 +339,19 @@ static int dwxgmac2_host_irq_status(struct stmmac_priv *priv, static int dwxgmac2_host_mtl_irq_status(struct stmmac_priv *priv, struct mac_device_info *hw, u32 chan) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; void __iomem *ioaddr = hw->pcsr; int ret = 0; u32 status; status = readl(ioaddr + XGMAC_MTL_INT_STATUS); if (status & BIT(chan)) { - u32 chan_status = readl(ioaddr + XGMAC_MTL_QINT_STATUS(chan)); + u32 chan_status = readl(ioaddr + XGMAC_MTL_QINT_STATUS(addrs, chan)); if (chan_status & XGMAC_RXOVFIS) ret |= CORE_IRQ_MTL_RX_OVERFLOW; - writel(~0x0, ioaddr + XGMAC_MTL_QINT_STATUS(chan)); + writel(~0x0, ioaddr + XGMAC_MTL_QINT_STATUS(addrs, chan)); } return ret; @@ -1144,14 +1147,15 @@ static int dwxgmac3_rxp_config(void __iomem *ioaddr, static int dwxgmac2_get_mac_tx_timestamp(struct mac_device_info *hw, u64 *ts) { void __iomem *ioaddr = hw->pcsr; + const struct dwxgmac_addrs *addrs = hw->dwxgmac_addrs; u32 value; - if (readl_poll_timeout_atomic(ioaddr + XGMAC_TIMESTAMP_STATUS, + if (readl_poll_timeout_atomic(ioaddr + XGMAC_TIMESTAMP_STATUS(addrs), value, value & XGMAC_TXTSC, 100, 10000)) return -EBUSY; - *ts = readl(ioaddr + XGMAC_TXTIMESTAMP_NSEC) & XGMAC_TXTSSTSLO; - *ts += readl(ioaddr + XGMAC_TXTIMESTAMP_SEC) * 1000000000ULL; + *ts = readl(ioaddr + XGMAC_TXTIMESTAMP_NSEC(addrs)) & XGMAC_TXTSSTSLO; + *ts += readl(ioaddr + XGMAC_TXTIMESTAMP_SEC(addrs)) * 1000000000ULL; return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index 078e7c1c58ca8..ebf5ff7ec5555 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -48,13 +48,14 @@ static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv, void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg, u32 chan) { - u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(addrs, chan)); if (dma_cfg->pblx8) value |= XGMAC_PBLx8; - writel(value, ioaddr + XGMAC_DMA_CH_CONTROL(chan)); - writel(XGMAC_DMA_INT_DEFAULT_EN, ioaddr + XGMAC_DMA_CH_INT_EN(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_CONTROL(addrs, chan)); + writel(XGMAC_DMA_INT_DEFAULT_EN, ioaddr + XGMAC_DMA_CH_INT_EN(addrs, chan)); } static void dwxgmac2_dma_init_rx_chan(struct stmmac_priv *priv, @@ -62,15 +63,16 @@ static void dwxgmac2_dma_init_rx_chan(struct stmmac_priv *priv, struct stmmac_dma_cfg *dma_cfg, dma_addr_t phy, u32 chan) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; u32 rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; u32 value; - value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); value = u32_replace_bits(value, rxpbl, XGMAC_RxPBL); - writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); - writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(chan)); - writel(lower_32_bits(phy), ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(chan)); + writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(addrs, chan)); + writel(lower_32_bits(phy), ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(addrs, chan)); } static void dwxgmac2_dma_init_tx_chan(struct stmmac_priv *priv, @@ -78,15 +80,16 @@ static void dwxgmac2_dma_init_tx_chan(struct stmmac_priv *priv, struct stmmac_dma_cfg *dma_cfg, dma_addr_t phy, u32 chan) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; u32 txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; u32 value; - value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); value = u32_replace_bits(value, txpbl, XGMAC_TxPBL); - writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); - writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(chan)); - writel(lower_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(chan)); + writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(addrs, chan)); + writel(lower_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(addrs, chan)); } static void dwxgmac2_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi) @@ -119,16 +122,18 @@ static void dwxgmac2_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi) static void dwxgmac2_dma_dump_regs(struct stmmac_priv *priv, void __iomem *ioaddr, u32 *reg_space) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; int i; - for (i = (XGMAC_DMA_MODE / 4); i < XGMAC_REGSIZE; i++) + for (i = (XGMAC_DMA_MODE / 4); i < XGMAC_REGSIZE(addrs); i++) reg_space[i] = readl(ioaddr + i * 4); } static void dwxgmac2_dma_rx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, int mode, u32 channel, int fifosz, u8 qmode) { - u32 value = readl(ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + u32 value = readl(ioaddr + XGMAC_MTL_RXQ_OPMODE(addrs, channel)); unsigned int rqs = fifosz / 256 - 1; unsigned int rtc; @@ -150,7 +155,7 @@ static void dwxgmac2_dma_rx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, value = u32_replace_bits(value, rqs, XGMAC_RQS); if ((fifosz >= 4096) && (qmode != MTL_QUEUE_AVB)) { - u32 flow = readl(ioaddr + XGMAC_MTL_RXQ_FLOW_CONTROL(channel)); + u32 flow = readl(ioaddr + XGMAC_MTL_RXQ_FLOW_CONTROL(addrs, channel)); unsigned int rfd, rfa; value |= XGMAC_EHFC; @@ -179,16 +184,17 @@ static void dwxgmac2_dma_rx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, flow = u32_replace_bits(flow, rfd, XGMAC_RFD); flow = u32_replace_bits(flow, rfa, XGMAC_RFA); - writel(flow, ioaddr + XGMAC_MTL_RXQ_FLOW_CONTROL(channel)); + writel(flow, ioaddr + XGMAC_MTL_RXQ_FLOW_CONTROL(addrs, channel)); } - writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); + writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(addrs, channel)); } static void dwxgmac2_dma_tx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, int mode, u32 channel, int fifosz, u8 qmode) { - u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(channel)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(addrs, channel)); unsigned int tqs = fifosz / 256 - 1; unsigned int ttc, txqen; @@ -226,45 +232,48 @@ static void dwxgmac2_dma_tx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, value = u32_replace_bits(value, txqen, XGMAC_TXQEN); value = u32_replace_bits(value, tqs, XGMAC_TQS); - writel(value, ioaddr + XGMAC_MTL_TXQ_OPMODE(channel)); + writel(value, ioaddr + XGMAC_MTL_TXQ_OPMODE(addrs, channel)); } static void dwxgmac2_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan, bool rx, bool tx) { - u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(addrs, chan)); if (rx) value |= XGMAC_DMA_INT_DEFAULT_RX; if (tx) value |= XGMAC_DMA_INT_DEFAULT_TX; - writel(value, ioaddr + XGMAC_DMA_CH_INT_EN(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_INT_EN(addrs, chan)); } static void dwxgmac2_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan, bool rx, bool tx) { - u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(addrs, chan)); if (rx) value &= ~XGMAC_DMA_INT_DEFAULT_RX; if (tx) value &= ~XGMAC_DMA_INT_DEFAULT_TX; - writel(value, ioaddr + XGMAC_DMA_CH_INT_EN(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_INT_EN(addrs, chan)); } static void dwxgmac2_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; u32 value; - value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); value |= XGMAC_TXST; - writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); value = readl(ioaddr + XGMAC_TX_CONFIG); value |= XGMAC_CONFIG_TE; @@ -274,11 +283,12 @@ static void dwxgmac2_dma_start_tx(struct stmmac_priv *priv, static void dwxgmac2_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; u32 value; - value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); value &= ~XGMAC_TXST; - writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); value = readl(ioaddr + XGMAC_TX_CONFIG); value &= ~XGMAC_CONFIG_TE; @@ -288,11 +298,12 @@ static void dwxgmac2_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, static void dwxgmac2_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; u32 value; - value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); value |= XGMAC_RXST; - writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); value = readl(ioaddr + XGMAC_RX_CONFIG); value |= XGMAC_CONFIG_RE; @@ -302,11 +313,12 @@ static void dwxgmac2_dma_start_rx(struct stmmac_priv *priv, static void dwxgmac2_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; u32 value; - value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); value &= ~XGMAC_RXST; - writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); } static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, @@ -315,8 +327,9 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, u32 dir) { struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); - u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan)); - u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(addrs, chan)); + u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(addrs, chan)); int ret = 0; if (dir == DMA_DIR_RX) @@ -355,7 +368,7 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, } /* Clear interrupts */ - writel(intr_en & intr_status, ioaddr + XGMAC_DMA_CH_STATUS(chan)); + writel(intr_en & intr_status, ioaddr + XGMAC_DMA_CH_STATUS(addrs, chan)); return ret; } @@ -504,105 +517,120 @@ static int dw25gmac_get_hw_feature(void __iomem *ioaddr, static void dwxgmac2_rx_watchdog(struct stmmac_priv *priv, void __iomem *ioaddr, u32 riwt, u32 queue) { - writel(riwt & XGMAC_RWT, ioaddr + XGMAC_DMA_CH_Rx_WATCHDOG(queue)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + + writel(riwt & XGMAC_RWT, ioaddr + XGMAC_DMA_CH_Rx_WATCHDOG(addrs, queue)); } static void dwxgmac2_set_rx_ring_len(struct stmmac_priv *priv, void __iomem *ioaddr, u32 len, u32 chan) { - writel(len, ioaddr + XGMAC_DMA_CH_RxDESC_RING_LEN(chan)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + + writel(len, ioaddr + XGMAC_DMA_CH_RxDESC_RING_LEN(addrs, chan)); } static void dwxgmac2_set_tx_ring_len(struct stmmac_priv *priv, void __iomem *ioaddr, u32 len, u32 chan) { - writel(len, ioaddr + XGMAC_DMA_CH_TxDESC_RING_LEN(chan)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + + writel(len, ioaddr + XGMAC_DMA_CH_TxDESC_RING_LEN(addrs, chan)); } static void dwxgmac2_set_rx_tail_ptr(struct stmmac_priv *priv, void __iomem *ioaddr, u32 ptr, u32 chan) { - writel(ptr, ioaddr + XGMAC_DMA_CH_RxDESC_TAIL_LPTR(chan)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + + writel(ptr, ioaddr + XGMAC_DMA_CH_RxDESC_TAIL_LPTR(addrs, chan)); } static void dwxgmac2_set_tx_tail_ptr(struct stmmac_priv *priv, void __iomem *ioaddr, u32 ptr, u32 chan) { - writel(ptr, ioaddr + XGMAC_DMA_CH_TxDESC_TAIL_LPTR(chan)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + + writel(ptr, ioaddr + XGMAC_DMA_CH_TxDESC_TAIL_LPTR(addrs, chan)); } static void dwxgmac2_enable_tso(struct stmmac_priv *priv, void __iomem *ioaddr, bool en, u32 chan) { - u32 value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + u32 value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); if (en) value |= XGMAC_TSE; else value &= ~XGMAC_TSE; - writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); } static void dwxgmac2_qmode(struct stmmac_priv *priv, void __iomem *ioaddr, u32 channel, u8 qmode) { - u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(channel)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(addrs, channel)); u32 flow = readl(ioaddr + XGMAC_RX_FLOW_CTRL); unsigned int txqen; if (qmode != MTL_QUEUE_AVB) { txqen = 0x2; - writel(0, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(channel)); + writel(0, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(addrs, channel)); } else { txqen = 0x1; writel(flow & (~XGMAC_RFE), ioaddr + XGMAC_RX_FLOW_CTRL); } value = u32_replace_bits(value, txqen, XGMAC_TXQEN); - writel(value, ioaddr + XGMAC_MTL_TXQ_OPMODE(channel)); + writel(value, ioaddr + XGMAC_MTL_TXQ_OPMODE(addrs, channel)); } static void dwxgmac2_set_bfsize(struct stmmac_priv *priv, void __iomem *ioaddr, int bfsize, u32 chan) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; u32 value; - value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); value = u32_replace_bits(value, bfsize, XGMAC_RBSZ); - writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); } static void dwxgmac2_enable_sph(struct stmmac_priv *priv, void __iomem *ioaddr, bool en, u32 chan) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; u32 value = readl(ioaddr + XGMAC_RX_CONFIG); value &= ~XGMAC_CONFIG_HDSMS; value |= XGMAC_CONFIG_HDSMS_256; /* Segment max 256 bytes */ writel(value, ioaddr + XGMAC_RX_CONFIG); - value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan)); + value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(addrs, chan)); if (en) value |= XGMAC_SPH; else value &= ~XGMAC_SPH; - writel(value, ioaddr + XGMAC_DMA_CH_CONTROL(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_CONTROL(addrs, chan)); } static int dwxgmac2_enable_tbs(struct stmmac_priv *priv, void __iomem *ioaddr, bool en, u32 chan) { - u32 value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + u32 value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); if (en) value |= XGMAC_EDSE; else value &= ~XGMAC_EDSE; - writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); - value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)) & XGMAC_EDSE; + value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)) & XGMAC_EDSE; if (en && !value) return -EIO; diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c index 4bea373a881c7..a00e6dd7dc18f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c @@ -388,8 +388,11 @@ int stmmac_hwif_init(struct stmmac_priv *priv) mac->vlan = mac->vlan ? : entry->vlan; priv->hw = mac; + mac->dwxgmac_addrs = priv->plat->dwxgmac_addrs; priv->fpe_cfg.reg = entry->regs.fpe_reg; - priv->ptpaddr = priv->ioaddr + entry->regs.ptp_off; + priv->ptpaddr = priv->ioaddr + + (priv->plat->dwxgmac_addrs ? + priv->plat->dwxgmac_addrs->timestamp_base : entry->regs.ptp_off); priv->mmcaddr = priv->ioaddr + entry->regs.mmc_off; memcpy(&priv->ptp_clock_ops, entry->ptp, sizeof(struct ptp_clock_info)); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index c616a1c95e5dd..828d7a15e6694 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -351,8 +351,9 @@ static int stmmac_ethtool_get_regs_len(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); - if (priv->plat->core_type == DWMAC_CORE_XGMAC) - return XGMAC_REGSIZE * 4; + if (priv->plat->core_type == DWMAC_CORE_XGMAC || + priv->plat->core_type == DWMAC_CORE_25GMAC) + return XGMAC_REGSIZE(priv->plat->dwxgmac_addrs) * 4; else if (priv->plat->core_type == DWMAC_CORE_GMAC4) return GMAC4_REG_SPACE_SIZE; return REG_SPACE_SIZE; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c index b6b5ef7c8fc48..5ecfa469f2436 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c @@ -265,9 +265,12 @@ int dwxgmac3_fpe_map_preemption_class(struct net_device *ndev, if (!num_tc) { /* Restore default TC:Queue mapping */ for (u32 i = 0; i < priv->plat->tx_queues_to_use; i++) { - val = readl(priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(i)); + val = readl(priv->ioaddr + + XGMAC_MTL_TXQ_OPMODE(priv->plat->dwxgmac_addrs, + i)); writel(u32_replace_bits(val, i, XGMAC_Q2TCMAP), - priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(i)); + priv->ioaddr + + XGMAC_MTL_TXQ_OPMODE(priv->plat->dwxgmac_addrs, i)); } } @@ -288,9 +291,13 @@ int dwxgmac3_fpe_map_preemption_class(struct net_device *ndev, preemptible_txqs |= GENMASK(offset + count - 1, offset); for (u32 i = 0; i < count; i++) { - val = readl(priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(offset + i)); + val = readl(priv->ioaddr + + XGMAC_MTL_TXQ_OPMODE(priv->plat->dwxgmac_addrs, + offset + i)); writel(u32_replace_bits(val, tc, XGMAC_Q2TCMAP), - priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(offset + i)); + priv->ioaddr + + XGMAC_MTL_TXQ_OPMODE(priv->plat->dwxgmac_addrs, + offset + i)); } } diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 7976c0597f395..49caf6073770d 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -188,6 +188,16 @@ struct dwmac4_addrs { u32 mtl_low_cred_offset; }; +/* Address layout for XGMAC MTL, DMA, and timestamp registers */ +struct dwxgmac_addrs { + u32 dma_even_chan_base; + u32 dma_odd_chan_base; + u32 dma_chan_offset; + u32 mtl_chan_base; + u32 mtl_chan_offset; + u32 timestamp_base; +}; + enum dwmac_core_type { DWMAC_CORE_MAC100, DWMAC_CORE_GMAC, @@ -359,6 +369,7 @@ struct plat_stmmacenet_data { int msi_rx_base_vec; int msi_tx_base_vec; const struct dwmac4_addrs *dwmac4_addrs; + const struct dwxgmac_addrs *dwxgmac_addrs; unsigned int flags; struct stmmac_dma_cfg __dma_cfg; }; From d1a3cde1ce0e7e0d24142671ec9dcc42f361f267 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 23 Sep 2026 03:31:38 +0530 Subject: [PATCH 0391/1133] FROMLIST: net: stmmac: qcom-ethqos: support external PCS Select the XPCS instance initialized by stmmac when firmware provides a pcs-handle. Reject interfaces that are not supported by the selected PCS. Link: https://lore.kernel.org/netdev/20260923-qcom_xpcs_nord_emac-v1-8-4b1c682af70f@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index ddb714d7e2749..82980c54a381e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include "stmmac.h" #include "stmmac_platform.h" @@ -1052,6 +1054,47 @@ static int ethqos_scmi_setup(struct qcom_ethqos *ethqos, return 0; } +static int qcom_ethqos_pcs_init(struct stmmac_priv *priv) +{ + struct fwnode_handle *pcsnode; + struct dw_xpcs *xpcs; + + pcsnode = fwnode_find_reference(dev_fwnode(priv->device), + "pcs-handle", 0); + xpcs = xpcs_create_fwnode(pcsnode); + fwnode_handle_put(pcsnode); + if (IS_ERR(xpcs)) + return PTR_ERR(xpcs); + + priv->hw->xpcs = xpcs; + + return 0; +} + +static void qcom_ethqos_pcs_exit(struct stmmac_priv *priv) +{ + if (!priv->hw->xpcs) + return; + + xpcs_destroy(priv->hw->xpcs); + priv->hw->xpcs = NULL; +} + +static struct phylink_pcs * +qcom_ethqos_select_pcs(struct stmmac_priv *priv, phy_interface_t interface) +{ + struct phylink_pcs *pcs; + + if (!priv->hw->xpcs) + return ERR_PTR(-ENODEV); + + pcs = xpcs_to_phylink_pcs(priv->hw->xpcs); + if (!test_bit(interface, pcs->supported_interfaces)) + return ERR_PTR(-EOPNOTSUPP); + + return pcs; +} + static int qcom_ethqos_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1147,6 +1190,12 @@ static int qcom_ethqos_probe(struct platform_device *pdev) for (i = 1; i < plat_dat->tx_queues_to_use; i++) plat_dat->tx_queues_cfg[i].tbs_en = 1; + if (fwnode_property_present(dev_fwnode(dev), "pcs-handle")) { + plat_dat->pcs_init = qcom_ethqos_pcs_init; + plat_dat->pcs_exit = qcom_ethqos_pcs_exit; + plat_dat->select_pcs = qcom_ethqos_select_pcs; + } + return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); } From c574f0e0c467d93af873788cae67437eb28e1b50 Mon Sep 17 00:00:00 2001 From: Pankaj Patil Date: Tue, 5 May 2026 19:07:27 +0530 Subject: [PATCH 0392/1133] FROMLIST: arm64: dts: qcom: glymur: Add psci reboot-mode edl Add PSCI SYSTEM_RESET2 reboot-modes for glymur to be invoked by the psci reboot-mode driver. The following modes are defined: - edl: reboot into emergency download mode for image loading via the Firehose protocol. Support for these modes is dependent on the psci firmware Link: https://lore.kernel.org/lkml/20260505-glymur_reboot_mode-v1-1-59fe3e9a6868@oss.qualcomm.com/ Signed-off-by: Pankaj Patil Signed-off-by: Pradyot Kumar Nayak --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 7 +++++++ arch/arm64/boot/dts/qcom/glymur.dtsi | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index 58158b51fe295..b9ee6af3c2ecb 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -976,6 +976,13 @@ "qcom/glymur/soccp_dtb.mbn"; }; +&psci { + reboot-mode { + mode-edl = <0x80000000 0x1>; + mode-bootloader = <0x80010001 0x2>; + }; +}; + &tlmm { gpio-reserved-ranges = <4 4>, /* EC TZ Secure I3C */ <10 2>, /* OOB UART */ diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index 65a398c0a9920..95b117e4922a1 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -438,7 +438,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; From ae6508b7c3e2a01604e6710305070d6fca331dd4 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Fri, 24 Jul 2026 12:48:13 +0530 Subject: [PATCH 0393/1133] FROMLIST: arm64: dts: qcom: glymur: Enable LLCC/DDR/DDR_QOS DVFS On Qualcomm Glymur SoCs, the memlat governor and the mechanism for controlling the LLCC and DDR/DDR_QOS frequencies run on the CPU Control Processor (CPUCP). Add the CPUCP mailbox and SCMI nodes required for the QCOM SCMI Generic Extension protocol to probe and get functional bus DVFS on Glymur/Mahua SoCs. Link: https://lore.kernel.org/lkml/20260724-rfc_v8_scmi_memlat-v1-8-cb732bcff1f4@oss.qualcomm.com/ Signed-off-by: Pragnesh Papaniya Signed-off-by: Sibi Sankar --- arch/arm64/boot/dts/qcom/glymur.dtsi | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index 95b117e4922a1..9582ae4675252 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -419,6 +419,20 @@ #power-domain-cells = <1>; }; }; + + cpucp_scmi: scmi-1 { + compatible = "arm,scmi"; + mboxes = <&cpucp_mbox 0>, <&cpucp_mbox 2>; + mbox-names = "tx", "rx"; + shmem = <&cpucp_scp_lpri0>, <&cpucp_scp_lpri1>; + + #address-cells = <1>; + #size-cells = <0>; + + scmi_vendor: protocol@80 { + reg = <0x80>; + }; + }; }; clk_virt: interconnect-0 { @@ -8194,6 +8208,13 @@ #mbox-cells = <1>; }; + cpucp_mbox: mailbox@17620000 { + compatible = "qcom,glymur-cpucp-mbox", "qcom,x1e80100-cpucp-mbox"; + reg = <0x0 0x17620000 0 0x8000>, <0 0x18830000 0 0x8000>; + interrupts = ; + #mbox-cells = <1>; + }; + timer@17810000 { compatible = "arm,armv7-timer-mem"; reg = <0x0 0x17810000 0x0 0x1000>; @@ -8378,6 +8399,26 @@ }; }; + cpucp_sram: sram@18b4e000 { + compatible = "mmio-sram"; + reg = <0x0 0x18b4e000 0x0 0x400>; + + #address-cells = <1>; + #size-cells = <1>; + + ranges = <0x0 0x0 0x18b4e000 0x400>; + + cpucp_scp_lpri0: scp-sram-section@0 { + compatible = "arm,scmi-shmem"; + reg = <0x0 0x200>; + }; + + cpucp_scp_lpri1: scp-sram-section@200 { + compatible = "arm,scmi-shmem"; + reg = <0x200 0x200>; + }; + }; + nsi_noc: interconnect@1d600000 { compatible = "qcom,glymur-nsinoc"; reg = <0x0 0x1d600000 0x0 0x14080>; From 10b7107c0b33809d75e0146ae8ec2129de6c8049 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Thu, 2 Jul 2026 22:52:57 +0530 Subject: [PATCH 0394/1133] FROMLIST: arm64: dts: qcom: glymur: Enable SPEL powercap driver The Qualcomm SoC Power and Electrical Limits (SPEL) provides hardware based power monitoring and limiting capabilities for various power domains including System, SoC, CPU clusters, GPU, and various other subsystems for glymur. Link: https://lore.kernel.org/lkml/20260702-qcom_spel_driver_upstream-v3-4-434d50f0c5b0@oss.qualcomm.com/ Signed-off-by: Manaf Meethalavalappu Pallikunhi Signed-off-by: Sibi Sankar --- arch/arm64/boot/dts/qcom/glymur.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index 9582ae4675252..8c82ba53621fc 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -6098,6 +6098,16 @@ }; }; + power-limits@ef3b000 { + compatible = "qcom,glymur-spel"; + reg = <0x0 0x0ef3b000 0x0 0x1000>, + <0x0 0x0ef3d000 0x0 0x1000>, + <0x0 0x0ef3e000 0x0 0x1000>; + reg-names = "config", + "constraints", + "nodes"; + }; + tlmm: pinctrl@f100000 { compatible = "qcom,glymur-tlmm"; reg = <0x0 0x0f100000 0x0 0xf00000>; From e4c71243f424311e303b7982b247c4e23d34c46a Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Tue, 13 Oct 2026 03:16:47 -0700 Subject: [PATCH 0395/1133] FROMLIST: arm64: dts: qcom: Add refgen supplies for PCIe PHY on Glymur and Mahua boards The PCIe PHYs on Glymur and Mahua require a reference voltage provided by REFGEN, which in turn is powered by two LDOs. Since there is no devicetree node for REFGEN, add the vdda-refgen0p9 and vdda-refgen1p2 supplies for each PCIe PHY node. Link: https://lore.kernel.org/all/20261013-phy_refgen_1012-v3-3-f28305289499@oss.qualcomm.com/ Signed-off-by: Qiang Yu Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio --- .../boot/dts/qcom/glymur-asus-zenbook-a14-ux3407na.dts | 2 ++ .../boot/dts/qcom/glymur-asus-zenbook-a16-ux3607oa.dts | 4 ++++ arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 6 ++++++ arch/arm64/boot/dts/qcom/glymur-hp-elitebook-x-g2q.dts | 4 ++++ arch/arm64/boot/dts/qcom/glymur-lenovo-yoga-slim7x.dts | 6 ++++++ arch/arm64/boot/dts/qcom/glymur-qcb.dts | 6 ++++++ arch/arm64/boot/dts/qcom/mahua-crd.dts | 2 ++ .../boot/dts/qcom/mahua-lenovo-thinkpad-t14s-gen7-lcd.dts | 6 ++++++ 8 files changed, 36 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-asus-zenbook-a14-ux3407na.dts b/arch/arm64/boot/dts/qcom/glymur-asus-zenbook-a14-ux3407na.dts index e96e65a0c5b49..d1746845a6093 100644 --- a/arch/arm64/boot/dts/qcom/glymur-asus-zenbook-a14-ux3407na.dts +++ b/arch/arm64/boot/dts/qcom/glymur-asus-zenbook-a14-ux3407na.dts @@ -735,6 +735,8 @@ &pcie4_phy { vdda-phy-supply = <&vreg_l1c1>; vdda-pll-supply = <&vreg_l4f1>; + vdda-refgen0p9-supply = <&vreg_l1c1>; + vdda-refgen1p2-supply = <&vreg_l4f1>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/glymur-asus-zenbook-a16-ux3607oa.dts b/arch/arm64/boot/dts/qcom/glymur-asus-zenbook-a16-ux3607oa.dts index 95da35125d754..bf3c828c8a0b4 100644 --- a/arch/arm64/boot/dts/qcom/glymur-asus-zenbook-a16-ux3607oa.dts +++ b/arch/arm64/boot/dts/qcom/glymur-asus-zenbook-a16-ux3607oa.dts @@ -818,6 +818,8 @@ &pcie4_phy { vdda-phy-supply = <&vreg_l1c_e1>; vdda-pll-supply = <&vreg_l4f_e1>; + vdda-refgen0p9-supply = <&vreg_l1c_e1>; + vdda-refgen1p2-supply = <&vreg_l4f_e1>; status = "okay"; }; @@ -843,6 +845,8 @@ &pcie5_phy { vdda-phy-supply = <&vreg_l2f_e0>; vdda-pll-supply = <&vreg_l4c_e0>; + vdda-refgen0p9-supply = <&vreg_l2f_e0>; + vdda-refgen1p2-supply = <&vreg_l4c_e0>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index b9ee6af3c2ecb..5c1256692968c 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -764,6 +764,8 @@ &pcie4_phy { vdda-phy-supply = <&vreg_l1c_e1_0p82>; vdda-pll-supply = <&vreg_l4f_e1_1p08>; + vdda-refgen0p9-supply = <&vreg_l1c_e1_0p82>; + vdda-refgen1p2-supply = <&vreg_l4f_e1_1p08>; status = "okay"; }; @@ -800,6 +802,8 @@ &pcie5_phy { vdda-phy-supply = <&vreg_l2f_e0_0p82>; vdda-pll-supply = <&vreg_l4h_e0_1p2>; + vdda-refgen0p9-supply = <&vreg_l2f_e0_0p82>; + vdda-refgen1p2-supply = <&vreg_l4h_e0_1p2>; status = "okay"; }; @@ -821,6 +825,8 @@ &pcie6_phy { vdda-phy-supply = <&vreg_l1c_e1_0p82>; vdda-pll-supply = <&vreg_l4f_e1_1p08>; + vdda-refgen0p9-supply = <&vreg_l1c_e1_0p82>; + vdda-refgen1p2-supply = <&vreg_l4f_e1_1p08>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/glymur-hp-elitebook-x-g2q.dts b/arch/arm64/boot/dts/qcom/glymur-hp-elitebook-x-g2q.dts index 096d40e49210a..7f79470ec0048 100644 --- a/arch/arm64/boot/dts/qcom/glymur-hp-elitebook-x-g2q.dts +++ b/arch/arm64/boot/dts/qcom/glymur-hp-elitebook-x-g2q.dts @@ -545,6 +545,8 @@ &pcie4_phy { vdda-phy-supply = <&vreg_l1c_e1_0p91>; vdda-pll-supply = <&vreg_l4f_e1_1p2>; + vdda-refgen0p9-supply = <&vreg_l1c_e1_0p91>; + vdda-refgen1p2-supply = <&vreg_l4f_e1_1p2>; status = "okay"; }; @@ -581,6 +583,8 @@ &pcie5_phy { vdda-phy-supply = <&vreg_l2f_e0_0p94>; vdda-pll-supply = <&vreg_l4h_e0_1p2>; + vdda-refgen0p9-supply = <&vreg_l2f_e0_0p94>; + vdda-refgen1p2-supply = <&vreg_l4h_e0_1p2>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/glymur-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/glymur-lenovo-yoga-slim7x.dts index 769f195c99d91..130946ba97852 100644 --- a/arch/arm64/boot/dts/qcom/glymur-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/glymur-lenovo-yoga-slim7x.dts @@ -743,6 +743,8 @@ &pcie4_phy { vdda-phy-supply = <&vreg_l1c_e1>; vdda-pll-supply = <&vreg_l4f_e1>; + vdda-refgen0p9-supply = <&vreg_l1c_e1>; + vdda-refgen1p2-supply = <&vreg_l4f_e1>; status = "okay"; }; @@ -779,6 +781,8 @@ &pcie5_phy { vdda-phy-supply = <&vreg_l2f_e0>; vdda-pll-supply = <&vreg_l4h_e0>; + vdda-refgen0p9-supply = <&vreg_l2f_e0>; + vdda-refgen1p2-supply = <&vreg_l4h_e0>; status = "okay"; }; @@ -800,6 +804,8 @@ &pcie6_phy { vdda-phy-supply = <&vreg_l1c_e1>; vdda-pll-supply = <&vreg_l4f_e1>; + vdda-refgen0p9-supply = <&vreg_l1c_e1>; + vdda-refgen1p2-supply = <&vreg_l4f_e1>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/glymur-qcb.dts b/arch/arm64/boot/dts/qcom/glymur-qcb.dts index 17d8ff3aed23b..f26bdc1cd84a7 100644 --- a/arch/arm64/boot/dts/qcom/glymur-qcb.dts +++ b/arch/arm64/boot/dts/qcom/glymur-qcb.dts @@ -448,6 +448,8 @@ &pcie4_phy { vdda-phy-supply = <&vreg_l1c_e1_0p82>; vdda-pll-supply = <&vreg_l4f_e1_1p08>; + vdda-refgen0p9-supply = <&vreg_l1c_e1_0p82>; + vdda-refgen1p2-supply = <&vreg_l4f_e1_1p08>; status = "okay"; }; @@ -484,6 +486,8 @@ &pcie5_phy { vdda-phy-supply = <&vreg_l2f_e0_0p82>; vdda-pll-supply = <&vreg_l4h_e0_1p2>; + vdda-refgen0p9-supply = <&vreg_l2f_e0_0p82>; + vdda-refgen1p2-supply = <&vreg_l4h_e0_1p2>; status = "okay"; }; @@ -505,6 +509,8 @@ &pcie6_phy { vdda-phy-supply = <&vreg_l1c_e1_0p82>; vdda-pll-supply = <&vreg_l4f_e1_1p08>; + vdda-refgen0p9-supply = <&vreg_l1c_e1_0p82>; + vdda-refgen1p2-supply = <&vreg_l4f_e1_1p08>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/mahua-crd.dts b/arch/arm64/boot/dts/qcom/mahua-crd.dts index 17e40f2a6259f..45c95543fff8d 100644 --- a/arch/arm64/boot/dts/qcom/mahua-crd.dts +++ b/arch/arm64/boot/dts/qcom/mahua-crd.dts @@ -23,6 +23,8 @@ &pcie3b_phy { vdda-phy-supply = <&vreg_l3c_e1_0p89>; vdda-pll-supply = <&vreg_l2c_e1_1p14>; + vdda-refgen0p9-supply = <&vreg_l1c_e1_0p82>; + vdda-refgen1p2-supply = <&vreg_l4f_e1_1p08>; }; &tcsr { diff --git a/arch/arm64/boot/dts/qcom/mahua-lenovo-thinkpad-t14s-gen7-lcd.dts b/arch/arm64/boot/dts/qcom/mahua-lenovo-thinkpad-t14s-gen7-lcd.dts index 26d6d8285e040..ac7e1382166db 100644 --- a/arch/arm64/boot/dts/qcom/mahua-lenovo-thinkpad-t14s-gen7-lcd.dts +++ b/arch/arm64/boot/dts/qcom/mahua-lenovo-thinkpad-t14s-gen7-lcd.dts @@ -813,6 +813,8 @@ &pcie4_phy { vdda-phy-supply = <&vreg_l1c_e1_0p82>; vdda-pll-supply = <&vreg_l4f_e1_1p2>; + vdda-refgen0p9-supply = <&vreg_l1c_e1_0p82>; + vdda-refgen1p2-supply = <&vreg_l4f_e1_1p2>; status = "okay"; }; @@ -850,6 +852,8 @@ &pcie5_phy { vdda-phy-supply = <&vreg_l2f_e0_0p94>; vdda-pll-supply = <&vreg_l4h_e0_1p2>; + vdda-refgen0p9-supply = <&vreg_l2f_e0_0p94>; + vdda-refgen1p2-supply = <&vreg_l4h_e0_1p2>; status = "okay"; }; @@ -872,6 +876,8 @@ &pcie6_phy { vdda-phy-supply = <&vreg_l1c_e1_0p82>; vdda-pll-supply = <&vreg_l4f_e1_1p2>; + vdda-refgen0p9-supply = <&vreg_l1c_e1_0p82>; + vdda-refgen1p2-supply = <&vreg_l4f_e1_1p2>; status = "okay"; }; From 57e4a334af30bb82693b2dc63b0da3e2e9276a50 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Jul 2026 10:39:04 +0800 Subject: [PATCH 0396/1133] FROMLIST: arm64: dts: qcom: glymur: use Aggregator TNOC compatible The traceNoC node is the system-level Aggregator TNOC, so it must own a valid ATID that tags the whole aggregation path. It was marked compatible with "qcom,coresight-itnoc", an Interconnect TNOC, which is never assigned an ATID. As a result the aggregator had no trace ID and could not tag the merged trace. An Interconnect TNOC is a subsystem-level aggregator: it merges trace from the ATB sources within its subsystem (TPDMs and other ATB masters) and forwards the combined stream to the system-level Aggregator TNOC. It carries no ATID of its own, because the Aggregator TNOC downstream in the path already owns the ATID. Switch the node to "qcom,coresight-tnoc" so it is described as the Aggregator TNOC it is and is assigned a system trace ID. Rename the node to "tn" and use the "apb_pclk" clock name as required by the Aggregator TNOC binding. Link: https://lore.kernel.org/all/20260710-fix-tracenoc-probe-issue-v6-5-41eb36fef8d9@oss.qualcomm.com/ Fixes: 1f7d0c42a08d ("arm64: dts: qcom: glymur: add coresight nodes") Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/glymur.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index 8c82ba53621fc..6b5b64eba0f5d 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -7293,12 +7293,12 @@ }; }; - itnoc@11200000 { - compatible = "qcom,coresight-itnoc"; + tn@11200000 { + compatible = "qcom,coresight-tnoc"; reg = <0x0 0x11200000 0x0 0x3c00>; clocks = <&aoss_qmp>; - clock-names = "apb"; + clock-names = "apb_pclk"; in-ports { #address-cells = <1>; From c036cb8c3ba5af1e239c30fdd0472e97d2f21715 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Mon, 5 Oct 2026 17:54:10 +0530 Subject: [PATCH 0397/1133] FROMLIST: arm64: dts: qcom: pmh0101: Enable BCL sensor node Add Battery Current Limiting (BCL) hardware monitor node for pmh0101 PMIC. The BCL monitors battery voltage and current, providing hardware interrupts when configurable thresholds are violated. Link: https://lore.kernel.org/all/20261005-qcom-bcl-hwmon-v4-9-50b9a8c730b7@oss.qualcomm.com/ Reviewed-by: Abel Vesa Signed-off-by: Manaf Meethalavalappu Pallikunhi Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/pmh0101.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pmh0101.dtsi b/arch/arm64/boot/dts/qcom/pmh0101.dtsi index b1ec413259583..5635ed350f383 100644 --- a/arch/arm64/boot/dts/qcom/pmh0101.dtsi +++ b/arch/arm64/boot/dts/qcom/pmh0101.dtsi @@ -43,6 +43,17 @@ #thermal-sensor-cells = <0>; }; + sensor@4700 { + compatible = "qcom,pmh0101-bcl"; + reg = <0x4700>; + interrupts = <0x1 0x47 0x0 IRQ_TYPE_EDGE_RISING>, + <0x1 0x47 0x1 IRQ_TYPE_EDGE_RISING>, + <0x1 0x47 0x2 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "max-min", + "critical", + "emergency"; + }; + pmh0101_gpios: gpio@8800 { compatible = "qcom,pmh0101-gpio", "qcom,spmi-gpio"; reg = <0x8800>; From 49ef1706067bf7cb8d9a723ad78e1c68ac89fdab Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Mon, 5 Oct 2026 17:54:13 +0530 Subject: [PATCH 0398/1133] FROMLIST: arm64: dts: qcom: smb2370: Enable BCL sensor node Add Battery Current Limiting (BCL) hardware monitor node for smb2370 PMIC. The BCL monitors battery voltage and current, providing hardware interrupts when configurable thresholds are violated. Link: https://lore.kernel.org/all/20261005-qcom-bcl-hwmon-v4-12-50b9a8c730b7@oss.qualcomm.com/ Reviewed-by: Abel Vesa Signed-off-by: Manaf Meethalavalappu Pallikunhi --- arch/arm64/boot/dts/qcom/smb2370.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/smb2370.dtsi b/arch/arm64/boot/dts/qcom/smb2370.dtsi index 1e02578e4ee34..4809b3d8cfe25 100644 --- a/arch/arm64/boot/dts/qcom/smb2370.dtsi +++ b/arch/arm64/boot/dts/qcom/smb2370.dtsi @@ -10,6 +10,17 @@ #address-cells = <1>; #size-cells = <0>; + sensor@4700 { + compatible = "qcom,smb2370-bcl"; + reg = <0x4700>; + interrupts = <0x9 0x47 0x0 IRQ_TYPE_EDGE_RISING>, + <0x9 0x47 0x1 IRQ_TYPE_EDGE_RISING>, + <0x9 0x47 0x2 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "max-min", + "critical", + "emergency"; + }; + smb2370_j_e2_eusb2_repeater: phy@fd00 { compatible = "qcom,smb2370-eusb2-repeater"; reg = <0xfd00>; From 61a2c415258db6f35e1d9865e495c9c80a27ae8d Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Thu, 17 Sep 2026 10:30:27 +0530 Subject: [PATCH 0399/1133] FROMLIST: arm64: dts: qcom: glymur: Add iris video node Add iris video codec to glymur SoC, which comes with significantly different powering up sequence than previous platforms, thus different clocks and resets. Link: https://lore.kernel.org/all/20260917-glymur-v11-8-e0c8bc914742@oss.qualcomm.com/ Reviewed-by: Vikash Garodia Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Tested-by: Konrad Dybcio Signed-off-by: Vishnu Reddy --- arch/arm64/boot/dts/qcom/glymur.dtsi | 120 +++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index 6b5b64eba0f5d..ef3da2afc025f 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -5820,6 +5820,126 @@ }; }; + iris: video-codec@aa00000 { + compatible = "qcom,glymur-iris"; + reg = <0x0 0x0aa00000 0x0 0xf0000>; + + clocks = <&gcc GCC_VIDEO_AXI0C_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&gcc GCC_VIDEO_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK>, + <&gcc GCC_VIDEO_AXI1_CLK>, + <&videocc VIDEO_CC_MVS1_CLK>, + <&videocc VIDEO_CC_MVS1_FREERUN_CLK>; + clock-names = "core_iface", + "core", + "vcodec0_core", + "vcodec0_iface", + "core_freerun", + "vcodec0_core_freerun", + "vcodec1_iface", + "vcodec1_core", + "vcodec1_core_freerun"; + + dma-coherent; + + interconnects = <&hsc_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_VENUS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_VIDEO QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + interrupts = ; + + memory-region = <&video_mem>; + + operating-points-v2 = <&iris_opp_table>; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc VIDEO_CC_MVS1_GDSC>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vcodec1"; + + resets = <&gcc GCC_VIDEO_AXI0C_CLK_ARES>, + <&gcc GCC_VIDEO_AXI0_CLK_ARES>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK_ARES>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK_ARES>, + <&gcc GCC_VIDEO_AXI1_CLK_ARES>, + <&videocc VIDEO_CC_MVS1_FREERUN_CLK_ARES>; + reset-names = "core_bus", + "vcodec0_bus", + "core", + "vcodec0_core", + "vcodec1_bus", + "vcodec1_core"; + + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0x0 0xffe00000>; + + status = "disabled"; + + non-pixel { + iommus = <&apps_smmu 0x1940 0x0>, + <&apps_smmu 0x1944 0x0>, + <&apps_smmu 0x19e0 0x0>; + iommu-ranges = <0x25800000 0xda600000>; + }; + + pixel { + iommus = <&apps_smmu 0x1943 0x0>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000 240000000 360000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 507000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-366000000 { + opp-hz = /bits/ 64 <366000000 366000000 549000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_nom>; + }; + + opp-533333334 { + opp-hz = /bits/ 64 <533333334 533333334 800000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo>; + }; + + opp-655000000 { + opp-hz = /bits/ 64 <655000000 655000000 982000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo_l1>; + }; + }; + }; + videocc: clock-controller@aaf0000 { compatible = "qcom,glymur-videocc"; reg = <0x0 0x0aaf0000 0x0 0x10000>; From 5421f91bd7808d9a8fc0b62f245f456d92d446d1 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Thu, 17 Sep 2026 10:30:28 +0530 Subject: [PATCH 0400/1133] FROMLIST: arm64: dts: qcom: glymur-crd: Enable iris video codec node The iris hardware block is described in the glymur SoC DTSI, and enabling it here allows the media iris driver to probe and use the video codec functionality. Link: https://lore.kernel.org/all/20260917-glymur-v11-9-e0c8bc914742@oss.qualcomm.com/ Reviewed-by: Vikash Garodia Reviewed-by: Dmitry Baryshkov Signed-off-by: Vishnu Reddy --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index 5c1256692968c..4b6067746c7ba 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -694,6 +694,16 @@ }; }; +&iris { + firmware-name = "qcom/vpu/vpu36_p4_s7.mbn"; + + status = "okay"; + + video-firmware { + iommus = <&apps_smmu 0x19e2 0x0>; + }; +}; + &lpass_vamacro { pinctrl-0 = <&dmic01_default>, <&dmic23_default>; pinctrl-names = "default"; From 842afb2abcda5edc052c366ed125d9c65b51455e Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 23 Sep 2026 03:34:07 +0530 Subject: [PATCH 0401/1133] FROMLIST: net: stmmac: add Qualcomm Nord ETHQOS support Qualcomm Nord provides two ETHQOS controllers based on the Synopsys DesignWare XGMAC IP. Add their register layout, wrapper configuration for USXGMII, EEE clock handling required for PCS link-up, and platform-specific SGMII loopback control. Link: ttps://lore.kernel.org/netdev/20260923-qcom_xpcs_nord_emac-v1-9-4b1c682af70f@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 154 +++++++++++++++++- 1 file changed, 146 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 82980c54a381e..c15d48d124cea 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -25,8 +25,14 @@ #define RGMII_IO_MACRO_CONFIG2 0x1C #define RGMII_IO_MACRO_DEBUG1 0x20 #define EMAC_SYSTEM_LOW_POWER_DEBUG 0x28 +#define RGMII_IO_MACRO_SCRATCH_2 0x44 #define EMAC_WRAPPER_SGMII_PHY_CNTRL1 0xf4 +#define RGMII_IO_MACRO_BYPASS 0x16C +#define EMAC_WRAPPER_SGMII_PHY_CNTRL0 0x170 +#define EMAC_WRAPPER_SGMII_PHY_CNTRL1_V4 0x174 +#define EMAC_WRAPPER_USXGMII_MUX_SEL 0x1D0 + /* RGMII_IO_MACRO_CONFIG fields */ #define RGMII_CONFIG_FUNC_CLK_EN BIT(30) #define RGMII_CONFIG_POS_NEG_DATA_SEL BIT(23) @@ -82,6 +88,21 @@ #define RGMII_CONFIG2_RX_PROG_SWAP BIT(7) #define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6) #define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5) +#define RGMII_CONFIG2_MODE_EN_VIA_GMII BIT(21) + +/* EMAC_WRAPPER_SGMII_PHY_CNTRL0 fields */ +#define SGMII_PHY_CNTRL0_2P5G_1G_CLK_SEL GENMASK(6, 5) + +/* EMAC_WRAPPER_SGMII_PHY_CNTRL1_V4 fields */ +#define SGMII_PHY_CNTRL1_USXGMII_GMII_MASTER_CLK_MUX_SEL BIT(4) +#define SGMII_PHY_CNTRL1_RGMII_SGMII_CLK_MUX_SEL BIT(0) + +/* RGMII_IO_MACRO_BYPASS fields */ +#define RGMII_BYPASS_EN BIT(0) + +/* EMAC_WRAPPER_USXGMII_MUX_SEL fields */ +#define USXGMII_CLK_BLK_GMII_CLK_BLK_SEL BIT(1) +#define USXGMII_CLK_BLK_CLK_EN BIT(0) /* EMAC_WRAPPER_SGMII_PHY_CNTRL1 bits */ #define SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN BIT(3) @@ -118,6 +139,9 @@ struct ethqos_emac_driver_data { * query it. */ unsigned long ptp_clk_rate; + struct dwxgmac_addrs dwxgmac_addrs; + enum dwmac_core_type core_type; + void (*set_sgmii_loopback)(struct qcom_ethqos *ethqos, bool enable); int (*setup)(struct qcom_ethqos *ethqos, struct plat_stmmacenet_data *plat_dat); }; @@ -126,6 +150,7 @@ struct qcom_ethqos { struct platform_device *pdev; void __iomem *rgmii_base; struct clk *link_clk; + struct clk *eee_clk; struct phy *serdes_phy; phy_interface_t phy_mode; struct clk_bulk_data noc_clks[ETHQOS_MAX_NOC_CLKS]; @@ -133,6 +158,7 @@ struct qcom_ethqos { int num_noc_clks; struct dev_pm_domain_list *pds; const struct ethqos_emac_driver_data *data; + void (*set_sgmii_loopback)(struct qcom_ethqos *ethqos, bool enable); }; static u32 rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) @@ -232,6 +258,15 @@ qcom_ethqos_set_sgmii_loopback(struct qcom_ethqos *ethqos, bool enable) EMAC_WRAPPER_SGMII_PHY_CNTRL1); } +static void +qcom_ethqos_set_sgmii_loopback_nord(struct qcom_ethqos *ethqos, bool enable) +{ + rgmii_updatel(ethqos, + SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN, + enable ? SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN : 0, + EMAC_WRAPPER_SGMII_PHY_CNTRL1_V4); +} + static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos) { rgmii_setmask(ethqos, RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG); @@ -256,6 +291,7 @@ static const struct ethqos_emac_driver_data emac_v2_3_0_data = { .num_rgmii_por = ARRAY_SIZE(emac_v2_3_0_por), .rgmii_config_loopback_en = true, .has_emac_ge_3 = false, + .core_type = DWMAC_CORE_GMAC4, .setup = ethqos_hlos_setup, }; @@ -273,6 +309,7 @@ static const struct ethqos_emac_driver_data emac_v2_1_0_data = { .num_rgmii_por = ARRAY_SIZE(emac_v2_1_0_por), .rgmii_config_loopback_en = false, .has_emac_ge_3 = false, + .core_type = DWMAC_CORE_GMAC4, .setup = ethqos_hlos_setup, }; @@ -290,6 +327,7 @@ static const struct ethqos_emac_driver_data emac_v3_0_0_data = { .num_rgmii_por = ARRAY_SIZE(emac_v3_0_0_por), .rgmii_config_loopback_en = false, .has_emac_ge_3 = true, + .core_type = DWMAC_CORE_GMAC4, .dwmac4_addrs = { .dma_chan = 0x00008100, .dma_chan_offset = 0x1000, @@ -325,6 +363,8 @@ static const struct ethqos_emac_driver_data emac_v4_0_0_data = { .has_emac_ge_3 = true, .link_clk_name = "phyaux", .needs_sgmii_loopback = true, + .core_type = DWMAC_CORE_GMAC4, + .set_sgmii_loopback = qcom_ethqos_set_sgmii_loopback, .dma_addr_width = 36, .dwmac4_addrs = { .dma_chan = 0x00008100, @@ -349,7 +389,9 @@ static const struct ethqos_emac_driver_data emac_v4_0_0_scmi_data = { .has_emac_ge_3 = true, .needs_sgmii_loopback = true, .dma_addr_width = 36, + .core_type = DWMAC_CORE_GMAC4, .ptp_clk_rate = 230400000, + .set_sgmii_loopback = qcom_ethqos_set_sgmii_loopback, .dwmac4_addrs = { .dma_chan = 0x00008100, .dma_chan_offset = 0x1000, @@ -378,6 +420,7 @@ static const struct ethqos_noc_clk_cfg shikra_noc_clks[] = { static const struct ethqos_emac_driver_data shikra_data = { .dma_addr_width = 36, .has_emac_ge_3 = true, + .core_type = DWMAC_CORE_GMAC4, .noc_clk_cfg = shikra_noc_clks, .num_noc_clks = ARRAY_SIZE(shikra_noc_clks), .rgmii_config_loopback_en = false, @@ -607,6 +650,47 @@ static void ethqos_rgmii_id_macro_init(struct qcom_ethqos *ethqos, int speed) rgmii_setmask(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); } +static void ethqos_configure_usxgmii(struct qcom_ethqos *ethqos) +{ + unsigned int i; + + for (i = 0; i < ethqos->data->num_rgmii_por; i++) + rgmii_writel(ethqos, ethqos->data->rgmii_por[i].value, + ethqos->data->rgmii_por[i].offset); + + ethqos_set_func_clk_en(ethqos); + + rgmii_updatel(ethqos, RGMII_BYPASS_EN, RGMII_BYPASS_EN, + RGMII_IO_MACRO_BYPASS); + rgmii_updatel(ethqos, RGMII_CONFIG2_MODE_EN_VIA_GMII, 0, + RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, SGMII_PHY_CNTRL0_2P5G_1G_CLK_SEL, BIT(5), + EMAC_WRAPPER_SGMII_PHY_CNTRL0); + rgmii_updatel(ethqos, SGMII_PHY_CNTRL1_RGMII_SGMII_CLK_MUX_SEL, 0, + EMAC_WRAPPER_SGMII_PHY_CNTRL1_V4); + rgmii_updatel(ethqos, SGMII_PHY_CNTRL1_USXGMII_GMII_MASTER_CLK_MUX_SEL, + SGMII_PHY_CNTRL1_USXGMII_GMII_MASTER_CLK_MUX_SEL, + EMAC_WRAPPER_SGMII_PHY_CNTRL1_V4); + + rgmii_updatel(ethqos, USXGMII_CLK_BLK_GMII_CLK_BLK_SEL, 0, + EMAC_WRAPPER_USXGMII_MUX_SEL); + rgmii_updatel(ethqos, USXGMII_CLK_BLK_CLK_EN, 0, + EMAC_WRAPPER_USXGMII_MUX_SEL); + + rgmii_updatel(ethqos, USXGMII_CLK_BLK_GMII_CLK_BLK_SEL, + USXGMII_CLK_BLK_GMII_CLK_BLK_SEL, + EMAC_WRAPPER_USXGMII_MUX_SEL); +} + +static void +ethqos_fix_mac_speed_usxgmii(void *bsp_priv, phy_interface_t interface, + int speed, unsigned int mode) +{ + struct qcom_ethqos *ethqos = bsp_priv; + + ethqos_configure_usxgmii(ethqos); +} + static void ethqos_fix_mac_speed_rgmii(void *bsp_priv, phy_interface_t interface, int speed, unsigned int mode) @@ -774,7 +858,8 @@ static int ethqos_mac_finish_serdes(struct net_device *ndev, void *priv, struct qcom_ethqos *ethqos = priv; int ret = 0; - qcom_ethqos_set_sgmii_loopback(ethqos, false); + if (ethqos->set_sgmii_loopback) + ethqos->set_sgmii_loopback(ethqos, false); /* The interface mode is only known once phylink has resolved it and * may change at runtime, so keep it in sync for later @@ -833,9 +918,21 @@ static int ethqos_clks_config(void *priv, bool enabled) dev_err(ðqos->pdev->dev, "NOC clocks enable failed: %d\n", ret); clk_disable_unprepare(ethqos->link_clk); - dev_pm_opp_set_rate(ðqos->pdev->dev, 0); - return ret; - } + dev_pm_opp_set_rate(ðqos->pdev->dev, 0); + return ret; + } + } + + /* PCS link-up depends on the EEE clock due to a hardware quirk. */ + ret = clk_prepare_enable(ethqos->eee_clk); + if (ret) { + dev_err(ðqos->pdev->dev, "eee_clk enable failed\n"); + if (ethqos->num_noc_clks) + clk_bulk_disable_unprepare(ethqos->num_noc_clks, + ethqos->noc_clks); + clk_disable_unprepare(ethqos->link_clk); + dev_pm_opp_set_rate(ðqos->pdev->dev, 0); + return ret; } /* Enable functional clock to prevent DMA reset to timeout due @@ -843,12 +940,14 @@ static int ethqos_clks_config(void *priv, bool enabled) * cycled. The actual configuration will be adjusted once * ethqos' fix_mac_speed() method is invoked. */ - qcom_ethqos_set_sgmii_loopback(ethqos, true); + if (ethqos->set_sgmii_loopback) + ethqos->set_sgmii_loopback(ethqos, true); ethqos_set_func_clk_en(ethqos); } else { if (ethqos->num_noc_clks) clk_bulk_disable_unprepare(ethqos->num_noc_clks, ethqos->noc_clks); + clk_disable_unprepare(ethqos->eee_clk); clk_disable_unprepare(ethqos->link_clk); if (ethqos->num_noc_clks) dev_pm_opp_set_rate(ðqos->pdev->dev, 0); @@ -941,6 +1040,11 @@ static int ethqos_hlos_setup(struct qcom_ethqos *ethqos, return dev_err_probe(dev, PTR_ERR(ethqos->link_clk), "Failed to get link_clk\n"); + ethqos->eee_clk = devm_clk_get_optional(dev, "eee"); + if (IS_ERR(ethqos->eee_clk)) + return dev_err_probe(dev, PTR_ERR(ethqos->eee_clk), + "Failed to get eee_clk\n"); + plat_dat->clks_config = ethqos_clks_config; ret = ethqos_clks_config(ethqos, true); @@ -952,7 +1056,8 @@ static int ethqos_hlos_setup(struct qcom_ethqos *ethqos, return ret; ethqos_set_clk_tx_rate(ethqos, NULL, plat_dat->phy_interface, SPEED_10); - qcom_ethqos_set_sgmii_loopback(ethqos, true); + if (ethqos->set_sgmii_loopback) + ethqos->set_sgmii_loopback(ethqos, true); ethqos_set_func_clk_en(ethqos); switch (ethqos->phy_mode) { @@ -1134,6 +1239,10 @@ static int qcom_ethqos_probe(struct platform_device *pdev) case PHY_INTERFACE_MODE_SGMII: plat_dat->mac_finish = ethqos_mac_finish_serdes; break; + case PHY_INTERFACE_MODE_USXGMII: + plat_dat->fix_mac_speed = ethqos_fix_mac_speed_usxgmii; + plat_dat->mac_finish = ethqos_mac_finish_serdes; + break; default: dev_err(dev, "Unsupported phy mode %s\n", phy_modes(ethqos->phy_mode)); @@ -1143,6 +1252,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ethqos->pdev = pdev; data = of_device_get_match_data(dev); ethqos->data = data; + ethqos->set_sgmii_loopback = data->set_sgmii_loopback; if (WARN_ON(!data->setup)) return -EINVAL; @@ -1170,9 +1280,11 @@ static int qcom_ethqos_probe(struct platform_device *pdev) plat_dat->clk_csr = STMMAC_CSR_60_100M; plat_dat->bsp_priv = ethqos; plat_dat->ptp_clk_freq_config = ethqos_ptp_clk_freq_config; - plat_dat->core_type = DWMAC_CORE_GMAC4; + plat_dat->core_type = data->core_type; if (data->has_emac_ge_3) plat_dat->dwmac4_addrs = &data->dwmac4_addrs; + if (data->dwxgmac_addrs.dma_even_chan_base) + plat_dat->dwxgmac_addrs = &data->dwxgmac_addrs; plat_dat->pmt = true; if (of_property_read_bool(np, "snps,tso")) plat_dat->flags |= STMMAC_FLAG_TSO_EN; @@ -1199,8 +1311,34 @@ static int qcom_ethqos_probe(struct platform_device *pdev) return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); } +static const struct ethqos_emac_por emac_nord_por[] = { + { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C04D03 }, + { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C }, + { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00222060 }, + { .offset = RGMII_IO_MACRO_SCRATCH_2, .value = 0x4c }, +}; + +static const struct ethqos_emac_driver_data emac_nord_data = { + .rgmii_por = emac_nord_por, + .num_rgmii_por = ARRAY_SIZE(emac_nord_por), + .dma_addr_width = 40, + .link_clk_name = "phyaux", + .core_type = DWMAC_CORE_25GMAC, + .set_sgmii_loopback = qcom_ethqos_set_sgmii_loopback_nord, + .setup = ethqos_hlos_setup, + .dwxgmac_addrs = { + .dma_even_chan_base = 0x00008500, + .dma_odd_chan_base = 0x00008580, + .dma_chan_offset = 0x00001000, + .mtl_chan_base = 0x00008000, + .mtl_chan_offset = 0x00001000, + .timestamp_base = 0x00007000, + }, +}; + static const struct of_device_id qcom_ethqos_match[] = { - { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data}, + { .compatible = "qcom,nord-ethqos", .data = &emac_nord_data }, + { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data }, { .compatible = "qcom,sa8255p-ethqos", .data = &emac_v4_0_0_scmi_data}, { .compatible = "qcom,sa8775p-ethqos", .data = &emac_v4_0_0_data}, { .compatible = "qcom,sc8280xp-ethqos", .data = &emac_v3_0_0_data}, From 4d556571888481060b98d3f7202311ab0cbedc54 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 23 Sep 2026 03:34:51 +0530 Subject: [PATCH 0402/1133] PENDING: net: stmmac: QCOM DW25GMAC fixes Qualcomm Nord requires DW25GMAC HDMA channels to wait for CSR initialization, mappings for channels not exposed to Linux, and independent VDMA and PDMA traffic-class maps. This patch is tightly coupled with the following ongoing series from Broadcom adding the core driver and hwif integration: https://lore.kernel.org/netdev/20260402213629.1996133-2-jitendra.vegiraju@broadcom.com/ https://lore.kernel.org/netdev/20260402213629.1996133-3-jitendra.vegiraju@broadcom.com/ That series is expected to be revised. Before posting this patch, it must be rebased onto the latest Broadcom revision and retested on Qualcomm Nord hardware. Keep this change downstream until those dependencies are satisfied, then revise and post the remaining Qualcomm-specific delta. Signed-off-by: Mohd Ayaan Anwar --- .../net/ethernet/stmicro/stmmac/dw25gmac.c | 164 ++++++++++++++---- .../net/ethernet/stmicro/stmmac/dw25gmac.h | 10 ++ .../stmicro/stmmac/dwmac-qcom-ethqos.c | 17 ++ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 20 +++ include/linux/stmmac.h | 4 + 5 files changed, 181 insertions(+), 34 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dw25gmac.c b/drivers/net/ethernet/stmicro/stmmac/dw25gmac.c index 82eb22bff73e0..27443f7fa827d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dw25gmac.c +++ b/drivers/net/ethernet/stmicro/stmmac/dw25gmac.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2024-2026 Broadcom Corporation */ +#include #include "stmmac.h" #include "dwxgmac2.h" #include "dw25gmac.h" @@ -21,6 +22,23 @@ u32 dw25gmac_decode_vdma_count(u32 regval) return 0; } +static u32 dw25gmac_tc(const struct stmmac_dma_cfg *dma_cfg, + const u8 *map, u32 chan) +{ + if (map && chan < dma_cfg->dma_map_size) + return map[chan]; + + return chan < 8 ? chan : chan - 7; +} + +static int dw25gmac_dma_ch_ind_wait(void __iomem *ioaddr) +{ + u32 value; + + return readl_poll_timeout(ioaddr + XXVGMAC_DMA_CH_IND_CONTROL, value, + !(value & XGMAC_OB), 10, 20000); +} + static int rd_dma_ch_ind(void __iomem *ioaddr, u8 mode, u32 channel) { u32 reg_val = 0; @@ -29,6 +47,9 @@ static int rd_dma_ch_ind(void __iomem *ioaddr, u8 mode, u32 channel) reg_val |= FIELD_PREP(XXVGMAC_ADDR_OFFSET, channel); reg_val |= XXVGMAC_CMD_TYPE | XXVGMAC_OB; writel(reg_val, ioaddr + XXVGMAC_DMA_CH_IND_CONTROL); + if (dw25gmac_dma_ch_ind_wait(ioaddr)) + pr_err_ratelimited("dw25gmac: indirect read timed out\n"); + return readl(ioaddr + XXVGMAC_DMA_CH_IND_DATA); } @@ -41,6 +62,8 @@ static void wr_dma_ch_ind(void __iomem *ioaddr, u8 mode, u32 channel, u32 val) reg_val |= FIELD_PREP(XXVGMAC_ADDR_OFFSET, channel); reg_val |= XGMAC_OB; writel(reg_val, ioaddr + XXVGMAC_DMA_CH_IND_CONTROL); + if (dw25gmac_dma_ch_ind_wait(ioaddr)) + pr_err_ratelimited("dw25gmac: indirect write timed out\n"); } void dw25gmac_dma_init(void __iomem *ioaddr, @@ -51,6 +74,10 @@ void dw25gmac_dma_init(void __iomem *ioaddr, u32 value; u32 i; + if (readl_poll_timeout(ioaddr + XGMAC_DMA_MODE, value, + value & XXVGMAC_HMIC, 10, 200000)) + pr_warn("dw25gmac: timeout waiting for HMIC\n"); + value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE); value &= ~(XGMAC_AAL | XGMAC_EAME); if (dma_cfg->aal) @@ -84,13 +111,61 @@ void dw25gmac_dma_init(void __iomem *ioaddr, } } +static void +dw25gmac_dma_map_tx_chan(struct stmmac_priv *priv, void __iomem *ioaddr, + u32 chan) +{ + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + const struct stmmac_dma_cfg *dma_cfg = priv->plat->dma_cfg; + u32 pdma_tc, vdma_tc; + u32 value; + + pdma_tc = dw25gmac_tc(dma_cfg, dma_cfg->pdma_tc_map, chan); + vdma_tc = dw25gmac_tc(dma_cfg, dma_cfg->vdma_tc_map, chan); + + value = rd_dma_ch_ind(ioaddr, MODE_TXEXTCFG, chan); + value = u32_replace_bits(value, pdma_tc, XXVGMAC_TP2TCMP); + value = u32_replace_bits(value, 15, XXVGMAC_ORRQ); + wr_dma_ch_ind(ioaddr, MODE_TXEXTCFG, chan, value); + + value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); + value = u32_replace_bits(value, vdma_tc, XXVGMAC_TVDMA2TCMP); + writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); +} + +static void +dw25gmac_dma_map_rx_chan(struct stmmac_priv *priv, void __iomem *ioaddr, + u32 chan, bool enable_pdma) +{ + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + const struct stmmac_dma_cfg *dma_cfg = priv->plat->dma_cfg; + u32 pdma_tc, vdma_tc; + u32 value; + + pdma_tc = dw25gmac_tc(dma_cfg, dma_cfg->pdma_tc_map, chan); + vdma_tc = dw25gmac_tc(dma_cfg, dma_cfg->vdma_tc_map, chan); + + value = rd_dma_ch_ind(ioaddr, MODE_RXEXTCFG, chan); + value = u32_replace_bits(value, pdma_tc, XXVGMAC_RP2TCMP); + value = u32_replace_bits(value, 15, XXVGMAC_OWRQ); + if (enable_pdma) + value |= XXVGMAC_RXPEN; + else + value &= ~XXVGMAC_RXPEN; + wr_dma_ch_ind(ioaddr, MODE_RXEXTCFG, chan, value); + + value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); + value = u32_replace_bits(value, vdma_tc, XXVGMAC_RVDMA2TCMP); + writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); +} + void dw25gmac_dma_init_tx_chan(struct stmmac_priv *priv, void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg, dma_addr_t dma_addr, u32 chan) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; u32 value; - u32 tc; /* Descriptor cache size and prefetch threshold size */ value = rd_dma_ch_ind(ioaddr, MODE_TXDESCCTRL, chan); @@ -101,25 +176,12 @@ void dw25gmac_dma_init_tx_chan(struct stmmac_priv *priv, value |= FIELD_PREP(XXVGMAC_TDPS, XXVGMAC_TDPS_HALF); wr_dma_ch_ind(ioaddr, MODE_TXDESCCTRL, chan, value); - /* Use one-to-one mapping between VDMA, TC, and PDMA. */ - tc = chan; - - /* 1-to-1 PDMA to TC mapping */ - value = rd_dma_ch_ind(ioaddr, MODE_TXEXTCFG, chan); - value &= ~XXVGMAC_TP2TCMP; - value |= FIELD_PREP(XXVGMAC_TP2TCMP, tc); - wr_dma_ch_ind(ioaddr, MODE_TXEXTCFG, chan, value); - - /* 1-to-1 VDMA to TC mapping */ - value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); - value &= ~XXVGMAC_TVDMA2TCMP; - value |= FIELD_PREP(XXVGMAC_TVDMA2TCMP, tc); - writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + dw25gmac_dma_map_tx_chan(priv, ioaddr, chan); writel(upper_32_bits(dma_addr), - ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(chan)); + ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(addrs, chan)); writel(lower_32_bits(dma_addr), - ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(chan)); + ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(addrs, chan)); } void dw25gmac_dma_init_rx_chan(struct stmmac_priv *priv, @@ -127,8 +189,8 @@ void dw25gmac_dma_init_rx_chan(struct stmmac_priv *priv, struct stmmac_dma_cfg *dma_cfg, dma_addr_t dma_addr, u32 chan) { + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; u32 value; - u32 tc; /* Descriptor cache size and prefetch threshold size */ value = rd_dma_ch_ind(ioaddr, MODE_RXDESCCTRL, chan); @@ -139,23 +201,57 @@ void dw25gmac_dma_init_rx_chan(struct stmmac_priv *priv, value |= FIELD_PREP(XXVGMAC_RDPS, XXVGMAC_RDPS_HALF); wr_dma_ch_ind(ioaddr, MODE_RXDESCCTRL, chan, value); - /* Use one-to-one mapping between VDMA, TC, and PDMA. */ - tc = chan; - - /* 1-to-1 PDMA to TC mapping */ - value = rd_dma_ch_ind(ioaddr, MODE_RXEXTCFG, chan); - value &= ~XXVGMAC_RP2TCMP; - value |= FIELD_PREP(XXVGMAC_RP2TCMP, tc); - wr_dma_ch_ind(ioaddr, MODE_RXEXTCFG, chan, value); - - /* 1-to-1 VDMA to TC mapping */ - value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); - value &= ~XXVGMAC_RVDMA2TCMP; - value |= FIELD_PREP(XXVGMAC_RVDMA2TCMP, tc); - writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + dw25gmac_dma_map_rx_chan(priv, ioaddr, chan, true); writel(upper_32_bits(dma_addr), - ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(chan)); + ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(addrs, chan)); writel(lower_32_bits(dma_addr), - ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(chan)); + ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(addrs, chan)); +} + +void dw25gmac_dma_map_tx_offline_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, u32 chan) +{ + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + u32 value; + + value = rd_dma_ch_ind(ioaddr, MODE_TXDESCCTRL, chan); + value &= ~(XXVGMAC_TXDCSZ | XXVGMAC_TDPS); + wr_dma_ch_ind(ioaddr, MODE_TXDESCCTRL, chan, value); + + dw25gmac_dma_map_tx_chan(priv, ioaddr, chan); + + value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); + value &= ~XGMAC_TXST; + writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(addrs, chan)); +} + +void dw25gmac_dma_map_rx_offline_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, u32 chan) +{ + const struct dwxgmac_addrs *addrs = priv->plat->dwxgmac_addrs; + u32 value; + + value = rd_dma_ch_ind(ioaddr, MODE_RXDESCCTRL, chan); + value &= ~(XXVGMAC_RXDCSZ | XXVGMAC_RDPS); + wr_dma_ch_ind(ioaddr, MODE_RXDESCCTRL, chan, value); + + dw25gmac_dma_map_rx_chan(priv, ioaddr, chan, false); + + value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); + value &= ~XGMAC_RXST; + writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(addrs, chan)); +} + +void dw25gmac_desc_cache_compute(void __iomem *ioaddr) +{ + u32 value; + + value = readl(ioaddr + XGMAC_DMA_MODE); + value |= XXVGMAC_DSCB; + writel(value, ioaddr + XGMAC_DMA_MODE); + + if (readl_poll_timeout(ioaddr + XGMAC_DMA_MODE, value, + !(value & XXVGMAC_DSCB), 10, 200)) + pr_warn("dw25gmac: timeout waiting for DSCB completion\n"); } diff --git a/drivers/net/ethernet/stmicro/stmmac/dw25gmac.h b/drivers/net/ethernet/stmicro/stmmac/dw25gmac.h index b2eee66f04d58..5bb812ecea2dd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dw25gmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/dw25gmac.h @@ -5,6 +5,10 @@ #ifndef __STMMAC_DW25GMAC_H__ #define __STMMAC_DW25GMAC_H__ +/* DMA_MODE register bits specific to DW25GMAC */ +#define XXVGMAC_DSCB BIT(16) /* Descriptor Cache Size Computation Busy */ +#define XXVGMAC_HMIC BIT(17) /* HDMA CSR memory initialization complete */ + /* Hardware features */ #define XXVGMAC_HWFEAT_VDMA_RXCNT GENMASK(16, 12) #define XXVGMAC_HWFEAT_VDMA_TXCNT GENMASK(22, 18) @@ -38,6 +42,7 @@ enum dma_ch_ind_modes { #define XXVGMAC_RPBLX8_MODE BIT(19) #define XXVGMAC_RP2TCMP GENMASK(18, 16) #define XXVGMAC_OWRQ GENMASK(13, 8) +#define XXVGMAC_RXPEN BIT(31) /* RX PDMA enable (in RXEXTCFG) */ /* Tx Descriptor control */ #define XXVGMAC_TXDCSZ GENMASK(2, 0) @@ -89,4 +94,9 @@ void dw25gmac_dma_init_rx_chan(struct stmmac_priv *priv, void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg, dma_addr_t dma_addr, u32 chan); +void dw25gmac_dma_map_tx_offline_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, u32 chan); +void dw25gmac_dma_map_rx_offline_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, u32 chan); +void dw25gmac_desc_cache_compute(void __iomem *ioaddr); #endif /* __STMMAC_DW25GMAC_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index c15d48d124cea..5fa0da5036db3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -142,6 +142,9 @@ struct ethqos_emac_driver_data { struct dwxgmac_addrs dwxgmac_addrs; enum dwmac_core_type core_type; void (*set_sgmii_loopback)(struct qcom_ethqos *ethqos, bool enable); + const u8 *vdma_tc_map; + const u8 *pdma_tc_map; + u32 dma_map_size; int (*setup)(struct qcom_ethqos *ethqos, struct plat_stmmacenet_data *plat_dat); }; @@ -1252,6 +1255,9 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ethqos->pdev = pdev; data = of_device_get_match_data(dev); ethqos->data = data; + plat_dat->dma_cfg->vdma_tc_map = data->vdma_tc_map; + plat_dat->dma_cfg->pdma_tc_map = data->pdma_tc_map; + plat_dat->dma_cfg->dma_map_size = data->dma_map_size; ethqos->set_sgmii_loopback = data->set_sgmii_loopback; if (WARN_ON(!data->setup)) @@ -1318,6 +1324,14 @@ static const struct ethqos_emac_por emac_nord_por[] = { { .offset = RGMII_IO_MACRO_SCRATCH_2, .value = 0x4c }, }; +static const u8 nord_vdma_tc_map[] = { + 0, 1, 2, 3, 4, 5, 6, 6, 1, 2, 3, 4, +}; + +static const u8 nord_pdma_tc_map[] = { + 0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 7, 7, +}; + static const struct ethqos_emac_driver_data emac_nord_data = { .rgmii_por = emac_nord_por, .num_rgmii_por = ARRAY_SIZE(emac_nord_por), @@ -1325,6 +1339,9 @@ static const struct ethqos_emac_driver_data emac_nord_data = { .link_clk_name = "phyaux", .core_type = DWMAC_CORE_25GMAC, .set_sgmii_loopback = qcom_ethqos_set_sgmii_loopback_nord, + .vdma_tc_map = nord_vdma_tc_map, + .pdma_tc_map = nord_pdma_tc_map, + .dma_map_size = ARRAY_SIZE(nord_vdma_tc_map), .setup = ethqos_hlos_setup, .dwxgmac_addrs = { .dma_even_chan_base = 0x00008500, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index ebccd0009092c..a1f00071c8f22 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -50,6 +50,7 @@ #include "stmmac.h" #include "stmmac_pcs.h" #include "stmmac_xdp.h" +#include "dw25gmac.h" #include #include #include "dwmac1000.h" @@ -3358,6 +3359,25 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) stmmac_set_queue_tx_tail_ptr(priv, tx_q, chan, 0); } + /* + * DW25GMAC (HDMA) requires every hardware VDMA to have a valid TC + * mapping before descriptor-cache base addresses are computed. Keep + * channels not exposed to Linux genuinely offline: their descriptor + * cache size is zero, their start bit is clear, and an unused RX PDMA + * is explicitly disabled through RXPEN. + */ + if (priv->plat->core_type == DWMAC_CORE_25GMAC) { + u32 rx_sup = priv->dma_cap.number_rx_channel; + u32 tx_sup = priv->dma_cap.number_tx_channel; + u32 och; + + for (och = rx_channels_count; och < rx_sup; och++) + dw25gmac_dma_map_rx_offline_chan(priv, priv->ioaddr, och); + for (och = tx_channels_count; och < tx_sup; och++) + dw25gmac_dma_map_tx_offline_chan(priv, priv->ioaddr, och); + dw25gmac_desc_cache_compute(priv->ioaddr); + } + return ret; } diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 49caf6073770d..bfb5b235f20aa 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -124,6 +124,10 @@ struct stmmac_dma_cfg { bool multi_msi_en; /* atds: stmmac core internal */ bool atds; + /* Optional DW25GMAC VDMA and PDMA traffic-class mappings. */ + const u8 *vdma_tc_map; + const u8 *pdma_tc_map; + u32 dma_map_size; }; #define AXI_BLEN 7 From bfc25c644019a4e0339ff9310d09a818e310c82e Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Thu, 23 Jul 2026 22:31:22 +0530 Subject: [PATCH 0403/1133] WORKAROUND: arm64: dts: qcom: Disable usb hs controller on Glymur CRD On Glymur, there is an issue while working with the FP sensor connected to USB Hs only controller. The issue is as follows: 1) During boot, the usb controller initialises fine, but an error stating that the descriptor read from FP sensor failed and hence the controller is in an unknown state with failed enumeration of FP sensor. 2) At this point, the problem may be resource voting, but if unbind and rebind is done on the controller, enumeration is fine. All resources were thorughly checked and also schematic was checked to ensure that no GPIOs (if any) are left un-initialised. But resources seem to be fine. 3) When in this state, if we try to enter system suspend, GDSC too gets off, and also on resume we see that usb controller goes dead. And further attempts to enter suspend are gated by this dead controller. 4) If we re-bind controller on boot and then let enumration be successful, and then enter suspend, we see a SMMU crash on resume. On upstream code however, enumeration is fine on every reboot. This suspend-resume behavior is gating XO SD and hence disable it on CRD. Signed-off-by: Krishna Kurapati Signed-off-by: Pratham Pratap --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 87 ++++++++++++++++++------ 1 file changed, 65 insertions(+), 22 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index 4b6067746c7ba..17d8cf92f8460 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -660,16 +660,74 @@ #phy-cells = <0>; }; - ptn3222_1: redriver@47 { - compatible = "nxp,ptn3222"; - reg = <0x47>; + pm8010: pmic@8 { + compatible = "qcom,pm8008"; + reg = <0x8>; - reset-gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; + interrupts-extended = <&tlmm 90 IRQ_TYPE_EDGE_RISING>; + reset-gpios = <&tlmm 106 GPIO_ACTIVE_LOW>; - vdd3v3-supply = <&vreg_l8b_e0_1p50>; - vdd1v8-supply = <&vreg_l15b_e0_1p8>; + vdd-l1-l2-supply = <&vreg_l6p>; + vdd-l3-l4-supply = <&vreg_bob1_e0>; + vdd-l5-supply = <&vreg_bob1_e0>; + vdd-l6-supply = <&vreg_bob1_e0>; + vdd-l7-supply = <&vreg_bob1_e0>; - #phy-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pm8010_default>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pm8010 0 0 2>; + + interrupt-controller; + #interrupt-cells = <2>; + + #thermal-sensor-cells = <0>; + + regulators { + vreg_l1p: ldo1 { + regulator-name = "vreg_l1p"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + vreg_l2p: ldo2 { + regulator-name = "vreg_l2p"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + vreg_l3p: ldo3 { + regulator-name = "vreg_l3p"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + vreg_l4p: ldo4 { + regulator-name = "vreg_l4p"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vreg_l5p: ldo5 { + regulator-name = "vreg_l5p"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + vreg_l6p: ldo6 { + regulator-name = "vreg_l6p"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vreg_l7p: ldo7 { + regulator-name = "vreg_l7p"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + }; }; }; @@ -1254,21 +1312,6 @@ remote-endpoint = <&pmic_glink_ss_in1>; }; -&usb_hs { - dr_mode = "host"; - - status = "okay"; -}; - -&usb_hs_phy { - vdd-supply = <&vreg_l2h_e0_0p72>; - vdda12-supply = <&vreg_l4h_e0_1p2>; - - phys = <&ptn3222_1>; - - status = "okay"; -}; - &usb_mp { status = "okay"; }; From 818cc1537744cb9e8ff25aeeabdbac95c6fa088b Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Fri, 31 Jul 2026 23:36:19 +0530 Subject: [PATCH 0404/1133] FROMLIST: arm64: dts: qcom: glymur: Add ADC support for Glymur CRD Add the ADC channels under the PMK8850 ADC node for the other PMICS on the board with ADC peripherals. This includes die temperature and VPH power channels per PMIC. Add a thermal zone corresponding to the PMK8850 xo_therm ADC thermistor channel to enable temperature monitoring. Also add io-channels and io-channel-names properties to the temp_alarm nodes so that they can get temperature reading from the newly added ADC die_temp channels. Link: https://lore.kernel.org/all/20260731-pmic5_gen4_adc-v1-6-9c49b2eea6f9@oss.qualcomm.com/ Signed-off-by: Jishnu Prakash --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 151 +++++++++++++++++++++++ 1 file changed, 151 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index 17d8cf92f8460..1591006ba74f7 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -12,6 +12,7 @@ #include #include +#include "qcom-adc5-gen4.h" / { model = "Qualcomm Technologies, Inc. Glymur CRD"; @@ -165,6 +166,26 @@ regulator-boot-on; }; + thermal-zones { + sys-0-thermal { + thermal-sensors = <&pmk8850_vadc ADC5_GEN4_AMUX1_THM_100K_PU(0, 0)>; + + trips { + trip0 { + temperature = <70000>; + hysteresis = <2000>; + type = "hot"; + }; + + trip1 { + temperature = <90000>; + hysteresis = <2000>; + type = "hot"; + }; + }; + }; + }; + vreg_nvme: regulator-nvme { compatible = "regulator-fixed"; @@ -904,6 +925,39 @@ wake-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>; }; +&pmcx0102_c_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 2)>; + io-channel-names = "thermal"; +}; + +&pmcx0102_c_e1_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(1, 2)>; + io-channel-names = "thermal"; +}; + +&pmcx0102_d_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 3)>; + io-channel-names = "thermal"; +}; + +&pmcx0102_d_e1_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(1, 3)>; + io-channel-names = "thermal"; +}; + +&pmh0101_gpios { + nvme_reg_en: nvme-reg-en-state { + pins = "gpio14"; + function = "normal"; + bias-disable; + }; +}; + +&pmh0101_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 1)>; + io-channel-names = "thermal"; +}; + &pmh0110_f_e1_gpios { nvme_sec_reg_en: nvme-reg-en-state { pins = "gpio14"; @@ -940,10 +994,107 @@ }; }; +&pmh0110_f_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 5)>; + io-channel-names = "thermal"; +}; + +&pmh0110_f_e1_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(1, 5)>; + io-channel-names = "thermal"; +}; + +&pmh0110_h_e0_temp_alarm { + io-channels = <&pmk8850_vadc ADC5_GEN4_DIE_TEMP(0, 7)>; + io-channel-names = "thermal"; +}; + &pmk8850_rtc { qcom,no-alarm; }; +&pmk8850_vadc { + channel@103 { + reg = ; + label = "pmh0101_die_temp"; + }; + + channel@18e { + reg = ; + label = "pmh0101_vph_pwr"; + }; + + channel@203 { + reg = ; + label = "pmcx0102_c_e0_die_temp"; + }; + + channel@28e { + reg = ; + label = "pmcx0102_c_e0_vph_pwr"; + }; + + channel@303 { + reg = ; + label = "pmcx0102_d_e0_die_temp"; + }; + + channel@38e { + reg = ; + label = "pmcx0102_d_e0_vph_pwr"; + }; + + channel@503 { + reg = ; + label = "pmh0110_f_e0_die_temp"; + }; + + channel@58e { + reg = ; + label = "pmh0110_f_e0_vph_pwr"; + }; + + channel@703 { + reg = ; + label = "pmh0110_h_e0_die_temp"; + }; + + channel@78e { + reg = ; + label = "pmh0110_h_e0_vph_pwr"; + }; + + channel@2203 { + reg = ; + label = "pmcx0102_c_e1_die_temp"; + }; + + channel@228e { + reg = ; + label = "pmcx0102_c_e1_vph_pwr"; + }; + + channel@2303 { + reg = ; + label = "pmcx0102_d_e1_die_temp"; + }; + + channel@238e { + reg = ; + label = "pmcx0102_d_e1_vph_pwr"; + }; + + channel@2503 { + reg = ; + label = "pmh0110_f_e1_die_temp"; + }; + + channel@258e { + reg = ; + label = "pmh0110_f_e1_vph_pwr"; + }; +}; + &pon_resin { linux,code = ; status = "okay"; From adf3b2db84757d6b54a54b005060ae694cd70ec0 Mon Sep 17 00:00:00 2001 From: Gopikrishna Garmidi Date: Fri, 16 Oct 2026 03:30:22 -0700 Subject: [PATCH 0405/1133] FROMLIST: arm64: dts: qcom: Add Kalambo SoC Introduce support for the Qualcomm Kalambo SoC. It is derived from Mahua with CPU cluster 0 (cpu0-cpu5) removed, leaving only cluster 1 (cpu6-cpu11). The surviving cluster is re-added in the cpu-map as cluster0, since the kernel stops scanning at the first missing clusterN index. cpu6-cpu11 are reassigned to SCMI performance domain 0, as domain 1 is no longer present. Kalambo uses PDP1 for SCMI transport. The tx shmem (lpri1) sits at offset 0x200 within imem, pushing the tx region end to 0x380, so the imem size is overridden accordingly. The rx shmem (lpri0) remains at offset 0x0. The PDP mailbox registers are overridden to match the Kalambo SCP firmware. Kalambo's PDC input mux differs from Glymur. Pins 109 and 110 carry tsens6 and tsens7 alarms, which are absent on Kalambo, and pins 134, 138, 156, 158, 172, 181 and 202 carry gp_irq_hvm inputs with nothing wired to them instead of wakeup GPIOs. Override the PDC ranges to leave those pins unmapped. Add labels to the cpus and cpu-map nodes in glymur.dtsi to allow derived SoCs to delete and redefine the cpu-map entirely. Since Kalambo does not use CPU cluster0, disable bwmon_cluster0 to avoid unnecessary traffic while retaining its shared cpu_bwmon_opp_table for bwmon_cluster1. Link: https://lore.kernel.org/all/20261016-b4-kalambo-crd-v9-1-11e6a40b68e2@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Co-developed-by: Sibi Sankar Signed-off-by: Gopikrishna Garmidi Signed-off-by: Sibi Sankar --- arch/arm64/boot/dts/qcom/glymur.dtsi | 4 +- arch/arm64/boot/dts/qcom/kalambo.dtsi | 123 ++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/kalambo.dtsi diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index ef3da2afc025f..ed2496deb3884 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -35,7 +35,7 @@ #address-cells = <2>; #size-cells = <2>; - cpus { + cpus: cpus { #address-cells = <2>; #size-cells = <0>; @@ -273,7 +273,7 @@ #cooling-cells = <2>; }; - cpu-map { + cpu_map: cpu-map { cluster0 { core0 { cpu = <&cpu0>; diff --git a/arch/arm64/boot/dts/qcom/kalambo.dtsi b/arch/arm64/boot/dts/qcom/kalambo.dtsi new file mode 100644 index 0000000000000..868b924c47346 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/kalambo.dtsi @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include "mahua.dtsi" + +/delete-node/ &cluster0_pd; +/delete-node/ &cpu_map; +/delete-node/ &cpu0; +/delete-node/ &cpu1; +/delete-node/ &cpu2; +/delete-node/ &cpu3; +/delete-node/ &cpu4; +/delete-node/ &cpu5; +/delete-node/ &cpu_pd0; +/delete-node/ &cpu_pd1; +/delete-node/ &cpu_pd2; +/delete-node/ &cpu_pd3; +/delete-node/ &cpu_pd4; +/delete-node/ &cpu_pd5; +/delete-node/ &cpu_scp_lpri1; + +&bwmon_cluster0 { + status = "disabled"; +}; + +&cpu6 { + power-domains = <&cpu_pd6>, <&scmi_perf 0>; + power-domain-names = "psci", "perf"; +}; + +&cpu7 { + power-domains = <&cpu_pd7>, <&scmi_perf 0>; + power-domain-names = "psci", "perf"; +}; + +&cpu8 { + power-domains = <&cpu_pd8>, <&scmi_perf 0>; + power-domain-names = "psci", "perf"; +}; + +&cpu9 { + power-domains = <&cpu_pd9>, <&scmi_perf 0>; + power-domain-names = "psci", "perf"; +}; + +&cpu10 { + power-domains = <&cpu_pd10>, <&scmi_perf 0>; + power-domain-names = "psci", "perf"; +}; + +&cpu11 { + power-domains = <&cpu_pd11>, <&scmi_perf 0>; + power-domain-names = "psci", "perf"; +}; + +&cpus { + cpu-map { + cluster0 { + core0 { + cpu = <&cpu6>; + }; + + core1 { + cpu = <&cpu7>; + }; + + core2 { + cpu = <&cpu8>; + }; + + core3 { + cpu = <&cpu9>; + }; + + core4 { + cpu = <&cpu10>; + }; + + core5 { + cpu = <&cpu11>; + }; + }; + }; +}; + +&imem { + reg = <0x0 0x81e08600 0x0 0x380>; + ranges = <0x0 0x0 0x81e08600 0x380>; + + cpu_scp_lpri1: scp-sram-section@200 { + compatible = "arm,scmi-shmem"; + reg = <0x200 0x180>; + }; +}; + +&pdc { + qcom,pdc-ranges = <0 745 38>, + <40 785 11>, + <51 527 4>, + <57 533 10>, + <70 546 4>, + <75 551 18>, + <108 619 1>, + <111 622 19>, + <130 717 4>, + <135 722 3>, + <139 726 3>, + <142 251 5>, + <147 796 9>, + <157 806 1>, + <159 808 4>, + <171 4104 1>, + <173 4106 8>, + <182 4115 20>, + <203 4136 4>; +}; + +&pdp0_mbox { + reg = <0x0 0x17610000 0x0 0x8000>, + <0x0 0x1a980000 0x0 0x8000>; +}; From 22815403589567274d4f327394ae2c92762a1037 Mon Sep 17 00:00:00 2001 From: Gopikrishna Garmidi Date: Fri, 16 Oct 2026 03:30:23 -0700 Subject: [PATCH 0406/1133] FROMLIST: arm64: dts: qcom: Add Kalambo CRD Introduce support for the CRD based on the Qualcomm Kalambo SoC. Similar to Mahua, it is pin-to-pin compatible with the Glymur CRD. It reuses the common CRD board description and drops the PMIC nodes not present on this design. Kalambo uses the same QREF topology as Mahua through the qcom,mahua-tcsr compatible TCSR block. Connect the QREF and refgen supply inputs to the corresponding CRD LDOs so that the reference clocks for the PCIe and USB PHYs can operate. Link: https://lore.kernel.org/all/20261016-b4-kalambo-crd-v9-2-11e6a40b68e2@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Signed-off-by: Gopikrishna Garmidi --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/kalambo-crd.dts | 37 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/kalambo-crd.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..b7f1e543a2484 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -50,6 +50,7 @@ dtb-$(CONFIG_ARCH_QCOM) += ipq9574-rdp454.dtb dtb-$(CONFIG_ARCH_QCOM) += ipq9650-rdp488.dtb dtb-$(CONFIG_ARCH_QCOM) += kaanapali-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += kaanapali-qrd.dtb +dtb-$(CONFIG_ARCH_QCOM) += kalambo-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += lemans-evk.dtb lemans-evk-camera-csi1-imx577-dtbs := lemans-evk.dtb lemans-evk-camera-csi1-imx577.dtbo diff --git a/arch/arm64/boot/dts/qcom/kalambo-crd.dts b/arch/arm64/boot/dts/qcom/kalambo-crd.dts new file mode 100644 index 0000000000000..9149cf6ad94b4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/kalambo-crd.dts @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include "kalambo.dtsi" +#include "glymur-crd.dtsi" + +/delete-node/ &pmcx0102_d_e0; +/delete-node/ &pmcx0102_d0_thermal; +/delete-node/ &pmh0104_i_e0; +/delete-node/ &pmh0104_i0_thermal; +/delete-node/ &pmh0104_j_e0; +/delete-node/ &pmh0104_j0_thermal; + +/ { + model = "Qualcomm Technologies, Inc. Kalambo CRD"; + compatible = "qcom,kalambo-crd", "qcom,kalambo"; +}; + +&tcsr { + vdda-qrefrpt0-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrpt1-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrpt2-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrpt3-0p9-supply = <&vreg_l1f_e1_0p82>; + vdda-qrefrpt4-0p9-supply = <&vreg_l2h_e0_0p72>; + vdda-qrefrpt5-0p9-supply = <&vreg_l2h_e0_0p72>; + vdda-qrefrx0-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrx1-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrx2-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrx3-0p9-supply = <&vreg_l2h_e0_0p72>; + vdda-qreftx1-0p9-supply = <&vreg_l1f_e1_0p82>; + vdda-refgen3-0p9-supply = <&vreg_l1f_e1_0p82>; + vdda-refgen3-1p2-supply = <&vreg_l4f_e1_1p08>; +}; From d91e08368a89add2c093198930321d68b992add6 Mon Sep 17 00:00:00 2001 From: Pradeep P V K Date: Wed, 28 Oct 2026 17:54:46 +0530 Subject: [PATCH 0407/1133] FROMLIST: arm64: dts: qcom: glymur: Add UFS nodes Add UFS PHY and UFS host controller nodes for Glymur SoC. Link: https://lore.kernel.org/all/20261028-glymur_ufs_qcb_enablement-v5-1-09cda5e3bab3@oss.qualcomm.com/ Reviewed-by: Abel Vesa Signed-off-by: Pradeep P V K Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/glymur.dtsi | 125 ++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index ed2496deb3884..c3717674deca6 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -825,9 +825,9 @@ <0>, /* QUSB4 1 PHY RX 1 */ <0>, /* QUSB4 2 PHY RX 0 */ <0>, /* QUSB4 2 PHY RX 1 */ - <0>, /* UFS PHY RX Symbol 0 */ - <0>, /* UFS PHY RX Symbol 1 */ - <0>, /* UFS PHY TX Symbol 0 */ + <&ufs_mem_phy 0>, + <&ufs_mem_phy 1>, + <&ufs_mem_phy 2>, <&usb_0_qmpphy QMP_USB43DP_USB3_PIPE_CLK>, <&usb_1_qmpphy QMP_USB43DP_USB3_PIPE_CLK>, <&usb_2_qmpphy QMP_USB43DP_USB3_PIPE_CLK>, @@ -4116,6 +4116,125 @@ reg = <0x0 0x010c3000 0x0 0x1000>; }; + ufs_mem_phy: phy@1d80000 { + compatible = "qcom,glymur-qmp-ufs-phy"; + reg = <0x0 0x01d80000 0x0 0x2000>; + + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&gcc GCC_UFS_PHY_PHY_AUX_CLK>, + /* UFS and PCIE4 share the same clkref */ + <&tcsr TCSR_PCIE_4_CLKREF_EN>; + + clock-names = "ref", + "ref_aux", + "qref"; + + resets = <&ufs_mem_hc 0>; + reset-names = "ufsphy"; + + #clock-cells = <1>; + #phy-cells = <0>; + + status = "disabled"; + }; + + ufs_mem_hc: ufshc@1d84000 { + compatible = "qcom,glymur-ufshc", + "qcom,ufshc", + "jedec,ufs-2.0"; + reg = <0x0 0x01d84000 0x0 0x3000>, + <0x0 0x01da0000 0x0 0x15000>; + reg-names = "std", + "mcq"; + + interrupts = ; + + clocks = <&gcc GCC_UFS_PHY_AXI_CLK>, + <&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>, + <&gcc GCC_UFS_PHY_AHB_CLK>, + <&gcc GCC_UFS_PHY_UNIPRO_CORE_CLK>, + <&rpmhcc RPMH_LN_BB_CLK3>, + <&gcc GCC_UFS_PHY_TX_SYMBOL_0_CLK>, + <&gcc GCC_UFS_PHY_RX_SYMBOL_0_CLK>, + <&gcc GCC_UFS_PHY_RX_SYMBOL_1_CLK>; + clock-names = "core_clk", + "bus_aggr_clk", + "iface_clk", + "core_clk_unipro", + "ref_clk", + "tx_lane0_sync_clk", + "rx_lane0_sync_clk", + "rx_lane1_sync_clk"; + + operating-points-v2 = <&ufs_opp_table>; + + resets = <&gcc GCC_UFS_PHY_BCR>; + reset-names = "rst"; + + interconnects = <&aggre2_noc MASTER_UFS_MEM QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&hsc_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_UFS_MEM_CFG QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "ufs-ddr", + "cpu-ufs"; + + power-domains = <&gcc GCC_UFS_PHY_GDSC>; + required-opps = <&rpmhpd_opp_nom>; + + iommus = <&apps_smmu 0x460 0>; + dma-coherent; + + msi-parent = <&gic_its 0x460>; + lanes-per-direction = <2>; + + phys = <&ufs_mem_phy>; + phy-names = "ufsphy"; + + #reset-cells = <1>; + + status = "disabled"; + + ufs_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <100000000>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <0>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-201500000 { + opp-hz = /bits/ 64 <201500000>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <201500000>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <0>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-403000000 { + opp-hz = /bits/ 64 <403000000>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <403000000>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <0>, + /bits/ 64 <0>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + cryptobam: dma-controller@1dc4000 { compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; reg = <0x0 0x01dc4000 0x0 0x28000>; From 004daa0a4a9530b4b5b0aac4335f5deebea4cbb2 Mon Sep 17 00:00:00 2001 From: Pradeep P V K Date: Wed, 28 Oct 2026 17:54:47 +0530 Subject: [PATCH 0408/1133] FROMLIST: arm64: dts: qcom: glymur-qcb: Enable UFS Enable UFS for glymur-qcb board. Link: https://lore.kernel.org/all/20261028-glymur_ufs_qcb_enablement-v5-2-09cda5e3bab3@oss.qualcomm.com/ Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Signed-off-by: Pradeep P V K --- arch/arm64/boot/dts/qcom/glymur-qcb.dts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-qcb.dts b/arch/arm64/boot/dts/qcom/glymur-qcb.dts index f26bdc1cd84a7..08c6445fe6516 100644 --- a/arch/arm64/boot/dts/qcom/glymur-qcb.dts +++ b/arch/arm64/boot/dts/qcom/glymur-qcb.dts @@ -703,3 +703,21 @@ vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; }; }; + +&ufs_mem_hc { + reset-gpios = <&tlmm 250 GPIO_ACTIVE_LOW>; + + vcc-supply = <&vreg_l17b_e0_2p4>; + vcc-max-microamp = <1200000>; + vccq-supply = <&vreg_l12b_e0_1p14>; + vccq-max-microamp = <1200000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l1c_e1_0p82>; + vdda-pll-supply = <&vreg_l4f_e1_1p08>; + + status = "okay"; +}; From bba4c9ba04169fae3732ed5a0a36eb32e3057b59 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 22 Sep 2026 18:35:24 +0800 Subject: [PATCH 0409/1133] FROMLIST: arm64: dts: qcom: glymur: Add CoreSight nodes for APSS debug block The APSS debug block is built with CoreSight devices like ETM, replicator, funnel and TMC ETF. Add dt nodes for these devices to enable ETM trace. The replicator, funnel and TMC ETF nodes in this block are physically powered by the CPU cluster power rail rather than by a dedicated always-on rail. Add a power-domains property referencing the corresponding cluster_pdN domain to each of these nodes, so their power state is tied to the CPU cluster domain and the runtime PM core can power the domain on before the devices are accessed and let it be powered off otherwise. Mahua is based on glymur but only has 12 CPUs across two clusters instead of 18 across three, so delete the ETM and cluster2 CoreSight nodes that have no corresponding CPUs on that platform. [Pending: Kalambo changes need posting out once it land upstream] Link: https://lore.kernel.org/all/20260922-add-etm-devices-for-multiple-qcom-platforms-v1-4-c2a8c3225a2e@oss.qualcomm.com/ Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/glymur.dtsi | 1184 +++++++++++++++++++++++++ arch/arm64/boot/dts/qcom/kalambo.dtsi | 22 + arch/arm64/boot/dts/qcom/mahua.dtsi | 16 + 3 files changed, 1222 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index c3717674deca6..4a44208fdfe01 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -397,6 +397,312 @@ }; }; + etm-0 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + etm-1 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + etm-2 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + etm-3 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + etm-4 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu4>; + qcom,skip-power-up; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc0_4_rep_in>; + }; + }; + }; + }; + + etm-5 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu5>; + qcom,skip-power-up; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc0_5_rep_in>; + }; + }; + }; + }; + + etm-6 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu6>; + qcom,skip-power-up; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + etm-7 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu7>; + qcom,skip-power-up; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; + + etm-8 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu8>; + qcom,skip-power-up; + + out-ports { + port { + etm8_out: endpoint { + remote-endpoint = <&ncc1_2_rep_in>; + }; + }; + }; + }; + + etm-9 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu9>; + qcom,skip-power-up; + + out-ports { + port { + etm9_out: endpoint { + remote-endpoint = <&ncc1_3_rep_in>; + }; + }; + }; + }; + + etm-10 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu10>; + qcom,skip-power-up; + + out-ports { + port { + etm10_out: endpoint { + remote-endpoint = <&ncc1_4_rep_in>; + }; + }; + }; + }; + + etm-11 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu11>; + qcom,skip-power-up; + + out-ports { + port { + etm11_out: endpoint { + remote-endpoint = <&ncc1_5_rep_in>; + }; + }; + }; + }; + + etm12: etm-12 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu12>; + qcom,skip-power-up; + + out-ports { + port { + etm12_out: endpoint { + remote-endpoint = <&ncc2_0_rep_in>; + }; + }; + }; + }; + + etm13: etm-13 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu13>; + qcom,skip-power-up; + + out-ports { + port { + etm13_out: endpoint { + remote-endpoint = <&ncc2_1_rep_in>; + }; + }; + }; + }; + + etm14: etm-14 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu14>; + qcom,skip-power-up; + + out-ports { + port { + etm14_out: endpoint { + remote-endpoint = <&ncc2_2_rep_in>; + }; + }; + }; + }; + + etm15: etm-15 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu15>; + qcom,skip-power-up; + + out-ports { + port { + etm15_out: endpoint { + remote-endpoint = <&ncc2_3_rep_in>; + }; + }; + }; + }; + + etm16: etm-16 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu16>; + qcom,skip-power-up; + + out-ports { + port { + etm16_out: endpoint { + remote-endpoint = <&ncc2_4_rep_in>; + }; + }; + }; + }; + + etm17: etm-17 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu17>; + qcom,skip-power-up; + + out-ports { + port { + etm17_out: endpoint { + remote-endpoint = <&ncc2_5_rep_in>; + }; + }; + }; + }; + firmware { scm: scm { compatible = "qcom,scm-glymur", "qcom,scm"; @@ -7599,6 +7905,14 @@ }; }; + port@36 { + reg = <0x36>; + + tn_ag_in54: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; + port@3f { reg = <0x3f>; @@ -7980,6 +8294,51 @@ }; }; + funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + + port@2 { + reg = <2>; + + apss_funnel_in2: endpoint { + remote-endpoint = <&ncc2_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in54>; + }; + }; + }; + }; + tpdm@11c03000 { compatible = "qcom,coresight-tpdm", "arm,primecell"; reg = <0x0 0x11c03000 0x0 0x1000>; @@ -8668,6 +9027,831 @@ }; }; + funnel@1d021000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x1d021000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@1d029000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1d029000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + funnel@1d081000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x1d081000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc0_1_funnel_in4: endpoint { + remote-endpoint = <&ncc0_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc0_1_funnel_in5: endpoint { + remote-endpoint = <&ncc0_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + replicator@1d090000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d090000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d0a0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d0a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@1d0b0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d0b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@1d0c0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d0c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + replicator@1d0d0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d0d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_4_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc0_4_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in4>; + }; + }; + }; + }; + + replicator@1d0e0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d0e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_5_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc0_5_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in5>; + }; + }; + }; + }; + + funnel@1d121000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x1d121000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@1d129000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1d129000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + funnel@1d181000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x1d181000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc1_1_funnel_in2: endpoint { + remote-endpoint = <&ncc1_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc1_1_funnel_in3: endpoint { + remote-endpoint = <&ncc1_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc1_1_funnel_in4: endpoint { + remote-endpoint = <&ncc1_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc1_1_funnel_in5: endpoint { + remote-endpoint = <&ncc1_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; + }; + }; + }; + }; + + replicator@1d190000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d190000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@1d1a0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d1a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm7_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; + + replicator@1d1b0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d1b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + port { + ncc1_2_rep_in: endpoint { + remote-endpoint = <&etm8_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in2>; + }; + }; + }; + }; + + replicator@1d1c0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d1c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + port { + ncc1_3_rep_in: endpoint { + remote-endpoint = <&etm9_out>; + }; + }; + }; + + out-ports { + port { + ncc1_3_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in3>; + }; + }; + }; + }; + + replicator@1d1d0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d1d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + port { + ncc1_4_rep_in: endpoint { + remote-endpoint = <&etm10_out>; + }; + }; + }; + + out-ports { + port { + ncc1_4_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in4>; + }; + }; + }; + }; + + replicator@1d1e0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d1e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + port { + ncc1_5_rep_in: endpoint { + remote-endpoint = <&etm11_out>; + }; + }; + }; + + out-ports { + port { + ncc1_5_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in5>; + }; + }; + }; + }; + + cluster2_funnel_l2: funnel@1d221000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x1d221000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc2_2_funnel_in2: endpoint { + remote-endpoint = <&ncc2_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc2_2_funnel_out: endpoint { + remote-endpoint = <&ncc2_etf_in>; + }; + }; + }; + }; + + cluster2_etf: tmc@1d229000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1d229000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + + in-ports { + port { + ncc2_etf_in: endpoint { + remote-endpoint = <&ncc2_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc2_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in2>; + }; + }; + }; + }; + + cluster2_funnel_l1: funnel@1d281000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x1d281000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc2_1_funnel_in0: endpoint { + remote-endpoint = <&ncc2_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc2_1_funnel_in1: endpoint { + remote-endpoint = <&ncc2_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc2_1_funnel_in2: endpoint { + remote-endpoint = <&ncc2_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc2_1_funnel_in3: endpoint { + remote-endpoint = <&ncc2_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc2_1_funnel_in4: endpoint { + remote-endpoint = <&ncc2_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc2_1_funnel_in5: endpoint { + remote-endpoint = <&ncc2_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc2_1_funnel_out: endpoint { + remote-endpoint = <&ncc2_2_funnel_in2>; + }; + }; + }; + }; + + cluster2_rep_2_0: replicator@1d290000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d290000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + + in-ports { + port { + ncc2_0_rep_in: endpoint { + remote-endpoint = <&etm12_out>; + }; + }; + }; + + out-ports { + port { + ncc2_0_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in0>; + }; + }; + }; + }; + + cluster2_rep_2_1: replicator@1d2a0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d2a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + + in-ports { + port { + ncc2_1_rep_in: endpoint { + remote-endpoint = <&etm13_out>; + }; + }; + }; + + out-ports { + port { + ncc2_1_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in1>; + }; + }; + }; + }; + + cluster2_rep_2_2: replicator@1d2b0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d2b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + + in-ports { + port { + ncc2_2_rep_in: endpoint { + remote-endpoint = <&etm14_out>; + }; + }; + }; + + out-ports { + port { + ncc2_2_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in2>; + }; + }; + }; + }; + + cluster2_rep_2_3: replicator@1d2c0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d2c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + + in-ports { + port { + ncc2_3_rep_in: endpoint { + remote-endpoint = <&etm15_out>; + }; + }; + }; + + out-ports { + port { + ncc2_3_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in3>; + }; + }; + }; + }; + + cluster2_rep_2_4: replicator@1d2d0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d2d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + + in-ports { + port { + ncc2_4_rep_in: endpoint { + remote-endpoint = <&etm16_out>; + }; + }; + }; + + out-ports { + port { + ncc2_4_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in4>; + }; + }; + }; + }; + + cluster2_rep_2_5: replicator@1d2e0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1d2e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster2_pd>; + + in-ports { + port { + ncc2_5_rep_in: endpoint { + remote-endpoint = <&etm17_out>; + }; + }; + }; + + out-ports { + port { + ncc2_5_rep_out: endpoint { + remote-endpoint = <&ncc2_1_funnel_in5>; + }; + }; + }; + }; + nsi_noc: interconnect@1d600000 { compatible = "qcom,glymur-nsinoc"; reg = <0x0 0x1d600000 0x0 0x14080>; diff --git a/arch/arm64/boot/dts/qcom/kalambo.dtsi b/arch/arm64/boot/dts/qcom/kalambo.dtsi index 868b924c47346..da40cd49db4bb 100644 --- a/arch/arm64/boot/dts/qcom/kalambo.dtsi +++ b/arch/arm64/boot/dts/qcom/kalambo.dtsi @@ -20,6 +20,28 @@ /delete-node/ &cpu_pd4; /delete-node/ &cpu_pd5; /delete-node/ &cpu_scp_lpri1; +/delete-node/ &apss_funnel_in0; + +/ { + /delete-node/ etm-0; + /delete-node/ etm-1; + /delete-node/ etm-2; + /delete-node/ etm-3; + /delete-node/ etm-4; + /delete-node/ etm-5; +}; + +&soc { + /delete-node/ funnel@1d021000; + /delete-node/ tmc@1d029000; + /delete-node/ funnel@1d081000; + /delete-node/ replicator@1d090000; + /delete-node/ replicator@1d0a0000; + /delete-node/ replicator@1d0b0000; + /delete-node/ replicator@1d0c0000; + /delete-node/ replicator@1d0d0000; + /delete-node/ replicator@1d0e0000; +}; &bwmon_cluster0 { status = "disabled"; diff --git a/arch/arm64/boot/dts/qcom/mahua.dtsi b/arch/arm64/boot/dts/qcom/mahua.dtsi index a59c5ed7b48e7..e3c8cc3e4bda2 100644 --- a/arch/arm64/boot/dts/qcom/mahua.dtsi +++ b/arch/arm64/boot/dts/qcom/mahua.dtsi @@ -6,8 +6,18 @@ /* Mahua is heavily based on Glymur, with some meaningful differences */ #include "glymur.dtsi" +/delete-node/ &apss_funnel_in2; /delete-node/ &bwmon_cluster2; +/delete-node/ &cluster2_etf; +/delete-node/ &cluster2_funnel_l1; +/delete-node/ &cluster2_funnel_l2; /delete-node/ &cluster2_pd; +/delete-node/ &cluster2_rep_2_0; +/delete-node/ &cluster2_rep_2_1; +/delete-node/ &cluster2_rep_2_2; +/delete-node/ &cluster2_rep_2_3; +/delete-node/ &cluster2_rep_2_4; +/delete-node/ &cluster2_rep_2_5; /delete-node/ &cpu_map_cluster2; /delete-node/ &cpu12; /delete-node/ &cpu13; @@ -24,6 +34,12 @@ /delete-node/ &cti_wpss; /delete-node/ &pcie3_phy; /delete-node/ &pcie3a; +/delete-node/ &etm12; +/delete-node/ &etm13; +/delete-node/ &etm14; +/delete-node/ &etm15; +/delete-node/ &etm16; +/delete-node/ &etm17; /delete-node/ &thermal_aoss_6; /delete-node/ &thermal_aoss_7; /delete-node/ &thermal_cpu_2_0_0; From 03f34fde232708c3f59975cbc3c728c5fd2e6c5d Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Fri, 3 Jul 2026 18:08:32 +0530 Subject: [PATCH 0410/1133] FROMGIT: power: sequencing: pwrseq-pcie-m2: Add QCC2072 BT PCI device ID Add the Qualcomm QCC2072 Bluetooth device (PCI ID 0x1112) to the pwrseq_m2_pci_ids table so the M.2 power sequencer can create the serdev node for its BT interface on enumeration. Signed-off-by: Krishna Chaitanya Chundru Link: https://patch.msgid.link/20260703-eliza_evk-v1-3-7624440bd76d@oss.qualcomm.com Signed-off-by: Bartosz Golaszewski --- drivers/power/sequencing/pwrseq-pcie-m2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c index 56c5d51293c10..0b29822886eed 100644 --- a/drivers/power/sequencing/pwrseq-pcie-m2.c +++ b/drivers/power/sequencing/pwrseq-pcie-m2.c @@ -227,6 +227,8 @@ static const struct pci_device_id pwrseq_m2_pci_ids[] = { .driver_data = (kernel_ulong_t)"qcom,wcn7850-bt" }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x1107, PCI_VENDOR_ID_FOXCONN, 0xe0ee), .driver_data = (kernel_ulong_t)"qcom,wcn7850-bt" }, + { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x1112), + .driver_data = (kernel_ulong_t)"qcom,qcc2072-bt" }, { } /* Sentinel */ }; From 6a52b78ecdce0d378cfb3f6290396837d480bc4f Mon Sep 17 00:00:00 2001 From: Rahul Samana Date: Mon, 27 Jul 2026 14:41:26 +0530 Subject: [PATCH 0411/1133] FROMLIST: dt-bindings: bluetooth: qca: add QCC2072 QCC2072 can be used on M.2 E-key cards where the card power resources are described by the pcie-m2-e-connector node. In that setup, the M.2 power sequencing provider creates the Bluetooth serdev child after matching the QCC2072 PCI function. Integrated non-M.2 designs need board-specific power resources. Document only the compatible for now and leave those properties to be added with matching driver support. Document the qcom,qcc2072-bt compatible used for QCC2072 Bluetooth controllers connected over UART. Link: https://lore.kernel.org/r/20260727-rb3-industrial-bt-uart-v2-1-2d100f30e202@oss.qualcomm.com CRs-Fixed: 4615698 Signed-off-by: Rahul Samana --- .../net/bluetooth/qcom,qcc2072-bt.yaml | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml diff --git a/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml b/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml new file mode 100644 index 0000000000000..e4b281ef261f4 --- /dev/null +++ b/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/bluetooth/qcom,qcc2072-bt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm QCC2072 Bluetooth + +maintainers: + - Bartosz Golaszewski + - Balakrishna Godavarthi + - Rocky Liao + +description: + Qualcomm QCC2072 Bluetooth controller connected over UART. + + QCC2072 can be populated on an M.2 E-key card, where the card power + supplies and sideband signals are modeled by the pcie-m2-e-connector node. + The M.2 power sequencing provider creates the Bluetooth serdev device and + uses this compatible after matching the QCC2072 PCI function. + + Integrated non-M.2 designs require board-specific power resources. Those + properties, together with a static devicetree example, should be added when + integrated non-M.2 support is added. + +properties: + compatible: + enum: + - qcom,qcc2072-bt + +required: + - compatible + +allOf: + - $ref: bluetooth-controller.yaml# + - $ref: qcom,bluetooth-common.yaml + - $ref: /schemas/serial/serial-peripheral-props.yaml# + +unevaluatedProperties: false From 4c6a2a4a0e3e421837135e9f50dde1005e7439eb Mon Sep 17 00:00:00 2001 From: Vivek Sahu Date: Mon, 27 Jul 2026 14:41:26 +0530 Subject: [PATCH 0412/1133] FROMLIST: Bluetooth: qca: add QCC2072 support QCC2072 uses the ORN firmware and NVM naming scheme. The tested RB3 Gen 2 Industrial BT-over-UART setup also needs the BCS calibration TLV to be combined with the selected NVM before download. Keep the BCS/NVM combination in a helper so missing calibration data or allocation failures can fall back to downloading the NVM alone without a local skip label. Select the NVM file and BCS calibration file using the controller board ID when available, with fallback to the default files. Initialize the BCS calibration filename independently of the NVM filename source so custom NVM firmware-name paths do not leave it unset. Register the QCC2072 compatible with hci_qca and route it through the same UART setup, speed switching and power-control paths as recent Qualcomm Bluetooth controllers. This continues the QCC2072 enablement work previously posted by Vivek Sahu and later extended by Yepuri Siddu for the RB3 Gen 2 Industrial BT-over-UART use case. Link: https://lore.kernel.org/r/20260727-rb3-industrial-bt-uart-v2-2-2d100f30e202@oss.qualcomm.com CRs-Fixed: 4615698 Signed-off-by: Vivek Sahu Co-developed-by: Yepuri Siddu Signed-off-by: Yepuri Siddu Co-developed-by: Rahul Samana Signed-off-by: Rahul Samana --- drivers/bluetooth/btqca.c | 72 ++++++++++++++++++++++++++++++++++++- drivers/bluetooth/btqca.h | 2 ++ drivers/bluetooth/hci_qca.c | 24 +++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 22b08ab05b829..5af8fe1936c22 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -550,6 +550,54 @@ static int qca_inject_cmd_complete_event(struct hci_dev *hdev) return hci_recv_frame(hdev, skb); } +static void qca_combine_nvm_calib(struct hci_dev *hdev, u8 **data, + int *size, char *calib_name, + size_t max_size) +{ + const struct firmware *calib_fw; + struct tlv_type_hdr *outer_hdr; + size_t inner_len, combined_size; + u8 *combined_data; + int err; + + err = request_firmware(&calib_fw, calib_name, &hdev->dev); + if (err) { + if (qca_get_alt_nvm_file(calib_name, max_size)) + err = request_firmware(&calib_fw, calib_name, &hdev->dev); + + if (err) { + bt_dev_err(hdev, "QCA Failed to request file: %s (%d)", + calib_name, err); + return; + } + } + + bt_dev_info(hdev, "QCA Downloading %s", calib_name); + + inner_len = *size + calib_fw->size; + combined_size = sizeof(*outer_hdr) + inner_len; + combined_data = vmalloc(combined_size); + if (!combined_data) { + bt_dev_warn(hdev, + "QCA Failed to allocate memory for file: %s", + calib_name); + release_firmware(calib_fw); + return; + } + + outer_hdr = (struct tlv_type_hdr *)combined_data; + /* high 24 bits = payload length, low 8 bits = type */ + outer_hdr->type_len = cpu_to_le32((inner_len << 8) | 4); + memcpy(combined_data + sizeof(*outer_hdr), *data, *size); + memcpy(combined_data + sizeof(*outer_hdr) + *size, + calib_fw->data, calib_fw->size); + release_firmware(calib_fw); + + vfree(*data); + *data = combined_data; + *size = combined_size; +} + static int qca_download_firmware(struct hci_dev *hdev, struct qca_fw_config *config, enum qca_btsoc_type soc_type, @@ -595,6 +643,11 @@ static int qca_download_firmware(struct hci_dev *hdev, memcpy(data, fw->data, size); release_firmware(fw); + if (soc_type == QCA_QCC2072 && config->type == TLV_TYPE_NVM) + qca_combine_nvm_calib(hdev, &data, &size, + config->calib_name, + sizeof(config->calib_name)); + ret = qca_tlv_check_data(hdev, config, data, size, soc_type); if (ret) goto out; @@ -826,6 +879,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, snprintf(config.fwname, sizeof(config.fwname), "qca/hmtbtfw%02x.tlv", rom_ver); break; + case QCA_QCC2072: + snprintf(config.fwname, sizeof(config.fwname), + "qca/ornbtfw%02x.tlv", rom_ver); + break; default: snprintf(config.fwname, sizeof(config.fwname), "qca/rampatch_%08x.bin", soc_ver); @@ -859,7 +916,8 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, /* Give the controller some time to get ready to receive the NVM */ msleep(10); - if (soc_type == QCA_QCA2066 || soc_type == QCA_WCN7850) + if (soc_type == QCA_QCA2066 || soc_type == QCA_WCN7850 || + soc_type == QCA_QCC2072) qca_read_fw_board_id(hdev, &boardid); /* Download NVM configuration */ @@ -920,12 +978,23 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname), "hmtnv", soc_type, ver, rom_ver, boardid); break; + case QCA_QCC2072: + qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname), + "ornnv", soc_type, ver, + rom_ver, boardid); + break; default: snprintf(config.fwname, sizeof(config.fwname), "qca/nvm_%08x.bin", soc_ver); } } + if (soc_type == QCA_QCC2072) + qca_get_nvm_name_by_board(config.calib_name, + sizeof(config.calib_name), + "ornbcscal", soc_type, ver, + rom_ver, boardid); + err = qca_download_firmware(hdev, &config, soc_type, rom_ver); if (err < 0 && !firmware_name && soc_type == QCA_WCN6855) { qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname), @@ -983,6 +1052,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: /* get fw build info */ err = qca_read_fw_build_info(hdev); if (err < 0) diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index 8f3c1b1c77b3d..425133096eda5 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h @@ -94,6 +94,7 @@ enum qca_tlv_type { struct qca_fw_config { u8 type; char fwname[64]; + char calib_name[64]; uint8_t user_baud_rate; enum qca_tlv_dnld_mode dnld_mode; enum qca_tlv_dnld_mode dnld_type; @@ -158,6 +159,7 @@ enum qca_btsoc_type { QCA_WCN6750, QCA_WCN6855, QCA_WCN7850, + QCA_QCC2072, }; #if IS_ENABLED(CONFIG_BT_QCA) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 7089e9b639b2a..e9d17772865a0 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1375,6 +1375,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) /* Give the controller time to process the request */ switch (qca_soc_type(hu)) { + case QCA_QCC2072: case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: @@ -1462,6 +1463,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu, static int qca_check_speeds(struct hci_uart *hu) { switch (qca_soc_type(hu)) { + case QCA_QCC2072: case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: @@ -1513,6 +1515,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: hci_uart_set_flow_control(hu, true); break; @@ -1548,6 +1551,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: hci_uart_set_flow_control(hu, false); break; @@ -1864,6 +1868,7 @@ static int qca_power_on(struct hci_dev *hdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: ret = qca_regulator_init(hu); break; @@ -1963,6 +1968,10 @@ static int qca_setup(struct hci_uart *hu) soc_name = "wcn7850"; break; + case QCA_QCC2072: + soc_name = "qcc2072"; + break; + default: soc_name = "ROME/QCA6390"; } @@ -1986,6 +1995,7 @@ static int qca_setup(struct hci_uart *hu) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: if (qcadev && qcadev->bdaddr_property_broken) hci_set_quirk(hdev, HCI_QUIRK_BDADDR_PROPERTY_BROKEN); @@ -2019,6 +2029,7 @@ static int qca_setup(struct hci_uart *hu) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: break; default: @@ -2172,6 +2183,12 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = { .num_vregs = 4, }; +static const struct qca_device_data qca_soc_data_qcc2072 __maybe_unused = { + .soc_type = QCA_QCC2072, + .num_vregs = 0, + .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES, +}; + static const struct qca_device_data qca_soc_data_wcn6750 __maybe_unused = { .soc_type = QCA_WCN6750, .vregs = (struct qca_vreg []) { @@ -2280,6 +2297,7 @@ static void qca_power_off(struct hci_uart *hu) case QCA_WCN6750: case QCA_WCN6855: + case QCA_QCC2072: gpiod_set_value_cansleep(qcadev->bt_en, 0); msleep(100); qca_regulator_disable(qcadev); @@ -2435,6 +2453,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: qcadev->bt_power = devm_kzalloc(&serdev->dev, sizeof(struct qca_power), GFP_KERNEL); @@ -2454,6 +2473,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: + case QCA_QCC2072: if (!device_property_present(&serdev->dev, "enable-gpios")) { /* * Backward compatibility with old DT sources. If the @@ -2496,6 +2516,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) if (!qcadev->bt_en && (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855 || + data->soc_type == QCA_QCC2072 || data->soc_type == QCA_WCN7850)) power_ctrl_enabled = false; @@ -2504,6 +2525,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) if (IS_ERR(qcadev->sw_ctrl) && (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855 || + data->soc_type == QCA_QCC2072 || data->soc_type == QCA_WCN7850)) { dev_err(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); return PTR_ERR(qcadev->sw_ctrl); @@ -2582,6 +2604,7 @@ static void qca_serdev_remove(struct serdev_device *serdev) struct qca_power *power = qcadev->bt_power; switch (qcadev->btsoc_type) { + case QCA_QCC2072: case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: @@ -2791,6 +2814,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,wcn6750-bt", .data = &qca_soc_data_wcn6750}, { .compatible = "qcom,wcn6855-bt", .data = &qca_soc_data_wcn6855}, { .compatible = "qcom,wcn7850-bt", .data = &qca_soc_data_wcn7850}, + { .compatible = "qcom,qcc2072-bt", .data = &qca_soc_data_qcc2072 }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); From 397d46b1a4d9dc6496583496f4ce45e1a9061c50 Mon Sep 17 00:00:00 2001 From: Rahul Samana Date: Mon, 27 Jul 2026 14:41:26 +0530 Subject: [PATCH 0413/1133] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: label BT PMU and M.2 PCI node The reworked RB3 Gen 2 Industrial BT UART overlay needs to disable the on-board WCN6750 PMU and add a graph endpoint to the M.2 PCI node. Label the exact WCN6750 PMU node and PCI child node connected to the M.2 E-key slot so the overlay can patch them directly instead of using a full path or reconstructing the nested PCI hierarchy. Link: https://lore.kernel.org/r/20260727-rb3-industrial-bt-uart-v2-4-2d100f30e202@oss.qualcomm.com CRs-Fixed: 4615698 Signed-off-by: Rahul Samana --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 909039816a216..5dfedb4a273a8 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -325,7 +325,7 @@ regulator-enable-ramp-delay = <10000>; }; - wcn6750-pmu { + wcn6750_pmu: wcn6750-pmu { compatible = "qcom,wcn6750-pmu"; pinctrl-0 = <&bt_en>; pinctrl-names = "default"; @@ -901,7 +901,7 @@ bus-range = <0x3 0xff>; }; - pcie@2,0 { + pcie0_m2_e: pcie@2,0 { reg = <0x21000 0x0 0x0 0x0 0x0>; #address-cells = <3>; #size-cells = <2>; From 86caec3909278c7ae5f804e2ae0a26ad347f4579 Mon Sep 17 00:00:00 2001 From: Rahul Samana Date: Mon, 27 Jul 2026 14:41:27 +0530 Subject: [PATCH 0414/1133] FROMLIST: arm64: dts: qcom: kodiak: mark PCIe root port as bridge The PCI core needs to associate the DT node below the QCS6490 PCIe host bridge with the enumerated PCI-to-PCI bridge device before child nodes can be matched against the PCI topology. Add compatible = "pciclass,0604" to pcie0_port so child nodes below the bridge can be matched by the PCI device class. Link: https://lore.kernel.org/r/20260727-rb3-industrial-bt-uart-v2-5-2d100f30e202@oss.qualcomm.com CRs-Fixed: 4615698 Reviewed-by: Konrad Dybcio Signed-off-by: Rahul Samana --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 8c7523602d271..ad7d2079659d9 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -2310,6 +2310,7 @@ status = "disabled"; pcie0_port: pcie@0 { + compatible = "pciclass,0604"; device_type = "pci"; reg = <0x0 0x0 0x0 0x0 0x0>; bus-range = <0x01 0xff>; From 4553fcb0a1027063a2ce40071d5ab1641cc1bd12 Mon Sep 17 00:00:00 2001 From: Rahul Samana Date: Mon, 27 Jul 2026 14:41:27 +0530 Subject: [PATCH 0415/1133] FROMLIST: arm64: dts: qcom: rb3gen2: add Industrial BT UART overlay The reworked RB3 Gen 2 Industrial mezzanine keeps the common Industrial mezzanine hardware description but routes QCC2072 Bluetooth over UART4 instead of the default Bluetooth-over-USB path. Build this variant by applying the common Industrial mezzanine overlay first, followed by the BT UART overlay. The overlay models the M.2 E-key connector graph endpoints for PCIe and UART, and disables the on-board WCN6750 PMU and UART7 path so the M.2 QCC2072 Bluetooth controller can be used instead. Link: https://lore.kernel.org/r/20260727-rb3-industrial-bt-uart-v2-6-2d100f30e202@oss.qualcomm.com CRs-Fixed: 4615698 Signed-off-by: Rahul Samana --- arch/arm64/boot/dts/qcom/Makefile | 2 + ...-rb3gen2-industrial-mezzanine-bt-uart.dtso | 129 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-bt-uart.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..5d36ce8ebc117 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -196,8 +196,10 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine.dtbo qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo +qcs6490-rb3gen2-industrial-mezzanine-bt-uart-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo qcs6490-rb3gen2-industrial-mezzanine-bt-uart.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-bt-uart.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-minipc-g1iot.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-rubikpi3.dtb diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-bt-uart.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-bt-uart.dtso new file mode 100644 index 0000000000000..67577d6f279f4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-bt-uart.dtso @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&{/} { + vreg_wcn_3p3: regulator-wcn-3p3 { + compatible = "regulator-fixed"; + regulator-name = "VREG_WCN_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-boot-on; + }; + + m2-e-connector { + compatible = "pcie-m2-e-connector"; + vpcie3v3-supply = <&vreg_wcn_3p3>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_pcie_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&pcie0_m2_e_ep>; + }; + }; + + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_uart_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&uart4_m2_e_ep>; + }; + }; + }; + }; +}; + +&qup_uart4_cts { + bias-bus-hold; +}; + +&qup_uart4_rts { + drive-strength = <2>; + bias-disable; +}; + +&qup_uart4_rx { + bias-pull-up; +}; + +&qup_uart4_tx { + drive-strength = <2>; + bias-disable; +}; + +&tlmm { + qup_uart4_sleep_cts: qup-uart4-sleep-cts-state { + pins = "gpio16"; + function = "gpio"; + bias-bus-hold; + }; + + qup_uart4_sleep_rts: qup-uart4-sleep-rts-state { + pins = "gpio17"; + function = "gpio"; + bias-pull-down; + }; + + qup_uart4_sleep_tx: qup-uart4-sleep-tx-state { + pins = "gpio18"; + function = "gpio"; + bias-pull-up; + }; + + qup_uart4_sleep_rx: qup-uart4-sleep-rx-state { + pins = "gpio19"; + function = "gpio"; + bias-pull-up; + }; +}; + +&pcie0_m2_e { + port { + pcie0_m2_e_ep: endpoint { + remote-endpoint = <&m2_e_pcie_ep>; + }; + }; +}; + +&uart4 { + interrupts-extended = <&intc GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>, + <&tlmm 19 IRQ_TYPE_EDGE_FALLING>; + pinctrl-names = "default", "sleep"; + pinctrl-1 = <&qup_uart4_sleep_cts>, <&qup_uart4_sleep_rts>, + <&qup_uart4_sleep_tx>, <&qup_uart4_sleep_rx>; + + status = "okay"; + + port { + uart4_m2_e_ep: endpoint { + remote-endpoint = <&m2_e_uart_ep>; + }; + }; +}; + +&uart7 { + status = "disabled"; +}; + +&wcn6750_pmu { + status = "disabled"; +}; From 8384d4140b8b067289a8c85e0466f9706255d803 Mon Sep 17 00:00:00 2001 From: Rahul Samana Date: Sat, 1 Aug 2026 16:11:54 +0530 Subject: [PATCH 0416/1133] BACKPORT: arm64: dts: qcom: rb3gen2: fix BT UART PCIe endpoint The pcie0_m2_e label was added to the base RB3 Gen 2 PCIe1 topology, but the QCC2072 device on the Industrial mezzanine BT UART variant is behind the Industrial PCIe0 switch. Drop the incorrect base label and patch the actual Industrial PCIe0 downstream port from the BT UART overlay so pwrseq-pcie-m2 can associate the enumerated QCC2072 PCI function with the M.2 connector. Signed-off-by: Rahul Samana --- ...qcs6490-rb3gen2-industrial-mezzanine-bt-uart.dtso | 12 ++++++++---- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-bt-uart.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-bt-uart.dtso index 67577d6f279f4..591af9dfc64e1 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-bt-uart.dtso +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-bt-uart.dtso @@ -96,10 +96,14 @@ }; }; -&pcie0_m2_e { - port { - pcie0_m2_e_ep: endpoint { - remote-endpoint = <&m2_e_pcie_ep>; +&pcie0_port { + pcie@0,0 { + pcie@2,0 { + port { + pcie0_m2_e_ep: endpoint { + remote-endpoint = <&m2_e_pcie_ep>; + }; + }; }; }; }; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 5dfedb4a273a8..eb7bc71220884 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -901,7 +901,7 @@ bus-range = <0x3 0xff>; }; - pcie0_m2_e: pcie@2,0 { + pcie@2,0 { reg = <0x21000 0x0 0x0 0x0 0x0>; #address-cells = <3>; #size-cells = <2>; From 5bf80f0d4d46e6d59754bb36ccd94a0d236daeaa Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 22 Sep 2026 22:38:26 +0530 Subject: [PATCH 0417/1133] PENDING: arm64: dts: qcom: glymur: Add WCD9378 headphone support Add the LPASS glue and SoundWire topology needed to bring up the WCD9378 (Tambora) headphone codec on Glymur. SoC dtsi: - lpass_rxmacro (0x06a70000) and lpass_txmacro (0x06a90000) codec nodes with their LPASS clock inputs: mclk, macro/dcodec votes, npl and the VA macro fsgen. - lpass_audiocc (0x06a94000) and lpasscc (0x07680000) clock controllers, which drive the SoundWire RX/TX CGCR resets. - swr1 (RX @ 0x06a80000) and swr2 (TX @ 0x07630000) SoundWire controllers, disabled by default so that boards pick the topology. Mobile-mode boards use swr1/swr2 as independent buses; compute-mode boards use swr2 as the bus master with swr1 as its data-only lane provider. Board (CRD) dtsi: - Enable the compute-mode topology: swr1 becomes a data-only lane provider via #qcom,swrm-lane-cells, contributing DATA lanes 2 and 3 to swr2 through qcom,secondary-lanes. swr2 owns SWR_CLK, the control lane and DATA lanes 0/1, and hosts wcd9378c as its sole SDCA slave. The unified-bus per-port arrays on swr2 describe DP2 (capture) and DP6/DP7/DP8 (playback), with qcom,ports-lane-control routing each port to the owning IP. - WCD Playback and WCD Capture DAI links on RX_CODEC_DMA_RX_0 and TX_CODEC_DMA_TX_3, plus DAPM routes for HPH playback (IT 41 <- HPHL/HPHR_OUT) and the TX macro <- WCD OT 36 capture bridge. - wcd_default reset pin state on gpio191. Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 148 +++++++++++++++++++- arch/arm64/boot/dts/qcom/glymur.dtsi | 165 +++++++++++++++++++++++ 2 files changed, 312 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index 1591006ba74f7..ab5981f402126 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -268,7 +268,18 @@ "VA DMIC0", "vdd-micb", "VA DMIC1", "vdd-micb", "VA DMIC2", "vdd-micb", - "VA DMIC3", "vdd-micb"; + "VA DMIC3", "vdd-micb", + "IT 41 Playback", "HPHL_OUT", + "IT 41 Playback", "HPHR_OUT", + /* + * Bridge the TX macro SoundWire input to the + * WCD9378 capture output terminal (OT 36, DP2) + * so DAPM completes the codec -> macro capture + * path. Without this the macro powers up its + * decimator but no data is pulled from the + * codec. + */ + "TX SWR_INPUT1", "OT 36 Capture"; wsa-dai-link { link-name = "WSA Playback"; @@ -289,6 +300,45 @@ }; }; + /* + * WCD9378 compute mode: swr2 is the bus master and swr1 is + * its lane provider (contributing DATA lanes 2 and 3), so + * both DAI links reference &swr2 as the controller DAI. + * swr2 cell 0 = dout (playback) + * swr2 cell 1 = din (capture) + */ + wcd-playback-dai-link { + link-name = "WCD Playback"; + + cpu { + sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>; + }; + + codec { + sound-dai = <&wcd9378c 0>, <&swr2 0>, <&lpass_rxmacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-capture-dai-link { + link-name = "WCD Capture"; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + codec { + sound-dai = <&wcd9378c 18>, <&swr2 1>, <&lpass_txmacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + va-dai-link { link-name = "VA Capture"; @@ -1168,6 +1218,94 @@ }; }; +/* + * WCD9378 compute-mode SoundWire. + * + * Two physical SWR IPs come together to form one logical multi-lane bus: + * + * - swr1 (RX @ 0x06a80000) is retargeted as a data-only lane provider + * contributing DATA lanes 2 and 3. It does not enumerate slaves of + * its own; its DATA0/DATA1 in local numbering are exposed to swr2 as + * bus lanes 2/3 via qcom,secondary-lanes on swr2. + * - swr2 (TX @ 0x07630000) is the SoundWire bus master: it owns SWR_CLK, + * the control lane and DATA lanes 0/1, and hosts wcd9378c as the sole + * SDCA slave. The two-cell lane pairs in qcom,secondary-lanes tell + * the driver to route DPn writes for bus lanes 2/3 through the + * provider's ops. + */ +&swr1 { + /* + * Data-only lane provider. #qcom,swrm-lane-cells = <1> marks this + * node as provider-only, so no bus master is registered and no slave + * nodes are enumerated here. + */ + #qcom,swrm-lane-cells = <1>; + + status = "okay"; +}; + +&swr2 { + /* + * Unified-bus per-port arrays for WCD9378 SDCA compute mode. Ports 2 + * (DP2 capture) and 6/7/8 (DP6/7/8 playback) drive traffic. The lane + * control array routes each port to the owning IP: bus lanes 0/1 on + * swr2 (local), lanes 2/3 on swr1 (via the provider). + */ + qcom,secondary-lanes = <&swr1 0>, <&swr1 1>; + + qcom,ports-block-pack-mode = + /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0x00 + 0x01 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-word-length = + /bits/ 8 <0xff 0x01 0xff 0xff 0xff 0x01 0x07 + 0x04 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-offset1 = + /bits/ 8 <0x00 0x01 0x02 0x00 0x00 0x00 0x00 + 0x0b 0x00 0x00 0x00 0x00 0x00 0x00>; + qcom,ports-offset2 = + /bits/ 8 <0x00 0x00 0x00 0x00 0xff 0x00 0x00 + 0x0b 0x00 0x00 0x00 0x00 0x00 0x00>; + qcom,ports-sinterval-low = + /bits/ 8 <0x00 0x01 0x03 0x03 0x00 0x03 0x1f + 0x1f 0x00 0x00 0x00 0x00 0x00 0x00>; + qcom,ports-hstart = + /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0x00 0x00 + 0x00 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-hstop = + /bits/ 8 <0xff 0x0f 0xff 0xff 0xff 0x0f 0x0f + 0x0f 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-lane-control = + /bits/ 8 <0xff 0x01 0x00 0x01 0xff 0x03 0x02 + 0x02 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-ch-mask = + /bits/ 8 <0xff 0x01 0xff 0xff 0xff 0x03 0x01 + 0x03 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-block-group-count = + /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + + status = "okay"; + + wcd9378c: codec@3,0 { + compatible = "qcom,wcd9378c", "sdw20217011000"; + reg = <0 3>; + + pinctrl-0 = <&wcd_default>; + pinctrl-names = "default"; + + qcom,port-mapping = <2 2 3 4 5 6 7 8>; + + reset-gpios = <&tlmm 191 GPIO_ACTIVE_LOW>; + + vdd-buck-supply = <&vreg_l15b_e0_1p8>; + vdd-rxtx-supply = <&vreg_l15b_e0_1p8>; + vdd-io-supply = <&vreg_l18b_e0_1p2>; + vdd-mic-bias-supply = <&vreg_bob1_e0>; + + #sound-dai-cells = <1>; + }; +}; + &swr3 { status = "okay"; @@ -1366,6 +1504,14 @@ }; }; + wcd_default: wcd-reset-n-active-state { + pins = "gpio191"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; + wcn_wlan_bt_en: wcn-wlan-bt-en-state { pins = "gpio116", "gpio117"; function = "gpio"; diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index 4a44208fdfe01..c3ef7fa9a5516 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -5009,6 +5009,105 @@ }; }; + lpass_rxmacro: codec@6a70000 { + compatible = "qcom,glymur-lpass-rx-macro"; + reg = <0x0 0x06a70000 0x0 0x1000>; + clocks = <&q6prmcc LPASS_CLK_ID_RX_CORE_TX_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>, + <&q6prmcc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&lpass_vamacro>; + clock-names = "mclk", + "npl", + "macro", + "dcodec", + "fsgen"; + + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + swr1: soundwire@6a80000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x0 0x06a80000 0x0 0x10000>; + interrupts = ; + clocks = <&lpass_rxmacro>; + clock-names = "iface"; + label = "RX"; + + resets = <&lpass_audiocc 0>; + reset-names = "swr_audio_cgcr"; + + pinctrl-0 = <&rx_swr_active>; + pinctrl-names = "default"; + + qcom,din-ports = <1>; + qcom,dout-ports = <13>; + + qcom,ports-block-pack-mode = + /bits/ 8 <0xff 0xff 0x01 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-word-length = + /bits/ 8 <0x01 0x07 0x04 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-offset1 = + /bits/ 8 <0x00 0x00 0x0b 0x01 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00>; + qcom,ports-offset2 = + /bits/ 8 <0x00 0x00 0x0b 0x00 0x00 0xff 0xff + 0xff 0xff 0x00 0x00 0x00 0x00 0x00>; + qcom,ports-sinterval = + /bits/ 16 <0x03 0x1f 0x1f 0x07 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00>; + qcom,ports-hstart = + /bits/ 8 <0x00 0x03 0x00 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-hstop = + /bits/ 8 <0xff 0x06 0x0f 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-lane-control = + /bits/ 8 <0x01 0x00 0x00 0x00 0x00 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-block-group-count = + /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + + #address-cells = <2>; + #size-cells = <0>; + #sound-dai-cells = <1>; + status = "disabled"; + }; + + lpass_txmacro: codec@6a90000 { + compatible = "qcom,glymur-lpass-tx-macro"; + reg = <0x0 0x06a90000 0x0 0x1000>; + 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_vamacro>; + clock-names = "mclk", + "npl", + "macro", + "dcodec", + "fsgen"; + + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + lpass_audiocc: clock-controller@6a94000 { + compatible = "qcom,glymur-lpassaudiocc"; + reg = <0x0 0x06a94000 0x0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + swr0: soundwire@6c80000 { compatible = "qcom,soundwire-v3.1.0"; reg = <0x0 0x06c80000 0x0 0x10000>; @@ -5112,6 +5211,65 @@ #interconnect-cells = <2>; }; + swr2: soundwire@7630000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x0 0x07630000 0x0 0x10000>; + interrupts = ; + interrupt-names = "core"; + clocks = <&lpass_txmacro>; + clock-names = "iface"; + label = "TX"; + + resets = <&lpasscc 1>; + reset-names = "swr_audio_cgcr"; + + pinctrl-0 = <&tx_swr_active>; + pinctrl-names = "default"; + + /* + * Sample interval is encoded as (sample_interval - 1). + * At a 38.4MHz bus clock and a 50x16 frame shape the + * frame rate is 48kHz, so 48kHz capture on port 2 + * needs sample_interval = 1, encoded as 0x00. + * + * HStop is 0x0f and word length 0x01 (1-bit PDM) for + * master port 2, which carries the WCD9378 DP2 + * capture stream on lane 1. + */ + qcom,ports-block-pack-mode = + /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-word-length = + /bits/ 8 <0xff 0x01 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-offset1 = + /bits/ 8 <0x00 0x01 0x02 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00>; + qcom,ports-offset2 = + /bits/ 8 <0x00 0xff 0x00 0x00 0xff 0xff 0xff + 0xff 0x00 0x00 0x00 0x00 0x00 0x00>; + qcom,ports-sinterval-low = + /bits/ 8 <0x00 0x00 0x03 0x03 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00>; + qcom,ports-hstart = + /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-hstop = + /bits/ 8 <0xff 0x0f 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-lane-control = + /bits/ 8 <0xff 0x01 0x00 0x01 0xff 0x03 0x02 + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-block-group-count = + /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff>; + + #address-cells = <2>; + #size-cells = <0>; + #sound-dai-cells = <1>; + status = "disabled"; + }; + lpass_vamacro: codec@7660000 { compatible = "qcom,glymur-lpass-va-macro", "qcom,sm8550-lpass-va-macro"; reg = <0x0 0x07660000 0x0 0x2000>; @@ -5127,6 +5285,13 @@ #sound-dai-cells = <1>; }; + lpasscc: clock-controller@7680000 { + compatible = "qcom,glymur-lpasscc"; + reg = <0x0 0x07680000 0x0 0x10000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + lpass_tlmm: pinctrl@7760000 { compatible = "qcom,glymur-lpass-lpi-pinctrl", "qcom,sm8650-lpass-lpi-pinctrl"; reg = <0x0 0x07760000 0x0 0x20000>; From adbc42259f8b0805b5317d6f95364337d38cd511 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:23 +0530 Subject: [PATCH 0418/1133] FROMLIST: arm64: dts: qcom: lemans: Add PSCI SYSTEM_RESET2 types Add support for SYSTEM_RESET2 vendor-specific resets as reboot-modes in the psci node. Describe the resets: "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/20251109-arm-psci-system_reset2-vendor-reboots-v17-10-46e085bca4cc@oss.qualcomm.com Signed-off-by: Elliot Berman Signed-off-by: Shivendra Pratap --- arch/arm64/boot/dts/qcom/lemans.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 1fdb72fa55184..5dafa124b1416 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -618,6 +618,11 @@ #power-domain-cells = <0>; domain-idle-states = <&cluster_sleep_apss_rsc_pc>; }; + + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; }; reserved-memory { From e5402c5fefbd9f9186572ac61e05eb4bd140d2ef Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Sun, 9 Nov 2025 20:07:21 +0530 Subject: [PATCH 0419/1133] FROMLIST: arm64: dts: qcom: qcm6490-idp: Add PSCI SYSTEM_RESET2 types Add support for SYSTEM_RESET2 vendor-specific resets in qcm6490-idp as reboot-modes. Describe the resets: "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/20251109-arm-psci-system_reset2-vendor-reboots-v17-8-46e085bca4cc@oss.qualcomm.com Reviewed-by: Konrad Dybcio Signed-off-by: Elliot Berman Signed-off-by: Shivendra Pratap --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 2 +- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 8c7523602d271..d1b5eb9e86ddf 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -867,7 +867,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index af7821e02fdbf..e42dc572c7708 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -792,6 +792,13 @@ bias-disable; }; +&psci { + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + &qupv3_id_0 { status = "okay"; }; From e671adb284a42b6f904b7f705928ce357279a7b2 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Sun, 9 Nov 2025 20:07:22 +0530 Subject: [PATCH 0420/1133] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Add PSCI SYSTEM_RESET2 types Add support for SYSTEM_RESET2 vendor-specific resets in qcs6490-rb3gen2 as reboot-modes. Describe the resets: "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/20251109-arm-psci-system_reset2-vendor-reboots-v17-9-46e085bca4cc@oss.qualcomm.com Reviewed-by: Konrad Dybcio Signed-off-by: Elliot Berman Signed-off-by: Shivendra Pratap --- 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 909039816a216..6ba5ff1582e45 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -1107,6 +1107,13 @@ bias-disable; }; +&psci { + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + &qup_uart7_cts { /* * Configure a bias-bus-hold on CTS to lower power From 3fdbeaa6817e24ae03dc73771e3dcf221343ed2b Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Sun, 9 Aug 2026 17:59:01 +0530 Subject: [PATCH 0421/1133] FROMLIST: arm64: dts: qcom: kodiak: Enable CDSP & Modem cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP/Modem does not throttle its speed automatically when it reaches high temperatures in kodiak. Set up CDSP cooling by throttling the cdsp when it reaches 100°C and for modem when it reaches to 95°C. Add polling-delay-passive so the governor periodically evaluates the zone during passive cooling and steps up cooling levels when temperature stabilizes below the next trip. Since the remoteproc_mpss node doesn't exist on non modem boards, the cooling-maps that reference it cause DT compilation errors. To fix that remove inherited mdmss cooling-map nodes. Link: https://lore.kernel.org/r/20260809-b4-qmi-tmd-v8-5-b15d47adc379@oss.qualcomm.com Reviewed-by: Daniel Lezcano Signed-off-by: Gaurav Kohli --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 125 ++++++++++++++++++ .../dts/qcom/qcs6490-radxa-dragon-q6a.dts | 8 ++ .../qcom/qcs6490-thundercomm-minipc-g1iot.dts | 8 ++ .../dts/qcom/qcs6490-thundercomm-rubikpi3.dts | 8 ++ .../dts/qcom/qcs6490-vicharak-axon-mini.dts | 8 ++ .../dts/qcom/sc7280-herobrine-lte-sku.dtsi | 10 ++ .../dts/qcom/sc7280-herobrine-wifi-sku.dtsi | 9 ++ 7 files changed, 176 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index d1b5eb9e86ddf..a086ac7cd3ce5 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -30,6 +30,7 @@ #include #include #include +#include #include / { @@ -3445,6 +3446,8 @@ qcom,smem-states = <&modem_smp2p_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <3>; + status = "disabled"; glink-edge { @@ -4817,6 +4820,8 @@ qcom,smem-states = <&cdsp_smp2p_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <3>; + status = "disabled"; glink-edge { @@ -7785,6 +7790,8 @@ }; nspss0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 3>; trips { @@ -7794,15 +7801,31 @@ type = "hot"; }; + nspss0_alert1: trip-point1 { + temperature = <100000>; + hysteresis = <5000>; + type = "passive"; + }; + nspss0_crit: nspss0-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nspss0_alert1>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nspss1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 4>; trips { @@ -7812,12 +7835,26 @@ type = "hot"; }; + nspss1_alert1: trip-point1 { + temperature = <100000>; + hysteresis = <5000>; + type = "passive"; + }; + nspss1_crit: nspss1-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nspss1_alert1>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; video-thermal { @@ -7857,6 +7894,8 @@ }; mdmss0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 7>; trips { @@ -7866,15 +7905,37 @@ type = "hot"; }; + mdmss0_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss0_crit: mdmss0-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + mdmss0_pa_cooling_map: map0 { + trip = <&mdmss0_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_PA + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + + mdmss0_modem_cooling_map: map1 { + trip = <&mdmss0_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_MODEM + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; mdmss1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 8>; trips { @@ -7884,15 +7945,37 @@ type = "hot"; }; + mdmss1_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss1_crit: mdmss1-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + mdmss1_pa_cooling_map: map0 { + trip = <&mdmss1_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_PA + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + + mdmss1_modem_cooling_map: map1 { + trip = <&mdmss1_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_MODEM + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; mdmss2-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 9>; trips { @@ -7902,15 +7985,37 @@ type = "hot"; }; + mdmss2_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss2_crit: mdmss2-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + mdmss2_pa_cooling_map: map0 { + trip = <&mdmss2_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_PA + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + + mdmss2_modem_cooling_map: map1 { + trip = <&mdmss2_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_MODEM + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; mdmss3-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens1 10>; trips { @@ -7920,12 +8025,32 @@ type = "hot"; }; + mdmss3_alert1: trip-point1 { + temperature = <95000>; + hysteresis = <2000>; + type = "passive"; + }; + mdmss3_crit: mdmss3-crit { temperature = <110000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + mdmss3_pa_cooling_map: map0 { + trip = <&mdmss3_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_PA + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + + mdmss3_modem_cooling_map: map1 { + trip = <&mdmss3_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_MODEM + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; camera0-thermal { diff --git a/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts b/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts index ed0b81710b9a9..45c7b8c2db6a1 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-radxa-dragon-q6a.dts @@ -24,6 +24,14 @@ /delete-node/ &adsp_mem; /delete-node/ &cdsp_mem; /delete-node/ &ipa_fw_mem; +/delete-node/ &mdmss0_pa_cooling_map; +/delete-node/ &mdmss0_modem_cooling_map; +/delete-node/ &mdmss1_pa_cooling_map; +/delete-node/ &mdmss1_modem_cooling_map; +/delete-node/ &mdmss2_pa_cooling_map; +/delete-node/ &mdmss2_modem_cooling_map; +/delete-node/ &mdmss3_pa_cooling_map; +/delete-node/ &mdmss3_modem_cooling_map; /delete-node/ &mpss_mem; /delete-node/ &remoteproc_mpss; /delete-node/ &remoteproc_wpss; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts index cfcb22bfb2989..caad57b79c1ed 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-minipc-g1iot.dts @@ -22,6 +22,14 @@ /delete-node/ &cdsp_mem; /delete-node/ &ipa_fw_mem; /delete-node/ &mpss_mem; +/delete-node/ &mdmss0_pa_cooling_map; +/delete-node/ &mdmss0_modem_cooling_map; +/delete-node/ &mdmss1_pa_cooling_map; +/delete-node/ &mdmss1_modem_cooling_map; +/delete-node/ &mdmss2_pa_cooling_map; +/delete-node/ &mdmss2_modem_cooling_map; +/delete-node/ &mdmss3_pa_cooling_map; +/delete-node/ &mdmss3_modem_cooling_map; /delete-node/ &remoteproc_mpss; /delete-node/ &remoteproc_wpss; /delete-node/ &rmtfs_mem; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts index 4ab7771fce1b0..7d58c94ee3bee 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-thundercomm-rubikpi3.dts @@ -23,6 +23,14 @@ /delete-node/ &adsp_mem; /delete-node/ &cdsp_mem; /delete-node/ &ipa_fw_mem; +/delete-node/ &mdmss0_pa_cooling_map; +/delete-node/ &mdmss0_modem_cooling_map; +/delete-node/ &mdmss1_pa_cooling_map; +/delete-node/ &mdmss1_modem_cooling_map; +/delete-node/ &mdmss2_pa_cooling_map; +/delete-node/ &mdmss2_modem_cooling_map; +/delete-node/ &mdmss3_pa_cooling_map; +/delete-node/ &mdmss3_modem_cooling_map; /delete-node/ &mpss_mem; /delete-node/ &remoteproc_mpss; /delete-node/ &remoteproc_wpss; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-vicharak-axon-mini.dts b/arch/arm64/boot/dts/qcom/qcs6490-vicharak-axon-mini.dts index 496b7583e4a28..979e7d3be5d9f 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-vicharak-axon-mini.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-vicharak-axon-mini.dts @@ -25,6 +25,14 @@ /delete-node/ &cdsp_mem; /delete-node/ &ipa_fw_mem; /delete-node/ &mpss_mem; +/delete-node/ &mdmss0_pa_cooling_map; +/delete-node/ &mdmss0_modem_cooling_map; +/delete-node/ &mdmss1_pa_cooling_map; +/delete-node/ &mdmss1_modem_cooling_map; +/delete-node/ &mdmss2_pa_cooling_map; +/delete-node/ &mdmss2_modem_cooling_map; +/delete-node/ &mdmss3_pa_cooling_map; +/delete-node/ &mdmss3_modem_cooling_map; /delete-node/ &remoteproc_mpss; /delete-node/ &remoteproc_wpss; /delete-node/ &rmtfs_mem; diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi index ac89724ee0993..891941906a467 100644 --- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi @@ -28,8 +28,18 @@ status = "okay"; }; +/delete-node/ &mdmss0_pa_cooling_map; +/delete-node/ &mdmss0_modem_cooling_map; +/delete-node/ &mdmss1_pa_cooling_map; +/delete-node/ &mdmss1_modem_cooling_map; +/delete-node/ &mdmss2_pa_cooling_map; +/delete-node/ &mdmss2_modem_cooling_map; +/delete-node/ &mdmss3_pa_cooling_map; +/delete-node/ &mdmss3_modem_cooling_map; + &remoteproc_mpss { compatible = "qcom,sc7280-mss-pil"; + /delete-property/ #cooling-cells; reg = <0 0x04080000 0 0x10000>, <0 0x04180000 0 0x48>; reg-names = "qdsp6", "rmb"; diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi index 3ebc915f0dc2f..296c72672ec58 100644 --- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi @@ -7,6 +7,15 @@ /* WIFI SKUs save 256M by not having modem/mba/rmtfs memory regions defined. */ +/delete-node/ &mdmss0_pa_cooling_map; +/delete-node/ &mdmss0_modem_cooling_map; +/delete-node/ &mdmss1_pa_cooling_map; +/delete-node/ &mdmss1_modem_cooling_map; +/delete-node/ &mdmss2_pa_cooling_map; +/delete-node/ &mdmss2_modem_cooling_map; +/delete-node/ &mdmss3_pa_cooling_map; +/delete-node/ &mdmss3_modem_cooling_map; + /delete-node/ &mpss_mem; /delete-node/ &remoteproc_mpss; /delete-node/ &rmtfs_mem; From 4c174a4f3af19112f22c3bec75ad9eb9125c9970 Mon Sep 17 00:00:00 2001 From: Gopi Botlagunta Date: Fri, 30 Jan 2026 15:57:25 +0530 Subject: [PATCH 0422/1133] FROMLIST: arm64: dts: qcom: Enable lvds panel-DV215FHM-R01 for rb3gen2 industrial mezzanine Below is the routing diagram of dsi lanes from qcs6490 soc to mezzanine. DSI0 --> SW1403.4 --> LT9611uxc --> hdmi port | --> SW2700.1 --> dsi connector | --> LT9211c --> LVDS connector Disable hdmi connector for industrial mezzanine and enable LT9211c bridge and lvds panel node. LT9211c is powered by default with reset gpio connected to 117. Link: https://lore.kernel.org/r/20260130-add-lt9211c-bridge-for-rb3gen2-industrial-mezzanine-v2-1-a98714fa1531@oss.qualcomm.com Signed-off-by: Gopi Botlagunta Co-developed-by: Yi Zhang Signed-off-by: Yi Zhang --- .../qcs6490-rb3gen2-industrial-mezzanine.dtso | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso index e8780646ab19c..5fa54d7626ddd 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso @@ -36,6 +36,111 @@ status = "disabled"; }; +/ { + hdmi-connector { + status = "disabled"; + }; + + panel_lvds: panel-lvds@0 { + compatible = "panel-lvds"; + data-mapping = "vesa-24"; + width-mm = <476>; + height-mm = <268>; + + status = "okay"; + + panel-timing { + clock-frequency = <148500000>; + hactive = <1920>; + vactive = <1080>; + hfront-porch = <88>; + hback-porch = <148>; + hsync-len = <44>; + vfront-porch = <4>; + vback-porch = <36>; + vsync-len = <5>; + de-active = <1>; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + dual-lvds-odd-pixels; + panel_in_lvds_odd: endpoint { + remote-endpoint = <<9211c_out_odd>; + }; + }; + + port@1 { + reg = <1>; + + dual-lvds-even-pixels; + panel_in_lvds_even: endpoint { + remote-endpoint = <<9211c_out_even>; + }; + + }; + }; + }; + +}; + +&i2c1 { + status = "okay"; + + lvds_bridge: lvds-bridge@29 { + compatible = "lontium,lt9211c"; + reg = <0x29>; + reset-gpios = <&tlmm 117 1>; + + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9211c_in: endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9211c_out_odd: endpoint { + remote-endpoint = <&panel_in_lvds_odd>; + }; + }; + + port@3 { + reg = <3>; + + lt9211c_out_even: endpoint { + remote-endpoint = <&panel_in_lvds_even>; + }; + }; + }; + }; + + +}; + +<9611_codec { + status = "disabled"; +}; + +&mdss_dsi0_out { + remote-endpoint = <<9211c_in>; +}; + &spi11 { #address-cells = <1>; #size-cells = <0>; From 5a532424a7fe3206402e4a61a3ad89ee97936f11 Mon Sep 17 00:00:00 2001 From: Janaki Ramaiah Thota Date: Tue, 3 Feb 2026 12:48:07 +0530 Subject: [PATCH 0423/1133] FROMLIST: arm64: dts: qcom: qcm6490-idp: add and enable BT node Add the PMU node for WCN6750 present on the qcm6490-idp board and assign its power outputs to the Bluetooth module. In WCN6750 module sw_ctrl and wifi-enable pins are handled in the wifi controller firmware. Therefore, it is not required to have those pins' entries in the PMU node. Link: https://lore.kernel.org/r/20260203071807.764036-1-janaki.thota@oss.qualcomm.com Reviewed-by: Konrad Dybcio Signed-off-by: Janaki Ramaiah Thota --- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index e42dc572c7708..d3ddf6b51963e 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -799,6 +799,39 @@ }; }; +&qup_uart7_cts { + /* + * Configure a bias-bus-hold on CTS to lower power + * usage when Bluetooth is turned off. Bus hold will + * maintain a low power state regardless of whether + * the Bluetooth module drives the pin in either + * direction or leaves the pin fully unpowered. + */ + bias-bus-hold; +}; + +&qup_uart7_rts { + /* We'll drive RTS, so no pull */ + drive-strength = <2>; + bias-disable; +}; + +&qup_uart7_rx { + /* + * Configure a pull-up on RX. This is needed to avoid + * garbage data when the TX pin of the Bluetooth module is + * in tri-state (module powered off or not driving the + * signal yet). + */ + bias-pull-up; +}; + +&qup_uart7_tx { + /* We'll drive TX, so no pull */ + drive-strength = <2>; + bias-disable; +}; + &qupv3_id_0 { status = "okay"; }; From 0e83d4148620ecd81a47197b5142b240570c4241 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Thu, 12 Feb 2026 17:36:29 +0530 Subject: [PATCH 0424/1133] FROMLIST: arm64: dts: qcom: qcm6490-idp: Enable PCIe1 Remove PCIe1 clocks from protected-list and enable PCIe1 controller and its corresponding PHY nodes on qcm6490-idp platform. PCIe1 is used to connect NVMe based SSD's on this platform. Signed-off-by: Sushrut Shree Trivedi Link: https://lore.kernel.org/r/20260212-qcm6490-idp-v1-1-80a45bd46ac5@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 39 ++++++++++++++++++++---- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index d3ddf6b51963e..419339095ed9f 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -591,12 +591,7 @@ }; &gcc { - protected-clocks = ,, - , , - , , - , , - , , - , , + protected-clocks = , , ,, , , , @@ -679,6 +674,22 @@ status = "okay"; }; +&pcie1 { + perst-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&pcie1_reset_n>, <&pcie1_wake_n>, <&pcie1_clkreq_n>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie1_phy { + vdda-phy-supply = <&vreg_l10c_0p88>; + vdda-pll-supply = <&vreg_l6b_1p2>; + + status = "okay"; +}; + &pm7250b_gpios { lcd_disp_bias_en: lcd-disp-bias-en-state { pins = "gpio2"; @@ -1110,6 +1121,22 @@ bias-pull-up; }; + pcie1_reset_n: pcie1-reset-n-state { + pins = "gpio2"; + function = "gpio"; + drive-strength = <16>; + output-low; + bias-disable; + }; + + pcie1_wake_n: pcie1-wake-n-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + sd_cd: sd-cd-state { pins = "gpio91"; function = "gpio"; From 1a539c92df34efbb43cd1e4b67e6b4ec2ab546e8 Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Thu, 24 Sep 2026 12:38:42 +0530 Subject: [PATCH 0425/1133] FROMLIST: power: Extend power_on_reason.h for upcoming PSCRR framework Prepare for the introduction of the Power State Change Reason Recorder (PSCRR) framework by expanding the power_on_reason.h header. This extension includes new power-on reasons: - POWER_ON_REASON_OVER_CURRENT for over-current conditions. - POWER_ON_REASON_REGULATOR_FAILURE for regulator failures. - POWER_ON_REASON_OVER_TEMPERATURE for over temperature situations. - POWER_ON_REASON_EC_PANIC for EC panics. - POWER_ON_REASON_EXTERNAL for an external reset source. Co-developed-by: Oleksij Rempel Signed-off-by: Oleksij Rempel Reviewed-by: Sebastian Reichel Signed-off-by: Faruque Ansari Reviewed-by: Matti Vaittinen Link: https://lore.kernel.org/r/20260924-pscrr-framework-v15-1-7af87107e0d3@oss.qualcomm.com --- include/linux/power/power_on_reason.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/power/power_on_reason.h b/include/linux/power/power_on_reason.h index 95a1ec0c403c6..13e61ace14f5b 100644 --- a/include/linux/power/power_on_reason.h +++ b/include/linux/power/power_on_reason.h @@ -15,5 +15,10 @@ #define POWER_ON_REASON_XTAL_FAIL "crystal oscillator failure" #define POWER_ON_REASON_BROWN_OUT "brown-out reset" #define POWER_ON_REASON_UNKNOWN "unknown reason" +#define POWER_ON_REASON_OVER_CURRENT "over current" +#define POWER_ON_REASON_REGULATOR_FAILURE "regulator failure" +#define POWER_ON_REASON_OVER_TEMPERATURE "over temperature" +#define POWER_ON_REASON_EC_PANIC "EC panic" +#define POWER_ON_REASON_EXTERNAL "external reset" #endif /* POWER_ON_REASON_H */ From 474be93361b35cd883622df5d8744e748224312f Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Thu, 24 Sep 2026 12:38:43 +0530 Subject: [PATCH 0426/1133] FROMLIST: reboot: hw_protection_trigger: use standardized numeric shutdown/reboot reasons instead of strings Prepares the kernel for the Power State Change Reason (PSCR) recorder, which will store shutdown and reboot reasons in persistent storage. Instead of using string-based reason descriptions, which are often too large to fit within limited storage spaces (e.g., RTC clocks with only 8 bits of battery-backed storage), we introduce `enum psc_reason`. This enumerates predefined reasons for power state changes, making it efficient to store and retrieve shutdown causes. Key changes: - Introduced `enum psc_reason`, defining structured reasons for power state changes. - Replaced string-based shutdown reasons with `psc_reason` identifiers. - Implemented `get_psc_reason()` and `set_psc_reason()` for tracking the last shutdown cause. - Added `psc_reason_to_str()` to map enum values to human-readable strings. - Updated `hw_protection_trigger()` to use `psc_reason` instead of string parameters. - Updated all consumers of `hw_protection_trigger()` to pass an appropriate `psc_reason` value instead of a string. - All structured logs now go through a single `pr_emerg()` in `__hw_protection_trigger()`, providing consistent output: HARDWARE PROTECTION : () Co-developed-by: Oleksij Rempel Signed-off-by: Oleksij Rempel Reviewed-by: Matti Vaittinen Acked-by: Mark Brown Acked-by: Tzung-Bi Shih Acked-by: Daniel Lezcano Signed-off-by: Faruque Ansari Link: https://lore.kernel.org/r/20260924-pscrr-framework-v15-2-7af87107e0d3@oss.qualcomm.com --- drivers/platform/chrome/cros_ec_lpc.c | 2 +- drivers/regulator/core.c | 16 +++--- drivers/regulator/irq_helpers.c | 9 ++-- drivers/thermal/thermal_core.c | 3 +- include/linux/reboot.h | 78 +++++++++++++++++++++++++-- kernel/reboot.c | 1 + 6 files changed, 91 insertions(+), 18 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index 78cfff80cdeaf..00e98d12ddbcf 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -455,7 +455,7 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data) blocking_notifier_call_chain(&ec_dev->panic_notifier, 0, ec_dev); kobject_uevent_env(&ec_dev->dev->kobj, KOBJ_CHANGE, (char **)env); /* Begin orderly shutdown. EC will force reset after a short period. */ - __hw_protection_trigger("CrOS EC Panic", -1, HWPROT_ACT_SHUTDOWN); + __hw_protection_trigger(PSCR_EC_PANIC, -1, HWPROT_ACT_SHUTDOWN); /* Do not query for other events after a panic is reported */ return; } diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 14422cfe80e2d..3cb126aba28fb 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -5554,26 +5554,26 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free); static void regulator_handle_critical(struct regulator_dev *rdev, unsigned long event) { - const char *reason = NULL; + enum psc_reason pscr; if (!rdev->constraints->system_critical) return; switch (event) { case REGULATOR_EVENT_UNDER_VOLTAGE: - reason = "System critical regulator: voltage drop detected"; + pscr = PSCR_UNDER_VOLTAGE; break; case REGULATOR_EVENT_OVER_CURRENT: - reason = "System critical regulator: over-current detected"; + pscr = PSCR_OVER_CURRENT; break; case REGULATOR_EVENT_FAIL: - reason = "System critical regulator: unknown error"; + pscr = PSCR_REGULATOR_FAILURE; + break; + default: + pscr = PSCR_UNKNOWN; } - if (!reason) - return; - - hw_protection_trigger(reason, + hw_protection_trigger(pscr, rdev->constraints->uv_less_critical_window_ms); } diff --git a/drivers/regulator/irq_helpers.c b/drivers/regulator/irq_helpers.c index cdbd170d2b150..eea6dc3bf84b4 100644 --- a/drivers/regulator/irq_helpers.c +++ b/drivers/regulator/irq_helpers.c @@ -66,15 +66,16 @@ static void regulator_notifier_isr_work(struct work_struct *work) reread: if (d->fatal_cnt && h->retry_cnt > d->fatal_cnt) { if (!d->die) - return hw_protection_trigger("Regulator HW failure? - no IC recovery", + return hw_protection_trigger(PSCR_REGULATOR_FAILURE, REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS); + ret = d->die(rid); /* * If the 'last resort' IC recovery failed we will have * nothing else left to do... */ if (ret) - return hw_protection_trigger("Regulator HW failure. IC recovery failed", + return hw_protection_trigger(PSCR_REGULATOR_FAILURE, REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS); /* @@ -255,13 +256,13 @@ static irqreturn_t regulator_notifier_isr(int irq, void *data) if (d->fatal_cnt && h->retry_cnt > d->fatal_cnt) { /* If we have no recovery, just try shut down straight away */ if (!d->die) { - hw_protection_trigger("Regulator failure. Retry count exceeded", + hw_protection_trigger(PSCR_REGULATOR_FAILURE, REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS); } else { ret = d->die(rid); /* If die() failed shut down as a last attempt to save the HW */ if (ret) - hw_protection_trigger("Regulator failure. Recovery failed", + hw_protection_trigger(PSCR_REGULATOR_FAILURE, REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS); } } diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index e8d4da0aeac38..d29be36788e53 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -319,11 +319,10 @@ static void thermal_zone_device_halt(struct thermal_zone_device *tz, * Its a must for forced_emergency_poweroff_work to be scheduled. */ int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS; - const char *msg = "Temperature too high"; dev_emerg(&tz->device, "%s: critical temperature reached\n", tz->type); - __hw_protection_trigger(msg, poweroff_delay_ms, action); + __hw_protection_trigger(PSCR_OVER_TEMPERATURE, poweroff_delay_ms, action); } void thermal_zone_device_critical(struct thermal_zone_device *tz) diff --git a/include/linux/reboot.h b/include/linux/reboot.h index aa08c3bbbf59a..08a7549bbc40e 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h @@ -178,6 +178,73 @@ void ctrl_alt_del(void); extern void orderly_poweroff(bool force); extern void orderly_reboot(void); + +/** + * enum psc_reason - Enumerates reasons for power state changes. + * + * This enum defines various reasons why a system might transition into a + * shutdown, reboot, or kexec state. While originally intended for hardware + * protection events, `psc_reason` can be extended to track other system + * transitions, such as controlled reboots triggered by software or + * maintenance operations. + * + * The values in this enumeration provide structured and standardized + * identifiers that replace free-form string descriptions. They are designed + * to be stored efficiently, making them suitable for use in environments + * with limited storage, such as battery-backed RTC registers, non-volatile + * memory, or bootloader communication mechanisms. + * + * Importantly, the order of these values **must remain stable**, as + * bootloaders, user-space tools, or post-mortem investigation utilities + * may rely on their numerical representation for consistent behavior. + * + * @PSCR_UNKNOWN: Unknown or unspecified reason for the power state change. + * This value serves as a default when no explicit cause is recorded. + * + * @PSCR_UNDER_VOLTAGE: Shutdown or reboot triggered due to supply voltage + * dropping below a safe threshold. This helps prevent instability or + * corruption caused by insufficient power. + * + * @PSCR_OVER_CURRENT: System shutdown or reboot due to excessive current draw, + * which may indicate a short circuit, an overloaded power rail, or other + * hardware faults requiring immediate action. + * + * @PSCR_REGULATOR_FAILURE: A critical failure in a voltage regulator, causing + * improper power delivery. This may be due to internal component failure, + * transient conditions, or external load issues requiring mitigation. + * + * @PSCR_OVER_TEMPERATURE: System shutdown or reboot due to excessive thermal + * conditions. This attempts to prevent hardware damage when temperature + * sensors detect unsafe levels, often impacting CPUs, GPUs, or power + * components. + * + * @PSCR_EC_PANIC: Shutdown or reboot triggered by an Embedded Controller (EC) + * panic. The EC is a microcontroller responsible for low-level system + * management, including power sequencing, thermal control, and battery + * management. An EC panic may indicate critical firmware issues, power + * management errors, or an unrecoverable hardware fault requiring + * immediate response. + * + * @PSCR_REASON_COUNT: Number of defined power state change reasons. This + * value is useful for range checking and potential future extensions + * while maintaining compatibility. + */ +enum psc_reason { + PSCR_UNKNOWN, + PSCR_UNDER_VOLTAGE, + PSCR_OVER_CURRENT, + PSCR_REGULATOR_FAILURE, + PSCR_OVER_TEMPERATURE, + PSCR_EC_PANIC, + + /* Number of reasons */ + PSCR_REASON_COUNT, +}; + +#define PSCR_MAX_REASON (PSCR_REASON_COUNT - 1) + +const char *psc_reason_to_str(enum psc_reason reason); + /** * enum hw_protection_action - Hardware protection action * @@ -191,13 +258,13 @@ extern void orderly_reboot(void); */ enum hw_protection_action { HWPROT_ACT_DEFAULT, HWPROT_ACT_SHUTDOWN, HWPROT_ACT_REBOOT }; -void __hw_protection_trigger(const char *reason, int ms_until_forced, +void __hw_protection_trigger(enum psc_reason reason, int ms_until_forced, enum hw_protection_action action); /** * hw_protection_trigger - Trigger default emergency system hardware protection action * - * @reason: Reason of emergency shutdown or reboot to be printed. + * @reason: Reason of emergency shutdown or reboot. * @ms_until_forced: Time to wait for orderly shutdown or reboot before * triggering it. Negative value disables the forced * shutdown or reboot. @@ -206,11 +273,16 @@ void __hw_protection_trigger(const char *reason, int ms_until_forced, * hardware from further damage. The exact action taken is controllable at * runtime and defaults to shutdown. */ -static inline void hw_protection_trigger(const char *reason, int ms_until_forced) +static inline void hw_protection_trigger(enum psc_reason reason, + int ms_until_forced) { __hw_protection_trigger(reason, ms_until_forced, HWPROT_ACT_DEFAULT); } +enum psc_reason get_psc_reason(void); +enum psc_reason get_psc_first_reason(void); +void set_psc_reason(enum psc_reason reason); + /* * Emergency restart, callable from an interrupt handler. */ diff --git a/kernel/reboot.c b/kernel/reboot.c index 9a84401adde5a..ae4758a369acb 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include From b4c33caf770c3beccb74ab732736a5b3c59cdbd5 Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Thu, 24 Sep 2026 12:38:44 +0530 Subject: [PATCH 0427/1133] FROMLIST: reboot: add parsable tokens for power state change reasons psc_reason_to_str() returns human-readable labels that contain spaces (e.g. "over temperature"). Those are fine for logs but unusable as values in a space-separated sysfs list or as a write target. Extend the single reason descriptor table with a stable, space-free token next to the existing label, and add psc_reason_to_token() and psc_reason_from_token() so consumers can emit and parse reasons without inventing their own string table. Co-developed-by: Oleksij Rempel Signed-off-by: Oleksij Rempel Signed-off-by: Faruque Ansari Reviewed-by: Matti Vaittinen Link: https://lore.kernel.org/r/20260924-pscrr-framework-v15-3-7af87107e0d3@oss.qualcomm.com --- include/linux/reboot.h | 2 + kernel/reboot.c | 208 ++++++++++++++++++++++++++++++----------- 2 files changed, 156 insertions(+), 54 deletions(-) diff --git a/include/linux/reboot.h b/include/linux/reboot.h index 08a7549bbc40e..4c5327dd76456 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h @@ -244,6 +244,8 @@ enum psc_reason { #define PSCR_MAX_REASON (PSCR_REASON_COUNT - 1) const char *psc_reason_to_str(enum psc_reason reason); +const char *psc_reason_to_token(enum psc_reason reason); +int psc_reason_from_token(const char *token, enum psc_reason *reason); /** * enum hw_protection_action - Hardware protection action diff --git a/kernel/reboot.c b/kernel/reboot.c index ae4758a369acb..dac43ff68fc50 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -8,7 +8,6 @@ #define pr_fmt(fmt) "reboot: " fmt #include -#include #include #include #include @@ -16,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -28,7 +26,8 @@ */ static int C_A_D = 1; -struct pid __rcu *cad_pid; +struct pid *cad_pid; +EXPORT_SYMBOL(cad_pid); #if defined(CONFIG_ARM) #define DEFAULT_REBOOT_MODE = REBOOT_HARD @@ -52,6 +51,8 @@ int reboot_default = 1; int reboot_cpu; enum reboot_type reboot_type = BOOT_ACPI; int reboot_force; +static enum psc_reason psc_last_reason = PSCR_UNKNOWN; +static enum psc_reason psc_first_reason = PSCR_UNKNOWN; struct sys_off_handler { struct notifier_block nb; @@ -96,14 +97,6 @@ void emergency_restart(void) { kmsg_dump(KMSG_DUMP_EMERG); system_state = SYSTEM_RESTART; - - /* - * NBCON kthreads won't be flushed and stopped properly in - * the emergency restart. Move them to the atomic mode. - */ - nbcon_cpu_emergency_enter(); - printk_trigger_flush(); - machine_emergency_restart(); } EXPORT_SYMBOL_GPL(emergency_restart); @@ -1021,10 +1014,153 @@ static void hw_failure_emergency_schedule(enum hw_protection_action action, msecs_to_jiffies(action_delay_ms)); } +/** + * get_psc_reason - Retrieve the last recorded power state change reason. + * + * This function returns the most recent power state change reason stored + * in `psc_last_reason`. The value is set using `set_psc_reason()` when a + * shutdown, reboot, or kexec event occurs. + * + * The reason can be used for system diagnostics, post-mortem analysis, or + * debugging unexpected power state changes. Bootloaders or user-space tools + * may retrieve this value to determine why the system last transitioned to + * a new power state. + * + * Return: A value from `enum psc_reason`, indicating the last known power + * state change reason. + */ +enum psc_reason get_psc_reason(void) +{ + return READ_ONCE(psc_last_reason); +} +EXPORT_SYMBOL_GPL(get_psc_reason); + +/** + * get_psc_first_reason - Retrieve the first power state change reason. + * + * Returns the first meaningful (non-PSCR_UNKNOWN) reason recorded during this + * boot, i.e. the root cause, as opposed to get_psc_reason() which returns the + * most recent one. A later event (a watchdog pretimeout, a kernel panic, ...) + * updates the last reason but leaves this one untouched, so a recorder using + * the "first" record policy can preserve the original cause. + * + * Return: A value from `enum psc_reason`. + */ +enum psc_reason get_psc_first_reason(void) +{ + return READ_ONCE(psc_first_reason); +} +EXPORT_SYMBOL_GPL(get_psc_first_reason); + +/** + * set_psc_reason - Set the reason for the last power state change. + * + * @reason: A value from `enum psc_reason` indicating the cause of the power + * state change. + * + * This function records the reason for a shutdown, reboot, or kexec event + * by storing it in `psc_last_reason`. It ensures that the value remains + * consistent within the running system, allowing retrieval via + * `get_psc_reason()` for diagnostics, logging, or post-mortem analysis. + * + * Persistence Consideration: + * - This function **does not persist** the recorded reason across power cycles. + * - After a system reset or complete power loss, the recorded reason is lost. + * - To store power state change reasons persistently, additional tools such as + * the Power State Change Reason Recorder (PSCRR) framework should be used. + */ +void set_psc_reason(enum psc_reason reason) +{ + WRITE_ONCE(psc_last_reason, reason); + + /* + * Latch the first meaningful reason of this boot as the root cause, so + * that a later event overwriting the last reason does not hide it from + * a recorder using the "first" record policy. + */ + if (reason != PSCR_UNKNOWN && + READ_ONCE(psc_first_reason) == PSCR_UNKNOWN) + WRITE_ONCE(psc_first_reason, reason); +} +EXPORT_SYMBOL_GPL(set_psc_reason); + +/** + * struct psc_reason_desc - Descriptor for a power state change reason. + * @token: Stable, parsable identifier without spaces (e.g. "over-temperature"). + * Suitable for use in sysfs values and as a user/kernel contract. + * @label: Human-readable description (e.g. "over temperature"), for logs. + */ +struct psc_reason_desc { + const char *token; + const char *label; +}; + +static const struct psc_reason_desc psc_reason_descs[] = { + [PSCR_UNKNOWN] = { "unknown", POWER_ON_REASON_UNKNOWN }, + [PSCR_UNDER_VOLTAGE] = { "under-voltage", POWER_ON_REASON_BROWN_OUT }, + [PSCR_OVER_CURRENT] = { "over-current", POWER_ON_REASON_OVER_CURRENT }, + [PSCR_REGULATOR_FAILURE] = { "regulator-failure", POWER_ON_REASON_REGULATOR_FAILURE }, + [PSCR_OVER_TEMPERATURE] = { "over-temperature", POWER_ON_REASON_OVER_TEMPERATURE }, + [PSCR_EC_PANIC] = { "ec-panic", POWER_ON_REASON_EC_PANIC }, +}; + +/** + * psc_reason_to_str - Human-readable label for a power state change reason. + * @reason: The `psc_reason` value to convert. + * + * Return: The label string, or "Invalid" if @reason is out of range. For a + * stable, parsable form use psc_reason_to_token() instead. + */ +const char *psc_reason_to_str(enum psc_reason reason) +{ + if (reason < 0 || reason >= PSCR_REASON_COUNT) + return "Invalid"; + return psc_reason_descs[reason].label; +} +EXPORT_SYMBOL_GPL(psc_reason_to_str); + +/** + * psc_reason_to_token - Stable, parsable token for a power state change reason. + * @reason: The `psc_reason` value to convert. + * + * Return: The token string (no spaces), or "invalid" if @reason is out of + * range. Round-trips with psc_reason_from_token(). + */ +const char *psc_reason_to_token(enum psc_reason reason) +{ + if (reason < 0 || reason >= PSCR_REASON_COUNT) + return "invalid"; + return psc_reason_descs[reason].token; +} +EXPORT_SYMBOL_GPL(psc_reason_to_token); + +/** + * psc_reason_from_token - Parse a reason token into a `psc_reason` value. + * @token: A token as returned by psc_reason_to_token(). A trailing newline is + * tolerated. + * @reason: Output; set on success. + * + * Return: 0 on success or -EINVAL if @token matches no known reason. + */ +int psc_reason_from_token(const char *token, enum psc_reason *reason) +{ + int i; + + for (i = 0; i < PSCR_REASON_COUNT; i++) { + if (sysfs_streq(token, psc_reason_descs[i].token)) { + *reason = i; + return 0; + } + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(psc_reason_from_token); + /** * __hw_protection_trigger - Trigger an emergency system shutdown or reboot * - * @reason: Reason of emergency shutdown or reboot to be printed. + * @reason: Reason of emergency shutdown or reboot. * @ms_until_forced: Time to wait for orderly shutdown or reboot before * triggering it. Negative value disables the forced * shutdown or reboot. @@ -1036,7 +1172,7 @@ static void hw_failure_emergency_schedule(enum hw_protection_action action, * pending even if the previous request has given a large timeout for forced * shutdown/reboot. */ -void __hw_protection_trigger(const char *reason, int ms_until_forced, +void __hw_protection_trigger(enum psc_reason reason, int ms_until_forced, enum hw_protection_action action) { static atomic_t allow_proceed = ATOMIC_INIT(1); @@ -1044,8 +1180,11 @@ void __hw_protection_trigger(const char *reason, int ms_until_forced, if (action == HWPROT_ACT_DEFAULT) action = hw_protection_action; - pr_emerg("HARDWARE PROTECTION %s (%s)\n", - hw_protection_action_str(action), reason); + set_psc_reason(reason); + + pr_emerg("HARDWARE PROTECTION %s: %i (%s)\n", + hw_protection_action_str(action), reason, + psc_reason_to_str(reason)); /* Shutdown should be initiated only once. */ if (!atomic_dec_and_test(&allow_proceed)) @@ -1377,39 +1516,6 @@ static struct attribute *reboot_attrs[] = { }; #ifdef CONFIG_SYSCTL -static int proc_do_cad_pid(const struct ctl_table *table, int write, void *buffer, - size_t *lenp, loff_t *ppos) -{ - struct ctl_table tmp_table = *table; - struct pid *new_pid; - struct pid *old_pid; - pid_t tmp_pid; - int r; - - rcu_read_lock(); - tmp_pid = pid_vnr(rcu_dereference(cad_pid)); - rcu_read_unlock(); - - tmp_table.data = &tmp_pid; - - r = proc_dointvec(&tmp_table, write, buffer, lenp, ppos); - if (r || !write) - return r; - - new_pid = find_get_pid(tmp_pid); - if (!new_pid) - return -ESRCH; - - old_pid = unrcu_pointer(xchg(&cad_pid, RCU_INITIALIZER(new_pid))); - /* - * Wait for cad_pid readers before put_pid(). We cannot use - * call_rcu() here because free_pid() already owns pid->rcu. - */ - synchronize_rcu(); - put_pid(old_pid); - return 0; -} - static const struct ctl_table kern_reboot_table[] = { { .procname = "poweroff_cmd", @@ -1425,12 +1531,6 @@ static const struct ctl_table kern_reboot_table[] = { .mode = 0644, .proc_handler = proc_dointvec, }, - { - .procname = "cad_pid", - .maxlen = sizeof(int), - .mode = 0600, - .proc_handler = proc_do_cad_pid, - }, }; static void __init kernel_reboot_sysctls_init(void) From 6468a888c5efa06403f9722e31282adc0f729f05 Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Thu, 24 Sep 2026 12:38:45 +0530 Subject: [PATCH 0428/1133] FROMLIST: reboot: extend psc_reason with power-on and reset causes psc_reason covered only the protection reasons. Extend it to mirror the full POWER_ON_REASON_* vocabulary - power-on, watchdog, software, external, RTC, reset button, CPU clock and crystal failures - so a provider can report why the system last powered on, not only why it was shut down. New values are appended to keep the existing numeric ABI. Co-developed-by: Oleksij Rempel Signed-off-by: Oleksij Rempel Signed-off-by: Faruque Ansari Reviewed-by: Matti Vaittinen Link: https://lore.kernel.org/r/20260924-pscrr-framework-v15-4-7af87107e0d3@oss.qualcomm.com --- include/linux/reboot.h | 28 ++++++++++++++++++++++++++++ kernel/reboot.c | 12 ++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/linux/reboot.h b/include/linux/reboot.h index 4c5327dd76456..13f004ad1066a 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h @@ -225,9 +225,28 @@ extern void orderly_reboot(void); * management errors, or an unrecoverable hardware fault requiring * immediate response. * + * @PSCR_POWER_ON: Regular cold power-on (e.g. via a PMIC power-on request). + * + * @PSCR_WATCHDOG: Reset caused by a watchdog timeout. + * + * @PSCR_SOFTWARE: Software-initiated reset or reboot. + * + * @PSCR_EXTERNAL: Reset asserted through an external pin or reset input. + * + * @PSCR_RTC: Wake-up or power-on triggered by the RTC. + * + * @PSCR_RESET_BUTTON: Reset triggered by a user reset button. + * + * @PSCR_CPU_CLK_FAIL: Reset caused by a CPU clock failure. + * + * @PSCR_XTAL_FAIL: Reset caused by a crystal oscillator failure. + * * @PSCR_REASON_COUNT: Number of defined power state change reasons. This * value is useful for range checking and potential future extensions * while maintaining compatibility. + * + * The reasons mirror the POWER_ON_REASON_* strings in + * ; keep the two in sync when extending. */ enum psc_reason { PSCR_UNKNOWN, @@ -236,6 +255,15 @@ enum psc_reason { PSCR_REGULATOR_FAILURE, PSCR_OVER_TEMPERATURE, PSCR_EC_PANIC, + /* Append new reasons here; the numeric order is ABI. */ + PSCR_POWER_ON, + PSCR_WATCHDOG, + PSCR_SOFTWARE, + PSCR_EXTERNAL, + PSCR_RTC, + PSCR_RESET_BUTTON, + PSCR_CPU_CLK_FAIL, + PSCR_XTAL_FAIL, /* Number of reasons */ PSCR_REASON_COUNT, diff --git a/kernel/reboot.c b/kernel/reboot.c index dac43ff68fc50..d325f61b2c890 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -7,7 +7,9 @@ #define pr_fmt(fmt) "reboot: " fmt +#include #include +#include #include #include #include @@ -1102,7 +1104,17 @@ static const struct psc_reason_desc psc_reason_descs[] = { [PSCR_REGULATOR_FAILURE] = { "regulator-failure", POWER_ON_REASON_REGULATOR_FAILURE }, [PSCR_OVER_TEMPERATURE] = { "over-temperature", POWER_ON_REASON_OVER_TEMPERATURE }, [PSCR_EC_PANIC] = { "ec-panic", POWER_ON_REASON_EC_PANIC }, + [PSCR_POWER_ON] = { "power-on", POWER_ON_REASON_REGULAR }, + [PSCR_WATCHDOG] = { "watchdog", POWER_ON_REASON_WATCHDOG }, + [PSCR_SOFTWARE] = { "software", POWER_ON_REASON_SOFTWARE }, + [PSCR_EXTERNAL] = { "external", POWER_ON_REASON_EXTERNAL }, + [PSCR_RTC] = { "rtc", POWER_ON_REASON_RTC }, + [PSCR_RESET_BUTTON] = { "reset-button", POWER_ON_REASON_RST_BTN }, + [PSCR_CPU_CLK_FAIL] = { "cpu-clock-failure", POWER_ON_REASON_CPU_CLK_FAIL }, + [PSCR_XTAL_FAIL] = { "crystal-failure", POWER_ON_REASON_XTAL_FAIL }, }; +static_assert(ARRAY_SIZE(psc_reason_descs) == PSCR_REASON_COUNT, + "psc_reason_descs[] must have an entry for every psc_reason"); /** * psc_reason_to_str - Human-readable label for a power state change reason. From 3281b7bc9dd80c6636877432a15eff19cdd6151b Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Thu, 24 Sep 2026 12:38:46 +0530 Subject: [PATCH 0429/1133] FROMLIST: power: reset: Introduce PSCR Recording Framework for Non-Volatile Storage Introduce the Power State Change Reasons Recording (PSCRR) framework: a generic mechanism to record why the last power state change (shutdown or reboot) happened - under-voltage, thermal, watchdog, software-triggered, etc. - so a postmortem reason survives a reboot or an abrupt power loss. PSCRR is built around providers. A provider is either a hardware reason source (a PMIC, SoC reset controller or watchdog exposing a reset cause) or a recorder that persists the reason across a power cycle (an NVMEM or RTC scratch cell). Each provider gets a directory under /sys/kernel/pscrr/providerN/ exposing its name, backing device, the set of observed reasons (as tokens), its capabilities, the reasons it supports and - for recorders - a record policy. The reason set is deliberately not collapsed to a single winning cause, since resets are often multi-causal. Reasons are the numeric enum psc_reason values from reboot.h, shared with the POWER_ON_REASON_* vocabulary, so they store compactly in small battery-backed cells. The current reason (get/set_psc_reason(), set by the thermal/regulator/hw_protection paths) is written to every recorder from the reboot notifier. Co-developed-by: Oleksij Rempel Signed-off-by: Oleksij Rempel Reported-by: Francesco Valla Closes: https://lore.kernel.org/all/178749889134.204450.5740187753642158305.b4-review@b4/ Signed-off-by: Faruque Ansari Reviewed-by: Matti Vaittinen Link: https://lore.kernel.org/r/20260924-pscrr-framework-v15-5-7af87107e0d3@oss.qualcomm.com --- MAINTAINERS | 11 + drivers/power/reset/Kconfig | 2 + drivers/power/reset/Makefile | 1 + drivers/power/reset/pscrr/Kconfig | 33 ++ drivers/power/reset/pscrr/Makefile | 2 + drivers/power/reset/pscrr/pscrr.c | 640 +++++++++++++++++++++++++++++ include/linux/pscrr.h | 107 +++++ 7 files changed, 796 insertions(+) create mode 100644 drivers/power/reset/pscrr/Kconfig create mode 100644 drivers/power/reset/pscrr/Makefile create mode 100644 drivers/power/reset/pscrr/pscrr.c create mode 100644 include/linux/pscrr.h diff --git a/MAINTAINERS b/MAINTAINERS index 93abbb315065d..bbe685e9349ae 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22259,6 +22259,17 @@ F: Documentation/devicetree/bindings/connector/pcie-m2-e-connector.yaml F: Documentation/devicetree/bindings/connector/pcie-m2-m-connector.yaml F: drivers/power/sequencing/pwrseq-pcie-m2.c +POWER STATE CHANGE REASON RECORDING (PSCRR) +M: Oleksij Rempel +M: Faruque Ansari +R: Pengutronix Kernel Team +L: linux-pm@vger.kernel.org +S: Maintained +F: Documentation/ABI/testing/sysfs-kernel-pscrr +F: drivers/power/reset/pscrr/ +F: include/linux/pscrr.h +F: tools/testing/selftests/pscrr/ + POWER STATE COORDINATION INTERFACE (PSCI) M: Mark Rutland M: Lorenzo Pieralisi diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index bce996bbef28f..f24ff89dd94e6 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -377,3 +377,5 @@ config POWER_RESET_QEMU_VIRT_CTRL provides this controller, such as the m68k virt machine. endif + +source "drivers/power/reset/pscrr/Kconfig" diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index e31cab4ba78ef..c73dc747e36c1 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_POWER_RESET_KEYSTONE) += keystone-reset.o obj-$(CONFIG_POWER_RESET_SYSCON) += syscon-reboot.o obj-$(CONFIG_POWER_RESET_SYSCON_POWEROFF) += syscon-poweroff.o obj-$(CONFIG_POWER_RESET_RMOBILE) += rmobile-reset.o +obj-$(CONFIG_PSCRR) += pscrr/ obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o diff --git a/drivers/power/reset/pscrr/Kconfig b/drivers/power/reset/pscrr/Kconfig new file mode 100644 index 0000000000000..72de82731b531 --- /dev/null +++ b/drivers/power/reset/pscrr/Kconfig @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-only +menuconfig PSCRR + bool "Power State Change Reasons Recording (PSCRR) Framework" + depends on POWER_RESET + help + Enables the Power State Change Reasons Recording (PSCRR) framework. + + PSCRR records why the system last shut down or rebooted into + non-volatile storage, so the reason survives the reset and can be + read by the bootloader or early user space on the next boot. Reasons + come from software (thermal or regulator hardware-protection events, + a watchdog pretimeout, a kernel panic, a controlled reboot) or from + hardware reset-cause registers (PMIC, SoC reset controller, watchdog). + + It helps whenever the real cause would otherwise be lost or ambiguous + on the next boot, for example: + + - the reset is abrupt and block storage (eMMC/NAND) may not survive + it; on systems that can detect the event in time - such as an + imminent power loss with a short backup-capacitor window - the + reason can still be persisted first; + + - the hardware does not preserve the cause and the boot looks like a + plain power-on reset, e.g. a watchdog pretimeout that escalates + into a panic reboot would otherwise be indistinguishable from a + POR. + + The framework is extensible and exposes software-defined and + hardware-reported reasons through one interface. Sudden power cuts, + CPU freezes or other uncontrolled resets may still go unrecorded + unless hardware provides the reset cause. + + If unsure, say N. diff --git a/drivers/power/reset/pscrr/Makefile b/drivers/power/reset/pscrr/Makefile new file mode 100644 index 0000000000000..e5530a8589713 --- /dev/null +++ b/drivers/power/reset/pscrr/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_PSCRR) += pscrr.o diff --git a/drivers/power/reset/pscrr/pscrr.c b/drivers/power/reset/pscrr/pscrr.c new file mode 100644 index 0000000000000..f7c1478a50c4b --- /dev/null +++ b/drivers/power/reset/pscrr/pscrr.c @@ -0,0 +1,640 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * pscrr.c - Core Power State Change Reason Recording + * + * PSCRR records why the last power state change (shutdown/reboot) happened. + * Reasons come from providers: hardware reset-cause registers (PMIC, SoC reset + * controller, watchdog), persistent recorders (NVMEM/RTC scratch), the + * bootloader's device-tree /chosen/reset-source (a built-in provider here), or + * test stubs. Each provider gets a directory under /sys/kernel/pscrr/ and reports + * the full set of reasons it observed - the picture is deliberately not + * collapsed to a single "winning" cause, since resets are often multi-causal. + * + * Sysfs (per provider, under /sys/kernel/pscrr/providerN/): + * name ro human label of the provider + * device symlink to the backing device (if any) + * reason the provider's reason set, as tokens; writable (record + * one reason) when the provider supports it + * caps ro non-default capabilities ("writable"); empty for a + * read-only, single-slot provider + * supported_reasons ro reasons this provider can report or record + * record_policy recorders only: keep the "first" or "last" reason + * recorded in a power cycle + * + * The kernel keeps the first (root cause) and last power-state-change reason + * (get_psc_first_reason()/get_psc_reason(), set by the thermal, regulator and + * hw_protection paths). At reboot each recorder is given the first or the last + * reason according to its record policy. + * + * Copyright (C) 2025 Pengutronix, Oleksij Rempel + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#define pr_fmt(fmt) "PSCRR: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct kobject *pscrr_root; +static DEFINE_MUTEX(pscrr_lock); +static LIST_HEAD(pscrr_dirs); +static DEFINE_IDA(pscrr_ida); + +/* + * Record policy: when several reasons are recorded in one power cycle, keep the + * first (root cause) or overwrite with the last. Global, tunable via sysfs. + */ +enum pscrr_record_policy { + PSCRR_RECORD_FIRST, + PSCRR_RECORD_LAST, +}; + +/* + * Per-provider sysfs directory. Core-owned and self-freeing on kobject_put(), + * so its lifetime is decoupled from the caller-owned struct pscrr_provider. + * + * The sysfs show/store callbacks below dereference ->provider without + * pscrr_lock: kobject_del() in pscrr_provider_unregister() blocks until + * every in-flight callback on this kobject returns before the directory + * (and thus ->provider) can be torn down, so a callback that is running + * always sees a live provider. + */ +struct pscrr_provider_dir { + struct kobject kobj; + struct pscrr_provider *provider; + struct list_head node; + int id; + enum pscrr_record_policy policy; /* single-slot recorder: keep first/last */ + bool recorded; /* a reason was recorded this power cycle */ +}; + +static inline struct pscrr_provider_dir *to_pscrr_dir(struct kobject *kobj) +{ + return container_of(kobj, struct pscrr_provider_dir, kobj); +} + +/*----------------------------------------------------------------------*/ +/* Per-provider attributes */ +/*----------------------------------------------------------------------*/ + +static ssize_t name_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", to_pscrr_dir(kobj)->provider->name); +} + +static struct kobj_attribute pscrr_name_attr = __ATTR_RO(name); + +static int pscrr_parse_reason(const char *buf, enum psc_reason *out) +{ + unsigned int val; + + /* Accept either a decimal index or a reason token. */ + if (!kstrtouint(buf, 0, &val)) { + if (val >= PSCR_REASON_COUNT) + return -ERANGE; + *out = val; + return 0; + } + + return psc_reason_from_token(buf, out); +} + +static ssize_t reason_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + struct pscrr_provider *p = to_pscrr_dir(kobj)->provider; + DECLARE_BITMAP(reasons, PSCR_REASON_COUNT); + ssize_t len = 0; + int bit, ret; + + bitmap_zero(reasons, PSCR_REASON_COUNT); + + ret = p->ops->read_reasons(p, reasons); + if (ret) + return ret; + + for_each_set_bit(bit, reasons, PSCR_REASON_COUNT) + len += sysfs_emit_at(buf, len, "%s%s", len ? " " : "", + psc_reason_to_token(bit)); + len += sysfs_emit_at(buf, len, "\n"); + + return len; +} + +/* Record @reason into @dir honouring the global record policy. */ +static int pscrr_do_record(struct pscrr_provider_dir *dir, enum psc_reason reason) +{ + struct pscrr_provider *p = dir->provider; + int ret; + + if (!p->ops->write_reason) + return -EOPNOTSUPP; + + /* + * PSCR_UNKNOWN clears the slot and releases the latch, regardless of + * policy, so a reason recorded afterwards is taken again. + */ + if (reason == PSCR_UNKNOWN) { + ret = p->ops->write_reason(p, reason); + if (ret) + return ret; + + dir->recorded = false; + return 0; + } + + /* Reject reasons the provider does not advertise (NULL == all). */ + if (p->supported_reasons && !test_bit(reason, p->supported_reasons)) + return -EINVAL; + + /* "first" policy: keep the first reason recorded this power cycle. */ + if (dir->policy == PSCRR_RECORD_FIRST && dir->recorded) + return 0; + + ret = p->ops->write_reason(p, reason); + if (ret) + return ret; + + dir->recorded = true; + + return 0; +} + +static ssize_t reason_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct pscrr_provider_dir *dir = to_pscrr_dir(kobj); + enum psc_reason reason; + int ret; + + if (!dir->provider->ops->write_reason) + return -EOPNOTSUPP; + + ret = pscrr_parse_reason(buf, &reason); + if (ret) + return ret; + + /* Serialise the record state against concurrent stores and the notifier. */ + scoped_guard(mutex, &pscrr_lock) + ret = pscrr_do_record(dir, reason); + if (ret) + return ret; + + return count; +} + +static struct kobj_attribute pscrr_reason_attr = + __ATTR(reason, 0644, reason_show, reason_store); + +static ssize_t caps_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + struct pscrr_provider *p = to_pscrr_dir(kobj)->provider; + ssize_t len = 0; + + /* Readable and single-slot are the defaults and not listed. */ + if (p->ops->write_reason) + len += sysfs_emit_at(buf, len, "writable"); + + return len + sysfs_emit_at(buf, len, "\n"); +} + +static struct kobj_attribute pscrr_caps_attr = __ATTR_RO(caps); + +static ssize_t supported_reasons_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct pscrr_provider *p = to_pscrr_dir(kobj)->provider; + const unsigned long *sup = p->supported_reasons; + ssize_t len = 0; + int i; + + for (i = 0; i < PSCR_REASON_COUNT; i++) { + if (sup && !test_bit(i, sup)) /* NULL means all */ + continue; + len += sysfs_emit_at(buf, len, "%s%s", len ? " " : "", + psc_reason_to_token(i)); + } + + return len + sysfs_emit_at(buf, len, "\n"); +} + +static struct kobj_attribute pscrr_supported_attr = + __ATTR(supported_reasons, 0444, supported_reasons_show, NULL); + +static ssize_t record_policy_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct pscrr_provider_dir *dir = to_pscrr_dir(kobj); + + return sysfs_emit(buf, "%s\n", + READ_ONCE(dir->policy) == PSCRR_RECORD_FIRST ? + "first" : "last"); +} + +static ssize_t record_policy_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct pscrr_provider_dir *dir = to_pscrr_dir(kobj); + + guard(mutex)(&pscrr_lock); + + if (sysfs_streq(buf, "first")) + WRITE_ONCE(dir->policy, PSCRR_RECORD_FIRST); + else if (sysfs_streq(buf, "last")) + WRITE_ONCE(dir->policy, PSCRR_RECORD_LAST); + else + return -EINVAL; + + return count; +} + +static struct kobj_attribute pscrr_record_policy_attr = + __ATTR(record_policy, 0644, record_policy_show, record_policy_store); + +static struct attribute *pscrr_dir_attrs[] = { + &pscrr_name_attr.attr, + &pscrr_reason_attr.attr, + &pscrr_caps_attr.attr, + &pscrr_supported_attr.attr, + &pscrr_record_policy_attr.attr, + NULL, +}; + +static umode_t pscrr_dir_is_visible(struct kobject *kobj, struct attribute *attr, + int n) +{ + struct pscrr_provider *p = to_pscrr_dir(kobj)->provider; + + /* A provider without write_reason() exposes reason read-only. */ + if (attr == &pscrr_reason_attr.attr && !p->ops->write_reason) + return 0444; + + /* record_policy only applies to a (single-slot) recorder. */ + if (attr == &pscrr_record_policy_attr.attr && !p->ops->write_reason) + return 0; + + return attr->mode; +} + +static const struct attribute_group pscrr_dir_group = { + .attrs = pscrr_dir_attrs, + .is_visible = pscrr_dir_is_visible, +}; + +static const struct attribute_group *pscrr_dir_groups[] = { + &pscrr_dir_group, + NULL, +}; + +static void pscrr_dir_release(struct kobject *kobj) +{ + kfree(to_pscrr_dir(kobj)); +} + +static const struct kobj_type pscrr_dir_ktype = { + .sysfs_ops = &kobj_sysfs_ops, + .release = pscrr_dir_release, + .default_groups = pscrr_dir_groups, +}; + +/*----------------------------------------------------------------------*/ +/* Provider registration */ +/*----------------------------------------------------------------------*/ + +/** + * pscrr_provider_register - register a power state change reason provider + * @p: caller-owned provider description + * + * Creates /sys/kernel/pscrr/providerN/ with "name" and "reason" attributes + * and, when @p->dev is set, a "device" symlink. @p->reason is writable when + * @p provides write_reason(). The provider must outlive the matching + * pscrr_provider_unregister() call. + * + * Return: 0 on success or a negative errno. + */ +int pscrr_provider_register(struct pscrr_provider *p) +{ + struct pscrr_provider_dir *dir; + int ret; + + if (!p || !p->name || !p->ops || !p->ops->read_reasons) + return -EINVAL; + + /* + * pscrr_root is set once at core init and cleared at core exit; + * neither transition is serialised against this function by + * pscrr_lock, so check it up front rather than under the lock below. + */ + if (!pscrr_root) + return -ENODEV; + + dir = kzalloc_obj(*dir); + if (!dir) + return -ENOMEM; + + dir->provider = p; + dir->policy = PSCRR_RECORD_FIRST; + + /* ida_alloc() and the kobject/sysfs calls below are individually thread-safe. */ + dir->id = ida_alloc(&pscrr_ida, GFP_KERNEL); + if (dir->id < 0) { + ret = dir->id; + kfree(dir); + return ret; + } + + ret = kobject_init_and_add(&dir->kobj, &pscrr_dir_ktype, pscrr_root, + "provider%d", dir->id); + if (ret) { + /* + * kobject_init_and_add() failed: per its contract only + * kobject_put() may follow, no kobject_del(). + */ + ida_free(&pscrr_ida, dir->id); + kobject_put(&dir->kobj); + return ret; + } + + if (p->dev) { + ret = sysfs_create_link(&dir->kobj, &p->dev->kobj, "device"); + if (ret) + goto err_del; + } + + /* pscrr_lock only serialises pscrr_dirs against concurrent (un)registration. */ + scoped_guard(mutex, &pscrr_lock) + list_add_tail(&dir->node, &pscrr_dirs); + + return 0; + +err_del: + kobject_del(&dir->kobj); + ida_free(&pscrr_ida, dir->id); + kobject_put(&dir->kobj); + return ret; +} +EXPORT_SYMBOL_GPL(pscrr_provider_register); + +/** + * pscrr_provider_unregister - remove a previously registered provider + * @p: the provider passed to pscrr_provider_register() + */ +void pscrr_provider_unregister(struct pscrr_provider *p) +{ + struct pscrr_provider_dir *dir = NULL, *iter; + + scoped_guard(mutex, &pscrr_lock) { + list_for_each_entry(iter, &pscrr_dirs, node) { + if (iter->provider == p) { + dir = iter; + list_del(&dir->node); + break; + } + } + } + + if (!dir) + return; + + /* + * Tear the sysfs directory down outside pscrr_lock: kobject_del() + * drains in-flight reason/record_policy stores, which take pscrr_lock, + * so holding it here would deadlock. Release the id only once the + * directory is gone, so a concurrent register cannot reuse it and + * collide on the providerN name. + */ + if (p->dev) + sysfs_remove_link(&dir->kobj, "device"); + kobject_del(&dir->kobj); + ida_free(&pscrr_ida, dir->id); + kobject_put(&dir->kobj); +} +EXPORT_SYMBOL_GPL(pscrr_provider_unregister); + +static void pscrr_provider_devm_release(void *p) +{ + pscrr_provider_unregister(p); +} + +/** + * devm_pscrr_provider_register - device-managed reason provider registration + * @dev: device the provider belongs to; also backs the "device" symlink + * @name: human-readable provider label + * @ops: provider callback table; read_reasons() is required, write_reason() is + * optional and makes the provider a recorder + * @supported_reasons: bitmap of the reasons the provider supports, or NULL + * for all; set before the provider is exposed in sysfs + * @priv: provider private data, handed back to the @ops callbacks + * + * Allocates and registers a struct pscrr_provider and schedules its + * unregistration when @dev is unbound, so the caller keeps no reference to it. + * + * Return: the registered provider on success or an ERR_PTR() on failure. When + * CONFIG_PSCRR is disabled the call resolves to a stub returning NULL, so + * callers need no IS_ENABLED() guard. + */ +struct pscrr_provider * +devm_pscrr_provider_register(struct device *dev, const char *name, + const struct pscrr_provider_ops *ops, + const unsigned long *supported_reasons, void *priv) +{ + struct pscrr_provider *p; + int ret; + + p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); + if (!p) + return ERR_PTR(-ENOMEM); + + p->name = name; + p->dev = dev; + p->ops = ops; + p->supported_reasons = supported_reasons; + p->priv = priv; + + ret = pscrr_provider_register(p); + if (ret) + return ERR_PTR(ret); + + ret = devm_add_action_or_reset(dev, pscrr_provider_devm_release, p); + if (ret) + return ERR_PTR(ret); + + return p; +} +EXPORT_SYMBOL_GPL(devm_pscrr_provider_register); + +/*----------------------------------------------------------------------*/ +/* Record path: reboot notifier writes the current reason to recorders */ +/*----------------------------------------------------------------------*/ + +/* + * Record the current power-state-change reason into every provider, giving + * each the first (root cause) or the last reason according to its record + * policy. The kernel keeps both, so "first" is meaningful even when later + * events overwrite the last reason. The caller holds pscrr_lock, or runs where + * the provider list is stable (panic). + */ +static void pscrr_record_current(void) +{ + enum psc_reason first = get_psc_first_reason(); + enum psc_reason last = get_psc_reason(); + struct pscrr_provider_dir *dir; + + list_for_each_entry(dir, &pscrr_dirs, node) + pscrr_do_record(dir, dir->policy == PSCRR_RECORD_FIRST ? + first : last); +} + +static int pscrr_reboot_notifier(struct notifier_block *nb, + unsigned long action, void *unused) +{ + guard(mutex)(&pscrr_lock); + + /* + * A reboot, halt or power-off that reaches here with no more specific + * reason is software-initiated by definition. Record it as such rather + * than leaving it unattributed; a real cause set earlier (thermal, + * under-voltage, ...) is already latched and left untouched. + */ + if (get_psc_reason() == PSCR_UNKNOWN) + set_psc_reason(PSCR_SOFTWARE); + + pscrr_record_current(); + + return NOTIFY_DONE; +} + +static struct notifier_block pscrr_reboot_nb = { + .notifier_call = pscrr_reboot_notifier, +}; + +/*----------------------------------------------------------------------*/ +/* Built-in provider: device-tree /chosen/reset-source */ +/*----------------------------------------------------------------------*/ + +/* + * Bootloaders such as barebox record the SoC reset cause in the standard + * device-tree /chosen/reset-source property. When it is present, surface it as + * a read-only, device-less provider so the bootloader's view of the last reset + * shows up next to any hardware or software providers - the framework just + * reads the property already there, with no dedicated node or new binding. + */ +static const struct { + const char *name; + enum psc_reason reason; +} pscrr_reset_source_map[] = { + { "POR", PSCR_POWER_ON }, + { "RST", PSCR_SOFTWARE }, + { "WDG", PSCR_WATCHDOG }, + { "THERM", PSCR_OVER_TEMPERATURE }, + { "EXT", PSCR_EXTERNAL }, + { "BROWNOUT", PSCR_UNDER_VOLTAGE }, +}; + +static const unsigned long +pscrr_reset_source_supported[BITS_TO_LONGS(PSCR_REASON_COUNT)] = { + BIT(PSCR_UNDER_VOLTAGE) | BIT(PSCR_OVER_TEMPERATURE) | + BIT(PSCR_POWER_ON) | BIT(PSCR_WATCHDOG) | BIT(PSCR_SOFTWARE) | + BIT(PSCR_EXTERNAL), +}; + +/* Parsed once at init; read back by the provider's read_reasons(). */ +static enum psc_reason pscrr_reset_source_reason = PSCR_UNKNOWN; + +static int pscrr_reset_source_read(struct pscrr_provider *p, + unsigned long *reasons) +{ + set_bit(pscrr_reset_source_reason, reasons); + + return 0; +} + +static const struct pscrr_provider_ops pscrr_reset_source_ops = { + .read_reasons = pscrr_reset_source_read, +}; + +static struct pscrr_provider pscrr_reset_source_provider = { + .name = "reset-source", + .ops = &pscrr_reset_source_ops, + .supported_reasons = pscrr_reset_source_supported, +}; + +static void __init pscrr_register_reset_source(void) +{ + const char *name; + int i, ret; + + if (!IS_ENABLED(CONFIG_OF) || !of_chosen) + return; + + if (of_property_read_string(of_chosen, "reset-source", &name)) + return; + + for (i = 0; i < ARRAY_SIZE(pscrr_reset_source_map); i++) + if (!strcmp(name, pscrr_reset_source_map[i].name)) { + pscrr_reset_source_reason = pscrr_reset_source_map[i].reason; + break; + } + + ret = pscrr_provider_register(&pscrr_reset_source_provider); + if (ret) + pr_warn("failed to register the reset-source provider: %d\n", ret); +} + +/*----------------------------------------------------------------------*/ +/* Module init/exit */ +/*----------------------------------------------------------------------*/ + +static int __init pscrr_core_init(void) +{ + int ret; + + pscrr_root = kobject_create_and_add("pscrr", kernel_kobj); + if (!pscrr_root) + return -ENOMEM; + + ret = register_reboot_notifier(&pscrr_reboot_nb); + if (ret) { + kobject_put(pscrr_root); + pscrr_root = NULL; + return ret; + } + + pscrr_register_reset_source(); + + return 0; +} + +static void __exit pscrr_core_exit(void) +{ + pscrr_provider_unregister(&pscrr_reset_source_provider); + unregister_reboot_notifier(&pscrr_reboot_nb); + kobject_put(pscrr_root); + pscrr_root = NULL; + ida_destroy(&pscrr_ida); +} + +/* Bring the core up before device drivers probe and register providers. */ +subsys_initcall(pscrr_core_init); +module_exit(pscrr_core_exit); + +MODULE_AUTHOR("Oleksij Rempel "); +MODULE_AUTHOR("Faruque Ansari "); +MODULE_DESCRIPTION("Power State Change Reason Recording (PSCRR) core"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/pscrr.h b/include/linux/pscrr.h new file mode 100644 index 0000000000000..330d6ac191bd2 --- /dev/null +++ b/include/linux/pscrr.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * pscrr.h - Public header for Power State Change Reason Recording (PSCRR). + * + * Copyright (C) 2025 Pengutronix, Oleksij Rempel + */ + +#ifndef __PSCRR_H__ +#define __PSCRR_H__ + +#include + +struct device; +struct pscrr_provider; + +/** + * struct pscrr_provider_ops - Provider callbacks. + * @read_reasons: Fill @reasons with the complete set this source observed. + * @reasons is a bitmap of PSCR_REASON_COUNT bits; set members + * with set_bit(PSCR_x, reasons). Return 0 on success or a + * negative errno. Required. Driver state is reached via p->priv. + * @write_reason: Persist @reason. Called from the reboot notifier for + * recorder-capable providers so the cause survives the power + * cycle. Leave NULL for read-only hardware sources. + * + * A const ops table per provider type; extend it with new callbacks without + * touching the registration signature or existing callers. + */ +struct pscrr_provider_ops { + int (*read_reasons)(struct pscrr_provider *p, unsigned long *reasons); + int (*write_reason)(struct pscrr_provider *p, enum psc_reason reason); +}; + +/** + * struct pscrr_provider - A source (and optionally recorder) of power state + * change reasons. + * + * A provider represents one place the system can learn *why* the last power + * state change happened: a hardware reset-cause register (PMIC, SoC SRC, + * watchdog), a persistent recorder (NVMEM/RTC scratch), or a test stub. Each + * registered provider gets its own directory under /sys/kernel/pscrr/, so the + * full, un-prioritised picture is visible: several providers - and several + * reasons within one provider - can be reported simultaneously. + * + * @name: Human-readable label, exported as the "name" attribute. The + * directory itself is core-indexed (providerN), so this need not + * be unique. Required. + * @dev: Backing device. When set it is exported as the "device" symlink + * in the provider directory, tying the reason to real hardware. + * May be NULL (e.g. for a test provider). + * @ops: Provider callbacks. Required. + * @supported_reasons: Bitmap of the reasons this provider can store or report, + * limited e.g. by the storage size. 0 means all reasons. + * @priv: Provider private data, passed back through the callbacks. + * + * Providers are readable and single-slot by default; only capabilities beyond + * that (currently: writable) are advertised. + */ +struct pscrr_provider { + const char *name; + struct device *dev; + const struct pscrr_provider_ops *ops; + const unsigned long *supported_reasons; + void *priv; +}; + +#if IS_ENABLED(CONFIG_PSCRR) +int pscrr_provider_register(struct pscrr_provider *p); +void pscrr_provider_unregister(struct pscrr_provider *p); + +/** + * devm_pscrr_provider_register - allocate, fill and register a provider + * @dev: device the provider belongs to (also the "device" symlink target) + * @name: provider label + * @ops: provider callbacks + * @supported_reasons: bitmap of supported reasons, or NULL for all + * @priv: driver state passed back through the callbacks + * + * The provider is unregistered automatically on device teardown. + * + * Return: the provider on success, ERR_PTR() on failure, or NULL when PSCRR + * is not built (so the caller need not guard the call). + */ +struct pscrr_provider * +devm_pscrr_provider_register(struct device *dev, const char *name, + const struct pscrr_provider_ops *ops, + const unsigned long *supported_reasons, void *priv); +#else +static inline int pscrr_provider_register(struct pscrr_provider *p) +{ + return -EOPNOTSUPP; +} + +static inline void pscrr_provider_unregister(struct pscrr_provider *p) +{ +} + +static inline struct pscrr_provider * +devm_pscrr_provider_register(struct device *dev, const char *name, + const struct pscrr_provider_ops *ops, + const unsigned long *supported_reasons, void *priv) +{ + return NULL; +} +#endif + +#endif /* __PSCRR_H__ */ From 58806af087f23500576b58c82e5b3bc333b44c59 Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Thu, 24 Sep 2026 12:38:47 +0530 Subject: [PATCH 0430/1133] FROMLIST: Documentation: Add sysfs documentation for PSCRR Document the Power State Change Reasons Recording (PSCRR) sysfs interface under /sys/kernel/pscrr/: the per-provider directories and their name, device, reason, caps, supported_reasons and record_policy attributes, including the stable reason token values. Co-developed-by: Oleksij Rempel Signed-off-by: Oleksij Rempel Reviewed-by: Matti Vaittinen Signed-off-by: Faruque Ansari Link: https://lore.kernel.org/r/20260924-pscrr-framework-v15-6-7af87107e0d3@oss.qualcomm.com --- Documentation/ABI/testing/sysfs-kernel-pscrr | 108 +++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-kernel-pscrr diff --git a/Documentation/ABI/testing/sysfs-kernel-pscrr b/Documentation/ABI/testing/sysfs-kernel-pscrr new file mode 100644 index 0000000000000..63aa411b7362e --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-pscrr @@ -0,0 +1,108 @@ +What: /sys/kernel/pscrr/ +Date: July 2026 +KernelVersion: 7.2 +Contact: Oleksij Rempel +Description: + Root directory of the Power State Change Reason Recording + (PSCRR) framework. It contains one subdirectory per registered + reason provider, named providerN (N is an arbitrary, stable + index assigned at registration). + + A provider is either a hardware reason source (a PMIC, SoC + reset controller or watchdog exposing a reset cause) or a + recorder that persists the current reason across a power cycle + (e.g. an NVMEM or RTC scratch cell). The set of reasons is + deliberately not collapsed to a single "winning" cause, since + resets are often multi-causal. + +What: /sys/kernel/pscrr/providerN/name +Date: July 2026 +KernelVersion: 7.2 +Contact: Oleksij Rempel +Description: + (RO) Human-readable label identifying the provider, e.g. + "pca9450" or "nvmem". + +What: /sys/kernel/pscrr/providerN/device +Date: July 2026 +KernelVersion: 7.2 +Contact: Oleksij Rempel +Description: + Symbolic link to the backing struct device of the provider. + Present only for providers that are bound to a device. + +What: /sys/kernel/pscrr/providerN/reason +Date: July 2026 +KernelVersion: 7.2 +Contact: Oleksij Rempel +Description: + The set of power state change reasons observed by this + provider, as a space-separated list of reason tokens (an + empty line means no reason is recorded). + + The attribute is writable only for providers that can record + a reason; for a pure hardware source it is read-only. A write + records one reason and accepts either a reason token or its + decimal index. The tokens and their stable numeric values are: + + == ================= ============================================ + 0 unknown Unknown or unspecified reason + 1 under-voltage Supply voltage dropped below a safe level + 2 over-current Excessive current draw / possible short + 3 regulator-failure Voltage regulator failure + 4 over-temperature Unsafe temperature detected + 5 ec-panic Embedded controller (EC) panic + 6 power-on Regular cold power-on + 7 watchdog Watchdog timeout + 8 software Software-initiated reset or reboot + 9 external External reset input asserted + 10 rtc RTC-triggered wake-up or power-on + 11 reset-button User reset button + 12 cpu-clock-failure CPU clock failure + 13 crystal-failure Crystal oscillator failure + == ================= ============================================ + + The numeric order is stable ABI: new reasons are only ever + appended. A provider may support only a subset of these; see + "supported_reasons". + +What: /sys/kernel/pscrr/providerN/caps +Date: July 2026 +KernelVersion: 7.2 +Contact: Oleksij Rempel +Description: + (RO) Space-separated list of the provider's non-default + capabilities. Being readable and storing a single reason are + the defaults and are not listed. Currently defined: + + ======== ============================================== + writable the provider can record a reason (see "reason" + and "record_policy") + ======== ============================================== + + An empty line therefore denotes a read-only, single-slot + provider. + +What: /sys/kernel/pscrr/providerN/supported_reasons +Date: July 2026 +KernelVersion: 7.2 +Contact: Oleksij Rempel +Description: + (RO) Space-separated list of the reason tokens (see "reason") + this provider is able to report or record. A provider that + supports every reason lists them all. + +What: /sys/kernel/pscrr/providerN/record_policy +Date: July 2026 +KernelVersion: 7.2 +Contact: Oleksij Rempel +Description: + (RW) Policy used when more than one reason is recorded during a + single power cycle. Present only for providers that can record + (see "caps"). Valid values are: + + ===== ================================================= + first keep the first reason recorded this cycle (the + root cause); this is the default + last overwrite with the most recently recorded reason + ===== ================================================= From 2aa34799ea22e5c33716d79a9ec93414175840aa Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Thu, 24 Sep 2026 16:56:01 +0530 Subject: [PATCH 0431/1133] FROMLIST: power: reset: pscrr: add kernel panic reason tracking Kernel panic resets are not recorded in NVMEM, causing subsequent boots to report PSCR_UNKNOWN and making post-mortem analysis more difficult. Register a panic notifier to preserve the shutdown reason across panic -triggered resets. Add PSCR_KERNEL_PANIC as a dedicated reset reason code and its corresponding reason string to identify kernel panic resets on subsequent boots. Link: https://lore.kernel.org/r/20260805-pscrr-reboot-reason-v4-1-54ef517084cc@oss.qualcomm.com Signed-off-by: Faruque Ansari --- drivers/power/reset/pscrr/pscrr.c | 27 +++++++++++++++++++++++++++ include/linux/power/power_on_reason.h | 1 + include/linux/reboot.h | 3 +++ kernel/reboot.c | 1 + 4 files changed, 32 insertions(+) diff --git a/drivers/power/reset/pscrr/pscrr.c b/drivers/power/reset/pscrr/pscrr.c index f7c1478a50c4b..0be293c14575a 100644 --- a/drivers/power/reset/pscrr/pscrr.c +++ b/drivers/power/reset/pscrr/pscrr.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -524,6 +525,29 @@ static struct notifier_block pscrr_reboot_nb = { .notifier_call = pscrr_reboot_notifier, }; +/* + * Panic notifier: record that the machine went down through a kernel panic, so + * the cause is visible on the next boot. Runs in atomic panic context, so the + * provider list is walked without pscrr_lock - providers no longer come or go + * once the machine is going down. + */ +static int pscrr_panic_notifier(struct notifier_block *nb, + unsigned long action, void *unused) +{ + struct pscrr_provider_dir *dir; + + set_psc_reason(PSCR_KERNEL_PANIC); + + list_for_each_entry(dir, &pscrr_dirs, node) + pscrr_do_record(dir, get_psc_reason()); + + return NOTIFY_DONE; +} + +static struct notifier_block pscrr_panic_nb = { + .notifier_call = pscrr_panic_notifier, +}; + /*----------------------------------------------------------------------*/ /* Built-in provider: device-tree /chosen/reset-source */ /*----------------------------------------------------------------------*/ @@ -616,6 +640,8 @@ static int __init pscrr_core_init(void) return ret; } + atomic_notifier_chain_register(&panic_notifier_list, &pscrr_panic_nb); + pscrr_register_reset_source(); return 0; @@ -624,6 +650,7 @@ static int __init pscrr_core_init(void) static void __exit pscrr_core_exit(void) { pscrr_provider_unregister(&pscrr_reset_source_provider); + atomic_notifier_chain_unregister(&panic_notifier_list, &pscrr_panic_nb); unregister_reboot_notifier(&pscrr_reboot_nb); kobject_put(pscrr_root); pscrr_root = NULL; diff --git a/include/linux/power/power_on_reason.h b/include/linux/power/power_on_reason.h index 13e61ace14f5b..8c99bdd750215 100644 --- a/include/linux/power/power_on_reason.h +++ b/include/linux/power/power_on_reason.h @@ -20,5 +20,6 @@ #define POWER_ON_REASON_OVER_TEMPERATURE "over temperature" #define POWER_ON_REASON_EC_PANIC "EC panic" #define POWER_ON_REASON_EXTERNAL "external reset" +#define POWER_ON_REASON_KERNEL_PANIC "kernel panic" #endif /* POWER_ON_REASON_H */ diff --git a/include/linux/reboot.h b/include/linux/reboot.h index 13f004ad1066a..a117dd5eaecd0 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h @@ -241,6 +241,8 @@ extern void orderly_reboot(void); * * @PSCR_XTAL_FAIL: Reset caused by a crystal oscillator failure. * + * @PSCR_KERNEL_PANIC: Reset that followed a kernel panic. + * * @PSCR_REASON_COUNT: Number of defined power state change reasons. This * value is useful for range checking and potential future extensions * while maintaining compatibility. @@ -264,6 +266,7 @@ enum psc_reason { PSCR_RESET_BUTTON, PSCR_CPU_CLK_FAIL, PSCR_XTAL_FAIL, + PSCR_KERNEL_PANIC, /* Number of reasons */ PSCR_REASON_COUNT, diff --git a/kernel/reboot.c b/kernel/reboot.c index d325f61b2c890..c8a482baf4f05 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -1112,6 +1112,7 @@ static const struct psc_reason_desc psc_reason_descs[] = { [PSCR_RESET_BUTTON] = { "reset-button", POWER_ON_REASON_RST_BTN }, [PSCR_CPU_CLK_FAIL] = { "cpu-clock-failure", POWER_ON_REASON_CPU_CLK_FAIL }, [PSCR_XTAL_FAIL] = { "crystal-failure", POWER_ON_REASON_XTAL_FAIL }, + [PSCR_KERNEL_PANIC] = { "kernel-panic", POWER_ON_REASON_KERNEL_PANIC }, }; static_assert(ARRAY_SIZE(psc_reason_descs) == PSCR_REASON_COUNT, "psc_reason_descs[] must have an entry for every psc_reason"); From 5941352e6cbc7a8255a0c5a535ac860cb50edc1d Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Thu, 24 Sep 2026 16:56:18 +0530 Subject: [PATCH 0432/1133] FROMLIST: power: reset: pscrr: add watchdog pretimeout reason tracking Watchdog pretimeout resets are not recorded with a dedicated reason, causing subsequent boots to report PSCR_UNKNOWN and making it difficult to distinguish them from other unexpected resets. Add PSCR_WATCHDOG_PRETIMEOUT as a dedicated reason code and prevent the panic notifier from overwriting a watchdog pretimeout reason with PSCR_KERNEL_PANIC when the pretimeout governor triggers a panic. Link: https://lore.kernel.org/r/20260805-pscrr-reboot-reason-v4-2-54ef517084cc@oss.qualcomm.com Signed-off-by: Faruque Ansari --- drivers/power/reset/pscrr/pscrr.c | 11 +++++++---- include/linux/power/power_on_reason.h | 1 + include/linux/reboot.h | 4 ++++ kernel/reboot.c | 1 + 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/power/reset/pscrr/pscrr.c b/drivers/power/reset/pscrr/pscrr.c index 0be293c14575a..8fb795af2cc5c 100644 --- a/drivers/power/reset/pscrr/pscrr.c +++ b/drivers/power/reset/pscrr/pscrr.c @@ -534,12 +534,15 @@ static struct notifier_block pscrr_reboot_nb = { static int pscrr_panic_notifier(struct notifier_block *nb, unsigned long action, void *unused) { - struct pscrr_provider_dir *dir; - set_psc_reason(PSCR_KERNEL_PANIC); + /* + * Do not overwrite a watchdog pretimeout reason already set by the + * pretimeout path before it triggered this panic. + */ + if (get_psc_reason() != PSCR_WATCHDOG_PRETIMEOUT) + set_psc_reason(PSCR_KERNEL_PANIC); - list_for_each_entry(dir, &pscrr_dirs, node) - pscrr_do_record(dir, get_psc_reason()); + pscrr_record_current(); return NOTIFY_DONE; } diff --git a/include/linux/power/power_on_reason.h b/include/linux/power/power_on_reason.h index 8c99bdd750215..8e3889fa43ef9 100644 --- a/include/linux/power/power_on_reason.h +++ b/include/linux/power/power_on_reason.h @@ -21,5 +21,6 @@ #define POWER_ON_REASON_EC_PANIC "EC panic" #define POWER_ON_REASON_EXTERNAL "external reset" #define POWER_ON_REASON_KERNEL_PANIC "kernel panic" +#define POWER_ON_REASON_WATCHDOG_PRETIMEOUT "watchdog pretimeout" #endif /* POWER_ON_REASON_H */ diff --git a/include/linux/reboot.h b/include/linux/reboot.h index a117dd5eaecd0..6d5ecc6cdc00b 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h @@ -243,6 +243,9 @@ extern void orderly_reboot(void); * * @PSCR_KERNEL_PANIC: Reset that followed a kernel panic. * + * @PSCR_WATCHDOG_PRETIMEOUT: Recorded when a watchdog pretimeout fires, before + * the pretimeout governor brings the system down. + * * @PSCR_REASON_COUNT: Number of defined power state change reasons. This * value is useful for range checking and potential future extensions * while maintaining compatibility. @@ -267,6 +270,7 @@ enum psc_reason { PSCR_CPU_CLK_FAIL, PSCR_XTAL_FAIL, PSCR_KERNEL_PANIC, + PSCR_WATCHDOG_PRETIMEOUT, /* Number of reasons */ PSCR_REASON_COUNT, diff --git a/kernel/reboot.c b/kernel/reboot.c index c8a482baf4f05..033cbadda522c 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -1113,6 +1113,7 @@ static const struct psc_reason_desc psc_reason_descs[] = { [PSCR_CPU_CLK_FAIL] = { "cpu-clock-failure", POWER_ON_REASON_CPU_CLK_FAIL }, [PSCR_XTAL_FAIL] = { "crystal-failure", POWER_ON_REASON_XTAL_FAIL }, [PSCR_KERNEL_PANIC] = { "kernel-panic", POWER_ON_REASON_KERNEL_PANIC }, + [PSCR_WATCHDOG_PRETIMEOUT] = { "watchdog-pretimeout", POWER_ON_REASON_WATCHDOG_PRETIMEOUT }, }; static_assert(ARRAY_SIZE(psc_reason_descs) == PSCR_REASON_COUNT, "psc_reason_descs[] must have an entry for every psc_reason"); From 4a5e850e69d7426df2eb802b970f8925ecbd9d43 Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Thu, 24 Sep 2026 16:56:32 +0530 Subject: [PATCH 0433/1133] FROMLIST: watchdog: pretimeout: update PSC reason in panic pretimeout governor Update the PSC reset reason by invoking set_psc_reason(PSCR_WATCHDOG_PRETIMEOUT) from the panic governor pretimeout handler before calling panic(), so the reset cause is committed to persistent storage before the system goes down. Link: https://lore.kernel.org/r/20260805-pscrr-reboot-reason-v4-3-54ef517084cc@oss.qualcomm.com Acked-by: Guenter Roeck Signed-off-by: Faruque Ansari --- drivers/watchdog/pretimeout_panic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/watchdog/pretimeout_panic.c b/drivers/watchdog/pretimeout_panic.c index 8c3ac674dc456..819487b5e6fee 100644 --- a/drivers/watchdog/pretimeout_panic.c +++ b/drivers/watchdog/pretimeout_panic.c @@ -5,6 +5,7 @@ #include #include +#include #include #include "watchdog_pretimeout.h" @@ -17,6 +18,7 @@ */ static void pretimeout_panic(struct watchdog_device *wdd) { + set_psc_reason(PSCR_WATCHDOG_PRETIMEOUT); panic("watchdog pretimeout event\n"); } From 697c53f3a28b56b22a58ddefbe6ac16f95755d70 Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Mon, 14 Sep 2026 10:08:45 +0530 Subject: [PATCH 0434/1133] FROMLIST: dt-bindings: nvmem: layouts: Add PSCRR NVMEM layout Add a schema for the PSCRR NVMEM layout, which persists the power state change reason in a single NVMEM cell so it survives a power cycle and can be read back on the next boot. Link: https://lore.kernel.org/r/20260914-pscrr-provider-v3-1-c45cb16542e8@oss.qualcomm.com Signed-off-by: Faruque Ansari --- .../bindings/nvmem/layouts/nvmem-layout.yaml | 1 + .../bindings/nvmem/layouts/pscrr-nvmem.yaml | 87 +++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 89 insertions(+) create mode 100644 Documentation/devicetree/bindings/nvmem/layouts/pscrr-nvmem.yaml diff --git a/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml b/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml index 3825070606511..24545db614167 100644 --- a/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml +++ b/Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml @@ -21,6 +21,7 @@ oneOf: - $ref: fixed-layout.yaml - $ref: kontron,sl28-vpd.yaml - $ref: onie,tlv-layout.yaml + - $ref: pscrr-nvmem.yaml - $ref: u-boot,env.yaml properties: diff --git a/Documentation/devicetree/bindings/nvmem/layouts/pscrr-nvmem.yaml b/Documentation/devicetree/bindings/nvmem/layouts/pscrr-nvmem.yaml new file mode 100644 index 0000000000000..118669d33f5c2 --- /dev/null +++ b/Documentation/devicetree/bindings/nvmem/layouts/pscrr-nvmem.yaml @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/nvmem/layouts/pscrr-nvmem.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVMEM layout for the Power State Change Reason recorder (PSCRR) + +maintainers: + - Faruque Ansari + - Oleksij Rempel + +description: + An NVMEM layout for a Power State Change Reason (PSCRR) recorder. The + reboot or shutdown cause is persisted into a single small NVMEM cell, + such as an RTC scratch register, a PMIC SDAM (Scratch Data Access Memory) + byte, or an EEPROM byte, so the reason survives a power cycle and can be + read back on the next boot. + +select: false + +properties: + compatible: + const: pscrr-nvmem + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + +patternProperties: + "^.*@[0-9a-f]+$": + type: object + description: + The single NVMEM cell used to persist the power state change reason. + + properties: + reg: + items: + - items: + - description: Offset, in bytes, of the cell within the + parent NVMEM device. + - const: 1 + description: + Offset and size, in bytes, of the cell within the parent NVMEM + device. The reason value occupies a single byte, so the size + must be 1. + + bits: + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + - minimum: 0 + maximum: 7 + description: + Bit offset within the byte addressed by reg. + - minimum: 1 + maximum: 8 + description: + Number of bits used to store the reason. Must be wide enough + to hold every value of enum psc_reason (currently 4 bits or + more). + description: + Optional. When absent, the whole byte addressed by reg is used. + + required: + - reg + + additionalProperties: false + +required: + - compatible + +additionalProperties: false + +examples: + - | + nvmem-layout { + compatible = "pscrr-nvmem"; + #address-cells = <1>; + #size-cells = <1>; + + reboot-reason-persist@49 { + reg = <0x49 0x1>; + bits = <0 4>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index bbe685e9349ae..ccc31c0a55c89 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22266,6 +22266,7 @@ R: Pengutronix Kernel Team L: linux-pm@vger.kernel.org S: Maintained F: Documentation/ABI/testing/sysfs-kernel-pscrr +F: Documentation/devicetree/bindings/nvmem/layouts/pscrr-nvmem.yaml F: drivers/power/reset/pscrr/ F: include/linux/pscrr.h F: tools/testing/selftests/pscrr/ From d9ee007e095e26a73577bac78a25ec666aafdbf8 Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Mon, 14 Sep 2026 10:08:46 +0530 Subject: [PATCH 0435/1133] FROMLIST: power: reset: Add PSCRR NVMEM recorder Record the power state change reason into a NVMEM cell (a PMIC SDAM byte, RTC scratch register, or EEPROM) and read it back on the next boot, so the cause survives a power cycle. The recorder is implemented as an NVMEM layout driver: it owns the single cell described by its layout binding and adds it to the parent NVMEM device, rather than acting as a standalone consumer of someone else's cell. Link: https://lore.kernel.org/r/20260914-pscrr-provider-v3-2-c45cb16542e8@oss.qualcomm.com Co-developed-by: Oleksij Rempel Signed-off-by: Oleksij Rempel Signed-off-by: Faruque Ansari --- drivers/power/reset/pscrr/Kconfig | 14 ++ drivers/power/reset/pscrr/Makefile | 1 + drivers/power/reset/pscrr/pscrr-nvmem.c | 269 ++++++++++++++++++++++++ 3 files changed, 284 insertions(+) create mode 100644 drivers/power/reset/pscrr/pscrr-nvmem.c diff --git a/drivers/power/reset/pscrr/Kconfig b/drivers/power/reset/pscrr/Kconfig index 72de82731b531..459b05ba32d30 100644 --- a/drivers/power/reset/pscrr/Kconfig +++ b/drivers/power/reset/pscrr/Kconfig @@ -31,3 +31,17 @@ menuconfig PSCRR unless hardware provides the reset cause. If unsure, say N. + +if PSCRR + +config PSCRR_NVMEM + tristate "PSCRR NVMEM recorder provider" + depends on NVMEM_LAYOUTS + help + PSCRR recorder that stores the power state change reason in a + small NVMEM cell (such as an RTC scratch register) and reads it + back on the next boot, so the cause survives a power cycle. + + If unsure, say N. + +endif # PSCRR diff --git a/drivers/power/reset/pscrr/Makefile b/drivers/power/reset/pscrr/Makefile index e5530a8589713..95c80c80c7da0 100644 --- a/drivers/power/reset/pscrr/Makefile +++ b/drivers/power/reset/pscrr/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_PSCRR) += pscrr.o +obj-$(CONFIG_PSCRR_NVMEM) += pscrr-nvmem.o diff --git a/drivers/power/reset/pscrr/pscrr-nvmem.c b/drivers/power/reset/pscrr/pscrr-nvmem.c new file mode 100644 index 0000000000000..64f67f0521e06 --- /dev/null +++ b/drivers/power/reset/pscrr/pscrr-nvmem.c @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * pscrr-nvmem.c - NVMEM layout driver for PSCRR + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * Copyright (C) 2025 Pengutronix, Oleksij Rempel + */ + +#include +#include +#include +#include +#include +#include +#include + +struct pscrr_nvmem { + struct nvmem_device *nvmem; + u32 offset; /* byte offset of the cell, from reg[0] */ + u32 bit_offset; /* 0 when the cell has no "bits" property */ + u32 nbits; /* BITS_PER_BYTE when the cell has no "bits" property */ + enum psc_reason reason; +}; + +static inline u8 pscrr_nvmem_mask(struct pscrr_nvmem *priv) +{ + return (u8)GENMASK(priv->bit_offset + priv->nbits - 1, priv->bit_offset); +} + +static int pscrr_nvmem_raw_read(struct pscrr_nvmem *priv, u8 *raw) +{ + int ret; + + ret = nvmem_device_read(priv->nvmem, priv->offset, sizeof(*raw), raw); + + return ret < 0 ? ret : 0; +} + +static int pscrr_nvmem_raw_write(struct pscrr_nvmem *priv, u8 raw) +{ + int ret; + + ret = nvmem_device_write(priv->nvmem, priv->offset, sizeof(raw), &raw); + + return ret < 0 ? ret : 0; +} + +static int pscrr_nvmem_cell_read(struct pscrr_nvmem *priv, u8 *out) +{ + u8 raw, mask = pscrr_nvmem_mask(priv); + int ret; + + ret = pscrr_nvmem_raw_read(priv, &raw); + if (ret) + return ret; + + *out = (raw & mask) >> priv->bit_offset; + + return 0; +} + +static int pscrr_nvmem_cell_write(struct pscrr_nvmem *priv, u8 val) +{ + u8 raw, mask = pscrr_nvmem_mask(priv); + int ret; + + /* Sub-byte cell: preserve the neighbouring bits, read-modify-write. */ + if (priv->nbits < BITS_PER_BYTE) { + ret = pscrr_nvmem_raw_read(priv, &raw); + if (ret) + return ret; + } else { + raw = 0; + } + + raw = (raw & ~mask) | ((val << priv->bit_offset) & mask); + + return pscrr_nvmem_raw_write(priv, raw); +} + +static int pscrr_nvmem_read_reasons(struct pscrr_provider *p, + unsigned long *reasons) +{ + struct pscrr_nvmem *priv = p->priv; + + /* + * Report the reason latched at probe (or overwritten by a later + * record); the cell itself was cleared at probe, so it is not read + * live here. + */ + set_bit(READ_ONCE(priv->reason), reasons); + + return 0; +} + +static int pscrr_nvmem_write_reason(struct pscrr_provider *p, + enum psc_reason reason) +{ + struct pscrr_nvmem *priv = p->priv; + int ret; + + if (reason >= PSCR_REASON_COUNT) + return -EINVAL; + + ret = pscrr_nvmem_cell_write(priv, reason); + if (ret) + return ret; + + WRITE_ONCE(priv->reason, reason); + + return 0; +} + +static const struct pscrr_provider_ops pscrr_nvmem_ops = { + .read_reasons = pscrr_nvmem_read_reasons, + .write_reason = pscrr_nvmem_write_reason, +}; + +static struct device_node *pscrr_nvmem_get_cell(struct device *dev, + struct nvmem_device *nvmem, + u32 reg[2]) +{ + struct device_node *layout_np, *cell_np = NULL; + + layout_np = of_nvmem_layout_get_container(nvmem); + if (!layout_np) + return ERR_PTR(-ENOENT); + + for_each_child_of_node_scoped(layout_np, child) { + if (of_property_read_u32_array(child, "reg", reg, 2)) + continue; + + cell_np = of_node_get(child); + break; + } + of_node_put(layout_np); + + return cell_np ?: ERR_PTR(dev_err_probe(dev, -ENOENT, + "missing pscr nvmem cell\n")); +} + +static int pscrr_nvmem_add_cells(struct nvmem_layout *layout) +{ + struct device *dev = &layout->dev; + struct pscrr_nvmem *priv; + struct device_node *cell_np; + struct nvmem_cell_info info = { }; + u32 reg[2], bits[2]; + u8 val; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->nvmem = layout->nvmem; + + cell_np = pscrr_nvmem_get_cell(dev, priv->nvmem, reg); + if (IS_ERR(cell_np)) + return PTR_ERR(cell_np); + + /* The reason is a single byte; a bit cell still occupies one. */ + if (reg[1] != sizeof(val)) { + of_node_put(cell_np); + return dev_err_probe(dev, -EINVAL, + "unsupported pscr nvmem cell size\n"); + } + priv->offset = reg[0]; + + if (!of_property_read_u32_array(cell_np, "bits", bits, ARRAY_SIZE(bits))) { + priv->bit_offset = bits[0]; + priv->nbits = bits[1]; + } else { + priv->bit_offset = 0; + priv->nbits = BITS_PER_BYTE; + } + + if (priv->bit_offset + priv->nbits > BITS_PER_BYTE * reg[1]) { + of_node_put(cell_np); + return dev_err_probe(dev, -EINVAL, "bits exceed cell size\n"); + } + + /* PSCR_REASON_COUNT must fit in the allotted bits. */ + if (PSCR_REASON_COUNT > (1U << priv->nbits)) { + of_node_put(cell_np); + return dev_err_probe(dev, -EINVAL, + "too few bits for the reason range\n"); + } + + /* + * The cell survives resets, so at boot it still holds whatever the + * previous session recorded before it went down. Latch that as this + * boot's reason, then clear the cell back to PSCR_UNKNOWN: if this + * session is later cut short by an abrupt reset that never runs the + * recorder (watchdog power-cycle, sudden power loss), the next boot + * reads "unknown" instead of a stale reason left over from an earlier + * cycle. + */ + ret = pscrr_nvmem_cell_read(priv, &val); + if (ret) { + of_node_put(cell_np); + return dev_err_probe(dev, ret, + "failed to read the pscr nvmem cell\n"); + } + + priv->reason = val < PSCR_REASON_COUNT ? val : PSCR_UNKNOWN; + + ret = pscrr_nvmem_cell_write(priv, PSCR_UNKNOWN); + if (ret) { + of_node_put(cell_np); + return dev_err_probe(dev, ret, + "failed to clear the pscr nvmem cell\n"); + } + + info.name = kasprintf(GFP_KERNEL, "%pOFn", cell_np); + if (!info.name) { + of_node_put(cell_np); + return -ENOMEM; + } + info.offset = reg[0]; + info.bytes = reg[1]; + info.bit_offset = priv->bit_offset; + info.nbits = priv->nbits; + info.np = cell_np; + + ret = nvmem_add_one_cell(priv->nvmem, &info); + kfree(info.name); + if (ret) { + of_node_put(cell_np); + return ret; + } + + return PTR_ERR_OR_ZERO(devm_pscrr_provider_register(dev, "nvmem", + &pscrr_nvmem_ops, NULL, + priv)); +} + +static int pscrr_nvmem_probe(struct nvmem_layout *layout) +{ + layout->add_cells = pscrr_nvmem_add_cells; + + return nvmem_layout_register(layout); +} + +static void pscrr_nvmem_remove(struct nvmem_layout *layout) +{ + nvmem_layout_unregister(layout); +} + +static const struct of_device_id pscrr_nvmem_of_match[] = { + { .compatible = "pscrr-nvmem" }, + { } +}; +MODULE_DEVICE_TABLE(of, pscrr_nvmem_of_match); + +static struct nvmem_layout_driver pscrr_nvmem_layout = { + .driver = { + .name = "pscrr-nvmem", + .of_match_table = pscrr_nvmem_of_match, + }, + .probe = pscrr_nvmem_probe, + .remove = pscrr_nvmem_remove, +}; +module_nvmem_layout_driver(pscrr_nvmem_layout); + +MODULE_AUTHOR("Oleksij Rempel "); +MODULE_AUTHOR("Faruque Ansari "); +MODULE_DESCRIPTION("NVMEM recorder provider for PSCRR"); +MODULE_LICENSE("GPL"); From 875a1018b1705cffc19174b0edd9cd9085187cde Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:24 +0800 Subject: [PATCH 0436/1133] FROMLIST: ACPI/AEST: Register arm64_ras platform devices from AEST v2 Parse the ARM Error Source Table (AEST) v2 [1] and present each error-source node to the RAS subsystem as a generic platform device. Rather than letting the RAS driver consume AEST-specific structures directly, all per-node metadata (interface type, register bases, group format, record bitmaps, GSIVs, vendor data) is conveyed via fwnode software-node properties. This keeps every AEST encoding detail in the ACPI front-end and lets the same back-end driver bind unchanged when a Device Tree front-end is added later. If the interface flags indicate an associated ACPI namespace device (AEST_XFACE_FLAG_ERROR_DEVICE), the companion ACPI device is looked up and attached so that downstream drivers can reach it. [1]: https://developer.arm.com/documentation/den0085/0200/ Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- MAINTAINERS | 8 ++ drivers/acpi/arm64/Kconfig | 10 ++ drivers/acpi/arm64/Makefile | 1 + drivers/acpi/arm64/aest.c | 256 ++++++++++++++++++++++++++++++++++++ include/linux/acpi_aest.h | 19 +++ 5 files changed, 294 insertions(+) create mode 100644 drivers/acpi/arm64/aest.c create mode 100644 include/linux/acpi_aest.h diff --git a/MAINTAINERS b/MAINTAINERS index ccc31c0a55c89..ac061d5e8cac5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -359,6 +359,14 @@ S: Maintained F: drivers/acpi/loongarch/ F: include/linux/acpi_iovt.h +ACPI AEST +M: Ruidong Tian +L: linux-acpi@vger.kernel.org +L: linux-arm-kernel@lists.infradead.org +S: Supported +F: drivers/acpi/arm64/aest.c +F: include/linux/acpi_aest.h + ACPI FOR RISC-V (ACPI/riscv) M: Sunil V L L: linux-acpi@vger.kernel.org diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig index f2fd79f22e7d8..49b487bba928c 100644 --- a/drivers/acpi/arm64/Kconfig +++ b/drivers/acpi/arm64/Kconfig @@ -24,3 +24,13 @@ config ACPI_APMT config ACPI_MPAM bool + +config ACPI_AEST + bool "ARM Error Source Table Support" + depends on ARM64_RAS_EXTN + help + The Arm Error Source Table (AEST) provides details on ACPI + extensions that enable kernel-first handling of errors in a + system that supports the Armv8 RAS extensions. + + If set, the kernel will report and log hardware errors. diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile index 9390b57cb5648..bad77fdbf8dd0 100644 --- a/drivers/acpi/arm64/Makefile +++ b/drivers/acpi/arm64/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_ACPI_IORT) += iort.o obj-$(CONFIG_ACPI_MPAM) += mpam.o obj-$(CONFIG_ACPI_PROCESSOR_IDLE) += cpuidle.o obj-$(CONFIG_ARM_AMBA) += amba.o +obj-$(CONFIG_ACPI_AEST) += aest.o obj-y += dma.o init.o obj-y += thermal_cpufreq.o diff --git a/drivers/acpi/arm64/aest.c b/drivers/acpi/arm64/aest.c new file mode 100644 index 0000000000000..8cf24467d0c25 --- /dev/null +++ b/drivers/acpi/arm64/aest.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#include +#include +#include +#include + +#include "init.h" + +#undef pr_fmt +#define pr_fmt(fmt) "ACPI AEST: " fmt + +/* + * Fill the per-AEST-entry inner properties (node-type / interface-type / + * group-format / record bitmaps / register bases ...). + */ +static int __init +aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, + int *p, struct platform_device *pdev) +{ + struct acpi_aest_node_interface_header *interface; + struct acpi_aest_node_interface_common *common = NULL; + u64 *record_implemented = NULL; + u64 *status_reporting = NULL; + u64 *addressing_mode = NULL; + int group_len = 0, i; + size_t len; + + interface = ACPI_ADD_PTR(struct acpi_aest_node_interface_header, + hdr, hdr->node_interface_offset); + switch (interface->group_format) { + case ACPI_AEST_NODE_GROUP_FORMAT_4K: { + struct acpi_aest_node_interface_4k *itf = + (struct acpi_aest_node_interface_4k *)(interface + 1); + + record_implemented = &itf->error_record_implemented; + status_reporting = &itf->error_status_reporting; + addressing_mode = &itf->addressing_mode; + group_len = 1; + common = &itf->common; + break; + } + case ACPI_AEST_NODE_GROUP_FORMAT_16K: { + struct acpi_aest_node_interface_16k *itf = + (struct acpi_aest_node_interface_16k *)(interface + 1); + + record_implemented = itf->error_record_implemented; + status_reporting = itf->error_status_reporting; + addressing_mode = itf->addressing_mode; + group_len = 4; + common = &itf->common; + break; + } + case ACPI_AEST_NODE_GROUP_FORMAT_64K: { + struct acpi_aest_node_interface_64k *itf = + (struct acpi_aest_node_interface_64k *)(interface + 1); + + record_implemented = itf->error_record_implemented; + status_reporting = itf->error_status_reporting; + addressing_mode = itf->addressing_mode; + group_len = 14; + common = &itf->common; + break; + } + default: + pr_err("invalid group format: %d\n", interface->group_format); + return -EINVAL; + } + + if (interface->flags & AEST_XFACE_FLAG_ERROR_DEVICE) { + struct acpi_device *companion; + char uid[16]; + int n; + + n = snprintf(uid, sizeof(uid), "%u", + common->error_node_device); + if (n > 0 && n < sizeof(uid)) { + companion = acpi_dev_get_first_match_dev("ARMHE000", + uid, -1); + if (companion) { + ACPI_COMPANION_SET(&pdev->dev, companion); + acpi_dev_put(companion); + } else { + pr_debug("MSC.%u: missing namespace entry\n", + common->error_node_device); + } + } + } + + props[(*p)++] = PROPERTY_ENTRY_U8("arm,node-type", hdr->type); + props[(*p)++] = PROPERTY_ENTRY_U8("arm,group-format", + interface->group_format); + props[(*p)++] = PROPERTY_ENTRY_U32("arm,error-records-count", + interface->error_record_count); + props[(*p)++] = PROPERTY_ENTRY_U32("arm,error-records-index", + interface->error_record_index); + props[(*p)++] = PROPERTY_ENTRY_U32("arm,interface-flags", + interface->flags); + props[(*p)++] = PROPERTY_ENTRY_U64_ARRAY_LEN("arm,record-implemented", + record_implemented, + group_len); + props[(*p)++] = PROPERTY_ENTRY_U64_ARRAY_LEN("arm,status-reporting", + status_reporting, + group_len); + props[(*p)++] = PROPERTY_ENTRY_U64("arm,error-group-base", + common->error_group_register_base); + + len = hdr->node_interface_offset - hdr->node_specific_offset; + props[(*p)++] = + PROPERTY_ENTRY_U8_ARRAY_LEN("arm,node-specific-data", + ACPI_ADD_PTR(u8, hdr, hdr->node_specific_offset), len); + + return 0; +} + +static int __init +aest_create_node_fwnode(struct acpi_aest_hdr *hdr, struct platform_device *pdev) +{ + struct property_entry props[10] = { }; + int p = 0; + int ret; + + ret = aest_init_node_props(hdr, props, &p, pdev); + if (ret) + return ret; + + return device_create_managed_software_node(&pdev->dev, props, NULL); +} + +static int aest_node_mem_size(u8 group_format) +{ + switch (group_format) { + case ACPI_AEST_NODE_GROUP_FORMAT_4K: + return SZ_4K; + case ACPI_AEST_NODE_GROUP_FORMAT_16K: + return SZ_16K; + case ACPI_AEST_NODE_GROUP_FORMAT_64K: + return SZ_64K; + default: + return SZ_4K; + } +} + +DEFINE_FREE(res, struct resource *, if (_T) kfree(_T)) + +static struct platform_device *__init +acpi_aest_alloc_pdev(struct acpi_aest_hdr *aest_hdr) +{ + struct platform_device *pdev __free(platform_device_put) = + platform_device_alloc("arm64_ras", PLATFORM_DEVID_AUTO); + struct resource *res __free(res) = NULL; + struct acpi_aest_node_interface_header *interface; + int ret, j = 0; + + if (!pdev) + return ERR_PTR(-ENOMEM); + + res = kcalloc(1, sizeof(*res), GFP_KERNEL); + if (!res) + return ERR_PTR(-ENOMEM); + + interface = ACPI_ADD_PTR(struct acpi_aest_node_interface_header, + aest_hdr, aest_hdr->node_interface_offset); + if (interface->type != ACPI_AEST_NODE_SYSTEM_REGISTER) { + res[j].name = AEST_NODE_NAME; + res[j].start = interface->address; + res[j].end = res[j].start + aest_node_mem_size(interface->group_format) - 1; + res[j].flags = IORESOURCE_MEM; + j++; + } + + ret = platform_device_add_resources(pdev, res, j); + if (ret) + return ERR_PTR(ret); + + return_ptr(pdev); +} + +static int __init acpi_aest_init_node(struct acpi_aest_hdr *aest_hdr) +{ + struct platform_device *pdev __free(platform_device_put) = NULL; + int ret; + + pdev = acpi_aest_alloc_pdev(aest_hdr); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + ret = aest_create_node_fwnode(aest_hdr, pdev); + if (ret) + return ret; + + ret = platform_device_add(pdev); + if (ret) + return ret; + pr_debug("Platform device added for AEST node: %s.%d\n", + pdev->name, pdev->id); + retain_and_null_ptr(pdev); + + return 0; +} + +static int __init acpi_aest_init_nodes(struct acpi_table_header *aest_table) +{ + struct acpi_aest_hdr *aest_node, *aest_end; + struct acpi_table_aest *aest; + int rc; + + aest = (struct acpi_table_aest *)aest_table; + aest_node = ACPI_ADD_PTR(struct acpi_aest_hdr, aest, + sizeof(struct acpi_table_header)); + aest_end = ACPI_ADD_PTR(struct acpi_aest_hdr, aest, aest_table->length); + + while (aest_node < aest_end) { + if (((u64)aest_node + aest_node->length) > (u64)aest_end) { + pr_warn(FW_WARN + "AEST node pointer overflow, bad table.\n"); + return -EINVAL; + } + + rc = acpi_aest_init_node(aest_node); + if (rc) + return rc; + + aest_node = ACPI_ADD_PTR(struct acpi_aest_hdr, aest_node, + aest_node->length); + } + + return 0; +} + +static int __init acpi_aest_init(void) +{ + int ret; + + if (acpi_disabled) + return 0; + + struct acpi_table_header *aest_table __free(acpi_put_table) = + acpi_get_table_pointer(ACPI_SIG_AEST, 0); + if (IS_ERR(aest_table)) + return 0; + + ret = acpi_aest_init_nodes(aest_table); + if (ret) { + pr_err("Failed init aest node %d\n", ret); + return ret; + } + + return 0; +} +subsys_initcall_sync(acpi_aest_init); diff --git a/include/linux/acpi_aest.h b/include/linux/acpi_aest.h new file mode 100644 index 0000000000000..e485a62368914 --- /dev/null +++ b/include/linux/acpi_aest.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ACPI_AEST_H__ +#define __ACPI_AEST_H__ + +#include + +/* AEST resource name */ +#define AEST_NODE_NAME "AEST:NODE" + +/* AEST interface */ +#define AEST_XFACE_FLAG_SHARED BIT(0) +#define AEST_XFACE_FLAG_CLEAR_MISC BIT(1) +#define AEST_XFACE_FLAG_ERROR_DEVICE BIT(2) +#define AEST_XFACE_FLAG_AFFINITY BIT(3) +#define AEST_XFACE_FLAG_ERROR_GROUP BIT(4) +#define AEST_XFACE_FLAG_FAULT_INJECT BIT(5) +#define AEST_XFACE_FLAG_INT_CONFIG BIT(6) + +#endif /* __ACPI_AEST_H__ */ From f9bf943f56e33ff12c522deeacfc73a637ff9f36 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:25 +0800 Subject: [PATCH 0437/1133] FROMLIST: arm64: ras: Add probe/remove for arm64_ras driver Introduce the back-end platform driver that binds to the devices created by the AEST front-end. Driver input is taken exclusively from fwnode properties, so the same probe path serves any future front-end (DT, hand-rolled) without conditional code. The probe builds two layers of state: - struct ras_node: one AEST error source - struct ras_record: one error record inside a node This split mirrors the hardware: a node owns the shared MMIO/ERRGSR window and policy, while records are the unit at which errors are reported, masked and polled. Later patches plug interrupts, decoding, storm mitigation and userspace ABI onto these two objects without touching the front-end. Signed-off-by: Umang Chheda Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- MAINTAINERS | 2 + arch/arm64/include/asm/ras.h | 15 ++ drivers/ras/Kconfig | 1 + drivers/ras/Makefile | 1 + drivers/ras/arm64/Kconfig | 16 +++ drivers/ras/arm64/Makefile | 5 + drivers/ras/arm64/ras-core.c | 266 +++++++++++++++++++++++++++++++++++ drivers/ras/arm64/ras.h | 104 ++++++++++++++ include/linux/acpi_aest.h | 3 + 9 files changed, 413 insertions(+) create mode 100644 arch/arm64/include/asm/ras.h create mode 100644 drivers/ras/arm64/Kconfig create mode 100644 drivers/ras/arm64/Makefile create mode 100644 drivers/ras/arm64/ras-core.c create mode 100644 drivers/ras/arm64/ras.h diff --git a/MAINTAINERS b/MAINTAINERS index ac061d5e8cac5..dd5350a01163c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -364,7 +364,9 @@ M: Ruidong Tian L: linux-acpi@vger.kernel.org L: linux-arm-kernel@lists.infradead.org S: Supported +F: arch/arm64/include/asm/ras.h F: drivers/acpi/arm64/aest.c +F: drivers/ras/arm64/ F: include/linux/acpi_aest.h ACPI FOR RISC-V (ACPI/riscv) diff --git a/arch/arm64/include/asm/ras.h b/arch/arm64/include/asm/ras.h new file mode 100644 index 0000000000000..b6640b9972bfb --- /dev/null +++ b/arch/arm64/include/asm/ras.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_RAS_H +#define __ASM_RAS_H + +#include + +struct ras_ext_regs { + u64 err_fr; + u64 err_ctlr; + u64 err_status; + u64 err_addr; + u64 err_misc[4]; +}; + +#endif /* __ASM_RAS_H */ diff --git a/drivers/ras/Kconfig b/drivers/ras/Kconfig index 070e17639faa3..cc12744016548 100644 --- a/drivers/ras/Kconfig +++ b/drivers/ras/Kconfig @@ -55,6 +55,7 @@ config RAS_CEC_DEBUG file that dumps out the current state of all pages logged so far. source "drivers/ras/amd/atl/Kconfig" +source "drivers/ras/arm64/Kconfig" config RAS_FMPM tristate "FRU Memory Poison Manager" diff --git a/drivers/ras/Makefile b/drivers/ras/Makefile index 11f95d59d3972..1b62a3017fa33 100644 --- a/drivers/ras/Makefile +++ b/drivers/ras/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_RAS_CEC) += cec.o obj-$(CONFIG_RAS_FMPM) += amd/fmpm.o obj-y += amd/atl/ +obj-$(CONFIG_ARM64_RAS_DRIVER) += arm64/ diff --git a/drivers/ras/arm64/Kconfig b/drivers/ras/arm64/Kconfig new file mode 100644 index 0000000000000..dcdeaa216d676 --- /dev/null +++ b/drivers/ras/arm64/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# ARM Error Source Table Support +# +# Copyright (c) 2025, Alibaba Group. +# + +config ARM64_RAS_DRIVER + tristate "ARM64 RAS Driver" + depends on ARM64 && ACPI_AEST && RAS + help + This is the RAS driver for the arm64 architecture. It depends on + the Arm Error Source Table (AEST) to provide basic register and + interrupt information. + + If set, the kernel will report and process hardware errors. diff --git a/drivers/ras/arm64/Makefile b/drivers/ras/arm64/Makefile new file mode 100644 index 0000000000000..c5387f05a067e --- /dev/null +++ b/drivers/ras/arm64/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_ARM64_RAS_DRIVER) += arm64_ras.o + +arm64_ras-y := ras-core.o diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c new file mode 100644 index 0000000000000..b5448f4a841f6 --- /dev/null +++ b/drivers/ras/arm64/ras-core.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#include +#include +#include + +#include "ras.h" + +#undef pr_fmt +#define pr_fmt(fmt) "arm64_ras: " fmt + +static const char *const ras_node_name[] = { + [ACPI_AEST_PROCESSOR_ERROR_NODE] = "processor", + [ACPI_AEST_MEMORY_ERROR_NODE] = "memory", + [ACPI_AEST_SMMU_ERROR_NODE] = "smmu", + [ACPI_AEST_VENDOR_ERROR_NODE] = "vendor", + [ACPI_AEST_GIC_ERROR_NODE] = "gic", + [ACPI_AEST_PCIE_ERROR_NODE] = "pcie", + [ACPI_AEST_PROXY_ERROR_NODE] = "proxy", +}; + +const struct ras_group ras_group_config[] = { + [ACPI_AEST_NODE_GROUP_FORMAT_4K] = { + .errgsr_num = ERXGROUP_4K_ERRGSR_NUM, + .size = ERXGROUP_4K_SIZE, + .errgsr_offset = ERXGROUP_4K_OFFSET, + }, + [ACPI_AEST_NODE_GROUP_FORMAT_16K] = { + .errgsr_num = ERXGROUP_16K_ERRGSR_NUM, + .size = ERXGROUP_16K_SIZE, + .errgsr_offset = ERXGROUP_16K_OFFSET, + }, + [ACPI_AEST_NODE_GROUP_FORMAT_64K] = { + .errgsr_num = ERXGROUP_64K_ERRGSR_NUM, + .size = ERXGROUP_64K_SIZE, + .errgsr_offset = ERXGROUP_64K_OFFSET, + }, +}; + +static int ras_init_record(struct ras_record *record, int i, struct ras_node *node) +{ + record->name = devm_kasprintf(node->dev, GFP_KERNEL, "record%d", i); + if (!record->name) + return -ENOMEM; + + if (node->base) + record->regs_base = node->base + sizeof(struct ras_ext_regs) * i; + + record->index = i; + record->node = node; + + return 0; +} + +static char *alloc_ras_node_name(struct ras_node *node) +{ + char *name; + struct acpi_aest_processor *processor = NULL; + + switch (node->type) { + case ACPI_AEST_PROCESSOR_ERROR_NODE: + processor = (struct acpi_aest_processor *)node->specific_data; + + /* + * Shared/global processor nodes (e.g. cluster L3 cache, DSU) + * have processor_id=0 and use smp_processor_id() at error-log + * time — using processor_id in the name would produce the same + * "processor.0" string for every shared node and every CPU0 + * per-PE node, making logs ambiguous. + * + * For shared/global nodes, build the name from the resource + * type and the device id so each node gets a unique, meaningful + * name (e.g. "processor.cache.1", "processor.tlb.2"). + * + * For per-PE nodes, keep the original "processor." form. + */ + if (processor->flags & + (ACPI_AEST_PROC_FLAG_SHARED | ACPI_AEST_PROC_FLAG_GLOBAL)) { + static const char *const res_name[] = { + [ACPI_AEST_CACHE_RESOURCE] = "cache", + [ACPI_AEST_TLB_RESOURCE] = "tlb", + [ACPI_AEST_GENERIC_RESOURCE] = "generic", + }; + u8 rtype = processor->resource_type; + const char *rstr = (rtype < ARRAY_SIZE(res_name) && + res_name[rtype]) ? res_name[rtype] : "unknown"; + + name = devm_kasprintf(node->dev, GFP_KERNEL, + "%s.%s.%x", + ras_node_name[node->type], + rstr, + *(u32 *)(processor + 1)); + } else { + name = devm_kasprintf(node->dev, GFP_KERNEL, + "%s.%d", + ras_node_name[node->type], + processor->processor_id); + } + break; + case ACPI_AEST_MEMORY_ERROR_NODE: + case ACPI_AEST_SMMU_ERROR_NODE: + case ACPI_AEST_VENDOR_ERROR_NODE: + case ACPI_AEST_GIC_ERROR_NODE: + case ACPI_AEST_PCIE_ERROR_NODE: + case ACPI_AEST_PROXY_ERROR_NODE: + name = devm_kasprintf(node->dev, GFP_KERNEL, "%s.%llx", + ras_node_name[node->type], node->addr); + break; + default: + dev_warn(node->dev, "unknown AEST node type %u\n", node->type); + return NULL; + } + + return name; +} + +static int ras_node_set_errgsr(struct ras_node *node, phys_addr_t base) +{ + phys_addr_t errgsr_base; + int ret; + + if (!(node->flags & AEST_XFACE_FLAG_ERROR_GROUP)) { + node->errgsr = node->base + node->group->errgsr_offset; + return 0; + } + + ret = device_property_read_u64(node->dev, "arm,error-group-base", + &errgsr_base); + if (ret || !errgsr_base) + return -EINVAL; + + node->errgsr = errgsr_base - base + node->base; + return 0; +} + +static struct ras_node *ras_init_node(struct platform_device *pdev) +{ + int i, ret = 0; + struct device *dev = &pdev->dev; + struct resource *mem; + struct ras_node *node; + + node = devm_kzalloc(&pdev->dev, sizeof(*node), GFP_KERNEL); + if (!node) + return ERR_PTR(-ENOMEM); + + node->dev = &pdev->dev; + + ret = ret ?: device_property_read_u8(dev, "arm,node-type", &node->type); + ret = ret ?: device_property_read_u8(dev, "arm,group-format", &node->group_format); + ret = ret ?: device_property_read_u32(dev, "arm,interface-flags", &node->flags); + ret = ret ?: device_property_read_u32(dev, "arm,error-records-count", &node->record_count); + ret = ret ?: device_property_read_u32(dev, "arm,error-records-index", &node->record_index); + if (ret) + return ERR_PTR(ret); + node->group = &ras_group_config[node->group_format]; + + node->record_implemented = devm_bitmap_zalloc(dev, + node->group->errgsr_num * BITS_PER_TYPE(u64), + GFP_KERNEL); + if (!node->record_implemented) + return ERR_PTR(-ENOMEM); + node->status_reporting = devm_bitmap_zalloc(dev, + node->group->errgsr_num * BITS_PER_TYPE(u64), + GFP_KERNEL); + if (!node->status_reporting) + return ERR_PTR(-ENOMEM); + + ret = device_property_read_u64_array(dev, "arm,record-implemented", + (u64 *)node->record_implemented, + node->group->errgsr_num); + ret = ret ?: device_property_read_u64_array(dev, "arm,status-reporting", + (u64 *)node->status_reporting, + node->group->errgsr_num); + if (ret) + return ERR_PTR(ret); + + node->specific_data_size = device_property_count_u8(dev, "arm,node-specific-data"); + if (node->specific_data_size > 0) { + node->specific_data = devm_kzalloc(dev, node->specific_data_size, GFP_KERNEL); + if (!node->specific_data) + return ERR_PTR(-ENOMEM); + ret = device_property_read_u8_array(dev, "arm,node-specific-data", + node->specific_data, + node->specific_data_size); + if (ret) + return ERR_PTR(ret); + } + + mem = platform_get_resource(to_platform_device(dev), IORESOURCE_MEM, 0); + if (mem) { + node->addr = mem->start; + node->base = devm_ioremap(node->dev, mem->start, resource_size(mem)); + if (!node->base) + return ERR_PTR(-ENOMEM); + + ret = ras_node_set_errgsr(node, mem->start); + if (ret) + return ERR_PTR(ret); + } + + node->name = alloc_ras_node_name(node); + if (!node->name) + return ERR_PTR(-ENOMEM); + + node->records = devm_kcalloc(node->dev, node->record_count, + sizeof(struct ras_record), GFP_KERNEL); + if (!node->records) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < node->record_count; i++) { + ret = ras_init_record(&node->records[i], + i + node->record_index, node); + if (ret) + return ERR_PTR(ret); + } + ras_node_dbg(node, "base: %llx\n", node->addr); + return node; +} + +static int arm64_ras_probe(struct platform_device *pdev) +{ + int ret; + struct ras_node *node; + + node = ras_init_node(pdev); + if (IS_ERR(node)) + return PTR_ERR(node); + + ret = dev_set_name(&pdev->dev, "%s%d", ras_node_name[node->type], + pdev->id); + if (ret) + return ret; + + platform_set_drvdata(pdev, node); + + return 0; +} + +static struct platform_driver arm64_ras_driver = { + .driver = { + .name = "arm64_ras", + }, + .probe = arm64_ras_probe, +}; + +static int __init arm64_ras_init(void) +{ + return platform_driver_register(&arm64_ras_driver); +} +module_init(arm64_ras_init); + +static void __exit arm64_ras_exit(void) +{ + platform_driver_unregister(&arm64_ras_driver); +} +module_exit(arm64_ras_exit); + +MODULE_DESCRIPTION("ARM RAS Driver"); +MODULE_AUTHOR("Ruidong Tian "); +MODULE_LICENSE("GPL"); diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h new file mode 100644 index 0000000000000..3d83f8b26da7d --- /dev/null +++ b/drivers/ras/arm64/ras.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#ifndef _DRIVERS_RAS_ARM64_RAS_H_ +#define _DRIVERS_RAS_ARM64_RAS_H_ + +#include +#include + +#define ras_node_err(__node, format, ...) \ + dev_err((__node)->dev, "%s: " format, (__node)->name, \ + ##__VA_ARGS__) +#define ras_node_info(__node, format, ...) \ + dev_info((__node)->dev, "%s: " format, (__node)->name, \ + ##__VA_ARGS__) +#define ras_node_dbg(__node, format, ...) \ + dev_dbg((__node)->dev, "%s: " format, (__node)->name, \ + ##__VA_ARGS__) + +#define ras_record_err(__record, format, ...) \ + dev_err((__record)->node->dev, "%s: %s: " format, \ + (__record)->node->name, (__record)->name, ##__VA_ARGS__) +#define ras_record_info(__record, format, ...) \ + dev_info((__record)->node->dev, "%s: %s: " format, \ + (__record)->node->name, (__record)->name, ##__VA_ARGS__) +#define ras_record_dbg(__record, format, ...) \ + dev_dbg((__record)->node->dev, "%s: %s: " format, \ + (__record)->node->name, (__record)->name, ##__VA_ARGS__) + +#define ERXGROUP_4K_OFFSET 0xE00 +#define ERXGROUP_16K_OFFSET 0x3800 +#define ERXGROUP_64K_OFFSET 0xE000 +#define ERXGROUP_4K_SIZE SZ_4K +#define ERXGROUP_16K_SIZE SZ_16K +#define ERXGROUP_64K_SIZE SZ_64K +#define ERXGROUP_4K_ERRGSR_NUM 1 +#define ERXGROUP_16K_ERRGSR_NUM 4 +#define ERXGROUP_64K_ERRGSR_NUM 14 + +struct ras_record { + char *name; + void __iomem *regs_base; + struct ras_node *node; + + int index; +}; + +struct ras_group { + int errgsr_num; + size_t size; + u64 errgsr_offset; +}; + +extern const struct ras_group ras_group_config[]; + +struct ras_node { + char *name; + + struct device *dev; + const struct ras_group *group; + + void __iomem *base; + void __iomem *errgsr; + phys_addr_t addr; + + u8 *specific_data; + /* + * This bitmap indicates which of the error records within this error + * node must be polled for error status. + * Bit[n] of this field pertains to error record corresponding to + * index n in this error group. + * Bit[n] = 0b: Error record at index n needs to be polled. + * Bit[n] = 1b: Error record at index n does not need to be polled. + */ + unsigned long *record_implemented; + /* + * This bitmap indicates which of the error records within this error + * node support error status reporting using ERRGSR register. + * Bit[n] of this field pertains to error record corresponding to + * index n in this error group. + * Bit[n] = 0b: Error record at index n supports error status reporting + * through ERRGSR.S. + * Bit[n] = 1b: Error record at index n does not support error reporting + * through the ERRGSR.S bit. If this error record is + * implemented, then it must be polled explicitly for + * error events. + */ + unsigned long *status_reporting; + struct ras_record *records; + + u32 specific_data_size; + u32 record_count; + u32 record_index; + u32 flags; + + u8 type; + u8 group_format; +}; + +#endif /* _DRIVERS_RAS_ARM64_RAS_H_ */ diff --git a/include/linux/acpi_aest.h b/include/linux/acpi_aest.h index e485a62368914..df6369bcc96b8 100644 --- a/include/linux/acpi_aest.h +++ b/include/linux/acpi_aest.h @@ -16,4 +16,7 @@ #define AEST_XFACE_FLAG_FAULT_INJECT BIT(5) #define AEST_XFACE_FLAG_INT_CONFIG BIT(6) +#define ACPI_AEST_PROC_FLAG_GLOBAL BIT(0) +#define ACPI_AEST_PROC_FLAG_SHARED BIT(1) + #endif /* __ACPI_AEST_H__ */ From 2641cd8301f22bfa5c7e2382dca1f9064e024c5d Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:26 +0800 Subject: [PATCH 0438/1133] FROMLIST: arm64: ras: Unify the read/write interface for system and MMIO registers ARM RAS error records are reachable either through system registers (PE-affine sources) or through memory-mapped windows (off-core sources), depending on the AEST interface type. Hard-coding the choice at every call site would scatter that knowledge across the driver and double every future change. Introduce a ras_access ops table that hides the transport behind a single read/write contract, so all later error handling, masking and injection code is access-method-agnostic and can be reasoned about as plain register operations. Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- drivers/acpi/arm64/aest.c | 3 +- drivers/ras/arm64/ras-core.c | 5 +- drivers/ras/arm64/ras.h | 94 ++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/arm64/aest.c b/drivers/acpi/arm64/aest.c index 8cf24467d0c25..3a813fe7047c6 100644 --- a/drivers/acpi/arm64/aest.c +++ b/drivers/acpi/arm64/aest.c @@ -93,6 +93,7 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, } props[(*p)++] = PROPERTY_ENTRY_U8("arm,node-type", hdr->type); + props[(*p)++] = PROPERTY_ENTRY_U8("arm,interface-type", interface->type); props[(*p)++] = PROPERTY_ENTRY_U8("arm,group-format", interface->group_format); props[(*p)++] = PROPERTY_ENTRY_U32("arm,error-records-count", @@ -121,7 +122,7 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, static int __init aest_create_node_fwnode(struct acpi_aest_hdr *hdr, struct platform_device *pdev) { - struct property_entry props[10] = { }; + struct property_entry props[11] = { }; int p = 0; int ret; diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index b5448f4a841f6..47ab78cc88d7c 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -51,6 +51,7 @@ static int ras_init_record(struct ras_record *record, int i, struct ras_node *no if (node->base) record->regs_base = node->base + sizeof(struct ras_ext_regs) * i; + record->access = &ras_access[node->access_type]; record->index = i; record->node = node; @@ -152,6 +153,7 @@ static struct ras_node *ras_init_node(struct platform_device *pdev) node->dev = &pdev->dev; ret = ret ?: device_property_read_u8(dev, "arm,node-type", &node->type); + ret = ret ?: device_property_read_u8(dev, "arm,interface-type", &node->access_type); ret = ret ?: device_property_read_u8(dev, "arm,group-format", &node->group_format); ret = ret ?: device_property_read_u32(dev, "arm,interface-flags", &node->flags); ret = ret ?: device_property_read_u32(dev, "arm,error-records-count", &node->record_count); @@ -219,7 +221,8 @@ static struct ras_node *ras_init_node(struct platform_device *pdev) if (ret) return ERR_PTR(ret); } - ras_node_dbg(node, "base: %llx\n", node->addr); + ras_node_dbg(node, "base: %llx, access_type: %s\n", + node->addr, node->access_type ? "MMIO" : "Register"); return node; } diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h index 3d83f8b26da7d..94ffeb83b2515 100644 --- a/drivers/ras/arm64/ras.h +++ b/drivers/ras/arm64/ras.h @@ -11,6 +11,11 @@ #include #include +#define record_read(record, offset) \ + ((record)->access->read((record)->regs_base, (offset))) +#define record_write(record, offset, val) \ + ((record)->access->write((record)->regs_base, (offset), (val))) + #define ras_node_err(__node, format, ...) \ dev_err((__node)->dev, "%s: " format, (__node)->name, \ ##__VA_ARGS__) @@ -41,10 +46,25 @@ #define ERXGROUP_16K_ERRGSR_NUM 4 #define ERXGROUP_64K_ERRGSR_NUM 14 +#define ERXFR 0x0 +#define ERXCTLR 0x8 +#define ERXSTATUS 0x10 +#define ERXADDR 0x18 +#define ERXMISC0 0x20 +#define ERXMISC1 0x28 +#define ERXMISC2 0x30 +#define ERXMISC3 0x38 + +struct ras_access { + u64 (*read)(void __iomem *base, u32 offset); + void (*write)(void __iomem *base, u32 offset, u64 val); +}; + struct ras_record { char *name; void __iomem *regs_base; struct ras_node *node; + const struct ras_access *access; int index; }; @@ -98,7 +118,81 @@ struct ras_node { u32 flags; u8 type; + u8 access_type; u8 group_format; }; +#define CASE_READ(res, x) \ + case (x): { \ + res = read_sysreg_s(SYS_##x##_EL1); \ + break; \ + } + +#define CASE_WRITE(val, x) \ + case (x): { \ + write_sysreg_s((val), SYS_##x##_EL1); \ + break; \ + } + +static inline u64 ras_sysreg_read(void __iomem *base __always_unused, u32 offset) +{ + u64 res; + + switch (offset) { + CASE_READ(res, ERXFR) + CASE_READ(res, ERXCTLR) + CASE_READ(res, ERXSTATUS) + CASE_READ(res, ERXADDR) + CASE_READ(res, ERXMISC0) + CASE_READ(res, ERXMISC1) + CASE_READ(res, ERXMISC2) + CASE_READ(res, ERXMISC3) + default: + res = 0; + } + return res; +} + +static inline void ras_sysreg_write(void __iomem *base __always_unused, u32 offset, u64 val) +{ + switch (offset) { + CASE_WRITE(val, ERXFR) + CASE_WRITE(val, ERXCTLR) + CASE_WRITE(val, ERXSTATUS) + CASE_WRITE(val, ERXADDR) + CASE_WRITE(val, ERXMISC0) + CASE_WRITE(val, ERXMISC1) + CASE_WRITE(val, ERXMISC2) + CASE_WRITE(val, ERXMISC3) + default: + return; + } +} + +static inline u64 ras_iomem_read(void __iomem *base, u32 offset) +{ + return readq_relaxed(base + offset); +} + +static inline void ras_iomem_write(void __iomem *base, u32 offset, u64 val) +{ + writeq_relaxed(val, base + offset); +} + +/* access type is decided by AEST interface type. */ +static const struct ras_access ras_access[] = { + [ACPI_AEST_NODE_SYSTEM_REGISTER] = { + .read = ras_sysreg_read, + .write = ras_sysreg_write, + }, + [ACPI_AEST_NODE_MEMORY_MAPPED] = { + .read = ras_iomem_read, + .write = ras_iomem_write, + }, + [ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED] = { + .read = ras_iomem_read, + .write = ras_iomem_write, + }, +}; + #endif /* _DRIVERS_RAS_ARM64_RAS_H_ */ From 4ab782653919c2eb2f56f505dc8d37a7948030ff Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:27 +0800 Subject: [PATCH 0439/1133] FROMLIST: arm64: ras: Support RAS Common Fault Injection Model Extension Add inject register descripted in Common Fault Injection Model Extension. Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- drivers/acpi/arm64/aest.c | 4 +++- drivers/ras/arm64/ras-core.c | 27 +++++++++++++++++++++++++-- drivers/ras/arm64/ras.h | 10 ++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/arm64/aest.c b/drivers/acpi/arm64/aest.c index 3a813fe7047c6..868013498abba 100644 --- a/drivers/acpi/arm64/aest.c +++ b/drivers/acpi/arm64/aest.c @@ -110,6 +110,8 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, group_len); props[(*p)++] = PROPERTY_ENTRY_U64("arm,error-group-base", common->error_group_register_base); + props[(*p)++] = PROPERTY_ENTRY_U64("arm,fault-inject-base", + common->fault_inject_register_base); len = hdr->node_interface_offset - hdr->node_specific_offset; props[(*p)++] = @@ -122,7 +124,7 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, static int __init aest_create_node_fwnode(struct acpi_aest_hdr *hdr, struct platform_device *pdev) { - struct property_entry props[11] = { }; + struct property_entry props[12] = { }; int p = 0; int ret; diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index 47ab78cc88d7c..1dd4713764495 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -139,6 +139,23 @@ static int ras_node_set_errgsr(struct ras_node *node, phys_addr_t base) return 0; } +static int ras_node_set_inj_base(struct ras_node *node, phys_addr_t base) +{ + phys_addr_t inj_base = 0; + int ret = 0; + + if (!(node->flags & AEST_XFACE_FLAG_FAULT_INJECT)) + return 0; + + ret = device_property_read_u64(node->dev, "arm,fault-inject-base", + &inj_base); + if (ret || !inj_base) + return -EINVAL; + + node->inj = inj_base - base + node->base; + return 0; +} + static struct ras_node *ras_init_node(struct platform_device *pdev) { int i, ret = 0; @@ -204,6 +221,11 @@ static struct ras_node *ras_init_node(struct platform_device *pdev) ret = ras_node_set_errgsr(node, mem->start); if (ret) return ERR_PTR(ret); + ret = ras_node_set_inj_base(node, mem->start); + if (ret) + return ERR_PTR(ret); + } else if (node->access_type == ACPI_AEST_NODE_MEMORY_MAPPED) { + return ERR_PTR(-EINVAL); } node->name = alloc_ras_node_name(node); @@ -221,8 +243,9 @@ static struct ras_node *ras_init_node(struct platform_device *pdev) if (ret) return ERR_PTR(ret); } - ras_node_dbg(node, "base: %llx, access_type: %s\n", - node->addr, node->access_type ? "MMIO" : "Register"); + ras_node_dbg(node, "base: %llx, access_type: %s, %s inject\n", + node->addr, node->access_type ? "MMIO" : "Register", + node->flags & AEST_XFACE_FLAG_FAULT_INJECT ? "with" : "without"); return node; } diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h index 94ffeb83b2515..da03593e5f7f0 100644 --- a/drivers/ras/arm64/ras.h +++ b/drivers/ras/arm64/ras.h @@ -54,6 +54,9 @@ #define ERXMISC1 0x28 #define ERXMISC2 0x30 #define ERXMISC3 0x38 +#define ERXPFGF 0x800 +#define ERXPFGCTL 0x808 +#define ERXPFGCDN 0x810 struct ras_access { u64 (*read)(void __iomem *base, u32 offset); @@ -85,6 +88,7 @@ struct ras_node { void __iomem *base; void __iomem *errgsr; + void __iomem *inj; phys_addr_t addr; u8 *specific_data; @@ -147,6 +151,9 @@ static inline u64 ras_sysreg_read(void __iomem *base __always_unused, u32 offset CASE_READ(res, ERXMISC1) CASE_READ(res, ERXMISC2) CASE_READ(res, ERXMISC3) + CASE_READ(res, ERXPFGF) + CASE_READ(res, ERXPFGCTL) + CASE_READ(res, ERXPFGCDN) default: res = 0; } @@ -164,6 +171,9 @@ static inline void ras_sysreg_write(void __iomem *base __always_unused, u32 offs CASE_WRITE(val, ERXMISC1) CASE_WRITE(val, ERXMISC2) CASE_WRITE(val, ERXMISC3) + CASE_WRITE(val, ERXPFGF) + CASE_WRITE(val, ERXPFGCTL) + CASE_WRITE(val, ERXPFGCDN) default: return; } From 10cf95081eca698febde0b67e0d45d911d01e3d4 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:28 +0800 Subject: [PATCH 0440/1133] FROMLIST: arm64: ras: Plumb AEST interrupts as platform IRQ resources AEST describes one or more interrupts per error source for delivering Fault Handling (FHI) and Error Recovery (ERI) events. This change keeps the existing front-end / back-end split: - The ACPI front-end is the only place that understands AEST interrupt encodings; it registers each GSI and exposes the resulting Linux IRQs as named platform resources ("AEST:FHI" / "AEST:ERI"). - The back-end looks up its IRQs by name and requests them according to routing type. SPIs are device-shared and use a normal shared handler. PPIs are inherently per-CPU, so the node is cloned into a percpu ras_node and the handler is installed via request_percpu_irq() with that percpu cookie, ensuring each CPU services its own copy of the source. Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- drivers/acpi/arm64/aest.c | 56 +++++++++++++++++- drivers/ras/arm64/ras-core.c | 109 +++++++++++++++++++++++++++++++++++ drivers/ras/arm64/ras.h | 2 + include/linux/acpi_aest.h | 7 +++ 4 files changed, 172 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/arm64/aest.c b/drivers/acpi/arm64/aest.c index 868013498abba..af03f4365cfa6 100644 --- a/drivers/acpi/arm64/aest.c +++ b/drivers/acpi/arm64/aest.c @@ -15,6 +15,40 @@ #undef pr_fmt #define pr_fmt(fmt) "ACPI AEST: " fmt +static int acpi_aest_parse_irqs(struct platform_device *pdev, + struct acpi_aest_hdr *aest_hdr, + struct resource *res, int *res_idx) +{ + int i; + struct acpi_aest_node_interrupt_v2 *interrupt; + int trigger, irq; + + interrupt = ACPI_ADD_PTR(struct acpi_aest_node_interrupt_v2, aest_hdr, + aest_hdr->node_interrupt_offset); + for (i = 0; i < aest_hdr->node_interrupt_count; i++, interrupt++) { + trigger = (interrupt->flags & AEST_INTERRUPT_MODE) ? + ACPI_LEVEL_SENSITIVE : + ACPI_EDGE_SENSITIVE; + + irq = acpi_register_gsi(&pdev->dev, interrupt->gsiv, trigger, + ACPI_ACTIVE_HIGH); + if (irq <= 0) { + pr_err("failed to map AEST GSI %d\n", interrupt->gsiv); + return irq ? irq : -EINVAL; + } + + res[*res_idx].start = irq; + res[*res_idx].end = irq; + res[*res_idx].flags = IORESOURCE_IRQ; + res[*res_idx].name = interrupt->type ? AEST_ERI_NAME : + AEST_FHI_NAME; + + (*res_idx)++; + } + + return 0; +} + /* * Fill the per-AEST-entry inner properties (node-type / interface-type / * group-format / record bitmaps / register bases ...). @@ -25,9 +59,11 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, { struct acpi_aest_node_interface_header *interface; struct acpi_aest_node_interface_common *common = NULL; + struct acpi_aest_node_interrupt_v2 *interrupt; u64 *record_implemented = NULL; u64 *status_reporting = NULL; u64 *addressing_mode = NULL; + u32 fhi_gsiv = 0, eri_gsiv = 0; int group_len = 0, i; size_t len; @@ -72,6 +108,15 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, return -EINVAL; } + interrupt = ACPI_ADD_PTR(struct acpi_aest_node_interrupt_v2, hdr, + hdr->node_interrupt_offset); + for (i = 0; i < hdr->node_interrupt_count; i++, interrupt++) { + if (interrupt->type == ACPI_AEST_NODE_FAULT_HANDLING) + fhi_gsiv = interrupt->gsiv; + else if (interrupt->type == ACPI_AEST_NODE_ERROR_RECOVERY) + eri_gsiv = interrupt->gsiv; + } + if (interface->flags & AEST_XFACE_FLAG_ERROR_DEVICE) { struct acpi_device *companion; char uid[16]; @@ -112,6 +157,8 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, common->error_group_register_base); props[(*p)++] = PROPERTY_ENTRY_U64("arm,fault-inject-base", common->fault_inject_register_base); + props[(*p)++] = PROPERTY_ENTRY_U32("arm,fhi-gsiv", fhi_gsiv); + props[(*p)++] = PROPERTY_ENTRY_U32("arm,eri-gsiv", eri_gsiv); len = hdr->node_interface_offset - hdr->node_specific_offset; props[(*p)++] = @@ -124,7 +171,7 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, static int __init aest_create_node_fwnode(struct acpi_aest_hdr *hdr, struct platform_device *pdev) { - struct property_entry props[12] = { }; + struct property_entry props[14] = { }; int p = 0; int ret; @@ -163,7 +210,8 @@ acpi_aest_alloc_pdev(struct acpi_aest_hdr *aest_hdr) if (!pdev) return ERR_PTR(-ENOMEM); - res = kcalloc(1, sizeof(*res), GFP_KERNEL); + res = kcalloc(AEST_MAX_INTERRUPT_PER_NODE + 1, sizeof(*res), + GFP_KERNEL); if (!res) return ERR_PTR(-ENOMEM); @@ -177,6 +225,10 @@ acpi_aest_alloc_pdev(struct acpi_aest_hdr *aest_hdr) j++; } + ret = acpi_aest_parse_irqs(pdev, aest_hdr, res, &j); + if (ret) + return ERR_PTR(ret); + ret = platform_device_add_resources(pdev, res, j); if (ret) return ERR_PTR(ret); diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index 1dd4713764495..9520415df8cb3 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -5,6 +5,7 @@ * Copyright (c) 2025, Alibaba Group. */ +#include #include #include #include @@ -14,6 +15,8 @@ #undef pr_fmt #define pr_fmt(fmt) "arm64_ras: " fmt +static DEFINE_PER_CPU(struct ras_node, percpu_ras_node); + static const char *const ras_node_name[] = { [ACPI_AEST_PROCESSOR_ERROR_NODE] = "processor", [ACPI_AEST_MEMORY_ERROR_NODE] = "memory", @@ -42,6 +45,55 @@ const struct ras_group ras_group_config[] = { }, }; +static irqreturn_t ras_irq_func(int irq, void *input) +{ + struct ras_node *node = input; + + return IRQ_HANDLED; +} + +static int ras_register_irq(struct ras_node *node) +{ + int i, irq, ret; + char *irq_desc; + + irq_desc = devm_kasprintf(node->dev, GFP_KERNEL, "%s.%s.", + dev_driver_string(node->dev), + node->name); + if (!irq_desc) + return -ENOMEM; + + for (i = 0; i < AEST_MAX_INTERRUPT_PER_NODE; i++) { + irq = node->irq[i]; + + if (!irq) + continue; + + if (irq_is_percpu_devid(irq)) { + ret = request_percpu_irq(irq, ras_irq_func, irq_desc, + node->oncore_node); + if (ret) + goto free; + } else { + ret = devm_request_irq(node->dev, irq, ras_irq_func, IRQF_SHARED, + irq_desc, node); + if (ret) + return ret; + } + } + return 0; + +free: + for (i = i - 1; i >= 0; i--) { + irq = node->irq[i]; + + if (irq_is_percpu_devid(irq)) + free_percpu_irq(irq, node->oncore_node); + } + + return ret; +} + static int ras_init_record(struct ras_record *record, int i, struct ras_node *node) { record->name = devm_kasprintf(node->dev, GFP_KERNEL, "record%d", i); @@ -249,6 +301,53 @@ static struct ras_node *ras_init_node(struct platform_device *pdev) return node; } + +static int __setup_ppi(struct ras_node *node) +{ + int cpu; + struct ras_node *oncore_node; + size_t size; + + node->oncore_node = &percpu_ras_node; + for_each_possible_cpu(cpu) { + oncore_node = per_cpu_ptr(&percpu_ras_node, cpu); + memcpy(oncore_node, node, sizeof(struct ras_node)); + + oncore_node->records = devm_kcalloc( + node->dev, oncore_node->record_count, + sizeof(struct ras_record), GFP_KERNEL); + if (!oncore_node->records) + return -ENOMEM; + + size = oncore_node->record_count * + sizeof(struct ras_record); + memcpy(oncore_node->records, node->records, size); + + ras_node_dbg(node, "Init node on CPU%d.\n", cpu); + } + + return 0; +} + +static int ras_setup_irq(struct platform_device *pdev, struct ras_node *node) +{ + int fhi_irq, eri_irq; + + fhi_irq = platform_get_irq_byname_optional(pdev, AEST_FHI_NAME); + if (fhi_irq > 0) + node->irq[ACPI_AEST_NODE_FAULT_HANDLING] = fhi_irq; + + eri_irq = platform_get_irq_byname_optional(pdev, AEST_ERI_NAME); + if (eri_irq > 0) + node->irq[ACPI_AEST_NODE_ERROR_RECOVERY] = eri_irq; + + /* Allocate and initialise the percpu device pointer for PPI */ + if (irq_is_percpu(fhi_irq) || irq_is_percpu(eri_irq)) + return __setup_ppi(node); + + return 0; +} + static int arm64_ras_probe(struct platform_device *pdev) { int ret; @@ -263,6 +362,16 @@ static int arm64_ras_probe(struct platform_device *pdev) if (ret) return ret; + ret = ras_setup_irq(pdev, node); + if (ret) + return ret; + + ret = ras_register_irq(node); + if (ret) { + ras_node_err(node, "register irq failed\n"); + return ret; + } + platform_set_drvdata(pdev, node); return 0; diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h index da03593e5f7f0..b64eae59b6acc 100644 --- a/drivers/ras/arm64/ras.h +++ b/drivers/ras/arm64/ras.h @@ -85,6 +85,7 @@ struct ras_node { struct device *dev; const struct ras_group *group; + struct ras_node __percpu *oncore_node; void __iomem *base; void __iomem *errgsr; @@ -124,6 +125,7 @@ struct ras_node { u8 type; u8 access_type; u8 group_format; + u32 irq[AEST_MAX_INTERRUPT_PER_NODE]; }; #define CASE_READ(res, x) \ diff --git a/include/linux/acpi_aest.h b/include/linux/acpi_aest.h index df6369bcc96b8..a462895a7b5a7 100644 --- a/include/linux/acpi_aest.h +++ b/include/linux/acpi_aest.h @@ -6,6 +6,13 @@ /* AEST resource name */ #define AEST_NODE_NAME "AEST:NODE" +#define AEST_FHI_NAME "AEST:FHI" +#define AEST_ERI_NAME "AEST:ERI" + +/* AEST interrupt */ +#define AEST_INTERRUPT_MODE BIT(0) + +#define AEST_MAX_INTERRUPT_PER_NODE 2 /* AEST interface */ #define AEST_XFACE_FLAG_SHARED BIT(0) From a330fced88ebcf20ec48d834c24e28984790149f Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:29 +0800 Subject: [PATCH 0441/1133] FROMLIST: arm64: ras: Enable error reporting Until now, AEST nodes were registered but never had interrupt routing programmed, so probe finished without actually arming any error source. Both shared and PE (oncore) nodes need this bring-up; the difference is only that oncore state is percpu and must follow CPU online/offline. Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- arch/arm64/include/asm/ras.h | 10 +++ drivers/acpi/arm64/aest.c | 4 +- drivers/ras/arm64/ras-core.c | 159 ++++++++++++++++++++++++++++++++++- drivers/ras/arm64/ras.h | 32 +++++++ include/linux/cpuhotplug.h | 1 + 5 files changed, 204 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/ras.h b/arch/arm64/include/asm/ras.h index b6640b9972bfb..a992610d7755f 100644 --- a/arch/arm64/include/asm/ras.h +++ b/arch/arm64/include/asm/ras.h @@ -2,8 +2,18 @@ #ifndef __ASM_RAS_H #define __ASM_RAS_H +#include #include +/* ERRCTLR */ +#define ERR_CTLR_CFI BIT(8) +#define ERR_CTLR_FI BIT(3) +#define ERR_CTLR_UI BIT(2) + +/* ERRIRQCR */ +#define ERRFHICR0_OFFSET 0x0 +#define ERRERICR0_OFFSET 0x10 + struct ras_ext_regs { u64 err_fr; u64 err_ctlr; diff --git a/drivers/acpi/arm64/aest.c b/drivers/acpi/arm64/aest.c index af03f4365cfa6..5733c91c8e0d6 100644 --- a/drivers/acpi/arm64/aest.c +++ b/drivers/acpi/arm64/aest.c @@ -157,6 +157,8 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, common->error_group_register_base); props[(*p)++] = PROPERTY_ENTRY_U64("arm,fault-inject-base", common->fault_inject_register_base); + props[(*p)++] = PROPERTY_ENTRY_U64("arm,interrupt-config-base", + common->interrupt_config_register_base); props[(*p)++] = PROPERTY_ENTRY_U32("arm,fhi-gsiv", fhi_gsiv); props[(*p)++] = PROPERTY_ENTRY_U32("arm,eri-gsiv", eri_gsiv); @@ -171,7 +173,7 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, static int __init aest_create_node_fwnode(struct acpi_aest_hdr *hdr, struct platform_device *pdev) { - struct property_entry props[14] = { }; + struct property_entry props[15] = { }; int p = 0; int ret; diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index 9520415df8cb3..98f274b9731dc 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -5,6 +5,7 @@ * Copyright (c) 2025, Alibaba Group. */ +#include #include #include #include @@ -45,6 +46,21 @@ const struct ras_group ras_group_config[] = { }, }; +static void ras_node_foreach_record(void (*func)(struct ras_record *, void *), + struct ras_node *node, void *data, + unsigned long *bitmap) +{ + int i; + + for_each_clear_bit(i, bitmap, node->record_count) { + ras_select_record(node, i); + + func(&node->records[i], data); + + ras_sync(node); + } + } + static irqreturn_t ras_irq_func(int irq, void *input) { struct ras_node *node = input; @@ -52,6 +68,23 @@ static irqreturn_t ras_irq_func(int irq, void *input) return IRQ_HANDLED; } +static void ras_config_irq(struct ras_node *node) +{ + u32 fhi_gsi, eri_gsi; + + if (!node->irq_config) + return; + + if (!device_property_read_u32(node->dev, "arm,fhi-gsiv", &fhi_gsi)) + writeq_relaxed(fhi_gsi, node->irq_config + ERRFHICR0_OFFSET); + + if (!device_property_read_u32(node->dev, "arm,eri-gsiv", &eri_gsi)) + writeq_relaxed(eri_gsi, node->irq_config + ERRERICR0_OFFSET); + + ras_node_dbg(node, "config irq fhi_gsi %u eri_gsi %u at %pK", + fhi_gsi, eri_gsi, node->irq_config); +} + static int ras_register_irq(struct ras_node *node) { int i, irq, ret; @@ -94,6 +127,21 @@ static int ras_register_irq(struct ras_node *node) return ret; } +static void ras_enable_irq(struct ras_record *record) +{ + struct ras_node *node = record->node; + u64 err_ctlr; + + err_ctlr = record_read(record, ERXCTLR); + + if (node->irq[0]) + err_ctlr |= (ERR_CTLR_FI | ERR_CTLR_CFI); + if (node->irq[1]) + err_ctlr |= ERR_CTLR_UI; + + record_write(record, ERXCTLR, err_ctlr); +} + static int ras_init_record(struct ras_record *record, int i, struct ras_node *node) { record->name = devm_kasprintf(node->dev, GFP_KERNEL, "record%d", i); @@ -110,6 +158,85 @@ static int ras_init_record(struct ras_record *record, int i, struct ras_node *no return 0; } +static void ras_online_record(struct ras_record *record, void *data) +{ + ras_enable_irq(record); +} + +static void ras_online_node(struct ras_node *node) +{ + if (!node->name) + return; + + ras_config_irq(node); + + ras_node_foreach_record(ras_online_record, node, NULL, + node->record_implemented); +} + +static void ras_online_oncore_dev(void *data) +{ + int fhi_irq, eri_irq; + struct ras_node *node = this_cpu_ptr(data); + + ras_online_node(node); + + fhi_irq = node->irq[ACPI_AEST_NODE_FAULT_HANDLING]; + if (fhi_irq > 0) + enable_percpu_irq(fhi_irq, IRQ_TYPE_NONE); + eri_irq = node->irq[ACPI_AEST_NODE_ERROR_RECOVERY]; + if (eri_irq > 0) + enable_percpu_irq(eri_irq, IRQ_TYPE_NONE); +} + +static void ras_offline_oncore_dev(void *data) +{ + int fhi_irq, eri_irq; + struct ras_node *node = this_cpu_ptr(data); + + fhi_irq = node->irq[ACPI_AEST_NODE_FAULT_HANDLING]; + if (fhi_irq > 0) + disable_percpu_irq(fhi_irq); + eri_irq = node->irq[ACPI_AEST_NODE_ERROR_RECOVERY]; + if (eri_irq > 0) + disable_percpu_irq(eri_irq); +} + +static int ras_starting_cpu(unsigned int cpu) +{ + pr_debug("CPU%d starting\n", cpu); + ras_online_oncore_dev(&percpu_ras_node); + + return 0; +} + +static int ras_dying_cpu(unsigned int cpu) +{ + pr_debug("CPU%d dying\n", cpu); + ras_offline_oncore_dev(&percpu_ras_node); + + return 0; +} + +static void arm64_ras_remove(struct platform_device *pdev) +{ + struct ras_node *node = platform_get_drvdata(pdev); + int i; + + platform_set_drvdata(pdev, NULL); + + if (node->type != ACPI_AEST_PROCESSOR_ERROR_NODE) + return; + + cpuhp_remove_state(CPUHP_AP_ARM_RAS_STARTING); + on_each_cpu(ras_offline_oncore_dev, node->oncore_node, 1); + + for (i = 0; i < AEST_MAX_INTERRUPT_PER_NODE; i++) { + if (node->irq[i]) + free_percpu_irq(node->irq[i], node->oncore_node); + } +} + static char *alloc_ras_node_name(struct ras_node *node) { char *name; @@ -208,6 +335,23 @@ static int ras_node_set_inj_base(struct ras_node *node, phys_addr_t base) return 0; } +static int ras_node_set_irq_base(struct ras_node *node, phys_addr_t base) +{ + phys_addr_t irq_base; + int ret; + + if (!(node->flags & AEST_XFACE_FLAG_INT_CONFIG)) + return 0; + + ret = device_property_read_u64(node->dev, "arm,interrupt-config-base", + &irq_base); + if (ret || !irq_base) + return 0; + + node->irq_config = irq_base - base + node->base; + return 0; +} + static struct ras_node *ras_init_node(struct platform_device *pdev) { int i, ret = 0; @@ -276,6 +420,9 @@ static struct ras_node *ras_init_node(struct platform_device *pdev) ret = ras_node_set_inj_base(node, mem->start); if (ret) return ERR_PTR(ret); + ret = ras_node_set_irq_base(node, mem->start); + if (ret) + return ERR_PTR(ret); } else if (node->access_type == ACPI_AEST_NODE_MEMORY_MAPPED) { return ERR_PTR(-EINVAL); } @@ -372,6 +519,15 @@ static int arm64_ras_probe(struct platform_device *pdev) return ret; } + if (ras_node_is_oncore(node)) + ret = cpuhp_setup_state(CPUHP_AP_ARM_RAS_STARTING, + "drivers/ras/arm64/ras:starting", + ras_starting_cpu, ras_dying_cpu); + else + ras_online_node(node); + if (ret) + return ret; + platform_set_drvdata(pdev, node); return 0; @@ -381,7 +537,8 @@ static struct platform_driver arm64_ras_driver = { .driver = { .name = "arm64_ras", }, - .probe = arm64_ras_probe, + .probe = arm64_ras_probe, + .remove = arm64_ras_remove, }; static int __init arm64_ras_init(void) diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h index b64eae59b6acc..c26a0aae26c5d 100644 --- a/drivers/ras/arm64/ras.h +++ b/drivers/ras/arm64/ras.h @@ -90,6 +90,7 @@ struct ras_node { void __iomem *base; void __iomem *errgsr; void __iomem *inj; + void __iomem *irq_config; phys_addr_t addr; u8 *specific_data; @@ -126,6 +127,7 @@ struct ras_node { u8 access_type; u8 group_format; u32 irq[AEST_MAX_INTERRUPT_PER_NODE]; + u32 gsi[AEST_MAX_INTERRUPT_PER_NODE]; }; #define CASE_READ(res, x) \ @@ -207,4 +209,34 @@ static const struct ras_access ras_access[] = { }, }; +static inline bool ras_node_is_oncore(struct ras_node *node) +{ + /* + * A processor node is "on-core" (uses PPI + cpuhp) only when its + * interrupt is a per-CPU PPI. A shared processor node (e.g. cluster + * L3 cache, DSU) uses an SPI and must follow the non-oncore path + * (aest_online_dev) so that aest_config_irq and aest_online_dev are + * called instead of cpuhp_setup_state. + */ + if (node->type != ACPI_AEST_PROCESSOR_ERROR_NODE) + return false; + return irq_is_percpu(node->irq[ACPI_AEST_NODE_FAULT_HANDLING]) || + irq_is_percpu(node->irq[ACPI_AEST_NODE_ERROR_RECOVERY]); +} + +static inline void ras_select_record(struct ras_node *node, int index) +{ + if (node->type == ACPI_AEST_PROCESSOR_ERROR_NODE) { + write_sysreg_s(index, SYS_ERRSELR_EL1); + isb(); + } +} + +/* Ensure all writes has taken effect. */ +static inline void ras_sync(struct ras_node *node) +{ + if (node->type == ACPI_AEST_PROCESSOR_ERROR_NODE) + isb(); +} + #endif /* _DRIVERS_RAS_ARM64_RAS_H_ */ diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 1b6dba159bb23..b0bd85a71108b 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -178,6 +178,7 @@ enum cpuhp_state { CPUHP_AP_HYPERV_TIMER_STARTING, /* Must be the last timer callback */ CPUHP_AP_DUMMY_TIMER_STARTING, + CPUHP_AP_ARM_RAS_STARTING, CPUHP_AP_ARM_XEN_STARTING, CPUHP_AP_ARM_XEN_RUNSTATE_STARTING, CPUHP_AP_ARM64_ISNDEP_STARTING, From 62e5e466ca926116576361bce3a4c3c69f40865f Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:30 +0800 Subject: [PATCH 0442/1133] FROMLIST: arm64: ras: Add error record processing and interrupt handling Wire the IRQs registered by the front-end into a record-processing routine, so that interrupts raised by an error source actually translate into observable error events. Signed-off-by: Umang Chheda Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- arch/arm64/include/asm/ras.h | 26 +++++ drivers/ras/arm64/ras-core.c | 213 +++++++++++++++++++++++++++++++++++ include/linux/acpi_aest.h | 4 + 3 files changed, 243 insertions(+) diff --git a/arch/arm64/include/asm/ras.h b/arch/arm64/include/asm/ras.h index a992610d7755f..42900e1e9a191 100644 --- a/arch/arm64/include/asm/ras.h +++ b/arch/arm64/include/asm/ras.h @@ -5,6 +5,32 @@ #include #include +/* ERRSTATUS */ +#define ERR_STATUS_AV BIT(31) +#define ERR_STATUS_V BIT(30) +#define ERR_STATUS_UE BIT(29) +#define ERR_STATUS_ER BIT(28) +#define ERR_STATUS_OF BIT(27) +#define ERR_STATUS_MV BIT(26) +#define ERR_STATUS_CE GENMASK(25, 24) +#define ERR_STATUS_DE BIT(23) +#define ERR_STATUS_PN BIT(22) +#define ERR_STATUS_UET GENMASK(21, 20) +#define ERR_STATUS_CI BIT(19) +#define ERR_STATUS_IERR GENMASK_ULL(15, 8) +#define ERR_STATUS_SERR GENMASK_ULL(7, 0) + +/* These bits are write-one-to-clear */ +#define ERR_STATUS_W1TC \ + (ERR_STATUS_AV | ERR_STATUS_V | ERR_STATUS_UE | ERR_STATUS_ER | \ + ERR_STATUS_OF | ERR_STATUS_MV | ERR_STATUS_CE | ERR_STATUS_DE | \ + ERR_STATUS_PN | ERR_STATUS_UET | ERR_STATUS_CI) + +#define ERR_STATUS_UET_UC 0 +#define ERR_STATUS_UET_UEU 1 +#define ERR_STATUS_UET_UEO 2 +#define ERR_STATUS_UET_UER 3 + /* ERRCTLR */ #define ERR_CTLR_CFI BIT(8) #define ERR_CTLR_FI BIT(3) diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index 98f274b9731dc..8c6d202882ed4 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -16,6 +17,12 @@ #undef pr_fmt #define pr_fmt(fmt) "arm64_ras: " fmt +static bool panic_on_ue; +module_param(panic_on_ue, bool, 0600); +MODULE_PARM_DESC(aest_panic_on_ue, + "Panic on unrecoverable error: 0=off 1=on (default: 1)"); + + static DEFINE_PER_CPU(struct ras_node, percpu_ras_node); static const char *const ras_node_name[] = { @@ -46,6 +53,145 @@ const struct ras_group ras_group_config[] = { }, }; +#define AEST_LOG_PREFIX_BUFFER 64 + +static void ras_print(struct ras_record *record, struct ras_ext_regs *regs) +{ + static atomic_t seqno = { 0 }; + struct ras_node *node = record->node; + u8 *data = node->specific_data; + unsigned int curr_seqno; + char pfx_seq[AEST_LOG_PREFIX_BUFFER]; + int index = record->index; + + curr_seqno = atomic_inc_return(&seqno); + snprintf(pfx_seq, sizeof(pfx_seq), "{%u}" HW_ERR, curr_seqno); + pr_info("%sHardware error from AEST %s\n", pfx_seq, node->name); + + switch (node->type) { + case ACPI_AEST_PROCESSOR_ERROR_NODE: { + struct acpi_aest_processor *proc = (struct acpi_aest_processor *)data; + + if (proc->flags & + (ACPI_AEST_PROC_FLAG_SHARED | ACPI_AEST_PROC_FLAG_GLOBAL)) + pr_err("%s Error from shared processor resource (interrupt handled on CPU%d)\n", + pfx_seq, smp_processor_id()); + else + pr_err("%s Error from CPU%d\n", pfx_seq, smp_processor_id()); + break; + } + case ACPI_AEST_MEMORY_ERROR_NODE: + pr_err("%s Error from memory at SRAT proximity domain %#x\n", + pfx_seq, + ((struct acpi_aest_memory *)data)->srat_proximity_domain); + break; + case ACPI_AEST_SMMU_ERROR_NODE: + pr_err("%s Error from SMMU IORT node %#x subcomponent %#x\n", + pfx_seq, + ((struct acpi_aest_smmu *)data)->iort_node_reference, + ((struct acpi_aest_smmu *)data)->subcomponent_reference); + break; + case ACPI_AEST_VENDOR_ERROR_NODE: + pr_err("%s Error from vendor hid %8.8s uid %#x\n", pfx_seq, + ((struct acpi_aest_vendor_v2 *)data)->acpi_hid, + ((struct acpi_aest_vendor_v2 *)data)->acpi_uid); + break; + case ACPI_AEST_GIC_ERROR_NODE: + pr_err("%s Error from GIC type %#x instance %#x\n", pfx_seq, + ((struct acpi_aest_gic *)data)->interface_type, + ((struct acpi_aest_gic *)data)->instance_id); + break; + default: + pr_err("%s Unknown AEST node type\n", pfx_seq); + return; + } + + pr_err("%s ERR%dFR: 0x%llx\n", pfx_seq, index, regs->err_fr); + pr_err("%s ERR%dCTRL: 0x%llx\n", pfx_seq, index, regs->err_ctlr); + pr_err("%s ERR%dSTATUS: 0x%llx\n", pfx_seq, index, regs->err_status); + if (regs->err_status & ERR_STATUS_AV) + pr_err("%s ERR%dADDR: 0x%llx\n", pfx_seq, index, + regs->err_addr); + + if (regs->err_status & ERR_STATUS_MV) { + pr_err("%s ERR%dMISC0: 0x%llx\n", pfx_seq, index, + regs->err_misc[0]); + pr_err("%s ERR%dMISC1: 0x%llx\n", pfx_seq, index, + regs->err_misc[1]); + pr_err("%s ERR%dMISC2: 0x%llx\n", pfx_seq, index, + regs->err_misc[2]); + pr_err("%s ERR%dMISC3: 0x%llx\n", pfx_seq, index, + regs->err_misc[3]); + } +} + +static void ras_do_proc(struct ras_record *record, struct ras_ext_regs *regs) +{ + ras_print(record, regs); +} + +static void ras_panic(struct ras_record *record, struct ras_ext_regs *regs, + char *msg) +{ + ras_print(record, regs); + + panic(msg); +} + +static void ras_proc_record(struct ras_record *record, void *data) +{ + struct ras_ext_regs regs = { 0 }; + int *count = data; + u64 ue; + + regs.err_status = record_read(record, ERXSTATUS); + if (!(regs.err_status & ERR_STATUS_V)) + return; + + (*count)++; + + if (regs.err_status & ERR_STATUS_AV) + regs.err_addr = record_read(record, ERXADDR); + + regs.err_fr = record_read(record, ERXFR); + regs.err_ctlr = record_read(record, ERXCTLR); + + if (regs.err_status & ERR_STATUS_MV) { + regs.err_misc[0] = record_read(record, ERXMISC0); + regs.err_misc[1] = record_read(record, ERXMISC1); + if (record->node->flags & AEST_XFACE_FLAG_CLEAR_MISC) { + record_write(record, ERXMISC0, 0); + record_write(record, ERXMISC1, 0); + } + } + + /* panic if unrecoverable and uncontainable error encountered */ + ue = FIELD_GET(ERR_STATUS_UET, regs.err_status); + if ((regs.err_status & ERR_STATUS_UE) && + (ue == ERR_STATUS_UET_UC || ue == ERR_STATUS_UET_UEU)) { + if (!panic_on_ue) + ras_record_err(record, "UE detected, panic suppressed\n"); + else + ras_panic(record, ®s, + "AEST: unrecoverable error encountered"); + } + + ras_do_proc(record, ®s); + + /* Write-one-to-clear the bits we've seen */ + regs.err_status &= ERR_STATUS_W1TC; + + /* Multi bit filed need to write all-ones to clear. */ + if (regs.err_status & ERR_STATUS_CE) + regs.err_status |= ERR_STATUS_CE; + + /* Multi bit filed need to write all-ones to clear. */ + if (regs.err_status & ERR_STATUS_UET) + regs.err_status |= ERR_STATUS_UET; + + record_write(record, ERXSTATUS, regs.err_status); +} + static void ras_node_foreach_record(void (*func)(struct ras_record *, void *), struct ras_node *node, void *data, unsigned long *bitmap) @@ -59,12 +205,72 @@ static void ras_node_foreach_record(void (*func)(struct ras_record *, void *), ras_sync(node); } +} + +static void ras_node_foreach_poll_record(void (*func)(struct ras_record *, void *), + struct ras_node *node, void *data) +{ + int i; + /* + * Per AEST spec: + * - record_implemented: bitmap of records that are actually + * implemented (valid records on this node). + * - status_reporting: bitmap of records whose error status is + * reported through ERRGSR; these will be discovered via the + * ERRGSR scan path below and do not need polling. + * + * The remaining records (implemented but not reported via ERRGSR) + * must be polled one by one to detect errors. Compute that set as: + * poll_bitmap = record_implemented & ~status_reporting + */ + for_each_clear_bit(i, node->record_implemented, node->record_count) { + if (!test_bit(i, node->status_reporting)) + continue; + + ras_select_record(node, i); + + func(&node->records[i], data); + + ras_sync(node); + } +} + +static int ras_proc(struct ras_node *node) +{ + int count = 0, i, j, size = node->record_count; + u64 err_group = 0; + + ras_node_foreach_poll_record(ras_proc_record, node, &count); + + if (!node->errgsr) + return count; + + ras_node_dbg(node, "Report bitmap %*pb\n", size, node->status_reporting); + for (i = 0; i < BITS_TO_U64(size); i++) { + err_group = readq_relaxed((void *)node->errgsr + i * 8); + ras_node_dbg(node, "errgsr[%d]: 0x%llx\n", i, err_group); + + for_each_set_bit(j, (unsigned long *)&err_group, BITS_PER_LONG) { + /* + * Error group base is only valid in Memory Map node, + * so driver do not need to write select register and + * sync. + */ + if (test_bit(i * BITS_PER_LONG + j, node->status_reporting)) + continue; + ras_proc_record(&node->records[j], &count); + } } + return count; +} + static irqreturn_t ras_irq_func(int irq, void *input) { struct ras_node *node = input; + ras_proc(node); + return IRQ_HANDLED; } @@ -165,9 +371,16 @@ static void ras_online_record(struct ras_record *record, void *data) static void ras_online_node(struct ras_node *node) { + int count = 0; + if (!node->name) return; + ras_node_foreach_record(ras_proc_record, node, &count, + node->record_implemented); + + ras_node_dbg(node, "%d errors found before enabled\n", count); + ras_config_irq(node); ras_node_foreach_record(ras_online_record, node, NULL, diff --git a/include/linux/acpi_aest.h b/include/linux/acpi_aest.h index a462895a7b5a7..9cb0fcb52c39b 100644 --- a/include/linux/acpi_aest.h +++ b/include/linux/acpi_aest.h @@ -9,6 +9,10 @@ #define AEST_FHI_NAME "AEST:FHI" #define AEST_ERI_NAME "AEST:ERI" +/* AEST component */ +#define ACPI_AEST_PROC_FLAG_GLOBAL BIT(0) +#define ACPI_AEST_PROC_FLAG_SHARED BIT(1) + /* AEST interrupt */ #define AEST_INTERRUPT_MODE BIT(0) From bdc24ce01c50eeddd28e7a27904f9a8e96593ca1 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:31 +0800 Subject: [PATCH 0443/1133] FROMLIST: arm64: ras: Handle memory failure for uncorrectable errors When an uncorrectable error (UE/DE) is detected and the error record reports a System Physical Address (SPA), invoke memory_failure() to offline the affected page. This prevents further consumption of corrupted data. Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- arch/arm64/include/asm/ras.h | 4 ++++ drivers/acpi/arm64/aest.c | 5 ++++- drivers/ras/arm64/ras-core.c | 21 +++++++++++++++++++++ drivers/ras/arm64/ras.h | 26 ++++++++++++++++++++++++++ include/linux/acpi_aest.h | 3 +++ 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/ras.h b/arch/arm64/include/asm/ras.h index 42900e1e9a191..7bef631a395cb 100644 --- a/arch/arm64/include/asm/ras.h +++ b/arch/arm64/include/asm/ras.h @@ -31,6 +31,10 @@ #define ERR_STATUS_UET_UEO 2 #define ERR_STATUS_UET_UER 3 +/* ERRADDR */ +#define ERR_ADDR_AI BIT(61) +#define ERR_ADDR_PADDR GENMASK_ULL(55, 0) + /* ERRCTLR */ #define ERR_CTLR_CFI BIT(8) #define ERR_CTLR_FI BIT(3) diff --git a/drivers/acpi/arm64/aest.c b/drivers/acpi/arm64/aest.c index 5733c91c8e0d6..1b020ab7eccd5 100644 --- a/drivers/acpi/arm64/aest.c +++ b/drivers/acpi/arm64/aest.c @@ -153,6 +153,9 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, props[(*p)++] = PROPERTY_ENTRY_U64_ARRAY_LEN("arm,status-reporting", status_reporting, group_len); + props[(*p)++] = PROPERTY_ENTRY_U64_ARRAY_LEN("arm,addressing-mode", + addressing_mode, + group_len); props[(*p)++] = PROPERTY_ENTRY_U64("arm,error-group-base", common->error_group_register_base); props[(*p)++] = PROPERTY_ENTRY_U64("arm,fault-inject-base", @@ -173,7 +176,7 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, static int __init aest_create_node_fwnode(struct acpi_aest_hdr *hdr, struct platform_device *pdev) { - struct property_entry props[15] = { }; + struct property_entry props[16] = { }; int p = 0; int ret; diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index 8c6d202882ed4..babb390b795f4 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -127,7 +127,17 @@ static void ras_print(struct ras_record *record, struct ras_ext_regs *regs) static void ras_do_proc(struct ras_record *record, struct ras_ext_regs *regs) { + u64 status = regs->err_status, addr = regs->err_addr; + ras_print(record, regs); + + if (status & ERR_STATUS_CE) + return; + + if (record->addressing_mode == AEST_ADDRESS_LA || (addr & ERR_ADDR_AI)) + return; + + memory_failure_queue(addr & PHYS_MASK, 0); } static void ras_panic(struct ras_record *record, struct ras_ext_regs *regs, @@ -360,7 +370,10 @@ static int ras_init_record(struct ras_record *record, int i, struct ras_node *no record->access = &ras_access[node->access_type]; record->index = i; record->node = node; + record->addressing_mode = test_bit(i, node->addressing_mode); + ras_record_dbg(record, "record initialized, addressing mode: %s\n", + record->addressing_mode ? "LA" : "SPA"); return 0; } @@ -598,6 +611,11 @@ static struct ras_node *ras_init_node(struct platform_device *pdev) GFP_KERNEL); if (!node->status_reporting) return ERR_PTR(-ENOMEM); + node->addressing_mode = devm_bitmap_zalloc(dev, + node->group->errgsr_num * BITS_PER_TYPE(u64), + GFP_KERNEL); + if (!node->addressing_mode) + return ERR_PTR(-ENOMEM); ret = device_property_read_u64_array(dev, "arm,record-implemented", (u64 *)node->record_implemented, @@ -605,6 +623,9 @@ static struct ras_node *ras_init_node(struct platform_device *pdev) ret = ret ?: device_property_read_u64_array(dev, "arm,status-reporting", (u64 *)node->status_reporting, node->group->errgsr_num); + ret = ret ?: device_property_read_u64_array(dev, "arm,addressing-mode", + (u64 *)node->addressing_mode, + node->group->errgsr_num); if (ret) return ERR_PTR(ret); diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h index c26a0aae26c5d..11c6def1e4bf9 100644 --- a/drivers/ras/arm64/ras.h +++ b/drivers/ras/arm64/ras.h @@ -70,6 +70,16 @@ struct ras_record { const struct ras_access *access; int index; + /* + * This bit specifies the addressing mode to populate the ERR_ADDR + * register: + * 0b: Error record reports System Physical Addresses (SPA) in + * the ERR_ADDR register. + * 1b: Error record reports error node-specific Logical Addresses (LA) + * in the ERR_ADDR register. OS must use other means to translate + * the reported LA into SPA. + */ + int addressing_mode; }; struct ras_group { @@ -116,6 +126,22 @@ struct ras_node { * error events. */ unsigned long *status_reporting; + /* + * This bitmap specifies the addressing mode used by each + * error record within this error node to populate the + * ERR_ADDR register. + * Bit[n] of this field pertains to error record corresponding + * to index n in the error group. + * Bit[n] = 0b: Error record at index n reports System + * Physical Addresses (SPA) in the ERR_ADDR + * register. + * Bit[n] = 1b: Error record at index n reports error + * node-specific Logical Addresses (LA) in the + * ERR_ADDR register. + * OS must use other means to translate the reported LA + * into SPA + */ + unsigned long *addressing_mode; struct ras_record *records; u32 specific_data_size; diff --git a/include/linux/acpi_aest.h b/include/linux/acpi_aest.h index 9cb0fcb52c39b..9a8aa234d9e5b 100644 --- a/include/linux/acpi_aest.h +++ b/include/linux/acpi_aest.h @@ -13,6 +13,9 @@ #define ACPI_AEST_PROC_FLAG_GLOBAL BIT(0) #define ACPI_AEST_PROC_FLAG_SHARED BIT(1) +#define AEST_ADDRESS_SPA 0 +#define AEST_ADDRESS_LA 1 + /* AEST interrupt */ #define AEST_INTERRUPT_MODE BIT(0) From 6c56e0aa5631bb4e109f967e9bd89f1f02fe55c4 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:32 +0800 Subject: [PATCH 0444/1133] FROMLIST: arm64: ras: Probe RAS architecture version The RAS version of a component can be probed via its ERRDEVARCH register. In cases where a component (e.g., SMMU) does not implement an ERRDEVARCH register, the driver falls back to using the RAS version of the Processing Element (PE). Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- arch/arm64/include/asm/ras.h | 3 +++ drivers/ras/arm64/ras-core.c | 25 +++++++++++++++++++++++++ drivers/ras/arm64/ras.h | 3 +++ 3 files changed, 31 insertions(+) diff --git a/arch/arm64/include/asm/ras.h b/arch/arm64/include/asm/ras.h index 7bef631a395cb..5b938ff03e746 100644 --- a/arch/arm64/include/asm/ras.h +++ b/arch/arm64/include/asm/ras.h @@ -44,6 +44,9 @@ #define ERRFHICR0_OFFSET 0x0 #define ERRERICR0_OFFSET 0x10 +/* ERRDEVARCH */ +#define ERRDEVARCH_REV GENMASK(19, 16) + struct ras_ext_regs { u64 err_fr; u64 err_ctlr; diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index babb390b795f4..9fbc98e89f159 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -169,9 +169,18 @@ static void ras_proc_record(struct ras_record *record, void *data) if (regs.err_status & ERR_STATUS_MV) { regs.err_misc[0] = record_read(record, ERXMISC0); regs.err_misc[1] = record_read(record, ERXMISC1); + if (record->node->version >= ID_AA64PFR0_EL1_RAS_V1P1) { + regs.err_misc[2] = record_read(record, ERXMISC2); + regs.err_misc[3] = record_read(record, ERXMISC3); + } + if (record->node->flags & AEST_XFACE_FLAG_CLEAR_MISC) { record_write(record, ERXMISC0, 0); record_write(record, ERXMISC1, 0); + if (record->node->version >= ID_AA64PFR0_EL1_RAS_V1P1) { + record_write(record, ERXMISC2, 0); + record_write(record, ERXMISC3, 0); + } } } @@ -358,6 +367,21 @@ static void ras_enable_irq(struct ras_record *record) record_write(record, ERXCTLR, err_ctlr); } +static int get_ras_node_ver(struct ras_node *node) +{ + u32 reg; + + if (node->type == ACPI_AEST_GIC_ERROR_NODE) { + if (!node->base) + return 0; + + reg = readl_relaxed(node->base + GIC_ERRDEVARCH); + return FIELD_GET(ERRDEVARCH_REV, reg); + } + + return FIELD_GET(ID_AA64PFR0_EL1_RAS_MASK, read_cpuid(ID_AA64PFR0_EL1)); +} + static int ras_init_record(struct ras_record *record, int i, struct ras_node *node) { record->name = devm_kasprintf(node->dev, GFP_KERNEL, "record%d", i); @@ -665,6 +689,7 @@ static struct ras_node *ras_init_node(struct platform_device *pdev) if (!node->name) return ERR_PTR(-ENOMEM); + node->version = get_ras_node_ver(node); node->records = devm_kcalloc(node->dev, node->record_count, sizeof(struct ras_record), GFP_KERNEL); if (!node->records) diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h index 11c6def1e4bf9..03d1b498acc44 100644 --- a/drivers/ras/arm64/ras.h +++ b/drivers/ras/arm64/ras.h @@ -58,6 +58,8 @@ #define ERXPFGCTL 0x808 #define ERXPFGCDN 0x810 +#define GIC_ERRDEVARCH 0xFFBC + struct ras_access { u64 (*read)(void __iomem *base, u32 offset); void (*write)(void __iomem *base, u32 offset, u64 val); @@ -148,6 +150,7 @@ struct ras_node { u32 record_count; u32 record_index; u32 flags; + int version; u8 type; u8 access_type; From 316392c0d61952df81928482f5057a15ad1dc3dc Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:33 +0800 Subject: [PATCH 0445/1133] FROMLIST: arm64: ras: Support CE threshold of error record The CE threshold defines the number of Correctable Errors (CE) that must occur in a record before triggering an interrupt. Error records support multiple threshold configurations, including 8B, 16B, and 32B. This patch detects the supported threshold settings for error records and sets the default threshold to 1, ensuring an interrupt is generated for every CE occurrence. Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- arch/arm64/include/asm/ras.h | 41 +++++++++++++++++ drivers/ras/arm64/ras-core.c | 85 +++++++++++++++++++++++++++++++++++- drivers/ras/arm64/ras.h | 18 ++++++++ 3 files changed, 143 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/ras.h b/arch/arm64/include/asm/ras.h index 5b938ff03e746..ae67cfcc214ea 100644 --- a/arch/arm64/include/asm/ras.h +++ b/arch/arm64/include/asm/ras.h @@ -5,6 +5,39 @@ #include #include +/* ERRFR */ +#define ERR_FR_CE GENMASK_ULL(54, 53) +#define ERR_FR_RP BIT(15) +#define ERR_FR_CEC GENMASK_ULL(14, 12) + +#define ERR_FR_RP_SINGLE_COUNTER 0 +#define ERR_FR_RP_DOUBLE_COUNTER 1 + +#define ERR_FR_CEC_0B_COUNTER 0 +#define ERR_FR_CEC_8B_COUNTER BIT(1) +#define ERR_FR_CEC_16B_COUNTER BIT(2) + +/* ERRMISC0 */ + +/* ERRFR.CEC == 0b010, ERRFR.RP == 0 */ +#define ERR_MISC0_8B_OF BIT(39) +#define ERR_MISC0_8B_CEC GENMASK_ULL(38, 32) + +/* ERRFR.CEC == 0b100, ERRFR.RP == 0 */ +#define ERR_MISC0_16B_OF BIT(47) +#define ERR_MISC0_16B_CEC GENMASK_ULL(46, 32) + +#define ERR_MISC0_CEC_SHIFT 32 + +#define ERR_8B_CEC_MAX (ERR_MISC0_8B_CEC >> ERR_MISC0_CEC_SHIFT) +#define ERR_16B_CEC_MAX (ERR_MISC0_16B_CEC >> ERR_MISC0_CEC_SHIFT) + +/* ERRFR.CEC == 0b100, ERRFR.RP == 1 */ +#define ERR_MISC0_16B_OFO BIT(63) +#define ERR_MISC0_16B_CECO GENMASK_ULL(62, 48) +#define ERR_MISC0_16B_OFR BIT(47) +#define ERR_MISC0_16B_CECR GENMASK_ULL(46, 32) + /* ERRSTATUS */ #define ERR_STATUS_AV BIT(31) #define ERR_STATUS_V BIT(30) @@ -47,6 +80,14 @@ /* ERRDEVARCH */ #define ERRDEVARCH_REV GENMASK(19, 16) +enum ras_ce_threshold { + RAS_CE_THRESHOLD_0B, + RAS_CE_THRESHOLD_8B, + RAS_CE_THRESHOLD_16B, + RAS_CE_THRESHOLD_32B, + RAS_CE_THRESHOLD_UNKNOWN, +}; + struct ras_ext_regs { u64 err_fr; u64 err_ctlr; diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index 9fbc98e89f159..94514a5bb973d 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -53,6 +53,20 @@ const struct ras_group ras_group_config[] = { }, }; +static const struct ce_threshold_info ce_info[] = { + [RAS_CE_THRESHOLD_0B] = { 0 }, + [RAS_CE_THRESHOLD_8B] = { + .max_count = ERR_8B_CEC_MAX, + .mask = ERR_MISC0_8B_CEC, + .shift = ERR_MISC0_CEC_SHIFT, + }, + [RAS_CE_THRESHOLD_16B] = { + .max_count = ERR_16B_CEC_MAX, + .mask = ERR_MISC0_16B_CEC, + .shift = ERR_MISC0_CEC_SHIFT, + }, +}; + #define AEST_LOG_PREFIX_BUFFER 64 static void ras_print(struct ras_record *record, struct ras_ext_regs *regs) @@ -174,8 +188,8 @@ static void ras_proc_record(struct ras_record *record, void *data) regs.err_misc[3] = record_read(record, ERXMISC3); } + record_write(record, ERXMISC0, record->ce.reg_val); if (record->node->flags & AEST_XFACE_FLAG_CLEAR_MISC) { - record_write(record, ERXMISC0, 0); record_write(record, ERXMISC1, 0); if (record->node->version >= ID_AA64PFR0_EL1_RAS_V1P1) { record_write(record, ERXMISC2, 0); @@ -367,6 +381,73 @@ static void ras_enable_irq(struct ras_record *record) record_write(record, ERXCTLR, err_ctlr); } +static int ras_get_ce_threshold(struct ras_record *record) +{ + u64 err_fr, err_fr_cec, err_fr_rp; + + err_fr = record_read(record, ERXFR); + err_fr_cec = FIELD_GET(ERR_FR_CEC, err_fr); + err_fr_rp = FIELD_GET(ERR_FR_RP, err_fr); + + if (err_fr_cec == ERR_FR_CEC_0B_COUNTER) + return RAS_CE_THRESHOLD_0B; + else if (err_fr_rp == ERR_FR_RP_DOUBLE_COUNTER) + return RAS_CE_THRESHOLD_32B; + else if (err_fr_cec == ERR_FR_CEC_8B_COUNTER) + return RAS_CE_THRESHOLD_8B; + else if (err_fr_cec == ERR_FR_CEC_16B_COUNTER) + return RAS_CE_THRESHOLD_16B; + + return RAS_CE_THRESHOLD_UNKNOWN; +} + +static void ras_set_ce_threshold(struct ras_record *record) +{ + u64 err_misc0; + struct ce_threshold *ce = &record->ce; + const struct ce_threshold_info *info; + + record->threshold_type = ras_get_ce_threshold(record); + + switch (record->threshold_type) { + case RAS_CE_THRESHOLD_0B: + ras_record_dbg(record, "do not support CE threshold!\n"); + return; + case RAS_CE_THRESHOLD_8B: + ras_record_dbg(record, "support 8 bit CE threshold!\n"); + break; + case RAS_CE_THRESHOLD_16B: + ras_record_dbg(record, "support 16 bit CE threshold!\n"); + break; + case RAS_CE_THRESHOLD_32B: + ras_record_dbg(record, "not support 32 bit CE threshold!\n"); + return; + default: + ras_record_dbg(record, "Unknown misc0 ce threshold!\n"); + return; + } + + err_misc0 = record_read(record, ERXMISC0); + info = &ce_info[record->threshold_type]; + ce->info = info; + + /* Default CE threshold is 1 */ + ce->threshold = DEFAULT_CE_THRESHOLD; + /* + * The CEC field in ERXMISC0 is a saturating up-counter; the + * overflow flag (ERXSTATUS.OF) is asserted only when CEC + * saturates at max_count. To make "threshold" mean "trigger OF + * after `threshold` more CEs", preset CEC to max_count - threshold. + */ + ce->count = info->max_count - ce->threshold + 1; + ce->reg_val = (err_misc0 & ~info->mask) | + (ce->count << info->shift); + + record_write(record, ERXMISC0, ce->reg_val); + ras_record_dbg(record, "CE threshold is %llu, controlled by Kernel", + ce->threshold); +} + static int get_ras_node_ver(struct ras_node *node) { u32 reg; @@ -382,6 +463,7 @@ static int get_ras_node_ver(struct ras_node *node) return FIELD_GET(ID_AA64PFR0_EL1_RAS_MASK, read_cpuid(ID_AA64PFR0_EL1)); } + static int ras_init_record(struct ras_record *record, int i, struct ras_node *node) { record->name = devm_kasprintf(node->dev, GFP_KERNEL, "record%d", i); @@ -403,6 +485,7 @@ static int ras_init_record(struct ras_record *record, int i, struct ras_node *no static void ras_online_record(struct ras_record *record, void *data) { + ras_set_ce_threshold(record); ras_enable_irq(record); } diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h index 03d1b498acc44..ac3876912495a 100644 --- a/drivers/ras/arm64/ras.h +++ b/drivers/ras/arm64/ras.h @@ -11,6 +11,8 @@ #include #include +#define DEFAULT_CE_THRESHOLD 1 + #define record_read(record, offset) \ ((record)->access->read((record)->regs_base, (offset))) #define record_write(record, offset, val) \ @@ -65,12 +67,28 @@ struct ras_access { void (*write)(void __iomem *base, u32 offset, u64 val); }; +struct ce_threshold_info { + u64 max_count; + u64 mask; + u64 shift; +}; + +struct ce_threshold { + const struct ce_threshold_info *info; + u64 count; + u64 threshold; + u64 reg_val; +}; + struct ras_record { char *name; void __iomem *regs_base; struct ras_node *node; const struct ras_access *access; + struct ce_threshold ce; + enum ras_ce_threshold threshold_type; + int index; /* * This bit specifies the addressing mode to populate the ERR_ADDR From 9aed763d52e11d405277965d4a2dbacccbd9bd39 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:34 +0800 Subject: [PATCH 0446/1133] FROMLIST: arm64: ras: Add RAS decode notifier chain Introduce a blocking notifier chain that allows external modules (e.g., EDAC drivers, vendor-specific decoders) to receive and further decode RAS error events. Each error event is passed to all registered decoders after being logged. Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- drivers/ras/arm64/ras-core.c | 15 +++++++++++++++ include/linux/ras.h | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index 94514a5bb973d..0b07b69545ad1 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -139,11 +139,26 @@ static void ras_print(struct ras_record *record, struct ras_ext_regs *regs) } } +static ATOMIC_NOTIFIER_HEAD(ras_decoder_chain); + +void ras_register_decode_chain(struct notifier_block *nb) +{ + atomic_notifier_chain_register(&ras_decoder_chain, nb); +} +EXPORT_SYMBOL_GPL(ras_register_decode_chain); + +void ras_unregister_decode_chain(struct notifier_block *nb) +{ + atomic_notifier_chain_unregister(&ras_decoder_chain, nb); +} +EXPORT_SYMBOL_GPL(ras_unregister_decode_chain); + static void ras_do_proc(struct ras_record *record, struct ras_ext_regs *regs) { u64 status = regs->err_status, addr = regs->err_addr; ras_print(record, regs); + atomic_notifier_call_chain(&ras_decoder_chain, 0, record); if (status & ERR_STATUS_CE) return; diff --git a/include/linux/ras.h b/include/linux/ras.h index 468941bfe855f..11663150612f5 100644 --- a/include/linux/ras.h +++ b/include/linux/ras.h @@ -63,4 +63,12 @@ amd_convert_umc_mca_addr_to_sys_addr(struct atl_err *err) { return -EINVAL; } #define GET_LOGICAL_INDEX(mpidr) -EINVAL #endif /* CONFIG_ARM || CONFIG_ARM64 */ +#if IS_ENABLED(CONFIG_ARM64_RAS_DRIVER) +void ras_register_decode_chain(struct notifier_block *nb); +void ras_unregister_decode_chain(struct notifier_block *nb); +#else +static inline void ras_register_decode_chain(struct notifier_block *nb) {} +static inline void ras_unregister_decode_chain(struct notifier_block *nb) {} +#endif /* CONFIG_ARM64_RAS_DRIVER */ + #endif /* __RAS_H__ */ From 62f2d2bdea3fbae92791ce34c15f939edf884a2d Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:35 +0800 Subject: [PATCH 0447/1133] FROMLIST: arm64: ras: Expose config abi through debugfs Expose per-node and per-record configuration through debugfs so bring-up and validation can inspect and tweak driver state (CE threshold, error counters, ...) at runtime. Signed-off-by: Umang Chheda Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- Documentation/ABI/testing/debugfs-arm64-ras | 50 +++++ MAINTAINERS | 1 + drivers/ras/arm64/Makefile | 1 + drivers/ras/arm64/ras-core.c | 31 +++ drivers/ras/arm64/ras-sysfs.c | 211 ++++++++++++++++++++ drivers/ras/arm64/ras.h | 17 ++ drivers/ras/debugfs.c | 3 +- include/linux/ras.h | 2 + 8 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/debugfs-arm64-ras create mode 100644 drivers/ras/arm64/ras-sysfs.c diff --git a/Documentation/ABI/testing/debugfs-arm64-ras b/Documentation/ABI/testing/debugfs-arm64-ras new file mode 100644 index 0000000000000..d86bde83d0b94 --- /dev/null +++ b/Documentation/ABI/testing/debugfs-arm64-ras @@ -0,0 +1,50 @@ +What: /sys/kernel/debug/ras/arm64// +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + Directory representing a RAS node device, means device + type, like: + + - processor + - memory + - smmu + - ... + +What: /sys/kernel/debug/ras/arm64//record/err_* +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + (RW) Read/Write err_* register. + +What: /sys/kernel/debug/ras/arm64//err_count +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + (RO) Outputs error statistics for all error records of this node. + + +What: /sys/kernel/debug/ras/arm64//record/err_count +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + (RO) Outputs error statistics for this record. + +What: /sys/kernel/debug/ras/arm64//ce_threshold +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + (WO) Write the CE threshold to all records of this node. + Returns error if input exceeded the maximum threshold. + +What: /sys/kernel/debug/ras/arm64//record/ce_threshold +Date: Dec 2025 +KernelVersion: 6.19 +Contact: Ruidong Tian +Description: + (RW) Read and write the CE threshold to this record. + Returns error if input exceeded the maximum threshold. \ No newline at end of file diff --git a/MAINTAINERS b/MAINTAINERS index dd5350a01163c..15e33c329f0b3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -364,6 +364,7 @@ M: Ruidong Tian L: linux-acpi@vger.kernel.org L: linux-arm-kernel@lists.infradead.org S: Supported +F: Documentation/ABI/testing/debugfs-arm64-ras F: arch/arm64/include/asm/ras.h F: drivers/acpi/arm64/aest.c F: drivers/ras/arm64/ diff --git a/drivers/ras/arm64/Makefile b/drivers/ras/arm64/Makefile index c5387f05a067e..e13e223107dda 100644 --- a/drivers/ras/arm64/Makefile +++ b/drivers/ras/arm64/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_ARM64_RAS_DRIVER) += arm64_ras.o arm64_ras-y := ras-core.o +arm64_ras-y += ras-sysfs.o diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index 0b07b69545ad1..c427c131a8620 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -25,6 +25,8 @@ MODULE_PARM_DESC(aest_panic_on_ue, static DEFINE_PER_CPU(struct ras_node, percpu_ras_node); +struct dentry *arm64_ras_debugfs; + static const char *const ras_node_name[] = { [ACPI_AEST_PROCESSOR_ERROR_NODE] = "processor", [ACPI_AEST_MEMORY_ERROR_NODE] = "memory", @@ -158,6 +160,27 @@ static void ras_do_proc(struct ras_record *record, struct ras_ext_regs *regs) u64 status = regs->err_status, addr = regs->err_addr; ras_print(record, regs); + if (regs->err_status & ERR_STATUS_CE) + record->count.ce++; + if (regs->err_status & ERR_STATUS_DE) + record->count.de++; + if (regs->err_status & ERR_STATUS_UE) { + switch (FIELD_GET(ERR_STATUS_UET, regs->err_status)) { + case ERR_STATUS_UET_UC: + record->count.uc++; + break; + case ERR_STATUS_UET_UEU: + record->count.ueu++; + break; + case ERR_STATUS_UET_UER: + record->count.uer++; + break; + case ERR_STATUS_UET_UEO: + record->count.ueo++; + break; + } + } + atomic_notifier_call_chain(&ras_decoder_chain, 0, record); if (status & ERR_STATUS_CE) @@ -887,6 +910,8 @@ static int arm64_ras_probe(struct platform_device *pdev) platform_set_drvdata(pdev, node); + ras_node_init_debugfs(node); + return 0; } @@ -900,12 +925,18 @@ static struct platform_driver arm64_ras_driver = { static int __init arm64_ras_init(void) { +#ifdef CONFIG_DEBUG_FS + arm64_ras_debugfs = debugfs_create_dir("arm64", ras_debugfs_dir); +#endif return platform_driver_register(&arm64_ras_driver); } module_init(arm64_ras_init); static void __exit arm64_ras_exit(void) { +#ifdef CONFIG_DEBUG_FS + debugfs_remove_recursive(arm64_ras_debugfs); +#endif platform_driver_unregister(&arm64_ras_driver); } module_exit(arm64_ras_exit); diff --git a/drivers/ras/arm64/ras-sysfs.c b/drivers/ras/arm64/ras-sysfs.c new file mode 100644 index 0000000000000..03cc00b820e2d --- /dev/null +++ b/drivers/ras/arm64/ras-sysfs.c @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2025, Alibaba Group. + */ + +#include "ras.h" + +static int ras_store_threshold(struct ras_record *record, u64 threshold) +{ + struct ce_threshold *ce = &record->ce; + u64 err_misc0; + + if (!ce->info) + return -EOPNOTSUPP; + + if (threshold > ce->info->max_count) + return -EINVAL; + + ce->threshold = threshold; + ce->count = ce->info->max_count - threshold + 1; + + err_misc0 = record_read(record, ERXMISC0); + ce->reg_val = (err_misc0 & ~ce->info->mask) | + (ce->count << ce->info->shift); + + record_write(record, ERXMISC0, ce->reg_val); + return 0; +} + +static void ras_error_count(struct ras_record *record, struct record_count *count) +{ + count->ce += record->count.ce; + count->de += record->count.de; + count->uc += record->count.uc; + count->ueu += record->count.ueu; + count->uer += record->count.uer; + count->ueo += record->count.ueo; +} + +/* Debugfs for RAS node */ + +static int ras_node_err_count_show(struct seq_file *m, void *data) +{ + struct ras_node *node = m->private; + struct record_count count = { 0 }; + int i; + + for (i = 0; i < node->record_count; i++) + if (!test_bit(i, node->record_implemented)) + ras_error_count(&node->records[i], &count); + + seq_printf(m, "CE: %llu\n" + "DE: %llu\n" + "UC: %llu\n" + "UEU: %llu\n" + "UEO: %llu\n" + "UER: %llu\n", + count.ce, count.de, count.uc, count.ueu, + count.uer, count.ueo); + return 0; +} +DEFINE_SHOW_ATTRIBUTE(ras_node_err_count); + +/* Attribute for RAS record */ + +#define DEFINE_RAS_DEBUGFS_ATTR(name, offset) \ +static int name##_get(void *data, u64 *val) \ +{ \ + struct ras_record *record = data; \ + *val = record_read(record, offset); \ + return 0; \ +} \ +static int name##_set(void *data, u64 val) \ +{ \ + struct ras_record *record = data; \ + record_write(record, offset, val); \ + return 0; \ +} \ +DEFINE_DEBUGFS_ATTRIBUTE(name##_ops, name##_get, name##_set, "%#llx\n") + +DEFINE_RAS_DEBUGFS_ATTR(err_fr, ERXFR); +DEFINE_RAS_DEBUGFS_ATTR(err_ctrl, ERXCTLR); + +static int record_ce_threshold_get(void *data, u64 *val) +{ + struct ras_record *record = data; + + *val = record->ce.threshold; + return 0; +} + +static int record_ce_threshold_set(void *data, u64 val) +{ + struct ras_record *record = data; + + return ras_store_threshold(record, val); +} + +DEFINE_DEBUGFS_ATTRIBUTE(record_ce_threshold_ops, record_ce_threshold_get, + record_ce_threshold_set, "%llu\n"); + +/* Node-level ce_threshold: write threshold to all records of this node */ + +static int node_ce_threshold_set(void *data, u64 val) +{ + struct ras_node *node = data; + int i, ret, last_err = -EOPNOTSUPP; + + for (i = 0; i < node->record_count; i++) { + ret = ras_store_threshold(&node->records[i], val); + if (ret == 0) + last_err = 0; + else if (ret == -EINVAL) + return ret; + } + + return last_err; +} + +DEFINE_DEBUGFS_ATTRIBUTE(node_ce_threshold_ops, NULL, + node_ce_threshold_set, "%llu\n"); + +static int ras_record_err_count_show(struct seq_file *m, void *data) +{ + struct ras_record *record = m->private; + struct record_count count = { 0 }; + + ras_error_count(record, &count); + + seq_printf(m, "CE: %llu\n" + "DE: %llu\n" + "UC: %llu\n" + "UEU: %llu\n" + "UEO: %llu\n" + "UER: %llu\n", + count.ce, count.de, count.uc, count.ueu, + count.uer, count.ueo); + return 0; +} +DEFINE_SHOW_ATTRIBUTE(ras_record_err_count); + +static void ras_record_init_debugfs(struct ras_record *record) +{ + debugfs_create_file("err_fr", 0600, record->debugfs, + record, &err_fr_ops); + debugfs_create_file("err_ctrl", 0600, record->debugfs, + record, &err_ctrl_ops); + debugfs_create_file("err_count", 0400, record->debugfs, + record, &ras_record_err_count_fops); + debugfs_create_file("ce_threshold", 0600, record->debugfs, + record, &record_ce_threshold_ops); +} + +static void ras_init_records_debugfs(struct ras_node *node) +{ + struct ras_record *record; + int i; + + for (i = 0; i < node->record_count; i++) { + record = &node->records[i]; + if (!record->name || test_bit(i, node->record_implemented)) + continue; + record->debugfs = debugfs_create_dir(record->name, + node->debugfs); + + ras_record_init_debugfs(record); + } +} + +static void ras_oncore_node_init_debugfs(struct ras_node *node) +{ + int cpu; + struct ras_node *percpu_node; + char name[16]; + + for_each_possible_cpu(cpu) { + percpu_node = per_cpu_ptr(node->oncore_node, cpu); + + snprintf(name, sizeof(name), "processor%u", cpu); + percpu_node->debugfs = debugfs_create_dir(name, arm64_ras_debugfs); + + debugfs_create_file("err_count", 0400, percpu_node->debugfs, + percpu_node, &ras_node_err_count_fops); + debugfs_create_file("ce_threshold", 0200, percpu_node->debugfs, + percpu_node, &node_ce_threshold_ops); + ras_init_records_debugfs(percpu_node); + } +} + +void ras_node_init_debugfs(struct ras_node *node) +{ + if (!node->name) + return; + + if (ras_node_is_oncore(node)) { + ras_oncore_node_init_debugfs(node); + return; + } + + node->debugfs = debugfs_create_dir(node->name, arm64_ras_debugfs); + if (IS_ERR_OR_NULL(node->debugfs)) + return; + + debugfs_create_file("err_count", 0400, node->debugfs, + node, &ras_node_err_count_fops); + debugfs_create_file("ce_threshold", 0200, node->debugfs, + node, &node_ce_threshold_ops); + ras_init_records_debugfs(node); +} diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h index ac3876912495a..92cbb975b4df9 100644 --- a/drivers/ras/arm64/ras.h +++ b/drivers/ras/arm64/ras.h @@ -10,6 +10,7 @@ #include #include +#include #define DEFAULT_CE_THRESHOLD 1 @@ -62,6 +63,8 @@ #define GIC_ERRDEVARCH 0xFFBC +extern struct dentry *arm64_ras_debugfs; + struct ras_access { u64 (*read)(void __iomem *base, u32 offset); void (*write)(void __iomem *base, u32 offset, u64 val); @@ -80,14 +83,25 @@ struct ce_threshold { u64 reg_val; }; +struct record_count { + u64 ce; + u64 de; + u64 uc; + u64 uer; + u64 ueo; + u64 ueu; +}; + struct ras_record { char *name; void __iomem *regs_base; struct ras_node *node; const struct ras_access *access; + struct dentry *debugfs; struct ce_threshold ce; enum ras_ce_threshold threshold_type; + struct record_count count; int index; /* @@ -116,6 +130,7 @@ struct ras_node { struct device *dev; const struct ras_group *group; struct ras_node __percpu *oncore_node; + struct dentry *debugfs; void __iomem *base; void __iomem *errgsr; @@ -286,4 +301,6 @@ static inline void ras_sync(struct ras_node *node) isb(); } +void ras_node_init_debugfs(struct ras_node *node); + #endif /* _DRIVERS_RAS_ARM64_RAS_H_ */ diff --git a/drivers/ras/debugfs.c b/drivers/ras/debugfs.c index 42afd3de68b22..e4d9a5627e5f7 100644 --- a/drivers/ras/debugfs.c +++ b/drivers/ras/debugfs.c @@ -3,7 +3,8 @@ #include #include "debugfs.h" -static struct dentry *ras_debugfs_dir; +struct dentry *ras_debugfs_dir; +EXPORT_SYMBOL_GPL(ras_debugfs_dir); static atomic_t trace_count = ATOMIC_INIT(0); diff --git a/include/linux/ras.h b/include/linux/ras.h index 11663150612f5..976cd102f76c9 100644 --- a/include/linux/ras.h +++ b/include/linux/ras.h @@ -71,4 +71,6 @@ static inline void ras_register_decode_chain(struct notifier_block *nb) {} static inline void ras_unregister_decode_chain(struct notifier_block *nb) {} #endif /* CONFIG_ARM64_RAS_DRIVER */ +extern struct dentry *ras_debugfs_dir; + #endif /* __RAS_H__ */ From d63fe2a2fbbe1e659655997e32646c7532f5bc92 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:36 +0800 Subject: [PATCH 0448/1133] FROMLIST: arm64: ras: Introduce ras inject interface End-to-end validation of the RAS driver requires the ability to generate errors on demand. Driver gives two complementary paths, which the inject interface deliberately keeps separate: - Soft injection writes directly into the record's status registers and is unconstrained by the spec. It is the tool of choice for state-machine coverage: notifier delivery, ABI shape. - Hard injection drives the architected inject registers and obeys the hardware contract, exercising the real interrupt and decode paths. Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- Documentation/ABI/testing/debugfs-arm64-ras | 39 +++++- drivers/ras/arm64/Makefile | 1 + drivers/ras/arm64/ras-core.c | 26 ++-- drivers/ras/arm64/ras-inject.c | 127 ++++++++++++++++++++ drivers/ras/arm64/ras-sysfs.c | 1 + drivers/ras/arm64/ras.h | 2 + 6 files changed, 183 insertions(+), 13 deletions(-) create mode 100644 drivers/ras/arm64/ras-inject.c diff --git a/Documentation/ABI/testing/debugfs-arm64-ras b/Documentation/ABI/testing/debugfs-arm64-ras index d86bde83d0b94..a14f481c0c048 100644 --- a/Documentation/ABI/testing/debugfs-arm64-ras +++ b/Documentation/ABI/testing/debugfs-arm64-ras @@ -47,4 +47,41 @@ KernelVersion: 6.19 Contact: Ruidong Tian Description: (RW) Read and write the CE threshold to this record. - Returns error if input exceeded the maximum threshold. \ No newline at end of file + Returns error if input exceeded the maximum threshold. + +What: /sys/kernel/debug/ras/arm64//record/inject/err_* +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (RW) These registers are used to simulate soft injection errors + by holding error register values. You can write any values + to them. To trigger the injection, you need to write soft_inject + at last. The validity of the injected error depends on the + value written to err_status. + + Accepts values - any. + +What: /sys/kernel/debug/ras/arm64//record/inject/soft_inject +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (WO) Write any value to this file to trigger the error + injection. Make sure you have specified all necessary error + parameters, i.e. this write should be the last step when + injecting errors. + + Accepts values - any. + +What: /sys/kernel/debug/ras/arm64//record/inject/hard_inject +Date: Dec 2025 +KernelVersion 6.19 +Contact: Ruidong Tian +Description: + (WO) If the AEST table provides error injection registers, + you can write to them via this interface. For instance, + values can be written to the ERXPFGCTL register. The post-injection + behavior is then determined by the hardware specification. + + Accepts values - any. \ No newline at end of file diff --git a/drivers/ras/arm64/Makefile b/drivers/ras/arm64/Makefile index e13e223107dda..2f3119ac3ec5f 100644 --- a/drivers/ras/arm64/Makefile +++ b/drivers/ras/arm64/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_ARM64_RAS_DRIVER) += arm64_ras.o arm64_ras-y := ras-core.o arm64_ras-y += ras-sysfs.o +arm64_ras-y += ras-inject.o diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index c427c131a8620..8cde26ab95de9 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -200,7 +200,7 @@ static void ras_panic(struct ras_record *record, struct ras_ext_regs *regs, panic(msg); } -static void ras_proc_record(struct ras_record *record, void *data) +void ras_proc_record(struct ras_record *record, void *data, bool fake) { struct ras_ext_regs regs = { 0 }; int *count = data; @@ -240,13 +240,15 @@ static void ras_proc_record(struct ras_record *record, void *data) ue = FIELD_GET(ERR_STATUS_UET, regs.err_status); if ((regs.err_status & ERR_STATUS_UE) && (ue == ERR_STATUS_UET_UC || ue == ERR_STATUS_UET_UEU)) { - if (!panic_on_ue) - ras_record_err(record, "UE detected, panic suppressed\n"); - else + if (fake) + ras_record_info(record, + "Simulated error! Skip panic due to fault injection\n"); + else if (panic_on_ue) ras_panic(record, ®s, - "AEST: unrecoverable error encountered"); + "AEST: unrecoverable error encountered"); + else + ras_record_err(record, "UE detected, panic suppressed\n"); } - ras_do_proc(record, ®s); /* Write-one-to-clear the bits we've seen */ @@ -263,7 +265,7 @@ static void ras_proc_record(struct ras_record *record, void *data) record_write(record, ERXSTATUS, regs.err_status); } -static void ras_node_foreach_record(void (*func)(struct ras_record *, void *), +static void ras_node_foreach_record(void (*func)(struct ras_record *, void *, bool), struct ras_node *node, void *data, unsigned long *bitmap) { @@ -272,13 +274,13 @@ static void ras_node_foreach_record(void (*func)(struct ras_record *, void *), for_each_clear_bit(i, bitmap, node->record_count) { ras_select_record(node, i); - func(&node->records[i], data); + func(&node->records[i], data, false); ras_sync(node); } } -static void ras_node_foreach_poll_record(void (*func)(struct ras_record *, void *), +static void ras_node_foreach_poll_record(void (*func)(struct ras_record *, void *, bool), struct ras_node *node, void *data) { int i; @@ -300,7 +302,7 @@ static void ras_node_foreach_poll_record(void (*func)(struct ras_record *, void ras_select_record(node, i); - func(&node->records[i], data); + func(&node->records[i], data, false); ras_sync(node); } @@ -329,7 +331,7 @@ static int ras_proc(struct ras_node *node) */ if (test_bit(i * BITS_PER_LONG + j, node->status_reporting)) continue; - ras_proc_record(&node->records[j], &count); + ras_proc_record(&node->records[j], &count, false); } } @@ -521,7 +523,7 @@ static int ras_init_record(struct ras_record *record, int i, struct ras_node *no return 0; } -static void ras_online_record(struct ras_record *record, void *data) +static void ras_online_record(struct ras_record *record, void *data, bool __unused) { ras_set_ce_threshold(record); ras_enable_irq(record); diff --git a/drivers/ras/arm64/ras-inject.c b/drivers/ras/arm64/ras-inject.c new file mode 100644 index 0000000000000..7fb522a845e7b --- /dev/null +++ b/drivers/ras/arm64/ras-inject.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table Support + * + * Copyright (c) 2024, Alibaba Group. + */ + +#include "ras.h" + +static struct ras_ext_regs regs_inj; + +struct inj_attr { + struct attribute attr; + ssize_t (*show)(struct ras_node *n, struct inj_attr *a, char *b); + ssize_t (*store)(struct ras_node *n, struct inj_attr *a, const char *b, + size_t c); +}; + +struct ras_inject { + struct ras_node *node; + struct kobject kobj; +}; + +#define to_inj(k) container_of(k, struct ras_inject, kobj) +#define to_inj_attr(a) container_of(a, struct inj_attr, attr) + +static u64 ras_sysreg_read_inject(void *__unused, u32 offset) +{ + u64 *p = (u64 *)®s_inj; + + return p[offset/8]; +} + +static void ras_sysreg_write_inject(void *base, u32 offset, u64 val) +{ + u64 *p = (u64 *)®s_inj; + + p[offset/8] = val; +} + +static u64 ras_iomem_read_inject(void *base, u32 offset) +{ + u64 *p = (u64 *)®s_inj; + + return p[offset/8]; +} + +static void ras_iomem_write_inject(void *base, u32 offset, u64 val) +{ + u64 *p = (u64 *)®s_inj; + + p[offset/8] = val; +} + +static struct ras_access ras_access_inject[] = { + [ACPI_AEST_NODE_SYSTEM_REGISTER] = { + .read = ras_sysreg_read_inject, + .write = ras_sysreg_write_inject, + }, + + [ACPI_AEST_NODE_MEMORY_MAPPED] = { + .read = ras_iomem_read_inject, + .write = ras_iomem_write_inject, + }, + [ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED] = { + .read = ras_iomem_read_inject, + .write = ras_iomem_write_inject, + }, + { } +}; + +static int soft_inject_store(void *data, u64 val) +{ + int count = 0; + struct ras_record record_inj, *record = data; + struct ras_node *node = record->node; + + memcpy(&record_inj, record, sizeof(*record)); + record_inj.access = &ras_access_inject[node->access_type]; + + regs_inj.err_status |= ERR_STATUS_V; + + ras_proc_record(&record_inj, &count, true); + + if (count != 1) + return -EIO; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(soft_inject_ops, NULL, soft_inject_store, "%llu\n"); + +static int hard_inject_store(void *data, u64 val) +{ + struct ras_record *record = data; + struct ras_node *node = record->node; + + if (node->type != ACPI_AEST_PROCESSOR_ERROR_NODE && !node->inj) + return -EPERM; + + ras_select_record(node, record->index); + record_write(record, ERXPFGCTL, val); + record_write(record, ERXPFGCDN, 0x100); + ras_sync(node); + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(hard_inject_ops, NULL, hard_inject_store, "%llu\n"); + +void ras_inject_init_debugfs(struct ras_record *record) +{ + struct dentry *inj; + + inj = debugfs_create_dir("inject", record->debugfs); + + debugfs_create_u64("err_fr", 0600, inj, ®s_inj.err_fr); + debugfs_create_u64("err_ctrl", 0600, inj, ®s_inj.err_ctlr); + debugfs_create_u64("err_status", 0600, inj, ®s_inj.err_status); + debugfs_create_u64("err_addr", 0600, inj, ®s_inj.err_addr); + debugfs_create_u64("err_misc0", 0600, inj, ®s_inj.err_misc[0]); + debugfs_create_u64("err_misc1", 0600, inj, ®s_inj.err_misc[1]); + debugfs_create_u64("err_misc2", 0600, inj, ®s_inj.err_misc[2]); + debugfs_create_u64("err_misc3", 0600, inj, ®s_inj.err_misc[3]); + debugfs_create_file("soft_inject", 0200, inj, record, &soft_inject_ops); + + if (record->node->type == ACPI_AEST_PROCESSOR_ERROR_NODE || record->node->inj) + debugfs_create_file("hard_inject", 0200, inj, record, &hard_inject_ops); +} diff --git a/drivers/ras/arm64/ras-sysfs.c b/drivers/ras/arm64/ras-sysfs.c index 03cc00b820e2d..d8b351ee9aef5 100644 --- a/drivers/ras/arm64/ras-sysfs.c +++ b/drivers/ras/arm64/ras-sysfs.c @@ -151,6 +151,7 @@ static void ras_record_init_debugfs(struct ras_record *record) record, &ras_record_err_count_fops); debugfs_create_file("ce_threshold", 0600, record->debugfs, record, &record_ce_threshold_ops); + ras_inject_init_debugfs(record); } static void ras_init_records_debugfs(struct ras_node *node) diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h index 92cbb975b4df9..8a0d2909fe4b9 100644 --- a/drivers/ras/arm64/ras.h +++ b/drivers/ras/arm64/ras.h @@ -302,5 +302,7 @@ static inline void ras_sync(struct ras_node *node) } void ras_node_init_debugfs(struct ras_node *node); +void ras_inject_init_debugfs(struct ras_record *record); +void ras_proc_record(struct ras_record *record, void *data, bool fake); #endif /* _DRIVERS_RAS_ARM64_RAS_H_ */ From e899d383a9fed9c96fe172208efcdc5ffe01b098 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:37 +0800 Subject: [PATCH 0449/1133] FROMLIST: arm64: ras: support vendor node CMN700 The CMN (Coherent Mesh Network) architecture incorporates five distinct device types. Each device type is associated with an error group register set. CMN's error records utilize a memory-mapped single error record view [1]. Critically, one error record corresponds to one AEST node, implying that a single CMN instance can generate hundreds of AEST nodes. To manage this scale, this driver introduces a virtual ras node, which represents an entire CMN device, such as an HNI or HNF. This allows an HNF ras node, for instance, to leverage its errgsr register to pinpoint which specific error record has reported an error. [1]: https://developer.arm.com/documentation/102308/latest/ Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- drivers/acpi/arm64/aest.c | 111 ++++++++- drivers/ras/arm64/Makefile | 1 + drivers/ras/arm64/ras-cmn.c | 469 +++++++++++++++++++++++++++++++++++ drivers/ras/arm64/ras-core.c | 48 +++- drivers/ras/arm64/ras.h | 29 +++ 5 files changed, 650 insertions(+), 8 deletions(-) create mode 100644 drivers/ras/arm64/ras-cmn.c diff --git a/drivers/acpi/arm64/aest.c b/drivers/acpi/arm64/aest.c index 1b020ab7eccd5..1c68c83ccf4ad 100644 --- a/drivers/acpi/arm64/aest.c +++ b/drivers/acpi/arm64/aest.c @@ -5,6 +5,7 @@ * Copyright (c) 2025, Alibaba Group. */ +#include #include #include #include @@ -173,6 +174,10 @@ aest_init_node_props(struct acpi_aest_hdr *hdr, struct property_entry *props, return 0; } +/* + * Non-vendor path: attach all per-entry properties as the platform device's + * primary fwnode (single-layer structure). + */ static int __init aest_create_node_fwnode(struct acpi_aest_hdr *hdr, struct platform_device *pdev) { @@ -187,6 +192,51 @@ aest_create_node_fwnode(struct acpi_aest_hdr *hdr, struct platform_device *pdev) return device_create_managed_software_node(&pdev->dev, props, NULL); } +/* + * CMN700 path (double-layer structure): + * - first_time: create the parent fwnode on @pdev carrying the vendor + * identification (HID/UID); + * - always: hang a child swnode under @pdev's primary fwnode for the + * current AEST entry, so that multiple AEST entries sharing the same + * HID/UID accumulate as siblings under one platform device. + */ +static int __init +aest_create_cmn700_fwnode(struct acpi_aest_hdr *hdr, + struct platform_device *pdev, bool first_time) +{ + struct acpi_aest_node_interface_header *interface; + struct property_entry child_props[17] = { }; + struct fwnode_handle *child; + int p = 0; + int ret; + + ret = aest_init_node_props(hdr, child_props, &p, pdev); + if (ret) + return ret; + + if (first_time) { + ret = device_create_managed_software_node(&pdev->dev, child_props, NULL); + if (ret) + return ret; + } + + interface = ACPI_ADD_PTR(struct acpi_aest_node_interface_header, + hdr, hdr->node_interface_offset); + + child_props[p++] = PROPERTY_ENTRY_U64("arm,record-base", interface->address); + /* + * Hang the per-entry properties as a child swnode under the platform + * device's primary fwnode. AEST platform devices live for the whole + * system lifetime, so we intentionally do not track child fwnodes for + * removal here. + */ + child = fwnode_create_software_node(child_props, dev_fwnode(&pdev->dev)); + if (IS_ERR(child)) + return PTR_ERR(child); + + return 0; +} + static int aest_node_mem_size(u8 group_format) { switch (group_format) { @@ -264,9 +314,60 @@ static int __init acpi_aest_init_node(struct acpi_aest_hdr *aest_hdr) return 0; } +static DEFINE_XARRAY(aest_cmn700_groups); +static int __init acpi_aest_init_cmn700_node(struct acpi_aest_hdr *aest_hdr) +{ + struct acpi_aest_vendor_v2 *vendor; + struct platform_device *existing; + int ret; + + vendor = ACPI_ADD_PTR(struct acpi_aest_vendor_v2, aest_hdr, + aest_hdr->node_specific_offset); + + /* + * If a previous AEST entry already produced a platform device for + * the same vendor HID/UID, just append a child swnode for the + * current entry under that pdev's primary fwnode and return. + */ + existing = xa_load(&aest_cmn700_groups, vendor->acpi_uid); + if (existing) + return aest_create_cmn700_fwnode(aest_hdr, existing, false); + + struct platform_device *pdev __free(platform_device_put) = + acpi_aest_alloc_pdev(aest_hdr); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + ret = aest_create_cmn700_fwnode(aest_hdr, pdev, true); + if (ret) + return ret; + + ret = platform_device_add(pdev); + if (ret) + return ret; + + /* pdev is now owned by the driver core; release the cleanup-managed put. */ + struct platform_device *added = no_free_ptr(pdev); + + ret = xa_err(xa_store(&aest_cmn700_groups, vendor->acpi_uid, added, GFP_KERNEL)); + if (ret) + return ret; + + pr_debug("Platform device added for AEST vendor node: %s.%d\n", + added->name, added->id); + + return 0; +} + +static int __init is_acpi_aest_cmn_node(struct acpi_aest_vendor_v2 *vendor) +{ + return strncmp(vendor->acpi_hid, "ARMHC701", 8) == 0; +} + static int __init acpi_aest_init_nodes(struct acpi_table_header *aest_table) { struct acpi_aest_hdr *aest_node, *aest_end; + struct acpi_aest_vendor_v2 *vendor; struct acpi_table_aest *aest; int rc; @@ -281,8 +382,14 @@ static int __init acpi_aest_init_nodes(struct acpi_table_header *aest_table) "AEST node pointer overflow, bad table.\n"); return -EINVAL; } - - rc = acpi_aest_init_node(aest_node); + vendor = ACPI_ADD_PTR(struct acpi_aest_vendor_v2, aest_node, + aest_node->node_specific_offset); + + if (aest_node->type == ACPI_AEST_VENDOR_ERROR_NODE && + is_acpi_aest_cmn_node(vendor)) + rc = acpi_aest_init_cmn700_node(aest_node); + else + rc = acpi_aest_init_node(aest_node); if (rc) return rc; diff --git a/drivers/ras/arm64/Makefile b/drivers/ras/arm64/Makefile index 2f3119ac3ec5f..0e4c7421c131a 100644 --- a/drivers/ras/arm64/Makefile +++ b/drivers/ras/arm64/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_ARM64_RAS_DRIVER) += arm64_ras.o arm64_ras-y := ras-core.o arm64_ras-y += ras-sysfs.o arm64_ras-y += ras-inject.o +arm64_ras-y += ras-cmn.o diff --git a/drivers/ras/arm64/ras-cmn.c b/drivers/ras/arm64/ras-cmn.c new file mode 100644 index 0000000000000..109cdc46a7174 --- /dev/null +++ b/drivers/ras/arm64/ras-cmn.c @@ -0,0 +1,469 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM Error Source Table CMN-700 Support + * + * Copyright (c) 2025, Alibaba Inc + * + * CMN-700 exposes 6 RAS-relevant device types (HN-I, HN-F, XP, SBSX, + * RN-D/CXRA, MTSX). Each device type owns an error group register set + * holding a set of error records. + * + * CMN uses the memory-mapped single-record view, so every AEST node + * corresponds to exactly one CMN error record - a single mesh can + * yield hundreds of AEST entries. Per Arm ACPI Spec[1] §2.6.3.4 the + * device type is recovered from the AEST vendor-specific data. This + * driver enumerates every CMN AEST entry, reads the CMN node-info + * register and stitches all entries of the same type into one + * aggregate ras_node carrying many ras_records (one per logic_id). + * + * Each CMN instance owns its own error interrupt. The shared FHI/ERI + * lines are registered per ras_node with IRQF_SHARED, so every + * per-type handler runs and locates the offending record by walking + * the error group registers - mirroring CMN Spec[2] §3.8. + * + * The CMN RAS topology is: + * + * +----+ + * -->|XP | ...... + * | +----+ + * | + * | +----+ ...... + * | |HNI | +----------------+ + * | +----+ ->|record/AEST node| + * | | +----------------+ + * +------------+ | +----+ | . + * |CMN Instance|--| |HNF |---| . + * +------------+ | +----+ | . + * | | +----------------+ + * | +----+ ->|record/AEST node| + * | |SBSX| +----------------+ + * | +----+ ...... + * | + * | +----+ + * -->|RND | ...... (also MTSX) + * +----+ + * + * All addressing needed to reach the CMN RAS register block, the CMN + * node-info register and the CMN ERRGSR is taken from AEST. + * + * PERIPHBASE = ERRFR_addr - ERRFR_offset_in_register_block + * - register_block_offset_within_CMN + * = record_base - 0x3100 - cmn_node_offset + * + * where the CMN-700 record register block places ERRFR at offset 0x3100 + * (CMN-700 TRM[2]). The AEST "arm,node-specific-data" payload carries + * two u64s used by this driver: [0..7] = hnd_offset (locates the + * per-type ERRGSR via cmn_config->errgsr_offset()), [8..15] = + * cmn_node_offset (offset of this node's register block within CMN). + * + * Per CMN-700 erratum #2732981, ERRGSR for HN-I / HN-S / SBSX is + * broken; for those types the per-record status_reporting bit is left + * set so the core polls the records instead of reading ERRGSR. + * + * AEST topology consumed by this driver (see drivers/acpi/arm64/aest.c): + * + * pdev (arm64_ras, dev_name = "cmn700") + * ├── primary fwnode : + * └── child swnode x N: per-AEST-entry properties: + * arm,interface-type + * arm,record-base + * arm,node-specific-data[] (vendor data) + * + * Each child swnode corresponds to one AEST node, i.e. one CMN error + * record identified by (node_type, logic_id). + * + * [1] Arm ACPI for Armv8/Armv9: https://developer.arm.com/documentation/den0093/latest + * [2] CMN-700 TRM (Arm 102308): https://developer.arm.com/documentation/102308/latest + */ + +#include +#include +#include +#include +#include + +#include "ras.h" + + +#define CMN_NODE_INFO 0x0000 +#define CMN_NI_NODE_TYPE GENMASK_ULL(15, 0) +#define CMN_NI_NODE_ID GENMASK_ULL(31, 16) +#define CMN_NI_LOGICAL_ID GENMASK_ULL(47, 32) + +/* Subset of CMN node types relevant to RAS */ +enum cmn_ras_node_type { + CMN_TYPE_HNI = 0x4, + CMN_TYPE_HNF = 0x5, + CMN_TYPE_XP = 0x6, + CMN_TYPE_SBSX = 0x7, + CMN_TYPE_MTSX = 0x10, + CMN_TYPE_CXRA = 0x100, + CMN_TYPE_CXHA = 0x101, + CMN_TYPE_CCHA = 0x104, + CMN_TYPE_HNS = 0x200, +}; + +/* + * Offset of ERRFR within the CMN-700 RAS register block. + * AEST's interface->address points at ERRFR; subtracting this plus the + * cmn_node_offset (vendor-specific-data[8..15]) yields PERIPHBASE. + */ +#define CMN_ERRFR_OFFSET_IN_REGBLK 0x3100 + +#define CMN_RAS_DEV_NUM 6 +#define CMN700_ERRGSR_NUM 8 +#define CMN_ERRGSR_OFFSET 0x3000 + +struct cmn_vendor_data { + struct acpi_aest_vendor_v2 vendor; + int node_type; + int node_id; + int logic_id; +}; + +struct cmn_config { + int errgsr_num; + int dev_num; + const int *node_id_map; + const char *const *node_name; + int (*errgsr_mapping)(int errgsr_bit); + u64 (*errgsr_offset)(u64 hnd_offset, int node_idx); +}; + +static const char *const cmn700_node_name[] = { + [CMN_TYPE_HNI] = "HNI", + [CMN_TYPE_HNF] = "HNF", + [CMN_TYPE_XP] = "XP", + [CMN_TYPE_SBSX] = "SBSX", + [CMN_TYPE_CXRA] = "RND", + [CMN_TYPE_MTSX] = "MTSX", +}; + +static const int cmn700_node_id_map[] = { + [CMN_TYPE_HNI] = 1, + [CMN_TYPE_HNF] = 2, + [CMN_TYPE_XP] = 0, + [CMN_TYPE_SBSX] = 3, + [CMN_TYPE_CXRA] = 4, + [CMN_TYPE_MTSX] = 5, +}; + +static u64 cmn700_errgsr_offset(u64 hnd_offset, int node_idx) +{ + return hnd_offset + CMN_ERRGSR_OFFSET + + (node_idx * 2) * CMN700_ERRGSR_NUM * 8; +} + +static int cmn700_errgsr_mapping(int errgsr_bit) +{ + return errgsr_bit / 2; +} + +static struct cmn_config cmn700_config = { + .errgsr_num = CMN700_ERRGSR_NUM, + .dev_num = CMN_RAS_DEV_NUM, + .node_name = cmn700_node_name, + .node_id_map = cmn700_node_id_map, + .errgsr_mapping = cmn700_errgsr_mapping, + .errgsr_offset = cmn700_errgsr_offset, +}; + +static struct cmn_config *cmn_config; + + +static int cmn_init_vendor_data(struct device *dev, struct cmn_vendor_data *vendor_data, + u64 *errgsr_addr, u64 record_base) +{ + struct acpi_aest_vendor_v2 vendor; + u64 cmn_node_offset, reg, logic_id, type, node_id; + u64 hnd_offset, periphbase; + void __iomem *cmn_node_base; + struct fwnode_handle *child = dev_fwnode(dev); + + fwnode_property_read_u8_array(child, "arm,node-specific-data", + (u8 *)&vendor, sizeof(vendor)); + + hnd_offset = get_unaligned_le64(&vendor.vendor_specific_data[0]); + cmn_node_offset = get_unaligned_le64(&vendor.vendor_specific_data[8]); + + periphbase = record_base - CMN_ERRFR_OFFSET_IN_REGBLK - cmn_node_offset; + + cmn_node_base = devm_ioremap(dev, periphbase + cmn_node_offset + + CMN_NODE_INFO, SZ_4K); + if (!cmn_node_base) + return -ENOMEM; + + reg = readq_relaxed(cmn_node_base); + logic_id = FIELD_GET(CMN_NI_LOGICAL_ID, reg); + type = FIELD_GET(CMN_NI_NODE_TYPE, reg); + node_id = FIELD_GET(CMN_NI_NODE_ID, reg); + + if (type >= ARRAY_SIZE(cmn700_node_id_map) || + !cmn_config->node_name[type]) { + dev_dbg(dev, "Skipping unsupported CMN node type %llx\n", type); + return -ENODEV; + } + + *errgsr_addr = periphbase + cmn_config->errgsr_offset(hnd_offset, + cmn_config->node_id_map[type]); + + vendor_data->vendor = vendor; + vendor_data->node_type = type; + vendor_data->node_id = node_id; + vendor_data->logic_id = logic_id; + + devm_iounmap(dev, cmn_node_base); + + dev_dbg(dev, "periphbase %llx, node_offset %llx, logic_id %llx, type %llx, node_id %llx\n", + periphbase, cmn_node_offset, logic_id, type, node_id); + + return 0; +} + +/* + * Initialise one ras_node (representing one CMN node *type*, e.g. HN-F). + * Per CMN-700 erratum #2732981, ERRGSR for HN-I / HN-S / SBSX is broken; + * AEST conveys this via the per-record "Error group-based status reporting + * supported" flag (bit0 of arm,status-reporting). When that bit is 0 we + * leave node->errgsr NULL so the core polls instead of reading ERRGSR. + */ +static int cmn_init_node(struct platform_device *pdev, + struct ras_node *cmn_node, u64 type, u64 errgsr_addr) +{ + struct device *dev = &pdev->dev; + int ret; + + cmn_node->dev = dev; + cmn_node->type = ACPI_AEST_VENDOR_ERROR_NODE; + cmn_node->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%llx", + cmn_config->node_name[type], errgsr_addr); + if (!cmn_node->name) + return -ENOMEM; + + /* CMN700 just support version 1 */ + cmn_node->version = 1; + cmn_node->errgsr = devm_ioremap(dev, errgsr_addr, cmn_config->errgsr_num * 8); + if (!cmn_node->errgsr) + return -ENOMEM; + + cmn_node->errgsr_num = cmn_config->errgsr_num; + cmn_node->errgsr_mapping = cmn_config->errgsr_mapping; + cmn_node->record_count = cmn_config->errgsr_num * BITS_PER_LONG / 2; + cmn_node->record_implemented = devm_bitmap_zalloc( + dev, cmn_node->record_count, GFP_KERNEL); + if (!cmn_node->record_implemented) + return -ENOMEM; + bitmap_set(cmn_node->record_implemented, 0, cmn_node->record_count); + + cmn_node->status_reporting = devm_bitmap_zalloc( + dev, cmn_node->record_count, GFP_KERNEL); + if (!cmn_node->status_reporting) + return -ENOMEM; + bitmap_set(cmn_node->status_reporting, 0, cmn_node->record_count); + /* If !errgsr_supported leave bitmap zero so all records are polled. */ + + cmn_node->records = devm_kcalloc(dev, cmn_node->record_count, + sizeof(struct ras_record), GFP_KERNEL); + if (!cmn_node->records) + return -ENOMEM; + + cmn_node->specific_data_size = device_property_count_u8(dev, + "arm,node-specific-data"); + if (cmn_node->specific_data_size > 0) { + cmn_node->specific_data = devm_kzalloc(dev, cmn_node->specific_data_size, + GFP_KERNEL); + if (!cmn_node->specific_data) + return -ENOMEM; + ret = device_property_read_u8_array(dev, "arm,node-specific-data", + cmn_node->specific_data, + cmn_node->specific_data_size); + if (ret) + return ret; + } + + ras_node_dbg(cmn_node, "Init with errgsr %llx\n", errgsr_addr); + return 0; +} + +/* + * Process one AEST record (one child fwnode) and stitch it into the + * appropriate per-type ras_node. The ras_node is initialised lazily on the + * first record observed for that type. + */ +static int cmn_init_record(struct platform_device *pdev, struct ras_node *nodes, + struct fwnode_handle *child) +{ + struct device *dev = &pdev->dev; + u64 errgsr_addr, record_base; + struct cmn_vendor_data *vendor_data; + struct ras_node *cmn_node; + struct ras_record *record; + int ret, node_index; + u8 interface_type; + + + ret = fwnode_property_read_u8(child, "arm,interface-type", + &interface_type); + if (ret) + return ret; + if (interface_type != ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED) { + dev_err(dev, "CMN only supports single-record memory mapped\n"); + return -ENODEV; + } + + ret = fwnode_property_read_u64(child, "arm,record-base", + &record_base); + if (ret) + return ret; + + vendor_data = devm_kzalloc(dev, sizeof(*vendor_data), GFP_KERNEL); + if (!vendor_data) + return -ENOMEM; + + ret = cmn_init_vendor_data(dev, vendor_data, &errgsr_addr, record_base); + if (ret) + return ret; + + node_index = cmn_config->node_id_map[vendor_data->node_type]; + + cmn_node = &nodes[node_index]; + if (!cmn_node->name) { + ret = cmn_init_node(pdev, cmn_node, vendor_data->node_type, errgsr_addr); + if (ret) + return ret; + } + + if (vendor_data->logic_id >= cmn_node->record_count) { + dev_warn(dev, "logic_id %u exceeds record_count %u\n", + vendor_data->logic_id, cmn_node->record_count); + return 0; + } + + /* + * CMN-700 stitches several single-mapping AEST nodes into one + * aggregate ras_node, so the record_implemented / status_reporting + * bitmaps that ACPI normally provides per group are absent here + * and must be populated by the driver: clear the bit at this + * record's logic_id slot to mark it implemented (and reporting). + */ + clear_bit(vendor_data->logic_id, cmn_node->record_implemented); + /* CMN-700 erratum #2732981, ERRGSR for HN-I / HN-S / SBSX is broken */ + if (vendor_data->node_type != CMN_TYPE_HNI && + vendor_data->node_type != CMN_TYPE_HNS && + vendor_data->node_type != CMN_TYPE_SBSX) + clear_bit(vendor_data->logic_id, cmn_node->status_reporting); + + record = &cmn_node->records[vendor_data->logic_id]; + record->name = devm_kasprintf(dev, GFP_KERNEL, "record%d", vendor_data->logic_id); + if (!record->name) + return -ENOMEM; + record->regs_base = devm_ioremap(dev, + (resource_size_t)record_base, + sizeof(struct ras_ext_regs)); + if (!record->regs_base) + return -ENOMEM; + record->node = cmn_node; + record->index = vendor_data->logic_id; + record->access = &ras_access[interface_type]; + + record->vendor_data = vendor_data; + record->vendor_data_size = sizeof(*vendor_data); + + ras_record_dbg(record, "base %llx\n", record_base); + return 0; +} + +/* + * Vendor pdev (CMN) carries one shared fhi/eri pair. Register it on each + * populated ras_node with IRQF_SHARED so all per-type handlers run, and + * enable per-record FI/CFI/UI in ERXCTLR via the shared ras_enable_irq. + */ +static int cmn_register_record_irq(struct platform_device *pdev, + struct ras_node *nodes) +{ + struct device *dev = &pdev->dev; + int fhi_irq, eri_irq, i, ret; + + fhi_irq = platform_get_irq_byname_optional(pdev, AEST_FHI_NAME); + eri_irq = platform_get_irq_byname_optional(pdev, AEST_ERI_NAME); + if (fhi_irq <= 0 && eri_irq <= 0) + return 0; + + for (i = 0; i < cmn_config->dev_num; i++) { + struct ras_node *n = &nodes[i]; + char *desc; + + if (!n->name) /* slot not used by this CMN */ + continue; + + desc = devm_kasprintf(dev, GFP_KERNEL, "arm64_ras.%s.%s", + dev_name(dev), n->name); + if (!desc) + return -ENOMEM; + + if (fhi_irq > 0) { + ret = devm_request_irq(dev, fhi_irq, ras_irq_func, + IRQF_SHARED, desc, n); + if (ret) + return ret; + n->irq[0] = fhi_irq; + } + if (eri_irq > 0) { + ret = devm_request_irq(dev, eri_irq, ras_irq_func, + IRQF_SHARED, desc, n); + if (ret) + return ret; + n->irq[1] = eri_irq; + } + } + return 0; +} + +/* Common entry point: walk every child swnode under @pdev. */ +static int cmn_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct fwnode_handle *child; + struct ras_node *nodes; + int ret; + + nodes = devm_kcalloc(dev, cmn_config->dev_num, sizeof(*nodes), + GFP_KERNEL); + if (!nodes) + return -ENOMEM; + + /* + * In CMN-700, each AEST node is a single mapping record, so + * treat every child fwnode as one record rather than a node + * with multiple records underneath. + */ + device_for_each_child_node(dev, child) { + ret = cmn_init_record(pdev, nodes, child); + if (ret) { + fwnode_handle_put(child); + return ret; + } + } + + ret = cmn_register_record_irq(pdev, nodes); + if (ret) + return ret; + + platform_set_drvdata(pdev, nodes); + + for (int i = 0; i < cmn_config->dev_num; i++) { + ras_online_node(&nodes[i]); + ras_node_init_debugfs(&nodes[i]); + } + + return 0; +} + +int ras_cmn700_probe(struct platform_device *pdev) +{ + cmn_config = &cmn700_config; + + dev_set_name(&pdev->dev, "cmn700"); + + return cmn_probe(pdev); +} diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index 8cde26ab95de9..2fb645659694c 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -284,6 +284,7 @@ static void ras_node_foreach_poll_record(void (*func)(struct ras_record *, void struct ras_node *node, void *data) { int i; + /* * Per AEST spec: * - record_implemented: bitmap of records that are actually @@ -310,7 +311,7 @@ static void ras_node_foreach_poll_record(void (*func)(struct ras_record *, void static int ras_proc(struct ras_node *node) { - int count = 0, i, j, size = node->record_count; + int count = 0, i, j, size = node->record_count, record_idx; u64 err_group = 0; ras_node_foreach_poll_record(ras_proc_record, node, &count); @@ -321,24 +322,27 @@ static int ras_proc(struct ras_node *node) ras_node_dbg(node, "Report bitmap %*pb\n", size, node->status_reporting); for (i = 0; i < BITS_TO_U64(size); i++) { err_group = readq_relaxed((void *)node->errgsr + i * 8); - ras_node_dbg(node, "errgsr[%d]: 0x%llx\n", i, err_group); for_each_set_bit(j, (unsigned long *)&err_group, BITS_PER_LONG) { + record_idx = node->errgsr_mapping(i * BITS_PER_LONG + j); + ras_node_dbg(node, "errgsr[%d]: bit %d occur error\n", + i, record_idx); /* * Error group base is only valid in Memory Map node, * so driver do not need to write select register and * sync. */ - if (test_bit(i * BITS_PER_LONG + j, node->status_reporting)) + if (test_bit(record_idx, node->status_reporting)) continue; - ras_proc_record(&node->records[j], &count, false); + ras_proc_record(&node->records[record_idx], + &count, false); } } return count; } -static irqreturn_t ras_irq_func(int irq, void *input) +irqreturn_t ras_irq_func(int irq, void *input) { struct ras_node *node = input; @@ -529,7 +533,7 @@ static void ras_online_record(struct ras_record *record, void *data, bool __unus ras_enable_irq(record); } -static void ras_online_node(struct ras_node *node) +void ras_online_node(struct ras_node *node) { int count = 0; @@ -808,6 +812,7 @@ static struct ras_node *ras_init_node(struct platform_device *pdev) return ERR_PTR(-EINVAL); } + node->errgsr_mapping = default_errgsr_mapping; node->name = alloc_ras_node_name(node); if (!node->name) return ERR_PTR(-ENOMEM); @@ -877,10 +882,41 @@ static int ras_setup_irq(struct platform_device *pdev, struct ras_node *node) return 0; } +static struct ras_vendor_match vendor_match[] = { + { "ARMHC701", &ras_cmn700_probe }, + { }, +}; + +static int +ras_vendor_probe(struct platform_device *pdev) +{ + int i; + struct acpi_aest_vendor_v2 vendor; + + device_property_read_u8_array(&pdev->dev, "arm,node-specific-data", + (u8 *)&vendor, sizeof(vendor)); + + dev_dbg(&pdev->dev, "Try to probe vendor node %s\n", vendor.acpi_hid); + for (i = 0; i < ARRAY_SIZE(vendor_match); i++) { + if (!strncmp(vendor_match[i].hid, vendor.acpi_hid, 8)) + return vendor_match[i].probe(pdev); + } + + return -ENODEV; +} + static int arm64_ras_probe(struct platform_device *pdev) { int ret; struct ras_node *node; + u8 type; + + ret = device_property_read_u8(&pdev->dev, "arm,node-type", &type); + if (ret) + return ret; + + if (type == ACPI_AEST_VENDOR_ERROR_NODE) + return ras_vendor_probe(pdev); node = ras_init_node(pdev); if (IS_ERR(node)) diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h index 8a0d2909fe4b9..75aa4ac83a417 100644 --- a/drivers/ras/arm64/ras.h +++ b/drivers/ras/arm64/ras.h @@ -9,6 +9,7 @@ #define _DRIVERS_RAS_ARM64_RAS_H_ #include +#include #include #include @@ -98,6 +99,8 @@ struct ras_record { struct ras_node *node; const struct ras_access *access; struct dentry *debugfs; + void *vendor_data; + size_t vendor_data_size; struct ce_threshold ce; enum ras_ce_threshold threshold_type; @@ -177,6 +180,18 @@ struct ras_node { * into SPA */ unsigned long *addressing_mode; + /* + * Usually bit[n] in errgsr indicates [n]th error record within this + * error node report error. But some compoent may have different rules. + * For example, CMN700 TRM 4.3.5.12 say: + * ``` Error occurs when the index is even and Fault + * occurs when the index is odd. ``` + * Bit[n]: record[n] report ERROR. + * Bit[n + 1]: record[n] report FAULT. + * errgsr_mapping function is used to map errgsr bit to record index + * for various components. + */ + int (*errgsr_mapping)(int errgsr_bit); struct ras_record *records; u32 specific_data_size; @@ -184,6 +199,7 @@ struct ras_node { u32 record_index; u32 flags; int version; + int errgsr_num; u8 type; u8 access_type; @@ -301,8 +317,21 @@ static inline void ras_sync(struct ras_node *node) isb(); } +static inline int default_errgsr_mapping(int errgsr_bit) +{ + return errgsr_bit; +} + +struct ras_vendor_match { + char hid[ACPI_ID_LEN]; + int (*probe)(struct platform_device *pdev); +}; + void ras_node_init_debugfs(struct ras_node *node); void ras_inject_init_debugfs(struct ras_record *record); void ras_proc_record(struct ras_record *record, void *data, bool fake); +irqreturn_t ras_irq_func(int irq, void *input); +void ras_online_node(struct ras_node *node); +int ras_cmn700_probe(struct platform_device *pdev); #endif /* _DRIVERS_RAS_ARM64_RAS_H_ */ From 9981b5eba439941057cd9708756e09e6974471ab Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:38 +0800 Subject: [PATCH 0450/1133] FROMLIST: arm64: ras: Introduce ras error storm mitigation Corrected errors can occasionally be reported at a very high rate (known on x86 as a "CMCI storm"), consuming a substantial share of CPU time and disturbing the running workload. The RAS driver needs to throttle this so that error reporting itself does not become a denial of service. Adopt a hybrid per-record / per-node strategy: - Each record tracks its own CE history in a sliding window. By default a record enters storm mode once it accumulates more than 5 corrected errors within roughly one minute, at which point its FHI/CFI is masked via ERR_CTLR and the record is added to a node-wide poll set. It leaves storm mode after ~30 s without any further error, at which point the interrupt is unmasked again. The thresholds and the poll interval are exposed via debugfs so operators can retune the algorithm at runtime without rebuilding the kernel. - The node owns a single timer that drains every stormy record. The first record entering storm starts the timer; the last one leaving stops it. - The poll interval is adaptive: halved on each tick that still finds errors, doubled on each tick that does not, capped at 300 s. This way the driver tracks the actual storm intensity instead of paying a fixed polling cost. - - ERI / UI (uncorrectable reporting) is intentionally excluded: uncorrected errors must remain synchronous and never be rate-limited. The result bounds CPU spent on RAS under fault floods while preserving full fidelity for correctness-critical paths. Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- drivers/ras/arm64/Makefile | 1 + drivers/ras/arm64/ras-cmn.c | 10 ++ drivers/ras/arm64/ras-core.c | 45 +++++++- drivers/ras/arm64/ras-inject.c | 3 + drivers/ras/arm64/ras-storm.c | 198 +++++++++++++++++++++++++++++++++ drivers/ras/arm64/ras-sysfs.c | 107 ++++++++++++++++++ drivers/ras/arm64/ras.h | 37 ++++++ 7 files changed, 397 insertions(+), 4 deletions(-) create mode 100644 drivers/ras/arm64/ras-storm.c diff --git a/drivers/ras/arm64/Makefile b/drivers/ras/arm64/Makefile index 0e4c7421c131a..6897798f73144 100644 --- a/drivers/ras/arm64/Makefile +++ b/drivers/ras/arm64/Makefile @@ -6,3 +6,4 @@ arm64_ras-y := ras-core.o arm64_ras-y += ras-sysfs.o arm64_ras-y += ras-inject.o arm64_ras-y += ras-cmn.o +arm64_ras-y += ras-storm.o diff --git a/drivers/ras/arm64/ras-cmn.c b/drivers/ras/arm64/ras-cmn.c index 109cdc46a7174..489bbe38de5fe 100644 --- a/drivers/ras/arm64/ras-cmn.c +++ b/drivers/ras/arm64/ras-cmn.c @@ -452,6 +452,16 @@ static int cmn_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nodes); for (int i = 0; i < cmn_config->dev_num; i++) { + + if (!nodes[i].name) + continue; + + ret = arm64_ras_storm_init(&nodes[i]); + if (ret) { + ras_node_err(&nodes[i], "init storm mitigation failed\n"); + return ret; + } + ras_online_node(&nodes[i]); ras_node_init_debugfs(&nodes[i]); } diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index 2fb645659694c..82e8bb10870f1 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -207,6 +207,9 @@ void ras_proc_record(struct ras_record *record, void *data, bool fake) u64 ue; regs.err_status = record_read(record, ERXSTATUS); + + arm64_ras_storm_track_record(record, regs.err_status); + if (!(regs.err_status & ERR_STATUS_V)) return; @@ -265,9 +268,8 @@ void ras_proc_record(struct ras_record *record, void *data, bool fake) record_write(record, ERXSTATUS, regs.err_status); } -static void ras_node_foreach_record(void (*func)(struct ras_record *, void *, bool), - struct ras_node *node, void *data, - unsigned long *bitmap) +void ras_node_foreach_record(void (*func)(struct ras_record *, void *, bool), + struct ras_node *node, void *data, unsigned long *bitmap) { int i; @@ -410,7 +412,7 @@ static int ras_register_irq(struct ras_node *node) return ret; } -static void ras_enable_irq(struct ras_record *record) +void ras_enable_irq(struct ras_record *record) { struct ras_node *node = record->node; u64 err_ctlr; @@ -425,6 +427,15 @@ static void ras_enable_irq(struct ras_record *record) record_write(record, ERXCTLR, err_ctlr); } +void ras_disable_irq(struct ras_record *record) +{ + u64 err_ctlr; + + err_ctlr = record_read(record, ERXCTLR); + err_ctlr &= ~(ERR_CTLR_FI | ERR_CTLR_CFI); + record_write(record, ERXCTLR, err_ctlr); +} + static int ras_get_ce_threshold(struct ras_record *record) { u64 err_fr, err_fr_cec, err_fr_rp; @@ -533,6 +544,11 @@ static void ras_online_record(struct ras_record *record, void *data, bool __unus ras_enable_irq(record); } +static void ras_offline_record(struct ras_record *record, void *data, bool __unused) +{ + ras_disable_irq(record); +} + void ras_online_node(struct ras_node *node) { int count = 0; @@ -547,10 +563,23 @@ void ras_online_node(struct ras_node *node) ras_config_irq(node); + arm64_ras_storm_init(node); + ras_node_foreach_record(ras_online_record, node, NULL, node->record_implemented); } +static void ras_offline_node(struct ras_node *node) +{ + if (!node->name) + return; + + arm64_ras_storm_reset_node(node); + + ras_node_foreach_record(ras_offline_record, node, NULL, + node->record_implemented); +} + static void ras_online_oncore_dev(void *data) { int fhi_irq, eri_irq; @@ -571,6 +600,8 @@ static void ras_offline_oncore_dev(void *data) int fhi_irq, eri_irq; struct ras_node *node = this_cpu_ptr(data); + ras_offline_node(node); + fhi_irq = node->irq[ACPI_AEST_NODE_FAULT_HANDLING]; if (fhi_irq > 0) disable_percpu_irq(fhi_irq); @@ -937,6 +968,12 @@ static int arm64_ras_probe(struct platform_device *pdev) return ret; } + ret = arm64_ras_storm_init(node); + if (ret) { + ras_node_err(node, "init storm mitigation failed\n"); + return ret; + } + if (ras_node_is_oncore(node)) ret = cpuhp_setup_state(CPUHP_AP_ARM_RAS_STARTING, "drivers/ras/arm64/ras:starting", diff --git a/drivers/ras/arm64/ras-inject.c b/drivers/ras/arm64/ras-inject.c index 7fb522a845e7b..5e4b228067569 100644 --- a/drivers/ras/arm64/ras-inject.c +++ b/drivers/ras/arm64/ras-inject.c @@ -82,6 +82,9 @@ static int soft_inject_store(void *data, u64 val) ras_proc_record(&record_inj, &count, true); + memcpy(&record->count, &record_inj.count, sizeof(record->count)); + memcpy(&record->storm, &record_inj.storm, sizeof(record->storm)); + if (count != 1) return -EIO; diff --git a/drivers/ras/arm64/ras-storm.c b/drivers/ras/arm64/ras-storm.c new file mode 100644 index 0000000000000..6ec95a34809be --- /dev/null +++ b/drivers/ras/arm64/ras-storm.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * arm64 RAS error storm mitigation. + * + * This file plumbs the architecture-independent storm tracker + * (drivers/ras/storm.c) into the arm64 RAS driver. Storm tracking is + * per-record while the mitigation is mixed: + * + * - When a record enters storm mode its FHI (fault handling) and CFI + * (corrected fault) interrupts are masked via ERR_CTLR. + * - The first record entering storm starts the node's poll timer + * which drains all currently stormy records. + * - When a record leaves storm mode its interrupts are re-enabled and + * it is removed from the poll. The timer stops once no + * record remains in storm. + * + * Note that ERI / UI (uncorrected error reporting) is intentionally + * left untouched: uncorrected errors must continue to be delivered + * synchronously and never participate in storm suppression. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "ras.h" + +#define INITIAL_CHECK_INTERVAL (5 * 60) /* 5 minutes */ + +#define NUM_HISTORY_BITS (sizeof(u64) * BITS_PER_BYTE) + +/* How many errors within the history buffer mark the start of a storm. */ +#define STORM_BEGIN_THRESHOLD 5 + +/* + * How many polls of machine check bank without an error before declaring + * the storm is over. Since it is tracked by the bitmasks in the history + * field of struct storm_bank the mask is 30 bits [0 ... 29]. + */ +#define STORM_END_POLL_THRESHOLD 29 + +static void arm64_ras_storm_timer_fn(struct timer_list *t) +{ + struct ras_node *node = timer_container_of(node, t, storm_timer); + unsigned long iv = msecs_to_jiffies(node->timer_interval); + int count = 0; + + ras_node_dbg(node, "Stormy bitmap %*pb\n", node->record_count, node->storm_bitmap); + ras_node_foreach_record(ras_proc_record, node, &count, node->storm_bitmap); + + if (count) + iv = max(iv / 2, (unsigned long) HZ/100); + else + iv = min(iv * 2, INITIAL_CHECK_INTERVAL * HZ); + + + node->timer_interval = jiffies_to_msecs(iv); + + if (atomic_read(&node->stormy_count)) { + ras_node_dbg(node, "next poll at %d ms\n", node->timer_interval); + mod_timer(&node->storm_timer, jiffies + iv); + } +} + +static void +arm64_ras_storm_reset_record(struct ras_record *record, void *__unused0, bool __unused1) +{ + struct ras_storm_unit *unit = &record->storm; + + unit->in_storm_mode = false; + unit->history = 0; + unit->timestamp = 0; +} + +void arm64_ras_storm_reset_node(void *data) +{ + struct ras_node *node = data; + + node->begin_threshold = STORM_BEGIN_THRESHOLD; + node->end_poll_threshold = STORM_END_POLL_THRESHOLD; + node->timer_interval = INITIAL_CHECK_INTERVAL * MSEC_PER_SEC; + + timer_delete_sync(&node->storm_timer); + bitmap_set(node->storm_bitmap, 0, node->record_count); + + ras_node_foreach_record(arm64_ras_storm_reset_record, node, NULL, node->record_implemented); +} + +static int arm64_ras_storm_do_init(struct ras_node *node) +{ + node->storm_bitmap = devm_bitmap_zalloc(node->dev, + node->record_count, GFP_KERNEL); + if (!node->storm_bitmap) + return -ENOMEM; + + timer_setup(&node->storm_timer, arm64_ras_storm_timer_fn, 0); + + return devm_add_action_or_reset(node->dev, + arm64_ras_storm_reset_node, node); +} + +int arm64_ras_storm_init(struct ras_node *node) +{ + int ret = 0; + + if (!node->record_count) + return ret; + + /* + * Per-CPU (oncore) nodes re-enter this path on every CPU + * online transition, so the bitmap is allocated only on the + * first call and reused on subsequent re-inits. + */ + if (!node->storm_bitmap) { + ret = arm64_ras_storm_do_init(node); + if (ret) + return ret; + } + + arm64_ras_storm_reset_node(node); + return ret; +} + +/** + * The function maintains the unit's history bitmap and decides whether + * the unit should enter or leave storm mode. + */ +static void ras_track_storm(struct ras_storm_unit *unit, bool corrected) +{ + unsigned long now = jiffies, delta; + unsigned int shift = 1; + u64 history = 0; + + /* + * Check how long it has been since this bank was last checked, + * and adjust the amount of "shift" to apply to history. + */ + delta = now - unit->timestamp; + shift = (delta + HZ) / HZ; + + /* If it has been a long time since the last poll, clear history. */ + if (shift < NUM_HISTORY_BITS) + history = unit->history << shift; + + unit->timestamp = now; + + /* History keeps track of corrected errors. VAL=1 && UC=0 */ + if (corrected) + history |= 1; + + unit->history = history; +} + +void arm64_ras_storm_track_record(struct ras_record *record, u64 err_status) +{ + struct ras_storm_unit *u = &record->storm; + struct ras_node *node = record->node; + + ras_track_storm(u, err_status & ERR_STATUS_CE); + + if (u->in_storm_mode) { + /* + * Storm ends when no corrected error has been seen for + * STORM_END_POLL_THRESHOLD + 1 consecutive polls. + */ + if (u->history & GENMASK_ULL(node->end_poll_threshold, 0)) + return; + + u->in_storm_mode = false; + u->history = 0; + set_bit(record->index, node->storm_bitmap); + + ras_node_info(node, "%s: exited storm mode\n", record->name); + ras_enable_irq(record); + + if (atomic_dec_and_test(&record->node->stormy_count)) + timer_delete(&node->storm_timer); + } else { + if (hweight64(u->history) < node->begin_threshold) + return; + + u->in_storm_mode = true; + clear_bit(record->index, node->storm_bitmap); + + ras_node_info(node, "%s: entered storm mode\n", record->name); + ras_disable_irq(record); + /* + * If this is the first record on this node to enter storm mode + * start polling. + */ + if (atomic_inc_return(&record->node->stormy_count) == 1) + mod_timer(&node->storm_timer, + jiffies + msecs_to_jiffies(node->timer_interval)); + } +} diff --git a/drivers/ras/arm64/ras-sysfs.c b/drivers/ras/arm64/ras-sysfs.c index d8b351ee9aef5..9bf83d92d4209 100644 --- a/drivers/ras/arm64/ras-sysfs.c +++ b/drivers/ras/arm64/ras-sysfs.c @@ -122,6 +122,109 @@ static int node_ce_threshold_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(node_ce_threshold_ops, NULL, node_ce_threshold_set, "%llu\n"); +/* Storm debugfs entries */ + +static int storm_stormy_count_get(void *data, u64 *val) +{ + struct ras_node *node = data; + + *val = atomic_read(&node->stormy_count); + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(storm_stormy_count_ops, storm_stormy_count_get, + NULL, "%llu\n"); + +static int storm_begin_threshold_get(void *data, u64 *val) +{ + struct ras_node *node = data; + + *val = node->begin_threshold; + return 0; +} + +static int storm_begin_threshold_set(void *data, u64 val) +{ + struct ras_node *node = data; + + if (val < 1 || val > BITS_PER_LONG) + return -EINVAL; + + node->begin_threshold = val; + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(storm_begin_threshold_ops, storm_begin_threshold_get, + storm_begin_threshold_set, "%llu\n"); + +static int storm_end_poll_threshold_get(void *data, u64 *val) +{ + struct ras_node *node = data; + + *val = node->end_poll_threshold; + return 0; +} + +static int storm_end_poll_threshold_set(void *data, u64 val) +{ + struct ras_node *node = data; + + if (val >= BITS_PER_LONG) + return -EINVAL; + + node->end_poll_threshold = val; + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(storm_end_poll_threshold_ops, + storm_end_poll_threshold_get, + storm_end_poll_threshold_set, "%llu\n"); + +static int storm_interval_ms_get(void *data, u64 *val) +{ + struct ras_node *node = data; + + *val = node->timer_interval; + return 0; +} + +static int storm_interval_ms_set(void *data, u64 val) +{ + struct ras_node *node = data; + + node->timer_interval = val; + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(storm_interval_ms_ops, + storm_interval_ms_get, + storm_interval_ms_set, "%llu\n"); + +static int record_in_storm_get(void *data, u64 *val) +{ + struct ras_record *record = data; + + *val = atomic_read(&record->node->stormy_count); + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(record_in_storm_ops, record_in_storm_get, + NULL, "%llu\n"); + +static void ras_storm_init_debugfs(struct ras_node *node) +{ + struct dentry *storm_dir; + + if (!node->record_count) + return; + + storm_dir = debugfs_create_dir("storm", node->debugfs); + + debugfs_create_file("stormy_count", 0400, storm_dir, + node, &storm_stormy_count_ops); + debugfs_create_file("begin_threshold", 0600, storm_dir, + node, &storm_begin_threshold_ops); + debugfs_create_file("end_poll_threshold", 0600, storm_dir, + node, &storm_end_poll_threshold_ops); + debugfs_create_file("check_interval_ms", 0600, storm_dir, + node, &storm_interval_ms_ops); +} + static int ras_record_err_count_show(struct seq_file *m, void *data) { struct ras_record *record = m->private; @@ -151,6 +254,8 @@ static void ras_record_init_debugfs(struct ras_record *record) record, &ras_record_err_count_fops); debugfs_create_file("ce_threshold", 0600, record->debugfs, record, &record_ce_threshold_ops); + debugfs_create_file("in_storm", 0400, record->debugfs, + record, &record_in_storm_ops); ras_inject_init_debugfs(record); } @@ -186,6 +291,7 @@ static void ras_oncore_node_init_debugfs(struct ras_node *node) percpu_node, &ras_node_err_count_fops); debugfs_create_file("ce_threshold", 0200, percpu_node->debugfs, percpu_node, &node_ce_threshold_ops); + ras_storm_init_debugfs(percpu_node); ras_init_records_debugfs(percpu_node); } } @@ -208,5 +314,6 @@ void ras_node_init_debugfs(struct ras_node *node) node, &ras_node_err_count_fops); debugfs_create_file("ce_threshold", 0200, node->debugfs, node, &node_ce_threshold_ops); + ras_storm_init_debugfs(node); ras_init_records_debugfs(node); } diff --git a/drivers/ras/arm64/ras.h b/drivers/ras/arm64/ras.h index 75aa4ac83a417..e54082e2c3b9f 100644 --- a/drivers/ras/arm64/ras.h +++ b/drivers/ras/arm64/ras.h @@ -12,6 +12,7 @@ #include #include #include +#include #define DEFAULT_CE_THRESHOLD 1 @@ -93,6 +94,19 @@ struct record_count { u64 ueu; }; +/* + * history: Bitmask tracking errors occurrence. Each set bit + * represents an error seen. + * + * timestamp: Last time (in jiffies) that the bank was polled. + * in_storm_mode: Is this bank in storm mode? + */ +struct ras_storm_unit { + u64 history; + u64 timestamp; + bool in_storm_mode; +}; + struct ras_record { char *name; void __iomem *regs_base; @@ -105,6 +119,7 @@ struct ras_record { struct ce_threshold ce; enum ras_ce_threshold threshold_type; struct record_count count; + struct ras_storm_unit storm; int index; /* @@ -193,6 +208,9 @@ struct ras_node { */ int (*errgsr_mapping)(int errgsr_bit); struct ras_record *records; + unsigned long *storm_bitmap; + + struct timer_list storm_timer; u32 specific_data_size; u32 record_count; @@ -206,6 +224,15 @@ struct ras_node { u8 group_format; u32 irq[AEST_MAX_INTERRUPT_PER_NODE]; u32 gsi[AEST_MAX_INTERRUPT_PER_NODE]; + + /* + * @stormy_count: Updated concurrently from hardirq and + * timer softirqs. + */ + atomic_t stormy_count; + unsigned int begin_threshold; + unsigned int end_poll_threshold; + unsigned int timer_interval; }; #define CASE_READ(res, x) \ @@ -334,4 +361,14 @@ irqreturn_t ras_irq_func(int irq, void *input); void ras_online_node(struct ras_node *node); int ras_cmn700_probe(struct platform_device *pdev); +void ras_disable_irq(struct ras_record *record); +void ras_enable_irq(struct ras_record *record); +void ras_node_foreach_record(void (*func)(struct ras_record *, void *, bool), + struct ras_node *node, void *data, unsigned long *bitmap); + +/* ras-storm.c */ +int arm64_ras_storm_init(struct ras_node *node); +void arm64_ras_storm_track_record(struct ras_record *record, u64 err_status); +void arm64_ras_storm_reset_node(void *data); + #endif /* _DRIVERS_RAS_ARM64_RAS_H_ */ From 300b36c05b976d9f4df76b83ddae1bef57dfa3e3 Mon Sep 17 00:00:00 2001 From: Ruidong Tian Date: Tue, 2 Jun 2026 15:15:39 +0800 Subject: [PATCH 0451/1133] FROMLIST: trace, ras: add ARM RAS extension trace event Add a trace event for hardware errors reported by the ARMv8 RAS extension registers. userspace app can monitor this trace event and decode error information. Signed-off-by: Ruidong Tian Link: https://lore.kernel.org/all/20260602071540.3711528-1-tianruidong@linux.alibaba.com/ --- drivers/ras/arm64/ras-core.c | 5 +++ drivers/ras/ras.c | 3 ++ include/ras/ras_event.h | 79 ++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/drivers/ras/arm64/ras-core.c b/drivers/ras/arm64/ras-core.c index 82e8bb10870f1..3f4e7866bb75e 100644 --- a/drivers/ras/arm64/ras-core.c +++ b/drivers/ras/arm64/ras-core.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "ras.h" @@ -181,6 +182,10 @@ static void ras_do_proc(struct ras_record *record, struct ras_ext_regs *regs) } } + trace_arm_ras_ext_event(record->node->type, record->index, regs, + record->node->specific_data, record->node->specific_data_size, + record->vendor_data, record->vendor_data_size); + atomic_notifier_call_chain(&ras_decoder_chain, 0, record); if (status & ERR_STATUS_CE) diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c index 03df3db623346..c8858b745021c 100644 --- a/drivers/ras/ras.c +++ b/drivers/ras/ras.c @@ -115,6 +115,9 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event); EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event); EXPORT_TRACEPOINT_SYMBOL_GPL(non_standard_event); EXPORT_TRACEPOINT_SYMBOL_GPL(arm_event); +#ifdef CONFIG_ARM64_RAS_EXTN +EXPORT_TRACEPOINT_SYMBOL_GPL(arm_ras_ext_event); +#endif static int __init parse_ras_param(char *str) { diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h index fdb785fa4613a..346c868f3cf70 100644 --- a/include/ras/ras_event.h +++ b/include/ras/ras_event.h @@ -381,6 +381,85 @@ TRACE_EVENT(aer_event, "Not available") ); #endif /* CONFIG_PCIEAER */ + +/* + * ARM RAS Extension Events Report + * + * This event is generated when an error reported by the ARM RAS extension + * hardware is detected. + */ + +#ifdef CONFIG_ARM64_RAS_EXTN +#include +TRACE_EVENT(arm_ras_ext_event, + + TP_PROTO(const u8 type, + const u32 index, + struct ras_ext_regs *regs, + const u8 *specific_data, + const u32 specific_data_size, + const u8 *vendor_data, + const u32 vendor_data_size), + + TP_ARGS(type, index, regs, specific_data, specific_data_size, + vendor_data, vendor_data_size), + + TP_STRUCT__entry( + __field(u8, type) + __field(u32, index) + __field(u64, err_fr) + __field(u64, err_ctlr) + __field(u64, err_status) + __field(u64, err_addr) + __field(u64, err_misc0) + __field(u64, err_misc1) + __field(u64, err_misc2) + __field(u64, err_misc3) + __field(u32, specific_data_size) + __dynamic_array(u8, specific_data, specific_data_size) + __field(u32, vendor_data_size) + __dynamic_array(u8, vendor_data, vendor_data_size) + ), + + TP_fast_assign( + __entry->type = type; + __entry->index = index; + __entry->err_fr = regs->err_fr; + __entry->err_ctlr = regs->err_ctlr; + __entry->err_status = regs->err_status; + __entry->err_addr = regs->err_addr; + __entry->err_misc0 = regs->err_misc[0]; + __entry->err_misc1 = regs->err_misc[1]; + __entry->err_misc2 = regs->err_misc[2]; + __entry->err_misc3 = regs->err_misc[3]; + __entry->specific_data_size = specific_data_size; + memcpy(__get_dynamic_array(specific_data), specific_data, specific_data_size); + __entry->vendor_data_size = vendor_data_size; + memcpy(__get_dynamic_array(vendor_data), vendor_data, vendor_data_size); + ), + + TP_printk("type: %d; index: %d; " + "ERR_FR: %llx; ERR_CTLR: %llx; ERR_STATUS: %llx; " + "ERR_ADDR: %llx; ERR_MISC0: %llx; ERR_MISC1: %llx; " + "ERR_MISC2: %llx; ERR_MISC3: %llx; " + "specific data len:%d; specific data:%s; " + "vendor data len:%d; vendor data:%s", + __entry->type, + __entry->index, + __entry->err_fr, + __entry->err_ctlr, + __entry->err_status, + __entry->err_addr, + __entry->err_misc0, + __entry->err_misc1, + __entry->err_misc2, + __entry->err_misc3, + __entry->specific_data_size, + __print_hex(__get_dynamic_array(specific_data), __entry->specific_data_size), + __entry->vendor_data_size, + __print_hex(__get_dynamic_array(vendor_data), __entry->vendor_data_size)) +); +#endif /* CONFIG_ARM64_RAS_EXTN */ #endif /* _TRACE_HW_EVENT_MC_H */ /* This part must be outside protection */ From 20940be4b6ca2150db01d9776823b185e61b1f9a Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Fri, 18 Sep 2026 15:27:42 +0530 Subject: [PATCH 0452/1133] FROMLIST: dt-bindings: arm: ras: Introduce ARM RAS error sources ARMv8 and later processors implement the RAS (Reliability, Availability and Serviceability) extensions, exposing hardware error records through a standardised register interface. Add Device Tree bindings to describe RAS error sources. Signed-off-by: Umang Chheda Link: https://lore.kernel.org/all/20260918095746.3347893-1-umang.chheda@oss.qualcomm.com/ --- .../devicetree/bindings/arm/arm,ras.yaml | 235 ++++++++++++++++++ include/dt-bindings/arm/arm,ras.h | 11 + 2 files changed, 246 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/arm,ras.yaml create mode 100644 include/dt-bindings/arm/arm,ras.h diff --git a/Documentation/devicetree/bindings/arm/arm,ras.yaml b/Documentation/devicetree/bindings/arm/arm,ras.yaml new file mode 100644 index 0000000000000..8bff222f77c3e --- /dev/null +++ b/Documentation/devicetree/bindings/arm/arm,ras.yaml @@ -0,0 +1,235 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/arm,ras.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ARM RAS error source + +maintainers: + - Umang Chheda + +description: | + ARMv8 and later processors implement the Reliability, Availability and + Serviceability (RAS) extensions. Hardware blocks that support RAS expose + one or more error records through a standardised register interface. Each + error record captures information about a detected hardware error (cache + ECC fault, TLB parity error, interconnect error, etc.) and can optionally + signal the OS via an interrupt. + + Each DT node described by this binding represents one RAS error source — + a hardware block that exposes a set of error records. Error records are + accessed either through system registers (for processor-local resources + such as L1/L2 caches and TLBs) or through a memory-mapped register window + (for shared or off-core resources such as L3 caches, SMMUs and GICs). + +properties: + compatible: + description: + Identifies the class of hardware block this error source belongs to. + arm,ras-processor covers processor error sources (cache, TLB, etc.). + arm,ras-smmu covers SMMU error sources. + arm,ras-gic covers GIC error sources. + enum: + - arm,ras-processor + - arm,ras-smmu + - arm,ras-gic + + reg: + description: + Register windows for this error source. When absent the error records + are accessed through system registers (ERRSELR_EL1 + ERX*_EL1). + When present, each range must have a corresponding entry in reg-names. + The primary error-record window is named "err-records"; additional + optional windows are named "err-group", "fault-inject", and "irq-config". + minItems: 1 + maxItems: 4 + + reg-names: + description: + Names for the register windows listed in reg. The first entry must be + "err-records" for the primary error-record window. + err-group is the error group status register window (ERRGSR). + fault-inject is the fault injection register window (ERXPFG*). + irq-config is the interrupt routing configuration window. + minItems: 1 + maxItems: 4 + items: + enum: + - err-records + - err-group + - fault-inject + - irq-config + + interrupts: + minItems: 1 + items: + - description: + Fault Handling Interrupt (FHI), fired when a corrected error + counter overflows or a deferred error is detected. + - description: + Error Recovery Interrupt (ERI), fired when an uncorrected + recoverable error is detected. + + interrupt-names: + minItems: 1 + items: + - const: fhi + - const: eri + + arm,group-format: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Layout of the memory-mapped error-record group window. + Determines the number of ERRGSR registers available. + A 4 KiB group provides 1 ERRGSR, a 16 KiB group provides + 4 ERRGSRs, and a 64 KiB group provides 14 ERRGSRs. + Each ERRGSR reports status for up to 56 error records. + enum: [0, 1, 2] + + arm,num-records: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Total number of error records in this error source, including both + implemented and unimplemented slots. + minimum: 1 + + arm,record-impl: + $ref: /schemas/types.yaml#/definitions/uint64-array + description: + Bitmap of implemented error records. Bit N set to 1 means error + record N is present and active in this error source. Bit N set to 0 + means record N is not implemented and must be skipped. The array + length must equal the number of ERRGSRs implied by arm,group-format + (1 element for 4K, 4 for 16K, 14 for 64K). For system-register + nodes (no reg property) a single u64 element is used. + minItems: 1 + maxItems: 14 + + arm,status-reporting: + $ref: /schemas/types.yaml#/definitions/uint64-array + description: + Bitmap indicating which implemented error records require direct + polling of ERX_STATUS by software. Bit N set to 1 means error + record N is not represented in an ERRGSR status register and must + be checked by reading ERX_STATUS directly. Bit N set to 0 means + error record N is represented in an ERRGSR status register and can + be discovered through the ERRGSR scan path. + For system-register error sources (no reg property), ERRGSR + registers are not present. Therefore all implemented error records + must be polled directly and arm,status-reporting shall be identical + to arm,record-impl. + The number of array elements shall match arm,record-impl. + minItems: 1 + maxItems: 14 + + arm,addressing-mode: + $ref: /schemas/types.yaml#/definitions/uint64-array + description: + Bitmap indicating the address type reported in ERR_ADDR for each + implemented error record. Bit N set to 1 means error record N + reports a Logical Address (LA); bit N set to 0 means it reports a + System Physical Address (SPA). When absent all records are assumed + to report SPA. The number of array elements shall match + arm,record-impl. + minItems: 1 + maxItems: 14 + + # Processor error source properties (arm,ras-processor only) + arm,cache-ref: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the cache node (L1, L2, or L3) that this processor error + source monitors. + + # SMMU error source properties (arm,ras-smmu only) + arm,smmu-ref: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the SMMU node that this error source monitors. + + # GIC error source properties (arm,ras-gic only) + arm,gic-ref: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the GIC node that this error source monitors. + +required: + - compatible + - arm,num-records + - arm,record-impl + - arm,status-reporting + +dependentRequired: + reg: ['arm,group-format'] + +allOf: + - if: + properties: + compatible: + contains: + const: arm,ras-processor + then: + required: + - arm,cache-ref + else: + properties: + arm,cache-ref: false + + - if: + properties: + compatible: + contains: + const: arm,ras-smmu + then: + required: + - arm,smmu-ref + else: + properties: + arm,smmu-ref: false + + - if: + properties: + compatible: + contains: + const: arm,ras-gic + then: + required: + - arm,gic-ref + else: + properties: + arm,gic-ref: false + +unevaluatedProperties: false + +examples: + - | + #include + #include + + cache-error-l2 { + compatible = "arm,ras-processor"; + arm,num-records = <1>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x1>; + arm,cache-ref = <&l2_0>; + interrupts = ; + interrupt-names = "fhi"; + }; + + - | + #include + #include + + gic-error@17a00000 { + compatible = "arm,ras-gic"; + reg = <0x0 0x17a00000 0x0 0x10000>; + reg-names = "err-records"; + arm,group-format = ; + arm,num-records = <1>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x0>; + arm,gic-ref = <&gic>; + interrupts = ; + interrupt-names = "fhi"; + }; diff --git a/include/dt-bindings/arm/arm,ras.h b/include/dt-bindings/arm/arm,ras.h new file mode 100644 index 0000000000000..cd11e360fdae5 --- /dev/null +++ b/include/dt-bindings/arm/arm,ras.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ + +#ifndef _DT_BINDINGS_ARM_RAS_H +#define _DT_BINDINGS_ARM_RAS_H + +/* arm,group-format - error record group register window layout */ +#define ARM_RAS_GROUP_4K 0 /* 4 KiB, 1 ERRGSR */ +#define ARM_RAS_GROUP_16K 1 /* 16 KiB, 4 ERRGSRs */ +#define ARM_RAS_GROUP_64K 2 /* 64 KiB, 14 ERRGSRs */ + +#endif /* _DT_BINDINGS_ARM_RAS_H */ From 8b019a24da8d460817554aa2a050006c4287125e Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Fri, 18 Sep 2026 15:27:43 +0530 Subject: [PATCH 0453/1133] FROMLIST: arm64: ras: Add Device Tree frontend Add a Device Tree frontend for the ARM64 RAS driver, allowing it to be used on platforms without ACPI firmware. The error sources defined in DT are registered as arm64_ras platform devices at boot. The frontend produces the same software fwnode properties as the ACPI path, so the core driver probes DT and ACPI nodes identically without any firmware-specific knowledge. Signed-off-by: Umang Chheda Link: https://lore.kernel.org/all/20260918095746.3347893-1-umang.chheda@oss.qualcomm.com/ --- drivers/ras/arm64/Kconfig | 25 ++- drivers/ras/arm64/Makefile | 2 + drivers/ras/arm64/ras-of.c | 383 +++++++++++++++++++++++++++++++++++++ 3 files changed, 405 insertions(+), 5 deletions(-) create mode 100644 drivers/ras/arm64/ras-of.c diff --git a/drivers/ras/arm64/Kconfig b/drivers/ras/arm64/Kconfig index dcdeaa216d676..8bdb219bc90f5 100644 --- a/drivers/ras/arm64/Kconfig +++ b/drivers/ras/arm64/Kconfig @@ -1,16 +1,31 @@ # SPDX-License-Identifier: GPL-2.0 # -# ARM Error Source Table Support +# ARM RAS driver # # Copyright (c) 2025, Alibaba Group. # +config ARM64_RAS_DT + bool "ARM64 RAS Device Tree support" + depends on ARM64_RAS_EXTN && OF + help + Enable Device Tree support for the ARM64 RAS driver. + + When selected, RAS error sources described in the Device Tree + (arm,ras-processor, arm,ras-smmu, arm,ras-gic etc) are registered + as platform devices at boot, allowing the driver to be used on + platforms without ACPI firmware. + config ARM64_RAS_DRIVER tristate "ARM64 RAS Driver" - depends on ARM64 && ACPI_AEST && RAS + depends on ARM64 && (ACPI_AEST || ARM64_RAS_DT) && RAS help - This is the RAS driver for the arm64 architecture. It depends on - the Arm Error Source Table (AEST) to provide basic register and - interrupt information. + This is the RAS driver for the arm64 architecture. It uses the + ARMv8 RAS extension register interface to discover, configure, + and handle hardware errors from processor caches, SMMUs, and GICs. + + On ACPI systems the error source topology is provided by the AEST + ACPI table (requires ACPI_AEST). On Device Tree systems it is + provided by "arm,ras-*" nodes in the DT root (requires ARM64_RAS_DT). If set, the kernel will report and process hardware errors. diff --git a/drivers/ras/arm64/Makefile b/drivers/ras/arm64/Makefile index 6897798f73144..aee2f9de37f6a 100644 --- a/drivers/ras/arm64/Makefile +++ b/drivers/ras/arm64/Makefile @@ -7,3 +7,5 @@ arm64_ras-y += ras-sysfs.o arm64_ras-y += ras-inject.o arm64_ras-y += ras-cmn.o arm64_ras-y += ras-storm.o + +obj-$(CONFIG_ARM64_RAS_DT) += ras-of.o diff --git a/drivers/ras/arm64/ras-of.c b/drivers/ras/arm64/ras-of.c new file mode 100644 index 0000000000000..d876031f24741 --- /dev/null +++ b/drivers/ras/arm64/ras-of.c @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2026 Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef pr_fmt +#define pr_fmt(fmt) "DT RAS: " fmt + +/* Maximum number of software fwnode properties per RAS node */ +#define RAS_OF_MAX_PROPS 20 + +static const unsigned long ras_of_type_processor __initconst = + ACPI_AEST_PROCESSOR_ERROR_NODE; +static const unsigned long ras_of_type_smmu __initconst = + ACPI_AEST_SMMU_ERROR_NODE; +static const unsigned long ras_of_type_gic __initconst = + ACPI_AEST_GIC_ERROR_NODE; + +static const struct of_device_id ras_of_match[] __initconst = { + { .compatible = "arm,ras-processor", .data = &ras_of_type_processor }, + { .compatible = "arm,ras-smmu", .data = &ras_of_type_smmu }, + { .compatible = "arm,ras-gic", .data = &ras_of_type_gic }, + { } +}; + +static const char * const __initconst ras_of_irq_res_names[] = { + [ACPI_AEST_NODE_FAULT_HANDLING] = AEST_FHI_NAME, + [ACPI_AEST_NODE_ERROR_RECOVERY] = AEST_ERI_NAME, +}; + +static const char * const __initconst ras_of_dt_irq_names[] = { + "fhi", "eri" +}; + +static int __init ras_of_build_node_data(struct device_node *np, + u8 node_type, int index, + int fhi_virq, + u8 **data_out, u32 *size_out) +{ + *data_out = NULL; + *size_out = 0; + + switch (node_type) { + case ACPI_AEST_PROCESSOR_ERROR_NODE: { + /* + * Allocate the processor header plus the cache sub-structure. + * resource_type is inferred from the presence of the 'cache' + * phandle: if present the resource is a cache, otherwise it + * is treated as a generic processor resource. + * flags (SHARED/GLOBAL) are inferred from the interrupt type: + * a PPI is per-PE (global); an SPI is shared across a cluster. + */ + size_t total = sizeof(struct acpi_aest_processor) + + sizeof(struct acpi_aest_processor_cache); + struct acpi_aest_processor_cache *c; + struct acpi_aest_processor *proc; + struct device_node *cache_np; + u8 pflags; + + proc = kzalloc(total, GFP_KERNEL); + if (!proc) + return -ENOMEM; + + cache_np = of_parse_phandle(np, "arm,cache-ref", 0); + if (cache_np) { + proc->resource_type = ACPI_AEST_CACHE_RESOURCE; + c = (struct acpi_aest_processor_cache *)(proc + 1); + /* + * alloc_ras_node_name() reads c->cache_reference as + * the name disambiguator for shared/global nodes. + */ + c->cache_reference = cache_np->phandle; + of_node_put(cache_np); + } else { + proc->resource_type = ACPI_AEST_GENERIC_RESOURCE; + } + + /* + * Infer scope from the FHI interrupt type: a PPI is + * per-PE (set GLOBAL); an SPI is cluster-shared (set SHARED). + * alloc_ras_node_name() uses flags to choose the name format. + */ + pflags = irq_is_percpu(fhi_virq) ? + ACPI_AEST_PROC_FLAG_GLOBAL : + ACPI_AEST_PROC_FLAG_SHARED; + proc->flags = pflags; + proc->processor_id = (u32)index; + + *data_out = (u8 *)proc; + *size_out = (u32)total; + break; + } + case ACPI_AEST_SMMU_ERROR_NODE: { + struct acpi_aest_smmu *smmu; + struct device_node *smmu_np; + + smmu = kzalloc_obj(*smmu, GFP_KERNEL); + if (!smmu) + return -ENOMEM; + + smmu_np = of_parse_phandle(np, "arm,smmu-ref", 0); + if (smmu_np) { + smmu->iort_node_reference = smmu_np->phandle; + of_node_put(smmu_np); + } + + *data_out = (u8 *)smmu; + *size_out = sizeof(*smmu); + break; + } + case ACPI_AEST_GIC_ERROR_NODE: { + struct acpi_aest_gic *gic; + struct device_node *gic_np; + + gic = kzalloc_obj(*gic, GFP_KERNEL); + if (!gic) + return -ENOMEM; + + gic_np = of_parse_phandle(np, "arm,gic-ref", 0); + if (gic_np) { + gic->instance_id = gic_np->phandle; + of_node_put(gic_np); + } + *data_out = (u8 *)gic; + *size_out = sizeof(*gic); + break; + } + default: + return -EINVAL; + } + + return 0; +} + +/* + * Determine the register access type from the DT node: + * no reg -> system-register access (ERRSELR_EL1 + ERX*_EL1) + * 1 range -> memory-mapped access + * 2+ ranges -> single-record memory-mapped access + */ +static u8 __init ras_of_interface_type(struct device_node *np) +{ + int addr_cells, size_cells, reg_len; + + if (!of_property_present(np, "reg")) + return ACPI_AEST_NODE_SYSTEM_REGISTER; + + addr_cells = of_n_addr_cells(np); + size_cells = of_n_size_cells(np); + if (addr_cells <= 0 || size_cells <= 0) + return ACPI_AEST_NODE_SYSTEM_REGISTER; + + reg_len = of_property_count_elems_of_size(np, "reg", sizeof(u32)); + if (reg_len <= 0) + return ACPI_AEST_NODE_SYSTEM_REGISTER; + + if (reg_len <= addr_cells + size_cells) + return ACPI_AEST_NODE_MEMORY_MAPPED; + + return ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED; +} + +static resource_size_t __init ras_of_mem_size(u32 gfmt) +{ + switch (gfmt) { + case ACPI_AEST_NODE_GROUP_FORMAT_16K: + return SZ_16K; + case ACPI_AEST_NODE_GROUP_FORMAT_64K: + return SZ_64K; + default: + return SZ_4K; + } +} + +static u32 __init ras_of_virq_to_gsiv(int virq) +{ + struct irq_data *irqd = irq_get_irq_data(virq); + + return irqd ? (u32)irqd->hwirq : 0; +} + +static int __init ras_of_attach_fwnode(struct device_node *np, + struct platform_device *pdev, + u8 node_type, u8 itype, u32 gfmt, + int index, int fhi_virq, + u32 fhi_gsiv, u32 eri_gsiv) +{ + u64 rec_impl[14] = { }; + u64 stat_rep[14] = { }; + u64 addr_mode[14] = { }; + u64 err_group_base = 0, fault_inject_base = 0, irq_cfg_base = 0; + struct property_entry props[RAS_OF_MAX_PROPS] = { }; + struct resource res; + u8 *node_data = NULL; + u32 node_data_size = 0; + u32 nrec = 1; + int group_len, p = 0, i, ret; + + of_property_read_u32(np, "arm,num-records", &nrec); + + switch (gfmt) { + case ACPI_AEST_NODE_GROUP_FORMAT_16K: + group_len = 4; + break; + case ACPI_AEST_NODE_GROUP_FORMAT_64K: + group_len = 14; + break; + default: + group_len = 1; + break; + } + + of_property_read_u64_array(np, "arm,record-impl", rec_impl, group_len); + of_property_read_u64_array(np, "arm,status-reporting", stat_rep, group_len); + of_property_read_u64_array(np, "arm,addressing-mode", addr_mode, group_len); + + /* + * DT binding: bit=1 means record IS implemented. + * ras-core.c uses for_each_clear_bit() on record_implemented, so + * bit=0 means implemented internally. Invert before storing. + */ + for (i = 0; i < group_len; i++) + rec_impl[i] = ~rec_impl[i]; + + /* Named MMIO windows — only present on memory-mapped nodes */ + if (itype != ACPI_AEST_NODE_SYSTEM_REGISTER) { + int idx; + + idx = of_property_match_string(np, "reg-names", "err-group"); + if (idx >= 0 && !of_address_to_resource(np, idx, &res)) + err_group_base = res.start; + + idx = of_property_match_string(np, "reg-names", "fault-inject"); + if (idx >= 0 && !of_address_to_resource(np, idx, &res)) + fault_inject_base = res.start; + + idx = of_property_match_string(np, "reg-names", "irq-config"); + if (idx >= 0 && !of_address_to_resource(np, idx, &res)) + irq_cfg_base = res.start; + } + + ret = ras_of_build_node_data(np, node_type, index, fhi_virq, + &node_data, &node_data_size); + if (ret) + return ret; + + props[p++] = PROPERTY_ENTRY_U8("arm,node-type", node_type); + props[p++] = PROPERTY_ENTRY_U8("arm,interface-type", itype); + props[p++] = PROPERTY_ENTRY_U8("arm,group-format", (u8)gfmt); + props[p++] = PROPERTY_ENTRY_U32("arm,error-records-count", nrec); + props[p++] = PROPERTY_ENTRY_U32("arm,error-records-index", 0); + props[p++] = PROPERTY_ENTRY_U32("arm,interface-flags", 0); + props[p++] = PROPERTY_ENTRY_U64_ARRAY_LEN("arm,record-implemented", + rec_impl, group_len); + props[p++] = PROPERTY_ENTRY_U64_ARRAY_LEN("arm,status-reporting", + stat_rep, group_len); + props[p++] = PROPERTY_ENTRY_U64_ARRAY_LEN("arm,addressing-mode", + addr_mode, group_len); + props[p++] = PROPERTY_ENTRY_U64("arm,error-group-base", err_group_base); + props[p++] = PROPERTY_ENTRY_U64("arm,fault-inject-base", fault_inject_base); + props[p++] = PROPERTY_ENTRY_U64("arm,interrupt-config-base", irq_cfg_base); + props[p++] = PROPERTY_ENTRY_U32("arm,fhi-gsiv", fhi_gsiv); + props[p++] = PROPERTY_ENTRY_U32("arm,eri-gsiv", eri_gsiv); + + if (node_data && node_data_size) + props[p++] = PROPERTY_ENTRY_U8_ARRAY_LEN("arm,node-specific-data", + node_data, node_data_size); + + ret = device_create_managed_software_node(&pdev->dev, props, NULL); + + kfree(node_data); + return ret; +} + +static int __init ras_of_init_one_node(struct device_node *np, u8 node_type, + int index) +{ + struct resource res[AEST_MAX_INTERRUPT_PER_NODE + 1] = { }; + struct platform_device *pdev; + u32 gfmt = ACPI_AEST_NODE_GROUP_FORMAT_4K; + u32 gsiv[AEST_MAX_INTERRUPT_PER_NODE] = { }; + int virq[AEST_MAX_INTERRUPT_PER_NODE] = { }; + int nres = 0, ret, i; + u8 itype; + + itype = ras_of_interface_type(np); + of_property_read_u32(np, "arm,group-format", &gfmt); + + pdev = platform_device_alloc("arm64_ras", PLATFORM_DEVID_AUTO); + if (!pdev) + return -ENOMEM; + + if (itype != ACPI_AEST_NODE_SYSTEM_REGISTER) { + struct resource mmio_res; + + ret = of_address_to_resource(np, 0, &mmio_res); + if (ret) { + pr_err("node %pOF: missing 'reg' for MMIO interface\n", np); + goto err_put; + } + res[nres].name = AEST_NODE_NAME; + res[nres].start = mmio_res.start; + res[nres].end = mmio_res.start + ras_of_mem_size(gfmt) - 1; + res[nres].flags = IORESOURCE_MEM; + nres++; + } + + for (i = 0; i < AEST_MAX_INTERRUPT_PER_NODE; i++) { + int irq_num = of_irq_get_byname(np, ras_of_dt_irq_names[i]); + + if (irq_num <= 0) + continue; + + gsiv[i] = ras_of_virq_to_gsiv(irq_num); + virq[i] = irq_num; + + res[nres].name = ras_of_irq_res_names[i]; + res[nres].start = irq_num; + res[nres].end = irq_num; + res[nres].flags = IORESOURCE_IRQ; + nres++; + } + + ret = platform_device_add_resources(pdev, res, nres); + if (ret) + goto err_put; + + ret = ras_of_attach_fwnode(np, pdev, node_type, itype, gfmt, index, + virq[ACPI_AEST_NODE_FAULT_HANDLING], + gsiv[ACPI_AEST_NODE_FAULT_HANDLING], + gsiv[ACPI_AEST_NODE_ERROR_RECOVERY]); + if (ret) + goto err_put; + + ret = platform_device_add(pdev); + if (ret) + goto err_put; + + pr_debug("registered RAS node %pOF as arm64_ras.%d\n", np, pdev->id); + return 0; + +err_put: + platform_device_put(pdev); + return ret; +} + +static int __init ras_of_init(void) +{ + const struct of_device_id *match; + struct device_node *np; + int index = 0, ret; + + if (!acpi_disabled) + return 0; + + for_each_matching_node_and_match(np, ras_of_match, &match) { + u8 node_type = *(const unsigned long *)match->data; + + ret = ras_of_init_one_node(np, node_type, index++); + if (ret) { + pr_err("failed to register RAS node %pOF: %d\n", + np, ret); + of_node_put(np); + return ret; + } + } + + if (index) + pr_info("registered %d RAS error source(s) from DT\n", index); + + return 0; +} +subsys_initcall_sync(ras_of_init); From 5400d9d086e4a9d392f5f5009cecc3772047e441 Mon Sep 17 00:00:00 2001 From: Faiyaz Mohammed Date: Wed, 28 Oct 2026 20:33:28 +0530 Subject: [PATCH 0454/1133] FROMLIST: dt-bindings: cache: qcom,llcc: allow optional second interrupt for LCP/SRP ECC QCM2390 (Shikra) has an LCP/SRP block that signals DDR DRAM ECC errors on a dedicated interrupt line separate from the existing TRP/DRP cache ECC interrupt. Allow an optional second interrupt in the LLCC binding, add interrupt-names with "llcc-ecc" and "llcc-lcp-ecc", and enforce both are present when compatible is qcom,shikra-llcc. Signed-off-by: Faiyaz Mohammed Link: https://lore.kernel.org/r/20261014-master-v1-1-aba3cfcfbac9@oss.qualcomm.com --- .../devicetree/bindings/cache/qcom,llcc.yaml | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml index 2141e5d4de63b..3546cf7c25195 100644 --- a/Documentation/devicetree/bindings/cache/qcom,llcc.yaml +++ b/Documentation/devicetree/bindings/cache/qcom,llcc.yaml @@ -64,7 +64,17 @@ properties: maxItems: 18 interrupts: - maxItems: 1 + minItems: 1 + items: + - description: TRP/DRP LLCC cache ECC (ddrss_apps_interrupt[2]) + - description: LCP/SRP DDR DRAM ECC (ddrss_apps_interrupt[1]), present + on platforms with an LCP/SRP block such as QCM2390 + + interrupt-names: + minItems: 1 + items: + - const: llcc-ecc + - const: llcc-lcp-ecc memory-region: maxItems: 1 @@ -234,6 +244,20 @@ allOf: - const: llcc1_base - const: llcc_broadcast_base + - if: + properties: + compatible: + contains: + const: qcom,shikra-llcc + then: + properties: + interrupts: + minItems: 2 + interrupt-names: + minItems: 2 + required: + - interrupt-names + - if: properties: compatible: From b6ef9148c909e857e57cc7c680b45040032b1c36 Mon Sep 17 00:00:00 2001 From: Faiyaz Mohammed Date: Wed, 28 Oct 2026 20:35:41 +0530 Subject: [PATCH 0455/1133] FROMLIST: soc: qcom: llcc: add LCP/SRP DDR DRAM ECC register offsets Add LCP/SRP ECC register offsets to struct llcc_edac_reg_offset and create llcc_lcp_srp_edac_reg_offset for QCM2390, leaving the shared llcc_v2_1_edac_reg_offset table unchanged. Switch shikra_cfg to the new table so other platforms with the same block can reuse it. Add lcp_irq to struct llcc_drv_data and retrieve the optional second interrupt in qcom_llcc_probe(), propagating non-absence errors so the driver defers correctly. Signed-off-by: Faiyaz Mohammed Link: https://lore.kernel.org/r/20261014-master-v1-2-aba3cfcfbac9@oss.qualcomm.com --- drivers/soc/qcom/llcc-qcom.c | 44 +++++++++++++++++++++++++++++- include/linux/soc/qcom/llcc-qcom.h | 13 +++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index d7a42a8040a16..d39d440a9e0c5 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -4509,6 +4509,41 @@ static const struct llcc_edac_reg_offset llcc_v2_1_edac_reg_offset = { .drp_ecc_db_err_syn0 = 0x52120, }; +static const struct llcc_edac_reg_offset llcc_lcp_srp_edac_reg_offset = { + .trp_ecc_error_status0 = 0x20344, + .trp_ecc_error_status1 = 0x20348, + .trp_ecc_sb_err_syn0 = 0x2034c, + .trp_ecc_db_err_syn0 = 0x20370, + .trp_ecc_error_cntr_clear = 0x20440, + .trp_interrupt_0_status = 0x20480, + .trp_interrupt_0_clear = 0x20484, + .trp_interrupt_0_enable = 0x20488, + + /* LLCC Common registers */ + .cmn_status0 = 0x3400c, + .cmn_interrupt_0_enable = 0x3401c, + .cmn_interrupt_1_enable = 0x3402c, + .cmn_interrupt_2_enable = 0x3403c, + + /* LLCC DRP registers */ + .drp_ecc_error_cfg = 0x50000, + .drp_ecc_error_cntr_clear = 0x50004, + .drp_interrupt_status = 0x50020, + .drp_interrupt_clear = 0x50028, + .drp_interrupt_enable = 0x5002c, + .drp_ecc_error_status0 = 0x520f4, + .drp_ecc_error_status1 = 0x520f8, + .drp_ecc_sb_err_syn0 = 0x520fc, + .drp_ecc_db_err_syn0 = 0x52120, + + /* LCP/SRP DDR DRAM ECC registers */ + .lcp_srp_ecc_error_cntr_clear = 0x59004, + .lcp_srp_ecc_error_status1 = 0x59010, + .lcp_srp_interrupt_status = 0x59070, + .lcp_srp_interrupt_clear = 0x59074, + .lcp_srp_interrupt_enable = 0x59078, +}; + static const struct llcc_edac_reg_offset llcc_v6_edac_reg_offset = { .trp_ecc_error_status0 = 0x47448, .trp_ecc_error_status1 = 0x47450, @@ -4767,7 +4802,7 @@ static const struct qcom_llcc_config shikra_cfg[] = { .sct_data = shikra_data, .size = ARRAY_SIZE(shikra_data), .reg_offset = llcc_v2_1_reg_offset, - .edac_reg_offset = &llcc_v2_1_edac_reg_offset, + .edac_reg_offset = &llcc_lcp_srp_edac_reg_offset, .irq_configured = true, }, }; @@ -5799,6 +5834,13 @@ static int qcom_llcc_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, drv_data->ecc_irq, "failed to get IRQ resource\n"); + if (cfg->edac_reg_offset && cfg->edac_reg_offset->lcp_srp_interrupt_enable) { + drv_data->lcp_irq = platform_get_irq_optional(pdev, 1); + if (drv_data->lcp_irq < 0 && drv_data->lcp_irq != -ENXIO) { + ret = drv_data->lcp_irq; + goto err; + } + } drv_data->edac_reg_offset = cfg->edac_reg_offset; drv_data->ecc_irq_configured = cfg->irq_configured; drv_data->dev = dev; diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h index 713cb0221b14c..020d0b4116d23 100644 --- a/include/linux/soc/qcom/llcc-qcom.h +++ b/include/linux/soc/qcom/llcc-qcom.h @@ -139,6 +139,7 @@ struct llcc_edac_reg_offset { /* LLCC Common registers */ u32 cmn_status0; u32 cmn_interrupt_0_enable; + u32 cmn_interrupt_1_enable; u32 cmn_interrupt_2_enable; /* LLCC DRP registers */ @@ -151,6 +152,16 @@ struct llcc_edac_reg_offset { u32 drp_ecc_error_status1; u32 drp_ecc_sb_err_syn0; u32 drp_ecc_db_err_syn0; + + /* + * LCP/SRP DDR DRAM ECC registers (LLCC broadcast space). + * Zero on platforms that do not support LCP/SRP ECC reporting. + */ + u32 lcp_srp_ecc_error_cntr_clear; + u32 lcp_srp_ecc_error_status1; + u32 lcp_srp_interrupt_status; + u32 lcp_srp_interrupt_clear; + u32 lcp_srp_interrupt_enable; }; /** @@ -165,6 +176,7 @@ struct llcc_edac_reg_offset { * @cfg_size: size of the config data table * @num_banks: Number of LLCC banks * @ecc_irq: interrupt for LLCC cache error detection and reporting + * @lcp_irq: interrupt for LCP/SRP DDR DRAM ECC error reporting or negative errno on failure * @ecc_irq_configured: 'True' if firmware has already configured the irq propagation * @version: Indicates the LLCC version * @desc: Array pointer of pre-allocated LLCC slice descriptors @@ -180,6 +192,7 @@ struct llcc_drv_data { u32 cfg_size; u32 num_banks; int ecc_irq; + int lcp_irq; bool ecc_irq_configured; u32 version; struct llcc_slice_desc *desc; From 51bd1e6078fc39bb84722d9aa466ef12f2f5dc0b Mon Sep 17 00:00:00 2001 From: Faiyaz Mohammed Date: Wed, 28 Oct 2026 20:37:27 +0530 Subject: [PATCH 0456/1133] FROMLIST: edac: qcom: add LCP/SRP DDR DRAM ECC support for Shikra Add qcom_llcc_lcp_setup() to enable LCP/SRP interrupt routing when firmware has not pre-configured it, and llcc_lcp_ecc_irq_handler() to report per-bank correctable and uncorrectable DDR DRAM ECC errors. LCP/SRP setup is skipped when ecc_irq_configured is set (e.g. Shikra, where DSF firmware handles IRQ routing). A missing lcp_irq is non-fatal; TRP/DRP ECC reporting continues unaffected. Signed-off-by: Faiyaz Mohammed Link: https://lore.kernel.org/r/20261014-master-v1-3-aba3cfcfbac9@oss.qualcomm.com --- drivers/edac/qcom_edac.c | 147 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/drivers/edac/qcom_edac.c b/drivers/edac/qcom_edac.c index f3da9385ca0d8..b4f7b2493650c 100644 --- a/drivers/edac/qcom_edac.c +++ b/drivers/edac/qcom_edac.c @@ -3,6 +3,7 @@ * Copyright (c) 2018, The Linux Foundation. All rights reserved. */ +#include #include #include #include @@ -44,8 +45,16 @@ #define SB_DB_TRP_INTERRUPT_ENABLE 0x3 #define TRP0_INTERRUPT_ENABLE 0x1 #define DRP0_INTERRUPT_ENABLE BIT(6) +#define SRP_INTERRUPT_ENABLE BIT(7) #define SB_DB_DRP_INTERRUPT_ENABLE 0x3 +/* LCP/SRP DDR DRAM ECC */ +#define LCP_SB_ECC_ERROR BIT(0) +#define LCP_DB_ECC_ERROR BIT(1) +#define LCP_SRP_SB_DB_INTERRUPT_ENABLE 0x3 +#define LCP_DB_ERR_COUNT_MASK GENMASK(4, 0) +#define LCP_SB_ERR_COUNT_MASK GENMASK(23, 16) + #define ECC_POLL_MSEC 5000 enum { @@ -124,6 +133,29 @@ static int qcom_llcc_core_setup(struct llcc_drv_data *drv, struct regmap *llcc_b return ret; } +/* + * Enable LCP/SRP DDR DRAM ECC interrupt generation and route events to + * ddrss_apps_interrupt[1] via cmn_interrupt_1_enable. Only called when + * !ecc_irq_configured; on platforms like Shikra where firmware pre-configures + * both TRP/DRP and LCP/SRP routing, the driver skips this and only requests + * the IRQ handler. + */ +static int qcom_llcc_lcp_setup(struct llcc_drv_data *drv, + struct regmap *llcc_bcast_regmap) +{ + int ret; + + ret = regmap_set_bits(llcc_bcast_regmap, + drv->edac_reg_offset->cmn_interrupt_1_enable, + SRP_INTERRUPT_ENABLE); + if (ret) + return ret; + + return regmap_set_bits(llcc_bcast_regmap, + drv->edac_reg_offset->lcp_srp_interrupt_enable, + LCP_SRP_SB_DB_INTERRUPT_ENABLE); +} + /* Clear the error interrupt and counter registers */ static int qcom_llcc_clear_error_status(int err_type, struct llcc_drv_data *drv) @@ -334,6 +366,92 @@ static void llcc_ecc_check(struct edac_device_ctl_info *edev_ctl) llcc_ecc_irq_handler(0, edev_ctl); } +/* + * Handler for the optional LCP/SRP DDR DRAM ECC interrupt + * (ddrss_apps_interrupt[1]). The LCP/SRP registers live in each LLCC + * instance's address space, so iterate over all banks and read status + * per-instance. Broadcast-write the clear after the full loop, mirroring + * the TRP/DRP handler pattern. + */ +static irqreturn_t llcc_lcp_ecc_irq_handler(int irq, void *edev_ctl) +{ + struct edac_device_ctl_info *edac_dev_ctl = edev_ctl; + struct llcc_drv_data *drv = edac_dev_ctl->dev->platform_data; + const struct llcc_edac_reg_offset *reg = drv->edac_reg_offset; + irqreturn_t irq_rc = IRQ_NONE; + u32 intr_status, err_status, clr_reg; + int i, ret; + + /* Iterate over banks: LCP/SRP status registers are per-LLCC instance */ + for (i = 0; i < drv->num_banks; i++) { + ret = regmap_read(drv->regmaps[i], reg->lcp_srp_interrupt_status, + &intr_status); + if (ret) + continue; + + intr_status &= LCP_SB_ECC_ERROR | LCP_DB_ECC_ERROR; + if (!intr_status) + continue; + + irq_rc = IRQ_HANDLED; + + ret = regmap_read(drv->regmaps[i], reg->lcp_srp_ecc_error_status1, + &err_status); + if (ret) { + edac_printk(KERN_ERR, EDAC_LLCC, + "LCP/SRP error status read failed for bank%u: %d\n", + i, ret); + continue; + } + + if (intr_status & LCP_DB_ECC_ERROR) { + u32 db_cnt = FIELD_GET(LCP_DB_ERR_COUNT_MASK, err_status); + + edac_printk(KERN_CRIT, EDAC_LLCC, + "LCP/SRP DDR DRAM Double-bit ECC error in bank%u: count=%u status=0x%08x\n", + i, db_cnt, err_status); + edac_device_handle_ue(edac_dev_ctl, 0, i, + "LCP/SRP DDR DRAM uncorrectable error"); + } + + if (intr_status & LCP_SB_ECC_ERROR) { + u32 sb_cnt = FIELD_GET(LCP_SB_ERR_COUNT_MASK, err_status); + + edac_printk(KERN_WARNING, EDAC_LLCC, + "LCP/SRP DDR DRAM Single-bit ECC error in bank%u: count=%u status=0x%08x\n", + i, sb_cnt, err_status); + edac_device_handle_ce(edac_dev_ctl, 0, i, + "LCP/SRP DDR DRAM correctable error"); + } + } + + if (irq_rc != IRQ_HANDLED) + return irq_rc; + + clr_reg = reg->lcp_srp_interrupt_clear ? + reg->lcp_srp_interrupt_clear : + reg->lcp_srp_interrupt_status; + + if (clr_reg) { + ret = regmap_write(drv->bcast_regmap, clr_reg, + LCP_SB_ECC_ERROR | LCP_DB_ECC_ERROR); + if (ret) + edac_printk(KERN_ERR, EDAC_LLCC, + "LCP/SRP interrupt clear failed: %d\n", ret); + } + + if (reg->lcp_srp_ecc_error_cntr_clear) { + ret = regmap_write(drv->bcast_regmap, + reg->lcp_srp_ecc_error_cntr_clear, + DRP_TRP_CNT_CLEAR); + if (ret) + edac_printk(KERN_ERR, EDAC_LLCC, + "LCP/SRP counter clear failed: %d\n", ret); + } + + return irq_rc; +} + static int qcom_llcc_edac_probe(struct platform_device *pdev) { struct llcc_drv_data *llcc_driv_data = pdev->dev.platform_data; @@ -372,6 +490,8 @@ static int qcom_llcc_edac_probe(struct platform_device *pdev) edac_op_state = EDAC_OPSTATE_INT; goto irq_done; } + dev_warn(dev, "failed to request LLCC ECC irq %d: %d, falling back to polling\n", + ecc_irq, rc); } /* Fall back to polling mode otherwise */ @@ -386,6 +506,33 @@ static int qcom_llcc_edac_probe(struct platform_device *pdev) return rc; } + /* + * Set up LCP/SRP DDR DRAM ECC after the EDAC device is published. + * Skip hardware routing setup if firmware already configured IRQ + * propagation (irq_configured); only request the IRQ handler. + * Guard on a non-zero lcp_srp_interrupt_enable offset to confirm + * this LLCC variant actually has an LCP/SRP block. + */ + if (llcc_driv_data->lcp_irq > 0 && + llcc_driv_data->edac_reg_offset->lcp_srp_interrupt_enable) { + if (!llcc_driv_data->ecc_irq_configured) { + rc = qcom_llcc_lcp_setup(llcc_driv_data, + llcc_driv_data->bcast_regmap); + if (rc) { + dev_warn(dev, "LCP/SRP interrupt setup failed: %d\n", rc); + goto lcp_done; + } + } + rc = devm_request_irq(dev, llcc_driv_data->lcp_irq, + llcc_lcp_ecc_irq_handler, + 0, "llcc_lcp_ecc", edev_ctl); + if (rc) + dev_warn(dev, + "failed to request LCP ECC irq %d: %d, DDR DRAM ECC reporting disabled\n", + llcc_driv_data->lcp_irq, rc); + } +lcp_done: + rc = 0; platform_set_drvdata(pdev, edev_ctl); return rc; From 2341f5bb30146287436569863ba9968288892876 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Mon, 6 Jul 2026 22:26:34 +0530 Subject: [PATCH 0457/1133] FROMLIST: dt-bindings: iommu: arm,smmu: Document interconnects property Some SoC implementations require a bandwidth vote on an interconnect path before the SMMU register space is accessible. Add the optional 'interconnects' property to the binding to allow platform DT nodes to describe this path. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bibek Kumar Patro Link: https://lore.kernel.org/r/20260706-smmu_interconnect_addition-v3-1-afdca0125a65@oss.qualcomm.com --- .../devicetree/bindings/iommu/arm,smmu.yaml | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml index 6748351c78122..b5488b9d62bca 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml @@ -252,6 +252,13 @@ properties: minItems: 1 maxItems: 3 + interconnects: + maxItems: 1 + description: + Interconnect path to the SMMU register space. Required on SoCs + where the SMMU registers are only accessible after a bandwidth + vote has been placed on the interconnect fabric. + nvidia,memory-controller: description: | A phandle to the memory controller on NVIDIA Tegra186 and later SoCs. @@ -656,6 +663,26 @@ allOf: clock-names: false clocks: false + - if: + properties: + compatible: + items: + - enum: + - qcom,qcs615-smmu-500 + - qcom,qcs8300-smmu-500 + - qcom,sa8775p-smmu-500 + - qcom,sc7280-smmu-500 + - const: qcom,adreno-smmu + - const: qcom,smmu-500 + - const: arm,mmu-500 + then: + properties: + interconnects: + maxItems: 1 + else: + properties: + interconnects: false + - if: properties: compatible: From f0103ed38aacb1cd8125d0888f740d40e9ce1661 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Mon, 6 Jul 2026 22:26:35 +0530 Subject: [PATCH 0458/1133] FROMLIST: iommu/arm-smmu: Add interconnect bandwidth voting support On some SoCs the SMMU registers require an active interconnect bandwidth vote to be accessible. While other clients typically satisfy this requirement implicitly, certain corner cases (e.g. during sleep/wakeup transitions) can leave the SMMU without a vote, causing intermittent register access failures. Add support for an optional interconnect path to the arm-smmu driver and vote for bandwidth while the SMMU is active. The path is acquired from DT if present and ignored otherwise. The bandwidth vote is enabled before accessing SMMU registers during probe and runtime resume, and released during runtime suspend and on error paths. Generally, from an architectural perspective, GEM_NOC and DDR are expected to have an active vote whenever the adreno_smmu block is powered on. In most common use cases, this requirement is implicitly satisfied because other GPU-related clients (for example, the GMU device) already hold a GEM_NOC vote when adreno_smmu is enabled. However, there are certain corner cases, such as during sleep/wakeup transitions, where the GEM_NOC vote can be removed before adreno_smmu is powered down. If adreno_smmu is then accessed while the interconnect vote is missing, it can lead to the observed failures. Because of the precise ordering involved, this scenario is difficult to reproduce consistently. (also GDSC is involved in adreno usecases can have an independent vote) Signed-off-by: Bibek Kumar Patro Link: https://lore.kernel.org/r/20260706-smmu_interconnect_addition-v3-2-afdca0125a65@oss.qualcomm.com --- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 55 +++++++++++++++++++++- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.h | 3 ++ drivers/iommu/arm/arm-smmu/arm-smmu.c | 27 ++++++++++- drivers/iommu/arm/arm-smmu/arm-smmu.h | 2 + 4 files changed, 84 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index 795e8ec7e8faf..121fd85e296fd 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -608,6 +609,45 @@ static int qcom_sdm845_smmu500_reset(struct arm_smmu_device *smmu) return ret; } +static int qcom_adreno_smmu_icc_init(struct arm_smmu_device *smmu) +{ + struct qcom_smmu *qsmmu = container_of(smmu, struct qcom_smmu, smmu); + int err; + + qsmmu->icc_path = devm_of_icc_get(smmu->dev, NULL); + if (!IS_ERR(qsmmu->icc_path)) + return 0; + + err = PTR_ERR(qsmmu->icc_path); + + if (err == -ENODEV) { + qsmmu->icc_path = NULL; + return 0; + } + return dev_err_probe(smmu->dev, err, + "failed to get interconnect path\n"); +} + +static int qcom_adreno_smmu_runtime_resume(struct arm_smmu_device *smmu) +{ + struct qcom_smmu *qsmmu = container_of(smmu, struct qcom_smmu, smmu); + int ret; + + ret = icc_set_bw(qsmmu->icc_path, 0, 1); + WARN_ON_ONCE(ret); + return ret; +} + +static int qcom_adreno_smmu_runtime_suspend(struct arm_smmu_device *smmu) +{ + struct qcom_smmu *qsmmu = container_of(smmu, struct qcom_smmu, smmu); + int ret; + + ret = icc_set_bw(qsmmu->icc_path, 0, 0); + WARN_ON_ONCE(ret); + return ret; +} + static const struct arm_smmu_impl qcom_smmu_v2_impl = { .init_context = qcom_smmu_init_context, .cfg_probe = qcom_smmu_cfg_probe, @@ -649,6 +689,8 @@ static const struct arm_smmu_impl qcom_adreno_smmu_v2_impl = { .alloc_context_bank = qcom_adreno_smmu_alloc_context_bank, .write_sctlr = qcom_adreno_smmu_write_sctlr, .tlb_sync = qcom_smmu_tlb_sync, + .runtime_resume = qcom_adreno_smmu_runtime_resume, + .runtime_suspend = qcom_adreno_smmu_runtime_suspend, .context_fault_needs_threaded_irq = true, }; @@ -659,6 +701,8 @@ static const struct arm_smmu_impl qcom_adreno_smmu_500_impl = { .alloc_context_bank = qcom_adreno_smmu_alloc_context_bank, .write_sctlr = qcom_adreno_smmu_write_sctlr, .tlb_sync = qcom_smmu_tlb_sync, + .runtime_resume = qcom_adreno_smmu_runtime_resume, + .runtime_suspend = qcom_adreno_smmu_runtime_suspend, .context_fault_needs_threaded_irq = true, }; @@ -668,11 +712,14 @@ static struct arm_smmu_device *qcom_smmu_create(struct arm_smmu_device *smmu, const struct device_node *np = smmu->dev->of_node; const struct arm_smmu_impl *impl; struct qcom_smmu *qsmmu; + bool is_adreno_smmu; + int ret; if (!data) return ERR_PTR(-EINVAL); - if (np && of_device_is_compatible(np, "qcom,adreno-smmu")) + is_adreno_smmu = np && of_device_is_compatible(np, "qcom,adreno-smmu"); + if (is_adreno_smmu) impl = data->adreno_impl; else impl = data->impl; @@ -692,6 +739,12 @@ static struct arm_smmu_device *qcom_smmu_create(struct arm_smmu_device *smmu, qsmmu->smmu.impl = impl; qsmmu->data = data; + if (is_adreno_smmu) { + ret = qcom_adreno_smmu_icc_init(&qsmmu->smmu); + if (ret) + return ERR_PTR(ret); + } + return &qsmmu->smmu; } diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.h b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.h index 8addd453f5f1c..6835b40339cea 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.h +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.h @@ -6,12 +6,15 @@ #ifndef _ARM_SMMU_QCOM_H #define _ARM_SMMU_QCOM_H +#include + struct qcom_smmu { struct arm_smmu_device smmu; const struct qcom_smmu_match_data *data; bool bypass_quirk; u8 bypass_cbndx; u32 stall_enabled; + struct icc_path *icc_path; }; enum qcom_smmu_impl_reg_offset { diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index 889a0966d36cd..fcbfdd1432e50 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -2186,6 +2186,14 @@ static int arm_smmu_device_probe(struct platform_device *pdev) if (err) return err; + if (smmu->impl && smmu->impl->runtime_resume) { + err = smmu->impl->runtime_resume(smmu); + if (err) { + clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks); + return err; + } + } + err = arm_smmu_device_cfg_probe(smmu); if (err) return err; @@ -2268,8 +2276,11 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev) if (pm_runtime_enabled(smmu->dev)) pm_runtime_force_suspend(smmu->dev); - else + else { clk_bulk_disable(smmu->num_clks, smmu->clks); + if (smmu->impl && smmu->impl->runtime_suspend) + smmu->impl->runtime_suspend(smmu); + } clk_bulk_unprepare(smmu->num_clks, smmu->clks); } @@ -2289,9 +2300,18 @@ static int __maybe_unused arm_smmu_runtime_resume(struct device *dev) struct arm_smmu_device *smmu = dev_get_drvdata(dev); int ret; + if (smmu->impl && smmu->impl->runtime_resume) { + ret = smmu->impl->runtime_resume(smmu); + if (ret) + return ret; + } + ret = clk_bulk_enable(smmu->num_clks, smmu->clks); - if (ret) + if (ret) { + if (smmu->impl && smmu->impl->runtime_suspend) + smmu->impl->runtime_suspend(smmu); return ret; + } arm_smmu_device_reset(smmu); @@ -2304,6 +2324,9 @@ static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev) clk_bulk_disable(smmu->num_clks, smmu->clks); + if (smmu->impl && smmu->impl->runtime_suspend) + return smmu->impl->runtime_suspend(smmu); + return 0; } diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h index 26d2e33cd328b..ed08f86cf99d6 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h @@ -455,6 +455,8 @@ struct arm_smmu_impl { void (*write_s2cr)(struct arm_smmu_device *smmu, int idx); void (*write_sctlr)(struct arm_smmu_device *smmu, int idx, u32 reg); void (*probe_finalize)(struct arm_smmu_device *smmu, struct device *dev); + int (*runtime_resume)(struct arm_smmu_device *smmu); + int (*runtime_suspend)(struct arm_smmu_device *smmu); }; #define INVALID_SMENDX -1 From 9e4b5fbe563bac5dcf8007ad8a798d1f6e7baf63 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Mon, 6 Jul 2026 22:26:36 +0530 Subject: [PATCH 0459/1133] FROMLIST: arm64: dts: qcom: kodiak: Add GEM_NOC interconnect for adreno SMMU On Kodiak platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Signed-off-by: Bibek Kumar Patro Link: https://lore.kernel.org/r/20260706-smmu_interconnect_addition-v3-3-afdca0125a65@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 8c7523602d271..bf3a3b0c24350 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -3404,6 +3404,8 @@ power-domains = <&gpucc GPU_CC_CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; gfx_0_tbu: tbu@3dd9000 { From 54ec97300f6e8e041491991e8caf952d2a1dcbef Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Mon, 21 Sep 2026 16:44:07 +0530 Subject: [PATCH 0460/1133] FROMLIST: iommu/io-pgtable-arm: Add support for contiguous hint bit Add support for the contiguous hint (CONT) bit in ARM LPAE page tables. When a set of consecutive PTEs map a naturally aligned contiguous block of memory, set CONT on every descriptor in that group so the hardware can combine translations and improve TLB reach. Advertise the supported CONT group sizes in pgsize_bitmap. Callers select those sizes through the normal page-size selection path; io-pgtable-arm then installs the corresponding tagged descriptors directly. A partial unmap of a tagged CONT group is rejected before modifying any descriptor, so a rejected request cannot leave the group partly unmapped. The IO_PGTABLE_QUIRK_ARM_NO_CONT_HINT quirk allows SMMU drivers to disable CONT support for hardware with implementation-specific errata. Suggested-by: Robin Murphy Signed-off-by: Vijayanand Jitta Link: https://lore.kernel.org/r/20260921-iommu_contig_hint-v5-1-e7fbd1c3774d@oss.qualcomm.com Signed-off-by: Prakash Gupta --- drivers/iommu/io-pgtable-arm.c | 125 +++++++++++++++++++++++++++++---- include/linux/io-pgtable.h | 3 + 2 files changed, 115 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 476c0e25631af..01d98959c514f 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -86,6 +86,21 @@ /* Software bit for solving coherency races */ #define ARM_LPAE_PTE_SW_SYNC (((arm_lpae_iopte)1) << 55) +/* PTE Contiguous Bit */ +#define ARM_LPAE_PTE_CONT (((arm_lpae_iopte)1) << 52) + +/* + * Contiguous hint group sizes per granule: + * + *------------------------------------------------------------------ + *| Page Size | CONT PTE | Block | CONT Block | L1 Block | CONT L1 | + *------------------------------------------------------------------ + *| 4K | 64K | 2M | 32M | 1G | 16G | + *| 16K | 2M | 32M | 1G | | | + *| 64K | 2M | 512M | 16G | | | + *------------------------------------------------------------------ + */ + /* Stage-1 PTE */ #define ARM_LPAE_PTE_AP_UNPRIV (((arm_lpae_iopte)1) << 6) #define ARM_LPAE_PTE_AP_RDONLY_BIT 7 @@ -453,6 +468,24 @@ static arm_lpae_iopte arm_lpae_install_table(arm_lpae_iopte *table, return old; } +static int arm_lpae_num_cont(size_t size) +{ + switch (size) { + case SZ_4K: + case SZ_2M: + case SZ_1G: + return 16; + case SZ_64K: + case SZ_32M: + case SZ_512M: + return 32; + case SZ_16K: + return 128; + default: + return 1; + } +} + static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova, phys_addr_t paddr, size_t size, size_t pgcount, arm_lpae_iopte prot, int lvl, arm_lpae_iopte *ptep, @@ -462,20 +495,41 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova, size_t block_size = ARM_LPAE_BLOCK_SIZE(lvl, data); size_t tblsz = ARM_LPAE_GRANULE(data); struct io_pgtable_cfg *cfg = &data->iop.cfg; - int ret = 0, num_entries, max_entries, map_idx_start; + int num_cont = arm_lpae_num_cont(block_size); + size_t cont_size = 0, entries_per_map; + int num_entries, max_entries, map_idx_start; + bool cont = false; + + if (num_cont > 1 && block_size <= SIZE_MAX / num_cont) + cont_size = num_cont * block_size; /* Find our entry at the current level */ map_idx_start = ARM_LPAE_LVL_IDX(iova, lvl, data); ptep += map_idx_start; /* If we can install a leaf entry at this level, then do so */ - if (size == block_size) { + if (size == block_size || + (!(cfg->quirks & IO_PGTABLE_QUIRK_ARM_NO_CONT_HINT) && + size == cont_size)) { + int ret; + + cont = size == cont_size; + if (cont && (!IS_ALIGNED(iova, size) || !IS_ALIGNED(paddr, size))) + return -EINVAL; + + entries_per_map = size / block_size; max_entries = arm_lpae_max_entries(map_idx_start, data); - num_entries = min_t(int, pgcount, max_entries); - ret = arm_lpae_init_pte(data, iova, paddr, prot, lvl, num_entries, ptep); + num_entries = min_t(size_t, pgcount, + max_entries / entries_per_map) * entries_per_map; + if (!num_entries) + return -EINVAL; + if (cont) + prot |= ARM_LPAE_PTE_CONT; + + ret = arm_lpae_init_pte(data, iova, paddr, prot, lvl, + num_entries, ptep); if (!ret) - *mapped += num_entries * size; - + *mapped += num_entries * block_size; return ret; } @@ -660,12 +714,18 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, { arm_lpae_iopte pte; struct io_pgtable *iop = &data->iop; + size_t block_size = ARM_LPAE_BLOCK_SIZE(lvl, data); + int num_cont = arm_lpae_num_cont(block_size); + size_t cont_size = 0, entries_per_map; int i = 0, num_entries, max_entries, unmap_idx_start; /* Something went horribly wrong and we ran out of page table */ if (WARN_ON(lvl == ARM_LPAE_MAX_LEVELS)) return 0; + if (num_cont > 1 && block_size <= SIZE_MAX / num_cont) + cont_size = num_cont * block_size; + unmap_idx_start = ARM_LPAE_LVL_IDX(iova, lvl, data); ptep += unmap_idx_start; pte = READ_ONCE(*ptep); @@ -675,9 +735,27 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, } /* If the size matches this level, we're in the right place */ - if (size == ARM_LPAE_BLOCK_SIZE(lvl, data)) { + if (size == block_size || + (!(data->iop.cfg.quirks & IO_PGTABLE_QUIRK_ARM_NO_CONT_HINT) && + size == cont_size)) { + entries_per_map = size / block_size; max_entries = arm_lpae_max_entries(unmap_idx_start, data); - num_entries = min_t(int, pgcount, max_entries); + num_entries = min_t(size_t, pgcount, + max_entries / entries_per_map) * entries_per_map; + if (!num_entries) + return 0; + + /* + * A CONT group must be invalidated as a unit. Reject a request that + * starts or ends inside a tagged group before changing any PTEs. + */ + if ((READ_ONCE(*ptep) & ARM_LPAE_PTE_CONT && + !IS_ALIGNED(iova, cont_size)) || + (READ_ONCE(ptep[num_entries - 1]) & ARM_LPAE_PTE_CONT && + !IS_ALIGNED(iova + num_entries * block_size, cont_size))) { + WARN_ONCE(true, "Unmap of a partial CONT IOPTE group is not allowed"); + return 0; + } /* Find and handle non-leaf entries */ for (i = 0; i < num_entries; i++) { @@ -691,7 +769,8 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, __arm_lpae_clear_pte(&ptep[i], &iop->cfg, 1); /* Also flush any partial walks */ - io_pgtable_tlb_flush_walk(iop, iova + i * size, size, + io_pgtable_tlb_flush_walk(iop, + iova + i * block_size, block_size, ARM_LPAE_GRANULE(data)); __arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data)); } @@ -702,9 +781,10 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data, if (gather && !iommu_iotlb_gather_queued(gather)) for (int j = 0; j < i; j++) - io_pgtable_tlb_add_page(iop, gather, iova + j * size, size); + io_pgtable_tlb_add_page(iop, gather, + iova + j * block_size, block_size); - return i * size; + return i * block_size; } else if (iopte_leaf(pte, lvl, iop->fmt)) { WARN_ONCE(true, "Unmap of a partial large IOPTE is not allowed"); return 0; @@ -943,8 +1023,23 @@ static void arm_lpae_restrict_pgsizes(struct io_pgtable_cfg *cfg) } cfg->pgsize_bitmap &= page_sizes; + if (!(cfg->quirks & IO_PGTABLE_QUIRK_ARM_NO_CONT_HINT)) { + unsigned long sizes = cfg->pgsize_bitmap; + + while (sizes) { + unsigned long size = BIT(__ffs(sizes)); + int num_cont = arm_lpae_num_cont(size); + + if (size <= ULONG_MAX / num_cont) + cfg->pgsize_bitmap |= num_cont * size; + sizes &= ~size; + } + } + cfg->ias = min(cfg->ias, max_addr_bits); cfg->oas = min(cfg->oas, max_addr_bits); + cfg->pgsize_bitmap &= GENMASK_ULL(cfg->ias, 0); + cfg->pgsize_bitmap &= GENMASK_ULL(cfg->oas, 0); } static struct arm_lpae_io_pgtable * @@ -1001,7 +1096,8 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie) IO_PGTABLE_QUIRK_ARM_TTBR1 | IO_PGTABLE_QUIRK_ARM_OUTER_WBWA | IO_PGTABLE_QUIRK_ARM_HD | - IO_PGTABLE_QUIRK_NO_WARN)) + IO_PGTABLE_QUIRK_NO_WARN | + IO_PGTABLE_QUIRK_ARM_NO_CONT_HINT)) return NULL; data = arm_lpae_alloc_pgtable(cfg); @@ -1103,7 +1199,8 @@ arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie) typeof(&cfg->arm_lpae_s2_cfg.vtcr) vtcr = &cfg->arm_lpae_s2_cfg.vtcr; if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_S2FWB | - IO_PGTABLE_QUIRK_NO_WARN)) + IO_PGTABLE_QUIRK_NO_WARN | + IO_PGTABLE_QUIRK_ARM_NO_CONT_HINT)) return NULL; data = arm_lpae_alloc_pgtable(cfg); @@ -1224,6 +1321,8 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie) return NULL; cfg->pgsize_bitmap &= (SZ_4K | SZ_2M | SZ_1G); + /* Mali LPAE has no CONT bit - never advertise CONT page sizes */ + cfg->quirks |= IO_PGTABLE_QUIRK_ARM_NO_CONT_HINT; data = arm_lpae_alloc_pgtable(cfg); if (!data) diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h index e19872e37e067..7b2097aaffb09 100644 --- a/include/linux/io-pgtable.h +++ b/include/linux/io-pgtable.h @@ -86,6 +86,8 @@ struct io_pgtable_cfg { * * IO_PGTABLE_QUIRK_ARM_HD: Enables dirty tracking in stage 1 pagetable. * IO_PGTABLE_QUIRK_ARM_S2FWB: Use the FWB format for the MemAttrs bits + * IO_PGTABLE_QUIRK_ARM_NO_CONT_HINT: Disable use of the contiguous + * hint for hardware affected by implementation-specific errata. * * IO_PGTABLE_QUIRK_NO_WARN: Do not WARN_ON() on conflicting * mappings, but silently return -EEXISTS. Normally an attempt @@ -103,6 +105,7 @@ struct io_pgtable_cfg { #define IO_PGTABLE_QUIRK_ARM_HD BIT(7) #define IO_PGTABLE_QUIRK_ARM_S2FWB BIT(8) #define IO_PGTABLE_QUIRK_NO_WARN BIT(9) + #define IO_PGTABLE_QUIRK_ARM_NO_CONT_HINT BIT(10) unsigned long quirks; unsigned long pgsize_bitmap; unsigned int ias; From d4170e059d1093b4c67c5ca77b1871385e31ae7d Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Sat, 12 Sep 2026 03:55:38 +0530 Subject: [PATCH 0461/1133] FROMLIST: iommu: arm-smmu-qcom: Skip fault-info reads when suspended qcom_adreno_smmu_get_fault_info() accesses SMMU registers without holding a runtime PM reference. A fault is raised while the SMMU is active, but the GPU may drop its power vote before the threaded fault handler reaches the callback, allowing the SMMU to runtime suspend. Accessing the SMMU registers after suspend has started is unsafe and may cause subsequent register accesses during runtime resume to fail with a NoC error and an asynchronous SError. Use pm_runtime_get_if_active() to keep the SMMU active while collecting the fault information, and skip the register reads if suspend has already started. Signed-off-by: Bibek Kumar Patro Link: https://lore.kernel.org/r/20260912-priv_call_runtime_handlers-v1-1-fc0c3a17523f@oss.qualcomm.com --- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index 121fd85e296fd..a0c24769a9168 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -130,6 +130,18 @@ static void qcom_adreno_smmu_get_fault_info(const void *cookie, struct arm_smmu_cfg *cfg = &smmu_domain->cfg; struct arm_smmu_device *smmu = smmu_domain->smmu; + /* + * A fault can only fire while the SMMU is active (GPU is issuing + * transactions). Use get_if_active so that if by a rare race the + * device has already suspended, we skip the register reads rather + * than triggering a cold resume which would call device_reset and + * destroy the fault state we are trying to capture. + */ + if (pm_runtime_get_if_active(smmu->dev) <= 0) { + dev_warn(smmu->dev, "get_fault_info: device not active, skipping\n"); + return; + } + info->fsr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSR); info->fsynr0 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSYNR0); info->fsynr1 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSYNR1); @@ -137,6 +149,8 @@ static void qcom_adreno_smmu_get_fault_info(const void *cookie, info->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx)); info->ttbr0 = arm_smmu_cb_readq(smmu, cfg->cbndx, ARM_SMMU_CB_TTBR0); info->contextidr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_CONTEXTIDR); + + pm_runtime_put_autosuspend(smmu->dev); } static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled) From dc762f5fc19e1013f1fd708d0e3afc6d0df8d6a9 Mon Sep 17 00:00:00 2001 From: Ketan Kishore Date: Fri, 17 Jul 2026 14:55:47 +0530 Subject: [PATCH 0462/1133] FROMLIST: amba: bus: Fix race condition during DMA configure at IOMMU probe time amba_dma_configure() can be invoked from the IOMMU probe path while a device's driver is still being bound asynchronously by really_probe() on another thread. Call trace: amba_dma_configure __iommu_probe_device probe_iommu_group bus_for_each_dev iommu_device_register arm_smmu_device_probe platform_probe really_probe __driver_probe_device driver_probe_device __device_attach_driver bus_for_each_drv __device_attach device_initial_probe bus_probe_device deferred_probe_work_func process_scheduled_works worker_thread kthread ret_from_fork dev->driver is read and converted to a struct amba_driver before it is known whether dev->driver is actually set. If a driver bind completes concurrently with the IOMMU probe path, the driver_managed_dma could end up being dereferenced through an invalid pointer derived from NULL. Update amba_dma_configure() to read dev->driver once and test if it's NULL before using it. This ensures that we don't dereference an invalid amba driver pointer if the device driver is asynchronously bound while configuring the DMA. This is the same TOCTOU race already fixed for the platform bus in commit 95deee37a123 ("platform: Fix race condition during DMA configure at IOMMU probe time") and for fsl-mc in commit 152f33ee30ee ("bus: fsl_mc: Fix driver_managed_dma check"). amba_dma_configure() has the identical pattern, so apply the same fix here. Fixes: bcb81ac6ae3c ("iommu: Get DT/ACPI parsing into the proper probe path") Cc: stable@vger.kernel.org # 6.1+ Signed-off-by: Ketan Kishore Reviewed-by: Ketan Kishore Reviewed-by: Will McVicker Link: https://lore.kernel.org/r/20260717-iommu_races-v2-1-d0b7789275af@oss.qualcomm.com --- drivers/amba/bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index d721d64a98580..0cdda7e07af71 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -324,7 +324,7 @@ static void amba_shutdown(struct device *dev) static int amba_dma_configure(struct device *dev) { - struct amba_driver *drv = to_amba_driver(dev->driver); + const struct device_driver *drv = READ_ONCE(dev->driver); enum dev_dma_attr attr; int ret = 0; @@ -336,7 +336,7 @@ static int amba_dma_configure(struct device *dev) } /* @drv may not be valid when we're called from the IOMMU layer */ - if (!ret && dev->driver && !drv->driver_managed_dma) { + if (!ret && drv && !to_amba_driver(drv)->driver_managed_dma) { ret = iommu_device_use_default_domain(dev); if (ret) arch_teardown_dma_ops(dev); From 477cd5c977740373d337a9f05353b35947f3a613 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Thu, 15 Oct 2026 16:22:26 +0530 Subject: [PATCH 0463/1133] FROMLIST: arm64: dts: qcom: glymur: Add CAMSS and CSIPHY nodes for Glymur Glymur shares the same IP as X1E80100, with three CSIPHYs that use the new standalone PHY API. Compared to X1E80100, csiphy2 is absent on Glymur. Link: https://lore.kernel.org/all/20261015-glymur_camss_dts-v2-1-e7b1f403146f@oss.qualcomm.com/ Tested-by: Konrad Dybcio # Zenbook A16 Signed-off-by: Nihal Kumar Gupta Acked-by: Konrad Dybcio Tested-by: Christian Cortner # Asus Zenbook A16 (UX3607OA) --- arch/arm64/boot/dts/qcom/glymur.dtsi | 320 +++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index c3ef7fa9a5516..c2686c48018f5 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -1092,6 +1092,50 @@ }; }; + csiphy_mxa_opp_table: opp-table-mxa { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs_d1>; + }; + }; + + csiphy_mxc_opp_table: opp-table-mxc { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + soc: soc@0 { compatible = "simple-bus"; #address-cells = <2>; @@ -5968,6 +6012,282 @@ status = "disabled"; }; + camss: isp@acb6000 { + compatible = "qcom,glymur-camss"; + + reg = <0x0 0x0acb6000 0x0 0x1000>, + <0x0 0x0acb7000 0x0 0x2000>, + <0x0 0x0acb9000 0x0 0x2000>, + <0x0 0x0acbb000 0x0 0x2000>, + <0x0 0x0acc6000 0x0 0x1000>, + <0x0 0x0acca000 0x0 0x1000>, + <0x0 0x0acf6000 0x0 0x1000>, + <0x0 0x0acf7000 0x0 0x1000>, + <0x0 0x0acf8000 0x0 0x1000>, + <0x0 0x0ac62000 0x0 0xf000>, + <0x0 0x0ac71000 0x0 0xf000>, + <0x0 0x0acc7000 0x0 0x2000>, + <0x0 0x0accb000 0x0 0x2000>; + reg-names = "csid_wrapper", + "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&hsc_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x20>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_IFE_1_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "top"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + camss_csiphy0_inep: endpoint { + remote-endpoint = <&csiphy0_out_ep>; + }; + }; + + port@1 { + reg = <1>; + + camss_csiphy1_inep: endpoint { + remote-endpoint = <&csiphy1_out_ep>; + }; + }; + + port@3 { + reg = <3>; + + camss_csiphy4_inep: endpoint { + remote-endpoint = <&csiphy4_out_ep>; + }; + }; + }; + }; + + csiphy0: phy@ace4000 { + compatible = "qcom,glymur-csi2-phy", "qcom,x1e80100-csi2-phy"; + reg = <0x0 0x0ace4000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy0_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy0_out_ep: endpoint { + remote-endpoint = <&camss_csiphy0_inep>; + }; + }; + }; + }; + + csiphy1: phy@ace6000 { + compatible = "qcom,glymur-csi2-phy", "qcom,x1e80100-csi2-phy"; + reg = <0x0 0x0ace6000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy1_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy1_out_ep: endpoint { + remote-endpoint = <&camss_csiphy1_inep>; + }; + }; + }; + }; + + csiphy4: phy@acec000 { + compatible = "qcom,glymur-csi2-phy", "qcom,x1e80100-csi2-phy"; + reg = <0x0 0x0acec000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MX>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxa_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy4_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy4_out_ep: endpoint { + remote-endpoint = <&camss_csiphy4_inep>; + }; + }; + }; + }; + camcc: clock-controller@ade0000 { compatible = "qcom,glymur-camcc"; reg = <0x0 0x0ade0000 0x0 0x20000>; From 7fe51c8b194082acdcffbd7a6105329347da7601 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Thu, 15 Oct 2026 16:22:27 +0530 Subject: [PATCH 0464/1133] FROMLIST: arm64: dts: qcom: glymur: Add CCI definitions for Glymur Qualcomm Glymur SoC has two Camera Control Interface (CCI) controllers. Each controller contains two I2C hosts. Link: https://lore.kernel.org/all/20261015-glymur_camss_dts-v2-2-e7b1f403146f@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Signed-off-by: Nihal Kumar Gupta Tested-by: Christian Cortner # Asus Zenbook A16 (UX3607OA) --- arch/arm64/boot/dts/qcom/glymur.dtsi | 202 +++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index c2686c48018f5..ad5c11dc17fe6 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -6012,6 +6012,80 @@ status = "disabled"; }; + cci0: cci@ac15000 { + compatible = "qcom,glymur-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0ac15000 0x0 0x1000>; + + interrupts = ; + + clocks = <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "ahb", + "cci"; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + pinctrl-0 = <&cci0_0_default>, <&cci0_1_default>; + pinctrl-1 = <&cci0_0_sleep>, <&cci0_1_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <400000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <400000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@ac16000 { + compatible = "qcom,glymur-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0ac16000 0x0 0x1000>; + + interrupts = ; + + clocks = <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "ahb", + "cci"; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + pinctrl-0 = <&cci1_0_default>, <&cci1_1_default>; + pinctrl-1 = <&cci1_0_sleep>, <&cci1_1_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <400000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <400000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + camss: isp@acb6000 { compatible = "qcom,glymur-camss"; @@ -7808,6 +7882,134 @@ }; }; + cci0_0_default: cci0-0-default-state { + sda-pins { + pins = "gpio101"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio102"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci0_0_sleep: cci0-0-sleep-state { + sda-pins { + pins = "gpio101"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio102"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci0_1_default: cci0-1-default-state { + sda-pins { + pins = "gpio103"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio104"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci0_1_sleep: cci0-1-sleep-state { + sda-pins { + pins = "gpio103"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio104"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_0_default: cci1-0-default-state { + sda-pins { + pins = "gpio105"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio106"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci1_0_sleep: cci1-0-sleep-state { + sda-pins { + pins = "gpio105"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio106"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_1_default: cci1-1-default-state { + sda-pins { + pins = "gpio235"; + function = "asc_cci"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + + scl-pins { + pins = "gpio236"; + function = "asc_cci"; + drive-strength = <2>; + bias-pull-up = <2200>; + }; + }; + + cci1_1_sleep: cci1-1-sleep-state { + sda-pins { + pins = "gpio235"; + function = "asc_cci"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio236"; + function = "asc_cci"; + drive-strength = <2>; + bias-pull-down; + }; + }; + sdc2_default_state: sdc2-default-state { clk-pins { pins = "sdc2_clk"; From c0c8738a40e3ebdcf15c00f6f0064ca2adcc555e Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Thu, 15 Oct 2026 16:22:28 +0530 Subject: [PATCH 0465/1133] FROMLIST: arm64: dts: qcom: glymur: Add camera MCLK pinctrl Add pinctrl definitions for camera master clock pins on Glymur. Link: https://lore.kernel.org/all/20261015-glymur_camss_dts-v2-3-e7b1f403146f@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Signed-off-by: Nihal Kumar Gupta Tested-by: Christian Cortner # Asus Zenbook A16 (UX3607OA) --- arch/arm64/boot/dts/qcom/glymur.dtsi | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index ad5c11dc17fe6..b86047cc23187 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -7882,6 +7882,41 @@ }; }; + cam_mclk0_default: cam-mclk0-default-state { + pins = "gpio96"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam_mclk1_default: cam-mclk1-default-state { + pins = "gpio97"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam_mclk2_default: cam-mclk2-default-state { + pins = "gpio98"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam_mclk3_default: cam-mclk3-default-state { + pins = "gpio99"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam_mclk4_default: cam-mclk4-default-state { + pins = "gpio100"; + function = "cam_asc_mclk4"; + drive-strength = <2>; + bias-disable; + }; + cci0_0_default: cci0-0-default-state { sda-pins { pins = "gpio101"; From 6639fabe95a9521c268818d879ba67cfa0bce7eb Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Thu, 15 Oct 2026 16:22:29 +0530 Subject: [PATCH 0466/1133] FROMLIST: arm64: dts: qcom: glymur-crd: Add PM8010 camera PMIC Add the PM8010 PMIC node with seven LDO regulators and pinctrl configuration for reset pin. The LDOs are needed to power the camera sensors and associated hardware. Link: https://lore.kernel.org/all/20261015-glymur_camss_dts-v2-4-e7b1f403146f@oss.qualcomm.com/ Signed-off-by: Jishnu Prakash Signed-off-by: Nihal Kumar Gupta Tested-by: Christian Cortner # Asus Zenbook A16 (UX3607OA) --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 75 ++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index ab5981f402126..93674485260ba 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -800,6 +800,72 @@ }; }; }; + + pm8010: pmic@8 { + compatible = "qcom,pm8010-i2c"; + reg = <0x8>; + + reset-gpios = <&tlmm 106 GPIO_ACTIVE_LOW>; + + vdd-l1-l2-supply = <&vreg_l6p>; + vdd-l3-l4-supply = <&vreg_bob1_e0>; + vdd-l5-supply = <&vreg_bob1_e0>; + vdd-l6-supply = <&vreg_bob1_e0>; + vdd-l7-supply = <&vreg_bob1_e0>; + + pinctrl-names = "default"; + pinctrl-0 = <&pm8010_default>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pm8010 0 0 2>; + + #thermal-sensor-cells = <0>; + + regulators { + vreg_l1p: ldo1 { + regulator-name = "vreg_l1p"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + vreg_l2p: ldo2 { + regulator-name = "vreg_l2p"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + vreg_l3p: ldo3 { + regulator-name = "vreg_l3p"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + vreg_l4p: ldo4 { + regulator-name = "vreg_l4p"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vreg_l5p: ldo5 { + regulator-name = "vreg_l5p"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + vreg_l6p: ldo6 { + regulator-name = "vreg_l6p"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vreg_l7p: ldo7 { + regulator-name = "vreg_l7p"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + }; + }; }; &i2c8 { @@ -1476,6 +1542,15 @@ }; }; + pm8010_default: pm8010-default-state { + reset-n-pins { + pins = "gpio106"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + sdc2_card_det_n: sd-card-det-n-state { pins = "gpio221"; function = "gpio"; From 423d20b249a4a7fb1c7d96d1dbcbb4affec84680 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Thu, 15 Oct 2026 16:22:30 +0530 Subject: [PATCH 0467/1133] FROMLIST: arm64: dts: qcom: glymur-crd: Add ov08x40 RGB sensor on CSIPHY4 Define ov08x40 on cci1_i2c1. The RGB sensor is connected to CSIPHY4 in four-lane mode. Link: https://lore.kernel.org/all/20261015-glymur_camss_dts-v2-5-e7b1f403146f@oss.qualcomm.com/ Reviewed-by: Abel Vesa Signed-off-by: Nihal Kumar Gupta Reviewed-by: Konrad Dybcio Tested-by: Christian Cortner # Asus Zenbook A16 (UX3607OA) --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 64 ++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index 93674485260ba..9e1cab93bd304 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -11,6 +11,7 @@ #include "smb2370.dtsi" /* SPMI2: SID-9/10/11 */ #include +#include #include #include "qcom-adc5-gen4.h" @@ -660,6 +661,62 @@ }; }; +&camss { + status = "okay"; +}; + +&camss_csiphy4_inep { + data-lanes = <1 2 3 4>; +}; + +&cci1 { + pinctrl-0 = <&cci1_1_default>; + pinctrl-1 = <&cci1_1_sleep>; + + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov08x40"; + reg = <0x36>; + + reset-gpios = <&tlmm 239 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&cam_mclk4_default &cam_reset4_default>; + pinctrl-names = "default"; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + avdd-supply = <&vreg_l7p>; + dovdd-supply = <&vreg_l4p>; + dvdd-supply = <&vreg_l4p>; + + port { + ov08x40_out_ep: endpoint { + data-lanes = <1 2 3 4>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&csiphy4_in_ep>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l1f_e1_0p82>; + vdda-1p2-supply = <&vreg_l4f_e1_1p08>; + + status = "okay"; +}; + +&csiphy4_in_ep { + bus-type = ; + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&ov08x40_out_ep>; +}; + &i2c9 { clock-frequency = <400000>; @@ -1607,6 +1664,13 @@ drive-strength = <2>; bias-disable; }; + + cam_reset4_default: cam-reset4-default-state { + pins = "gpio239"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; }; &uart14 { From 5ee2cb0c612486599a6ebba0bb0fa9b75e935a01 Mon Sep 17 00:00:00 2001 From: Jie Zhang Date: Thu, 8 Oct 2026 13:43:57 +0530 Subject: [PATCH 0468/1133] FROMLIST: arm64: dts: qcom: mahua: Support GPU and GMU Mahua SoC has a new GPU called Adreno X2-85, a slightly smaller variant of the Adreno X2-90 found on glymur. Override the compatible strings to correctly support it's GPU and GMU. Signed-off-by: Jie Zhang Signed-off-by: Akhil P Oommen Signed-off-by: Kavisha Shah Link: https://lore.kernel.org/lkml/20260925-mahua-gpu-v1-5-0fa0bfd8d315@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/mahua.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/mahua.dtsi b/arch/arm64/boot/dts/qcom/mahua.dtsi index e3c8cc3e4bda2..3c365319e9cfc 100644 --- a/arch/arm64/boot/dts/qcom/mahua.dtsi +++ b/arch/arm64/boot/dts/qcom/mahua.dtsi @@ -143,6 +143,14 @@ <0>; /* USB4 PHY 2 Max */ }; +&gmu { + compatible = "qcom,adreno-gmu-x285.0", "qcom,adreno-gmu"; +}; + +&gpu { + compatible = "qcom,adreno-44060000", "qcom,adreno"; +}; + &hsc_noc { compatible = "qcom,mahua-hscnoc"; }; From 96e610327bd9de1f9ba021c3c70379605c0e86ea Mon Sep 17 00:00:00 2001 From: Anvesh Jain P Date: Mon, 28 Sep 2026 12:06:39 +0530 Subject: [PATCH 0469/1133] FROMLIST: arm64: dts: qcom: glymur: Add EC thermal zones Add support for back cover, keyboard, and SoC thermal zones through temperature sensors hosted on the EC for Glymur and Mahua CRDs. Link: https://lore.kernel.org/all/20260928-ec_thermistor_support-v1-3-d9c1bae4cd0d@oss.qualcomm.com/ Signed-off-by: Anvesh Jain P Signed-off-by: Sibi Sankar --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 45 +++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index 9e1cab93bd304..bb52582c9fc1d 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -722,10 +722,12 @@ status = "okay"; - embedded-controller@76 { + ec: embedded-controller@76 { compatible = "qcom,glymur-crd-ec", "qcom,hamoa-crd-ec"; reg = <0x76>; + #thermal-sensor-cells = <1>; + interrupts-extended = <&tlmm 66 IRQ_TYPE_EDGE_FALLING>; pinctrl-0 = <&ec_int_n_default>; @@ -1457,6 +1459,47 @@ }; }; +&thermal_zones { + ec-back-cover { + polling-delay = <10000>; + thermal-sensors = <&ec 2>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <5000>; + type = "hot"; + }; + }; + }; + + ec-keyboard { + polling-delay = <10000>; + thermal-sensors = <&ec 1>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <5000>; + type = "hot"; + }; + }; + }; + + ec-soc { + polling-delay = <10000>; + thermal-sensors = <&ec 0>; + + trips { + trip-point0 { + temperature = <90000>; + hysteresis = <5000>; + type = "hot"; + }; + }; + }; +}; + &remoteproc_soccp { firmware-name = "qcom/glymur/soccp.mbn", "qcom/glymur/soccp_dtb.mbn"; From 29bb3512121d1c5ff22e5319af808ef489f72728 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 21 Oct 2026 19:21:24 +0530 Subject: [PATCH 0470/1133] FROMLIST: arm64: dts: qcom: glymur-crd: Describe the PCIe M.2 Key B connector The Glymur CRD has a WWAN M.2 slot connected to PCIe6. Currently the vreg_wwan supply is described directly on the PCIe6 host bridge. As a result, the supply follows the PCIe controller power state and is turned off when the controller is powered down, regardless of the requirements of the device connected to the slot. Move control of the WWAN supply to the generic pci-pwrctrl-slot/pwrseq-pcie-m2 framework. This allows slot power to be coordinated with PCI device power-management requirements and keeps the supply enabled when required by the PCI device, such as for PME-based wake-up. Describe the slot as a PCIe M.2 Mechanical Key B connector and link it to the PCIe6 Root Port using a graph port/endpoint pair, as required by the pcie-m2-b-connector binding. Link: https://patch.msgid.link/20261021-pcie6_fix-v1-3-ad37134c35a3@oss.qualcomm.com Signed-off-by: Krishna Chaitanya Chundru --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 29 ++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index bb52582c9fc1d..422883a2d5276 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -259,6 +259,27 @@ pinctrl-names = "default"; }; + wwan-connector { + compatible = "pcie-m2-b-connector"; + vpcie3v3-supply = <&vreg_wwan>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + wwan_m2_pcie_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&pcie6_port0_ep>; + }; + }; + }; + }; + sound { compatible = "qcom,glymur-sndcard"; model = "GLYMUR-CRD"; @@ -1078,8 +1099,6 @@ }; &pcie6 { - vddpe-3v3-supply = <&vreg_wwan>; - pinctrl-0 = <&pcie6_default>; pinctrl-names = "default"; @@ -1098,6 +1117,12 @@ &pcie6_port0 { reset-gpios = <&tlmm 149 GPIO_ACTIVE_LOW>; wake-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>; + + port { + pcie6_port0_ep: endpoint { + remote-endpoint = <&wwan_m2_pcie_ep>; + }; + }; }; &pmcx0102_c_e0_temp_alarm { From 44629468f0a26170f2586ba16ba34d173bd8dd35 Mon Sep 17 00:00:00 2001 From: Gopikrishna Garmidi Date: Fri, 9 Oct 2026 20:26:36 +0530 Subject: [PATCH 0471/1133] FROMLIST: dt-bindings: arm: qcom: Add Mahua QCB Document the Mahua QCB (Qualcomm Compute Board) board id, an open form-factor Mahua board intended for compute bring-up and power/signal measurement. Link: https://lore.kernel.org/all/20261027114955.1266499-2-sivansh.gupta@oss.qualcomm.com/ Signed-off-by: Gopikrishna Garmidi Signed-off-by: Sivansh Gupta --- Documentation/devicetree/bindings/arm/qcom.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 121ca557ce1ef..933a2361b5d78 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -192,6 +192,7 @@ properties: - items: - enum: - qcom,mahua-crd + - qcom,mahua-qcb - const: qcom,mahua - items: From 9523f2a7b07f513caa460cef122b6c672d3b89c8 Mon Sep 17 00:00:00 2001 From: Sivansh Gupta Date: Mon, 26 Oct 2026 14:55:16 +0530 Subject: [PATCH 0472/1133] FROMLIST: arm64: dts: qcom: Commonize glymur-qcb.dts to glymur-qcb.dtsi Glymur QCB and Mahua QCB both share common nodes as they use the same underlying board. Move all common nodes to glymur-qcb.dtsi file to allow for reuse. Link: https://lore.kernel.org/all/20261027114955.1266499-4-sivansh.gupta@oss.qualcomm.com/ Signed-off-by: Sivansh Gupta --- arch/arm64/boot/dts/qcom/glymur-qcb.dts | 691 +---------------------- arch/arm64/boot/dts/qcom/glymur-qcb.dtsi | 671 ++++++++++++++++++++++ 2 files changed, 672 insertions(+), 690 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/glymur-qcb.dtsi diff --git a/arch/arm64/boot/dts/qcom/glymur-qcb.dts b/arch/arm64/boot/dts/qcom/glymur-qcb.dts index 08c6445fe6516..f0ed47adfc2fe 100644 --- a/arch/arm64/boot/dts/qcom/glymur-qcb.dts +++ b/arch/arm64/boot/dts/qcom/glymur-qcb.dts @@ -6,563 +6,11 @@ /dts-v1/; #include "glymur.dtsi" - -#include "pmcx0102.dtsi" /* SPMI0: SID-2/3 SPMI1: SID-2/3 */ -#include "pmh0101.dtsi" /* SPMI0: SID-1 */ -#include "pmh0110-glymur.dtsi" /* SPMI0: SID-5/7 SPMI1: SID-5 */ -#include "pmh0104-glymur.dtsi" /* SPMI0: SID-8/9 SPMI1: SID-11 */ -#include "pmk8850.dtsi" /* SPMI0: SID-0 */ -#include "smb2370.dtsi" /* SPMI2: SID-9/10/11 */ +#include "glymur-qcb.dtsi" / { model = "Qualcomm Technologies, Inc. Glymur QCB"; compatible = "qcom,glymur-qcb", "qcom,glymur"; - - aliases { - serial0 = &uart21; - serial1 = &uart14; - i2c0 = &i2c0; - i2c1 = &i2c4; - i2c2 = &i2c5; - i2c3 = &i2c9; - spi0 = &spi18; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - clocks { - xo_board: xo-board { - compatible = "fixed-clock"; - clock-frequency = <38400000>; - #clock-cells = <0>; - }; - - sleep_clk: sleep-clk { - compatible = "fixed-clock"; - clock-frequency = <32000>; - #clock-cells = <0>; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - - pinctrl-0 = <&key_vol_up_default>; - pinctrl-names = "default"; - - key-volume-up { - label = "Volume Up"; - linux,code = ; - gpios = <&pmh0101_gpios 6 GPIO_ACTIVE_LOW>; - debounce-interval = <15>; - linux,can-disable; - wakeup-source; - }; - }; - - vreg_nvme: regulator-nvme { - compatible = "regulator-fixed"; - - regulator-name = "VREG_NVME_3P3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - - gpio = <&pmh0101_gpios 14 GPIO_ACTIVE_HIGH>; - enable-active-high; - - pinctrl-0 = <&nvme_reg_en>; - pinctrl-names = "default"; - - regulator-boot-on; - }; - - vreg_wcn_0p95: regulator-wcn-0p95 { - compatible = "regulator-fixed"; - - regulator-name = "VREG_WCN_0P95"; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <950000>; - - vin-supply = <&vreg_wcn_3p3>; - }; - - vreg_wcn_3p3: regulator-wcn-3p3 { - compatible = "regulator-fixed"; - - regulator-name = "VREG_WCN_3P3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - - gpio = <&tlmm 94 GPIO_ACTIVE_HIGH>; - enable-active-high; - - pinctrl-0 = <&wcn_sw_en>; - pinctrl-names = "default"; - - regulator-boot-on; - }; - - vreg_wwan: regulator-wwan { - compatible = "regulator-fixed"; - - regulator-name = "VREG_WWAN_3P3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - - gpio = <&tlmm 246 GPIO_ACTIVE_HIGH>; - enable-active-high; - - pinctrl-0 = <&wwan_reg_en>; - pinctrl-names = "default"; - }; - - wcn7850-pmu { - compatible = "qcom,wcn7850-pmu"; - - vdd-supply = <&vreg_wcn_0p95>; - vddio-supply = <&vreg_l15b_e0_1p8>; - vddaon-supply = <&vreg_l15b_e0_1p8>; - vdddig-supply = <&vreg_l15b_e0_1p8>; - vddrfa1p2-supply = <&vreg_l15b_e0_1p8>; - vddrfa1p8-supply = <&vreg_l15b_e0_1p8>; - - wlan-enable-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>; - bt-enable-gpios = <&tlmm 116 GPIO_ACTIVE_HIGH>; - - pinctrl-0 = <&wcn_wlan_bt_en>; - pinctrl-names = "default"; - - 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_1p8: ldo7 { - regulator-name = "vreg_pmu_rfa_1p8"; - }; - - vreg_pmu_pcie_0p9: ldo8 { - regulator-name = "vreg_pmu_pcie_0p9"; - }; - - vreg_pmu_pcie_1p8: ldo9 { - regulator-name = "vreg_pmu_pcie_1p8"; - }; - }; - }; -}; - -&apps_rsc { - regulators-0 { - compatible = "qcom,pmh0101-rpmh-regulators"; - qcom,pmic-id = "B_E0"; - - vreg_bob1_e0: bob1 { - regulator-name = "vreg_bob1_e0"; - regulator-min-microvolt = <2200000>; - regulator-max-microvolt = <4224000>; - regulator-initial-mode = ; - }; - - vreg_bob2_e0: bob2 { - regulator-name = "vreg_bob2_e0"; - regulator-min-microvolt = <2540000>; - regulator-max-microvolt = <3600000>; - regulator-initial-mode = ; - }; - - vreg_l1b_e0_1p8: ldo1 { - regulator-name = "vreg_l1b_e0_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-initial-mode = ; - }; - - vreg_l2b_e0_2p9: ldo2 { - regulator-name = "vreg_l2b_e0_2p9"; - regulator-min-microvolt = <2904000>; - regulator-max-microvolt = <2904000>; - regulator-initial-mode = ; - }; - - vreg_l7b_e0_2p79: ldo7 { - regulator-name = "vreg_l7b_e0_2p79"; - regulator-min-microvolt = <2790000>; - regulator-max-microvolt = <2792000>; - regulator-initial-mode = ; - }; - - vreg_l8b_e0_1p50: ldo8 { - regulator-name = "vreg_l8b_e0_1p50"; - regulator-min-microvolt = <1504000>; - regulator-max-microvolt = <1504000>; - regulator-initial-mode = ; - }; - - vreg_l9b_e0_2p7: ldo9 { - regulator-name = "vreg_l9b_e0_2p7"; - regulator-min-microvolt = <2704000>; - regulator-max-microvolt = <2704000>; - regulator-initial-mode = ; - }; - - vreg_l10b_e0_1p8: ldo10 { - regulator-name = "vreg_l10b_e0_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-initial-mode = ; - }; - - vreg_l11b_e0_1p2: ldo11 { - regulator-name = "vreg_l11b_e0_1p2"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-initial-mode = ; - }; - - vreg_l12b_e0_1p14: ldo12 { - regulator-name = "vreg_l12b_e0_1p14"; - regulator-min-microvolt = <1144000>; - regulator-max-microvolt = <1144000>; - regulator-initial-mode = ; - }; - - vreg_l15b_e0_1p8: ldo15 { - regulator-name = "vreg_l15b_e0_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-initial-mode = ; - }; - - vreg_l17b_e0_2p4: ldo17 { - regulator-name = "vreg_l17b_e0_2p4"; - regulator-min-microvolt = <2400000>; - regulator-max-microvolt = <2700000>; - regulator-initial-mode = ; - }; - - vreg_l18b_e0_1p2: ldo18 { - regulator-name = "vreg_l18b_e0_1p2"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-initial-mode = ; - }; - }; - - regulators-1 { - compatible = "qcom,pmcx0102-rpmh-regulators"; - qcom,pmic-id = "C_E1"; - - vreg_l1c_e1_0p82: ldo1 { - regulator-name = "vreg_l1c_e1_0p82"; - regulator-min-microvolt = <832000>; - regulator-max-microvolt = <832000>; - regulator-initial-mode = ; - }; - - vreg_l2c_e1_1p14: ldo2 { - regulator-name = "vreg_l2c_e1_1p14"; - regulator-min-microvolt = <1144000>; - regulator-max-microvolt = <1144000>; - regulator-initial-mode = ; - }; - - vreg_l3c_e1_0p89: ldo3 { - regulator-name = "vreg_l3c_e1_0p89"; - regulator-min-microvolt = <890000>; - regulator-max-microvolt = <980000>; - regulator-initial-mode = ; - }; - - vreg_l4c_e1_0p72: ldo4 { - regulator-name = "vreg_l4c_e1_0p72"; - regulator-min-microvolt = <720000>; - regulator-max-microvolt = <720000>; - regulator-initial-mode = ; - }; - }; - - regulators-2 { - compatible = "qcom,pmh0110-rpmh-regulators"; - qcom,pmic-id = "F_E0"; - - vreg_s7f_e0_1p32: smps7 { - regulator-name = "vreg_s7f_e0_1p32"; - regulator-min-microvolt = <1320000>; - regulator-max-microvolt = <1352000>; - regulator-initial-mode = ; - }; - - vreg_s8f_e0_0p95: smps8 { - regulator-name = "vreg_s8f_e0_0p95"; - regulator-min-microvolt = <952000>; - regulator-max-microvolt = <1200000>; - regulator-initial-mode = ; - }; - - vreg_s9f_e0_1p9: smps9 { - regulator-name = "vreg_s9f_e0_1p9"; - regulator-min-microvolt = <1900000>; - regulator-max-microvolt = <2000000>; - regulator-initial-mode = ; - }; - - vreg_l2f_e0_0p82: ldo2 { - regulator-name = "vreg_l2f_e0_0p82"; - regulator-min-microvolt = <832000>; - regulator-max-microvolt = <832000>; - regulator-initial-mode = ; - }; - - vreg_l3f_e0_0p72: ldo3 { - regulator-name = "vreg_l3f_e0_0p72"; - regulator-min-microvolt = <720000>; - regulator-max-microvolt = <720000>; - regulator-initial-mode = ; - }; - - vreg_l4f_e0_1p08: ldo4 { - regulator-name = "vreg_l4f_e0_1p08"; - regulator-min-microvolt = <1080000>; - regulator-max-microvolt = <1200000>; - regulator-initial-mode = ; - }; - }; - - regulators-3 { - compatible = "qcom,pmh0110-rpmh-regulators"; - qcom,pmic-id = "F_E1"; - - vreg_s7f_e1_0p3: smps7 { - regulator-name = "vreg_s7f_e1_0p3"; - regulator-min-microvolt = <300000>; - regulator-max-microvolt = <1200000>; - regulator-initial-mode = ; - }; - - vreg_l1f_e1_0p82: ldo1 { - regulator-name = "vreg_l1f_e1_0p82"; - regulator-min-microvolt = <832000>; - regulator-max-microvolt = <832000>; - regulator-initial-mode = ; - }; - - vreg_l2f_e1_0p83: ldo2 { - regulator-name = "vreg_l2f_e1_0p83"; - regulator-min-microvolt = <832000>; - regulator-max-microvolt = <832000>; - regulator-initial-mode = ; - }; - - vreg_l4f_e1_1p08: ldo4 { - regulator-name = "vreg_l4f_e1_1p08"; - regulator-min-microvolt = <1080000>; - regulator-max-microvolt = <1320000>; - regulator-initial-mode = ; - }; - }; - - regulators-4 { - compatible = "qcom,pmh0110-rpmh-regulators"; - qcom,pmic-id = "H_E0"; - - vreg_l1h_e0_0p89: ldo1 { - regulator-name = "vreg_l1h_e0_0p89"; - regulator-min-microvolt = <832000>; - regulator-max-microvolt = <832000>; - regulator-initial-mode = ; - }; - - vreg_l2h_e0_0p72: ldo2 { - regulator-name = "vreg_l2h_e0_0p72"; - regulator-min-microvolt = <832000>; - regulator-max-microvolt = <832000>; - regulator-initial-mode = ; - }; - - vreg_l3h_e0_0p32: ldo3 { - regulator-name = "vreg_l3h_e0_0p32"; - regulator-min-microvolt = <320000>; - regulator-max-microvolt = <2000000>; - regulator-initial-mode = ; - }; - - vreg_l4h_e0_1p2: ldo4 { - regulator-name = "vreg_l4h_e0_1p2"; - regulator-min-microvolt = <1080000>; - regulator-max-microvolt = <1320000>; - regulator-initial-mode = ; - }; - }; -}; - -&i2c9 { - clock-frequency = <400000>; - - status = "okay"; - - embedded-controller@76 { - compatible = "qcom,glymur-qcb-ec", "qcom,hamoa-crd-ec"; - reg = <0x76>; - - interrupts-extended = <&tlmm 66 IRQ_TYPE_EDGE_FALLING>; - - pinctrl-0 = <&ec_int_n_default>; - pinctrl-names = "default"; - }; -}; - -&pcie4 { - pinctrl-0 = <&pcie4_default>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&pcie4_phy { - vdda-phy-supply = <&vreg_l1c_e1_0p82>; - vdda-pll-supply = <&vreg_l4f_e1_1p08>; - vdda-refgen0p9-supply = <&vreg_l1c_e1_0p82>; - vdda-refgen1p2-supply = <&vreg_l4f_e1_1p08>; - - status = "okay"; -}; - -&pcie4_port0 { - reset-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>; - wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>; - - wifi@0 { - compatible = "pci17cb,1107"; - reg = <0x10000 0x0 0x0 0x0 0x0>; - - vddaon-supply = <&vreg_pmu_aon_0p59>; - vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; - vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; - vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; - vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; - vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; - vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; - vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>; - vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>; - }; -}; - -&pcie5 { - vddpe-3v3-supply = <&vreg_nvme>; - - pinctrl-0 = <&pcie5_default>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&pcie5_phy { - vdda-phy-supply = <&vreg_l2f_e0_0p82>; - vdda-pll-supply = <&vreg_l4h_e0_1p2>; - vdda-refgen0p9-supply = <&vreg_l2f_e0_0p82>; - vdda-refgen1p2-supply = <&vreg_l4h_e0_1p2>; - - status = "okay"; -}; - -&pcie5_port0 { - reset-gpios = <&tlmm 152 GPIO_ACTIVE_LOW>; - wake-gpios = <&tlmm 154 GPIO_ACTIVE_LOW>; -}; - -&pcie6 { - vddpe-3v3-supply = <&vreg_wwan>; - - pinctrl-0 = <&pcie6_default>; - pinctrl-names = "default"; - - status = "okay"; -}; - -&pcie6_phy { - vdda-phy-supply = <&vreg_l1c_e1_0p82>; - vdda-pll-supply = <&vreg_l4f_e1_1p08>; - vdda-refgen0p9-supply = <&vreg_l1c_e1_0p82>; - vdda-refgen1p2-supply = <&vreg_l4f_e1_1p08>; - - status = "okay"; -}; - -&pcie6_port0 { - reset-gpios = <&tlmm 149 GPIO_ACTIVE_LOW>; - wake-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>; -}; - -&pmh0101_gpios { - key_vol_up_default: key-vol-up-default-state { - pins = "gpio6"; - function = "normal"; - output-disable; - bias-pull-up; - }; - - nvme_reg_en: nvme-reg-en-state { - pins = "gpio14"; - function = "normal"; - bias-disable; - }; -}; - -&pmk8850_rtc { - qcom,no-alarm; - qcom,uefi-rtc-info; -}; - -&pon_resin { - linux,code = ; - - status = "okay"; -}; - -&remoteproc_adsp { - firmware-name = "qcom/glymur/adsp.mbn", - "qcom/glymur/adsp_dtb.mbn"; - - status = "okay"; -}; - -&remoteproc_cdsp { - firmware-name = "qcom/glymur/cdsp.mbn", - "qcom/glymur/cdsp_dtb.mbn"; - - status = "okay"; -}; - -&remoteproc_soccp { - firmware-name = "qcom/glymur/soccp.mbn", - "qcom/glymur/soccp_dtb.mbn"; }; &tcsr { @@ -584,140 +32,3 @@ vdda-refgen4-0p9-supply = <&vreg_l1f_e1_0p82>; vdda-refgen4-1p2-supply = <&vreg_l4f_e1_1p08>; }; - -&tlmm { - gpio-reserved-ranges = <4 4>, /* EC TZ Secure I3C */ - <10 2>, /* OOB UART */ - <44 4>; /* Security SPI (TPM) */ - - ec_int_n_default: ec-int-n-state { - pins = "gpio66"; - function = "gpio"; - bias-disable; - }; - - pcie4_default: pcie4-default-state { - clkreq-n-pins { - pins = "gpio147"; - function = "pcie4_clk_req_n"; - drive-strength = <2>; - bias-pull-up; - }; - - perst-n-pins { - pins = "gpio146"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - - wake-n-pins { - pins = "gpio148"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - pcie5_default: pcie5-default-state { - clkreq-n-pins { - pins = "gpio153"; - function = "pcie5_clk_req_n"; - drive-strength = <2>; - bias-pull-up; - }; - - perst-n-pins { - pins = "gpio152"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - - wake-n-pins { - pins = "gpio154"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - pcie6_default: pcie6-default-state { - clkreq-n-pins { - pins = "gpio150"; - function = "pcie6_clk_req_n"; - drive-strength = <2>; - bias-pull-up; - }; - - perst-n-pins { - pins = "gpio149"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - - wake-n-pins { - pins = "gpio151"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - wcn_wlan_bt_en: wcn-wlan-bt-en-state { - pins = "gpio116", "gpio117"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - - wcn_sw_en: wcn-sw-en-state { - pins = "gpio94"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - - wwan_reg_en: wwan-reg-en-state { - pins = "gpio246"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; -}; - -&uart14 { - status = "okay"; - - bluetooth { - compatible = "qcom,wcn7850-bt"; - max-speed = <3200000>; - - vddaon-supply = <&vreg_pmu_aon_0p59>; - vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; - vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; - vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; - vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; - vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; - vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; - }; -}; - -&ufs_mem_hc { - reset-gpios = <&tlmm 250 GPIO_ACTIVE_LOW>; - - vcc-supply = <&vreg_l17b_e0_2p4>; - vcc-max-microamp = <1200000>; - vccq-supply = <&vreg_l12b_e0_1p14>; - vccq-max-microamp = <1200000>; - - status = "okay"; -}; - -&ufs_mem_phy { - vdda-phy-supply = <&vreg_l1c_e1_0p82>; - vdda-pll-supply = <&vreg_l4f_e1_1p08>; - - status = "okay"; -}; diff --git a/arch/arm64/boot/dts/qcom/glymur-qcb.dtsi b/arch/arm64/boot/dts/qcom/glymur-qcb.dtsi new file mode 100644 index 0000000000000..9751fbcc5f824 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-qcb.dtsi @@ -0,0 +1,671 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include "pmcx0102.dtsi" /* SPMI0: SID-2/3 SPMI1: SID-2/3 */ +#include "pmh0101.dtsi" /* SPMI0: SID-1 */ +#include "pmh0110-glymur.dtsi" /* SPMI0: SID-5/7 SPMI1: SID-5 */ +#include "pmh0104-glymur.dtsi" /* SPMI0: SID-8/9 SPMI1: SID-11 */ +#include "pmk8850.dtsi" /* SPMI0: SID-0 */ +#include "smb2370.dtsi" /* SPMI2: SID-9/10/11 */ + +/ { + aliases { + serial0 = &uart21; + serial1 = &uart14; + i2c0 = &i2c0; + i2c1 = &i2c4; + i2c2 = &i2c5; + i2c3 = &i2c9; + spi0 = &spi18; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + clocks { + xo_board: xo-board { + compatible = "fixed-clock"; + clock-frequency = <38400000>; + #clock-cells = <0>; + }; + + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + clock-frequency = <32000>; + #clock-cells = <0>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&key_vol_up_default>; + pinctrl-names = "default"; + + key-volume-up { + label = "Volume Up"; + linux,code = ; + gpios = <&pmh0101_gpios 6 GPIO_ACTIVE_LOW>; + debounce-interval = <15>; + linux,can-disable; + wakeup-source; + }; + }; + + vreg_nvme: regulator-nvme { + compatible = "regulator-fixed"; + + regulator-name = "VREG_NVME_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&pmh0101_gpios 14 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&nvme_reg_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; + + vreg_wcn_0p95: regulator-wcn-0p95 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_WCN_0P95"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <950000>; + + vin-supply = <&vreg_wcn_3p3>; + }; + + vreg_wcn_3p3: regulator-wcn-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_WCN_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 94 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&wcn_sw_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; + + vreg_wwan: regulator-wwan { + compatible = "regulator-fixed"; + + regulator-name = "VREG_WWAN_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 246 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&wwan_reg_en>; + pinctrl-names = "default"; + }; + + wcn7850-pmu { + compatible = "qcom,wcn7850-pmu"; + + vdd-supply = <&vreg_wcn_0p95>; + vddio-supply = <&vreg_l15b_e0_1p8>; + vddaon-supply = <&vreg_l15b_e0_1p8>; + vdddig-supply = <&vreg_l15b_e0_1p8>; + vddrfa1p2-supply = <&vreg_l15b_e0_1p8>; + vddrfa1p8-supply = <&vreg_l15b_e0_1p8>; + + wlan-enable-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>; + bt-enable-gpios = <&tlmm 116 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&wcn_wlan_bt_en>; + pinctrl-names = "default"; + + 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_1p8: ldo7 { + regulator-name = "vreg_pmu_rfa_1p8"; + }; + + vreg_pmu_pcie_0p9: ldo8 { + regulator-name = "vreg_pmu_pcie_0p9"; + }; + + vreg_pmu_pcie_1p8: ldo9 { + regulator-name = "vreg_pmu_pcie_1p8"; + }; + }; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pmh0101-rpmh-regulators"; + qcom,pmic-id = "B_E0"; + + vreg_bob1_e0: bob1 { + regulator-name = "vreg_bob1_e0"; + regulator-min-microvolt = <2200000>; + regulator-max-microvolt = <4224000>; + regulator-initial-mode = ; + }; + + vreg_bob2_e0: bob2 { + regulator-name = "vreg_bob2_e0"; + regulator-min-microvolt = <2540000>; + regulator-max-microvolt = <3600000>; + regulator-initial-mode = ; + }; + + vreg_l1b_e0_1p8: ldo1 { + regulator-name = "vreg_l1b_e0_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l2b_e0_2p9: ldo2 { + regulator-name = "vreg_l2b_e0_2p9"; + regulator-min-microvolt = <2904000>; + regulator-max-microvolt = <2904000>; + regulator-initial-mode = ; + }; + + vreg_l7b_e0_2p79: ldo7 { + regulator-name = "vreg_l7b_e0_2p79"; + regulator-min-microvolt = <2790000>; + regulator-max-microvolt = <2792000>; + regulator-initial-mode = ; + }; + + vreg_l8b_e0_1p50: ldo8 { + regulator-name = "vreg_l8b_e0_1p50"; + regulator-min-microvolt = <1504000>; + regulator-max-microvolt = <1504000>; + regulator-initial-mode = ; + }; + + vreg_l9b_e0_2p7: ldo9 { + regulator-name = "vreg_l9b_e0_2p7"; + regulator-min-microvolt = <2704000>; + regulator-max-microvolt = <2704000>; + regulator-initial-mode = ; + }; + + vreg_l10b_e0_1p8: ldo10 { + regulator-name = "vreg_l10b_e0_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l11b_e0_1p2: ldo11 { + regulator-name = "vreg_l11b_e0_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l12b_e0_1p14: ldo12 { + regulator-name = "vreg_l12b_e0_1p14"; + regulator-min-microvolt = <1144000>; + regulator-max-microvolt = <1144000>; + regulator-initial-mode = ; + }; + + vreg_l15b_e0_1p8: ldo15 { + regulator-name = "vreg_l15b_e0_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = ; + }; + + vreg_l17b_e0_2p4: ldo17 { + regulator-name = "vreg_l17b_e0_2p4"; + regulator-min-microvolt = <2400000>; + regulator-max-microvolt = <2700000>; + regulator-initial-mode = ; + }; + + vreg_l18b_e0_1p2: ldo18 { + regulator-name = "vreg_l18b_e0_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + }; + + regulators-1 { + compatible = "qcom,pmcx0102-rpmh-regulators"; + qcom,pmic-id = "C_E1"; + + vreg_l1c_e1_0p82: ldo1 { + regulator-name = "vreg_l1c_e1_0p82"; + regulator-min-microvolt = <832000>; + regulator-max-microvolt = <832000>; + regulator-initial-mode = ; + }; + + vreg_l2c_e1_1p14: ldo2 { + regulator-name = "vreg_l2c_e1_1p14"; + regulator-min-microvolt = <1144000>; + regulator-max-microvolt = <1144000>; + regulator-initial-mode = ; + }; + + vreg_l3c_e1_0p89: ldo3 { + regulator-name = "vreg_l3c_e1_0p89"; + regulator-min-microvolt = <890000>; + regulator-max-microvolt = <980000>; + regulator-initial-mode = ; + }; + + vreg_l4c_e1_0p72: ldo4 { + regulator-name = "vreg_l4c_e1_0p72"; + regulator-min-microvolt = <720000>; + regulator-max-microvolt = <720000>; + regulator-initial-mode = ; + }; + }; + + regulators-2 { + compatible = "qcom,pmh0110-rpmh-regulators"; + qcom,pmic-id = "F_E0"; + + vreg_s7f_e0_1p32: smps7 { + regulator-name = "vreg_s7f_e0_1p32"; + regulator-min-microvolt = <1320000>; + regulator-max-microvolt = <1352000>; + regulator-initial-mode = ; + }; + + vreg_s8f_e0_0p95: smps8 { + regulator-name = "vreg_s8f_e0_0p95"; + regulator-min-microvolt = <952000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_s9f_e0_1p9: smps9 { + regulator-name = "vreg_s9f_e0_1p9"; + regulator-min-microvolt = <1900000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = ; + }; + + vreg_l2f_e0_0p82: ldo2 { + regulator-name = "vreg_l2f_e0_0p82"; + regulator-min-microvolt = <832000>; + regulator-max-microvolt = <832000>; + regulator-initial-mode = ; + }; + + vreg_l3f_e0_0p72: ldo3 { + regulator-name = "vreg_l3f_e0_0p72"; + regulator-min-microvolt = <720000>; + regulator-max-microvolt = <720000>; + regulator-initial-mode = ; + }; + + vreg_l4f_e0_1p08: ldo4 { + regulator-name = "vreg_l4f_e0_1p08"; + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + }; + + regulators-3 { + compatible = "qcom,pmh0110-rpmh-regulators"; + qcom,pmic-id = "F_E1"; + + vreg_s7f_e1_0p3: smps7 { + regulator-name = "vreg_s7f_e1_0p3"; + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l1f_e1_0p82: ldo1 { + regulator-name = "vreg_l1f_e1_0p82"; + regulator-min-microvolt = <832000>; + regulator-max-microvolt = <832000>; + regulator-initial-mode = ; + }; + + vreg_l2f_e1_0p83: ldo2 { + regulator-name = "vreg_l2f_e1_0p83"; + regulator-min-microvolt = <832000>; + regulator-max-microvolt = <832000>; + regulator-initial-mode = ; + }; + + vreg_l4f_e1_1p08: ldo4 { + regulator-name = "vreg_l4f_e1_1p08"; + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <1320000>; + regulator-initial-mode = ; + }; + }; + + regulators-4 { + compatible = "qcom,pmh0110-rpmh-regulators"; + qcom,pmic-id = "H_E0"; + + vreg_l1h_e0_0p89: ldo1 { + regulator-name = "vreg_l1h_e0_0p89"; + regulator-min-microvolt = <832000>; + regulator-max-microvolt = <832000>; + regulator-initial-mode = ; + }; + + vreg_l2h_e0_0p72: ldo2 { + regulator-name = "vreg_l2h_e0_0p72"; + regulator-min-microvolt = <832000>; + regulator-max-microvolt = <832000>; + regulator-initial-mode = ; + }; + + vreg_l3h_e0_0p32: ldo3 { + regulator-name = "vreg_l3h_e0_0p32"; + regulator-min-microvolt = <320000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = ; + }; + + vreg_l4h_e0_1p2: ldo4 { + regulator-name = "vreg_l4h_e0_1p2"; + regulator-min-microvolt = <1080000>; + regulator-max-microvolt = <1320000>; + regulator-initial-mode = ; + }; + }; +}; + +&i2c9 { + clock-frequency = <400000>; + status = "okay"; + + embedded-controller@76 { + compatible = "qcom,glymur-qcb-ec", "qcom,hamoa-crd-ec"; + reg = <0x76>; + + interrupts-extended = <&tlmm 66 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-0 = <&ec_int_n_default>; + pinctrl-names = "default"; + }; +}; + +&pcie4 { + pinctrl-0 = <&pcie4_default>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie4_phy { + vdda-phy-supply = <&vreg_l1c_e1_0p82>; + vdda-pll-supply = <&vreg_l4f_e1_1p08>; + + status = "okay"; +}; + +&pcie4_port0 { + reset-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>; + + wifi@0 { + compatible = "pci17cb,1107"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>; + }; +}; + +&pcie5 { + vddpe-3v3-supply = <&vreg_nvme>; + + pinctrl-0 = <&pcie5_default>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie5_phy { + vdda-phy-supply = <&vreg_l2f_e0_0p82>; + vdda-pll-supply = <&vreg_l4h_e0_1p2>; + + status = "okay"; +}; + +&pcie5_port0 { + reset-gpios = <&tlmm 152 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 154 GPIO_ACTIVE_LOW>; +}; + +&pcie6 { + vddpe-3v3-supply = <&vreg_wwan>; + + pinctrl-0 = <&pcie6_default>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie6_phy { + vdda-phy-supply = <&vreg_l1c_e1_0p82>; + vdda-pll-supply = <&vreg_l4f_e1_1p08>; + + status = "okay"; +}; + +&pcie6_port0 { + reset-gpios = <&tlmm 149 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>; +}; + +&pmh0101_gpios { + key_vol_up_default: key-vol-up-default-state { + pins = "gpio6"; + function = "normal"; + output-disable; + bias-pull-up; + }; + + nvme_reg_en: nvme-reg-en-state { + pins = "gpio14"; + function = "normal"; + bias-disable; + }; +}; + +&pmk8850_rtc { + qcom,no-alarm; + qcom,uefi-rtc-info; +}; + +&pon_resin { + linux,code = ; + + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/glymur/adsp.mbn", + "qcom/glymur/adsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/glymur/cdsp.mbn", + "qcom/glymur/cdsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_soccp { + firmware-name = "qcom/glymur/soccp.mbn", + "qcom/glymur/soccp_dtb.mbn"; +}; + +&tlmm { + gpio-reserved-ranges = <4 4>, /* EC TZ Secure I3C */ + <10 2>, /* OOB UART */ + <44 4>; /* Security SPI (TPM) */ + + ec_int_n_default: ec-int-n-state { + pins = "gpio66"; + function = "gpio"; + bias-disable; + }; + + pcie4_default: pcie4-default-state { + clkreq-n-pins { + pins = "gpio147"; + function = "pcie4_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio146"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio148"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie5_default: pcie5-default-state { + clkreq-n-pins { + pins = "gpio153"; + function = "pcie5_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio152"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio154"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie6_default: pcie6-default-state { + clkreq-n-pins { + pins = "gpio150"; + function = "pcie6_clk_req_n"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio149"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio151"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + wcn_wlan_bt_en: wcn-wlan-bt-en-state { + pins = "gpio116", "gpio117"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wcn_sw_en: wcn-sw-en-state { + pins = "gpio94"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wwan_reg_en: wwan-reg-en-state { + pins = "gpio246"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; + +&uart14 { + status = "okay"; + + bluetooth { + compatible = "qcom,wcn7850-bt"; + max-speed = <3200000>; + + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>; + vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>; + }; +}; From 39e51951a89e825dd96270a18217b6d583a3c290 Mon Sep 17 00:00:00 2001 From: Sivansh Gupta Date: Mon, 26 Oct 2026 12:19:48 +0530 Subject: [PATCH 0473/1133] FROMLIST: arm64: dts: qcom: Add Mahua QCB Add initial device tree support for Mahua QCB. Mahua QCB is a variant of Glymur QCB but using Mahua SoC instead of Glymur SoC. Mahua is a 12 core derivative of Glymur SoC. Unlike the CRD, the QCB is suitable for compute workloads, power measurements and oscilloscope-based hardware validation. Includes glymur-qcb.dtsi, adds Mahua QCB specific board compatible, adds tcsr regulator-supply properties, removed cluster2 PMIC/thermal nodes. Link: https://lore.kernel.org/all/20261027114955.1266499-5-sivansh.gupta@oss.qualcomm.com/ Co-developed-by: Gopikrishna Garmidi Signed-off-by: Gopikrishna Garmidi Signed-off-by: Sivansh Gupta --- arch/arm64/boot/dts/qcom/Makefile | 1 + arch/arm64/boot/dts/qcom/mahua-qcb.dts | 38 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/mahua-qcb.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index b7f1e543a2484..ce658334261b0 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -66,6 +66,7 @@ lemans-evk-ifp-mezzanine-dtbs := lemans-evk.dtb lemans-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-ifp-mezzanine.dtb dtb-$(CONFIG_ARCH_QCOM) += mahua-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += mahua-lenovo-thinkpad-t14s-gen7-lcd.dtb +dtb-$(CONFIG_ARCH_QCOM) += mahua-qcb.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-fairphone-fp6.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-nothing-asteroids.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza.dtb diff --git a/arch/arm64/boot/dts/qcom/mahua-qcb.dts b/arch/arm64/boot/dts/qcom/mahua-qcb.dts new file mode 100644 index 0000000000000..0c742c54a2371 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/mahua-qcb.dts @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include "mahua.dtsi" +#include "glymur-qcb.dtsi" + +/* PMICs tied to Glymur's cluster2 are absent on Mahua. */ +/delete-node/ &pmcx0102_d_e0; +/delete-node/ &pmcx0102_d0_thermal; +/delete-node/ &pmh0104_i_e0; +/delete-node/ &pmh0104_i0_thermal; +/delete-node/ &pmh0104_j_e0; +/delete-node/ &pmh0104_j0_thermal; + +/ { + model = "Qualcomm Technologies, Inc. Mahua QCB"; + compatible = "qcom,mahua-qcb", "qcom,mahua"; +}; + +&tcsr { + vdda-qrefrpt0-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrpt1-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrpt2-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrpt3-0p9-supply = <&vreg_l1f_e1_0p82>; + vdda-qrefrpt4-0p9-supply = <&vreg_l2h_e0_0p72>; + vdda-qrefrpt5-0p9-supply = <&vreg_l2h_e0_0p72>; + vdda-qrefrx0-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrx1-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrx2-0p9-supply = <&vreg_l2f_e1_0p83>; + vdda-qrefrx3-0p9-supply = <&vreg_l2h_e0_0p72>; + vdda-qreftx1-0p9-supply = <&vreg_l1f_e1_0p82>; + vdda-refgen3-0p9-supply = <&vreg_l1f_e1_0p82>; + vdda-refgen3-1p2-supply = <&vreg_l4f_e1_1p08>; +}; From 781e62c888768421276ceaf5867ccd777e4ed4eb Mon Sep 17 00:00:00 2001 From: Giri Prasad Goriparthi Date: Wed, 28 Oct 2026 18:44:20 +0530 Subject: [PATCH 0474/1133] FROMLIST: arm64: dts: qcom: glymur-crd: Add pull-up for SD card detect The SD card detect signal is active low and requires a defined high level when no card is inserted. With the GPIO bias disabled, the card-detect input can be left floating and result in spurious interrupts. Enable the internal pull-up on the SD card detect GPIO to keep the signal at a defined level when the card is absent and avoid spurious card-detect interrupts. Link:https://lore.kernel.org/all/20261028-gly_spu-v1-1-1b5b4e1f8341@oss.qualcomm.com/ Signed-off-by: Giri Prasad Goriparthi --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index 422883a2d5276..b8c95f5755c73 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -1680,7 +1680,7 @@ pins = "gpio221"; function = "gpio"; drive-strength = <2>; - bias-disable; + bias-pull-up; }; tpad_default: tpad-default-state { From 235cffce41a76f82b8e939a6a263f75d949f130b Mon Sep 17 00:00:00 2001 From: Karthik S Date: Wed, 16 Sep 2026 19:01:43 +0530 Subject: [PATCH 0475/1133] PENDING: ASoC: qcom: sc8280xp: enable support for talos-lyra Add the necessary board widgets, kcontrols and DAPM routes for max98091 codec support. Enable required DAI format, sysclk and other required configs. Signed-off-by: Karthik S --- .../bindings/sound/qcom,sm8250.yaml | 1 + sound/soc/qcom/sc8280xp.c | 32 ++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml index e2e3fc99e6d9a..40b68b72f8f4a 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml @@ -55,6 +55,7 @@ properties: - qcom,sdm845-sndcard - qcom,sm8250-sndcard - qcom,sm8450-sndcard + - qcom,talos-lyra-sndcard - qcom,x1e80100-sndcard - thundercomm,qcs6490-rubikpi3-sndcard diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 9aae6aadd43da..e26c66fd13d37 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -44,8 +44,9 @@ static struct snd_soc_dapm_widget sc8280xp_dapm_widgets[] = { static const struct snd_kcontrol_new max98090_controls[] = { SOC_DAPM_PIN_SWITCH("Headset Mic12"), - SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic34"), SOC_DAPM_PIN_SWITCH("Headset Mic56"), + SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Speaker"), SOC_DAPM_PIN_SWITCH("Receiver"), SOC_DAPM_PIN_SWITCH("Int Mic"), @@ -56,6 +57,7 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = { SND_SOC_DAPM_MIC("Mic Jack", NULL), SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic12", NULL), + SND_SOC_DAPM_MIC("Headset Mic34", NULL), SND_SOC_DAPM_MIC("Headset Mic56", NULL), SND_SOC_DAPM_MIC("Int Mic", NULL), SND_SOC_DAPM_SPK("Receiver", NULL), @@ -81,6 +83,21 @@ struct sc8280xp_dai_data { .dai_data = (const struct sc8280xp_dai_data[]) { __VA_ARGS__ }, \ .num_dai_data = ARRAY_SIZE(((const struct sc8280xp_dai_data[]) { __VA_ARGS__ })) +static const struct snd_soc_dapm_route talos_lyra_dapm_routes[] = { + {"IN12", NULL, "Headset Mic12"}, + {"Headset Mic12", NULL, "MICBIAS"}, + {"IN34", NULL, "Headset Mic34"}, + {"Headset Mic34", NULL, "MICBIAS"}, + {"IN56", NULL, "Headset Mic56"}, + {"Headset Mic56", NULL, "MICBIAS"}, + {"Headphone", NULL, "HPL"}, + {"Headphone", NULL, "HPR"}, + {"Receiver", NULL, "RCVL"}, + {"Receiver", NULL, "RCVR"}, + {"Speaker", NULL, "SPKL"}, + {"Speaker", NULL, "SPKR"}, +}; + struct qcom_snd_soc_common { const char *driver_name; const struct snd_soc_dapm_widget *dapm_widgets; @@ -624,6 +641,18 @@ static const struct qcom_snd_soc_common qcs615_priv_data = { .codec_sysclk_set = true, }; +static const struct qcom_snd_soc_common talos_lyra_priv_data = { + .driver_name = "qcs615", + .dapm_widgets = max98090_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98090_dapm_widgets), + .dapm_routes = talos_lyra_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(talos_lyra_dapm_routes), + .controls = max98090_controls, + .num_controls = ARRAY_SIZE(max98090_controls), + .codec_dai_fmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BC_FC, + .codec_sysclk_set = true, +}; + static const struct qcom_snd_soc_common qcm6490_priv_data = { .driver_name = "qcm6490", .dapm_widgets = sc8280xp_dapm_widgets, @@ -750,6 +779,7 @@ static const struct of_device_id snd_sc8280xp_dt_match[] = { { .compatible = "qcom,sm8550-sndcard", .data = &sm8550_priv_data }, { .compatible = "qcom,sm8650-sndcard", .data = &sm8650_priv_data }, { .compatible = "qcom,sm8750-sndcard", .data = &sm8750_priv_data }, + { .compatible = "qcom,talos-lyra-sndcard", .data = &talos_lyra_priv_data }, {} }; From f9ece36530a41e7afc8fa6a9e0ca1c43747a08fb Mon Sep 17 00:00:00 2001 From: Karthik S Date: Wed, 16 Sep 2026 19:02:33 +0530 Subject: [PATCH 0476/1133] PENDING: pinctrl: qcom: add QCS615 LPASS LPI pinctrl driver Add the LPASS LPI pinctrl driver for the QCS615 SoC. The driver supports 32 GPIOs in the range 0-31 and provides pin control functionality for the LPASS LPI block. Signed-off-by: Karthik S --- .../qcom,qcs615-lpass-lpi-pinctrl.yaml | 114 +++++++++++ drivers/pinctrl/qcom/Kconfig | 10 + drivers/pinctrl/qcom/Makefile | 1 + .../pinctrl/qcom/pinctrl-qcs615-lpass-lpi.c | 185 ++++++++++++++++++ 4 files changed, 310 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,qcs615-lpass-lpi-pinctrl.yaml create mode 100644 drivers/pinctrl/qcom/pinctrl-qcs615-lpass-lpi.c diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,qcs615-lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,qcs615-lpass-lpi-pinctrl.yaml new file mode 100644 index 0000000000000..dc1525d7bf552 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,qcs615-lpass-lpi-pinctrl.yaml @@ -0,0 +1,114 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/qcom,qcs615-lpass-lpi-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm QCS615 SoC LPASS LPI TLMM + +maintainers: + - Karthik S + +description: + Top Level Mode Multiplexer pin controller in the Low Power Audio SubSystem + (LPASS) Low Power Island (LPI) of Qualcomm QCS615 SoC. + +properties: + compatible: + const: qcom,qcs615-lpass-lpi-pinctrl + + reg: + items: + - description: LPASS LPI TLMM Control and Status registers + - description: LPASS LPI MCC registers + + clocks: + items: + - description: LPASS Core voting clock + + clock-names: + items: + - const: core + +patternProperties: + "-state$": + oneOf: + - $ref: "#/$defs/qcom-qcs615-lpass-state" + - patternProperties: + "-pins$": + $ref: "#/$defs/qcom-qcs615-lpass-state" + additionalProperties: false + +$defs: + qcom-qcs615-lpass-state: + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + $ref: qcom,lpass-lpi-common.yaml#/$defs/qcom-tlmm-state + unevaluatedProperties: false + + properties: + pins: + description: + List of gpio pins affected by the properties specified in this + subnode. + items: + pattern: "^gpio([0-9]|1[0-9]|2[0-9]|3[0-1])$" + + function: + enum: [ dmic1_clk, dmic1_data, dmic2_clk, dmic2_data, gpio, i2s1_clk, + i2s1_data, i2s1_ws, spkr_i2s_mclk_a ] + description: + Specify the alternative function to be configured for the specified + pins. + +allOf: + - $ref: qcom,lpass-lpi-common.yaml# + +required: + - compatible + - reg + - clocks + - clock-names + +unevaluatedProperties: false + +examples: + - | + #include + lpi_tlmm: pinctrl@62b40000 { + compatible = "qcom,qcs615-lpass-lpi-pinctrl"; + reg = <0x62b40000 0x20000>, + <0x62b00000 0x10000>; + clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "core"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&lpi_tlmm 0 0 32>; + + i2s1-active-state { + clk-pins { + pins = "gpio8"; + function = "i2s1_clk"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + ws-pins { + pins = "gpio9"; + function = "i2s1_ws"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + data-pins { + pins = "gpio10", "gpio11"; + function = "i2s1_data"; + drive-strength = <8>; + bias-disable; + }; + }; + }; diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 707067b9251f0..abe7155f209fd 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -72,6 +72,16 @@ config PINCTRL_HAWI_LPASS_LPI (Low Power Island) found on the Qualcomm Technologies Inc Hawi platform. +config PINCTRL_QCS615_LPASS_LPI + tristate "Qualcomm Technologies Inc QCS615 LPASS LPI pin controller driver" + depends on ARM64 || COMPILE_TEST + depends on PINCTRL_LPASS_LPI + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI + (Low Power Island) found on the Qualcomm Technologies Inc QCS615 + platform. + config PINCTRL_MILOS_LPASS_LPI tristate "Qualcomm Milos LPASS LPI pin controller driver" depends on ARM64 || COMPILE_TEST diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index a3daca77a4487..32d1b1bd53ded 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_PINCTRL_MSM8998) += pinctrl-msm8998.o obj-$(CONFIG_PINCTRL_QCM2290) += pinctrl-qcm2290.o obj-$(CONFIG_PINCTRL_QCS404) += pinctrl-qcs404.o obj-$(CONFIG_PINCTRL_QCS615) += pinctrl-qcs615.o +obj-$(CONFIG_PINCTRL_QCS615_LPASS_LPI) += pinctrl-qcs615-lpass-lpi.o obj-$(CONFIG_PINCTRL_QCS8300) += pinctrl-qcs8300.o obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o obj-$(CONFIG_PINCTRL_MDM9607) += pinctrl-mdm9607.o diff --git a/drivers/pinctrl/qcom/pinctrl-qcs615-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-qcs615-lpass-lpi.c new file mode 100644 index 0000000000000..78c8e7670c38c --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-qcs615-lpass-lpi.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * ALSA SoC platform-machine driver for QTi LPASS + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-lpass-lpi.h" + +enum lpass_lpi_functions { + LPI_MUX_i2s1_clk, + LPI_MUX_i2s1_ws, + LPI_MUX_i2s1_data, + LPI_MUX_spkr_i2s_mclk_a, + LPI_MUX_dmic1_clk, + LPI_MUX_dmic1_data, + LPI_MUX_dmic2_clk, + LPI_MUX_dmic2_data, + LPI_MUX_gpio, + LPI_MUX__, +}; + +static int gpio8_pins[] = { 8 }; +static int gpio9_pins[] = { 9 }; +static int gpio10_pins[] = { 10 }; +static int gpio11_pins[] = { 11 }; +static int gpio19_pins[] = { 19 }; +static int gpio26_pins[] = { 26 }; +static int gpio27_pins[] = { 27 }; +static int gpio28_pins[] = { 28 }; +static int gpio29_pins[] = { 29 }; +static int gpio0_pins[] = { 0 }; +static int gpio1_pins[] = { 1 }; +static int gpio2_pins[] = { 2 }; +static int gpio3_pins[] = { 3 }; +static int gpio4_pins[] = { 4 }; +static int gpio5_pins[] = { 5 }; +static int gpio6_pins[] = { 6 }; +static int gpio7_pins[] = { 7 }; +static int gpio12_pins[] = { 12 }; +static int gpio13_pins[] = { 13 }; +static int gpio14_pins[] = { 14 }; +static int gpio15_pins[] = { 15 }; +static int gpio16_pins[] = { 16 }; +static int gpio17_pins[] = { 17 }; +static int gpio18_pins[] = { 18 }; +static int gpio20_pins[] = { 20 }; +static int gpio21_pins[] = { 21 }; +static int gpio22_pins[] = { 22 }; +static int gpio23_pins[] = { 23 }; +static int gpio24_pins[] = { 24 }; +static int gpio25_pins[] = { 25 }; +static int gpio30_pins[] = { 30 }; +static int gpio31_pins[] = { 31 }; + +static const struct pinctrl_pin_desc qcs615_lpi_pins[] = { + PINCTRL_PIN(0, "gpio0"), + PINCTRL_PIN(1, "gpio1"), + PINCTRL_PIN(2, "gpio2"), + PINCTRL_PIN(3, "gpio3"), + PINCTRL_PIN(4, "gpio4"), + PINCTRL_PIN(5, "gpio5"), + PINCTRL_PIN(6, "gpio6"), + PINCTRL_PIN(7, "gpio7"), + PINCTRL_PIN(8, "gpio8"), + PINCTRL_PIN(9, "gpio9"), + PINCTRL_PIN(10, "gpio10"), + PINCTRL_PIN(11, "gpio11"), + PINCTRL_PIN(12, "gpio12"), + PINCTRL_PIN(13, "gpio13"), + PINCTRL_PIN(14, "gpio14"), + PINCTRL_PIN(15, "gpio15"), + PINCTRL_PIN(16, "gpio16"), + PINCTRL_PIN(17, "gpio17"), + PINCTRL_PIN(18, "gpio18"), + PINCTRL_PIN(19, "gpio19"), + PINCTRL_PIN(20, "gpio20"), + PINCTRL_PIN(21, "gpio21"), + PINCTRL_PIN(22, "gpio22"), + PINCTRL_PIN(23, "gpio23"), + PINCTRL_PIN(24, "gpio24"), + PINCTRL_PIN(25, "gpio25"), + PINCTRL_PIN(26, "gpio26"), + PINCTRL_PIN(27, "gpio27"), + PINCTRL_PIN(28, "gpio28"), + PINCTRL_PIN(29, "gpio29"), + PINCTRL_PIN(30, "gpio30"), + PINCTRL_PIN(31, "gpio31"), +}; + +static const char * const i2s1_clk_groups[] = { "gpio8" }; +static const char * const i2s1_ws_groups[] = { "gpio9" }; +static const char * const i2s1_data_groups[] = { "gpio10", "gpio11" }; +static const char * const spkr_i2s_mclk_a_groups[] = { "gpio19" }; +static const char * const dmic1_clk_groups[] = { "gpio26" }; +static const char * const dmic1_data_groups[] = { "gpio27" }; +static const char * const dmic2_clk_groups[] = { "gpio28" }; +static const char * const dmic2_data_groups[] = { "gpio29" }; + +static const struct lpi_pingroup qcs615_groups[] = { + LPI_PINGROUP(0, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(1, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(2, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(3, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(4, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(5, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(6, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(7, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(8, LPI_NO_SLEW, _, _, i2s1_clk, _), + LPI_PINGROUP(9, LPI_NO_SLEW, _, _, i2s1_ws, _), + LPI_PINGROUP(10, LPI_NO_SLEW, _, _, _, i2s1_data), + LPI_PINGROUP(11, LPI_NO_SLEW, _, i2s1_data, _, _), + LPI_PINGROUP(12, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(13, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(14, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(15, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(16, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(17, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(18, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(19, LPI_NO_SLEW, spkr_i2s_mclk_a, _, _, _), + LPI_PINGROUP(20, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(21, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(22, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(23, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(24, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(25, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(26, LPI_NO_SLEW, dmic1_clk, _, _, _), + LPI_PINGROUP(27, LPI_NO_SLEW, dmic1_data, _, _, _), + LPI_PINGROUP(28, LPI_NO_SLEW, dmic2_clk, _, _, _), + LPI_PINGROUP(29, LPI_NO_SLEW, dmic2_data, _, _, _), + LPI_PINGROUP(30, LPI_NO_SLEW, _, _, _, _), + LPI_PINGROUP(31, LPI_NO_SLEW, _, _, _, _), +}; + +static const struct lpi_function qcs615_functions[] = { + LPI_FUNCTION(i2s1_clk), + LPI_FUNCTION(i2s1_ws), + LPI_FUNCTION(i2s1_data), + LPI_FUNCTION(spkr_i2s_mclk_a), + LPI_FUNCTION(dmic1_clk), + LPI_FUNCTION(dmic1_data), + LPI_FUNCTION(dmic2_clk), + LPI_FUNCTION(dmic2_data), +}; + +static const struct lpi_pinctrl_variant_data qcs615_lpi_data = { + .pins = qcs615_lpi_pins, + .npins = ARRAY_SIZE(qcs615_lpi_pins), + .groups = qcs615_groups, + .ngroups = ARRAY_SIZE(qcs615_groups), + .functions = qcs615_functions, + .nfunctions = ARRAY_SIZE(qcs615_functions), +}; + +static const struct of_device_id lpi_pinctrl_of_match[] = { + { + .compatible = "qcom,qcs615-lpass-lpi-pinctrl", + .data = &qcs615_lpi_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, lpi_pinctrl_of_match); + +static const struct dev_pm_ops lpi_pinctrl_pm_ops = { + RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static struct platform_driver lpi_pinctrl_driver = { + .driver = { + .name = "qcom-qcs615-lpass-lpi-pinctrl", + .of_match_table = lpi_pinctrl_of_match, + .pm = pm_ptr(&lpi_pinctrl_pm_ops), + }, + .probe = lpi_pinctrl_probe, + .remove = lpi_pinctrl_remove, +}; + +module_platform_driver(lpi_pinctrl_driver); +MODULE_DESCRIPTION("QTI QCS615 LPI GPIO pin control driver"); +MODULE_LICENSE("GPL"); From b76931d3fb94791f28ce590db87f30884fdb3798 Mon Sep 17 00:00:00 2001 From: Pragnesh Papaniya Date: Thu, 4 Jun 2026 19:26:20 +0530 Subject: [PATCH 0477/1133] FROMLIST: firmware: arm_scmi: Add SCMI QCOM Generic Extension Protocol documentation Add System Control Management Interface (SCMI) Qualcomm Generic Extension Protocol documentation. It consists of a small set of generic SET/GET/ START/STOP commands, which is used to turn on/off and configure Qualcomm SoC specific algorithms that run on the SCP. It currently only supports MEMLAT (memory latency governor) algorithm. The immutable pairing of the MEMLAT algorithm string with the supported param_ids associated with it are documented here. Co-developed-by: Sibi Sankar Signed-off-by: Sibi Sankar Signed-off-by: Pragnesh Papaniya Link: https://lore.kernel.org/lkml/20260724-rfc_v8_scmi_memlat-v1-1-cb732bcff1f4@oss.qualcomm.com/ --- .../arm_scmi/vendors/qcom/qcom_generic.rst | 954 ++++++++++++++++++ 1 file changed, 954 insertions(+) create mode 100644 drivers/firmware/arm_scmi/vendors/qcom/qcom_generic.rst diff --git a/drivers/firmware/arm_scmi/vendors/qcom/qcom_generic.rst b/drivers/firmware/arm_scmi/vendors/qcom/qcom_generic.rst new file mode 100644 index 0000000000000..42e327d538414 --- /dev/null +++ b/drivers/firmware/arm_scmi/vendors/qcom/qcom_generic.rst @@ -0,0 +1,954 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. include:: + +================================================================================== +System Control and Management Interface (SCMI) Qualcomm Generic Extension Protocol +================================================================================== + +:Copyright: |copy| Qualcomm Technologies, Inc. and/or its subsidiaries. + +:Authors: + - Sibi Sankar + - Pragnesh Papaniya + +System Control and Management Interface Qualcomm Generic Extension Vendor Protocol +================================================================================== + +System Control Management Interface (SCMI) Qualcomm Generic Extension Protocol +consists of a small set of generic SET/GET/START/STOP commands, which is used to +turn on/off and configure Qualcomm SoC specific algorithms that run on the SCP. +Each algorithm is identified through an algorithm string and has an immutable list +of param_ids. All supported algorithms (currently just MEMLAT) have their own +dedicated section and are listed after the generic commands. + +Commands: +_________ + +PROTOCOL_VERSION +~~~~~~~~~~~~~~~~ + +message_id: 0x0 +protocol_id: 0x80 + ++---------------+--------------------------------------------------------------+ +|Return values | ++---------------+--------------------------------------------------------------+ +|Name |Description | ++---------------+--------------------------------------------------------------+ +|int32 status |See ARM SCMI Specification for status code definitions. | ++---------------+--------------------------------------------------------------+ +|uint32 version |For this revision of the specification, this value must be | +| |0x10000. | ++---------------+--------------------------------------------------------------+ + +PROTOCOL_ATTRIBUTES +~~~~~~~~~~~~~~~~~~~ + +message_id: 0x1 +protocol_id: 0x80 + ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|int32 status |See ARM SCMI Specification for status code definitions. | ++------------------+-----------------------------------------------------------+ +|uint32 attributes |Bits[31:16] Reserved, must be set to 0. | +| |Bits[15:8] Number of agents in the system. Must match the | +| |value reported by the standard BASE protocol's | +| |PROTOCOL_ATTRIBUTES response. | +| |Bits[7:0] Number of algorithmic strings supported by the | +| |system. Only "MEMLAT" is currently supported hence it | +| |returns 1. | ++------------------+-----------------------------------------------------------+ + +PROTOCOL_MESSAGE_ATTRIBUTES +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +message_id: 0x2 +protocol_id: 0x80 + ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|int32 status |See ARM SCMI Specification for status code definitions. | ++------------------+-----------------------------------------------------------+ +|uint32 attributes |For all message IDs the parameter has a value of 0. | ++------------------+-----------------------------------------------------------+ + +QCOM_SCMI_SET_PARAM +~~~~~~~~~~~~~~~~~~~ + +message_id: 0x10 +protocol_id: 0x80 + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 ext_id |Reserved, must be zero. | ++------------------+-----------------------------------------------------------+ +|uint32 algo_low |Lower 32-bit value of the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 algo_high |Upper 32-bit value of the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 param_id |Serves as the token message id for the algorithm string | +| |and is used to set various parameters supported by it. | ++------------------+-----------------------------------------------------------+ +|uint32 buf[] |Serves as the payload for the specified param_id and | +| |algorithm string pair. The payload size depends on the | +| |(algorithm string, param_id) pair; see the per-algorithm | +| |sections below. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS: if the param_id and buf[] is parsed successfully | +| |by the chosen algorithm string. | +| |NOT_SUPPORTED: if the algorithm string does not have any | +| |matches. | +| |INVALID_PARAMETERS: if the param_id and the buf[] passed | +| |is rejected by the algorithm string. | ++------------------+-----------------------------------------------------------+ + +QCOM_SCMI_GET_PARAM +~~~~~~~~~~~~~~~~~~~ + +message_id: 0x11 +protocol_id: 0x80 + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 ext_id |Reserved, must be zero. | ++------------------+-----------------------------------------------------------+ +|uint32 algo_low |Lower 32-bit value of the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 algo_high |Upper 32-bit value of the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 param_id |Serves as the token message id for the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 buf[] |Serves as the payload and store of value for the specified | +| |param_id and algorithm string pair. The payload size | +| |depends on the (algorithm string, param_id) pair; see the | +| |per-algorithm sections below. The response payload is | +| |returned in the same buffer, overwriting the request | +| |contents on success. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS: if the param_id and buf[] is parsed successfully | +| |by the chosen algorithm string and the result is copied | +| |into buf[]. | +| |NOT_SUPPORTED: if the algorithm string does not have any | +| |matches. | +| |INVALID_PARAMETERS: if the param_id and the buf[] passed | +| |is rejected by the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 buf[] |Holds the payload of the result of the query, returned in | +| |the same buffer used to send the request. Size depends on | +| |the (algorithm string, param_id) pair. | ++------------------+-----------------------------------------------------------+ + +QCOM_SCMI_START_ACTIVITY +~~~~~~~~~~~~~~~~~~~~~~~~ + +message_id: 0x12 +protocol_id: 0x80 + +The activity to be started is defined by the algorithm string; see the +per-algorithm sections (e.g. MEMLAT_START_TIMER) for valid param_ids. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 ext_id |Reserved, must be zero. | ++------------------+-----------------------------------------------------------+ +|uint32 algo_low |Lower 32-bit value of the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 algo_high |Upper 32-bit value of the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 param_id |Serves as the token message id for the algorithm string | +| |and is generally used to start the activity performed by | +| |the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 buf[] |Serves as the payload for the specified param_id and | +| |algorithm string pair. The payload size depends on the | +| |(algorithm string, param_id) pair; see the per-algorithm | +| |sections below. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS: if the activity performed by the algorithm string | +| |starts successfully, or if it was already running. | +| |NOT_SUPPORTED: if the algorithm string does not have any | +| |matches. | ++------------------+-----------------------------------------------------------+ + +QCOM_SCMI_STOP_ACTIVITY +~~~~~~~~~~~~~~~~~~~~~~~ + +message_id: 0x13 +protocol_id: 0x80 + +The activity to be stopped is defined by the algorithm string; see the +per-algorithm sections (e.g. MEMLAT_STOP_TIMER) for valid param_ids. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 ext_id |Reserved, must be zero. | ++------------------+-----------------------------------------------------------+ +|uint32 algo_low |Lower 32-bit value of the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 algo_high |Upper 32-bit value of the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 param_id |Serves as the token message id for the algorithm string | +| |and is generally used to stop the activity performed by | +| |the algorithm string. | ++------------------+-----------------------------------------------------------+ +|uint32 buf[] |Serves as the payload for the specified param_id and | +| |algorithm string pair. The payload size depends on the | +| |(algorithm string, param_id) pair; see the per-algorithm | +| |sections below. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS: if the activity performed by the algorithm string | +| |stops successfully, or if it was not running. | +| |NOT_SUPPORTED: if the algorithm string does not have any | +| |matches. | ++------------------+-----------------------------------------------------------+ + +MEMLAT: Memory Latency algorithm +________________________________ + +The MEMLAT algorithm (0x4d454d4c4154, ASCII "MEMLAT") scales the DDR, LLCC and +DDR_QOS buses in response to memory-latency-bound workloads. It runs on the CPUCP: +every sampling window it reads the per-CPU AMU counters, derives its statistics +(instructions-per-miss, back-end stall, write-back ratio), maps that to a target +level and votes for it directly on the DDR/LLCC/DDR_QOS interconnect. The kernel +never issues a frequency request in that loop. The 6-byte value is treated as a +64-bit algorithm string and split into two uint32 fields on the wire: algo_low +carries its lower 32 bits and algo_high its upper 32 bits. + +With a distinct need to have the memory buses scaling done in SCP in response to +memory-latency-bound workloads, none of the existing SCMI solutions could be used +as-is. MPAM does not apply either: it is not enabled on all of the affected parts +(e.g. Hamoa). The role split between SCP and client driver is described next. + +MEMLAT client driver pseudo-code: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: text + + probe(): + SET_COMMON_EV_MAP # AMU events (all groups) + for each memory group (DDR / LLCC / DDR_QOS): + SET_MEM_GROUP # bind group to interconnect + SET_GRP_EV_MAP # per-group AMU events + for each monitor in the group: + SET_MONITOR # topology, cpumask, name + IPM_CEIL / BE_STALL_FLOOR # per-monitor tuneables + MON_FREQ_MAP # cpufreq -> memfreq map + SET_MIN_FREQ / SET_MAX_FREQ # clamps + SAMPLE_MS # sampling period + SET_EFFECTIVE_FREQ_METHOD # cpu-freq derivation method + START_TIMER # CPUCP now scales autonomously + + devfreq poll (twice per CPUCP sample period): + GET_CUR_FREQ # read voted freq, per monitor + + remove(): + STOP_TIMER + +SCP pseudo-code: +~~~~~~~~~~~~~~~~ + +.. code-block:: text + + every sample_ms: + for each CPU: + sample AMU counters (instructions, cycles, cache-misses, stalls) + derive per-CPU IPM, back-end-stall % and write-back ratio + + for each configured memory group (DDR / LLCC / DDR_QOS): + for each monitor in the group: + best_freq = 0 + for each CPU in the monitor's cpumask: + if CPU is memory-bound (IPM/stall/write-back vs. the + monitor's configured thresholds): + freq = CPU's cpufreq, optionally scaled toward the ceiling + best_freq = max(best_freq, freq) + monitor.target_freq = monitor's cpufreq->memfreq map(best_freq) + + group_vote = max(target_freq of every monitor in the group) + if group_vote changed since the last sample: + vote group_vote onto the group's interconnect path + + GET_CUR_FREQ returns a monitor's last target_freq + START_TIMER / STOP_TIMER: resume / suspend the loop above + +MEMLAT: Supported memory buses +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The hw_type field carried in most payloads identifies the memory group: + ++----------+--------------------------------------------------------------+ +|hw_type |Group | ++----------+--------------------------------------------------------------+ +|0 |DDR | ++----------+--------------------------------------------------------------+ +|1 |LLCC | ++----------+--------------------------------------------------------------+ +|2 |DDR_QOS_COMPUTE | ++----------+--------------------------------------------------------------+ +|3 |DDR_QOS_MOBILE | ++----------+--------------------------------------------------------------+ + +All multi-byte fields below are little-endian. mon_idx selects a monitor +within the group (0-based, less than the firmware-supported maximum). All +SET commands return the SCMI status word; on success it carries SUCCESS, on +lookup failure INVALID_PARAMETERS, and on an unknown param_id NOT_SUPPORTED. + +Frequency units are not uniform across commands (kHz, MHz or a raw 0/1 +DDR_QOS level, depending on the param_id); each command documents its own +units below. + +MEMLAT_SET_MEM_GROUP +~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x10 (16) +command: QCOM_SCMI_SET_PARAM + +Allocates a new memory group on the firmware side and binds it to the +underlying interconnect path (DDR / LLCC / DDR_QOS). + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 cpumask |Bitmask of HW CPU IDs that contribute counters to this | +| |group (limited to 32 CPUs). | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier (0 = DDR, 1 = LLCC, | +| |2 = DDR_QOS_COMPUTE, 3 = DDR_QOS_MOBILE). | ++------------------+-----------------------------------------------------------+ +|uint32 mon_type |Reserved for SET_MEM_GROUP (set to 0; populated only on | +| |SET_MONITOR). | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Reserved for SET_MEM_GROUP (set to 0). | ++------------------+-----------------------------------------------------------+ +|char mon_name[20] |Reserved for SET_MEM_GROUP (zero-filled). | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS: group allocated. | +| |BUSY: no free memory group slot (the firmware-supported | +| |maximum number of groups is already configured). | ++------------------+-----------------------------------------------------------+ + +MEMLAT_SET_MONITOR +~~~~~~~~~~~~~~~~~~ + +param_id: 0x11 (17) +command: QCOM_SCMI_SET_PARAM + +Adds a monitor (a CPU subset that votes within an already-configured +group). + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 cpumask |Bitmask of HW CPU IDs assigned to this monitor (must be a | +| |subset of the group's cpumask; limited to 32 CPUs). | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier the monitor belongs to. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_type |0 = IPM-based latency monitor, 1 = compute (passive | +| |governor tracking cpufreq map irrespective of IPM) monitor | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Index of the monitor within the group. | ++------------------+-----------------------------------------------------------+ +|char mon_name[20] |Human-readable monitor name (NUL-terminated, used in | +| |firmware log lines). | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS: monitor created. | +| |NOT_FOUND: hw_type does not match any configured group, or | +| |the firmware-supported maximum number of monitors already | +| |exist for the group. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_SET_COMMON_EV_MAP +~~~~~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x12 (18) +command: QCOM_SCMI_SET_PARAM + +Configures the common counter IDs (instructions, cycles, stall, etc.) +that the firmware reads on every sample for every CPU. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 num_evs |Number of valid entries in cid[]. | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Set to 0xFF (sentinel for the common-events case). | ++------------------+-----------------------------------------------------------+ +|uint8 cid[] |Array of CPUCP counter IDs indexed by INST/CYC/CONST_CYC/ | +| |FE_STALL/BE_STALL. 0xFF marks an unused slot. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if num_evs exceeds the | +| |firmware-supported maximum. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_SET_GRP_EV_MAP +~~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x13 (19) +command: QCOM_SCMI_SET_PARAM + +Configures the per-group event IDs (cache miss / writeback / access) +used by the IPM and write-back computations for the selected hw_type. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 num_evs |Number of valid entries in cid[]. | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint8 cid[] |Array of CPUCP counter IDs indexed by MISS/WB/ACC. 0xFF | +| |marks an unused slot. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if hw_type is unknown or | +| |num_evs exceeds the firmware-supported maximum. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_ADAPTIVE_LOW_FREQ +~~~~~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x14 (20) +command: QCOM_SCMI_SET_PARAM + +Sets the adaptive low-frequency floor for a group. When the algorithm's +voted frequency falls below this floor the firmware clamps it up to the +adaptive floor instead. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Ignored (group-scoped parameter). | ++------------------+-----------------------------------------------------------+ +|uint32 val |Adaptive low frequency in kHz (converted to MHz by the | +| |firmware). | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if hw_type does not match a | +| |configured group. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_ADAPTIVE_HIGH_FREQ +~~~~~~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x15 (21) +command: QCOM_SCMI_SET_PARAM + +Sets the adaptive high-frequency floor for a group. Units and behaviour +mirror MEMLAT_ADAPTIVE_LOW_FREQ. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Ignored (group-scoped parameter). | ++------------------+-----------------------------------------------------------+ +|uint32 val |Adaptive high frequency in kHz (converted to MHz by the | +| |firmware). | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if hw_type does not match a | +| |configured group. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_GET_ADAPTIVE_CUR_FREQ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x16 (22) +command: QCOM_SCMI_GET_PARAM + +Reads the group's current adaptive frequency. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if hw_type does not match a | +| |configured group. | ++------------------+-----------------------------------------------------------+ +|uint32 cur_freq |Current adaptive frequency in kHz. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_IPM_CEIL +~~~~~~~~~~~~~~~ + +param_id: 0x17 (23) +command: QCOM_SCMI_SET_PARAM + +Sets the IPM (Instructions-Per-Miss) ceiling for a monitor. CPUs whose +IPM falls at or below this ceiling are considered memory-bound and +contribute their cpufreq into the monitor's voting pool. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|uint32 val |IPM ceiling (instructions per cache miss). | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) does | +| |not match a registered monitor. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_FE_STALL_FLOOR +~~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x18 (24) +command: QCOM_SCMI_SET_PARAM + +Sets the front-end stall floor (in percent) for a monitor. Analogous to +MEMLAT_BE_STALL_FLOOR but for front-end stalls. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|uint32 val |Front-end stall floor in percent (0..100). | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) does | +| |not match a registered monitor. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_BE_STALL_FLOOR +~~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x19 (25) +command: QCOM_SCMI_SET_PARAM + +Sets the back-end stall floor (in percent) for a monitor. CPUs whose +back-end stall percentage is at or above this floor are eligible to have +their cpufreq scaled up by the freq-scale knobs below. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|uint32 val |Back-end stall floor in percent (0..100). | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) does | +| |not match a registered monitor. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_WB_PCT +~~~~~~~~~~~~~ + +param_id: 0x1A (26) +command: QCOM_SCMI_SET_PARAM + +Sets the write-back ratio threshold (in percent) for a monitor. A CPU's +write-back ratio must be at or above this value for the monitor to treat +it as memory-bound. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|uint32 val |Write-back ratio threshold in percent. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) does | +| |not match a registered monitor. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_IPM_FILTER +~~~~~~~~~~~~~~~~~ + +param_id: 0x1B (27) +command: QCOM_SCMI_SET_PARAM + +Sets the IPM filter for a monitor. A CPU's IPM must be at or below this +value (in addition to the write-back check) for the monitor to select it. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|uint32 val |IPM filter (instructions per cache miss). | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) does | +| |not match a registered monitor. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_FREQ_SCALE_PCT +~~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x1C (28) +command: QCOM_SCMI_SET_PARAM + +Sets the frequency-scale percentage for a monitor. When non-zero, a +memory-bound CPU's effective frequency is boosted proportionally to how +far its IPM is below the ceiling, bounded by the scale floor/ceiling +below. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|uint32 val |Frequency-scale factor in percent. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) does | +| |not match a registered monitor. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_FREQ_SCALE_CEIL_MHZ +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x1D (29) +command: QCOM_SCMI_SET_PARAM + +Sets the upper cpufreq bound (in MHz) for the freq-scale boost above. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|uint32 val |Frequency-scale ceiling in MHz. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) does | +| |not match a registered monitor. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_FREQ_SCALE_FLOOR_MHZ +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x1E (30) +command: QCOM_SCMI_SET_PARAM + +Sets the lower cpufreq bound (in MHz) for the freq-scale boost above. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|uint32 val |Frequency-scale floor in MHz. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) does | +| |not match a registered monitor. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_SAMPLE_MS +~~~~~~~~~~~~~~~~ + +param_id: 0x1F (31) +command: QCOM_SCMI_SET_PARAM + +Sets the sampling period (in milliseconds) used by the firmware update +loop. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|int32 sample_ms |Sampling period in milliseconds. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_MON_FREQ_MAP +~~~~~~~~~~~~~~~~~~~ + +param_id: 0x20 (32) +command: QCOM_SCMI_SET_PARAM + +Programs the cpufreq to memfreq voting table for a single monitor. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|uint32 nr_rows |Number of valid rows in tbl[] (must not exceed the | +| |firmware-supported maximum). | ++------------------+-----------------------------------------------------------+ +|struct { |Per-row mapping. cpu_freq_mhz is the cpufreq trigger in | +|u16 cpu_freq_mhz; |MHz; mem_freq_mhz is the resulting memfreq vote (MHz for | +|u16 mem_freq_mhz; |DDR/LLCC, a level index 0/1 for DDR_QOS). | +|} tbl[] | | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) is | +| |unknown / OUT_OF_RANGE if nr_rows exceeds the | +| |firmware-supported maximum. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_SET_MIN_FREQ +~~~~~~~~~~~~~~~~~~~ + +param_id: 0x21 (33) +command: QCOM_SCMI_SET_PARAM + +Clamps a monitor's vote to a minimum value. Units are kHz for DDR/LLCC and +raw level index for DDR_QOS. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|uint32 val |Minimum frequency: kHz for DDR/LLCC, level for DDR_QOS. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) does | +| |not match a registered monitor. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_SET_MAX_FREQ +~~~~~~~~~~~~~~~~~~~ + +param_id: 0x22 (34) +command: QCOM_SCMI_SET_PARAM + +Clamps a monitor's vote to a maximum value. Units identical to +MEMLAT_SET_MIN_FREQ. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|uint32 val |Maximum frequency: kHz for DDR/LLCC, level for DDR_QOS. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) does | +| |not match a registered monitor. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_GET_CUR_FREQ +~~~~~~~~~~~~~~~~~~~ + +param_id: 0x23 (35) +command: QCOM_SCMI_GET_PARAM + +Reads the current target frequency that the firmware is voting for the +selected (hw_type, mon_idx) tuple. The response payload is returned in +the same buffer used to send the request, overwriting it on success. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|uint32 hw_type |Memory group identifier. | ++------------------+-----------------------------------------------------------+ +|uint32 mon_idx |Monitor index within the group. | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if (hw_type, mon_idx) does | +| |not match a registered monitor. | ++------------------+-----------------------------------------------------------+ +|uint32 cur_freq |Current target frequency in kHz for DDR/LLCC; raw level | +| |(0/1) for DDR_QOS. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_START_TIMER +~~~~~~~~~~~~~~~~~~ + +param_id: 0x24 (36) +command: QCOM_SCMI_START_ACTIVITY + +Starts the firmware sampling and voting loop at the configured +sample_ms interval. Has no payload beyond the QCOM_SCMI_START_ACTIVITY +header. + ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS: timer started (or was already running). | +| |GENERIC_ERROR: events not yet initialized | +| |(MEMLAT_SET_GRP_EV_MAP not called for any group). | +| |NOT_SUPPORTED: invalid param_id under START_ACTIVITY. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_STOP_TIMER +~~~~~~~~~~~~~~~~~ + +param_id: 0x25 (37) +command: QCOM_SCMI_STOP_ACTIVITY + +Suspends the firmware sampling and voting loop. Has no payload beyond +the QCOM_SCMI_STOP_ACTIVITY header. The configured monitors and freq +maps are retained, so a subsequent MEMLAT_START_TIMER resumes voting +without re-programming. + ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS: timer stopped (or was already stopped). | +| |NOT_SUPPORTED: invalid param_id under STOP_ACTIVITY. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_GET_TIMESTAMP +~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x26 (38) +command: QCOM_SCMI_GET_PARAM + +Reads the firmware timestamp (nanoseconds). + ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS. | ++------------------+-----------------------------------------------------------+ +|uint64 tstamp |Firmware timestamp in nanoseconds. | ++------------------+-----------------------------------------------------------+ + +MEMLAT_SET_EFFECTIVE_FREQ_METHOD +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +param_id: 0x27 (39) +command: QCOM_SCMI_SET_PARAM + +Selects the algorithm used to derive the per-CPU effective frequency +from the cycle counters. + ++------------------+-----------------------------------------------------------+ +|Parameters | ++------------------+-----------------------------------------------------------+ +|Name |Description | ++------------------+-----------------------------------------------------------+ +|int32 method |0: const-cycles method (CPU cycles / const-cycles, scaled | +| |by the cluster's max frequency). | +| |1: legacy method (CPU cycles / sampling-window time). | ++------------------+-----------------------------------------------------------+ +|Return values | ++------------------+-----------------------------------------------------------+ +|int32 status |SUCCESS / INVALID_PARAMETERS if method is not 0 or 1. | ++------------------+-----------------------------------------------------------+ From 98ffc6a03cdeaac68d396f193244aef4fad2bbee Mon Sep 17 00:00:00 2001 From: Pragnesh Papaniya Date: Thu, 4 Jun 2026 19:26:21 +0530 Subject: [PATCH 0478/1133] FROMLIST: dt-bindings: firmware: arm,scmi: Add Qualcomm Generic Extension Protocol Add the binding schema for the SCMI Qualcomm Generic Extension Protocol which helps support Bus DVFS on Glymur/Mahua/Hamoa/Purwa/Kaanapali SoCs. Co-developed-by: Sibi Sankar Signed-off-by: Sibi Sankar Signed-off-by: Pragnesh Papaniya Link: https://lore.kernel.org/lkml/20260724-rfc_v8_scmi_memlat-v1-2-cb732bcff1f4@oss.qualcomm.com/ --- .../bindings/firmware/arm,scmi.yaml | 1 + .../bindings/firmware/qcom,generic-scmi.yaml | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 Documentation/devicetree/bindings/firmware/qcom,generic-scmi.yaml diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml index 6fc44105f1c37..85f06a6a74520 100644 --- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml +++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml @@ -24,6 +24,7 @@ description: | anyOf: - $ref: /schemas/firmware/nxp,imx95-scmi.yaml + - $ref: /schemas/firmware/qcom,generic-scmi.yaml properties: $nodename: diff --git a/Documentation/devicetree/bindings/firmware/qcom,generic-scmi.yaml b/Documentation/devicetree/bindings/firmware/qcom,generic-scmi.yaml new file mode 100644 index 0000000000000..a50e5e8fdcccc --- /dev/null +++ b/Documentation/devicetree/bindings/firmware/qcom,generic-scmi.yaml @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/firmware/qcom,generic-scmi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: System Control and Management Interface (SCMI) Qualcomm Generic Extension Protocol + +maintainers: + - Pragnesh Papaniya + - Sibi Sankar + +properties: + protocol@80: + description: + SCMI Qualcomm Generic Extension Protocol exposes Qualcomm SoC specific + algorithms such as Memory Latency (MEMLAT) bound DDR/LLCC/DDR-QOS bus DVFS. + The algorithm runs on the SCP, it can be turned on/off and be configured + through a pairing of algorithm strings with an immutable list param_ids. + $ref: '/schemas/firmware/arm,scmi.yaml#/$defs/protocol-node' + unevaluatedProperties: false + + properties: + reg: + const: 0x80 + +additionalProperties: true From cf3fdc472447440eb254d55474d60f590566a2d7 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 4 Jun 2026 19:26:22 +0530 Subject: [PATCH 0479/1133] FROMLIST: firmware: arm_scmi: vendors: Add QCOM SCMI Generic Extensions The System Control Management Interface (SCMI) Qualcomm Generic Extension Protocol consists of a small set of generic SET/GET/ START/STOP commands, which is used to turn on/off and configure Qualcomm SoC specific algorithms that run on the SCP. Co-developed-by: Amir Vajid Signed-off-by: Amir Vajid Co-developed-by: Ramakrishna Gottimukkula Signed-off-by: Ramakrishna Gottimukkula Signed-off-by: Sibi Sankar Co-developed-by: Pragnesh Papaniya Signed-off-by: Pragnesh Papaniya Link: https://lore.kernel.org/lkml/20260724-rfc_v8_scmi_memlat-v1-3-cb732bcff1f4@oss.qualcomm.com/ --- MAINTAINERS | 10 + drivers/firmware/arm_scmi/Kconfig | 1 + drivers/firmware/arm_scmi/Makefile | 1 + .../firmware/arm_scmi/vendors/qcom/Kconfig | 15 ++ .../firmware/arm_scmi/vendors/qcom/Makefile | 2 + .../arm_scmi/vendors/qcom/qcom-generic-ext.c | 183 ++++++++++++++++++ include/linux/scmi_qcom_protocol.h | 37 ++++ 7 files changed, 249 insertions(+) create mode 100644 drivers/firmware/arm_scmi/vendors/qcom/Kconfig create mode 100644 drivers/firmware/arm_scmi/vendors/qcom/Makefile create mode 100644 drivers/firmware/arm_scmi/vendors/qcom/qcom-generic-ext.c create mode 100644 include/linux/scmi_qcom_protocol.h diff --git a/MAINTAINERS b/MAINTAINERS index 93abbb315065d..4dfc61cda402b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -27284,6 +27284,16 @@ S: Maintained F: Documentation/devicetree/bindings/firmware/nxp,*scmi.yaml F: drivers/firmware/arm_scmi/vendors/imx/ +SYSTEM CONTROL MANAGEMENT INTERFACE (SCMI) Qualcomm Generic Extension Protocol driver +M: Pragnesh Papaniya +M: Sibi Sankar +L: arm-scmi@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/firmware/qcom,generic-scmi.yaml +F: drivers/firmware/arm_scmi/vendors/qcom/ +F: include/linux/scmi_qcom_protocol.h + SYSTEM RESET/SHUTDOWN DRIVERS M: Sebastian Reichel L: linux-pm@vger.kernel.org diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig index 783c24a20e291..3918aa2e7140a 100644 --- a/drivers/firmware/arm_scmi/Kconfig +++ b/drivers/firmware/arm_scmi/Kconfig @@ -84,6 +84,7 @@ config ARM_SCMI_QUIRKS source "drivers/firmware/arm_scmi/transports/Kconfig" source "drivers/firmware/arm_scmi/vendors/imx/Kconfig" +source "drivers/firmware/arm_scmi/vendors/qcom/Kconfig" endif #ARM_SCMI_PROTOCOL diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index 780cd62b2f78a..5a0e003c2477a 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -13,6 +13,7 @@ scmi-module-objs := $(scmi-driver-y) $(scmi-protocols-y) $(scmi-transport-y) obj-$(CONFIG_ARM_SCMI_PROTOCOL) += transports/ obj-$(CONFIG_ARM_SCMI_PROTOCOL) += vendors/imx/ +obj-$(CONFIG_ARM_SCMI_PROTOCOL) += vendors/qcom/ obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-core.o obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o diff --git a/drivers/firmware/arm_scmi/vendors/qcom/Kconfig b/drivers/firmware/arm_scmi/vendors/qcom/Kconfig new file mode 100644 index 0000000000000..8aa0efd6a03d0 --- /dev/null +++ b/drivers/firmware/arm_scmi/vendors/qcom/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only +menu "ARM SCMI QCOM Vendor Protocols" + +config QCOM_SCMI_GENERIC_EXT + tristate "Qualcomm Technologies, Inc. SCMI Generic Vendor Protocol" + depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF) + help + The QCOM SCMI vendor protocol provides a generic way of exposing + a number of Qualcomm SoC specific features (like memory bus scaling) + through a mixture of pre-determined algorithm strings and param_id + pairs hosted on the SCMI controller. + + This driver defines/documents the message IDs used for this + communication and also exposes the operations used by the clients. +endmenu diff --git a/drivers/firmware/arm_scmi/vendors/qcom/Makefile b/drivers/firmware/arm_scmi/vendors/qcom/Makefile new file mode 100644 index 0000000000000..6b98fabbebb86 --- /dev/null +++ b/drivers/firmware/arm_scmi/vendors/qcom/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_QCOM_SCMI_GENERIC_EXT) += qcom-generic-ext.o diff --git a/drivers/firmware/arm_scmi/vendors/qcom/qcom-generic-ext.c b/drivers/firmware/arm_scmi/vendors/qcom/qcom-generic-ext.c new file mode 100644 index 0000000000000..7ca920c8da059 --- /dev/null +++ b/drivers/firmware/arm_scmi/vendors/qcom/qcom-generic-ext.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include + +#include "../../common.h" + +/* + * This protocol is intended as a generic way of exposing a number of Qualcomm + * SoC specific features through a mixture of pre-determined algorithm string + * and param_id pairs hosted on the SCMI controller. + * + * The QCOM SCMI Vendor Protocol has the protocol id as 0x80 and vendor id set + * to Qualcomm and the supported version is set to 0x10000. The PROTOCOL_VERSION + * command returns version 1.0. + */ + +/** + * enum qcom_generic_ext_protocol_cmd - vendor specific commands supported by SCMI Qualcomm + * generic vendor protocol. + * + * @QCOM_SCMI_SET_PARAM: is used to set the parameter of a specific algo_str hosted on + * QCOM SCMI Vendor Protocol. The tx len depends on the algo_str used. + * @QCOM_SCMI_GET_PARAM: is used to get parameter information of a specific algo_str + * hosted on QCOM SCMI Vendor Protocol. The tx and rx len depends + * on the algo_str used. + * @QCOM_SCMI_START_ACTIVITY: is used to start the activity performed by the algo_str. + * @QCOM_SCMI_STOP_ACTIVITY: is used to stop a pre-existing activity performed by the algo_str. + */ +enum qcom_generic_ext_protocol_cmd { + QCOM_SCMI_SET_PARAM = 0x10, + QCOM_SCMI_GET_PARAM = 0x11, + QCOM_SCMI_START_ACTIVITY = 0x12, + QCOM_SCMI_STOP_ACTIVITY = 0x13, +}; + +/** + * struct qcom_scmi_msg - represents the various parameters to be populated + * for using the QCOM SCMI Vendor Protocol + * + * @ext_id: reserved, must be zero + * @algo_low: lower 32 bits of the algo_str + * @algo_high: upper 32 bits of the algo_str + * @param_id: serves as token message id to the specific algo_str + * @buf: serves as the payload to the specified param_id and algo_str pair + */ +struct qcom_scmi_msg { + __le32 ext_id; + __le32 algo_low; + __le32 algo_high; + __le32 param_id; + __le32 buf[]; +}; + +/* + * The firmware only implements a handful of algorithm strings. Keep an + * allowlist so a client cannot push an unsupported (or garbage) string to + * the firmware; extend it as new algorithms are added. + */ +static const u64 qcom_scmi_algo_str[] = { + 0x4d454d4c4154ULL, /* "MEMLAT" */ +}; + +static bool qcom_scmi_algo_str_valid(u64 algo_str) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(qcom_scmi_algo_str); i++) + if (algo_str == qcom_scmi_algo_str[i]) + return true; + + return false; +} + +static int qcom_scmi_common_xfer(const struct scmi_protocol_handle *ph, + enum qcom_generic_ext_protocol_cmd cmd_id, void *buf, + size_t buf_len, u64 algo_str, u32 param_id, size_t rx_size) +{ + struct scmi_xfer *t; + struct qcom_scmi_msg *msg; + int ret; + + if (!qcom_scmi_algo_str_valid(algo_str)) + return -EINVAL; + + /* Reject calls where rx_size exceeds buf_len. */ + if (rx_size > buf_len) + return -EINVAL; + + ret = ph->xops->xfer_get_init(ph, cmd_id, buf_len + sizeof(*msg), rx_size, &t); + if (ret) + return ret; + + msg = t->tx.buf; + msg->ext_id = 0; + msg->algo_low = cpu_to_le32(lower_32_bits(algo_str)); + msg->algo_high = cpu_to_le32(upper_32_bits(algo_str)); + msg->param_id = cpu_to_le32(param_id); + if (buf_len) + memcpy(msg->buf, buf, buf_len); + + ret = ph->xops->do_xfer(ph, t); + if (!ret && rx_size) { + /* + * The response is returned into the caller's @buf, replacing + * the tx payload. Bound the copy to the caller's buffer since + * t->rx.len is reported by the firmware, and require at least + * the expected rx_size so the caller never reads stale tx data. + */ + if (t->rx.len < rx_size || t->rx.len > buf_len) + ret = -EPROTO; + else + memcpy(buf, t->rx.buf, rx_size); + } + ph->xops->xfer_put(ph, t); + + return ret; +} + +static int qcom_scmi_set_param(const struct scmi_protocol_handle *ph, void *buf, size_t buf_len, + u64 algo_str, u32 param_id) +{ + return qcom_scmi_common_xfer(ph, QCOM_SCMI_SET_PARAM, buf, buf_len, algo_str, + param_id, 0); +} + +static int qcom_scmi_get_param(const struct scmi_protocol_handle *ph, void *buf, size_t buf_len, + u64 algo_str, u32 param_id, size_t rx_size) +{ + return qcom_scmi_common_xfer(ph, QCOM_SCMI_GET_PARAM, buf, buf_len, algo_str, + param_id, rx_size); +} + +static int qcom_scmi_start_activity(const struct scmi_protocol_handle *ph, void *buf, + size_t buf_len, u64 algo_str, u32 param_id) +{ + return qcom_scmi_common_xfer(ph, QCOM_SCMI_START_ACTIVITY, buf, buf_len, algo_str, + param_id, 0); +} + +static int qcom_scmi_stop_activity(const struct scmi_protocol_handle *ph, void *buf, + size_t buf_len, u64 algo_str, u32 param_id) +{ + return qcom_scmi_common_xfer(ph, QCOM_SCMI_STOP_ACTIVITY, buf, buf_len, algo_str, + param_id, 0); +} + +static const struct qcom_generic_ext_ops qcom_proto_ops = { + .set_param = qcom_scmi_set_param, + .get_param = qcom_scmi_get_param, + .start_activity = qcom_scmi_start_activity, + .stop_activity = qcom_scmi_stop_activity, +}; + +static int qcom_generic_ext_protocol_init(const struct scmi_protocol_handle *ph) +{ + dev_dbg(ph->dev, "QCOM Generic Vendor Version %d.%d\n", + PROTOCOL_REV_MAJOR(ph->version), PROTOCOL_REV_MINOR(ph->version)); + + return 0; +} + +static const struct scmi_protocol qcom_generic_ext = { + .id = SCMI_PROTOCOL_QCOM_GENERIC, + .owner = THIS_MODULE, + .instance_init = &qcom_generic_ext_protocol_init, + .ops = &qcom_proto_ops, + .vendor_id = "Qualcomm", + .supported_version = 0x10000, +}; +module_scmi_protocol(qcom_generic_ext); + +MODULE_ALIAS("scmi-protocol-" __stringify(SCMI_PROTOCOL_QCOM_GENERIC) "-Qualcomm"); +MODULE_AUTHOR("Pragnesh Papaniya "); +MODULE_AUTHOR("Sibi Sankar "); +MODULE_DESCRIPTION("QCOM SCMI Generic Vendor Protocol"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/scmi_qcom_protocol.h b/include/linux/scmi_qcom_protocol.h new file mode 100644 index 0000000000000..41632ee7bbc7a --- /dev/null +++ b/include/linux/scmi_qcom_protocol.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * SCMI Message Protocol driver QCOM extension header + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _LINUX_SCMI_QCOM_PROTOCOL_H +#define _LINUX_SCMI_QCOM_PROTOCOL_H + +#include + +#define SCMI_PROTOCOL_QCOM_GENERIC 0x80 + +struct scmi_protocol_handle; + +/** + * struct qcom_generic_ext_ops - represents the various operations provided + * by QCOM Generic Vendor Protocol + * + * @set_param: set parameter specified by param_id and algo_str pair. + * @get_param: retrieve parameter specified by param_id and algo_str pair. + * @start_activity: initiate a specific activity defined by algo_str. + * @stop_activity: halt previously initiated activity defined by algo_str. + */ +struct qcom_generic_ext_ops { + int (*set_param)(const struct scmi_protocol_handle *ph, void *buf, size_t buf_len, + u64 algo_str, u32 param_id); + int (*get_param)(const struct scmi_protocol_handle *ph, void *buf, size_t buf_len, + u64 algo_str, u32 param_id, size_t rx_size); + int (*start_activity)(const struct scmi_protocol_handle *ph, void *buf, size_t buf_len, + u64 algo_str, u32 param_id); + int (*stop_activity)(const struct scmi_protocol_handle *ph, void *buf, size_t buf_len, + u64 algo_str, u32 param_id); +}; + +#endif /* _LINUX_SCMI_QCOM_PROTOCOL_H */ From 2c937f7f127dd3191949afac996a264a2908ecc3 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 4 Jun 2026 19:26:23 +0530 Subject: [PATCH 0480/1133] FROMLIST: PM / devfreq: Add new target_freq attribute flag for governors The target_freq sysfs attribute exposes a governor's predicted next target frequency. Not every devfreq governor has a meaningful value to report there; some merely observe an externally-driven device. Add a DEVFREQ_GOV_ATTR_TARGET_FREQ attribute flag that governors with a meaningful target frequency must opt in to. Gate the existing target_freq sysfs read on the flag and return -EINVAL when the active governor does not advertise it. Tag all in-tree governors so visible behaviour stays unchanged for in-tree users. Out-of-tree governors that drive frequency updates and want to keep target_freq readable need to set the new flag. Signed-off-by: Sibi Sankar Co-developed-by: Pragnesh Papaniya Signed-off-by: Pragnesh Papaniya Link: https://lore.kernel.org/lkml/20260724-rfc_v8_scmi_memlat-v1-4-cb732bcff1f4@oss.qualcomm.com/ --- Documentation/ABI/testing/sysfs-class-devfreq | 8 ++++++++ drivers/devfreq/devfreq.c | 6 ++++++ drivers/devfreq/governor_passive.c | 1 + drivers/devfreq/governor_performance.c | 1 + drivers/devfreq/governor_powersave.c | 1 + drivers/devfreq/governor_simpleondemand.c | 1 + drivers/devfreq/governor_userspace.c | 1 + drivers/devfreq/hisi_uncore_freq.c | 1 + drivers/devfreq/tegra30-devfreq.c | 3 ++- include/linux/devfreq-governor.h | 3 +++ 10 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq index df8ba88b9f6ae..5be9940a58532 100644 --- a/Documentation/ABI/testing/sysfs-class-devfreq +++ b/Documentation/ABI/testing/sysfs-class-devfreq @@ -37,6 +37,14 @@ Description: The /sys/class/devfreq/.../target_freq shows the next governor predicted target frequency of the corresponding devfreq object. + Reading this attribute returns -EINVAL when the active + governor does not advertise DEVFREQ_GOV_ATTR_TARGET_FREQ. + All in-tree governors that drive frequency transitions tag + this attribute, so existing in-tree behaviour is unchanged. + Out-of-tree governors that previously relied on the + unconditional read of df->previous_freq must opt in by + setting DEVFREQ_GOV_ATTR_TARGET_FREQ in their attrs field. + What: /sys/class/devfreq/.../trans_stat Date: October 2012 Contact: MyungJoo Ham diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 82dd9a43dc621..398cbf2a6fb3e 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -1562,6 +1562,12 @@ static ssize_t target_freq_show(struct device *dev, { struct devfreq *df = to_devfreq(dev); + guard(mutex)(&devfreq_list_lock); + + if (!df->profile || !df->governor || + !IS_SUPPORTED_ATTR(df->governor->attrs, TARGET_FREQ)) + return -EINVAL; + return sprintf(buf, "%lu\n", df->previous_freq); } static DEVICE_ATTR_RO(target_freq); diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c index d7feecd900f1d..b75e4bbee4b13 100644 --- a/drivers/devfreq/governor_passive.c +++ b/drivers/devfreq/governor_passive.c @@ -448,6 +448,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq, static struct devfreq_governor devfreq_passive = { .name = DEVFREQ_GOV_PASSIVE, + .attrs = DEVFREQ_GOV_ATTR_TARGET_FREQ, .flags = DEVFREQ_GOV_FLAG_IMMUTABLE, .get_target_freq = devfreq_passive_get_target_freq, .event_handler = devfreq_passive_event_handler, diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c index fdb22bf512cf1..b9ec587f582cc 100644 --- a/drivers/devfreq/governor_performance.c +++ b/drivers/devfreq/governor_performance.c @@ -37,6 +37,7 @@ static int devfreq_performance_handler(struct devfreq *devfreq, static struct devfreq_governor devfreq_performance = { .name = DEVFREQ_GOV_PERFORMANCE, + .attrs = DEVFREQ_GOV_ATTR_TARGET_FREQ, .get_target_freq = devfreq_performance_func, .event_handler = devfreq_performance_handler, }; diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c index ee2d6ec8a5122..69eab1d0a7fcc 100644 --- a/drivers/devfreq/governor_powersave.c +++ b/drivers/devfreq/governor_powersave.c @@ -37,6 +37,7 @@ static int devfreq_powersave_handler(struct devfreq *devfreq, static struct devfreq_governor devfreq_powersave = { .name = DEVFREQ_GOV_POWERSAVE, + .attrs = DEVFREQ_GOV_ATTR_TARGET_FREQ, .get_target_freq = devfreq_powersave_func, .event_handler = devfreq_powersave_handler, }; diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c index ac9c5e9e51a49..65ff9d912ef9c 100644 --- a/drivers/devfreq/governor_simpleondemand.c +++ b/drivers/devfreq/governor_simpleondemand.c @@ -118,6 +118,7 @@ static int devfreq_simple_ondemand_handler(struct devfreq *devfreq, static struct devfreq_governor devfreq_simple_ondemand = { .name = DEVFREQ_GOV_SIMPLE_ONDEMAND, .attrs = DEVFREQ_GOV_ATTR_POLLING_INTERVAL + | DEVFREQ_GOV_ATTR_TARGET_FREQ | DEVFREQ_GOV_ATTR_TIMER, .get_target_freq = devfreq_simple_ondemand_func, .event_handler = devfreq_simple_ondemand_handler, diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c index 3906ebedbae84..d1b765a7b8e56 100644 --- a/drivers/devfreq/governor_userspace.c +++ b/drivers/devfreq/governor_userspace.c @@ -135,6 +135,7 @@ static int devfreq_userspace_handler(struct devfreq *devfreq, static struct devfreq_governor devfreq_userspace = { .name = DEVFREQ_GOV_USERSPACE, + .attrs = DEVFREQ_GOV_ATTR_TARGET_FREQ, .get_target_freq = devfreq_userspace_func, .event_handler = devfreq_userspace_handler, }; diff --git a/drivers/devfreq/hisi_uncore_freq.c b/drivers/devfreq/hisi_uncore_freq.c index ac55641b0259a..1e67f7547e043 100644 --- a/drivers/devfreq/hisi_uncore_freq.c +++ b/drivers/devfreq/hisi_uncore_freq.c @@ -398,6 +398,7 @@ static struct devfreq_governor hisi_platform_governor = { * Set interrupt_driven to skip the devfreq monitor mechanism, though * this governor is not interrupt-driven. */ + .attrs = DEVFREQ_GOV_ATTR_TARGET_FREQ, .flags = DEVFREQ_GOV_FLAG_IRQ_DRIVEN, .get_target_freq = hisi_platform_gov_func, .event_handler = hisi_platform_gov_handler, diff --git a/drivers/devfreq/tegra30-devfreq.c b/drivers/devfreq/tegra30-devfreq.c index 401aac6a9f07e..fcb278c4a74c9 100644 --- a/drivers/devfreq/tegra30-devfreq.c +++ b/drivers/devfreq/tegra30-devfreq.c @@ -776,7 +776,8 @@ static int tegra_governor_event_handler(struct devfreq *devfreq, static struct devfreq_governor tegra_devfreq_governor = { .name = "tegra_actmon", - .attrs = DEVFREQ_GOV_ATTR_POLLING_INTERVAL, + .attrs = DEVFREQ_GOV_ATTR_POLLING_INTERVAL + | DEVFREQ_GOV_ATTR_TARGET_FREQ, .flags = DEVFREQ_GOV_FLAG_IMMUTABLE | DEVFREQ_GOV_FLAG_IRQ_DRIVEN, .get_target_freq = tegra_governor_get_target, diff --git a/include/linux/devfreq-governor.h b/include/linux/devfreq-governor.h index dfdd0160a29f3..2853f571dfdf7 100644 --- a/include/linux/devfreq-governor.h +++ b/include/linux/devfreq-governor.h @@ -43,9 +43,12 @@ * : Indicate polling_interval sysfs attribute * - DEVFREQ_GOV_ATTR_TIMER * : Indicate timer sysfs attribute + * - DEVFREQ_GOV_ATTR_TARGET_FREQ + * : Indicate the target freq sysfs attribute */ #define DEVFREQ_GOV_ATTR_POLLING_INTERVAL BIT(0) #define DEVFREQ_GOV_ATTR_TIMER BIT(1) +#define DEVFREQ_GOV_ATTR_TARGET_FREQ BIT(2) /** * struct devfreq_governor - Devfreq policy governor From 6abfd20a61759a700104639d783daa20ce09f4de Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 4 Jun 2026 19:26:24 +0530 Subject: [PATCH 0481/1133] FROMLIST: PM / devfreq: Add new track_remote flag for governors Some devfreq governors need to track frequency changes performed on remote devices rather than driving the frequency updates themselves. In such cases, the device's frequency is already updated by an external entity and devfreq only needs to keep its transition statistics and notifier subscribers in sync. Add a new DEVFREQ_GOV_FLAG_TRACK_REMOTE governor flag. When set, devfreq_set_target() skips the profile->target() update sequence but still emits the DEVFREQ_PRECHANGE/DEVFREQ_POSTCHANGE notification pair and the devfreq_frequency trace event, so transition-notifier subscribers (passive governor, devfreq cooling, etc.) and tracing observe the remote frequency change exactly as they would on the normal path, and the transition statistics are refreshed. Signed-off-by: Sibi Sankar Co-developed-by: Pragnesh Papaniya Signed-off-by: Pragnesh Papaniya Link: https://lore.kernel.org/lkml/20260724-rfc_v8_scmi_memlat-v1-5-cb732bcff1f4@oss.qualcomm.com/ --- drivers/devfreq/devfreq.c | 21 +++++++++++++++++++++ include/linux/devfreq-governor.h | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 398cbf2a6fb3e..216c126004d2f 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -348,6 +348,26 @@ static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq, unsigned long cur_freq; int err = 0; + /* + * When a remote agent (e.g. firmware) owns the frequency, skip the + * local profile->target() call. Still emit the PRECHANGE/POSTCHANGE + * pair and the trace event so that transition-notifier subscribers + * (passive governor, devfreq cooling, etc.) and tracing observe the + * frequency change exactly as they would on the normal path. + */ + if (devfreq->governor && + IS_SUPPORTED_FLAG(devfreq->governor->flags, TRACK_REMOTE)) { + freqs.old = devfreq->previous_freq; + freqs.new = new_freq; + devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE); + + if (trace_devfreq_frequency_enabled() && new_freq != freqs.old) + trace_devfreq_frequency(devfreq, new_freq, freqs.old); + + devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE); + goto update_status; + } + if (devfreq->profile->get_cur_freq) devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq); else @@ -375,6 +395,7 @@ static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq, freqs.new = new_freq; devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE); +update_status: if (devfreq_update_status(devfreq, new_freq)) dev_warn(&devfreq->dev, "Couldn't update frequency transition information.\n"); diff --git a/include/linux/devfreq-governor.h b/include/linux/devfreq-governor.h index 2853f571dfdf7..e4f7b6cb07bc5 100644 --- a/include/linux/devfreq-governor.h +++ b/include/linux/devfreq-governor.h @@ -33,9 +33,14 @@ * : This governor is never changeable to other governors. * - DEVFREQ_GOV_FLAG_IRQ_DRIVEN * : The devfreq won't schedule the work for this governor. + * - DEVFREQ_GOV_FLAG_TRACK_REMOTE + * : The governor only tracks frequency changes performed by a remote + * agent (e.g. firmware); devfreq skips the local profile->target() + * call and just keeps its statistics and notifiers in sync. */ #define DEVFREQ_GOV_FLAG_IMMUTABLE BIT(0) #define DEVFREQ_GOV_FLAG_IRQ_DRIVEN BIT(1) +#define DEVFREQ_GOV_FLAG_TRACK_REMOTE BIT(2) /* * Definition of governor attribute flags except for common sysfs attributes From 767c2f3053d2ece1d04076617bd5f5f427e1bb17 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 4 Jun 2026 19:26:25 +0530 Subject: [PATCH 0482/1133] FROMLIST: PM / devfreq: Add a governor for tracking remote device frequencies On SoCs where the governor and the mechanism to control the frequency for devices like caches is hosted on the System Control Processor (SCP), there exists a need to track the frequency changes in a reliable way and provide ways to tweak parameters on the remote governor. Add a new "remote" devfreq governor that uses the track_remote flag to expose the remote device's frequency to userspace via trans_stat. The governor deliberately does not advertise the DEVFREQ_GOV_ATTR_TARGET_FREQ attribute since the kernel cannot set the frequency on a remote-managed device; reads of the target_freq sysfs node therefore return -EINVAL. Signed-off-by: Sibi Sankar Signed-off-by: Pragnesh Papaniya Link: https://lore.kernel.org/lkml/20260724-rfc_v8_scmi_memlat-v1-6-cb732bcff1f4@oss.qualcomm.com/ --- drivers/devfreq/Kconfig | 8 ++++ drivers/devfreq/Makefile | 1 + drivers/devfreq/governor_remote.c | 73 +++++++++++++++++++++++++++++++ include/linux/devfreq.h | 1 + 4 files changed, 83 insertions(+) create mode 100644 drivers/devfreq/governor_remote.c diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index c999c4a1e5675..2caa875549141 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -56,6 +56,14 @@ config DEVFREQ_GOV_POWERSAVE the DEVFREQ framework returns the lowest frequency available at any time. +config DEVFREQ_GOV_REMOTE + tristate "Remote" + help + A simple governor to track the frequency of devices whose + dvfs control lies outside the kernel. This governor acts + as an observer and provides for ways to track frequency and + set/get information related to the remote dvfs device. + config DEVFREQ_GOV_USERSPACE tristate "Userspace" help diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile index 404179d79a9db..cde57c8cda764 100644 --- a/drivers/devfreq/Makefile +++ b/drivers/devfreq/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_PM_DEVFREQ_EVENT) += devfreq-event.o obj-$(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) += governor_simpleondemand.o obj-$(CONFIG_DEVFREQ_GOV_PERFORMANCE) += governor_performance.o obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o +obj-$(CONFIG_DEVFREQ_GOV_REMOTE) += governor_remote.o obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o diff --git a/drivers/devfreq/governor_remote.c b/drivers/devfreq/governor_remote.c new file mode 100644 index 0000000000000..df3819757e56f --- /dev/null +++ b/drivers/devfreq/governor_remote.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include + +static int devfreq_remote_track_func(struct devfreq *devfreq, unsigned long *freq) +{ + if (!devfreq->profile->get_cur_freq) + return -ENXIO; + + return devfreq->profile->get_cur_freq(devfreq->dev.parent, freq); +} + +static int devfreq_remote_track_handler(struct devfreq *devfreq, unsigned int event, void *data) +{ + switch (event) { + case DEVFREQ_GOV_START: + devfreq_monitor_start(devfreq); + break; + + case DEVFREQ_GOV_STOP: + devfreq_monitor_stop(devfreq); + break; + + case DEVFREQ_GOV_UPDATE_INTERVAL: + devfreq_update_interval(devfreq, (unsigned int *)data); + break; + + case DEVFREQ_GOV_SUSPEND: + devfreq_monitor_suspend(devfreq); + break; + + case DEVFREQ_GOV_RESUME: + devfreq_monitor_resume(devfreq); + break; + } + + return 0; +} + +static struct devfreq_governor devfreq_remote_track = { + .name = DEVFREQ_GOV_REMOTE, + .attrs = DEVFREQ_GOV_ATTR_POLLING_INTERVAL + | DEVFREQ_GOV_ATTR_TIMER, + .flags = DEVFREQ_GOV_FLAG_IMMUTABLE + | DEVFREQ_GOV_FLAG_TRACK_REMOTE, + .get_target_freq = devfreq_remote_track_func, + .event_handler = devfreq_remote_track_handler, +}; + +static int __init devfreq_remote_track_init(void) +{ + return devfreq_add_governor(&devfreq_remote_track); +} +subsys_initcall(devfreq_remote_track_init); + +static void __exit devfreq_remote_track_exit(void) +{ + int ret; + + ret = devfreq_remove_governor(&devfreq_remote_track); + if (ret) + pr_err("%s: failed to remove governor %d\n", __func__, ret); +} +module_exit(devfreq_remote_track_exit); + +MODULE_DESCRIPTION("DEVFREQ Remote Tracking governor"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index dc1075dc34460..4d50cf2309504 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -21,6 +21,7 @@ #define DEVFREQ_GOV_POWERSAVE "powersave" #define DEVFREQ_GOV_USERSPACE "userspace" #define DEVFREQ_GOV_PASSIVE "passive" +#define DEVFREQ_GOV_REMOTE "remote" /* DEVFREQ notifier interface */ #define DEVFREQ_TRANSITION_NOTIFIER (0) From 92557c9919490531d9d87929c25c50750046cf82 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 4 Jun 2026 19:26:26 +0530 Subject: [PATCH 0483/1133] FROMLIST: PM / devfreq: Introduce the QCOM SCMI Memlat devfreq driver On Qualcomm Glymur, Mahua, X1E/X1P (Hamoa/Purwa) and Kaanapali SoCs, the memory-latency (memlat) governor runs entirely on the CPU Control Processor (CPUCP). Every sampling window the CPUCP reads the per-CPU PMU counters, derives its statistics (instructions-per-miss, back-end stall), maps them to a target operating point for the DDR, LLCC and DDR_QOS buses and votes it directly to the interconnect. The kernel is never in that runtime decision loop; the CPUCP algorithm and its controls are reached through the QCOM SCMI Generic Extension Protocol, addressed via the "MEMLAT" algorithm string. Introduce a devfreq SCMI client driver whose role is split in two. At probe it configures the CPUCP algorithm once (event maps, per-monitor tuneables, the cpufreq-to-memfreq maps and min/max clamps) and starts it; this half is required, as without it the CPUCP has no per-SoC data to run the algorithm. Thereafter the driver only reads back the current operating point. Each bus is modelled as a devfreq device and uses the remote devfreq governor precisely for this "observe a frequency someone else drives" case: it exposes the read-back through trans_stat and lets userspace retune the remote governor's parameters. Co-developed-by: Amir Vajid Signed-off-by: Amir Vajid Co-developed-by: Ramakrishna Gottimukkula Signed-off-by: Ramakrishna Gottimukkula Signed-off-by: Sibi Sankar Co-developed-by: Pragnesh Papaniya Signed-off-by: Pragnesh Papaniya Link: https://lore.kernel.org/lkml/20260724-rfc_v8_scmi_memlat-v1-7-cb732bcff1f4@oss.qualcomm.com/ --- MAINTAINERS | 8 + drivers/devfreq/Kconfig | 15 + drivers/devfreq/Makefile | 1 + drivers/devfreq/scmi-qcom-memlat-devfreq.c | 1331 ++++++++++++++++++++ 4 files changed, 1355 insertions(+) create mode 100644 drivers/devfreq/scmi-qcom-memlat-devfreq.c diff --git a/MAINTAINERS b/MAINTAINERS index 4dfc61cda402b..08764f9f8e4a7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23167,6 +23167,14 @@ S: Maintained F: Documentation/devicetree/bindings/spmi/qcom,*spmi-pmic-arb*.yaml F: drivers/spmi/spmi-pmic-arb.c +QUALCOMM SCMI MEMLAT DEVFREQ DRIVER +M: Pragnesh Papaniya +M: Sibi Sankar +L: linux-arm-msm@vger.kernel.org +L: linux-pm@vger.kernel.org +S: Maintained +F: drivers/devfreq/scmi-qcom-memlat-devfreq.c + QUALCOMM TEE (QCOMTEE) DRIVER M: Amirreza Zarrabi L: linux-arm-msm@vger.kernel.org diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 2caa875549141..fdf6484fc72c9 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -169,6 +169,21 @@ config ARM_SUN8I_A33_MBUS_DEVFREQ This adds the DEVFREQ driver for the MBUS controller in some Allwinner sun8i (A33 through H3) and sun50i (A64 and H5) SoCs. +config SCMI_QCOM_MEMLAT_DEVFREQ + tristate "Qualcomm SCMI memory latency (memlat) devfreq driver" + depends on QCOM_SCMI_GENERIC_EXT || COMPILE_TEST + select DEVFREQ_GOV_REMOTE + help + Enable memory-bus (DDR/LLCC/DDR_QOS) scaling on Qualcomm Glymur, + X1E/X1P-class and Kaanapali SoCs. The scaling algorithm itself runs + autonomously on the CPU Control Processor (CPUCP); this driver only + configures and starts it at boot and then exposes each bus as a + devfreq device so its operating point is visible via trans_stat and + tunable from userspace. + + Nothing else needs to be enabled for the scaling to take effect. Say Y + or M here on the affected Qualcomm SoCs; otherwise say N. + source "drivers/devfreq/event/Kconfig" endif # PM_DEVFREQ diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile index cde57c8cda764..b11f94e2f4855 100644 --- a/drivers/devfreq/Makefile +++ b/drivers/devfreq/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_ARM_MEDIATEK_CCI_DEVFREQ) += mtk-cci-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_SUN8I_A33_MBUS_DEVFREQ) += sun8i-a33-mbus.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o +obj-$(CONFIG_SCMI_QCOM_MEMLAT_DEVFREQ) += scmi-qcom-memlat-devfreq.o # DEVFREQ Event Drivers obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/ diff --git a/drivers/devfreq/scmi-qcom-memlat-devfreq.c b/drivers/devfreq/scmi-qcom-memlat-devfreq.c new file mode 100644 index 0000000000000..9ca85b2f4c1a3 --- /dev/null +++ b/drivers/devfreq/scmi-qcom-memlat-devfreq.c @@ -0,0 +1,1331 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* CPUCP AMU event indices programmed into the common/group event maps. */ +#define MEMLAT_EV_CPU_CYCLES 0 +#define MEMLAT_EV_CNT_CYCLES 1 +#define MEMLAT_EV_INST_RETIRED 2 +#define MEMLAT_EV_STALL_BACKEND_MEM 3 +#define MEMLAT_EV_L2_D_RFILL 5 + +/* Sentinel for an event slot that is not wired to any AMU counter. */ +#define MEMLAT_INVALID_IDX 0xff + +/* hw_type value that targets every group (common events are not group-scoped). */ +#define MEMLAT_HW_TYPE_ALL 0xff + +#define MEMLAT_ALGO_STR 0x4d454d4c4154ULL /* "MEMLAT" */ + +/** + * struct scmi_qcom_map_table - one row of a monitor's cpufreq->memfreq map + * @cpu_freq_mhz: CPU frequency threshold, in MHz. When the monitor's busiest + * CPU is at or above this frequency, the firmware votes the + * paired memory frequency. + * @mem_freq_mhz: memory frequency to vote, in MHz (a 0/1 level for DDR_QOS). + */ +struct scmi_qcom_map_table { + unsigned int cpu_freq_mhz; + unsigned int mem_freq_mhz; +}; + +struct scmi_qcom_opp_data { + u64 freq; +}; + +struct scmi_qcom_memory_range { + unsigned int min_freq_khz; + unsigned int max_freq_khz; +}; + +enum common_ev_idx { + INST_IDX, + CYC_IDX, + CONST_CYC_IDX, + FE_STALL_IDX, + BE_STALL_IDX, + NUM_COMMON_EVS +}; + +enum grp_ev_idx { + MISS_IDX, + WB_IDX, + ACC_IDX, + NUM_GRP_EVS +}; + +/* + * hw_type identifiers for the memory buses. These are a firmware-defined + * encoding carried in the node/scalar/map/ev messages; the driver only + * mirrors them here. + */ +enum scmi_qcom_memlat_hw_type { + MEMLAT_HW_DDR = 0, + MEMLAT_HW_LLCC = 1, + MEMLAT_HW_DDR_QOS_COMPUTE = 2, + MEMLAT_HW_DDR_QOS_MOBILE = 3, +}; + +/** + * struct scmi_qcom_monitor_cfg - per-monitor firmware tuneables + * @table: cpufreq->memfreq voting map for this monitor. + * @name: monitor name, forwarded to the firmware and used in its log lines. + * @be_stall_floor: back-end-stall gating threshold, in percent. Each sample + * window the firmware computes a per-CPU back-end-stall + * percentage (stall cycles / total cycles); a CPU only + * contributes its frequency vote to this monitor when that + * percentage is at or above @be_stall_floor. A value of 1 + * therefore means "any stall counts", i.e. the CPU is + * effectively always eligible. + * @cpu_mask: bitmask of CPUs whose counters this monitor aggregates. + * @ipm_ceil: instructions-per-miss ceiling. A CPU is treated as + * memory-latency-bound (and eligible to vote) only when its IPM is + * at or below this ceiling; a monitor with @ipm_ceil == 0 is a + * "compute" monitor and scales passively with cpufreq. + * @table_len: number of valid rows in @table. + */ +struct scmi_qcom_monitor_cfg { + const struct scmi_qcom_map_table *table; + const char *name; + u32 be_stall_floor; + u32 cpu_mask; + u32 ipm_ceil; + u32 table_len; +}; + +struct scmi_qcom_memory_cfg { + const struct scmi_qcom_monitor_cfg *monitor_cfg; + const struct scmi_qcom_opp_data *mem_table; + struct scmi_qcom_memory_range memory_range; + const u32 *grp_ev; + const char *name; + enum scmi_qcom_memlat_hw_type memory_type; + u32 monitor_cnt; + u32 num_opps; +}; + +struct scmi_qcom_memlat_cfg_data { + const struct scmi_qcom_memory_cfg *memory_cfg; + const u32 *common_ev; + bool cpucp_legacy_freq_method; + u32 cpucp_sample_ms; + u32 memory_cnt; +}; + +#define MEMLAT_MAX_NAME_LEN 20 +#define MEMLAT_MAX_MAP_ENTRIES 10 + +/* + * param_ids of the "MEMLAT" algo_str hosted by the Qualcomm Generic Vendor + * Protocol. MEMLAT detects memory-latency-bound workloads and scales the + * memory buses accordingly; these are the fixed wire-protocol tokens that + * the firmware matches. + * + * MEMLAT_SET_MEM_GROUP: initializes the frequency/level scaling functions for the memory bus. + * MEMLAT_SET_MONITOR: configures the monitor to work on a specific memory bus. + * MEMLAT_SET_COMMON_EV_MAP: set up common counters used to monitor the cpu frequency. + * MEMLAT_SET_GRP_EV_MAP: set up any specific counters used to monitor the memory bus. + * MEMLAT_ADAPTIVE_LOW_FREQ: set the adaptive low frequency floor of the memory bus. + * MEMLAT_ADAPTIVE_HIGH_FREQ: set the adaptive high frequency floor of the memory bus. + * MEMLAT_GET_ADAPTIVE_CUR_FREQ: query the current adaptive frequency of the memory bus. + * MEMLAT_IPM_CEIL: set the IPM (Instruction Per Misses) ceiling per monitor. + * MEMLAT_FE_STALL_FLOOR: set the front-end stall floor per monitor. + * MEMLAT_BE_STALL_FLOOR: set the back-end stall floor per monitor. + * MEMLAT_WB_PCT: set the write-back percentage threshold per monitor. + * MEMLAT_IPM_FILTER: set the IPM filter used to reject non-latency samples per monitor. + * MEMLAT_FREQ_SCALE_PCT: set the frequency scaling percentage per monitor. + * MEMLAT_FREQ_SCALE_CEIL_MHZ: set the cpu frequency ceiling for scaling per monitor. + * MEMLAT_FREQ_SCALE_FLOOR_MHZ: set the cpu frequency floor for scaling per monitor. + * MEMLAT_SAMPLE_MS: set the sampling period for all the monitors. + * MEMLAT_MON_FREQ_MAP: setup the cpufreq to memfreq map. + * MEMLAT_SET_MIN_FREQ: set the min frequency of the memory bus. + * MEMLAT_SET_MAX_FREQ: set the max frequency of the memory bus. + * MEMLAT_GET_CUR_FREQ: query the current frequency/level of the memory bus. + * MEMLAT_START_TIMER: start all the monitors with the requested sampling period. + * MEMLAT_STOP_TIMER: stop all the running monitors. + * MEMLAT_GET_TIMESTAMP: query the firmware timestamp. + * MEMLAT_SET_EFFECTIVE_FREQ_METHOD: set the method used to determine cpu frequency. + */ +#define MEMLAT_SET_MEM_GROUP 16 +#define MEMLAT_SET_MONITOR 17 +#define MEMLAT_SET_COMMON_EV_MAP 18 +#define MEMLAT_SET_GRP_EV_MAP 19 +#define MEMLAT_ADAPTIVE_LOW_FREQ 20 +#define MEMLAT_ADAPTIVE_HIGH_FREQ 21 +#define MEMLAT_GET_ADAPTIVE_CUR_FREQ 22 +#define MEMLAT_IPM_CEIL 23 +#define MEMLAT_FE_STALL_FLOOR 24 +#define MEMLAT_BE_STALL_FLOOR 25 +#define MEMLAT_WB_PCT 26 +#define MEMLAT_IPM_FILTER 27 +#define MEMLAT_FREQ_SCALE_PCT 28 +#define MEMLAT_FREQ_SCALE_CEIL_MHZ 29 +#define MEMLAT_FREQ_SCALE_FLOOR_MHZ 30 +#define MEMLAT_SAMPLE_MS 31 +#define MEMLAT_MON_FREQ_MAP 32 +#define MEMLAT_SET_MIN_FREQ 33 +#define MEMLAT_SET_MAX_FREQ 34 +#define MEMLAT_GET_CUR_FREQ 35 +#define MEMLAT_START_TIMER 36 +#define MEMLAT_STOP_TIMER 37 +#define MEMLAT_GET_TIMESTAMP 38 +#define MEMLAT_SET_EFFECTIVE_FREQ_METHOD 39 + +struct cpucp_map_table { + __le16 cpu_freq_mhz; + __le16 mem_freq_mhz; +}; + +struct map_param_msg { + __le32 hw_type; + __le32 mon_idx; + __le32 nr_rows; + struct cpucp_map_table tbl[MEMLAT_MAX_MAP_ENTRIES]; +}; + +struct node_msg { + __le32 cpumask; + __le32 hw_type; + __le32 mon_type; + __le32 mon_idx; + char mon_name[MEMLAT_MAX_NAME_LEN]; +}; + +struct scalar_param_msg { + __le32 hw_type; + __le32 mon_idx; + __le32 val; +}; + +struct ev_map_msg { + __le32 num_evs; + __le32 hw_type; + __le32 cid[NUM_COMMON_EVS]; +}; + +/* + * MEMLAT_GET_CUR_FREQ reuses the request buffer for its response, so express + * the in/out aliasing as a union rather than reinterpreting the bytes. + */ +union cur_freq_msg { + struct scalar_param_msg req; + __le32 resp; +}; + +struct scmi_qcom_memory_info { + const struct scmi_qcom_memory_cfg *cfg; + struct devfreq_dev_profile profile; + struct devfreq *devfreq; + struct faux_device *fdev; + struct scmi_protocol_handle *ph; + const struct qcom_generic_ext_ops *ops; +}; + +struct scmi_qcom_memlat_info { + struct scmi_protocol_handle *ph; + const struct qcom_generic_ext_ops *ops; + const struct scmi_qcom_memlat_cfg_data *cfg_data; + struct scmi_qcom_memory_info **memory; + u32 memory_cnt; +}; + +/* + * ========================================================================== + * Per-SoC configuration + * ========================================================================== + */ + +static const u32 glymur_common_ev[NUM_COMMON_EVS] = { + [INST_IDX] = MEMLAT_EV_INST_RETIRED, + [CYC_IDX] = MEMLAT_EV_CPU_CYCLES, + [CONST_CYC_IDX] = MEMLAT_EV_CNT_CYCLES, + [FE_STALL_IDX] = MEMLAT_INVALID_IDX, + [BE_STALL_IDX] = MEMLAT_EV_STALL_BACKEND_MEM, +}; + +static const u32 glymur_ddr_grp_ev[NUM_GRP_EVS] = { + [MISS_IDX] = MEMLAT_EV_L2_D_RFILL, + [WB_IDX] = MEMLAT_INVALID_IDX, + [ACC_IDX] = MEMLAT_INVALID_IDX, +}; + +static const u32 glymur_llcc_grp_ev[NUM_GRP_EVS] = { + [MISS_IDX] = MEMLAT_EV_L2_D_RFILL, + [WB_IDX] = MEMLAT_INVALID_IDX, + [ACC_IDX] = MEMLAT_INVALID_IDX, +}; + +static const u32 glymur_ddr_qos_grp_ev[NUM_GRP_EVS] = { + [MISS_IDX] = MEMLAT_EV_L2_D_RFILL, + [WB_IDX] = MEMLAT_INVALID_IDX, + [ACC_IDX] = MEMLAT_INVALID_IDX, +}; + +static const u32 hamoa_common_ev[NUM_COMMON_EVS] = { + [INST_IDX] = MEMLAT_EV_INST_RETIRED, + [CYC_IDX] = MEMLAT_EV_CPU_CYCLES, + [CONST_CYC_IDX] = MEMLAT_EV_CNT_CYCLES, + [FE_STALL_IDX] = MEMLAT_INVALID_IDX, + [BE_STALL_IDX] = MEMLAT_EV_STALL_BACKEND_MEM, +}; + +static const u32 hamoa_ddr_grp_ev[NUM_GRP_EVS] = { + [MISS_IDX] = MEMLAT_EV_L2_D_RFILL, + [WB_IDX] = MEMLAT_INVALID_IDX, + [ACC_IDX] = MEMLAT_INVALID_IDX, +}; + +static const u32 hamoa_llcc_grp_ev[NUM_GRP_EVS] = { + [MISS_IDX] = MEMLAT_EV_L2_D_RFILL, + [WB_IDX] = MEMLAT_INVALID_IDX, + [ACC_IDX] = MEMLAT_INVALID_IDX, +}; + +static const u32 hamoa_ddr_qos_grp_ev[NUM_GRP_EVS] = { + [MISS_IDX] = MEMLAT_EV_L2_D_RFILL, + [WB_IDX] = MEMLAT_INVALID_IDX, + [ACC_IDX] = MEMLAT_INVALID_IDX, +}; + +static const u32 kaanapali_common_ev[NUM_COMMON_EVS] = { + [INST_IDX] = MEMLAT_EV_INST_RETIRED, + [CYC_IDX] = MEMLAT_EV_CPU_CYCLES, + [CONST_CYC_IDX] = MEMLAT_INVALID_IDX, + [FE_STALL_IDX] = MEMLAT_INVALID_IDX, + [BE_STALL_IDX] = MEMLAT_INVALID_IDX, +}; + +static const u32 kaanapali_ddr_grp_ev[NUM_GRP_EVS] = { + [MISS_IDX] = MEMLAT_EV_L2_D_RFILL, + [WB_IDX] = MEMLAT_INVALID_IDX, + [ACC_IDX] = MEMLAT_INVALID_IDX, +}; + +static const u32 kaanapali_llcc_grp_ev[NUM_GRP_EVS] = { + [MISS_IDX] = MEMLAT_EV_L2_D_RFILL, + [WB_IDX] = MEMLAT_INVALID_IDX, + [ACC_IDX] = MEMLAT_INVALID_IDX, +}; + +static const u32 kaanapali_ddr_qos_grp_ev[NUM_GRP_EVS] = { + [MISS_IDX] = MEMLAT_EV_L2_D_RFILL, + [WB_IDX] = MEMLAT_INVALID_IDX, + [ACC_IDX] = MEMLAT_INVALID_IDX, +}; + +static const struct scmi_qcom_opp_data glymur_llcc_table[] = { + { .freq = 315000000 }, + { .freq = 479000000 }, + { .freq = 545000000 }, + { .freq = 725000000 }, + { .freq = 840000000 }, + { .freq = 959000000 }, + { .freq = 1090000000 }, + { .freq = 1211000000 }, +}; + +static const struct scmi_qcom_opp_data hamoa_llcc_table[] = { + { .freq = 300000000 }, + { .freq = 466000000 }, + { .freq = 600000000 }, + { .freq = 806000000 }, + { .freq = 933000000 }, + { .freq = 1066000000 }, +}; + +static const struct scmi_qcom_opp_data kaanapali_llcc_table[] = { + { .freq = 282000000 }, + { .freq = 350000000 }, + { .freq = 533000000 }, + { .freq = 605600000 }, + { .freq = 806000000 }, + { .freq = 933000000 }, + { .freq = 1066000000 }, + { .freq = 1211000000 }, + { .freq = 1350000000 }, +}; + +static const struct scmi_qcom_opp_data glymur_ddr_table[] = { + { .freq = 200000000 }, + { .freq = 547000000 }, + { .freq = 1353000000 }, + { .freq = 1555000000 }, + { .freq = 1708000000 }, + { .freq = 2092000000 }, + { .freq = 2736000000 }, + { .freq = 3187000000 }, + { .freq = 3686000000 }, + { .freq = 4224000000 }, + { .freq = 4761000000 }, +}; + +static const struct scmi_qcom_opp_data hamoa_ddr_table[] = { + { .freq = 200000000 }, + { .freq = 547000000 }, + { .freq = 768000000 }, + { .freq = 1555000000 }, + { .freq = 1708000000 }, + { .freq = 2092000000 }, + { .freq = 2736000000 }, + { .freq = 3187000000 }, + { .freq = 3686000000 }, + { .freq = 4224000000 }, +}; + +static const struct scmi_qcom_opp_data kaanapali_ddr_table[] = { + { .freq = 547000000 }, + { .freq = 1353000000 }, + { .freq = 1555000000 }, + { .freq = 1708000000 }, + { .freq = 2092000000 }, + { .freq = 2736000000 }, + { .freq = 3187000000 }, + { .freq = 3686000000 }, + { .freq = 4224000000 }, + { .freq = 4780000000 }, + { .freq = 5333000000 }, +}; + +/* + * DDR_QOS is a boolean bus: the firmware reports level 0 (nominal) or 1 + * (boost) rather than a frequency. dev_pm_opp_add_dynamic() rejects a zero + * frequency, so the two OPP entries below use 1 and 100 purely as distinct, + * non-zero devfreq keys for the two levels; the values are not real + * frequencies. scmi_qcom_devfreq_get_cur_freq() maps the reported level back + * to the matching OPP frequency. + */ +static const struct scmi_qcom_opp_data glymur_ddr_qos_table[] = { + { .freq = 1 }, + { .freq = 100 }, +}; + +static const struct scmi_qcom_memory_cfg glymur_memory_cfg[] = { + { + .memory_type = MEMLAT_HW_DDR, + .name = "ddr", + .mem_table = glymur_ddr_table, + .num_opps = ARRAY_SIZE(glymur_ddr_table), + .grp_ev = glymur_ddr_grp_ev, + .monitor_cnt = 4, + .memory_range = { .min_freq_khz = 547000, .max_freq_khz = 4761000 }, + .monitor_cfg = (const struct scmi_qcom_monitor_cfg[]) { + { + .name = "mon_0", + .cpu_mask = 0x3f, + .ipm_ceil = 60000000, + .be_stall_floor = 1, + .table_len = 8, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 960, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 1133, .mem_freq_mhz = 1353 }, + { .cpu_freq_mhz = 1594, .mem_freq_mhz = 1555 }, + { .cpu_freq_mhz = 1920, .mem_freq_mhz = 1708 }, + { .cpu_freq_mhz = 2228, .mem_freq_mhz = 2736 }, + { .cpu_freq_mhz = 2362, .mem_freq_mhz = 3187 }, + { .cpu_freq_mhz = 2650, .mem_freq_mhz = 3686 }, + { .cpu_freq_mhz = 2938, .mem_freq_mhz = 4761 }, + } + }, + { + .name = "mon_1", + .cpu_mask = 0xfc0, + .ipm_ceil = 60000000, + .be_stall_floor = 1, + .table_len = 8, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 356, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 1018, .mem_freq_mhz = 1353 }, + { .cpu_freq_mhz = 1536, .mem_freq_mhz = 1555 }, + { .cpu_freq_mhz = 1748, .mem_freq_mhz = 1708 }, + { .cpu_freq_mhz = 2324, .mem_freq_mhz = 2736 }, + { .cpu_freq_mhz = 2496, .mem_freq_mhz = 3187 }, + { .cpu_freq_mhz = 2900, .mem_freq_mhz = 3686 }, + { .cpu_freq_mhz = 3514, .mem_freq_mhz = 4761 }, + } + }, + { + .name = "mon_2", + .cpu_mask = 0x3f000, + .ipm_ceil = 60000000, + .be_stall_floor = 1, + .table_len = 8, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 356, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 1018, .mem_freq_mhz = 1353 }, + { .cpu_freq_mhz = 1536, .mem_freq_mhz = 1555 }, + { .cpu_freq_mhz = 1748, .mem_freq_mhz = 1708 }, + { .cpu_freq_mhz = 2324, .mem_freq_mhz = 2736 }, + { .cpu_freq_mhz = 2496, .mem_freq_mhz = 3187 }, + { .cpu_freq_mhz = 2900, .mem_freq_mhz = 3686 }, + { .cpu_freq_mhz = 3514, .mem_freq_mhz = 4761 }, + } + }, + { + .name = "mon_3", + .cpu_mask = 0x3ffff, + .table_len = 4, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2823, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 3034, .mem_freq_mhz = 1555 }, + { .cpu_freq_mhz = 3226, .mem_freq_mhz = 1708 }, + { .cpu_freq_mhz = 5012, .mem_freq_mhz = 2092 }, + } + }, + }, + }, + { + .memory_type = MEMLAT_HW_LLCC, + .name = "llcc", + .mem_table = glymur_llcc_table, + .num_opps = ARRAY_SIZE(glymur_llcc_table), + .grp_ev = glymur_llcc_grp_ev, + .monitor_cnt = 3, + .memory_range = { .min_freq_khz = 315000, .max_freq_khz = 1211000 }, + .monitor_cfg = (const struct scmi_qcom_monitor_cfg[]) { + { + .name = "mon_0", + .cpu_mask = 0x3f, + .ipm_ceil = 60000000, + .be_stall_floor = 1, + .table_len = 7, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 960, .mem_freq_mhz = 315 }, + { .cpu_freq_mhz = 1113, .mem_freq_mhz = 479 }, + { .cpu_freq_mhz = 1594, .mem_freq_mhz = 545 }, + { .cpu_freq_mhz = 1920, .mem_freq_mhz = 725 }, + { .cpu_freq_mhz = 2362, .mem_freq_mhz = 840 }, + { .cpu_freq_mhz = 2650, .mem_freq_mhz = 959 }, + { .cpu_freq_mhz = 2938, .mem_freq_mhz = 1211 }, + } + }, + { + .name = "mon_1", + .cpu_mask = 0xfc0, + .ipm_ceil = 60000000, + .be_stall_floor = 1, + .table_len = 7, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 356, .mem_freq_mhz = 315 }, + { .cpu_freq_mhz = 1018, .mem_freq_mhz = 479 }, + { .cpu_freq_mhz = 1536, .mem_freq_mhz = 545 }, + { .cpu_freq_mhz = 1748, .mem_freq_mhz = 725 }, + { .cpu_freq_mhz = 2496, .mem_freq_mhz = 840 }, + { .cpu_freq_mhz = 2900, .mem_freq_mhz = 959 }, + { .cpu_freq_mhz = 3514, .mem_freq_mhz = 1211 }, + } + }, + { + .name = "mon_2", + .cpu_mask = 0x3f000, + .ipm_ceil = 60000000, + .be_stall_floor = 1, + .table_len = 7, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 356, .mem_freq_mhz = 315 }, + { .cpu_freq_mhz = 1018, .mem_freq_mhz = 479 }, + { .cpu_freq_mhz = 1536, .mem_freq_mhz = 545 }, + { .cpu_freq_mhz = 1748, .mem_freq_mhz = 725 }, + { .cpu_freq_mhz = 2496, .mem_freq_mhz = 840 }, + { .cpu_freq_mhz = 2900, .mem_freq_mhz = 959 }, + { .cpu_freq_mhz = 3514, .mem_freq_mhz = 1211 }, + } + }, + }, + }, + { + .memory_type = MEMLAT_HW_DDR_QOS_COMPUTE, + .name = "ddr-qos", + .monitor_cnt = 3, + .mem_table = glymur_ddr_qos_table, + .num_opps = ARRAY_SIZE(glymur_ddr_qos_table), + .grp_ev = glymur_ddr_qos_grp_ev, + .memory_range = { .min_freq_khz = 0, .max_freq_khz = 1 }, + .monitor_cfg = (const struct scmi_qcom_monitor_cfg[]) { + { + .name = "mon_0", + .cpu_mask = 0x3f, + .ipm_ceil = 80000000, + .be_stall_floor = 1, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2362, .mem_freq_mhz = 0 }, + { .cpu_freq_mhz = 2938, .mem_freq_mhz = 1 }, + } + }, + { + .name = "mon_1", + .cpu_mask = 0xfc0, + .ipm_ceil = 80000000, + .be_stall_floor = 1, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2496, .mem_freq_mhz = 0 }, + { .cpu_freq_mhz = 3514, .mem_freq_mhz = 1 }, + } + }, + { + .name = "mon_2", + .cpu_mask = 0x3f000, + .ipm_ceil = 80000000, + .be_stall_floor = 1, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2496, .mem_freq_mhz = 0 }, + { .cpu_freq_mhz = 3514, .mem_freq_mhz = 1 }, + } + }, + }, + }, +}; + +static const struct scmi_qcom_memory_cfg hamoa_memory_cfg[] = { + { + .memory_type = MEMLAT_HW_DDR, + .name = "ddr", + .mem_table = hamoa_ddr_table, + .num_opps = ARRAY_SIZE(hamoa_ddr_table), + .grp_ev = hamoa_ddr_grp_ev, + .monitor_cnt = 4, + .memory_range = { .min_freq_khz = 200000, .max_freq_khz = 4224000 }, + .monitor_cfg = (const struct scmi_qcom_monitor_cfg[]) { + { + .name = "mon_0", + .cpu_mask = 0xf, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 6, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 999, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 1440, .mem_freq_mhz = 768 }, + { .cpu_freq_mhz = 1671, .mem_freq_mhz = 1555 }, + { .cpu_freq_mhz = 2189, .mem_freq_mhz = 2092 }, + { .cpu_freq_mhz = 2516, .mem_freq_mhz = 3187 }, + { .cpu_freq_mhz = 3860, .mem_freq_mhz = 4224 }, + } + }, + { + .name = "mon_1", + .cpu_mask = 0xf0, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 6, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 999, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 1440, .mem_freq_mhz = 768 }, + { .cpu_freq_mhz = 1671, .mem_freq_mhz = 1555 }, + { .cpu_freq_mhz = 2189, .mem_freq_mhz = 2092 }, + { .cpu_freq_mhz = 2516, .mem_freq_mhz = 3187 }, + { .cpu_freq_mhz = 3860, .mem_freq_mhz = 4224 }, + } + }, + { + .name = "mon_2", + .cpu_mask = 0xf00, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 6, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 999, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 1440, .mem_freq_mhz = 768 }, + { .cpu_freq_mhz = 1671, .mem_freq_mhz = 1555 }, + { .cpu_freq_mhz = 2189, .mem_freq_mhz = 2092 }, + { .cpu_freq_mhz = 2516, .mem_freq_mhz = 3187 }, + { .cpu_freq_mhz = 3860, .mem_freq_mhz = 4224 }, + } + }, + { + .name = "mon_3", + .cpu_mask = 0xfff, + .table_len = 4, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 1440, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 2189, .mem_freq_mhz = 768 }, + { .cpu_freq_mhz = 2516, .mem_freq_mhz = 1555 }, + { .cpu_freq_mhz = 3860, .mem_freq_mhz = 2092 }, + } + }, + }, + }, + { + .memory_type = MEMLAT_HW_LLCC, + .name = "llcc", + .mem_table = hamoa_llcc_table, + .num_opps = ARRAY_SIZE(hamoa_llcc_table), + .grp_ev = hamoa_llcc_grp_ev, + .monitor_cnt = 3, + .memory_range = { .min_freq_khz = 300000, .max_freq_khz = 1066000 }, + .monitor_cfg = (const struct scmi_qcom_monitor_cfg[]) { + { + .name = "mon_0", + .cpu_mask = 0xf, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 6, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 999, .mem_freq_mhz = 300 }, + { .cpu_freq_mhz = 1440, .mem_freq_mhz = 466 }, + { .cpu_freq_mhz = 1671, .mem_freq_mhz = 600 }, + { .cpu_freq_mhz = 2189, .mem_freq_mhz = 806 }, + { .cpu_freq_mhz = 2516, .mem_freq_mhz = 933 }, + { .cpu_freq_mhz = 3860, .mem_freq_mhz = 1066 }, + } + }, + { + .name = "mon_1", + .cpu_mask = 0xf0, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 6, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 999, .mem_freq_mhz = 300 }, + { .cpu_freq_mhz = 1440, .mem_freq_mhz = 466 }, + { .cpu_freq_mhz = 1671, .mem_freq_mhz = 600 }, + { .cpu_freq_mhz = 2189, .mem_freq_mhz = 806 }, + { .cpu_freq_mhz = 2516, .mem_freq_mhz = 933 }, + { .cpu_freq_mhz = 3860, .mem_freq_mhz = 1066 }, + } + }, + { + .name = "mon_2", + .cpu_mask = 0xf00, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 6, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 999, .mem_freq_mhz = 300 }, + { .cpu_freq_mhz = 1440, .mem_freq_mhz = 466 }, + { .cpu_freq_mhz = 1671, .mem_freq_mhz = 600 }, + { .cpu_freq_mhz = 2189, .mem_freq_mhz = 806 }, + { .cpu_freq_mhz = 2516, .mem_freq_mhz = 933 }, + { .cpu_freq_mhz = 3860, .mem_freq_mhz = 1066 }, + } + }, + }, + }, + { + .memory_type = MEMLAT_HW_DDR_QOS_COMPUTE, + .name = "ddr-qos", + .monitor_cnt = 3, + .mem_table = glymur_ddr_qos_table, + .num_opps = ARRAY_SIZE(glymur_ddr_qos_table), + .grp_ev = hamoa_ddr_qos_grp_ev, + .memory_range = { .min_freq_khz = 0, .max_freq_khz = 1 }, + .monitor_cfg = (const struct scmi_qcom_monitor_cfg[]) { + { + .name = "mon_0", + .cpu_mask = 0xf, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2189, .mem_freq_mhz = 0 }, + { .cpu_freq_mhz = 3860, .mem_freq_mhz = 1 }, + } + }, + { + .name = "mon_1", + .cpu_mask = 0xf0, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2189, .mem_freq_mhz = 0 }, + { .cpu_freq_mhz = 3860, .mem_freq_mhz = 1 }, + } + }, + { + .name = "mon_2", + .cpu_mask = 0xf00, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2189, .mem_freq_mhz = 0 }, + { .cpu_freq_mhz = 3860, .mem_freq_mhz = 1 }, + } + }, + }, + }, +}; + +static const struct scmi_qcom_memory_cfg kaanapali_memory_cfg[] = { + { + .memory_type = MEMLAT_HW_DDR, + .name = "ddr", + .mem_table = kaanapali_ddr_table, + .num_opps = ARRAY_SIZE(kaanapali_ddr_table), + .grp_ev = kaanapali_ddr_grp_ev, + .monitor_cnt = 4, + .memory_range = { .min_freq_khz = 547000, .max_freq_khz = 5333000 }, + .monitor_cfg = (const struct scmi_qcom_monitor_cfg[]) { + { + .name = "mon_0", + .cpu_mask = 0x3f, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 6, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 787, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 960, .mem_freq_mhz = 1353 }, + { .cpu_freq_mhz = 1200, .mem_freq_mhz = 1555 }, + { .cpu_freq_mhz = 1536, .mem_freq_mhz = 2092 }, + { .cpu_freq_mhz = 2534, .mem_freq_mhz = 3187 }, + { .cpu_freq_mhz = 3552, .mem_freq_mhz = 3686 }, + } + }, + { + .name = "mon_1", + .cpu_mask = 0xc0, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 8, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 614, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 864, .mem_freq_mhz = 1353 }, + { .cpu_freq_mhz = 1382, .mem_freq_mhz = 2092 }, + { .cpu_freq_mhz = 2131, .mem_freq_mhz = 3187 }, + { .cpu_freq_mhz = 2726, .mem_freq_mhz = 3686 }, + { .cpu_freq_mhz = 3513, .mem_freq_mhz = 4224 }, + { .cpu_freq_mhz = 3916, .mem_freq_mhz = 4780 }, + { .cpu_freq_mhz = 4185, .mem_freq_mhz = 5333 }, + } + }, + { + .name = "mon_2", + .cpu_mask = 0xff, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2035, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 4185, .mem_freq_mhz = 2092 }, + } + }, + { + .name = "mon_3", + .cpu_mask = 0xc0, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2726, .mem_freq_mhz = 547 }, + { .cpu_freq_mhz = 4185, .mem_freq_mhz = 4224 }, + } + }, + }, + }, + { + .memory_type = MEMLAT_HW_LLCC, + .name = "llcc", + .mem_table = kaanapali_llcc_table, + .num_opps = ARRAY_SIZE(kaanapali_llcc_table), + .grp_ev = kaanapali_llcc_grp_ev, + .monitor_cnt = 3, + .memory_range = { .min_freq_khz = 282000, .max_freq_khz = 1350000 }, + .monitor_cfg = (const struct scmi_qcom_monitor_cfg[]) { + { + .name = "mon_0", + .cpu_mask = 0x3f, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 5, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 787, .mem_freq_mhz = 282 }, + { .cpu_freq_mhz = 960, .mem_freq_mhz = 350 }, + { .cpu_freq_mhz = 1536, .mem_freq_mhz = 533 }, + { .cpu_freq_mhz = 2534, .mem_freq_mhz = 806 }, + { .cpu_freq_mhz = 3552, .mem_freq_mhz = 933 }, + } + }, + { + .name = "mon_1", + .cpu_mask = 0xc0, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 8, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 614, .mem_freq_mhz = 282 }, + { .cpu_freq_mhz = 864, .mem_freq_mhz = 350 }, + { .cpu_freq_mhz = 1382, .mem_freq_mhz = 533 }, + { .cpu_freq_mhz = 2131, .mem_freq_mhz = 806 }, + { .cpu_freq_mhz = 2726, .mem_freq_mhz = 933 }, + { .cpu_freq_mhz = 3513, .mem_freq_mhz = 1066 }, + { .cpu_freq_mhz = 3916, .mem_freq_mhz = 1211 }, + { .cpu_freq_mhz = 4185, .mem_freq_mhz = 1350 }, + } + }, + { + .name = "mon_2", + .cpu_mask = 0xff, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2035, .mem_freq_mhz = 282 }, + { .cpu_freq_mhz = 4185, .mem_freq_mhz = 533 }, + } + }, + }, + }, + { + .memory_type = MEMLAT_HW_DDR_QOS_MOBILE, + .name = "ddr-qos", + .monitor_cnt = 4, + .mem_table = glymur_ddr_qos_table, + .num_opps = ARRAY_SIZE(glymur_ddr_qos_table), + .grp_ev = kaanapali_ddr_qos_grp_ev, + .memory_range = { .min_freq_khz = 0, .max_freq_khz = 1 }, + .monitor_cfg = (const struct scmi_qcom_monitor_cfg[]) { + { + .name = "mon_0", + .cpu_mask = 0xff, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2035, .mem_freq_mhz = 0 }, + { .cpu_freq_mhz = 4185, .mem_freq_mhz = 1 }, + } + }, + { + .name = "mon_1", + .cpu_mask = 0xc0, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 1574, .mem_freq_mhz = 0 }, + { .cpu_freq_mhz = 4185, .mem_freq_mhz = 1 }, + } + }, + { + .name = "mon_2", + .cpu_mask = 0xc0, + .ipm_ceil = 20000000, + .be_stall_floor = 1, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 2131, .mem_freq_mhz = 0 }, + { .cpu_freq_mhz = 4185, .mem_freq_mhz = 1 }, + } + }, + { + .name = "mon_3", + .cpu_mask = 0xc0, + .table_len = 2, + .table = (const struct scmi_qcom_map_table[]) { + { .cpu_freq_mhz = 3513, .mem_freq_mhz = 0 }, + { .cpu_freq_mhz = 4185, .mem_freq_mhz = 1 }, + } + }, + }, + }, +}; + +static const struct scmi_qcom_memlat_cfg_data glymur_memlat_data = { + .memory_cfg = glymur_memory_cfg, + .common_ev = glymur_common_ev, + .cpucp_legacy_freq_method = true, + .cpucp_sample_ms = 4, + .memory_cnt = ARRAY_SIZE(glymur_memory_cfg), +}; + +static const struct scmi_qcom_memlat_cfg_data hamoa_memlat_data = { + .memory_cfg = hamoa_memory_cfg, + .common_ev = hamoa_common_ev, + .cpucp_legacy_freq_method = true, + .cpucp_sample_ms = 4, + .memory_cnt = ARRAY_SIZE(hamoa_memory_cfg), +}; + +static const struct scmi_qcom_memlat_cfg_data kaanapali_memlat_data = { + .memory_cfg = kaanapali_memory_cfg, + .common_ev = kaanapali_common_ev, + .cpucp_legacy_freq_method = true, + .cpucp_sample_ms = 4, + .memory_cnt = ARRAY_SIZE(kaanapali_memory_cfg), +}; + +static const struct of_device_id scmi_qcom_memlat_configs[] = { + { .compatible = "qcom,glymur", .data = &glymur_memlat_data }, + { .compatible = "qcom,mahua", .data = &glymur_memlat_data }, + { .compatible = "qcom,x1e80100", .data = &hamoa_memlat_data }, + { .compatible = "qcom,x1p42100", .data = &hamoa_memlat_data }, + { .compatible = "qcom,kaanapali", .data = &kaanapali_memlat_data }, + { } +}; + +static int memlat_set_param(struct scmi_qcom_memlat_info *info, void *msg, + size_t size, u32 param_id) +{ + return info->ops->set_param(info->ph, msg, size, MEMLAT_ALGO_STR, param_id); +} + +static int configure_cpucp_common_events(struct scmi_qcom_memlat_info *info) +{ + struct ev_map_msg ev = {}; + int i; + + ev.num_evs = cpu_to_le32(NUM_COMMON_EVS); + ev.hw_type = cpu_to_le32(MEMLAT_HW_TYPE_ALL); + for (i = 0; i < NUM_COMMON_EVS; i++) + ev.cid[i] = cpu_to_le32(info->cfg_data->common_ev[i]); + + return memlat_set_param(info, &ev, sizeof(ev), MEMLAT_SET_COMMON_EV_MAP); +} + +static int configure_cpucp_grp(struct device *dev, struct scmi_qcom_memlat_info *info, + int memory_index) +{ + const struct scmi_qcom_memory_cfg *cfg = &info->cfg_data->memory_cfg[memory_index]; + struct ev_map_msg ev = {}; + struct node_msg node = {}; + int ret, i; + + node.cpumask = cpu_to_le32(*cpumask_bits(cpu_possible_mask)); + node.hw_type = cpu_to_le32(cfg->memory_type); + + /* mon_type/mon_idx are don't-care for SET_MEM_GROUP; leave them zero. */ + ret = memlat_set_param(info, &node, sizeof(node), MEMLAT_SET_MEM_GROUP); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to configure mem type %d\n", + cfg->memory_type); + + ev.num_evs = cpu_to_le32(NUM_GRP_EVS); + ev.hw_type = cpu_to_le32(cfg->memory_type); + for (i = 0; i < NUM_GRP_EVS; i++) + ev.cid[i] = cpu_to_le32(cfg->grp_ev[i]); + + ret = memlat_set_param(info, &ev, sizeof(ev), MEMLAT_SET_GRP_EV_MAP); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to configure event map for mem type %d\n", + cfg->memory_type); + + return 0; +} + +static int configure_cpucp_mon(struct device *dev, struct scmi_qcom_memlat_info *info, + int memory_index, int monitor_index) +{ + const struct scmi_qcom_memory_cfg *cfg = &info->cfg_data->memory_cfg[memory_index]; + const struct scmi_qcom_monitor_cfg *mon = &cfg->monitor_cfg[monitor_index]; + struct scalar_param_msg scalar = {}; + struct map_param_msg map = {}; + struct node_msg node = {}; + int ret, i; + + if (mon->table_len > MEMLAT_MAX_MAP_ENTRIES) + return -EINVAL; + + node.cpumask = cpu_to_le32(mon->cpu_mask); + node.hw_type = cpu_to_le32(cfg->memory_type); + + /* The compute monitor passively scales with cpufreq irrespective of IPM ratio. */ + node.mon_type = cpu_to_le32(!mon->ipm_ceil); + node.mon_idx = cpu_to_le32(monitor_index); + strscpy(node.mon_name, mon->name, sizeof(node.mon_name)); + ret = memlat_set_param(info, &node, sizeof(node), MEMLAT_SET_MONITOR); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to configure monitor %s\n", mon->name); + + scalar.hw_type = cpu_to_le32(cfg->memory_type); + scalar.mon_idx = cpu_to_le32(monitor_index); + scalar.val = cpu_to_le32(mon->ipm_ceil); + ret = memlat_set_param(info, &scalar, sizeof(scalar), MEMLAT_IPM_CEIL); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to set ipm ceil for %s\n", mon->name); + + scalar.val = cpu_to_le32(mon->be_stall_floor); + ret = memlat_set_param(info, &scalar, sizeof(scalar), MEMLAT_BE_STALL_FLOOR); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to set be_stall_floor for %s\n", mon->name); + + map.hw_type = cpu_to_le32(cfg->memory_type); + map.mon_idx = cpu_to_le32(monitor_index); + map.nr_rows = cpu_to_le32(mon->table_len); + for (i = 0; i < mon->table_len; i++) { + map.tbl[i].cpu_freq_mhz = cpu_to_le16(mon->table[i].cpu_freq_mhz); + map.tbl[i].mem_freq_mhz = cpu_to_le16(mon->table[i].mem_freq_mhz); + } + ret = memlat_set_param(info, &map, sizeof(map), MEMLAT_MON_FREQ_MAP); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to configure freq_map for %s\n", mon->name); + + scalar.val = cpu_to_le32(cfg->memory_range.min_freq_khz); + ret = memlat_set_param(info, &scalar, sizeof(scalar), MEMLAT_SET_MIN_FREQ); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to set min_freq for %s\n", mon->name); + + scalar.val = cpu_to_le32(cfg->memory_range.max_freq_khz); + ret = memlat_set_param(info, &scalar, sizeof(scalar), MEMLAT_SET_MAX_FREQ); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to set max_freq for %s\n", mon->name); + + return 0; +} + +static int scmi_qcom_devfreq_get_cur_freq(struct device *dev, unsigned long *freq) +{ + struct scmi_qcom_memory_info *memory = dev_get_drvdata(dev); + const struct qcom_generic_ext_ops *ops = memory->ops; + const struct scmi_qcom_memory_cfg *cfg = memory->cfg; + u32 max_freq_khz = 0; + int ret, i; + + /* The bus's voted frequency is the max reported across all its monitors. */ + for (i = 0; i < cfg->monitor_cnt; i++) { + union cur_freq_msg msg = {}; + + msg.req.hw_type = cpu_to_le32(cfg->memory_type); + msg.req.mon_idx = cpu_to_le32(i); + + ret = ops->get_param(memory->ph, &msg, sizeof(msg.req), MEMLAT_ALGO_STR, + MEMLAT_GET_CUR_FREQ, sizeof(msg.resp)); + if (ret < 0) { + /* One monitor failing shouldn't abort the whole read-back. */ + dev_warn_once(dev, "failed to get current frequency for %s\n", + cfg->monitor_cfg[i].name); + continue; + } + + max_freq_khz = max(max_freq_khz, le32_to_cpu(msg.resp)); + } + + /* + * DDR/LLCC report a frequency in kHz (converted to Hz for the OPP + * table); DDR_QOS reports a 0/1 level mapped to its synthetic OPP keys. + */ + if (cfg->memory_range.max_freq_khz > 1) + *freq = (unsigned long)((u64)max_freq_khz * HZ_PER_KHZ); + else + *freq = max_freq_khz ? 100 : 1; + + return 0; +} + +static void scmi_qcom_memlat_teardown(struct scmi_qcom_memlat_info *info) +{ + for (int i = 0; i < info->memory_cnt; i++) { + struct scmi_qcom_memory_info *memory = info->memory[i]; + + if (!memory || !memory->fdev) + continue; + + if (memory->devfreq) + devfreq_remove_device(memory->devfreq); + dev_pm_opp_remove_all_dynamic(&memory->fdev->dev); + faux_device_destroy(memory->fdev); + } +} + +static int scmi_qcom_memlat_configure_events(struct scmi_device *sdev, + struct scmi_qcom_memlat_info *info) +{ + const struct qcom_generic_ext_ops *ops = info->ops; + struct scmi_protocol_handle *ph = info->ph; + __le32 sample_ms, freq_method; + int i, j, ret; + + ret = configure_cpucp_common_events(info); + if (ret < 0) + return dev_err_probe(&sdev->dev, ret, "failed to configure common events\n"); + + for (i = 0; i < info->memory_cnt; i++) { + ret = configure_cpucp_grp(&sdev->dev, info, i); + if (ret < 0) + return ret; + + for (j = 0; j < info->memory[i]->cfg->monitor_cnt; j++) { + ret = configure_cpucp_mon(&sdev->dev, info, i, j); + if (ret < 0) + return ret; + } + } + + sample_ms = cpu_to_le32(info->cfg_data->cpucp_sample_ms); + ret = memlat_set_param(info, &sample_ms, sizeof(sample_ms), MEMLAT_SAMPLE_MS); + if (ret < 0) + return dev_err_probe(&sdev->dev, ret, "failed to set sample_ms\n"); + + freq_method = cpu_to_le32(info->cfg_data->cpucp_legacy_freq_method); + ret = memlat_set_param(info, &freq_method, sizeof(freq_method), + MEMLAT_SET_EFFECTIVE_FREQ_METHOD); + if (ret < 0) + return dev_err_probe(&sdev->dev, ret, + "failed to set effective frequency calc method\n"); + + /* Start sampling and voting timer */ + ret = ops->start_activity(ph, NULL, 0, MEMLAT_ALGO_STR, MEMLAT_START_TIMER); + if (ret < 0) + return dev_err_probe(&sdev->dev, ret, "failed to start memory group timer\n"); + + for (i = 0; i < info->memory_cnt; i++) { + struct scmi_qcom_memory_info *memory = info->memory[i]; + const struct scmi_qcom_memory_range *range = &memory->cfg->memory_range; + struct devfreq_dev_profile *profile = &memory->profile; + + /* + * CPUCP re-evaluates and re-votes at most once per cpucp_sample_ms, + * so a new operating point can appear only that often. Polling at half + * that period guarantees each distinct vote is observed in trans_stat + * before it can change again. + */ + profile->polling_ms = max(1U, info->cfg_data->cpucp_sample_ms / 2); + profile->get_cur_freq = scmi_qcom_devfreq_get_cur_freq; + profile->initial_freq = range->max_freq_khz > 1 ? + (unsigned long)((u64)range->min_freq_khz * HZ_PER_KHZ) : + range->min_freq_khz; + + faux_device_set_drvdata(memory->fdev, memory); + + memory->devfreq = devfreq_add_device(&memory->fdev->dev, profile, + DEVFREQ_GOV_REMOTE, NULL); + if (IS_ERR(memory->devfreq)) { + ret = PTR_ERR(memory->devfreq); + memory->devfreq = NULL; + ops->stop_activity(ph, NULL, 0, MEMLAT_ALGO_STR, MEMLAT_STOP_TIMER); + return dev_err_probe(&sdev->dev, ret, "failed to add devfreq device\n"); + } + } + + return 0; +} + +static int scmi_qcom_memlat_setup(struct scmi_device *sdev, struct scmi_qcom_memlat_info *info) +{ + const struct scmi_qcom_memlat_cfg_data *cfg_data; + int ret, i, j; + + cfg_data = of_machine_get_match_data(scmi_qcom_memlat_configs); + if (!cfg_data) { + dev_dbg(&sdev->dev, "no memlat config data for this platform\n"); + return -ENODEV; + } + + info->cfg_data = cfg_data; + info->memory = devm_kcalloc(&sdev->dev, cfg_data->memory_cnt, + sizeof(*info->memory), GFP_KERNEL); + if (!info->memory) + return -ENOMEM; + + for (i = 0; i < cfg_data->memory_cnt; i++) { + const struct scmi_qcom_memory_cfg *memory_cfg = &cfg_data->memory_cfg[i]; + struct scmi_qcom_memory_info *memory; + + memory = devm_kzalloc(&sdev->dev, sizeof(*memory), GFP_KERNEL); + if (!memory) { + ret = -ENOMEM; + goto err_teardown; + } + + memory->cfg = memory_cfg; + memory->ops = info->ops; + memory->ph = info->ph; + info->memory[i] = memory; + + memory->fdev = faux_device_create(memory_cfg->name, &sdev->dev, NULL); + if (!memory->fdev) { + ret = dev_err_probe(&sdev->dev, -ENODEV, + "failed to create faux device\n"); + goto err_teardown; + } + info->memory_cnt = i + 1; + + for (j = 0; j < memory_cfg->num_opps; j++) { + struct dev_pm_opp_data data = { + .freq = memory_cfg->mem_table[j].freq, + }; + + ret = dev_pm_opp_add_dynamic(&memory->fdev->dev, &data); + if (ret) { + dev_err_probe(&sdev->dev, ret, "failed to add OPP\n"); + goto err_teardown; + } + } + } + + return 0; + +err_teardown: + scmi_qcom_memlat_teardown(info); + return ret; +} + +static int scmi_qcom_devfreq_memlat_probe(struct scmi_device *sdev) +{ + const struct scmi_handle *handle = sdev->handle; + const struct qcom_generic_ext_ops *ops; + struct scmi_qcom_memlat_info *info; + struct scmi_protocol_handle *ph; + int ret; + + if (!handle) + return -ENODEV; + + info = devm_kzalloc(&sdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_QCOM_GENERIC, &ph); + if (IS_ERR(ops)) + return PTR_ERR(ops); + + info->ops = ops; + info->ph = ph; + + ret = scmi_qcom_memlat_setup(sdev, info); + if (ret) + return ret; + + ret = scmi_qcom_memlat_configure_events(sdev, info); + if (ret) { + scmi_qcom_memlat_teardown(info); + return ret; + } + + dev_set_drvdata(&sdev->dev, info); + + return 0; +} + +static void scmi_qcom_devfreq_memlat_remove(struct scmi_device *sdev) +{ + struct scmi_qcom_memlat_info *info = dev_get_drvdata(&sdev->dev); + int ret; + + ret = info->ops->stop_activity(info->ph, NULL, 0, MEMLAT_ALGO_STR, MEMLAT_STOP_TIMER); + if (ret < 0) + dev_err(&sdev->dev, "failed to stop memory group timer\n"); + + scmi_qcom_memlat_teardown(info); +} + +static const struct scmi_device_id scmi_id_table[] = { + { SCMI_PROTOCOL_QCOM_GENERIC, "qcom-generic-ext" }, + { }, +}; +MODULE_DEVICE_TABLE(scmi, scmi_id_table); + +static struct scmi_driver scmi_qcom_devfreq_memlat_driver = { + .name = "scmi-qcom-devfreq-memlat", + .probe = scmi_qcom_devfreq_memlat_probe, + .remove = scmi_qcom_devfreq_memlat_remove, + .id_table = scmi_id_table, +}; +module_scmi_driver(scmi_qcom_devfreq_memlat_driver); + +MODULE_AUTHOR("Pragnesh Papaniya "); +MODULE_AUTHOR("Sibi Sankar "); +MODULE_DESCRIPTION("Qualcomm SCMI memlat devfreq driver"); +MODULE_LICENSE("GPL"); From 7acfd264490b6f6c62b367a81f1ef793f3dad92b Mon Sep 17 00:00:00 2001 From: Iranna Mundaganur Date: Wed, 28 Oct 2026 12:22:26 +0530 Subject: [PATCH 0484/1133] FROMLIST: soc: qcom: icc-bwmon: Update zone1_thres_count to 3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce zone1_thres_count from 16 to 3 so the driver can lower the bus vote after 3 sample windows instead of waiting for 16. The previous 16‑window delay (~64 ms) is too long at higher FPS workloads, causing delayed decision making and measurable power regression. Empirical tuning showed that lower values (e.g., 2) made bwmon behavior jittery, while higher values (4–6) were stable but less responsive and reduced power savings. A value of 3 provided the best balance: responsive enough for timely power reduction while maintaining stable bwmon operation. Significant power savings were observed across multiple use cases when reducing the threshold from 16 to 3: USECASE zone1_thres_count=16 zone1_thres_count=3 4K video playback 236.15 mA 203.15 mA Sleep 7mA 6.9mA Display (idle display) 71.95mA 67.11mA Signed-off-by: Shivnandan Kumar Signed-off-by: Pushpendra Singh Signed-off-by: Iranna Mundaganur Link: https://lore.kernel.org/all/20260227111051.1789439-1-pussin@qti.qualcomm.com/ --- drivers/soc/qcom/icc-bwmon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 597f9025e4228..e46975da7dba6 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -830,7 +830,7 @@ static const struct icc_bwmon_data msm8998_bwmon_data = { static const struct icc_bwmon_data sdm845_cpu_bwmon_data = { .sample_ms = 4, .count_unit_kb = 64, - .zone1_thres_count = 16, + .zone1_thres_count = 3, .zone3_thres_count = 1, .quirks = BWMON_HAS_GLOBAL_IRQ, .regmap_fields = sdm845_cpu_bwmon_reg_fields, @@ -849,7 +849,7 @@ static const struct icc_bwmon_data sdm845_llcc_bwmon_data = { static const struct icc_bwmon_data sc7280_llcc_bwmon_data = { .sample_ms = 4, .count_unit_kb = 64, - .zone1_thres_count = 16, + .zone1_thres_count = 3, .zone3_thres_count = 1, .quirks = BWMON_NEEDS_FORCE_CLEAR, .regmap_fields = sdm845_llcc_bwmon_reg_fields, From 8533928130b31243609ca60255cb8b8d7f701bae Mon Sep 17 00:00:00 2001 From: Kamal Wadhwa Date: Fri, 9 Oct 2026 17:36:05 +0530 Subject: [PATCH 0485/1133] FROMLIST: arm64: dts: qcom: glymur-crd: Mark L4C regulator as boot-on to save power On current Glymur Rev-1 boards, the third USB controller and PHY are not enabled, so the L4C regulator has no active consumers. The regulator node cannot be removed, however, since Rev-2 boards will enable the corresponding USB hardware. This rail may have been left enabled by the bootloader. The RPMH regulator driver cannot query real hardware state, so without regulator-boot-on the core assumes the rail is already off and never issues an explicit disable during late cleanup, leaving it enabled indefinitely while unused. Add regulator-boot-on so the core knows to explicitly disable the rail during late cleanup when no consumers are present. Link: https://lore.kernel.org/all/20261009-b4-regulator-boot-on-l4c-v1-1-7b76c2b2ea76@oss.qualcomm.com/ Signed-off-by: Kamal Wadhwa Reviewed-by: Abel Vesa --- arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi index b8c95f5755c73..b52845f5d8cf3 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi @@ -565,6 +565,7 @@ regulator-min-microvolt = <720000>; regulator-max-microvolt = <720000>; regulator-initial-mode = ; + regulator-boot-on; }; }; From 1ae92a7170667da160a30d12f6df860318510ee4 Mon Sep 17 00:00:00 2001 From: Anvesh Jain P Date: Mon, 28 Sep 2026 12:06:37 +0530 Subject: [PATCH 0486/1133] FROMLIST: dt-bindings: embedded-controller: qcom,hamoa-crd-ec: Add thermal sensors Describe the Hamoa embedded controller as a thermal-sensor provider for firmware-reported thermistors. The populated channels are discovered from the EC firmware capability response. Link: https://lore.kernel.org/all/20260928-ec_thermistor_support-v1-1-d9c1bae4cd0d@oss.qualcomm.com/ Signed-off-by: Anvesh Jain P Signed-off-by: Sibi Sankar --- .../embedded-controller/qcom,hamoa-crd-ec.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/embedded-controller/qcom,hamoa-crd-ec.yaml b/Documentation/devicetree/bindings/embedded-controller/qcom,hamoa-crd-ec.yaml index aa23382595c22..6280af952e19f 100644 --- a/Documentation/devicetree/bindings/embedded-controller/qcom,hamoa-crd-ec.yaml +++ b/Documentation/devicetree/bindings/embedded-controller/qcom,hamoa-crd-ec.yaml @@ -15,6 +15,9 @@ description: EC running on different MCU chips. The EC handles things like fan control, temperature sensors, access to EC internal state changes. +allOf: + - $ref: /schemas/thermal/thermal-sensor.yaml# + properties: compatible: oneOf: @@ -35,6 +38,14 @@ properties: interrupts: maxItems: 1 + "#thermal-sensor-cells": + description: + The EC exposes up to 7 onboard thermistors (indices 0-6). Which + indices are physically populated on a given board is discovered at + runtime from EC firmware capabilities; a board may reference any index + 0-6. + const: 1 + required: - compatible - reg @@ -52,6 +63,7 @@ examples: embedded-controller@76 { compatible = "qcom,hamoa-crd-ec"; reg = <0x76>; + #thermal-sensor-cells = <1>; interrupts-extended = <&tlmm 66 IRQ_TYPE_LEVEL_HIGH>; }; From c46f06d11b1192572b2841acb93e111c84692f8a Mon Sep 17 00:00:00 2001 From: Anvesh Jain P Date: Mon, 28 Sep 2026 12:06:38 +0530 Subject: [PATCH 0487/1133] FROMLIST: platform: arm64: qcom-hamoa-ec: Add thermistor sensors The Qualcomm embedded controller has exclusive access to multiple onboard thermistors programmatically discoverable through the EC_THERMAL_CAPABILITIES command. The temperature values are reported in degree Celsius through the EC_THERMISTOR_TEMP_CMD. Register these thermistors with the thermal framework by adding support to the EC_THERMISTOR_TEMP_CMD and convert it to millidegree units as required by the thermal framework. Link: https://lore.kernel.org/all/20260928-ec_thermistor_support-v1-2-d9c1bae4cd0d@oss.qualcomm.com/ Signed-off-by: Anvesh Jain P Signed-off-by: Sibi Sankar --- drivers/platform/arm64/qcom-hamoa-ec.c | 74 ++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/drivers/platform/arm64/qcom-hamoa-ec.c b/drivers/platform/arm64/qcom-hamoa-ec.c index d34afd901324d..a921986c55304 100644 --- a/drivers/platform/arm64/qcom-hamoa-ec.c +++ b/drivers/platform/arm64/qcom-hamoa-ec.c @@ -16,16 +16,19 @@ #include #include #include +#include #define EC_SCI_EVT_READ_CMD 0x05 #define EC_FW_VERSION_CMD 0x0e #define EC_MODERN_STANDBY_CMD 0x23 +#define EC_THERMISTOR_TEMP_CMD 0x29 /* + thermistor_id (0-6) selects thermistor 1-7 */ #define EC_FAN_DBG_CONTROL_CMD 0x30 #define EC_SCI_EVT_CONTROL_CMD 0x35 #define EC_THERMAL_CAP_CMD 0x42 #define EC_FW_VERSION_RESP_LEN 4 #define EC_THERMAL_CAP_RESP_LEN 3 +#define EC_THERMISTOR_TEMP_RESP_LEN 3 #define EC_FAN_DEBUG_CMD_LEN 6 #define EC_FAN_SPEED_DATA_SIZE 4 @@ -39,6 +42,7 @@ #define EC_MAX_FAN_CNT 2 #define EC_FAN_NAME_SIZE 20 #define EC_FAN_MAX_PWM 255 +#define EC_MAX_THERMISTOR_CNT 7 enum qcom_ec_sci_events { EC_FAN1_STATUS_CHANGE_EVT = 0x30, @@ -64,6 +68,7 @@ struct qcom_ec_thermal_cap { #define EC_THERMAL_FAN_CNT(x) (FIELD_GET(GENMASK(1, 0), (x))) #define EC_THERMAL_FAN_TYPE(x) (FIELD_GET(GENMASK(4, 2), (x))) #define EC_THERMAL_THERMISTOR_MASK(x) (FIELD_GET(GENMASK(7, 0), (x))) +#define EC_THERMISTOR_PRESENT(mask, id) ((mask) & BIT(id)) u8 fan_cnt; u8 fan_type; u8 thermistor_mask; @@ -81,6 +86,12 @@ struct qcom_ec { struct qcom_ec_thermal_cap thermal_cap; struct qcom_ec_version version; struct i2c_client *client; + struct qcom_ec_thermal_zone *ec_tz; +}; + +struct qcom_ec_thermal_zone { + struct qcom_ec *ec; + u8 thermistor_id; }; static int qcom_ec_read(struct qcom_ec *ec, u8 cmd, u8 resp_len, u8 *resp) @@ -183,6 +194,43 @@ static int qcom_ec_thermal_capabilities(struct device *dev) return 0; } +/* + * EC Thermistor Temperature (cmd 0x29 + thermistor_id, id 0-6 selects + * thermistor 1-7): + * + * Read Response: + * ---------------------------------------------------------------------- + * | Offset | Name | Description | + * ---------------------------------------------------------------------- + * | 0x00 | Byte count | Number of bytes in response (=2) | + * ---------------------------------------------------------------------- + * | 0x01 (LSB)| Temperature | Signed 16-bit, unit of 0.1 degC, | + * | 0x02 (MSB)| | range -40..+125 degC | + * ---------------------------------------------------------------------- + */ +static int qcom_ec_thermistor_get_temp(struct thermal_zone_device *tz, int *temp) +{ + struct qcom_ec_thermal_zone *ec_tz = thermal_zone_device_priv(tz); + struct qcom_ec *ec = ec_tz->ec; + u8 resp[EC_THERMISTOR_TEMP_RESP_LEN]; + s16 raw; + int ret; + + ret = qcom_ec_read(ec, EC_THERMISTOR_TEMP_CMD + ec_tz->thermistor_id, + EC_THERMISTOR_TEMP_RESP_LEN, resp); + if (ret < 0) + return ret; + + raw = (s16)get_unaligned_le16(&resp[1]); + *temp = raw * 100; + + return 0; +} + +static const struct thermal_zone_device_ops qcom_ec_thermistor_ops = { + .get_temp = qcom_ec_thermistor_get_temp, +}; + static irqreturn_t qcom_ec_irq(int irq, void *data) { struct qcom_ec *ec = data; @@ -387,6 +435,32 @@ static int qcom_ec_probe(struct i2c_client *client) if (ret < 0) return dev_err_probe(dev, ret, "Failed to read thermal capabilities\n"); + if (ec->thermal_cap.thermistor_mask) { + ec->ec_tz = devm_kcalloc(dev, EC_MAX_THERMISTOR_CNT, sizeof(*ec->ec_tz), + GFP_KERNEL); + if (!ec->ec_tz) + return -ENOMEM; + + for (i = 0; i < EC_MAX_THERMISTOR_CNT; i++) { + struct qcom_ec_thermal_zone *ec_tz = &ec->ec_tz[i]; + struct thermal_zone_device *tzd; + + if (!EC_THERMISTOR_PRESENT(ec->thermal_cap.thermistor_mask, i)) + continue; + + ec_tz->ec = ec; + ec_tz->thermistor_id = i; + + tzd = devm_thermal_of_zone_register(dev, i, ec_tz, &qcom_ec_thermistor_ops); + if (IS_ERR(tzd)) { + ret = PTR_ERR(tzd); + if (ret != -ENODEV) + dev_warn(dev, "Failed to register thermistor%u zone: %d\n", + i, ret); + } + } + } + if (ec->thermal_cap.fan_cnt == 0) { dev_warn(dev, FW_BUG "Failed to get fan count, firmware update required\n"); return 0; From 93ef91e550ff9759daab5581e998cada8f35eaf7 Mon Sep 17 00:00:00 2001 From: Ananthu C V Date: Tue, 29 Sep 2026 17:08:06 +0530 Subject: [PATCH 0488/1133] FROMLIST: arch_topology: seed capacity_freq_ref with highest available frequency capacity_freq_ref, the per-CPU frequency-invariance reference used by schedutil, is seeded from policy->cpuinfo.max_freq at policy creation. If boost isn't enabled yet at boot, max_freq reflects only the non-boost ceiling, so capacity_freq_ref never learns about boost frequencies for the policy's lifetime. Enabling boost later raises policy->max, but capacity_freq_ref stays stale, leaving schedutil unable to scale utilization or target a frequency above the non-boost maximum. Seed capacity_freq_ref with the highest available frequency regardless of whether boost is enabled. Runtime enforcement, still handled by policy->max, is unaffected. Link: https://lore.kernel.org/all/20260929-schedutil-boost-frequency-handling-v3-1-68de169498c7@oss.qualcomm.com/ Suggested-by: Vincent Guittot Signed-off-by: Ananthu C V Tested-by: Oleg Keri # Lenovo Yoga Slim 7x Gen 11 --- drivers/base/arch_topology.c | 3 ++- include/linux/cpufreq.h | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 8c5e47c28d9a3..92966be712d56 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -404,7 +404,8 @@ init_cpu_capacity_callback(struct notifier_block *nb, cpumask_andnot(cpus_to_visit, cpus_to_visit, policy->related_cpus); for_each_cpu(cpu, policy->related_cpus) { - per_cpu(capacity_freq_ref, cpu) = policy->cpuinfo.max_freq; + per_cpu(capacity_freq_ref, cpu) = max(policy->cpuinfo.max_freq, + cpufreq_frequency_table_max(policy)); freq_inv_set_max_ratio(cpu, per_cpu(capacity_freq_ref, cpu) * HZ_PER_KHZ); } diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index d3d0d9d02aa4a..a571b35071e2e 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -1110,6 +1110,19 @@ static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy, return idx; } +static inline unsigned int cpufreq_frequency_table_max(struct cpufreq_policy *policy) +{ + int idx; + + if (!policy->freq_table) + return policy->cpuinfo.max_freq; + + idx = cpufreq_frequency_table_target(policy, UINT_MAX, 0, UINT_MAX, + CPUFREQ_RELATION_H); + + return policy->freq_table[idx].frequency; +} + static inline int cpufreq_table_count_valid_entries(const struct cpufreq_policy *policy) { struct cpufreq_frequency_table *pos; From 40b3c1f97688b9bef9e26072c625af3a2c97dde4 Mon Sep 17 00:00:00 2001 From: Ananthu C V Date: Tue, 29 Sep 2026 17:08:07 +0530 Subject: [PATCH 0489/1133] FROMLIST: cpufreq: fix policy max not returning to non-boost freq on boost disable Commit 538b0188da46 ("cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known") introduced a guard for cpuinfo max updates to only increase, to preserve driver-set values above the freq table maximum. Later commit db80ad776cd2 ("cpufreq: Remove driver default policy->min/max init") dropped the 'policy->max = max_freq' assignment from cpufreq_frequency_table_cpuinfo, leaving that one-way-guard to be the only path for cpuinfo max and consequently policy max to be updated, causing both values to be stuck at boost frequency even when boost is disabled. Unconditionally track the highest non-boost frequency (max_base_freq) in the freq table. If boost frequencies are available, use the highest frequency from the table/max_base_freq instead of cpuinfo->max_freq to control boost values, so the value can decrease again when boost is disabled. Link: https://lore.kernel.org/all/20260929-schedutil-boost-frequency-handling-v3-2-68de169498c7@oss.qualcomm.com/ Fixes: db80ad776cd2 ("cpufreq: Remove driver default policy->min/max init") Signed-off-by: Ananthu C V Tested-by: Oleg Keri # Lenovo Yoga Slim 7x Gen 11 --- drivers/cpufreq/cpufreq.c | 16 +++++++++++++++- drivers/cpufreq/freq_table.c | 9 ++++++++- include/linux/cpufreq.h | 3 +++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 54dde8419bdc4..e7cc77632e567 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -574,6 +574,8 @@ static ssize_t show_local_boost(struct cpufreq_policy *policy, char *buf) static int policy_set_boost(struct cpufreq_policy *policy, bool enable) { + unsigned int max_freq; + unsigned int max_table_freq; int ret; if (policy->boost_enabled == enable) @@ -587,7 +589,19 @@ static int policy_set_boost(struct cpufreq_policy *policy, bool enable) return ret; } - ret = freq_qos_update_request(&policy->boost_freq_req, policy->cpuinfo.max_freq); + max_table_freq = cpufreq_frequency_table_max(policy); + + if (policy_has_boost_freq(policy)) { + max_freq = enable ? max_table_freq : policy->cpuinfo.max_base_freq; + + if (!max_freq) + /* when the freq table contains only boost frequencies */ + max_freq = max_table_freq; + } else { + max_freq = policy->cpuinfo.max_freq; + } + + ret = freq_qos_update_request(&policy->boost_freq_req, max_freq); if (ret < 0) { policy->boost_enabled = !policy->boost_enabled; cpufreq_driver->set_boost(policy, policy->boost_enabled); diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index ea994647abc88..820ed4559f6c1 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -14,7 +14,7 @@ * FREQUENCY TABLE HELPERS * *********************************************************************/ -static bool policy_has_boost_freq(struct cpufreq_policy *policy) +bool policy_has_boost_freq(struct cpufreq_policy *policy) { struct cpufreq_frequency_table *pos, *table = policy->freq_table; @@ -27,17 +27,22 @@ static bool policy_has_boost_freq(struct cpufreq_policy *policy) return false; } +EXPORT_SYMBOL_GPL(policy_has_boost_freq); int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy) { struct cpufreq_frequency_table *pos, *table = policy->freq_table; unsigned int min_freq = ~0; unsigned int max_freq = 0; + unsigned int max_base_freq = 0; unsigned int freq, i; cpufreq_for_each_valid_entry_idx(pos, table, i) { freq = pos->frequency; + if (!(pos->flags & CPUFREQ_BOOST_FREQ) && freq > max_base_freq) + max_base_freq = freq; + if ((!cpufreq_boost_enabled() || !policy->boost_enabled) && (pos->flags & CPUFREQ_BOOST_FREQ)) continue; @@ -57,6 +62,8 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy) if (policy->cpuinfo.max_freq < max_freq) policy->cpuinfo.max_freq = max_freq; + policy->cpuinfo.max_base_freq = max_base_freq; + if (min_freq == ~0) return -EINVAL; else diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index a571b35071e2e..aa8dadcbd10d9 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -45,6 +45,7 @@ enum cpufreq_table_sorting { struct cpufreq_cpuinfo { unsigned int max_freq; unsigned int min_freq; + unsigned int max_base_freq; /* Highest non-boost frequency in the table */ /* in 10^(-9) s = nanoseconds */ unsigned int transition_latency; @@ -794,6 +795,8 @@ struct cpufreq_frequency_table { int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy); +bool policy_has_boost_freq(struct cpufreq_policy *policy); + int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy); int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy); From d707a71ffeff477f092126a5b36c9e9b08abaf2a Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Sat, 26 Sep 2026 10:49:16 +0530 Subject: [PATCH 0490/1133] Revert "ASoC: qcom: audioreach: compute active channel maps from channel_map" The change regresses the audio record test case on Hamoa. Revert it to restore the previous channel mapping behavior for the record path. [ 682.119643] qcom-apm gprsvc:service:2:1: Error (1) Processing 0x01001002 cmd [ 682.119652] qcom-apm gprsvc:service:2:1: DSP returned error[1001002] 1 [ 682.119659] q6apm-lpass-dais 6800000.remoteproc:glink-edge:gpr:service@1:bedais: Failed to start APM port 110 [ 682.119661] q6apm-lpass-dais 6800000.remoteproc:glink-edge:gpr:service@1:bedais: ASoC error (-22): at soc_dai_trigger() on VA_CODEC_DMA_TX_0 [ 682.119664] MultiMedia4 Capture: ASoC error (-22): at dpcm_be_dai_trigger() on MultiMedia4 Capture [ 682.119666] MultiMedia4 Capture: ASoC error (-22): trigger FE cmd: 1 failed This reverts commit c663014e452d69d5f34b8b16fecf1590b3696082. Fixes: c663014e452d ("ASoC: qcom: audioreach: compute active channel maps from channel_map") Signed-off-by: Salendarsingh Gaud --- sound/soc/qcom/qdsp6/audioreach.c | 47 +++++++------------------------ 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c index d2dc5d37bccf8..0350afb5995a0 100644 --- a/sound/soc/qcom/qdsp6/audioreach.c +++ b/sound/soc/qcom/qdsp6/audioreach.c @@ -719,7 +719,6 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph, int pm_sz = APM_HW_EP_PMODE_CFG_PSIZE; int size = ic_sz + ep_sz + fs_sz + pm_sz; void *p; - int i; struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); if (IS_ERR(pkt)) @@ -758,12 +757,7 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph, intf_cfg->cfg.lpaif_type = module->hw_interface_type; intf_cfg->cfg.intf_index = module->hw_interface_idx; - intf_cfg->cfg.active_channels_mask = 0; - /* Convert the physical channel mapping into a bit field */ - for (i = 0; i < AR_PCM_MAX_NUM_CHANNEL; i++) - if (cfg->channel_map[i]) - intf_cfg->cfg.active_channels_mask |= BIT(i); - + intf_cfg->cfg.active_channels_mask = (1 << cfg->num_channels) - 1; p += ic_sz; pm_cfg = p; @@ -862,7 +856,7 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph, uint32_t num_channels = cfg->num_channels; int payload_size = APM_MFC_CFG_PSIZE(media_format, num_channels) + APM_MODULE_PARAM_DATA_SIZE; - int i, j; + int i; void *p; struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); @@ -882,12 +876,8 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph, media_format->sample_rate = cfg->sample_rate; media_format->bit_width = cfg->bit_width; media_format->num_channels = cfg->num_channels; - /* Convert the physical mapping to a logical mapping of the channels */ - for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) { - if (!cfg->channel_map[i]) - continue; - media_format->channel_mapping[j++] = cfg->channel_map[i]; - } + for (i = 0; i < num_channels; i++) + media_format->channel_mapping[i] = cfg->channel_map[i]; return q6apm_send_cmd_sync(graph->apm, pkt, 0); } @@ -1183,7 +1173,6 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph, struct apm_pcm_module_media_fmt_cmd *cfg; struct apm_module_param_data *param_data; int payload_size; - int i, j; if (num_channels > 4) { dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels); @@ -1217,12 +1206,7 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph, media_cfg->num_channels = mcfg->num_channels; media_cfg->q_factor = mcfg->bit_width - 1; media_cfg->bits_per_sample = mcfg->bit_width; - /* Convert the physical mapping to a logical mapping of the channels */ - for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < mcfg->num_channels; i++) { - if (!mcfg->channel_map[i]) - continue; - media_cfg->channel_mapping[j++] = mcfg->channel_map[i]; - } + memcpy(media_cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels); return q6apm_send_cmd_sync(graph->apm, pkt, 0); } @@ -1272,7 +1256,6 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph, struct payload_media_fmt_pcm *cfg; struct media_format *header; int rc, payload_size; - int i, j; void *p; if (num_channels > 4) { @@ -1312,12 +1295,7 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph, cfg->q_factor = mcfg->bit_width - 1; cfg->endianness = PCM_LITTLE_ENDIAN; cfg->num_channels = mcfg->num_channels; - /* Convert the physical mapping to a logical mapping of the channels */ - for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) { - if (!mcfg->channel_map[i]) - continue; - cfg->channel_mapping[j++] = mcfg->channel_map[i]; - } + memcpy(cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels); } else { rc = audioreach_set_compr_media_format(header, p, mcfg); if (rc) @@ -1394,7 +1372,7 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph, struct apm_module_sp_vi_ex_mode_cfg *ex_cfg; int op_sz, cm_sz, ex_sz; struct apm_module_param_data *param_data; - int rc, i, payload_size, j; + int rc, i, payload_size; struct gpr_pkt *pkt; void *p; @@ -1435,19 +1413,14 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph, param_data->param_size = cm_sz - APM_MODULE_PARAM_DATA_SIZE; cm_cfg->cfg.num_channels = num_channels * 2; - /* Convert the physical mapping to a logical mapping of the channels */ - for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < num_channels; i++) { - if (!mcfg->channel_map[i]) - continue; + for (i = 0; i < num_channels; i++) { /* * Map speakers into Vsense and then Isense of each channel. * E.g. for PCM_CHANNEL_FL and PCM_CHANNEL_FR to: * [1, 2, 3, 4] */ - cm_cfg->cfg.channel_mapping[2 * j] = (mcfg->channel_map[i] - 1) * 2 + 1; - cm_cfg->cfg.channel_mapping[2 * j + 1] = (mcfg->channel_map[i] - 1) * 2 + 2; - - ++j; + cm_cfg->cfg.channel_mapping[2 * i] = (mcfg->channel_map[i] - 1) * 2 + 1; + cm_cfg->cfg.channel_mapping[2 * i + 1] = (mcfg->channel_map[i] - 1) * 2 + 2; } p += cm_sz; From e96017a20ee7a0067cfd4d8a35491d7e00faebba Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 22 Sep 2026 21:05:05 +0530 Subject: [PATCH 0491/1133] PENDING: ASoC: SDCA: fix probe races and improve codec driver integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address several issues in the SDCA class framework and add support for codec-specific SDCA SoundWire drivers.   Changes include: - Fix race between class_boot_work() and sdw_bus_probe() by waiting for SoundWire probe completion before IRQ allocation. - Re-enable IRQs when pm_runtime_force_suspend() fails. - Cancel deferred boot work through devres to avoid use-after-free issues during probe unwind. - Correct pm_runtime reference handling during probe. - Export sdca_class_read_prop() for reuse by codec-specific drivers. - Add sdca_class_hw_ops with hw_init() support. - Add populate_function() callback support for DT-based SDCA devices. - Export sdca_class_pm_ops for codec driver integration. - Allow per-port BPS configuration by deferring BPS selection to compute_params() implementations.   These changes improve probe reliability, runtime PM handling and enable integration of codec-specific SDCA implementations such as WCD9378-SDCA. Signed-off-by: Mohammad Rafi Shaik --- include/sound/sdca_class.h | 39 +++++++-- sound/soc/codecs/wcd9378-sdca.c | 124 +++++++++++++++++++++++++-- sound/soc/sdca/sdca_class.c | 69 ++++++++++++--- sound/soc/sdca/sdca_class_function.c | 22 ++++- sound/soc/sdca/sdca_jack.c | 11 +++ 5 files changed, 236 insertions(+), 29 deletions(-) diff --git a/include/sound/sdca_class.h b/include/sound/sdca_class.h index 794a756472cd6..5170763f9b4ad 100644 --- a/include/sound/sdca_class.h +++ b/include/sound/sdca_class.h @@ -20,16 +20,38 @@ struct sdw_slave; struct sdca_function_data; /** - * struct sdca_class_ops - optional codec-provided class callbacks + * struct sdca_class_hw_ops - optional codec hardware callbacks + * @hw_init: enable supplies, toggle reset, etc. Runs from sdca_class_probe() + * before the class regmap is created and before the slave is + * ATTACHED; callers needing bus I/O must sdw_slave_wait_for_init() + * first. * @populate_function: fill @function (entities, clusters, init_table, ...) * from static tables in place of sdca_parse_function() on * DT/non-DisCo platforms. Called once per SDCA function with - * @dev pointing at that function's device. Pure data source; - * performs no bus I/O. Return 0 on success or a negative errno. + * @dev pointing at that function's device. Must leave + * @function->desc alone. Pure data source; performs no bus + * I/O. Return 0 on success or a negative errno. May be NULL. + * @set_jack: called from the SDCA class function driver's ASoC .set_jack, + * after the jack has been registered with sdca_jack_set_jack(); + * use to enable hardware detection (e.g. arm the MBHC comparator) + * that must not be turned on any earlier, since doing so before + * the machine driver has finished registering the jack can raise + * a detection interrupt that blocks the deferred card probe. + * May be NULL. + * @ge_mode_detected: called from sdca_jack_process() every time a GE + * DETECTED_MODE interrupt fires, unlike @set_jack which only + * runs once at jack registration; use to re-arm hardware + * detection logic that must be reconfigured after every + * transition (e.g. toggling a mechanical comparator's + * polarity-select bit so the next opposite-direction transition + * is still seen). May be NULL. */ -struct sdca_class_ops { +struct sdca_class_hw_ops { + int (*hw_init)(struct sdw_slave *slave); int (*populate_function)(struct device *dev, struct sdca_function_data *function); + int (*set_jack)(struct sdw_slave *slave, struct regmap *dev_regmap); + int (*ge_mode_detected)(struct sdw_slave *slave, struct regmap *dev_regmap); }; struct sdca_class_drv { @@ -39,7 +61,7 @@ struct sdca_class_drv { struct sdca_interrupt_info *irq_info; - const struct sdca_class_ops *ops; + const struct sdca_class_hw_ops *hw_ops; struct mutex regmap_lock; /* Serialise function initialisations */ @@ -48,9 +70,10 @@ struct sdca_class_drv { }; /* Library helpers used by codec-specific SDCA SoundWire drivers. */ +int sdca_class_read_prop(struct sdw_slave *sdw); int sdca_class_probe(struct sdw_slave *sdw, struct sdca_class_drv *drv, - const struct sdca_class_ops *ops); + const struct sdca_class_hw_ops *hw_ops); void sdca_class_remove(struct sdca_class_drv *drv); /* @@ -61,10 +84,14 @@ void sdca_class_remove(struct sdca_class_drv *drv); * struct wcd_priv *priv = dev_get_drvdata(dev); * return sdca_class_runtime_suspend(&priv->class); * } + * + * The built-in class_sdw_driver in sdca_class.c uses sdca_class_pm_ops + * directly because it stashes the sdca_class_drv in drvdata itself. */ int sdca_class_runtime_suspend(struct sdca_class_drv *drv); int sdca_class_runtime_resume(struct sdca_class_drv *drv); int sdca_class_system_suspend(struct sdca_class_drv *drv); int sdca_class_system_resume(struct sdca_class_drv *drv); +extern const struct dev_pm_ops sdca_class_pm_ops; #endif /* __SDCA_CLASS_H__ */ diff --git a/sound/soc/codecs/wcd9378-sdca.c b/sound/soc/codecs/wcd9378-sdca.c index 7c15f885390ce..37a666bcae09d 100644 --- a/sound/soc/codecs/wcd9378-sdca.c +++ b/sound/soc/codecs/wcd9378-sdca.c @@ -813,8 +813,17 @@ static struct sdca_init_write wcd9378_sdca_init_table[] = { { .addr = 0x401804f2, .val = 0x80 }, /* DRE_DLY_VAL SWR_HPHL(0) */ { .addr = 0x401804f2, .val = 0x00 }, /* DRE_DLY_VAL SWR_HPHR(0) */ { .addr = 0x40180501, .val = 0x01 }, /* SEQR_CTRL SYS_USAGE_CTRL */ - /* Arms MBHC: jack insertion asserts SDCA_4 (GE_DETECTED_MODE). */ - { .addr = 0x40180601, .val = 0x01 }, /* MBHC_CTRL DEVICE_DET */ + /* + * Arms MBHC: jack insertion asserts SDCA_4 (GE_DETECTED_MODE). + * ACCESSORY_TYPE[2:0] (bits 2:0 of this register) selects what + * Detected_Mode/Selected_Mode the HW FSM pops on insertion; reset + * default is 3 (Headset). Keep it at 3 here -- writing 1 forces + * Jack_Unknown, which only updates Detected_Mode and leaves + * Selected_Mode untouched, so sdca_jack_process()'s own + * Jack_Unknown-substitution logic ends up reporting a stale + * Selected_Mode=0 on every insertion. + */ + { .addr = 0x40180601, .val = 0x03 }, /* MBHC_CTRL DEVICE_DET */ { .addr = 0x40180414, .val = 0x00 }, /* CDC_COMP_CTL_0 */ { .addr = 0x401804f2, .val = 0x88 }, /* DRE_DLY_VAL */ { .addr = 0x40180517, .val = 0x07 }, /* SEQR_CTRL HPH_UP_T7 */ @@ -832,10 +841,6 @@ static struct sdca_init_write wcd9378_sdca_init_table[] = { { .addr = 0x0000005c, .val = 0x10 }, /* INTMASK_1 SDCA_4 (GE_DETECTED_MODE) */ { .addr = 0x4018016a, .val = 0x00 }, /* CP_DTOP_CTRL_14 */ { .addr = 0x40180165, .val = 0x6b }, /* CP_DTOP_CTRL_9 */ - /* - * L_DET_EN is left disabled: asserting SDCA_4 before the machine - * card registers the jack blocks the deferred card probe. - */ }; /* Function Descriptor */ @@ -860,6 +865,18 @@ static struct sdca_function_data wcd9378_sdca_data = { /* Vendor SCP register: host clock divide-by-2 (bank 1 shadow). */ #define WCD9378_SCP_HOST_CLK_DIV2_CTL_B1 0xf0 +#define WCD9378_ANA_MBHC_MECH_ADDR 0x40180014 +#define WCD9378_ANA_MBHC_MECH_ENABLE 0xB5 +#define WCD9378_ANA_MBHC_MECH_DET_TYP 0x20 +#define WCD9378_ANA_MBHC_ELECT_ADDR 0x40180015 +#define WCD9378_ANA_MBHC_ELECT_BIAS_EN 0x01 +#define WCD9378_MBHC_NEW_INT_MECH_DET_CURRENT_ADDR 0x401801b1 +#define WCD9378_MBHC_HSDET_PULLUP_CTL_2P0_UA 0x08 +#define WCD9378_MBHC_NEW_PLUG_DETECT_CTL_ADDR 0x40180122 +#define WCD9378_MBHC_INSREM_DBNC_96MS 0x06 +#define WCD9378_MBHC_NEW_CTL_1_ADDR 0x40180120 +#define WCD9378_MBHC_NEW_CTL_1_RCO_EN 0x80 + /* Slave ports 1..8, mapped to master ports via qcom,port-mapping. */ #define WCD9378_SDCA_MAX_PORTS 8 @@ -966,8 +983,99 @@ static int wcd9378_sdca_populate_function(struct device *dev, return 0; } -static const struct sdca_class_ops wcd9378_sdca_class_ops = { - .populate_function = wcd9378_sdca_populate_function, +static int wcd9378_sdca_set_jack(struct sdw_slave *slave, struct regmap *dev_regmap) +{ + struct device *dev = &slave->dev; + int ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) { + dev_err(dev, "failed to resume for jack detect enable: %d\n", ret); + return ret; + } + + ret = regmap_write(dev_regmap, WCD9378_MBHC_NEW_INT_MECH_DET_CURRENT_ADDR, + WCD9378_MBHC_HSDET_PULLUP_CTL_2P0_UA); + if (ret) { + dev_err(dev, "MBHC_NEW_INT_MECH_DET_CURRENT: %d\n", ret); + goto out; + } + + ret = regmap_write(dev_regmap, WCD9378_ANA_MBHC_MECH_ADDR, + WCD9378_ANA_MBHC_MECH_ENABLE); + if (ret) { + dev_err(dev, "ANA_MBHC_MECH: %d\n", ret); + goto out; + } + + ret = regmap_write(dev_regmap, WCD9378_MBHC_NEW_PLUG_DETECT_CTL_ADDR, + WCD9378_MBHC_INSREM_DBNC_96MS); + if (ret) { + dev_err(dev, "MBHC_NEW_PLUG_DETECT_CTL: %d\n", ret); + goto out; + } + + ret = regmap_write(dev_regmap, WCD9378_ANA_MBHC_ELECT_ADDR, + WCD9378_ANA_MBHC_ELECT_BIAS_EN); + if (ret) { + dev_err(dev, "ANA_MBHC_ELECT: %d\n", ret); + goto out; + } + + ret = regmap_write(dev_regmap, WCD9378_MBHC_NEW_CTL_1_ADDR, + WCD9378_MBHC_NEW_CTL_1_RCO_EN); + if (ret) + dev_err(dev, "MBHC_NEW_CTL_1: %d\n", ret); + +out: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +/* + * MECH_DET_TYP selects which transition direction (insert/remove) the + * mechanical comparator is armed for; toggle it after every GE 35 + * DETECTED_MODE interrupt so the opposite-direction transition is still + * seen next time. + */ +static int wcd9378_sdca_ge_mode_detected(struct sdw_slave *slave, + struct regmap *dev_regmap) +{ + struct device *dev = &slave->dev; + unsigned int val; + int ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) { + dev_err(dev, "failed to resume for mech detect rearm: %d\n", ret); + return ret; + } + + ret = regmap_read(dev_regmap, WCD9378_ANA_MBHC_MECH_ADDR, &val); + if (ret) { + dev_err(dev, "ANA_MBHC_MECH read for rearm: %d\n", ret); + goto out; + } + + val ^= WCD9378_ANA_MBHC_MECH_DET_TYP; + + ret = regmap_write(dev_regmap, WCD9378_ANA_MBHC_MECH_ADDR, val); + if (ret) + dev_err(dev, "ANA_MBHC_MECH write for rearm: %d\n", ret); + +out: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +static const struct sdca_class_hw_ops wcd9378_sdca_class_ops = { + .populate_function = wcd9378_sdca_populate_function, + .set_jack = wcd9378_sdca_set_jack, + .ge_mode_detected = wcd9378_sdca_ge_mode_detected, }; int wcd9378_sdca_probe(struct sdw_slave *slave, diff --git a/sound/soc/sdca/sdca_class.c b/sound/soc/sdca/sdca_class.c index ee61c983dc574..e997528c5f2f9 100644 --- a/sound/soc/sdca/sdca_class.c +++ b/sound/soc/sdca/sdca_class.c @@ -7,8 +7,10 @@ * https://www.mipi.org/mipi-sdca-v1-0-download */ +#include #include #include +#include #include #include #include @@ -23,8 +25,17 @@ #include #define CLASS_SDW_ATTACH_TIMEOUT_MS 5000 +#define CLASS_SDW_PROBED_TIMEOUT_MS 500 -static int class_read_prop(struct sdw_slave *sdw) +/** + * sdca_class_read_prop - fill SDCA-common SoundWire slave properties + * @sdw: SoundWire slave + * + * Exported so codec-specific SoundWire drivers can invoke the SDCA + * common property setup from their own sdw_slave_ops.read_prop, and + * then apply codec-specific overrides inline. + */ +int sdca_class_read_prop(struct sdw_slave *sdw) { struct sdw_slave_prop *prop = &sdw->prop; int ret; @@ -39,9 +50,10 @@ static int class_read_prop(struct sdw_slave *sdw) return 0; } +EXPORT_SYMBOL_NS_GPL(sdca_class_read_prop, "SND_SOC_SDCA_CLASS"); static const struct sdw_slave_ops class_sdw_ops = { - .read_prop = class_read_prop, + .read_prop = sdca_class_read_prop, }; static void class_regmap_lock(void *data) @@ -106,12 +118,21 @@ static void class_boot_work(struct work_struct *work) struct sdca_class_drv *drv = container_of(work, struct sdca_class_drv, boot_work); + unsigned long deadline; int ret; ret = sdw_slave_wait_for_init(drv->sdw, CLASS_SDW_ATTACH_TIMEOUT_MS); if (ret) goto err; + deadline = jiffies + msecs_to_jiffies(CLASS_SDW_PROBED_TIMEOUT_MS); + while (!drv->sdw->probed && time_before(jiffies, deadline)) + usleep_range(1000, 2000); + + if (!drv->sdw->probed) + dev_warn(drv->dev, + "timed out waiting for slave probe to complete\n"); + regcache_cache_only(drv->dev_regmap, false); drv->irq_info = devm_sdca_irq_allocate(drv->dev, drv->dev_regmap, @@ -139,6 +160,20 @@ static void class_boot_work(struct work_struct *work) pm_runtime_put_sync(drv->dev); } +static void sdca_class_cancel_boot_work(void *data) +{ + struct sdca_class_drv *drv = data; + + /* + * If boot_work never got to run, class_boot_work() also never + * released the pm_runtime reference that sdca_class_probe() took + * with pm_runtime_get_noresume(). Drop it here so the device + * isn't stuck non-idle after devres unwinds. + */ + if (cancel_work_sync(&drv->boot_work)) + pm_runtime_put_noidle(drv->dev); +} + /** * sdca_class_probe - SDCA class SoundWire slave probe helper * @sdw: SoundWire slave @@ -147,8 +182,8 @@ static void class_boot_work(struct work_struct *work) * allocation and sets its own dev_set_drvdata() -- the framework * does not touch drvdata. Typically embedded in the codec's own * priv struct so codec drivers can keep per-slave state. - * @ops: optional codec-provided class callbacks (may be NULL for - * pure-generic SDCA parts that need no quirks) + * @hw_ops: optional device-specific hw_ops (may be NULL for pure-generic + * SDCA parts that need no quirks) * * Codec-specific SoundWire drivers call this from their .probe after * allocating a struct sdca_class_drv (usually embedded in their own @@ -158,7 +193,7 @@ static void class_boot_work(struct work_struct *work) */ int sdca_class_probe(struct sdw_slave *sdw, struct sdca_class_drv *drv, - const struct sdca_class_ops *ops) + const struct sdca_class_hw_ops *hw_ops) { struct device *dev = &sdw->dev; struct regmap_config *dev_config; @@ -176,10 +211,16 @@ int sdca_class_probe(struct sdw_slave *sdw, drv->dev = dev; drv->sdw = sdw; - drv->ops = ops; + drv->hw_ops = hw_ops; mutex_init(&drv->regmap_lock); mutex_init(&drv->init_lock); + if (hw_ops && hw_ops->hw_init) { + ret = hw_ops->hw_init(sdw); + if (ret) + return dev_err_probe(dev, ret, "hw_init failed\n"); + } + INIT_WORK(&drv->boot_work, class_boot_work); dev_config->lock_arg = &drv->regmap_lock; @@ -202,6 +243,10 @@ int sdca_class_probe(struct sdw_slave *sdw, return ret; } + ret = devm_add_action_or_reset(dev, sdca_class_cancel_boot_work, drv); + if (ret) + return ret; + queue_work(system_long_wq, &drv->boot_work); return 0; @@ -230,14 +275,13 @@ static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id * sdca_class_remove - SDCA class SoundWire slave remove helper * @drv: caller-owned sdca_class_drv (the one handed to sdca_class_probe()). * - * Cancels the deferred boot work so devres can safely free @drv and the - * embedding codec priv without racing class_boot_work. Codec-specific - * SoundWire drivers that call sdca_class_probe() must call this from - * their .remove with the same drv pointer they passed to probe. + * Boot-work cancellation is now handled by a devm action installed in + * sdca_class_probe(); this remains as a no-op remove hook for symmetry + * with sdca_class_probe(), and to give codec drivers a stable API to + * call from their .remove. */ void sdca_class_remove(struct sdca_class_drv *drv) { - cancel_work_sync(&drv->boot_work); } EXPORT_SYMBOL_NS_GPL(sdca_class_remove, "SND_SOC_SDCA_CLASS"); @@ -366,10 +410,11 @@ static int class_pm_runtime_resume(struct device *dev) return sdca_class_runtime_resume(dev_get_drvdata(dev)); } -static const struct dev_pm_ops sdca_class_pm_ops = { +const struct dev_pm_ops sdca_class_pm_ops = { SYSTEM_SLEEP_PM_OPS(class_pm_system_suspend, class_pm_system_resume) RUNTIME_PM_OPS(class_pm_runtime_suspend, class_pm_runtime_resume, NULL) }; +EXPORT_SYMBOL_NS_GPL(sdca_class_pm_ops, "SND_SOC_SDCA_CLASS"); static const struct sdw_device_id class_sdw_id[] = { SDW_SLAVE_ENTRY(0x01FA, 0x4245, 0), diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c index 13b70f0f0dbf7..2062433cc9c1f 100644 --- a/sound/soc/sdca/sdca_class_function.c +++ b/sound/soc/sdca/sdca_class_function.c @@ -142,6 +142,14 @@ static int class_function_sdw_add_peripheral(struct snd_pcm_substream *substream snd_sdw_params_to_config(substream, params, &sconfig, &pconfig); + /* + * Defer BPS selection to the per-port values programmed by + * qcom_swrm_compute_params() so a single stream can carry ports + * with different wire widths (e.g. WCD9378 HPH DP6 2-bit PDM + + * DP7 8-bit PCM envelope). + */ + sconfig.bps = 0; + /* * FIXME: As also noted in sdca_asoc_get_port(), currently only * a single unshared port is supported for each DAI. @@ -212,6 +220,14 @@ static int class_function_set_jack(struct snd_soc_component *component, { struct class_function_drv *drv = snd_soc_component_get_drvdata(component); struct sdca_class_drv *core = drv->core; + int ret; + + if (core->hw_ops && core->hw_ops->set_jack) { + ret = core->hw_ops->set_jack(core->sdw, core->dev_regmap); + if (ret) + dev_warn(component->dev, + "failed to enable hardware jack detection: %d\n", ret); + } return sdca_jack_set_jack(core->irq_info, jack); } @@ -363,10 +379,10 @@ static int class_function_probe(struct auxiliary_device *auxdev, drv->core = core; drv->function = &sdev->function; - if (core->ops && core->ops->populate_function) { - ret = core->ops->populate_function(dev, drv->function); - } else if (drv->function->desc->node) { + if (drv->function->desc->node) { ret = sdca_parse_function(dev, drv->function); + } else if (core->hw_ops && core->hw_ops->populate_function) { + ret = core->hw_ops->populate_function(dev, drv->function); } else { dev_err(dev, "no firmware node and no populate_function hook\n"); return -ENOENT; diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c index 73f8067906a90..eb431be82df9e 100644 --- a/sound/soc/sdca/sdca_jack.c +++ b/sound/soc/sdca/sdca_jack.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,7 @@ int sdca_jack_process(struct sdca_interrupt *interrupt) { struct device *dev = interrupt->dev; struct snd_soc_component *component = interrupt->component; + struct sdca_class_drv *core = dev_get_drvdata(component->dev->parent); struct snd_soc_card *card = component->card; struct rw_semaphore *rwsem = &card->snd_card->controls_rwsem; struct jack_state *state = interrupt->priv; @@ -82,6 +84,12 @@ int sdca_jack_process(struct sdca_interrupt *interrupt) dev_dbg(dev, "%s: %#x\n", interrupt->name, val); + if (core && core->hw_ops && core->hw_ops->ge_mode_detected) { + ret = core->hw_ops->ge_mode_detected(core->sdw, core->dev_regmap); + if (ret) + dev_warn(dev, "failed to re-arm ge mode detection: %d\n", ret); + } + ucontrol = kzalloc_obj(*ucontrol); if (!ucontrol) return -ENOMEM; @@ -267,6 +275,9 @@ int sdca_jack_report(struct sdca_interrupt *interrupt) type = sdca_range_search(range, SDCA_SELECTED_MODE_INDEX, val, SDCA_SELECTED_MODE_TERM_TYPE); + if (val == SDCA_DETECTED_MODE_JACK_UNPLUGGED) + type = 0; + snd_soc_jack_report(jack_state->jack, type_get_mask(type), jack_state->mask); return 0; From db01b657fadfe683c6df41e9e9fc347c507ba20f Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 22 Sep 2026 21:38:02 +0530 Subject: [PATCH 0492/1133] PENDING: ASoC: dt-bindings: qcom: add Glymur LPASS and SoundWire binding updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add device tree binding updates required for Glymur audio support and recent Qualcomm SoundWire enhancements.   This change introduces bindings for the Glymur LPASS clock controller along with the associated clock ID definitions used by LPASS macro codecs and SoundWire controllers.   It also updates the Qualcomm SoundWire bindings to: - Allow vendor-specific compatibles alongside SoundWire class-ID compatibles on slave devices. - Document the qcom,ports-ch-mask property used for per-port channel mask configuration. - Describe SoundWire lane provider and consumer topologies for platforms that combine multiple controller instances to expose additional data lanes.   These updates align the DT schemas with existing driver functionality and provide the bindings required for upcoming Glymur audio platform support. Signed-off-by: Mohammad Rafi Shaik --- .../bindings/clock/qcom,glymur-lpasscc.yaml | 60 +++++++ .../bindings/sound/qcom,lpass-rx-macro.yaml | 2 + .../bindings/sound/qcom,lpass-tx-macro.yaml | 2 + .../bindings/soundwire/qcom,soundwire.yaml | 147 ++++++++++++++++-- .../soundwire/soundwire-controller.yaml | 12 +- .../dt-bindings/clock/qcom,glymur-lpasscc.h | 19 +++ 6 files changed, 226 insertions(+), 16 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/qcom,glymur-lpasscc.yaml create mode 100644 include/dt-bindings/clock/qcom,glymur-lpasscc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,glymur-lpasscc.yaml b/Documentation/devicetree/bindings/clock/qcom,glymur-lpasscc.yaml new file mode 100644 index 0000000000000..916ab1b3dbeeb --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,glymur-lpasscc.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,glymur-lpasscc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm LPASS Core & Audio Clock Controller on Glymur + +maintainers: + - Srinivas Kandagatla + +description: | + Qualcomm LPASS core and audio clock control module provides the clocks, + and reset on Glymur. + + See also: + include/dt-bindings/clock/qcom,glymur-lpasscc.h + +properties: + compatible: + enum: + - qcom,glymur-lpassaudiocc + - qcom,glymur-lpasscc + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + #include + lpass_audiocc: clock-controller@32a9000 { + compatible = "qcom,glymur-lpassaudiocc"; + reg = <0x032a9000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + - | + #include + lpasscc: clock-controller@33e0000 { + compatible = "qcom,glymur-lpasscc"; + reg = <0x033e0000 0x12000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; +... diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml index 4988e7ed6e34b..4ab6f1bc93eb6 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml @@ -13,6 +13,7 @@ properties: compatible: oneOf: - enum: + - qcom,glymur-lpass-rx-macro - qcom,sc7280-lpass-rx-macro - qcom,sm6115-lpass-rx-macro - qcom,sm8250-lpass-rx-macro @@ -104,6 +105,7 @@ allOf: properties: compatible: enum: + - qcom,glymur-lpass-rx-macro - qcom,sc8280xp-lpass-rx-macro - qcom,sm8250-lpass-rx-macro - qcom,sm8450-lpass-rx-macro diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml index d8682ff2e82c5..7fdc824e9099d 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml @@ -13,6 +13,7 @@ properties: compatible: oneOf: - enum: + - qcom,glymur-lpass-tx-macro - qcom,sc7280-lpass-tx-macro - qcom,sm6115-lpass-tx-macro - qcom,sm8250-lpass-tx-macro @@ -91,6 +92,7 @@ allOf: properties: compatible: enum: + - qcom,glymur-lpass-tx-macro - qcom,sc8280xp-lpass-tx-macro - qcom,sm8250-lpass-tx-macro - qcom,sm8450-lpass-tx-macro diff --git a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml index 81532cf69dd0c..df8de683a8227 100644 --- a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml +++ b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml @@ -10,8 +10,14 @@ maintainers: - Srinivas Kandagatla - Srinivasa Rao Mandadapu -description: - The Qualcomm SoundWire controller along with its board specific bus parameters. +description: | + The Qualcomm SoundWire controller along with its board specific bus + parameters. + + On v3.1.0 and later, two instances may pair as a lane-provider/consumer + pair sharing one SWR_CLK, to expose a bus with more than two DATA lanes. + The consumer references the provider via qcom,secondary-lanes; the provider + is marked by #qcom,swrm-lane-cells. properties: compatible: @@ -216,6 +222,47 @@ properties: maximum: 4 - const: 0xff + qcom,ports-ch-mask: + $ref: /schemas/types.yaml#/definitions/uint8-array + description: + Per-port intrinsic SoundWire channel mask. Used when programming + the master DPn PORT_CTRL channel-enable field so a port's slot + layout (e.g. stereo PDM) is transmitted independently of the PCM + stream's channel count. 0xff means the option is not applicable + for that port. + minItems: 3 + maxItems: 17 + + '#qcom,swrm-lane-cells': + description: + Marks this node as a lane provider. The single cell in a referring + phandle is the provider-local DATA lane index. + const: 1 + + qcom,secondary-lanes: + description: + Extra DATA lanes borrowed from other Qualcomm SoundWire instances + (lane providers). Each entry is a pair. The N-th + entry becomes bus lane (num-lanes + N); slave port mappings must + follow this order. + $ref: /schemas/types.yaml#/definitions/phandle-array + items: + items: + - description: phandle of a Qualcomm SoundWire lane provider + - description: provider-local DATA lane index + minItems: 1 + maxItems: 6 + + num-lanes: + description: + Number of DATA lanes this instance exposes locally. Optional, + defaults to 2. On a bus master, bus lanes 0..num-lanes-1 come + from this instance; higher-numbered lanes come from + qcom,secondary-lanes entries in order. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 8 + label: maxItems: 1 @@ -225,20 +272,48 @@ required: - interrupts - clocks - clock-names - - '#sound-dai-cells' - - '#address-cells' - - '#size-cells' - - qcom,ports-offset1 - - qcom,ports-offset2 - -oneOf: - - required: - - qcom,ports-sinterval-low - - required: - - qcom,ports-sinterval allOf: - $ref: soundwire-controller.yaml# + - if: + required: + - '#qcom,swrm-lane-cells' + then: + properties: + qcom,secondary-lanes: false + '#sound-dai-cells': false + qcom,ports-word-length: false + qcom,ports-sinterval-low: false + qcom,ports-sinterval: false + qcom,ports-offset1: false + qcom,ports-offset2: false + qcom,ports-lane-control: false + qcom,ports-block-pack-mode: false + qcom,ports-hstart: false + qcom,ports-hstop: false + qcom,ports-block-group-count: false + qcom,ports-ch-mask: false + else: + required: + - '#sound-dai-cells' + - qcom,ports-offset1 + - qcom,ports-offset2 + oneOf: + - required: + - qcom,ports-sinterval-low + - required: + - qcom,ports-sinterval + - if: + anyOf: + - required: + - '#qcom,swrm-lane-cells' + - required: + - qcom,secondary-lanes + then: + properties: + compatible: + contains: + const: qcom,soundwire-v3.1.0 unevaluatedProperties: false @@ -283,3 +358,49 @@ examples: qcom,rx-port-mapping = <1 2 3 4 5>; }; }; + + - | + #include + + /* Provider IP: contributes two DATA lanes to another master's bus */ + swr_lane_provider: soundwire@6ad0000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x06ad0000 0x10000>; + interrupts = ; + clocks = <&lpass_provider_clk>; + clock-names = "iface"; + resets = <&lpass_audiocc 4>; + reset-names = "swr_audio_cgcr"; + #qcom,swrm-lane-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + }; + + /* Bus master consuming both lanes of the provider above */ + soundwire@6ac0000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x06ac0000 0x10000>; + interrupts = ; + clocks = <&lpass_master_clk>; + clock-names = "iface"; + resets = <&lpass_audiocc 3>; + reset-names = "swr_audio_cgcr"; + qcom,secondary-lanes = <&swr_lane_provider 0>, + <&swr_lane_provider 1>; + + qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04>; + qcom,ports-sinterval-low = /bits/ 8 <0x03 0x3f 0x1f>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0b>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0b>; + qcom,ports-lane-control = /bits/ 8 <0x00 0x02 0x03>; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + + codec@0,4 { + compatible = "sdw20217010d00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3>; + }; + }; diff --git a/Documentation/devicetree/bindings/soundwire/soundwire-controller.yaml b/Documentation/devicetree/bindings/soundwire/soundwire-controller.yaml index fdeb8af417d7c..a95ca97f0755e 100644 --- a/Documentation/devicetree/bindings/soundwire/soundwire-controller.yaml +++ b/Documentation/devicetree/bindings/soundwire/soundwire-controller.yaml @@ -30,9 +30,10 @@ patternProperties: properties: compatible: - pattern: "^sdw[0-9a-f]{1}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{2}$" - description: Is the textual representation of SoundWire Enumeration - address. compatible string should contain SoundWire Version ID, + contains: + pattern: "^sdw[0-9a-f]{1}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{2}$" + description: The SoundWire enumeration address must appear as one + of the compatible strings. It encodes the SoundWire Version ID, Manufacturer ID, Part ID and Class ID in order and shall be in lower-case hexadecimal with leading zeroes. Valid sizes of these fields are @@ -44,6 +45,11 @@ patternProperties: More Information on detail of encoding of these fields can be found in MIPI Alliance DisCo & SoundWire 1.0 Specifications. + Vendor-variant compatibles ("vendor,part") may precede the + class-ID compatible per standard DT convention, so that codec + drivers can disambiguate mode/variant via + device_is_compatible(). + reg: maxItems: 1 description: diff --git a/include/dt-bindings/clock/qcom,glymur-lpasscc.h b/include/dt-bindings/clock/qcom,glymur-lpasscc.h new file mode 100644 index 0000000000000..2eefbec77c5c5 --- /dev/null +++ b/include/dt-bindings/clock/qcom,glymur-lpasscc.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2025, Qualcomm Inc. + * Linaro Ltd. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_LPASSCC_GLYMUR_H +#define _DT_BINDINGS_CLK_QCOM_LPASSCC_GLYMUR_H + +/* LPASS AUDIO CC CSR */ +#define LPASS_AUDIO_SWR_RX_CGCR 0 +//FIXME +#define LPASS_AUDIO_SWR_TX_CGCR 1 +#define LPASS_AUDIO_SWR_WSA1_CGCR 2 +#define LPASS_AUDIO_SWR_WSA2_CGCR 3 +#define LPASS_AUDIO_SWR_WSA3_CGCR 4 +#define LPASS_AUDIO_SWR_WSA4_CGCR 5 + +#endif From 4f37ca8295e301730f5f6347b2e7aa3a0a8d30e0 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Thu, 29 May 2025 17:06:00 +0530 Subject: [PATCH 0493/1133] 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 | 326 ++++++++++++++++++++++++++++++++ 1 file changed, 326 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..54cf8fa1cd0e0 --- /dev/null +++ b/arch/arm64/configs/prune.config @@ -0,0 +1,326 @@ +# 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_DEVMEM is not set +# CONFIG_STRICT_DEVMEM 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 From 5af241055cb9caa73341312f2a58c75f11ead7e8 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 23 Sep 2025 14:20:27 +0530 Subject: [PATCH 0494/1133] QCLINUX: arch: arm64: configs: Define qcom.config and enable DMABUF heaps The `qcom.config` file serves as a Qualcomm-specific kernel configuration fragment used to enable features required by Qualcomm SoCs. It helps ensure that essential features and subsystems required by Qualcomm platforms are enabled. This initial version of `qcom.config` enables DMABUF heap support, including the system heap and default CMA heap. These configurations are essential for buffer sharing across subsystems such as camera, display, and DSP on Qualcomm platforms like qcs6490. Signed-off-by: Komal Bajaj --- arch/arm64/configs/qcom.config | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 arch/arm64/configs/qcom.config diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config new file mode 100644 index 0000000000000..f5164133e8930 --- /dev/null +++ b/arch/arm64/configs/qcom.config @@ -0,0 +1,3 @@ +CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DMABUF_HEAPS_CMA=y From 2e450750db76ae790c3d01334eace53cd619146e Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 26 Sep 2025 10:08:11 +0800 Subject: [PATCH 0495/1133] QCLINUX:arch: arm64: configs: Enable coresight components in qcom.config Add Coresight configs to enable Coresight device drivers on mainline. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom.config | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index f5164133e8930..895e933b8ac85 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -1,3 +1,9 @@ CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_DMABUF_HEAPS_CMA=y +CONFIG_CORESIGHT_TPDM=m +CONFIG_CORESIGHT_DUMMY=m +CONFIG_CORESIGHT_CTCU=m +CONFIG_CORESIGHT_SOURCE_ETM4X=m +CONFIG_CORESIGHT_TGU=m +CONFIG_CORESIGHT_CORESIGHT_TNOC=m From 1954a7a06b030867d06c63c1b6add80ac9089aae Mon Sep 17 00:00:00 2001 From: Charan Teja Kalla Date: Tue, 30 Sep 2025 18:27:55 +0530 Subject: [PATCH 0496/1133] QCLINUX: defconfig: enable zram defconfig on qcom.config Enable ZRAM defconfig on qcom.config. This empowers users to use the compressed block devices for usecases, eg: swap device on zram. Tested: make ARCH=arm64 menuconfig defconfig qcom.config, booted with this configuration on QEMU and verified if /dev/zram0 is exist. Signed-off-by: Charan Teja Kalla --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 895e933b8ac85..d088c252c0756 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -7,3 +7,4 @@ CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_SOURCE_ETM4X=m CONFIG_CORESIGHT_TGU=m CONFIG_CORESIGHT_CORESIGHT_TNOC=m +CONFIG_ZRAM=y From 2eb799101e77e972ca1e73a9a6ac73cc45bd227c Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Mon, 6 Oct 2025 16:56:58 +0530 Subject: [PATCH 0497/1133] QCLINUX: defconfig: Enable scheduler and thermal related configs Enabled key configs for thermal management (CPU_IDLE_THERMAL, IDLE_INJECT), scheduler (SCHED_DEBUG, SCHEDSTATS, TRACE_MMIO_ACCESS), and power control (POWERCAP, UCLAMP_TASK). Also enabled KPROBES, PAN emulation and watchdog pretimeout panic governor for improved instrumentation and security. Signed-off-by: Komal Bajaj --- arch/arm64/configs/qcom.config | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index d088c252c0756..971dbb2b486bc 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -1,10 +1,33 @@ -CONFIG_DMABUF_HEAPS=y -CONFIG_DMABUF_HEAPS_SYSTEM=y -CONFIG_DMABUF_HEAPS_CMA=y -CONFIG_CORESIGHT_TPDM=m +# qcom.config for Qualcomm-specific kernel configuration +# +# $ make ARCH=arm64 defconfig qcom.config +# +# Keep alphabetically sorted +CONFIG_ARM64_SW_TTBR0_PAN=y +CONFIG_CORESIGHT_CORESIGHT_TNOC=m +CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_DUMMY=m CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_SOURCE_ETM4X=m CONFIG_CORESIGHT_TGU=m -CONFIG_CORESIGHT_CORESIGHT_TNOC=m +CONFIG_CORESIGHT_TPDM=m +CONFIG_CPU_IDLE_THERMAL=y +# CONFIG_DEBUG_INFO_REDUCED is not set +CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_HEAPS_CMA=y +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_IDLE_INJECT=y +CONFIG_KPROBES=y +CONFIG_POWERCAP=y +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TRACE_MMIO_ACCESS=y +CONFIG_UCLAMP_TASK_GROUP=y +CONFIG_UCLAMP_TASK=y +# CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y CONFIG_ZRAM=y From 9930eabceb88b1431a1ef89f607d51b236b5b309 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Mon, 6 Oct 2025 17:11:01 +0530 Subject: [PATCH 0498/1133] QCLINUX: debug: Enable additional Qualcomm-specific debug configs Enabled various debug-related kernel config options to improve system diagnostics and aid in development and issue analysis. Signed-off-by: Komal Bajaj --- kernel/configs/debug.config | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index ac878669c1936..25d2ebaa64779 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -116,3 +116,12 @@ CONFIG_FUNCTION_TRACER=y # CONFIG_DEBUG_PREEMPT=y CONFIG_PREEMPT=y + +# +# Qualcomm Debug Configs +# +CONFIG_CMA_DEBUG=y +CONFIG_DEBUG_LIST=y +CONFIG_DEBUG_PAGEALLOC=y +# CONFIG_FW_LOADER_DEBUG is not set +CONFIG_HARDLOCKUP_DETECTOR=y From 810d8512b1a294c0608e9eeb4e11726c97a91916 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 31 Oct 2025 15:58:40 +0800 Subject: [PATCH 0499/1133] QCLINUX: arch: arm64: configs: Enable stm components in qcom.config Add STM configs to enable STM functions, like stm ftrace and stm heartbeat. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom.config | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 971dbb2b486bc..a05f6e73a8979 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -21,6 +21,11 @@ CONFIG_KPROBES=y CONFIG_POWERCAP=y CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y +CONFIG_STM_PROTO_BASIC=m +CONFIG_STM_PROTO_SYS_T=m +CONFIG_STM_SOURCE_CONSOLE=m +CONFIG_STM_SOURCE_FTRACE=m +CONFIG_STM_SOURCE_HEARTBEAT=m CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y From 41b09d798c947ff404f0d8dc42efc5ee002b5cac Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 13 Oct 2026 16:02:40 +0530 Subject: [PATCH 0500/1133] PENDING: soundwire: add multi-lane, multi-port and SDCA enablement support Add the SoundWire core and Qualcomm controller changes required for SDCA codec topologies and for Qualcomm SoCs that combine two controller instances to expose additional data lanes. Core stream changes: - Allow a Slave to contribute more than one port to the same stream across multiple sdw_stream_add_slave() calls. Ports are now always appended to port_list and the pre-call count is used so port configuration only fills in newly added entries instead of overwriting those from earlier calls. - Preserve per-port port_params.bps pre-set by compute_params() and only fall back to the stream-wide value when it was left at zero, so a single stream can carry ports with different wire widths. - Explicitly set port_params.num so master port_params callbacks always receive the correct port number. Qualcomm controller changes: - Add the optional qcom,ports-ch-mask property to fix the per-port channel mask where the stream derived value is insufficient, such as a wired stereo PDM port opened by a mono PCM stream. - Gate the additional DIN PCM port control register for ports that belong to a PCM stream, as required by SDCA class compliant slaves. - Implement the lane provider role, where a controller declaring #qcom,swrm-lane-cells is brought up as a data only lane source and does not register a SoundWire bus of its own. - Implement the lane consumer role, where qcom,secondary-lanes resolves a provider at probe time and deferred probe is used until the provider is ready. Per-port DPn register accesses that land on a borrowed lane are translated and routed to the provider, and the port lane selector is converted to provider local numbering. - Program MM_SYNC on both controllers of a multi-master pair so their frame generators lock to a single SWR_CLK, and re-apply it on resume since it does not survive a bus clock stop. - Program the frame control SSP period derived from the current frame geometry on v3.1.0+ parts, both at init and on every bank switch, and clear CLK_DIV in the same place. - Fan broadcast SCP_FrameCtrl writes out to per-slave unicasts on a multi-master pair, where the hardware broadcast is not acted upon by the slaves. Bus changes: - Iterate every string in a slave node compatible property when matching the SoundWire class ID, so a vendor variant compatible can precede the class ID compatible. Non-multilane platforms are unaffected: without qcom,secondary-lanes no provider is resolved and all register accesses keep using the existing paths. Signed-off-by: Mohammad Rafi Shaik --- drivers/soundwire/qcom.c | 511 +++++++++++++++++++++++++++++++++++-- drivers/soundwire/stream.c | 127 ++++----- 2 files changed, 554 insertions(+), 84 deletions(-) diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 6e0c5fb10efad..f82a6be05a49d 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,24 @@ #define SWRM_V3_COMP_PARAMS_RD_FIFO_DEPTH GENMASK(23, 18) #define SWRM_COMP_MASTER_ID 0x104 + +/* + * Multi-master sync, v3.1.0 and later. Two controller instances can be tied + * together so that a single SWR_CLK drives both frame generators, which lets + * the pair expose the sum of their DATA lanes on one logical bus. + */ +#define SWRM_V3_MM_SYNC_CONFIG 0x108 +#define SWRM_V3_MM_SYNC_CONNECTED_MASTER GENMASK(15, 0) +#define SWRM_V3_MM_SYNC_IS_DEPENDENT_MASTER BIT(16) +#define SWRM_V3_MM_SYNC_MASK_CONTROL_BITS BIT(17) + +#define SWRM_V3_COMP_FEATURE_CFG 0x010 +/* Reset value of the feature bits which must be preserved */ +#define SWRM_V3_COMP_FEATURE_CFG_DEFAULT GENMASK(3, 1) +#define SWRM_V3_COMP_FEATURE_CFG_FORCE_MODE_EN BIT(9) +#define SWRM_V3_COMP_FEATURE_CFG_CLK_PIN_AVAIL BIT(10) +#define SWRM_V3_COMP_FEATURE_CFG_CLK_STOP_EXEC_ON_CMD_IGNORE BIT(12) + #define SWRM_V1_3_INTERRUPT_STATUS 0x200 #define SWRM_V2_0_INTERRUPT_STATUS 0x5000 #define SWRM_INTERRUPT_STATUS_RMSK GENMASK(16, 0) @@ -95,6 +114,16 @@ #define SWRM_MCP_FRAME_CTRL_BANK_ADDR(m) (0x101C + 0x40 * (m)) #define SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK GENMASK(2, 0) #define SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK GENMASK(7, 3) +#define SWRM_MCP_FRAME_CTRL_BANK_CLK_DIV_BMSK GENMASK(10, 8) +#define SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK GENMASK(23, 16) +/* + * The Sample Sync Pulse is emitted at a fixed 4kHz and its period is + * programmed in frames - 1. The frame rate is the bit rate (SoundWire + * clocks two bits per cycle) divided by the frame shape. + */ +#define SWRM_SSP_RATE 4000 +#define SWRM_SSP_PERIOD(freq, rows, cols) \ + (2 * (freq) / ((rows) * (cols) * SWRM_SSP_RATE) - 1) #define SWRM_MCP_BUS_CTRL 0x1044 #define SWRM_MCP_BUS_CLK_START BIT(1) #define SWRM_MCP_CFG_ADDR 0x1048 @@ -113,6 +142,9 @@ #define SWRM_DPn_PORT_HCTRL_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m) #define SWRM_DPn_BLOCK_CTRL3_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m) #define SWRM_DPn_SAMPLECTRL2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m) +#define SWRM_DP_PCM_PORT_CTRL(n) (0x1154 + 0x100 * ((n) - 1)) +#define SWRM_DP_PCM_PORT_CTRL_EN 0x03 +#define SWRM_DPn_SLOT_STRIDE 0x100 #define SWR_V1_3_MSTR_MAX_REG_ADDR 0x1740 #define SWR_V2_0_MSTR_MAX_REG_ADDR 0x50ac @@ -162,6 +194,7 @@ struct qcom_swrm_port_config { u8 word_length; u8 blk_group_count; u8 lane_control; + u8 ch_mask; }; /* @@ -187,6 +220,9 @@ enum { SWRM_OFFSET_DP_SAMPLECTRL2_BANK, }; +/* Number of DATA lanes exposed by every Qualcomm SWR master IP so far */ +#define SWRM_MAX_DATA_LANES 2 + struct qcom_swrm_ctrl { struct sdw_bus bus; struct device *dev; @@ -195,6 +231,40 @@ struct qcom_swrm_ctrl { const unsigned int *reg_layout; void __iomem *mmio; struct reset_control *audio_cgcr; + /* + * Multi-lane support, v3.1.0 and later. A controller described in DT + * with "#qcom,swrm-lane-cells" is a lane provider: it does not run a + * bus of its own, it only lends its DATA lanes (and the matching DPn + * slots) to a second controller which references them through + * "qcom,secondary-lanes". MM_SYNC ties the two frame generators to a + * single SWR_CLK, so peripherals see one logical bus whose lane count + * is the sum of both IPs. + * + * is_lane_provider is the role flag; lane_provider_ready tells a + * consumer probing concurrently that the provider is set up far + * enough to be used, rather than something to defer on. + */ + bool is_lane_provider; + bool lane_provider_ready; + /* + * Consumer state. lane_provider is the single provider IP whose DATA + * lanes this bus borrows, NULL when the bus stands alone. Bus lanes + * [provider_lane_base, provider_lane_base + num_provider_lanes) map to + * the provider's local lanes [0, num_provider_lanes); the DT parsing in + * qcom_swrm_setup_lane_provider() enforces that shape. lane_consumer + * is the reverse link, set on the provider. + */ + struct qcom_swrm_ctrl *lane_provider; + struct qcom_swrm_ctrl *lane_consumer; + u8 provider_lane_base; + u8 num_provider_lanes; + /* + * DPn address delta applied to per-port register accesses routed to + * the provider. Computed once at setup from the lowest numbered port + * assigned to a provider lane: that port maps to the provider's DP1, + * the next one to DP2 and so on. + */ + u32 provider_dpn_offset; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs; #endif @@ -935,17 +1005,80 @@ static bool swrm_wait_for_frame_gen_enabled(struct qcom_swrm_ctrl *ctrl) return false; } +/* + * Tie the frame generators of a lane provider and its consumer to a single + * SWR_CLK. Both sides point MM_SYNC at the other's master ID; the provider + * additionally marks itself dependent so that bus control, reset and clock + * stop come from the consumer instead of being driven locally. + */ +static int qcom_swrm_program_mm_sync(struct qcom_swrm_ctrl *ctrl) +{ + struct qcom_swrm_ctrl *peer; + u32 feature_cfg; + u32 conn_mask; + int ret; + + peer = ctrl->is_lane_provider ? ctrl->lane_consumer : ctrl->lane_provider; + if (!peer) + return 0; + + /* + * CONNECTED_MASTER is a bitmap of peer master IDs. Those are one + * based, and are only reported by the IPs which implement MM_SYNC, so + * bail out rather than shifting by a negative amount. + */ + if (peer->bus.controller_id < 1) { + dev_err(ctrl->dev, "invalid peer master ID %d for MM sync\n", + peer->bus.controller_id); + return -EINVAL; + } + + conn_mask = FIELD_PREP(SWRM_V3_MM_SYNC_CONNECTED_MASTER, + BIT(peer->bus.controller_id - 1)); + + feature_cfg = SWRM_V3_COMP_FEATURE_CFG_DEFAULT | + SWRM_V3_COMP_FEATURE_CFG_FORCE_MODE_EN | + SWRM_V3_COMP_FEATURE_CFG_CLK_STOP_EXEC_ON_CMD_IGNORE; + + if (ctrl->is_lane_provider) + conn_mask |= SWRM_V3_MM_SYNC_IS_DEPENDENT_MASTER | + SWRM_V3_MM_SYNC_MASK_CONTROL_BITS; + else + /* Only the consumer drives the shared SWR_CLK pin */ + feature_cfg |= SWRM_V3_COMP_FEATURE_CFG_CLK_PIN_AVAIL; + + ret = ctrl->reg_write(ctrl, SWRM_V3_MM_SYNC_CONFIG, conn_mask); + if (ret) + return ret; + + return ctrl->reg_write(ctrl, SWRM_V3_COMP_FEATURE_CFG, feature_cfg); +} + static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl) { u32 val; + int ret; /* Clear Rows and Cols */ val = FIELD_PREP(SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK, ctrl->rows_index); val |= FIELD_PREP(SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK, ctrl->cols_index); + /* + * A synced pair needs an explicit SSP period so that both frame + * generators agree on where the sample sync pulse falls, and needs + * both banks primed because bank switches are mirrored to the + * provider. + */ + if (ctrl->lane_provider) + val |= FIELD_PREP(SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK, + SWRM_SSP_PERIOD(ctrl->bus.params.curr_dr_freq, + ctrl->bus.params.row, + ctrl->bus.params.col)); reset_control_reset(ctrl->audio_cgcr); ctrl->reg_write(ctrl, SWRM_MCP_FRAME_CTRL_BANK_ADDR(0), val); + if (ctrl->lane_provider) + ctrl->reg_write(ctrl, SWRM_MCP_FRAME_CTRL_BANK_ADDR(1), val); /* Enable Auto enumeration */ ctrl->reg_write(ctrl, SWRM_ENUMERATOR_CFG_ADDR, 1); @@ -961,6 +1094,10 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl) u32p_replace_bits(&val, SWRM_DEF_CMD_NO_PINGS, SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK); ctrl->reg_write(ctrl, SWRM_MCP_CFG_ADDR, val); + ret = qcom_swrm_program_mm_sync(ctrl); + if (ret) + return ret; + if (ctrl->version == SWRM_VERSION_1_7_0) { ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee); ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, @@ -1027,31 +1164,31 @@ static int qcom_swrm_read_prop(struct sdw_bus *bus) return 0; } -static enum sdw_command_response qcom_swrm_xfer_msg(struct sdw_bus *bus, - struct sdw_msg *msg) +static enum sdw_command_response qcom_swrm_xfer_msg_one(struct qcom_swrm_ctrl *ctrl, + struct sdw_msg *msg, + u8 dev_num) { - struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); int ret, i, len; if (msg->page) { - if (ctrl->page1_cache[msg->dev_num] != msg->addr_page1) { + if (ctrl->page1_cache[dev_num] != msg->addr_page1) { ret = qcom_swrm_cmd_fifo_wr_cmd(ctrl, msg->addr_page1, - msg->dev_num, + dev_num, SDW_SCP_ADDRPAGE1); if (ret) return ret; - ctrl->page1_cache[msg->dev_num] = msg->addr_page1; + ctrl->page1_cache[dev_num] = msg->addr_page1; } - if (ctrl->page2_cache[msg->dev_num] != msg->addr_page2) { + if (ctrl->page2_cache[dev_num] != msg->addr_page2) { ret = qcom_swrm_cmd_fifo_wr_cmd(ctrl, msg->addr_page2, - msg->dev_num, + dev_num, SDW_SCP_ADDRPAGE2); if (ret) return ret; - ctrl->page2_cache[msg->dev_num] = msg->addr_page2; + ctrl->page2_cache[dev_num] = msg->addr_page2; } } @@ -1059,7 +1196,7 @@ static enum sdw_command_response qcom_swrm_xfer_msg(struct sdw_bus *bus, for (i = 0; i < msg->len;) { len = min(msg->len - i, QCOM_SWRM_MAX_RD_LEN); - ret = qcom_swrm_cmd_fifo_rd_cmd(ctrl, msg->dev_num, + ret = qcom_swrm_cmd_fifo_rd_cmd(ctrl, dev_num, msg->addr + i, len, &msg->buf[i]); if (ret) @@ -1070,7 +1207,7 @@ static enum sdw_command_response qcom_swrm_xfer_msg(struct sdw_bus *bus, } else if (msg->flags == SDW_MSG_FLAG_WRITE) { for (i = 0; i < msg->len; i++) { ret = qcom_swrm_cmd_fifo_wr_cmd(ctrl, msg->buf[i], - msg->dev_num, + dev_num, msg->addr + i); if (ret) return SDW_CMD_IGNORED; @@ -1080,20 +1217,113 @@ static enum sdw_command_response qcom_swrm_xfer_msg(struct sdw_bus *bus, return SDW_CMD_OK; } +static enum sdw_command_response qcom_swrm_xfer_msg(struct sdw_bus *bus, + struct sdw_msg *msg) +{ + struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); + enum sdw_command_response resp; + struct sdw_slave *slave; + + /* + * A broadcast written by a synced master pair is emitted onto the + * shared frame, but the hardware never raises SPECIAL_CMD_ID_FINISHED + * and peripherals do not act on it, so an SCP_FrameCtrl update sent + * that way is lost. Fan such a broadcast out into one unicast per + * enumerated peripheral, which is equivalent from their point of view. + */ + if (ctrl->lane_provider && msg->dev_num == SDW_BROADCAST_DEV_NUM && + (msg->addr == SDW_SCP_FRAMECTRL_B0 || + msg->addr == SDW_SCP_FRAMECTRL_B1)) { + list_for_each_entry(slave, &bus->slaves, node) { + if (slave->dev_num == SDW_ENUM_DEV_NUM || + slave->dev_num >= SDW_BROADCAST_DEV_NUM) + continue; + + resp = qcom_swrm_xfer_msg_one(ctrl, msg, slave->dev_num); + if (resp != SDW_CMD_OK) + return resp; + } + + return SDW_CMD_OK; + } + + return qcom_swrm_xfer_msg_one(ctrl, msg, msg->dev_num); +} + static int qcom_swrm_pre_bank_switch(struct sdw_bus *bus) { u32 reg = SWRM_MCP_FRAME_CTRL_BANK_ADDR(bus->params.next_bank); struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); u32 val; + int ret; ctrl->reg_read(ctrl, reg, &val); u32p_replace_bits(&val, ctrl->cols_index, SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK); u32p_replace_bits(&val, ctrl->rows_index, SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK); + if (ctrl->lane_provider) { + struct qcom_swrm_ctrl *provider = ctrl->lane_provider; + + /* + * The provider has to follow the frame shape but must not + * program a clock divider or an SSP period of its own, so + * mirror the bank before adding those. + */ + ret = provider->reg_write(provider, reg, val); + if (ret) + return ret; + + u32p_replace_bits(&val, 0, + SWRM_MCP_FRAME_CTRL_BANK_CLK_DIV_BMSK); + u32p_replace_bits(&val, + SWRM_SSP_PERIOD(bus->params.curr_dr_freq, + bus->params.row, + bus->params.col), + SWRM_MCP_FRAME_CTRL_BANK_SSP_PERIOD_BMSK); + } + return ctrl->reg_write(ctrl, reg, val); } +/* + * Per-port DPn register dispatch. A port whose lane_control names a bus lane + * lent by the provider is serviced by the provider's DPn block, so rebase the + * address onto the provider's slot numbering and use its own accessors. + * Everything else lands on this controller, which keeps AHB parented (SLIMbus) + * platforms on their existing regmap path. + */ +static struct qcom_swrm_ctrl *qcom_swrm_port_target(struct qcom_swrm_ctrl *ctrl, + u8 port_num, u32 *reg) +{ + u8 lane = ctrl->pconfig[port_num].lane_control; + + if (!ctrl->lane_provider || lane == SWR_INVALID_PARAM || + lane < ctrl->provider_lane_base || + lane >= ctrl->provider_lane_base + ctrl->num_provider_lanes) + return ctrl; + + *reg -= ctrl->provider_dpn_offset; + + return ctrl->lane_provider; +} + +static int qcom_swrm_port_reg_write(struct qcom_swrm_ctrl *ctrl, u8 port_num, + u32 reg, u32 val) +{ + struct qcom_swrm_ctrl *tgt = qcom_swrm_port_target(ctrl, port_num, ®); + + return tgt->reg_write(tgt, reg, val); +} + +static int qcom_swrm_port_reg_read(struct qcom_swrm_ctrl *ctrl, u8 port_num, + u32 reg, u32 *val) +{ + struct qcom_swrm_ctrl *tgt = qcom_swrm_port_target(ctrl, port_num, ®); + + return tgt->reg_read(tgt, reg, val); +} + static int qcom_swrm_port_params(struct sdw_bus *bus, struct sdw_port_params *p_params, unsigned int bank) @@ -1101,8 +1331,9 @@ static int qcom_swrm_port_params(struct sdw_bus *bus, struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); u32 offset = ctrl->reg_layout[SWRM_OFFSET_DP_BLOCK_CTRL_1]; - return ctrl->reg_write(ctrl, SWRM_DPn_BLOCK_CTRL_1(offset, p_params->num), - p_params->bps - 1); + return qcom_swrm_port_reg_write(ctrl, p_params->num, + SWRM_DPn_BLOCK_CTRL_1(offset, p_params->num), + p_params->bps - 1); } static int qcom_swrm_transport_params(struct sdw_bus *bus, @@ -1123,7 +1354,7 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus, value |= pcfg->off2 << SWRM_DP_PORT_CTRL_OFFSET2_SHFT; value |= pcfg->si & 0xff; - ret = ctrl->reg_write(ctrl, reg, value); + ret = qcom_swrm_port_reg_write(ctrl, params->port_num, reg, value); if (ret) goto err; @@ -1132,7 +1363,7 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus, value = (pcfg->si >> 8) & 0xff; reg = SWRM_DPn_SAMPLECTRL2_BANK(offset, params->port_num, bank); - ret = ctrl->reg_write(ctrl, reg, value); + ret = qcom_swrm_port_reg_write(ctrl, params->port_num, reg, value); if (ret) goto err; } @@ -1141,8 +1372,18 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus, offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_2_BANK]; reg = SWRM_DPn_PORT_CTRL_2_BANK(offset, params->port_num, bank); + /* + * DPn PORT_CTRL_2 selects the DATA pin in the local numbering + * of whichever IP owns the port, so a lane borrowed from the + * provider has to be translated back to the provider's own + * lane number. + */ value = pcfg->lane_control; - ret = ctrl->reg_write(ctrl, reg, value); + if (ctrl->lane_provider && value >= ctrl->provider_lane_base && + value < ctrl->provider_lane_base + ctrl->num_provider_lanes) + value -= ctrl->provider_lane_base; + + ret = qcom_swrm_port_reg_write(ctrl, params->port_num, reg, value); if (ret) goto err; } @@ -1153,7 +1394,7 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus, reg = SWRM_DPn_BLOCK_CTRL2_BANK(offset, params->port_num, bank); value = pcfg->blk_group_count; - ret = ctrl->reg_write(ctrl, reg, value); + ret = qcom_swrm_port_reg_write(ctrl, params->port_num, reg, value); if (ret) goto err; } @@ -1163,10 +1404,10 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus, if (pcfg->hstart != SWR_INVALID_PARAM && pcfg->hstop != SWR_INVALID_PARAM) { value = (pcfg->hstop << 4) | pcfg->hstart; - ret = ctrl->reg_write(ctrl, reg, value); + ret = qcom_swrm_port_reg_write(ctrl, params->port_num, reg, value); } else { value = (SWR_HSTOP_MAX_VAL << 4) | SWR_HSTART_MIN_VAL; - ret = ctrl->reg_write(ctrl, reg, value); + ret = qcom_swrm_port_reg_write(ctrl, params->port_num, reg, value); } if (ret) @@ -1175,13 +1416,29 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus, if (pcfg->bp_mode != SWR_INVALID_PARAM) { offset = ctrl->reg_layout[SWRM_OFFSET_DP_BLOCK_CTRL3_BANK]; reg = SWRM_DPn_BLOCK_CTRL3_BANK(offset, params->port_num, bank); - ret = ctrl->reg_write(ctrl, reg, pcfg->bp_mode); + ret = qcom_swrm_port_reg_write(ctrl, params->port_num, reg, + pcfg->bp_mode); } err: return ret; } +static bool qcom_swrm_port_is_pcm(struct sdw_bus *bus, unsigned int port_num) +{ + struct sdw_master_runtime *m_rt; + struct sdw_port_runtime *p_rt; + + list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) { + list_for_each_entry(p_rt, &m_rt->port_list, port_node) { + if (p_rt->num == port_num) + return m_rt->stream->type == SDW_STREAM_PCM; + } + } + + return false; +} + static int qcom_swrm_port_enable(struct sdw_bus *bus, struct sdw_enable_ch *enable_ch, unsigned int bank) @@ -1189,18 +1446,49 @@ static int qcom_swrm_port_enable(struct sdw_bus *bus, u32 reg; struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); u32 val; + int ret; u32 offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_BANK]; reg = SWRM_DPn_PORT_CTRL_BANK(offset, enable_ch->port_num, bank); - ctrl->reg_read(ctrl, reg, &val); + qcom_swrm_port_reg_read(ctrl, enable_ch->port_num, reg, &val); - if (enable_ch->enable) - val |= (enable_ch->ch_mask << SWRM_DP_PORT_CTRL_EN_CHAN_SHFT); - else + if (enable_ch->enable) { + u8 ch_mask = ctrl->pconfig[enable_ch->port_num].ch_mask; + + /* + * Prefer the per-port ch_mask from DT (qcom,ports-ch-mask) when + * present. The SDCA stream setup path arrives here with + * enable_ch->ch_mask reflecting stream-level ch_count, which + * for a mono PCM opening a stereo port only enables channel 0 + * on the wire. The DT value describes the port's intrinsic + * channel layout (e.g. 0x3 for a 2-channel stereo port) so both + * slots are transmitted regardless of PCM channel count. + */ + if (ch_mask == SWR_INVALID_PARAM) + ch_mask = enable_ch->ch_mask; + val |= (ch_mask << SWRM_DP_PORT_CTRL_EN_CHAN_SHFT); + } else { val &= ~(0xff << SWRM_DP_PORT_CTRL_EN_CHAN_SHFT); + } - return ctrl->reg_write(ctrl, reg, val); + /* + * On v3.1.0 and later a PCM port needs its data path gated through + * PCM_PORT_CTRL on top of the per-port enable. Earlier IPs have no + * such register, and the stream type is not a reliable discriminator + * there either: the Qualcomm ASoC glue allocates every stream as + * SDW_STREAM_PCM, so restrict this to the versions which need it. + */ + if (ctrl->version >= SWRM_VERSION_3_1_0 && + qcom_swrm_port_is_pcm(bus, enable_ch->port_num)) { + ret = qcom_swrm_port_reg_write(ctrl, enable_ch->port_num, + SWRM_DP_PCM_PORT_CTRL(enable_ch->port_num), + enable_ch->enable ? SWRM_DP_PCM_PORT_CTRL_EN : 0); + if (ret) + return ret; + } + + return qcom_swrm_port_reg_write(ctrl, enable_ch->port_num, reg, val); } static const struct sdw_master_port_ops qcom_swrm_port_ops = { @@ -1569,6 +1857,7 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) pcfg->word_length = SWR_INVALID_PARAM; pcfg->blk_group_count = SWR_INVALID_PARAM; pcfg->lane_control = SWR_INVALID_PARAM; + pcfg->ch_mask = SWR_INVALID_PARAM; of_property_read_u8_index(np, "qcom,ports-hstart", i, &pcfg->hstart); @@ -1580,6 +1869,8 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) i, &pcfg->blk_group_count); of_property_read_u8_index(np, "qcom,ports-lane-control", i, &pcfg->lane_control); + + of_property_read_u8_index(np, "qcom,ports-ch-mask", i, &pcfg->ch_mask); } return 0; @@ -1613,6 +1904,126 @@ static int swrm_reg_show(struct seq_file *s_file, void *data) DEFINE_SHOW_ATTRIBUTE(swrm_reg); #endif +/* + * Resolve "qcom,secondary-lanes" into the single lane provider whose DATA lanes + * this controller borrows. Every entry has to name the same provider and its + * local lanes in order starting at 0, which is what lets the DPn dispatcher + * translate addresses with one constant delta. Returns -EPROBE_DEFER for as + * long as the provider has not finished probing. + */ +static int qcom_swrm_setup_lane_provider(struct qcom_swrm_ctrl *ctrl) +{ + unsigned int first_port = 0, last_port = 0; + struct device_node *np = ctrl->dev->of_node; + struct qcom_swrm_ctrl *provider; + struct of_phandle_args args; + struct platform_device *pdev; + int i, ret; + + if (!of_property_present(np, "qcom,secondary-lanes")) + return 0; + + /* + * All entries have to name the same provider, so resolve it from the + * first one and let the loop below only validate the lane indices. + */ + ret = of_parse_phandle_with_args(np, "qcom,secondary-lanes", + "#qcom,swrm-lane-cells", 0, &args); + if (ret) + return ret; + + pdev = of_find_device_by_node(args.np); + of_node_put(args.np); + if (!pdev) + return -EPROBE_DEFER; + + provider = platform_get_drvdata(pdev); + if (!provider || !provider->lane_provider_ready) { + put_device(&pdev->dev); + return -EPROBE_DEFER; + } + + /* + * Hold a link to the provider: this controller dereferences it on every + * bank switch and on every DPn access for a borrowed lane, so it must + * not be unbound first. + */ + ret = device_link_add(ctrl->dev, &pdev->dev, + DL_FLAG_AUTOREMOVE_CONSUMER) ? 0 : -EINVAL; + put_device(&pdev->dev); + if (ret) + return dev_err_probe(ctrl->dev, ret, + "failed to link to lane provider\n"); + + ctrl->lane_provider = provider; + provider->lane_consumer = ctrl; + ctrl->provider_lane_base = SWRM_MAX_DATA_LANES; + + for (i = 0; i < SWRM_MAX_DATA_LANES; i++) { + bool same_provider; + + ret = of_parse_phandle_with_args(np, "qcom,secondary-lanes", + "#qcom,swrm-lane-cells", i, + &args); + if (ret == -ENOENT) + break; + if (ret) + return ret; + + same_provider = args.np == provider->dev->of_node; + of_node_put(args.np); + + if (!same_provider) + return dev_err_probe(ctrl->dev, -EINVAL, + "qcom,secondary-lanes: multiple providers not supported\n"); + + if (args.args_count != 1 || args.args[0] != i) + return dev_err_probe(ctrl->dev, -EINVAL, + "qcom,secondary-lanes entry %d: expected provider lane %d\n", + i, i); + + ctrl->num_provider_lanes++; + } + + if (ctrl->provider_lane_base + ctrl->num_provider_lanes > SDW_MAX_LANES) + return dev_err_probe(ctrl->dev, -EINVAL, + "too many lanes: %u local + %u borrowed\n", + ctrl->provider_lane_base, + ctrl->num_provider_lanes); + + /* + * Ports driven from a borrowed lane are serviced by the provider's own + * DPn blocks, in order: the lowest such port maps to the provider's + * DP1, the next one to DP2 and so on. A single address delta only + * describes that if the ports form one contiguous run, so require it. + */ + for (i = 1; i <= ctrl->nports; i++) { + u8 lane = ctrl->pconfig[i].lane_control; + + if (lane == SWR_INVALID_PARAM || + lane < ctrl->provider_lane_base || + lane >= ctrl->provider_lane_base + ctrl->num_provider_lanes) + continue; + + if (first_port && i != last_port + 1) + return dev_err_probe(ctrl->dev, -EINVAL, + "ports on borrowed lanes must be contiguous, %d follows %u\n", + i, last_port); + + if (!first_port) + first_port = i; + last_port = i; + } + + if (!first_port) + return dev_err_probe(ctrl->dev, -EINVAL, + "qcom,secondary-lanes set but no port uses a borrowed lane\n"); + + ctrl->provider_dpn_offset = (first_port - 1) * SWRM_DPn_SLOT_STRIDE; + + return 0; +} + static int qcom_swrm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1632,6 +2043,8 @@ static int qcom_swrm_probe(struct platform_device *pdev) data = of_device_get_match_data(dev); ctrl->ee = data->ee; + ctrl->is_lane_provider = of_property_present(dev->of_node, + "#qcom,swrm-lane-cells"); ctrl->max_reg = data->max_reg; ctrl->reg_layout = data->reg_layout; ctrl->rows_index = sdw_find_row_index(data->default_rows); @@ -1683,6 +2096,32 @@ static int qcom_swrm_probe(struct platform_device *pdev) init_completion(&ctrl->broadcast); init_completion(&ctrl->enumeration); + ctrl->reg_read(ctrl, SWRM_COMP_HW_VERSION, &ctrl->version); + + ctrl->bus.controller_id = -1; + + if (ctrl->version > SWRM_VERSION_1_3_0) { + ctrl->reg_read(ctrl, SWRM_COMP_MASTER_ID, &val); + ctrl->bus.controller_id = val; + } + + if (ctrl->is_lane_provider) { + /* + * A lane provider has no control lane and therefore no bus of + * its own: no peripherals to enumerate, no ports to configure + * from DT and no DAIs. Stop here, before anything that would + * touch the uninitialised sdw_bus. The consumer starts the + * frame generator once MM_SYNC ties the two together. + */ + ctrl->lane_provider_ready = true; + + dev_dbg(dev, "Qualcomm SoundWire lane provider v%x.%x.%x registered\n", + (ctrl->version >> 24) & 0xff, (ctrl->version >> 16) & 0xff, + ctrl->version & 0xffff); + + return 0; + } + ctrl->bus.ops = &qcom_swrm_ops; ctrl->bus.port_ops = &qcom_swrm_port_ops; ctrl->bus.compute_params = &qcom_swrm_compute_params; @@ -1692,6 +2131,10 @@ static int qcom_swrm_probe(struct platform_device *pdev) if (ret) goto err_clk; + ret = qcom_swrm_setup_lane_provider(ctrl); + if (ret) + goto err_clk; + params = &ctrl->bus.params; params->max_dr_freq = DEFAULT_CLK_FREQ; params->curr_dr_freq = DEFAULT_CLK_FREQ; @@ -1749,7 +2192,18 @@ static int qcom_swrm_probe(struct platform_device *pdev) goto err_clk; } - qcom_swrm_init(ctrl); + if (ctrl->lane_provider) { + ret = qcom_swrm_init(ctrl->lane_provider); + if (ret) { + dev_err(dev, "failed to init lane provider: %d\n", ret); + goto err_master_add; + } + } + + ret = qcom_swrm_init(ctrl); + if (ret) + goto err_master_add; + wait_for_completion_timeout(&ctrl->enumeration, msecs_to_jiffies(TIMEOUT_MS)); ret = qcom_swrm_register_dais(ctrl); @@ -1786,7 +2240,8 @@ static void qcom_swrm_remove(struct platform_device *pdev) { struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(&pdev->dev); - sdw_bus_master_delete(&ctrl->bus); + if (!ctrl->is_lane_provider) + sdw_bus_master_delete(&ctrl->bus); clk_disable_unprepare(ctrl->hclk); } @@ -1821,6 +2276,8 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev) } else { reset_control_reset(ctrl->audio_cgcr); + qcom_swrm_program_mm_sync(ctrl); + if (ctrl->version == SWRM_VERSION_1_7_0) { ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee); ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index 0b00fcdcab2d6..2c1b2e30f8359 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -991,15 +991,53 @@ static int sdw_port_config(struct sdw_port_runtime *p_rt, return 0; } -static void sdw_port_free(struct sdw_port_runtime *p_rt) +/* + * sdw_stream_add_master()/sdw_stream_add_slave() can be called more than + * once for the same stream: .hw_params may be invoked repeatedly for a + * DAI, and a device may route several DAIs - each contributing its own + * data port - through a single stream. Look up the port runtime by port + * number so that repeated calls reconfigure the existing entry while a + * port which is not part of the stream yet gets a new one appended. + */ +static struct sdw_port_runtime *sdw_port_find(struct list_head *port_list, + unsigned int num) { - list_del(&p_rt->port_node); - kfree(p_rt); + struct sdw_port_runtime *p_rt; + + list_for_each_entry(p_rt, port_list, port_node) { + if (p_rt->num == num) + return p_rt; + } + + return NULL; } -static bool sdw_slave_port_allocated(struct sdw_slave_runtime *s_rt) +static int sdw_port_alloc_missing(struct list_head *port_list, + const struct sdw_port_config *port_config, + unsigned int num_ports) { - return !list_empty(&s_rt->port_list); + struct sdw_port_runtime *p_rt; + int i; + + for (i = 0; i < num_ports; i++) { + if (sdw_port_find(port_list, port_config[i].num)) + continue; + + p_rt = sdw_port_alloc(port_list); + if (!p_rt) + return -ENOMEM; + + /* claim the number so the next iteration finds this entry */ + p_rt->num = port_config[i].num; + } + + return 0; +} + +static void sdw_port_free(struct sdw_port_runtime *p_rt) +{ + list_del(&p_rt->port_node); + kfree(p_rt); } static void sdw_slave_port_free(struct sdw_slave *slave, @@ -1022,23 +1060,6 @@ static void sdw_slave_port_free(struct sdw_slave *slave, } } -static int sdw_slave_port_alloc(struct sdw_slave *slave, - struct sdw_slave_runtime *s_rt, - unsigned int num_config) -{ - struct sdw_port_runtime *p_rt; - int i; - - /* Iterate for number of ports to perform initialization */ - for (i = 0; i < num_config; i++) { - p_rt = sdw_port_alloc(&s_rt->port_list); - if (!p_rt) - return -ENOMEM; - } - - return 0; -} - static int sdw_slave_port_is_valid_range(struct device *dev, int num) { if (!SDW_VALID_PORT_RANGE(num)) { @@ -1052,14 +1073,14 @@ static int sdw_slave_port_is_valid_range(struct device *dev, int num) static int sdw_slave_port_config(struct sdw_slave *slave, struct sdw_slave_runtime *s_rt, const struct sdw_port_config *port_config, + unsigned int num_ports, bool is_bpt_stream) { struct sdw_port_runtime *p_rt; int ret; int i; - i = 0; - list_for_each_entry(p_rt, &s_rt->port_list, port_node) { + for (i = 0; i < num_ports; i++) { if (!is_bpt_stream) { ret = sdw_slave_port_is_valid_range(&slave->dev, port_config[i].num); if (ret < 0) @@ -1081,10 +1102,13 @@ static int sdw_slave_port_config(struct sdw_slave *slave, return -EINVAL; } + p_rt = sdw_port_find(&s_rt->port_list, port_config[i].num); + if (!p_rt) + return -EINVAL; + ret = sdw_port_config(p_rt, port_config, i); if (ret < 0) return ret; - i++; } return 0; @@ -1104,35 +1128,22 @@ static void sdw_master_port_free(struct sdw_master_runtime *m_rt) } } -static int sdw_master_port_alloc(struct sdw_master_runtime *m_rt, - unsigned int num_ports) +static int sdw_master_port_config(struct sdw_master_runtime *m_rt, + const struct sdw_port_config *port_config, + unsigned int num_ports) { struct sdw_port_runtime *p_rt; + int ret; int i; - /* Iterate for number of ports to perform initialization */ for (i = 0; i < num_ports; i++) { - p_rt = sdw_port_alloc(&m_rt->port_list); + p_rt = sdw_port_find(&m_rt->port_list, port_config[i].num); if (!p_rt) - return -ENOMEM; - } - - return 0; -} - -static int sdw_master_port_config(struct sdw_master_runtime *m_rt, - const struct sdw_port_config *port_config) -{ - struct sdw_port_runtime *p_rt; - int ret; - int i; + return -EINVAL; - i = 0; - list_for_each_entry(p_rt, &m_rt->port_list, port_node) { ret = sdw_port_config(p_rt, port_config, i); if (ret < 0) return ret; - i++; } return 0; @@ -1376,7 +1387,8 @@ static int sdw_config_stream(struct device *dev, if (stream->params.bps && stream->params.bps != stream_config->bps) { - dev_err(dev, "bps not matching, stream:%s\n", stream->name); + dev_err(dev, "bps not matching, stream:%s, %u vs %u\n", + stream->name, stream->params.bps, stream_config->bps); return -EINVAL; } @@ -2017,6 +2029,7 @@ int sdw_stream_add_master(struct sdw_bus *bus, { struct sdw_master_runtime *m_rt; bool alloc_master_rt = false; + bool first_ports = false; int ret; mutex_lock(&bus->bus_lock); @@ -2056,13 +2069,15 @@ int sdw_stream_add_master(struct sdw_bus *bus, alloc_master_rt = true; } - if (!sdw_master_port_allocated(m_rt)) { - ret = sdw_master_port_alloc(m_rt, num_ports); - if (ret) - goto alloc_error; + if (!sdw_master_port_allocated(m_rt)) + first_ports = true; + + ret = sdw_port_alloc_missing(&m_rt->port_list, port_config, num_ports); + if (ret) + goto alloc_error; + if (first_ports) stream->m_rt_count++; - } ret = sdw_master_rt_config(m_rt, stream_config); if (ret < 0) @@ -2072,7 +2087,7 @@ int sdw_stream_add_master(struct sdw_bus *bus, if (ret) goto unlock; - ret = sdw_master_port_config(m_rt, port_config); + ret = sdw_master_port_config(m_rt, port_config, num_ports); goto unlock; @@ -2190,11 +2205,9 @@ int sdw_stream_add_slave(struct sdw_slave *slave, alloc_slave_rt = true; } - if (!sdw_slave_port_allocated(s_rt)) { - ret = sdw_slave_port_alloc(slave, s_rt, num_ports); - if (ret) - goto alloc_error; - } + ret = sdw_port_alloc_missing(&s_rt->port_list, port_config, num_ports); + if (ret) + goto alloc_error; ret = sdw_master_rt_config(m_rt, stream_config); if (ret) @@ -2208,7 +2221,7 @@ int sdw_stream_add_slave(struct sdw_slave *slave, if (ret) goto unlock; - ret = sdw_slave_port_config(slave, s_rt, port_config, + ret = sdw_slave_port_config(slave, s_rt, port_config, num_ports, stream->type == SDW_STREAM_BPT); if (ret) goto unlock; From 4013b9165a78930271b396271acb52f26c3eba69 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 22 Sep 2026 22:10:27 +0530 Subject: [PATCH 0501/1133] PENDING: ASoC: codecs: lpass-macro: add codec version 2.9 and fix register cache handling Add LPASS macro codec support for codec version 2.9 and correct several register cache issues affecting all four macro codecs. Codec version handling in lpass-rx-macro: - Handle LPASS_CODEC_VERSION_2_9 in the version based switch statements so it is treated the same as the other members of the 2.5 family, which is what Glymur requires. This covers the read-write register check, the control and widget selection at component probe, and the register stride and default table selection at probe. - Add LPASS_MACRO_FLAG_HAS_NPL_CLOCK to the sm8550 match entry. The missing flag left sm8550 running without its NPL clock, which caused sporadic playback stalls. Register default sorting in lpass-rx-macro and lpass-wsa-macro: - Both drivers build the register defaults array by concatenating a base table with a codec version specific one, so the result is not in register address order because the version specific ranges overlap the base range. Regmap detects this, warns that the driver needs fixing, and sorts its own copy at runtime. Sort the concatenated array before handing it to regmap so the warning goes away and regmap does not sort a second time. The base and version specific split is kept deliberately for readability, so a static reorder is not appropriate here. Cache type for all four macro codecs: - Switch the register cache from REGCACHE_FLAT to REGCACHE_MAPLE in lpass-rx-macro, lpass-wsa-macro, lpass-tx-macro and lpass-va-macro. A flat cache hides missing default reads by returning the zero initialised cache slot instead of performing a bus read, and the caller cannot tell that value apart from a real hardware value, so any readable non-volatile register without a default silently returns wrong data. With a maple cache a miss returns -ENOENT and the regmap core falls back to a real bus read, so the caller always observes the true hardware value. Write cache behaviour is unchanged. Signed-off-by: Mohammad Rafi Shaik --- sound/soc/codecs/lpass-rx-macro.c | 7 ++++++- sound/soc/codecs/lpass-tx-macro.c | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index c41eb8de61609..cc44b0329cd28 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -1613,6 +1613,7 @@ static bool rx_is_rw_register(struct device *dev, unsigned int reg) case LPASS_CODEC_VERSION_2_6: case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: + case LPASS_CODEC_VERSION_2_9: return rx_2_5_is_rw_register(dev, reg); default: break; @@ -3652,6 +3653,7 @@ static int rx_macro_component_probe(struct snd_soc_component *component) case LPASS_CODEC_VERSION_2_6: case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: + case LPASS_CODEC_VERSION_2_9: controls = rx_macro_2_5_snd_controls; num_controls = ARRAY_SIZE(rx_macro_2_5_snd_controls); widgets = rx_macro_2_5_dapm_widgets; @@ -3837,6 +3839,7 @@ static int rx_macro_probe(struct platform_device *pdev) case LPASS_CODEC_VERSION_2_6: case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: + case LPASS_CODEC_VERSION_2_9: rx->rxn_reg_stride = 0xc0; rx->rxn_reg_stride2 = 0x0; def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_2_5_defaults); @@ -3934,9 +3937,11 @@ static int rx_macro_probe(struct platform_device *pdev) static const struct of_device_id rx_macro_dt_match[] = { { + .compatible = "qcom,glymur-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { .compatible = "qcom,sc7280-lpass-rx-macro", .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, - }, { .compatible = "qcom,sm6115-lpass-rx-macro", .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 6deaaabe43afa..f3cd8c67ef978 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -2477,8 +2477,21 @@ static const struct tx_macro_data lpass_ver_11 = { .extra_routes_num = ARRAY_SIZE(tx_audio_map_v9_2), }; +static const struct tx_macro_data lpass_ver_11_glymur = { + .flags = LPASS_MACRO_FLAG_HAS_NPL_CLOCK | + LPASS_MACRO_FLAG_RESET_SWR, + .ver = LPASS_VER_11_0_0, + .extra_widgets = tx_macro_dapm_widgets_v9_2, + .extra_widgets_num = ARRAY_SIZE(tx_macro_dapm_widgets_v9_2), + .extra_routes = tx_audio_map_v9_2, + .extra_routes_num = ARRAY_SIZE(tx_audio_map_v9_2), +}; + static const struct of_device_id tx_macro_dt_match[] = { { + .compatible = "qcom,glymur-lpass-tx-macro", + .data = &lpass_ver_11_glymur, + }, { /* * The block is actually LPASS v9.4, but keep LPASS v9 match * data and audio widgets, due to compatibility reasons. @@ -2512,6 +2525,7 @@ static const struct of_device_id tx_macro_dt_match[] = { { } }; MODULE_DEVICE_TABLE(of, tx_macro_dt_match); + static struct platform_driver tx_macro_driver = { .driver = { .name = "tx_macro", From 79716798889a14623babe72cdf39b1a801ec1c9f Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 22 Sep 2026 22:16:23 +0530 Subject: [PATCH 0502/1133] PENDING: clk: qcom: add Glymur LPASS clock controller with reset lines Add a thin LPASS clock controller driver for Glymur that exposes the reset lines required by the LPASS audio macro codecs and the SoundWire masters. The driver provides no clocks of its own and acts purely as a reset provider over two register regions. The driver registers two device tree compatibles, each with its own regmap and reset map: - qcom,glymur-lpassaudiocc covers the LPASS audio CSR region and exposes the receive path reset line together with the four WSA SoundWire reset lines. - qcom,glymur-lpasscc covers the LPASS TCSR region and exposes the transmit path SoundWire reset line. Probe resolves the per compatible controller description from the match data and hands it to the common Qualcomm clock controller probe helper, which builds the regmap and registers the reset controller. Reset identifiers come from the Glymur LPASS clock controller device tree binding header. A new SC_LPASSCC_GLYMUR Kconfig symbol builds the driver as a module by default on Qualcomm platforms, matching the other LPASS clock controller entries. These reset lines are required for the LPASS audio macros and the SoundWire compute mode controller to come out of reset on Glymur. Signed-off-by: Mohammad Rafi Shaik --- drivers/clk/qcom/Kconfig | 11 ++++ drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/lpasscc-glymur.c | 91 +++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 drivers/clk/qcom/lpasscc-glymur.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 27d0ab24d50a4..89e6a636e4973 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -1274,6 +1274,17 @@ config SC_LPASSCC_8280XP Say Y if you want to use the LPASS branch clocks of the LPASS clock controller to reset the LPASS subsystem. +config SC_LPASSCC_GLYMUR + tristate "GLYMUR Low Power Audio Subsystem (LPASS) Clock Controller" + depends on ARM64 || COMPILE_TEST + default m if ARCH_QCOM + help + Support for the LPASS clock controller on Glymur devices. + Say Y if you want to use the LPASS branch clocks of the LPASS clock + controller to reset the LPASS subsystem. Required for the LPASS + audio macros and the SoundWire compute-mode controller to leave + reset on Glymur. + config SC_LPASS_CORECC_7180 tristate "SC7180 LPASS Core Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 6affb5073f269..0c7a67b9cee33 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -151,6 +151,7 @@ obj-$(CONFIG_SC_LPASSCC_7280) += lpasscc-sc7280.o obj-$(CONFIG_SC_LPASSCC_8280XP) += lpasscc-sc8280xp.o obj-$(CONFIG_SC_LPASS_CORECC_7180) += lpasscorecc-sc7180.o obj-$(CONFIG_SC_LPASS_CORECC_7280) += lpasscorecc-sc7280.o lpassaudiocc-sc7280.o +obj-$(CONFIG_SC_LPASSCC_GLYMUR) += lpasscc-glymur.o obj-$(CONFIG_SC_VIDEOCC_7180) += videocc-sc7180.o obj-$(CONFIG_SC_VIDEOCC_7280) += videocc-sc7280.o obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o diff --git a/drivers/clk/qcom/lpasscc-glymur.c b/drivers/clk/qcom/lpasscc-glymur.c new file mode 100644 index 0000000000000..fe1b16a6f1327 --- /dev/null +++ b/drivers/clk/qcom/lpasscc-glymur.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2025, Qualcomm Inc + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "reset.h" + +static const struct qcom_reset_map lpass_audiocc_glymur_resets[] = { + [LPASS_AUDIO_SWR_RX_CGCR] = { 0xA0, 1 }, + [LPASS_AUDIO_SWR_WSA1_CGCR] = { 0xB0, 1 }, + [LPASS_AUDIO_SWR_WSA2_CGCR] = { 0xD8, 1 }, + [LPASS_AUDIO_SWR_WSA3_CGCR] = { 0x300C, 1 }, + [LPASS_AUDIO_SWR_WSA4_CGCR] = { 0x301C, 1 }, +}; + +static const struct regmap_config lpass_audiocc_glymur_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .name = "lpass-audio-csr", + .max_register = 0x1000, +}; + +static const struct qcom_cc_desc lpass_audiocc_glymur_reset_desc = { + .config = &lpass_audiocc_glymur_regmap_config, + .resets = lpass_audiocc_glymur_resets, + .num_resets = ARRAY_SIZE(lpass_audiocc_glymur_resets), +}; + +static const struct qcom_reset_map lpasscc_glymur_resets[] = { + [LPASS_AUDIO_SWR_TX_CGCR] = { 0xa028, 1 }, +}; + +static const struct regmap_config lpasscc_glymur_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .name = "lpass-tcsr", + .max_register = 0x12000, +}; + +static const struct qcom_cc_desc lpasscc_glymur_reset_desc = { + .config = &lpasscc_glymur_regmap_config, + .resets = lpasscc_glymur_resets, + .num_resets = ARRAY_SIZE(lpasscc_glymur_resets), +}; + +static const struct of_device_id lpasscc_glymur_match_table[] = { + { + .compatible = "qcom,glymur-lpassaudiocc", + .data = &lpass_audiocc_glymur_reset_desc, + }, { + .compatible = "qcom,glymur-lpasscc", + .data = &lpasscc_glymur_reset_desc, + }, + { } +}; +MODULE_DEVICE_TABLE(of, lpasscc_glymur_match_table); + +static int lpasscc_glymur_probe(struct platform_device *pdev) +{ + const struct qcom_cc_desc *desc = of_device_get_match_data(&pdev->dev); + + return qcom_cc_probe_by_index(pdev, 0, desc); +} + +static struct platform_driver lpasscc_glymur_driver = { + .probe = lpasscc_glymur_probe, + .driver = { + .name = "lpasscc-glymur", + .of_match_table = lpasscc_glymur_match_table, + }, +}; + +module_platform_driver(lpasscc_glymur_driver); + +MODULE_AUTHOR("Srinivas Kandagatla "); +MODULE_DESCRIPTION("QTI LPASSCC SC8280XP Driver"); +MODULE_LICENSE("GPL"); From c12b28aa1fd53ebbf4fa9bc513f824ba39165c27 Mon Sep 17 00:00:00 2001 From: Gopi Chandra Sekhar Reddy Kanala Date: Mon, 31 Aug 2026 11:59:08 +0530 Subject: [PATCH 0503/1133] PENDING: arm64: defconfig: enable SDCA and WCD9378 SDCA codec Enable SDCA and WCD9378 SDCA codec as module. Signed-off-by: Gopi Chandra Sekhar Reddy Kanala --- arch/arm64/configs/defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7b4985b29b21c..4ca7af9e23f2b 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1113,6 +1113,10 @@ CONFIG_SND_SOC_MT8195=m CONFIG_SND_SOC_MT8195_MT6359=m CONFIG_SND_SOC_MT8365=m CONFIG_SND_SOC_MT8365_MT6357=m +CONFIG_SND_SOC_SDCA=m +CONFIG_SND_SOC_SDCA_OPTIONAL=m +CONFIG_SND_SOC_SDCA_CLASS=m +CONFIG_SND_SOC_SDCA_CLASS_FUNCTION=m CONFIG_SND_MESON_AXG_SOUND_CARD=m CONFIG_SND_MESON_GX_SOUND_CARD=m CONFIG_SND_SOC_QCOM=m @@ -1189,6 +1193,7 @@ CONFIG_SND_SOC_WCD9335=m CONFIG_SND_SOC_WCD934X=m CONFIG_SND_SOC_WCD937X_SDW=m CONFIG_SND_SOC_WCD939X_SDW=m +CONFIG_SND_SOC_WCD9378_SDCA=m CONFIG_SND_SOC_WM8524=m CONFIG_SND_SOC_WM8904=m CONFIG_SND_SOC_WM8960=m From de815245e4566720aa8273a561fcd8aecca8dbbd Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Wed, 19 Aug 2026 11:12:03 +0530 Subject: [PATCH 0504/1133] FROMLIST: soc: qcom: pd-mapper: Add support for Maili SoC Add support for the Qualcomm Maili SoC to the protection domain mapper. Maili shares the same protection domain configuration as Kaanapali, so reuse the existing Kaanapali domain data. Link: https://lore.kernel.org/all/20260819054203.61385-3-prasad.kumpatla@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Prasad Kumpatla --- drivers/soc/qcom/qcom_pd_mapper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index 64ca99d7fad92..3376423d237f0 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -626,6 +626,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,hawi", .data = kaanapali_domains, }, { .compatible = "qcom,kaanapali", .data = kaanapali_domains, }, { .compatible = "qcom,mahua", .data = glymur_domains, }, + { .compatible = "qcom,maili", .data = kaanapali_domains, }, { .compatible = "qcom,milos", .data = sm8550_domains, }, { .compatible = "qcom,msm8226", .data = NULL, }, { .compatible = "qcom,msm8909", .data = NULL, }, From 35c4fd26452f94c0cf25092457399e3710f7485e Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Wed, 23 Sep 2026 14:16:22 +0530 Subject: [PATCH 0505/1133] FROMLIST: ASoC: dt-bindings: qcom: Add Maili LPASS macro codecs Add compatibles for the RX, TX and VA macro codecs found in the Low Power Audio SubSystem (LPASS) of the Qualcomm Maili SoC. The Maili RX, TX and VA macros are identical to their Hawi counterparts, so document them with the corresponding Hawi compatible as fallback. Link: https://patch.msgid.link/20260923084627.748920-4-prasad.kumpatla@oss.qualcomm.com Signed-off-by: Prasad Kumpatla --- .../devicetree/bindings/sound/qcom,lpass-rx-macro.yaml | 3 +++ .../devicetree/bindings/sound/qcom,lpass-tx-macro.yaml | 3 +++ .../devicetree/bindings/sound/qcom,lpass-va-macro.yaml | 3 +++ 3 files changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml index 4ab6f1bc93eb6..e96ad0b6f40c3 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml @@ -28,6 +28,9 @@ properties: - qcom,sm8750-lpass-rx-macro - qcom,x1e80100-lpass-rx-macro - const: qcom,sm8550-lpass-rx-macro + - items: + - const: qcom,maili-lpass-rx-macro + - const: qcom,hawi-lpass-rx-macro reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml index 7fdc824e9099d..62cb8b583eb54 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml @@ -28,6 +28,9 @@ properties: - qcom,sm8750-lpass-tx-macro - qcom,x1e80100-lpass-tx-macro - const: qcom,sm8550-lpass-tx-macro + - items: + - const: qcom,maili-lpass-tx-macro + - const: qcom,hawi-lpass-tx-macro reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml index aea31fbdad376..7334112ea8995 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml @@ -28,6 +28,9 @@ properties: - qcom,sm8750-lpass-va-macro - qcom,x1e80100-lpass-va-macro - const: qcom,sm8550-lpass-va-macro + - items: + - const: qcom,maili-lpass-va-macro + - const: qcom,hawi-lpass-va-macro reg: maxItems: 1 From 5ed58d79149a4027719cf42c171f264e7f71cef0 Mon Sep 17 00:00:00 2001 From: Sarath Ganapathiraju Date: Mon, 28 Sep 2026 21:27:38 +0530 Subject: [PATCH 0506/1133] FROMLIST: dt-bindings: clock: qcom: Add LPASS VA CSR HeartBeat pulse clock Add a binding for the Qualcomm LPASS VA CSR rate generator node that exposes the lpass_heartbeat_pulse clock on Hawi. The HeartBeat Pulse, also known as RateGen Pulse, synchronizes the start of DMAs and Codec Interfaces for the audio usecase and can serve as a periodic wakeup source for the DSP. Require the LPASS LPR and audio vote clocks to access VA CSR register space safely. Signed-off-by: Sarath Ganapathiraju Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20260928-master-v9-1-2277f09f9a09@oss.qualcomm.com --- .../clock/qcom,hawi-lpass-va-csr.yaml | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,hawi-lpass-va-csr.yaml diff --git a/Documentation/devicetree/bindings/clock/qcom,hawi-lpass-va-csr.yaml b/Documentation/devicetree/bindings/clock/qcom,hawi-lpass-va-csr.yaml new file mode 100644 index 0000000000000..601da83add2bd --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,hawi-lpass-va-csr.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,hawi-lpass-va-csr.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm LPASS VA CSR heartbeat pulse clock provider + +maintainers: + - Srinivas Kandagatla + - Sarath Ganapathiraju + +description: + The Hawi LPASS (Low Power Audio Subsystem) VA CSR block contains a + rate generator that produces a periodic HeartBeat Pulse, also known + as the RateGen Pulse. This pulse synchronizes the start of DMAs and + Codec Interfaces for audio usecases and can serve as a periodic wakeup + source for the DSP. + +properties: + compatible: + enum: + - qcom,hawi-lpass-va-csr + + reg: + maxItems: 1 + description: Address and size of the VA CSR register block. + + clocks: + items: + - description: LPASS LPR (Low Power Resource) voting clock + - description: LPASS Audio voting clock + + clock-names: + items: + - const: lpr + - const: audio + + "#clock-cells": + const: 0 + +required: + - compatible + - reg + - clocks + - clock-names + - "#clock-cells" + +additionalProperties: false + +examples: + - | + #include + + clock-controller@7ee0000 { + compatible = "qcom,hawi-lpass-va-csr"; + reg = <0x07ee0000 0xe000>; + clocks = <&q6prmcc LPASS_HW_LPR_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "lpr", "audio"; + #clock-cells = <0>; + }; From 20ce5e34672fc1dfe74ed433a3898f4fde4dcf70 Mon Sep 17 00:00:00 2001 From: Sarath Ganapathiraju Date: Mon, 28 Sep 2026 21:27:39 +0530 Subject: [PATCH 0507/1133] FROMLIST: clk: qcom: Add LPASS VA CSR heartbeat pulse clock The HeartBeat Pulse, also known as RateGen Pulse, synchronizes the start of DMAs and Codec Interfaces for the audio usecases and can serve as a periodic wakeup source for the DSP. Add the LPASS VA CSR driver that models the rate generator as a clock provider so consumers can enable and disable it through the common clock framework. Attach the DT vote clocks to runtime PM and resume the device before programming the rate generator registers in probe. Also take a runtime PM reference from the clock prepare path so later enable and disable register accesses happen only while the LPASS votes are active. Signed-off-by: Sarath Ganapathiraju Link: https://patch.msgid.link/20260928-master-v9-2-2277f09f9a09@oss.qualcomm.com --- drivers/clk/qcom/Kconfig | 14 +++ drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/lpass-va-csr.c | 174 ++++++++++++++++++++++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 drivers/clk/qcom/lpass-va-csr.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 89e6a636e4973..bffee0ab3a94b 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -2148,6 +2148,20 @@ config CLK_GFM_LPASS_SM8250 Support for the Glitch Free Mux (GFM) Low power audio subsystem (LPASS) clocks found on SM8250 SoCs. +config QCOM_CLK_LPASS_HEARTBEAT_PULSE + tristate "Qualcomm LPASS VA CSR heartbeat pulse clock provider" + depends on COMMON_CLK + depends on ARM64 || COMPILE_TEST + select REGMAP_MMIO + default m if ARCH_QCOM + help + Qualcomm LPASS VA CSR block contains the rate generator hardware + that produces the HeartBeat Pulse (also known as RateGen Pulse). + This driver models the rate generator as a clock provider so + that consumers can enable or disable it via the common clock + framework, and it can be used to synchronize the start of DMAs + and Codec Interfaces or as a periodic wakeup source for the DSP. + config SM_VIDEOCC_8450 tristate "SM8450 Video Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 0c7a67b9cee33..52038debcd96d 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -110,6 +110,7 @@ obj-$(CONFIG_QCOM_A7PLL) += a7-pll.o obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o obj-$(CONFIG_QCOM_CLK_APCC_MSM8996) += apcs-msm8996.o clk-cpu-8996.o clk-cbf-8996.o obj-$(CONFIG_QCOM_CLK_APCS_SDX55) += apcs-sdx55.o +obj-$(CONFIG_QCOM_CLK_LPASS_HEARTBEAT_PULSE) += lpass-va-csr.o obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o diff --git a/drivers/clk/qcom/lpass-va-csr.c b/drivers/clk/qcom/lpass-va-csr.c new file mode 100644 index 0000000000000..93eafb2e043ab --- /dev/null +++ b/drivers/clk/qcom/lpass-va-csr.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-regmap.h" + +#define LPASS_RATE_GEN_CTRL 0xd000 +#define LPASS_RATE_GEN_COUNTER_0 0xd004 +#define LPASS_RATE_GEN_DELAY 0xd010 + +#define LPASS_RATE_GEN_MAX_REG LPASS_RATE_GEN_DELAY + +#define LPASS_RG_CTRL_EN BIT(0) + +struct lpass_va_csr_data { + u32 counter_0; + u32 delay; +}; + +static const struct lpass_va_csr_data hawi_csr_data = { + .counter_0 = 0x960, + .delay = 0x16, +}; + +static const struct regmap_config lpass_rate_gen_regmap_config = { + .name = "lpass_rate_gen", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = LPASS_RATE_GEN_MAX_REG, + .cache_type = REGCACHE_MAPLE, +}; + +struct lpass_va_csr { + struct device *dev; + struct clk_regmap hb; +}; + +#define to_lpass_va_csr(_hw) \ + container_of(to_clk_regmap(_hw), struct lpass_va_csr, hb) + +static int lpass_va_csr_hb_prepare(struct clk_hw *hw) +{ + struct lpass_va_csr *csr = to_lpass_va_csr(hw); + + return pm_runtime_resume_and_get(csr->dev); +} + +static void lpass_va_csr_hb_unprepare(struct clk_hw *hw) +{ + struct lpass_va_csr *csr = to_lpass_va_csr(hw); + + pm_runtime_put_sync(csr->dev); +} + +static const struct clk_ops lpass_va_csr_hb_ops = { + .prepare = lpass_va_csr_hb_prepare, + .unprepare = lpass_va_csr_hb_unprepare, + .enable = clk_enable_regmap, + .disable = clk_disable_regmap, +}; + +static int lpass_va_csr_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct lpass_va_csr_data *data = of_device_get_match_data(dev); + struct lpass_va_csr *csr; + struct clk_init_data init = { + .name = "lpass_heartbeat_pulse", + .ops = &lpass_va_csr_hb_ops, + }; + struct regmap *regmap; + void __iomem *base; + int ret; + + csr = devm_kzalloc(dev, sizeof(*csr), GFP_KERNEL); + if (!csr) + return -ENOMEM; + + csr->dev = dev; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + regmap = devm_regmap_init_mmio(dev, base, + &lpass_rate_gen_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "failed to init regmap\n"); + + ret = devm_pm_runtime_enable(dev); + if (ret) + return dev_err_probe(dev, ret, "failed to enable PM runtime\n"); + + ret = devm_pm_clk_create(dev); + if (ret) + return ret; + + ret = of_pm_clk_add_clks(dev); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to get vote clocks\n"); + + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; + + ret = regmap_write(regmap, LPASS_RATE_GEN_COUNTER_0, data->counter_0); + if (ret) { + pm_runtime_put_sync(dev); + return ret; + } + + ret = regmap_write(regmap, LPASS_RATE_GEN_DELAY, data->delay); + if (ret) { + pm_runtime_put_sync(dev); + return ret; + } + + csr->hb.regmap = regmap; + csr->hb.enable_reg = LPASS_RATE_GEN_CTRL; + csr->hb.enable_mask = LPASS_RG_CTRL_EN; + csr->hb.hw.init = &init; + + ret = devm_clk_register_regmap(dev, &csr->hb); + if (ret) { + pm_runtime_put_sync(dev); + return ret; + } + + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &csr->hb.hw); + if (ret) { + pm_runtime_put_sync(dev); + return ret; + } + + pm_runtime_put_sync(dev); + + return 0; +} + +static const struct of_device_id lpass_va_csr_dt_match[] = { + { .compatible = "qcom,hawi-lpass-va-csr", .data = &hawi_csr_data }, + {} +}; +MODULE_DEVICE_TABLE(of, lpass_va_csr_dt_match); + +static const struct dev_pm_ops lpass_va_csr_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static struct platform_driver lpass_va_csr_driver = { + .driver = { + .name = "qcom-lpass-va-csr", + .of_match_table = lpass_va_csr_dt_match, + .pm = pm_ptr(&lpass_va_csr_pm_ops), + }, + .probe = lpass_va_csr_probe, +}; + +module_platform_driver(lpass_va_csr_driver); + +MODULE_DESCRIPTION("Qualcomm LPASS VA CSR heartbeat pulse clock provider"); +MODULE_LICENSE("GPL"); From 00b5b6c77c6ada885563c4e84c0e3349b5e7ef35 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 22 Sep 2026 15:12:31 +0530 Subject: [PATCH 0508/1133] FROMLIST: ASoC: qcom: lpass-macro-common: Add missing v2.9 version string LPASS_CODEC_VERSION_2_9 is detected by lpass-va-macro.c and consumed by lpass-wsa-macro.c, but lpass_macro_get_codec_version_string() never learned about it, so the probe log reports "LPASS Codec Version NA" on those parts. Add the missing case. Reviewed-by: Srinivas Kandagatla Signed-off-by: Mohammad Rafi Shaik Reviewed-by: Ajay Kumar Nandam Link: https://patch.msgid.link/20260922-add_shikra_support-v1-2-6c6cb6444caf@oss.qualcomm.com --- sound/soc/codecs/lpass-macro-common.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h index 10ad682019fa7..573b2145e1c49 100644 --- a/sound/soc/codecs/lpass-macro-common.h +++ b/sound/soc/codecs/lpass-macro-common.h @@ -68,6 +68,8 @@ static inline const char *lpass_macro_get_codec_version_string(int version) return "v2.7"; case LPASS_CODEC_VERSION_2_8: return "v2.8"; + case LPASS_CODEC_VERSION_2_9: + return "v2.9"; default: break; } From 98c7dd4af7e2c7c77dd229b0118ec617aac5160a Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Tue, 22 Sep 2026 15:12:35 +0530 Subject: [PATCH 0509/1133] FROMLIST: ASoC: dt-bindings: qcom: Add Hawi LPASS macro codecs Document compatibles for the RX, TX and VA macro codecs found in the Low Power Audio SubSystem (LPASS) of the Qualcomm Hawi SoC. All three macros differ from SM8550, so describe them as standalone compatibles with their own clock constraints rather than as SM8550 fallbacks: the RX macro uses the 'lpr' clock instead of the 'macro' clock, the TX macro is based on Bolero v4.0, and the VA macro takes an additional "heartbeatpulse" clock sourced from the LPASS VA CSR rate generator. Signed-off-by: Mohammad Rafi Shaik Link: https://patch.msgid.link/20260922-add_shikra_support-v1-6-6c6cb6444caf@oss.qualcomm.com Signed-off-by: Prasad Kumpatla --- .../bindings/sound/qcom,lpass-rx-macro.yaml | 18 ++++++++++++++++++ .../bindings/sound/qcom,lpass-tx-macro.yaml | 19 +++++++++++++++++++ .../bindings/sound/qcom,lpass-va-macro.yaml | 19 +++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml index e96ad0b6f40c3..0a5eb51076231 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml @@ -14,6 +14,7 @@ properties: oneOf: - enum: - qcom,glymur-lpass-rx-macro + - qcom,hawi-lpass-rx-macro - qcom,sc7280-lpass-rx-macro - qcom,sm6115-lpass-rx-macro - qcom,sm8250-lpass-rx-macro @@ -143,6 +144,23 @@ allOf: - const: dcodec - const: fsgen + - if: + properties: + compatible: + enum: + - qcom,hawi-lpass-rx-macro + then: + properties: + clocks: + minItems: 4 + maxItems: 4 + clock-names: + items: + - const: mclk + - const: lpr + - const: dcodec + - const: fsgen + unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml index 62cb8b583eb54..8becbb5a0815d 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml @@ -14,6 +14,7 @@ properties: oneOf: - enum: - qcom,glymur-lpass-tx-macro + - qcom,hawi-lpass-tx-macro - qcom,sc7280-lpass-tx-macro - qcom,sm6115-lpass-tx-macro - qcom,sm8250-lpass-tx-macro @@ -147,6 +148,24 @@ allOf: - const: dcodec - const: fsgen + - if: + properties: + compatible: + contains: + enum: + - qcom,hawi-lpass-tx-macro + then: + properties: + clocks: + minItems: 4 + maxItems: 4 + clock-names: + items: + - const: mclk + - const: lpr + - const: dcodec + - const: fsgen + unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml index 7334112ea8995..cafc3a52ff20a 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml @@ -13,6 +13,7 @@ properties: compatible: oneOf: - enum: + - qcom,hawi-lpass-va-macro - qcom,sc7280-lpass-va-macro - qcom,sm6115-lpass-va-macro - qcom,sm8250-lpass-va-macro @@ -171,6 +172,24 @@ allOf: - const: macro - const: dcodec + - if: + properties: + compatible: + contains: + enum: + - qcom,hawi-lpass-va-macro + then: + properties: + clocks: + minItems: 4 + maxItems: 4 + clock-names: + items: + - const: mclk + - const: lpr + - const: dcodec + - const: heartbeatpulse + unevaluatedProperties: false examples: From 072ae8d8aad27c1f3ae4a6b47b29a77cb005cb72 Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Tue, 22 Sep 2026 15:12:36 +0530 Subject: [PATCH 0510/1133] FROMLIST: ASoC: qcom: lpass-tx-macro: Add support for Bolero v4.0 Hawi integrates the Bolero v4.0 TX macro, which extends the v9.x TX macro with a port-select stage in the SWR microphone input path and an adaptive filter (ADPT) block. Add the additional CFG2 mux registers and per-path CFG2 registers to the register map, extend the maximum register offset to cover the new ADPT control register, and describe the new v4.0 decimator, SWR microphone, WSA and port-select mux widgets and their routes. The ADPT block has to be disabled before a decimator is enabled. This register only exists on v4.0, so gate the write on a has_adpt flag set from the match data rather than issuing it unconditionally. Add the "qcom,hawi-lpass-tx-macro" compatible and its match data to select the new widgets and routes. Co-developed-by: Sarath Ganapathiraju Signed-off-by: Sarath Ganapathiraju Signed-off-by: Mohammad Rafi Shaik Link: https://patch.msgid.link/20260922-add_shikra_support-v1-7-6c6cb6444caf@oss.qualcomm.com Signed-off-by: Prasad Kumpatla --- sound/soc/codecs/lpass-macro-common.h | 1 + sound/soc/codecs/lpass-tx-macro.c | 442 +++++++++++++++++++++++++- 2 files changed, 442 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h index 573b2145e1c49..05f20aa60913f 100644 --- a/sound/soc/codecs/lpass-macro-common.h +++ b/sound/soc/codecs/lpass-macro-common.h @@ -16,6 +16,7 @@ enum lpass_version { LPASS_VER_9_2_0, LPASS_VER_10_0_0, LPASS_VER_11_0_0, + LPASS_VER_15_0_0, }; enum lpass_codec_version { diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index f3cd8c67ef978..717f17032493a 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -67,6 +67,14 @@ #define CDC_TX_INP_MUX_ADC_MUX6_CFG1 (0x0134) #define CDC_TX_INP_MUX_ADC_MUX7_CFG0 (0x0138) #define CDC_TX_INP_MUX_ADC_MUX7_CFG1 (0x013C) +#define CDC_TX_INP_MUX_ADC_MUX0_CFG2 (0x0140) +#define CDC_TX_INP_MUX_ADC_MUX1_CFG2 (0x0144) +#define CDC_TX_INP_MUX_ADC_MUX2_CFG2 (0x0148) +#define CDC_TX_INP_MUX_ADC_MUX3_CFG2 (0x014C) +#define CDC_TX_INP_MUX_ADC_MUX4_CFG2 (0x0150) +#define CDC_TX_INP_MUX_ADC_MUX5_CFG2 (0x0154) +#define CDC_TX_INP_MUX_ADC_MUX6_CFG2 (0x0158) +#define CDC_TX_INP_MUX_ADC_MUX7_CFG2 (0x015C) #define CDC_TX_ANC0_CLK_RESET_CTL (0x0200) #define CDC_TX_ANC0_MODE_1_CTL (0x0204) #define CDC_TX_ANC0_MODE_2_CTL (0x0208) @@ -108,6 +116,16 @@ #define CDC_TX0_TX_PATH_SEC5 (0x0424) #define CDC_TX0_TX_PATH_SEC6 (0x0428) #define CDC_TX0_TX_PATH_SEC7 (0x042C) +#define CDC_TX0_TX_PATH_CFG2 (0x0430) +#define CDC_TX1_TX_PATH_CFG2 (0x04B0) +#define CDC_TX2_TX_PATH_CFG2 (0x0530) +#define CDC_TX3_TX_PATH_CFG2 (0x05B0) +#define CDC_TX4_TX_PATH_CFG2 (0x0630) +#define CDC_TX5_TX_PATH_CFG2 (0x06B0) +#define CDC_TX6_TX_PATH_CFG2 (0x0730) +#define CDC_TX7_TX_PATH_CFG2 (0x07B0) +#define CDC_ADPT0_ADPT_CTRL (0x0800) + #define CDC_TX0_MBHC_CTL_EN_MASK BIT(6) #define CDC_TX1_TX_PATH_CTL (0x0480) #define CDC_TX1_TX_PATH_CFG0 (0x0484) @@ -186,7 +204,7 @@ #define CDC_TX7_TX_PATH_SEC4 (0x07A0) #define CDC_TX7_TX_PATH_SEC5 (0x07A4) #define CDC_TX7_TX_PATH_SEC6 (0x07A8) -#define TX_MAX_OFFSET (0x07A8) +#define TX_MAX_OFFSET (CDC_ADPT0_ADPT_CTRL) #define TX_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ @@ -258,6 +276,7 @@ struct hpf_work { struct tx_macro_data { unsigned int flags; unsigned int ver; + bool has_adpt; const struct snd_soc_dapm_widget *extra_widgets; size_t extra_widgets_num; const struct snd_soc_dapm_route *extra_routes; @@ -327,6 +346,14 @@ static struct reg_default tx_defaults[] = { { CDC_TX_INP_MUX_ADC_MUX6_CFG1, 0x00}, { CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0x00}, { CDC_TX_INP_MUX_ADC_MUX7_CFG1, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX0_CFG2, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX1_CFG2, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX2_CFG2, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX3_CFG2, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX4_CFG2, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX5_CFG2, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX6_CFG2, 0x00}, + { CDC_TX_INP_MUX_ADC_MUX7_CFG2, 0x00}, { CDC_TX_ANC0_CLK_RESET_CTL, 0x00}, { CDC_TX_ANC0_MODE_1_CTL, 0x00}, { CDC_TX_ANC0_MODE_2_CTL, 0x00}, @@ -432,6 +459,15 @@ static struct reg_default tx_defaults[] = { { CDC_TX7_TX_PATH_SEC4, 0x20}, { CDC_TX7_TX_PATH_SEC5, 0x00}, { CDC_TX7_TX_PATH_SEC6, 0x00}, + { CDC_TX0_TX_PATH_CFG2, 0x03}, + { CDC_TX1_TX_PATH_CFG2, 0x03}, + { CDC_TX2_TX_PATH_CFG2, 0x03}, + { CDC_TX3_TX_PATH_CFG2, 0x03}, + { CDC_TX4_TX_PATH_CFG2, 0x03}, + { CDC_TX5_TX_PATH_CFG2, 0x03}, + { CDC_TX6_TX_PATH_CFG2, 0x03}, + { CDC_TX7_TX_PATH_CFG2, 0x03}, + { CDC_ADPT0_ADPT_CTRL, 0x00}, }; static bool tx_is_volatile_register(struct device *dev, unsigned int reg) @@ -502,6 +538,14 @@ static bool tx_is_rw_register(struct device *dev, unsigned int reg) case CDC_TX_INP_MUX_ADC_MUX6_CFG1: case CDC_TX_INP_MUX_ADC_MUX7_CFG0: case CDC_TX_INP_MUX_ADC_MUX7_CFG1: + case CDC_TX_INP_MUX_ADC_MUX0_CFG2: + case CDC_TX_INP_MUX_ADC_MUX1_CFG2: + case CDC_TX_INP_MUX_ADC_MUX2_CFG2: + case CDC_TX_INP_MUX_ADC_MUX3_CFG2: + case CDC_TX_INP_MUX_ADC_MUX4_CFG2: + case CDC_TX_INP_MUX_ADC_MUX5_CFG2: + case CDC_TX_INP_MUX_ADC_MUX6_CFG2: + case CDC_TX_INP_MUX_ADC_MUX7_CFG2: case CDC_TX0_TX_PATH_CTL: case CDC_TX0_TX_PATH_CFG0: case CDC_TX0_TX_PATH_CFG1: @@ -591,6 +635,15 @@ static bool tx_is_rw_register(struct device *dev, unsigned int reg) case CDC_TX7_TX_PATH_SEC4: case CDC_TX7_TX_PATH_SEC5: case CDC_TX7_TX_PATH_SEC6: + case CDC_TX0_TX_PATH_CFG2: + case CDC_TX1_TX_PATH_CFG2: + case CDC_TX2_TX_PATH_CFG2: + case CDC_TX3_TX_PATH_CFG2: + case CDC_TX4_TX_PATH_CFG2: + case CDC_TX5_TX_PATH_CFG2: + case CDC_TX6_TX_PATH_CFG2: + case CDC_TX7_TX_PATH_CFG2: + case CDC_ADPT0_ADPT_CTRL: return true; } @@ -929,6 +982,9 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: + /* Disable the ADPT block before enabling the decimator */ + if (tx->data->has_adpt) + snd_soc_component_write_field(component, CDC_ADPT0_ADPT_CTRL, 0xFF, 0x0); adc_mux_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG1(decimator); if (snd_soc_component_read(component, adc_mux_reg) & SWR_MIC) { adc_reg = CDC_TX_INP_MUX_ADC_MUXn_CFG0(decimator); @@ -2027,6 +2083,377 @@ static const struct snd_soc_dapm_route tx_audio_map_v9_2[] = { {"TX SMIC MUX7", "SWR_MIC11", "TX SWR_INPUT11"}, }; +static const char * const adc_mux_text_v9_3[] = { + "MSM_DMIC", "SWR_MIC", "ANC_FB_TUNE1", "RX_SWR_MIC" +}; + +static SOC_ENUM_SINGLE_DECL(tx_dec0_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX0_CFG1, + 0, adc_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_dec1_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX1_CFG1, + 0, adc_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_dec2_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX2_CFG1, + 0, adc_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_dec3_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX3_CFG1, + 0, adc_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_dec4_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX4_CFG1, + 0, adc_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_dec5_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX5_CFG1, + 0, adc_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_dec6_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX6_CFG1, + 0, adc_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_dec7_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX7_CFG1, + 0, adc_mux_text_v9_3); + +static const struct snd_kcontrol_new tx_dec0_mux_v9_3 = + SOC_DAPM_ENUM("tx_dec0", tx_dec0_enum_v9_3); +static const struct snd_kcontrol_new tx_dec1_mux_v9_3 = + SOC_DAPM_ENUM("tx_dec1", tx_dec1_enum_v9_3); +static const struct snd_kcontrol_new tx_dec2_mux_v9_3 = + SOC_DAPM_ENUM("tx_dec2", tx_dec2_enum_v9_3); +static const struct snd_kcontrol_new tx_dec3_mux_v9_3 = + SOC_DAPM_ENUM("tx_dec3", tx_dec3_enum_v9_3); +static const struct snd_kcontrol_new tx_dec4_mux_v9_3 = + SOC_DAPM_ENUM("tx_dec4", tx_dec4_enum_v9_3); +static const struct snd_kcontrol_new tx_dec5_mux_v9_3 = + SOC_DAPM_ENUM("tx_dec5", tx_dec5_enum_v9_3); +static const struct snd_kcontrol_new tx_dec6_mux_v9_3 = + SOC_DAPM_ENUM("tx_dec6", tx_dec6_enum_v9_3); +static const struct snd_kcontrol_new tx_dec7_mux_v9_3 = + SOC_DAPM_ENUM("tx_dec7", tx_dec7_enum_v9_3); + +static const char * const smic_mux_text_v9_3[] = { + "ZERO", "SWR_MIC0", "SWR_MIC1", "SWR_MIC2", "SWR_MIC3", + "SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7", +}; + +static SOC_ENUM_SINGLE_DECL(tx_smic0_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX0_CFG0, + 0, smic_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_smic1_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX1_CFG0, + 0, smic_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_smic2_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX2_CFG0, + 0, smic_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_smic3_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX3_CFG0, + 0, smic_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_smic4_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX4_CFG0, + 0, smic_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_smic5_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX5_CFG0, + 0, smic_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_smic6_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX6_CFG0, + 0, smic_mux_text_v9_3); +static SOC_ENUM_SINGLE_DECL(tx_smic7_enum_v9_3, CDC_TX_INP_MUX_ADC_MUX7_CFG0, + 0, smic_mux_text_v9_3); + +static const struct snd_kcontrol_new tx_smic0_mux_v9_3 = SOC_DAPM_ENUM_EXT("tx_smic0", + tx_smic0_enum_v9_3, snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic1_mux_v9_3 = SOC_DAPM_ENUM_EXT("tx_smic1", + tx_smic1_enum_v9_3, snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic2_mux_v9_3 = SOC_DAPM_ENUM_EXT("tx_smic2", + tx_smic2_enum_v9_3, snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic3_mux_v9_3 = SOC_DAPM_ENUM_EXT("tx_smic3", + tx_smic3_enum_v9_3, snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic4_mux_v9_3 = SOC_DAPM_ENUM_EXT("tx_smic4", + tx_smic4_enum_v9_3, snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic5_mux_v9_3 = SOC_DAPM_ENUM_EXT("tx_smic5", + tx_smic5_enum_v9_3, snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic6_mux_v9_3 = SOC_DAPM_ENUM_EXT("tx_smic6", + tx_smic6_enum_v9_3, snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); +static const struct snd_kcontrol_new tx_smic7_mux_v9_3 = SOC_DAPM_ENUM_EXT("tx_smic7", + tx_smic7_enum_v9_3, snd_soc_dapm_get_enum_double, tx_macro_put_dec_enum); + +static const char * const tx_wsa_mux_text[] = { + "NO_WSA", "WSA1", "WSA2", "WSA3", "WSA4" +}; + +static SOC_ENUM_SINGLE_DECL(tx_wsa_mux0_enum, CDC_TX_INP_MUX_ADC_MUX0_CFG1, + 4, tx_wsa_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_wsa_mux1_enum, CDC_TX_INP_MUX_ADC_MUX1_CFG1, + 4, tx_wsa_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_wsa_mux2_enum, CDC_TX_INP_MUX_ADC_MUX2_CFG1, + 4, tx_wsa_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_wsa_mux3_enum, CDC_TX_INP_MUX_ADC_MUX3_CFG1, + 4, tx_wsa_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_wsa_mux4_enum, CDC_TX_INP_MUX_ADC_MUX4_CFG1, + 4, tx_wsa_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_wsa_mux5_enum, CDC_TX_INP_MUX_ADC_MUX5_CFG1, + 4, tx_wsa_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_wsa_mux6_enum, CDC_TX_INP_MUX_ADC_MUX6_CFG1, + 4, tx_wsa_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_wsa_mux7_enum, CDC_TX_INP_MUX_ADC_MUX7_CFG1, + 4, tx_wsa_mux_text); + +static const struct snd_kcontrol_new tx_wsa_mux0_mux = + SOC_DAPM_ENUM("tx_wsa_mux0", tx_wsa_mux0_enum); +static const struct snd_kcontrol_new tx_wsa_mux1_mux = + SOC_DAPM_ENUM("tx_wsa_mux1", tx_wsa_mux1_enum); +static const struct snd_kcontrol_new tx_wsa_mux2_mux = + SOC_DAPM_ENUM("tx_wsa_mux2", tx_wsa_mux2_enum); +static const struct snd_kcontrol_new tx_wsa_mux3_mux = + SOC_DAPM_ENUM("tx_wsa_mux3", tx_wsa_mux3_enum); +static const struct snd_kcontrol_new tx_wsa_mux4_mux = + SOC_DAPM_ENUM("tx_wsa_mux4", tx_wsa_mux4_enum); +static const struct snd_kcontrol_new tx_wsa_mux5_mux = + SOC_DAPM_ENUM("tx_wsa_mux5", tx_wsa_mux5_enum); +static const struct snd_kcontrol_new tx_wsa_mux6_mux = + SOC_DAPM_ENUM("tx_wsa_mux6", tx_wsa_mux6_enum); +static const struct snd_kcontrol_new tx_wsa_mux7_mux = + SOC_DAPM_ENUM("tx_wsa_mux7", tx_wsa_mux7_enum); + +static const char * const tx_psel_mux_text[] = { + "PORT0", "PORT1", "PORT2", "PORT3", "PORT4" +}; + +static SOC_ENUM_SINGLE_DECL(tx_psel_mux0_enum, CDC_TX_INP_MUX_ADC_MUX0_CFG2, + 0, tx_psel_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_psel_mux1_enum, CDC_TX_INP_MUX_ADC_MUX1_CFG2, + 0, tx_psel_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_psel_mux2_enum, CDC_TX_INP_MUX_ADC_MUX2_CFG2, + 0, tx_psel_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_psel_mux3_enum, CDC_TX_INP_MUX_ADC_MUX3_CFG2, + 0, tx_psel_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_psel_mux4_enum, CDC_TX_INP_MUX_ADC_MUX4_CFG2, + 0, tx_psel_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_psel_mux5_enum, CDC_TX_INP_MUX_ADC_MUX5_CFG2, + 0, tx_psel_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_psel_mux6_enum, CDC_TX_INP_MUX_ADC_MUX6_CFG2, + 0, tx_psel_mux_text); +static SOC_ENUM_SINGLE_DECL(tx_psel_mux7_enum, CDC_TX_INP_MUX_ADC_MUX7_CFG2, + 0, tx_psel_mux_text); + +static const struct snd_kcontrol_new tx_psel_mux0_mux = + SOC_DAPM_ENUM("tx_psel_mux0", tx_psel_mux0_enum); +static const struct snd_kcontrol_new tx_psel_mux1_mux = + SOC_DAPM_ENUM("tx_psel_mux1", tx_psel_mux1_enum); +static const struct snd_kcontrol_new tx_psel_mux2_mux = + SOC_DAPM_ENUM("tx_psel_mux2", tx_psel_mux2_enum); +static const struct snd_kcontrol_new tx_psel_mux3_mux = + SOC_DAPM_ENUM("tx_psel_mux3", tx_psel_mux3_enum); +static const struct snd_kcontrol_new tx_psel_mux4_mux = + SOC_DAPM_ENUM("tx_psel_mux4", tx_psel_mux4_enum); +static const struct snd_kcontrol_new tx_psel_mux5_mux = + SOC_DAPM_ENUM("tx_psel_mux5", tx_psel_mux5_enum); +static const struct snd_kcontrol_new tx_psel_mux6_mux = + SOC_DAPM_ENUM("tx_psel_mux6", tx_psel_mux6_enum); +static const struct snd_kcontrol_new tx_psel_mux7_mux = + SOC_DAPM_ENUM("tx_psel_mux7", tx_psel_mux7_enum); + +static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_v15[] = { + SND_SOC_DAPM_MUX("TX DEC0 MUX", SND_SOC_NOPM, 0, 0, &tx_dec0_mux_v9_3), + SND_SOC_DAPM_MUX("TX DEC1 MUX", SND_SOC_NOPM, 0, 0, &tx_dec1_mux_v9_3), + SND_SOC_DAPM_MUX("TX DEC2 MUX", SND_SOC_NOPM, 0, 0, &tx_dec2_mux_v9_3), + SND_SOC_DAPM_MUX("TX DEC3 MUX", SND_SOC_NOPM, 0, 0, &tx_dec3_mux_v9_3), + SND_SOC_DAPM_MUX("TX DEC4 MUX", SND_SOC_NOPM, 0, 0, &tx_dec4_mux_v9_3), + SND_SOC_DAPM_MUX("TX DEC5 MUX", SND_SOC_NOPM, 0, 0, &tx_dec5_mux_v9_3), + SND_SOC_DAPM_MUX("TX DEC6 MUX", SND_SOC_NOPM, 0, 0, &tx_dec6_mux_v9_3), + SND_SOC_DAPM_MUX("TX DEC7 MUX", SND_SOC_NOPM, 0, 0, &tx_dec7_mux_v9_3), + + SND_SOC_DAPM_MUX("TX SMIC MUX0", SND_SOC_NOPM, 0, 0, &tx_smic0_mux_v9_3), + SND_SOC_DAPM_MUX("TX SMIC MUX1", SND_SOC_NOPM, 0, 0, &tx_smic1_mux_v9_3), + SND_SOC_DAPM_MUX("TX SMIC MUX2", SND_SOC_NOPM, 0, 0, &tx_smic2_mux_v9_3), + SND_SOC_DAPM_MUX("TX SMIC MUX3", SND_SOC_NOPM, 0, 0, &tx_smic3_mux_v9_3), + SND_SOC_DAPM_MUX("TX SMIC MUX4", SND_SOC_NOPM, 0, 0, &tx_smic4_mux_v9_3), + SND_SOC_DAPM_MUX("TX SMIC MUX5", SND_SOC_NOPM, 0, 0, &tx_smic5_mux_v9_3), + SND_SOC_DAPM_MUX("TX SMIC MUX6", SND_SOC_NOPM, 0, 0, &tx_smic6_mux_v9_3), + SND_SOC_DAPM_MUX("TX SMIC MUX7", SND_SOC_NOPM, 0, 0, &tx_smic7_mux_v9_3), + + SND_SOC_DAPM_MUX("TX WSA MUX0", SND_SOC_NOPM, 0, 0, &tx_wsa_mux0_mux), + SND_SOC_DAPM_MUX("TX WSA MUX1", SND_SOC_NOPM, 0, 0, &tx_wsa_mux1_mux), + SND_SOC_DAPM_MUX("TX WSA MUX2", SND_SOC_NOPM, 0, 0, &tx_wsa_mux2_mux), + SND_SOC_DAPM_MUX("TX WSA MUX3", SND_SOC_NOPM, 0, 0, &tx_wsa_mux3_mux), + SND_SOC_DAPM_MUX("TX WSA MUX4", SND_SOC_NOPM, 0, 0, &tx_wsa_mux4_mux), + SND_SOC_DAPM_MUX("TX WSA MUX5", SND_SOC_NOPM, 0, 0, &tx_wsa_mux5_mux), + SND_SOC_DAPM_MUX("TX WSA MUX6", SND_SOC_NOPM, 0, 0, &tx_wsa_mux6_mux), + SND_SOC_DAPM_MUX("TX WSA MUX7", SND_SOC_NOPM, 0, 0, &tx_wsa_mux7_mux), + + SND_SOC_DAPM_MUX("TX PORT SEL MUX0", SND_SOC_NOPM, 0, 0, &tx_psel_mux0_mux), + SND_SOC_DAPM_MUX("TX PORT SEL MUX1", SND_SOC_NOPM, 0, 0, &tx_psel_mux1_mux), + SND_SOC_DAPM_MUX("TX PORT SEL MUX2", SND_SOC_NOPM, 0, 0, &tx_psel_mux2_mux), + SND_SOC_DAPM_MUX("TX PORT SEL MUX3", SND_SOC_NOPM, 0, 0, &tx_psel_mux3_mux), + SND_SOC_DAPM_MUX("TX PORT SEL MUX4", SND_SOC_NOPM, 0, 0, &tx_psel_mux4_mux), + SND_SOC_DAPM_MUX("TX PORT SEL MUX5", SND_SOC_NOPM, 0, 0, &tx_psel_mux5_mux), + SND_SOC_DAPM_MUX("TX PORT SEL MUX6", SND_SOC_NOPM, 0, 0, &tx_psel_mux6_mux), + SND_SOC_DAPM_MUX("TX PORT SEL MUX7", SND_SOC_NOPM, 0, 0, &tx_psel_mux7_mux), + + SND_SOC_DAPM_INPUT("TX SWR_INPUT"), +}; + +static const struct snd_soc_dapm_route tx_audio_map_v15[] = { + /* DEC0 */ + {"TX DEC0 MUX", "SWR_MIC", "TX SMIC MUX0"}, + {"TX SMIC MUX0", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX0", "SWR_MIC0", "TX WSA MUX0"}, + {"TX SMIC MUX0", "SWR_MIC1", "TX WSA MUX0"}, + {"TX SMIC MUX0", "SWR_MIC2", "TX WSA MUX0"}, + {"TX SMIC MUX0", "SWR_MIC3", "TX WSA MUX0"}, + {"TX SMIC MUX0", "SWR_MIC4", "TX WSA MUX0"}, + {"TX SMIC MUX0", "SWR_MIC5", "TX WSA MUX0"}, + {"TX SMIC MUX0", "SWR_MIC6", "TX WSA MUX0"}, + {"TX SMIC MUX0", "SWR_MIC7", "TX WSA MUX0"}, + {"TX WSA MUX0", "NO_WSA", "TX PORT SEL MUX0"}, + {"TX WSA MUX0", "WSA1", "TX PORT SEL MUX0"}, + {"TX WSA MUX0", "WSA2", "TX PORT SEL MUX0"}, + {"TX WSA MUX0", "WSA3", "TX PORT SEL MUX0"}, + {"TX WSA MUX0", "WSA4", "TX PORT SEL MUX0"}, + {"TX PORT SEL MUX0", "PORT0", "TX SWR_INPUT"}, + {"TX PORT SEL MUX0", "PORT1", "TX SWR_INPUT"}, + {"TX PORT SEL MUX0", "PORT2", "TX SWR_INPUT"}, + {"TX PORT SEL MUX0", "PORT3", "TX SWR_INPUT"}, + {"TX PORT SEL MUX0", "PORT4", "TX SWR_INPUT"}, + + /* DEC1 */ + {"TX DEC1 MUX", "SWR_MIC", "TX SMIC MUX1"}, + {"TX SMIC MUX1", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX1", "SWR_MIC0", "TX WSA MUX1"}, + {"TX SMIC MUX1", "SWR_MIC1", "TX WSA MUX1"}, + {"TX SMIC MUX1", "SWR_MIC2", "TX WSA MUX1"}, + {"TX SMIC MUX1", "SWR_MIC3", "TX WSA MUX1"}, + {"TX SMIC MUX1", "SWR_MIC4", "TX WSA MUX1"}, + {"TX SMIC MUX1", "SWR_MIC5", "TX WSA MUX1"}, + {"TX SMIC MUX1", "SWR_MIC6", "TX WSA MUX1"}, + {"TX SMIC MUX1", "SWR_MIC7", "TX WSA MUX1"}, + {"TX WSA MUX1", "NO_WSA", "TX PORT SEL MUX1"}, + {"TX WSA MUX1", "WSA1", "TX PORT SEL MUX1"}, + {"TX WSA MUX1", "WSA2", "TX PORT SEL MUX1"}, + {"TX WSA MUX1", "WSA3", "TX PORT SEL MUX1"}, + {"TX WSA MUX1", "WSA4", "TX PORT SEL MUX1"}, + {"TX PORT SEL MUX1", "PORT0", "TX SWR_INPUT"}, + {"TX PORT SEL MUX1", "PORT1", "TX SWR_INPUT"}, + {"TX PORT SEL MUX1", "PORT2", "TX SWR_INPUT"}, + {"TX PORT SEL MUX1", "PORT3", "TX SWR_INPUT"}, + {"TX PORT SEL MUX1", "PORT4", "TX SWR_INPUT"}, + + /* DEC2 */ + {"TX DEC2 MUX", "SWR_MIC", "TX SMIC MUX2"}, + {"TX SMIC MUX2", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX2", "SWR_MIC0", "TX WSA MUX2"}, + {"TX SMIC MUX2", "SWR_MIC1", "TX WSA MUX2"}, + {"TX SMIC MUX2", "SWR_MIC2", "TX WSA MUX2"}, + {"TX SMIC MUX2", "SWR_MIC3", "TX WSA MUX2"}, + {"TX SMIC MUX2", "SWR_MIC4", "TX WSA MUX2"}, + {"TX SMIC MUX2", "SWR_MIC5", "TX WSA MUX2"}, + {"TX SMIC MUX2", "SWR_MIC6", "TX WSA MUX2"}, + {"TX SMIC MUX2", "SWR_MIC7", "TX WSA MUX2"}, + {"TX WSA MUX2", "NO_WSA", "TX PORT SEL MUX2"}, + {"TX WSA MUX2", "WSA1", "TX PORT SEL MUX2"}, + {"TX WSA MUX2", "WSA2", "TX PORT SEL MUX2"}, + {"TX WSA MUX2", "WSA3", "TX PORT SEL MUX2"}, + {"TX WSA MUX2", "WSA4", "TX PORT SEL MUX2"}, + {"TX PORT SEL MUX2", "PORT0", "TX SWR_INPUT"}, + {"TX PORT SEL MUX2", "PORT1", "TX SWR_INPUT"}, + {"TX PORT SEL MUX2", "PORT2", "TX SWR_INPUT"}, + {"TX PORT SEL MUX2", "PORT3", "TX SWR_INPUT"}, + {"TX PORT SEL MUX2", "PORT4", "TX SWR_INPUT"}, + + /* DEC3 */ + {"TX DEC3 MUX", "SWR_MIC", "TX SMIC MUX3"}, + {"TX SMIC MUX3", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX3", "SWR_MIC0", "TX WSA MUX3"}, + {"TX SMIC MUX3", "SWR_MIC1", "TX WSA MUX3"}, + {"TX SMIC MUX3", "SWR_MIC2", "TX WSA MUX3"}, + {"TX SMIC MUX3", "SWR_MIC3", "TX WSA MUX3"}, + {"TX SMIC MUX3", "SWR_MIC4", "TX WSA MUX3"}, + {"TX SMIC MUX3", "SWR_MIC5", "TX WSA MUX3"}, + {"TX SMIC MUX3", "SWR_MIC6", "TX WSA MUX3"}, + {"TX SMIC MUX3", "SWR_MIC7", "TX WSA MUX3"}, + {"TX WSA MUX3", "NO_WSA", "TX PORT SEL MUX3"}, + {"TX WSA MUX3", "WSA1", "TX PORT SEL MUX3"}, + {"TX WSA MUX3", "WSA2", "TX PORT SEL MUX3"}, + {"TX WSA MUX3", "WSA3", "TX PORT SEL MUX3"}, + {"TX WSA MUX3", "WSA4", "TX PORT SEL MUX3"}, + {"TX PORT SEL MUX3", "PORT0", "TX SWR_INPUT"}, + {"TX PORT SEL MUX3", "PORT1", "TX SWR_INPUT"}, + {"TX PORT SEL MUX3", "PORT2", "TX SWR_INPUT"}, + {"TX PORT SEL MUX3", "PORT3", "TX SWR_INPUT"}, + {"TX PORT SEL MUX3", "PORT4", "TX SWR_INPUT"}, + + /* DEC4 */ + {"TX DEC4 MUX", "SWR_MIC", "TX SMIC MUX4"}, + {"TX SMIC MUX4", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX4", "SWR_MIC0", "TX WSA MUX4"}, + {"TX SMIC MUX4", "SWR_MIC1", "TX WSA MUX4"}, + {"TX SMIC MUX4", "SWR_MIC2", "TX WSA MUX4"}, + {"TX SMIC MUX4", "SWR_MIC3", "TX WSA MUX4"}, + {"TX SMIC MUX4", "SWR_MIC4", "TX WSA MUX4"}, + {"TX SMIC MUX4", "SWR_MIC5", "TX WSA MUX4"}, + {"TX SMIC MUX4", "SWR_MIC6", "TX WSA MUX4"}, + {"TX SMIC MUX4", "SWR_MIC7", "TX WSA MUX4"}, + {"TX WSA MUX4", "NO_WSA", "TX PORT SEL MUX4"}, + {"TX WSA MUX4", "WSA1", "TX PORT SEL MUX4"}, + {"TX WSA MUX4", "WSA2", "TX PORT SEL MUX4"}, + {"TX WSA MUX4", "WSA3", "TX PORT SEL MUX4"}, + {"TX WSA MUX4", "WSA4", "TX PORT SEL MUX4"}, + {"TX PORT SEL MUX4", "PORT0", "TX SWR_INPUT"}, + {"TX PORT SEL MUX4", "PORT1", "TX SWR_INPUT"}, + {"TX PORT SEL MUX4", "PORT2", "TX SWR_INPUT"}, + {"TX PORT SEL MUX4", "PORT3", "TX SWR_INPUT"}, + {"TX PORT SEL MUX4", "PORT4", "TX SWR_INPUT"}, + + /* DEC5 */ + {"TX DEC5 MUX", "SWR_MIC", "TX SMIC MUX5"}, + {"TX SMIC MUX5", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX5", "SWR_MIC0", "TX WSA MUX5"}, + {"TX SMIC MUX5", "SWR_MIC1", "TX WSA MUX5"}, + {"TX SMIC MUX5", "SWR_MIC2", "TX WSA MUX5"}, + {"TX SMIC MUX5", "SWR_MIC3", "TX WSA MUX5"}, + {"TX SMIC MUX5", "SWR_MIC4", "TX WSA MUX5"}, + {"TX SMIC MUX5", "SWR_MIC5", "TX WSA MUX5"}, + {"TX SMIC MUX5", "SWR_MIC6", "TX WSA MUX5"}, + {"TX SMIC MUX5", "SWR_MIC7", "TX WSA MUX5"}, + {"TX WSA MUX5", "NO_WSA", "TX PORT SEL MUX5"}, + {"TX WSA MUX5", "WSA1", "TX PORT SEL MUX5"}, + {"TX WSA MUX5", "WSA2", "TX PORT SEL MUX5"}, + {"TX WSA MUX5", "WSA3", "TX PORT SEL MUX5"}, + {"TX WSA MUX5", "WSA4", "TX PORT SEL MUX5"}, + {"TX PORT SEL MUX5", "PORT0", "TX SWR_INPUT"}, + {"TX PORT SEL MUX5", "PORT1", "TX SWR_INPUT"}, + {"TX PORT SEL MUX5", "PORT2", "TX SWR_INPUT"}, + {"TX PORT SEL MUX5", "PORT3", "TX SWR_INPUT"}, + {"TX PORT SEL MUX5", "PORT4", "TX SWR_INPUT"}, + + /* DEC6 */ + {"TX DEC6 MUX", "SWR_MIC", "TX SMIC MUX6"}, + {"TX SMIC MUX6", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX6", "SWR_MIC0", "TX WSA MUX6"}, + {"TX SMIC MUX6", "SWR_MIC1", "TX WSA MUX6"}, + {"TX SMIC MUX6", "SWR_MIC2", "TX WSA MUX6"}, + {"TX SMIC MUX6", "SWR_MIC3", "TX WSA MUX6"}, + {"TX SMIC MUX6", "SWR_MIC4", "TX WSA MUX6"}, + {"TX SMIC MUX6", "SWR_MIC5", "TX WSA MUX6"}, + {"TX SMIC MUX6", "SWR_MIC6", "TX WSA MUX6"}, + {"TX SMIC MUX6", "SWR_MIC7", "TX WSA MUX6"}, + {"TX WSA MUX6", "NO_WSA", "TX PORT SEL MUX6"}, + {"TX WSA MUX6", "WSA1", "TX PORT SEL MUX6"}, + {"TX WSA MUX6", "WSA2", "TX PORT SEL MUX6"}, + {"TX WSA MUX6", "WSA3", "TX PORT SEL MUX6"}, + {"TX WSA MUX6", "WSA4", "TX PORT SEL MUX6"}, + {"TX PORT SEL MUX6", "PORT0", "TX SWR_INPUT"}, + {"TX PORT SEL MUX6", "PORT1", "TX SWR_INPUT"}, + {"TX PORT SEL MUX6", "PORT2", "TX SWR_INPUT"}, + {"TX PORT SEL MUX6", "PORT3", "TX SWR_INPUT"}, + {"TX PORT SEL MUX6", "PORT4", "TX SWR_INPUT"}, + + /* DEC7 */ + {"TX DEC7 MUX", "SWR_MIC", "TX SMIC MUX7"}, + {"TX SMIC MUX7", NULL, "TX_SWR_CLK"}, + {"TX SMIC MUX7", "SWR_MIC0", "TX WSA MUX7"}, + {"TX SMIC MUX7", "SWR_MIC1", "TX WSA MUX7"}, + {"TX SMIC MUX7", "SWR_MIC2", "TX WSA MUX7"}, + {"TX SMIC MUX7", "SWR_MIC3", "TX WSA MUX7"}, + {"TX SMIC MUX7", "SWR_MIC4", "TX WSA MUX7"}, + {"TX SMIC MUX7", "SWR_MIC5", "TX WSA MUX7"}, + {"TX SMIC MUX7", "SWR_MIC6", "TX WSA MUX7"}, + {"TX SMIC MUX7", "SWR_MIC7", "TX WSA MUX7"}, + {"TX WSA MUX7", "NO_WSA", "TX PORT SEL MUX7"}, + {"TX WSA MUX7", "WSA1", "TX PORT SEL MUX7"}, + {"TX WSA MUX7", "WSA2", "TX PORT SEL MUX7"}, + {"TX WSA MUX7", "WSA3", "TX PORT SEL MUX7"}, + {"TX WSA MUX7", "WSA4", "TX PORT SEL MUX7"}, + {"TX PORT SEL MUX7", "PORT0", "TX SWR_INPUT"}, + {"TX PORT SEL MUX7", "PORT1", "TX SWR_INPUT"}, + {"TX PORT SEL MUX7", "PORT2", "TX SWR_INPUT"}, + {"TX PORT SEL MUX7", "PORT3", "TX SWR_INPUT"}, + {"TX PORT SEL MUX7", "PORT4", "TX SWR_INPUT"}, +}; + static const struct snd_kcontrol_new tx_macro_snd_controls[] = { SOC_SINGLE_S8_TLV("TX_DEC0 Volume", CDC_TX0_TX_VOL_CTL, @@ -2487,6 +2914,16 @@ static const struct tx_macro_data lpass_ver_11_glymur = { .extra_routes_num = ARRAY_SIZE(tx_audio_map_v9_2), }; +static const struct tx_macro_data lpass_ver_15 = { + .flags = LPASS_MACRO_FLAG_RESET_SWR, + .ver = LPASS_VER_15_0_0, + .has_adpt = true, + .extra_widgets = tx_macro_dapm_widgets_v15, + .extra_widgets_num = ARRAY_SIZE(tx_macro_dapm_widgets_v15), + .extra_routes = tx_audio_map_v15, + .extra_routes_num = ARRAY_SIZE(tx_audio_map_v15), +}; + static const struct of_device_id tx_macro_dt_match[] = { { .compatible = "qcom,glymur-lpass-tx-macro", @@ -2512,6 +2949,9 @@ static const struct of_device_id tx_macro_dt_match[] = { }, { .compatible = "qcom,sm8550-lpass-tx-macro", .data = &lpass_ver_11, + }, { + .compatible = "qcom,hawi-lpass-tx-macro", + .data = &lpass_ver_15, }, { .compatible = "qcom,sc8280xp-lpass-tx-macro", /* From e8575ded9542b3b3a819ac536eed7f205cc1065f Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Tue, 22 Sep 2026 15:12:37 +0530 Subject: [PATCH 0511/1133] FROMLIST: ASoC: qcom: lpass: Add support for LPASS codec v4.0 Hawi and Maili use the LPASS codec v4.0, which the macro drivers do not yet recognise. Add LPASS_CODEC_VERSION_4_0 and its "v4.0" version string, and detect it in the VA macro when the hardware reports major version 4, minor 0. The RX macro register layout of LPASS codec v4.0 matches the v2.5+ layout, so reuse the existing v2.5 register access helpers, controls, widgets and register defaults for it. Unlike v4.1, v4.0 does not need the FS counter bypass or the adaptive filter blocks, so those stay keyed off v4.1 only. Add the "qcom,hawi-lpass-rx-macro" and "qcom,hawi-lpass-va-macro" compatibles, both pointing at the sm8550 match data, so the version is read back from the hardware at probe. Signed-off-by: Mohammad Rafi Shaik Link: https://patch.msgid.link/20260922-add_shikra_support-v1-8-6c6cb6444caf@oss.qualcomm.com Signed-off-by: Prasad Kumpatla --- sound/soc/codecs/lpass-macro-common.h | 6 ++++++ sound/soc/codecs/lpass-rx-macro.c | 8 ++++++++ sound/soc/codecs/lpass-va-macro.c | 12 ++++++++++++ 3 files changed, 26 insertions(+) diff --git a/sound/soc/codecs/lpass-macro-common.h b/sound/soc/codecs/lpass-macro-common.h index 05f20aa60913f..a51a6012a7ec9 100644 --- a/sound/soc/codecs/lpass-macro-common.h +++ b/sound/soc/codecs/lpass-macro-common.h @@ -31,6 +31,8 @@ enum lpass_codec_version { LPASS_CODEC_VERSION_2_7, LPASS_CODEC_VERSION_2_8, LPASS_CODEC_VERSION_2_9, + LPASS_CODEC_VERSION_4_0, + LPASS_CODEC_VERSION_4_1, }; struct lpass_macro { @@ -71,6 +73,10 @@ static inline const char *lpass_macro_get_codec_version_string(int version) return "v2.8"; case LPASS_CODEC_VERSION_2_9: return "v2.9"; + case LPASS_CODEC_VERSION_4_0: + return "v4.0"; + case LPASS_CODEC_VERSION_4_1: + return "v4.1"; default: break; } diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index cc44b0329cd28..e74d44edf6c16 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -1614,6 +1614,8 @@ static bool rx_is_rw_register(struct device *dev, unsigned int reg) case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: case LPASS_CODEC_VERSION_2_9: + case LPASS_CODEC_VERSION_4_0: + case LPASS_CODEC_VERSION_4_1: return rx_2_5_is_rw_register(dev, reg); default: break; @@ -3654,6 +3656,8 @@ static int rx_macro_component_probe(struct snd_soc_component *component) case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: case LPASS_CODEC_VERSION_2_9: + case LPASS_CODEC_VERSION_4_0: + case LPASS_CODEC_VERSION_4_1: controls = rx_macro_2_5_snd_controls; num_controls = ARRAY_SIZE(rx_macro_2_5_snd_controls); widgets = rx_macro_2_5_dapm_widgets; @@ -3840,6 +3844,8 @@ static int rx_macro_probe(struct platform_device *pdev) case LPASS_CODEC_VERSION_2_7: case LPASS_CODEC_VERSION_2_8: case LPASS_CODEC_VERSION_2_9: + case LPASS_CODEC_VERSION_4_0: + case LPASS_CODEC_VERSION_4_1: rx->rxn_reg_stride = 0xc0; rx->rxn_reg_stride2 = 0x0; def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_2_5_defaults); @@ -3953,6 +3959,8 @@ static const struct of_device_id rx_macro_dt_match[] = { .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, }, { .compatible = "qcom,sm8550-lpass-rx-macro", + }, { + .compatible = "qcom,hawi-lpass-rx-macro", }, { .compatible = "qcom,sc8280xp-lpass-rx-macro", .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 03d6434a4a126..299a608341066 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -1526,6 +1526,17 @@ static int va_macro_set_lpass_codec_version(struct va_macro *va) default: break; } + } else if (maj == 4) { + switch (min) { + case 0: + version = LPASS_CODEC_VERSION_4_0; + break; + case 1: + version = LPASS_CODEC_VERSION_4_1; + break; + default: + break; + } } if (version == LPASS_CODEC_VERSION_UNKNOWN) { @@ -1774,6 +1785,7 @@ static const struct of_device_id va_macro_dt_match[] = { { .compatible = "qcom,sm8250-lpass-va-macro", .data = &sm8250_va_data }, { .compatible = "qcom,sm8450-lpass-va-macro", .data = &sm8450_va_data }, { .compatible = "qcom,sm8550-lpass-va-macro", .data = &sm8550_va_data }, + { .compatible = "qcom,hawi-lpass-va-macro", .data = &sm8550_va_data }, { .compatible = "qcom,sc8280xp-lpass-va-macro", .data = &sm8450_va_data }, {} }; From 1854336b4ba353bac6686a8f1ecd9c103e1e4f61 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 15:41:40 +0530 Subject: [PATCH 0512/1133] FROMLIST: ASoC: codecs: lpass-rx-macro: manage clocks in runtime PM Replace PM clock framework usage with explicit clock prepare/enable and disable/unprepare operations from runtime PM callbacks. This keeps the RX macro clock prepare state tied to the runtime PM active state, so idle suspend can release parent clock votes. Use DEFINE_RUNTIME_DEV_PM_OPS() so system suspend forces the same runtime suspend path for an active device. Link: https://lore.kernel.org/all/20260928-xo-sd-runtimepm-v1-final-v1-1-e3ebade3aeb7@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-rx-macro.c | 74 ++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index e74d44edf6c16..7eb05ffa367b3 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -670,6 +669,53 @@ struct rx_macro { }; #define to_rx_macro(_hw) container_of(_hw, struct rx_macro, hw) +static void rx_macro_disable_clocks(struct rx_macro *rx) +{ + clk_disable_unprepare(rx->fsgen); + clk_disable_unprepare(rx->npl); + clk_disable_unprepare(rx->mclk); + clk_disable_unprepare(rx->dcodec); + clk_disable_unprepare(rx->macro); +} + +static int rx_macro_enable_clocks(struct rx_macro *rx) +{ + int ret; + + ret = clk_prepare_enable(rx->macro); + if (ret) + return ret; + + ret = clk_prepare_enable(rx->dcodec); + if (ret) + goto err_dcodec; + + ret = clk_prepare_enable(rx->mclk); + if (ret) + goto err_mclk; + + ret = clk_prepare_enable(rx->npl); + if (ret) + goto err_npl; + + ret = clk_prepare_enable(rx->fsgen); + if (ret) + goto err_fsgen; + + return 0; + +err_fsgen: + clk_disable_unprepare(rx->npl); +err_npl: + clk_disable_unprepare(rx->mclk); +err_mclk: + clk_disable_unprepare(rx->dcodec); +err_dcodec: + clk_disable_unprepare(rx->macro); + + return ret; +} + struct wcd_iir_filter_ctl { unsigned int iir_idx; unsigned int band_idx; @@ -3889,14 +3935,6 @@ static int rx_macro_probe(struct platform_device *pdev) if (ret) return ret; - ret = devm_pm_clk_create(dev); - if (ret) - return ret; - - ret = of_pm_clk_add_clks(dev); - if (ret < 0) - return ret; - pm_runtime_set_autosuspend_delay(dev, 100); pm_runtime_use_autosuspend(dev); ret = devm_pm_runtime_enable(dev); @@ -3972,16 +4010,9 @@ MODULE_DEVICE_TABLE(of, rx_macro_dt_match); static int rx_macro_runtime_suspend(struct device *dev) { struct rx_macro *rx = dev_get_drvdata(dev); - int ret; regcache_cache_only(rx->regmap, true); - - ret = pm_clk_suspend(dev); - if (ret) { - regcache_cache_only(rx->regmap, false); - return ret; - } - + rx_macro_disable_clocks(rx); regcache_mark_dirty(rx->regmap); return 0; @@ -3992,7 +4023,7 @@ static int rx_macro_runtime_resume(struct device *dev) struct rx_macro *rx = dev_get_drvdata(dev); int ret; - ret = pm_clk_resume(dev); + ret = rx_macro_enable_clocks(rx); if (ret) { regcache_cache_only(rx->regmap, true); regcache_mark_dirty(rx->regmap); @@ -4004,16 +4035,15 @@ static int rx_macro_runtime_resume(struct device *dev) if (ret) { regcache_cache_only(rx->regmap, true); regcache_mark_dirty(rx->regmap); - pm_clk_suspend(dev); + rx_macro_disable_clocks(rx); return ret; } return 0; } -static const struct dev_pm_ops rx_macro_pm_ops = { - RUNTIME_PM_OPS(rx_macro_runtime_suspend, rx_macro_runtime_resume, NULL) -}; +static DEFINE_RUNTIME_DEV_PM_OPS(rx_macro_pm_ops, rx_macro_runtime_suspend, + rx_macro_runtime_resume, NULL); static struct platform_driver rx_macro_driver = { .driver = { From 12feba8dd8636330fa79605ae36884f973161c1d Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 15:41:41 +0530 Subject: [PATCH 0513/1133] FROMLIST: ASoC: codecs: lpass-tx-macro: manage clocks in runtime PM Replace PM clock framework usage with explicit clock prepare/enable and disable/unprepare operations from runtime PM callbacks. This keeps the TX macro clock prepare state tied to the runtime PM active state, so idle suspend can release parent clock votes. Use DEFINE_RUNTIME_DEV_PM_OPS() so system suspend forces the same runtime suspend path for an active device. Link: https://lore.kernel.org/all/20260928-xo-sd-runtimepm-v1-final-v1-2-e3ebade3aeb7@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-tx-macro.c | 75 +++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 717f17032493a..5e774bd645081 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -308,6 +307,53 @@ struct tx_macro { }; #define to_tx_macro(_hw) container_of(_hw, struct tx_macro, hw) +static void tx_macro_disable_clocks(struct tx_macro *tx) +{ + clk_disable_unprepare(tx->fsgen); + clk_disable_unprepare(tx->npl); + clk_disable_unprepare(tx->mclk); + clk_disable_unprepare(tx->dcodec); + clk_disable_unprepare(tx->macro); +} + +static int tx_macro_enable_clocks(struct tx_macro *tx) +{ + int ret; + + ret = clk_prepare_enable(tx->macro); + if (ret) + return ret; + + ret = clk_prepare_enable(tx->dcodec); + if (ret) + goto err_dcodec; + + ret = clk_prepare_enable(tx->mclk); + if (ret) + goto err_mclk; + + ret = clk_prepare_enable(tx->npl); + if (ret) + goto err_npl; + + ret = clk_prepare_enable(tx->fsgen); + if (ret) + goto err_fsgen; + + return 0; + +err_fsgen: + clk_disable_unprepare(tx->npl); +err_npl: + clk_disable_unprepare(tx->mclk); +err_mclk: + clk_disable_unprepare(tx->dcodec); +err_dcodec: + clk_disable_unprepare(tx->macro); + + return ret; +} + static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); static struct reg_default tx_defaults[] = { @@ -2755,14 +2801,6 @@ static int tx_macro_probe(struct platform_device *pdev) if (ret) goto err; - ret = devm_pm_clk_create(dev); - if (ret) - goto err; - - ret = of_pm_clk_add_clks(dev); - if (ret < 0) - goto err; - pm_runtime_set_autosuspend_delay(dev, 100); pm_runtime_use_autosuspend(dev); ret = devm_pm_runtime_enable(dev); @@ -2773,7 +2811,6 @@ static int tx_macro_probe(struct platform_device *pdev) if (ret < 0) goto err; - /* reset soundwire block */ if (tx->data->flags & LPASS_MACRO_FLAG_RESET_SWR) regmap_update_bits(tx->regmap, CDC_TX_CLK_RST_CTRL_SWR_CONTROL, @@ -2822,16 +2859,9 @@ static void tx_macro_remove(struct platform_device *pdev) static int tx_macro_runtime_suspend(struct device *dev) { struct tx_macro *tx = dev_get_drvdata(dev); - int ret; regcache_cache_only(tx->regmap, true); - - ret = pm_clk_suspend(dev); - if (ret) { - regcache_cache_only(tx->regmap, false); - return ret; - } - + tx_macro_disable_clocks(tx); regcache_mark_dirty(tx->regmap); return 0; @@ -2842,7 +2872,7 @@ static int tx_macro_runtime_resume(struct device *dev) struct tx_macro *tx = dev_get_drvdata(dev); int ret; - ret = pm_clk_resume(dev); + ret = tx_macro_enable_clocks(tx); if (ret) { regcache_cache_only(tx->regmap, true); regcache_mark_dirty(tx->regmap); @@ -2854,16 +2884,15 @@ static int tx_macro_runtime_resume(struct device *dev) if (ret) { regcache_cache_only(tx->regmap, true); regcache_mark_dirty(tx->regmap); - pm_clk_suspend(dev); + tx_macro_disable_clocks(tx); return ret; } return 0; } -static const struct dev_pm_ops tx_macro_pm_ops = { - RUNTIME_PM_OPS(tx_macro_runtime_suspend, tx_macro_runtime_resume, NULL) -}; +static DEFINE_RUNTIME_DEV_PM_OPS(tx_macro_pm_ops, tx_macro_runtime_suspend, + tx_macro_runtime_resume, NULL); static const struct tx_macro_data lpass_ver_9 = { .flags = LPASS_MACRO_FLAG_HAS_NPL_CLOCK | From 846dd967ae87d467da1c911874c53bf87b7b924e Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 16:14:42 +0530 Subject: [PATCH 0514/1133] FROMLIST: ASoC: codecs: lpass-va-macro: manage clocks in runtime PM Replace PM clock framework usage with explicit clock prepare/enable and disable/unprepare operations from runtime PM callbacks. This keeps the VA macro clock prepare state tied to the runtime PM active state, so idle suspend can release parent clock votes. Use DEFINE_RUNTIME_DEV_PM_OPS() so system suspend forces the same runtime suspend path for an active device. Link: https://lore.kernel.org/all/20260928-xo-sd-runtimepm-v1-final-v1-3-e3ebade3aeb7@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-va-macro.c | 78 +++++++++++++++++++------------ 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 299a608341066..c1b8d644d072d 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -233,6 +232,46 @@ struct va_macro { #define to_va_macro(_hw) container_of(_hw, struct va_macro, hw) +static void va_macro_disable_clocks(struct va_macro *va) +{ + clk_disable_unprepare(va->npl); + clk_disable_unprepare(va->mclk); + clk_disable_unprepare(va->dcodec); + clk_disable_unprepare(va->macro); +} + +static int va_macro_enable_clocks(struct va_macro *va) +{ + int ret; + + ret = clk_prepare_enable(va->macro); + if (ret) + return ret; + + ret = clk_prepare_enable(va->dcodec); + if (ret) + goto err_dcodec; + + ret = clk_prepare_enable(va->mclk); + if (ret) + goto err_mclk; + + ret = clk_prepare_enable(va->npl); + if (ret) + goto err_npl; + + return 0; + +err_npl: + clk_disable_unprepare(va->mclk); +err_mclk: + clk_disable_unprepare(va->dcodec); +err_dcodec: + clk_disable_unprepare(va->macro); + + return ret; +} + struct va_macro_data { bool has_swr_master; bool has_npl_clk; @@ -1632,14 +1671,6 @@ static int va_macro_probe(struct platform_device *pdev) goto err; } - ret = devm_pm_clk_create(dev); - if (ret) - goto err; - - ret = of_pm_clk_add_clks(dev); - if (ret < 0) - goto err; - pm_runtime_set_autosuspend_delay(dev, 100); pm_runtime_use_autosuspend(dev); ret = devm_pm_runtime_enable(dev); @@ -1730,16 +1761,9 @@ static void va_macro_remove(struct platform_device *pdev) static int va_macro_runtime_suspend(struct device *dev) { struct va_macro *va = dev_get_drvdata(dev); - int ret; regcache_cache_only(va->regmap, true); - - ret = pm_clk_suspend(dev); - if (ret) { - regcache_cache_only(va->regmap, false); - return ret; - } - + va_macro_disable_clocks(va); regcache_mark_dirty(va->regmap); return 0; @@ -1748,14 +1772,11 @@ static int va_macro_runtime_suspend(struct device *dev) static int va_macro_runtime_resume(struct device *dev) { struct va_macro *va = dev_get_drvdata(dev); - int ret, sret; + int ret; - ret = pm_clk_resume(dev); - if (ret) { - regcache_cache_only(va->regmap, true); - regcache_mark_dirty(va->regmap); + ret = va_macro_enable_clocks(va); + if (ret) return ret; - } regcache_cache_only(va->regmap, false); @@ -1763,11 +1784,7 @@ static int va_macro_runtime_resume(struct device *dev) if (ret) { regcache_cache_only(va->regmap, true); regcache_mark_dirty(va->regmap); - sret = pm_clk_suspend(dev); - if (sret) - dev_err(va->dev, - "failed to suspend clocks after regcache sync failure: %d\n", - sret); + va_macro_disable_clocks(va); return ret; } @@ -1775,9 +1792,8 @@ static int va_macro_runtime_resume(struct device *dev) } -static const struct dev_pm_ops va_macro_pm_ops = { - RUNTIME_PM_OPS(va_macro_runtime_suspend, va_macro_runtime_resume, NULL) -}; +static DEFINE_RUNTIME_DEV_PM_OPS(va_macro_pm_ops, va_macro_runtime_suspend, + va_macro_runtime_resume, NULL); static const struct of_device_id va_macro_dt_match[] = { { .compatible = "qcom,sc7280-lpass-va-macro", .data = &sc7280_va_data }, From 5b96d705fced7b7be14e9899f3cee209cda8c59e Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 16:14:50 +0530 Subject: [PATCH 0515/1133] FROMLIST: ASoC: codecs: lpass-wsa-macro: manage clocks in runtime PM Replace PM clock framework usage with explicit clock prepare/enable and disable/unprepare operations from runtime PM callbacks. This keeps the WSA macro clock prepare state tied to the runtime PM active state, so idle suspend can release parent clock votes. Use DEFINE_RUNTIME_DEV_PM_OPS() so system suspend forces the same runtime suspend path for an active device. Link: https://lore.kernel.org/all/20260928-xo-sd-runtimepm-v1-final-v1-4-e3ebade3aeb7@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam Signed-off-by: Aiyaz Patel --- sound/soc/codecs/lpass-wsa-macro.c | 86 +++++++++++++++++++----------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 899c8bee4645f..de9add3211539 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -424,6 +423,53 @@ struct wsa_macro { }; #define to_wsa_macro(_hw) container_of(_hw, struct wsa_macro, hw) +static void wsa_macro_disable_clocks(struct wsa_macro *wsa) +{ + clk_disable_unprepare(wsa->fsgen); + clk_disable_unprepare(wsa->npl); + clk_disable_unprepare(wsa->mclk); + clk_disable_unprepare(wsa->dcodec); + clk_disable_unprepare(wsa->macro); +} + +static int wsa_macro_enable_clocks(struct wsa_macro *wsa) +{ + int ret; + + ret = clk_prepare_enable(wsa->macro); + if (ret) + return ret; + + ret = clk_prepare_enable(wsa->dcodec); + if (ret) + goto err_dcodec; + + ret = clk_prepare_enable(wsa->mclk); + if (ret) + goto err_mclk; + + ret = clk_prepare_enable(wsa->npl); + if (ret) + goto err_npl; + + ret = clk_prepare_enable(wsa->fsgen); + if (ret) + goto err_fsgen; + + return 0; + +err_fsgen: + clk_disable_unprepare(wsa->npl); +err_npl: + clk_disable_unprepare(wsa->mclk); +err_mclk: + clk_disable_unprepare(wsa->dcodec); +err_dcodec: + clk_disable_unprepare(wsa->macro); + + return ret; +} + static const struct wsa_reg_layout wsa_codec_v2_1 = { .rx_intx_1_mix_inp0_sel_mask = GENMASK(2, 0), .rx_intx_1_mix_inp1_sel_mask = GENMASK(5, 3), @@ -2794,14 +2840,6 @@ static int wsa_macro_probe(struct platform_device *pdev) if (ret) return ret; - ret = devm_pm_clk_create(dev); - if (ret) - return ret; - - ret = of_pm_clk_add_clks(dev); - if (ret < 0) - return ret; - pm_runtime_set_autosuspend_delay(dev, 100); pm_runtime_use_autosuspend(dev); ret = devm_pm_runtime_enable(dev); @@ -2847,16 +2885,9 @@ static int wsa_macro_probe(struct platform_device *pdev) static int wsa_macro_runtime_suspend(struct device *dev) { struct wsa_macro *wsa = dev_get_drvdata(dev); - int ret; regcache_cache_only(wsa->regmap, true); - - ret = pm_clk_suspend(dev); - if (ret) { - regcache_cache_only(wsa->regmap, false); - return ret; - } - + wsa_macro_disable_clocks(wsa); regcache_mark_dirty(wsa->regmap); return 0; @@ -2865,34 +2896,27 @@ static int wsa_macro_runtime_suspend(struct device *dev) static int wsa_macro_runtime_resume(struct device *dev) { struct wsa_macro *wsa = dev_get_drvdata(dev); - int ret, sret; + int ret; - ret = pm_clk_resume(dev); - if (ret) { - regcache_cache_only(wsa->regmap, true); - regcache_mark_dirty(wsa->regmap); + ret = wsa_macro_enable_clocks(wsa); + if (ret) return ret; - } + regcache_cache_only(wsa->regmap, false); ret = regcache_sync(wsa->regmap); if (ret) { regcache_cache_only(wsa->regmap, true); regcache_mark_dirty(wsa->regmap); - sret = pm_clk_suspend(dev); - if (sret) - dev_err(dev, - "failed to suspend clocks after regcache sync failure: %d\n", - sret); + wsa_macro_disable_clocks(wsa); return ret; } return 0; } -static const struct dev_pm_ops wsa_macro_pm_ops = { - RUNTIME_PM_OPS(wsa_macro_runtime_suspend, wsa_macro_runtime_resume, NULL) -}; +static DEFINE_RUNTIME_DEV_PM_OPS(wsa_macro_pm_ops, wsa_macro_runtime_suspend, + wsa_macro_runtime_resume, NULL); static const struct of_device_id wsa_macro_dt_match[] = { { From 6c8729eda11769d8a7531532ffab7b7b5269d2ad Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Mon, 28 Sep 2026 16:14:58 +0530 Subject: [PATCH 0516/1133] FROMLIST: ASoC: codecs: lpass-macro: drop PM_CLK dependency The LPASS macro codec drivers no longer use PM clock framework helpers after moving clock handling into runtime PM callbacks. Drop the PM_CLK dependency from RX, TX, VA and WSA macro Kconfig symbols. Link: https://lore.kernel.org/all/20260928-xo-sd-runtimepm-v1-final-v1-5-e3ebade3aeb7@oss.qualcomm.com/ Signed-off-by: Ajay Kumar Nandam Signed-off-by: Aiyaz Patel --- sound/soc/codecs/Kconfig | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index ba59dabeeccde..20186020bceac 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2972,28 +2972,24 @@ config SND_SOC_LPASS_MACRO_COMMON config SND_SOC_LPASS_WSA_MACRO depends on COMMON_CLK - depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm WSA Macro in LPASS(Low Power Audio SubSystem)" config SND_SOC_LPASS_VA_MACRO depends on COMMON_CLK - depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm VA Macro in LPASS(Low Power Audio SubSystem)" config SND_SOC_LPASS_RX_MACRO depends on COMMON_CLK - depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm RX Macro in LPASS(Low Power Audio SubSystem)" config SND_SOC_LPASS_TX_MACRO depends on COMMON_CLK - depends on PM_CLK select REGMAP_MMIO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm TX Macro in LPASS(Low Power Audio SubSystem)" From fd0fe563b49ea6dbfde513b986c3e5c2b4286393 Mon Sep 17 00:00:00 2001 From: Mohit Sharma Date: Thu, 22 Oct 2026 17:49:29 +0530 Subject: [PATCH 0517/1133] FROMLIST: ASoC: qcom: q6apm: Guard callbacks until probe data is ready The GPR bus needs to make response callbacks available before invoking a client probe because clients can issue synchronous commands from probe. This creates a short interval where a callback can run before the client has published its private data. Make q6apm publish its driver data only after all callback-visible state has been initialized. Have the q6apm and q6prm callbacks ignore packets received before driver data is available. Fixes: ec1471a898cc ("soc: qcom: apr: Add GPR support") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/all/20261022144130.2443667-2-mohit.sharma@oss.qualcomm.com/ Co-developed-by: Ajay Kumar Nandam Signed-off-by: Ajay Kumar Nandam Signed-off-by: Mohit Sharma --- sound/soc/qcom/qdsp6/q6apm.c | 6 ++++-- sound/soc/qcom/qdsp6/q6prm.c | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index bed3b64e83102..8e3314a2738c0 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -890,8 +890,6 @@ static int apm_probe(gpr_device_t *gdev) if (!apm) return -ENOMEM; - dev_set_drvdata(dev, apm); - mutex_init(&apm->lock); apm->dev = dev; apm->gdev = gdev; @@ -905,6 +903,7 @@ static int apm_probe(gpr_device_t *gdev) idr_init(&apm->modules_idr); + dev_set_drvdata(dev, apm); g_apm = apm; q6apm_get_apm_state(apm); @@ -949,6 +948,9 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op) const struct gpr_hdr *hdr = &data->hdr; int graph_id, is_pos_buf; + if (!apm) + return 0; + result = data->payload; switch (hdr->opcode) { diff --git a/sound/soc/qcom/qdsp6/q6prm.c b/sound/soc/qcom/qdsp6/q6prm.c index 2042ff1e8ff1b..5c927ebd81f41 100644 --- a/sound/soc/qcom/qdsp6/q6prm.c +++ b/sound/soc/qcom/qdsp6/q6prm.c @@ -194,6 +194,9 @@ static int prm_callback(const struct gpr_resp_pkt *data, void *priv, int op) const struct gpr_ibasic_rsp_result_t *result; const struct gpr_hdr *hdr = &data->hdr; + if (!prm) + return 0; + switch (hdr->opcode) { case PRM_CMD_RSP_REQUEST_HW_RSC: case PRM_CMD_RSP_RELEASE_HW_RSC: From 6b9b5022917f9def9275ddd6ff066c86e0f765cc Mon Sep 17 00:00:00 2001 From: Mohit Sharma Date: Thu, 22 Oct 2026 17:50:10 +0530 Subject: [PATCH 0518/1133] FROMLIST: soc: qcom: apr: Publish GPR callback before client probe A GPR service driver can issue synchronous commands from its probe path, or populate child devices which issue commands before the parent probe returns. The APR/GPR bus currently installs the GPR service callback only after the service driver's probe has completed. If a response arrives while the client probe is still running, GPR finds the destination service but cannot dispatch the response because the service callback is NULL. The client waiting for the response eventually times out. This was observed intermittently on Qualcomm Lemans and Monaco platforms when q6apm child probing sent an APM shared-memory map command before the parent probe returned. The failure has the following signature: qcom-apm ... CMD timeout for [100100c] opcode q6apm-dai ... Audio Start: Buffer Allocation failed rc = -110 snd-sc8280xp ... ASoC: can't create pcm MultiMedia1 Playback :-110 Install the GPR callback before invoking the client probe so responses to probe-time commands can be dispatched. Clear the callback again if probe fails, and preserve the existing callback ordering for APR clients. Fixes: ec1471a898cc ("soc: qcom: apr: Add GPR support") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/all/20261022144130.2443667-3-mohit.sharma@oss.qualcomm.com/ Co-developed-by: Ajay Kumar Nandam Signed-off-by: Ajay Kumar Nandam Signed-off-by: Mohit Sharma --- drivers/soc/qcom/apr.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index 2d5645ff99197..0220cebcfb1a7 100644 --- a/drivers/soc/qcom/apr.c +++ b/drivers/soc/qcom/apr.c @@ -342,13 +342,24 @@ static int apr_device_probe(struct device *dev) { struct apr_device *adev = to_apr_device(dev); struct apr_driver *adrv = to_apr_driver(dev->driver); + struct packet_router *apr = dev_get_drvdata(dev->parent); int ret; + if (apr->type == PR_TYPE_GPR) + adev->svc.callback = adrv->gpr_callback; + ret = adrv->probe(adev); - if (!ret) + if (ret) { + if (apr->type == PR_TYPE_GPR) + adev->svc.callback = NULL; + + return ret; + } + + if (apr->type != PR_TYPE_GPR) adev->svc.callback = adrv->gpr_callback; - return ret; + return 0; } static void apr_device_remove(struct device *dev) From 707d29cb7cd4c60455e964702a7f6012a3208035 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Wed, 14 Oct 2026 14:42:47 +0530 Subject: [PATCH 0519/1133] FROMLIST: ASoC: dt-bindings: qcom: Add Shikra RX and VA macro codecs Document compatibles for Qualcomm shikra rx and va macro codecs. This SoC does not provide macro and dcodec clock so reflect that in the bindings. Shikra integrates LPASS codec version 4.1, which is not backwards compatible with the already described compatibles. Link: https://lore.kernel.org/all/20261014-add_shikra_support_v5-v5-1-fb9f0667e613@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mohammad Rafi Shaik --- .../bindings/sound/qcom,lpass-rx-macro.yaml | 16 ++++++++++++++++ .../bindings/sound/qcom,lpass-va-macro.yaml | 17 +++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml index 0a5eb51076231..1b1bc24520391 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml @@ -16,6 +16,7 @@ properties: - qcom,glymur-lpass-rx-macro - qcom,hawi-lpass-rx-macro - qcom,sc7280-lpass-rx-macro + - qcom,shikra-lpass-rx-macro - qcom,sm6115-lpass-rx-macro - qcom,sm8250-lpass-rx-macro - qcom,sm8450-lpass-rx-macro @@ -161,6 +162,21 @@ allOf: - const: dcodec - const: fsgen + - if: + properties: + compatible: + enum: + - qcom,shikra-lpass-rx-macro + then: + properties: + clocks: + maxItems: 3 + clock-names: + items: + - const: mclk + - const: npl + - const: fsgen + unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml index cafc3a52ff20a..158d0fae1d08d 100644 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml @@ -15,6 +15,7 @@ properties: - enum: - qcom,hawi-lpass-va-macro - qcom,sc7280-lpass-va-macro + - qcom,shikra-lpass-va-macro - qcom,sm6115-lpass-va-macro - qcom,sm8250-lpass-va-macro - qcom,sm8450-lpass-va-macro @@ -190,6 +191,22 @@ allOf: - const: dcodec - const: heartbeatpulse + - if: + properties: + compatible: + contains: + enum: + - qcom,shikra-lpass-va-macro + then: + properties: + clocks: + minItems: 2 + maxItems: 2 + clock-names: + items: + - const: mclk + - const: npl + unevaluatedProperties: false examples: From 36d7aa2da1f3361a632a96d670d37e5eb946660a Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Wed, 14 Oct 2026 14:42:49 +0530 Subject: [PATCH 0520/1133] FROMLIST: ASoC: qcom: lpass-rx-macro: Add shikra compatible Add shikra RX macro compatible data and hook it into the LPASS codec v4.1 flow. The RX macro register layout of LPASS codec v4.1 matches the v2.5+ layout, so reuse the existing v2.5 register access helpers, controls and widgets for it. v4.1 additionally requires the FS counter to be bypassed before it is enabled during MCLK enable. This is a property of the codec version and not of the board, so key it off the version detected by the VA macro rather than off match data. Link: https://lore.kernel.org/all/20261014-add_shikra_support_v5-v5-3-fb9f0667e613@oss.qualcomm.com/ Reviewed-by: Ajay Kumar Nandam Signed-off-by: Mohammad Rafi Shaik --- sound/soc/codecs/lpass-rx-macro.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 7eb05ffa367b3..14a1b81ac020d 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -59,6 +59,7 @@ #define CDC_RX_FS_MCLK_CNT_ENABLE BIT(0) #define CDC_RX_FS_MCLK_CNT_CLR_MASK BIT(1) #define CDC_RX_FS_MCLK_CNT_CLR BIT(1) +#define CDC_RX_FS_CNT_BYPASS BIT(7) #define CDC_RX_CLK_RST_CTRL_SWR_CONTROL (0x0108) #define CDC_RX_SWR_CLK_EN_MASK BIT(0) #define CDC_RX_SWR_RESET_MASK BIT(1) @@ -651,6 +652,7 @@ struct rx_macro { bool is_ear_mode_on; bool hph_pwr_mode; bool hph_hd2_mode; + bool fs_cnt_bypass; struct snd_soc_component *component; unsigned long active_ch_mask[RX_MACRO_MAX_DAIS]; unsigned long active_ch_cnt[RX_MACRO_MAX_DAIS]; @@ -2094,6 +2096,11 @@ static int rx_macro_mclk_enable(struct rx_macro *rx, bool mclk_enable) CDC_RX_CLK_MCLK2_ENABLE); regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_RX_FS_MCLK_CNT_CLR_MASK, 0x00); + + if (rx->fs_cnt_bypass) + regmap_set_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_RX_FS_CNT_BYPASS); + regmap_update_bits(regmap, CDC_RX_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_RX_FS_MCLK_CNT_EN_MASK, CDC_RX_FS_MCLK_CNT_ENABLE); @@ -3894,6 +3901,7 @@ static int rx_macro_probe(struct platform_device *pdev) case LPASS_CODEC_VERSION_4_1: rx->rxn_reg_stride = 0xc0; rx->rxn_reg_stride2 = 0x0; + rx->fs_cnt_bypass = (rx->codec_version == LPASS_CODEC_VERSION_4_1); def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_2_5_defaults); reg_defaults = kmalloc_objs(struct reg_default, def_count); if (!reg_defaults) @@ -4002,6 +4010,9 @@ static const struct of_device_id rx_macro_dt_match[] = { }, { .compatible = "qcom,sc8280xp-lpass-rx-macro", .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, + }, { + .compatible = "qcom,shikra-lpass-rx-macro", + .data = (void *)LPASS_MACRO_FLAG_HAS_NPL_CLOCK, }, { } }; From 5a2e9815deb8871033f4cbe79d9a297145ef5bcd Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Wed, 14 Oct 2026 14:42:50 +0530 Subject: [PATCH 0521/1133] FROMLIST: ASoC: qcom: lpass-va-macro: Add shikra compatible Add shikra specific VA macro data and register programming needed by the LPASS codec v4.1 implementation. LPASS codec v4.1 extends the VA macro with four adaptive filter (ADPT) blocks at 0x0800..0x09a4 and requires the FS counter to be bypassed before it is enabled. Add the new registers as a separate reg_default array, used by a v4.1 specific regmap config. The register layout has to be chosen before the regmap exists, i.e. before CDC_VA_TOP_CSR_CORE_ID_* can be read, so it comes from match data; probe then cross checks it against the version reported by the hardware. Link: https://lore.kernel.org/all/20261014-add_shikra_support_v5-v5-4-fb9f0667e613@oss.qualcomm.com/ Signed-off-by: Mohammad Rafi Shaik --- sound/soc/codecs/lpass-va-macro.c | 276 +++++++++++++++++++++++++++++- 1 file changed, 269 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index c1b8d644d072d..bda58c4489b2c 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -25,6 +25,7 @@ #define CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL (0x0004) #define CDC_VA_FS_CONTROL_EN BIT(0) #define CDC_VA_FS_COUNTER_CLR BIT(1) +#define CDC_VA_FS_CNT_BYPASS BIT(7) #define CDC_VA_CLK_RST_CTRL_SWR_CONTROL (0x0008) #define CDC_VA_SWR_RESET_MASK BIT(1) #define CDC_VA_SWR_RESET_ENABLE BIT(1) @@ -155,7 +156,54 @@ #define CDC_VA_TX3_TX_PATH_SEC5 (0x05A4) #define CDC_VA_TX3_TX_PATH_SEC6 (0x05A8) +/* LPASS codec v4.1 adaptive filter (ADPT) blocks */ +#define CDC_VA_CDC_ADPT0_ADPT_CTRL 0x0800 +#define CDC_VA_ADPT_CTRL_EN_MASK GENMASK(7, 0) +#define CDC_VA_CDC_ADPT0_ADPT_GAIN_0 0x0804 +#define CDC_VA_CDC_ADPT0_ADPT_GAIN_1 0x0808 +#define CDC_VA_CDC_ADPT0_DH_FSM_CTRL 0x080c +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_0 0x0810 +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_1 0x0814 +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_2 0x0818 +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_3 0x081c +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_4 0x0820 +#define CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_5 0x0824 + +#define CDC_VA_CDC_ADPT1_ADPT_CTRL 0x0880 +#define CDC_VA_CDC_ADPT1_ADPT_GAIN_0 0x0884 +#define CDC_VA_CDC_ADPT1_ADPT_GAIN_1 0x0888 +#define CDC_VA_CDC_ADPT1_DH_FSM_CTRL 0x088c +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_0 0x0890 +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_1 0x0894 +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_2 0x0898 +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_3 0x089c +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_4 0x08a0 +#define CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_5 0x08a4 + +#define CDC_VA_CDC_ADPT2_ADPT_CTRL 0x0900 +#define CDC_VA_CDC_ADPT2_ADPT_GAIN_0 0x0904 +#define CDC_VA_CDC_ADPT2_ADPT_GAIN_1 0x0908 +#define CDC_VA_CDC_ADPT2_DH_FSM_CTRL 0x090c +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_0 0x0910 +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_1 0x0914 +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_2 0x0918 +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_3 0x091c +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_4 0x0920 +#define CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_5 0x0924 + +#define CDC_VA_CDC_ADPT3_ADPT_CTRL 0x0980 +#define CDC_VA_CDC_ADPT3_ADPT_GAIN_0 0x0984 +#define CDC_VA_CDC_ADPT3_ADPT_GAIN_1 0x0988 +#define CDC_VA_CDC_ADPT3_DH_FSM_CTRL 0x098c +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_0 0x0990 +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_1 0x0994 +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_2 0x0998 +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_3 0x099c +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_4 0x09a0 +#define CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_5 0x09a4 + #define VA_MAX_OFFSET (0x07A8) +#define VA_4_1_MAX_OFFSET 0x09a4 #define VA_MACRO_NUM_DECIMATORS 4 #define VA_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ @@ -209,7 +257,8 @@ struct va_macro { u16 dmic_clk_div; bool has_swr_master; bool has_npl_clk; - + bool fs_cnt_bypass; + bool has_adpt; int dec_mode[VA_MACRO_NUM_DECIMATORS]; struct regmap *regmap; struct clk *mclk; @@ -276,6 +325,7 @@ struct va_macro_data { bool has_swr_master; bool has_npl_clk; int version; + const struct regmap_config *regmap_config; }; static const struct va_macro_data sm8250_va_data = { @@ -396,6 +446,127 @@ static const struct reg_default va_defaults[] = { { CDC_VA_TX3_TX_PATH_SEC6, 0x00}, }; +static const struct reg_default va_4_1_defaults[] = { + /* VA macro */ + { CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, 0x00}, + { CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, 0x00}, + { CDC_VA_CLK_RST_CTRL_SWR_CONTROL, 0x00}, + { CDC_VA_TOP_CSR_TOP_CFG0, 0x00}, + { CDC_VA_TOP_CSR_DMIC0_CTL, 0x00}, + { CDC_VA_TOP_CSR_DMIC1_CTL, 0x00}, + { CDC_VA_TOP_CSR_DMIC2_CTL, 0x00}, + { CDC_VA_TOP_CSR_DMIC3_CTL, 0x00}, + { CDC_VA_TOP_CSR_DMIC_CFG, 0x80}, + { CDC_VA_TOP_CSR_DEBUG_BUS, 0x00}, + { CDC_VA_TOP_CSR_DEBUG_EN, 0x00}, + { CDC_VA_TOP_CSR_TX_I2S_CTL, 0x0C}, + { CDC_VA_TOP_CSR_I2S_CLK, 0x00}, + { CDC_VA_TOP_CSR_I2S_RESET, 0x00}, + { CDC_VA_TOP_CSR_CORE_ID_0, 0x00}, + { CDC_VA_TOP_CSR_CORE_ID_1, 0x00}, + { CDC_VA_TOP_CSR_CORE_ID_2, 0x00}, + { CDC_VA_TOP_CSR_CORE_ID_3, 0x00}, + { CDC_VA_TOP_CSR_SWR_MIC_CTL0, 0xEE}, + { CDC_VA_TOP_CSR_SWR_MIC_CTL1, 0xEE}, + { CDC_VA_TOP_CSR_SWR_MIC_CTL2, 0xEE}, + { CDC_VA_TOP_CSR_SWR_CTRL, 0x06}, + /* VA core */ + { CDC_VA_INP_MUX_ADC_MUX0_CFG0, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX0_CFG1, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX1_CFG0, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX1_CFG1, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX2_CFG0, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX2_CFG1, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX3_CFG0, 0x00}, + { CDC_VA_INP_MUX_ADC_MUX3_CFG1, 0x00}, + { CDC_VA_TX0_TX_PATH_CTL, 0x04}, + { CDC_VA_TX0_TX_PATH_CFG0, 0x10}, + { CDC_VA_TX0_TX_PATH_CFG1, 0x0B}, + { CDC_VA_TX0_TX_VOL_CTL, 0x00}, + { CDC_VA_TX0_TX_PATH_SEC0, 0x00}, + { CDC_VA_TX0_TX_PATH_SEC1, 0x00}, + { CDC_VA_TX0_TX_PATH_SEC2, 0x01}, + { CDC_VA_TX0_TX_PATH_SEC3, 0x3C}, + { CDC_VA_TX0_TX_PATH_SEC4, 0x20}, + { CDC_VA_TX0_TX_PATH_SEC5, 0x00}, + { CDC_VA_TX0_TX_PATH_SEC6, 0x00}, + { CDC_VA_TX0_TX_PATH_SEC7, 0x25}, + { CDC_VA_TX1_TX_PATH_CTL, 0x04}, + { CDC_VA_TX1_TX_PATH_CFG0, 0x10}, + { CDC_VA_TX1_TX_PATH_CFG1, 0x0B}, + { CDC_VA_TX1_TX_VOL_CTL, 0x00}, + { CDC_VA_TX1_TX_PATH_SEC0, 0x00}, + { CDC_VA_TX1_TX_PATH_SEC1, 0x00}, + { CDC_VA_TX1_TX_PATH_SEC2, 0x01}, + { CDC_VA_TX1_TX_PATH_SEC3, 0x3C}, + { CDC_VA_TX1_TX_PATH_SEC4, 0x20}, + { CDC_VA_TX1_TX_PATH_SEC5, 0x00}, + { CDC_VA_TX1_TX_PATH_SEC6, 0x00}, + { CDC_VA_TX2_TX_PATH_CTL, 0x04}, + { CDC_VA_TX2_TX_PATH_CFG0, 0x10}, + { CDC_VA_TX2_TX_PATH_CFG1, 0x0B}, + { CDC_VA_TX2_TX_VOL_CTL, 0x00}, + { CDC_VA_TX2_TX_PATH_SEC0, 0x00}, + { CDC_VA_TX2_TX_PATH_SEC1, 0x00}, + { CDC_VA_TX2_TX_PATH_SEC2, 0x01}, + { CDC_VA_TX2_TX_PATH_SEC3, 0x3C}, + { CDC_VA_TX2_TX_PATH_SEC4, 0x20}, + { CDC_VA_TX2_TX_PATH_SEC5, 0x00}, + { CDC_VA_TX2_TX_PATH_SEC6, 0x00}, + { CDC_VA_TX3_TX_PATH_CTL, 0x04}, + { CDC_VA_TX3_TX_PATH_CFG0, 0x10}, + { CDC_VA_TX3_TX_PATH_CFG1, 0x0B}, + { CDC_VA_TX3_TX_VOL_CTL, 0x00}, + { CDC_VA_TX3_TX_PATH_SEC0, 0x00}, + { CDC_VA_TX3_TX_PATH_SEC1, 0x00}, + { CDC_VA_TX3_TX_PATH_SEC2, 0x01}, + { CDC_VA_TX3_TX_PATH_SEC3, 0x3C}, + { CDC_VA_TX3_TX_PATH_SEC4, 0x20}, + { CDC_VA_TX3_TX_PATH_SEC5, 0x00}, + { CDC_VA_TX3_TX_PATH_SEC6, 0x00}, + /* ADPT blocks */ + { CDC_VA_CDC_ADPT0_ADPT_CTRL, 0x51}, + { CDC_VA_CDC_ADPT0_ADPT_GAIN_0, 0x11}, + { CDC_VA_CDC_ADPT0_ADPT_GAIN_1, 0x01}, + { CDC_VA_CDC_ADPT0_DH_FSM_CTRL, 0x02}, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_0, 0x77}, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_1, 0x64}, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_2, 0x00}, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_3, 0x41}, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_4, 0x04}, + { CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_5, 0x01}, + { CDC_VA_CDC_ADPT1_ADPT_CTRL, 0x51}, + { CDC_VA_CDC_ADPT1_ADPT_GAIN_0, 0x11}, + { CDC_VA_CDC_ADPT1_ADPT_GAIN_1, 0x01}, + { CDC_VA_CDC_ADPT1_DH_FSM_CTRL, 0x02}, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_0, 0x77}, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_1, 0x64}, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_2, 0x00}, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_3, 0x41}, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_4, 0x04}, + { CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_5, 0x01}, + { CDC_VA_CDC_ADPT2_ADPT_CTRL, 0x51}, + { CDC_VA_CDC_ADPT2_ADPT_GAIN_0, 0x11}, + { CDC_VA_CDC_ADPT2_ADPT_GAIN_1, 0x01}, + { CDC_VA_CDC_ADPT2_DH_FSM_CTRL, 0x02}, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_0, 0x77}, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_1, 0x64}, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_2, 0x00}, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_3, 0x41}, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_4, 0x04}, + { CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_5, 0x01}, + { CDC_VA_CDC_ADPT3_ADPT_CTRL, 0x51}, + { CDC_VA_CDC_ADPT3_ADPT_GAIN_0, 0x11}, + { CDC_VA_CDC_ADPT3_ADPT_GAIN_1, 0x01}, + { CDC_VA_CDC_ADPT3_DH_FSM_CTRL, 0x02}, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_0, 0x77}, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_1, 0x64}, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_2, 0x00}, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_3, 0x41}, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_4, 0x04}, + { CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_5, 0x01}, +}; + static bool va_is_rw_register(struct device *dev, unsigned int reg) { switch (reg) { @@ -469,6 +640,46 @@ static bool va_is_rw_register(struct device *dev, unsigned int reg) case CDC_VA_TX3_TX_PATH_SEC4: case CDC_VA_TX3_TX_PATH_SEC5: case CDC_VA_TX3_TX_PATH_SEC6: + case CDC_VA_CDC_ADPT0_ADPT_CTRL: + case CDC_VA_CDC_ADPT0_ADPT_GAIN_0: + case CDC_VA_CDC_ADPT0_ADPT_GAIN_1: + case CDC_VA_CDC_ADPT0_DH_FSM_CTRL: + case CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_0: + case CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_1: + case CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_2: + case CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_3: + case CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_4: + case CDC_VA_CDC_ADPT0_CUTOFF_FSM_CTRL_5: + case CDC_VA_CDC_ADPT1_ADPT_CTRL: + case CDC_VA_CDC_ADPT1_ADPT_GAIN_0: + case CDC_VA_CDC_ADPT1_ADPT_GAIN_1: + case CDC_VA_CDC_ADPT1_DH_FSM_CTRL: + case CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_0: + case CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_1: + case CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_2: + case CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_3: + case CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_4: + case CDC_VA_CDC_ADPT1_CUTOFF_FSM_CTRL_5: + case CDC_VA_CDC_ADPT2_ADPT_CTRL: + case CDC_VA_CDC_ADPT2_ADPT_GAIN_0: + case CDC_VA_CDC_ADPT2_ADPT_GAIN_1: + case CDC_VA_CDC_ADPT2_DH_FSM_CTRL: + case CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_0: + case CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_1: + case CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_2: + case CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_3: + case CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_4: + case CDC_VA_CDC_ADPT2_CUTOFF_FSM_CTRL_5: + case CDC_VA_CDC_ADPT3_ADPT_CTRL: + case CDC_VA_CDC_ADPT3_ADPT_GAIN_0: + case CDC_VA_CDC_ADPT3_ADPT_GAIN_1: + case CDC_VA_CDC_ADPT3_DH_FSM_CTRL: + case CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_0: + case CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_1: + case CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_2: + case CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_3: + case CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_4: + case CDC_VA_CDC_ADPT3_CUTOFF_FSM_CTRL_5: return true; } @@ -502,6 +713,26 @@ static const struct regmap_config va_regmap_config = { .writeable_reg = va_is_rw_register, }; +static const struct regmap_config va_4_1_regmap_config = { + .name = "va_macro", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .cache_type = REGCACHE_MAPLE, + .reg_defaults = va_4_1_defaults, + .num_reg_defaults = ARRAY_SIZE(va_4_1_defaults), + .max_register = VA_4_1_MAX_OFFSET, + .volatile_reg = va_is_volatile_register, + .readable_reg = va_is_readable_register, + .writeable_reg = va_is_rw_register, +}; + +static const struct va_macro_data shikra_va_data = { + .has_swr_master = true, + .has_npl_clk = true, + .regmap_config = &va_4_1_regmap_config, +}; + static int va_clk_rsc_fs_gen_request(struct va_macro *va, bool enable) { struct regmap *regmap = va->regmap; @@ -510,10 +741,14 @@ static int va_clk_rsc_fs_gen_request(struct va_macro *va, bool enable) regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, CDC_VA_MCLK_CONTROL_EN, CDC_VA_MCLK_CONTROL_EN); - /* clear the fs counter */ + regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR, CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR); + + if (va->fs_cnt_bypass) + regmap_set_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, + CDC_VA_FS_CNT_BYPASS); regmap_update_bits(regmap, CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, CDC_VA_FS_CONTROL_EN | CDC_VA_FS_COUNTER_CLR, CDC_VA_FS_CONTROL_EN); @@ -542,7 +777,7 @@ static int va_macro_mclk_enable(struct va_macro *va, bool mclk_enable) if (mclk_enable) { va_clk_rsc_fs_gen_request(va, true); regcache_mark_dirty(regmap); - regcache_sync_region(regmap, 0x0, VA_MAX_OFFSET); + regcache_sync_region(regmap, 0x0, regmap_get_max_register(regmap)); } else { va_clk_rsc_fs_gen_request(va, false); } @@ -788,6 +1023,7 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, unsigned int decimator; u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg; u16 tx_gain_ctl_reg; + u16 adpt_ctrl_reg; u8 hpf_cut_off_freq; struct va_macro *va = snd_soc_component_get_drvdata(comp); @@ -802,6 +1038,7 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, VA_MACRO_TX_PATH_OFFSET * decimator; tx_gain_ctl_reg = CDC_VA_TX0_TX_VOL_CTL + VA_MACRO_TX_PATH_OFFSET * decimator; + adpt_ctrl_reg = CDC_VA_CDC_ADPT0_ADPT_CTRL + decimator * VA_MACRO_TX_PATH_OFFSET; switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -811,6 +1048,10 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, /* Enable TX PGA Mute */ break; case SND_SOC_DAPM_POST_PMU: + if (va->has_adpt) + snd_soc_component_update_bits(comp, adpt_ctrl_reg, + CDC_VA_ADPT_CTRL_EN_MASK, 0x00); + /* Enable TX CLK */ snd_soc_component_update_bits(comp, tx_vol_ctl_reg, CDC_VA_TX_PATH_CLK_EN_MASK, @@ -1597,6 +1838,7 @@ static int va_macro_probe(struct platform_device *pdev) const struct va_macro_data *data; struct va_macro *va; void __iomem *base; + bool has_adpt_layout; u32 sample_rate = 0; int ret; int rpm_ret; @@ -1606,6 +1848,7 @@ static int va_macro_probe(struct platform_device *pdev) return -ENOMEM; va->dev = dev; + data = of_device_get_match_data(dev); va->macro = devm_clk_get_optional(dev, "macro"); if (IS_ERR(va->macro)) @@ -1642,15 +1885,15 @@ static int va_macro_probe(struct platform_device *pdev) goto err; } - va->regmap = devm_regmap_init_mmio(dev, base, &va_regmap_config); + dev_set_drvdata(dev, va); + + va->regmap = devm_regmap_init_mmio(dev, base, + data->regmap_config ?: &va_regmap_config); if (IS_ERR(va->regmap)) { ret = -EINVAL; goto err; } - dev_set_drvdata(dev, va); - - data = of_device_get_match_data(dev); va->has_swr_master = data->has_swr_master; va->has_npl_clk = data->has_npl_clk; @@ -1696,6 +1939,24 @@ static int va_macro_probe(struct platform_device *pdev) goto err_rpm_put; } + va->fs_cnt_bypass = (lpass_macro_get_codec_version() == LPASS_CODEC_VERSION_4_1); + va->has_adpt = (lpass_macro_get_codec_version() == LPASS_CODEC_VERSION_4_1); + + /* + * The register layout comes from match data, as it has to be picked + * before CDC_VA_TOP_CSR_CORE_ID_* can be read. Now that the codec + * version is known, make sure the two agree, so that the ADPT blocks + * are neither programmed outside the register window nor programmed + * on a codec that does not implement them. + */ + has_adpt_layout = data->regmap_config == &va_4_1_regmap_config; + if (va->has_adpt != has_adpt_layout) { + dev_err(dev, "LPASS codec %s does not match the compatible\n", + lpass_macro_get_codec_version_string(lpass_macro_get_codec_version())); + ret = -EINVAL; + goto err_rpm_put; + } + if (va->has_swr_master) { /* Set default CLK div to 1 */ regmap_update_bits(va->regmap, CDC_VA_TOP_CSR_SWR_MIC_CTL0, @@ -1803,6 +2064,7 @@ static const struct of_device_id va_macro_dt_match[] = { { .compatible = "qcom,sm8550-lpass-va-macro", .data = &sm8550_va_data }, { .compatible = "qcom,hawi-lpass-va-macro", .data = &sm8550_va_data }, { .compatible = "qcom,sc8280xp-lpass-va-macro", .data = &sm8450_va_data }, + { .compatible = "qcom,shikra-lpass-va-macro", .data = &shikra_va_data }, {} }; MODULE_DEVICE_TABLE(of, va_macro_dt_match); From 512a22035490fe0eb43a648b2698dc74d5e87d3d Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Wed, 14 Oct 2026 14:42:51 +0530 Subject: [PATCH 0522/1133] FROMLIST: ASoC: qcom: lpass-va-macro: Add SoundWire microphone support The VA decimators can currently capture audio only from DMIC inputs. Add support for routing audio from SoundWire microphone (SMIC) inputs as well. Update the decimator source selection logic to switch between DMIC and SMIC sources based on the active input path. The ADC_DMIC_SEL bit of CDC_VA_TXn_TX_PATH_CFG0 is shared by the DMIC and the SoundWire mic mux, so a mixer write to the mux that is not part of the active path can leave it stale. Program it from the resolved mux state when the decimator is enabled, so capture does not depend on the order in which userspace restores the two controls. Add a helper to detect whether a decimator is using a SoundWire microphone input. Use this information to skip DMIC-specific HPF programming sequences when the decimator is configured for an SMIC source. This enables VA decimators to capture audio from either DMIC or SoundWire microphone inputs. Link: https://lore.kernel.org/all/20261014-add_shikra_support_v5-v5-5-fb9f0667e613@oss.qualcomm.com/ Signed-off-by: Mohammad Rafi Shaik --- sound/soc/codecs/lpass-va-macro.c | 154 ++++++++++++++++++++++++++++-- 1 file changed, 147 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index bda58c4489b2c..f8519be589a3f 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -801,6 +801,16 @@ static int va_macro_mclk_event(struct snd_soc_dapm_widget *w, return 0; } +static bool is_amic_enabled(struct snd_soc_component *comp, int decimator) +{ + u16 adc_mux_reg; + + adc_mux_reg = CDC_VA_INP_MUX_ADC_MUX0_CFG1 + + VA_MACRO_ADC_MUX_CFG_OFFSET * decimator; + + return snd_soc_component_read(comp, adc_mux_reg) & BIT(0); +} + static int va_macro_put_dec_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -810,20 +820,26 @@ static int va_macro_put_dec_enum(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int val; u16 mic_sel_reg; + int decimator; + bool smic_mux; val = ucontrol->value.enumerated.item[0]; switch (e->reg) { case CDC_VA_INP_MUX_ADC_MUX0_CFG0: + decimator = 0; mic_sel_reg = CDC_VA_TX0_TX_PATH_CFG0; break; case CDC_VA_INP_MUX_ADC_MUX1_CFG0: + decimator = 1; mic_sel_reg = CDC_VA_TX1_TX_PATH_CFG0; break; case CDC_VA_INP_MUX_ADC_MUX2_CFG0: + decimator = 2; mic_sel_reg = CDC_VA_TX2_TX_PATH_CFG0; break; case CDC_VA_INP_MUX_ADC_MUX3_CFG0: + decimator = 3; mic_sel_reg = CDC_VA_TX3_TX_PATH_CFG0; break; default: @@ -832,10 +848,24 @@ static int va_macro_put_dec_enum(struct snd_kcontrol *kcontrol, return -EINVAL; } - if (val != 0) + /* + * SMIC enums use shift 0 (lower nibble of CFG0), DMIC enums use + * shift 4 (upper nibble of CFG0). Use e->shift_l to distinguish them + * without relying on widget name comparisons. + */ + smic_mux = (e->shift_l == 0); + + /* + * Both muxes feed the same decimator and share ADC_DMIC_SEL, so only + * the one the decimator is routed through may program it. A write to + * the mux that is not part of the active path would otherwise switch + * the input domain of a running capture. + */ + if (val != 0 && smic_mux == is_amic_enabled(component, decimator)) snd_soc_component_update_bits(component, mic_sel_reg, CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK, - CDC_VA_TX_PATH_ADC_DMIC_SEL_DMIC); + smic_mux ? CDC_VA_TX_PATH_ADC_DMIC_SEL_ADC : + CDC_VA_TX_PATH_ADC_DMIC_SEL_DMIC); return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); } @@ -1025,7 +1055,6 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, u16 tx_gain_ctl_reg; u16 adpt_ctrl_reg; u8 hpf_cut_off_freq; - struct va_macro *va = snd_soc_component_get_drvdata(comp); decimator = w->shift; @@ -1042,6 +1071,18 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: + /* + * ADC_DMIC_SEL is shared by the DMIC and the SoundWire mic + * mux, so its value depends on the order in which userspace + * restores the two controls. Program it from the resolved + * mux state of this decimator, which is what selects the + * input domain. + */ + snd_soc_component_update_bits(comp, dec_cfg_reg, + CDC_VA_TX_PATH_ADC_DMIC_SEL_MASK, + is_amic_enabled(comp, decimator) ? + CDC_VA_TX_PATH_ADC_DMIC_SEL_ADC : + CDC_VA_TX_PATH_ADC_DMIC_SEL_DMIC); snd_soc_component_update_bits(comp, dec_cfg_reg, CDC_VA_ADC_MODE_MASK, va->dec_mode[decimator] << CDC_VA_ADC_MODE_SHIFT); @@ -1056,9 +1097,15 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(comp, tx_vol_ctl_reg, CDC_VA_TX_PATH_CLK_EN_MASK, CDC_VA_TX_PATH_CLK_EN); - snd_soc_component_update_bits(comp, hpf_gate_reg, - CDC_VA_TX_HPF_ZERO_GATE_MASK, - CDC_VA_TX_HPF_ZERO_GATE); + /* + * Only the HPF zero gate assertion is specific to the DMIC + * path; the cutoff programming and the gate release below + * apply to both input domains. + */ + if (!is_amic_enabled(comp, decimator)) + snd_soc_component_update_bits(comp, hpf_gate_reg, + CDC_VA_TX_HPF_ZERO_GATE_MASK, + CDC_VA_TX_HPF_ZERO_GATE); usleep_range(1000, 1010); hpf_cut_off_freq = (snd_soc_component_read(comp, dec_cfg_reg) & @@ -1084,7 +1131,6 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, 0x0); } - usleep_range(1000, 1010); snd_soc_component_update_bits(comp, hpf_gate_reg, CDC_VA_TX_HPF_ZERO_GATE_MASK, @@ -1284,6 +1330,39 @@ static const char * const adc_mux_text[] = { "VA_DMIC", "SWR_MIC" }; +static const char * const smic_mux_text[] = { + "ZERO", "ADC0", "ADC1", "ADC2", "ADC3", "SWR_MIC0", "SWR_MIC1", + "SWR_MIC2", "SWR_MIC3", "SWR_MIC4", "SWR_MIC5", "SWR_MIC6", "SWR_MIC7" +}; + +static SOC_ENUM_SINGLE_DECL(va_smic0_enum, CDC_VA_INP_MUX_ADC_MUX0_CFG0, + 0, smic_mux_text); + +static SOC_ENUM_SINGLE_DECL(va_smic1_enum, CDC_VA_INP_MUX_ADC_MUX1_CFG0, + 0, smic_mux_text); + +static SOC_ENUM_SINGLE_DECL(va_smic2_enum, CDC_VA_INP_MUX_ADC_MUX2_CFG0, + 0, smic_mux_text); + +static SOC_ENUM_SINGLE_DECL(va_smic3_enum, CDC_VA_INP_MUX_ADC_MUX3_CFG0, + 0, smic_mux_text); + +static const struct snd_kcontrol_new va_smic0_mux = SOC_DAPM_ENUM_EXT("va_smic0", + va_smic0_enum, snd_soc_dapm_get_enum_double, + va_macro_put_dec_enum); + +static const struct snd_kcontrol_new va_smic1_mux = SOC_DAPM_ENUM_EXT("va_smic1", + va_smic1_enum, snd_soc_dapm_get_enum_double, + va_macro_put_dec_enum); + +static const struct snd_kcontrol_new va_smic2_mux = SOC_DAPM_ENUM_EXT("va_smic2", + va_smic2_enum, snd_soc_dapm_get_enum_double, + va_macro_put_dec_enum); + +static const struct snd_kcontrol_new va_smic3_mux = SOC_DAPM_ENUM_EXT("va_smic3", + va_smic3_enum, snd_soc_dapm_get_enum_double, + va_macro_put_dec_enum); + static SOC_ENUM_SINGLE_DECL(va_dec0_enum, CDC_VA_INP_MUX_ADC_MUX0_CFG1, 0, adc_mux_text); static SOC_ENUM_SINGLE_DECL(va_dec1_enum, CDC_VA_INP_MUX_ADC_MUX1_CFG1, @@ -1419,6 +1498,11 @@ static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = { SND_SOC_DAPM_MUX("VA DMIC MUX2", SND_SOC_NOPM, 0, 0, &va_dmic2_mux), SND_SOC_DAPM_MUX("VA DMIC MUX3", SND_SOC_NOPM, 0, 0, &va_dmic3_mux), + SND_SOC_DAPM_MUX("VA SMIC MUX0", SND_SOC_NOPM, 0, 0, &va_smic0_mux), + SND_SOC_DAPM_MUX("VA SMIC MUX1", SND_SOC_NOPM, 0, 0, &va_smic1_mux), + SND_SOC_DAPM_MUX("VA SMIC MUX2", SND_SOC_NOPM, 0, 0, &va_smic2_mux), + SND_SOC_DAPM_MUX("VA SMIC MUX3", SND_SOC_NOPM, 0, 0, &va_smic3_mux), + SND_SOC_DAPM_REGULATOR_SUPPLY("vdd-micb", 0, 0), SND_SOC_DAPM_INPUT("DMIC0 Pin"), SND_SOC_DAPM_INPUT("DMIC1 Pin"), @@ -1563,6 +1647,62 @@ static const struct snd_soc_dapm_route va_audio_map[] = { {"VA DMIC MUX3", "DMIC6", "VA DMIC6"}, {"VA DMIC MUX3", "DMIC7", "VA DMIC7"}, + {"VA DEC0 MUX", "SWR_MIC", "VA SMIC MUX0"}, + {"VA SMIC MUX0", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX0", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX0", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX0", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX0", "SWR_MIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX0", "SWR_MIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX0", "SWR_MIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX0", "SWR_MIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX0", "SWR_MIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX0", "SWR_MIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX0", "SWR_MIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX0", "SWR_MIC7", "VA SWR_MIC7"}, + + {"VA DEC1 MUX", "SWR_MIC", "VA SMIC MUX1"}, + {"VA SMIC MUX1", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX1", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX1", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX1", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX1", "SWR_MIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX1", "SWR_MIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX1", "SWR_MIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX1", "SWR_MIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX1", "SWR_MIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX1", "SWR_MIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX1", "SWR_MIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX1", "SWR_MIC7", "VA SWR_MIC7"}, + + {"VA DEC2 MUX", "SWR_MIC", "VA SMIC MUX2"}, + {"VA SMIC MUX2", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX2", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX2", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX2", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX2", "SWR_MIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX2", "SWR_MIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX2", "SWR_MIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX2", "SWR_MIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX2", "SWR_MIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX2", "SWR_MIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX2", "SWR_MIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX2", "SWR_MIC7", "VA SWR_MIC7"}, + + {"VA DEC3 MUX", "SWR_MIC", "VA SMIC MUX3"}, + {"VA SMIC MUX3", "ADC0", "VA SWR_ADC0"}, + {"VA SMIC MUX3", "ADC1", "VA SWR_ADC1"}, + {"VA SMIC MUX3", "ADC2", "VA SWR_ADC2"}, + {"VA SMIC MUX3", "ADC3", "VA SWR_ADC3"}, + {"VA SMIC MUX3", "SWR_MIC0", "VA SWR_MIC0"}, + {"VA SMIC MUX3", "SWR_MIC1", "VA SWR_MIC1"}, + {"VA SMIC MUX3", "SWR_MIC2", "VA SWR_MIC2"}, + {"VA SMIC MUX3", "SWR_MIC3", "VA SWR_MIC3"}, + {"VA SMIC MUX3", "SWR_MIC4", "VA SWR_MIC4"}, + {"VA SMIC MUX3", "SWR_MIC5", "VA SWR_MIC5"}, + {"VA SMIC MUX3", "SWR_MIC6", "VA SWR_MIC6"}, + {"VA SMIC MUX3", "SWR_MIC7", "VA SWR_MIC7"}, + { "VA DMIC0", NULL, "DMIC0 Pin" }, { "VA DMIC1", NULL, "DMIC1 Pin" }, { "VA DMIC2", NULL, "DMIC2 Pin" }, From 8eb15e96b56ba01306230f98805143b3d161a85f Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Thu, 10 Sep 2026 20:32:38 +0530 Subject: [PATCH 0523/1133] FROMLIST: ASoC: dt-bindings: qcom,sm8250: add Shikra sound card compatibles Add Shikra sound-card compatible strings to the Qualcomm sound card binding so DT can describe board-specific audio topologies: - qcom,shikra-cqm-sndcard - qcom,shikra-cqs-sndcard - qcom,shikra-iqs-sndcard Shikra EVK variants use different codec/interface combinations and DSP processing paths. Describing these variants explicitly in DT allows the machine driver to select the correct DAPM routes, controls, and clocking behavior for each board. Link: https://lore.kernel.org/all/20260910-shikra-machine-v2-v2-1-9bf6bad589d8@oss.qualcomm.com/ Co-developed-by: Mohammad Rafi Shaik Reviewed-by: Krzysztof Kozlowski Signed-off-by: Ajay Kumar Nandam Signed-off-by: Mohammad Rafi Shaik --- Documentation/devicetree/bindings/sound/qcom,sm8250.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml index 40b68b72f8f4a..6ca505869b084 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml @@ -53,6 +53,9 @@ properties: - qcom,sc8280xp-sndcard - qcom,sdm660-sndcard - qcom,sdm845-sndcard + - qcom,shikra-cqm-sndcard + - qcom,shikra-cqs-sndcard + - qcom,shikra-iqs-sndcard - qcom,sm8250-sndcard - qcom,sm8450-sndcard - qcom,talos-lyra-sndcard From 372625db55d44968ca647572a37a780a47f538d3 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Thu, 10 Sep 2026 20:32:39 +0530 Subject: [PATCH 0524/1133] FROMLIST: ASoC: qcom: sc8280xp: Extend hw_params for QAIF backends Prepare the sc8280xp machine driver for Shikra EVK variants that use Audio-IF (QAIF) based backends: - Add a `cpu_dai_fmt` field in qcom_snd_soc_common so that boards can override the default SND_SOC_DAIFMT_BP_FP for MI2S and TDM paths. - Handle the QAIF MI2S (AIF_MI2S_RX_0 ... AIF_MI2S_TX_12) and QAIF TDM (AIF_TDM_RX_0 ... AIF_TDM_TX_12) DAI ID ranges in sc8280xp_snd_hw_params() so that format and clock setup applies to QAIF backends. - Add VA_CODEC_DMA_TX_1 to qcom_snd_is_sdw_dai() and sc8280xp_be_hw_params_fixup() so that the VA codec DMA path is recognised as a SoundWire DAI. - Widen the sc8280xp_add_be_ops() link filter to also cover links with codecs (num_codecs > 0), since QAIF FE+BE links are not marked with no_pcm = 1. No functional change for existing platforms. Link: https://lore.kernel.org/all/20260910-shikra-machine-v2-v2-2-9bf6bad589d8@oss.qualcomm.com/ Co-developed-by: Mohammad Rafi Shaik Signed-off-by: Ajay Kumar Nandam Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/sc8280xp.c | 16 ++++++++++++---- sound/soc/qcom/sdw.c | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index e26c66fd13d37..421ec686ec992 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -107,6 +107,7 @@ struct qcom_snd_soc_common { const struct snd_kcontrol_new *controls; int num_controls; unsigned int codec_dai_fmt; + unsigned int cpu_dai_fmt; bool codec_sysclk_set; bool mi2s_mclk_enable; bool mi2s_bclk_enable; @@ -192,9 +193,15 @@ static int sc8280xp_tdm_hw_params(struct snd_pcm_substream *substream, if (!cpu_cfg.slots) return 0; - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); - if (ret && ret != -ENOTSUPP) - return ret; + if (data->priv->cpu_dai_fmt) { + ret = snd_soc_dai_set_fmt(cpu_dai, data->priv->cpu_dai_fmt); + if (ret && ret != -ENOTSUPP) + return ret; + } else { + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); + if (ret && ret != -ENOTSUPP) + return ret; + } if (data->priv->codec_dai_fmt) { for_each_rtd_codec_dais(rtd, i, codec_dai) { @@ -324,6 +331,7 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, case TX_CODEC_DMA_TX_1: case TX_CODEC_DMA_TX_2: case TX_CODEC_DMA_TX_3: + case VA_CODEC_DMA_TX_1: channels->min = 1; break; default: @@ -530,7 +538,7 @@ static void sc8280xp_add_be_ops(struct snd_soc_card *card) int i; for_each_card_prelinks(card, i, link) { - if (link->no_pcm == 1) { + if (link->no_pcm == 1 || link->num_codecs > 0) { link->init = sc8280xp_snd_init; link->exit = sc8280xp_snd_exit; link->be_hw_params_fixup = sc8280xp_be_hw_params_fixup; diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c index 6576b47a4c8c3..e19adb7c750b0 100644 --- a/sound/soc/qcom/sdw.c +++ b/sound/soc/qcom/sdw.c @@ -30,6 +30,7 @@ static bool qcom_snd_is_sdw_dai(int id) case TX_CODEC_DMA_TX_5: case RX_CODEC_DMA_RX_6: case RX_CODEC_DMA_RX_7: + case VA_CODEC_DMA_TX_1: case SLIMBUS_0_RX...SLIMBUS_6_TX: return true; default: From 2e552a9a39b3f934335d3b9f47179777aa7e0c32 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Thu, 10 Sep 2026 20:32:40 +0530 Subject: [PATCH 0525/1133] FROMLIST: ASoC: qcom: sc8280xp: Add shikra-cqm-evk compatible support Add machine driver support for the Qualcomm Shikra CQM EVK board. The Shikra CQM platform uses an I2S-based audio path with WSA885x amplifiers and PM4125/Rouleur codec components. The CQM variant uses DSP_A framing on its QAIF CPU DAI, configured via the cpu_dai_fmt field introduced in the preceding patch. Link: https://lore.kernel.org/all/20260910-shikra-machine-v2-v2-3-9bf6bad589d8@oss.qualcomm.com/ Co-developed-by: Mohammad Rafi Shaik Signed-off-by: Ajay Kumar Nandam Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/sc8280xp.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 421ec686ec992..2e98277cb408c 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -83,6 +83,11 @@ struct sc8280xp_dai_data { .dai_data = (const struct sc8280xp_dai_data[]) { __VA_ARGS__ }, \ .num_dai_data = ARRAY_SIZE(((const struct sc8280xp_dai_data[]) { __VA_ARGS__ })) +static const struct snd_soc_dapm_widget shikra_cqm_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), +}; + static const struct snd_soc_dapm_route talos_lyra_dapm_routes[] = { {"IN12", NULL, "Headset Mic12"}, {"Headset Mic12", NULL, "MICBIAS"}, @@ -714,6 +719,15 @@ static const struct qcom_snd_soc_common sc8280xp_priv_data = { .wcd_jack = true, }; +static const struct qcom_snd_soc_common shikra_cqm_priv_data = { + .driver_name = "shikra", + .dapm_widgets = shikra_cqm_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(shikra_cqm_dapm_widgets), + .cpu_dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BP_FP, + .mi2s_bclk_enable = true, + .codec_sysclk_set = true, +}; + static const struct qcom_snd_soc_common sm8450_priv_data = { .driver_name = "sm8450", .dapm_widgets = sc8280xp_dapm_widgets, @@ -782,6 +796,7 @@ static const struct of_device_id snd_sc8280xp_dt_match[] = { { .compatible = "qcom,qcs9075-sndcard", .data = &qcs9100_priv_data }, { .compatible = "qcom,qcs9100-sndcard", .data = &qcs9100_priv_data }, { .compatible = "qcom,sc8280xp-sndcard", .data = &sc8280xp_priv_data }, + { .compatible = "qcom,shikra-cqm-sndcard", .data = &shikra_cqm_priv_data }, { .compatible = "qcom,sm8450-sndcard", .data = &sm8450_priv_data }, { .compatible = "qcom,sm8475-sndcard", .data = &sm8475_priv_data }, { .compatible = "qcom,sm8550-sndcard", .data = &sm8550_priv_data }, From 936a23b34cc9e45e7e9ebd83bd54e4fca9147372 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Thu, 10 Sep 2026 20:32:41 +0530 Subject: [PATCH 0526/1133] FROMLIST: ASoC: qcom: sc8280xp: Add shikra-cqs-evk compatible support Add machine driver support for the Qualcomm Shikra CQS EVK board. The Shikra CQS platform uses an I2S-based audio path with WSA885x amplifiers and PM4125/Rouleur codec components with modem-DSP based audio processing. Link: https://lore.kernel.org/all/20260910-shikra-machine-v2-v2-4-9bf6bad589d8@oss.qualcomm.com/ Co-developed-by: Mohammad Rafi Shaik Signed-off-by: Ajay Kumar Nandam Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/sc8280xp.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 2e98277cb408c..8d5d64c9a68f3 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -728,6 +728,14 @@ static const struct qcom_snd_soc_common shikra_cqm_priv_data = { .codec_sysclk_set = true, }; +static const struct qcom_snd_soc_common shikra_cqs_priv_data = { + .driver_name = "shikra", + .dapm_widgets = shikra_cqm_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(shikra_cqm_dapm_widgets), + .mi2s_bclk_enable = true, + .codec_sysclk_set = true, +}; + static const struct qcom_snd_soc_common sm8450_priv_data = { .driver_name = "sm8450", .dapm_widgets = sc8280xp_dapm_widgets, @@ -797,6 +805,7 @@ static const struct of_device_id snd_sc8280xp_dt_match[] = { { .compatible = "qcom,qcs9100-sndcard", .data = &qcs9100_priv_data }, { .compatible = "qcom,sc8280xp-sndcard", .data = &sc8280xp_priv_data }, { .compatible = "qcom,shikra-cqm-sndcard", .data = &shikra_cqm_priv_data }, + { .compatible = "qcom,shikra-cqs-sndcard", .data = &shikra_cqs_priv_data }, { .compatible = "qcom,sm8450-sndcard", .data = &sm8450_priv_data }, { .compatible = "qcom,sm8475-sndcard", .data = &sm8475_priv_data }, { .compatible = "qcom,sm8550-sndcard", .data = &sm8550_priv_data }, From 84824210493fef3c65aa258bf7532ad795224381 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Nandam Date: Thu, 10 Sep 2026 20:32:42 +0530 Subject: [PATCH 0527/1133] FROMLIST: ASoC: qcom: sc8280xp: Add shikra-iqs-evk compatible support Add machine driver support for the Qualcomm Shikra IQS EVK board. The Shikra IQS platform uses a third-party MAX98091 codec with modem-DSP support. IQS requires board-level DAPM widgets and pin-switch kcontrols because the MAX98091 codec driver does not expose its own endpoint topology, unlike the Qualcomm WSA885x/Rouleur codecs used on the CQM/CQS variants. Link: https://lore.kernel.org/all/20260910-shikra-machine-v2-v2-5-9bf6bad589d8@oss.qualcomm.com/ Co-developed-by: Mohammad Rafi Shaik Signed-off-by: Ajay Kumar Nandam Signed-off-by: Mohammad Rafi Shaik --- sound/soc/qcom/sc8280xp.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 8d5d64c9a68f3..178036cec1945 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -88,6 +88,20 @@ static const struct snd_soc_dapm_widget shikra_cqm_dapm_widgets[] = { SND_SOC_DAPM_MIC("Mic Jack", NULL), }; +static const struct snd_soc_dapm_widget shikra_iqs_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_kcontrol_new shikra_iqs_controls[] = { + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Int Mic"), + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + static const struct snd_soc_dapm_route talos_lyra_dapm_routes[] = { {"IN12", NULL, "Headset Mic12"}, {"Headset Mic12", NULL, "MICBIAS"}, @@ -736,6 +750,19 @@ static const struct qcom_snd_soc_common shikra_cqs_priv_data = { .codec_sysclk_set = true, }; +static const struct qcom_snd_soc_common shikra_iqs_priv_data = { + .driver_name = "shikra", + .dapm_widgets = shikra_iqs_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(shikra_iqs_dapm_widgets), + .controls = shikra_iqs_controls, + .num_controls = ARRAY_SIZE(shikra_iqs_controls), + .codec_dai_fmt = SND_SOC_DAIFMT_CBP_CFP | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_I2S, + .codec_sysclk_set = true, + .mi2s_bclk_enable = true, +}; + static const struct qcom_snd_soc_common sm8450_priv_data = { .driver_name = "sm8450", .dapm_widgets = sc8280xp_dapm_widgets, @@ -806,6 +833,7 @@ static const struct of_device_id snd_sc8280xp_dt_match[] = { { .compatible = "qcom,sc8280xp-sndcard", .data = &sc8280xp_priv_data }, { .compatible = "qcom,shikra-cqm-sndcard", .data = &shikra_cqm_priv_data }, { .compatible = "qcom,shikra-cqs-sndcard", .data = &shikra_cqs_priv_data }, + { .compatible = "qcom,shikra-iqs-sndcard", .data = &shikra_iqs_priv_data }, { .compatible = "qcom,sm8450-sndcard", .data = &sm8450_priv_data }, { .compatible = "qcom,sm8475-sndcard", .data = &sm8475_priv_data }, { .compatible = "qcom,sm8550-sndcard", .data = &sm8550_priv_data }, From a1cf18383aa0770846fba32f1e2b64c5f3bc7235 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 15 Oct 2026 19:43:09 +0530 Subject: [PATCH 0528/1133] FROMLIST: ASoC: dt-bindings: qcom,pm4125-codec: Add the MBHC jack properties The binding already describes qcom,mbhc-buttons-vthreshold-microvolt, but not the rest of the data the MBHC block needs to detect a 3.5mm jack, even though wcd_dt_parse_mbhc_data() reads all of it from the codec node and the schema has unevaluatedProperties set to false. A board that describes its jack is therefore rejected by the schema. Document the remaining four properties, matching the descriptions used for the same properties in qcom,wcd93xx-common.yaml: - qcom,hphl-jack-type-normally-closed and qcom,ground-jack-type-normally-closed describe the board's jack switches. The MBHC logic has to know the idle state of the HPHL and ground switches to tell an insertion from a removal. - qcom,mbhc-headset-vthreshold-microvolt and qcom,mbhc-headphone-vthreshold-microvolt are the ADC thresholds that separate a headset from a headphone and a headphone from a floating jack. They are board specific because they depend on the jack wiring and on the microphone bias voltage they are measured against. All four stay optional, as they are for the wcd93xx codecs: the driver derives the thresholds from the microphone bias voltage when they are absent and assumes normally open switches, so existing device trees keep working unchanged. Link: https://lore.kernel.org/all/20261015-pm4125_mbhc_support-v1-1-8bc1212db6f7@oss.qualcomm.com/ Signed-off-by: Mohammad Rafi Shaik --- .../bindings/sound/qcom,pm4125-codec.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,pm4125-codec.yaml b/Documentation/devicetree/bindings/sound/qcom,pm4125-codec.yaml index 6e2f103be1d32..54e5b760761eb 100644 --- a/Documentation/devicetree/bindings/sound/qcom,pm4125-codec.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,pm4125-codec.yaml @@ -64,6 +64,24 @@ properties: minimum: 1800000 maximum: 2850000 + qcom,hphl-jack-type-normally-closed: + description: Indicates that HPHL jack switch type is normally closed + type: boolean + + qcom,ground-jack-type-normally-closed: + description: Indicates that Headset Ground switch type is normally closed + type: boolean + + qcom,mbhc-headset-vthreshold-microvolt: + description: Voltage threshold value for headset detection + minimum: 0 + maximum: 2850000 + + qcom,mbhc-headphone-vthreshold-microvolt: + description: Voltage threshold value for headphone detection + minimum: 0 + maximum: 2850000 + qcom,mbhc-buttons-vthreshold-microvolt: description: Array of 8 Voltage threshold values corresponding to headset From 3985b4348a6c9fe461fc087aae363654831767fa Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 15 Oct 2026 19:43:10 +0530 Subject: [PATCH 0529/1133] FROMLIST: ASoC: codecs: pm4125: Fix MBHC button threshold programming pm4125_mbhc_program_btn_thr() pre-shifts the computed threshold by two bits before handing it to snd_soc_component_write_field(). That helper already shifts the value by the number of trailing zeroes of the mask, so with PM4125_ANA_MBHC_BTN0_THRESHOLD_MASK being GENMASK(7, 2) the value gets shifted twice. The two most significant bits of the threshold are shifted out past the mask and the remaining bits land four times too high, so every button voltage is programmed wrong and button presses on a headset are either missed or reported as the wrong button. Pass the unshifted value and let the helper place it in the field. Link: https://lore.kernel.org/all/20261015-pm4125_mbhc_support-v1-2-8bc1212db6f7@oss.qualcomm.com/ Fixes: 8ad529484937 ("ASoC: codecs: add new pm4125 audio codec driver") Signed-off-by: Mohammad Rafi Shaik --- sound/soc/codecs/pm4125.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/pm4125.c b/sound/soc/codecs/pm4125.c index 674a2fbc4edae..923318c78d261 100644 --- a/sound/soc/codecs/pm4125.c +++ b/sound/soc/codecs/pm4125.c @@ -981,7 +981,7 @@ static void pm4125_mbhc_program_btn_thr(struct snd_soc_component *component, for (i = 0; i < num_btn; i++) { vth = ((btn_high[i] * 2) / 25) & 0x3F; snd_soc_component_write_field(component, PM4125_ANA_MBHC_BTN0_ZDET_VREF1 + i, - PM4125_ANA_MBHC_BTN0_THRESHOLD_MASK, vth << 2); + PM4125_ANA_MBHC_BTN0_THRESHOLD_MASK, vth); } } From 4d53b0051f581e4aa949505e57c5cdd83cee6375 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 15 Oct 2026 19:43:11 +0530 Subject: [PATCH 0530/1133] FROMLIST: ASoC: codecs: pm4125: Keep the micbias reference count balanced The analog master bias is shared between the microphone bias supplies and the playback and capture paths, so pm4125_global_mbias_enable() and pm4125_global_mbias_disable() reference count it and only touch PM4125_ANA_MBIAS_EN for the first user and the last one. MICB_DISABLE clamps the per-supply reference count at zero but then evaluates the enable and pull-up counts regardless, so a release that has no matching request still reaches pm4125_global_mbias_disable() and drops a reference it never took. The MBHC framework issues exactly such a release: it takes MIC_BIAS_2 once when it starts detecting a plug type and releases it both at the end of the correction work and again from wcd_micbias_disable(). Inserting a jack while a stream is running therefore switches the analog master bias off underneath it, leaving the path up but silent, and it stays silent until another stream takes the first reference again. Return early when there is nothing to release, so the hardware is only touched for a request that was actually made. While at it, use atomic_dec_if_positive() for the global count. atomic_dec_and_test() lets it go negative, and once it is negative the next enable increments it to zero instead of one and never re-arms the bias at all. Link: https://lore.kernel.org/all/20261015-pm4125_mbhc_support-v1-3-8bc1212db6f7@oss.qualcomm.com/ Signed-off-by: Mohammad Rafi Shaik --- sound/soc/codecs/pm4125.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/pm4125.c b/sound/soc/codecs/pm4125.c index 923318c78d261..2100f4e36bbbd 100644 --- a/sound/soc/codecs/pm4125.c +++ b/sound/soc/codecs/pm4125.c @@ -229,7 +229,7 @@ static int pm4125_global_mbias_disable(struct snd_soc_component *component) { struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); - if (atomic_dec_and_test(&pm4125->gloal_mbias_cnt)) { + if (atomic_dec_if_positive(&pm4125->gloal_mbias_cnt) == 0) { snd_soc_component_write_field(component, PM4125_ANA_MBIAS_EN, PM4125_ANA_MBIAS_EN_V2I_MASK, @@ -772,8 +772,18 @@ static int pm4125_micbias_control(struct snd_soc_component *component, int micb_ } break; case MICB_DISABLE: - if (pm4125->micb_ref[micb_index] > 0) - pm4125->micb_ref[micb_index]--; + /* + * Ignore a release that has no matching request. The MBHC + * framework releases MIC_BIAS_2 once when the plug type + * correction work ends and again when it turns the bias off, + * and honouring the second one would drop a reference on the + * shared global mbias that was never taken, switching the + * analog master bias off under an active stream. + */ + if (!pm4125->micb_ref[micb_index]) + break; + + pm4125->micb_ref[micb_index]--; if ((pm4125->micb_ref[micb_index] == 0) && (pm4125->pullup_ref[micb_index] > 0)) { snd_soc_component_update_bits(component, micb_reg, From 61e7c169c493b1f872fb1a4c41e509a402c78f72 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 15 Oct 2026 19:43:12 +0530 Subject: [PATCH 0531/1133] FROMLIST: ASoC: codecs: pm4125: Add the MBHC callbacks needed for jack detection The codec only hands the MBHC framework the electrical bias and button threshold callbacks, and leaves the rest of struct wcd_mbhc_cb empty. The framework falls back to driving the shared register fields itself for some of them, but it has no fallback at all for the ones that control hardware it cannot describe generically, so plug type detection runs without the RCO clock, without a micbias ramp and without the headset ground detection comparator, and never gets a usable ADC reading. Add the callbacks the ADC based detection logic needs: - clk_setup() enables the MBHC RCO, which clocks the detection FSM. - micbias_enable_status() lets the framework tell whether MIC_BIAS_2 is already up for recording, so it does not switch the button current source on underneath a capture stream. - hph_pull_up_control() selects the HPHL pull up current used while sensing an insertion, defaulting to 3uA as the hardware expects. - mbhc_micbias_control() routes the framework's MIC_BIAS_2 requests through pm4125_micbias_control() so they share the reference count with the DAPM micbias widgets and with the analog master bias. - mbhc_micb_ramp_control() ramps MIC_BIAS_2 instead of stepping it, which is required before the cross connection check reads the Schmitt trigger outputs. - mbhc_micb_ctrl_thr_mic() raises MIC_BIAS_2 to the threshold needed to tell a special headset from an extension cable, and puts it back afterwards. - get_micbias_val() reports the programmed MIC_BIAS_2 voltage. The generic path assumes a 1V base, while this codec starts at 1.6V in 50mV steps, so the framework would scale every threshold wrongly. - mbhc_gnd_det_ctrl() enables the headset ground pull up comparator together with ground detection, in that order on the way up and the reverse on the way down. - hph_pull_down_ctrl() parks the headphone outputs in a pull down while no jack is being driven. pm4125_mbhc_micb_adjust_voltage() changes MIC_BIAS_2 while it is enabled, which has to be done with the output briefly pulled up, so serialise it against concurrent requests with a mutex. Link: https://lore.kernel.org/all/20261015-pm4125_mbhc_support-v1-4-8bc1212db6f7@oss.qualcomm.com/ Signed-off-by: Mohammad Rafi Shaik --- sound/soc/codecs/pm4125.c | 202 +++++++++++++++++++++++++++++++++++++- sound/soc/codecs/pm4125.h | 13 +++ sound/soc/qcom/common.c | 1 + 3 files changed, 214 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/pm4125.c b/sound/soc/codecs/pm4125.c index 2100f4e36bbbd..6c519e879c8ca 100644 --- a/sound/soc/codecs/pm4125.c +++ b/sound/soc/codecs/pm4125.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -76,6 +77,7 @@ struct pm4125_priv { struct regmap_irq_chip_data *irq_chip; struct snd_soc_jack *jack; unsigned long status_mask; + struct mutex micb_lock; s32 micb_ref[PM4125_MAX_MICBIAS]; s32 pullup_ref[PM4125_MAX_MICBIAS]; @@ -968,6 +970,12 @@ static int pm4125_set_swr_port(struct snd_kcontrol *kcontrol, struct snd_ctl_ele return 1; } +static void pm4125_mbhc_clk_setup(struct snd_soc_component *component, bool enable) +{ + snd_soc_component_write_field(component, PM4125_ANA_MBHC_CTL_1, + PM4125_ANA_MBHC_CTL_RCO_EN_MASK, enable); +} + static void pm4125_mbhc_bias_control(struct snd_soc_component *component, bool enable) { snd_soc_component_write_field(component, PM4125_ANA_MBHC_ELECT, @@ -995,9 +1003,187 @@ static void pm4125_mbhc_program_btn_thr(struct snd_soc_component *component, } } +static bool pm4125_mbhc_micb_en_status(struct snd_soc_component *component, int micb_num) +{ + if (micb_num != MIC_BIAS_2) + return false; + + return snd_soc_component_read_field(component, PM4125_ANA_MICBIAS_MICB_1_2_EN, + PM4125_ANA_MICBIAS_MICB2_EN_MASK) == 1; +} + +static void pm4125_mbhc_hph_l_pull_up_control(struct snd_soc_component *component, + enum mbhc_hs_pullup_iref pull_up_cur) +{ + /* Default pull up current to 3uA */ + if (pull_up_cur < I_OFF || pull_up_cur > I_3P0_UA || pull_up_cur == I_DEFAULT) + pull_up_cur = I_3P0_UA; + + snd_soc_component_write_field(component, PM4125_ANA_MBHC_PLUG_DETECT_CTL, + PM4125_ANA_MBHC_HSDET_PULLUP_C_MASK, pull_up_cur); +} + +static int pm4125_mbhc_request_micbias(struct snd_soc_component *component, + int micb_num, int req) +{ + return pm4125_micbias_control(component, micb_num, req, false); +} + +static void pm4125_mbhc_micb_ramp_control(struct snd_soc_component *component, bool enable) +{ + if (enable) { + snd_soc_component_write_field(component, PM4125_ANA_MBHC_MICB2_RAMP, + PM4125_ANA_MBHC_MICB2_RAMP_SHIFT_MASK, + PM4125_ANA_MBHC_MICB2_RAMP_SHIFT_CTRL); + snd_soc_component_write_field(component, PM4125_ANA_MBHC_MICB2_RAMP, + PM4125_ANA_MBHC_MICB2_RAMP_EN_MASK, 1); + } else { + snd_soc_component_write_field(component, PM4125_ANA_MBHC_MICB2_RAMP, + PM4125_ANA_MBHC_MICB2_RAMP_EN_MASK, 0); + snd_soc_component_write_field(component, PM4125_ANA_MBHC_MICB2_RAMP, + PM4125_ANA_MBHC_MICB2_RAMP_SHIFT_MASK, 0); + } +} + +static int pm4125_mbhc_micb_adjust_voltage(struct snd_soc_component *component, + int req_volt, int micb_num) +{ + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + int cur_vout_ctl, req_vout_ctl, micb_en, ret = 0; + unsigned int pullup_mask, en_mask; + + switch (micb_num) { + case MIC_BIAS_1: + pullup_mask = PM4125_ANA_MICBIAS_MICB1_PULL_UP_MASK; + en_mask = PM4125_ANA_MICBIAS_MICB1_EN_MASK; + break; + case MIC_BIAS_2: + pullup_mask = PM4125_ANA_MICBIAS_MICB2_PULL_UP_MASK; + en_mask = PM4125_ANA_MICBIAS_MICB2_EN_MASK; + break; + default: + return -EINVAL; + } + + mutex_lock(&pm4125->micb_lock); + + /* + * If requested micbias voltage is same as current micbias voltage, + * then just return. Otherwise, adjust voltage as per requested value. + * If micbias is already enabled, then to avoid slow micbias ramp-up + * or down enable pull-up momentarily, change the micbias value and + * then re-enable micbias. + */ + micb_en = snd_soc_component_read_field(component, PM4125_ANA_MICBIAS_MICB_1_2_EN, + en_mask); + cur_vout_ctl = snd_soc_component_read_field(component, PM4125_ANA_MICBIAS_LDO_1_SETTING, + PM4125_ANA_MICBIAS_MICB_OUT_VAL_MASK); + + req_vout_ctl = wcd_get_micb_vout_ctl_val(component->dev, req_volt); + if (req_vout_ctl < 0) { + ret = -EINVAL; + goto exit; + } + + if (cur_vout_ctl == req_vout_ctl) + goto exit; + + if (micb_en == 1) + snd_soc_component_write_field(component, PM4125_ANA_MICBIAS_MICB_1_2_EN, + pullup_mask, + PM4125_ANA_MICBIAS_MICB_PULL_ENABLE); + + snd_soc_component_write_field(component, PM4125_ANA_MICBIAS_LDO_1_SETTING, + PM4125_ANA_MICBIAS_MICB_OUT_VAL_MASK, req_vout_ctl); + + if (micb_en == 1) { + snd_soc_component_write_field(component, PM4125_ANA_MICBIAS_MICB_1_2_EN, + pullup_mask, + PM4125_ANA_MICBIAS_MICB_PULL_DISABLE); + /* Add 2ms delay as per HW requirement after enabling micbias */ + usleep_range(2000, 2100); + } +exit: + mutex_unlock(&pm4125->micb_lock); + + return ret; +} + +static int pm4125_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *component, + int micb_num, bool req_en) +{ + struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); + int micb_mv; + + if (micb_num != MIC_BIAS_2) + return -EINVAL; + + /* + * If device tree micbias level is already above the minimum voltage + * needed to detect threshold microphone, then do not change the + * micbias, just return. + */ + if (pm4125->common.micb_mv[1] >= WCD_MBHC_THR_HS_MICB_MV) + return 0; + + micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : pm4125->common.micb_mv[1]; + + return pm4125_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2); +} + +static void pm4125_mbhc_get_micbias_val(struct snd_soc_component *component, int *mb) +{ + u8 vout_ctl; + + /* Read MBHC Micbias (Mic Bias2) voltage */ + vout_ctl = snd_soc_component_read_field(component, PM4125_ANA_MICBIAS_LDO_1_SETTING, + PM4125_ANA_MICBIAS_MICB_OUT_VAL_MASK); + + /* + * Formula for getting micbias from vout: + * micbias = 1.6V + VOUT_CTL * 50mV + */ + *mb = 1600 + (vout_ctl * 50); +} + +static void pm4125_mbhc_gnd_det_ctrl(struct snd_soc_component *component, bool enable) +{ + if (enable) { + snd_soc_component_write_field(component, PM4125_ANA_MBHC_MECH, + PM4125_ANA_MBHC_HSG_PULLUP_COMP_EN_MASK, 1); + snd_soc_component_write_field(component, PM4125_ANA_MBHC_MECH, + PM4125_ANA_MBHC_GND_DET_EN_MASK, 1); + } else { + snd_soc_component_write_field(component, PM4125_ANA_MBHC_MECH, + PM4125_ANA_MBHC_GND_DET_EN_MASK, 0); + snd_soc_component_write_field(component, PM4125_ANA_MBHC_MECH, + PM4125_ANA_MBHC_HSG_PULLUP_COMP_EN_MASK, 0); + } +} + +static void pm4125_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component, bool enable) +{ + u8 val = enable ? PM4125_ANA_HPHPA_CNP_GND_PULL_DOWN : + PM4125_ANA_HPHPA_CNP_GND_PULL_NONE; + + snd_soc_component_write_field(component, PM4125_ANA_HPHPA_CNP_CTL_2, + PM4125_ANA_HPHPA_CNP_GND_L_MASK, val); + snd_soc_component_write_field(component, PM4125_ANA_HPHPA_CNP_CTL_2, + PM4125_ANA_HPHPA_CNP_GND_R_MASK, val); +} + static const struct wcd_mbhc_cb mbhc_cb = { + .clk_setup = pm4125_mbhc_clk_setup, .mbhc_bias = pm4125_mbhc_bias_control, .set_btn_thr = pm4125_mbhc_program_btn_thr, + .micbias_enable_status = pm4125_mbhc_micb_en_status, + .hph_pull_up_control = pm4125_mbhc_hph_l_pull_up_control, + .mbhc_micbias_control = pm4125_mbhc_request_micbias, + .mbhc_micb_ramp_control = pm4125_mbhc_micb_ramp_control, + .mbhc_micb_ctrl_thr_mic = pm4125_mbhc_micb_ctrl_threshold_mic, + .get_micbias_val = pm4125_mbhc_get_micbias_val, + .mbhc_gnd_det_ctrl = pm4125_mbhc_gnd_det_ctrl, + .hph_pull_down_ctrl = pm4125_mbhc_hph_pull_down_ctrl, }; static int pm4125_mbhc_init(struct snd_soc_component *component) @@ -1692,6 +1878,7 @@ static int pm4125_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "Failed to get micbias\n"); atomic_set(&pm4125->gloal_mbias_cnt, 0); + mutex_init(&pm4125->micb_lock); cfg = &pm4125->mbhc_cfg; cfg->mbhc_micbias = MIC_BIAS_2; @@ -1700,11 +1887,22 @@ static int pm4125_probe(struct platform_device *pdev) cfg->num_btn = PM4125_MBHC_MAX_BUTTONS; cfg->micb_mv = pm4125->common.micb_mv[1]; cfg->linein_th = 5000; - cfg->hs_thr = 1700; - cfg->hph_thr = 50; wcd_dt_parse_mbhc_data(dev, &pm4125->mbhc_cfg); + cfg->hphl_swh = false; + cfg->gnd_swh = false; + cfg->hs_thr = 1700; + cfg->hph_thr = 50; + cfg->btn_high[0] = 75; + cfg->btn_high[1] = 150; + cfg->btn_high[2] = 237; + cfg->btn_high[3] = 500; + cfg->btn_high[4] = 500; + cfg->btn_high[5] = 500; + cfg->btn_high[6] = 500; + cfg->btn_high[7] = 500; + ret = pm4125_add_slave_components(pm4125, dev, &match); if (ret) return ret; diff --git a/sound/soc/codecs/pm4125.h b/sound/soc/codecs/pm4125.h index 25fd3106f44f4..3ee6f9c255b89 100644 --- a/sound/soc/codecs/pm4125.h +++ b/sound/soc/codecs/pm4125.h @@ -13,7 +13,9 @@ #define PM4125_DIG_BASE_ADDR 0x3400 #define PM4125_ANA_MICBIAS_MICB_1_2_EN (PM4125_ANA_BASE_ADDR+0x040) +#define PM4125_ANA_MICBIAS_MICB1_EN_MASK BIT(6) #define PM4125_ANA_MICBIAS_MICB1_PULL_UP_MASK BIT(5) +#define PM4125_ANA_MICBIAS_MICB2_EN_MASK BIT(2) #define PM4125_ANA_MICBIAS_MICB2_PULL_UP_MASK BIT(1) #define PM4125_ANA_MICBIAS_MICB2_PULL_DN_MASK BIT(0) #define PM4125_ANA_MICBIAS_MICB_PULL_ENABLE 1 @@ -25,6 +27,8 @@ #define PM4125_ANA_TX_AMIC1 (PM4125_ANA_BASE_ADDR+0x047) #define PM4125_ANA_TX_AMIC2 (PM4125_ANA_BASE_ADDR+0x048) #define PM4125_ANA_MBHC_MECH (PM4125_ANA_BASE_ADDR+0x05A) +#define PM4125_ANA_MBHC_GND_DET_EN_MASK BIT(6) +#define PM4125_ANA_MBHC_HSG_PULLUP_COMP_EN_MASK BIT(1) #define PM4125_ANA_MBHC_ELECT (PM4125_ANA_BASE_ADDR+0x05B) #define PM4125_ANA_MBHC_ELECT_BIAS_EN_MASK BIT(0) #define PM4125_ANA_MBHC_ELECT_BIAS_ENABLE 1 @@ -40,9 +44,14 @@ #define PM4125_ANA_MBHC_BTN3_ZDET_DBG_400 (PM4125_ANA_BASE_ADDR+0x063) #define PM4125_ANA_MBHC_BTN4_ZDET_DBG_1400 (PM4125_ANA_BASE_ADDR+0x064) #define PM4125_ANA_MBHC_MICB2_RAMP (PM4125_ANA_BASE_ADDR+0x065) +#define PM4125_ANA_MBHC_MICB2_RAMP_EN_MASK BIT(7) +#define PM4125_ANA_MBHC_MICB2_RAMP_SHIFT_MASK GENMASK(4, 2) +#define PM4125_ANA_MBHC_MICB2_RAMP_SHIFT_CTRL 3 #define PM4125_ANA_MBHC_CTL_1 (PM4125_ANA_BASE_ADDR+0x066) +#define PM4125_ANA_MBHC_CTL_RCO_EN_MASK BIT(7) #define PM4125_ANA_MBHC_CTL_2 (PM4125_ANA_BASE_ADDR+0x067) #define PM4125_ANA_MBHC_PLUG_DETECT_CTL (PM4125_ANA_BASE_ADDR+0x068) +#define PM4125_ANA_MBHC_HSDET_PULLUP_C_MASK GENMASK(7, 6) #define PM4125_ANA_MBHC_ZDET_ANA_CTL (PM4125_ANA_BASE_ADDR+0x069) #define PM4125_ANA_MBHC_ZDET_RAMP_CTL (PM4125_ANA_BASE_ADDR+0x06A) #define PM4125_ANA_MBHC_FSM_STATUS (PM4125_ANA_BASE_ADDR+0x06B) @@ -58,6 +67,10 @@ #define PM4125_ANA_HPHPA_CNP_CTL_1_EN_MASK BIT(1) #define PM4125_ANA_HPHPA_CNP_CTL_1_EN 1 #define PM4125_ANA_HPHPA_CNP_CTL_2 (PM4125_ANA_BASE_ADDR+0x084) +#define PM4125_ANA_HPHPA_CNP_GND_L_MASK GENMASK(5, 4) +#define PM4125_ANA_HPHPA_CNP_GND_R_MASK GENMASK(3, 2) +#define PM4125_ANA_HPHPA_CNP_GND_PULL_DOWN 2 +#define PM4125_ANA_HPHPA_CNP_GND_PULL_NONE 0 #define PM4125_ANA_HPHPA_CNP_OCP_EN_L_MASK BIT(1) #define PM4125_ANA_HPHPA_CNP_OCP_EN_R_MASK BIT(0) #define PM4125_ANA_HPHPA_CNP_OCP_ENABLE 1 diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 83b745f617a86..3ec1020fe9353 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -422,6 +422,7 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, case TX_CODEC_DMA_TX_1: case TX_CODEC_DMA_TX_2: case TX_CODEC_DMA_TX_3: + case VA_CODEC_DMA_TX_1: for_each_rtd_codec_dais(rtd, i, codec_dai) { rval = snd_soc_component_set_jack(codec_dai->component, jack, NULL); From 053eadf9f43e747f80245feb000f91a82039e9b0 Mon Sep 17 00:00:00 2001 From: Karthik S Date: Thu, 22 Oct 2026 12:20:24 +0530 Subject: [PATCH 0532/1133] FROMLIST: ASoC: dt-bindings: qcom,sm8250: Add shikra-iqs-lt9611uxd-evk sound card Add the shikra-iqs-lt9611uxd-evk sound card compatible so DT can describe board-specific audio topology. This Shikra EVK variant does not use the MAX98091 codec as the base shikra-iqs does; instead it uses the LT9611UXD HDMI bridge as an I2S audio codec. Describing these variants explicitly in DT allows the machine driver to select the correct DAPM routes, controls, and clocking behavior for each board. Link: https://lore.kernel.org/all/20261022074220.989787-3-karthik.s@oss.qualcomm.com/ Signed-off-by: Karthik S --- .../bindings/sound/qcom,sm8250.yaml | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml index 6ca505869b084..c0fde61c94e39 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml @@ -52,6 +52,7 @@ properties: - qcom,sc7180-qdsp6-sndcard - qcom,sc8280xp-sndcard - qcom,sdm660-sndcard + - qcom,shikra-iqs-lt9611uxd-sndcard - qcom,sdm845-sndcard - qcom,shikra-cqm-sndcard - qcom,shikra-cqs-sndcard @@ -254,3 +255,45 @@ examples: }; }; }; + + - | + #include + sound { + compatible = "qcom,shikra-iqs-lt9611uxd-sndcard"; + model = "shikra-iqs-lt9611uxd-evk"; + audio-routing = "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + pri-i2s-playback-dai-link { + link-name = "Analog Playback"; + cpu { + sound-dai = <&q6apmbedai PRIMARY_MI2S_RX>; + }; + platform { + sound-dai = <&q6apm>; + }; + codec { + sound-dai = <<9611uxd 0>; + }; + }; + + pri-i2s-capture-dai-link { + link-name = "Analog Capture"; + status = "disabled"; + }; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + platform { + sound-dai = <&q6apm>; + }; + codec { + sound-dai = <&vamacro 0>; + }; + }; + }; From 46326c6953e34ad367a190809a70a5888e2163c0 Mon Sep 17 00:00:00 2001 From: Karthik S Date: Thu, 22 Oct 2026 12:39:07 +0530 Subject: [PATCH 0533/1133] FROMLIST: ASoC: qcom: sc8280xp: Add shikra-iqs-lt9611uxd-evk compatible support Add machine driver support for the Shikra IQS EVK variant that uses the LT9611UXD HDMI bridge as an I2S audio codec instead of the MAX98091. The new compatible reuses the generic sc8280xp DAPM widgets and configures the codec DAI format for I2S with bit/frame clock driven by the codec. Link: https://lore.kernel.org/all/20261022074220.989787-3-karthik.s@oss.qualcomm.com/ Signed-off-by: Karthik S --- sound/soc/qcom/sc8280xp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 178036cec1945..15ed198877a80 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -763,6 +763,15 @@ static const struct qcom_snd_soc_common shikra_iqs_priv_data = { .mi2s_bclk_enable = true, }; +static const struct qcom_snd_soc_common shikra_iqs_lt9611uxd_priv_data = { + .driver_name = "shikra", + .dapm_widgets = sc8280xp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets), + .codec_dai_fmt = SND_SOC_DAIFMT_BC_FC | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_I2S, +}; + static const struct qcom_snd_soc_common sm8450_priv_data = { .driver_name = "sm8450", .dapm_widgets = sc8280xp_dapm_widgets, @@ -834,6 +843,8 @@ static const struct of_device_id snd_sc8280xp_dt_match[] = { { .compatible = "qcom,shikra-cqm-sndcard", .data = &shikra_cqm_priv_data }, { .compatible = "qcom,shikra-cqs-sndcard", .data = &shikra_cqs_priv_data }, { .compatible = "qcom,shikra-iqs-sndcard", .data = &shikra_iqs_priv_data }, + { .compatible = "qcom,shikra-iqs-lt9611uxd-sndcard", + .data = &shikra_iqs_lt9611uxd_priv_data }, { .compatible = "qcom,sm8450-sndcard", .data = &sm8450_priv_data }, { .compatible = "qcom,sm8475-sndcard", .data = &sm8475_priv_data }, { .compatible = "qcom,sm8550-sndcard", .data = &sm8550_priv_data }, From 4f12729c0dda67e80011e8b438ed31c817e99b1c Mon Sep 17 00:00:00 2001 From: Karthik S Date: Thu, 22 Oct 2026 12:20:43 +0530 Subject: [PATCH 0534/1133] FROMLIST: ASoC: qcom: q6apm-dai: Add 32-bit sample format support Add SNDRV_PCM_FMTBIT_S32_LE to the supported formats for both capture and playback hardware descriptors, and handle SNDRV_PCM_FORMAT_S32_LE in q6apm_dai_hw_params() to set bits_per_sample to 32. Link: https://lore.kernel.org/all/20261022074220.989787-3-karthik.s@oss.qualcomm.com/ Signed-off-by: Karthik S --- sound/soc/qcom/qdsp6/q6apm-dai.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 58beaf906b9ff..9002acf0e0cd2 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -202,7 +202,8 @@ static const struct snd_pcm_hardware q6apm_dai_hardware_capture = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_NO_REWINDS | SNDRV_PCM_INFO_SYNC_APPLPTR | SNDRV_PCM_INFO_BATCH), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE), .rates = SNDRV_PCM_RATE_8000_48000, .rate_min = 8000, .rate_max = 48000, @@ -222,7 +223,8 @@ static const struct snd_pcm_hardware q6apm_dai_hardware_playback = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_NO_REWINDS | SNDRV_PCM_INFO_SYNC_APPLPTR | SNDRV_PCM_INFO_BATCH), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE), .rates = SNDRV_PCM_RATE_8000_192000, .rate_min = 8000, .rate_max = 192000, @@ -641,6 +643,9 @@ static int q6apm_dai_hw_params(struct snd_soc_component *component, case SNDRV_PCM_FORMAT_S24_LE: prtd->bits_per_sample = 24; break; + case SNDRV_PCM_FORMAT_S32_LE: + prtd->bits_per_sample = 32; + break; default: return -EINVAL; } From f084244afa64d3895a83fda8bcd596f5ccda1c8e Mon Sep 17 00:00:00 2001 From: Karthik S Date: Thu, 22 Oct 2026 12:21:40 +0530 Subject: [PATCH 0535/1133] FROMLIST: ASoC: qcom: sc8280xp: Conditionally set S16_LE format in hw_params fixup The be_hw_params_fixup callback unconditionally forced S16_LE format for all backend DAIs. MI2S and DisplayPort DAIs need to negotiate format freely to support higher bit depths, so skip the format mask for those DAI IDs and only apply the S16_LE default for the remaining backends. Link: https://lore.kernel.org/all/20261022074220.989787-3-karthik.s@oss.qualcomm.com/ Signed-off-by: Karthik S --- sound/soc/qcom/sc8280xp.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 15ed198877a80..224d20c9a38b8 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -342,7 +342,16 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); rate->min = rate->max = 48000; - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + switch (cpu_dai->id) { + case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: + case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: + case DISPLAY_PORT_RX_0: + case DISPLAY_PORT_RX_1 ... DISPLAY_PORT_RX_7: + break; + default: + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + break; + } channels->min = 2; channels->max = 2; switch (cpu_dai->id) { From 0b51aeb4f438920007b75692b45b4bb7eab8b007 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Sat, 26 Sep 2026 12:04:00 +0530 Subject: [PATCH 0536/1133] FROMLIST: dt-bindings: media: qcom,venus: Add context bank subnodes to common schema The VPU issues DMA through several SMMU streams, and the hardware does not give every stream the same addressable range. The non-pixel stream cannot address the low 600MB of IOVA space, while the pixel stream can address the full range: +-----------------------------------------------------------+ | non-pixel stream addressable range (600 MB - 3.5 GB) | | 0x25800000 - 0xe0000000 | +-----------------------------------------------------------+ | pixel stream addressable range (0 - 3.5 GB) | | 0x00000000 - 0xe0000000 | +-----------------------------------------------------------+ A single "iommus" property on the video-codec node puts every stream in one IOMMU domain sharing one IOVA allocator, so nothing restricts a non-pixel buffer to avoid 0 to 600MB. Once an allocation lands below that boundary the hardware faults, which shows up as unhandled SMMU page faults and spontaneous reboots: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Given that the address range restriction is for specific VPU stream, it should be ideally be moved to that stream. To achieve the same, a subset of streams is now represented as subnodes, so that each can be associated with its respective addressable range. The design was discussed and agreed by mainatiners here https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org In the past, this limitation was addressed with an iommu-map approach, with the iris driver dynamically creating the devices. That approach was later concluded to be a hack to avoid having subnodes, and was NAKed by the iommu maintainers. It was discussed in detail here: https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org/ "iommu-ranges" on the subnode describes the *allowed* IOVA range that stream is allowed to use, so the IOVA is allocated from the specified range only. Define all the possible subnodes so as to describe all the VPU hardware iommu interfaces, both secure as well as non secure. address-cells, size-cells and dma-ranges declares the 1:1 DMA translation into the parent. The parent "iommus" is kept as an alternative via "oneOf", so platforms that have not been converted to subnodes still validate. New platforms should use the subnode form. Link: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-1-0322ca5dc10c@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue --- .../bindings/media/qcom,sc7180-venus.yaml | 15 --- .../bindings/media/qcom,venus-common.yaml | 97 +++++++++++++++++++ 2 files changed, 97 insertions(+), 15 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml b/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml index b21bed3148484..bfd8b1ad47312 100644 --- a/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml @@ -91,21 +91,6 @@ properties: deprecated: true additionalProperties: false - video-firmware: - type: object - additionalProperties: false - - description: | - Firmware subnode is needed when the platform does not - have TrustZone. - - properties: - iommus: - maxItems: 1 - - required: - - iommus - required: - compatible - power-domain-names diff --git a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml index 0be2f9119e782..6c205077bea4d 100644 --- a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml +++ b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml @@ -50,6 +50,93 @@ properties: minItems: 1 maxItems: 4 + '#address-cells': + const: 1 + + '#size-cells': + const: 1 + + dma-ranges: + maxItems: 1 + + non-pixel: + type: object + description: + Context bank for VPU non-pixel buffers, including compressed and internal buffers. + additionalProperties: false + + properties: + iommus: + maxItems: 1 + iommu-ranges: + maxItems: 1 + required: + - iommus + - iommu-ranges + + pixel: + type: object + description: + Context bank for VPU pixel buffers containing uncompressed video data. + additionalProperties: false + + properties: + iommus: + maxItems: 1 + required: + - iommus + + video-firmware: + type: object + description: + Context bank for the VPU firmware processing domain. + additionalProperties: false + + properties: + iommus: + maxItems: 1 + required: + - iommus + + secure-non-pixel: + type: object + description: + Context bank for VPU secure non-pixel buffers. + additionalProperties: false + + properties: + iommus: + maxItems: 1 + iommu-ranges: + maxItems: 1 + required: + - iommus + - iommu-ranges + + secure-pixel: + type: object + description: + Context bank for VPU secure pixel buffers containing uncompressed video data. + additionalProperties: false + + properties: + iommus: + maxItems: 1 + required: + - iommus + + secure-bitstream: + type: object + description: + Context bank for VPU secure bitstream buffers containing compressed video data. + additionalProperties: false + + properties: + iommus: + maxItems: 1 + required: + - iommus + required: - reg - clocks @@ -58,4 +145,14 @@ required: - memory-region - power-domains +oneOf: + - required: + - iommus + - required: + - '#address-cells' + - '#size-cells' + - dma-ranges + - non-pixel + - pixel + additionalProperties: true From f22795e0fe7f8fec83700c8563d2521a1838c475 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Sat, 26 Sep 2026 12:04:01 +0530 Subject: [PATCH 0537/1133] FORMLIST: dt-bindings: media: qcom,sm8550-iris: Add context bank subnodes The VPU issues DMA through several SMMU streams, and the hardware does not give every stream the same addressable range. The non-pixel stream cannot address the low 600MB of IOVA space, while the pixel stream can address the full range: +-----------------------------------------------------------+ | non-pixel stream addressable range (600 MB - 3.5 GB) | | 0x25800000 - 0xe0000000 | +-----------------------------------------------------------+ | pixel stream addressable range (0 - 3.5 GB) | | 0x00000000 - 0xe0000000 | +-----------------------------------------------------------+ A single "iommus" property on the video-codec node puts every stream in one IOMMU domain sharing one IOVA allocator, so nothing restricts a non-pixel buffer to avoid 0 to 600MB. Once an allocation lands below that boundary the hardware faults, which shows up as unhandled SMMU page faults and spontaneous reboots: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Given that the address range restriction is for specific VPU stream, it should be ideally be moved to that stream. To achieve the same, a subset of streams is now represented as subnodes, so that each can be associated with its respective addressable range. The design was discussed and agreed by mainatiners here https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org In the past, this limitation was addressed with an iommu-map approach, with the iris driver dynamically creating the devices. That approach was later concluded to be a hack to avoid having subnodes, and was NAKed by the iommu maintainers. It was discussed in detail here: https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org/ Update example to the subnode form. Doing so, it picks up the supporting properties needed on the video-codec node, address-cells, size-cells and dma-ranges to declare 1:1 DMA translation into the parent. Link: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-2-0322ca5dc10c@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue --- .../bindings/media/qcom,sm8550-iris.yaml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml index 0400ca1bff05d..6ee9d23554cff 100644 --- a/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml @@ -98,10 +98,10 @@ required: - interconnect-names - resets - reset-names - - iommus - dma-coherent allOf: + - $ref: qcom,venus-common.yaml# - if: properties: compatible: @@ -177,12 +177,23 @@ examples: resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x1940 0x0000>, - <&apps_smmu 0x1947 0x0000>; dma-coherent; operating-points-v2 = <&iris_opp_table>; + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0xe0000000>; + + non-pixel { + iommus = <&apps_smmu 0x1940 0x0>; + iommu-ranges = <0x25800000 0xba800000>; + }; + + pixel { + iommus = <&apps_smmu 0x1947 0x0>; + }; + iris_opp_table: opp-table { compatible = "operating-points-v2"; From 4e24028e1bc9d86b7ae1cd7dc72653c3ec469fc2 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Sat, 26 Sep 2026 12:04:02 +0530 Subject: [PATCH 0538/1133] FROMLIST: dt-bindings: media: qcom,sm8750-iris: Add context bank subnodes The VPU issues DMA through several SMMU streams, and the hardware does not give every stream the same addressable range. The non-pixel stream cannot address the low 600MB of IOVA space, while the pixel stream can address the full range: +-----------------------------------------------------------+ | non-pixel stream addressable range (600 MB - 3.5 GB) | | 0x25800000 - 0xe0000000 | +-----------------------------------------------------------+ | pixel stream addressable range (0 - 3.5 GB) | | 0x00000000 - 0xe0000000 | +-----------------------------------------------------------+ A single "iommus" property on the video-codec node puts every stream in one IOMMU domain sharing one IOVA allocator, so nothing restricts a non-pixel buffer to avoid 0 to 600MB. Once an allocation lands below that boundary the hardware faults, which shows up as unhandled SMMU page faults and spontaneous reboots: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Given that the address range restriction is for specific VPU stream, it should be ideally be moved to that stream. To achieve the same, a subset of streams is now represented as subnodes, so that each can be associated with its respective addressable range. The design was discussed and agreed by mainatiners here https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org In the past, this limitation was addressed with an iommu-map approach, with the iris driver dynamically creating the devices. That approach was later concluded to be a hack to avoid having subnodes, and was NAKed by the iommu maintainers. It was discussed in detail here: https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org/ Update example to the subnode form. Doing so, it picks up the supporting properties needed on the video-codec node, address-cells, size-cells and dma-ranges to declare 1:1 DMA translation into the parent. Link: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-3-0322ca5dc10c@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia --- .../bindings/media/qcom,sm8750-iris.yaml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,sm8750-iris.yaml b/Documentation/devicetree/bindings/media/qcom,sm8750-iris.yaml index c42d3470bdac7..b6d5ded1aae6a 100644 --- a/Documentation/devicetree/bindings/media/qcom,sm8750-iris.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sm8750-iris.yaml @@ -72,7 +72,6 @@ required: - dma-coherent - interconnects - interconnect-names - - iommus - power-domain-names - resets - reset-names @@ -110,8 +109,6 @@ examples: "vcodec0_core_freerun"; dma-coherent; - iommus = <&apps_smmu 0x1940 0>, - <&apps_smmu 0x1947 0>; interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY &config_noc SLAVE_VENUS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, @@ -144,6 +141,19 @@ examples: "core", "vcodec0_core"; + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0xe0000000>; + + non-pixel { + iommus = <&apps_smmu 0x1940 0x0>; + iommu-ranges = <0x25800000 0xba800000>; + }; + + pixel { + iommus = <&apps_smmu 0x1947 0x0>; + }; + iris_opp_table: opp-table { compatible = "operating-points-v2"; From 530331e36268b453cd7c2345760dbc051c18f2c4 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Sat, 26 Sep 2026 12:04:03 +0530 Subject: [PATCH 0539/1133] FROMLIST: iommu: of_iommu: Add support for "iommu-ranges" on a device node Reserving an IOVA address using "iommu-addresses" requires it to be placed in the reserved-memory node. But when "iommu-addresses" is the only property being described and there is no backing "reg" (i.e. no actual reserved system memory), it does not really belong under /reserved-memory. A device IOVA range is specific to its own address space, and does not describe the system physical memory to make it qualify under reserved-memory. Given this, place "iommu-addresses" inside reserved-memory only when it is paired with a "reg", otherwise, define it within the device own node. It was discussed here: https://lore.kernel.org/all/662f7093-fb0a-4564-9ca0-98e03e68ba9a@kernel.org Existing "iommu-addresses" property expects a phandle, which does not make sense when the property is defined within the device node. Introduce a new property, "iommu-ranges", to specify the device specific IOVA ranges when there is no backing "reg". Link: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-4-0322ca5dc10c@oss.qualcomm.com/ Suggested-by: Rob Herring Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/662f7093-fb0a-4564-9ca0-98e03e68ba9a@kernel.org --- drivers/iommu/of_iommu.c | 128 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 121 insertions(+), 7 deletions(-) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index a18bb60f6f3df..9766a6944d0e1 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -190,6 +190,111 @@ iommu_resv_region_get_type(struct device *dev, return IOMMU_RESV_RESERVED; } +/** + * of_iommu_derive_resv_regions - derive reserved regions which + * are outside of iommu-ranges + * @dev: device for which to get reserved regions + * @list: reserved region list + * + * A device can describe its own usable IOVA ranges directly on its node + * via "iommu-ranges". Everything not under those ranges is derived + * as a reserved region so the IOMMU allocator won't use it. Entries may + * appear in any order in the property. + */ +static void of_iommu_derive_resv_regions(struct device *dev, struct list_head *list) +{ + struct of_iommu_range { + struct list_head node; + phys_addr_t start; + phys_addr_t end; + } *pos, *new, *next_range; + int size, prot = IOMMU_READ | IOMMU_WRITE; + struct iommu_resv_region *region; + const __be32 *maps, *end; + struct list_head *prev; + phys_addr_t next = 0; + LIST_HEAD(ranges); + + maps = of_get_property(dev->of_node, "iommu-ranges", &size); + if (!maps) + return; + + end = maps + size / sizeof(__be32); + + while (maps < end) { + phys_addr_t iova, iova_end; + size_t length; + + maps = of_translate_dma_region(dev->of_node, maps, &iova, &length); + if (!maps) { + dev_err(dev, "%pOF: failed to parse iommu-ranges\n", + dev->of_node); + break; + } + + if (!length) + continue; + + iova_end = iova + length - 1; + + if (iova_end < iova) { + dev_err(dev, "%pOF: iommu-ranges overflows address space\n", + dev->of_node); + continue; + } + + prev = &ranges; + list_for_each_entry(pos, &ranges, node) { + if (pos->start > iova) + break; + prev = &pos->node; + } + + new = kmalloc_obj(*new); + if (!new) + continue; + + new->start = iova; + new->end = iova_end; + list_add(&new->node, prev); + } + + if (list_empty(&ranges)) + return; + + if (of_dma_is_coherent(dev->of_node)) + prot |= IOMMU_CACHE; + + list_for_each_entry_safe(pos, next_range, &ranges, node) { + if (pos->start > next) { + region = iommu_alloc_resv_region(next, pos->start - next, prot, + IOMMU_RESV_RESERVED, GFP_KERNEL); + if (region) + list_add_tail(®ion->list, list); + } + + if (pos->end == PHYS_ADDR_MAX) + goto exit; + + if (pos->end >= next) + next = pos->end + 1; + + list_del(&pos->node); + kfree(pos); + } + + region = iommu_alloc_resv_region(next, PHYS_ADDR_MAX - next + 1, + prot, IOMMU_RESV_RESERVED, GFP_KERNEL); + if (region) + list_add_tail(®ion->list, list); + +exit: + list_for_each_entry_safe(pos, next_range, &ranges, node) { + list_del(&pos->node); + kfree(pos); + } +} + /** * of_iommu_get_resv_regions - reserved region driver helper for device tree * @dev: device for which to get reserved regions @@ -214,10 +319,14 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list) memset(&phys, 0, sizeof(phys)); + maps = of_get_property(it.node, "iommu-addresses", &size); + if (!maps) + continue; + /* - * The "reg" property is optional and can be omitted by reserved-memory regions - * that represent reservations in the IOVA space, which are regions that should - * not be mapped. + * "iommu-addresses" must be used in combination with a "reg" that provides + * the physical address and size of this memory region, for an identity 1:1 + * IOVA mapping to that physical memory. */ if (of_property_present(it.node, "reg")) { err = of_address_to_resource(it.node, 0, &phys); @@ -226,11 +335,11 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list) it.node, err); continue; } - } - - maps = of_get_property(it.node, "iommu-addresses", &size); - if (!maps) + } else { + dev_err(dev, "%pOF: iommu-addresses requires a reg property\n", + it.node); continue; + } end = maps + size / sizeof(__be32); @@ -258,6 +367,9 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list) } type = iommu_resv_region_get_type(dev, &phys, iova, length); + if (type != IOMMU_RESV_DIRECT) + continue; + region = iommu_alloc_resv_region(iova, length, prot, type, GFP_KERNEL); if (region) @@ -265,6 +377,8 @@ void of_iommu_get_resv_regions(struct device *dev, struct list_head *list) } } } + + of_iommu_derive_resv_regions(dev, list); #endif } EXPORT_SYMBOL(of_iommu_get_resv_regions); From fea01fe3a04464cfdbd1bbd38f8e80b56d01ab82 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Sat, 26 Sep 2026 12:04:04 +0530 Subject: [PATCH 0540/1133] FROMLIST: media: iris: Add non-pixel and pixel context bank devices The VPU issues DMA through several SMMU streams, and the hardware does not give every stream the same addressable range. The non-pixel stream cannot address the low 600MB of IOVA space, while the pixel stream can address the full range: +-----------------------------------------------------------+ | non-pixel stream addressable range (600 MB - 3.5 GB) | | 0x25800000 - 0xe0000000 | +-----------------------------------------------------------+ | pixel stream addressable range (0 - 3.5 GB) | | 0x00000000 - 0xe0000000 | +-----------------------------------------------------------+ A single "iommus" property on the video-codec node puts every stream in one IOMMU domain sharing one IOVA allocator, so nothing restricts a non-pixel buffer to avoid 0 to 600MB. Once an allocation lands below that boundary the hardware faults, which shows up as unhandled SMMU page faults and spontaneous reboots: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Now the device tree describes "non-pixel" and "pixel" as separate context bank subnodes, each carrying its own "iommus" stream IDs. Add helper functions to create and clean up devices from these DT subnodes, and call them from iris_probe() and iris_remove(). This applies to the common probe path as it is required for all platforms. Set the context banks before v4l2_device_register() so the DMA plumbing is in place before any video device is visible to userspace, and tear them down on the probe error path and in iris_remove(). Link: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-5-0322ca5dc10c@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia --- drivers/media/platform/qcom/iris/iris_core.h | 4 ++ drivers/media/platform/qcom/iris/iris_probe.c | 71 ++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index 3e4cf652bf39a..2f14d80d25899 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -40,6 +40,8 @@ struct qcom_ubwc_cfg_data; * struct iris_core - holds core parameters valid for all instances * * @dev: reference to device structure + * @np_dev: reference to non-pixel device structure + * @p_dev: reference to pixel device structure * @reg_base: IO memory base address * @irq: iris irq * @v4l2_dev: a holder for v4l2 device structure @@ -86,6 +88,8 @@ struct qcom_ubwc_cfg_data; struct iris_core { struct device *dev; + struct device *np_dev; + struct device *p_dev; void __iomem *reg_base; int irq; struct v4l2_device v4l2_dev; diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 41dec90f3e2be..451c036c3a46d 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -201,6 +201,67 @@ static int iris_reserve_iova_region(struct device *dev, struct dma_iova_state ** return ret; } +static struct device *iris_create_cb_dev(struct iris_core *core, const char *name) +{ + struct platform_device_info plat_dev_info = {}; + struct device_node *child_of_node; + struct platform_device *pdev; + + child_of_node = of_get_child_by_name(core->dev->of_node, name); + if (!child_of_node) + return NULL; + + plat_dev_info.dma_mask = core->iris_platform_data->dma_mask; + plat_dev_info.fwnode = &child_of_node->fwnode; + plat_dev_info.name = child_of_node->name; + plat_dev_info.id = PLATFORM_DEVID_AUTO; + plat_dev_info.parent = core->dev; + + pdev = platform_device_register_full(&plat_dev_info); + of_node_put(child_of_node); + if (IS_ERR(pdev)) + return ERR_CAST(pdev); + + dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); + dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32)); + + return &pdev->dev; +} + +static int iris_init_cb_devs(struct iris_core *core) +{ + struct device *dev; + + dev = iris_create_cb_dev(core, "non-pixel"); + if (IS_ERR(dev)) + return PTR_ERR(dev); + + core->np_dev = dev; + + dev = iris_create_cb_dev(core, "pixel"); + if (IS_ERR(dev)) + goto unreg_np_dev; + + core->p_dev = dev; + + return 0; + +unreg_np_dev: + if (core->np_dev) + platform_device_unregister(to_platform_device(core->np_dev)); + core->np_dev = NULL; + + return PTR_ERR(dev); +} + +static void iris_deinit_cb_devs(struct iris_core *core) +{ + if (core->p_dev) + platform_device_unregister(to_platform_device(core->p_dev)); + if (core->np_dev) + platform_device_unregister(to_platform_device(core->np_dev)); +} + static int iris_register_video_device(struct iris_core *core, enum domain_type type) { struct video_device *vdev; @@ -260,6 +321,8 @@ static void iris_remove(struct platform_device *pdev) v4l2_device_unregister(&core->v4l2_dev); + iris_deinit_cb_devs(core); + iris_unreserve_iova_region(core->dev, core->iova_state); mutex_destroy(&core->lock); @@ -329,10 +392,14 @@ static int iris_probe(struct platform_device *pdev) if (ret) return ret; - ret = v4l2_device_register(dev, &core->v4l2_dev); + ret = iris_init_cb_devs(core); if (ret) goto err_unresv_iova_region; + ret = v4l2_device_register(dev, &core->v4l2_dev); + if (ret) + goto err_cb_deinit; + ret = iris_register_video_device(core, DECODER); if (ret) goto err_v4l2_unreg; @@ -366,6 +433,8 @@ static int iris_probe(struct platform_device *pdev) video_unregister_device(core->vdev_dec); err_v4l2_unreg: v4l2_device_unregister(&core->v4l2_dev); +err_cb_deinit: + iris_deinit_cb_devs(core); err_unresv_iova_region: iris_unreserve_iova_region(dev, core->iova_state); From 5e5dad6466bcae00ef5db90ef4d0475c994a0464 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Sat, 26 Sep 2026 12:04:05 +0530 Subject: [PATCH 0541/1133] FROMLIST: media: iris: Route buffers to the matching context bank device The VPU issues DMA through several SMMU streams, and the hardware does not give every stream the same addressable range. The non-pixel stream cannot address the low 600MB of IOVA space, while the pixel stream can address the full range. Add iris_get_cb_dev(), which maps a buffer type to the owning context bank device. Bitstream and internal buffers (BIN, ARP, COMV, LINE, NON_COMV, PERSIST) belong to the non-pixel device, and uncompressed buffers (DPB, PARTIAL, SCRATCH_1, SCRATCH_2, VPSS) to the pixel device. BUF_INPUT and BUF_OUTPUT depend on direction and are resolved from inst->domain: for a decoder the input is non-pixel and the output pixel, and the other way round for an encoder. Fall back to core->dev whenever the relevant context bank device is absent, so platforms still describing "iommus" on the parent iris node behave exactly as before to maintain backward compatibility. Link: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-6-0322ca5dc10c@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia --- .../media/platform/qcom/iris/iris_buffer.c | 8 ++-- .../media/platform/qcom/iris/iris_hfi_queue.c | 16 ++++---- .../media/platform/qcom/iris/iris_resources.c | 41 +++++++++++++++++++ .../media/platform/qcom/iris/iris_resources.h | 1 + drivers/media/platform/qcom/iris/iris_vidc.c | 4 +- 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index eb8de60c1177f..6e03d13ac1a79 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -531,7 +531,7 @@ static int iris_create_internal_buffer(struct iris_inst *inst, enum iris_buffer_type buffer_type, u32 index) { struct iris_buffers *buffers = &inst->buffers[buffer_type]; - struct iris_core *core = inst->core; + struct device *dev = iris_get_cb_dev(inst, buffer_type); struct iris_buffer *buffer; if (!buffers->size) @@ -547,7 +547,7 @@ static int iris_create_internal_buffer(struct iris_inst *inst, buffer->buffer_size = buffers->size; buffer->dma_attrs = DMA_ATTR_WRITE_COMBINE | DMA_ATTR_NO_KERNEL_MAPPING; - buffer->kvaddr = dma_alloc_attrs(core->dev, buffer->buffer_size, + buffer->kvaddr = dma_alloc_attrs(dev, buffer->buffer_size, &buffer->device_addr, GFP_KERNEL, buffer->dma_attrs); if (!buffer->kvaddr) { kfree(buffer); @@ -650,10 +650,10 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) void iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer) { - struct iris_core *core = inst->core; + struct device *dev = iris_get_cb_dev(inst, buffer->type); list_del(&buffer->list); - dma_free_attrs(core->dev, buffer->buffer_size, buffer->kvaddr, + dma_free_attrs(dev, buffer->buffer_size, buffer->kvaddr, buffer->device_addr, buffer->dma_attrs); kfree(buffer); } diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c index bf6db23b53e21..ce6a682b0f9ad 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c @@ -245,25 +245,26 @@ static void iris_hfi_queue_deinit(struct iris_iface_q_info *iface_q) int iris_hfi_queues_init(struct iris_core *core) { + struct device *dev = core->np_dev ? core->np_dev : core->dev; struct iris_hfi_queue_table_header *q_tbl_hdr; u32 queue_size; /* Iris hardware requires 4K queue alignment */ queue_size = ALIGN((sizeof(*q_tbl_hdr) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ)), SZ_4K); - core->iface_q_table_vaddr = dma_alloc_attrs(core->dev, queue_size, + core->iface_q_table_vaddr = dma_alloc_attrs(dev, queue_size, &core->iface_q_table_daddr, GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); if (!core->iface_q_table_vaddr) { - dev_err(core->dev, "queues alloc and map failed\n"); + dev_err(dev, "queues alloc and map failed\n"); return -ENOMEM; } - core->sfr_vaddr = dma_alloc_attrs(core->dev, SFR_SIZE, + core->sfr_vaddr = dma_alloc_attrs(dev, SFR_SIZE, &core->sfr_daddr, GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); if (!core->sfr_vaddr) { - dev_err(core->dev, "sfr alloc and map failed\n"); - dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr, + dev_err(dev, "sfr alloc and map failed\n"); + dma_free_attrs(dev, queue_size, core->iface_q_table_vaddr, core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); return -ENOMEM; } @@ -291,6 +292,7 @@ int iris_hfi_queues_init(struct iris_core *core) void iris_hfi_queues_deinit(struct iris_core *core) { + struct device *dev = core->np_dev ? core->np_dev : core->dev; u32 queue_size; if (!core->iface_q_table_vaddr) @@ -300,7 +302,7 @@ void iris_hfi_queues_deinit(struct iris_core *core) iris_hfi_queue_deinit(&core->message_queue); iris_hfi_queue_deinit(&core->command_queue); - dma_free_attrs(core->dev, SFR_SIZE, core->sfr_vaddr, + dma_free_attrs(dev, SFR_SIZE, core->sfr_vaddr, core->sfr_daddr, DMA_ATTR_WRITE_COMBINE); core->sfr_vaddr = NULL; @@ -309,7 +311,7 @@ void iris_hfi_queues_deinit(struct iris_core *core) queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ), SZ_4K); - dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr, + dma_free_attrs(dev, queue_size, core->iface_q_table_vaddr, core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); core->iface_q_table_vaddr = NULL; diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c index 883ef7e752915..9dbf209e3d4c0 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.c +++ b/drivers/media/platform/qcom/iris/iris_resources.c @@ -12,6 +12,7 @@ #include #include "iris_core.h" +#include "iris_instance.h" #include "iris_resources.h" #define BW_THRESHOLD 50000 @@ -140,3 +141,43 @@ int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type return 0; } + +struct device *iris_get_cb_dev(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + struct iris_core *core = inst->core; + struct device *dev = NULL; + + switch (buffer_type) { + case BUF_INPUT: + if (inst->domain == DECODER) + dev = core->np_dev; + else + dev = core->p_dev; + break; + case BUF_OUTPUT: + if (inst->domain == DECODER) + dev = core->p_dev; + else + dev = core->np_dev; + break; + case BUF_DPB: + case BUF_PARTIAL: + case BUF_SCRATCH_1: + case BUF_SCRATCH_2: + case BUF_VPSS: + dev = core->p_dev; + break; + case BUF_BIN: + case BUF_ARP: + case BUF_COMV: + case BUF_LINE: + case BUF_NON_COMV: + case BUF_PERSIST: + dev = core->np_dev; + break; + default: + dev_err(core->dev, "invalid buffer type: %d\n", buffer_type); + } + + return dev ? dev : core->dev; +} diff --git a/drivers/media/platform/qcom/iris/iris_resources.h b/drivers/media/platform/qcom/iris/iris_resources.h index 6bfbd2dc6db09..a9a5bddb19c24 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.h +++ b/drivers/media/platform/qcom/iris/iris_resources.h @@ -15,5 +15,6 @@ int iris_unset_icc_bw(struct iris_core *core); int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw); int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type clk_type); int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk_type); +struct device *iris_get_cb_dev(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 05aab6e3005d5..f41a00cf698af 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -126,7 +126,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ src_vq->drv_priv = inst; src_vq->buf_struct_size = sizeof(struct iris_buffer); src_vq->min_reqbufs_allocation = MIN_BUFFERS; - src_vq->dev = inst->core->dev; + src_vq->dev = iris_get_cb_dev(inst, BUF_INPUT); src_vq->lock = &inst->ctx_q_lock; ret = vb2_queue_init(src_vq); if (ret) @@ -140,7 +140,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ dst_vq->drv_priv = inst; dst_vq->buf_struct_size = sizeof(struct iris_buffer); dst_vq->min_reqbufs_allocation = MIN_BUFFERS; - dst_vq->dev = inst->core->dev; + dst_vq->dev = iris_get_cb_dev(inst, BUF_OUTPUT); dst_vq->lock = &inst->ctx_q_lock; return vb2_queue_init(dst_vq); From 3a9788fe4a186b75998af98856474b081d2924a4 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Sat, 26 Sep 2026 12:04:06 +0530 Subject: [PATCH 0542/1133] FROMLIST: media: iris: Skip DMA mask setup when the core device has no IOMMU Once the streams are described as context bank subnodes, the "iommus" property no longer sits on the parent iris node. That device then has no IOMMU domain of its own and never performs DMA directly, so calling dma_set_mask_and_coherent() on it is meaningless, and on a device with no IOMMU it can fail and abort probe. Set the DMA mask only when device_iommu_mapped() reports an IOMMU on the core device. Platforms that have not been converted still carry "iommus" on the parent node and keep the existing setup. For converted platforms the mask is applied to each context bank device instead, in iris_create_cb_dev(). Link: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-7-0322ca5dc10c@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Tested-by: Daniel J Blueman --- drivers/media/platform/qcom/iris/iris_probe.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 451c036c3a46d..2b9c70be71b8f 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -412,9 +412,11 @@ static int iris_probe(struct platform_device *pdev) dma_mask = core->iris_platform_data->dma_mask; - ret = dma_set_mask_and_coherent(dev, dma_mask); - if (ret) - goto err_vdev_unreg_enc; + if (device_iommu_mapped(dev)) { + ret = dma_set_mask_and_coherent(dev, dma_mask); + if (ret) + goto err_vdev_unreg_enc; + } dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32)); From dddd2a27116f253a177781a09bcb042a43958f04 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Thu, 17 Sep 2026 10:30:20 +0530 Subject: [PATCH 0543/1133] FROMLIST: dt-bindings: media: qcom,glymur-iris: Add glymur video codec Add device tree binding for the Qualcomm Glymur Iris video codec. Glymur is a new generation of video IP that introduces a dual-core architecture. The second core brings its own power domain, clocks, and reset lines, requiring additional power domains and clocks in the power sequence. The current maxItems constraints for clocks, power-domains and non-pixel iommus in the common venus schema were sized for platforms available at the time of authoring. The glymur platform introduces a dual core architecture that requires more clocks and power domains, exceeding these limits. Raise maxItems for clocks, clock-names, power-domains, power-domain-names and non-pixel iommus to accommodate glymur platform. The glymur platform specific schema have fixed constraints for these properties, so the common schema only acts as an upper bound. Since the common schema now only acts as an upper bound, add explicit maxItems overrides for the non-pixel iommus in the qcom,sm8550-iris and qcom,sm8750-iris schemas to keep the fixed constraints as before. Link: https://lore.kernel.org/all/20260917-glymur-v11-1-e0c8bc914742@oss.qualcomm.com/ Signed-off-by: Vishnu Reddy --- .../bindings/media/qcom,glymur-iris.yaml | 218 ++++++++++++++++++ .../bindings/media/qcom,sm8550-iris.yaml | 6 + .../bindings/media/qcom,sm8750-iris.yaml | 6 + .../bindings/media/qcom,venus-common.yaml | 11 +- 4 files changed, 236 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml b/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml new file mode 100644 index 0000000000000..de4792f3b658a --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml @@ -0,0 +1,218 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,glymur-iris.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Glymur SoC Iris video encoder and decoder + +maintainers: + - Vishnu Reddy + +description: + The Iris video processing unit on Qualcomm Glymur SoC is a video encode and + decode accelerator. + +properties: + compatible: + const: qcom,glymur-iris + + clocks: + maxItems: 9 + + clock-names: + items: + - const: core_iface + - const: core + - const: vcodec0_core + - const: vcodec0_iface + - const: core_freerun + - const: vcodec0_core_freerun + - const: vcodec1_iface + - const: vcodec1_core + - const: vcodec1_core_freerun + + dma-coherent: true + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: cpu-cfg + - const: video-mem + + non-pixel: + type: object + properties: + iommus: + maxItems: 3 + + operating-points-v2: true + opp-table: + type: object + + power-domains: + maxItems: 5 + + power-domain-names: + items: + - const: venus + - const: vcodec0 + - const: mxc + - const: mmcx + - const: vcodec1 + + resets: + maxItems: 6 + + reset-names: + items: + - const: core_bus + - const: vcodec0_bus + - const: core + - const: vcodec0_core + - const: vcodec1_bus + - const: vcodec1_core + +required: + - clocks + - clock-names + - compatible + - dma-coherent + - interconnects + - interconnect-names + - power-domains + - power-domain-names + - resets + - reset-names + +allOf: + - $ref: qcom,venus-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + + video-codec@aa00000 { + compatible = "qcom,glymur-iris"; + reg = <0x0aa00000 0xf0000>; + + clocks = <&gcc_video_axi0c_clk>, + <&videocc_mvs0c_clk>, + <&videocc_mvs0_clk>, + <&gcc_video_axi0_clk>, + <&videocc_mvs0c_freerun_clk>, + <&videocc_mvs0_freerun_clk>, + <&gcc_video_axi1_clk>, + <&videocc_mvs1_clk>, + <&videocc_mvs1_freerun_clk>; + clock-names = "core_iface", + "core", + "vcodec0_core", + "vcodec0_iface", + "core_freerun", + "vcodec0_core_freerun", + "vcodec1_iface", + "vcodec1_core", + "vcodec1_core_freerun"; + + dma-coherent; + + interconnects = <&hsc_noc_master_appss_proc &config_noc_slave_venus_cfg>, + <&mmss_noc_master_video &mc_virt_slave_ebi1>; + interconnect-names = "cpu-cfg", + "video-mem"; + + interrupts = ; + + memory-region = <&video_mem>; + + operating-points-v2 = <&iris_opp_table>; + + power-domains = <&videocc_mvs0c_gdsc>, + <&videocc_mvs0_gdsc>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc_mvs1_gdsc>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vcodec1"; + + resets = <&gcc_video_axi0c_clk_ares>, + <&gcc_video_axi0_clk_ares>, + <&videocc_mvs0c_freerun_clk_ares>, + <&videocc_mvs0_freerun_clk_ares>, + <&gcc_video_axi1_clk_ares>, + <&videocc_mvs1_freerun_clk_ares>; + reset-names = "core_bus", + "vcodec0_bus", + "core", + "vcodec0_core", + "vcodec1_bus", + "vcodec1_core"; + + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0xffe00000>; + + non-pixel { + iommus = <&apps_smmu 0x1940 0x0000>, + <&apps_smmu 0x1944 0x0000>, + <&apps_smmu 0x19e0 0x0000>; + iommu-ranges = <0x25800000 0xda600000>; + }; + + pixel { + iommus = <&apps_smmu 0x1943 0x0000>; + }; + + video-firmware { + iommus = <&apps_smmu 0x19e2 0x0000>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000 240000000 360000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 507000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-366000000 { + opp-hz = /bits/ 64 <366000000 366000000 549000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_nom>; + }; + + opp-533333334 { + opp-hz = /bits/ 64 <533333334 533333334 800000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo>; + }; + + opp-655000000 { + opp-hz = /bits/ 64 <655000000 655000000 982000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo_l1>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml index 6ee9d23554cff..81d35be565f9a 100644 --- a/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml @@ -81,6 +81,12 @@ properties: iommus: maxItems: 2 + non-pixel: + type: object + properties: + iommus: + maxItems: 1 + dma-coherent: true memory-region: diff --git a/Documentation/devicetree/bindings/media/qcom,sm8750-iris.yaml b/Documentation/devicetree/bindings/media/qcom,sm8750-iris.yaml index b6d5ded1aae6a..6c1ed1b9fdde4 100644 --- a/Documentation/devicetree/bindings/media/qcom,sm8750-iris.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sm8750-iris.yaml @@ -43,6 +43,12 @@ properties: iommus: maxItems: 2 + non-pixel: + type: object + properties: + iommus: + maxItems: 1 + operating-points-v2: true opp-table: type: object diff --git a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml index 6c205077bea4d..2283a5112e1ed 100644 --- a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml +++ b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml @@ -20,11 +20,11 @@ properties: clocks: minItems: 3 - maxItems: 7 + maxItems: 9 clock-names: minItems: 3 - maxItems: 7 + maxItems: 9 firmware-name: maxItems: 1 @@ -44,11 +44,11 @@ properties: power-domains: minItems: 1 - maxItems: 4 + maxItems: 5 power-domain-names: minItems: 1 - maxItems: 4 + maxItems: 5 '#address-cells': const: 1 @@ -67,7 +67,8 @@ properties: properties: iommus: - maxItems: 1 + minItems: 1 + maxItems: 3 iommu-ranges: maxItems: 1 required: From ed453e2810e881de2615f3c9778178f71ca2b893 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Thu, 17 Sep 2026 10:30:22 +0530 Subject: [PATCH 0544/1133] FROMLIST: media: iris: Replace enum-indexed clock and power domain tables with per-block structures As new platforms are added, the platform_clk_type and platform_pm_domain_type enums keep growing. Every new clock or power domain requires a new enum entry, and every enable/disable path has to loop through the clock table to find the right clock by enum value, adding overhead and boilerplate on each path. The enum index space is also shared across all hardware blocks. On the Glymur platform, the VPP0 index for VPU4x and the VCODEC1 index clash, making it error-prone to extend support without breaking existing platforms. Replace the flat tables and enum-based lookups with iris_power_domain, which bundles a power domain device and its associated clocks together per hardware block. Platform data describes each block via iris_power_domain_data, and the enable and disable helpers operate directly on an iris_power_domain instance, removing the need for any index lookup at runtime. Link: https://lore.kernel.org/all/20260917-glymur-v11-3-e0c8bc914742@oss.qualcomm.com/ Signed-off-by: Vishnu Reddy Reviewed-by: Vikash Garodia Reviewed-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_core.h | 23 ++- .../platform/qcom/iris/iris_platform_common.h | 42 ++---- .../platform/qcom/iris/iris_platform_sc7280.h | 28 +++- .../platform/qcom/iris/iris_platform_sm8250.h | 26 +++- .../platform/qcom/iris/iris_platform_sm8550.h | 26 +++- .../platform/qcom/iris/iris_platform_sm8750.h | 29 +++- .../platform/qcom/iris/iris_platform_vpu2.c | 20 +-- .../platform/qcom/iris/iris_platform_vpu3x.c | 32 ++-- .../qcom/iris/iris_platform_vpu_ar50lt.c | 37 +++-- .../qcom/iris/iris_platform_x1p42100.h | 27 +++- drivers/media/platform/qcom/iris/iris_probe.c | 137 ++++++++++++++++-- .../media/platform/qcom/iris/iris_resources.c | 81 +++++------ .../media/platform/qcom/iris/iris_resources.h | 8 +- drivers/media/platform/qcom/iris/iris_vpu3x.c | 37 +---- drivers/media/platform/qcom/iris/iris_vpu4x.c | 137 +++--------------- .../platform/qcom/iris/iris_vpu_ar50lt.c | 71 +-------- .../platform/qcom/iris/iris_vpu_common.c | 98 ++----------- 17 files changed, 376 insertions(+), 483 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index 2f14d80d25899..d2ebead659280 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -17,6 +17,13 @@ #include "iris_resources.h" #include "iris_state.h" +struct iris_power_domain { + struct device **dev; + unsigned int pd_cnt; + struct clk_bulk_data *clocks; + unsigned int clk_cnt; +}; + struct icc_info { const char *name; u32 bw_min_kbps; @@ -53,10 +60,12 @@ struct qcom_ubwc_cfg_data; * @iris_vb2_ops: iris vb2 ops * @icc_tbl: table of iris interconnects * @icc_count: count of iris interconnects - * @pmdomain_tbl: table of iris power domains + * @ctrl: power domain and clocks for the controller + * @vcodec: power domain and clocks for the vcodec + * @vcodec_vpp0: power domain and clocks for the vcodec VPP0 + * @vcodec_vpp1: power domain and clocks for the vcodec VPP1 + * @apv: power domain and clocks for the APV hardware block * @opp_pmdomain_tbl: table of opp power domains - * @clock_tbl: table of iris clocks - * @clk_count: count of iris clocks * @resets: table of iris reset clocks * @controller_resets: table of controller reset clocks * @iris_platform_data: a structure for platform data @@ -101,10 +110,12 @@ struct iris_core { const struct vb2_ops *iris_vb2_ops; struct icc_bulk_data *icc_tbl; u32 icc_count; - struct dev_pm_domain_list *pmdomain_tbl; + struct iris_power_domain *ctrl; + struct iris_power_domain *vcodec; + struct iris_power_domain *vcodec_vpp0; + struct iris_power_domain *vcodec_vpp1; + struct iris_power_domain *apv; struct dev_pm_domain_list *opp_pmdomain_tbl; - struct clk_bulk_data *clock_tbl; - u32 clk_count; struct reset_control_bulk_data *resets; struct reset_control_bulk_data *controller_resets; const struct iris_platform_data *iris_platform_data; diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index cddab9a9c375a..49a3dcec7546d 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -72,27 +72,6 @@ extern const struct iris_platform_data sm8650_data; extern const struct iris_platform_data sm8750_data; extern const struct iris_platform_data x1p42100_data; -enum platform_clk_type { - IRIS_AXI_CLK, /* AXI0 in case of platforms with multiple AXI clocks */ - IRIS_CTRL_CLK, - IRIS_AHB_CLK, - IRIS_HW_CLK, - IRIS_HW_AHB_CLK, - IRIS_AXI1_CLK, - IRIS_CTRL_FREERUN_CLK, - IRIS_HW_FREERUN_CLK, - IRIS_BSE_HW_CLK, - IRIS_VPP0_HW_CLK, - IRIS_VPP1_HW_CLK, - IRIS_APV_HW_CLK, - IRIS_THROTTLE_CLK, -}; - -struct platform_clk_data { - enum platform_clk_type clk_type; - const char *clk_name; -}; - struct tz_cp_config { u32 cp_start; u32 cp_size; @@ -256,12 +235,11 @@ struct icc_vote_data { u32 fps; }; -enum platform_pm_domain_type { - IRIS_CTRL_POWER_DOMAIN, - IRIS_HW_POWER_DOMAIN, - IRIS_VPP0_HW_POWER_DOMAIN, - IRIS_VPP1_HW_POWER_DOMAIN, - IRIS_APV_HW_POWER_DOMAIN, +struct iris_power_domain_data { + const char * const *pd_names; + unsigned int pd_cnt; + const char * const *clk_names; + unsigned int clk_cnt; }; struct iris_firmware_data { @@ -327,13 +305,14 @@ struct iris_platform_data { unsigned int icc_tbl_size; const struct bw_info *bw_tbl_dec; unsigned int bw_tbl_dec_size; - const char * const *pmdomain_tbl; - unsigned int pmdomain_tbl_size; + const struct iris_power_domain_data *ctrl_data; + const struct iris_power_domain_data *vcodec_data; + const struct iris_power_domain_data *vcodec_vpp0_data; + const struct iris_power_domain_data *vcodec_vpp1_data; + const struct iris_power_domain_data *apv_data; const char * const *opp_pd_tbl; unsigned int opp_pd_tbl_size; - const struct platform_clk_data *clk_tbl; const char * const *opp_clk_tbl; - unsigned int clk_tbl_size; const char * const *clk_rst_tbl; unsigned int clk_rst_tbl_size; const char * const *controller_rst_tbl; @@ -351,6 +330,7 @@ struct iris_platform_data { u32 wd_intr_mask; u32 icc_ib_multiplier; u32 max_session_count; + u32 num_cores; /* max number of macroblocks per frame supported */ u32 max_core_mbpf; /* max number of macroblocks per second supported */ diff --git a/drivers/media/platform/qcom/iris/iris_platform_sc7280.h b/drivers/media/platform/qcom/iris/iris_platform_sc7280.h index 0ec8f334df670..f19547a8a51de 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sc7280.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sc7280.h @@ -15,12 +15,28 @@ static const struct bw_info sc7280_bw_table_dec[] = { static const char * const sc7280_opp_pd_table[] = { "cx" }; -static const struct platform_clk_data sc7280_clk_table[] = { - {IRIS_CTRL_CLK, "core" }, - {IRIS_AXI_CLK, "iface" }, - {IRIS_AHB_CLK, "bus" }, - {IRIS_HW_CLK, "vcodec_core" }, - {IRIS_HW_AHB_CLK, "vcodec_bus" }, +static const struct iris_power_domain_data sc7280_ctrl_data = { + .pd_names = (const char *[]) { + "venus", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "iface", "core", "bus", + }, + .clk_cnt = 3, +}; + +static const struct iris_power_domain_data sc7280_vcodec_data[] = { + { + .pd_names = (const char *[]) { + "vcodec0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec_core", "vcodec_bus", + }, + .clk_cnt = 2, + }, }; static const char * const sc7280_opp_clk_table[] = { diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.h b/drivers/media/platform/qcom/iris/iris_platform_sm8250.h index 50306043eb8ec..7674cf9a330f7 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.h @@ -15,10 +15,28 @@ static const struct bw_info sm8250_bw_table_dec[] = { static const char * const sm8250_opp_pd_table[] = { "mx", "mmcx" }; -static const struct platform_clk_data sm8250_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, +static const struct iris_power_domain_data sm8250_ctrl_data = { + .pd_names = (const char *[]) { + "venus", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "iface", "core", + }, + .clk_cnt = 2, +}; + +static const struct iris_power_domain_data sm8250_vcodec_data[] = { + { + .pd_names = (const char *[]) { + "vcodec0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec0_core", + }, + .clk_cnt = 1, + }, }; static const char * const sm8250_opp_clk_table[] = { diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8550.h b/drivers/media/platform/qcom/iris/iris_platform_sm8550.h index 3c9dae995bb24..71de71a75e956 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8550.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8550.h @@ -8,10 +8,28 @@ static const char * const sm8550_clk_reset_table[] = { "bus" }; -static const struct platform_clk_data sm8550_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, +static const struct iris_power_domain_data sm8550_ctrl_data = { + .pd_names = (const char *[]) { + "venus", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "iface", "core", + }, + .clk_cnt = 2, +}; + +static const struct iris_power_domain_data sm8550_vcodec_data[] = { + { + .pd_names = (const char *[]) { + "vcodec0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec0_core", + }, + .clk_cnt = 1, + }, }; static struct platform_inst_caps platform_inst_cap_sm8550 = { diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8750.h b/drivers/media/platform/qcom/iris/iris_platform_sm8750.h index 719056656a5ba..45ab78781f4a5 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8750.h +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8750.h @@ -10,13 +10,28 @@ static const char * const sm8750_clk_reset_table[] = { "bus0", "bus1", "core", "vcodec0_core" }; -static const struct platform_clk_data sm8750_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, - {IRIS_AXI1_CLK, "iface1" }, - {IRIS_CTRL_FREERUN_CLK, "core_freerun" }, - {IRIS_HW_FREERUN_CLK, "vcodec0_core_freerun" }, +static const struct iris_power_domain_data sm8750_ctrl_data = { + .pd_names = (const char *[]) { + "venus", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "iface1", "core_freerun", "core", + }, + .clk_cnt = 3, +}; + +static const struct iris_power_domain_data sm8750_vcodec_data[] = { + { + .pd_names = (const char *[]) { + "vcodec0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "iface", "vcodec0_core_freerun", "vcodec0_core", + }, + .clk_cnt = 3, + }, }; #endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c index becbe37765449..de504fe1abec0 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c @@ -68,8 +68,6 @@ static const struct icc_info iris_icc_info_vpu2[] = { static const char * const iris_clk_reset_table_vpu2[] = { "bus", "core" }; -static const char * const iris_pmdomain_table_vpu2[] = { "venus", "vcodec0" }; - static const struct tz_cp_config tz_cp_config_vpu2[] = { { .cp_start = 0, @@ -86,12 +84,10 @@ const struct iris_platform_data milos_data = { .icc_tbl_size = ARRAY_SIZE(iris_icc_info_milos), .bw_tbl_dec = sm8250_bw_table_dec, .bw_tbl_dec_size = ARRAY_SIZE(sm8250_bw_table_dec), - .pmdomain_tbl = iris_pmdomain_table_vpu2, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu2), + .ctrl_data = &sm8250_ctrl_data, + .vcodec_data = sm8250_vcodec_data, .opp_pd_tbl = milos_opp_pd_table, .opp_pd_tbl_size = ARRAY_SIZE(milos_opp_pd_table), - .clk_tbl = sm8250_clk_table, - .clk_tbl_size = ARRAY_SIZE(sm8250_clk_table), .opp_clk_tbl = sm8250_opp_clk_table, .clk_rst_tbl = iris_clk_reset_table_vpu2, .clk_rst_tbl_size = ARRAY_SIZE(iris_clk_reset_table_vpu2), @@ -115,12 +111,10 @@ const struct iris_platform_data sc7280_data = { .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu2), .bw_tbl_dec = sc7280_bw_table_dec, .bw_tbl_dec_size = ARRAY_SIZE(sc7280_bw_table_dec), - .pmdomain_tbl = iris_pmdomain_table_vpu2, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu2), + .ctrl_data = &sc7280_ctrl_data, + .vcodec_data = sc7280_vcodec_data, .opp_pd_tbl = sc7280_opp_pd_table, .opp_pd_tbl_size = ARRAY_SIZE(sc7280_opp_pd_table), - .clk_tbl = sc7280_clk_table, - .clk_tbl_size = ARRAY_SIZE(sc7280_clk_table), .opp_clk_tbl = sc7280_opp_clk_table, /* Upper bound of DMA address range */ .dma_mask = 0xe0000000 - 1, @@ -149,12 +143,10 @@ const struct iris_platform_data sm8250_data = { .clk_rst_tbl_size = ARRAY_SIZE(iris_clk_reset_table_vpu2), .bw_tbl_dec = sm8250_bw_table_dec, .bw_tbl_dec_size = ARRAY_SIZE(sm8250_bw_table_dec), - .pmdomain_tbl = iris_pmdomain_table_vpu2, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu2), + .ctrl_data = &sm8250_ctrl_data, + .vcodec_data = sm8250_vcodec_data, .opp_pd_tbl = sm8250_opp_pd_table, .opp_pd_tbl_size = ARRAY_SIZE(sm8250_opp_pd_table), - .clk_tbl = sm8250_clk_table, - .clk_tbl_size = ARRAY_SIZE(sm8250_clk_table), .opp_clk_tbl = sm8250_opp_clk_table, /* Upper bound of DMA address range */ .dma_mask = 0xe0000000 - 1, diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index e963cb116313f..15e69d7e9c7b6 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -69,8 +69,6 @@ static const struct bw_info iris_bw_table_dec_vpu3x[] = { { ((1920 * 1080) / 256) * 30, 294000 }, }; -static const char * const iris_pmdomain_table_vpu3x[] = { "venus", "vcodec0" }; - static const char * const iris_opp_pd_table_vpu3x[] = { "mxc", "mmcx" }; static const char * const iris_opp_clk_table_vpu3x[] = { @@ -100,12 +98,10 @@ const struct iris_platform_data qcs8300_data = { .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .ctrl_data = &sm8550_ctrl_data, + .vcodec_data = sm8550_vcodec_data, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), - .clk_tbl = sm8550_clk_table, - .clk_tbl_size = ARRAY_SIZE(sm8550_clk_table), .opp_clk_tbl = iris_opp_clk_table_vpu3x, /* Upper bound of DMA address range */ .dma_mask = 0xe0000000 - 1, @@ -132,12 +128,10 @@ const struct iris_platform_data sm8550_data = { .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .ctrl_data = &sm8550_ctrl_data, + .vcodec_data = sm8550_vcodec_data, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), - .clk_tbl = sm8550_clk_table, - .clk_tbl_size = ARRAY_SIZE(sm8550_clk_table), .opp_clk_tbl = iris_opp_clk_table_vpu3x, /* Upper bound of DMA address range */ .dma_mask = 0xe0000000 - 1, @@ -172,12 +166,10 @@ const struct iris_platform_data sm8650_data = { .controller_rst_tbl_size = ARRAY_SIZE(sm8650_controller_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .ctrl_data = &sm8550_ctrl_data, + .vcodec_data = sm8550_vcodec_data, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), - .clk_tbl = sm8550_clk_table, - .clk_tbl_size = ARRAY_SIZE(sm8550_clk_table), .opp_clk_tbl = iris_opp_clk_table_vpu3x, /* Upper bound of DMA address range */ .dma_mask = 0xe0000000 - 1, @@ -204,12 +196,10 @@ const struct iris_platform_data sm8750_data = { .clk_rst_tbl_size = ARRAY_SIZE(sm8750_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .ctrl_data = &sm8750_ctrl_data, + .vcodec_data = sm8750_vcodec_data, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), - .clk_tbl = sm8750_clk_table, - .clk_tbl_size = ARRAY_SIZE(sm8750_clk_table), .opp_clk_tbl = iris_opp_clk_table_vpu3x, /* Upper bound of DMA address range */ .dma_mask = 0xe0000000 - 1, @@ -242,12 +232,10 @@ const struct iris_platform_data x1p42100_data = { .clk_rst_tbl_size = ARRAY_SIZE(sm8550_clk_reset_table), .bw_tbl_dec = iris_bw_table_dec_vpu3x, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), - .pmdomain_tbl = iris_pmdomain_table_vpu3x, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_vpu3x), + .ctrl_data = &x1p42100_ctrl_data, + .vcodec_data = x1p42100_vcodec_data, .opp_pd_tbl = iris_opp_pd_table_vpu3x, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), - .clk_tbl = x1p42100_clk_table, - .clk_tbl_size = ARRAY_SIZE(x1p42100_clk_table), .opp_clk_tbl = x1p42100_opp_clk_table, /* Upper bound of DMA address range */ .dma_mask = 0xe0000000 - 1, diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c index 43460b82ae77a..2eda205171ac1 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c @@ -43,17 +43,30 @@ static const struct icc_info iris_icc_info_ar50lt[] = { { "video-mem", 1000, 6500000 }, }; -static const char * const iris_pmdomain_table_ar50lt[] = { "venus", "vcodec0" }; - static const char * const iris_opp_pd_table_ar50lt[] = { "cx" }; -static const struct platform_clk_data iris_clk_table_ar50lt[] = { - {IRIS_CTRL_CLK, "core" }, - {IRIS_AXI_CLK, "iface" }, - {IRIS_AHB_CLK, "bus" }, - {IRIS_HW_CLK, "vcodec0_core" }, - {IRIS_HW_AHB_CLK, "vcodec0_bus" }, - {IRIS_THROTTLE_CLK, "throttle" }, +static const struct iris_power_domain_data ar50lt_ctrl_data = { + .pd_names = (const char *[]) { + "venus", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "core", "iface", "bus", + }, + .clk_cnt = 3, +}; + +static const struct iris_power_domain_data ar50lt_vcodec_data[] = { + { + .pd_names = (const char *[]) { + "vcodec0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec0_core", "vcodec0_bus", "throttle", + }, + .clk_cnt = 3, + }, }; static const char * const iris_opp_clk_table_ar50lt[] = { @@ -91,12 +104,10 @@ const struct iris_platform_data qcm2290_data = { .icc_tbl_size = ARRAY_SIZE(iris_icc_info_ar50lt), .bw_tbl_dec = iris_bw_table_dec_ar50lt, .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_ar50lt), - .pmdomain_tbl = iris_pmdomain_table_ar50lt, - .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_ar50lt), + .ctrl_data = &ar50lt_ctrl_data, + .vcodec_data = ar50lt_vcodec_data, .opp_pd_tbl = iris_opp_pd_table_ar50lt, .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_ar50lt), - .clk_tbl = iris_clk_table_ar50lt, - .clk_tbl_size = ARRAY_SIZE(iris_clk_table_ar50lt), .opp_clk_tbl = iris_opp_clk_table_ar50lt, /* Upper bound of DMA address range */ .dma_mask = 0xe0000000 - 1, diff --git a/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h b/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h index d89acfbc1233d..3444c1c3012b5 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h +++ b/drivers/media/platform/qcom/iris/iris_platform_x1p42100.h @@ -6,11 +6,28 @@ #ifndef __IRIS_PLATFORM_X1P42100_H__ #define __IRIS_PLATFORM_X1P42100_H__ -static const struct platform_clk_data x1p42100_clk_table[] = { - {IRIS_AXI_CLK, "iface" }, - {IRIS_CTRL_CLK, "core" }, - {IRIS_HW_CLK, "vcodec0_core" }, - {IRIS_BSE_HW_CLK, "vcodec0_bse" }, +static const struct iris_power_domain_data x1p42100_ctrl_data = { + .pd_names = (const char *[]) { + "venus", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "iface", "core", + }, + .clk_cnt = 2, +}; + +static const struct iris_power_domain_data x1p42100_vcodec_data[] = { + { + .pd_names = (const char *[]) { + "vcodec0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec0_core", "vcodec0_bse", + }, + .clk_cnt = 2, + }, }; static const char *const x1p42100_opp_clk_table[] = { diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 2b9c70be71b8f..acf73a24b9f96 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -39,15 +39,45 @@ static int iris_init_icc(struct iris_core *core) return devm_of_icc_bulk_get(core->dev, core->icc_count, core->icc_tbl); } -static int iris_init_power_domains(struct iris_core *core) +static int iris_init_power_domains_per_block(struct iris_core *core, + struct iris_power_domain *pd, + const struct iris_power_domain_data *pd_data) { - int ret; + struct dev_pm_domain_attach_data iris_pd_data = {}; + struct dev_pm_domain_list *pmdomain_tbl; + int ret, i; - struct dev_pm_domain_attach_data iris_pd_data = { - .pd_names = core->iris_platform_data->pmdomain_tbl, - .num_pd_names = core->iris_platform_data->pmdomain_tbl_size, - .pd_flags = PD_FLAG_NO_DEV_LINK, - }; + if (!pd_data->pd_cnt) + return -EINVAL; + + iris_pd_data.pd_names = pd_data->pd_names; + iris_pd_data.num_pd_names = pd_data->pd_cnt; + iris_pd_data.pd_flags = PD_FLAG_NO_DEV_LINK; + + ret = devm_pm_domain_attach_list(core->dev, &iris_pd_data, &pmdomain_tbl); + if (ret < 0) + return ret; + + pd->pd_cnt = pmdomain_tbl->num_pds; + + if (pd->pd_cnt != pd_data->pd_cnt) + return -EINVAL; + + pd->dev = devm_kzalloc(core->dev, pd->pd_cnt * sizeof(*pd->dev), GFP_KERNEL); + if (!pd->dev) + return -ENOMEM; + + for (i = 0; i < pd->pd_cnt; i++) + pd->dev[i] = pmdomain_tbl->pd_devs[i]; + + return 0; +} + +static int iris_init_power_domains(struct iris_core *core) +{ + const struct iris_platform_data *plat = core->iris_platform_data; + unsigned int num_cores = max(plat->num_cores, 1); + int i, ret; struct dev_pm_domain_attach_data iris_opp_pd_data = { .pd_names = core->iris_platform_data->opp_pd_tbl, @@ -60,10 +90,57 @@ static int iris_init_power_domains(struct iris_core *core) .config_clks = dev_pm_opp_config_clks_simple, }; - ret = devm_pm_domain_attach_list(core->dev, &iris_pd_data, &core->pmdomain_tbl); - if (ret < 0) + core->ctrl = devm_kzalloc(core->dev, sizeof(*core->ctrl), GFP_KERNEL); + if (!core->ctrl) + return -ENOMEM; + + ret = iris_init_power_domains_per_block(core, core->ctrl, plat->ctrl_data); + if (ret) return ret; + core->vcodec = devm_kzalloc(core->dev, num_cores * sizeof(*core->vcodec), GFP_KERNEL); + if (!core->vcodec) + return -ENOMEM; + + for (i = 0; i < num_cores; i++) { + ret = iris_init_power_domains_per_block(core, &core->vcodec[i], + &plat->vcodec_data[i]); + if (ret) + return ret; + } + + if (plat->vcodec_vpp0_data) { + core->vcodec_vpp0 = devm_kzalloc(core->dev, sizeof(*core->vcodec_vpp0), GFP_KERNEL); + if (!core->vcodec_vpp0) + return -ENOMEM; + + ret = iris_init_power_domains_per_block(core, core->vcodec_vpp0, + plat->vcodec_vpp0_data); + if (ret) + return ret; + } + + if (plat->vcodec_vpp1_data) { + core->vcodec_vpp1 = devm_kzalloc(core->dev, sizeof(*core->vcodec_vpp1), GFP_KERNEL); + if (!core->vcodec_vpp1) + return -ENOMEM; + + ret = iris_init_power_domains_per_block(core, core->vcodec_vpp1, + plat->vcodec_vpp1_data); + if (ret) + return ret; + } + + if (plat->apv_data) { + core->apv = devm_kzalloc(core->dev, sizeof(*core->apv), GFP_KERNEL); + if (!core->apv) + return -ENOMEM; + + ret = iris_init_power_domains_per_block(core, core->apv, plat->apv_data); + if (ret) + return ret; + } + ret = devm_pm_domain_attach_list(core->dev, &iris_opp_pd_data, &core->opp_pmdomain_tbl); /* backwards compatibility for incomplete ABI SM8250 */ if (ret == -ENODEV && @@ -82,17 +159,51 @@ static int iris_init_power_domains(struct iris_core *core) return devm_pm_opp_of_add_table(core->dev); } +static int iris_init_clocks_per_block(struct iris_core *core, struct iris_power_domain *pd, + const struct iris_power_domain_data *pd_data) +{ + unsigned int i; + + if (!pd_data) + return 0; + + pd->clk_cnt = pd_data->clk_cnt; + pd->clocks = devm_kcalloc(core->dev, pd->clk_cnt, sizeof(*pd->clocks), GFP_KERNEL); + if (!pd->clocks) + return -ENOMEM; + + for (i = 0; i < pd->clk_cnt; i++) + pd->clocks[i].id = pd_data->clk_names[i]; + + return devm_clk_bulk_get(core->dev, pd->clk_cnt, pd->clocks); +} + static int iris_init_clocks(struct iris_core *core) { + const struct iris_platform_data *plat = core->iris_platform_data; + unsigned int num_cores = max(plat->num_cores, 1); + unsigned int i; int ret; - ret = devm_clk_bulk_get_all(core->dev, &core->clock_tbl); - if (ret < 0) + ret = iris_init_clocks_per_block(core, core->ctrl, plat->ctrl_data); + if (ret) return ret; - core->clk_count = ret; + for (i = 0; i < num_cores; i++) { + ret = iris_init_clocks_per_block(core, &core->vcodec[i], &plat->vcodec_data[i]); + if (ret) + return ret; + } - return 0; + ret = iris_init_clocks_per_block(core, core->vcodec_vpp0, plat->vcodec_vpp0_data); + if (ret) + return ret; + + ret = iris_init_clocks_per_block(core, core->vcodec_vpp1, plat->vcodec_vpp1_data); + if (ret) + return ret; + + return iris_init_clocks_per_block(core, core->apv, plat->apv_data); } static int iris_init_reset_table(struct iris_core *core, diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c index 9dbf209e3d4c0..ae31f79c38230 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.c +++ b/drivers/media/platform/qcom/iris/iris_resources.c @@ -9,7 +9,6 @@ #include #include #include -#include #include "iris_core.h" #include "iris_instance.h" @@ -73,73 +72,63 @@ int iris_opp_set_rate(struct device *dev, unsigned long freq) return dev_pm_opp_set_opp(dev, opp); } -int iris_enable_power_domains(struct iris_core *core, struct device *pd_dev) +int iris_enable_power_domain_and_clocks(struct iris_core *core, struct iris_power_domain *pd) { - int ret; + int ret, i; ret = iris_opp_set_rate(core->dev, ULONG_MAX); if (ret) return ret; - return pm_runtime_resume_and_get(pd_dev); -} + for (i = 0; i < pd->pd_cnt; i++) { + ret = pm_runtime_resume_and_get(pd->dev[i]); + if (ret < 0) + goto error; + } -int iris_disable_power_domains(struct iris_core *core, struct device *pd_dev) -{ - int ret; - int pm_ret; + ret = clk_bulk_prepare_enable(pd->clk_cnt, pd->clocks); + if (ret) + goto error; - ret = iris_opp_set_rate(core->dev, 0); + return 0; - pm_ret = pm_runtime_put_sync(pd_dev); - if (!ret) - ret = pm_ret; +error: + iris_opp_set_rate(core->dev, 0); - return ret; -} + while (--i >= 0) + pm_runtime_put_sync(pd->dev[i]); -static struct clk *iris_get_clk_by_type(struct iris_core *core, enum platform_clk_type clk_type) -{ - const struct platform_clk_data *clk_tbl; - u32 clk_cnt, i, j; - - clk_tbl = core->iris_platform_data->clk_tbl; - clk_cnt = core->iris_platform_data->clk_tbl_size; - - for (i = 0; i < clk_cnt; i++) { - if (clk_tbl[i].clk_type == clk_type) { - for (j = 0; core->clock_tbl && j < core->clk_count; j++) { - if (!strcmp(core->clock_tbl[j].id, clk_tbl[i].clk_name)) - return core->clock_tbl[j].clk; - } - } - } - - return NULL; + return ret; } -int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk_type) +void iris_disable_power_domain_and_clocks(struct iris_core *core, struct iris_power_domain *pd) { - struct clk *clock; + int i; - clock = iris_get_clk_by_type(core, clk_type); - if (!clock) - return -ENOENT; + iris_opp_set_rate(core->dev, 0); + clk_bulk_disable_unprepare(pd->clk_cnt, pd->clocks); - return clk_prepare_enable(clock); + for (i = 0; i < pd->pd_cnt; i++) + pm_runtime_put_sync(pd->dev[i]); } -int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type clk_type) +int iris_genpd_set_hwmode(struct iris_power_domain *pd, bool mode) { - struct clk *clock; - - clock = iris_get_clk_by_type(core, clk_type); - if (!clock) - return -EINVAL; + int i, ret; - clk_disable_unprepare(clock); + for (i = 0; i < pd->pd_cnt; i++) { + ret = dev_pm_genpd_set_hwmode(pd->dev[i], mode); + if (ret) + goto error; + } return 0; + +error: + while (--i >= 0) + dev_pm_genpd_set_hwmode(pd->dev[i], !mode); + + return ret; } struct device *iris_get_cb_dev(struct iris_inst *inst, enum iris_buffer_type buffer_type) diff --git a/drivers/media/platform/qcom/iris/iris_resources.h b/drivers/media/platform/qcom/iris/iris_resources.h index a9a5bddb19c24..3e9116d05d558 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.h +++ b/drivers/media/platform/qcom/iris/iris_resources.h @@ -7,14 +7,14 @@ #define __IRIS_RESOURCES_H__ struct iris_core; +struct iris_power_domain; int iris_opp_set_rate(struct device *dev, unsigned long freq); -int iris_enable_power_domains(struct iris_core *core, struct device *pd_dev); -int iris_disable_power_domains(struct iris_core *core, struct device *pd_dev); int iris_unset_icc_bw(struct iris_core *core); int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw); -int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type clk_type); -int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk_type); +int iris_enable_power_domain_and_clocks(struct iris_core *core, struct iris_power_domain *pd); +void iris_disable_power_domain_and_clocks(struct iris_core *core, struct iris_power_domain *pd); +int iris_genpd_set_hwmode(struct iris_power_domain *pd, bool mode); struct device *iris_get_cb_dev(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index c3b760730c981..e1822b0ba4baf 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -205,53 +205,20 @@ static int iris_vpu33_power_off_controller(struct iris_core *core) val &= ~NOC_HALT; writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL); - iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); - disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); + iris_disable_power_domain_and_clocks(core, core->ctrl); return 0; } static int iris_vpu35_power_on_hw(struct iris_core *core) { - int ret; - - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); - if (ret) - return ret; - - ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); - if (ret) - goto err_disable_power; - - ret = iris_prepare_enable_clock(core, IRIS_HW_FREERUN_CLK); - if (ret) - goto err_disable_axi_clk; - - ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); - if (ret) - goto err_disable_hw_free_clk; - - return 0; - -err_disable_hw_free_clk: - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); -err_disable_axi_clk: - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); -err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); - - return ret; + return iris_enable_power_domain_and_clocks(core, core->vcodec); } static void iris_vpu35_power_off_hw(struct iris_core *core) { iris_vpu33_power_off_hardware(core); - - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); } const struct vpu_ops iris_vpu3_ops = { diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c index 90ccdc0d2a076..9d89d3f00acf7 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu4x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c @@ -27,27 +27,24 @@ static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 { int ret; - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], hw_mode); + ret = iris_genpd_set_hwmode(core->vcodec, hw_mode); if (ret) return ret; if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN], hw_mode); + ret = iris_genpd_set_hwmode(core->vcodec_vpp0, hw_mode); if (ret) goto restore_hw_domain_mode; } if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN], hw_mode); + ret = iris_genpd_set_hwmode(core->vcodec_vpp1, hw_mode); if (ret) goto restore_vpp0_domain_mode; } if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) { - ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs - [IRIS_APV_HW_POWER_DOMAIN], hw_mode); + ret = iris_genpd_set_hwmode(core->apv, hw_mode); if (ret) goto restore_vpp1_domain_mode; } @@ -56,37 +53,19 @@ static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 restore_vpp1_domain_mode: if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VPP1_HW_POWER_DOMAIN], - !hw_mode); + iris_genpd_set_hwmode(core->vcodec_vpp1, !hw_mode); restore_vpp0_domain_mode: if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_VPP0_HW_POWER_DOMAIN], - !hw_mode); + iris_genpd_set_hwmode(core->vcodec_vpp0, !hw_mode); restore_hw_domain_mode: - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], !hw_mode); + iris_genpd_set_hwmode(core->vcodec, !hw_mode); return ret; } static int iris_vpu4x_power_on_apv(struct iris_core *core) { - int ret; - - ret = iris_enable_power_domains(core, - core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); - if (ret) - return ret; - - ret = iris_prepare_enable_clock(core, IRIS_APV_HW_CLK); - if (ret) - goto disable_apv_hw_power_domain; - - return 0; - -disable_apv_hw_power_domain: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); - - return ret; + return iris_enable_power_domain_and_clocks(core, core->apv); } static void iris_vpu4x_power_off_apv(struct iris_core *core) @@ -138,8 +117,7 @@ static void iris_vpu4x_power_off_apv(struct iris_core *core) writel(0x0, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); disable_clocks_and_power: - iris_disable_unprepare_clock(core, IRIS_APV_HW_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_APV_HW_POWER_DOMAIN]); + iris_disable_power_domain_and_clocks(core, core->apv); } static void iris_vpu4x_ahb_sync_reset_apv(struct iris_core *core) @@ -158,116 +136,43 @@ static void iris_vpu4x_ahb_sync_reset_hardware(struct iris_core *core) writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); } -static int iris_vpu4x_enable_hardware_clocks(struct iris_core *core, u32 efuse_value) -{ - int ret; - - ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); - if (ret) - return ret; - - ret = iris_prepare_enable_clock(core, IRIS_HW_FREERUN_CLK); - if (ret) - goto disable_axi_clock; - - ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); - if (ret) - goto disable_hw_free_run_clock; - - ret = iris_prepare_enable_clock(core, IRIS_BSE_HW_CLK); - if (ret) - goto disable_hw_clock; - - if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { - ret = iris_prepare_enable_clock(core, IRIS_VPP0_HW_CLK); - if (ret) - goto disable_bse_hw_clock; - } - - if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { - ret = iris_prepare_enable_clock(core, IRIS_VPP1_HW_CLK); - if (ret) - goto disable_vpp0_hw_clock; - } - - return 0; - -disable_vpp0_hw_clock: - if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) - iris_disable_unprepare_clock(core, IRIS_VPP0_HW_CLK); -disable_bse_hw_clock: - iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); -disable_hw_clock: - iris_disable_unprepare_clock(core, IRIS_HW_CLK); -disable_hw_free_run_clock: - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); -disable_axi_clock: - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); - - return ret; -} - -static void iris_vpu4x_disable_hardware_clocks(struct iris_core *core, u32 efuse_value) -{ - if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) - iris_disable_unprepare_clock(core, IRIS_VPP1_HW_CLK); - - if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) - iris_disable_unprepare_clock(core, IRIS_VPP0_HW_CLK); - - iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); -} - static int iris_vpu4x_power_on_hardware(struct iris_core *core) { u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR); int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + ret = iris_enable_power_domain_and_clocks(core, core->vcodec); if (ret) return ret; if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN]); + ret = iris_enable_power_domain_and_clocks(core, core->vcodec_vpp0); if (ret) goto disable_hw_power_domain; } if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN]); + ret = iris_enable_power_domain_and_clocks(core, core->vcodec_vpp1); if (ret) goto disable_vpp0_power_domain; } - ret = iris_vpu4x_enable_hardware_clocks(core, efuse_value); - if (ret) - goto disable_vpp1_power_domain; - if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) { ret = iris_vpu4x_power_on_apv(core); if (ret) - goto disable_hw_clocks; + goto disable_vpp1_power_domain; } return 0; -disable_hw_clocks: - iris_vpu4x_disable_hardware_clocks(core, efuse_value); disable_vpp1_power_domain: if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN]); + iris_disable_power_domain_and_clocks(core, core->vcodec_vpp1); disable_vpp0_power_domain: if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN]); + iris_disable_power_domain_and_clocks(core, core->vcodec_vpp0); disable_hw_power_domain: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_power_domain_and_clocks(core, core->vcodec); return ret; } @@ -335,17 +240,13 @@ static void iris_vpu4x_power_off_hardware(struct iris_core *core) writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); disable_clocks_and_power: - iris_vpu4x_disable_hardware_clocks(core, efuse_value); - if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP1_HW_POWER_DOMAIN]); + iris_disable_power_domain_and_clocks(core, core->vcodec_vpp1); if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs - [IRIS_VPP0_HW_POWER_DOMAIN]); + iris_disable_power_domain_and_clocks(core, core->vcodec_vpp0); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_disable_power_domain_and_clocks(core, core->vcodec); } static int iris_vpu4x_set_hwmode(struct iris_core *core) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c index e084a5b49f2e3..1067e23a93e47 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c @@ -36,85 +36,24 @@ static void iris_vpu_ar50lt_disable_arp(struct iris_core *core) static int iris_vpu_ar50lt_power_off_controller(struct iris_core *core) { - iris_disable_unprepare_clock(core, IRIS_AHB_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); - iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); - + iris_disable_power_domain_and_clocks(core, core->ctrl); return 0; } static void iris_vpu_ar50lt_power_off_hw(struct iris_core *core) { - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], false); - iris_disable_unprepare_clock(core, IRIS_THROTTLE_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_genpd_set_hwmode(core->vcodec, false); + iris_disable_power_domain_and_clocks(core, core->vcodec); } static int iris_vpu_ar50lt_power_on_controller(struct iris_core *core) { - int ret; - - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); - if (ret) - return ret; - - ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK); - if (ret) - goto err_disable_power; - - ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); - if (ret && ret != -ENOENT) - goto err_disable_ctrl_clock; - - ret = iris_prepare_enable_clock(core, IRIS_AHB_CLK); - if (ret) - goto err_disable_axi_clock; - - return 0; - -err_disable_axi_clock: - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); -err_disable_ctrl_clock: - iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); -err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); - - return ret; + return iris_enable_power_domain_and_clocks(core, core->ctrl); } static int iris_vpu_ar50lt_power_on_hw(struct iris_core *core) { - int ret; - - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); - if (ret) - return ret; - - ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); - if (ret) - goto err_disable_power; - - ret = iris_prepare_enable_clock(core, IRIS_HW_AHB_CLK); - if (ret) - goto err_disable_hw_clock; - - ret = iris_prepare_enable_clock(core, IRIS_THROTTLE_CLK); - if (ret) - goto err_disable_hw_ahb_clock; - - return 0; - -err_disable_hw_ahb_clock: - iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); -err_disable_hw_clock: - iris_disable_unprepare_clock(core, IRIS_HW_CLK); -err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); - - return ret; + return iris_enable_power_domain_and_clocks(core, core->vcodec); } const struct vpu_ops iris_vpu_ar50lt_ops = { diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 243bd845349fe..4ea7bfd204df0 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -215,21 +215,15 @@ int iris_vpu_power_off_controller(struct iris_core *core) writel(0x0, core->reg_base + WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG); disable_power: - iris_disable_unprepare_clock(core, IRIS_AHB_CLK); - iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domain_and_clocks(core, core->ctrl); return 0; } void iris_vpu_power_off_hw(struct iris_core *core) { - dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], false); - iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); - iris_disable_unprepare_clock(core, IRIS_HW_CLK); - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); + iris_genpd_set_hwmode(core->vcodec, false); + iris_disable_power_domain_and_clocks(core, core->vcodec); } void iris_vpu_power_off(struct iris_core *core) @@ -248,7 +242,7 @@ int iris_vpu_power_on_controller(struct iris_core *core) u32 rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size; int ret; - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + ret = iris_enable_power_domain_and_clocks(core, core->ctrl); if (ret) return ret; @@ -256,60 +250,17 @@ int iris_vpu_power_on_controller(struct iris_core *core) if (ret) goto err_disable_power; - ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK); - if (ret) - goto err_disable_power; - - ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK); - if (ret) - goto err_disable_axi_clock; - - ret = iris_prepare_enable_clock(core, IRIS_AHB_CLK); - if (ret && ret != -ENOENT) - goto err_disable_ctrl_clock; - return 0; -err_disable_ctrl_clock: - iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); -err_disable_axi_clock: - iris_disable_unprepare_clock(core, IRIS_AXI_CLK); err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domain_and_clocks(core, core->ctrl); return ret; } int iris_vpu_power_on_hw(struct iris_core *core) { - int ret; - - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); - if (ret) - return ret; - - ret = iris_prepare_enable_clock(core, IRIS_HW_CLK); - if (ret) - goto err_disable_power; - - ret = iris_prepare_enable_clock(core, IRIS_HW_AHB_CLK); - if (ret && ret != -ENOENT) - goto err_disable_hw_clock; - - ret = iris_prepare_enable_clock(core, IRIS_BSE_HW_CLK); - if (ret && ret != -ENOENT) - goto err_disable_hw_ahb_clock; - - return 0; - -err_disable_hw_ahb_clock: - iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK); -err_disable_hw_clock: - iris_disable_unprepare_clock(core, IRIS_HW_CLK); -err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]); - - return ret; + return iris_enable_power_domain_and_clocks(core, core->vcodec); } int iris_vpu_set_hwmode(struct iris_core *core) @@ -319,7 +270,7 @@ int iris_vpu_set_hwmode(struct iris_core *core) writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); - return dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], true); + return iris_genpd_set_hwmode(core->vcodec, true); } int iris_vpu_switch_to_hwmode(struct iris_core *core) @@ -380,11 +331,7 @@ int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core) val, val == 0, 200, 2000); disable_power: - iris_disable_unprepare_clock(core, IRIS_CTRL_CLK); - iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); - iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); - - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); + iris_disable_power_domain_and_clocks(core, core->ctrl); reset_control_bulk_reset(clk_rst_tbl_size, core->resets); @@ -393,34 +340,7 @@ int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core) int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core) { - int ret; - - ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); - if (ret) - return ret; - - ret = iris_prepare_enable_clock(core, IRIS_AXI1_CLK); - if (ret) - goto err_disable_power; - - ret = iris_prepare_enable_clock(core, IRIS_CTRL_FREERUN_CLK); - if (ret) - goto err_disable_axi1_clk; - - ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK); - if (ret) - goto err_disable_ctrl_free_clk; - - return 0; - -err_disable_ctrl_free_clk: - iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK); -err_disable_axi1_clk: - iris_disable_unprepare_clock(core, IRIS_AXI1_CLK); -err_disable_power: - iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]); - - return ret; + return iris_enable_power_domain_and_clocks(core, core->ctrl); } void iris_vpu35_vpu4x_program_bootup_registers(struct iris_core *core) From 45c2ed11d8e2fae3274bf6fd23beef92ea72b49a Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Thu, 17 Sep 2026 10:30:23 +0530 Subject: [PATCH 0545/1133] FROMLIST: media: iris: Add power sequence for glymur Glymur platform has two video codec cores: vcodec0 and vcodec1. Both cores share a common clock source (video_cc_mvs0_clk_src) and the same power rails. The clock dividers between the source and the branch clocks are fixed. So when both cores are running, the source clock always runs at the highest frequency requested by either core. Since both cores share the same power rails, the power corner cannot be voted independently. Scaling one core's power corner up or down would directly affect the other, leading to under or over-voting. For these reasons, both cores should voted the clock and power rail must be based on the workload of both cores. Link: https://lore.kernel.org/all/20260917-glymur-v11-4-e0c8bc914742@oss.qualcomm.com/ Reviewed-by: Vikash Garodia Signed-off-by: Vishnu Reddy Reviewed-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_vpu3x.c | 129 +++++++++++++++++- .../platform/qcom/iris/iris_vpu_common.h | 1 + .../qcom/iris/iris_vpu_register_defines.h | 12 ++ 3 files changed, 137 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index e1822b0ba4baf..3851f3642cf33 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -17,14 +17,14 @@ #define NOC_HALT BIT(0) #define AON_WRAPPER_SPARE (AON_BASE_OFFS + 0x28) -static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core) +static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core, u32 pwr_status_bit) { u32 value, pwr_status; value = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS); - pwr_status = value & BIT(1); + pwr_status = value & pwr_status_bit; - return pwr_status ? false : true; + return !pwr_status; } static void iris_vpu3_power_off_hardware(struct iris_core *core) @@ -32,7 +32,7 @@ static void iris_vpu3_power_off_hardware(struct iris_core *core) u32 reg_val = 0, value, i; int ret; - if (iris_vpu3x_hw_power_collapsed(core)) + if (iris_vpu3x_hw_power_collapsed(core, VCODEC0_POWER_STATUS)) goto disable_power; dev_err(core->dev, "video hw is power on\n"); @@ -78,7 +78,7 @@ static void iris_vpu33_power_off_hardware(struct iris_core *core) u32 count = 0; int ret; - if (iris_vpu3x_hw_power_collapsed(core)) + if (iris_vpu3x_hw_power_collapsed(core, VCODEC0_POWER_STATUS)) goto disable_power; dev_err(core->dev, "video hw is power on\n"); @@ -221,6 +221,114 @@ static void iris_vpu35_power_off_hw(struct iris_core *core) iris_vpu33_power_off_hardware(core); } +static void iris_vpu36_power_off_vcodec(struct iris_core *core, u32 core_id) +{ + u32 bridge_hw_reset[] = {CORE_BRIDGE_HW_RESET_DISABLE, VCODEC1_BRIDGE_HW_RESET_DISABLE}; + u32 lpi_status_active[] = {NOC_LPI_STATUS_ACTIVE, NOC_LPI_VCODEC1_STATUS_ACTIVE}; + u32 power_down_prep[] = {REQ_POWER_DOWN_PREP, REQ_VCODEC1_POWER_DOWN_PREP}; + u32 lpi_status_done[] = {NOC_LPI_STATUS_DONE, NOC_LPI_VCODEC1_STATUS_DONE}; + u32 lpi_status_deny[] = {NOC_LPI_STATUS_DENY, NOC_LPI_VCODEC1_STATUS_DENY}; + u32 bridge_sw_reset[] = {CORE_BRIDGE_SW_RESET, VCODEC1_BRIDGE_SW_RESET}; + u32 idle_status[] = {VCODEC_SS_IDLE_STATUSN, VCODEC1_SS_IDLE_STATUSN}; + u32 power_status[] = {VCODEC0_POWER_STATUS, VCODEC1_POWER_STATUS}; + bool handshake_done, handshake_busy; + u32 value, i, count = 0; + int ret; + + if (iris_vpu3x_hw_power_collapsed(core, power_status[core_id])) + goto disable_power; + + value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + if (value) + writel(CORE_CLK_RUN, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + + for (i = 0; i < core->iris_platform_data->num_vpp_pipe; i++) { + ret = readl_poll_timeout(core->reg_base + idle_status[core_id] + 4 * i, + value, value & DMA_NOC_IDLE, 2000, 20000); + if (ret) + goto disable_power; + } + + do { + writel(power_down_prep[core_id], core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + usleep_range(15, 20); + value = readl(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS); + + handshake_done = value & lpi_status_done[core_id]; + handshake_busy = value & (lpi_status_deny[core_id] | lpi_status_active[core_id]); + + if (handshake_done || !handshake_busy) + break; + + writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + usleep_range(15, 20); + } while (++count < 1000); + + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS, + value, value & lpi_status_done[core_id], 200, 2000); + writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + if (ret) + goto disable_power; + + writel(bridge_sw_reset[core_id] | bridge_hw_reset[core_id], + core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(bridge_hw_reset[core_id], core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + +disable_power: + iris_genpd_set_hwmode(&core->vcodec[core_id], false); + iris_disable_power_domain_and_clocks(core, &core->vcodec[core_id]); +} + +static void iris_vpu36_power_off_hw(struct iris_core *core) +{ + u32 num_cores = core->iris_platform_data->num_cores; + int i; + + for (i = 0; i < num_cores; i++) + iris_vpu36_power_off_vcodec(core, i); +} + +static int iris_vpu36_power_on_hw(struct iris_core *core) +{ + u32 num_cores = core->iris_platform_data->num_cores; + int i, ret; + + for (i = 0; i < num_cores; i++) { + ret = iris_enable_power_domain_and_clocks(core, &core->vcodec[i]); + if (ret) + goto error; + } + + return 0; + +error: + while (--i >= 0) + iris_vpu36_power_off_vcodec(core, i); + + return ret; +} + +static int iris_vpu36_set_hwmode(struct iris_core *core) +{ + u32 num_cores = core->iris_platform_data->num_cores; + int i, ret; + + for (i = 0; i < num_cores; i++) { + ret = iris_genpd_set_hwmode(&core->vcodec[i], true); + if (ret) + goto error; + } + + return 0; + +error: + while (--i >= 0) + iris_genpd_set_hwmode(&core->vcodec[i], false); + + return ret; +} + const struct vpu_ops iris_vpu3_ops = { .power_off_hw = iris_vpu3_power_off_hardware, .power_on_hw = iris_vpu_power_on_hw, @@ -254,3 +362,14 @@ const struct vpu_ops iris_vpu35_ops = { .set_preset_registers = iris_vpu_set_preset_registers, .interrupt_init = iris_vpu_interrupt_init, }; + +const struct vpu_ops iris_vpu36_ops = { + .power_off_hw = iris_vpu36_power_off_hw, + .power_on_hw = iris_vpu36_power_on_hw, + .power_off_controller = iris_vpu35_vpu4x_power_off_controller, + .power_on_controller = iris_vpu35_vpu4x_power_on_controller, + .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, + .set_hwmode = iris_vpu36_set_hwmode, + .set_preset_registers = iris_vpu_set_preset_registers, + .interrupt_init = iris_vpu_interrupt_init, +}; \ No newline at end of file diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index a62b6184bde7e..5a9ca9d1902a6 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -12,6 +12,7 @@ extern const struct vpu_ops iris_vpu2_ops; extern const struct vpu_ops iris_vpu3_ops; extern const struct vpu_ops iris_vpu33_ops; extern const struct vpu_ops iris_vpu35_ops; +extern const struct vpu_ops iris_vpu36_ops; extern const struct vpu_ops iris_vpu4x_ops; extern const struct vpu_ops iris_vpu_ar50lt_ops; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h index 4fffa094c52fe..d21c2070c32a4 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h @@ -7,6 +7,7 @@ #define __IRIS_VPU_REGISTER_DEFINES_H__ #define VCODEC_BASE_OFFS 0x00000000 +#define VCODEC1_BASE_OFFS 0x00040000 #define AON_MVP_NOC_RESET 0x0001F000 #define CPU_BASE_OFFS 0x000A0000 #define WRAPPER_BASE_OFFS 0x000B0000 @@ -14,6 +15,8 @@ #define AON_BASE_OFFS 0x000E0000 #define VCODEC_SS_IDLE_STATUSN (VCODEC_BASE_OFFS + 0x70) +#define VCODEC1_SS_IDLE_STATUSN (VCODEC1_BASE_OFFS + 0x70) +#define DMA_NOC_IDLE BIT(22) #define AON_WRAPPER_MVP_NOC_RESET_REQ (AON_MVP_NOC_RESET + 0x000) #define VIDEO_NOC_RESET_REQ (BIT(0) | BIT(1)) @@ -35,6 +38,8 @@ #define CPU_CS_AHB_BRIDGE_SYNC_RESET (CPU_CS_BASE_OFFS + 0x160) #define CORE_BRIDGE_SW_RESET BIT(0) #define CORE_BRIDGE_HW_RESET_DISABLE BIT(1) +#define VCODEC1_BRIDGE_SW_RESET BIT(2) +#define VCODEC1_BRIDGE_HW_RESET_DISABLE BIT(3) #define CPU_CS_X2RPMH (CPU_CS_BASE_OFFS + 0x168) #define MSK_SIGNAL_FROM_TENSILICA BIT(0) @@ -51,14 +56,21 @@ #define WRAPPER_DEBUG_BRIDGE_LPI_STATUS (WRAPPER_BASE_OFFS + 0x58) #define WRAPPER_IRIS_CPU_NOC_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x5C) #define REQ_POWER_DOWN_PREP BIT(0) +#define REQ_VCODEC1_POWER_DOWN_PREP BIT(1) #define WRAPPER_IRIS_CPU_NOC_LPI_STATUS (WRAPPER_BASE_OFFS + 0x60) #define NOC_LPI_STATUS_DONE BIT(0) /* Indicates the NOC handshake is complete */ #define NOC_LPI_STATUS_DENY BIT(1) /* Indicates the NOC handshake is denied */ #define NOC_LPI_STATUS_ACTIVE BIT(2) /* Indicates the NOC is active */ +#define NOC_LPI_VCODEC1_STATUS_DONE BIT(8) +#define NOC_LPI_VCODEC1_STATUS_DENY BIT(9) +#define NOC_LPI_VCODEC1_STATUS_ACTIVE BIT(10) #define WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0 (WRAPPER_BASE_OFFS + 0x78) #define WRAPPER_CORE_POWER_STATUS (WRAPPER_BASE_OFFS + 0x80) +#define VCODEC0_POWER_STATUS BIT(1) +#define VCODEC1_POWER_STATUS BIT(4) + #define WRAPPER_CORE_CLOCK_CONFIG (WRAPPER_BASE_OFFS + 0x88) #define CORE_CLK_RUN 0x0 From 939d902295250f461756e2fa4b402049885dfef3 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Wed, 5 Nov 2025 14:26:27 +0530 Subject: [PATCH 0546/1133] QCLINUX: defconfig: enable amc6821 defconfig on qcom.config Enable SENSOR_AMC6821 defconfig to enable fan controller support. Signed-off-by: Gaurav Kohli --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index a05f6e73a8979..1f0710ae86383 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -26,6 +26,7 @@ CONFIG_STM_PROTO_SYS_T=m CONFIG_STM_SOURCE_CONSOLE=m CONFIG_STM_SOURCE_FTRACE=m CONFIG_STM_SOURCE_HEARTBEAT=m +CONFIG_SENSORS_AMC6821=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y From 13a598c47b7c1ad4835bd8271d780be099829f3d Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Thu, 13 Nov 2025 14:59:19 +0530 Subject: [PATCH 0547/1133] QCLINUX: defconfig: Enable QCA808X ethernet phy config Enable the config for the QCA808X ethernet PHY driver. Ethernet is non functional without this driver on Lemans and Monaco EVK. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 1f0710ae86383..553ded1bb2ca5 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -19,6 +19,7 @@ CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y CONFIG_POWERCAP=y +CONFIG_QCA808X_PHY=m CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y CONFIG_STM_PROTO_BASIC=m From 0249d507986360a714ff78e1401ad968c2b0fef5 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 14 Nov 2025 19:08:45 +0530 Subject: [PATCH 0548/1133] QCLINUX: defconfig: Enable EDAC_QCOM on qcom.config Enable QCOM EDAC driver support for QCOM SoCs. Signed-off-by: Komal Bajaj --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 553ded1bb2ca5..f419f7cdb4b4c 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -16,6 +16,7 @@ CONFIG_CPU_IDLE_THERMAL=y CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_EDAC_QCOM=m CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y CONFIG_POWERCAP=y From af80cc37ebefb17bd21ed4518f632d089c269fe6 Mon Sep 17 00:00:00 2001 From: Yingying Tang Date: Wed, 12 Nov 2025 11:29:07 +0800 Subject: [PATCH 0549/1133] QCLINUX: debug: Enable WLAN related debug configs Enable WLAN related debug configs. Signed-off-by: Yingying Tang --- kernel/configs/debug.config | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 25d2ebaa64779..4a77b402e3357 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -120,8 +120,31 @@ CONFIG_PREEMPT=y # # Qualcomm Debug Configs # +CONFIG_ATH11K_COREDUMP=y +CONFIG_ATH11K_DEBUG=y +CONFIG_ATH11K_DEBUGFS=y +CONFIG_ATH11K_TRACING=y +CONFIG_ATH12K_DEBUG=y +CONFIG_ATH12K_DEBUGFS=y +CONFIG_ATH12K_TRACING=y +CONFIG_ATH12K_COREDUMP=y +CONFIG_CFG80211_DEBUGFS=y CONFIG_CMA_DEBUG=y CONFIG_DEBUG_LIST=y CONFIG_DEBUG_PAGEALLOC=y +CONFIG_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_FTRACE_SYSCALLS=y +CONFIG_FUNCTION_GRAPH_TRACER=y # CONFIG_FW_LOADER_DEBUG is not set CONFIG_HARDLOCKUP_DETECTOR=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_KPROBE_EVENTS=y +CONFIG_MAC80211_DEBUGFS=y +CONFIG_NL80211_TESTMODE=y +CONFIG_PREEMPT_TRACER=y +CONFIG_PREEMPTIRQ_TRACEPOINTS=y +CONFIG_SCHED_TRACER=y +CONFIG_STACK_TRACER=y +CONFIG_TRACEPOINTS=y +CONFIG_TRACING=y +CONFIG_UPROBE_EVENTS=y From c0a6b1ee41d1f6cc1d2f669b4e3ce22860cc76e1 Mon Sep 17 00:00:00 2001 From: Yingying Tang Date: Wed, 12 Nov 2025 12:01:17 +0800 Subject: [PATCH 0550/1133] QCLINUX: defconfig: Enable ATH reg setting Enable ATH reg setting, then user can change country code by netlink command. Signed-off-by: Yingying Tang --- arch/arm64/configs/qcom.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index f419f7cdb4b4c..20f8ced53c2ec 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -4,6 +4,8 @@ # # Keep alphabetically sorted CONFIG_ARM64_SW_TTBR0_PAN=y +CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y CONFIG_CORESIGHT_CORESIGHT_TNOC=m CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_DUMMY=m @@ -17,6 +19,7 @@ CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_EDAC_QCOM=m +CONFIG_EXPERT=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y CONFIG_POWERCAP=y From 360df9e0a434335ecf413890a0766403e628790b Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Wed, 19 Nov 2025 19:55:44 +0530 Subject: [PATCH 0551/1133] QCLINUX: defconfig: Enable BT_RFCOMM, BT_BNEP and UHID Enable as modules the BT_BNEP and BT_RFCOMM drivers which are required for Bluetooth profiles such as PAN and SPP. Without these modules, PAN and SPP functionality will not be available. Enable UHID support to allow HID over GATT operations. Without this, user-space cannot create virtual HID devices, which impacts HID profile usage over Bluetooth. Signed-off-by: Wei Deng --- arch/arm64/configs/qcom.config | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 20f8ced53c2ec..f0c4f07c3bf41 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -5,6 +5,11 @@ # Keep alphabetically sorted CONFIG_ARM64_SW_TTBR0_PAN=y CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y CONFIG_CFG80211_CERTIFICATION_ONUS=y CONFIG_CORESIGHT_CORESIGHT_TNOC=m CONFIG_CORESIGHT_CTCU=m @@ -35,6 +40,7 @@ CONFIG_SENSORS_AMC6821=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y +CONFIG_UHID=m # CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y From 2b7355977fce9f18c34cb019b57348a5fa338a39 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 21 Nov 2025 10:01:00 +0530 Subject: [PATCH 0552/1133] QCLINUX: defconfig: Enable various power management configs Enable various PM configs to enable suspend-resume. Signed-off-by: Maulik Shah --- arch/arm64/configs/qcom.config | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index f0c4f07c3bf41..0ed1640e64146 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -27,6 +27,13 @@ CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM=y CONFIG_POWERCAP=y CONFIG_QCA808X_PHY=m CONFIG_SCHED_DEBUG=y From 083b74ba269988c36642900adc11cc29cd91da0a Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 21 Nov 2025 13:32:46 +0530 Subject: [PATCH 0553/1133] QCLINUX: debug: Enable power management debug configs Enabled various power management debug related kernel config options to improve system diagnostics and aid in development and issue analysis. Signed-off-by: Maulik Shah --- kernel/configs/debug.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 4a77b402e3357..fa5cb755ab55f 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -143,6 +143,9 @@ CONFIG_MAC80211_DEBUGFS=y CONFIG_NL80211_TESTMODE=y CONFIG_PREEMPT_TRACER=y CONFIG_PREEMPTIRQ_TRACEPOINTS=y +CONFIG_PM_ADVANCED_DEBUG=y +CONFIG_PM_DEBUG=y +CONFIG_PM_SLEEP_DEBUG=y CONFIG_SCHED_TRACER=y CONFIG_STACK_TRACER=y CONFIG_TRACEPOINTS=y From 86420f9ce0dd76e1039a2427612c06f9d421c3be Mon Sep 17 00:00:00 2001 From: Nikhil V Date: Thu, 27 Nov 2025 15:15:16 +0530 Subject: [PATCH 0554/1133] QCLINUX: defconfig: Enable watchdog drivers for VM usecases CrosVM supports vCPU Stall watchdog. QEMU supports I6300 ESB watchdog. Enable corresponding drivers for Guest VM usecases. Signed-off-by: Nikhil V --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 0ed1640e64146..3e203060de6e6 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -25,6 +25,7 @@ CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y +CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y CONFIG_PM_SLEEP=y @@ -48,6 +49,7 @@ CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y CONFIG_UHID=m +CONFIG_VCPU_STALL_DETECTOR=y # CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y From 695755f396e895f33f65c1d312a537da6b2e3f52 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Fri, 28 Nov 2025 12:38:09 +0530 Subject: [PATCH 0555/1133] QCLINUX: debug.config: Drop heavy debug configs Removed UBSAN, KASAN, kmemleak, lock proving, and function tracing from debug.config to reduce bootup time and prevent probe deferring issues. Signed-off-by: Komal Bajaj --- kernel/configs/debug.config | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index fa5cb755ab55f..1669b7be9b750 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -32,12 +32,12 @@ CONFIG_SECTION_MISMATCH_WARN_ONLY=y CONFIG_DEBUG_FS=y CONFIG_DEBUG_FS_ALLOW_ALL=y CONFIG_DEBUG_IRQFLAGS=y -CONFIG_UBSAN=y -CONFIG_UBSAN_BOOL=y -CONFIG_UBSAN_BOUNDS=y -CONFIG_UBSAN_ENUM=y -CONFIG_UBSAN_SHIFT=y -CONFIG_UBSAN_UNREACHABLE=y +# CONFIG_UBSAN is not set +# CONFIG_UBSAN_BOOL is not set +# CONFIG_UBSAN_BOUNDS is not set +# CONFIG_UBSAN_ENUM is not set +# CONFIG_UBSAN_SHIFT is not set +# CONFIG_UBSAN_UNREACHABLE is not set # # Networking Debugging # @@ -56,8 +56,8 @@ CONFIG_DEBUG_NET=y # CONFIG_SLUB_STATS is not set CONFIG_PAGE_EXTENSION=y CONFIG_PAGE_OWNER=y -CONFIG_DEBUG_KMEMLEAK=y -CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN is not set CONFIG_DEBUG_OBJECTS=y CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 CONFIG_DEBUG_OBJECTS_FREE=y @@ -72,10 +72,10 @@ CONFIG_DEBUG_VM=y CONFIG_DEBUG_VM_PGFLAGS=y CONFIG_DEBUG_VM_RB=y CONFIG_DEBUG_VM_VMACACHE=y -CONFIG_KASAN=y -CONFIG_KASAN_GENERIC=y -CONFIG_KASAN_INLINE=y -CONFIG_KASAN_VMALLOC=y +# CONFIG_KASAN is not set +# CONFIG_KASAN_GENERIC is not set +# CONFIG_KASAN_INLINE is not set +# CONFIG_KASAN_VMALLOC is not set CONFIG_PTDUMP_DEBUGFS=y CONFIG_SCHED_STACK_END_CHECK=y CONFIG_SLUB_DEBUG_ON=y @@ -93,7 +93,7 @@ CONFIG_SOFTLOCKUP_DETECTOR=y # Lock Debugging (spinlocks, mutexes, etc...) # # CONFIG_PROVE_RAW_LOCK_NESTING is not set -CONFIG_PROVE_LOCKING=y +# CONFIG_PROVE_LOCKING is not set # # Debug kernel data structures # @@ -101,16 +101,16 @@ CONFIG_BUG_ON_DATA_CORRUPTION=y # # RCU Debugging # -CONFIG_RCU_EXPERT=y -CONFIG_PROVE_RCU=y -CONFIG_PROVE_RCU_LIST=y +# CONFIG_RCU_EXPERT is not set +# CONFIG_PROVE_RCU is not set +# CONFIG_PROVE_RCU_LIST is not set # # Tracers # CONFIG_BRANCH_PROFILE_NONE=y CONFIG_DYNAMIC_FTRACE=y CONFIG_FTRACE=y -CONFIG_FUNCTION_TRACER=y +# CONFIG_FUNCTION_TRACER is not set # # Preemption # From b4bfb627791b301ec63aa28f5a0ea6e91a6f4e32 Mon Sep 17 00:00:00 2001 From: Nikhil V Date: Thu, 20 Nov 2025 15:11:23 +0530 Subject: [PATCH 0556/1133] QCLINUX: defconfig: Enable support for vhost-net, vsock Added the required configs to enable host kernel accelerator for virtio net(vhost-net) and virtual socket protocol(vsock). Signed-off-by: Nikhil V --- arch/arm64/configs/qcom.config | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 3e203060de6e6..d32f4bbf00f96 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -28,6 +28,8 @@ CONFIG_EXPERT=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y +CONFIG_MACVLAN=y +CONFIG_MACVTAP=y CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y CONFIG_PM_AUTOSLEEP=y @@ -50,6 +52,11 @@ CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y CONFIG_UHID=m CONFIG_VCPU_STALL_DETECTOR=y +CONFIG_VHOST_NET=y +CONFIG_VHOST_VSOCK=y +CONFIG_VSOCKETS=y +# CONFIG_VSOCKETS_DIAG is not set +# CONFIG_VSOCKETS_LOOPBACK is not set # CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y From e00db106c86537cc949c02c278b7784340014cc5 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Thu, 4 Dec 2025 18:20:29 +0530 Subject: [PATCH 0557/1133] QCLINUX: arm64: configs: qcom.config: Enable GUNYAH_WATCHDOG Enable Gunyah watchdog driver for rb3gen2. Signed-off-by: Shivendra Pratap --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index d32f4bbf00f96..702ee1b90a607 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -25,6 +25,7 @@ CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y +CONFIG_GUNYAH_WATCHDOG=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y CONFIG_KPROBES=y From 163d8d323c887c03b31bd776645165448aebbb77 Mon Sep 17 00:00:00 2001 From: Raghavender Reddy Bujala Date: Wed, 10 Dec 2025 16:16:53 +0530 Subject: [PATCH 0558/1133] QCLINUX: arm64: configs: qcom.config: Enable UINPUT Enable UINPUT, which is required for BT AVRC profile to register the events and All passthrough commands of AVRCP will be listed in this event under /dev/input/ Signed-off-by: Raghavender Reddy Bujala --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 702ee1b90a607..dd67da6c25f7a 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -28,6 +28,7 @@ CONFIG_EXPERT=y CONFIG_GUNYAH_WATCHDOG=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y +CONFIG_INPUT_UINPUT=y CONFIG_KPROBES=y CONFIG_MACVLAN=y CONFIG_MACVTAP=y From 9f8ab44a6677045f89b970a05f8279ee2a17fb28 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Mon, 15 Dec 2025 12:37:54 +0530 Subject: [PATCH 0559/1133] QCLINUX: defconfig: enable EMC2305 defconfig on qcom.config Enable SENSOR_EMC2305 defconfig to enable fan controller support. Signed-off-by: Gaurav Kohli --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index dd67da6c25f7a..28c53bd2fbc51 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -49,6 +49,7 @@ CONFIG_STM_SOURCE_CONSOLE=m CONFIG_STM_SOURCE_FTRACE=m CONFIG_STM_SOURCE_HEARTBEAT=m CONFIG_SENSORS_AMC6821=y +CONFIG_SENSORS_EMC2305=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y From 8a9e0f2388fb2df06dfd9cc725d9ea6c7d461e0d Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Wed, 17 Dec 2025 18:42:40 +0530 Subject: [PATCH 0560/1133] QCLINUX: arm64: configs: Added new rt.config for RT kernel Enabled PREEMPT_RT in new rt.config to enable RT kernel features. Signed-off-by: Anurag Pateriya --- arch/arm64/configs/rt.config | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 arch/arm64/configs/rt.config diff --git a/arch/arm64/configs/rt.config b/arch/arm64/configs/rt.config new file mode 100644 index 0000000000000..ca92615d38a17 --- /dev/null +++ b/arch/arm64/configs/rt.config @@ -0,0 +1,3 @@ +# rt.config for Real time kernel features +CONFIG_EXPERT=y +CONFIG_PREEMPT_RT=y From e1c6b350fadaa7ce88f69731b4bb16b60f32fa04 Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Thu, 11 Dec 2025 16:41:21 +0530 Subject: [PATCH 0561/1133] QCLINUX: arm64: configs: qcom.config: Enable I2C_QCOM_GENI as built-in On Lemans and Monaco EVK platforms the boot-from-SD-card feature requires an IO expander to be enabled at an early stage to detect the SD card. This IO expander is connected over I2C. Currently the I2C driver is built as a loadable module which resides on the SD card along with other modules. This creates a circular dependency where to detect the SD card the IO expander must be initialized the IO expander depends on the I2C driver and the I2C driver is on the SD card which cannot be accessed until detection succeeds. To break this dependency enable I2C_QCOM_GENI as built-in so that the driver is available during early boot. Signed-off-by: Viken Dadhaniya --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 28c53bd2fbc51..b49d58563974f 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -26,6 +26,7 @@ CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y CONFIG_GUNYAH_WATCHDOG=y +CONFIG_I2C_QCOM_GENI=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y CONFIG_INPUT_UINPUT=y From cfc95d9d68e3f60a97e7c55f5477c003d8506925 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 18 Dec 2025 15:10:56 +0530 Subject: [PATCH 0562/1133] QCLINUX: arm64: configs: Added Kubernetes support in qcom.config Adding config options for Kubernetes support in qcom.config Signed-off-by: Anurag Pateriya --- arch/arm64/configs/qcom.config | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index b49d58563974f..a5cd0552d921b 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -68,3 +68,13 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m CONFIG_WATCHDOG_PRETIMEOUT_GOV=y CONFIG_ZRAM=y + +# Kubernetes support +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_FAVOR_DYNMODS=y +CONFIG_IPC_NS=y +CONFIG_NAMESPACES=y +CONFIG_NET_NS=y +CONFIG_PID_NS=y +CONFIG_UTS_NS=y + From f11ad977c80e5e06e3972de211110c565490a2d8 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 23 Dec 2025 17:07:14 +0530 Subject: [PATCH 0563/1133] QCLINUX: qcom.comfig: disable ICE/UFS crypto RB3GEN2 on v6.19-rc2 crashes in qcom_ice_probe() and fails to boot. Disable inline crypto (ICE) and UFS crypto as a temporary workaround. Disabled: - CONFIG_QCOM_INLINE_CRYPTO_ENGINE - CONFIG_SCSI_UFS_CRYPTO Will be reverted once ICE probe is fixed. Signed-off-by: Komal Bajaj --- arch/arm64/configs/qcom.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index a5cd0552d921b..3e70e46afed10 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -78,3 +78,6 @@ CONFIG_NET_NS=y CONFIG_PID_NS=y CONFIG_UTS_NS=y +# Disable ICE/UFS crypto +# CONFIG_QCOM_INLINE_CRYPTO_ENGINE is not set +# CONFIG_SCSI_UFS_CRYPTO is not set From 16250dfb8a6193d89f86fb843d89c8388c20e1db Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Thu, 17 Sep 2026 10:30:24 +0530 Subject: [PATCH 0564/1133] FROMLIST: media: iris: Handle CPU_CS_SCIACMDARG3 register write via program bootup registers hook On the Glymur platform, the firmware reads CPU_CS_SCIACMDARG3 during boot to determine the VM count and increments it by 1. Writing the default 0x1 causes the firmware to treat the VM count as 2. To avoid that write 0x0 to CPU_CS_SCIACMDARG3 as a Glymur platform specific. Link: https://lore.kernel.org/all/20260917-glymur-v11-5-e0c8bc914742@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Vishnu Reddy Reviewed-by: Vikash Garodia --- drivers/media/platform/qcom/iris/iris_vpu3x.c | 6 ++++++ drivers/media/platform/qcom/iris/iris_vpu_common.c | 4 ++-- .../media/platform/qcom/iris/iris_vpu_register_defines.h | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index 3851f3642cf33..39bf924fb5e98 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -329,6 +329,11 @@ static int iris_vpu36_set_hwmode(struct iris_core *core) return ret; } +static void iris_vpu36_program_bootup_registers(struct iris_core *core) +{ + writel(0x0, core->reg_base + CPU_CS_SCIACMDARG3); +} + const struct vpu_ops iris_vpu3_ops = { .power_off_hw = iris_vpu3_power_off_hardware, .power_on_hw = iris_vpu_power_on_hw, @@ -368,6 +373,7 @@ const struct vpu_ops iris_vpu36_ops = { .power_on_hw = iris_vpu36_power_on_hw, .power_off_controller = iris_vpu35_vpu4x_power_off_controller, .power_on_controller = iris_vpu35_vpu4x_power_on_controller, + .program_bootup_registers = iris_vpu36_program_bootup_registers, .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, .set_hwmode = iris_vpu36_set_hwmode, .set_preset_registers = iris_vpu_set_preset_registers, diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 4ea7bfd204df0..b282cebeba52b 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -26,7 +26,6 @@ #define QTBL_ENABLE BIT(0) #define QTBL_ADDR (CPU_CS_BASE_OFFS + 0x54) -#define CPU_CS_SCIACMDARG3 (CPU_CS_BASE_OFFS + 0x58) #define SFR_ADDR (CPU_CS_BASE_OFFS + 0x5C) #define UC_REGION_ADDR (CPU_CS_BASE_OFFS + 0x64) #define UC_REGION_SIZE (CPU_CS_BASE_OFFS + 0x68) @@ -67,6 +66,8 @@ static void iris_vpu_setup_ucregion_memory_map(struct iris_core *core) writel(value, core->reg_base + SFR_ADDR); } + writel(0x1, core->reg_base + CPU_CS_SCIACMDARG3); + if (vpu_ops->program_bootup_registers) vpu_ops->program_bootup_registers(core); } @@ -78,7 +79,6 @@ int iris_vpu_boot_firmware(struct iris_core *core) iris_vpu_setup_ucregion_memory_map(core); writel(ctrl_init, core->reg_base + CTRL_INIT); - writel(0x1, core->reg_base + CPU_CS_SCIACMDARG3); while (!ctrl_status && count < max_tries) { ctrl_status = readl(core->reg_base + CTRL_STATUS); diff --git a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h index d21c2070c32a4..23068fca5f637 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h @@ -29,6 +29,7 @@ #define CPU_CS_A2HSOFTINTCLR (CPU_CS_BASE_OFFS + 0x1C) #define CLEAR_XTENSA2HOST_INTR BIT(0) +#define CPU_CS_SCIACMDARG3 (CPU_CS_BASE_OFFS + 0x58) #define CPU_CS_H2XSOFTINTEN (CPU_CS_BASE_OFFS + 0x148) #define HOST2XTENSA_INTR_ENABLE BIT(0) From adcbf54bf143bb61ee5e4dde3d498f803cb3114d Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Wed, 24 Dec 2025 18:34:18 +0530 Subject: [PATCH 0565/1133] QCLINUX: defconfig: enable Remoteproc cooling feature Enable Remoteproc cooling feature config. Signed-off-by: Gaurav Kohli --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 3e70e46afed10..deb196ca4eced 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -42,6 +42,8 @@ CONFIG_PM_WAKELOCKS_LIMIT=0 CONFIG_PM=y CONFIG_POWERCAP=y CONFIG_QCA808X_PHY=m +CONFIG_QCOM_QMI_COOLING=y +CONFIG_REMOTEPROC_THERMAL=y CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y CONFIG_STM_PROTO_BASIC=m From b3ecaf0b43fa1962586e25e3aa4568062dea580d Mon Sep 17 00:00:00 2001 From: Jagadeesh Pagadala Date: Thu, 8 Jan 2026 14:14:29 +0530 Subject: [PATCH 0566/1133] QCLINUX: arm64: configs: qcom.config: Enable CONNECTOR, PROC_EVENTS Enable CONFIG_CONNECTOR and CONFIG_PROC_EVENTS to allow userspace to receive process lifecycle events (fork/exec/exit) via the proc connector over netlink. Signed-off-by: Jagadeesh Pagadala --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index deb196ca4eced..8a86a3cb7813f 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -11,6 +11,7 @@ CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_RFCOMM=m CONFIG_BT_RFCOMM_TTY=y CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CONNECTOR=y CONFIG_CORESIGHT_CORESIGHT_TNOC=m CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_DUMMY=m @@ -41,6 +42,7 @@ CONFIG_PM_WAKELOCKS_LIMIT=0 # CONFIG_PM_WAKELOCKS_GC is not set CONFIG_PM=y CONFIG_POWERCAP=y +CONFIG_PROC_EVENTS=y CONFIG_QCA808X_PHY=m CONFIG_QCOM_QMI_COOLING=y CONFIG_REMOTEPROC_THERMAL=y From e520cfee9c3bd594c82d891656d57d435c183e02 Mon Sep 17 00:00:00 2001 From: Wenjia Zhang Date: Mon, 5 Jan 2026 15:59:47 +0800 Subject: [PATCH 0567/1133] QCLINUX: qcom.config: add crypto corresponding config Enable crypto api for user test. The configs are for testapp that's why the kernel upstream team would suggest having this enabled for clients who needs it and not by default since in qcom we need this, we should be enabling ideally in qcom-next. Signed-off-by: Wenjia Zhang --- arch/arm64/configs/qcom.config | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 8a86a3cb7813f..bdb40e6edf745 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -85,3 +85,9 @@ CONFIG_UTS_NS=y # Disable ICE/UFS crypto # CONFIG_QCOM_INLINE_CRYPTO_ENGINE is not set # CONFIG_SCSI_UFS_CRYPTO is not set + +# Support Crypto api +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_USER_API_AEAD=y From 9f3680852d736f99f20db6f6d9c24843d8ac8c49 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 19 Jan 2026 15:47:00 +0800 Subject: [PATCH 0568/1133] QCLINUX: prune.config: Enable backlight config for Hamoa/Purwa Hamoa/Purwa currently requires the backlight node from the eDP device, but this macro was overridden by CONFIG_DRM_NOUVEAU. Remove it from prune.config to properly enable the BACKLIGHT_* related config. Signed-off-by: Yongxing Mou --- arch/arm64/configs/prune.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index 54cf8fa1cd0e0..fba07d6ebe12d 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -188,7 +188,6 @@ # 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 From bbcdafe527ee547b926eb57447d6b81877d54739 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Fri, 23 Jan 2026 13:32:49 +0530 Subject: [PATCH 0569/1133] QCLINUX: qcom.config: Enable 39-bit VA space for 4K-page builds For Qualcomm 4K-page based builds, explicitly enable VA_BITS_39 in the qcom.config fragment. Lower-end arm64 systems typically do not benefit from a 48/52-bit VA space, while they do benefit from smaller page tables and reduced TLB pressure. Selecting 39-bit VA sizing aligns better with constraints and performance characteristics of lower-end Qualcomm platforms. This change does not affect 64K-page builds (which retain 48/52-bit VA). Background: - With 4K pages, arm64 supports 39-bit (3-level) or 48-bit (4-level) VAs. - 52-bit VAs are only available with 64K pages and ARMv8.2-LVA, and kernels must be able to fall back to 48-bit at boot. Signed-off-by: Anurag Pateriya --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index bdb40e6edf745..583c51acfeda2 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -4,6 +4,7 @@ # # Keep alphabetically sorted CONFIG_ARM64_SW_TTBR0_PAN=y +CONFIG_ARM64_VA_BITS_39=y CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS=y CONFIG_BT_BNEP=m CONFIG_BT_BNEP_MC_FILTER=y From 0b46c5eebfea1f23022d3f1f1a8c5d202153c3ff Mon Sep 17 00:00:00 2001 From: Wenjia Zhang Date: Tue, 27 Jan 2026 15:59:30 +0800 Subject: [PATCH 0570/1133] QCLINUX: qcom.config: enable the ICE related config Below is the reason why config aren't enable in upstream: Not all filesystem support encryption, the default config must be safe for all situation. Upstream kernel keeps optional features off by default. Filesystem encryption must be enabled in per-filesystem. Kernel developmenters added options to dosable fscrypt per-filesystem means it's not intended as default. CRs-Fixed: 4418940 Signed-off-by: Wenjia Zhang --- arch/arm64/configs/qcom.config | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 583c51acfeda2..95ffbc244bbe1 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -83,12 +83,15 @@ CONFIG_NET_NS=y CONFIG_PID_NS=y CONFIG_UTS_NS=y -# Disable ICE/UFS crypto -# CONFIG_QCOM_INLINE_CRYPTO_ENGINE is not set -# CONFIG_SCSI_UFS_CRYPTO is not set - # Support Crypto api CONFIG_CRYPTO_USER_API=y CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_SKCIPHER=y CONFIG_CRYPTO_USER_API_AEAD=y + +# Support ICE/UFS crypto driver +CONFIG_BLK_INLINE_ENCRYPTION=y +CONFIG_QCOM_INLINE_CRYPTO_ENGINE=m +CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y +CONFIG_SCSI_UFS_CRYPTO=y +CONFIG_FS_ENCRYPTION=y From 6cc3c0246524a404d4076b6ff640eeef11d941c5 Mon Sep 17 00:00:00 2001 From: Gopi Botlagunta Date: Wed, 12 Nov 2025 20:18:12 +0530 Subject: [PATCH 0571/1133] FROMLIST: arm64: configs: Update defconfig for DSI-LVDS bridge support Enable the LT9211 bridge driver to support DSI-to-LVDS conversion on the Qualcomm RB3GEN2 Industrial Kit. Signed-off-by: Gopi Botlagunta Co-developed-by: Yi Zhang Signed-off-by: Yi Zhang Link: https://lore.kernel.org/lkml/20260130-add-lt9211c-bridge-for-rb3gen2-industrial-mezzanine-v2-2-a98714fa1531@oss.qualcomm.com/ --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7b4985b29b21c..5d966980b175f 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -979,6 +979,7 @@ CONFIG_DRM_FSL_LDB=m CONFIG_DRM_I2C_NXP_TDA998X=m CONFIG_DRM_ITE_IT6263=m CONFIG_DRM_LONTIUM_LT8912B=m +CONFIG_DRM_LONTIUM_LT9211=m CONFIG_DRM_LONTIUM_LT9611=m CONFIG_DRM_LONTIUM_LT9611UXC=m CONFIG_DRM_LONTIUM_LT8713SX=m From 59e329f9e2e43e5f6b19868ff28b78664ea36ecd Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Thu, 29 Jan 2026 15:52:47 +0530 Subject: [PATCH 0572/1133] QCLINUX: qcom.config: Enable FTRACE option for performance profiling Enable kernel tracing option in qcom.config to support performance profiling on Qualcomm arm64 builds. Signed-off-by: Komal Bajaj --- arch/arm64/configs/qcom.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 95ffbc244bbe1..0c519f4f5699b 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -95,3 +95,6 @@ CONFIG_QCOM_INLINE_CRYPTO_ENGINE=m CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_SCSI_UFS_CRYPTO=y CONFIG_FS_ENCRYPTION=y + +# Support performance profiling +CONFIG_FTRACE=y From 78a1ad9767d75f394b601f3f653783f154bd0e34 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Wed, 18 Feb 2026 12:00:01 +0530 Subject: [PATCH 0573/1133] Revert "QCLINUX: qcom.config: Enable 39-bit VA space for 4K-page builds" This reverts commit 02fdded1047f4a65082e9ee523dec4af032d99bc. Since bootup issues are observed after enabling 39-bit VA, reverting it untill issues are root caused and fixed. Signed-off-by: Anurag Pateriya --- arch/arm64/configs/qcom.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 0c519f4f5699b..8dc73c1b87af0 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -4,7 +4,6 @@ # # Keep alphabetically sorted CONFIG_ARM64_SW_TTBR0_PAN=y -CONFIG_ARM64_VA_BITS_39=y CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS=y CONFIG_BT_BNEP=m CONFIG_BT_BNEP_MC_FILTER=y From ee7be3eeef33957e68d0bb1043a00b85591d1fe1 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 20 Feb 2026 08:33:37 +0530 Subject: [PATCH 0574/1133] QCLINUX: qcom.config: Enable CPUidle Teo and Menu governors Menu governor gets default enabled if Teo governor is not compiled in. Menu still stays as default governor when both are compiled in due to menu having higher rating than teo. Keeping Teo available helps in evaluating power and performance without spinning builds. Enable both menu and teo governors for CPUidle. Signed-off-by: Maulik Shah --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 8dc73c1b87af0..327fc43332c58 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -19,6 +19,8 @@ CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_SOURCE_ETM4X=m CONFIG_CORESIGHT_TGU=m CONFIG_CORESIGHT_TPDM=m +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_GOV_TEO=y CONFIG_CPU_IDLE_THERMAL=y # CONFIG_DEBUG_INFO_REDUCED is not set CONFIG_DMABUF_HEAPS=y From 948e43188a686343e6b153b1848f787b33d7d815 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Mon, 2 Mar 2026 18:33:59 +0530 Subject: [PATCH 0575/1133] QCLINUX: qcom.config: enable CONFIG_CMA for qcom chipsets CMA imposes system-wide memory constraints by reserving boot-time memory and restricting it to movable allocations. This alters allocator behavior even when CMA is not explicitly used. Since CMA sizing and applicability are platform-specific, mm/Kconfig intentionally provides no default opt-in for CONFIG_CMA. Enable CONFIG_CMA for all qcom chipsets Signed-off-by: Bibek Kumar Patro bibek.patro@oss.qualcomm.com --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 327fc43332c58..78478aef4e388 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -11,6 +11,7 @@ CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_RFCOMM=m CONFIG_BT_RFCOMM_TTY=y CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CMA=y CONFIG_CONNECTOR=y CONFIG_CORESIGHT_CORESIGHT_TNOC=m CONFIG_CORESIGHT_CTCU=m From 59154470dc2f413d8bef34b36a2b75341446a4a1 Mon Sep 17 00:00:00 2001 From: gaolez Date: Wed, 18 Mar 2026 16:15:38 +0800 Subject: [PATCH 0576/1133] QCLINUX: qcom.config: Enable testmode config Enabling this option exposes the NL80211_CMD_TESTMODE command, which permits userspace applications to send vendor-specific test commands to the driver for diagnostics and validation purposes. Signed-off-by: gaolez --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 78478aef4e388..a854f8d83638c 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -37,6 +37,7 @@ CONFIG_INPUT_UINPUT=y CONFIG_KPROBES=y CONFIG_MACVLAN=y CONFIG_MACVTAP=y +CONFIG_NL80211_TESTMODE=y CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y CONFIG_PM_AUTOSLEEP=y From e9334e39d7b1ae8c961123607b5662e63374a79a Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 24 Mar 2026 15:36:35 +0800 Subject: [PATCH 0577/1133] QCLINUX: qcom.config: update TGU config The TGU config has been changed in latest TGU driver version. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index a854f8d83638c..0d3ffd0edc064 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -18,7 +18,6 @@ CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_DUMMY=m CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_SOURCE_ETM4X=m -CONFIG_CORESIGHT_TGU=m CONFIG_CORESIGHT_TPDM=m CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_CPU_IDLE_GOV_TEO=y @@ -49,6 +48,7 @@ CONFIG_POWERCAP=y CONFIG_PROC_EVENTS=y CONFIG_QCA808X_PHY=m CONFIG_QCOM_QMI_COOLING=y +CONFIG_QCOM_TGU=m CONFIG_REMOTEPROC_THERMAL=y CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y From 899a7412fa71ad4471991d807d8eea32b7d1a748 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 25 Mar 2026 15:23:24 +0800 Subject: [PATCH 0578/1133] QCLINUX: qcom.config: fix the TNOC config Fix the wrong config for CORESIGHT_TNOC. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 0d3ffd0edc064..4b3c795b34b3f 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -13,7 +13,7 @@ CONFIG_BT_RFCOMM_TTY=y CONFIG_CFG80211_CERTIFICATION_ONUS=y CONFIG_CMA=y CONFIG_CONNECTOR=y -CONFIG_CORESIGHT_CORESIGHT_TNOC=m +CONFIG_CORESIGHT_TNOC=m CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_DUMMY=m CONFIG_CORESIGHT_CTCU=m From 568aea7874cf42905f75382a4db0a6b977da3e5d Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Sat, 28 Mar 2026 16:49:50 +0530 Subject: [PATCH 0579/1133] QCLINUX: qcom.config: Enable compressed firmware support Enable support for loading of compressed firmware. With compressed firmware binaries kernel is not able to load the firmware. Enable kernel configs to support compressed firmware. Signed-off-by: Salendarsingh Gaud --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 4b3c795b34b3f..7cccd0b1f0003 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -28,6 +28,8 @@ CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y +CONFIG_FW_LOADER_COMPRESS=y +CONFIG_FW_LOADER_COMPRESS_ZSTD=y CONFIG_GUNYAH_WATCHDOG=y CONFIG_I2C_QCOM_GENI=y CONFIG_I6300ESB_WDT=y From d44e91bacb91b0bd35be9a48b0df3262521856a7 Mon Sep 17 00:00:00 2001 From: Qian Zhang Date: Tue, 17 Mar 2026 17:20:25 +0800 Subject: [PATCH 0580/1133] QCLINUX: debug: Enable ATH11K CFR Enable RELAY and ATH11K_CFR for channel Frequency Response (CFR) module. Signed-off-by: Qian Zhang --- kernel/configs/debug.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 1669b7be9b750..07dfb0a31a92d 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -120,6 +120,7 @@ CONFIG_PREEMPT=y # # Qualcomm Debug Configs # +CONFIG_ATH11K_CFR=y CONFIG_ATH11K_COREDUMP=y CONFIG_ATH11K_DEBUG=y CONFIG_ATH11K_DEBUGFS=y @@ -146,6 +147,7 @@ CONFIG_PREEMPTIRQ_TRACEPOINTS=y CONFIG_PM_ADVANCED_DEBUG=y CONFIG_PM_DEBUG=y CONFIG_PM_SLEEP_DEBUG=y +CONFIG_RELAY=y CONFIG_SCHED_TRACER=y CONFIG_STACK_TRACER=y CONFIG_TRACEPOINTS=y From 9bd9d49cfa7bbbb623bdeeafebd76b8fea03f943 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 24 Mar 2026 12:18:21 +0530 Subject: [PATCH 0581/1133] QCLINUX: qcom.config: Enable MMC_CRYPTO for ICE emmc To enable ICE, require MMC_CRYPTO for sdhci and SCSI_UFS_CRYPTO for ufs based targets. SCSI_UFS_CRYPTO is already present, add MMC_CRYPTO for enabling inline encryption. Signed-off-by: Kuldeep Singh --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 7cccd0b1f0003..61c86bb5c2133 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -99,6 +99,7 @@ CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_QCOM_INLINE_CRYPTO_ENGINE=m CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_SCSI_UFS_CRYPTO=y +CONFIG_MMC_CRYPTO=y CONFIG_FS_ENCRYPTION=y # Support performance profiling From 3a86ab470e983973b1a9c374e1d1b54b2c2da0fd Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 15 Apr 2026 10:08:10 +0530 Subject: [PATCH 0582/1133] QCLINUX: prune.config: Enable Realtek PHY config for Rb3Gen2 Industrial board The Rb3Gen2 Industrial board has the Realtek RTL8221 PHY which fails to function correctly without the Realtek PHY driver. Remove CONFIG_REALTEK_PHY from prune.config to properly enable it. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/configs/prune.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index fba07d6ebe12d..a13ad5e28c009 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -92,7 +92,6 @@ # CONFIG_BROADCOM_PHY is not set # CONFIG_BCM54140_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 From f44d7d9805a45534890f1efabf873ff0e3bb7a95 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Fri, 17 Apr 2026 11:17:28 +0530 Subject: [PATCH 0583/1133] QCLINUX: qcom.config: Enable SYSFS config Enable CONFIG_WATCHDOG_SYSFS=y in arch/arm64/configs/qcom.config. Without this option, watchdog core does not expose sysfs watchdog attributes (e.g. timeout, timeleft, status, bootstatus, etc.) under /sys/class/watchdog/watchdogN/, which matches the observed behavior on iq-9075-evk where only basic entries were present. This makes watchdog sysfs nodes available on qcom-next/6.18.y builds that use this config fragment. Signed-off-by: Anurag Pateriya --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 61c86bb5c2133..0a5e0bed4b5ab 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -77,6 +77,7 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +CONFIG_WATCHDOG_SYSFS=y CONFIG_ZRAM=y # Kubernetes support From 3c888cbe5f1a8e5a5519793ac68c98b8655d4528 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Thu, 23 Apr 2026 12:38:59 +0530 Subject: [PATCH 0584/1133] QCLINUX: prune.config: Disable MMU_500 CPRE ERRATA workaround for Qualcomm SOC Disable MMU-500's CPRE ERRATA workaround for Qualcomm SOCs, to not disable prefetch functionality by CPRE bit reset in arm_mmu500_reset path during system suspend-resume cycle. Signed-off-by: Bibek Kumar Patro --- arch/arm64/configs/prune.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index a13ad5e28c009..fd35e50601532 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -322,3 +322,4 @@ # CONFIG_SUN_PARTITION is not set # CONFIG_SYSV68_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set +# CONFIG_ARM_SMMU_MMU_500_CPRE_ERRATA is not set From d663ccc5f7eb18bf4a8c6cb5bc6bc1303cb6ed8c Mon Sep 17 00:00:00 2001 From: Anvesh Jain P Date: Thu, 7 May 2026 00:34:27 +0530 Subject: [PATCH 0585/1133] FROMLIST: arm64: defconfig: Enable Qualcomm reference device EC driver Enable EC_QCOM_HAMOA as a module to support the embedded controller found on Qualcomm CRD reference devices such as Hamoa and Glymur. Link: https://lore.kernel.org/lkml/20260511-add-driver-for-ec-v9-6-e5437c39b7f8@oss.qualcomm.com/ Reviewed-by: Pankaj Patil Signed-off-by: Anvesh Jain P --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 5d966980b175f..77e7214e11d6c 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1452,6 +1452,7 @@ CONFIG_EC_LENOVO_YOGA_C630=m CONFIG_EC_LENOVO_THINKPAD_T14S=m CONFIG_EC_QCOM_HAMOA=m CONFIG_COMMON_CLK_APPLE_NCO=m +CONFIG_EC_QCOM_HAMOA=m CONFIG_COMMON_CLK_RK808=y CONFIG_COMMON_CLK_SCMI=y CONFIG_COMMON_CLK_SCPI=y From 6539452be76c669379800ad31e9cd0e7b5c4fe9b Mon Sep 17 00:00:00 2001 From: Pragnesh Papaniya Date: Tue, 12 May 2026 14:08:03 +0530 Subject: [PATCH 0586/1133] QCLINUX: qcom.config: Enable QCOM SCMI memlat bus scaling Enable the QCOM SCMI Generic Vendor Extension protocol (=y), the remote devfreq governor (=y), and the QCOM SCMI memlat devfreq device driver (=m) for LLCC/DDR/DDR_QOS bus scaling on Glymur and Hamoa SoCs. SCMI_QCOM_MEMLAT_DEVFREQ follows QCOM_CPUCP_MBOX at =m since it depends on that mailbox transport. Link: https://lore.kernel.org/lkml/20260507062237.78051-1-sibi.sankar@oss.qualcomm.com/ Signed-off-by: Sibi Sankar --- arch/arm64/configs/qcom.config | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 0a5e0bed4b5ab..1524c38bf3b62 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -105,3 +105,8 @@ CONFIG_FS_ENCRYPTION=y # Support performance profiling CONFIG_FTRACE=y + +# QCOM SCMI memlat bus scaling +CONFIG_QCOM_SCMI_GENERIC_EXT=y +CONFIG_DEVFREQ_GOV_REMOTE=y +CONFIG_SCMI_QCOM_MEMLAT_DEVFREQ=m From 9986425237486600837a652fd46901676fee967c Mon Sep 17 00:00:00 2001 From: Aastha Pandey Date: Tue, 19 May 2026 19:17:34 +0530 Subject: [PATCH 0587/1133] QCLINUX: defconfig: Enable Qualcomm SPEL driver The Qualcomm SoC Power and Electrical Limits (SPEL) provides hardware based power monitoring and limiting capabilities for various power domains including System, SoC, CPU clusters, GPU, and various other subsystems. The driver integrates with the Linux powercap framework, exposing SPEL capabilities through powercap sysfs interfaces. This allows userspace applications and thermal management daemons to monitor energy consumption and configure power limits for optimal power/performance balance. Signed-off-by: Aastha Pandey --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 1524c38bf3b62..6da162d42359c 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -50,6 +50,7 @@ CONFIG_POWERCAP=y CONFIG_PROC_EVENTS=y CONFIG_QCA808X_PHY=m CONFIG_QCOM_QMI_COOLING=y +CONFIG_QCOM_SPEL=m CONFIG_QCOM_TGU=m CONFIG_REMOTEPROC_THERMAL=y CONFIG_SCHED_DEBUG=y From 4b3713822fc5196897e6a8725b6dcbf11d9b56f2 Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Tue, 28 Apr 2026 15:20:41 +0530 Subject: [PATCH 0588/1133] QCLINUX: arm64: configs: Add Linux software RAID support Enable Linux software RAID support using MD framework. Signed-off-by: Monish Chunara Signed-off-by: Shubham Chouhan --- arch/arm64/configs/defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 77e7214e11d6c..77ed3f5b71540 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -341,6 +341,10 @@ CONFIG_PATA_PLATFORM=y CONFIG_PATA_OF_PLATFORM=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=y +CONFIG_MD_RAID456=y CONFIG_BLK_DEV_DM=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m From 0f2be022c2131e1907d22cde199ede4e42db7155 Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Wed, 15 Apr 2026 15:23:54 +0530 Subject: [PATCH 0589/1133] QCLINUX: arm64: configs: Enable SmartPQI support Enable SmartPQI support in arm64 configs to provide HW RAID support for systems using SmartPQI-based RAID controllers. Signed-off-by: Monish Chunara Signed-off-by: Sayali Lokhande --- arch/arm64/configs/qcom.config | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 6da162d42359c..3aa1a12a8902c 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -104,6 +104,18 @@ CONFIG_SCSI_UFS_CRYPTO=y CONFIG_MMC_CRYPTO=y CONFIG_FS_ENCRYPTION=y +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=m +CONFIG_BLK_DEV_BSG=y +# +# SCSI Transports +# +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_SMARTPQI=m + # Support performance profiling CONFIG_FTRACE=y From f94a697321256113fa72b5e77e36ca21b80bf541 Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Fri, 29 May 2026 15:12:22 +0530 Subject: [PATCH 0590/1133] QCLINUX: arm64: configs: enable USB configfs UVC and UAC2 functions Enable USB configfs support for UVC (USB Video Class) and UAC2 (USB Audio Class 2) function drivers in the Qualcomm ARM64 defconfig. This allows the platform to expose video and audio gadget functions via configfs, enabling use cases such as USB camera and audio device emulation over gadget mode. These options are required for test and development scenarios involving multimedia streaming over USB. Signed-off-by: Pratham Pratap --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 3aa1a12a8902c..874a5a6f431d4 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -66,6 +66,8 @@ CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y CONFIG_UHID=m +CONFIG_USB_CONFIGFS_F_UVC=y +CONFIG_USB_CONFIGFS_F_UAC2=y CONFIG_VCPU_STALL_DETECTOR=y CONFIG_VHOST_NET=y CONFIG_VHOST_VSOCK=y From c6e9b2c69f7305e84b98bf29e29bb0243a0c6cf8 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Thu, 17 Sep 2026 10:30:25 +0530 Subject: [PATCH 0591/1133] FROMLIST: media: iris: Add support to select core for dual core platforms On platforms with two video codec cores, select the hardware core for a new session based on the current Macroblocks Per Frame (MBPF) and Macroblocks Per Second (MBPS) load on each core. The selected core is communicated to the firmware via the HFI_PROP_CORE_ID property at stream-on time. Since both cores share the same clock source, the required clock frequency is the maximum of the aggregated frequencies across both cores. The total session count limit is scaled by the number of cores, since each core independently supports sessions up to its own limit. Link: https://lore.kernel.org/all/20260917-glymur-v11-6-e0c8bc914742@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Vishnu Reddy Reviewed-by: Vikash Garodia --- .../media/platform/qcom/iris/iris_common.c | 10 +++ .../media/platform/qcom/iris/iris_common.h | 1 + drivers/media/platform/qcom/iris/iris_core.h | 5 ++ .../platform/qcom/iris/iris_hfi_common.h | 1 + .../qcom/iris/iris_hfi_gen2_command.c | 19 ++++++ .../qcom/iris/iris_hfi_gen2_defines.h | 1 + .../media/platform/qcom/iris/iris_instance.h | 2 + drivers/media/platform/qcom/iris/iris_power.c | 20 +++++- drivers/media/platform/qcom/iris/iris_utils.c | 58 ++++++++++------ drivers/media/platform/qcom/iris/iris_utils.h | 3 +- drivers/media/platform/qcom/iris/iris_vb2.c | 4 ++ drivers/media/platform/qcom/iris/iris_vidc.c | 6 +- drivers/media/platform/qcom/iris/iris_vpu3x.c | 66 +++++++++++++++++++ .../platform/qcom/iris/iris_vpu_common.h | 2 + 14 files changed, 174 insertions(+), 24 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_common.c b/drivers/media/platform/qcom/iris/iris_common.c index 25836561bcf3e..4e1e7d38e3fbd 100644 --- a/drivers/media/platform/qcom/iris/iris_common.c +++ b/drivers/media/platform/qcom/iris/iris_common.c @@ -46,6 +46,16 @@ void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) inst->metadata_idx++; } +int iris_set_core_id(struct iris_inst *inst) +{ + const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops; + + if (!inst->core_id || !hfi_ops->session_set_core_id) + return 0; + + return hfi_ops->session_set_core_id(inst, inst->core_id); +} + int iris_process_streamon_input(struct iris_inst *inst) { const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops; diff --git a/drivers/media/platform/qcom/iris/iris_common.h b/drivers/media/platform/qcom/iris/iris_common.h index b2a27b781c9ac..34e32c60f7687 100644 --- a/drivers/media/platform/qcom/iris/iris_common.h +++ b/drivers/media/platform/qcom/iris/iris_common.h @@ -11,6 +11,7 @@ struct iris_buffer; int iris_vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf); void iris_set_ts_metadata(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf); +int iris_set_core_id(struct iris_inst *inst); int iris_process_streamon_input(struct iris_inst *inst); int iris_process_streamon_output(struct iris_inst *inst); int iris_session_streamoff(struct iris_inst *inst, u32 plane); diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index d2ebead659280..7a2da9a1f0289 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -41,6 +41,11 @@ enum domain_type { DECODER = BIT(1), }; +enum iris_vcodec_core_id { + IRIS_VCODEC0 = 1, + IRIS_VCODEC1, +}; + struct qcom_ubwc_cfg_data; /** diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index 16099f9a25b65..5841e5f9c1228 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -132,6 +132,7 @@ struct iris_hfi_session_ops { int (*session_drain)(struct iris_inst *inst, u32 plane); int (*session_resume_drain)(struct iris_inst *inst, u32 plane); int (*session_close)(struct iris_inst *inst); + int (*session_set_core_id)(struct iris_inst *inst, u32 core_id); }; struct hfi_subscription_params { 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 388a36ff2b07b..b071980ddd27a 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -1359,6 +1359,24 @@ static int iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct i inst_hfi_gen2->packet->size); } +static int iris_hfi_gen2_set_core_id(struct iris_inst *inst, u32 core_id) +{ + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); + u32 payload = core_id; + + iris_hfi_gen2_packet_session_command(inst, + HFI_PROP_CORE_ID, + HFI_HOST_FLAGS_NONE, + HFI_PORT_NONE, + inst->session_id, + HFI_PAYLOAD_U32, + &payload, + sizeof(u32)); + + return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, + inst_hfi_gen2->packet->size); +} + static const struct iris_hfi_session_ops iris_hfi_gen2_session_ops = { .session_open = iris_hfi_gen2_session_open, .session_set_config_params = iris_hfi_gen2_session_set_config_params, @@ -1372,6 +1390,7 @@ static const struct iris_hfi_session_ops iris_hfi_gen2_session_ops = { .session_drain = iris_hfi_gen2_session_drain, .session_resume_drain = iris_hfi_gen2_session_resume_drain, .session_close = iris_hfi_gen2_session_close, + .session_set_core_id = iris_hfi_gen2_set_core_id, }; static struct iris_inst *iris_hfi_gen2_get_instance(void) 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 2b8b057d35a9b..96650297e7251 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -56,6 +56,7 @@ #define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123 #define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124 #define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128 +#define HFI_PROP_CORE_ID 0x030001a9 enum hfi_rate_control { HFI_RC_VBR_CFR = 0x00000000, diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h index 771269e705d98..d851ab61df6f0 100644 --- a/drivers/media/platform/qcom/iris/iris_instance.h +++ b/drivers/media/platform/qcom/iris/iris_instance.h @@ -25,6 +25,7 @@ struct iris_hfi_session_ops; * @list: used for attach an instance to the core * @kref: reference count, keeps the instance alive while the IRQ thread uses it * @core: pointer to core structure + * @core_id: specifies the hardware core on which the session runs * @session_id: id of current video session * @hfi_session_ops: iris HFI session ops * @ctx_q_lock: lock to serialize queues related ioctls @@ -73,6 +74,7 @@ struct iris_inst { struct list_head list; struct kref kref; struct iris_core *core; + u32 core_id; u32 session_id; const struct iris_hfi_session_ops *hfi_session_ops; struct mutex ctx_q_lock;/* lock to serialize queues related ioctls */ diff --git a/drivers/media/platform/qcom/iris/iris_power.c b/drivers/media/platform/qcom/iris/iris_power.c index 91aa21d4070eb..a875647b31628 100644 --- a/drivers/media/platform/qcom/iris/iris_power.c +++ b/drivers/media/platform/qcom/iris/iris_power.c @@ -75,14 +75,12 @@ static int iris_vote_interconnects(struct iris_inst *inst) return iris_set_interconnects(inst); } -static int iris_set_clocks(struct iris_inst *inst) +static u64 iris_get_required_freq(struct iris_inst *inst) { struct iris_core *core = inst->core; struct iris_inst *instance; u64 freq = 0; - int ret; - mutex_lock(&core->lock); list_for_each_entry(instance, &core->instances, list) { if (!instance->max_input_data_size) continue; @@ -90,6 +88,22 @@ static int iris_set_clocks(struct iris_inst *inst) freq += instance->power.min_freq; } + return freq; +} + +static int iris_set_clocks(struct iris_inst *inst) +{ + const struct vpu_ops *vpu_ops = inst->core->iris_platform_data->vpu_ops; + struct iris_core *core = inst->core; + u64 freq; + int ret; + + mutex_lock(&core->lock); + if (vpu_ops->get_required_freq) + freq = vpu_ops->get_required_freq(inst); + else + freq = iris_get_required_freq(inst); + core->power.clk_freq = freq; ret = iris_opp_set_rate(core->dev, freq); mutex_unlock(&core->lock); diff --git a/drivers/media/platform/qcom/iris/iris_utils.c b/drivers/media/platform/qcom/iris/iris_utils.c index 1096cc4b01c36..7299330965dab 100644 --- a/drivers/media/platform/qcom/iris/iris_utils.c +++ b/drivers/media/platform/qcom/iris/iris_utils.c @@ -7,6 +7,7 @@ #include #include "iris_instance.h" +#include "iris_vpu_common.h" #include "iris_utils.h" bool iris_res_is_less_than(u32 width, u32 height, @@ -23,7 +24,7 @@ bool iris_res_is_less_than(u32 width, u32 height, return false; } -int iris_get_mbpf(struct iris_inst *inst) +u32 iris_get_mbpf(struct iris_inst *inst) { struct v4l2_format *inp_f = inst->fmt_src; u32 height = max(inp_f->fmt.pix_mp.height, inst->crop.height); @@ -32,6 +33,13 @@ int iris_get_mbpf(struct iris_inst *inst) return NUM_MBS_PER_FRAME(height, width); } +u32 iris_get_mbps(struct iris_inst *inst) +{ + u32 fps = max(inst->frame_rate, inst->operating_rate); + + return iris_get_mbpf(inst) * fps; +} + bool iris_split_mode_enabled(struct iris_inst *inst) { return inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_NV12 || @@ -107,40 +115,52 @@ struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id) return NULL; } -int iris_check_core_mbpf(struct iris_inst *inst) +static int iris_check_core_load(struct iris_inst *inst, bool mbpf) { - struct iris_core *core = inst->core; + const struct iris_platform_data *platform_data = inst->core->iris_platform_data; + u32 max_load = mbpf ? platform_data->max_core_mbpf : platform_data->max_core_mbps; struct iris_inst *instance; - u32 total_mbpf = 0; + u32 total_load = 0; - mutex_lock(&core->lock); - list_for_each_entry(instance, &core->instances, list) - total_mbpf += iris_get_mbpf(instance); - mutex_unlock(&core->lock); + list_for_each_entry(instance, &inst->core->instances, list) + total_load += mbpf ? iris_get_mbpf(instance) : iris_get_mbps(instance); - if (total_mbpf > core->iris_platform_data->max_core_mbpf) + if (total_load > max_load) return -ENOMEM; return 0; } -int iris_check_core_mbps(struct iris_inst *inst) +int iris_check_core_mbpf(struct iris_inst *inst) { + const struct vpu_ops *vpu_ops = inst->core->iris_platform_data->vpu_ops; struct iris_core *core = inst->core; - struct iris_inst *instance; - u32 total_mbps = 0, fps = 0; + int ret; mutex_lock(&core->lock); - list_for_each_entry(instance, &core->instances, list) { - fps = max(instance->frame_rate, instance->operating_rate); - total_mbps += iris_get_mbpf(instance) * fps; - } + if (vpu_ops->check_core_load) + ret = vpu_ops->check_core_load(inst, true); + else + ret = iris_check_core_load(inst, true); mutex_unlock(&core->lock); - if (total_mbps > core->iris_platform_data->max_core_mbps) - return -ENOMEM; + return ret; +} - return 0; +int iris_check_core_mbps(struct iris_inst *inst) +{ + const struct vpu_ops *vpu_ops = inst->core->iris_platform_data->vpu_ops; + struct iris_core *core = inst->core; + int ret; + + mutex_lock(&core->lock); + if (vpu_ops->check_core_load) + ret = vpu_ops->check_core_load(inst, false); + else + ret = iris_check_core_load(inst, false); + mutex_unlock(&core->lock); + + return ret; } bool is_rotation_90_or_270(struct iris_inst *inst) diff --git a/drivers/media/platform/qcom/iris/iris_utils.h b/drivers/media/platform/qcom/iris/iris_utils.h index be23acc0e8484..98a898de465a6 100644 --- a/drivers/media/platform/qcom/iris/iris_utils.h +++ b/drivers/media/platform/qcom/iris/iris_utils.h @@ -43,7 +43,8 @@ static inline enum iris_buffer_type iris_v4l2_type_to_driver(u32 type) bool iris_res_is_less_than(u32 width, u32 height, u32 ref_width, u32 ref_height); -int iris_get_mbpf(struct iris_inst *inst); +u32 iris_get_mbpf(struct iris_inst *inst); +u32 iris_get_mbps(struct iris_inst *inst); bool iris_split_mode_enabled(struct iris_inst *inst); bool iris_fmt_is_8bit(u32 pixelformat); bool iris_fmt_is_10bit(u32 pixelformat); diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index 8faf709c26c12..b190ebac08a06 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -180,6 +180,10 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count) if (ret) goto error; + ret = iris_set_core_id(inst); + if (ret) + goto error; + if (V4L2_TYPE_IS_OUTPUT(q->type)) { if (inst->domain == DECODER) ret = iris_vdec_streamon_input(inst); diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index f41a00cf698af..64b552f8251bd 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -58,16 +58,20 @@ void iris_inst_put(struct iris_inst *inst) static int iris_add_session(struct iris_inst *inst) { + const struct iris_platform_data *plat = inst->core->iris_platform_data; + u32 max_session_count = plat->max_session_count; struct iris_core *core = inst->core; struct iris_inst *iter; u32 count = 0; + max_session_count *= max(plat->num_cores, 1); + guard(mutex)(&core->lock); list_for_each_entry(iter, &core->instances, list) count++; - if (count >= core->iris_platform_data->max_session_count) + if (count >= max_session_count) return -EBUSY; list_add_tail(&inst->list, &core->instances); diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index 39bf924fb5e98..43b2caf94c71f 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -334,6 +334,70 @@ static void iris_vpu36_program_bootup_registers(struct iris_core *core) writel(0x0, core->reg_base + CPU_CS_SCIACMDARG3); } +static int iris_vpu36_check_core_load(struct iris_inst *inst, bool mbpf) +{ + const struct iris_platform_data *platform_data = inst->core->iris_platform_data; + u32 max_load = mbpf ? platform_data->max_core_mbpf : platform_data->max_core_mbps; + u32 max_session_cnt = platform_data->max_session_count; + u32 core0_session_cnt = 0, core1_session_cnt = 0; + u32 core0_load = 0, core1_load = 0; + bool select_core0, select_core1; + struct iris_inst *instance; + u32 load, new_load; + + list_for_each_entry(instance, &inst->core->instances, list) { + load = mbpf ? iris_get_mbpf(instance) : iris_get_mbps(instance); + + if (instance->core_id == IRIS_VCODEC0) { + core0_load += load; + core0_session_cnt++; + } else if (instance->core_id == IRIS_VCODEC1) { + core1_load += load; + core1_session_cnt++; + } + } + + if (inst->core_id == IRIS_VCODEC0) + return core0_load <= max_load ? 0 : -ENOMEM; + else if (inst->core_id == IRIS_VCODEC1) + return core1_load <= max_load ? 0 : -ENOMEM; + + new_load = mbpf ? iris_get_mbpf(inst) : iris_get_mbps(inst); + + select_core0 = core0_load + new_load <= max_load && core0_session_cnt < max_session_cnt; + select_core1 = core1_load + new_load <= max_load && core1_session_cnt < max_session_cnt; + + if (select_core0 && select_core1) + inst->core_id = (core0_load <= core1_load) ? IRIS_VCODEC0 : IRIS_VCODEC1; + else if (select_core0) + inst->core_id = IRIS_VCODEC0; + else if (select_core1) + inst->core_id = IRIS_VCODEC1; + else + return -ENOMEM; + + return 0; +} + +static u64 iris_vpu36_get_required_freq(struct iris_inst *inst) +{ + u64 vcodec0_freq = 0, vcodec1_freq = 0; + struct iris_core *core = inst->core; + struct iris_inst *instance; + + list_for_each_entry(instance, &core->instances, list) { + if (!instance->max_input_data_size) + continue; + + if (instance->core_id == IRIS_VCODEC0) + vcodec0_freq += instance->power.min_freq; + else if (instance->core_id == IRIS_VCODEC1) + vcodec1_freq += instance->power.min_freq; + } + + return max(vcodec0_freq, vcodec1_freq); +} + const struct vpu_ops iris_vpu3_ops = { .power_off_hw = iris_vpu3_power_off_hardware, .power_on_hw = iris_vpu_power_on_hw, @@ -378,4 +442,6 @@ const struct vpu_ops iris_vpu36_ops = { .set_hwmode = iris_vpu36_set_hwmode, .set_preset_registers = iris_vpu_set_preset_registers, .interrupt_init = iris_vpu_interrupt_init, + .check_core_load = iris_vpu36_check_core_load, + .get_required_freq = iris_vpu36_get_required_freq, }; \ No newline at end of file diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index 5a9ca9d1902a6..206f1e476d3ce 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -24,6 +24,8 @@ struct vpu_ops { void (*program_bootup_registers)(struct iris_core *core); u64 (*calc_freq)(struct iris_inst *inst, size_t data_size); int (*set_hwmode)(struct iris_core *core); + int (*check_core_load)(struct iris_inst *inst, bool mbpf); + u64 (*get_required_freq)(struct iris_inst *inst); void (*set_preset_registers)(struct iris_core *core); void (*interrupt_init)(struct iris_core *core); void (*disable_arp)(struct iris_core *core); From b3023b8d9992095a56fd303ad40956ef0f5ba50a Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Thu, 17 Sep 2026 10:30:26 +0530 Subject: [PATCH 0592/1133] FROMLIST: media: iris: Add platform data for glymur On glymur platform, the iris core shares most properties with the iris core on the SM8550 platform. The major difference is that glymur integrates two codec cores (vcodec0 and vcodec1), while SM8550 has only one. Add glymur specific platform data, reusing SM8550 definitions wherever applicable. Link: https://lore.kernel.org/all/20260917-glymur-v11-7-e0c8bc914742@oss.qualcomm.com/ Reviewed-by: Vikash Garodia Reviewed-by: Dmitry Baryshkov Signed-off-by: Vishnu Reddy --- drivers/media/platform/qcom/iris/Makefile | 1 + .../platform/qcom/iris/iris_platform_common.h | 5 ++ .../platform/qcom/iris/iris_platform_glymur.c | 78 +++++++++++++++++++ .../platform/qcom/iris/iris_platform_glymur.h | 15 ++++ .../platform/qcom/iris/iris_platform_vpu3x.c | 35 +++++++++ drivers/media/platform/qcom/iris/iris_probe.c | 4 + 6 files changed, 138 insertions(+) create mode 100644 drivers/media/platform/qcom/iris/iris_platform_glymur.c create mode 100644 drivers/media/platform/qcom/iris/iris_platform_glymur.h diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index bbd1f724963e6..0c0d4a3472185 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -24,6 +24,7 @@ qcom-iris-objs += iris_buffer.o \ iris_vb2.o \ iris_vdec.o \ iris_venc.o \ + iris_platform_glymur.o \ iris_vpu2.o \ iris_vpu3x.o \ iris_vpu4x.o \ diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 49a3dcec7546d..1eb8f33a7564f 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -43,6 +43,10 @@ struct iris_inst; #define BITRATE_DEFAULT_AR50LT 20000000 #define MIN_QP_8BIT_AR50LT 0 +#define VIDEO_REGION_SECURE_FW_REGION_ID 0 +#define VIDEO_REGION_VM0_SECURE_NP_ID 1 +#define VIDEO_REGION_VM0_NONSECURE_NP_ID 5 + enum stage_type { STAGE_1 = 1, STAGE_2 = 2, @@ -62,6 +66,7 @@ extern const struct iris_firmware_data iris_hfi_gen2_ar50lt_data; extern const struct platform_inst_slice_caps iris_vpu2_vpu3x_slice_caps; extern const struct platform_inst_slice_caps iris_ar50lt_slice_caps; +extern const struct iris_platform_data glymur_data; extern const struct iris_platform_data milos_data; extern const struct iris_platform_data qcm2290_data; extern const struct iris_platform_data qcs8300_data; diff --git a/drivers/media/platform/qcom/iris/iris_platform_glymur.c b/drivers/media/platform/qcom/iris/iris_platform_glymur.c new file mode 100644 index 0000000000000..49edae8120fed --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_glymur.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_core.h" +#include "iris_platform_common.h" + +const struct iris_power_domain_data iris_glymur_ctrl_data = { + .pd_names = (const char *[]) { + "venus", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "core_iface", "core_freerun", "core", + }, + .clk_cnt = 3, +}; + +const struct iris_power_domain_data iris_glymur_vcodec_data[] = { + { + .pd_names = (const char *[]) { + "vcodec0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec0_iface", "vcodec0_core_freerun", "vcodec0_core", + }, + .clk_cnt = 3, + }, + { + .pd_names = (const char *[]) { + "vcodec1", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec1_iface", "vcodec1_core_freerun", "vcodec1_core", + }, + .clk_cnt = 3, + }, +}; + +const char * const iris_glymur_clk_reset_table[] = { + "core_bus", + "vcodec0_bus", + "core", + "vcodec0_core", + "vcodec1_bus", + "vcodec1_core", +}; + +const char * const iris_glymur_opp_clk_table[] = { + "vcodec0_core", + "vcodec1_core", + "core", + NULL, +}; + +const struct tz_cp_config iris_glymur_tz_cp_config[] = { + { + .cp_start = VIDEO_REGION_SECURE_FW_REGION_ID, + .cp_size = 0, + .cp_nonpixel_start = 0, + .cp_nonpixel_size = 0x1000000, + }, + { + .cp_start = VIDEO_REGION_VM0_SECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x1000000, + .cp_nonpixel_size = 0x24800000, + }, + { + .cp_start = VIDEO_REGION_VM0_NONSECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x25800000, + .cp_nonpixel_size = 0xda600000, + }, +}; diff --git a/drivers/media/platform/qcom/iris/iris_platform_glymur.h b/drivers/media/platform/qcom/iris/iris_platform_glymur.h new file mode 100644 index 0000000000000..9f2877ec9901b --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_glymur.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_PLATFORM_GLYMUR_H__ +#define __IRIS_PLATFORM_GLYMUR_H__ + +extern const struct iris_power_domain_data iris_glymur_ctrl_data; +extern const struct iris_power_domain_data iris_glymur_vcodec_data[2]; +extern const char * const iris_glymur_clk_reset_table[6]; +extern const char * const iris_glymur_opp_clk_table[4]; +extern const struct tz_cp_config iris_glymur_tz_cp_config[3]; + +#endif /* __IRIS_PLATFORM_GLYMUR_H__ */ diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index 15e69d7e9c7b6..6ed4de2d15cec 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -12,6 +12,7 @@ #include "iris_vpu_buffer.h" #include "iris_vpu_common.h" +#include "iris_platform_glymur.h" #include "iris_platform_qcs8300.h" #include "iris_platform_sm8550.h" #include "iris_platform_sm8650.h" @@ -50,6 +51,12 @@ static const struct iris_firmware_desc iris_vpu35_p4_gen2_desc = { .fwname = "qcom/vpu/vpu35_p4.mbn", }; +static const struct iris_firmware_desc iris_vpu36_p4_s7_gen2_desc = { + .firmware_data = &iris_hfi_gen2_data, + .get_vpu_buffer_size = iris_vpu_buf_size, + .fwname = "qcom/vpu/vpu36_p4_s7.mbn", +}; + static const u32 iris_fmts_vpu3x_dec[] = { V4L2_PIX_FMT_H264, V4L2_PIX_FMT_HEVC, @@ -85,6 +92,34 @@ static const struct tz_cp_config tz_cp_config_vpu3[] = { }, }; +const struct iris_platform_data glymur_data = { + .firmware_desc_gen2 = &iris_vpu36_p4_s7_gen2_desc, + .vpu_ops = &iris_vpu36_ops, + .icc_tbl = iris_icc_info_vpu3x, + .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), + .clk_rst_tbl = iris_glymur_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(iris_glymur_clk_reset_table), + .bw_tbl_dec = iris_bw_table_dec_vpu3x, + .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), + .ctrl_data = &iris_glymur_ctrl_data, + .vcodec_data = iris_glymur_vcodec_data, + .opp_pd_tbl = iris_opp_pd_table_vpu3x, + .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), + .opp_clk_tbl = iris_glymur_opp_clk_table, + /* Upper bound of DMA address range */ + .dma_mask = 0xffe00000 - 1, + .inst_iris_fmts = iris_fmts_vpu3x_dec, + .inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu3x_dec), + .inst_caps = &platform_inst_cap_sm8550, + .tz_cp_config_data = iris_glymur_tz_cp_config, + .tz_cp_config_data_size = ARRAY_SIZE(iris_glymur_tz_cp_config), + .num_vpp_pipe = 4, + .max_session_count = 16, + .num_cores = 2, + .max_core_mbpf = NUM_MBS_8K * 2, + .max_core_mbps = ((8192 * 4320) / 256) * 60, +}; + /* * Shares most of SM8550 data except: * - inst_caps to platform_inst_cap_qcs8300 diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index acf73a24b9f96..6b683050dd245 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -600,6 +600,10 @@ static const struct dev_pm_ops iris_pm_ops = { }; static const struct of_device_id iris_dt_match[] = { + { + .compatible = "qcom,glymur-iris", + .data = &glymur_data, + }, { .compatible = "qcom,milos-iris", .data = &milos_data, From 2e4f30cddb2f88d757091cfafa5f3a87490a3271 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Sat, 1 Aug 2026 13:07:27 +0530 Subject: [PATCH 0593/1133] FROMLIST: dt-bindings: media: qcom,sc7280-venus: Add dma-coherent property While testing with some higher resolution clips, the venus hardware triggers a fault due to wrong input data being received. Corruption was also observed in the captured output when the client dumped it to a file. On debugging, this was traced to the venus node not declaring dma-coherent. As a result, DMA buffers shared between the CPU and the venus video hardware/controller are not guaranteed to be I/O coherent: CPU writes to an input buffer can remain in CPU caches without being visible to the video hardware when it reads the same buffer, so the hardware receives input data that does not match what the CPU wrote. Likewise, on the capture path, data written by the video hardware to the output buffer may not be visible to the CPU, so the client reads stale or partial data, resulting in corruption. Add the dma-coherent property to the venus node so that DMA buffers shared between the CPU and the video hardware and controller remain coherent. Link: https://lore.kernel.org/all/20260801-iris-fixes-dma-pseq-fint-v1-1-aba0cb22f6ab@oss.qualcomm.com/ Fixes: 37613aee2179 ("arm64: dts: qcom: sc7280: Add venus DT node") Cc: stable@vger.kernel.org Signed-off-by: Vishnu Reddy --- .../devicetree/bindings/media/qcom,sc7280-venus.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml b/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml index 9725fcb761dc0..cc31f3ba7e7e0 100644 --- a/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml @@ -42,6 +42,8 @@ properties: - const: vcodec_core - const: vcodec_bus + dma-coherent: true + iommus: maxItems: 1 @@ -85,6 +87,7 @@ properties: required: - compatible + - dma-coherent - power-domain-names - iommus @@ -119,6 +122,8 @@ examples: <&mmss_noc MASTER_VIDEO_P0 0 &mc_virt SLAVE_EBI1 0>; interconnect-names = "cpu-cfg", "video-mem"; + dma-coherent; + iommus = <&apps_smmu 0x2180 0x20>; memory-region = <&video_mem>; From 05cd7e6860a575319ebb3e583cb0300414192a2e Mon Sep 17 00:00:00 2001 From: Renjiang Han Date: Sat, 15 Aug 2026 21:55:01 +0530 Subject: [PATCH 0594/1133] FROMLIST: media: qcom: iris: add firmware debug logging support Iris does not provide runtime control for firmware debug logging, which makes firmware-side failures harder to diagnose without rebuilding or reloading the driver. Add a debugfs fw_level file under the Iris debugfs directory so the firmware debug log mask can be configured at runtime. Keep the default mask limited to firmware error and fatal messages to avoid enabling verbose firmware logging by default. Store the mask per Iris core, and normalize values written through debugfs so userspace reads back the same mask that is sent to firmware. Use READ_ONCE() and WRITE_ONCE() for lockless debugfs access and HFI packet construction. Program the firmware debug configuration during core initialization and before opening a new session. This lets a fw_level value written before session start take effect for that session without requiring a driver reload. Add HFI Gen1 and Gen2 support for sending the firmware debug configuration to firmware, and flush firmware debug messages from the debug queue. Firmware error and fatal messages are emitted through dev_err_ratelimited(), while other firmware debug messages use dev_dbg(). Treat failures to configure firmware debug logging as non-fatal, since they should not prevent video sessions from running. Link: https://lore.kernel.org/linux-media/20260815-media-qcom-iris-fw-log-v1-1-c8a70eb08849@oss.qualcomm.com/ Tested-by: Wangao Wang Signed-off-by: Renjiang Han --- drivers/media/platform/qcom/iris/Makefile | 1 + drivers/media/platform/qcom/iris/iris_core.h | 7 +++- .../media/platform/qcom/iris/iris_debugfs.c | 42 +++++++++++++++++++ .../media/platform/qcom/iris/iris_debugfs.h | 14 +++++++ .../platform/qcom/iris/iris_hfi_common.c | 35 ++++++++++++++++ .../platform/qcom/iris/iris_hfi_common.h | 10 +++++ .../qcom/iris/iris_hfi_gen1_command.c | 30 +++++++++++++ .../qcom/iris/iris_hfi_gen1_defines.h | 7 ++++ .../qcom/iris/iris_hfi_gen1_response.c | 31 +++++++++++--- .../qcom/iris/iris_hfi_gen2_command.c | 21 ++++++++++ .../qcom/iris/iris_hfi_gen2_defines.h | 3 ++ .../platform/qcom/iris/iris_hfi_gen2_packet.c | 29 +++++++++++++ .../platform/qcom/iris/iris_hfi_gen2_packet.h | 1 + .../qcom/iris/iris_hfi_gen2_response.c | 10 +++-- drivers/media/platform/qcom/iris/iris_probe.c | 5 +++ drivers/media/platform/qcom/iris/iris_vb2.c | 6 ++- 16 files changed, 241 insertions(+), 11 deletions(-) create mode 100644 drivers/media/platform/qcom/iris/iris_debugfs.c create mode 100644 drivers/media/platform/qcom/iris/iris_debugfs.h diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index 0c0d4a3472185..c6dbb36a90668 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -2,6 +2,7 @@ qcom-iris-objs += iris_buffer.o \ iris_common.o \ iris_core.o \ iris_ctrls.o \ + iris_debugfs.o \ iris_firmware.o \ iris_hfi_common.o \ iris_hfi_gen1.o \ diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index 7a2da9a1f0289..26e1a564a9966 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -47,6 +47,7 @@ enum iris_vcodec_core_id { }; struct qcom_ubwc_cfg_data; +struct dentry; /** * struct iris_core - holds core parameters valid for all instances @@ -85,7 +86,9 @@ struct qcom_ubwc_cfg_data; * @command_queue: shared interface queue to send commands to firmware * @message_queue: shared interface queue to receive responses from firmware * @debug_queue: shared interface queue to receive debug info from firmware - * @lock: a lock for this strucure + * @root: debugfs root directory + * @fw_debug: firmware debug log mask + * @lock: a lock for this structure * @response_packet: a pointer to response packet from fw to driver * @header_id: id of packet header * @packet_id: id of packet @@ -135,6 +138,8 @@ struct iris_core { struct iris_iface_q_info command_queue; struct iris_iface_q_info message_queue; struct iris_iface_q_info debug_queue; + struct dentry *root; + u32 fw_debug; struct mutex lock; /* lock for core related operations */ u8 *response_packet; u32 header_id; diff --git a/drivers/media/platform/qcom/iris/iris_debugfs.c b/drivers/media/platform/qcom/iris/iris_debugfs.c new file mode 100644 index 0000000000000..6122b994ad0aa --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_debugfs.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include + +#include "iris_core.h" +#include "iris_debugfs.h" + +static int iris_fw_level_get(void *data, u64 *val) +{ + struct iris_core *core = data; + + *val = READ_ONCE(core->fw_debug); + + return 0; +} + +static int iris_fw_level_set(void *data, u64 val) +{ + struct iris_core *core = data; + + WRITE_ONCE(core->fw_debug, (u32)val & IRIS_FW_DEBUG_LOGMASK); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(iris_fw_level_fops, iris_fw_level_get, + iris_fw_level_set, "0x%08llx\n"); + +void iris_debugfs_init(struct iris_core *core) +{ + core->root = debugfs_create_dir("iris", NULL); + debugfs_create_file("fw_level", 0600, core->root, core, + &iris_fw_level_fops); +} + +void iris_debugfs_deinit(struct iris_core *core) +{ + debugfs_remove(core->root); +} diff --git a/drivers/media/platform/qcom/iris/iris_debugfs.h b/drivers/media/platform/qcom/iris/iris_debugfs.h new file mode 100644 index 0000000000000..aa3cb97eb2b2e --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_debugfs.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_DEBUGFS_H__ +#define __IRIS_DEBUGFS_H__ + +struct iris_core; + +void iris_debugfs_init(struct iris_core *core); +void iris_debugfs_deinit(struct iris_core *core); + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c index dad906d03fdcb..c64352483e2fb 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c @@ -87,9 +87,44 @@ int iris_hfi_core_init(struct iris_core *core) if (ret) return ret; + if (hfi_ops->sys_set_debug) { + ret = hfi_ops->sys_set_debug(core); + if (ret) + dev_warn(core->dev, + "failed to configure firmware debug logging: %d\n", + ret); + } + return hfi_ops->sys_interframe_powercollapse(core); } +int iris_hfi_set_debug(struct iris_core *core) +{ + const struct iris_hfi_sys_ops *hfi_ops = core->hfi_sys_ops; + int ret = 0; + + if (!hfi_ops->sys_set_debug) + return 0; + + ret = pm_runtime_resume_and_get(core->dev); + if (ret < 0) + return ret; + + mutex_lock(&core->lock); + if (core->state != IRIS_CORE_INIT) { + ret = 0; + goto unlock; + } + + ret = hfi_ops->sys_set_debug(core); + +unlock: + mutex_unlock(&core->lock); + pm_runtime_put_autosuspend(core->dev); + + return ret; +} + irqreturn_t iris_hfi_isr(int irq, void *data) { disable_irq_nosync(irq); diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index 5841e5f9c1228..95a2186fb8269 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -105,9 +105,18 @@ struct iris_hfi_prop_type_handle { int (*handle)(struct iris_inst *inst, u32 plane); }; +#define IRIS_FW_DEBUG_LOW 0x00000001 +#define IRIS_FW_DEBUG_MEDIUM 0x00000002 +#define IRIS_FW_DEBUG_HIGH 0x00000004 +#define IRIS_FW_DEBUG_ERROR 0x00000008 +#define IRIS_FW_DEBUG_FATAL 0x00000010 +#define IRIS_FW_DEBUG_PERF 0x00000020 +#define IRIS_FW_DEBUG_LOGMASK 0x0fffffff + struct iris_hfi_sys_ops { int (*sys_init)(struct iris_core *core); int (*sys_image_version)(struct iris_core *core); + int (*sys_set_debug)(struct iris_core *core); int (*sys_interframe_powercollapse)(struct iris_core *core); int (*sys_pc_prep)(struct iris_core *core); @@ -155,6 +164,7 @@ u32 iris_hfi_get_v4l2_color_primaries(u32 hfi_primaries); u32 iris_hfi_get_v4l2_transfer_char(u32 hfi_characterstics); u32 iris_hfi_get_v4l2_matrix_coefficients(u32 hfi_coefficients); int iris_hfi_core_init(struct iris_core *core); +int iris_hfi_set_debug(struct iris_core *core); int iris_hfi_pm_suspend(struct iris_core *core); int iris_hfi_pm_resume(struct iris_core *core); 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 47e9147a9b6d3..997a35809c647 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -53,6 +53,35 @@ static int iris_hfi_gen1_sys_image_version(struct iris_core *core) return iris_hfi_queue_cmd_write_locked(core, &packet, packet.hdr.size); } +static int iris_hfi_gen1_sys_set_debug(struct iris_core *core) +{ + struct hfi_sys_set_property_pkt *pkt; + struct hfi_debug_config *hfi; + u32 fw_debug; + u32 packet_size; + int ret; + + packet_size = struct_size(pkt, data, 1) + sizeof(*hfi); + pkt = kzalloc(packet_size, GFP_KERNEL); + if (!pkt) + return -ENOMEM; + + hfi = (struct hfi_debug_config *)&pkt->data[1]; + + pkt->hdr.size = packet_size; + pkt->hdr.pkt_type = HFI_CMD_SYS_SET_PROPERTY; + pkt->num_properties = 1; + pkt->data[0] = HFI_PROPERTY_SYS_DEBUG_CONFIG; + fw_debug = READ_ONCE(core->fw_debug) & IRIS_FW_DEBUG_LOGMASK; + hfi->config = fw_debug; + hfi->mode = fw_debug ? HFI_DEBUG_MODE_QUEUE : 0; + + ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt->hdr.size); + kfree(pkt); + + return ret; +} + static int iris_hfi_gen1_sys_interframe_powercollapse(struct iris_core *core) { struct hfi_sys_set_property_pkt *pkt; @@ -1179,6 +1208,7 @@ static struct iris_inst *iris_hfi_gen1_get_instance(void) static const struct iris_hfi_sys_ops iris_hfi_gen1_sys_ops = { .sys_init = iris_hfi_gen1_sys_init, .sys_image_version = iris_hfi_gen1_sys_image_version, + .sys_set_debug = iris_hfi_gen1_sys_set_debug, .sys_interframe_powercollapse = iris_hfi_gen1_sys_interframe_powercollapse, .sys_pc_prep = iris_hfi_gen1_sys_pc_prep, 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 6981e6e84fd8d..5a6b8a1efa773 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h @@ -81,6 +81,13 @@ #define HFI_BUFFER_INTERNAL_SCRATCH_1 0x7 #define HFI_BUFFER_INTERNAL_SCRATCH_2 0x8 +#define HFI_DEBUG_MODE_QUEUE 0x01 +struct hfi_debug_config { + u32 config; + u32 mode; +}; + +#define HFI_PROPERTY_SYS_DEBUG_CONFIG 0x1 #define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL 0x5 #define HFI_PROPERTY_SYS_IMAGE_VERSION 0x6 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 ffa98139f0eb8..355bf24c94bc6 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c @@ -756,16 +756,35 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response static void iris_hfi_gen1_flush_debug_queue(struct iris_core *core, u8 *packet) { - struct hfi_msg_sys_coverage_pkt *pkt; + struct hfi_msg_sys_debug_pkt *pkt; + struct hfi_pkt_hdr *hdr; + u32 log_size; + u8 *log; while (!iris_hfi_queue_dbg_read(core, packet)) { - pkt = (struct hfi_msg_sys_coverage_pkt *)packet; + hdr = (struct hfi_pkt_hdr *)packet; - if (pkt->hdr.pkt_type != HFI_MSG_SYS_COV) { - struct hfi_msg_sys_debug_pkt *pkt = - (struct hfi_msg_sys_debug_pkt *)packet; + if (hdr->size <= sizeof(*hdr)) + continue; + + if (hdr->size >= IFACEQ_CORE_PKT_SIZE) + continue; + + if (hdr->pkt_type != HFI_MSG_SYS_COV) { + pkt = (struct hfi_msg_sys_debug_pkt *)packet; + + if (hdr->size <= sizeof(*pkt)) + continue; + + log = pkt->msg_data; + log_size = hdr->size - sizeof(*pkt); + if (pkt->msg_size < log_size) + log_size = pkt->msg_size; - dev_dbg(core->dev, "%s", pkt->msg_data); + if (pkt->msg_type & (IRIS_FW_DEBUG_ERROR | IRIS_FW_DEBUG_FATAL)) + dev_err_ratelimited(core->dev, "%.*s", (int)log_size, log); + else + dev_dbg(core->dev, "%.*s", (int)log_size, log); } } } 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 b071980ddd27a..f8b38f82ae309 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -17,6 +17,9 @@ #define SYS_IFPC_PKT_SIZE (sizeof(struct iris_hfi_header) + \ sizeof(struct iris_hfi_packet) + sizeof(u32)) +#define SYS_DEBUG_PKT_SIZE (sizeof(struct iris_hfi_header) + \ + 2 * (sizeof(struct iris_hfi_packet) + sizeof(u32))) + #define SYS_NO_PAYLOAD_PKT_SIZE (sizeof(struct iris_hfi_header) + \ sizeof(struct iris_hfi_packet)) @@ -54,6 +57,23 @@ static int iris_hfi_gen2_sys_image_version(struct iris_core *core) return ret; } +static int iris_hfi_gen2_sys_set_debug(struct iris_core *core) +{ + struct iris_hfi_header *hdr; + int ret; + + hdr = kzalloc(SYS_DEBUG_PKT_SIZE, GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + iris_hfi_gen2_packet_set_debug(core, hdr); + ret = iris_hfi_queue_cmd_write_locked(core, hdr, hdr->size); + + kfree(hdr); + + return ret; +} + static int iris_hfi_gen2_sys_interframe_powercollapse(struct iris_core *core) { struct iris_hfi_header *hdr; @@ -1410,6 +1430,7 @@ static struct iris_inst *iris_hfi_gen2_get_instance(void) static const struct iris_hfi_sys_ops iris_hfi_gen2_sys_ops = { .sys_init = iris_hfi_gen2_sys_init, .sys_image_version = iris_hfi_gen2_sys_image_version, + .sys_set_debug = iris_hfi_gen2_sys_set_debug, .sys_interframe_powercollapse = iris_hfi_gen2_sys_interframe_powercollapse, .sys_pc_prep = iris_hfi_gen2_sys_pc_prep, 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 96650297e7251..8a8ac4f4e0edc 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h @@ -39,6 +39,9 @@ #define HFI_PROP_UBWC_BANK_SWZL_LEVEL2 0x03000007 #define HFI_PROP_UBWC_BANK_SWZL_LEVEL3 0x03000008 #define HFI_PROP_UBWC_BANK_SPREADING 0x03000009 +#define HFI_PROP_DEBUG_CONFIG 0x0300000a +#define HFI_PROP_DEBUG_LOG_LEVEL 0x0300000b +#define HFI_DEBUG_CONFIG_DEFAULT 0x00000000 #define HFI_PROP_CODEC 0x03000100 #define HFI_PROP_COLOR_FORMAT 0x03000101 #define HFI_PROP_BITSTREAM_RESOLUTION 0x03000103 diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c index 6e04175eb904b..452a68ce97bcb 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c @@ -229,6 +229,35 @@ void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_ NULL, 0); } +void iris_hfi_gen2_packet_set_debug(struct iris_core *core, struct iris_hfi_header *hdr) +{ + u32 fw_debug; + u32 payload; + + iris_hfi_gen2_create_header(hdr, 0, core->header_id++); + + payload = HFI_DEBUG_CONFIG_DEFAULT; + iris_hfi_gen2_create_packet(hdr, + HFI_PROP_DEBUG_CONFIG, + HFI_HOST_FLAGS_NONE, + HFI_PAYLOAD_U32_ENUM, + HFI_PORT_NONE, + core->packet_id++, + &payload, + sizeof(u32)); + + fw_debug = READ_ONCE(core->fw_debug) & IRIS_FW_DEBUG_LOGMASK; + payload = fw_debug; + iris_hfi_gen2_create_packet(hdr, + HFI_PROP_DEBUG_LOG_LEVEL, + HFI_HOST_FLAGS_NONE, + HFI_PAYLOAD_U32_ENUM, + HFI_PORT_NONE, + core->packet_id++, + &payload, + sizeof(u32)); +} + void iris_hfi_gen2_packet_session_command(struct iris_inst *inst, u32 pkt_type, u32 flags, u32 port, u32 session_id, u32 payload_type, void *payload, diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h index 25b9582349ca1..aff025fbf5ead 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h @@ -111,6 +111,7 @@ u32 iris_hfi_gen2_get_color_info(u32 matrix_coeff, u32 transfer_char, u32 primar void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_header *hdr); void iris_hfi_gen2_packet_image_version(struct iris_core *core, struct iris_hfi_header *hdr); +void iris_hfi_gen2_packet_set_debug(struct iris_core *core, struct iris_hfi_header *hdr); void iris_hfi_gen2_packet_session_command(struct iris_inst *inst, u32 pkt_type, u32 flags, u32 port, u32 session_id, u32 payload_type, void *payload, 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 f0782c4b1e6e8..4ee5aa7d6b3c4 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -992,20 +992,24 @@ static int iris_hfi_gen2_handle_response(struct iris_core *core, void *response) static void iris_hfi_gen2_flush_debug_queue(struct iris_core *core, u8 *packet) { struct hfi_debug_header *pkt; + u32 log_size; u8 *log; while (!iris_hfi_queue_dbg_read(core, packet)) { pkt = (struct hfi_debug_header *)packet; - if (pkt->size < sizeof(*pkt)) + if (pkt->size <= sizeof(*pkt) + 1) continue; if (pkt->size >= IFACEQ_CORE_PKT_SIZE) continue; - packet[pkt->size] = '\0'; log = (u8 *)packet + sizeof(*pkt) + 1; - dev_dbg(core->dev, "%s", log); + log_size = pkt->size - sizeof(*pkt) - 1; + if (pkt->debug_level & (IRIS_FW_DEBUG_ERROR | IRIS_FW_DEBUG_FATAL)) + dev_err_ratelimited(core->dev, "%.*s", (int)log_size, log); + else + dev_dbg(core->dev, "%.*s", (int)log_size, log); } } diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 6b683050dd245..b0695f84dfc03 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -12,6 +12,7 @@ #include #include +#include "iris_debugfs.h" #include "iris_core.h" #include "iris_ctrls.h" #include "iris_vidc.h" @@ -435,6 +436,7 @@ static void iris_remove(struct platform_device *pdev) iris_deinit_cb_devs(core); iris_unreserve_iova_region(core->dev, core->iova_state); + iris_debugfs_deinit(core); mutex_destroy(&core->lock); } @@ -459,6 +461,7 @@ static int iris_probe(struct platform_device *pdev) if (!core) return -ENOMEM; core->dev = dev; + core->fw_debug = IRIS_FW_DEBUG_ERROR | IRIS_FW_DEBUG_FATAL; core->state = IRIS_CORE_DEINIT; mutex_init(&core->lock); @@ -538,6 +541,8 @@ static int iris_probe(struct platform_device *pdev) if (ret) goto err_vdev_unreg_enc; + iris_debugfs_init(core); + return 0; err_vdev_unreg_enc: diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c index b190ebac08a06..bd8e425751ebb 100644 --- a/drivers/media/platform/qcom/iris/iris_vb2.c +++ b/drivers/media/platform/qcom/iris/iris_vb2.c @@ -131,7 +131,9 @@ int iris_vb2_queue_setup(struct vb2_queue *q, goto unlock; if (!inst->once_per_session_set) { - inst->once_per_session_set = true; + ret = iris_hfi_set_debug(core); + if (ret) + dev_warn(core->dev, "failed to set firmware debug level: %d\n", ret); ret = inst->hfi_session_ops->session_open(inst); if (ret) { @@ -140,6 +142,8 @@ int iris_vb2_queue_setup(struct vb2_queue *q, goto unlock; } + inst->once_per_session_set = true; + ret = iris_inst_change_state(inst, IRIS_INST_INIT); if (ret) goto unlock; From 0178b58823b68b78f084f537f5606a69e300164c Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Sat, 19 Sep 2026 10:14:55 +0530 Subject: [PATCH 0595/1133] FROMLIST: dt-bindings: media: qcom,nord-iris: Add nord video codec The nord platform uses the same dual-core iris video codec hardware as glymur, with matching clocks and power domains. Add a qcom,nord-iris compatible string that falls back to qcom,glymur-iris, allowing nord to reuse the existing glymur iris devicetree schema. Link: https://lore.kernel.org/all/20260919-nord-iris-v1-1-94428761ec06@oss.qualcomm.com/ Signed-off-by: Vishnu Reddy --- .../devicetree/bindings/media/qcom,glymur-iris.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml b/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml index de4792f3b658a..558b85ef9ea02 100644 --- a/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml +++ b/Documentation/devicetree/bindings/media/qcom,glymur-iris.yaml @@ -15,7 +15,11 @@ description: properties: compatible: - const: qcom,glymur-iris + oneOf: + - items: + - const: qcom,nord-iris + - const: qcom,glymur-iris + - const: qcom,glymur-iris clocks: maxItems: 9 From 716bd3c4908cd731919aac2ed51cfe4f0fd522d1 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Sat, 5 Sep 2026 19:27:23 +0530 Subject: [PATCH 0596/1133] FROMLIST: media: iris: Retain firmware confirmed video_format across GOP restarts During speed-based rewind, the client restarts the decoder queues once per group of pictures (GOP). This is because playing a GOP-based stream in reverse requires decoding each group forward first and then showing its frames in reverse order. Each restart makes the driver resend the colour info property on the bitstream port, which firmware always treats as a sign that the stream's properties may have changed. The driver never stored the video_format value that firmware had last confirmed, so it resent colour info with a fixed unspecified value instead of the real one, and the value firmware received kept differing from what it already had. On every restart during rewind, this looked to firmware like a real change on the bitstream port, so firmware sent a settings-change notification, and the driver treated it as a dynamic resolution change and paused the port. The client then removed its buffers and built new ones for a resolution that had not actually changed, stalling playback once per GOP. Store and send back the same video_format value firmware already confirmed so both sides stay in agreement across every restart, avoiding the false settings-change notification. Link: https://lore.kernel.org/all/20260905-read_video_format_from_firmware-v2-1-21a606cdd288@oss.qualcomm.com/ Signed-off-by: Vishnu Reddy --- drivers/media/platform/qcom/iris/iris_hfi_common.h | 1 + drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c | 3 ++- drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h index 95a2186fb8269..44b8b440dbdff 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h @@ -152,6 +152,7 @@ struct hfi_subscription_params { u32 fw_min_count; u32 pic_order_cnt; u32 color_info; + u32 video_format; u32 profile; u32 level; u32 tier; 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 f8b38f82ae309..e0b12fe0595cf 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c @@ -378,7 +378,7 @@ static int iris_hfi_gen2_set_colorspace(struct iris_inst *inst, u32 plane) struct v4l2_pix_format_mplane *pixmp = &inst->fmt_src->fmt.pix_mp; u32 video_signal_type_present_flag = 0, color_info; u32 matrix_coeff = HFI_MATRIX_COEFF_RESERVED; - u32 video_format = UNSPECIFIED_COLOR_FORMAT; + u32 video_format = inst_hfi_gen2->src_subcr_params.video_format; u32 full_range = V4L2_QUANTIZATION_DEFAULT; u32 transfer_char = HFI_TRANSFER_RESERVED; u32 port = iris_hfi_gen2_get_port(inst, plane); @@ -826,6 +826,7 @@ static int iris_hfi_gen2_session_open(struct iris_inst *inst) inst_hfi_gen2->ipsc_properties_set = false; inst_hfi_gen2->opsc_properties_set = false; + inst_hfi_gen2->src_subcr_params.video_format = UNSPECIFIED_COLOR_FORMAT; inst_hfi_gen2->packet = kzalloc(4096, GFP_KERNEL); if (!inst_hfi_gen2->packet) 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 4ee5aa7d6b3c4..f53401697316b 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c @@ -581,6 +581,8 @@ static void iris_hfi_gen2_read_input_subcr_params(struct iris_inst *inst) full_range = (subsc_params.color_info & 0x2000000) >> 25; video_signal_type_present_flag = (subsc_params.color_info & 0x20000000) >> 29; + inst_hfi_gen2->src_subcr_params.video_format = + (subsc_params.color_info & 0x1C000000) >> 26; pixmp_op->colorspace = V4L2_COLORSPACE_DEFAULT; pixmp_op->xfer_func = V4L2_XFER_FUNC_DEFAULT; From ea3156af3f3dadd07b50cdddada18c75cadc6742 Mon Sep 17 00:00:00 2001 From: Venkata Siva Pavan KumarVenkatapatigari Date: Tue, 29 Sep 2026 17:21:21 +0530 Subject: [PATCH 0597/1133] FROMLIST: media: iris: Fix VSP clock calculation for high bitrate streams Frame drops were observed during high-resolution streams decoded at high bitrates, as well as concurrent decode sessions. Analysis showed that the Video Signal Processor (VSP) clock requirement was underestimated for these workloads, resulting in insufficient clock scaling and reduced processing throughput. Update the VSP frequency calculation to more accurately reflect the processing requirements of different codecs and bitrates, ensuring that the requested clock frequency is sufficient to sustain the workload and prevent frame drops. Link: https://lore.kernel.org/all/20261006-fix-vsp-freq-calc-v1-1-53532d893852@oss.qualcomm.com Fixes: 82b96a8d8d6e ("media: iris: Move vpu35 specific api to common to use for vpu4") Cc: stable@vger.kernel.org Signed-off-by: Vishnu Reddy Signed-off-by: Venkata Siva Pavan KumarVenkatapatigari Signed-off-by: Nagesh Jamakhandi --- .../platform/qcom/iris/iris_vpu_common.c | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index b282cebeba52b..83e2144aada15 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -374,11 +374,32 @@ u64 iris_vpu2_calculate_frequency(struct iris_inst *inst, size_t data_size) return max(vpp_freq, vsp_freq); } +static u64 iris_get_vsp_ref_bitrate(struct iris_inst *inst) +{ + struct device *dev = inst->core->dev; + u32 codec = inst->codec; + + switch (codec) { + case V4L2_PIX_FMT_H264: + return 150; + case V4L2_PIX_FMT_HEVC: + return 140; + case V4L2_PIX_FMT_VP9: + return 70; + case V4L2_PIX_FMT_AV1: + return 100; + default: + dev_err(dev, "Unsupported codec\n"); + return 1; + } +} + u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst *inst, size_t data_size) { struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; struct v4l2_format *inp_f = inst->fmt_src; u32 height, width, mbs_per_second, mbpf; + u64 vsp_ref_bitrate, vsp_ref_freq; u64 fw_cycles, fw_vpp_cycles; u64 vsp_cycles, vpp_cycles; u32 fps = inst->frame_rate; @@ -405,7 +426,13 @@ u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst *inst, size_t data_siz vpp_cycles += div_u64(vpp_cycles * 5, 100); vsp_cycles = fps * data_size * 8; - vsp_cycles = div_u64(vsp_cycles, 2); + vsp_ref_bitrate = iris_get_vsp_ref_bitrate(inst); + vsp_ref_freq = inst->codec == V4L2_PIX_FMT_AV1 ? 533 : 444; + vsp_cycles = div_u64(vsp_ref_freq * vsp_cycles, vsp_ref_bitrate); + + /* VSP FW SW offset */ + vsp_cycles = div_u64(vsp_cycles * 1000, 1055); + /* VSP FW overhead 1.05 */ vsp_cycles = div_u64(vsp_cycles * 21, 20); From 8dccc5e569265ce3318ce3bc8cb7a18d3c2d0ecc Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 1 Oct 2026 20:47:21 +0530 Subject: [PATCH 0598/1133] FROMLIST: media: iris: wait for vpu NoC to enter low power during power off The recommended hardware sequence requires software to wait for vpu NoC to enter in low power mode and then deassert the low power idle (LPI) control. Add the missing LPI status poll and move the LPI control deassertion after the hardware acks LPI mode. This avoids any pending transactions on vpu NoC before shutting it down. Link: https://lore.kernel.org/all/20261001-kaanapali-iris-v4-1-642f9ac5e699@oss.qualcomm.com Fixes: dde659d37036 ("media: iris: Introduce vpu ops for vpu4 with necessary hooks") Cc: stable@vger.kernel.org Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia --- drivers/media/platform/qcom/iris/iris_vpu4x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c index 9d89d3f00acf7..db0dadc99e468 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu4x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c @@ -221,6 +221,10 @@ static void iris_vpu4x_power_off_hardware(struct iris_core *core) if (!handshake_done && handshake_busy) dev_err(core->dev, "LPI handshake timeout\n"); + readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS, + value, value & BIT(0), 200, 2000); + writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + writel(MVP_NOC_RESET_REQ_MASK, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, value, value & MVP_NOC_RESET_REQ_MASK, 200, 2000); From 86edd4f2fbaaa138d284ba78f0566be8c1e72bec Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 1 Oct 2026 20:47:22 +0530 Subject: [PATCH 0599/1133] FROMLIST: media: dt-bindings: qcom-kaanapali-iris: Add kaanapali video codec binding Kaanapali SOC brings in the new generation of video IP i.e iris4. When compared to previous generation, iris3x, it has, - separate power domains for stream and pixel processing hardware blocks (bse and vpp). - additional power domain for apv codec. - power domains for individual pipes (VPPx). - different clocks and reset lines. Update maxitems constraints for clocks, power-domains, and non-pixel IOMMUs in the common venus schema to accommodate additional bindings in kaanapali. Kaanapali platform-specific schema defines fixed constraints for these properties, so the common schema now serves as an upper bound. As a result, add explicit maxitems constraints for the non-pixel IOMMUs in the qcom,sm8550-iris and qcom,sm8750-iris schemas to preserve their respective fixed constraints. Link: https://lore.kernel.org/all/20261001-kaanapali-iris-v4-2-642f9ac5e699@oss.qualcomm.com Signed-off-by: Vikash Garodia --- .../bindings/media/qcom,kaanapali-iris.yaml | 274 ++++++++++++++++++ .../bindings/media/qcom,venus-common.yaml | 8 +- 2 files changed, 278 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/qcom,kaanapali-iris.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,kaanapali-iris.yaml b/Documentation/devicetree/bindings/media/qcom,kaanapali-iris.yaml new file mode 100644 index 0000000000000..780f5a644b385 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,kaanapali-iris.yaml @@ -0,0 +1,274 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,kaanapali-iris.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Kaanapali Iris video encoder and decoder + +maintainers: + - Vikash Garodia + - Dikshita Agarwal + +description: + The iris video processing unit is a video encode and decode accelerator + present on Qualcomm Kaanapali SoC. + +properties: + compatible: + const: qcom,kaanapali-iris + + clocks: + maxItems: 10 + + clock-names: + items: + - const: iface + - const: core + - const: vcodec0_core + - const: iface1 + - const: core_freerun + - const: vcodec0_core_freerun + - const: vcodec_bse + - const: vcodec_vpp0 + - const: vcodec_vpp1 + - const: vcodec_apv + + dma-coherent: true + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: cpu-cfg + - const: video-mem + + operating-points-v2: true + opp-table: + type: object + + power-domains: + maxItems: 7 + + power-domain-names: + items: + - const: venus + - const: vcodec0 + - const: mxc + - const: mmcx + - const: vpp0 + - const: vpp1 + - const: apv + + resets: + maxItems: 4 + + reset-names: + items: + - const: bus0 + - const: bus1 + - const: core + - const: vcodec0_core + + '#address-cells': + const: 1 + + '#size-cells': + const: 1 + + dma-ranges: + maxItems: 1 + + non-pixel: + type: object + description: + Non pixel context bank is needed when video hardware have distinct iommus for non pixel + buffers. Non pixel buffers are compressed and internal buffers. + properties: + iommus: + maxItems: 3 + memory-region: + maxItems: 1 + required: + - iommus + - memory-region + additionalProperties: false + + pixel: + type: object + description: + Pixel context bank is needed when video hardware have distinct iommus for pixel buffers. + Pixel buffers are uncompressed buffers. + properties: + iommus: + maxItems: 1 + required: + - iommus + additionalProperties: false + + video-firmware: + type: object + description: + Firmware context bank represents the firmware processing domain of the VPU. Required to boot + VPU when no hypervisor is present. + properties: + iommus: + maxItems: 1 + required: + - iommus + additionalProperties: false + +required: + - compatible + - dma-coherent + - interconnects + - interconnect-names + - power-domain-names + - resets + - reset-names + - '#address-cells' + - '#size-cells' + - dma-ranges + - non-pixel + - pixel + +allOf: + - $ref: qcom,venus-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + + video-codec@2000000 { + compatible = "qcom,kaanapali-iris"; + reg = <0x02000000 0xf0000>; + + clocks = <&gcc_video_axi0_clk>, + <&video_cc_mvs0c_clk>, + <&video_cc_mvs0_clk>, + <&gcc_video_axi1_clk>, + <&video_cc_mvs0c_freerun_clk>, + <&video_cc_mvs0_freerun_clk>, + <&video_cc_mvs0b_clk>, + <&video_cc_mvs0_vpp0_clk>, + <&video_cc_mvs0_vpp1_clk>, + <&video_cc_mvs0a_clk>; + clock-names = "iface", + "core", + "vcodec0_core", + "iface1", + "core_freerun", + "vcodec0_core_freerun", + "vcodec_bse", + "vcodec_vpp0", + "vcodec_vpp1", + "vcodec_apv"; + + dma-coherent; + + interconnects = <&gem_noc_master_appss_proc &config_noc_slave_venus_cfg>, + <&mmss_noc_master_video_mvp &mc_virt_slave_ebi1>; + interconnect-names = "cpu-cfg", + "video-mem"; + + interrupts = ; + + memory-region = <&video_mem>; + + operating-points-v2 = <&iris_opp_table>; + + power-domains = <&video_cc_mvs0c_gdsc>, + <&video_cc_mvs0_gdsc>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&video_cc_mvs0_vpp0_gdsc>, + <&video_cc_mvs0_vpp1_gdsc>, + <&video_cc_mvs0a_gdsc>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vpp0", + "vpp1", + "apv"; + + resets = <&gcc_video_axi0_clk_ares>, + <&gcc_video_axi1_clk_ares>, + <&video_cc_mvs0c_freerun_clk_ares>, + <&video_cc_mvs0_freerun_clk_ares>; + reset-names = "bus0", + "bus1", + "core", + "vcodec0_core"; + + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0xffc00000>; + + non-pixel { + iommus = <&apps_smmu 0x1940 0x0>, + <&apps_smmu 0x1944 0x0>, + <&apps_smmu 0x1a20 0x0>; + memory-region = <&iris_resv>; + }; + + pixel { + iommus = <&apps_smmu 0x1943 0x0>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000 240000000 240000000 360000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 338000000 507000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-420000000 { + opp-hz = /bits/ 64 <420000000 420000000 420000000 630000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-533000000 { + opp-hz = /bits/ 64 <533000000 533000000 533000000 800000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_nom>; + }; + + opp-630000000 { + opp-hz = /bits/ 64 <630000000 630000000 630000000 1104000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo>; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000 630000000 630000000 1260000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo_l0>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000 630000000 850000000 1260000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo_l1>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml index 2283a5112e1ed..445125612f9c2 100644 --- a/Documentation/devicetree/bindings/media/qcom,venus-common.yaml +++ b/Documentation/devicetree/bindings/media/qcom,venus-common.yaml @@ -20,11 +20,11 @@ properties: clocks: minItems: 3 - maxItems: 9 + maxItems: 10 clock-names: minItems: 3 - maxItems: 9 + maxItems: 10 firmware-name: maxItems: 1 @@ -44,11 +44,11 @@ properties: power-domains: minItems: 1 - maxItems: 5 + maxItems: 7 power-domain-names: minItems: 1 - maxItems: 5 + maxItems: 7 '#address-cells': const: 1 From a361454caea85d6de52436a8725aa8c402aa9361 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 1 Oct 2026 20:47:23 +0530 Subject: [PATCH 0600/1133] FROMLIST: media: iris: add iris4 specific H265 line buffer calculation The H265 decoder line buffer size calculation for iris4 (VPU4) was previously reusing the iris3 formula. While this works for most resolutions, certain configurations require a larger buffer size on iris4, causing firmware errors during decode. This resolves firmware failures seen with specific test vectors on kaanapali (iris4), and fixes the following failing fluster tests - PICSIZE_C_Bossen_1 - WPP_E_ericsson_MAIN_2 10bit tests - DBLK_A_MAIN10_VIXS_4 - INITQP_B_Main10_Sony_1 - WP_A_MAIN10_Toshiba_3 - WP_MAIN10_B_Toshiba_3 - WPP_A_ericsson_MAIN10_2 - WPP_B_ericsson_MAIN10_2 - WPP_C_ericsson_MAIN10_2 - WPP_E_ericsson_MAIN10_2 - WPP_F_ericsson_MAIN10_2 Link: https://lore.kernel.org/all/20261001-kaanapali-iris-v4-3-642f9ac5e699@oss.qualcomm.com Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia --- .../platform/qcom/iris/iris_vpu_buffer.c | 59 ++++++++++++++++++- .../platform/qcom/iris/iris_vpu_buffer.h | 16 +++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index a8170e5fa9e60..526cc405a715d 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -2134,6 +2134,63 @@ static u32 hfi_vpu4x_buffer_line_vp9d(u32 frame_width, u32 frame_height, u32 _yu return lb_size + dpb_obp_size; } +static u32 hfi_vpu4x_buffer_line_h265d(u32 frame_width, u32 frame_height, bool is_opb, + u32 num_vpp_pipes) +{ + u32 num_lcu_per_pipe, se_left_lb, vsp_left_lb, top_lb, qp_size; + u32 fe_left_lb = 0, dpb_obp = 0, lcu_size = LCU_SIZE_16; + int i; + + for (i = 0; i < num_vpp_pipes; i++) { + num_lcu_per_pipe = (DIV_ROUND_UP(frame_height, lcu_size) / num_vpp_pipes); + if (i == 0) + num_lcu_per_pipe += (DIV_ROUND_UP(frame_height, lcu_size) % num_vpp_pipes); + + fe_left_lb += DMA_ALIGNMENT * FE_LFT_CTRL_BYTES_PER_PACKETS * num_lcu_per_pipe * + FE_LFT_CTRL_LINE_NUMBERS; + fe_left_lb += DMA_ALIGNMENT * FE_LFT_DB_LUMA_CHROMA_BYTES_PER_PACKETS * + num_lcu_per_pipe * FE_LFT_DB_DATA_LINE_NUMBERS; + fe_left_lb += DMA_ALIGNMENT * FE_LFT_SAO_LUMA_BYTES_PER_PACKETS * + num_lcu_per_pipe; + fe_left_lb += DMA_ALIGNMENT * FE_LFT_SAO_CHROMA_BYTES_PER_PACKETS * + num_lcu_per_pipe; + fe_left_lb += DMA_ALIGNMENT * FE_LFT_LR_LUMA_CHROMA_BYTES_PER_PACKETS * + num_lcu_per_pipe * FE_LFT_LR_DATA_LINE_NUMBERS; + } + + if (is_opb) + dpb_obp = size_dpb_opb(frame_height, lcu_size) * num_vpp_pipes; + + se_left_lb = max3(((frame_height + LCU_SIZE_16 - 1) / H265_MIN_SE_CTRL_BLOCK_SIZE) * + MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE, + ((frame_height + LCU_SIZE_32 - 1) / H265_MIN_SE_CTRL_BLOCK_SIZE) * + MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE, + ((frame_height + LCU_SIZE_64 - 1) / H265_MIN_SE_CTRL_BLOCK_SIZE) * + MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE); + + vsp_left_lb = ALIGN(DIV_ROUND_UP(frame_height, LCU_SIZE_64) * + H265_NUM_TILE_ROW, DMA_ALIGNMENT); + + top_lb = DMA_ALIGNMENT * FE_TOP_CTRL_BYTES_PER_PACKETS * + DIV_ROUND_UP(frame_width, lcu_size) * FE_TOP_CTRL_LINE_NUMBERS; + top_lb += DMA_ALIGNMENT * FE_TOP_LUMA_BYTES_PER_PACKETS * + DIV_ROUND_UP(frame_width, lcu_size) * FE_TOP_DATA_LUMA_LINE_NUMBERS; + top_lb += DMA_ALIGNMENT * FE_TOP_CHROMA_BYTES_PER_PACKETS * + (DIV_ROUND_UP(frame_width, lcu_size) + 1) * FE_TOP_DATA_CHROMA_LINE_NUMBERS; + top_lb += ALIGN(((frame_width + LCU_SIZE_64 - 1) / H265_MIN_SE_CTRL_BLOCK_SIZE) * + MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE, DMA_ALIGNMENT); + top_lb += ALIGN(ALIGN(frame_width, LCU_SIZE_64) * PE_TOP_RECON_DATA_BYTES_PER_PACKETS, + DMA_ALIGNMENT); + top_lb += size_h265d_lb_vsp_top(frame_width, frame_height); + + qp_size = size_h265d_qp(frame_width, frame_height); + + return ((ALIGN(dpb_obp, DMA_ALIGNMENT) + ALIGN(se_left_lb, DMA_ALIGNMENT) + + ALIGN(vsp_left_lb, DMA_ALIGNMENT)) * num_vpp_pipes) + + ALIGN(fe_left_lb, DMA_ALIGNMENT) + ALIGN(top_lb, DMA_ALIGNMENT) + + ALIGN(qp_size, DMA_ALIGNMENT); +} + static u32 iris_vpu4x_dec_line_size(struct iris_inst *inst) { u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; @@ -2149,7 +2206,7 @@ static u32 iris_vpu4x_dec_line_size(struct iris_inst *inst) 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); + return hfi_vpu4x_buffer_line_h265d(width, height, is_opb, num_vpp_pipes); else if (inst->codec == V4L2_PIX_FMT_VP9) return hfi_vpu4x_buffer_line_vp9d(width, height, out_min_count, is_opb, num_vpp_pipes); diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index 2085e316a6bd8..632f95f1848c3 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -161,6 +161,22 @@ struct iris_inst; #define BITS_PER_CTRL_PACK 128 #define NUM_CTRL_PACK_LCU 10 +#define LCU_SIZE_16 16 +#define LCU_SIZE_32 32 +#define LCU_SIZE_64 64 + +#define H265_MIN_SE_CTRL_BLOCK_SIZE 8 +#define FE_LFT_CTRL_BYTES_PER_PACKETS 1 +#define FE_LFT_DB_LUMA_CHROMA_BYTES_PER_PACKETS 2 +#define FE_LFT_SAO_LUMA_BYTES_PER_PACKETS 1 +#define FE_LFT_SAO_CHROMA_BYTES_PER_PACKETS 2 +#define FE_LFT_LR_LUMA_CHROMA_BYTES_PER_PACKETS 8 + +#define FE_TOP_CTRL_BYTES_PER_PACKETS 1 +#define FE_TOP_LUMA_BYTES_PER_PACKETS 2 +#define FE_TOP_CHROMA_BYTES_PER_PACKETS 2 +#define PE_TOP_RECON_DATA_BYTES_PER_PACKETS 6 + static inline u32 size_h264d_lb_fe_top_data(u32 frame_width) { return MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * ALIGN(frame_width, 16) * 3; From 8db6dd87a8326b9ed77c0118472e8ff03c239289 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 1 Oct 2026 20:47:24 +0530 Subject: [PATCH 0601/1133] FROMLIST: media: iris: add platform data for kaanapali Add support for the kaanapali platform in the iris driver to support video functionality on kaanapali platform. Link: https://lore.kernel.org/all/20261001-kaanapali-iris-v4-4-642f9ac5e699@oss.qualcomm.com Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia --- drivers/media/platform/qcom/iris/Makefile | 2 + .../platform/qcom/iris/iris_platform_common.h | 1 + .../qcom/iris/iris_platform_kaanapali.c | 94 +++++++++++++++++++ .../qcom/iris/iris_platform_kaanapali.h | 18 ++++ .../platform/qcom/iris/iris_platform_vpu4x.c | 67 +++++++++++++ drivers/media/platform/qcom/iris/iris_probe.c | 4 + 6 files changed, 186 insertions(+) create mode 100644 drivers/media/platform/qcom/iris/iris_platform_kaanapali.c create mode 100644 drivers/media/platform/qcom/iris/iris_platform_kaanapali.h create mode 100644 drivers/media/platform/qcom/iris/iris_platform_vpu4x.c diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index c6dbb36a90668..672b89a2bc43a 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -25,10 +25,12 @@ qcom-iris-objs += iris_buffer.o \ iris_vb2.o \ iris_vdec.o \ iris_venc.o \ + iris_platform_kaanapali.o \ iris_platform_glymur.o \ iris_vpu2.o \ iris_vpu3x.o \ iris_vpu4x.o \ + iris_platform_vpu4x.o \ iris_vpu_ar50lt.o \ iris_vpu_buffer.o \ iris_vpu_common.o \ diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 1eb8f33a7564f..262435f2df406 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -67,6 +67,7 @@ extern const struct platform_inst_slice_caps iris_vpu2_vpu3x_slice_caps; extern const struct platform_inst_slice_caps iris_ar50lt_slice_caps; extern const struct iris_platform_data glymur_data; +extern const struct iris_platform_data kaanapali_data; extern const struct iris_platform_data milos_data; extern const struct iris_platform_data qcm2290_data; extern const struct iris_platform_data qcs8300_data; diff --git a/drivers/media/platform/qcom/iris/iris_platform_kaanapali.c b/drivers/media/platform/qcom/iris/iris_platform_kaanapali.c new file mode 100644 index 0000000000000..f8f0e07045504 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_kaanapali.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_core.h" +#include "iris_platform_common.h" + +const char *const iris_kaanapali_clk_reset_table[] = { + "bus0", + "bus1", + "core", + "vcodec0_core", +}; + +const struct iris_power_domain_data iris_kaanapali_ctrl_data = { + .pd_names = (const char *[]) { + "venus", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "iface1", "core", "core_freerun", + }, + .clk_cnt = 3, +}; + +const struct iris_power_domain_data iris_kaanapali_vcodec_data[] = { + { + .pd_names = (const char *[]) { + "vcodec0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "iface", "vcodec0_core", "vcodec0_core_freerun", "vcodec_bse", + }, + .clk_cnt = 4, + }, +}; + +const struct iris_power_domain_data iris_kaanapali_vpp0_data = { + .pd_names = (const char *[]) { + "vpp0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec_vpp0", + }, + .clk_cnt = 1, +}; + +const struct iris_power_domain_data iris_kaanapali_vpp1_data = { + .pd_names = (const char *[]) { + "vpp1", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec_vpp1", + }, + .clk_cnt = 1, +}; + +const struct iris_power_domain_data iris_kaanapali_apv_data = { + .pd_names = (const char *[]) { + "apv", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec_apv", + }, + .clk_cnt = 1, +}; + +const char *const iris_kaanapali_opp_clk_table[] = { + "vcodec0_core", + "vcodec_apv", + "vcodec_bse", + "core", + NULL, +}; + +struct tz_cp_config iris_kaanapali_tz_cp_config[] = { + { + .cp_start = VIDEO_REGION_VM0_SECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x01000000, + .cp_nonpixel_size = 0x24800000, + }, + { + .cp_start = VIDEO_REGION_VM0_NONSECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x25800000, + .cp_nonpixel_size = 0xda400000, + }, +}; diff --git a/drivers/media/platform/qcom/iris/iris_platform_kaanapali.h b/drivers/media/platform/qcom/iris/iris_platform_kaanapali.h new file mode 100644 index 0000000000000..732a28e53a875 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_kaanapali.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __IRIS_PLATFORM_KAANAPALI_H__ +#define __IRIS_PLATFORM_KAANAPALI_H__ + +extern const char *const iris_kaanapali_clk_reset_table[4]; +extern const struct iris_power_domain_data iris_kaanapali_ctrl_data; +extern const struct iris_power_domain_data iris_kaanapali_vcodec_data[1]; +extern const struct iris_power_domain_data iris_kaanapali_vpp0_data; +extern const struct iris_power_domain_data iris_kaanapali_vpp1_data; +extern const struct iris_power_domain_data iris_kaanapali_apv_data; +extern const char *const iris_kaanapali_opp_clk_table[5]; +extern struct tz_cp_config iris_kaanapali_tz_cp_config[2]; + +#endif /* __IRIS_PLATFORM_KAANAPALI_H__ */ diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu4x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu4x.c new file mode 100644 index 0000000000000..488b4b4948359 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu4x.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include "iris_hfi_gen2.h" +#include "iris_vpu_buffer.h" +#include "iris_vpu_common.h" + +#include "iris_platform_sm8550.h" +#include "iris_platform_kaanapali.h" + +static const struct iris_firmware_desc iris_vpu40_p2_s7_gen2_desc = { + .firmware_data = &iris_hfi_gen2_data, + .get_vpu_buffer_size = iris_vpu4x_buf_size, + .fwname = "qcom/vpu/vpu40_p2_s7.mbn", +}; + +static const u32 iris_fmts_vpu4x_dec[] = { + V4L2_PIX_FMT_H264, + V4L2_PIX_FMT_HEVC, + V4L2_PIX_FMT_VP9, +}; + +static const struct icc_info iris_icc_info_vpu4x[] = { + { "cpu-cfg", 1000, 1000 }, + { "video-mem", 1000, 15000000 }, +}; + +static const struct bw_info iris_bw_table_dec_vpu4x[] = { + { ((4096 * 2160) / 256) * 60, 1608000 }, + { ((4096 * 2160) / 256) * 30, 826000 }, + { ((1920 * 1080) / 256) * 60, 567000 }, + { ((1920 * 1080) / 256) * 30, 294000 }, +}; + +static const char * const iris_opp_pd_table_vpu4x[] = { "mxc", "mmcx" }; + +const struct iris_platform_data kaanapali_data = { + .firmware_desc_gen2 = &iris_vpu40_p2_s7_gen2_desc, + .vpu_ops = &iris_vpu4x_ops, + .icc_tbl = iris_icc_info_vpu4x, + .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu4x), + .clk_rst_tbl = iris_kaanapali_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(iris_kaanapali_clk_reset_table), + .bw_tbl_dec = iris_bw_table_dec_vpu4x, + .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu4x), + .ctrl_data = &iris_kaanapali_ctrl_data, + .vcodec_data = iris_kaanapali_vcodec_data, + .vcodec_vpp0_data = &iris_kaanapali_vpp0_data, + .vcodec_vpp1_data = &iris_kaanapali_vpp1_data, + .apv_data = &iris_kaanapali_apv_data, + .opp_pd_tbl = iris_opp_pd_table_vpu4x, + .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu4x), + .opp_clk_tbl = iris_kaanapali_opp_clk_table, + /* Upper bound of DMA address range */ + .dma_mask = 0xffc00000 - 1, + .inst_iris_fmts = iris_fmts_vpu4x_dec, + .inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu4x_dec), + .inst_caps = &platform_inst_cap_sm8550, + .tz_cp_config_data = iris_kaanapali_tz_cp_config, + .tz_cp_config_data_size = ARRAY_SIZE(iris_kaanapali_tz_cp_config), + .num_vpp_pipe = 2, + .max_session_count = 16, + .max_core_mbpf = NUM_MBS_8K * 2, + .max_core_mbps = ((8192 * 4320) / 256) * 60, +}; diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index b0695f84dfc03..14ad2197d1048 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -609,6 +609,10 @@ static const struct of_device_id iris_dt_match[] = { .compatible = "qcom,glymur-iris", .data = &glymur_data, }, + { + .compatible = "qcom,kaanapali-iris", + .data = &kaanapali_data, + }, { .compatible = "qcom,milos-iris", .data = &milos_data, From e95e19e22ab035283c4fb513c22a9311ed35f4a2 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Tue, 22 Sep 2026 11:28:21 +0800 Subject: [PATCH 0602/1133] FROMLIST: media: iris: fix VPU4x encoder line buffer size for rotation iris_vpu4x_enc_line_size was reading resolutions directly from inst->fmt_dst. Use iris_vpu_enc_get_bitstream_{width,height}() which account for the 90/270-degree rotation case. Link: https://lore.kernel.org/all/20260922-vpu4x_enc_line_size_fix-v1-1-f0ee5556bb0e@oss.qualcomm.com Fixes: df816dce1b01 ("media: iris: Introduce buffer size calculations for vpu4") Signed-off-by: Wangao Wang Reviewed-by: Vikash Garodia --- drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index 526cc405a715d..2ae3a2e1dbb0b 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -2419,9 +2419,8 @@ static u32 iris_vpu4x_enc_line_size(struct iris_inst *inst) { u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; u32 lcu_size = inst->codec == V4L2_PIX_FMT_HEVC ? 32 : 16; - struct v4l2_format *f = inst->fmt_dst; - u32 height = f->fmt.pix_mp.height; - u32 width = f->fmt.pix_mp.width; + u32 height = iris_vpu_enc_get_bitstream_height(inst); + u32 width = iris_vpu_enc_get_bitstream_width(inst); return hfi_vpu4x_buffer_line_enc(width, height, 0, num_vpp_pipes, lcu_size, inst->codec); From fbb24382f6d32d4913bcf9050743b1fc5b4a5014 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Tue, 22 Sep 2026 11:24:48 +0800 Subject: [PATCH 0603/1133] FROMLIST: media: iris: fix VPSS line buffer width and height order size_vpss_line_buf_vpu33() expects (num_pipes, height, width) but was called with width and height swapped, miscalculating VPSS line buffer size for non-square resolutions. Fixes: df816dce1b01 ("media: iris: Introduce buffer size calculations for vpu4") Link: https://lore.kernel.org/all/20260922-vpu4x_buffer_fix-v1-1-d1b6f1c24285@oss.qualcomm.com Signed-off-by: Wangao Wang Reviewed-by: Bryan O'Donoghue Reviewed-by: Vikash Garodia Reviewed-by: Konrad Dybcio --- drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index 2ae3a2e1dbb0b..5494e6010dc6f 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -2408,8 +2408,8 @@ static u32 hfi_vpu4x_buffer_line_enc(u32 frame_width, u32 frame_height, u32 dma_opb_lb_size = size_dma_opb_lb(num_vpp_pipes_enc, frame_width_coded, frame_height_coded); u32 dse_lb_size = ALIGN((256 + (16 * (frame_width_coded >> 4))), DMA_ALIGNMENT); - u32 size_vpss_lb_enc = size_vpss_line_buf_vpu33(num_vpp_pipes_enc, frame_width_coded, - frame_height_coded); + u32 size_vpss_lb_enc = size_vpss_line_buf_vpu33(num_vpp_pipes_enc, frame_height_coded, + frame_width_coded); return se_lb_size + te_lb_size + fe_lb_size + md_lb_size + dma_opb_lb_size + dse_lb_size + size_vpss_lb_enc; From 8831d64a70ac68451c58ec3d3155db259b06b0fd Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 10:41:12 +0800 Subject: [PATCH 0604/1133] FROMLIST: dt-bindings: media: qcom,maili-iris: Add Maili video codec Add a devicetree binding for the Iris4 video encoder and decoder block found on the Qualcomm Maili SoC. Compared to the Iris3 generation, this block has - separate clocks for BSE (Bitstream Engine) and VPP (Video Processing Pipeline). - power domain for VPP (Video Processing Pipeline). - different reset lines. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_maili-v2-2-7223738e330d@oss.qualcomm.com/ Signed-off-by: Wangao Wang --- .../bindings/media/qcom,maili-iris.yaml | 229 ++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,maili-iris.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,maili-iris.yaml b/Documentation/devicetree/bindings/media/qcom,maili-iris.yaml new file mode 100644 index 0000000000000..4ddc4df8481b5 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,maili-iris.yaml @@ -0,0 +1,229 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,maili-iris.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Maili SoC Iris video encoder and decoder + +maintainers: + - Vikash Garodia + - Dikshita Agarwal + +description: + The Iris video processing unit on Qualcomm Maili SoC is a video encode and + decode accelerator. + +properties: + compatible: + enum: + - qcom,maili-iris + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 8 + + clock-names: + items: + - const: iface + - const: core + - const: vcodec0_core + - const: iface1 + - const: core_freerun + - const: vcodec0_core_freerun + - const: vcodec_bse + - const: vcodec_vpp0 + + firmware-name: + maxItems: 1 + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: cpu-cfg + - const: video-mem + + power-domains: + maxItems: 5 + + power-domain-names: + items: + - const: venus + - const: vcodec0 + - const: mxc + - const: mmcx + - const: vpp0 + + resets: + maxItems: 4 + + reset-names: + items: + - const: bus0 + - const: bus1 + - const: core + - const: vcodec0_core + + iommus: + maxItems: 4 + + dma-coherent: true + + operating-points-v2: true + + opp-table: + type: object + +required: + - compatible + - dma-coherent + - interconnects + - interconnect-names + - power-domain-names + - resets + - reset-names + +allOf: + - $ref: qcom,venus-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + video-codec@2000000 { + compatible = "qcom,maili-iris"; + reg = <0x02000000 0xf0000>; + + interrupts = ; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&gcc GCC_VIDEO_AXI0C_CLK>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0B_CLK>, + <&videocc VIDEO_CC_MVS0_VPP0_CLK>; + clock-names = "iface", + "core", + "vcodec0_core", + "iface1", + "core_freerun", + "vcodec0_core_freerun", + "vcodec_bse", + "vcodec_vpp0"; + + dma-coherent; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_IRIS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_VIDEO_MVP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + memory-region = <&video_mem>; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc VIDEO_CC_MVS0_VPP0_GDSC>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vpp0"; + + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>, + <&gcc GCC_VIDEO_AXI0C_CLK_ARES>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK_ARES>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK_ARES>; + reset-names = "bus0", + "bus1", + "core", + "vcodec0_core"; + + operating-points-v2 = <&iris_opp_table>; + + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0xffc00000>; + + non-pixel { + iommus = <&apps_smmu 0x1540 0x0000>, + <&apps_smmu 0x1620 0x0000>, + <&apps_smmu 0x1544 0x0000>; + iommu-ranges = <0x25800000 0xda400000>; + }; + + pixel { + iommus = <&apps_smmu 0x1543 0x0000>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000 240000000 360000000>; + required-opps = <&rpmhpd_opp_low_svs_d2>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 507000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs>; + }; + + opp-420000000 { + opp-hz = /bits/ 64 <420000000 420000000 630000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000 533000000 800000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_nom>; + }; + + opp-630000000 { + opp-hz = /bits/ 64 <630000000 630000000 1104000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo>; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000 630000000 1260000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo_l1>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000 800000000 1260000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo_l3>; + }; + }; + }; From 6ed4e790f83f0e24b7c5aae7e62647a3fad4bc33 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 10:41:13 +0800 Subject: [PATCH 0605/1133] FROMLIST: media: iris: add AV1 decode buffer size support for vpu4x Add necessary buffer size calculation to support AV1 decode for vpu4x - wire AV1 into iris_vpu4x_dec_line_size() via hfi_buffer_line_av1d() - add hfi_vpu4x_buffer_persist_av1d() for the vpu4x's persist buffer size calculation - add BUF_PARTIAL to the vpu4x decoder dispatch table, which AV1D requires Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_maili-v2-3-7223738e330d@oss.qualcomm.com/ Signed-off-by: Wangao Wang --- .../platform/qcom/iris/iris_vpu_buffer.c | 34 +++++++++++++++++-- .../platform/qcom/iris/iris_vpu_buffer.h | 1 + 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index 5494e6010dc6f..756dc63e23d80 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -2210,6 +2210,8 @@ static u32 iris_vpu4x_dec_line_size(struct iris_inst *inst) else if (inst->codec == V4L2_PIX_FMT_VP9) return hfi_vpu4x_buffer_line_vp9d(width, height, out_min_count, is_opb, num_vpp_pipes); + else if (inst->codec == V4L2_PIX_FMT_AV1) + return hfi_buffer_line_av1d(width, height, is_opb, num_vpp_pipes); return 0; } @@ -2233,14 +2235,39 @@ static u32 hfi_vpu4x_buffer_persist_vp9d(void) HDR10_HIST_EXTRADATA_SIZE; } +static u32 hfi_vpu4x_buffer_persist_av1d(u32 max_width, u32 max_height, + u32 total_ref_count, u32 rpu_enabled) +{ + u32 comv_size = hfi_buffer_comv_av1d(max_width, max_height, total_ref_count); + u32 seq_hdr = SIZE_AV1D_SEQUENCE_HEADER * 2 + SIZE_AV1D_METADATA; + u32 per_pic = AV1D_NUM_HW_PIC_BUF * + (SIZE_AV1D_TILE_OFFSET + SIZE_AV1D_QM + SIZE_AV1D_ARP + SIZE_AV1D_METADATA); + u32 frame_hdr = AV1D_NUM_FRAME_HEADERS * + (SIZE_AV1D_FRAME_HEADER + 2 * SIZE_AV1D_PROB_TABLE); + u32 extradata = HDR10_HIST_EXTRADATA_SIZE + + rpu_enabled * NUM_HW_PIC_BUF * SIZE_DOLBY_RPU_METADATA; + + return ALIGN(seq_hdr + per_pic + frame_hdr + comv_size + extradata, DMA_ALIGNMENT); +} + static u32 iris_vpu4x_dec_persist_size(struct iris_inst *inst) { - if (inst->codec == V4L2_PIX_FMT_H264) + struct platform_inst_caps *caps; + + if (inst->codec == V4L2_PIX_FMT_H264) { return hfi_buffer_persist_h264d(); - else if (inst->codec == V4L2_PIX_FMT_HEVC) + } else if (inst->codec == V4L2_PIX_FMT_HEVC) { return hfi_vpu4x_buffer_persist_h265d(0); - else if (inst->codec == V4L2_PIX_FMT_VP9) + } else if (inst->codec == V4L2_PIX_FMT_VP9) { return hfi_vpu4x_buffer_persist_vp9d(); + } else if (inst->codec == V4L2_PIX_FMT_AV1) { + caps = inst->core->iris_platform_data->inst_caps; + if (inst->fw_caps[DRAP].value) + return hfi_vpu4x_buffer_persist_av1d(caps->max_frame_width, + caps->max_frame_height, 16, 0); + else + return hfi_vpu4x_buffer_persist_av1d(0, 0, 0, 0); + } return 0; } @@ -2539,6 +2566,7 @@ u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_typ {BUF_PERSIST, iris_vpu4x_dec_persist_size }, {BUF_DPB, iris_vpu_dec_dpb_size }, {BUF_SCRATCH_1, iris_vpu_dec_scratch1_size }, + {BUF_PARTIAL, iris_vpu_dec_partial_size }, }; static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = { diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index 632f95f1848c3..9af2c8611484c 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -127,6 +127,7 @@ struct iris_inst; #define SIZE_AV1D_TILE_OFFSET 65536 #define SIZE_AV1D_QM 3328 #define SIZE_AV1D_PROB_TABLE 22784 +#define SIZE_AV1D_ARP 9728 #define SIZE_SLICE_CMD_BUFFER (ALIGN(20480, 256)) #define SIZE_SPS_PPS_SLICE_HDR (2048 + 4096) From 82b167cc39b77309aa7c54c6a9ae4cf2ebc5dac2 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 10:41:14 +0800 Subject: [PATCH 0606/1133] FROMLIST: media: iris: add maili platform data Add platform data for the Maili Iris VPU4 block so the driver can match the qcom,maili-iris compatible and initialize the hardware. Describe the Maili-specific clocks, power domains, firmware, resets, bandwidth data, DMA range, secure memory configuration, and decode capabilities. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_maili-v2-4-7223738e330d@oss.qualcomm.com/ Signed-off-by: Wangao Wang --- .../platform/qcom/iris/iris_platform_common.h | 1 + .../platform/qcom/iris/iris_platform_maili.h | 73 +++++++++++++++++++ .../platform/qcom/iris/iris_platform_vpu4x.c | 36 +++++++++ drivers/media/platform/qcom/iris/iris_probe.c | 4 + 4 files changed, 114 insertions(+) create mode 100644 drivers/media/platform/qcom/iris/iris_platform_maili.h diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 262435f2df406..d2bd2c810c53b 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -68,6 +68,7 @@ extern const struct platform_inst_slice_caps iris_ar50lt_slice_caps; extern const struct iris_platform_data glymur_data; extern const struct iris_platform_data kaanapali_data; +extern const struct iris_platform_data maili_data; extern const struct iris_platform_data milos_data; extern const struct iris_platform_data qcm2290_data; extern const struct iris_platform_data qcs8300_data; diff --git a/drivers/media/platform/qcom/iris/iris_platform_maili.h b/drivers/media/platform/qcom/iris/iris_platform_maili.h new file mode 100644 index 0000000000000..f0ac80d40faf9 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_maili.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __IRIS_PLATFORM_MAILI_H__ +#define __IRIS_PLATFORM_MAILI_H__ + +static const char *const maili_clk_reset_table[] = { + "bus0", + "bus1", + "core", + "vcodec0_core", +}; + +static const struct iris_power_domain_data maili_ctrl_data = { + .pd_names = (const char *[]) { + "venus", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "iface1", "core", "core_freerun", + }, + .clk_cnt = 3, +}; + +static const struct iris_power_domain_data maili_vcodec_data[] = { + { + .pd_names = (const char *[]) { + "vcodec0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "iface", "vcodec0_core", "vcodec0_core_freerun", "vcodec_bse", + }, + .clk_cnt = 4, + }, +}; + +static const struct iris_power_domain_data maili_vpp0_data = { + .pd_names = (const char *[]) { + "vpp0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec_vpp0", + }, + .clk_cnt = 1, +}; + +static const char *const maili_opp_clk_table[] = { + "vcodec0_core", + "vcodec_bse", + "core", + NULL, +}; + +static struct tz_cp_config maili_tz_cp_config[] = { + { + .cp_start = VIDEO_REGION_VM0_SECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x01000000, + .cp_nonpixel_size = 0x24800000, + }, + { + .cp_start = VIDEO_REGION_VM0_NONSECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x25800000, + .cp_nonpixel_size = 0xda400000, + }, +}; + +#endif /* __IRIS_PLATFORM_MAILI_H__ */ diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu4x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu4x.c index 488b4b4948359..e990513f76c67 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu4x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu4x.c @@ -9,6 +9,7 @@ #include "iris_platform_sm8550.h" #include "iris_platform_kaanapali.h" +#include "iris_platform_maili.h" static const struct iris_firmware_desc iris_vpu40_p2_s7_gen2_desc = { .firmware_data = &iris_hfi_gen2_data, @@ -16,10 +17,17 @@ static const struct iris_firmware_desc iris_vpu40_p2_s7_gen2_desc = { .fwname = "qcom/vpu/vpu40_p2_s7.mbn", }; +static const struct iris_firmware_desc iris_vpu40_p1_s8_gen2_desc = { + .firmware_data = &iris_hfi_gen2_data, + .get_vpu_buffer_size = iris_vpu4x_buf_size, + .fwname = "qcom/vpu/vpu40_p1_s8.mbn", +}; + static const u32 iris_fmts_vpu4x_dec[] = { V4L2_PIX_FMT_H264, V4L2_PIX_FMT_HEVC, V4L2_PIX_FMT_VP9, + V4L2_PIX_FMT_AV1, }; static const struct icc_info iris_icc_info_vpu4x[] = { @@ -65,3 +73,31 @@ const struct iris_platform_data kaanapali_data = { .max_core_mbpf = NUM_MBS_8K * 2, .max_core_mbps = ((8192 * 4320) / 256) * 60, }; + +const struct iris_platform_data maili_data = { + .firmware_desc_gen2 = &iris_vpu40_p1_s8_gen2_desc, + .vpu_ops = &iris_vpu4x_ops, + .icc_tbl = iris_icc_info_vpu4x, + .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu4x), + .clk_rst_tbl = maili_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(maili_clk_reset_table), + .bw_tbl_dec = iris_bw_table_dec_vpu4x, + .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu4x), + .ctrl_data = &maili_ctrl_data, + .vcodec_data = maili_vcodec_data, + .vcodec_vpp0_data = &maili_vpp0_data, + .opp_pd_tbl = iris_opp_pd_table_vpu4x, + .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu4x), + .opp_clk_tbl = maili_opp_clk_table, + /* Upper bound of DMA address range */ + .dma_mask = 0xffc00000 - 1, + .inst_iris_fmts = iris_fmts_vpu4x_dec, + .inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu4x_dec), + .inst_caps = &platform_inst_cap_sm8550, + .tz_cp_config_data = maili_tz_cp_config, + .tz_cp_config_data_size = ARRAY_SIZE(maili_tz_cp_config), + .num_vpp_pipe = 1, + .max_session_count = 16, + .max_core_mbpf = NUM_MBS_8K, + .max_core_mbps = NUM_MBS_8K * 30, +}; diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 14ad2197d1048..e1a03246db18f 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -613,6 +613,10 @@ static const struct of_device_id iris_dt_match[] = { .compatible = "qcom,kaanapali-iris", .data = &kaanapali_data, }, + { + .compatible = "qcom,maili-iris", + .data = &maili_data, + }, { .compatible = "qcom,milos-iris", .data = &milos_data, From 6af413b0bcbcd97afefda5b3c78abf3b7d7282d5 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 11:27:51 +0800 Subject: [PATCH 0607/1133] FROMLIST: dt-bindings: media: qcom,hawi-iris: Add Hawi video codec Add a devicetree binding for the Iris5 video encoder and decoder block found on the Qualcomm Hawi SoC. Compared to the Iris4 generation, this block has - additional power domains for internal NoC(cx & mm). - additional clock for internal NoC(cx_iface). - additional power domain and clock for apv codec. - different reset lines. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_hawi-v2-1-016ec3d24b79@oss.qualcomm.com/ Signed-off-by: Wangao Wang --- .../bindings/media/qcom,hawi-iris.yaml | 256 ++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,hawi-iris.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,hawi-iris.yaml b/Documentation/devicetree/bindings/media/qcom,hawi-iris.yaml new file mode 100644 index 0000000000000..13e346414a231 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,hawi-iris.yaml @@ -0,0 +1,256 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,hawi-iris.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Hawi SoC Iris video encoder and decoder + +maintainers: + - Vikash Garodia + - Dikshita Agarwal + +description: + The Iris video processing unit on Qualcomm Hawi SoC is a video encode and + decode accelerator. + +properties: + compatible: + enum: + - qcom,hawi-iris + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 13 + + clock-names: + items: + - const: iface + - const: ifacec + - const: core + - const: core_freerun + - const: core_ctl_freerun + - const: core_debug + - const: cx_iface + - const: vcodec0_core + - const: vcodec_vpp0 + - const: vcodec_vpp1 + - const: vcodec_vpp0_vpp1_gating + - const: vcodec_apv + - const: vcodec_bse + + firmware-name: + maxItems: 1 + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: cpu-cfg + - const: video-mem + + power-domains: + maxItems: 9 + + power-domain-names: + items: + - const: venus + - const: vcodec0 + - const: mxc + - const: mmcx + - const: vpp0 + - const: vpp1 + - const: apv + - const: mm-int + - const: cx-int + + resets: + maxItems: 2 + + reset-names: + items: + - const: bus0 + - const: core + + iommus: + maxItems: 4 + + dma-coherent: true + + operating-points-v2: true + + opp-table: + type: object + +required: + - compatible + - dma-coherent + - interconnects + - interconnect-names + - power-domain-names + - resets + - reset-names + +allOf: + - $ref: qcom,venus-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + video-codec@2000000 { + compatible = "qcom,hawi-iris"; + reg = <0x02000000 0xf0000>; + + interrupts = ; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&gcc GCC_VIDEO_AXI0C_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0C_CTL_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0C_DEBUG_CLK>, + <&videocc VIDEO_CC_CX_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&videocc VIDEO_CC_MVS0_VPP0_CLK>, + <&videocc VIDEO_CC_MVS0_VPP1_CLK>, + <&videocc VIDEO_CC_MVS0_VPP0_VPP1_GATING_CLK>, + <&videocc VIDEO_CC_MVS0A_CLK>, + <&videocc VIDEO_CC_MVS0B_CLK>; + clock-names = "iface", + "ifacec", + "core", + "core_freerun", + "core_ctl_freerun", + "core_debug", + "cx_iface", + "vcodec0_core", + "vcodec_vpp0", + "vcodec_vpp1", + "vcodec_vpp0_vpp1_gating", + "vcodec_apv", + "vcodec_bse"; + + dma-coherent; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_IRIS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_VIDEO_MVP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + memory-region = <&video_mem>; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc VIDEO_CC_MVS0_VPP0_GDSC>, + <&videocc VIDEO_CC_MVS0_VPP1_GDSC>, + <&videocc VIDEO_CC_MVS0A_GDSC>, + <&videocc VIDEO_CC_MM_INT_GDSC>, + <&videocc VIDEO_CC_AXI0_CX_INT_GDSC>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vpp0", + "vpp1", + "apv", + "mm-int", + "cx-int"; + + resets = <&gcc GCC_VIDEO_AXI0C_CLK_ARES>, + <&videocc VIDEO_CC_MVS0C_CTL_FREERUN_CLK_ARES>; + reset-names = "bus0", + "core"; + + operating-points-v2 = <&iris_opp_table>; + + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0xffc00000>; + + non-pixel { + iommus = <&apps_smmu 0x1540 0x0000>, + <&apps_smmu 0x1620 0x0000>, + <&apps_smmu 0x1544 0x0000>; + iommu-ranges = <0x32000000 0xcdc00000>; + }; + + pixel { + iommus = <&apps_smmu 0x1543 0x0000>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000 150000000 150000000 225000000>; + required-opps = <&rpmhpd_opp_low_svs_d2>, + <&rpmhpd_opp_low_svs_d2>; + }; + + opp-285000000 { + opp-hz = /bits/ 64 <285000000 240000000 240000000 360000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs_d0>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 338000000 507000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-420000000 { + opp-hz = /bits/ 64 <420000000 420000000 420000000 630000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-560000000 { + opp-hz = /bits/ 64 <560000000 533000000 533000000 800000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_nom>; + }; + + opp-630000000 { + opp-hz = /bits/ 64 <630000000 630000000 630000000 1104000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo>; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000 710000000 710000000 1260000000>; + required-opps = <&rpmhpd_opp_turbo>, + <&rpmhpd_opp_turbo_l1>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000 710000000 850000000 1260000000>; + required-opps = <&rpmhpd_opp_turbo>, + <&rpmhpd_opp_turbo_l3>; + }; + }; + }; From 45db012d417e877d17ff1ab743ba587d4ae2ce2f Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 11:27:52 +0800 Subject: [PATCH 0608/1133] FROMLIST: media: iris: move shared APV PM helpers to iris_vpu_common The APV power on/off sequences and AHB bridge sync reset helpers are currently local to iris_vpu4x.c. VPU5x uses the same sequences, so keeping them in the VPU4x implementation would either prevent reuse or require duplicating the code. Move the helpers to iris_vpu_common.c and rename them with a vpu4x_vpu5x prefix to reflect their shared usage. Move the associated register constants, including APV_CLK_HALT, the efuse control bits, CPU_CS_APV_BRIDGE_SYNC_RESET, WRAPPER_EFUSE_MONITOR, and AON_WRAPPER_MVP_NOC_RESET_SYNCRST, to iris_vpu_register_defines.h so both implementations can use them. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_hawi-v2-2-016ec3d24b79@oss.qualcomm.com/ Signed-off-by: Wangao Wang --- drivers/media/platform/qcom/iris/iris_vpu4x.c | 88 +------------------ .../platform/qcom/iris/iris_vpu_common.c | 74 ++++++++++++++++ .../platform/qcom/iris/iris_vpu_common.h | 4 + .../qcom/iris/iris_vpu_register_defines.h | 10 +++ 4 files changed, 92 insertions(+), 84 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c index db0dadc99e468..2fdb89fc9157f 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu4x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c @@ -10,18 +10,11 @@ #include "iris_vpu_common.h" #include "iris_vpu_register_defines.h" -#define AON_WRAPPER_MVP_NOC_RESET_SYNCRST (AON_MVP_NOC_RESET + 0x08) -#define CPU_CS_APV_BRIDGE_SYNC_RESET (CPU_BASE_OFFS + 0x174) #define MVP_NOC_RESET_REQ_MASK 0x70103 #define VPU_IDLE_BITS 0x7103 -#define WRAPPER_EFUSE_MONITOR (WRAPPER_BASE_OFFS + 0x08) -#define APV_CLK_HALT BIT(1) #define CORE_CLK_HALT BIT(0) #define CORE_PWR_ON BIT(1) -#define DISABLE_VIDEO_APV_BIT BIT(27) -#define DISABLE_VIDEO_VPP1_BIT BIT(28) -#define DISABLE_VIDEO_VPP0_BIT BIT(29) static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 efuse_value) { @@ -63,79 +56,6 @@ static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 return ret; } -static int iris_vpu4x_power_on_apv(struct iris_core *core) -{ - return iris_enable_power_domain_and_clocks(core, core->apv); -} - -static void iris_vpu4x_power_off_apv(struct iris_core *core) -{ - bool handshake_done, handshake_busy; - u32 value, count = 0; - int ret; - - value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); - - if (value & APV_CLK_HALT) - writel(0x0, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); - - do { - writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); - usleep_range(10, 20); - value = readl(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS); - - handshake_done = value & NOC_LPI_STATUS_DONE; - handshake_busy = value & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); - - if (handshake_done || !handshake_busy) - break; - - writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); - usleep_range(10, 20); - - } while (++count < 1000); - - if (!handshake_done && handshake_busy) - dev_err(core->dev, "LPI handshake timeout\n"); - - writel(0x080200, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); - ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, - value, value & 0x080200, 200, 2000); - if (ret) - goto disable_clocks_and_power; - - writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_SYNCRST); - writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); - ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, - value, value == 0x0, 200, 2000); - if (ret) - goto disable_clocks_and_power; - - writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + - CPU_CS_APV_BRIDGE_SYNC_RESET); - writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); - writel(0x0, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); - -disable_clocks_and_power: - iris_disable_power_domain_and_clocks(core, core->apv); -} - -static void iris_vpu4x_ahb_sync_reset_apv(struct iris_core *core) -{ - writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + - CPU_CS_APV_BRIDGE_SYNC_RESET); - writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); - writel(0x0, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); -} - -static void iris_vpu4x_ahb_sync_reset_hardware(struct iris_core *core) -{ - writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + - CPU_CS_AHB_BRIDGE_SYNC_RESET); - writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); - writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); -} - static int iris_vpu4x_power_on_hardware(struct iris_core *core) { u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR); @@ -158,7 +78,7 @@ static int iris_vpu4x_power_on_hardware(struct iris_core *core) } if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) { - ret = iris_vpu4x_power_on_apv(core); + ret = iris_vpu_power_on_apv(core); if (ret) goto disable_vpp1_power_domain; } @@ -187,7 +107,7 @@ static void iris_vpu4x_power_off_hardware(struct iris_core *core) iris_vpu4x_genpd_set_hwmode(core, false, efuse_value); if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) - iris_vpu4x_power_off_apv(core); + iris_vpu_power_off_apv(core); value = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS); @@ -258,9 +178,9 @@ static int iris_vpu4x_set_hwmode(struct iris_core *core) u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR); if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) - iris_vpu4x_ahb_sync_reset_apv(core); + iris_vpu_ahb_sync_reset_apv(core); - iris_vpu4x_ahb_sync_reset_hardware(core); + iris_vpu_ahb_sync_reset_hardware(core); return iris_vpu4x_genpd_set_hwmode(core, true, efuse_value); } diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c index 83e2144aada15..8c50d5e0e9a41 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c @@ -21,6 +21,7 @@ #define CTRL_INIT_IDLE_MSG_BMSK 0x40000000 #define CTRL_ERROR_STATUS__M 0xfe #define CTRL_STATUS_PC_READY 0x100 +#define NOC_RESET_APV 0x080200 #define QTBL_INFO (CPU_CS_BASE_OFFS + 0x50) #define QTBL_ENABLE BIT(0) @@ -482,6 +483,79 @@ int iris_vpu_power_on(struct iris_core *core) return ret; } +int iris_vpu_power_on_apv(struct iris_core *core) +{ + return iris_enable_power_domain_and_clocks(core, core->apv); +} + +void iris_vpu_power_off_apv(struct iris_core *core) +{ + bool handshake_done, handshake_busy; + u32 value, count = 0; + int ret; + + value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + + if (value & APV_CLK_HALT) + writel(0x0, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + + do { + writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + usleep_range(10, 20); + value = readl(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS); + + handshake_done = value & NOC_LPI_STATUS_DONE; + handshake_busy = value & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); + + if (handshake_done || !handshake_busy) + break; + + writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + usleep_range(10, 20); + + } while (++count < 1000); + + if (!handshake_done && handshake_busy) + dev_err(core->dev, "LPI handshake timeout\n"); + + writel(0x080200, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, + value, value & 0x080200, 200, 2000); + if (ret) + goto disable_clocks_and_power; + + writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_SYNCRST); + writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, + value, value == 0x0, 200, 2000); + if (ret) + goto disable_clocks_and_power; + + writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + + CPU_CS_APV_BRIDGE_SYNC_RESET); + writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); + writel(0x0, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); + +disable_clocks_and_power: + iris_disable_power_domain_and_clocks(core, core->apv); +} + +void iris_vpu_ahb_sync_reset_apv(struct iris_core *core) +{ + writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + + CPU_CS_APV_BRIDGE_SYNC_RESET); + writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); + writel(0x0, core->reg_base + CPU_CS_APV_BRIDGE_SYNC_RESET); +} + +void iris_vpu_ahb_sync_reset_hardware(struct iris_core *core) +{ + writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); +} + void iris_vpu_set_preset_registers(struct iris_core *core) { writel(0x0, core->reg_base + 0xb0088); diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index 206f1e476d3ce..fdbc75cb5152b 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -49,6 +49,10 @@ int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core); int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core); void iris_vpu35_vpu4x_program_bootup_registers(struct iris_core *core); u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst *inst, size_t data_size); +int iris_vpu_power_on_apv(struct iris_core *core); +void iris_vpu_power_off_apv(struct iris_core *core); +void iris_vpu_ahb_sync_reset_apv(struct iris_core *core); +void iris_vpu_ahb_sync_reset_hardware(struct iris_core *core); void iris_vpu_set_preset_registers(struct iris_core *core); void iris_vpu_interrupt_init(struct iris_core *core); diff --git a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h index 23068fca5f637..9da580452a1d7 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h @@ -22,6 +22,7 @@ #define VIDEO_NOC_RESET_REQ (BIT(0) | BIT(1)) #define AON_WRAPPER_MVP_NOC_RESET_ACK (AON_MVP_NOC_RESET + 0x004) +#define AON_WRAPPER_MVP_NOC_RESET_SYNCRST (AON_MVP_NOC_RESET + 0x08) #define CPU_CS_BASE_OFFS (CPU_BASE_OFFS) #define CPU_IC_BASE_OFFS (CPU_BASE_OFFS) @@ -46,6 +47,14 @@ #define MSK_SIGNAL_FROM_TENSILICA BIT(0) #define MSK_CORE_POWER_ON BIT(1) +#define CPU_CS_APV_BRIDGE_SYNC_RESET (CPU_CS_BASE_OFFS + 0x174) + +/* Efuse bits controlling optional hardware blocks */ +#define WRAPPER_EFUSE_MONITOR (WRAPPER_BASE_OFFS + 0x08) +#define DISABLE_VIDEO_APV_BIT BIT(27) +#define DISABLE_VIDEO_VPP1_BIT BIT(28) +#define DISABLE_VIDEO_VPP0_BIT BIT(29) + #define WRAPPER_INTR_STATUS (WRAPPER_BASE_OFFS + 0x0C) #define WRAPPER_INTR_STATUS_A2H_BMSK BIT(2) @@ -74,6 +83,7 @@ #define WRAPPER_CORE_CLOCK_CONFIG (WRAPPER_BASE_OFFS + 0x88) #define CORE_CLK_RUN 0x0 +#define APV_CLK_HALT BIT(1) #define WRAPPER_TZ_CPU_STATUS (WRAPPER_TZ_BASE_OFFS + 0x10) From 0e9a31847e3d27dc7ac554652bf5b6cdc3794893 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 11:27:53 +0800 Subject: [PATCH 0609/1133] FROMLIST: media: iris: add VPU5x hardware ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Hawi SoC uses the VPU5x generation of the Iris video hardware, which requires handling for two new power domains — mm-int for the internal memory interconnect and cx-int for the CX domain AXI interface — as well as additional generation-specific clocks. Without a VPU5x vpu_ops implementation the Iris driver cannot power on or off the hardware on Hawi. Move the shared idle and core power status definitions to the common register header so they can be used by both VPU4x and VPU5x code. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_hawi-v2-3-016ec3d24b79@oss.qualcomm.com/ Signed-off-by: Wangao Wang --- drivers/media/platform/qcom/iris/Makefile | 1 + drivers/media/platform/qcom/iris/iris_core.h | 4 + drivers/media/platform/qcom/iris/iris_vpu4x.c | 4 - drivers/media/platform/qcom/iris/iris_vpu5x.c | 448 ++++++++++++++++++ .../platform/qcom/iris/iris_vpu_common.h | 1 + .../qcom/iris/iris_vpu_register_defines.h | 4 + 6 files changed, 458 insertions(+), 4 deletions(-) create mode 100644 drivers/media/platform/qcom/iris/iris_vpu5x.c diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index 672b89a2bc43a..695090117cabf 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -30,6 +30,7 @@ qcom-iris-objs += iris_buffer.o \ iris_vpu2.o \ iris_vpu3x.o \ iris_vpu4x.o \ + iris_vpu5x.o \ iris_platform_vpu4x.o \ iris_vpu_ar50lt.o \ iris_vpu_buffer.o \ diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index 26e1a564a9966..cad20caf7a0cc 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -71,6 +71,8 @@ struct dentry; * @vcodec_vpp0: power domain and clocks for the vcodec VPP0 * @vcodec_vpp1: power domain and clocks for the vcodec VPP1 * @apv: power domain and clocks for the APV hardware block + * @mm_int: power domain and clocks for the MM interconnect block + * @cx_int: power domain and clocks for the CX interconnect block * @opp_pmdomain_tbl: table of opp power domains * @resets: table of iris reset clocks * @controller_resets: table of controller reset clocks @@ -123,6 +125,8 @@ struct iris_core { struct iris_power_domain *vcodec_vpp0; struct iris_power_domain *vcodec_vpp1; struct iris_power_domain *apv; + struct iris_power_domain *mm_int; + struct iris_power_domain *cx_int; struct dev_pm_domain_list *opp_pmdomain_tbl; struct reset_control_bulk_data *resets; struct reset_control_bulk_data *controller_resets; diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c index 2fdb89fc9157f..144b87a06e220 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu4x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c @@ -11,10 +11,6 @@ #include "iris_vpu_register_defines.h" #define MVP_NOC_RESET_REQ_MASK 0x70103 -#define VPU_IDLE_BITS 0x7103 - -#define CORE_CLK_HALT BIT(0) -#define CORE_PWR_ON BIT(1) static int iris_vpu4x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 efuse_value) { diff --git a/drivers/media/platform/qcom/iris/iris_vpu5x.c b/drivers/media/platform/qcom/iris/iris_vpu5x.c new file mode 100644 index 0000000000000..7a4ed4b3a81db --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_vpu5x.c @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include + +#include "iris_instance.h" +#include "iris_vpu_common.h" +#include "iris_vpu_register_defines.h" + +/* + * iris5 specific register defines. + * Many base offsets are shared with prior generations: + * WRAPPER_BASE_OFFS = 0x000B0000 + * AON_BASE_OFFS = 0x000E0000 + * AON_MVP_NOC_RESET = 0x0001F000 + * CPU_BASE_OFFS = 0x000A0000 + */ + +#define WRAPPER_MVP_NOC_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x110) +#define WRAPPER_MVP_NOC_LPI_STATUS (WRAPPER_BASE_OFFS + 0x114) +#define WRAPPER_MVP_NOC_CX_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x118) +#define WRAPPER_MVP_NOC_CX_LPI_STATUS (WRAPPER_BASE_OFFS + 0x11C) + +#define AON_WRAPPER_MVP_NOC_ARCG_CONTROL (AON_BASE_OFFS + 0x10) + +#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL (AON_BASE_OFFS + 0x2C) +#define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS (AON_BASE_OFFS + 0x30) + +#define CPU_NOC_BASE_OFFS 0x000D0000 +#define CPU_NOC_ERRORLOGGER_MAINCTL_LOW (CPU_NOC_BASE_OFFS + 0x08) +#define CPU_NOC_SBM_FAULTINEN0_LOW (CPU_NOC_BASE_OFFS + 0x240) + +#define NOC_BASE_OFFS 0x00010000 +#define NOC_ERL_ERRORLOGGER_MAINCTL_LOW (NOC_BASE_OFFS + 0xA008) +#define NOC_ERL_ERRORLOGGER_ERRCLR_LOW (NOC_BASE_OFFS + 0xA018) +#define NOC_SBM_FAULTINEN0_LOW (NOC_BASE_OFFS + 0x7040) + +#define NOC5_RESET_VPP0_ONLY_DISABLED 0x36010E +#define NOC5_RESET_VPP1_DISABLED 0x35000F +#define NOC5_RESET_ALL_VPP_ENABLED 0x37010F + +#define NOC_LPI_PD_QREQ BIT(0) +#define NOC_SBM_FAULTINEN0_PORT0 BIT(0) +#define NOC_ERRORLOGGER_MAINCTL_FAULTEN BIT(0) +#define NOC_ERL_ERRORLOGGER_ERRCLR BIT(0) +#define AON_MVP_NOC_ARCG_OVERRIDE BIT(0) + +#define WRAPPER_INTR_MASK_SS_CPU_NOC BIT(6) +#define WRAPPER_INTR_MASK_SS_NOC BIT(5) + +static bool iris_vpu5x_hw_power_collapsed(struct iris_core *core) +{ + u32 value = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS); + + return !(value & CORE_PWR_ON); +} + +static int iris_vpu5x_genpd_set_hwmode(struct iris_core *core, bool hw_mode, u32 efuse_value) +{ + int ret; + + ret = iris_genpd_set_hwmode(core->vcodec, hw_mode); + if (ret) + return ret; + + if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { + ret = iris_genpd_set_hwmode(core->vcodec_vpp0, hw_mode); + if (ret) + goto restore_hw_domain_mode; + } + + if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { + ret = iris_genpd_set_hwmode(core->vcodec_vpp1, hw_mode); + if (ret) + goto restore_vpp0_domain_mode; + } + + if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) { + ret = iris_genpd_set_hwmode(core->apv, hw_mode); + if (ret) + goto restore_vpp1_domain_mode; + } + + ret = iris_genpd_set_hwmode(core->mm_int, hw_mode); + if (ret) + goto restore_apv_domain_mode; + + ret = iris_genpd_set_hwmode(core->cx_int, hw_mode); + if (ret) + goto restore_mm_int_domain_mode; + + return 0; + +restore_mm_int_domain_mode: + iris_genpd_set_hwmode(core->mm_int, !hw_mode); +restore_apv_domain_mode: + if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) + iris_genpd_set_hwmode(core->apv, !hw_mode); +restore_vpp1_domain_mode: + if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) + iris_genpd_set_hwmode(core->vcodec_vpp1, !hw_mode); +restore_vpp0_domain_mode: + if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) + iris_genpd_set_hwmode(core->vcodec_vpp0, !hw_mode); +restore_hw_domain_mode: + iris_genpd_set_hwmode(core->vcodec, !hw_mode); + + return ret; +} + +static int iris_vpu5x_set_hwmode(struct iris_core *core) +{ + u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR); + + if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) + iris_vpu_ahb_sync_reset_apv(core); + + iris_vpu_ahb_sync_reset_hardware(core); + + return iris_vpu5x_genpd_set_hwmode(core, true, efuse_value); +} + +/* + * Perform an LPI power-down handshake on a single NOC interface. + * + * Sets QREQ and polls for the status DONE bit. On a busy response the request + * is toggled and, when @errclr_offs is non-zero, the NOC error-log clear + * register at that offset is written between retries to unblock the fabric. + * Pass @errclr_offs = 0 for interfaces that do not require error clearing. + */ +static void iris_vpu5x_noc_lpi_handshake(struct iris_core *core, + u32 ctrl_offs, u32 status_offs, + u32 busy_mask, u32 errclr_offs, + const char *name) +{ + bool handshake_done, handshake_busy; + u32 value, count = 0; + int ret; + + do { + if (errclr_offs) { + value = readl(core->reg_base + errclr_offs); + value |= NOC_ERL_ERRORLOGGER_ERRCLR; + writel(value, core->reg_base + errclr_offs); + } + + value = readl(core->reg_base + ctrl_offs); + value |= NOC_LPI_PD_QREQ; + writel(value, core->reg_base + ctrl_offs); + usleep_range(10, 20); + + value = readl(core->reg_base + status_offs); + handshake_done = value & NOC_LPI_STATUS_DONE; + handshake_busy = value & busy_mask; + + if (handshake_done || !handshake_busy) + break; + + value = readl(core->reg_base + ctrl_offs); + value &= ~NOC_LPI_PD_QREQ; + writel(value, core->reg_base + ctrl_offs); + usleep_range(10, 20); + + } while (++count < 1000); + + if (!handshake_done && handshake_busy) + dev_err(core->dev, "%s NOC LPI handshake timeout\n", name); + + ret = readl_poll_timeout(core->reg_base + status_offs, + value, value & NOC_LPI_STATUS_DONE, 200, 2000); + if (ret) + dev_err(core->dev, "%s NOC LPI status timeout\n", name); + + value = readl(core->reg_base + ctrl_offs); + value &= ~NOC_LPI_PD_QREQ; + writel(value, core->reg_base + ctrl_offs); +} + +static int iris_vpu5x_power_on_cx_int(struct iris_core *core) +{ + u32 value; + int ret; + + ret = iris_enable_power_domain_and_clocks(core, core->cx_int); + if (ret) + return ret; + + value = readl(core->reg_base + WRAPPER_MVP_NOC_CX_LPI_CONTROL); + value &= ~NOC_LPI_PD_QREQ; + writel(value, core->reg_base + WRAPPER_MVP_NOC_CX_LPI_CONTROL); + + readl_poll_timeout(core->reg_base + WRAPPER_MVP_NOC_CX_LPI_STATUS, + value, !(value & NOC_LPI_STATUS_DONE), 200, 2000); + + return 0; +} + +static void iris_vpu5x_power_off_cx_int(struct iris_core *core) +{ + iris_vpu5x_noc_lpi_handshake(core, + WRAPPER_MVP_NOC_CX_LPI_CONTROL, + WRAPPER_MVP_NOC_CX_LPI_STATUS, + NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE, + NOC_ERL_ERRORLOGGER_ERRCLR_LOW, "CX"); + + iris_disable_power_domain_and_clocks(core, core->cx_int); +} + +static int iris_vpu5x_power_on_mm_int(struct iris_core *core) +{ + u32 value; + int ret; + + ret = iris_enable_power_domain_and_clocks(core, core->mm_int); + if (ret) + return ret; + + value = readl(core->reg_base + WRAPPER_MVP_NOC_LPI_CONTROL); + value &= ~NOC_LPI_PD_QREQ; + writel(value, core->reg_base + WRAPPER_MVP_NOC_LPI_CONTROL); + + readl_poll_timeout(core->reg_base + WRAPPER_MVP_NOC_LPI_STATUS, + value, !(value & NOC_LPI_STATUS_DONE), 200, 2000); + + return 0; +} + +static void iris_vpu5x_power_off_mm_int(struct iris_core *core) +{ + u32 value; + + value = readl(core->reg_base + WRAPPER_MVP_NOC_LPI_CONTROL); + value &= ~NOC_LPI_PD_QREQ; + writel(value, core->reg_base + WRAPPER_MVP_NOC_LPI_CONTROL); + + value = readl(core->reg_base + WRAPPER_MVP_NOC_CX_LPI_CONTROL); + value &= ~NOC_LPI_PD_QREQ; + writel(value, core->reg_base + WRAPPER_MVP_NOC_CX_LPI_CONTROL); + + iris_vpu5x_noc_lpi_handshake(core, + WRAPPER_MVP_NOC_LPI_CONTROL, + WRAPPER_MVP_NOC_LPI_STATUS, + NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE, + NOC_ERL_ERRORLOGGER_ERRCLR_LOW, "MM"); + + iris_disable_power_domain_and_clocks(core, core->mm_int); +} + +static int iris_vpu5x_power_on_hardware(struct iris_core *core) +{ + u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR); + int ret; + + ret = iris_vpu5x_power_on_cx_int(core); + if (ret) + return ret; + + ret = iris_vpu5x_power_on_mm_int(core); + if (ret) + goto err_disable_cx_int; + + ret = iris_enable_power_domain_and_clocks(core, core->vcodec); + if (ret) + goto err_disable_mm_int; + + if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) { + ret = iris_enable_power_domain_and_clocks(core, core->vcodec_vpp0); + if (ret) + goto err_disable_hw_power; + } + + if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) { + ret = iris_enable_power_domain_and_clocks(core, core->vcodec_vpp1); + if (ret) + goto err_disable_vpp0_power; + } + + if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) { + ret = iris_vpu_power_on_apv(core); + if (ret) + goto err_disable_vpp1_power; + } + + return 0; + +err_disable_vpp1_power: + if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) + iris_disable_power_domain_and_clocks(core, core->vcodec_vpp1); +err_disable_vpp0_power: + if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) + iris_disable_power_domain_and_clocks(core, core->vcodec_vpp0); +err_disable_hw_power: + iris_disable_power_domain_and_clocks(core, core->vcodec); +err_disable_mm_int: + iris_vpu5x_power_off_mm_int(core); +err_disable_cx_int: + iris_vpu5x_power_off_cx_int(core); + + return ret; +} + +static void iris_vpu5x_power_off_hardware(struct iris_core *core) +{ + u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR); + u32 noc_reset_mask; + u32 value; + int ret; + + iris_vpu5x_genpd_set_hwmode(core, false, efuse_value); + + if (!(efuse_value & DISABLE_VIDEO_APV_BIT)) + iris_vpu_power_off_apv(core); + + if (iris_vpu5x_hw_power_collapsed(core)) + goto disable_clocks_and_power; + + value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + if (value & CORE_CLK_HALT) + writel(CORE_CLK_RUN, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG); + + readl_poll_timeout(core->reg_base + VCODEC_SS_IDLE_STATUSN, + value, (value & VPU_IDLE_BITS) == VPU_IDLE_BITS, 2000, 20000); + + if (efuse_value & DISABLE_VIDEO_VPP0_BIT) + noc_reset_mask = NOC5_RESET_VPP0_ONLY_DISABLED; + else if (efuse_value & DISABLE_VIDEO_VPP1_BIT) + noc_reset_mask = NOC5_RESET_VPP1_DISABLED; + else + noc_reset_mask = NOC5_RESET_ALL_VPP_ENABLED; + + writel(noc_reset_mask, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, + value, (value & noc_reset_mask) == noc_reset_mask, 200, 2000); + if (ret) + dev_err(core->dev, "MVP NOC reset ack timeout\n"); + + writel(noc_reset_mask, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_SYNCRST); + writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_SYNCRST); + writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ); + + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK, + value, value == 0x0, 200, 2000); + if (ret) + dev_err(core->dev, "MVP NOC reset deassert timeout\n"); + + writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, + core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET); + +disable_clocks_and_power: + if (!(efuse_value & DISABLE_VIDEO_VPP1_BIT)) + iris_disable_power_domain_and_clocks(core, core->vcodec_vpp1); + + if (!(efuse_value & DISABLE_VIDEO_VPP0_BIT)) + iris_disable_power_domain_and_clocks(core, core->vcodec_vpp0); + + iris_disable_power_domain_and_clocks(core, core->vcodec); + iris_vpu5x_power_off_mm_int(core); + iris_vpu5x_power_off_cx_int(core); +} + +static int iris_vpu5x_power_on_controller(struct iris_core *core) +{ + u32 mask_val; + int ret; + + ret = iris_enable_power_domain_and_clocks(core, core->ctrl); + if (ret) + return ret; + + mask_val = readl(core->reg_base + CPU_NOC_SBM_FAULTINEN0_LOW); + mask_val |= NOC_SBM_FAULTINEN0_PORT0; + writel(mask_val, core->reg_base + CPU_NOC_SBM_FAULTINEN0_LOW); + + mask_val = readl(core->reg_base + CPU_NOC_ERRORLOGGER_MAINCTL_LOW); + mask_val |= NOC_ERRORLOGGER_MAINCTL_FAULTEN; + writel(mask_val, core->reg_base + CPU_NOC_ERRORLOGGER_MAINCTL_LOW); + + mask_val = readl(core->reg_base + WRAPPER_INTR_MASK); + mask_val &= ~WRAPPER_INTR_MASK_SS_CPU_NOC; + writel(mask_val, core->reg_base + WRAPPER_INTR_MASK); + + mask_val = readl(core->reg_base + NOC_SBM_FAULTINEN0_LOW); + mask_val |= NOC_SBM_FAULTINEN0_PORT0; + writel(mask_val, core->reg_base + NOC_SBM_FAULTINEN0_LOW); + + mask_val = readl(core->reg_base + NOC_ERL_ERRORLOGGER_MAINCTL_LOW); + mask_val |= NOC_ERRORLOGGER_MAINCTL_FAULTEN; + writel(mask_val, core->reg_base + NOC_ERL_ERRORLOGGER_MAINCTL_LOW); + + mask_val = readl(core->reg_base + WRAPPER_INTR_MASK); + mask_val &= ~WRAPPER_INTR_MASK_SS_NOC; + writel(mask_val, core->reg_base + WRAPPER_INTR_MASK); + + return 0; +} + +static int iris_vpu5x_power_off_controller(struct iris_core *core) +{ + u32 ctrl_rst_tbl_size = core->iris_platform_data->controller_rst_tbl_size; + u32 value; + + writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, + core->reg_base + CPU_CS_X2RPMH); + + iris_vpu5x_noc_lpi_handshake(core, + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL, + WRAPPER_IRIS_CPU_NOC_LPI_STATUS, + NOC_LPI_STATUS_DENY, 0, "CPU"); + + iris_vpu5x_noc_lpi_handshake(core, + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL, + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS, + NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE, 0, "Video CTL"); + + writel(0x0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL); + readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS, + value, value == 0x0, 200, 2000); + + value = readl(core->reg_base + AON_WRAPPER_MVP_NOC_ARCG_CONTROL); + value |= AON_MVP_NOC_ARCG_OVERRIDE; + writel(value, core->reg_base + AON_WRAPPER_MVP_NOC_ARCG_CONTROL); + + iris_disable_power_domain_and_clocks(core, core->ctrl); + + reset_control_bulk_assert(ctrl_rst_tbl_size, core->controller_resets); + usleep_range(400, 500); + reset_control_bulk_deassert(ctrl_rst_tbl_size, core->controller_resets); + + return 0; +} + +const struct vpu_ops iris_vpu5x_ops = { + .power_off_hw = iris_vpu5x_power_off_hardware, + .power_on_hw = iris_vpu5x_power_on_hardware, + .power_off_controller = iris_vpu5x_power_off_controller, + .power_on_controller = iris_vpu5x_power_on_controller, + .program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers, + .calc_freq = iris_vpu3x_vpu4x_calculate_frequency, + .set_hwmode = iris_vpu5x_set_hwmode, + .interrupt_init = iris_vpu_interrupt_init, + .set_preset_registers = iris_vpu_set_preset_registers, +}; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h index fdbc75cb5152b..95d9e8a507aec 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_common.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h @@ -14,6 +14,7 @@ extern const struct vpu_ops iris_vpu33_ops; extern const struct vpu_ops iris_vpu35_ops; extern const struct vpu_ops iris_vpu36_ops; extern const struct vpu_ops iris_vpu4x_ops; +extern const struct vpu_ops iris_vpu5x_ops; extern const struct vpu_ops iris_vpu_ar50lt_ops; struct vpu_ops { diff --git a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h index 9da580452a1d7..909575daa6a71 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h @@ -97,4 +97,8 @@ #define AON_WRAPPER_MVP_NOC_LPI_CONTROL (AON_BASE_OFFS) #define AON_WRAPPER_MVP_NOC_LPI_STATUS (AON_BASE_OFFS + 0x4) +#define VPU_IDLE_BITS 0x7103 +#define CORE_CLK_HALT BIT(0) +#define CORE_PWR_ON BIT(1) + #endif From eb76807fa5758f1fe64579956ac363ff7cb64acd Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 11:27:54 +0800 Subject: [PATCH 0610/1133] FROMLIST: media: iris: add VPU5x internal buffer size calculations VPU5x firmware uses internal buffer formulas that differ from VPU4x. In particular, the H.265 decoder persistent buffer needs space for SEI unregistered userdata and three-dimensional userdata, and the encoder calculations use a larger lambda LUT size. Add a VPU5x buffer-size dispatcher and a VPU5x-specific H.265 persistent buffer calculation while reusing the existing helpers for buffer types whose formulas are unchanged. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_hawi-v2-4-016ec3d24b79@oss.qualcomm.com/ Signed-off-by: Wangao Wang --- .../platform/qcom/iris/iris_vpu_buffer.c | 141 ++++++++++++++++++ .../platform/qcom/iris/iris_vpu_buffer.h | 4 +- 2 files changed, 144 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index 756dc63e23d80..068a25b9c235b 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -2216,6 +2216,54 @@ static u32 iris_vpu4x_dec_line_size(struct iris_inst *inst) return 0; } +/* iris5 AV1 line buffer uses hardware-specific LUT values indexed by resolution bucket */ +static u32 iris_vpu5x_dec_line_size_av1(u32 width, u32 height, + bool is_opb, u32 num_vpp_pipes) +{ + static const u32 lut_left[4] = { 905472, 1356800, 2890752, 5778432 }; + static const u32 lut_top[4][2] = { + { 307200, 450048 }, /* HD */ + { 499200, 713472 }, /* FHD */ + { 1343488, 1800192 }, /* 4K */ + { 3735552, 4648960 }, /* 8K */ + }; + u32 h_idx, w_idx; + + if (height <= 1280) + h_idx = 0; + else if (height <= 1920) + h_idx = 1; + else if (height <= 4096) + h_idx = 2; + else + h_idx = 3; + + if (width <= 1280) + w_idx = 0; + else if (width <= 1920) + w_idx = 1; + else if (width <= 4096) + w_idx = 2; + else + w_idx = 3; + + return lut_left[h_idx] * num_vpp_pipes + lut_top[w_idx][is_opb]; +} + +static u32 iris_vpu5x_dec_line_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_src; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + bool is_opb = iris_split_mode_enabled(inst); + + if (inst->codec == V4L2_PIX_FMT_AV1) + return iris_vpu5x_dec_line_size_av1(width, height, is_opb, num_vpp_pipes); + + return iris_vpu4x_dec_line_size(inst); +} + static u32 hfi_vpu4x_buffer_persist_h265d(u32 rpu_enabled) { return ALIGN((SIZE_SLIST_BUF_H265 * NUM_SLIST_BUF_H265 + H265_NUM_FRM_INFO * @@ -2272,6 +2320,54 @@ static u32 iris_vpu4x_dec_persist_size(struct iris_inst *inst) return 0; } +static u32 hfi_vpu5x_buffer_persist_h265d(bool rpu_enabled) +{ + u32 slist_buf = SIZE_SLIST_BUF_H265 * NUM_SLIST_BUF_H265; + u32 frame_info = H265_NUM_FRM_INFO * H265_DISPLAY_BUF_SIZE; + u32 tile_info = H265_NUM_TILE * sizeof(u32); + u32 per_pic = NUM_HW_PIC_BUF * + (SIZE_SEI_USERDATA + SIZE_SEI_USERDATA_UNREGISTERED + SIZE_H265D_ARP + + SIZE_THREE_DIMENSION_USERDATA); + u32 dolby_rpu = rpu_enabled * NUM_HW_PIC_BUF * SIZE_DOLBY_RPU_METADATA; + + return ALIGN(slist_buf + frame_info + tile_info + per_pic + dolby_rpu, DMA_ALIGNMENT); +} + +static u32 hfi_vpu5x_buffer_persist_av1d(u32 max_width, u32 max_height, u32 total_ref_count) +{ + u32 comv_size = hfi_buffer_comv_av1d(max_width, max_height, total_ref_count); + u32 seq_hdr = SIZE_AV1D_SEQUENCE_HEADER * 2 + SIZE_AV1D_METADATA; + u32 per_pic = AV1D_NUM_HW_PIC_BUF * + (SIZE_AV1D_TILE_OFFSET + SIZE_AV1D_QM + SIZE_AV1D_ARP + SIZE_AV1D_METADATA); + u32 frame_hdr = AV1D_NUM_FRAME_HEADERS * + (SIZE_AV1D_FRAME_HEADER + 2 * SIZE_AV1D_PROB_TABLE); + + return ALIGN(seq_hdr + per_pic + frame_hdr + comv_size + HDR10_HIST_EXTRADATA_SIZE, + DMA_ALIGNMENT); +} + +static u32 iris_vpu5x_dec_persist_size(struct iris_inst *inst) +{ + struct platform_inst_caps *caps; + + if (inst->codec == V4L2_PIX_FMT_H264) { + return hfi_buffer_persist_h264d(); + } else if (inst->codec == V4L2_PIX_FMT_HEVC) { + return hfi_vpu5x_buffer_persist_h265d(0); + } else if (inst->codec == V4L2_PIX_FMT_VP9) { + return hfi_vpu4x_buffer_persist_vp9d(); + } else if (inst->codec == V4L2_PIX_FMT_AV1) { + caps = inst->core->iris_platform_data->inst_caps; + if (inst->fw_caps[DRAP].value) + return hfi_vpu5x_buffer_persist_av1d(caps->max_frame_width, + caps->max_frame_height, 16); + else + return hfi_vpu5x_buffer_persist_av1d(0, 0, 0); + } + + return 0; +} + static u32 size_se_lb(u32 standard, u32 num_vpp_pipes_enc, u32 frame_width_coded, u32 frame_height_coded) { @@ -2598,6 +2694,51 @@ u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_typ return size; } +u32 iris_vpu5x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + const struct iris_vpu_buf_type_handle *buf_type_handle_arr = NULL; + u32 size = 0, buf_type_handle_size = 0, i; + + static const struct iris_vpu_buf_type_handle dec_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_dec_bin_size }, + {BUF_COMV, iris_vpu3x_4x_dec_comv_size }, + {BUF_NON_COMV, iris_vpu_dec_non_comv_size }, + {BUF_LINE, iris_vpu5x_dec_line_size }, + {BUF_PERSIST, iris_vpu5x_dec_persist_size }, + {BUF_DPB, iris_vpu_dec_dpb_size }, + {BUF_SCRATCH_1, iris_vpu_dec_scratch1_size }, + {BUF_PARTIAL, iris_vpu_dec_partial_size }, + }; + + static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_enc_bin_size }, + {BUF_COMV, iris_vpu_enc_comv_size }, + {BUF_NON_COMV, iris_vpu_enc_non_comv_size }, + {BUF_LINE, iris_vpu4x_enc_line_size }, + {BUF_ARP, iris_vpu_enc_arp_size }, + {BUF_VPSS, iris_vpu_enc_vpss_size }, + {BUF_SCRATCH_1, iris_vpu_enc_scratch1_size }, + {BUF_SCRATCH_2, iris_vpu_enc_scratch2_size }, + }; + + if (inst->domain == DECODER) { + buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle); + buf_type_handle_arr = dec_internal_buf_type_handle; + } else if (inst->domain == ENCODER) { + buf_type_handle_size = ARRAY_SIZE(enc_internal_buf_type_handle); + buf_type_handle_arr = enc_internal_buf_type_handle; + } + + for (i = 0; i < buf_type_handle_size; i++) { + if (buf_type_handle_arr[i].type == buffer_type) { + size = buf_type_handle_arr[i].handle(inst); + break; + } + } + + return size; +} + u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) { return inst->buffers[buffer_type].size; diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index 9af2c8611484c..53c5fa8d62209 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -67,6 +67,7 @@ struct iris_inst; #define VP9_UDC_HEADER_BUF_SIZE (3 * 128) #define SIZE_SEI_USERDATA 4096 +#define SIZE_SEI_USERDATA_UNREGISTERED 256 #define SIZE_DOLBY_RPU_METADATA (41 * 1024) #define H264_CABAC_HDR_RATIO_HD_TOT 1 #define H264_CABAC_RES_RATIO_HD_TOT 3 @@ -132,7 +133,7 @@ struct iris_inst; #define SIZE_SLICE_CMD_BUFFER (ALIGN(20480, 256)) #define SIZE_SPS_PPS_SLICE_HDR (2048 + 4096) #define SIZE_BSE_SLICE_CMD_BUF ((((8192 << 2) + 7) & (~7)) * 3) -#define SIZE_LAMBDA_LUT (256 * 11) +#define SIZE_LAMBDA_LUT (256 * 13) #define HFI_COL_FMT_NV12C_Y_TILE_HEIGHT (8) #define HFI_COL_FMT_NV12C_Y_TILE_WIDTH (32) @@ -341,6 +342,7 @@ static inline u32 size_av1d_qp(u32 frame_width, u32 frame_height) u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +u32 iris_vpu5x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); u32 iris_vpu_ar50lt_gen2_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type); From 3f0cfdb5d0d0f41059963504dbcfd0c7613f566f Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 11:27:55 +0800 Subject: [PATCH 0611/1133] FROMLIST: media: iris: add hawi platform data The Iris block in the Hawi SoC is a VPU5 capable of decoding H.264, H.265, VP9 and AV1, and encoding H.264 and H.265. Add the platform data entry describing the Hawi-specific clock tree, power domains, firmware image, bandwidth table, DMA address range, and secure memory regions so the Iris driver can match the qcom,hawi-iris compatible and initialize the hardware. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_hawi-v2-5-016ec3d24b79@oss.qualcomm.com/ Signed-off-by: Wangao Wang --- drivers/media/platform/qcom/iris/Makefile | 1 + .../platform/qcom/iris/iris_platform_common.h | 3 + .../platform/qcom/iris/iris_platform_hawi.h | 102 ++++++++++++++++++ .../platform/qcom/iris/iris_platform_vpu5.c | 89 +++++++++++++++ drivers/media/platform/qcom/iris/iris_probe.c | 34 +++++- 5 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/qcom/iris/iris_platform_hawi.h create mode 100644 drivers/media/platform/qcom/iris/iris_platform_vpu5.c diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile index 695090117cabf..7fc93b8e2ceef 100644 --- a/drivers/media/platform/qcom/iris/Makefile +++ b/drivers/media/platform/qcom/iris/Makefile @@ -15,6 +15,7 @@ qcom-iris-objs += iris_buffer.o \ iris_hfi_queue.o \ iris_platform_vpu2.o \ iris_platform_vpu3x.o \ + iris_platform_vpu5.o \ iris_platform_vpu_ar50lt.o \ iris_power.o \ iris_probe.o \ diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index d2bd2c810c53b..cdd62194fe6ee 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -67,6 +67,7 @@ extern const struct platform_inst_slice_caps iris_vpu2_vpu3x_slice_caps; extern const struct platform_inst_slice_caps iris_ar50lt_slice_caps; extern const struct iris_platform_data glymur_data; +extern const struct iris_platform_data hawi_data; extern const struct iris_platform_data kaanapali_data; extern const struct iris_platform_data maili_data; extern const struct iris_platform_data milos_data; @@ -317,6 +318,8 @@ struct iris_platform_data { const struct iris_power_domain_data *vcodec_vpp0_data; const struct iris_power_domain_data *vcodec_vpp1_data; const struct iris_power_domain_data *apv_data; + const struct iris_power_domain_data *mm_int_data; + const struct iris_power_domain_data *cx_int_data; const char * const *opp_pd_tbl; unsigned int opp_pd_tbl_size; const char * const *opp_clk_tbl; diff --git a/drivers/media/platform/qcom/iris/iris_platform_hawi.h b/drivers/media/platform/qcom/iris/iris_platform_hawi.h new file mode 100644 index 0000000000000..3c890b2c2ccfe --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_hawi.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __MEDIA_IRIS_PLATFORM_HAWI_H__ +#define __MEDIA_IRIS_PLATFORM_HAWI_H__ + +static const char * const hawi_clk_reset_table[] = { + "bus0", + "core", +}; + +static const struct iris_power_domain_data hawi_ctrl_data = { + .pd_names = (const char *[]) { + "venus", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "ifacec", "core", "core_ctl_freerun", "core_debug", + }, + .clk_cnt = 4, +}; + +static const struct iris_power_domain_data hawi_vcodec_data[] = { + { + .pd_names = (const char *[]) { + "vcodec0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "iface", "vcodec0_core", "vcodec_bse", + "vcodec_vpp0_vpp1_gating", + }, + .clk_cnt = 4, + }, +}; + +static const struct iris_power_domain_data hawi_vcodec_vpp0_data = { + .pd_names = (const char *[]) { + "vpp0", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec_vpp0", + }, + .clk_cnt = 1, +}; + +static const struct iris_power_domain_data hawi_vcodec_vpp1_data = { + .pd_names = (const char *[]) { + "vpp1", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec_vpp1", + }, + .clk_cnt = 1, +}; + +static const struct iris_power_domain_data hawi_apv_data = { + .pd_names = (const char *[]) { + "apv", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "vcodec_apv", + }, + .clk_cnt = 1, +}; + +static const struct iris_power_domain_data hawi_mm_int_data = { + .pd_names = (const char *[]) { + "mm-int", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "core_freerun", + }, + .clk_cnt = 1, +}; + +static const struct iris_power_domain_data hawi_cx_int_data = { + .pd_names = (const char *[]) { + "cx-int", + }, + .pd_cnt = 1, + .clk_names = (const char *[]) { + "cx_iface", + }, + .clk_cnt = 1, +}; + +static const char *const hawi_opp_clk_table[] = { + "vcodec0_core", + "vcodec_apv", + "vcodec_bse", + "core", + NULL, +}; + +#endif diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu5.c b/drivers/media/platform/qcom/iris/iris_platform_vpu5.c new file mode 100644 index 0000000000000..cade592c4ec26 --- /dev/null +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu5.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include "iris_core.h" +#include "iris_ctrls.h" +#include "iris_hfi_gen2.h" +#include "iris_hfi_gen2_defines.h" +#include "iris_platform_common.h" +#include "iris_vpu_buffer.h" +#include "iris_vpu_common.h" + +#include "iris_platform_sm8550.h" +#include "iris_platform_hawi.h" + +static const struct iris_firmware_desc iris_vpu50_p2_s8_gen2_desc = { + .firmware_data = &iris_hfi_gen2_data, + .get_vpu_buffer_size = iris_vpu5x_buf_size, + .fwname = "qcom/vpu/vpu50_p2_s8.mbn", +}; + +static const u32 iris_fmts_vpu5_dec[] = { + V4L2_PIX_FMT_H264, + V4L2_PIX_FMT_HEVC, + V4L2_PIX_FMT_VP9, + V4L2_PIX_FMT_AV1, +}; + +static const struct icc_info iris_icc_info_vpu5[] = { + { "cpu-cfg", 1000, 1000 }, + { "video-mem", 1000, 15000000 }, +}; + +static const struct bw_info iris_bw_table_dec_vpu5[] = { + { ((4096 * 2160) / 256) * 60, 1608000 }, + { ((4096 * 2160) / 256) * 30, 826000 }, + { ((1920 * 1080) / 256) * 60, 567000 }, + { ((1920 * 1080) / 256) * 30, 294000 }, +}; + +static const char * const iris_opp_pd_table_vpu5[] = { "mxc", "mmcx" }; + +static const struct tz_cp_config tz_cp_config_vpu5[] = { + { + .cp_start = VIDEO_REGION_VM0_SECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x0d000000, + .cp_nonpixel_size = 0x25000000, + }, + { + .cp_start = VIDEO_REGION_VM0_NONSECURE_NP_ID, + .cp_size = 0, + .cp_nonpixel_start = 0x32000000, + .cp_nonpixel_size = 0xcdc00000, + }, +}; + +const struct iris_platform_data hawi_data = { + .firmware_desc_gen2 = &iris_vpu50_p2_s8_gen2_desc, + .vpu_ops = &iris_vpu5x_ops, + .icc_tbl = iris_icc_info_vpu5, + .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu5), + .clk_rst_tbl = hawi_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(hawi_clk_reset_table), + .bw_tbl_dec = iris_bw_table_dec_vpu5, + .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu5), + .ctrl_data = &hawi_ctrl_data, + .vcodec_data = hawi_vcodec_data, + .vcodec_vpp0_data = &hawi_vcodec_vpp0_data, + .vcodec_vpp1_data = &hawi_vcodec_vpp1_data, + .apv_data = &hawi_apv_data, + .mm_int_data = &hawi_mm_int_data, + .cx_int_data = &hawi_cx_int_data, + .opp_pd_tbl = iris_opp_pd_table_vpu5, + .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu5), + .opp_clk_tbl = hawi_opp_clk_table, + /* Upper bound of DMA address range */ + .dma_mask = 0xffc00000 - 1, + .inst_iris_fmts = iris_fmts_vpu5_dec, + .inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu5_dec), + .inst_caps = &platform_inst_cap_sm8550, + .tz_cp_config_data = tz_cp_config_vpu5, + .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu5), + .num_vpp_pipe = 2, + .max_session_count = 16, + .max_core_mbpf = NUM_MBS_8K * 2, + .max_core_mbps = NUM_MBS_8K * 60, +}; diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index e1a03246db18f..d9be442c7fc7c 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -142,6 +142,26 @@ static int iris_init_power_domains(struct iris_core *core) return ret; } + if (plat->mm_int_data) { + core->mm_int = devm_kzalloc(core->dev, sizeof(*core->mm_int), GFP_KERNEL); + if (!core->mm_int) + return -ENOMEM; + + ret = iris_init_power_domains_per_block(core, core->mm_int, plat->mm_int_data); + if (ret) + return ret; + } + + if (plat->cx_int_data) { + core->cx_int = devm_kzalloc(core->dev, sizeof(*core->cx_int), GFP_KERNEL); + if (!core->cx_int) + return -ENOMEM; + + ret = iris_init_power_domains_per_block(core, core->cx_int, plat->cx_int_data); + if (ret) + return ret; + } + ret = devm_pm_domain_attach_list(core->dev, &iris_opp_pd_data, &core->opp_pmdomain_tbl); /* backwards compatibility for incomplete ABI SM8250 */ if (ret == -ENODEV && @@ -204,7 +224,15 @@ static int iris_init_clocks(struct iris_core *core) if (ret) return ret; - return iris_init_clocks_per_block(core, core->apv, plat->apv_data); + ret = iris_init_clocks_per_block(core, core->apv, plat->apv_data); + if (ret) + return ret; + + ret = iris_init_clocks_per_block(core, core->mm_int, plat->mm_int_data); + if (ret) + return ret; + + return iris_init_clocks_per_block(core, core->cx_int, plat->cx_int_data); } static int iris_init_reset_table(struct iris_core *core, @@ -609,6 +637,10 @@ static const struct of_device_id iris_dt_match[] = { .compatible = "qcom,glymur-iris", .data = &glymur_data, }, + { + .compatible = "qcom,hawi-iris", + .data = &hawi_data, + }, { .compatible = "qcom,kaanapali-iris", .data = &kaanapali_data, From 1769579e392f29bbdd2ceb3e2bc2421f4f208b1b Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Mon, 21 Sep 2026 17:51:34 +0800 Subject: [PATCH 0612/1133] FROMLIST: dt-bindings: media: qcom,sm8550-iris: Document Eliza IRIS accelerator Add the qcom,eliza-iris compatible for the IRIS video decoder/encoder accelerator found on the Eliza platform. Eliza belongs to the same IRIS v3 family as SM8550 and SM8650, and uses VPU3.3 with an SM8650-compatible clock and reset configuration. Like SM8650, it requires the bus, xo, and core resets, so include it in the existing allOf constraint that enforces resets minItems: 3. Link: https://lore.kernel.org/linux-arm-msm/20260921-add_iris_for_eliza-v2-1-5fe7be8c0230@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Wangao Wang --- Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml index 81d35be565f9a..0268946145726 100644 --- a/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sm8550-iris.yaml @@ -23,6 +23,7 @@ properties: - qcom,x1e80100-iris - const: qcom,sm8550-iris - enum: + - qcom,eliza-iris - qcom,qcs8300-iris - qcom,sm8550-iris - qcom,sm8650-iris @@ -112,6 +113,7 @@ allOf: properties: compatible: enum: + - qcom,eliza-iris - qcom,sm8650-iris then: properties: From d4b48347db2dd5b830f47b987cfd43f333f8ce84 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Mon, 21 Sep 2026 17:51:35 +0800 Subject: [PATCH 0613/1133] FROMLIST: media: iris: Add support for Eliza Add support for the Eliza Iris video codec. Eliza uses the VPU3.3 hardware with a dedicated vpu33_p2_s7 firmware variant and SM8650-compatible clock/reset tables. Key differences from SM8550: - firmware_desc_gen2: vpu33_p2_s7 (SM8550 uses vpu30_p4) - vpu_ops: iris_vpu33_ops - clk_rst_tbl: sm8650_clk_reset_table - controller_rst_tbl: sm8650_controller_reset_table - inst_caps: platform_inst_cap_qcs8300 (4K capable, 2 VPP pipes) Link: https://lore.kernel.org/linux-arm-msm/20260921-add_iris_for_eliza-v2-2-5fe7be8c0230@oss.qualcomm.com/ Reviewed-by: Vikash Garodia Signed-off-by: Wangao Wang --- .../platform/qcom/iris/iris_platform_common.h | 1 + .../platform/qcom/iris/iris_platform_vpu3x.c | 44 +++++++++++++++++++ drivers/media/platform/qcom/iris/iris_probe.c | 4 ++ 3 files changed, 49 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index cdd62194fe6ee..a145ef59e771a 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -66,6 +66,7 @@ extern const struct iris_firmware_data iris_hfi_gen2_ar50lt_data; extern const struct platform_inst_slice_caps iris_vpu2_vpu3x_slice_caps; extern const struct platform_inst_slice_caps iris_ar50lt_slice_caps; +extern const struct iris_platform_data eliza_data; extern const struct iris_platform_data glymur_data; extern const struct iris_platform_data hawi_data; extern const struct iris_platform_data kaanapali_data; diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index 6ed4de2d15cec..20d3b339339d0 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -45,6 +45,12 @@ static const struct iris_firmware_desc iris_vpu33_p4_gen2_desc = { .fwname = "qcom/vpu/vpu33_p4.mbn", }; +static const struct iris_firmware_desc iris_vpu33_p2_s7_gen2_desc = { + .firmware_data = &iris_hfi_gen2_data, + .get_vpu_buffer_size = iris_vpu33_buf_size, + .fwname = "qcom/vpu/vpu33_p2_s7.mbn", +}; + static const struct iris_firmware_desc iris_vpu35_p4_gen2_desc = { .firmware_data = &iris_hfi_gen2_data, .get_vpu_buffer_size = iris_vpu33_buf_size, @@ -120,6 +126,44 @@ const struct iris_platform_data glymur_data = { .max_core_mbps = ((8192 * 4320) / 256) * 60, }; +/* + * Shares most of SM8550 data except: + * - firmware_desc_gen2 to iris_vpu33_p2_s7_gen2_desc + * - vpu_ops to iris_vpu33_ops + * - clk_rst_tbl to sm8650_clk_reset_table + * - controller_rst_tbl to sm8650_controller_reset_table + * - inst_caps to platform_inst_cap_qcs8300 (4K capable, 2 VPP pipes) + */ +const struct iris_platform_data eliza_data = { + .firmware_desc_gen2 = &iris_vpu33_p2_s7_gen2_desc, + .vpu_ops = &iris_vpu33_ops, + .icc_tbl = iris_icc_info_vpu3x, + .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), + .clk_rst_tbl = sm8650_clk_reset_table, + .clk_rst_tbl_size = ARRAY_SIZE(sm8650_clk_reset_table), + .controller_rst_tbl = sm8650_controller_reset_table, + .controller_rst_tbl_size = ARRAY_SIZE(sm8650_controller_reset_table), + .bw_tbl_dec = iris_bw_table_dec_vpu3x, + .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_vpu3x), + .ctrl_data = &sm8550_ctrl_data, + .vcodec_data = sm8550_vcodec_data, + .opp_pd_tbl = iris_opp_pd_table_vpu3x, + .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_vpu3x), + .opp_clk_tbl = iris_opp_clk_table_vpu3x, + /* Upper bound of DMA address range */ + .dma_mask = 0xe0000000 - 1, + .inst_iris_fmts = iris_fmts_vpu3x_dec, + .inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu3x_dec), + .inst_caps = &platform_inst_cap_qcs8300, + .slice_caps = &iris_vpu2_vpu3x_slice_caps, + .tz_cp_config_data = tz_cp_config_vpu3, + .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3), + .num_vpp_pipe = 2, + .max_session_count = 16, + .max_core_mbpf = NUM_MBS_4K * 2, + .max_core_mbps = NUM_MBS_4K * 60, +}; + /* * Shares most of SM8550 data except: * - inst_caps to platform_inst_cap_qcs8300 diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index d9be442c7fc7c..25b1eb571b596 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -633,6 +633,10 @@ static const struct dev_pm_ops iris_pm_ops = { }; static const struct of_device_id iris_dt_match[] = { + { + .compatible = "qcom,eliza-iris", + .data = &eliza_data, + }, { .compatible = "qcom,glymur-iris", .data = &glymur_data, From 289de5250fcfe46ab1b6796fe885084b1ea986cc Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Fri, 23 Oct 2026 00:36:08 +0530 Subject: [PATCH 0614/1133] FROMLIST: media: iris: add cyclic intra refresh on AR50LT encoder The Gen2 AR50LT encoder capability table advertises only the RANDOM intra refresh type, so V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE exposes a single menu entry and userspace cannot select CYCLIC. Advertise CYCLIC alongside RANDOM in the AR50LT encoder capabilities so that userspace can choose between the two intra refresh types. RANDOM remains the default, so existing behaviour is unchanged. Link: https://lore.kernel.org/all/20261023-iris-ar50lt-ir-cyclic-v1-1-a81d7060585d@oss.qualcomm.com/ Signed-off-by: Gourav Kumar --- drivers/media/platform/qcom/iris/iris_hfi_gen2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c index 79bbd06ef8d2b..794c36d222d3a 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c @@ -2600,8 +2600,9 @@ static const struct platform_inst_fw_cap inst_fw_cap_gen2_ar50lt_enc[] = { { .cap_id = IR_TYPE, .min = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM, - .max = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM, - .step_or_mask = BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM), + .max = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC, + .step_or_mask = BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM) | + BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC), .value = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM, .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU, }, From 2d5282d866124e7cc86e03612acd67ec6a1fc30f Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Tue, 27 Oct 2026 17:32:20 +0530 Subject: [PATCH 0615/1133] FROMLIST: media: qcom: Pass proper PAS ID to set_remote_state API As per testing the SCM backend just ignores it while OP-TEE makes use of it to for proper book keeping purpose. Link: https://lore.kernel.org/all/20261027-pas-id-media-v10-1-8a5312d3050e@oss.qualcomm.com/ Reviewed-by: Mukesh Ojha Tested-by: Mukesh Ojha # Lemans Reviewed-by: Vikash Garodia Reviewed-by: Konrad Dybcio Signed-off-by: Sumit Garg Reviewed-by: Gourav Kumar --- drivers/media/platform/qcom/iris/iris_firmware.c | 2 +- drivers/media/platform/qcom/venus/firmware.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c index 21f57d37da187..ed2bd0e837970 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.c +++ b/drivers/media/platform/qcom/iris/iris_firmware.c @@ -262,5 +262,5 @@ int iris_fw_unload(struct iris_core *core) int iris_set_hw_state(struct iris_core *core, bool resume) { - return qcom_pas_set_remote_state(resume, 0); + return qcom_pas_set_remote_state(resume, IRIS_PAS_ID); } diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c index 3a38ff985822f..3c0727ea137d2 100644 --- a/drivers/media/platform/qcom/venus/firmware.c +++ b/drivers/media/platform/qcom/venus/firmware.c @@ -59,7 +59,7 @@ int venus_set_hw_state(struct venus_core *core, bool resume) int ret; if (core->use_tz) { - ret = qcom_pas_set_remote_state(resume, 0); + ret = qcom_pas_set_remote_state(resume, VENUS_PAS_ID); if (resume && ret == -EINVAL) ret = 0; return ret; From b2663e274fbb82d0bd43429d79af3aafa0e17c02 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Thu, 29 Oct 2026 10:34:53 +0800 Subject: [PATCH 0616/1133] FROMLIST: media: iris: fix ltr count rc_type validity check in gen2 The condition was inverted: CBR_VFR, CBR_CFR and RC_OFF are the valid rc_types for LTR, so reject anything that does NOT match these types. Link: https://lore.kernel.org/linux-arm-msm/20261029-gen2_ltr_fix-v1-1-6d5518d59b9c@oss.qualcomm.com/ Fixes: 6870381285b8 ("media: qcom: iris: Add Long-Term Reference support for encoder") Signed-off-by: Wangao Wang --- drivers/media/platform/qcom/iris/iris_ctrls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c index 4f2633bbb49f8..2fd5cec16faeb 100644 --- a/drivers/media/platform/qcom/iris/iris_ctrls.c +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c @@ -1279,9 +1279,9 @@ int iris_set_ltr_count_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_ty if (!ltr_count) return -EINVAL; - if (inst->hfi_rc_type == HFI_RC_CBR_VFR || - inst->hfi_rc_type == HFI_RC_CBR_CFR || - inst->hfi_rc_type == HFI_RC_OFF) { + if (inst->hfi_rc_type != HFI_RC_CBR_VFR && + inst->hfi_rc_type != HFI_RC_CBR_CFR && + inst->hfi_rc_type != HFI_RC_OFF) { inst->fw_caps[LTR_COUNT].value = 0; return -EINVAL; } From 3edabe9bf3b6effa7d42b16c33430346901cae7a Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Thu, 17 Sep 2026 10:30:21 +0530 Subject: [PATCH 0617/1133] FROMLIST: media: iris: Enable Secure PAS support with IOMMU managed by Linux On platforms where a hypervisor is present, all Secure Monitor Calls (SMC) are intercepted. For qcom_scm_pas_auth_and_reset(), the hypervisor registers a Shared Memory (SHM) bridge over the Peripheral Image Loader (PIL) memory region so that TrustZone (TZ) can access it, forwards the authentication SMC to TZ, and upon return maps the PIL region and triggers the co-processor bring-up sequence: HLOS -> Hypervisor(SHM setup) -> TZ(auth) -> Hypervisor(map+reset) -> IRIS On platforms without a hypervisor, Linux drives these steps directly. The SHM bridge infrastructure required for this is already upstream [1]. To isolate firmware memory in its own Input-Output Memory Management Unit (IOMMU) context, a dedicated stream ID (SID) is required, tied to the firmware function ID. This SID is specified via the iommu-map property in the device tree using the firmware function ID as the lookup key. A firmware device is created and mapped to this SID. The presence of a SID mapped to the firmware device via iommu-map is used to detect whether a hypervisor is absent: when the firmware device has a SID mapped, Linux manages the IOMMU directly; when no SID is mapped, a hypervisor is assumed to be present and these steps are skipped. Extend the Iris driver to support Secure Peripheral Authentication Service (PAS) on platforms where Linux manages the IOMMU, by creating the firmware context device and performing the necessary IOMMU mapping when the firmware device SID is present. [1] https://lore.kernel.org/lkml/20260105-kvmrprocv10-v10-0-022e96815380 @oss.qualcomm.com/ Link: https://lore.kernel.org/all/20260917-glymur-v11-2-e0c8bc914742@oss.qualcomm.com/ Reviewed-by: Vishnu Reddy Co-developed-by: Vikash Garodia Signed-off-by: Vikash Garodia Signed-off-by: Mukesh Ojha Reviewed-by: Dmitry Baryshkov Signed-off-by: Vishnu Reddy --- drivers/media/platform/qcom/iris/iris_core.h | 4 + .../media/platform/qcom/iris/iris_firmware.c | 79 +++++++++++++++---- drivers/media/platform/qcom/iris/iris_probe.c | 12 +++ 3 files changed, 78 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index cad20caf7a0cc..1c724ea2be0d3 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -55,6 +55,8 @@ struct dentry; * @dev: reference to device structure * @np_dev: reference to non-pixel device structure * @p_dev: reference to pixel device structure + * @fw_dev: reference to firmware device structure + * @pas_ctx: PAS context for authenticated firmware load and shutdown * @reg_base: IO memory base address * @irq: iris irq * @v4l2_dev: a holder for v4l2 device structure @@ -109,6 +111,8 @@ struct iris_core { struct device *dev; struct device *np_dev; struct device *p_dev; + struct device *fw_dev; + struct qcom_pas_context *pas_ctx; void __iomem *reg_base; int irq; struct v4l2_device v4l2_dev; diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c index ed2bd0e837970..ba65bd2db8b76 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.c +++ b/drivers/media/platform/qcom/iris/iris_firmware.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include "iris_firmware.h" #define IRIS_PAS_ID 9 +#define IRIS_FIRMWARE_START_ADDR 0 /* Detect Gen2 firmware by scanning the blob for: * QC_IMAGE_VERSION_STRING= @@ -173,24 +175,32 @@ static void iris_detect_firmware(struct iris_core *core, const char *fw_name, static int iris_load_fw_to_memory(struct iris_core *core) { + struct device *fw_dev = core->fw_dev ? core->fw_dev : core->dev; const struct iris_firmware_desc *desc = NULL; const struct firmware *firmware = NULL; - struct device *dev = core->dev; + struct qcom_pas_context *ctx; + struct iommu_domain *domain; struct resource res; phys_addr_t mem_phys; const char *fw_name; size_t res_size; ssize_t fw_size; - void *mem_virt; int ret; - ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); + ret = of_reserved_mem_region_to_resource(core->dev->of_node, 0, &res); if (ret) return ret; mem_phys = res.start; res_size = resource_size(&res); + if (!core->pas_ctx) { + ctx = devm_qcom_pas_context_alloc(core->dev, IRIS_PAS_ID, mem_phys, res_size); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + core->pas_ctx = ctx; + } + firmware = iris_load_firmware(core, &fw_name, &desc); if (IS_ERR(firmware)) return PTR_ERR(firmware); @@ -201,27 +211,51 @@ static int iris_load_fw_to_memory(struct iris_core *core) goto err_release_fw; } - mem_virt = memremap(mem_phys, res_size, MEMREMAP_WC); - if (!mem_virt) { - ret = -ENOMEM; + core->pas_ctx->use_tzmem = !!core->fw_dev; + ret = qcom_mdt_pas_load(core->pas_ctx, firmware, fw_name, NULL); + if (ret) goto err_release_fw; - } - memset(mem_virt, 0, res_size); + if (core->pas_ctx->use_tzmem) { + domain = iommu_get_domain_for_dev(fw_dev); + if (!domain) { + ret = -ENODEV; + goto err_release_fw; + } + + ret = iommu_map(domain, IRIS_FIRMWARE_START_ADDR, mem_phys, res_size, + IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + } - ret = qcom_mdt_load(dev, firmware, fw_name, - IRIS_PAS_ID, mem_virt, mem_phys, res_size, NULL); + if (!ret) { + void *mem_virt = memremap(mem_phys, res_size, MEMREMAP_WC); - if (!ret) + if (!mem_virt) { + ret = -ENOMEM; + goto err_release_fw; + } iris_detect_firmware(core, fw_name, mem_virt, res_size, desc); + memunmap(mem_virt); + } - memunmap(mem_virt); err_release_fw: release_firmware(firmware); return ret; } +static void iris_fw_iommu_unmap(struct iris_core *core) +{ + struct iommu_domain *domain; + + if (!core->fw_dev) + return; + + domain = iommu_get_domain_for_dev(core->fw_dev); + if (domain) + iommu_unmap(domain, IRIS_FIRMWARE_START_ADDR, core->pas_ctx->mem_size); +} + int iris_fw_load(struct iris_core *core) { const struct tz_cp_config *cp_config; @@ -233,10 +267,10 @@ int iris_fw_load(struct iris_core *core) return ret; } - ret = qcom_pas_auth_and_reset(IRIS_PAS_ID); + ret = qcom_pas_prepare_and_auth_reset(core->pas_ctx); if (ret) { dev_err(core->dev, "auth and reset failed: %d\n", ret); - return ret; + goto err_unmap; } for (i = 0; i < core->iris_platform_data->tz_cp_config_data_size; i++) { @@ -247,17 +281,28 @@ int iris_fw_load(struct iris_core *core) cp_config->cp_nonpixel_size); if (ret) { dev_err(core->dev, "qcom_scm_mem_protect_video_var failed: %d\n", ret); - qcom_pas_shutdown(IRIS_PAS_ID); - return ret; + goto err_pas_shutdown; } } return 0; + +err_pas_shutdown: + qcom_pas_shutdown(IRIS_PAS_ID); +err_unmap: + iris_fw_iommu_unmap(core); + + return ret; } int iris_fw_unload(struct iris_core *core) { - return qcom_pas_shutdown(IRIS_PAS_ID); + int ret; + + ret = qcom_pas_shutdown(IRIS_PAS_ID); + iris_fw_iommu_unmap(core); + + return ret; } int iris_set_hw_state(struct iris_core *core, bool resume) diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 25b1eb571b596..4b5b5cdded199 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -384,8 +384,18 @@ static int iris_init_cb_devs(struct iris_core *core) core->p_dev = dev; + dev = iris_create_cb_dev(core, "video-firmware"); + if (IS_ERR(dev)) + goto unreg_p_dev; + + core->fw_dev = dev; + return 0; +unreg_p_dev: + if (core->p_dev) + platform_device_unregister(to_platform_device(core->p_dev)); + core->p_dev = NULL; unreg_np_dev: if (core->np_dev) platform_device_unregister(to_platform_device(core->np_dev)); @@ -396,6 +406,8 @@ static int iris_init_cb_devs(struct iris_core *core) static void iris_deinit_cb_devs(struct iris_core *core) { + if (core->fw_dev) + platform_device_unregister(to_platform_device(core->fw_dev)); if (core->p_dev) platform_device_unregister(to_platform_device(core->p_dev)); if (core->np_dev) From 345812eb7d723e78ba264fa843889e268e0902c2 Mon Sep 17 00:00:00 2001 From: Renjiang Han Date: Thu, 30 Apr 2026 15:56:48 +0530 Subject: [PATCH 0618/1133] PENDING: media: qcom: venus: support PAS boot and flexible IOMMU handling On platforms where PAS is available, firmware authentication and reset are performed via the secure world, while IOMMU configuration may be handled either by Linux or outside of it. Extend the Venus firmware flow to support both PAS and non-PAS setups. When PAS is available, load the firmware using a PAS context and trigger the prepare/auth/reset sequence. If the firmware device is IOMMU-mapped, use its IOMMU domain to map the reserved firmware memory before reset; otherwise, retain the existing secure-world-managed behavior. When PAS is not available, fall back to the existing non-PAS firmware loading path where Linux performs firmware loading and IOMMU mapping. The firmware stream ID is described via the iommu-map function identifier in the device tree. Signed-off-by: Renjiang Han --- drivers/media/platform/qcom/venus/core.h | 2 + drivers/media/platform/qcom/venus/firmware.c | 294 ++++++++++++++----- 2 files changed, 217 insertions(+), 79 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 93fa77f05834c..9b2e0cbcbc5b7 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -228,6 +228,8 @@ struct venus_core { size_t mapped_mem_size; phys_addr_t mem_phys; size_t mem_size; + struct qcom_pas_context *ctx; + bool iommu_domain_owned; } fw; struct mutex lock; struct list_head instances; diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c index 3c0727ea137d2..0027bae5f2111 100644 --- a/drivers/media/platform/qcom/venus/firmware.c +++ b/drivers/media/platform/qcom/venus/firmware.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "core.h" #include "firmware.h" @@ -79,87 +80,125 @@ int venus_set_hw_state(struct venus_core *core, bool resume) return 0; } -static int venus_load_fw(struct venus_core *core, const char *fwname, - phys_addr_t *mem_phys, size_t *mem_size) +static int venus_load_fw_prepare(struct venus_core *core, const char *fwname, + phys_addr_t *mem_phys, size_t *res_size, + const struct firmware **mdt) { - const struct firmware *mdt; struct resource res; - struct device *dev; ssize_t fw_size; - void *mem_va; int ret; - *mem_phys = 0; - *mem_size = 0; - - dev = core->dev; - ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); + ret = of_reserved_mem_region_to_resource(core->dev->of_node, 0, &res); if (ret) { - dev_err(dev, "failed to lookup reserved memory-region\n"); + dev_err(core->dev, "failed to lookup reserved memory-region\n"); return -EINVAL; } - ret = request_firmware(&mdt, fwname, dev); - if (ret < 0) + *mem_phys = res.start; + *res_size = resource_size(&res); + + ret = request_firmware(mdt, fwname, core->dev); + if (ret < 0) { + dev_err(core->dev, "%s: request_firmware: %d\n", __func__, ret); return ret; + } - fw_size = qcom_mdt_get_size(mdt); + fw_size = qcom_mdt_get_size(*mdt); if (fw_size < 0) { ret = fw_size; - goto err_release_fw; + goto err_release; } - *mem_phys = res.start; - *mem_size = resource_size(&res); - - if (*mem_size < fw_size || fw_size > VENUS_FW_MEM_SIZE) { + if (*res_size < fw_size || fw_size > VENUS_FW_MEM_SIZE) { ret = -EINVAL; - goto err_release_fw; - } - - mem_va = memremap(*mem_phys, *mem_size, MEMREMAP_WC); - if (!mem_va) { - dev_err(dev, "unable to map memory region %pa size %#zx\n", mem_phys, *mem_size); - ret = -ENOMEM; - goto err_release_fw; + goto err_release; } - if (core->use_tz) - ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, - mem_va, *mem_phys, *mem_size, NULL); - else - ret = qcom_mdt_load_no_init(dev, mdt, fwname, mem_va, - *mem_phys, *mem_size, NULL); + return 0; - memunmap(mem_va); -err_release_fw: - release_firmware(mdt); +err_release: + release_firmware(*mdt); return ret; } -static int venus_boot_no_tz(struct venus_core *core, phys_addr_t mem_phys, - size_t mem_size) +static int venus_load_fw(struct venus_core *core, + const struct firmware *mdt, const char *fwname, + phys_addr_t mem_phys, size_t res_size) { - struct iommu_domain *iommu; + struct qcom_pas_context *ctx; struct device *dev; int ret; - dev = core->fw.dev; - if (!dev) - return -EPROBE_DEFER; + dev = core->fw.dev ? core->fw.dev : core->dev; + ctx = devm_qcom_pas_context_alloc(dev, VENUS_PAS_ID, mem_phys, res_size); + if (!ctx) { + dev_err(core->dev, "%s: ctx is null\n", __func__); + return -ENOMEM; + } - iommu = core->fw.iommu_domain; - core->fw.mapped_mem_size = mem_size; + ctx->use_tzmem = !!core->fw.dev; - ret = iommu_map(iommu, VENUS_FW_START_ADDR, mem_phys, mem_size, - IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + ret = qcom_mdt_pas_load(ctx, mdt, fwname, NULL); + qcom_pas_metadata_release(ctx); if (ret) { - dev_err(dev, "could not map video firmware region\n"); + dev_err(core->dev, "%s: qcom_mdt_pas_load: %d\n", __func__, ret); return ret; } - venus_reset_cpu(core); + if (core->fw.iommu_domain) { + ret = iommu_map(core->fw.iommu_domain, 0, mem_phys, res_size, + IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + if (ret) { + dev_err(core->dev, "%s: iommu_map: %d\n", __func__, ret); + return ret; + } + } + + core->fw.mapped_mem_size = res_size; + + ret = qcom_pas_prepare_and_auth_reset(ctx); + if (ret) { + dev_err(core->dev, "%s: qcom_pas_prepare_and_auth_reset: %d\n", __func__, ret); + if (core->fw.iommu_domain) + iommu_unmap(core->fw.iommu_domain, 0, res_size); + core->fw.mapped_mem_size = 0; + return ret; + } + core->fw.ctx = ctx; + return 0; +} + +static int venus_load_fw_no_tz(struct venus_core *core, + const struct firmware *mdt, const char *fwname, + phys_addr_t mem_phys, size_t res_size) +{ + void *mem_va; + int ret; + + mem_va = memremap(mem_phys, res_size, MEMREMAP_WC); + if (!mem_va) { + dev_err(core->dev, + "unable to map memory region %pa size %#zx\n", &mem_phys, res_size); + return -ENOMEM; + } + + ret = qcom_mdt_load_no_init(core->fw.dev, mdt, fwname, mem_va, mem_phys, res_size, NULL); + memunmap(mem_va); + if (ret) { + dev_err(core->dev, "%s: qcom_mdt_load_no_init: %d\n", __func__, ret); + return ret; + } + + ret = iommu_map(core->fw.iommu_domain, VENUS_FW_START_ADDR, mem_phys, + res_size, IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL); + if (ret) { + dev_err(core->dev, "could not map video firmware region\n"); + return ret; + } + + core->fw.mapped_mem_size = res_size; + venus_reset_cpu(core); return 0; } @@ -213,36 +252,35 @@ int venus_boot(struct venus_core *core) { struct device *dev = core->dev; const struct venus_resources *res = core->res; + const struct firmware *mdt; const char *fwpath = NULL; phys_addr_t mem_phys; - size_t mem_size; + size_t res_size; int ret; if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) || - (core->use_tz && !qcom_pas_is_available())) - return -EPROBE_DEFER; + (!core->use_tz && !qcom_pas_is_available())) + return driver_deferred_probe_check_state(core->dev); - ret = of_property_read_string_index(dev->of_node, "firmware-name", 0, - &fwpath); + ret = of_property_read_string_index(dev->of_node, "firmware-name", 0, &fwpath); if (ret) fwpath = core->res->fwname; - ret = venus_load_fw(core, fwpath, &mem_phys, &mem_size); - if (ret) { - dev_err(dev, "fail to load video firmware\n"); - return -EINVAL; - } - - core->fw.mem_size = mem_size; - core->fw.mem_phys = mem_phys; + ret = venus_load_fw_prepare(core, fwpath, &mem_phys, &res_size, &mdt); + if (ret) + return ret; if (core->use_tz) - ret = qcom_pas_auth_and_reset(VENUS_PAS_ID); + ret = venus_load_fw(core, mdt, fwpath, mem_phys, res_size); else - ret = venus_boot_no_tz(core, mem_phys, mem_size); + ret = venus_load_fw_no_tz(core, mdt, fwpath, mem_phys, res_size); - if (ret) + release_firmware(mdt); + + if (ret) { + dev_err(dev, "fail to load video firmware\n"); return ret; + } if (core->use_tz && res->cp_size) { /* @@ -260,24 +298,29 @@ int venus_boot(struct venus_core *core) res->cp_nonpixel_start, res->cp_nonpixel_size); if (ret) { - qcom_pas_shutdown(VENUS_PAS_ID); - dev_err(dev, "set virtual address ranges fail (%d)\n", - ret); + venus_shutdown(core); + dev_err(dev, "set virtual address ranges fail (%d)\n", ret); return ret; } } - return 0; + return ret; } int venus_shutdown(struct venus_core *core) { int ret; - if (core->use_tz) + if (core->use_tz) { ret = qcom_pas_shutdown(VENUS_PAS_ID); - else + if (core->fw.iommu_domain && core->fw.mapped_mem_size) { + iommu_unmap(core->fw.iommu_domain, 0, core->fw.mapped_mem_size); + core->fw.mapped_mem_size = 0; + } + core->fw.ctx = NULL; + } else { ret = venus_shutdown_no_tz(core); + } return ret; } @@ -302,6 +345,94 @@ int venus_firmware_check(struct venus_core *core) return -EINVAL; } +static struct device *venus_firmware_alloc_platform_dev(struct venus_core *core, + const char *name, const u32 *f_id) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc(name, 0); + if (!pdev) { + dev_err(core->dev, "%s: platform_device_alloc err\n", __func__); + return ERR_PTR(-ENOMEM); + } + + pdev->dev.parent = core->dev; + + ret = platform_device_add(pdev); + if (ret) { + dev_err(core->dev, "%s: platform_device_add err(%d)\n", __func__, ret); + platform_device_put(pdev); + return ERR_PTR(ret); + } + + ret = of_dma_configure_id(&pdev->dev, core->dev->of_node, true, f_id); + if (ret) { + dev_err(core->dev, "%s: of_dma_configure_id err(%d)\n", __func__, ret); + platform_device_unregister(to_platform_device(&pdev->dev)); + return ERR_PTR(ret); + } + + return &pdev->dev; +} + +static int venus_firmware_setup_iommu_dev(struct venus_core *core) +{ + const u32 f_id = VENUS_FIRMWARE; + struct device *dev; + int ret = 0; + + dev = venus_firmware_alloc_platform_dev(core, "video_firmware", &f_id); + if (IS_ERR(dev)) { + dev_err(core->dev, "%s: err\n", __func__); + return PTR_ERR(dev); + } + + if (!device_iommu_mapped(dev)) { + device_unregister(dev); + return -ENODEV; + } + + ret = dma_set_mask_and_coherent(dev, core->res->dma_mask); + if (ret) { + device_unregister(dev); + return ret; + } + + core->fw.dev = dev; + core->fw.iommu_domain = iommu_get_domain_for_dev(core->fw.dev); + core->fw.iommu_domain_owned = false; + + return 0; +} + +static int venus_firmware_init_auto_detect(struct venus_core *core) +{ + int ret; + + core->use_tz = false; + if (qcom_pas_is_available()) { + if (qcom_pas_supported(VENUS_PAS_ID)) + core->use_tz = true; + } else { + ret = driver_deferred_probe_check_state(core->dev); + if (ret == -EPROBE_DEFER) + return ret; + } + + /* + * 1. use_tz is false: No authentication is performed. + * 2. use_tz is true: TZ perform authentication. + * a. device_iommu_mapped true: Linux config smmu + * b. device_iommu_mapped false: TZ config smmu + */ + ret = venus_firmware_setup_iommu_dev(core); + if (ret == -ENODEV && core->use_tz) + ret = 0; + + return ret; +} + int venus_firmware_init(struct venus_core *core) { struct platform_device_info info; @@ -312,8 +443,8 @@ int venus_firmware_init(struct venus_core *core) np = of_get_child_by_name(core->dev->of_node, "video-firmware"); if (!np) { - core->use_tz = true; - return 0; + ret = venus_firmware_init_auto_detect(core); + return ret; } memset(&info, 0, sizeof(info)); @@ -352,6 +483,7 @@ int venus_firmware_init(struct venus_core *core) } core->fw.iommu_domain = iommu_dom; + core->fw.iommu_domain_owned = true; of_node_put(np); @@ -360,6 +492,7 @@ int venus_firmware_init(struct venus_core *core) err_iommu_free: iommu_domain_free(iommu_dom); err_unregister: + core->fw.dev = NULL; platform_device_unregister(pdev); of_node_put(np); return ret; @@ -372,14 +505,17 @@ void venus_firmware_deinit(struct venus_core *core) if (!core->fw.dev) return; - iommu = core->fw.iommu_domain; - - iommu_detach_device(iommu, core->fw.dev); + if (!core->use_tz && core->fw.iommu_domain_owned) { + iommu = core->fw.iommu_domain; - if (core->fw.iommu_domain) { - iommu_domain_free(iommu); - core->fw.iommu_domain = NULL; + if (iommu) { + iommu_detach_device(iommu, core->fw.dev); + iommu_domain_free(iommu); + } } - platform_device_unregister(to_platform_device(core->fw.dev)); + core->fw.dev = NULL; + core->fw.ctx = NULL; + core->fw.iommu_domain = NULL; + core->fw.iommu_domain_owned = false; } From a08d7a577280a797971194b9e1fdabc9ab2c47ef Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Fri, 24 Jul 2026 19:11:28 +0530 Subject: [PATCH 0619/1133] PENDING: dt-bindings: media: qcom,sc7280-venus: Add video firmware sub node A dedicated firmware device is required to map the firmware region to the device's IOMMU mapped stream ID, which is the firmware stream ID, in order to boot the Iris firmware when no hypervisor is present. Signed-off-by: Vishnu Reddy --- .../bindings/media/qcom,sc7280-venus.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml b/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml index cc31f3ba7e7e0..e6b2a5e8748c3 100644 --- a/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml @@ -85,6 +85,21 @@ properties: deprecated: true additionalProperties: false + video-firmware: + type: object + additionalProperties: false + + description: | + Firmware subnode is needed when the platform does not + have TrustZone. + + properties: + iommus: + maxItems: 1 + + required: + - iommus + required: - compatible - dma-coherent From 7d40324801a7978acdafa6ec58c5338b93e7093d Mon Sep 17 00:00:00 2001 From: Renjiang Han Date: Thu, 30 Apr 2026 15:38:03 +0530 Subject: [PATCH 0620/1133] PENDING: dt-bindings: media: qcom: venus: add iommu-map support Add optional iommu-map property to the Qualcomm Venus video codec binding to describe IOMMU stream IDs for additional functional blocks exposed by the hardware. Update the example to show how the firmware stream can be mapped to an SMMU stream ID using a function identifier. Signed-off-by: Renjiang Han --- .../devicetree/bindings/media/qcom,sc7180-venus.yaml | 5 +++++ include/dt-bindings/media/qcom,qcs615-venus.h | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 include/dt-bindings/media/qcom,qcs615-venus.h diff --git a/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml b/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml index bfd8b1ad47312..5de4445a486d7 100644 --- a/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml @@ -50,6 +50,9 @@ properties: iommus: maxItems: 1 + iommu-map: + maxItems: 1 + memory-region: maxItems: 1 @@ -101,6 +104,7 @@ unevaluatedProperties: false examples: - | #include + #include #include venus: video-codec@aa00000 { @@ -118,5 +122,6 @@ examples: clock-names = "core", "iface", "bus", "vcodec0_core", "vcodec0_bus"; iommus = <&apps_smmu 0x0c00 0x60>; + iommu-map = ; memory-region = <&venus_mem>; }; diff --git a/include/dt-bindings/media/qcom,qcs615-venus.h b/include/dt-bindings/media/qcom,qcs615-venus.h new file mode 100644 index 0000000000000..ca755f2f6aa40 --- /dev/null +++ b/include/dt-bindings/media/qcom,qcs615-venus.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_MEDIA_QCOM_QCS615_VENUS_H_ +#define _DT_BINDINGS_MEDIA_QCOM_QCS615_VENUS_H_ + +#define VENUS_FIRMWARE 0 + +#endif From 0b7fa61116a9a7c3bba8ee44e6ebd7ee8bfc43e2 Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Fri, 11 Sep 2026 18:08:56 +0530 Subject: [PATCH 0621/1133] FROMLIST: media: iris: Skip SCM call for non-SCM PAS backend qcom_scm_mem_protect_video_var() is only serviced by the SCM backend; with OP-TEE the TEE owns secure memory protection. Use qcom_pas_get_backend() to issue the SCM call only for the SCM backend. Link: https://lore.kernel.org/all/20260911-video-optee-pas-v1-v1-2-7bbddaaac5ba@kernel.org/ Assisted-by: Copilot:claude-opus-4.8 Signed-off-by: Jorge Ramirez-Ortiz Co-developed-by: Sumit Garg Signed-off-by: Sumit Garg --- drivers/media/platform/qcom/iris/iris_firmware.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c index ba65bd2db8b76..83fef6c835c14 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.c +++ b/drivers/media/platform/qcom/iris/iris_firmware.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "iris_core.h" #include "iris_firmware.h" @@ -259,6 +260,7 @@ static void iris_fw_iommu_unmap(struct iris_core *core) int iris_fw_load(struct iris_core *core) { const struct tz_cp_config *cp_config; + const char *pas_backend; int i, ret; ret = iris_load_fw_to_memory(core); @@ -273,6 +275,15 @@ int iris_fw_load(struct iris_core *core) goto err_unmap; } + /* + * qcom_scm_mem_protect_video_var() only applies to the SCM backend; + * other backends (e.g. OP-TEE) own secure memory protection and do + * not service this call. + */ + pas_backend = qcom_pas_get_backend(); + if (!pas_backend || strcmp(pas_backend, QCOM_PAS_BACKEND_SCM)) + return 0; + for (i = 0; i < core->iris_platform_data->tz_cp_config_data_size; i++) { cp_config = &core->iris_platform_data->tz_cp_config_data[i]; ret = qcom_scm_mem_protect_video_var(cp_config->cp_start, From 5b5678242acc4170e3aebd499b1af2857c3ebea3 Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Fri, 11 Sep 2026 18:08:57 +0530 Subject: [PATCH 0622/1133] FROMLIST: media: venus: Skip SCM call for non-SCM PAS backend qcom_scm_mem_protect_video_var() is only serviced by the SCM backend; with OP-TEE the TEE owns secure memory protection. Use qcom_pas_get_backend() to issue the SCM call only for the SCM backend. Link: https://lore.kernel.org/all/20260911-video-optee-pas-v1-v1-3-7bbddaaac5ba@kernel.org/ Assisted-by: Copilot:claude-opus-4.8 Signed-off-by: Sumit Garg --- drivers/media/platform/qcom/venus/firmware.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c index 0027bae5f2111..964d746dc0bb9 100644 --- a/drivers/media/platform/qcom/venus/firmware.c +++ b/drivers/media/platform/qcom/venus/firmware.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "core.h" #include "firmware.h" @@ -254,6 +255,7 @@ int venus_boot(struct venus_core *core) const struct venus_resources *res = core->res; const struct firmware *mdt; const char *fwpath = NULL; + const char *pas_backend; phys_addr_t mem_phys; size_t res_size; int ret; @@ -283,6 +285,14 @@ int venus_boot(struct venus_core *core) } if (core->use_tz && res->cp_size) { + /* + * qcom_scm_mem_protect_video_var() only applies to the SCM + * backend; other backends (e.g. OP-TEE) own secure memory + * protection and do not service this call. + */ + pas_backend = qcom_pas_get_backend(); + if (!pas_backend || strcmp(pas_backend, QCOM_PAS_BACKEND_SCM)) + return ret; /* * Clues for porting using downstream data: * cp_start = 0 From 234ed780bc5f627995a46e310b9d199232ede101 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Mon, 21 Sep 2026 17:29:21 +0530 Subject: [PATCH 0623/1133] PENDING: media: iris: Enable slice capabilities for glymur Assign the slice capability data to the Glymur platform to enable slice mode support in the iris driver. Signed-off-by: Vishnu Reddy --- drivers/media/platform/qcom/iris/iris_platform_vpu3x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index 20d3b339339d0..7ce6a394bda51 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -117,6 +117,7 @@ const struct iris_platform_data glymur_data = { .inst_iris_fmts = iris_fmts_vpu3x_dec, .inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu3x_dec), .inst_caps = &platform_inst_cap_sm8550, + .slice_caps = &iris_vpu2_vpu3x_slice_caps, .tz_cp_config_data = iris_glymur_tz_cp_config, .tz_cp_config_data_size = ARRAY_SIZE(iris_glymur_tz_cp_config), .num_vpp_pipe = 4, From 1e05914014b4c8c9dca3bd62c8c31b2878daacfb Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Tue, 3 Nov 2026 00:50:24 +0530 Subject: [PATCH 0624/1133] PENDING: media: iris: Skip IOVA reservation when core device has no IOMMU iris_probe() reserves the 0-600MB IOVA range on the core device, which assumes "iommus" sits on the video-codec node. With context bank subnodes ("non-pixel", "pixel") the "iommus" are on the subnodes, the core device has no IOMMU domain, and the range restriction comes from "iommu-ranges" instead. Before: dma_iova_try_alloc() fails on the core device, the reserve returns -ENOMEM and probe aborts silently with ENOMEM. After: reserve the range only if device_iommu_mapped() is true for the core device, so legacy platforms are unchanged and context bank platforms probe normally. Make iris_unreserve_iova_region() return early on a NULL iova_state, since the reserve may now be skipped. Signed-off-by: Gourav Kumar --- drivers/media/platform/qcom/iris/iris_probe.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 4b5b5cdded199..60f1d34c8c6f9 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -294,6 +294,9 @@ static void iris_unreserve_iova_region(struct device *dev, struct dma_iova_state { unsigned int i; + if (!iova_state) + return; + for (i = 0; dma_iova_size(&iova_state[i]); i++) dma_iova_free(dev, &iova_state[i]); } @@ -541,10 +544,18 @@ static int iris_probe(struct platform_device *pdev) if (ret) return ret; - ret = iris_reserve_iova_region(dev, &core->iova_state, IRIS_NP_RESERVE_IOVA_START, - IRIS_NP_RESERVE_IOVA_SIZE); - if (ret) - return ret; + /* + * With context bank subnodes the "iommus" sit on the subnodes and the + * non-pixel IOVA restriction comes from "iommu-ranges", so reserve the + * range here only when the core device itself is behind an IOMMU. + */ + if (device_iommu_mapped(dev)) { + ret = iris_reserve_iova_region(dev, &core->iova_state, + IRIS_NP_RESERVE_IOVA_START, + IRIS_NP_RESERVE_IOVA_SIZE); + if (ret) + return ret; + } ret = iris_init_cb_devs(core); if (ret) From b64ca4b9b33c4e0fb924f36f328f0074bbc07e64 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Tue, 3 Nov 2026 12:07:36 +0530 Subject: [PATCH 0625/1133] FROMLIST: media: qcom: camss: Fully unprepare OPE clocks on suspend OPE uses pm_clk to manage its clocks. pm_clk prepares clocks when they are added, but runtime suspend only disables normal clocks, leaving the CAMSS OPE clocks prepared while idle. Manage the OPE clocks directly with bulk clock helpers so runtime suspend disables and unprepares them. Link: https://lore.kernel.org/all/20261102-camss-isp-ope-v12-6-702254689feb@oss.qualcomm.com/ Assisted-by: LLM Co-developed-by: Hans de Goede Signed-off-by: Hans de Goede Co-developed-by: Nihal Kumar Gupta Signed-off-by: Nihal Kumar Gupta Signed-off-by: Loic Poulain --- drivers/media/platform/qcom/camss/ope/core.c | 44 ++++++++++++++------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/qcom/camss/ope/core.c b/drivers/media/platform/qcom/camss/ope/core.c index 122e6c8deb022..b266153aaca4f 100644 --- a/drivers/media/platform/qcom/camss/ope/core.c +++ b/drivers/media/platform/qcom/camss/ope/core.c @@ -595,6 +595,8 @@ struct ope_dev { struct icc_path *icc_data; struct icc_path *icc_config; + struct clk_bulk_data *clks; + int nclks; void __iomem *base; void __iomem *base_rd; @@ -3696,18 +3698,17 @@ static int ope_init_power(struct ope_dev *ope) if (ret && ret != -ENODEV) return dev_err_probe(dev, ret, "invalid OPP table\n"); - ret = devm_pm_runtime_enable(dev); - if (ret) - return ret; + ret = devm_clk_bulk_get_all(dev, &ope->clks); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to get clocks\n"); + else if (!ret) + return dev_err_probe(dev, -EINVAL, "not enough clocks in DT\n"); + ope->nclks = ret; - ret = devm_pm_clk_create(dev); + ret = devm_pm_runtime_enable(dev); if (ret) return ret; - ret = of_pm_clk_add_clks(dev); - if (ret < 0) - return ret; - return 0; } @@ -3752,6 +3753,7 @@ static int ope_probe(struct platform_device *pdev) spin_lock_init(&ope->ctx_lock); spin_lock_init(&ope->sched_lock); INIT_WORK(&ope->run_work, ope_run_work); + platform_set_drvdata(pdev, ope); ret = dma_set_mask(dev, DMA_BIT_MASK(32)); if (ret) { @@ -3792,10 +3794,10 @@ static int ope_probe(struct platform_device *pdev) /* ope ownership is transferred to ope_v4l2_register(), even on failure */ ret = ope_v4l2_register(ope); - if (ret) + if (ret) { + platform_set_drvdata(pdev, NULL); return dev_err_probe(dev, ret, "V4L2 registration failed\n"); - - platform_set_drvdata(pdev, ope); + } /* Everything @ope_irq() touches is in place, let interrupts in */ enable_irq(ope->irq); @@ -3803,6 +3805,7 @@ static int ope_probe(struct platform_device *pdev) return 0; err_free: + platform_set_drvdata(pdev, NULL); mutex_destroy(&ope->mutex); kfree(ope); return ret; @@ -3816,6 +3819,22 @@ static void ope_remove(struct platform_device *pdev) ope_unregister(ope); } +static int ope_runtime_suspend(struct device *dev) +{ + struct ope_dev *ope = dev_get_drvdata(dev); + + clk_bulk_disable_unprepare(ope->nclks, ope->clks); + + return 0; +} + +static int ope_runtime_resume(struct device *dev) +{ + struct ope_dev *ope = dev_get_drvdata(dev); + + return clk_bulk_prepare_enable(ope->nclks, ope->clks); +} + static const struct of_device_id ope_dt_ids[] = { { .compatible = "qcom,qcm2290-camss-ope" }, { }, @@ -3823,7 +3842,8 @@ static const struct of_device_id ope_dt_ids[] = { MODULE_DEVICE_TABLE(of, ope_dt_ids); static const struct dev_pm_ops ope_pm_ops = { - SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) + SET_RUNTIME_PM_OPS(ope_runtime_suspend, ope_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver ope_driver = { From d06d8edfb8299f2b93cffe28cef9ac90e5938de5 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Fri, 11 Sep 2026 14:38:13 +0530 Subject: [PATCH 0626/1133] soc: qcom: rpmh-rsc: Update CMD_MSGID_LEN to 4 bytes for read request Newer SoC like hawi with RSC version v4.5 support 4 byte message read request instead of default 8 byte on older SoCs. The write request continues to be 8 bytes. The CMD_MSGID_LEN field is [3:0] bits. Describe the length bits as a GENMASK() and use FIELD_PREP() when programming 4-byte or 8-byte message length. Tested-by: Mukesh Ojha #Hawi Signed-off-by: Maulik Shah --- drivers/soc/qcom/rpmh-rsc.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index c4542318eac47..c5ed9874bb67b 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -7,6 +7,7 @@ #define pr_fmt(fmt) "%s " fmt, KBUILD_MODNAME #include +#include #include #include #include @@ -86,7 +87,7 @@ enum { #define TCS_AMC_MODE_TRIGGER BIT(24) /* TCS CMD register bit mask */ -#define CMD_MSGID_LEN 8 +#define CMD_MSGID_LEN GENMASK(3, 0) #define CMD_MSGID_RESP_REQ BIT(8) #define CMD_MSGID_WRITE BIT(16) #define CMD_STATUS_ISSUED BIT(8) @@ -499,13 +500,20 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, const struct tcs_request *msg) { u32 msgid; - u32 cmd_msgid = CMD_MSGID_LEN; + u32 cmd_msgid; u32 cmd_enable = 0; struct tcs_cmd *cmd; int i, j; /* Convert all commands to RR when the request has wait_for_compl set */ - cmd_msgid |= msg->wait_for_compl ? CMD_MSGID_RESP_REQ : 0; + cmd_msgid = msg->wait_for_compl ? CMD_MSGID_RESP_REQ : 0; + + if (msg->is_read && (drv->ver.major > 4 || + (drv->ver.major == 4 && drv->ver.minor >= 5))) + cmd_msgid |= FIELD_PREP(CMD_MSGID_LEN, 4); + else + cmd_msgid |= FIELD_PREP(CMD_MSGID_LEN, 8); + if (!msg->is_read) cmd_msgid |= CMD_MSGID_WRITE; From 29aefb0b6332bf33d0321dc41a3c669f9d9a20c3 Mon Sep 17 00:00:00 2001 From: Yijie Yang Date: Tue, 22 Sep 2026 16:19:58 -0700 Subject: [PATCH 0627/1133] FROMLIST: dt-bindings: arm: qcom: Document Maili SoC and its reference board Document the Maili SoC binding and the board which use it. Signed-off-by: Jingyi Wang Signed-off-by: Yijie Yang Link: https://lore.kernel.org/r/20260922-maili-dts-v1-1-ac2b1b76bfd9@oss.qualcomm.com --- Documentation/devicetree/bindings/arm/qcom.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 121ca557ce1ef..360bf529d0d5b 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -201,6 +201,11 @@ properties: - const: lenovo,thinkpad-t14s-gen7 - const: qcom,mahua + - items: + - enum: + - qcom,maili-mtp + - const: qcom,maili + - description: Sierra Wireless MangOH Green with WP8548 Module items: - const: swir,mangoh-green-wp8548 From 5f96d4a653df3f0f6aee6057592a3f6d7f31be1c Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Wed, 23 Sep 2026 14:16:23 +0530 Subject: [PATCH 0628/1133] FROMLIST: arm64: dts: qcom: hawi: add LPASS audio subsystem nodes Add the Low Power Audio SubSystem (LPASS) device tree infrastructure for Hawi to describe the ADSP-based audio pipeline. Add the GPR (Generic Packet Router) node with q6apm and q6prm audio services, LPASS RX, TX and VA macro codecs, SoundWire controllers, VA CSR clock provider, and LPI TLMM pinctrl node required by the audio subsystem. Link: https://lore.kernel.org/lkml/20260923084627.748920-5-prasad.kumpatla@oss.qualcomm.com/ Signed-off-by: Prasad Kumpatla Signed-off-by: Mukesh Ojha --- arch/arm64/boot/dts/qcom/hawi.dtsi | 291 +++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi.dtsi b/arch/arm64/boot/dts/qcom/hawi.dtsi index 6b0a0ff0faa45..3074a6601066f 100644 --- a/arch/arm64/boot/dts/qcom/hawi.dtsi +++ b/arch/arm64/boot/dts/qcom/hawi.dtsi @@ -22,6 +22,8 @@ #include #include "hawi-ipcc.h" +#include +#include / { interrupt-parent = <&intc>; @@ -3838,6 +3840,295 @@ dma-coherent; }; }; + + 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"; + + q6apmbedai: bedais { + compatible = "qcom,q6apm-lpass-dais"; + #address-cells = <1>; + #size-cells = <0>; + #sound-dai-cells = <1>; + }; + + q6apmdai: dais { + compatible = "qcom,q6apm-dais"; + iommus = <&apps_smmu 0x0c01 0x80>, + <&apps_smmu 0x0c41 0x20>; + }; + }; + + 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>; + }; + }; + }; + }; + }; + + lpass_rxmacro: codec@72c0000 { + compatible = "qcom,hawi-lpass-rx-macro"; + reg = <0x0 0x072c0000 0x0 0x1000>; + clocks = <&q6prmcc LPASS_CLK_ID_RX_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_LPR_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&lpass_vamacro>; + clock-names = "mclk", "lpr", "dcodec", "fsgen"; + + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + swr1: soundwire@72d0000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x0 0x072d0000 0x0 0x10000>; + interrupts = ; + clocks = <&lpass_rxmacro>; + clock-names = "iface"; + label = "RX"; + + pinctrl-0 = <&rx_swr_active>; + pinctrl-names = "default"; + + qcom,din-ports = <1>; + qcom,dout-ports = <11>; + qcom,ports-sinterval = /bits/ 16 <0x03 0x3f 0x1f 0x07 0x00 0x18f 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0b 0x01 0x00 0x00 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0b 0x00 0x00 0x00 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-hstart = /bits/ 8 <0xff 0x03 0xff 0xff 0xff 0x08 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0x06 0xff 0xff 0xff 0x08 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04 0xff 0xff 0x0f 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0x00 0x01 0xff 0xff 0x00 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0x00 0x00 0xff 0xff 0xff 0xff 0xff 0xff>; + qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00 0x00 0x00 0xff 0xff 0xff 0xff 0xff 0xff>; + + #address-cells = <2>; + #size-cells = <0>; + #sound-dai-cells = <1>; + + status = "disabled"; + }; + + lpass_txmacro: codec@72e0000 { + compatible = "qcom,hawi-lpass-tx-macro"; + reg = <0x0 0x72e0000 0x0 0x1000>; + clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_LPR_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&lpass_vamacro>; + clock-names = "mclk", "lpr", "dcodec", "fsgen"; + + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + swr2: soundwire@7e90000 { + compatible = "qcom,soundwire-v3.1.0"; + reg = <0x0 0x7e90000 0x0 0x10000>; + interrupts = , + ; + interrupt-names = "core", "wakeup"; + clocks = <&lpass_txmacro>; + clock-names = "iface"; + label = "TX"; + + pinctrl-0 = <&tx_swr_active>; + pinctrl-names = "default"; + + qcom,din-ports = <4>; + qcom,dout-ports = <0>; + qcom,ports-sinterval-low = /bits/ 8 <0x01 0x01 0x03 0x03>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x00 0x01>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0xff 0x00 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0xff 0x0f 0xff>; + qcom,ports-word-length = /bits/ 8 <0xff 0x00 0x00 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0x00 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0x00 0xff>; + qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x01 0x00>; + + #address-cells = <2>; + #size-cells = <0>; + #sound-dai-cells = <1>; + + status = "disabled"; + }; + + lpass_vamacro: codec@7ec0000 { + compatible = "qcom,hawi-lpass-va-macro"; + reg = <0x0 0x07ec0000 0x0 0x2000>; + clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_LPR_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&lpass_va_csr>; + clock-names = "mclk", "lpr", "dcodec", "heartbeatpulse"; + + #clock-cells = <0>; + clock-output-names = "fsgen"; + #sound-dai-cells = <1>; + }; + + lpass_va_csr: va-csr@7ee0000 { + compatible = "qcom,hawi-lpass-va-csr"; + reg = <0x0 0x07ee0000 0x0 0xe000>; + clocks = <&q6prmcc LPASS_HW_LPR_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "lpr", "audio"; + #clock-cells = <0>; + }; + + lpass_tlmm: pinctrl@7f60000 { + compatible = "qcom,hawi-lpass-lpi-pinctrl"; + reg = <0x0 0x07f60000 0x0 0x20000>; + + clocks = <&q6prmcc LPASS_HW_LPR_VOTE + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "lpr", "audio"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&lpass_tlmm 0 0 23>; + + dmic01_default: dmic01-default-state { + clk-pins { + pins = "gpio6"; + function = "dmic1_clk"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio7"; + function = "dmic1_data"; + drive-strength = <8>; + input-enable; + }; + }; + + dmic23_default: dmic23-default-state { + clk-pins { + pins = "gpio8"; + function = "dmic2_clk"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio9"; + function = "dmic2_data"; + drive-strength = <8>; + input-enable; + }; + }; + + lpi_i2s1_active: lpi-i2s1-active-state { + clk-pins { + pins = "gpio10"; + function = "i2s1_clk"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + ws-pins { + pins = "gpio11"; + function = "i2s1_ws"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + data-pins { + pins = "gpio15", "gpio16"; + function = "i2s1_data"; + drive-strength = <8>; + bias-disable; + output-high; + }; + }; + + lpi_i2s1_sleep: lpi-i2s1-sleep-state { + clk-pins { + pins = "gpio10"; + function = "i2s1_clk"; + drive-strength = <2>; + bias-pull-down; + input-enable; + }; + + ws-pins { + pins = "gpio11"; + function = "i2s1_ws"; + drive-strength = <2>; + bias-pull-down; + input-enable; + }; + + data-pins { + pins = "gpio15", "gpio16"; + function = "i2s1_data"; + drive-strength = <2>; + bias-pull-down; + input-enable; + }; + }; + + rx_swr_active: rx-swr-active-state { + clk-pins { + pins = "gpio3"; + function = "swr_rx_clk"; + drive-strength = <2>; + slew-rate = <1>; + bias-disable; + }; + + data-pins { + pins = "gpio4", "gpio5"; + function = "swr_rx_data"; + drive-strength = <2>; + slew-rate = <1>; + bias-bus-hold; + }; + }; + + tx_swr_active: tx-swr-active-state { + clk-pins { + pins = "gpio0"; + function = "swr_tx_clk"; + drive-strength = <2>; + slew-rate = <1>; + bias-disable; + }; + + data-pins { + pins = "gpio1", "gpio2", "gpio14"; + function = "swr_tx_data"; + drive-strength = <2>; + slew-rate = <1>; + bias-bus-hold; + }; }; }; From 74cf27f93cd2a94aa2f555771c8d27c77648221f Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Wed, 23 Sep 2026 14:16:24 +0530 Subject: [PATCH 0629/1133] FROMLIST: arm64: dts: qcom: hawi-mtp: enable audio playback and capture Wire up the audio use cases on the Hawi MTP board on top of the LPASS nodes added to the SoC dtsi. Add the sound card (qcom,hawi-sndcard) with the TDM playback, WCD playback/capture and VA DMIC capture DAI links and the associated audio routing. Describe the WCD9395 codec, enable the RX and TX SoundWire controllers with their WCD RX/TX satellite ports, and add the WSA8855 speaker amplifier on i2c3. Configure the VA macro DMIC supply and the required TLMM pin states (WCD reset, WSA IRQ, WSA shutdown). Link: https://lore.kernel.org/lkml/20260923084627.748920-6-prasad.kumpatla@oss.qualcomm.com/ Signed-off-by: Prasad Kumpatla Signed-off-by: Mukesh Ojha --- arch/arm64/boot/dts/qcom/hawi-mtp.dts | 206 ++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi-mtp.dts b/arch/arm64/boot/dts/qcom/hawi-mtp.dts index c38e5fab7a2cb..23b091d5dc37f 100644 --- a/arch/arm64/boot/dts/qcom/hawi-mtp.dts +++ b/arch/arm64/boot/dts/qcom/hawi-mtp.dts @@ -5,10 +5,12 @@ /dts-v1/; #include +#include #include #include #include #include +#include #include "hawi.dtsi" @@ -126,6 +128,122 @@ }; }; + hawi_sound: sound { + compatible = "qcom,hawi-sndcard", "qcom,sm8450-sndcard"; + model = "HAWI-MTP"; + + audio-routing = "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2", + "VA DMIC0", "MIC BIAS1", + "VA DMIC1", "MIC BIAS1", + "VA DMIC2", "MIC BIAS3", + "VA DMIC3", "MIC BIAS3", + "TX SWR_INPUT", "ADC2_OUTPUT"; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&lpi_i2s1_active>; + pinctrl-1 = <&lpi_i2s1_sleep>; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + + codec { + sound-dai = <&lpass_vamacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-capture-dai-link { + link-name = "WCD Capture"; + + codec { + sound-dai = <&wcd939x 1>, <&swr2 0>, <&lpass_txmacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-playback-dai-link { + link-name = "WCD Playback"; + + codec { + sound-dai = <&wcd939x 0>, <&swr1 0>, <&lpass_rxmacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wsa-playback-dai-link { + link-name = "WSA Playback"; + + codec { + sound-dai = <&wsa885x>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; + }; + + cpu { + sound-dai = <&q6apmbedai AIF_TDM_RX_1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + + wcd939x: audio-codec { + compatible = "qcom,wcd9395-codec", "qcom,wcd9390-codec"; + + pinctrl-0 = <&wcd_default>; + pinctrl-names = "default"; + + qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 + 500000 500000 500000 500000>; + qcom,mbhc-headphone-vthreshold-microvolt = <50000>; + qcom,mbhc-headset-vthreshold-microvolt = <1700000>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + qcom,micbias4-microvolt = <1800000>; + qcom,rx-device = <&wcd_rx>; + qcom,tx-device = <&wcd_tx>; + + reset-gpios = <&tlmm 161 GPIO_ACTIVE_LOW>; + + vdd-buck-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l15b_1p8>; + vdd-mic-bias-supply = <&vreg_bob1>; + vdd-px-supply = <&vreg_l3i_1p2>; + vdd-rxtx-supply = <&vreg_l15b_1p8>; + + #sound-dai-cells = <1>; + }; + sdcard_vdd_3p0: sdcard-vdd-3p0 { compatible = "regulator-fixed"; @@ -144,6 +262,70 @@ }; }; +&lpass_vamacro { + pinctrl-0 = <&dmic01_default>, <&dmic23_default>; + pinctrl-names = "default"; + + vdd-micb-supply = <&vreg_l10b_1p8>; + qcom,dmic-sample-rate = <4800000>; +}; + + +&q6apmbedai { + dai@40 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_QAIF_IF1_IBIT + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; +}; + +&i2c3 { + status = "okay"; + + wsa885x: speaker@c { + compatible = "qcom,wsa8855"; + reg = <0x0c>; + + interrupt-parent = <&tlmm>; + interrupts = <77 IRQ_TYPE_EDGE_FALLING>; + + pinctrl-0 = <&wsa885x_spkr_sd_n &wsa885x_irq_gpio>; + pinctrl-names = "default"; + + powerdown-gpios = <&pmh0110_f_e0_gpios 11 GPIO_ACTIVE_LOW>; + + vdd-1p8-supply = <&vreg_l2g_1p8>; + vdd-io-supply = <&vreg_l1g_1p2>; + + qcom,battery-config = "1s"; + + #sound-dai-cells = <0>; + + status = "okay"; + }; +}; + +&swr1 { + status = "okay"; + wcd_rx: codec@0,4 { + compatible = "sdw20217010e00"; + reg = <0 4>; + + qcom,rx-port-mapping = <1 2 3 4 5 9>; + }; +}; + +&swr2 { + status = "okay"; + + wcd_tx: codec@0,3 { + compatible = "sdw20217010e00"; + reg = <0 3>; + qcom,tx-port-mapping = <3 3 3 4>; + }; +}; + &apps_rsc { regulators-0 { compatible = "qcom,pmh0101-rpmh-regulators"; @@ -812,6 +994,16 @@ reset-gpios = <&tlmm 220 GPIO_ACTIVE_LOW>; }; +&pmh0110_f_e0_gpios { + wsa885x_spkr_sd_n: wsa885x-spkr-sd-n-state { + pins = "gpio11"; + function = "normal"; + input-disable; + output-enable; + power-source = <1>; /* 1.8V */ + }; +}; + &pmh0101_flash { status = "okay"; @@ -934,6 +1126,20 @@ <119 2>, /* SoCCP */ <144 2>; /* CXM UART */ + wcd_default: wcd-reset-n-active-state { + pins = "gpio161"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + wsa885x_irq_gpio: wsa885x-irq-state { + pins = "gpio77"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + key_vol_up_default: key-vol-up-default-state { pins = "gpio101"; function = "gpio"; From 65761a91ec6035d353ba866383916401af267130 Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Wed, 23 Sep 2026 14:16:27 +0530 Subject: [PATCH 0630/1133] FROMLIST: arm64: defconfig: Enable Hawi LPASS LPI pinctrl driver Build the LPASS LPI pinctrl driver as module, as required by the Hawi and Maili platforms to control all the LPI GPIOs. Link: https://lore.kernel.org/lkml/20260923084627.748920-9-prasad.kumpatla@oss.qualcomm.com/ Signed-off-by: Prasad Kumpatla Signed-off-by: Mukesh Ojha --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7b4985b29b21c..01b74b045bf32 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -706,6 +706,7 @@ CONFIG_PINCTRL_IMX_SCMI=y CONFIG_PINCTRL_IMX91=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y CONFIG_PINCTRL_LPASS_LPI=m +CONFIG_PINCTRL_HAWI_LPASS_LPI=m CONFIG_PINCTRL_MILOS_LPASS_LPI=m CONFIG_PINCTRL_SC7280_LPASS_LPI=m CONFIG_PINCTRL_SM6115_LPASS_LPI=m From 2d3cbc042ccdb21869b9fdf4a90fcb1a37759961 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Wed, 23 Sep 2026 15:55:52 +0530 Subject: [PATCH 0631/1133] FROMLIST: arm64: dts: qcom: hawi: Add GPU support Adreno 850 is the next generation of A8x GPU present in Hawi SoC. It shares the ADRENO_8XX_GEN2 family and slice architecture with A840, but has many architectural improvements. There is a new block Matrix ALU (MALU) which helps to accelerate certain compute workloads. Also, there is a new Bx rail that powers a part of the GPU IP. GMU is now powered by a dedicated GDSC powered by MxG rail. Add the GPU and GMU nodes describing the register maps, interrupts, clocks, power domains, IOMMU, interconnect paths and the OPP tables. Link: https://lore.kernel.org/lkml/20260923-hawi-gpu-v1-12-0c3c79a1a470@oss.qualcomm.com/ Assisted-by: LLM Reviewed-by: Konrad Dybcio Signed-off-by: Akhil P Oommen Signed-off-by: Mukesh Ojha --- arch/arm64/boot/dts/qcom/hawi.dtsi | 336 +++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi.dtsi b/arch/arm64/boot/dts/qcom/hawi.dtsi index 3074a6601066f..cf69bc530f3a9 100644 --- a/arch/arm64/boot/dts/qcom/hawi.dtsi +++ b/arch/arm64/boot/dts/qcom/hawi.dtsi @@ -3611,6 +3611,277 @@ #reset-cells = <1>; }; + gpu: gpu@3d00000 { + compatible = "qcom,adreno-44051401", "qcom,adreno"; + reg = <0x0 0x03d00000 0x0 0x6c000>, + <0x0 0x03d9e000 0x0 0x2000>; + reg-names = "kgsl_3d0_reg_memory", + "cx_mem"; + + interrupts = ; + + iommus = <&adreno_smmu 0 0x0>, + <&adreno_smmu 1 0x0>; + + operating-points-v2 = <&gpu_opp_table>; + + qcom,gmu = <&gmu>; + #cooling-cells = <2>; + + nvmem-cells = <&gpu_speed_bin>; + nvmem-cell-names = "speed_bin"; + + interconnects = <&gem_noc MASTER_GFX3D QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "gfx-mem"; + + status = "disabled"; + + gpu_zap_shader: zap-shader { + memory-region = <&gpu_microcode_mem>; + }; + + gpu_opp_table: opp-table { + compatible = "operating-points-v2-adreno", + "operating-points-v2"; + + /* Only applicable for SKUs with 1500 MHz Fmax */ + opp-1500000000 { + opp-hz = /bits/ 64 <1500000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x01>; + qcom,opp-acd-level = <0x802f5ffd>; + }; + + /* Only applicable for SKUs with 1500 MHz Fmax */ + opp-1475000000 { + opp-hz = /bits/ 64 <1475000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x01>; + qcom,opp-acd-level = <0x802f5ffd>; + }; + + opp-1450000000 { + opp-hz = /bits/ 64 <1450000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x03>; + qcom,opp-acd-level = <0x88285ffd>; + }; + + opp-1400000000 { + opp-hz = /bits/ 64 <1400000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x03>; + qcom,opp-acd-level = <0x88285ffd>; + }; + + opp-1350000000 { + opp-hz = /bits/ 64 <1350000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x07>; + qcom,opp-acd-level = <0xa8295ffd>; + }; + + opp-1275000000 { + opp-hz = /bits/ 64 <1275000000>; + opp-level = ; + opp-peak-kBps = <18671875>; + opp-supported-hw = <0x07>; + qcom,opp-acd-level = <0xa82a5ffd>; + }; + + opp-1201000000 { + opp-hz = /bits/ 64 <1201000000>; + opp-level = ; + opp-peak-kBps = <18671875>; + opp-supported-hw = <0x07>; + qcom,opp-acd-level = <0x882b5ffd>; + }; + + opp-1126000000 { + opp-hz = /bits/ 64 <1126000000>; + opp-level = ; + opp-peak-kBps = <16500000>; + opp-supported-hw = <0x07>; + qcom,opp-acd-level = <0xa82b5ffd>; + }; + + opp-1025000000-0 { + opp-hz = /bits/ 64 <1025000000>; + opp-level = ; + opp-peak-kBps = <16500000>; + opp-supported-hw = <0x07>; + qcom,opp-acd-level = <0xa82b5ffd>; + }; + + /* Only applicable for SKUs with 1025 MHz Fmax */ + opp-1025000000-1 { + opp-hz = /bits/ 64 <1025000000>; + opp-level = ; + opp-peak-kBps = <20832031>; + opp-supported-hw = <0x08>; + qcom,opp-acd-level = <0xa82b5ffd>; + }; + + opp-951000000 { + opp-hz = /bits/ 64 <951000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82c5ffd>; + }; + + opp-843000000 { + opp-hz = /bits/ 64 <843000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82c5ffd>; + }; + + opp-801000000 { + opp-hz = /bits/ 64 <801000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82c5ffd>; + }; + + opp-759000000 { + opp-hz = /bits/ 64 <759000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x882d5ffd>; + }; + + opp-693000000 { + opp-hz = /bits/ 64 <693000000>; + opp-level = ; + opp-peak-kBps = <12449218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xa82f5ffd>; + }; + + opp-636000000 { + opp-hz = /bits/ 64 <636000000>; + opp-level = ; + opp-peak-kBps = <10687500>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe0285ffd>; + }; + + opp-578000000 { + opp-hz = /bits/ 64 <578000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe0285ffd>; + }; + + opp-539000000 { + opp-hz = /bits/ 64 <539000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xc02c5ffd>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xc02c5ffd>; + }; + + opp-461000000 { + opp-hz = /bits/ 64 <461000000>; + opp-level = ; + opp-peak-kBps = <8171875>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe02d5ffd>; + }; + + opp-422000000 { + opp-hz = /bits/ 64 <422000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe02d5ffd>; + }; + + opp-390000000 { + opp-hz = /bits/ 64 <390000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe02d5ffd>; + }; + + opp-357000000 { + opp-hz = /bits/ 64 <357000000>; + opp-level = ; + opp-peak-kBps = <6074218>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82a5ffd>; + }; + + opp-325000000 { + opp-hz = /bits/ 64 <325000000>; + opp-level = ; + opp-peak-kBps = <5285156>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82a5ffd>; + }; + + opp-274000000 { + opp-hz = /bits/ 64 <274000000>; + opp-level = ; + opp-peak-kBps = <5285156>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe82a5ffd>; + }; + + opp-222000000 { + opp-hz = /bits/ 64 <222000000>; + opp-level = ; + opp-peak-kBps = <2136718>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xaa2a5ffd>; + }; + + opp-190000000 { + opp-hz = /bits/ 64 <190000000>; + opp-level = ; + opp-peak-kBps = <2136718>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0x8a2f5ffd>; + }; + + opp-157000000 { + opp-hz = /bits/ 64 <157000000>; + opp-level = ; + opp-peak-kBps = <2136718>; + opp-supported-hw = <0x0f>; + qcom,opp-acd-level = <0xe22d5ffd>; + }; + + opp-125000000 { + opp-hz = /bits/ 64 <125000000>; + opp-level = ; + opp-peak-kBps = <2136718>; + opp-supported-hw = <0x0f>; + /* ACD is disabled */ + }; + }; + }; + gxclkctl: clock-controller@3d64000 { compatible = "qcom,hawi-gxclkctl", "qcom,kaanapali-gxclkctl"; @@ -3623,6 +3894,71 @@ #power-domain-cells = <1>; }; + gmu: gmu@3d6c000 { + compatible = "qcom,adreno-gmu-850.1", "qcom,adreno-gmu"; + reg = <0x0 0x03d6c000 0x0 0x32000>; + reg-names = "gmu"; + + interrupts = , + ; + interrupt-names = "hfi", "gmu"; + + clocks = <&gpucc GPU_CC_CX_GMU_CLK>, + <&gpucc GPU_CC_CXO_CLK>, + <&gcc GCC_GPU_GEMNOC_GFX_CLK>, + <&gpucc GPU_CC_AHB_CLK>, + <&gpucc GPU_CC_MXG_AHB_CLK>, + <&gpucc GPU_CC_HUB_CX_INT_CLK>; + clock-names = "gmu", + "cxo", + "memnoc", + "ahb", + "mxg_ahb", + "hub"; + + power-domains = <&gpucc GPU_CC_CX_GDSC>, + <&gxclkctl GX_CLKCTL_GX_GDSC>, + <&gpucc GPU_CC_MXG_GDSC>; + power-domain-names = "cx", + "gx", + "gmu_mx"; + + iommus = <&adreno_smmu 5 0x0>; + + qcom,qmp = <&aoss_qmp>; + + operating-points-v2 = <&gmu_opp_table>; + + gmu_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-556000000 { + opp-hz = /bits/ 64 <556000000>; + opp-level = ; + }; + + opp-788000000 { + opp-hz = /bits/ 64 <788000000>; + opp-level = ; + }; + + opp-825000000 { + opp-hz = /bits/ 64 <825000000>; + opp-level = ; + }; + + opp-880000000 { + opp-hz = /bits/ 64 <880000000>; + opp-level = ; + }; + + opp-917000000 { + opp-hz = /bits/ 64 <917000000>; + opp-level = ; + }; + }; + }; + gpucc: clock-controller@3d90000 { compatible = "qcom,hawi-gpucc"; reg = <0x0 0x03d90000 0x0 0x9800>; From 657f8c9f0375f4cc2f2b35cd38ca118ef3104ca7 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Wed, 23 Sep 2026 15:55:53 +0530 Subject: [PATCH 0632/1133] FROMLIST: arm64: dts: qcom: hawi-mtp: Enable GPU Add the secure firmware name property and enable GPU support on Hawi MTP device. Link: https://lore.kernel.org/lkml/20260923-hawi-gpu-v1-13-0c3c79a1a470@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Akhil P Oommen Signed-off-by: Mukesh Ojha --- arch/arm64/boot/dts/qcom/hawi-mtp.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi-mtp.dts b/arch/arm64/boot/dts/qcom/hawi-mtp.dts index 23b091d5dc37f..2f3bf77f93ba5 100644 --- a/arch/arm64/boot/dts/qcom/hawi-mtp.dts +++ b/arch/arm64/boot/dts/qcom/hawi-mtp.dts @@ -962,6 +962,14 @@ }; }; +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/hawi/gen81100_zap.mbn"; +}; + &pcie0 { status = "okay"; }; From fc82e05bcde3cc80200fde9b488ddd89aed9bd3f Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Wed, 23 Sep 2026 16:32:38 +0530 Subject: [PATCH 0633/1133] FROMLIST: arm64: dts: qcom: hawi: Add CAMSS and CSIPHY nodes for Hawi Add dtsi to describe the Hawi CAMSS and CSIPHY block 3 x TPG 3 x CSID 2 x CSID Lite 3 x IFE 2 x IFE Lite 6 x CSIPHY Signed-off-by: Hangxiang Ma Co-developed-by: Nihal Kumar Gupta Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-7-cbbb42e534ef@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/hawi.dtsi | 463 +++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi.dtsi b/arch/arm64/boot/dts/qcom/hawi.dtsi index cf69bc530f3a9..648ad02b8cb0c 100644 --- a/arch/arm64/boot/dts/qcom/hawi.dtsi +++ b/arch/arm64/boot/dts/qcom/hawi.dtsi @@ -550,6 +550,28 @@ }; }; + csiphy_mxc_opp_table: opp-table-mxc { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs_d1_1>, + <&rpmhpd_opp_low_svs_d1_1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d0>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_nom>; + }; + }; + soc@0 { compatible = "simple-bus"; @@ -4489,6 +4511,447 @@ qcom,bcm-voters = <&apps_bcm_voter>; }; + camss: isp@9253000 { + compatible = "qcom,hawi-camss"; + + reg = <0x0 0x09253000 0x0 0x5e80>, + <0x0 0x09263000 0x0 0x5e80>, + <0x0 0x09273000 0x0 0x5e80>, + <0x0 0x092d3000 0x0 0x3880>, + <0x0 0x092e7000 0x0 0x3880>, + <0x0 0x093fd000 0x0 0x400>, + <0x0 0x093fe000 0x0 0x400>, + <0x0 0x093ff000 0x0 0x400>, + <0x0 0x09151000 0x0 0x20000>, + <0x0 0x09171000 0x0 0x20000>, + <0x0 0x09191000 0x0 0x20000>, + <0x0 0x092dc000 0x0 0x6800>, + <0x0 0x092f0000 0x0 0x6800>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_DCD_XO_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_TITAN_MNOC_HF_CLK>, + <&camcc CAM_CC_TITAN_MNOC_SF_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "camnoc_dcd_xo", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_mnoc_hf", + "cpas_mnoc_sf", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc"; + + iommus = <&apps_smmu 0x1800 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + camss_csiphy0_inep: endpoint { + remote-endpoint = <&csiphy0_out_ep>; + }; + }; + + port@1 { + reg = <1>; + + camss_csiphy1_inep: endpoint { + remote-endpoint = <&csiphy1_out_ep>; + }; + }; + + port@2 { + reg = <2>; + + camss_csiphy2_inep: endpoint { + remote-endpoint = <&csiphy2_out_ep>; + }; + }; + + port@3 { + reg = <3>; + + camss_csiphy3_inep: endpoint { + remote-endpoint = <&csiphy3_out_ep>; + }; + }; + + port@4 { + reg = <4>; + + camss_csiphy4_inep: endpoint { + remote-endpoint = <&csiphy4_out_ep>; + }; + }; + + port@5 { + reg = <5>; + + camss_csiphy5_inep: endpoint { + remote-endpoint = <&csiphy5_out_ep>; + }; + }; + }; + }; + + csiphy0: phy@9523000 { + compatible = "qcom,hawi-csi2-phy", "qcom,kaanapali-csi2-phy"; + reg = <0x0 0x09523000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy0_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy0_out_ep: endpoint { + remote-endpoint = <&camss_csiphy0_inep>; + }; + }; + }; + }; + + csiphy1: phy@9525000 { + compatible = "qcom,hawi-csi2-phy", "qcom,kaanapali-csi2-phy"; + reg = <0x0 0x09525000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy1_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy1_out_ep: endpoint { + remote-endpoint = <&camss_csiphy1_inep>; + }; + }; + }; + }; + + csiphy2: phy@9527000 { + compatible = "qcom,hawi-csi2-phy", "qcom,kaanapali-csi2-phy"; + reg = <0x0 0x09527000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy2_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy2_out_ep: endpoint { + remote-endpoint = <&camss_csiphy2_inep>; + }; + }; + }; + }; + + csiphy3: phy@9529000 { + compatible = "qcom,hawi-csi2-phy", "qcom,kaanapali-csi2-phy"; + reg = <0x0 0x09529000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy3_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy3_out_ep: endpoint { + remote-endpoint = <&camss_csiphy3_inep>; + }; + }; + }; + }; + + csiphy4: phy@952b000 { + compatible = "qcom,hawi-csi2-phy", "qcom,kaanapali-csi2-phy"; + reg = <0x0 0x0952b000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy4_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy4_out_ep: endpoint { + remote-endpoint = <&camss_csiphy4_inep>; + }; + }; + }; + }; + + csiphy5: phy@952d000 { + compatible = "qcom,hawi-csi2-phy", "qcom,kaanapali-csi2-phy"; + reg = <0x0 0x0952d000 0x0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>; + clock-names = "core", + "timer", + "ahb"; + + interrupts = ; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>, + <&rpmhpd RPMHPD_MMCX>, + <&rpmhpd RPMHPD_MXC>; + power-domain-names = "top", + "mmcx", + "mx"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + csiphy5_in_ep: endpoint { + }; + }; + + port@1 { + reg = <1>; + + csiphy5_out_ep: endpoint { + remote-endpoint = <&camss_csiphy5_inep>; + }; + }; + }; + }; + camcc: clock-controller@956d000 { compatible = "qcom,hawi-camcc"; reg = <0x0 0x0956d000 0x0 0x80000>; From f16800da2f92df0e5bb3bd810fd75cc6d0c1a5da Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Wed, 23 Sep 2026 16:32:39 +0530 Subject: [PATCH 0634/1133] FROMLIST: arm64: dts: qcom: hawi: Add CCI definitions for Hawi Qualcomm Hawi SoC has three Camera Control Interface (CCI). Each controller contains two I2C hosts. Signed-off-by: Hangxiang Ma Reviewed-by: Konrad Dybcio Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-8-cbbb42e534ef@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/hawi.dtsi | 194 +++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi.dtsi b/arch/arm64/boot/dts/qcom/hawi.dtsi index 648ad02b8cb0c..2d42ef0bf9ddc 100644 --- a/arch/arm64/boot/dts/qcom/hawi.dtsi +++ b/arch/arm64/boot/dts/qcom/hawi.dtsi @@ -4688,6 +4688,116 @@ }; }; + cci0: cci@941b000 { + compatible = "qcom,hawi-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941b000 0x0 0x1000>; + + interrupts = ; + + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "ahb", + "cci"; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + pinctrl-0 = <&cci0_0_default>, <&cci0_1_default>; + pinctrl-1 = <&cci0_0_sleep>, <&cci0_1_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@941c000 { + compatible = "qcom,hawi-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941c000 0x0 0x1000>; + + interrupts = ; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "ahb", + "cci"; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + pinctrl-0 = <&cci1_0_default>, <&cci1_1_default>; + pinctrl-1 = <&cci1_0_sleep>, <&cci1_1_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci2: cci@941d000 { + compatible = "qcom,hawi-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0941d000 0x0 0x1000>; + + interrupts = ; + + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "ahb", + "cci"; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + pinctrl-0 = <&cci2_0_default>, <&cci2_1_default>; + pinctrl-1 = <&cci2_0_sleep>, <&cci2_1_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci2_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci2_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + csiphy0: phy@9523000 { compatible = "qcom,hawi-csi2-phy", "qcom,kaanapali-csi2-phy"; reg = <0x0 0x09523000 0x0 0x2000>; @@ -5226,6 +5336,90 @@ #interrupt-cells = <2>; wakeup-parent = <&pdc>; + cci0_0_default: cci0-0-default-state { + pins = "gpio109", "gpio110"; + function = "cci_i2c0"; + drive-strength = <2>; + bias-pull-up; + }; + + cci0_0_sleep: cci0-0-sleep-state { + pins = "gpio109", "gpio110"; + function = "cci_i2c0"; + drive-strength = <2>; + bias-pull-down; + }; + + cci0_1_default: cci0-1-default-state { + pins = "gpio111", "gpio112"; + function = "cci_i2c1"; + drive-strength = <2>; + bias-pull-up; + }; + + cci0_1_sleep: cci0-1-sleep-state { + pins = "gpio111", "gpio112"; + function = "cci_i2c1"; + drive-strength = <2>; + bias-pull-down; + }; + + cci1_0_default: cci1-0-default-state { + pins = "gpio113", "gpio114"; + function = "cci_i2c2"; + drive-strength = <2>; + bias-pull-up; + }; + + cci1_0_sleep: cci1-0-sleep-state { + pins = "gpio113", "gpio114"; + function = "cci_i2c2"; + drive-strength = <2>; + bias-pull-down; + }; + + cci1_1_default: cci1-1-default-state { + pins = "gpio107", "gpio160"; + function = "cci_i2c3"; + drive-strength = <2>; + bias-pull-up; + }; + + cci1_1_sleep: cci1-1-sleep-state { + pins = "gpio107", "gpio160"; + function = "cci_i2c3"; + drive-strength = <2>; + bias-pull-down; + }; + + cci2_0_default: cci2-0-default-state { + pins = "gpio108", "gpio149"; + function = "cci_i2c4"; + drive-strength = <2>; + bias-pull-up; + }; + + cci2_0_sleep: cci2-0-sleep-state { + pins = "gpio108", "gpio149"; + function = "cci_i2c4"; + drive-strength = <2>; + bias-pull-down; + }; + + cci2_1_default: cci2-1-default-state { + pins = "gpio115", "gpio116"; + function = "cci_i2c5"; + drive-strength = <2>; + bias-pull-up; + }; + + cci2_1_sleep: cci2-1-sleep-state { + pins = "gpio115", "gpio116"; + function = "cci_i2c5"; + drive-strength = <2>; + bias-pull-down; + }; + qup_i2c8_data_clk: qup-i2c8-data-clk-state { /* SDA, SCL */ pins = "gpio0", "gpio1"; From 83c0682298ec89de9e332eb538a5e731444f4489 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Wed, 23 Sep 2026 16:32:40 +0530 Subject: [PATCH 0635/1133] FROMLIST: arm64: dts: qcom: hawi: Add camera MCLK pinctrl for Hawi Define pinctrl definitions to enable camera master clocks on Hawi. Signed-off-by: Hangxiang Ma Reviewed-by: Konrad Dybcio Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-9-cbbb42e534ef@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/hawi.dtsi | 56 ++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi.dtsi b/arch/arm64/boot/dts/qcom/hawi.dtsi index 2d42ef0bf9ddc..3515ee43952ed 100644 --- a/arch/arm64/boot/dts/qcom/hawi.dtsi +++ b/arch/arm64/boot/dts/qcom/hawi.dtsi @@ -5336,6 +5336,62 @@ #interrupt-cells = <2>; wakeup-parent = <&pdc>; + cam0_default: cam0-default-state { + pins = "gpio89"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam1_default: cam1-default-state { + pins = "gpio90"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam2_default: cam2-default-state { + pins = "gpio91"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam3_default: cam3-default-state { + pins = "gpio92"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam4_default: cam4-default-state { + pins = "gpio93"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam5_default: cam5-default-state { + pins = "gpio94"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam6_default: cam6-default-state { + pins = "gpio95"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam7_default: cam7-default-state { + pins = "gpio96"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + cci0_0_default: cci0-0-default-state { pins = "gpio109", "gpio110"; function = "cci_i2c0"; From d97db91fb9e12ffb9400c724f1848d9556b0f18e Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Wed, 23 Sep 2026 16:32:41 +0530 Subject: [PATCH 0636/1133] FROMLIST: arm64: dts: qcom: hawi-mtp: Enable camera subsystem for Hawi MTP Enable the camera subsystem on the Hawi MTP along with the S5KJN5 sensor connected to CSIPHY2 through I2C0 CCI1. Add the camera master clock and sensor reset pin states on the TLMM GPIOs. Signed-off-by: Hangxiang Ma Co-developed-by: Nihal Kumar Gupta Reviewed-by: Konrad Dybcio Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-10-cbbb42e534ef@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/hawi-mtp.dts | 62 +++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi-mtp.dts b/arch/arm64/boot/dts/qcom/hawi-mtp.dts index 2f3bf77f93ba5..56d9b6188337c 100644 --- a/arch/arm64/boot/dts/qcom/hawi-mtp.dts +++ b/arch/arm64/boot/dts/qcom/hawi-mtp.dts @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -962,6 +963,60 @@ }; }; +&camss { + status = "okay"; +}; + +&camss_csiphy2_inep { + data-lanes = <1 2 3 4>; +}; + +&cci0 { + status = "okay"; +}; + +&cci0_i2c1 { + camera@10 { + compatible = "samsung,s5kjn5"; + reg = <0x10>; + reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&cam2_default &cam2_reset>; + pinctrl-names = "default"; + + clocks = <&cambistmclkcc CAM_BIST_MCLK_CC_MCLK2_CLK>; + assigned-clocks = <&cambistmclkcc CAM_BIST_MCLK_CC_MCLK2_CLK>; + assigned-clock-rates = <19200000>; + + afvdd-supply = <&vreg_l5m_2p8>; + vdda-supply = <&vreg_l7m_2p2>; + vddd-supply = <&vreg_l1m_1p0>; + vddio-supply = <&vreg_l4n_1p8>; + vddio1p2-supply = <&vreg_l2n_1p2>; + + port { + s5kjn5_ep: endpoint { + link-frequencies = /bits/ 64 <1248000000>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&csiphy2_in_ep>; + }; + }; + }; +}; + +&csiphy2 { + vdda-0p9-supply = <&vreg_l1i_0p8>; + vdda-1p2-supply = <&vreg_l3d_1p2>; + + status = "okay"; +}; + +&csiphy2_in_ep { + bus-type = ; + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&s5kjn5_ep>; +}; + &gpu { status = "okay"; }; @@ -1134,6 +1189,13 @@ <119 2>, /* SoCCP */ <144 2>; /* CXM UART */ + cam2_reset: cam2-reset-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + wcd_default: wcd-reset-n-active-state { pins = "gpio161"; function = "gpio"; From d1b68f8c7fb9e227e97321bebcaab6b5f947d284 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 11:27:56 +0800 Subject: [PATCH 0637/1133] FROMLIST: arm64: dts: qcom: hawi: add iris video codec node Add the iris video codec device node for the hawi SoC, describing the register space, interrupt, nine power domains (including the VPU5x-specific mm-int and cx-int domains), thirteen clocks, two interconnect paths for CPU config and video memory bandwidth, IOMMU mappings, and the operating point table covering 150 MHz through 1000 MHz. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_hawi-v2-6-016ec3d24b79@oss.qualcomm.com/ Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Signed-off-by: Wangao Wang --- arch/arm64/boot/dts/qcom/hawi.dtsi | 158 +++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi.dtsi b/arch/arm64/boot/dts/qcom/hawi.dtsi index 3515ee43952ed..4cc265b278216 100644 --- a/arch/arm64/boot/dts/qcom/hawi.dtsi +++ b/arch/arm64/boot/dts/qcom/hawi.dtsi @@ -443,6 +443,10 @@ reg = <0x0 0xbd500000 0x0 0xf00000>; no-map; }; + + iris_resv: reservation-iris { + iommu-addresses = <&iris_non_pixel 0x0 0x0 0x0 0x32000000>; + }; }; smp2p-adsp { @@ -3442,6 +3446,160 @@ power-domains = <&gcc GCC_UFS_PHY_GDSC>; }; + iris: video-codec@2000000 { + compatible = "qcom,hawi-iris"; + reg = <0x0 0x02000000 0x0 0xf0000>; + + interrupts = ; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc VIDEO_CC_MVS0_VPP0_GDSC>, + <&videocc VIDEO_CC_MVS0_VPP1_GDSC>, + <&videocc VIDEO_CC_MVS0A_GDSC>, + <&videocc VIDEO_CC_MM_INT_GDSC>, + <&videocc VIDEO_CC_AXI0_CX_INT_GDSC>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vpp0", + "vpp1", + "apv", + "mm-int", + "cx-int"; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&gcc GCC_VIDEO_AXI0C_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0C_CTL_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0C_DEBUG_CLK>, + <&videocc VIDEO_CC_CX_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&videocc VIDEO_CC_MVS0_VPP0_CLK>, + <&videocc VIDEO_CC_MVS0_VPP1_CLK>, + <&videocc VIDEO_CC_MVS0_VPP0_VPP1_GATING_CLK>, + <&videocc VIDEO_CC_MVS0A_CLK>, + <&videocc VIDEO_CC_MVS0B_CLK>; + clock-names = "iface", + "ifacec", + "core", + "core_freerun", + "core_ctl_freerun", + "core_debug", + "cx_iface", + "vcodec0_core", + "vcodec_vpp0", + "vcodec_vpp1", + "vcodec_vpp0_vpp1_gating", + "vcodec_apv", + "vcodec_bse"; + + operating-points-v2 = <&iris_opp_table>; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_IRIS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_VIDEO_MVP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + memory-region = <&video_mem>; + + resets = <&gcc GCC_VIDEO_AXI0C_CLK_ARES>, + <&videocc VIDEO_CC_MVS0C_CTL_FREERUN_CLK_ARES>; + reset-names = "bus0", + "core"; + + dma-coherent; + + #address-cells = <2>; + #size-cells = <2>; + + status = "disabled"; + + iris_non_pixel: non-pixel { + iommus = <&apps_smmu 0x1540 0x0000>, + <&apps_smmu 0x1620 0x0000>, + <&apps_smmu 0x1544 0x0000>; + memory-region = <&iris_resv>; + }; + + iris_pixel: pixel { + iommus = <&apps_smmu 0x1543 0x0000>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000 150000000 + 150000000 225000000>; + required-opps = <&rpmhpd_opp_low_svs_d2>, + <&rpmhpd_opp_low_svs_d2>; + }; + + opp-285000000 { + opp-hz = /bits/ 64 <285000000 240000000 + 240000000 360000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs_d0>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 + 338000000 507000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-420000000 { + opp-hz = /bits/ 64 <420000000 420000000 + 420000000 630000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 + 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-560000000 { + opp-hz = /bits/ 64 <560000000 533000000 + 533000000 800000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_nom>; + }; + + opp-630000000 { + opp-hz = /bits/ 64 <630000000 630000000 + 630000000 1104000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo>; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000 710000000 + 710000000 1260000000>; + required-opps = <&rpmhpd_opp_turbo>, + <&rpmhpd_opp_turbo_l1>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000 710000000 + 850000000 1260000000>; + required-opps = <&rpmhpd_opp_turbo>, + <&rpmhpd_opp_turbo_l3>; + }; + }; + }; + videocc: clock-controller@20f0000 { compatible = "qcom,hawi-videocc"; reg = <0x0 0x020f0000 0x0 0x10000>; From 4a3a9dc4c855dc18b67313819915c5fb4706a393 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 11:27:57 +0800 Subject: [PATCH 0638/1133] FROMLIST: arm64: dts: qcom: hawi: enable iris on mtp board Enable the iris video codec on the hawi MTP reference board. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_hawi-v2-7-016ec3d24b79@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Wangao Wang --- arch/arm64/boot/dts/qcom/hawi-mtp.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi-mtp.dts b/arch/arm64/boot/dts/qcom/hawi-mtp.dts index 56d9b6188337c..72cb15cd8d4da 100644 --- a/arch/arm64/boot/dts/qcom/hawi-mtp.dts +++ b/arch/arm64/boot/dts/qcom/hawi-mtp.dts @@ -1025,6 +1025,10 @@ firmware-name = "qcom/hawi/gen81100_zap.mbn"; }; +&iris { + status = "okay"; +}; + &pcie0 { status = "okay"; }; From d41df8805d608aacdd248e4d912f6aa3e03ad1ed Mon Sep 17 00:00:00 2001 From: Ekansh Gupta Date: Wed, 21 Oct 2026 17:15:02 +0530 Subject: [PATCH 0639/1133] FROMLIST: arm64: dts: qcom: hawi: Add memory-region for audio PD Reserve memory region for audio PD dynamic loading and remote heap requirements. Add the required VMID list for memory ownership transfers. Link: https://lore.kernel.org/all/20261021-hawi-rh-v1-1-401143c22401@oss.qualcomm.com/ Signed-off-by: Ekansh Gupta Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Signed-off-by: Niharika Kacharla --- arch/arm64/boot/dts/qcom/hawi.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi.dtsi b/arch/arm64/boot/dts/qcom/hawi.dtsi index 4cc265b278216..60bf7366faaab 100644 --- a/arch/arm64/boot/dts/qcom/hawi.dtsi +++ b/arch/arm64/boot/dts/qcom/hawi.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -447,6 +448,14 @@ iris_resv: reservation-iris { iommu-addresses = <&iris_non_pixel 0x0 0x0 0x0 0x32000000>; }; + + adsp_rpc_remote_heap_mem: adsp-rpc-remote-heap { + compatible = "shared-dma-pool"; + alloc-ranges = <0x0 0x0 0x1 0x0>; + no-map; + alignment = <0x0 0x400000>; + size = <0x0 0x800000>; + }; }; smp2p-adsp { @@ -4299,6 +4308,9 @@ compatible = "qcom,hawi-fastrpc", "qcom,kaanapali-fastrpc"; qcom,glink-channels = "fastrpcglink-apps-dsp"; label = "adsp"; + memory-region = <&adsp_rpc_remote_heap_mem>; + qcom,vmids = ; #address-cells = <1>; #size-cells = <0>; From 8eb6cb5a895a2c2398b9f768a01f7cde1be2a74a Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 2 Jun 2026 20:51:49 +0530 Subject: [PATCH 0640/1133] FROMLIST: dt-bindings: clock: qcom: Add bindings for PDM GP_MN clock divider Add device tree bindings for the Qualcomm Peripheral Web's PDM GP_MN clock divider. The hardware generates a fractional output frequency from a fixed input clock (typically TCXO4) using the relation Fout = Fin * (M / N), with duty cycle controlled by a separate D register. The clock output is routed over a gpio controlled pin. Link: https://lore.kernel.org/r/20260602-pdm_clk_gp_mnd_v1-v1-1-1522662b6c53@oss.qualcomm.com Signed-off-by: Taniya Das --- .../bindings/clock/qcom,clk-gp-mnd.yaml | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml diff --git a/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml b/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml new file mode 100644 index 0000000000000..c1688bb3d68d8 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,clk-gp-mnd.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,clk-gp-mnd.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Peripheral Web's PDM GP_MN Clock Divider + +maintainers: + - Taniya Das + +description: | + The Peripheral Web's PDM GP_MN clock divider receives an input clock + (TCXO4) with frequency Fin and generates an output clock with + frequency Fout = Fin * (M / N) and a duty cycle controlled by D + and routed over a gpio pin. + + The divider is configured using three registers: + + - GP_MN_CLK_MDIV: holds the M value. + - GP_MN_CLK_NDIV: holds the ones complement of (N - M). + - GP_MN_CLK_DUTY: holds the D value. + + For every N input clock cycles the GP_MN produces M output clock + cycles. D is the number of native clock cycles in which the GP_MN + output is low, counted over 2^13 native clock cycles. + + Hardware constraints: + + M <= 511 + N <= 8191 + N > 2 * M + M < D < (N - M) + M and N must be coprime (no common divisor) + +properties: + compatible: + const: qcom,clk-gp-mnd + + reg: + maxItems: 1 + + clocks: + items: + - description: PDM XO4 source clock + - description: PDM AHB bus clock for register access + + clock-names: + items: + - const: pdm_clk + - const: ahb_clk + + '#clock-cells': + const: 0 + + clock-output-names: + maxItems: 1 + + pinctrl-0: + description: Pin configuration for the GP_MN output in the active state. + + pinctrl-names: + items: + - const: active + + assigned-clocks: + maxItems: 1 + description: Parent clock phandle used to set the input frequency. + + assigned-clock-rates: + maxItems: 1 + description: | + Rate for the parent clock in Hz. + Supported rates: 19200000, 9600000, 6400000, 4800000. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - clock-output-names + - pinctrl-0 + - pinctrl-names + - assigned-clocks + - assigned-clock-rates + +additionalProperties: false + +examples: + - | + #include + gp_mn: clock-controller@88d3000 { + compatible = "qcom,clk-gp-mnd"; + reg = <0x88d3000 0xc>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + clock-output-names = "gp_mn_clk"; + pinctrl-0 = <&gp_mn_pin_active>; + pinctrl-names = "active"; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + #clock-cells = <0>; + }; From bb6d479696dc1813dccda37cfcd9476672ebc5bc Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 2 Jun 2026 20:51:50 +0530 Subject: [PATCH 0641/1133] FROMLIST: clk: qcom: Add a driver for PDM GP_MN fractional clock divider The PDM (Pulse Density Modulation) hardware block on Qualcomm SoCs contains a GP_MN clock divider that produces a fractional output frequency from a fixed input clock (typically TCXO4): Fout = Fin * (M / N) The hardware encodes the period in the NDIV register as the 1's complement of (N - M), and controls the duty cycle via a separate DUTY register that counts the number of low-phase native clock cycles over the period N. Add a standalone platform driver for this block that uses rational_best_approximation() to find the closest M/N pair within the 9-bit M and 13-bit N hardware limits, programs the MDIV, NDIV, and DUTY registers via regmap, and implements the full clk_ops surface including determine_rate, set_rate, recalc_rate, get_duty_cycle, and set_duty_cycle. The PDM AHB bus clock is gated around every register access. Link: https://lore.kernel.org/r/20260602-pdm_clk_gp_mnd_v1-v1-2-1522662b6c53@oss.qualcomm.com Signed-off-by: Taniya Das --- drivers/clk/qcom/Kconfig | 15 ++ drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/clk-gp-mnd.c | 333 ++++++++++++++++++++++++++++++++++ 3 files changed, 349 insertions(+) create mode 100644 drivers/clk/qcom/clk-gp-mnd.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 27d0ab24d50a4..d9f1df77b715b 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -2148,4 +2148,19 @@ config SM_VIDEOCC_8450 SM8450 or SM8475 devices. Say Y if you want to support video devices and functionality such as video encode/decode. + +config QCOM_CLK_GP_MND + tristate "Qualcomm PDM GP_MN clock divider" + depends on ARM64 || COMPILE_TEST + help + Support for the Qualcomm PDM GP_MN clock divider found in PDM + (Pulse Density Modulation) hardware blocks. + Given an input clock of frequency Fin (TCXO4), the output + frequency is Fout = Fin * (M / N). For every N input cycles + the divider produces M output cycles. D controls the duty + cycle: it is the number of native clock cycles in which the + GP_MN output is low, counted over 8192 native clock cycles. + + Say Y or M if you want to support GP_MN-based frequency and + duty-cycle configuration on Qualcomm SoCs. endif diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 6affb5073f269..4e8563be8e1b9 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -227,6 +227,7 @@ obj-$(CONFIG_SM_VIDEOCC_8550) += videocc-sm8550.o obj-$(CONFIG_SM_VIDEOCC_8750) += videocc-sm8750.o obj-$(CONFIG_SM_VIDEOCC_MILOS) += videocc-milos.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o +obj-$(CONFIG_QCOM_CLK_GP_MND) += clk-gp-mnd.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o obj-$(CONFIG_QCOM_HFPLL) += hfpll.o obj-$(CONFIG_KRAITCC) += krait-cc.o diff --git a/drivers/clk/qcom/clk-gp-mnd.c b/drivers/clk/qcom/clk-gp-mnd.c new file mode 100644 index 0000000000000..826b6b62ddc7b --- /dev/null +++ b/drivers/clk/qcom/clk-gp-mnd.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * PDM GP_MND clock divider register offsets. + * + * The hardware computes: + * Fout = Fin * (M / N) + * + * with duty cycle controlled by D, where M < D < (N - M). + * + * Register encoding: + * MDIV = M + * NDIV = ~(N - M) [1's complement of (N - M), masked to N_REG_WIDTH bits] + * DUTY = D + */ +#define GP_MND_MDIV_REG 0x0 +#define GP_MND_NDIV_REG 0x4 +#define GP_MND_DUTY_REG 0x8 + +#define GP_MND_M_WIDTH 9 +#define GP_MND_N_WIDTH 13 + +#define GP_MND_MAX_M GENMASK(GP_MND_M_WIDTH - 1, 0) +#define GP_MND_MAX_N GENMASK(GP_MND_N_WIDTH - 1, 0) + +/** + * struct clk_gp_mnd - GP_MND fractional clock divider + * @pdm_ahb_clk: AHB bus clock required for register access + * @regmap: register map for the PDM block + * @hw: handle between common and hardware-specific interfaces + * @m_val: M value (numerator) + * @n_val: N value (period) + */ +struct clk_gp_mnd { + struct clk *pdm_ahb_clk; + struct regmap *regmap; + struct clk_hw hw; + unsigned int m_val; + unsigned int n_val; +}; + +#define to_clk_gp_mnd(_hw) container_of(_hw, struct clk_gp_mnd, hw) + +static int gp_mnd_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + unsigned long m = 0, n = 0; + + rational_best_approximation(req->rate, req->best_parent_rate, + (unsigned long)GP_MND_MAX_M, + (unsigned long)GP_MND_MAX_N, + &m, &n); + + if (!m || !n) + return -EINVAL; + + /* N = 2M + 1 leaves no valid D satisfying M < D < (N - M) */ + if (n == 2 * m + 1) + return -EINVAL; + + req->rate = DIV_ROUND_CLOSEST_ULL((u64)req->best_parent_rate * m, n); + + return 0; +} + +static int gp_mnd_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned long m = 0, n = 0; + unsigned int d_val, n_val; + int ret; + + rational_best_approximation(rate, parent_rate, + (unsigned long)GP_MND_MAX_M, + (unsigned long)GP_MND_MAX_N, + &m, &n); + + if (!m || !n) + return -EINVAL; + + /* + * When N = 2M + 1 the valid D range [M+1, M] is empty; no duty + * cycle can satisfy M < D < (N - M). Reject before touching hw. + */ + if (n == 2 * m + 1) + return -EINVAL; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_write(gp->regmap, GP_MND_MDIV_REG, m); + if (ret) + goto err_unprepare; + + /* N divider holds the 1's complement of (N - M), N_WIDTH bits wide */ + n_val = ~(n - m) & GP_MND_MAX_N; + ret = regmap_write(gp->regmap, GP_MND_NDIV_REG, n_val); + if (ret) + goto err_unprepare; + + /* Program the closest-to-50% duty cycle. */ + d_val = n / 2; + ret = regmap_write(gp->regmap, GP_MND_DUTY_REG, d_val); + if (ret) + goto err_unprepare; + + gp->m_val = m; + gp->n_val = n; + +err_unprepare: + clk_disable_unprepare(gp->pdm_ahb_clk); + + return ret; +} + +static unsigned long gp_mnd_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int m_val, n_val; + int ret; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return 0; + + ret = regmap_read(gp->regmap, GP_MND_MDIV_REG, &m_val); + if (ret) + goto out_unprepare; + + m_val &= GP_MND_MAX_M; + + ret = regmap_read(gp->regmap, GP_MND_NDIV_REG, &n_val); + if (ret) + goto out_unprepare; + + /* Reverse the 1's complement encoding: N = ~NDIV_REG + M */ + n_val = (~n_val & GP_MND_MAX_N) + m_val; + +out_unprepare: + clk_disable_unprepare(gp->pdm_ahb_clk); + + if (ret) + return 0; + + if (!n_val) + return 0; + + gp->m_val = m_val; + gp->n_val = n_val; + + return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * m_val, n_val); +} + +static int gp_mnd_clk_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int d_val; + int ret; + + if (!gp->n_val) { + duty->num = 1; + duty->den = 2; + return 0; + } + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_read(gp->regmap, GP_MND_DUTY_REG, &d_val); + + clk_disable_unprepare(gp->pdm_ahb_clk); + + if (ret) + return ret; + + duty->num = d_val; + duty->den = gp->n_val; + + return 0; +} + +static int gp_mnd_clk_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_gp_mnd *gp = to_clk_gp_mnd(hw); + unsigned int d_val; + int ret; + + if (!gp->n_val || !gp->m_val) + return -EINVAL; + + /* D = (1 - duty) * N, giving the low-phase count */ + d_val = DIV_ROUND_UP((u64)(duty->den - duty->num) * gp->n_val, duty->den); + + /* Hardware constraint: M < D < (N - M) */ + if (d_val <= gp->m_val || d_val >= (gp->n_val - gp->m_val)) + return -EINVAL; + + ret = clk_prepare_enable(gp->pdm_ahb_clk); + if (ret) + return ret; + + ret = regmap_write(gp->regmap, GP_MND_DUTY_REG, d_val); + + clk_disable_unprepare(gp->pdm_ahb_clk); + + return ret; +} + +static const struct clk_ops clk_gp_mnd_ops = { + .determine_rate = gp_mnd_clk_determine_rate, + .set_rate = gp_mnd_clk_set_rate, + .recalc_rate = gp_mnd_clk_recalc_rate, + .get_duty_cycle = gp_mnd_clk_get_duty_cycle, + .set_duty_cycle = gp_mnd_clk_set_duty_cycle, +}; + +static const struct regmap_config gp_mnd_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, +}; + +static int clk_gp_mnd_probe(struct platform_device *pdev) +{ + struct clk_parent_data parent_data = { .index = 0 }; + struct clk_init_data init = { + .ops = &clk_gp_mnd_ops, + .parent_data = &parent_data, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }; + struct device *dev = &pdev->dev; + struct clk_gp_mnd *gp; + struct clk *clk; + struct pinctrl *pin; + struct pinctrl_state *pin_default_state; + void __iomem *base; + int ret; + + gp = devm_kzalloc(dev, sizeof(*gp), GFP_KERNEL); + if (!gp) + return -ENOMEM; + + gp->pdm_ahb_clk = devm_clk_get(dev, "ahb_clk"); + if (IS_ERR(gp->pdm_ahb_clk)) + return dev_err_probe(dev, PTR_ERR(gp->pdm_ahb_clk), + "failed to get ahb_clk\n"); + + clk = devm_clk_get(dev, "pdm_clk"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + /* Set default rate if not already configured */ + if (!clk_get_rate(clk)) { + ret = clk_set_rate(clk, 19200000); + if (ret) + dev_warn(dev, "failed to set default pdm_clk rate\n"); + } + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "failed to map PDM registers\n"); + + gp->regmap = devm_regmap_init_mmio(dev, base, &gp_mnd_regmap_config); + if (IS_ERR(gp->regmap)) + return dev_err_probe(dev, PTR_ERR(gp->regmap), + "failed to init regmap\n"); + + ret = of_property_read_string_index(dev->of_node, + "clock-output-names", 0, + &init.name); + if (ret) + return dev_err_probe(dev, ret, "missing clock-output-names\n"); + + gp->hw.init = &init; + + pin = devm_pinctrl_get(dev); + if (IS_ERR(pin)) + return dev_err_probe(dev, PTR_ERR(pin), "missing pinctrl device\n"); + + pin_default_state = pinctrl_lookup_state(pin, "active"); + if (IS_ERR(pin_default_state)) + return dev_err_probe(dev, PTR_ERR(pin_default_state), + "missing pinctrl default state\n"); + + ret = pinctrl_select_state(pin, pin_default_state); + if (ret) + return dev_err_probe(dev, ret, + "failed to select pinctrl default state\n"); + + ret = devm_clk_hw_register(dev, &gp->hw); + if (ret) + return dev_err_probe(dev, ret, + "failed to register gp_mnd clock\n"); + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &gp->hw); +} + +static const struct of_device_id clk_gp_mnd_match_table[] = { + { .compatible = "qcom,clk-gp-mnd" }, + { } +}; +MODULE_DEVICE_TABLE(of, clk_gp_mnd_match_table); + +static struct platform_driver clk_gp_mnd_driver = { + .probe = clk_gp_mnd_probe, + .driver = { + .name = "qcom-clk-gp-mnd", + .of_match_table = clk_gp_mnd_match_table, + }, +}; +module_platform_driver(clk_gp_mnd_driver); + +MODULE_DESCRIPTION("Qualcomm PDM GP_MND clock divider driver"); +MODULE_LICENSE("GPL"); From 1c082dbc458e68613ea8954f135d3644df2cd153 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 4 Jun 2026 10:33:28 +0530 Subject: [PATCH 0642/1133] PENDING: dt-bindings: ptp: Add support for Qualcomm TSCSS module Qualcomm TSCSS is a time synchronization subsystem composed of two main blocks: the Time Stamp Counter (TSC) and the Event Timestamp Unit (ETU). The TSC block is a timestamp generator that maintains a running counter used for system timekeeping. The ETU block captures timestamps for external events using one of the available timestamp sources. Signed-off-by: Imran Shaik --- .../devicetree/bindings/ptp/qcom,tsc.yaml | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 Documentation/devicetree/bindings/ptp/qcom,tsc.yaml diff --git a/Documentation/devicetree/bindings/ptp/qcom,tsc.yaml b/Documentation/devicetree/bindings/ptp/qcom,tsc.yaml new file mode 100644 index 0000000000000..092e267e29da4 --- /dev/null +++ b/Documentation/devicetree/bindings/ptp/qcom,tsc.yaml @@ -0,0 +1,104 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/ptp/qcom,tsc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Timestamp Counter Subsystem (TSCSS) + +maintainers: + - Imran Shaik + - Taniya Das + +description: + Qualcomm TSCSS is a time synchronization subsystem composed of two main + blocks - the Time Stamp Counter (TSC) and the Event Timestamp Unit (ETU). + + The TSC block is a timestamp generator that maintains a running counter used + for system timekeeping. The ETU block captures timestamps for external events + using one of the available timestamp sources. + +properties: + compatible: + enum: + - qcom,tsc + + reg: + maxItems: 2 + + reg-names: + items: + - const: tsc + - const: etu + + clocks: + items: + - description: TSC AHB clock + - description: TSC cntr clock + - description: TSC ETU clock + + clock-names: + items: + - const: cfg_ahb + - const: cntr + - const: etu + + interrupts: + maxItems: 1 + + interrupt-names: + items: + - const: etu_summary_irq + + qcom,tsc-nsec-update: + description: + Indicates the TSC counters have values in nanoseconds, rather than + in secs and nanoseconds. + type: boolean + + qcom,etu-slice: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of ETU slice numbers corresponding to the ETU sel. + In case this property is not defined the sel number will be + considered as the slice number for ETU offset calculation. + + qcom,etu-event-sel: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of ETU event sel numbers for the corresponding ETU slice + numbers. + + qcom,etu-event-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: + ETU event sel names for the corresponding event sel numbers. + +required: + - compatible + - reg + - clocks + - clock-names + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + #include + tsc: tsc@1c80000 { + compatible = "qcom,tsc"; + reg = <0x01c80000 0x2000>, + <0x01ca0000 0x20000>; + reg-names = "tsc", "etu"; + clocks = <&tscss_ahb_clock>, <&tscss_cntr_clock>, + <&tscss_cntr_clock>; + clock-names = "cfg_ahb", "cntr", "etu"; + interrupts = ; + interrupt-names = "etu_summary_irq"; + qcom,etu-slice = <10 11>; + qcom,etu-event-sel = <10 11>; + qcom,etu-event-names = "gps_pps", "tod_pps"; + qcom,tsc-nsec-update; + }; From 3aac875d0b29eb61e46fc3a8ab14fe9b2a8a32ab Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Tue, 31 Mar 2026 07:04:51 +0530 Subject: [PATCH 0643/1133] PENDING: ptp: Add support for Qualcomm TSCSS hardware Add support for the Qualcomm TSCSS hardware, that is a time synchronization subsystem composed of two main blocks: the Time Stamp Counter (TSC) and the Event Timestamp Unit (ETU). Signed-off-by: Imran Shaik --- drivers/ptp/Kconfig | 9 + drivers/ptp/Makefile | 1 + drivers/ptp/ptp_qcom_tsc.c | 842 +++++++++++++++++++++++++++++++++++++ 3 files changed, 852 insertions(+) create mode 100644 drivers/ptp/ptp_qcom_tsc.c diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index feb50f8cc406a..d7878fe80334a 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -264,4 +264,13 @@ config PTP_NETC_V4_TIMER synchronization. It also supports periodic output signal (e.g. PPS) and external trigger timestamping. +config PTP_QCOM_CLOCK_TSC + tristate "Qualcomm TSC as PTP clock" + depends on COMMON_CLK && PTP_1588_CLOCK + help + This driver adds support for using the Qualcomm Timestamp Counter (TSC) + as a PTP clock the requires for time stamping of PTP packets. + It also registers interrupts for Event Timestamp Unit (ETU) and updates + the TSC timestamps to PTP clock event. + endmenu diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile index bdc47e284f14e..6789b2a517b1d 100644 --- a/drivers/ptp/Makefile +++ b/drivers/ptp/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_PTP_1588_CLOCK_OCP) += ptp_ocp.o obj-$(CONFIG_PTP_DFL_TOD) += ptp_dfl_tod.o obj-$(CONFIG_PTP_S390) += ptp_s390.o obj-$(CONFIG_PTP_NETC_V4_TIMER) += ptp_netc.o +obj-$(CONFIG_PTP_QCOM_CLOCK_TSC) += ptp_qcom_tsc.o diff --git a/drivers/ptp/ptp_qcom_tsc.c b/drivers/ptp/ptp_qcom_tsc.c new file mode 100644 index 0000000000000..4df38665a56e6 --- /dev/null +++ b/drivers/ptp/ptp_qcom_tsc.c @@ -0,0 +1,842 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * QCOM TSC PTP : Linux driver for Time Stamp Counter Hardware. + * + */ + +#define pr_fmt(fmt) "qcom_tsc: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register offset definitions */ +#define TSCSS_TSC_CONTROL_CNTCR 0x0 +#define TSCSS_TSC_CONTROL_CNTCV_LO 0x8 +#define TSCSS_TSC_CONTROL_CNTCV_HI 0xC +#define TSCSS_TSC_CONTROL_CNTCV_FRAC 0x10 +#define TSCSS_TSC_SLEEP_INCR_VAL_LO 0x24 +#define TSCSS_TSC_SLEEP_INCR_VAL_HI 0x28 +#define TSCSS_TSC_DRIFT_CORRECT_INCR_VAL 0x2C +#define TSCSS_TSC_DRIFT_CORRECT_DURATION 0x30 +#define TSCSS_TSC_DRIFT_CORRECT_CMD 0x34 +#define TSCSS_TSC_ROLLOVER_VAL 0x3C +#define TSCSS_TSC_SPARE 0x40 +#define TSCSS_TSC_OFFSET_LO 0x50 +#define TSCSS_TSC_OFFSET_HI 0x54 +#define TSCSS_TSC_FUSA_CFG_STAT 0xF54 +#define TSCSS_TSC_READ_CNTCV_LO 0x1000 +#define TSCSS_TSC_READ_CNTCV_HI 0x1004 +#define TSCSS_TSC_HW_PRELOAD_VAL_LO 0x0060 +#define TSCSS_TSC_HW_PRELOAD_VAL_HI 0x0064 + +#define TSCSS_TSC_SLICE_ETU_CFG 0x0 +#define TSCSS_TSC_SLICE_ETU_STATUS 0x4 +#define TSCSS_ETU_SLICE_TSC_TS_LO 0x8 +#define TSCSS_ETU_SLICE_TSC_TS_HI 0xC +#define TSCSS_ETU_SLICE_TS_EVENT_TYPE 0x10 +#define TSCSS_ETU_SLICE_GCTR_TS_LO 0x20 +#define TSCSS_ETU_SLICE_GCTR_TS_HI 0x24 +#define TSCSS_ETU_SLICE_FIFO_CLR 0x30 +#define TSCSS_ETU_SLICE_SW_TRIG_CFG 0x34 +#define TSCSS_ETU_SLICE_TIMER_TRIG_PERIOD 0x38 +#define MAX_ETU_SLICE 16 + +#define DRIFT_CORRECT_MAX_PERIOD 0x1FFFF +#define DRIFT_CORRECT_MAX_RES 0x7FFFC0 + +#define TSC_PRELOAD_POLLING_DELAY_MS 100 +#define NSEC_SHFT 32 +#define NSEC_MASK GENMASK_ULL(31, 0) +#define NSEC 1000000000ULL +#define XO_MHZ 19200000 +#define TSCSS_TSC_ETU_SLICE_BASE(reg_base, num, offset) \ + (reg_base + num * 0x1000 + offset) + +struct qcom_etu_slice { + char name[10]; + struct ptp_clock *ptp_clock; + void __iomem *etu_baseaddr; + u64 etu_tsc_timestamp; + u64 last_sec; + u64 global_qtimer; + int extts_enable; + int extts_irq; + int extts_index; + int extts_event_sel; + int extts_slice_num; + int extts_event_type; + u32 etu_tsc_sec; + u32 etu_tsc_nsec; + u32 etu_gctr_sec; + u32 etu_gctr_nsec; + bool extts_present; +}; + +struct qcom_ptp_tsc { + struct device *dev; + void __iomem *baseaddr; + void __iomem *etu_baseaddr; + struct clk *tsc_cfg_ahb_clk; + struct clk *tsc_cntr_clk; + struct clk *tsc_etu_clk; + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_clock_info; + struct qcom_etu_slice etu_slice[MAX_ETU_SLICE]; + int pps_enable; + int total_etu_cnt; + bool tsc_nsec_update; + bool tsc_hw_preload; + spinlock_t reg_lock; + struct delayed_work tsc_preload_poll_work; + u32 configured_slice_mask; +}; + +static void tsc_preload_poll(struct work_struct *work) +{ + struct qcom_ptp_tsc *timer = container_of(work, struct qcom_ptp_tsc, + tsc_preload_poll_work.work); + u32 regval; + + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + /* Check for the HW_PRELOAD_STATUS and disable HW_PRELOAD */ + if (!(regval & BIT(14))) { + regval &= ~BIT(2); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + pr_info("TSC CNTCR: 0x%x HW_PRELOAD is disabled\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR)); + return; + } + + pr_debug("TSC CNTCR: 0x%x HW_PRELOAD_STATUS is not cleared\n", regval); + mod_delayed_work(system_highpri_wq, &timer->tsc_preload_poll_work, + msecs_to_jiffies(TSC_PRELOAD_POLLING_DELAY_MS)); +} + +static int qcom_ptp_tsc_is_enabled(void __iomem *addr) +{ + return readl_relaxed(addr + TSCSS_TSC_CONTROL_CNTCR) & BIT(0); +} + +static void qcom_tod_read(struct qcom_ptp_tsc *timer, struct timespec64 *ts) +{ + u64 temp, final; + u32 sec, nsec; + + if (!qcom_ptp_tsc_is_enabled(timer->baseaddr)) { + pr_debug("TSC is not enabled\n"); + return; + } + + sec = readl_relaxed(timer->baseaddr + TSCSS_TSC_READ_CNTCV_HI); + nsec = readl_relaxed(timer->baseaddr + TSCSS_TSC_READ_CNTCV_LO); + + pr_debug("CNTR_HI: 0x%x, sec %u\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI), sec); + pr_debug("CNTR_LO: 0x%x nsec %u\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO), nsec); + + if (timer->tsc_nsec_update) { + temp = sec; + final = (temp << NSEC_SHFT) | nsec; + sec = div_u64_rem(final, NSEC, &nsec); + pr_debug("tsc_nsec_update: %d, sec %u, nsec %u\n", + timer->tsc_nsec_update, sec, nsec); + } + + ts->tv_sec = sec; + ts->tv_nsec = nsec; +} + +static void qcom_ptp_enable_tsc_hw_preload(struct qcom_ptp_tsc *timer, struct timespec64 ts) +{ + u32 regval; + int timeout = 500; + + /* Enable HW_PRELOAD */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + regval |= BIT(2); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + /* Program PRELOAD registers */ + writel_relaxed(ts.tv_sec, timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_HI); + writel_relaxed(ts.tv_nsec, timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_LO); + + pr_debug("HW_PRELOAD_VAL_HI: 0x%x\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_HI)); + pr_debug("HW_PRELOAD_VAL_LO: 0x%x\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_HW_PRELOAD_VAL_LO)); + + /* Check for the HW_PRELOAD_STATUS and start poll thread */ + while (timeout-- > 0) { + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + if (regval & BIT(14)) { + pr_debug("TSC CNTR: 0x%x HW_PRELOAD is enabled\n", regval); + mod_delayed_work(system_highpri_wq, &timer->tsc_preload_poll_work, + msecs_to_jiffies(TSC_PRELOAD_POLLING_DELAY_MS)); + return; + } + udelay(1); + } + + pr_warn("TSC CNTR: 0x%x HW_PRELOAD enable failed\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR)); +} + +static int qcom_ptp_update_tsc_cntr(struct qcom_ptp_tsc *timer, + struct timespec64 offset) +{ + u64 timestamp = 0; + u32 regval; + + /* Update to 1ns resolution */ + if (timer->tsc_nsec_update) { + timestamp = offset.tv_sec * NSEC + offset.tv_nsec; + writel_relaxed((timestamp >> NSEC_SHFT), + timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI); + writel_relaxed(timestamp & NSEC_MASK, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO); + } else { + writel_relaxed(offset.tv_sec, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI); + writel_relaxed(offset.tv_nsec, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO); + } + + pr_debug("Timestamp %llu: sec: %lld, nsec: %ld\n", timestamp, + offset.tv_sec, offset.tv_nsec); + + pr_debug("CNTR_HI: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI)); + pr_debug("CNTR_LO: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO)); + + /* Enable the counter */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + regval |= BIT(0); + + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + return 0; +} + +static void qcom_ptp_update_tsc_offset(struct qcom_ptp_tsc *timer, + struct timespec64 offset) +{ + struct timespec64 tod; + u32 regval; + + if (timer->tsc_nsec_update) { + /* Read TOD and add delta */ + qcom_tod_read(timer, &tod); + tod = timespec64_add(tod, offset); + + pr_debug("%s disable the counter and re-init with tod+delta\n", __func__); + /* Disable the counter */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + regval &= ~BIT(0); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + /* Re-initialize the counter with updated time */ + qcom_ptp_update_tsc_cntr(timer, tod); + } else { + writel_relaxed(offset.tv_nsec, timer->baseaddr + TSCSS_TSC_OFFSET_LO); + writel_relaxed(offset.tv_sec, timer->baseaddr + TSCSS_TSC_OFFSET_HI); + + pr_debug("OFFSET_HI: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_OFFSET_HI)); + pr_debug("OFFSET_LO: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_OFFSET_LO)); + } + + pr_debug("CNTCV_HI: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_HI)); + pr_debug("CNTCV_LO: 0x%x\n", readl_relaxed(timer->baseaddr + TSCSS_TSC_CONTROL_CNTCV_LO)); +} + +static int qcom_ptp_normal_drift_correction(struct qcom_ptp_tsc *timer, long delta) +{ + u64 regval = 0, period, subperiod = 4, res = 64, incval = 0, multiple, total_cycles; + bool is_jump; + + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD); + if (regval & BIT(1)) { + pr_debug("Previous drift correction is still in progress...\n"); + return -EINVAL; + } + + regval = 0; + + if (delta == 0) + return 0; + + if (delta < 0) { + /* Swallow the counter */ + delta = -delta; + regval &= ~BIT(31); + is_jump = false; + + if (delta > DRIFT_CORRECT_MAX_RES) { + period = DRIFT_CORRECT_MAX_PERIOD; + pr_debug("Delta(%ldns) > 8.3ms, program max swallow resolution\n", delta); + } else { + period = div_u64(delta, res); + } + } else { + /* Jump the counter */ + regval |= BIT(31); + is_jump = true; + + total_cycles = delta / res; + multiple = total_cycles / DRIFT_CORRECT_MAX_RES; + pr_debug("total_cycles = %lld multiple = %lld\n", total_cycles, multiple); + if (multiple == 0) { + if (delta < res) { + period = 1; + incval = res + delta; + } else { + period = div_u64(delta, res); + incval = res * 2; + } + } else { + pr_debug("Delta(%ldns) > 8.3ms, do nothing...\n", delta); + return 0; + } + } + + regval |= subperiod; + regval |= (period << 12); + + pr_debug("delta:%ld period:%lld subperiod:%lld is_jump:%d regval:0x%llx\n", + delta, period, subperiod, is_jump, regval); + + /* Update jump/swallow, period, subperiod */ + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_DURATION); + + /* Update the INCR VAL */ + writel_relaxed(incval, timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_INCR_VAL); + + /* Trigger the drift correction */ + regval = readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD); + regval |= BIT(0); + writel_relaxed(regval, timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD); + + readl_poll_timeout(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD, + regval, !(regval & BIT(1)), 5, 500); + + pr_debug("duration = 0x%x incr_val = 0x%x cmd = 0x%x\n", + readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_DURATION), + readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_INCR_VAL), + readl_relaxed(timer->baseaddr + TSCSS_TSC_DRIFT_CORRECT_CMD)); + + return 0; +} + +/* + * PTP clock operations + */ +static int qcom_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) +{ + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + + return qcom_ptp_normal_drift_correction(timer, scaled_ppm_to_ppb(scaled_ppm)); +} + +static int qcom_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + unsigned long flags; + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + struct timespec64 offset; + + spin_lock_irqsave(&timer->reg_lock, flags); + + offset = ns_to_timespec64(delta); + pr_debug("sec: %lld, nsec: %ld\n", offset.tv_sec, offset.tv_nsec); + + qcom_ptp_update_tsc_offset(timer, offset); + spin_unlock_irqrestore(&timer->reg_lock, flags); + + return 0; +} + +static int qcom_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) +{ + unsigned long flags; + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + + spin_lock_irqsave(&timer->reg_lock, flags); + qcom_tod_read(timer, ts); + spin_unlock_irqrestore(&timer->reg_lock, flags); + return 0; +} + +/** + * qcom_ptp_settime - Set the current time on the hardware clock + * @ptp: ptp clock structure + * @ts: timespec64 containing the new time for the cycle counter + */ +static int qcom_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) +{ + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, ptp_clock_info); + struct timespec64 delta, tod; + struct timespec64 offset; + unsigned long flags; + int ret; + + spin_lock_irqsave(&timer->reg_lock, flags); + + pr_debug("TS.sec %lld TS.tv_nsec %ld\n", ts->tv_sec, ts->tv_nsec); + + if (!qcom_ptp_tsc_is_enabled(timer->baseaddr)) { + /* Update the Counter */ + offset.tv_sec = ts->tv_sec; + offset.tv_nsec = ts->tv_nsec; + + ret = qcom_ptp_update_tsc_cntr(timer, offset); + + spin_unlock_irqrestore(&timer->reg_lock, flags); + return ret; + } + + /* Get the current timer value */ + qcom_tod_read(timer, &tod); + + /* Subtract the current reported time from our desired time */ + delta = timespec64_sub((struct timespec64)*ts, tod); + + pr_debug("Delta.sec %lld delta.tv_nsec %ld\n", delta.tv_sec, delta.tv_nsec); + + /* Update the Counter */ + qcom_ptp_update_tsc_offset(timer, delta); + + spin_unlock_irqrestore(&timer->reg_lock, flags); + return 0; +} + +static void qcom_etu_event_handler(struct qcom_etu_slice *etu, struct qcom_ptp_tsc *timer) +{ + struct ptp_clock_event extts_event; + u64 ts, temp; + u32 regval; + + etu->etu_tsc_sec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_TSC_TS_HI)); + + etu->etu_tsc_nsec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_TSC_TS_LO)); + + if (!timer->tsc_nsec_update) { + ts = etu->etu_tsc_sec * NSEC + etu->etu_tsc_nsec; + } else { + temp = etu->etu_tsc_sec; + ts = (temp << NSEC_SHFT) | etu->etu_tsc_nsec; + } + + if (ts != etu->etu_tsc_timestamp) { + extts_event.type = PTP_CLOCK_EXTTS; + extts_event.index = etu->extts_index; + extts_event.timestamp = ts; + + pr_debug("type:%d index:%d timestamp:%llu\n", extts_event.type, + extts_event.index, extts_event.timestamp); + + ptp_clock_event(etu->ptp_clock, &extts_event); + } + etu->etu_tsc_timestamp = ts; + + pr_debug("etu_tsc_sec:%u etu_tsc_nsec:%u etu_tsc_timestamp:%llu\n", + etu->etu_tsc_sec, etu->etu_tsc_nsec, etu->etu_tsc_timestamp); + + etu->etu_gctr_sec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_GCTR_TS_HI)); + + etu->etu_gctr_nsec = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_GCTR_TS_LO)); + + etu->extts_event_type = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_TS_EVENT_TYPE)); + + /* Concatenate GCTR_TS_HI(31:0) & GCTR_TS_LO(31:8) and divide with 19.2MHz */ + etu->global_qtimer = (((u64)etu->etu_gctr_sec << 24) | + (etu->etu_gctr_nsec >> 8)) / XO_MHZ; + + pr_debug("etu_gctr_sec:%u etu_gctr_nsec:%u global_qtimer:%llx extts_event_type %d\n", + etu->etu_gctr_sec, etu->etu_gctr_nsec, + etu->global_qtimer, etu->extts_event_type); + + regval = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_TSC_SLICE_ETU_CFG)); + regval &= ~BIT(17); + regval &= ~BIT(16); + + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_TSC_SLICE_ETU_CFG)); + + /* FIFO CLR */ + writel_relaxed(0x7, TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_ETU_SLICE_FIFO_CLR)); + + /* Enable GCTR_TS_EN & TSCTR_TS_EN*/ + regval |= BIT(16) | BIT(17); + + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + etu->extts_slice_num, TSCSS_TSC_SLICE_ETU_CFG)); +} + +static irqreturn_t qcom_etu_summary_irq_handler(int irq, void *data) +{ + struct qcom_etu_slice *etu; + struct qcom_ptp_tsc *timer; + unsigned long mask; + u32 status; + int slice; + + timer = data; + mask = timer->configured_slice_mask; + + for_each_set_bit(slice, &mask, MAX_ETU_SLICE) { + etu = &timer->etu_slice[slice]; + status = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(etu->etu_baseaddr, + slice, TSCSS_TSC_SLICE_ETU_STATUS)); + + if (etu->extts_enable && (status & GENMASK(5, 0))) + qcom_etu_event_handler(etu, timer); + } + + return IRQ_HANDLED; +} + +static void qcom_tsc_configure_etu(struct qcom_ptp_tsc *timer, int slice) +{ + void __iomem *base = timer->etu_baseaddr; + u32 regval; + + /* Register for the IRQ */ + regval = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + regval |= (timer->etu_slice[slice].extts_event_sel << 4) & GENMASK(9, 4); + + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + + regval = readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + + /* Enable GCTR_TS_EN & TSCTR_TS_EN*/ + regval |= BIT(16) | BIT(17); + /* Interrupt MASK enable */ + regval |= BIT(31); + + /* Enable rising edge config */ + regval |= BIT(0); + writel_relaxed(regval, TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG)); + + /* Bitmask of configured slices.*/ + timer->configured_slice_mask |= BIT(slice); + + pr_debug("ETU_SLICE#%d: 0x%x\n", slice, + readl_relaxed(TSCSS_TSC_ETU_SLICE_BASE(base, slice, TSCSS_TSC_SLICE_ETU_CFG))); +} + +static int qcom_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + struct qcom_ptp_tsc *timer = container_of(ptp, struct qcom_ptp_tsc, + ptp_clock_info); + struct timespec64 ts; + int slice; + + pr_debug("Request Type %d\n", rq->type); + + switch (rq->type) { + case PTP_CLK_REQ_PPS: + timer->pps_enable = 1; + return 0; + case PTP_CLK_REQ_EXTTS: + pr_debug("PTP_CLK_REQ_EXTTS: Request external Index %d\n", rq->extts.index); + + if (rq->extts.index >= timer->total_etu_cnt) + return -EINVAL; + else if (!on) + return 0; + + for (slice = 0; slice < MAX_ETU_SLICE; slice++) { + if (!timer->etu_slice[slice].extts_present) + continue; + + if (rq->extts.index == timer->etu_slice[slice].extts_index) { + pr_debug("slice %d, index %d, etu_index %d\n", slice, + rq->extts.index, timer->etu_slice[slice].extts_index); + qcom_tsc_configure_etu(timer, + timer->etu_slice[slice].extts_slice_num); + timer->etu_slice[slice].extts_enable = true; + } + + } + return 0; + case PTP_CLK_REQ_PEROUT: + if (timer->tsc_hw_preload) { + if (!rq->perout.period.sec) { + /* Get the current timer value */ + qcom_tod_read(timer, &ts); + } else { + pr_debug("PTP_CLK_REQ_PEROUT: sec:%lld nsec:%u\n", + rq->perout.period.sec, rq->perout.period.nsec); + ts.tv_sec = rq->perout.period.sec; + ts.tv_nsec = rq->perout.period.nsec; + } + + /* Preload TSC with tv_sec += 1 and tv_nsec = 0 values */ + ts.tv_sec += 1; + ts.tv_nsec = 0; + qcom_ptp_enable_tsc_hw_preload(timer, ts); + } + return 0; + default: + break; + } + + return -EOPNOTSUPP; +} + +static struct ptp_clock_info qcom_ptp_clock_info = { + .owner = THIS_MODULE, + .name = "QCOM TSC", + .max_adj = 999999999, + /* The number of external time stamp channels. */ + .n_ext_ts = 1, + .n_per_out = 1, + .pps = 1, + .adjfine = qcom_ptp_adjfine, + .adjtime = qcom_ptp_adjtime, + .gettime64 = qcom_ptp_gettime, + .settime64 = qcom_ptp_settime, + .enable = qcom_ptp_enable, +}; + +/* module operations */ + +static void qcom_ptp_tsc_remove(struct platform_device *pdev) +{ + struct qcom_ptp_tsc *timer = platform_get_drvdata(pdev); + + if (timer->ptp_clock) { + ptp_clock_unregister(timer->ptp_clock); + timer->ptp_clock = NULL; + } + + if (timer->tsc_etu_clk) + clk_disable_unprepare(timer->tsc_etu_clk); + + if (timer->tsc_cntr_clk) + clk_disable_unprepare(timer->tsc_cntr_clk); + + if (timer->tsc_cfg_ahb_clk) + clk_disable_unprepare(timer->tsc_cfg_ahb_clk); + +} + +static int qcom_tsc_etu_get_data(struct platform_device *pdev, + struct qcom_ptp_tsc *timer) +{ + struct device *dev = &pdev->dev; + struct resource *r_mem; + struct pinctrl *pinctrl; + int ret, cnt, i, summary_irq; + + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!r_mem) { + dev_err(&pdev->dev, "No ETU resource defined\n"); + return 0; + } + + timer->etu_baseaddr = devm_ioremap_resource(&pdev->dev, r_mem); + if (IS_ERR(timer->etu_baseaddr)) + return PTR_ERR(timer->etu_baseaddr); + + summary_irq = platform_get_irq_byname(pdev, "etu_summary_irq"); + + if (summary_irq > 0) { + ret = devm_request_irq(dev, summary_irq, + qcom_etu_summary_irq_handler, IRQF_TRIGGER_HIGH, + "etu_summary_irq", timer); + if (ret) { + dev_err(&pdev->dev, "Request_summary_irq failed:%d: err:%d\n", + summary_irq, ret); + return ret; + } + } + + cnt = of_property_count_elems_of_size(dev->of_node, "qcom,etu-event-sel", + sizeof(u32)); + pr_debug("Number of event-sel %d\n", cnt); + + for (i = 0; i < cnt; i++) { + const char *name; + u32 sel, slice; + + ret = of_property_read_u32_index(dev->of_node, "qcom,etu-event-sel", i, &sel); + if (ret) + break; + + ret = of_property_read_u32_index(dev->of_node, "qcom,etu-slice", i, &slice); + if (ret) { + pr_debug("etu-slice property does not exist, configure using sel value\n"); + slice = sel; + } + + timer->etu_slice[slice].etu_baseaddr = timer->etu_baseaddr; + timer->etu_slice[slice].extts_index = i; + timer->etu_slice[slice].extts_event_sel = sel; + timer->etu_slice[slice].extts_slice_num = slice; + of_property_read_string_index(dev->of_node, + "qcom,etu-event-names", i, &name); + + strscpy(timer->etu_slice[slice].name, name, sizeof(timer->etu_slice[slice].name)); + + timer->etu_slice[slice].extts_irq = summary_irq; + + pr_debug("sel: %d, index: %d, slice-num:%d slice-name: %s, IRQ: %d\n", sel, + timer->etu_slice[slice].extts_index, slice, + timer->etu_slice[slice].name, timer->etu_slice[slice].extts_irq); + + timer->etu_slice[slice].extts_present = true; + timer->etu_slice[slice].ptp_clock = timer->ptp_clock; + } + + timer->total_etu_cnt = cnt; + timer->ptp_clock_info.n_ext_ts = cnt; + + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) + dev_info(&pdev->dev, "No default pinctrl found\n"); + + return 0; +} + +static int qcom_ptp_tsc_probe(struct platform_device *pdev) +{ + struct qcom_ptp_tsc *timer; + struct resource *r_mem; + u32 cntr_val; + int ret; + + timer = devm_kzalloc(&pdev->dev, sizeof(*timer), GFP_KERNEL); + if (!timer) + return -ENOMEM; + + timer->dev = &pdev->dev; + + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r_mem) { + dev_err(&pdev->dev, "no IO resource defined\n"); + return -ENXIO; + } + + timer->baseaddr = devm_ioremap_resource(&pdev->dev, r_mem); + if (IS_ERR(timer->baseaddr)) + return PTR_ERR(timer->baseaddr); + + spin_lock_init(&timer->reg_lock); + + timer->tsc_cfg_ahb_clk = devm_clk_get(&pdev->dev, "cfg_ahb"); + if (IS_ERR(timer->tsc_cfg_ahb_clk)) { + if (PTR_ERR(timer->tsc_cfg_ahb_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get CFG AHB clock\n"); + return PTR_ERR(timer->tsc_cfg_ahb_clk); + } + + timer->tsc_cntr_clk = devm_clk_get(&pdev->dev, "cntr"); + if (IS_ERR(timer->tsc_cntr_clk)) { + if (PTR_ERR(timer->tsc_cntr_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get Counter clock\n"); + return PTR_ERR(timer->tsc_cntr_clk); + } + + timer->tsc_etu_clk = devm_clk_get(&pdev->dev, "etu"); + if (IS_ERR(timer->tsc_etu_clk)) { + if (PTR_ERR(timer->tsc_etu_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get ETU clock\n"); + return PTR_ERR(timer->tsc_etu_clk); + } + + ret = clk_prepare_enable(timer->tsc_cfg_ahb_clk); + if (ret) { + pr_debug("Failed to enable AHB clock\n"); + return ret; + } + + ret = clk_prepare_enable(timer->tsc_cntr_clk); + if (ret) { + pr_debug("Failed to enable counter clock\n"); + return ret; + } + + ret = clk_prepare_enable(timer->tsc_etu_clk); + if (ret) { + pr_debug("Failed to enable etu clock\n"); + return ret; + } + + timer->tsc_nsec_update = of_property_read_bool(pdev->dev.of_node, + "qcom,tsc-nsec-update"); + + timer->tsc_hw_preload = of_property_read_bool(pdev->dev.of_node, + "qcom,tsc-hw-preload"); + + if (timer->tsc_hw_preload) + INIT_DEFERRABLE_WORK(&timer->tsc_preload_poll_work, tsc_preload_poll); + + timer->ptp_clock_info = qcom_ptp_clock_info; + + timer->ptp_clock = ptp_clock_register(&timer->ptp_clock_info, &pdev->dev); + if (IS_ERR(timer->ptp_clock)) { + ret = PTR_ERR(timer->ptp_clock); + dev_err(&pdev->dev, "Failed to register ptp clock\n"); + goto out; + } + + qcom_tsc_etu_get_data(pdev, timer); + + if (!timer->tsc_nsec_update) { + cntr_val = (timer->tsc_hw_preload ? 0x1D8 : 0x1CC); + writel_relaxed(0x3B9AC9FF, timer->baseaddr + TSCSS_TSC_ROLLOVER_VAL); + } else { + cntr_val = 0x18C; + } + + writel_relaxed(cntr_val, timer->baseaddr + TSCSS_TSC_CONTROL_CNTCR); + + pr_info("TSC CNTR 0x%x tsc-nsec-update %d tsc-hw-preload %d\n", + readl_relaxed(timer->baseaddr), timer->tsc_nsec_update, timer->tsc_hw_preload); + + platform_set_drvdata(pdev, timer); + + return 0; +out: + timer->ptp_clock = NULL; + return ret; +} + +static const struct of_device_id tsc_of_match[] = { + { .compatible = "qcom,tsc", }, + { /* end of table */ } +}; +MODULE_DEVICE_TABLE(of, tsc_of_match); + +static struct platform_driver qcom_ptp_tsc_driver = { + .probe = qcom_ptp_tsc_probe, + .remove = qcom_ptp_tsc_remove, + .driver = { + .name = "qcom_ptp_tsc", + .of_match_table = tsc_of_match, + }, +}; + +module_platform_driver(qcom_ptp_tsc_driver); + +MODULE_DESCRIPTION("PTP QCOM TSC driver"); +MODULE_LICENSE("GPL"); From 2e77318da6eca6fef1ee1d71c146b461ae5543db Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Sat, 27 Jun 2026 20:45:39 +0530 Subject: [PATCH 0644/1133] WORKAROUND: clk: qcom: gdsc: Conditionally disable GDSC if synced_poweroff flag is set USB, PCIE GDSCs require the GDSC to left ON in USB host mode and PCIE non-D3 cold usecases even during system suspend. To handle this use the GenPD's synced_poweroff flag which can be set by USB/PCIE drivers if they require the GDSC to be disabled before suspend. If the GDSC is required to be left ON, the USB/PCIE drivers can avoid setting this flag before suspend. Add support for custom gdsc disable callback that disables GDSC based on GenPD's synced_poweroff flag. Signed-off-by: Jagadeesh Kona Signed-off-by: Krishna Kurapati --- drivers/clk/qcom/gdsc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h index 2f9665b664e60..1acb5c97ccd96 100644 --- a/drivers/clk/qcom/gdsc.h +++ b/drivers/clk/qcom/gdsc.h @@ -94,6 +94,7 @@ int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *, void gdsc_unregister(struct gdsc_desc *desc); int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain); int gdsc_gx_disable(struct generic_pm_domain *domain); +#define gdsc_synced_poweroff_disable gdsc_gx_disable #else static inline int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *rcdev, From ea0d239a4ec31d563d144385b5762df7eedd96be Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Sat, 27 Jun 2026 20:47:20 +0530 Subject: [PATCH 0645/1133] WORKAROUND: clk: qcom: gcc: Use gdsc_synced_poweroff_disable for USB GDSC's Use gdsc_synced_poweroff_disable callback for USB GDSC's on qcs615 platforms so these GDSC's get disabled only when consumer drivers explicitly invoke dev_pm_genpd_synced_poweroff() API before suspend. Signed-off-by: Jagadeesh Kona Signed-off-by: Krishna Kurapati --- drivers/clk/qcom/gcc-qcs615.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/qcom/gcc-qcs615.c b/drivers/clk/qcom/gcc-qcs615.c index e096af7d82bf5..778536f966579 100644 --- a/drivers/clk/qcom/gcc-qcs615.c +++ b/drivers/clk/qcom/gcc-qcs615.c @@ -2674,6 +2674,7 @@ static struct gdsc usb20_sec_gdsc = { .clk_dis_wait_val = 0x2, .pd = { .name = "usb20_sec_gdsc", + .power_off = gdsc_synced_poweroff_disable, }, .pwrsts = PWRSTS_OFF_ON, }; @@ -2685,6 +2686,7 @@ static struct gdsc usb30_prim_gdsc = { .clk_dis_wait_val = 0x2, .pd = { .name = "usb30_prim_gdsc", + .power_off = gdsc_synced_poweroff_disable, }, .pwrsts = PWRSTS_OFF_ON, }; From 4def63accaa8b67e111aa9e73149bbe256d51ac4 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sat, 27 Jun 2026 20:48:23 +0530 Subject: [PATCH 0646/1133] WORKAROUND: usb: dwc3: qcom: Add support to keep GDSC On during host mode bus suspend On targets pre-sm8750, when DUT enters bus suspend in host mode, there is a xHCI crash seen on resume. During bus susend use case if the device is wakeup capable, the GDSC needs to be kept ON to retain memory and avoid SMMU faults. Set synced_poweroff flag to false to ensure GDSC is turned OFF during cable disconnect or non-bus suspend host mode scenario. Signed-off-by: Krishna Kurapati --- drivers/usb/dwc3/dwc3-qcom.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index ac68b4218b56b..7c095783a8d76 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "core.h" #include "glue.h" @@ -362,6 +363,8 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup) for (i = 0; i < qcom->num_ports; i++) qcom->ports[i].usb2_speed = dwc3_qcom_read_usb2_speed(qcom, i); dwc3_qcom_enable_interrupts(qcom); + } else { + dev_pm_genpd_synced_poweroff(qcom->dev); } qcom->is_suspended = true; From 77eb3d5a690978681b2e83bab97de32bf8043a3b Mon Sep 17 00:00:00 2001 From: Jagadeesh Pagadala Date: Wed, 3 Jun 2026 18:21:38 +0530 Subject: [PATCH 0647/1133] QCLINUX: arm64: configs: qcom.config: Enable CONFIG_SWIOTLB_DYNAMIC Enable CONFIG_SWIOTLB_DYNAMIC to reduce static SWIOTLB memory reservation by allowing the bounce buffer pool to grow dynamically based on runtime DMA requirements. Signed-off-by: Jagadeesh Pagadala --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 874a5a6f431d4..7278a517e074f 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -62,6 +62,7 @@ CONFIG_STM_SOURCE_FTRACE=m CONFIG_STM_SOURCE_HEARTBEAT=m CONFIG_SENSORS_AMC6821=y CONFIG_SENSORS_EMC2305=y +CONFIG_SWIOTLB_DYNAMIC=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y From 594dc45eb4c867bea5ed27c6c77c6446f7337b23 Mon Sep 17 00:00:00 2001 From: Shivam Rawat Date: Mon, 11 May 2026 13:58:26 +0530 Subject: [PATCH 0648/1133] QCLINUX: arm64: configs: Enable GPU virtualization Enable DRM VirtIO GPU configs to support GPU virtualization Signed-off-by: Shivam Rawat --- arch/arm64/configs/qcom.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 7278a517e074f..dba412e6a78fc 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -126,3 +126,7 @@ CONFIG_FTRACE=y CONFIG_QCOM_SCMI_GENERIC_EXT=y CONFIG_DEVFREQ_GOV_REMOTE=y CONFIG_SCMI_QCOM_MEMLAT_DEVFREQ=m + +# GPU Virtualization support +CONFIG_DRM_VIRTIO_GPU=m +CONFIG_DRM_VIRTIO_GPU_KMS=m From ebe0ca29989224b697cff5e8b6c2892e81838ffa Mon Sep 17 00:00:00 2001 From: Jagadeesh Pagadala Date: Tue, 9 Jun 2026 21:17:00 +0530 Subject: [PATCH 0649/1133] QCLINUX: arm64: configs: qcom.config: Enable LZ4 backend for zram Enable CONFIG_ZRAM_BACKEND_LZ4 to allow use of LZ4 compression for zram. LZ4 offers low latency and reduced CPU overhead, making it well-suited for embedded systems. Signed-off-by: Jagadeesh Pagadala --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index dba412e6a78fc..481be7e9cb1f2 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -83,6 +83,7 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m CONFIG_WATCHDOG_PRETIMEOUT_GOV=y CONFIG_WATCHDOG_SYSFS=y CONFIG_ZRAM=y +CONFIG_ZRAM_BACKEND_LZ4=y # Kubernetes support CONFIG_CFS_BANDWIDTH=y From 7d2a7be9137ac35e195e9828b32cde2348a4be13 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 11 Jun 2026 11:18:55 +0530 Subject: [PATCH 0650/1133] QCLINUX: arm64: configs: qcom: Set DRIVER_DEFERRED_PROBE_TIMEOUT to 60 Set the deferred probe timeout to 60 seconds in the Qualcomm config fragment.With the kernel default of 10s ,we are observing probe deferrals on Qualcomm platforms where supplier drivers (e.g. regulators, clocks) are probing late; 60s gives sufficient margin without waiting indefinitely. Signed-off-by: Anurag Pateriya --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 481be7e9cb1f2..5b8848e617f21 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -26,6 +26,7 @@ CONFIG_CPU_IDLE_THERMAL=y CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DRIVER_DEFERRED_PROBE_TIMEOUT=60 CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y CONFIG_FW_LOADER_COMPRESS=y From a1f2b7efbb8cb1ae92596797432acc9f537c5fda Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Thu, 11 Jun 2026 16:10:45 +0530 Subject: [PATCH 0651/1133] QCLINUX: kernel: debug.config: Additional debug configs Add configs for ATH11K/ATH12K debug/coredump/tracing, CMA debug, pstore/EFI vars, ftrace extensions (dynamic ftrace with args/call-ops/ direct-calls, hwlat/timerlat/sched tracers, snapshot), lockup detectors, lock debugging (spinlock, rwsems, list), DMABUF sysfs stats, WQ watchdog, PM debug, and various other debug instrumentation. These configs are already part of QLI.1.0. Adding them to QLI.2.0 and QLI mainline. Signed-off-by: Anurag Pateriya --- kernel/configs/debug.config | 48 ++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 07dfb0a31a92d..2ba799a24eb7b 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -125,31 +125,73 @@ CONFIG_ATH11K_COREDUMP=y CONFIG_ATH11K_DEBUG=y CONFIG_ATH11K_DEBUGFS=y CONFIG_ATH11K_TRACING=y +CONFIG_ATH12K_COREDUMP=y CONFIG_ATH12K_DEBUG=y CONFIG_ATH12K_DEBUGFS=y CONFIG_ATH12K_TRACING=y -CONFIG_ATH12K_COREDUMP=y CONFIG_CFG80211_DEBUGFS=y CONFIG_CMA_DEBUG=y +CONFIG_CMA_DEBUGFS=y +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE=16000 CONFIG_DEBUG_LIST=y CONFIG_DEBUG_PAGEALLOC=y +CONFIG_DEBUG_RWSEMS=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +CONFIG_DMABUF_SYSFS_STATS=y +CONFIG_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS=y +CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y CONFIG_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_EFI_VARS_PSTORE=y +CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y +CONFIG_FTRACE_MCOUNT_RECORD=y +CONFIG_FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY=y CONFIG_FTRACE_SYSCALLS=y +CONFIG_FUNCTION_ALIGNMENT=8 +CONFIG_FUNCTION_ALIGNMENT_8B=y CONFIG_FUNCTION_GRAPH_TRACER=y # CONFIG_FW_LOADER_DEBUG is not set +CONFIG_GENERIC_TRACER=y CONFIG_HARDLOCKUP_DETECTOR=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y +CONFIG_HWLAT_TRACER=y CONFIG_IRQSOFF_TRACER=y CONFIG_KPROBE_EVENTS=y +CONFIG_LOCALVERSION="" +CONFIG_LOCKUP_DETECTOR=y CONFIG_MAC80211_DEBUGFS=y CONFIG_NL80211_TESTMODE=y -CONFIG_PREEMPT_TRACER=y -CONFIG_PREEMPTIRQ_TRACEPOINTS=y +CONFIG_PARAVIRT_TIME_ACCOUNTING=y +CONFIG_PCIEAER_INJECT=y +CONFIG_PID_IN_CONTEXTIDR=y CONFIG_PM_ADVANCED_DEBUG=y CONFIG_PM_DEBUG=y CONFIG_PM_SLEEP_DEBUG=y +CONFIG_PREEMPT_TRACER=y +CONFIG_PREEMPTIRQ_TRACEPOINTS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_BLK=y +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 +CONFIG_PSTORE_PMSG=y +CONFIG_RCU_CPU_STALL_CPUTIME=y +CONFIG_REED_SOLOMON=y CONFIG_RELAY=y CONFIG_SCHED_TRACER=y CONFIG_STACK_TRACER=y +CONFIG_TEST_DYNAMIC_DEBUG=y +CONFIG_TIMERLAT_TRACER=y +CONFIG_TRACE_IRQFLAGS=y +CONFIG_TRACE_IRQFLAGS_NMI=y +CONFIG_TRACER_MAX_TRACE=y +CONFIG_TRACER_SNAPSHOT=y +CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y CONFIG_TRACEPOINTS=y CONFIG_TRACING=y CONFIG_UPROBE_EVENTS=y +CONFIG_WQ_CPU_INTENSIVE_REPORT=y +CONFIG_WQ_WATCHDOG=y From 23569f754fb1f962b0ad878c7af4827db3adfbab Mon Sep 17 00:00:00 2001 From: Hariprasad kelam Date: Wed, 17 Jun 2026 14:15:45 +0530 Subject: [PATCH 0652/1133] QCLINUX: qcom.config: Enable Intel IXGBE driver Enable the IXGBE and IXGBEVF drivers to support the Intel X550 T2 NIC on QLI boards with SR-IOV support. Signed-off-by: Hariprasad kelam --- arch/arm64/configs/qcom.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 5b8848e617f21..7d4654ad6c0ba 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -36,6 +36,8 @@ CONFIG_I2C_QCOM_GENI=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y CONFIG_INPUT_UINPUT=y +CONFIG_IXGBE=m +CONFIG_IXGBEVF=m CONFIG_KPROBES=y CONFIG_MACVLAN=y CONFIG_MACVTAP=y From 6cd343f07fcabf1be6a8ec59111d7ccbae7f7f31 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 23 Jun 2026 16:12:26 +0530 Subject: [PATCH 0653/1133] QCLINUX: prune.config: Enable the TI DP83867 PHY driver The Shikra EVK boards have an RGMII TI PHY connected to the dual EMACs of the SoC. Remove its config from prune.config to enable its driver. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/configs/prune.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index fd35e50601532..6f75cb6b2744a 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -93,7 +93,6 @@ # CONFIG_BCM54140_PHY is not set # CONFIG_MICROSEMI_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 From a8de0f20be45ec75710741aba75ff465d9358ae2 Mon Sep 17 00:00:00 2001 From: Ashay Jaiswal Date: Sat, 13 Jun 2026 18:21:35 +0530 Subject: [PATCH 0654/1133] QCLINUX: arm64: configs: qcom: Enable SCHED_CLASS_EXT (sched_ext) Enable the extensible scheduling class (SCX) which allows BPF-based scheduling policies. Also enable its cgroup dependencies: - CONFIG_SCHED_CLASS_EXT=y -- core sched_ext class BTF support (DEBUG_INFO_BTF, DEBUG_INFO_BTF_MODULES) is enabled which is required by SCHED_CLASS_EXT and also needed for BPF CO-RE and kernel module BTF. Signed-off-by: Ashay Jaiswal --- arch/arm64/configs/qcom.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 7d4654ad6c0ba..2ed89468aac8c 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -23,6 +23,9 @@ CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_CPU_IDLE_GOV_TEO=y CONFIG_CPU_IDLE_THERMAL=y # CONFIG_DEBUG_INFO_REDUCED is not set +CONFIG_DEBUG_INFO_BTF=y +CONFIG_DEBUG_INFO_BTF_MODULES=y +# CONFIG_MODULE_ALLOW_BTF_MISMATCH is not set CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y @@ -56,6 +59,7 @@ CONFIG_QCOM_QMI_COOLING=y CONFIG_QCOM_SPEL=m CONFIG_QCOM_TGU=m CONFIG_REMOTEPROC_THERMAL=y +CONFIG_SCHED_CLASS_EXT=y CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y CONFIG_STM_PROTO_BASIC=m From a8a23b94e09397f9d88a4d68e857541936282ef3 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Wed, 1 Jul 2026 18:03:24 +0530 Subject: [PATCH 0655/1133] QCLINUX: qcom.config: Enable DMA_CMA for DMA-BUF heap support Enable CONFIG_DMA_CMA as a dependency to allow the DMA-BUF heap configs (DMABUF_HEAPS, DMABUF_HEAPS_CMA, DMABUF_HEAPS_SYSTEM) to be selected in qcom.config. Signed-off-by: Bibek Kumar Patro --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 2ed89468aac8c..23a42184e2bbd 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -26,6 +26,7 @@ CONFIG_CPU_IDLE_THERMAL=y CONFIG_DEBUG_INFO_BTF=y CONFIG_DEBUG_INFO_BTF_MODULES=y # CONFIG_MODULE_ALLOW_BTF_MISMATCH is not set +CONFIG_DMA_CMA=y CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y From ecbfe8c0e15735caeab2894db1a7080260d6f907 Mon Sep 17 00:00:00 2001 From: Dipa Ramesh Mantre Date: Thu, 23 Jul 2026 09:45:49 +0530 Subject: [PATCH 0656/1133] QCLINUX: defconfig: Enable Qualcomm pmic BCL driver Enable Qualcomm pmic BCL driver config. Signed-off-by: Dipa Ramesh Mantre --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 23a42184e2bbd..77053c03a8f20 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -70,6 +70,7 @@ CONFIG_STM_SOURCE_FTRACE=m CONFIG_STM_SOURCE_HEARTBEAT=m CONFIG_SENSORS_AMC6821=y CONFIG_SENSORS_EMC2305=y +CONFIG_SENSORS_QCOM_SPMI_BCL=y CONFIG_SWIOTLB_DYNAMIC=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y From caaf3c03b7bcb9b32f51054279d54d51365fea44 Mon Sep 17 00:00:00 2001 From: Rajkumar Patel Date: Tue, 21 Jul 2026 12:15:43 +0530 Subject: [PATCH 0657/1133] QCLINUX: arm64: configs: qcom: Enable XDP sockets (AF_XDP) Enable CONFIG_XDP_SOCKETS to support AF_XDP zero-copy networking on Qualcomm platforms. AF_XDP provides a high-performance path for packet processing by allowing XDP programs to redirect frames directly to userspace via shared memory rings, bypassing the normal kernel network stack. Signed-off-by: Rajkumar Patel --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 77053c03a8f20..47d1e53c0c855 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -91,6 +91,7 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m CONFIG_WATCHDOG_PRETIMEOUT_GOV=y CONFIG_WATCHDOG_SYSFS=y +CONFIG_XDP_SOCKETS=y CONFIG_ZRAM=y CONFIG_ZRAM_BACKEND_LZ4=y From 5c501bb5a3c9309acb4cc16abf85b95f83b12bc5 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 29 Jul 2026 07:43:21 +0530 Subject: [PATCH 0658/1133] FROMLIST: arm64: defconfig: Enable PCIe hotplug support Enable CONFIG_HOTPLUG_PCI_PCIE to support native PCIe hotplug controllers on arm64 platforms. Link: https://lore.kernel.org/r/20260728-hotplug_pci-v1-1-d1f38cfb9122@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 77ed3f5b71540..5cb1909b22b4b 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -210,6 +210,7 @@ CONFIG_NFC_NXP_NCI_I2C=m CONFIG_NFC_S3FWRN5_I2C=m CONFIG_PCI=y CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=y CONFIG_PCIEAER=y CONFIG_PCI_IOV=y CONFIG_PCI_PASID=y From ce8d639cbff4898feab850c97e10ae4217bd1ed2 Mon Sep 17 00:00:00 2001 From: Linghui Wu Date: Fri, 31 Jul 2026 20:03:17 +0800 Subject: [PATCH 0659/1133] QCLINUX: debug: Enable ATH10K debug configs Enable ATH10K debug, debugfs, tracing, and devcoredump support in kernel/configs/debug.config. This complements the existing Qualcomm WLAN debug configs for ATH11K and ATH12K and enables ath10k firmware crash debugging. Signed-off-by: Linghui Wu --- kernel/configs/debug.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 2ba799a24eb7b..abc7c72678679 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -120,6 +120,9 @@ CONFIG_PREEMPT=y # # Qualcomm Debug Configs # +CONFIG_ATH10K_DEBUG=y +CONFIG_ATH10K_DEBUGFS=y +CONFIG_ATH10K_TRACING=y CONFIG_ATH11K_CFR=y CONFIG_ATH11K_COREDUMP=y CONFIG_ATH11K_DEBUG=y @@ -139,6 +142,7 @@ CONFIG_DEBUG_PAGEALLOC=y CONFIG_DEBUG_RWSEMS=y CONFIG_DEBUG_SPINLOCK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +CONFIG_DEV_COREDUMP=y CONFIG_DMABUF_SYSFS_STATS=y CONFIG_DYNAMIC_FTRACE_WITH_ARGS=y CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS=y From e52184371d1f85f532904ab32da8154b225691da Mon Sep 17 00:00:00 2001 From: Jagadeesh Pagadala Date: Thu, 6 Aug 2026 09:04:28 +0530 Subject: [PATCH 0660/1133] QCLINUX: arm64: configs: qcom: reduce SWIOTLB size to 2 MiB Set CONFIG_SWIOTLB_DEFAULT_SIZE_MB=2 to reduce the default SWIOTLB pool size from 64 MiB to 2 MiB. This lowers kernel reserved memory and increases available RAM for user space. Signed-off-by: Jagadeesh Pagadala --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 47d1e53c0c855..aa0cc121b89f0 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -71,6 +71,7 @@ CONFIG_STM_SOURCE_HEARTBEAT=m CONFIG_SENSORS_AMC6821=y CONFIG_SENSORS_EMC2305=y CONFIG_SENSORS_QCOM_SPMI_BCL=y +CONFIG_SWIOTLB_DEFAULT_SIZE_MB=2 CONFIG_SWIOTLB_DYNAMIC=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y From cbb66b2ce2fd3a0dd038e1e67641b79cb45a80a4 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Tue, 4 Aug 2026 15:30:38 +0530 Subject: [PATCH 0661/1133] QCLINUX: kernel: configs: debug: Disable KASLR for debug builds KASLR randomizes the kernel load address at boot to mitigate address leak exploits. While essential for production, it hinders debugging: breakpoints become unreliable, crash dump analysis is harder, and stack trace symbolication requires a fixed base address. Thus, disable CONFIG_RANDOMIZE_BASE in debug.config only. Signed-off-by: Komal Bajaj --- kernel/configs/debug.config | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index abc7c72678679..ec8e66511d319 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -182,6 +182,7 @@ CONFIG_PSTORE_COMPRESS=y CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 CONFIG_PSTORE_PMSG=y +# CONFIG_RANDOMIZE_BASE is not set CONFIG_RCU_CPU_STALL_CPUTIME=y CONFIG_REED_SOLOMON=y CONFIG_RELAY=y From 3e4d891b5edccbb3c90c0e77c2772a68b6186d53 Mon Sep 17 00:00:00 2001 From: Ankit Sharma Date: Mon, 10 Aug 2026 17:43:04 +0530 Subject: [PATCH 0662/1133] QCLINUX: qcom.config: Enable FUNCTION_TRACER CONFIG_FUNCTION_TRACER is useful for custom schedulers, so enable it in default build. Signed-off-by: Ankit Sharma --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index aa0cc121b89f0..99f05d2a8c9bc 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -133,6 +133,7 @@ CONFIG_SCSI_SMARTPQI=m # Support performance profiling CONFIG_FTRACE=y +CONFIG_FUNCTION_TRACER=y # QCOM SCMI memlat bus scaling CONFIG_QCOM_SCMI_GENERIC_EXT=y From 30b825e734d29d3f0aa730a056337d24ddac86a2 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 11 Aug 2026 13:39:58 +0800 Subject: [PATCH 0663/1133] QCLINUX: qcom.config: enable STM OST protocol Update the config to enable the STM OST protocol for transferring trace data. Signed-off-by: Jie Gan --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 99f05d2a8c9bc..20bc4fd5101de 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -64,6 +64,7 @@ CONFIG_SCHED_CLASS_EXT=y CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y CONFIG_STM_PROTO_BASIC=m +CONFIG_STM_PROTO_OST=m CONFIG_STM_PROTO_SYS_T=m CONFIG_STM_SOURCE_CONSOLE=m CONFIG_STM_SOURCE_FTRACE=m From 9dcc9f02a4bce43791f81f3668e628875cf195be Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Mon, 3 Aug 2026 17:43:00 +0530 Subject: [PATCH 0664/1133] PENDING: arm64: defconfig: Enable OV08X40 camera sensor driver Add CONFIG_VIDEO_OV08X40=m to enable the OmniVision OV08X40 CSIPHY4 in four lane mode. Signed-off-by: Nihal Kumar Gupta --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 5cb1909b22b4b..5a42aae3afe9b 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -970,6 +970,7 @@ CONFIG_VIDEO_TI_J721E_CSI2RX=m CONFIG_VIDEO_HANTRO=m CONFIG_VIDEO_IMX219=m CONFIG_VIDEO_IMX412=m +CONFIG_VIDEO_OV08X40=m CONFIG_VIDEO_OV5640=m CONFIG_VIDEO_OV5645=m CONFIG_VIDEO_S5KJN1=m From c6705b62f4ed85a200c6a19730aae5fa4cd24f6f Mon Sep 17 00:00:00 2001 From: Kamal Wadhwa Date: Fri, 21 Aug 2026 00:22:32 +0530 Subject: [PATCH 0665/1133] FROMLIST: arm64: defconfig: Enable Qualcomm PMIC GLINK RTC driver On Glymur, the PMIC RTC alarm IRQ cannot be delivered over SPMI to rtc-pm8xxx, because that permission is routed to the charger firmware running on a remote subsystem instead. The rtc-glink driver requests RTC time/alarm access over the existing PMIC GLINK channel to work around this. Enable CONFIG_RTC_DRV_QCOM_GLINK as a module so the reference arm64 defconfig covers this driver on Glymur. Depends-on: series ("rtc: Add Qualcomm PMIC RTC-GLINK support for Glymur") from Kamal Wadhwa Link: https://lore.kernel.org/all/20260807-rtc-glink-cleanup-v1-0-7801e4d69c4f@oss.qualcomm.com/ Link: https://lore.kernel.org/all/20260821-rtc-glink-defconfig-v1-1-3e989bec1151@oss.qualcomm.com/ Signed-off-by: Kamal Wadhwa --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 5a42aae3afe9b..b1c8626d275b9 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1390,6 +1390,7 @@ CONFIG_RTC_DRV_PL031=y CONFIG_RTC_DRV_SUN6I=y CONFIG_RTC_DRV_ARMADA38X=y CONFIG_RTC_DRV_PM8XXX=m +CONFIG_RTC_DRV_QCOM_GLINK=m CONFIG_RTC_DRV_TEGRA=y CONFIG_RTC_DRV_SNVS=m CONFIG_RTC_DRV_BBNSM=m From 9b5b1f433b86684922fd40f44d518985db9fb61a Mon Sep 17 00:00:00 2001 From: Karthik S Date: Tue, 8 Sep 2026 17:35:37 +0530 Subject: [PATCH 0666/1133] PENDING: arm64: defconfig: Enable QCS615 LPASS LPI pinctrl driver LPASS LPI pinctrl driver for the QCS615 SoC supports 32 GPIOs in the range 0-31 and provides pin control functionality for the LPASS LPI block. Signed-off-by: Karthik S --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index b1c8626d275b9..816c776d721a2 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -711,6 +711,7 @@ CONFIG_PINCTRL_IMX_SCMI=y CONFIG_PINCTRL_IMX91=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y CONFIG_PINCTRL_LPASS_LPI=m +CONFIG_PINCTRL_QCS615_LPASS_LPI=m CONFIG_PINCTRL_MILOS_LPASS_LPI=m CONFIG_PINCTRL_SC7280_LPASS_LPI=m CONFIG_PINCTRL_SM6115_LPASS_LPI=m From 28b7cb6d7bd0d7293f2e6ed35507a80f2ca7634d Mon Sep 17 00:00:00 2001 From: Anup Kulkarni Date: Wed, 9 Sep 2026 18:15:16 +0530 Subject: [PATCH 0667/1133] QCLINUX: qcom.config: Enable CAN_VCAN Enable CAN and virtual CAN config for RTSS CAN module used to communicate with user-space applications using SocketCAN APIs. Signed-off-by: Anup Kulkarni --- arch/arm64/configs/qcom.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 20bc4fd5101de..878991e246b36 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -10,6 +10,9 @@ CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_RFCOMM=m CONFIG_BT_RFCOMM_TTY=y +CONFIG_CAN=y +CONFIG_CAN_DEV=y +CONFIG_CAN_VCAN=m CONFIG_CFG80211_CERTIFICATION_ONUS=y CONFIG_CMA=y CONFIG_CONNECTOR=y From 3e1f8d5d5c28317f44745d21e368c0f97955c25a Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Thu, 10 Sep 2026 14:31:47 +0800 Subject: [PATCH 0668/1133] QCLINUX: qcom.config: Enable UDMABUF support CMA memory is currently insufficient for libcamera operation at some resolutions. Switch to the community-recommended UDMA buffer allocation mechanism. Signed-off-by: Wenmeng Liu --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 878991e246b36..4cdff765736bd 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -80,6 +80,7 @@ CONFIG_SWIOTLB_DYNAMIC=y CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y +CONFIG_UDMABUF=y CONFIG_UHID=m CONFIG_USB_CONFIGFS_F_UVC=y CONFIG_USB_CONFIGFS_F_UAC2=y From 385a65f1b75af15ae36572c1b8138965a6bfe699 Mon Sep 17 00:00:00 2001 From: Nikhil V Date: Mon, 8 Dec 2025 15:49:36 +0530 Subject: [PATCH 0669/1133] QCLINUX: defconfig: Enable Virtio FE drivers Added required configs to enable virtio FE drivers for Guest VM's. Signed-off-by: Nikhil V --- arch/arm64/configs/qcom.config | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 4cdff765736bd..c732950540df6 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -34,12 +34,19 @@ CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_DRIVER_DEFERRED_PROBE_TIMEOUT=60 +CONFIG_DRM=y +# CONFIG_DRM_DEBUG_MM is not set +CONFIG_DRM_GEM_SHMEM_HELPER=y +CONFIG_DRM_KMS_HELPER=y CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y +CONFIG_FUSE_FS=y CONFIG_FW_LOADER_COMPRESS=y CONFIG_FW_LOADER_COMPRESS_ZSTD=y +CONFIG_GPIO_VIRTIO=y CONFIG_GUNYAH_WATCHDOG=y CONFIG_I2C_QCOM_GENI=y +CONFIG_I2C_VIRTIO=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y CONFIG_INPUT_UINPUT=y @@ -66,6 +73,10 @@ CONFIG_REMOTEPROC_THERMAL=y CONFIG_SCHED_CLASS_EXT=y CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y +CONFIG_SND=y +CONFIG_SND_VIRTIO=y +CONFIG_SOUND=y +CONFIG_SPI_VIRTIO=y CONFIG_STM_PROTO_BASIC=m CONFIG_STM_PROTO_OST=m CONFIG_STM_PROTO_SYS_T=m @@ -87,6 +98,12 @@ CONFIG_USB_CONFIGFS_F_UAC2=y CONFIG_VCPU_STALL_DETECTOR=y CONFIG_VHOST_NET=y CONFIG_VHOST_VSOCK=y +CONFIG_VIRTIO_FS=y +CONFIG_VIRTIO_INPUT=y +CONFIG_VIRTIO_IOMMU=y +CONFIG_VIRTIO_MEM=y +CONFIG_VIRTIO_RTC=y +CONFIG_VIRTIO_VSOCKETS=y CONFIG_VSOCKETS=y # CONFIG_VSOCKETS_DIAG is not set # CONFIG_VSOCKETS_LOOPBACK is not set From b44b2fcce19292e3d65dc17f7047ccc2748cbc54 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Fri, 31 Jul 2026 17:57:44 +0530 Subject: [PATCH 0670/1133] FROMLIST: arm64: defconfig: Enable CAMSS OPE driver Add CONFIG_VIDEO_QCOM_CAMSS_OPE=m to enable the Offline Processing Engine driver for Agatti and Shikra platforms (e.g. Arduino UNO Q). Signed-off-by: Nihal Kumar Gupta Signed-off-by: Loic Poulain Upstream-Status: Submitted [https://lore.kernel.org/all/20260915-camss-isp-ope-v7-9-77b13d131d3d@oss.qualcomm.com/] --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 816c776d721a2..0bb9ef6c263e5 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -948,6 +948,7 @@ CONFIG_VIDEO_IMX8_ISI=m CONFIG_VIDEO_IMX8_ISI_M2M=y CONFIG_VIDEO_IMX8_JPEG=m CONFIG_VIDEO_QCOM_CAMSS=m +CONFIG_VIDEO_QCOM_CAMSS_OPE=m CONFIG_VIDEO_QCOM_IRIS=m CONFIG_VIDEO_QCOM_VENUS=m CONFIG_VIDEO_RCAR_CSI2=m From edc63995e5bc729355e4ed9e709b315e5f2913bb Mon Sep 17 00:00:00 2001 From: Venkat Ramana Sugamanchi Date: Fri, 25 Sep 2026 17:47:03 +0530 Subject: [PATCH 0671/1133] QCLINUX: qcom.config: Enable Intel IGC driver Enable the IGC drivers to support the Intel I226 NIC card. Signed-off-by: Venkat Ramana Sugamanchi --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index c732950540df6..32a914ec63054 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -49,6 +49,7 @@ CONFIG_I2C_QCOM_GENI=y CONFIG_I2C_VIRTIO=y CONFIG_I6300ESB_WDT=y CONFIG_IDLE_INJECT=y +CONFIG_IGC=y CONFIG_INPUT_UINPUT=y CONFIG_IXGBE=m CONFIG_IXGBEVF=m From 00fc18ae72ff3d5bc24b85dc1a627d80416021a6 Mon Sep 17 00:00:00 2001 From: Roopak Houji Date: Tue, 15 Sep 2026 18:27:40 +0530 Subject: [PATCH 0672/1133] QCLINUX: qcom.config: Enable TCG_QCOM Enable Qualcomm TCG support as a module in the Qualcomm arm64 config. Signed-off-by: Roopak Houji --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 32a914ec63054..65ba6a655aa5d 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -89,6 +89,7 @@ CONFIG_SENSORS_EMC2305=y CONFIG_SENSORS_QCOM_SPMI_BCL=y CONFIG_SWIOTLB_DEFAULT_SIZE_MB=2 CONFIG_SWIOTLB_DYNAMIC=y +CONFIG_TCG_QCOM=m CONFIG_TRACE_MMIO_ACCESS=y CONFIG_UCLAMP_TASK_GROUP=y CONFIG_UCLAMP_TASK=y From a7c8294cfd133d4b0c3b98d14f0bbbfbc6a2805f Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 24 Sep 2026 09:16:29 +0530 Subject: [PATCH 0673/1133] QCLINUX: qcom.config: Disable CPUFREQ_DT driver A SoC-specific cpufreq driver already handles CPU frequency scalinig on Qualcomm platforms. As a result, the generic cpufreq-dt driver fails to register against the same CPUs: cpufreq-dt cpufreq-dt: failed register driver: -17 cpufreq-dt cpufreq-dt: probe with driver cpufreq-dt failed with error -17 Disable CPUFREQ_DT to avoid this redundant probe/registration conflict on Qualcomm targets. Signed-off-by: Imran Shaik --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 65ba6a655aa5d..a097b7e29c288 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -25,6 +25,7 @@ CONFIG_CORESIGHT_TPDM=m CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_CPU_IDLE_GOV_TEO=y CONFIG_CPU_IDLE_THERMAL=y +# CONFIG_CPUFREQ_DT is not set # CONFIG_DEBUG_INFO_REDUCED is not set CONFIG_DEBUG_INFO_BTF=y CONFIG_DEBUG_INFO_BTF_MODULES=y From a7963acbff3494bc5fe1a119529e9dcf07068dd8 Mon Sep 17 00:00:00 2001 From: Anand Tiwari Date: Tue, 6 Oct 2026 22:07:14 +0530 Subject: [PATCH 0674/1133] QCLINUX: prune.config: Enable the TI-SN65DSI83 driver Remove sn65dsi83 from prune.config to enable it Signed-off-by: Anand Tiwari --- arch/arm64/configs/prune.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index 6f75cb6b2744a..4f10b2f562d22 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -201,7 +201,6 @@ # 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 From f04d2fd2329005f736325833df27b224870dbc71 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Wed, 7 Oct 2026 18:07:50 +0530 Subject: [PATCH 0675/1133] FROMLIST: arm64: defconfig: Enable S5KJN5 camera sensor for Qualcomm boards Enable the S5KJN5 driver which is used for the camera sensor on the Qualcomm Hawi and Maili MTP boards. Signed-off-by: Nihal Kumar Gupta Upstream-Status: Submitted Link: https://lore.kernel.org/all/20260923-hawi-maili-camss-v1-15-cbbb42e534ef@oss.qualcomm.com/ --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 0bb9ef6c263e5..abed9214fd82e 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -976,6 +976,7 @@ CONFIG_VIDEO_OV08X40=m CONFIG_VIDEO_OV5640=m CONFIG_VIDEO_OV5645=m CONFIG_VIDEO_S5KJN1=m +CONFIG_VIDEO_S5KJN5=m CONFIG_AUXDISPLAY=y CONFIG_SEG_LED_GPIO=m CONFIG_DRM=m From 1b28fb2a4f131d97d7872bdc18d647176d4ae0c1 Mon Sep 17 00:00:00 2001 From: Hariharan Sreedhar Date: Fri, 9 Oct 2026 17:40:17 +0530 Subject: [PATCH 0676/1133] QCLINUX: arm64: configs: qcom.config: Enable NVMe link speed switching Add support for dynamically adjusting the PCIe link rate of NVMe devices based on I/O activity. The link is downgraded to a configurable minimum rate during periods of low activity to save power, and upgraded to the maximum supported rate as soon as the workload exceeds a computed threshold, so that peak performance is maintained under load. Add config for NVMe speed switch Link: https://lore.kernel.org/all/9e99e007bf05a608b1b82da740c2b33935a27175.1790222172.git.liaoxuan@hygon.cn/ Signed-off-by: Krishna Chaitanya Chundru Signed-off-by: Hariharan Sreedhar --- arch/arm64/configs/qcom.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index a097b7e29c288..4e989da6d37f4 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -58,6 +58,7 @@ CONFIG_KPROBES=y CONFIG_MACVLAN=y CONFIG_MACVTAP=y CONFIG_NL80211_TESTMODE=y +CONFIG_NVME_SPEED_SWITCH=y CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y CONFIG_PM_AUTOSLEEP=y From 6efbd13faca3a5d1610e9f6468d4609d1354a89b Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Fri, 16 Oct 2026 21:15:14 +0530 Subject: [PATCH 0677/1133] FROMLIST: arm64: defconfig: Enable RPi touchscreen V2 regulator and ILI9881C panel Enable the regulator driver for the Raspberry Pi touchscreen V2 power and backlight controller, and the Ilitek ILI9881C DSI panel driver, as modules, for the Raspberry Pi 7 inch DSI panel on the 22-pin JDISP1 DSI0 connector on Qualcomm Shikra EVK, Talos Lyra EVK boards. Signed-off-by: Vishnu Saini Link: https://lore.kernel.org/all/20261021-shikra_display_overlays-v1-4-adaea735999f@oss.qualcomm.com/ --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index abed9214fd82e..aad2feb9d9e4e 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -909,6 +909,7 @@ CONFIG_REGULATOR_QCOM_SMD_RPM=y CONFIG_REGULATOR_QCOM_SPMI=y CONFIG_REGULATOR_QCOM_USB_VBUS=m CONFIG_REGULATOR_RAA215300=y +CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2=m CONFIG_REGULATOR_RK808=y CONFIG_REGULATOR_S2MPS11=y CONFIG_REGULATOR_SGM3804=y @@ -1039,6 +1040,7 @@ CONFIG_DRM_PANEL_LVDS=m CONFIG_DRM_PANEL_HIMAX_HX8279=m CONFIG_DRM_PANEL_HIMAX_HX83112A=m CONFIG_DRM_PANEL_HIMAX_HX83112B=m +CONFIG_DRM_PANEL_ILITEK_ILI9881C=m CONFIG_DRM_PANEL_ILITEK_ILI9806E_SPI=m CONFIG_DRM_PANEL_ILITEK_ILI9882T=m CONFIG_DRM_PANEL_KHADAS_TS050=m From dba7e280d832cc7fd0e4055f5697d496fd239082 Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Sat, 17 Oct 2026 09:14:40 +0530 Subject: [PATCH 0678/1133] FROMLIST: arm64: defconfig: Enable Waveshare DSI panel and touch GPIO drivers Enable the Waveshare DSI touch GPIO/backlight controller driver and the Jadard JD9365DA-H3 DSI panel driver, as modules, for the Waveshare 8 inch DSI panel on the 22-pin JDISP1 DSI0 connector on the Qualcomm Shikra EVK, Talos Lyra EVK boards. Signed-off-by: Vishnu Saini Link: https://lore.kernel.org/all/20261021-shikra_display_overlays-v1-6-adaea735999f@oss.qualcomm.com/ --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index aad2feb9d9e4e..c734db6975f22 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -735,6 +735,7 @@ CONFIG_GPIO_SYSCON=y CONFIG_GPIO_UNIPHIER=y CONFIG_GPIO_VF610=y CONFIG_GPIO_VISCONTI=y +CONFIG_GPIO_WAVESHARE_DSI_TOUCH=m CONFIG_GPIO_WCD934X=m CONFIG_GPIO_XGENE=y CONFIG_GPIO_XGENE_SB=y @@ -1043,6 +1044,7 @@ CONFIG_DRM_PANEL_HIMAX_HX83112B=m CONFIG_DRM_PANEL_ILITEK_ILI9881C=m CONFIG_DRM_PANEL_ILITEK_ILI9806E_SPI=m CONFIG_DRM_PANEL_ILITEK_ILI9882T=m +CONFIG_DRM_PANEL_JADARD_JD9365DA_H3=m CONFIG_DRM_PANEL_KHADAS_TS050=m CONFIG_DRM_PANEL_MANTIX_MLAF057WE51=m CONFIG_DRM_PANEL_NOVATEK_NT36672A=m From 4925c9181c005d7c81221aa379d57dd43e9889e8 Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Sat, 17 Oct 2026 09:14:40 +0530 Subject: [PATCH 0679/1133] QCLINUX: prune.config: Enable the Goodix touchscreen driver Remove TOUCHSCREEN_GOODIX from prune.config to enable it. It is used by the touch controllers on the Raspberry Pi 7 inch (GT911) and Waveshare 8 inch (GT9271) DSI panels. Signed-off-by: Vishnu Saini --- arch/arm64/configs/prune.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index 4f10b2f562d22..0d3bc0c02bf3d 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -108,7 +108,6 @@ # 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 From 87f69f6acb96be19823358bccf86c66b595a5043 Mon Sep 17 00:00:00 2001 From: Nikhil V Date: Fri, 30 Oct 2026 11:50:44 +0530 Subject: [PATCH 0680/1133] QCLINUX: defconfig: Remove redundant DRM configs DRM is already enabled as a module in the base defconfig. Remove the redundant DRM entries from qcom.config. Signed-off-by: Nikhil V --- arch/arm64/configs/qcom.config | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index 4e989da6d37f4..f053cd630758f 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -35,10 +35,6 @@ CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_HEAPS_CMA=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_DRIVER_DEFERRED_PROBE_TIMEOUT=60 -CONFIG_DRM=y -# CONFIG_DRM_DEBUG_MM is not set -CONFIG_DRM_GEM_SHMEM_HELPER=y -CONFIG_DRM_KMS_HELPER=y CONFIG_EDAC_QCOM=m CONFIG_EXPERT=y CONFIG_FUSE_FS=y From 4eb7d79ea2afb1eab01e2ede80be39fd9082c587 Mon Sep 17 00:00:00 2001 From: Anand Tiwari Date: Wed, 21 Oct 2026 20:47:29 +0530 Subject: [PATCH 0681/1133] FROMLIST: arm64: defconfig: Enable PWM_CLK for backlight PWM support Enable CONFIG_PWM_CLK so the generic clock-based PWM driver is available, used by the Talos Lyra EVK LVDS panel overlay backlight. Signed-off-by: Anand Tiwari Link: https://lore.kernel.org/r/20261021-lyra-display-upstream-post-v1-5-585caa39cd7c@oss.qualcomm.com --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index c734db6975f22..84bc9a5c49741 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1635,6 +1635,7 @@ CONFIG_PWM_ADP5585=m CONFIG_PWM_APPLE=m CONFIG_PWM_BCM2835=m CONFIG_PWM_BRCMSTB=m +CONFIG_PWM_CLK=m CONFIG_PWM_CROS_EC=m CONFIG_PWM_IMX27=m CONFIG_PWM_MEDIATEK=m From 0ba9fadac21635e23165a6ae26ff68501b2657e2 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 25 Apr 2026 13:50:49 +0300 Subject: [PATCH 0682/1133] QCLINUX: prune.qconfig: reenable R8169 Radxa Dragon Q6A board uses R8169 Ethernet controller. To simplify support for that board in meta-qcom ecosystem, stop disabling R8169 driver (which will be built as a module). Signed-off-by: Dmitry Baryshkov --- arch/arm64/configs/prune.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index 0d3bc0c02bf3d..e0b2cf7443a78 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -86,7 +86,6 @@ # 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 From 7bf726677f0e3a5f9b4a41506e433511a7ce0ac9 Mon Sep 17 00:00:00 2001 From: Jiaxing Li Date: Mon, 26 Oct 2026 15:16:55 +0800 Subject: [PATCH 0683/1133] QCLINUX: arm64: defconfig: Enable DRBG as a module for stdrng users Commit 2ecdf5c9910e ("crypto: qcom-rng - Remove crypto_rng interface") removed the Qualcomm RNG implementation of stdrng. With DRBG disabled, libkcapi RNG requests for stdrng fail on affected Qualcomm systems. Enable DRBG as a module to provide stdrng for existing libkcapi users. Fixes: 2ecdf5c9910e ("crypto: qcom-rng - Remove crypto_rng interface") Signed-off-by: Jiaxing Li --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 84bc9a5c49741..f4a11176c3826 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1854,6 +1854,7 @@ CONFIG_CRYPTO_CHACHA20=m CONFIG_CRYPTO_ECHAINIV=y CONFIG_CRYPTO_SHA3=m CONFIG_CRYPTO_SM3=m +CONFIG_CRYPTO_DRBG=m CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_AES_ARM64_CE_BLK=y From b510675780a39fc5c4464d43bd19ffe17706ebc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Minier?= Date: Wed, 21 Oct 2026 22:15:13 +0200 Subject: [PATCH 0684/1133] QCLINUX: prune.config: Keep simple DRM bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep support for "Simple DRM bridge", useful on some Snapdragon-based OEM laptops. Closes: https://github.com/qualcomm-linux/kernel/issues/1148 Signed-off-by: Loïc Minier --- arch/arm64/configs/prune.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/prune.config b/arch/arm64/configs/prune.config index e0b2cf7443a78..72234fc49b608 100644 --- a/arch/arm64/configs/prune.config +++ b/arch/arm64/configs/prune.config @@ -195,7 +195,6 @@ # 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 From 8c1c1c3e7b9253f2da5e1e3201a52905c2979b04 Mon Sep 17 00:00:00 2001 From: Sneh Mankad Date: Wed, 21 Oct 2026 14:37:46 +0530 Subject: [PATCH 0685/1133] QCLINUX: qcom.config: Make Teo governor as default for CPUidle Menu governor still stays as default governor when both are compiled in due to menu having higher rating than teo. Make Teo governor as default governor. Teo is proven to benefit performance use cases without any power impacts. Signed-off-by: Sneh Mankad --- arch/arm64/configs/qcom.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/qcom.config b/arch/arm64/configs/qcom.config index f053cd630758f..2d5a621bb93e7 100644 --- a/arch/arm64/configs/qcom.config +++ b/arch/arm64/configs/qcom.config @@ -22,7 +22,7 @@ CONFIG_CORESIGHT_DUMMY=m CONFIG_CORESIGHT_CTCU=m CONFIG_CORESIGHT_SOURCE_ETM4X=m CONFIG_CORESIGHT_TPDM=m -CONFIG_CPU_IDLE_GOV_MENU=y +# CONFIG_CPU_IDLE_GOV_MENU is not set CONFIG_CPU_IDLE_GOV_TEO=y CONFIG_CPU_IDLE_THERMAL=y # CONFIG_CPUFREQ_DT is not set From 5d707d020e4ab97f1cc12bcd525132b83d6b8937 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Thu, 29 Oct 2026 10:00:19 +0530 Subject: [PATCH 0686/1133] QCLINUX: kernel: configs: debug: Enable MHI bus debugfs support Enable CONFIG_MHI_BUS_DEBUG to expose debugfs entries for the MHI transport, useful for debugging and testing MHI controllers. Signed-off-by: Krishna Chaitanya Chundru --- kernel/configs/debug.config | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index ec8e66511d319..dc54ee4627e23 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -167,6 +167,7 @@ CONFIG_KPROBE_EVENTS=y CONFIG_LOCALVERSION="" CONFIG_LOCKUP_DETECTOR=y CONFIG_MAC80211_DEBUGFS=y +CONFIG_MHI_BUS_DEBUG=y CONFIG_NL80211_TESTMODE=y CONFIG_PARAVIRT_TIME_ACCOUNTING=y CONFIG_PCIEAER_INJECT=y From 0499af24347c49899093145d69b67f097498e9dd Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Wed, 14 Oct 2026 11:05:39 +0530 Subject: [PATCH 0687/1133] FROMLIST: clk: qcom: gcc-qcs615: Add additional frequencies for GP clocks Add support for 10kHz and 100kHz GCC GP clock frequencies required for display backlight PWM functionality on Qualcomm QCS615 (Talos) SoC. Link: https://lore.kernel.org/r/20261016-talos-gp-clk-freqs-update-v1-1-17c9a095063c@oss.qualcomm.com/ Signed-off-by: Imran Shaik --- drivers/clk/qcom/gcc-qcs615.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/qcom/gcc-qcs615.c b/drivers/clk/qcom/gcc-qcs615.c index 778536f966579..1fd3fc398dda4 100644 --- a/drivers/clk/qcom/gcc-qcs615.c +++ b/drivers/clk/qcom/gcc-qcs615.c @@ -419,6 +419,8 @@ static struct clk_rcg2 gcc_emac_rgmii_clk_src = { }; static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(10000, P_BI_TCXO, 16, 1, 120), + F(100000, P_BI_TCXO, 16, 1, 12), F(25000000, P_GPLL0_OUT_AUX2_DIV, 12, 0, 0), F(50000000, P_GPLL0_OUT_AUX2_DIV, 6, 0, 0), F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), From 443bd58712afe0094e67d3e5b4ea04689f32f296 Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Fri, 16 Oct 2026 11:52:24 +0530 Subject: [PATCH 0688/1133] FROMLIST: clk: qcom: gcc-glymur: Use PWRSTS_RET_ON flag for USB GDSCs The USB GDSCs on Glymur are currently configured with PWRSTS_OFF_ON, which allows the GDSC framework to fully collapse these power domains during gdsc_disable(). When these GDSCs collapse, the corresponding USB configurations are not retained in USB host mode use-cases and this breaks the resume of USB controller from suspend. To avoid this, configure the USB GDSC power states to PWRSTS_RET_ON. This prevents the GDSC from powering off during gdsc_disable(), and allows hardware to retain the USB configurations across USB host mode use-cases. Link: https://lore.kernel.org/all/20261016-glymur-usb-ret-on-v1-1-1790a523fd9c@oss.qualcomm.com/ Signed-off-by: Jagadeesh Kona --- drivers/clk/qcom/gcc-glymur.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/clk/qcom/gcc-glymur.c b/drivers/clk/qcom/gcc-glymur.c index be18a555fe314..857596210f719 100644 --- a/drivers/clk/qcom/gcc-glymur.c +++ b/drivers/clk/qcom/gcc-glymur.c @@ -7752,7 +7752,7 @@ static struct gdsc gcc_usb20_prim_gdsc = { .pd = { .name = "gcc_usb20_prim_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -7764,7 +7764,7 @@ static struct gdsc gcc_usb30_mp_gdsc = { .pd = { .name = "gcc_usb30_mp_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -7776,7 +7776,7 @@ static struct gdsc gcc_usb30_prim_gdsc = { .pd = { .name = "gcc_usb30_prim_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -7788,7 +7788,7 @@ static struct gdsc gcc_usb30_sec_gdsc = { .pd = { .name = "gcc_usb30_sec_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -7800,7 +7800,7 @@ static struct gdsc gcc_usb30_tert_gdsc = { .pd = { .name = "gcc_usb30_tert_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -7812,7 +7812,7 @@ static struct gdsc gcc_usb3_mp_ss0_phy_gdsc = { .pd = { .name = "gcc_usb3_mp_ss0_phy_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -7824,7 +7824,7 @@ static struct gdsc gcc_usb3_mp_ss1_phy_gdsc = { .pd = { .name = "gcc_usb3_mp_ss1_phy_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -7872,7 +7872,7 @@ static struct gdsc gcc_usb_0_phy_gdsc = { .pd = { .name = "gcc_usb_0_phy_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -7884,7 +7884,7 @@ static struct gdsc gcc_usb_1_phy_gdsc = { .pd = { .name = "gcc_usb_1_phy_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; @@ -7896,7 +7896,7 @@ static struct gdsc gcc_usb_2_phy_gdsc = { .pd = { .name = "gcc_usb_2_phy_gdsc", }, - .pwrsts = PWRSTS_OFF_ON, + .pwrsts = PWRSTS_RET_ON, .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, }; From a37efd816420e9c7580cf0cc52f7c56b55078168 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Fri, 17 Oct 2025 11:25:35 +0530 Subject: [PATCH 0689/1133] QCLINUX: arm64: dts: qcom: Add camera DT binding Add the camera DT binding header, which will be utilized by the camera downstream drivers and DTSI files. Signed-off-by: Chandan Kumar Jha --- include/dt-bindings/camera/msm-camera.h | 155 ++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 include/dt-bindings/camera/msm-camera.h diff --git a/include/dt-bindings/camera/msm-camera.h b/include/dt-bindings/camera/msm-camera.h new file mode 100644 index 0000000000000..97228c26e7040 --- /dev/null +++ b/include/dt-bindings/camera/msm-camera.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __MSM_CAMERA_H +#define __MSM_CAMERA_H + +/* CPAS path data types */ +#define CAM_CPAS_PATH_DATA_IFE_START_OFFSET 0 +#define CAM_CPAS_PATH_DATA_IFE_LINEAR (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_IFE_VID (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_IFE_DISP (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_IFE_STATS (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_IFE_RDI0 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_IFE_RDI1 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_IFE_RDI2 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_IFE_RDI3 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 7) +#define CAM_CPAS_PATH_DATA_IFE_PDAF (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 8) +#define CAM_CPAS_PATH_DATA_IFE_PIXEL_RAW (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 9) +#define CAM_CPAS_PATH_DATA_IFE_MAX_OFFSET (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_IPE_START_OFFSET 32 +#define CAM_CPAS_PATH_DATA_IPE_RD_IN (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_IPE_RD_REF (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_IPE_WR_VID (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_IPE_WR_DISP (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_IPE_WR_REF (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_IPE_WR_APP (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_IPE_MAX_OFFSET (CAM_CPAS_PATH_DATA_IPE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_OPE_START_OFFSET 64 +#define CAM_CPAS_PATH_DATA_OPE_RD_IN (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_OPE_RD_REF (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_OPE_WR_VID (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_OPE_WR_DISP (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_OPE_WR_REF (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_OPE_MAX_OFFSET (CAM_CPAS_PATH_DATA_OPE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_SFE_START_OFFSET 96 +#define CAM_CPAS_PATH_DATA_SFE_NRDI (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_SFE_RDI0 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_SFE_RDI1 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_SFE_RDI2 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_SFE_RDI3 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_SFE_RDI4 (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_SFE_STATS (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_SFE_MAX_OFFSET (CAM_CPAS_PATH_DATA_SFE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_CRE_START_OFFSET (CAM_CPAS_PATH_DATA_SFE_MAX_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_CRE_RD_IN (CAM_CPAS_PATH_DATA_CRE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_CRE_WR_OUT (CAM_CPAS_PATH_DATA_CRE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_CRE_MAX_OFFSET (CAM_CPAS_PATH_DATA_CRE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_OFE_START_OFFSET (CAM_CPAS_PATH_DATA_CRE_MAX_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_OFE_RD_EXT (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 0) +#define CAM_CPAS_PATH_DATA_OFE_RD_INT_PDI (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_OFE_RD_INT_HDR (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_OFE_WR_VID (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_OFE_WR_DISP (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_OFE_WR_IR (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_OFE_WR_HDR_LTM (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_OFE_WR_DC4 (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 7) +#define CAM_CPAS_PATH_DATA_OFE_WR_AI (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 8) +#define CAM_CPAS_PATH_DATA_OFE_WR_PDI (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 9) +#define CAM_CPAS_PATH_DATA_OFE_WR_IDEALRAW (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 10) +#define CAM_CPAS_PATH_DATA_OFE_WR_STATS (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 11) +#define CAM_CPAS_PATH_DATA_OFE_MAX_OFFSET (CAM_CPAS_PATH_DATA_OFE_START_OFFSET + 31) + +#define CAM_CPAS_PATH_DATA_CONSO_OFFSET 256 +#define CAM_CPAS_PATH_DATA_ALL (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 0) + +/* IFE consolidated paths */ +#define CAM_CPAS_PATH_DATA_IFE_LINEAR_PDAF (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 1) +#define CAM_CPAS_PATH_DATA_IFE_UBWC_STATS (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 2) +#define CAM_CPAS_PATH_DATA_IFE_PIXEL_ALL (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 3) +#define CAM_CPAS_PATH_DATA_IFE_RDI_PIXEL_RAW (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 4) +#define CAM_CPAS_PATH_DATA_IFE_RDI_ALL (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 5) +#define CAM_CPAS_PATH_DATA_IFE_UBWC (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 6) +#define CAM_CPAS_PATH_DATA_IFE_LINEAR_STATS (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 7) +#define CAM_CPAS_PATH_DATA_IFE_UBWC_LINEAR (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 8) +#define CAM_CPAS_PATH_DATA_IFE_PDAF_LINEAR (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 9) + +/* IPE Consolidated paths */ +#define CAM_CPAS_PATH_DATA_IPE_WR_VID_DISP (CAM_CPAS_PATH_DATA_CONSO_OFFSET + 1) + +/* CPAS transaction types */ +#define CAM_CPAS_TRANSACTION_READ 0 +#define CAM_CPAS_TRANSACTION_WRITE 1 + +/* CPAS traffic merge types */ +#define CAM_CPAS_TRAFFIC_MERGE_SUM 0 +#define CAM_CPAS_TRAFFIC_MERGE_SUM_INTERLEAVE 1 + +/* Feature bit type */ +#define CAM_CPAS_FEATURE_TYPE_DISABLE 0 +#define CAM_CPAS_FEATURE_TYPE_ENABLE 1 +#define CAM_CPAS_FEATURE_TYPE_VALUE 2 + +/* Feature support bit positions in feature fuse register*/ +#define CAM_CPAS_QCFA_BINNING_ENABLE 0 +#define CAM_CPAS_SECURE_CAMERA_ENABLE 1 +#define CAM_CPAS_MF_HDR_ENABLE 2 +#define CAM_CPAS_MP_LIMIT_FUSE 3 +#define CAM_CPAS_ISP_FUSE 4 +#define CAM_CPAS_ISP_PIX_FUSE 5 +#define CAM_CPAS_ISP_LITE_FUSE 6 +#define CAM_CPAS_CSIPHY_FUSE 7 +#define CAM_CPAS_IPE_VID_OUT_8BPP_LIMIT_ENABLE 8 +#define CAM_CPAS_SFE_FUSE 9 +#define CAM_CPAS_CUSTOM_FUSE 10 +#define CAM_CPAS_CAM_FUSE 11 +#define CAM_CPAS_SHDR_FUSE 12 +#define CAM_CPAS_RT_OT_FUSE 13 +#define CAM_CPAS_FUSE_FEATURE_MAX 14 + +/* Flash type*/ +#define CAM_FLASH_TYPE_PMIC 0 +#define CAM_FLASH_TYPE_I2C 1 +#define CAM_FLASH_TYPE_GPIO 2 + +/* CCI master */ +#define CCI_MASTER_0 0 +#define CCI_MASTER_1 1 +#define CCI_MASTER_MAX 2 + +/* AON Camera IDs*/ +#define AON_CAM1 0 +#define AON_CAM2 1 +#define MAX_AON_CAM 2 +#define NOT_AON_CAM 255 + +/* Camera DRV enable masks */ +#define CAM_DDR_DRV 0x1 +#define CAM_CLK_DRV 0x2 + +/* Port index for BW voting */ +#define CAM_CPAS_PORT_HLOS_DRV 0 +#define CAM_CPAS_PORT_DRV_0 1 +#define CAM_CPAS_PORT_DRV_1 2 +#define CAM_CPAS_PORT_DRV_2 3 +#define CAM_CPAS_PORT_DRV_DYN 32 + +/* Domain ID types */ +#define CAM_CPAS_NON_SECURE_DOMAIN 0 +#define CAM_CPAS_SECURE_DOMAIN 1 + +/* Debug bypass driver */ +#define CAM_BYPASS_RGLTR 0x1 +#define CAM_BYPASS_RGLTR_MODE 0x2 +#define CAM_BYPASS_CLKS 0x4 +#define CAM_BYPASS_CESTA 0x8 +#define CAM_BYPASS_ICC 0x10 + +#endif From 91de3151ea0e87593d062a20ba49462bbd6ac0ff Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Fri, 10 Oct 2025 16:51:48 +0530 Subject: [PATCH 0690/1133] QCLINUX: arm64: dts: qcom: Add lemans camx overlay dts Add CAMX overlay dts file for lemans boards. This change also enables the compilation of the CAMX overlay on Lemans boards. Co-developed-by: Vikram Sharma Signed-off-by: Vikram Sharma Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 20 + .../boot/dts/qcom/lemans-camera-sensor.dtsi | 502 ++++ arch/arm64/boot/dts/qcom/lemans-camera.dtsi | 2559 +++++++++++++++++ .../dts/qcom/lemans-evk-camera-sensor.dtsi | 736 +++++ arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso | 138 + .../boot/dts/qcom/sa8775p-ride-camx.dtso | 16 + 6 files changed, 3971 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/lemans-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso create mode 100644 arch/arm64/boot/dts/qcom/sa8775p-ride-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..f7c7053d48a1e 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -523,3 +523,23 @@ x1p64100-microsoft-denali-el2-dtbs := x1p64100-microsoft-denali.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p64100-microsoft-denali.dtb x1p64100-microsoft-denali-el2.dtb x1p42100-microsoft-sp12in-el2-dtbs := x1p42100-microsoft-sp12in.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p42100-microsoft-sp12in.dtb x1p42100-microsoft-sp12in-el2.dtb + +lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb + +qcs9100-ride-camx-dtbs:= qcs9100-ride.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-camx.dtb + +qcs9100-ride-r3-camx-dtbs:= qcs9100-ride-r3.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3-camx.dtb + +sa8775p-ride-camx-dtbs:= sa8775p-ride.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtb + +sa8775p-ride-r3-camx-dtbs:= sa8775p-ride-r3.dtb sa8775p-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera-sensor.dtsi new file mode 100644 index 0000000000000..d531f89dda08e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-camera-sensor.dtsi @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 7 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 8 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 9 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; +}; + +&cam_cci3 { + /* GMSL deserializer 3 */ + qcom,cam-gmsl-deserializer3 { + cell-index = <3>; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 10 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET3"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser3_port0: endpoint { + remote-endpoint = <&gmsl_sensor12_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser3_port1: endpoint { + remote-endpoint = <&gmsl_sensor13_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser3_port2: endpoint { + remote-endpoint = <&gmsl_sensor14_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser3_port3: endpoint { + remote-endpoint = <&gmsl_sensor15_ep>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 0 */ + qcom,cam-gmsl-sensor12 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <12>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor12_ep: endpoint { + remote-endpoint = <&deser3_port0>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 1 */ + qcom,cam-gmsl-sensor13 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <13>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor13_ep: endpoint { + remote-endpoint = <&deser3_port1>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 2 */ + qcom,cam-gmsl-sensor14 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <14>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor14_ep: endpoint { + remote-endpoint = <&deser3_port2>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 3 */ + qcom,cam-gmsl-sensor15 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <15>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor15_ep: endpoint { + remote-endpoint = <&deser3_port3>; + }; + }; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared = <518 519 520 521>; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi new file mode 100644 index 0000000000000..18d78926b1f17 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi @@ -0,0 +1,2559 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&soc { + cam_cci0: qcom,cci0@ac13000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac13000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x13000>; + interrupts = ; + interrupt-names = "CCI0"; + operating-points-v2 = <&cci0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci0_active>; + pinctrl-1 = <&cci0_suspend>; + pinctrl-2 = <&cci1_active>; + pinctrl-3 = <&cci1_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <0>; + status = "ok"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci1: qcom,cci1@ac14000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac14000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x14000>; + interrupts = ; + interrupt-names = "CCI1"; + operating-points-v2 = <&cci1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci2_active>; + pinctrl-1 = <&cci2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <1>; + status = "ok"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci2: qcom,cci2@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "CCI2"; + operating-points-v2 = <&cci2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_2_CLK_SRC>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "cci_2_clk_src", + "cci_2_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_2_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci4_active>; + pinctrl-1 = <&cci4_suspend>; + pinctrl-2 = <&cci5_active>; + pinctrl-3 = <&cci5_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <2>; + status = "ok"; + + cci2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci2: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci2: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci2: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci2: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci3: qcom,cci3@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "CCI3"; + operating-points-v2 = <&cci3_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_3_CLK_SRC>, + <&camcc CAM_CC_CCI_3_CLK>; + clock-names = "cci_3_clk_src", + "cci_3_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_3_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci6_active>; + pinctrl-1 = <&cci6_suspend>; + pinctrl-2 = <&cci7_active>; + pinctrl-3 = <&cci7_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <3>; + status = "ok"; + + cci3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci3: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci3: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci3: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci3: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_csiphy0: qcom,csiphy0@ac9c000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0x0ac9c000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy0_opp_table>; + reg-cam-base = <0x9c000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + aggregator-rx; + cell-index = <0>; + status = "ok"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ac9e000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xac9e000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy1_opp_table>; + reg-cam-base = <0x9e000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <1>; + aggregator-rx; + status = "ok"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2@aca0000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xaca0000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy2_opp_table>; + reg-cam-base = <0xa0000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <2>; + aggregator-rx; + status = "ok"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy3: qcom,csiphy3@aca2000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xaca2000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy3_opp_table>; + reg-cam-base = <0xa2000>; + interrupts = ; + interrupt-names = "CSIPHY3"; + csi-vdd-1p2-supply = <&vreg_l1c>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1140000 831000>; + rgltr-max-voltage = <1260000 920000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy3_clk", + "csi3phytimer_clk_src", + "csi3phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <3>; + aggregator-rx; + status = "ok"; + + csiphy3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg17: qcom,tpg17@acac000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacac000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xac000 0x11000>; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <17>; + phy-id = <0>; + status = "ok"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg18: qcom,tpg18@acad000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacad000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xad000 0x11000>; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <18>; + phy-id = <1>; + status = "ok"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg19: qcom,tpg19@acae000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacae000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xae000 0x11000>; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <19>; + phy-id = <2>; + status = "ok"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe"; + status = "ok"; + }; + + qcom,cam-cpas { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac11000 0x0 0x1000>, + <0x0 0xac1A000 0x0 0x9400>, + <0x0 0xbbf0000 0x0 0x1f00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x11000 0x1A000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "gcc_camera_sf_axi_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "cam_cc_camnoc_axi_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_qdss_debug_xo_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 0 0 0 0 0 0 0 0>, + <0 0 0 80000000 0 0 300000000 0 400000000 0 0>, + <0 0 0 80000000 0 0 400000000 0 400000000 0 0>; + clock-cntl-level = "suspend", "svs_l1", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <480000000>; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnects = <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", "cam_hf_0", "cam_sf_0", "cam_sf_icp"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "csiphy3", + "cci0", "cci1", "cci2", "cci3","csid0", "csid1", + "csid2", "csid3", "csid4", "csid5", "csid6", + "ife0", "ife1", "ife2", "ife3", "ife4", + "ife5", "ife6", "ipe0", "sfe0", "sfe1", + "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "icp0", "tpg17", "tpg18", "tpg19"; + + enable-secure-qos-update; + cell-index = <0>; + status = "ok"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + icp_all_rd: icp-all-rd { + cell-index = <0>; + node-name = "icp-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_icp_rd>; + }; + + ife_0_wr_0: ife-0-wr-0 { + cell-index = <1>; + node-name = "ife-0-wr-0"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_0_wr_1: ife-0-wr-1 { + cell-index = <2>; + node-name = "ife-0-wr-1"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_1_wr_0: ife-1-wr-0 { + cell-index = <3>; + node-name = "ife-1-wr-0"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + + ife_1_wr_1: ife-1-wr-1 { + cell-index = <4>; + node-name = "ife-1-wr-1"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_lite_0_wr_0: ife-lite-0-wr-0 { + cell-index = <5>; + node-name = "ife-lite-0-wr-0"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_1_wr_0: ife-lite-1-wr-0 { + cell-index = <6>; + node-name = "ife-lite-1-wr-0"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_2_wr_0: ife-lite-2-wr-0 { + cell-index = <7>; + node-name = "ife-lite-2-wr-0"; + client-name = "ife4"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_3_wr_0: ife-lite-3-wr-0 { + cell-index = <8>; + node-name = "ife-lite-3-wr-0"; + client-name = "ife5"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_4_wr_0: ife-lite-4-wr-0 { + cell-index = <9>; + node-name = "ife-lite-4-wr-0"; + client-name = "ife6"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ipe_0_rd_all: ipe-0-rd-all { + cell-index = <10>; + node-name = "ipe-0-rd-all"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_rd1>; + }; + + ipe_0_wr_2: ipe-0-wr-2 { + cell-index = <11>; + node-name = "ipe-0-wr-2"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_wr2>; + }; + + ipe_cdm0_all_rd: ipe-cdm0-all-rd { + cell-index = <12>; + node-name = "ipe-cdm0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm0_all_rd_2: rt-cdm0-all-rd-2 { + cell-index = <13>; + node-name = "rt-cdm0-all-rd-2"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm1_all_rd_2: rt-cdm1-all-rd-2 { + cell-index = <14>; + node-name = "rt-cdm1-all-rd-2"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm2_all_rd_2: rt-cdm2-all-rd-2 { + cell-index = <15>; + node-name = "rt-cdm2-all-rd-2"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = + ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm3_all_rd_2: rt-cdm3-all-rd-2 { + cell-index = <16>; + node-name = "rt-cdm3-all-rd-2"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + sfe_0_rd_0: sfe-0-rd-0 { + cell-index = <17>; + node-name = "sfe-0-rd-0"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + + sfe_1_rd_0: sfe-1-rd-0 { + cell-index = <18>; + node-name = "sfe-1-rd-0"; + client-name = "sfe1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt_rd2: level1-nrt-rd2 { + cell-index = <19>; + node-name = "level1-nrt-rd2"; + parent-node = <&level2_nrt_rd2>; + traffic-merge-type = ; + }; + + level1_rt_rd0: level1-rt-read0 { + cell-index = <20>; + node-name = "level1-rt-rd0"; + parent-node = <&level2_rt_rd0>; + traffic-merge-type = ; + }; + + level1_rt_wr0: level1-rt-wr0 { + cell-index = <21>; + node-name = "level1-rt-wr0"; + parent-node = <&level2_rt_wr0>; + traffic-merge-type = ; + }; + + level1_rt_wr1: level1-rt-wr1 { + cell-index = <22>; + node-name = "level1-rt-wr1"; + parent-node = <&level2_rt_wr1>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_icp_rd: level2-icp-rd { + cell-index = <23>; + node-name = "level2-icp-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd1: level2-nrt-rd1 { + cell-index = <24>; + node-name = "level2-nrt-rd1"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd2: level2-nrt-rd2 { + cell-index = <25>; + node-name = "level2-nrt-rd2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_wr2: level2-nrt-wr2 { + cell-index = <26>; + node-name = "level2-nrt-wr2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_rd0: level2-rt-read0 { + cell-index = <27>; + node-name = "level2-rt-rd0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr0: level2-rt-wr0 { + cell-index = <28>; + node-name = "level2-rt-wr0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr1: level2-rt-wr1 { + cell-index = <29>; + node-name = "level2-rt-wr1"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <30>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = + ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <31>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = + ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt_rd_wr_sum: level3-rt-rd-wr-sum { + cell-index = <32>; + node-name = "level3-rt-rd-wr-sum"; + traffic-merge-type = + ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + }; + + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", "qcom,ipe0"; + num-icp = <1>; + num-ipe = <1>; + icp_use_pil; + status = "ok"; + }; + + qcom,cam-i3c-id-table { + i3c-sensor-id-table = <0x1B0 0x0766>; + i3c-eeprom-id-table = <>; + i3c-actuator-id-table = <>; + i3c-ois-id-table = <>; + status = "disabled"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "ok"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "ok"; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "ok"; + }; + + qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + force_cache_allocs; + status = "ok"; + + msm-cam-smmu-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0860 0x400>, + <&apps_smmu 0x0C60 0x400>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + rt_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x400>, + <&apps_smmu 0x0840 0x480>, + <&apps_smmu 0x08C0 0x480>, + <&apps_smmu 0x0C00 0x400>, + <&apps_smmu 0x0C40 0x480>, + <&apps_smmu 0x0CC0 0x480>; + cam-smmu-label = "icp"; + qcom,iommu-faults = "stall-disable", "non-fatal"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + subregion_support; + status = "ok"; + + /* Used for HFI queues/sec heap */ + iova-mem-region-generic-region { + iova-region-name = "icp_hfi"; + iova-region-start = <0x10400000>; + iova-region-len = <0x200000>; + iova-region-id = <0x0>; + }; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "ok"; + }; + + iova-mem-region-qdss { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "ok"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xfc00000>; + iova-region-id = <0x1>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x3400 0x0020>, + <&apps_smmu 0x3420 0x0020>; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + dma-coherent; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 64 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* start address: 0x100000 */ + /* leaving 1 MB pad at start */ + iova-region-start = <0x100000>; + /* Length: 0xfffe00000 */ + /* leaving 1 MB pad at end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,camera-main { + compatible = "qcom,camera"; + status = "ok"; + }; + + cam_csid0: qcom,csid0 { + compatible = "qcom,csid690"; + reg = <0x0 0xac7a000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid0", "csid_top"; + reg-cam-base = <0x7a000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid1: qcom,csid1 { + compatible = "qcom,csid690"; + reg = <0x0 0xac7c000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid1", "csid_top"; + reg-cam-base = <0x7c000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac84000 0x0 0xf01>; + reg-names = "csid-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "ok"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac88000 0x0 0xf01>; + reg-names = "csid-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "ok"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite2: qcom,csid-lite2 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac8c000 0x0 0xf01>; + reg-names = "csid-lite2"; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite2_opp_table>; + clock-control-debugfs = "true"; + cell-index = <4>; + status = "ok"; + + csid_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite3: qcom,csid-lite3 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac90000 0x0 0xf01>; + reg-names = "csid-lite3"; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite3_opp_table>; + clock-control-debugfs = "true"; + cell-index = <5>; + status = "ok"; + + csid_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite4: qcom,csid-lite4 { + compatible = "qcom,csid-lite690"; + reg = <0x0 0xac94000 0x0 0xf01>; + reg-names = "csid-lite4"; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite4_opp_table>; + clock-control-debugfs = "true"; + cell-index = <6>; + status = "ok"; + + csid_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_icp: qcom,icp { + compatible = "qcom,cam-icp_v3_0"; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0xac04000 0x0 0x1000>; + reg-names ="icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&pil_camera_mem>; + src-clock-name = "cam_cc_icp_clk_src"; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "cam_cc_soc_fast_ahb_clk_src", + "cam_cc_icp_ahb_clk", + "cam_cc_icp_clk_src", + "cam_cc_icp_clk"; + clock-rates = <300000000 0 480000000 0>, + <400000000 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + nrt-device; + fw_name = "CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + qos-val = <0xa0a>; + operating-points-v2 = <&icp_opp_table>; + icp-version = <0x0300>; + cam_hw_pid = <12>; + cell-index = <0>; + status = "ok"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0 { + compatible = "qcom,vfe690"; + reg = <0x0 0xac4d000 0x0 0xd000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife0", "cam_camnoc"; + reg-cam-base = <0x4d000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_0_clk", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_ife_0_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <8 16>; + cell-index = <0>; + status = "ok"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1 { + compatible = "qcom,vfe690"; + reg = <0x0 0xac5a000 0x0 0xd000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife1", "cam_camnoc"; + reg-cam-base = <0x5a000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_1_clk", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_ife_1_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <9 17>; + cell-index = <1>; + status = "ok"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac84000 0x0 0x1d00>; + reg-names = "ife-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <2>; + status = "ok"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac88000 0x0 0x1d00>; + reg-names = "ife-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <3>; + status = "ok"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite2: qcom,ife-lite2 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac8c000 0x0 0x1d00>; + reg-names = "ife-lite2"; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite2_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <4>; + status = "ok"; + + vfe_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite3: qcom,ife-lite3 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac90000 0x0 0x1d00>; + reg-names = "ife-lite3"; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite3_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <5>; + status = "ok"; + + vfe_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite4: qcom,ife-lite4 { + compatible = "qcom,vfe-lite690"; + reg = <0x0 0xac94000 0x0 0x1d00>; + reg-names = "ife-lite4"; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite4_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <6>; + status = "ok"; + + vfe_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0 { + compatible = "qcom,cam-ipe"; + reg = <0x0 0xac2d000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x2d000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + src-clock-name = "cam_cc_ipe_clk_src"; + clocks = <&camcc CAM_CC_CPAS_IPE_CLK>, + <&camcc CAM_CC_IPE_AHB_CLK>, + <&camcc CAM_CC_IPE_CLK>, + <&camcc CAM_CC_IPE_CLK_SRC>, + <&camcc CAM_CC_IPE_FAST_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>; + clock-names = "cam_cc_cpas_ipe_clk", + "cam_cc_ipe_ahb_clk", + "cam_cc_ipe_clk", + "cam_cc_ipe_clk_src", + "cam_cc_ipe_fast_ahb_clk", + "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 480000000 0 300000000>, + <0 0 0 600000000 0 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + operating-points-v2 = <&ipe0_opp_table>; + nrt-device; + cam_hw_pid = <14 15>; + cell-index = <0>; + status = "ok"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + + }; + + qcom,rt-cdm0 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x1000>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table0>; + clock-cntl-level = "svs"; + cdm-client-names = "ife0", "dualife0"; + single-context-cdm; + cell-index = <0>; + status = "ok"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm1 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac27000 0x0 0x1000>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x27000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table1>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife1", "dualife1"; + single-context-cdm; + cell-index = <1>; + status = "ok"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm2 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac28000 0x0 0x1000>; + reg-names = "rt-cdm2"; + reg-cam-base = <0x28000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table2>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <2>; + status = "ok"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm3 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac29000 0x0 0x1000>; + reg-names = "rt-cdm3"; + reg-cam-base = <0x29000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table3>; + clock-cntl-level = "svs"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <3>; + status = "ok"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_sfe_lite0: qcom,sfe-lite0 { + compatible = "qcom,sfe-lite690"; + reg = <0x0 0xac74000 0x0 0x1000>; + reg-names = "sfe-lite0"; + reg-cam-base = <0x74000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", + "cam_cc_sfe_lite_0_clk", + "cam_cc_cpas_sfe_lite_0_clk"; + clocks = <&camcc CAM_CC_SFE_LITE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_0_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_0_CLK>; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_0_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table0>; + cam_hw_pid = <4>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + cam_sfe_lite_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe_lite1: qcom,sfe-lite1 { + compatible = "qcom,sfe-lite690"; + reg = <0x0 0xac75000 0x0 0x1000>; + reg-names = "sfe-lite1"; + reg-cam-base = <0x75000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_1_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_1_CLK>; + clock-names = "cam_cc_sfe_lite_1_fast_ahb_clk", + "cam_cc_sfe_lite_1_clk", + "cam_cc_cpas_sfe_1_clk"; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_1_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table1>; + cam_hw_pid = <5>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + cam_sfe_lite_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; +}; + +&tlmm { + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* MCLK0 */ + mux { + pins = "gpio72"; + function = "cam_mclk"; + }; + + config { + pins = "gpio72"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* MCLK0 */ + mux { + pins = "gpio72"; + function = "cam_mclk"; + }; + + config { + pins = "gpio72"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio73"; + function = "cam_mclk"; + }; + + config { + pins = "gpio73"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio73"; + function = "cam_mclk"; + }; + + config { + pins = "gpio73"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio74"; + function = "cam_mclk"; + }; + + config { + pins = "gpio74"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio74"; + function = "cam_mclk"; + }; + + config { + pins = "gpio74"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* MCLK3 */ + mux { + pins = "gpio75"; + function = "cam_mclk"; + }; + + config { + pins = "gpio75"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* MCLK3 */ + mux { + pins = "gpio75"; + function = "cam_mclk"; + }; + + config { + pins = "gpio75"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci0_active: cci0-active { + mux { + /* CLK, DATA */ + pins = "gpio61","gpio60"; + function = "cci_i2c"; + }; + + config { + pins = "gpio61","gpio60"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci0_suspend: cci0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio61","gpio60"; + function = "cci_i2c"; + }; + + config { + pins = "gpio61","gpio60"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci1_active: cci1-active { + mux { + /* CLK, DATA */ + pins = "gpio53","gpio52"; + function = "cci_i2c"; + }; + + config { + pins = "gpio53","gpio52"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci1_suspend: cci1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio53","gpio52"; + function = "cci_i2c"; + }; + + config { + pins = "gpio53","gpio52"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci2_active: cci2-active { + mux { + /* CLK, DATA */ + pins = "gpio63","gpio62"; + function = "cci_i2c"; + }; + + config { + pins = "gpio63","gpio62"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci2_suspend: cci2-suspend { + mux { + /* CLK, DATA */ + pins = "gpio63","gpio62"; + function = "cci_i2c"; + }; + + config { + pins = "gpio63","gpio62"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_active: cci3-active { + mux { + /* CLK, DATA */ + pins = "gpio55","gpio54"; + function = "cci_i2c"; + }; + + config { + pins = "gpio55","gpio54"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci3_suspend: cci3-suspend { + mux { + /* CLK, DATA */ + pins = "gpio55","gpio54"; + function = "cci_i2c"; + }; + + config { + pins = "gpio55","gpio54"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci4_active: cci4-active { + mux { + /* CLK, DATA */ + pins = "gpio65","gpio64"; + function = "cci_i2c"; + }; + + config { + pins = "gpio65","gpio64"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci4_suspend: cci4-suspend { + mux { + /* CLK, DATA */ + pins = "gpio65","gpio64"; + function = "cci_i2c"; + }; + + config { + pins = "gpio65","gpio64"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci5_active: cci5-active { + mux { + /* CLK, DATA */ + pins = "gpio57","gpio56"; + function = "cci_i2c"; + }; + + config { + pins = "gpio57","gpio56"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci5_suspend: cci5-suspend { + mux { + /* CLK, DATA */ + pins = "gpio57","gpio56"; + function = "cci_i2c"; + }; + + config { + pins = "gpio57","gpio56"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci6_active: cci6-active { + mux { + /* CLK, DATA */ + pins = "gpio67","gpio66"; + function = "cci_i2c"; + }; + + config { + pins = "gpio67","gpio66"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci6_suspend: cci6-suspend { + mux { + /* CLK, DATA */ + pins = "gpio67","gpio66"; + function = "cci_i2c"; + }; + + config { + pins = "gpio67","gpio66"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci7_active: cci7-active { + mux { + /* CLK, DATA */ + pins = "gpio59","gpio58"; + function = "cci_i2c"; + }; + + config { + pins = "gpio59","gpio58"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci7_suspend: cci7-suspend { + mux { + /* CLK, DATA */ + pins = "gpio59","gpio58"; + function = "cci_i2c"; + }; + + config { + pins = "gpio59","gpio58"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi new file mode 100644 index 0000000000000..8eb1026e7da1b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -0,0 +1,736 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 7 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; + + /*cam0a-ov9282*/ + qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 72 0>, + <&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <20>; + status = "ok"; + }; + + /*cam24-ov13858*/ + qcom,cam-sensor24 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam24>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 72 0>, + <&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <24>; + status = "ok"; + }; + + eeprom_cam24: qcom,eeprom24 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 72 0>, + <&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <24>; + status = "ok"; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 8 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; + + /*cam1-ov9282*/ + qcom,cam-sensor21 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <21>; + status = "ok"; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 9 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; + + /*cam2-ov9282*/ + qcom,cam-sensor22 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>, + <&tlmm 134 0>, + <&pmm8654au_0_gpios 9 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <22>; + status = "ok"; + }; +}; + +&cam_cci3 { + /* GMSL deserializer 3 */ + qcom,cam-gmsl-deserializer3 { + cell-index = <3>; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&pmm8654au_0_gpios 10 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET3"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser3_port0: endpoint { + remote-endpoint = <&gmsl_sensor12_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser3_port1: endpoint { + remote-endpoint = <&gmsl_sensor13_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser3_port2: endpoint { + remote-endpoint = <&gmsl_sensor14_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser3_port3: endpoint { + remote-endpoint = <&gmsl_sensor15_ep>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 0 */ + qcom,cam-gmsl-sensor12 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <12>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor12_ep: endpoint { + remote-endpoint = <&deser3_port0>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 1 */ + qcom,cam-gmsl-sensor13 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <13>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor13_ep: endpoint { + remote-endpoint = <&deser3_port1>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 2 */ + qcom,cam-gmsl-sensor14 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <14>; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor14_ep: endpoint { + remote-endpoint = <&deser3_port2>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 3 */ + qcom,cam-gmsl-sensor15 { + cell-index = <15>; + compatible = "qcom,cam-gmsl-sensor"; + csiphy-sd-index = <3>; + status = "ok"; + + port { + gmsl_sensor15_ep: endpoint { + remote-endpoint = <&deser3_port3>; + }; + }; + }; + + /*cam3-ov9282*/ + qcom,cam-sensor23 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 75 0>, + <&tlmm 135 0>, + <&pmm8654au_0_gpios 10 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK3", + "CAMIF_RESET3", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <23>; + status = "ok"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared = <518 519 520 521>; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso new file mode 100644 index 0000000000000..520fb14660142 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camx.dtso @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "lemans-camera.dtsi" +#include "lemans-evk-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET */ + mux { + pins = "gpio132"; + function = "gpio"; + }; + + config { + pins = "gpio132"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio133"; + function = "gpio"; + }; + + config { + pins = "gpio133"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET */ + mux { + pins = "gpio134"; + function = "gpio"; + }; + + config { + pins = "gpio134"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst3: cam-sensor-active-rst3 { + /* RESET */ + mux { + pins = "gpio135"; + function = "gpio"; + }; + + config { + pins = "gpio135"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET */ + mux { + pins = "gpio132"; + function = "gpio"; + }; + + config { + pins = "gpio132"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio133"; + function = "gpio"; + }; + + config { + pins = "gpio133"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET */ + mux { + pins = "gpio134"; + function = "gpio"; + }; + + config { + pins = "gpio134"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst3: cam-sensor-suspend-rst3 { + /* RESET */ + mux { + pins = "gpio135"; + function = "gpio"; + }; + + config { + pins = "gpio135"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride-camx.dtso b/arch/arm64/boot/dts/qcom/sa8775p-ride-camx.dtso new file mode 100644 index 0000000000000..f81fa6565f281 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8775p-ride-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "lemans-camera.dtsi" +#include "lemans-camera-sensor.dtsi" From 7b0da058937be793cb2e9964d3382c96c27ab0a1 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Fri, 17 Oct 2025 11:25:35 +0530 Subject: [PATCH 0691/1133] QCLINUX: arm64: dts: qcom: Add rb3gen2 camx overlay dts Add CAMX overlay dts file for rb3gen2 vision mezzanine board. This change also enables the compilation of the CAMX overlay for Kodiak rb3gen2 vision mezzanine board. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 5 + arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi | 2471 +++++++++++++++++ .../qcom/qcs6490-rb3gen2-camera-sensor.dtsi | 551 ++++ ...qcs6490-rb3gen2-vision-mezzanine-camx.dtso | 24 + 4 files changed, 3051 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index f7c7053d48a1e..5ec7c86a1a875 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -528,6 +528,11 @@ lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb +qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ + qcs6490-rb3gen2-vision-mezzanine-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtb + qcs9100-ride-camx-dtbs:= qcs9100-ride.dtb sa8775p-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi new file mode 100644 index 0000000000000..f6af6827784bd --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi @@ -0,0 +1,2471 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&soc { + cam_a5: qcom,a5 { + compatible = "qcom,cam-a5"; + cell-index = <0>; + reg = <0x0 0xac00000 0x0 0x6000>, + <0x0 0xac10000 0x0 0x8000>, + <0x0 0xac18000 0x0 0x3000>; + reg-names = "a5_qgic", "a5_sierra", "a5_csr"; + reg-cam-base = <0x00000 0x10000 0x18000>; + interrupts = ; + interrupt-names = "a5"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "soc_fast_ahb", + "icp_ahb_clk", + "icp_clk_src", + "icp_clk"; + clock-rates = <100000000 0 400000000 0>, + <200000000 0 400000000 0>, + <300000000 0 600000000 0>, + <400000000 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "soc_fast_ahb"; + operating-points-v2 = <&a5_opp_table>; + fw_name = "CAMERA_ICP_170.elf"; + ubwc-ipe-fetch-cfg = <0x7073 0x707b>; + ubwc-ipe-write-cfg = <0x161cf 0x161ef>; + ubwc-bps-fetch-cfg = <0x7073 0x707b>; + ubwc-bps-write-cfg = <0x161cf 0x161ef>; + qos-val = <0x00000A0A>; + status = "ok"; + + a5_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps { + compatible = "qcom,cam-bps"; + cell-index = <0>; + reg = <0x0 0xac6f000 0x0 0x8000>; + reg-names = "bps_top"; + reg-cam-base = <0x6f000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_AREG_CLK>, + <&camcc CAM_CC_BPS_AXI_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_areg_clk", + "bps_axi_clk", + "bps_clk_src", + "bps_clk"; + clock-rates = <0 0 0 200000000 0>, + <0 0 0 400000000 0>, + <0 0 0 480000000 0>, + <0 0 0 600000000 0>, + <0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc", + "lrmecdm"; + status = "ok"; + }; + + qcom,cam-cpas { + compatible = "qcom,cam-cpas"; + cell-index = <0>; + label = "cpas"; + arch-compat = "cpas_top"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x0 0x0ac40000 0x0 0x1000>, + <0x0 0x0ac9f000 0x0 0x10000>; + reg-names = "cam_cpas_top", "cam_camnoc"; + reg-cam-base = <0x40000 0x9f000>; + cam_hw_fuse = , + , + , + , + , + ; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "gcc_camera_hf_axi_clk", + "gcc_camera_sf_axi_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_icp_ahb_clk", + "cam_cc_icp_clk"; + src-clock-name = "cam_cc_camnoc_axi_clk_src"; + clock-rates = <0 0 0 0 0 0 0 0>, + <0 0 80000000 0 150000000 0 0 0>, + <0 0 80000000 0 240000000 0 0 0>, + <0 0 80000000 0 320000000 0 0 0>, + <0 0 80000000 0 400000000 0 0 0>, + <0 0 80000000 0 480000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvs", "svs", + "svs_l1", "nominal", "turbo"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects = <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", "cam_hf_0", "cam_sf_0", "cam_sf_icp"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "csiphy3", + "csiphy4", "cci0", "cci1", "csid0", "csid1", + "csid2", "csid3", "csid4", "ife0", "ife1", + "ife2", "ife3", "ife4", "ipe0", "cam-cdm-intf0", + "cpas-cdm0", "bps0", "icp0", "jpeg-dma0", "jpeg-enc0", + "lrmecpas0"; + status = "ok"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + cpas_cdm0_all_rd: cpas-cdm0-all-rd { + cell-index = <2>; + node-name = "cpas-cdm0-all-rd"; + client-name = "cpas-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_read0>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <3>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_read0>; + }; + + ife0_pixelall_wr: ife0-pixelall-wr { + cell-index = <4>; + node-name = "ife0-pixelall-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife0_rdi_wr: ife0-rdi-wr { + cell-index = <5>; + node-name = "ife0-rdi-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife1_pixelall_wr: ife1-pixelall-wr { + cell-index = <6>; + node-name = "ife1-pixelall-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife1_rdi_wr: ife1-rdi-wr { + cell-index = <7>; + node-name = "ife1-rdi-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife2_pixelall_wr: ife2-pixelall-wr { + cell-index = <8>; + node-name = "ife2-pixelall-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write1>; + }; + + ife2_rdi_wr: ife2-rdi-wr { + cell-index = <9>; + node-name = "ife2-rdi-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife3_rdi_wr: ife3-rdi-wr { + cell-index = <10>; + node-name = "ife3-rdi-wr"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife4_rdi_wr: ife4-rdi-wr { + cell-index = <11>; + node-name = "ife4-rdi-wr"; + client-name = "ife4"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ipe0_all_rd: ipe0-all-rd { + cell-index = <12>; + node-name = "ipe0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_read0>; + }; + + ipe0_ref_wr: ipe0-ref-wr { + cell-index = <13>; + node-name = "ipe0-ref-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + ipe0_viddisp_wr: ipe0-viddisp-wr { + cell-index = <14>; + node-name = "ipe0-viddisp-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_write0>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <15>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_read0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <16>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_write0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <17>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_read0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <18>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt1_write0>; + }; + + lrme0_all_rd: lrme0-all-rd { + cell-index = <19>; + node-name = "lrme0-all-rd"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + lrme0_all_wr: lrme0-all-wr { + cell-index = <20>; + node-name = "lrme0-all-wr"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_write0: level1-nrt0-write0 { + cell-index = <21>; + node-name = "level1-nrt0-write0"; + parent-node = <&level2_nrt0_write0>; + traffic-merge-type = ; + }; + + level1_nrt0_read0: level1-nrt0-read0 { + cell-index = <22>; + node-name = "level1-nrt0-read0"; + parent-node = <&level2_nrt0_read0>; + traffic-merge-type = ; + }; + + level1_nrt1_write0: level1-nrt1-write0 { + cell-index = <23>; + node-name = "level1-nrt1-write0"; + parent-node = <&level2_nrt0_write0>; + traffic-merge-type = ; + }; + + level1_nrt1_read0: level1-nrt1-read0 { + cell-index = <24>; + node-name = "level1-nrt1-read0"; + parent-node = <&level2_nrt0_read0>; + traffic-merge-type = ; + }; + + level1_rt0_write0: level1-rt0-write0 { + cell-index = <25>; + node-name = "level1-rt0-write0"; + parent-node = <&level2_rt0_write0>; + traffic-merge-type = ; + }; + + level1_rt1_write0: level1-rt1-write0 { + cell-index = <26>; + node-name = "level1-rt1-write0"; + parent-node = <&level2_rt1_write0>; + traffic-merge-type = ; + }; + + level1_rt1_write1: level1-rt1-write1 { + cell-index = <27>; + node-name = "level1-rt1-write1"; + parent-node = <&level2_rt1_write0>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <3>; + camnoc-max-needed; + + level2_nrt0_write0: level2-nrt0-write0 { + cell-index = <28>; + node-name = "level2-nrt0-write0"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt0_read0: level2-nrt0-read0 { + cell-index = <29>; + node-name = "level2-nrt0-read0"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt1_read0: level2-nrt1-read0 { + cell-index = <30>; + node-name = "level2-nrt1-read0"; + parent-node = <&level3_nrt1_rd_sum>; + traffic-merge-type = + ; + bus-width-factor = <4>; + }; + + level2_rt0_write0: level2-rt0-write0 { + cell-index = <31>; + node-name = "level2-rt0-write0"; + parent-node = <&level3_rt0_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt1_write0: level2-rt1-write0 { + cell-index = <32>; + node-name = "level2-rt1-write0"; + parent-node = <&level3_rt0_wr_sum>; + traffic-merge-type = ; + }; + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <33>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + interconnect-names = "cam_sf_0"; + interconnects = + <&mmss_noc MASTER_CAMNOC_SF 0 + &mc_virt SLAVE_EBI1 0>; + }; + }; + + level3_nrt1_rd_sum: level3-nrt1-rd-sum { + cell-index = <34>; + node-name = "level3-nrt1-rd-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + interconnect-names = "cam_sf_icp"; + interconnects = + <&mmss_noc MASTER_CAMNOC_ICP 0 + &mc_virt SLAVE_EBI1 0>; + }; + }; + + level3_rt0_wr_sum: level3-rt0-wr-sum { + cell-index = <35>; + node-name = "level3-rt0-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + interconnect-names = "cam_hf_0"; + interconnects = + <&mmss_noc MASTER_CAMNOC_HF 0 + &mc_virt SLAVE_EBI1 0>; + }; + }; + }; + }; + }; + + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,a5", + "qcom,ipe0", + "qcom,bps"; + num-a5 = <1>; + num-ipe = <1>; + num-bps = <1>; + icp_pc_en; + status = "ok"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "ok"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "ok"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "ok"; + }; + + qcom,cam-lrme { + compatible = "qcom,cam-lrme"; + arch-compat = "lrme"; + status = "ok"; + }; + + qcom,camera-main { + compatible = "qcom,camera_kt"; + status = "ok"; + }; + + qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + force_cache_allocs; + status = "ok"; + + msm-cam-icp-fw { + compatible = "qcom,msm-cam-smmu-fw-dev"; + label="icp"; + memory-region = <&camera_mem>; + }; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2040 0x0>; + cam-smmu-label = "cpas-cdm"; + dma-coherent; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 3.4 GB */ + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm_cam_smmu_icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2000 0x20>, + <&apps_smmu 0x2020 0x20>, + <&apps_smmu 0x2062 0x0>, + <&apps_smmu 0x2080 0x20>, + <&apps_smmu 0x20A0 0x20>, + <&apps_smmu 0x2140 0x0>; + cam-smmu-label = "icp"; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-firmware { + /* Firmware region is 5MB */ + iova-region-name = "firmware"; + iova-region-start = <0x0>; + iova-region-len = <0x500000>; + iova-region-id = <0x0>; + status = "ok"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.7 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xcf300000>; + iova-region-id = <0x3>; + status = "ok"; + }; + + iova-mem-region-qdss { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "ok"; + }; + + iova-mem-region-secondary-heap { + /* Secondary heap region is 1MB long */ + iova-region-name = "secheap"; + iova-region-start = <0x10a00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x4>; + status = "ok"; + }; + + iova-mem-region-shared { + /* Shared region is 150MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x9600000>; + iova-region-id = <0x1>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x800 0x4E0>, + <&apps_smmu 0x820 0x4E0>, + <&apps_smmu 0x840 0x4E0>, + <&apps_smmu 0x860 0x4E0>, + <&apps_smmu 0x880 0x4E0>, + <&apps_smmu 0x8A0 0x4E0>, + <&apps_smmu 0x8C0 0x4E0>, + <&apps_smmu 0x8E0 0x4E0>, + <&apps_smmu 0xC00 0x4E0>, + <&apps_smmu 0xC20 0x4E0>, + <&apps_smmu 0xC40 0x4E0>, + <&apps_smmu 0xC60 0x4E0>, + <&apps_smmu 0xC80 0x4E0>, + <&apps_smmu 0xCA0 0x4E0>, + <&apps_smmu 0xCC0 0x4E0>, + <&apps_smmu 0xCE0 0x4E0>; + cam-smmu-label = "ife"; + multiple-client-devices; + dma-coherent; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x20C0 0x20>, + <&apps_smmu 0x20E0 0x20>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 3.4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-lrme { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2100 0x20>, + <&apps_smmu 0x2120 0x20>; + cam-smmu-label = "lrme"; + dma-coherent; + + lrme_iova_mem_map: iova-mem-map { + iova-mem-region-shared { + /* Shared region is 100MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x6400000>; + iova-region-id = <0x1>; + status = "ok"; + }; + + /* IO region is approximately 3.3 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x100000>; + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "ok"; + }; + + cam_cci0: qcom,cci0 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac4a000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x4a000>; + interrupts = ; + interrupt-names = "cci"; + operating-points-v2 = <&cci0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + pinctrl-0 = <&cci0_active &cci1_active>; + pinctrl-1 = <&cci0_suspend &cci1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 70 0>, + <&tlmm 71 0>, + <&tlmm 72 0>; + gpio-req-tbl-num = <0 1 2 3>; + gpio-req-tbl-flags = <1 1 1 1>; + gpio-req-tbl-label = "CCI_I2C_DATA0", + "CCI_I2C_CLK0", + "CCI_I2C_DATA1", + "CCI_I2C_CLK1"; + cell-index = <0>; + status = "ok"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci1: qcom,cci1 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac4b000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x4b000>; + interrupts = ; + interrupt-names = "cci"; + operating-points-v2 = <&cci1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pinctrl-0 = <&cci2_active &cci3_active>; + pinctrl-1 = <&cci2_suspend &cci3_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 74 0>, + <&tlmm 75 0>, + <&tlmm 76 0>; + gpio-req-tbl-num = <0 1 2 3>; + gpio-req-tbl-flags = <1 1 1 1>; + gpio-req-tbl-label = "CCI_I2C_DATA2", + "CCI_I2C_CLK2", + "CCI_I2C_DATA3", + "CCI_I2C_CLK3"; + cell-index = <1>; + status = "ok"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + qcom,cpas-cdm0 { + compatible = "qcom,cam170-cpas-cdm0"; + cell-index = <0>; + label = "cpas-cdm"; + reg = <0x0 0xac48000 0x0 0x1000>; + reg-names = "cpas-cdm"; + reg-cam-base = <0x48000>; + interrupts = ; + interrupt-names = "cpas-cdm"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clock-rates = <80000000 0>; + clock-cntl-level = "svs"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + operating-points-v2 = <&cdm_cpas_opp_table>; + cdm-client-names = "ife0", "ife1", "ife2", + "ife3", "ife4", "dualife"; + status = "ok"; + + cdm_cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csid0: qcom,csid0 { + compatible = "qcom,csid165_204"; + cell-index = <0>; + reg = <0x0 0xacb3000 0x0 0x1000>; + reg-names = "csid"; + reg-cam-base = <0xb3000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CSID_CLK>, + <&camcc CAM_CC_IFE_0_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <300000000 0 0 380000000 0 0>, + <400000000 0 0 510000000 0 0>, + <400000000 0 0 637000000 0 0>, + <400000000 0 0 760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid1: qcom,csid1 { + compatible = "qcom,csid165_204"; + cell-index = <1>; + reg = <0x0 0xacba000 0x0 0x1000>; + reg-names = "csid"; + reg-cam-base = <0xba000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CSID_CLK>, + <&camcc CAM_CC_IFE_1_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <300000000 0 0 380000000 0 0>, + <400000000 0 0 510000000 0 0>, + <400000000 0 0 637000000 0 0>, + <400000000 0 0 760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid2: qcom,csid2 { + compatible = "qcom,csid165_204"; + cell-index = <2>; + reg = <0x0 0x0acc1000 0x0 0x1000>; + reg-names = "csid"; + reg-cam-base = <0xc1000>; + interrupts = ; + interrupt-names = "csid2"; + power-domains = <&camcc CAM_CC_IFE_2_GDSC>; + clocks = <&camcc CAM_CC_IFE_2_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_2_CSID_CLK>, + <&camcc CAM_CC_IFE_2_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_2_CLK_SRC>, + <&camcc CAM_CC_IFE_2_CLK>, + <&camcc CAM_CC_IFE_2_AXI_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <300000000 0 0 380000000 0 0>, + <400000000 0 0 510000000 0 0>, + <400000000 0 0 637000000 0 0>, + <400000000 0 0 760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid2_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0 { + compatible = "qcom,csid-lite165"; + cell-index = <3>; + reg = <0x0 0xacc8000 0x0 0x1000>; + reg-names = "csid-lite"; + reg-cam-base = <0xc8000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_0_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_0_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_0_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_0_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk"; + clock-rates = <300000000 0 0 320000000 0>, + <400000000 0 0 400000000 0>, + <400000000 0 0 480000000 0>, + <400000000 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1 { + compatible = "qcom,csid-lite165"; + cell-index = <4>; + reg = <0x0 0x0accf000 0x0 0x1000>; + reg-names = "csid-lite"; + reg-cam-base = <0xcf000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_1_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_1_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_1_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_1_CLK>; + clock-names = "ife_csid_clk_src", + "ife_csid_clk", + "ife_cphy_rx_clk", + "ife_clk_src", + "ife_clk"; + clock-rates = <300000000 0 0 320000000 0>, + <400000000 0 0 400000000 0>, + <400000000 0 0 480000000 0>, + <400000000 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0 { + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + cell-index = <0>; + reg = <0x0 0x0ace0000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe0000>; + interrupts = ; + interrupt-names = "csiphy0"; + operating-points-v2 = <&csiphy0_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + clock-cntl-level = "lowsvs", "svs"; + src-clock-name = "csi0phytimer_clk_src"; + status = "ok"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1 { + cell-index = <1>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace2000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe2000>; + interrupts = ; + interrupt-names = "csiphy1"; + operating-points-v2 = <&csiphy1_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2 { + cell-index = <2>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "csiphy2"; + operating-points-v2 = <&csiphy2_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "csi2phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy3: qcom,csiphy3 { + cell-index = <3>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace6000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe6000>; + interrupts = ; + interrupt-names = "csiphy3"; + operating-points-v2 = <&csiphy3_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy3_clk", + "csi3phytimer_clk_src", + "csi3phytimer_clk"; + src-clock-name = "csi3phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4 { + cell-index = <4>; + compatible = "qcom,csiphy-v1.2.1", "qcom,csiphy"; + reg = <0x0 0xace8000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe8000>; + interrupts = ; + interrupt-names = "csiphy4"; + operating-points-v2 = <&csiphy4_opp_table>; + csi-vdd-1p2-supply = <&vreg_l6b_1p2>; + csi-vdd-0p9-supply = <&vreg_l10c_0p88>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1260000 1050000>; + rgltr-load-current = <54000 96400>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "lowsvs", "svs"; + clock-rates = <300000000 0 300000000 0>, + <400000000 0 300000000 0>; + status = "ok"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_ipe0: qcom,ipe0 { + compatible = "qcom,cam-ipe"; + cell-index = <0>; + reg = <0x0 0xac87000 0x0 0xa000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x87000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_0_AHB_CLK>, + <&camcc CAM_CC_IPE_0_AREG_CLK>, + <&camcc CAM_CC_IPE_0_AXI_CLK>, + <&camcc CAM_CC_IPE_0_CLK_SRC>, + <&camcc CAM_CC_IPE_0_CLK>; + clock-names = "ipe_0_ahb_clk", + "ipe_0_areg_clk", + "ipe_0_axi_clk", + "ipe_0_clk_src", + "ipe_0_clk"; + clock-rates = <0 0 0 300000000 0>, + <0 0 0 430000000 0>, + <0 0 0 520000000 0>, + <0 0 0 600000000 0>, + <0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "turbo"; + src-clock-name = "ipe_0_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + status = "ok"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-430000000 { + opp-hz = /bits/ 64 <430000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-520000000 { + opp-hz = /bits/ 64 <520000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma { + compatible = "qcom,cam_jpeg_dma_165"; + cell-index = <0>; + reg = <0x0 0xac52000 0x0 0x4000>, + <0x0 0x0ac9f000 0x0 0x10000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x52000 0x9f000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <600000000 0>; + clock-cntl-level = "nominal"; + src-clock-name = "jpegdma_clk_src"; + operating-points-v2 = <&jpeg_dma_opp_table>; + cam_hw_pid = <20 21>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <2>; + status = "ok"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc { + compatible = "qcom,cam_jpeg_enc_165"; + cell-index = <0>; + reg = <0x0 0xac4e000 0x0 0x4000>, + <0x0 0x0ac9f000 0x0 0x10000>; + reg-names = "jpege_hw", "cam_camnoc"; + reg-cam-base = <0x4e000 0x9f000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <600000000 0>; + clock-cntl-level = "nominal"; + src-clock-name = "jpegenc_clk_src"; + operating-points-v2 = <&jpeg_enc_opp_table>; + cam_hw_pid = <22 23>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <2>; + status = "ok"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_lrme: qcom,lrme { + compatible = "qcom,lrme"; + cell-index = <0>; + reg = <0x0 0xac6b000 0x0 0x1000>; + reg-names = "lrme"; + reg-cam-base = <0x6b000>; + interrupts = ; + interrupt-names = "lrme"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_LRME_CLK_SRC>, + <&camcc CAM_CC_LRME_CLK>; + clock-names = "lrme_clk_src", + "lrme_clk"; + clock-rates = <240000000 0>, + <300000000 0>, + <320000000 0>, + <400000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "lrme_clk_src"; + operating-points-v2 = <&lrme_opp_table>; + status = "ok"; + + lrme_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,vfe0 { + compatible = "qcom,vfe165_160"; + reg = <0x0 0xacaf000 0x0 0x5200>; + reg-names = "ife"; + reg-cam-base = <0xaf000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <380000000 0 0>, + <510000000 0 0>, + <637000000 0 0>, + <760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <760000000>; + cam_hw_pid = <24 8>; + cell-index = <0>; + status = "ok"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,vfe1 { + compatible = "qcom,vfe165_160"; + reg = <0x0 0xacb6000 0x0 0x5200>; + reg-names = "ife"; + reg-cam-base = <0xb6000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <380000000 0 0>, + <510000000 0 0>, + <637000000 0 0>, + <760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <760000000>; + cam_hw_pid = <25 9>; + cell-index = <1>; + status = "ok"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + + cam_vfe2: qcom,vfe2 { + compatible = "qcom,vfe165_160"; + reg = <0x0 0x0acbd000 0x0 0x5200>; + reg-names = "ife"; + reg-cam-base = <0xbd000>; + interrupts = ; + interrupt-names = "ife2"; + power-domains = <&camcc CAM_CC_IFE_2_GDSC>; + clocks = <&camcc CAM_CC_IFE_2_CLK_SRC>, + <&camcc CAM_CC_IFE_2_CLK>, + <&camcc CAM_CC_IFE_2_AXI_CLK>; + clock-names = "ife_clk_src", + "ife_clk", + "ife_axi_clk"; + clock-rates = <380000000 0 0>, + <510000000 0 0>, + <637000000 0 0>, + <760000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe2_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_2_DSP_CLK>; + clock-rates-option = <760000000>; + cam_hw_pid = <3 10>; + cell-index = <2>; + status = "ok"; + + vfe2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-380000000 { + opp-hz = /bits/ 64 <380000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-637000000 { + opp-hz = /bits/ 64 <637000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-760000000 { + opp-hz = /bits/ 64 <760000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,vfe-lite0 { + compatible = "qcom,vfe-lite165"; + cell-index = <3>; + reg = <0x0 0xacc4000 0x0 0x5000>; + reg-names = "ife-lite"; + reg-cam-base = <0xc4000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_0_CLK>; + clock-names = "ife_clk_src", + "ife_clk"; + clock-rates = <320000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <11>; + status = "ok"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,vfe-lite1 { + compatible = "qcom,vfe-lite165"; + reg = <0x0 0x0accb000 0x0 0x5000>; + reg-names = "ife-lite"; + reg-cam-base = <0xcb000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_1_CLK>; + clock-names = "ife_clk_src", + "ife_clk"; + clock-rates = <320000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "ife_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <12>; + cell-index = <4>; + status = "ok"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; +}; + +&tlmm { + cam_sensor_active_mux: cam-sensor-active-mux { + /* GC630 bypass mux */ + mux { + pins = "gpio1"; + function = "gpio"; + }; + + config { + pins = "gpio1"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + mux { + pins = "gpio20"; + function = "gpio"; + }; + + config { + pins = "gpio20"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET REARAUX */ + mux { + pins = "gpio21"; + function = "gpio"; + }; + + config { + pins = "gpio21"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET 2 */ + mux { + pins = "gpio77"; + function = "gpio"; + }; + + config { + pins = "gpio77"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst3: cam-sensor-active-rst3 { + /* RESET 3 */ + mux { + pins = "gpio78"; + function = "gpio"; + }; + + config { + pins = "gpio78"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET 4 */ + mux { + pins = "gpio79"; + function = "gpio"; + }; + + config { + pins = "gpio79"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_active: cam_sensor-mclk0-active { + /* MCLK0 */ + mux { + pins = "gpio64"; + function = "cam_mclk"; + }; + + config { + pins = "gpio64"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* MCLK0 */ + mux { + pins = "gpio64"; + function = "cam_mclk"; + }; + + config { + pins = "gpio64"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio65"; + function = "cam_mclk"; + }; + + config { + pins = "gpio65"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio65"; + function = "cam_mclk"; + }; + + config { + pins = "gpio65"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio66"; + function = "cam_mclk"; + }; + + config { + pins = "gpio66"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio66"; + function = "cam_mclk"; + }; + + config { + pins = "gpio66"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* MCLK3 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* MCLK3 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* MCLK4 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* MCLK4 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk5_active: cam-sensor-mclk5-active { + /* MCLK5 */ + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + + config { + pins = "gpio98"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk5_suspend: cam-sensor-mclk5-suspend { + /* MCLK5 */ + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + + config { + pins = "gpio98"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_mux: cam-sensor-suspend-mux { + /* GC630 bypass mux */ + mux { + pins = "gpio1"; + function = "gpio"; + }; + + config { + pins = "gpio1"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst0: cam_sensor-suspend-rst0 { + /* RESET REAR */ + mux { + pins = "gpio20"; + function = "gpio"; + }; + + config { + pins = "gpio20"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET REARAUX */ + mux { + pins = "gpio21"; + function = "gpio"; + }; + + config { + pins = "gpio21"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET 2 */ + mux { + pins = "gpio77"; + function = "gpio"; + }; + + config { + pins = "gpio77"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst3: cam-sensor-suspend-rst3 { + /* RESET 3 */ + mux { + pins = "gpio78"; + function = "gpio"; + }; + + config { + pins = "gpio78"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET 4 */ + mux { + pins = "gpio79"; + function = "gpio"; + }; + + config { + pins = "gpio79"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cci0_active: cci0-active { + mux { + /* DATA, CLK */ + pins = "gpio69","gpio70"; // Only 2 + function = "cci_i2c"; + }; + + config { + pins = "gpio69","gpio70"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci0_suspend: cci0-suspend { + mux { + /* DATA, CLK */ + pins = "gpio69","gpio70"; + function = "cci_i2c"; + }; + + config { + pins = "gpio69","gpio70"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci1_active: cci1-active { + mux { + /* DATA, CLK */ + pins = "gpio71","gpio72"; + function = "cci_i2c"; + }; + + config { + pins = "gpio71","gpio72"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci1_suspend: cci1-suspend { + mux { + /* DATA, CLK */ + pins = "gpio71","gpio72"; + function = "cci_i2c"; + }; + + config { + pins = "gpio71","gpio72"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci2_active: cci2-active { + mux { + /* DATA, CLK */ + pins = "gpio73","gpio74"; + function = "cci_i2c"; + }; + + config { + pins = "gpio73","gpio74"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci2_suspend: cci2-suspend { + mux { + /* DATA, CLK */ + pins = "gpio73","gpio74"; + function = "cci_i2c"; + }; + + config { + pins = "gpio73","gpio74"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_active: cci3-active { + mux { + /* DATA, CLK */ + pins = "gpio75","gpio76"; + function = "cci_i2c"; + }; + + config { + pins = "gpio75","gpio76"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_suspend: cci3-suspend { + mux { + /* DATA, CLK */ + pins = "gpio75","gpio76"; + function = "cci_i2c"; + }; + + config { + pins = "gpio75","gpio76"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi new file mode 100644 index 0000000000000..8b75b1a441db4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi @@ -0,0 +1,551 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + //cam1 interpose on dk csi0 + actuator_rear_cam11: qcom,actuator11 { + compatible = "qcom,actuator"; + cell-index = <11>; + cci-master = <1>; + regulator-names = "cam_vaf"; + rgltr-cntrl-support; + rgltr-min-voltage = <2856000>; + rgltr-max-voltage = <3104000>; + rgltr-load-current = <100000>; + }; + + eeprom_rear_cam11: qcom,eeprom11 { + compatible = "qcom,eeprom"; + cell-index = <11>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio", "cam_clk"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000 0>; + rgltr-max-voltage = <1800000 0>; + rgltr-load-current = <120000 0>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 65 0>, + <&tlmm 21 0>, + <&pm7250b_gpios 3 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0a-ov9282*/ + qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 64 0>, + <&tlmm 20 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam1-ov9282*/ + qcom,cam-sensor6 { + compatible = "qcom,cam-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 65 0>, + <&tlmm 21 0>, + <&pm7250b_gpios 3 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam1-imx586/imx686*/ + qcom,cam-sensor11 { + compatible = "qcom,cam-sensor"; + cell-index = <11>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + actuator-src = <&actuator_rear_cam11>; + eeprom-src = <&eeprom_rear_cam11>; + cam_vio-supply = <&vreg_l18b_1p8>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "cam_vio", "cam_clk"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000 0>; + rgltr-max-voltage = <1800000 0>; + rgltr-load-current = <120000 0>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 65 0>, + <&tlmm 21 0>, + <&pm7250b_gpios 3 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + +}; + +&cam_cci1 { + eeprom_cam2: qcom,eeprom0 { + compatible = "qcom,eeprom"; + cell-index = <8>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 66 0>, + <&tlmm 77 0>, + <&pm7250b_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam3: qcom,eeprom3 { + compatible = "qcom,eeprom"; + cell-index = <0>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 78 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK3", + "CAM_RESET3"; + sensor-position = <1>; + sensor-mode = <0>; + cci-master = <1>; + qcom,cam-power-seq-type ="cam_reset","cam_vio", + "cam_clk","cam_reset"; + qcom,cam-power-seq-val = "cam_reset","cam_vio", + "cam_mclk","cam_reset"; + qcom,cam-power-seq-cfg-val = <0 1 24000000 1>; + qcom,cam-power-seq-delay = <1 0 1 18>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam3-imx577*/ + qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + cell-index = <0>; + csiphy-sd-index = <3>; + eeprom-src = <&eeprom_cam3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 78 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK3", + "CAM_RESET3"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /* GMSL 1 */ + qcom,cam-sensor4 { + compatible = "qcom,cam-sensor"; + cell-index = <4>; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_4"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; + + /* GMSL 2 */ + qcom,cam-sensor5 { + compatible = "qcom,cam-sensor"; + cell-index = <5>; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_5"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; + + /*cam0b-ov9282*/ + qcom,cam-sensor7 { + compatible = "qcom,cam-sensor"; + cell-index = <7>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk4_active + &cam_sensor_active_rst5>; + pinctrl-1 = <&cam_sensor_mclk4_suspend + &cam_sensor_suspend_rst5>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 149 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK4", + "CAM_RESET5"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam2-imx577*/ + qcom,cam-sensor8 { + compatible = "qcom,cam-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam2>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 66 0>, + <&tlmm 77 0>, + <&pm7250b_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /* GMSL 3 */ + qcom,cam-sensor9 { + compatible = "qcom,cam-sensor"; + cell-index = <9>; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_9"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; + + /* GMSL 4 */ + qcom,cam-sensor10 { + compatible = "qcom,cam-sensor"; + cell-index = <10>; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&tlmm 93 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_10"; + sensor-mode = <0>; + cci-master = <1>; + status = "ok"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared-pinctrl = <640>; + shared-pctrl-gpio-names = "gmsl"; + pinctrl-0 = <&cam_sensor_active_gmsl>; + pinctrl-1 = <&cam_sensor_suspend_gmsl>; + pinctrl-names = "gmsl_active", "gmsl_suspend"; + status = "ok"; + }; +}; + +&tlmm { + cam_sensor_active_gmsl: cam-sensor-active-gmsl { + /* GMSL_ENABLE */ + mux { + pins = "gpio93"; + function = "gpio"; + }; + + config { + pins = "gpio93"; + bias-pull-up; + drive-strength = <2>; /* 2 MA */ + output-high; + }; + }; + + cam_sensor_active_rst5: cam-sensor-active-rst5 { + /* RESET 5 */ + mux { + pins = "gpio115"; + function = "gpio"; + }; + + config { + pins = "gpio115"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_gmsl: cam-sensor-suspend-gmsl { + /* GMSL_ENABLE */ + mux { + pins = "gpio93"; + function = "gpio"; + }; + + config { + pins = "gpio93"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst5: cam-sensor-suspend-rst5 { + /* RESET 5 */ + mux { + pins = "gpio115"; + function = "gpio"; + }; + + config { + pins = "gpio115"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtso new file mode 100644 index 0000000000000..eb183d7dbd3d5 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-vision-mezzanine-camx.dtso @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "qcs6490-camera.dtsi" +#include "qcs6490-rb3gen2-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; + +&cci1 { + status = "disabled"; +}; From 65289242d1983472882837506115c3c59b4bb139 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Sun, 19 Oct 2025 11:20:50 +0530 Subject: [PATCH 0692/1133] QCLINUX: arm64: dts: qcom: Add monaco camx overlay dts Add CAMX overlay dts file for Monaco boards. This change also enables the compilation of the CAMX overlay for Monaco boards. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 8 + .../boot/dts/qcom/monaco-camera-sensor.dtsi | 380 +++ arch/arm64/boot/dts/qcom/monaco-camera.dtsi | 2505 +++++++++++++++++ .../dts/qcom/monaco-evk-camera-sensor.dtsi | 794 ++++++ arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso | 107 + .../boot/dts/qcom/qcs8300-ride-camx.dtso | 16 + 6 files changed, 3810 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/monaco-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso create mode 100644 arch/arm64/boot/dts/qcom/qcs8300-ride-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 5ec7c86a1a875..375dec517cc0e 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -528,11 +528,19 @@ lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb +monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb + qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ qcs6490-rb3gen2-vision-mezzanine-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtb +qcs8300-ride-camx-dtbs:= qcs8300-ride.dtb qcs8300-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtb + qcs9100-ride-camx-dtbs:= qcs9100-ride.dtb sa8775p-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi new file mode 100644 index 0000000000000..0023c97edce91 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 75 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + gpios-shared = <518 519 520 521>; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi new file mode 100644 index 0000000000000..bd619b507831f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi @@ -0,0 +1,2505 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&soc { + cam_cci0: qcom,cci0@ac13000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac13000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x13000>; + interrupts = ; + interrupt-names = "CCI0"; + operating-points-v2 = <&cci0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <0>; + status = "ok"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci1: qcom,cci1@ac14000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac14000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x14000>; + interrupts = ; + interrupt-names = "CCI1"; + operating-points-v2 = <&cci1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl2_active &cci_i2c_sda2_active>; + pinctrl-1 = <&cci_i2c_scl2_suspend &cci_i2c_sda2_suspend>; + pinctrl-2 = <&cci_i2c_scl3_active &cci_i2c_sda3_active>; + pinctrl-3 = <&cci_i2c_scl3_suspend &cci_i2c_sda3_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <1>; + status = "ok"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_cci2: qcom,cci2@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "CCI2"; + operating-points-v2 = <&cci2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_2_CLK_SRC>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "cci_2_clk_src", + "cci_2_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_2_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl4_active &cci_i2c_sda4_active>; + pinctrl-1 = <&cci_i2c_scl4_suspend &cci_i2c_sda4_suspend>; + pinctrl-2 = <&cci_i2c_scl5_active &cci_i2c_sda5_active>; + pinctrl-3 = <&cci_i2c_scl5_suspend &cci_i2c_sda5_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <2>; + status = "ok"; + + cci2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci2: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_400Khz_cci2: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_1Mhz_cci2: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + + i2c_freq_100Khz_cci2: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + + cam_csiphy0: qcom,csiphy0@ac9c000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0x0ac9c000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy0_opp_table>; + reg-cam-base = <0x9c000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <0>; + aggregator-rx; + status = "ok"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ac9e000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xac9e000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy1_opp_table>; + reg-cam-base = <0x9e000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <1>; + aggregator-rx; + status = "ok"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2@aca0000 { + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0xaca0000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy2_opp_table>; + reg-cam-base = <0xa0000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + cell-index = <2>; + aggregator-rx; + status = "ok"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acac000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacac000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xac000 0x11000>; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <13>; + phy-id = <0>; + status = "ok"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acad000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacad000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xad000 0x11000>; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <14>; + phy-id = <1>; + status = "ok"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acae000 { + compatible = "qcom,cam-tpg1031"; + reg = <0x0 0xacae000 0x0 0x400>, + <0x0 0xac11000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xae000 0x11000>; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <15>; + phy-id = <2>; + status = "ok"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe"; + status = "ok"; + }; + + qcom,cam-cpas { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac11000 0x0 0x1000>, + <0x0 0xac1A000 0x0 0x9400>, + <0x0 0xbbf0000 0x0 0x1f00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x11000 0x1A000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "gcc_camera_sf_axi_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "cam_cc_camnoc_axi_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_qdss_debug_xo_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 0 0 0 0 0 0 0 0>, + <0 0 0 80000000 0 0 300000000 0 400000000 0 0>, + <0 0 0 80000000 0 0 400000000 0 400000000 0 0>; + clock-cntl-level = "suspend", "svs_l1", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <480000000>; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnects = <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", "cam_hf_0", "cam_sf_0", "cam_sf_icp"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", + "cci0", "cci1", "cci2", + "csid0", "csid1", "csid2", "csid3", + "csid4", "csid5", "csid6", "ife0", + "ife1", "ife2", "ife3", "ife4", + "ife5", "ife6", "ipe0", "sfe0", "sfe1", + "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "icp0", "tpg13", "tpg14", "tpg15"; + enable-secure-qos-update; + cell-index = <0>; + status = "ok"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + icp_all_rd: icp-all-rd { + cell-index = <0>; + node-name = "icp-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_icp_rd>; + }; + + ife_0_wr_0: ife-0-wr-0 { + cell-index = <1>; + node-name = "ife-0-wr-0"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_0_wr_1: ife-0-wr-1 { + cell-index = <2>; + node-name = "ife-0-wr-1"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_1_wr_0: ife-1-wr-0 { + cell-index = <3>; + node-name = "ife-1-wr-0"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_1_wr_1: ife-1-wr-1 { + cell-index = <3>; + node-name = "ife-1-wr-1"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr1>; + }; + + ife_lite_0_wr_0: ife-lite-0-wr-0 { + cell-index = <4>; + node-name = "ife-lite-0-wr-0"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_1_wr_0: ife-lite-1-wr-0 { + cell-index = <5>; + node-name = "ife-lite-1-wr-0"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_2_wr_0: ife-lite-2-wr-0 { + cell-index = <6>; + node-name = "ife-lite-2-wr-0"; + client-name = "ife4"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_3_wr_0: ife-lite-3-wr-0 { + cell-index = <7>; + node-name = "ife-lite-3-wr-0"; + client-name = "ife5"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_4_wr_0: ife-lite-4-wr-0 { + cell-index = <8>; + node-name = "ife-lite-4-wr-0"; + client-name = "ife6"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_wr0>; + }; + + ipe_0_rd_all: ipe-0-rd-all { + cell-index = <9>; + node-name = "ipe-0-rd-all"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_rd1>; + }; + + ipe_0_wr_2: ipe-0-wr-2 { + cell-index = <10>; + node-name = "ipe-0-wr-2"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_wr2>; + }; + + ipe_cdm0_all_rd: ipe-cdm0-all-rd { + cell-index = <11>; + node-name = "ipe-cdm0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm0_all_rd_2: rt-cdm0-all-rd-2 { + cell-index = <12>; + node-name = "rt-cdm0-all-rd-2"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm1_all_rd_2: rt-cdm1-all-rd-2 { + cell-index = <13>; + node-name = "rt-cdm1-all-rd-2"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm2_all_rd_2: rt-cdm2-all-rd-2 { + cell-index = <14>; + node-name = "rt-cdm2-all-rd-2"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm3_all_rd_2: rt-cdm3-all-rd-2 { + cell-index = <15>; + node-name = "rt-cdm3-all-rd-2"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt_rd2>; + }; + + sfe_0_rd_0: sfe-0-rd-0 { + cell-index = <16>; + node-name = "sfe-0-rd-0"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + + sfe_1_rd_0: sfe-1-rd-0 { + cell-index = <17>; + node-name = "sfe-1-rd-0"; + client-name = "sfe1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt_rd2: level1-nrt-rd2 { + cell-index = <22>; + node-name = "level1-nrt-rd2"; + parent-node = <&level2_nrt_rd2>; + traffic-merge-type = ; + }; + + level1_rt_rd0: level1-rt-read0 { + cell-index = <21>; + node-name = "level1-rt-rd0"; + parent-node = <&level2_rt_rd0>; + traffic-merge-type = ; + }; + + level1_rt_wr0: level1-rt-wr0 { + cell-index = <19>; + node-name = "level1-rt-wr0"; + parent-node = <&level2_rt_wr0>; + traffic-merge-type = ; + }; + + level1_rt_wr1: level1-rt-wr1 { + cell-index = <20>; + node-name = "level1-rt-wr1"; + parent-node = <&level2_rt_wr1>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_icp_rd: level2-icp-rd { + cell-index = <23>; + node-name = "level2-icp-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd1: level2-nrt-rd1 { + cell-index = <24>; + node-name = "level2-nrt-rd1"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd2: level2-nrt-rd2 { + cell-index = <25>; + node-name = "level2-nrt-rd2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_wr2: level2-nrt-wr2 { + cell-index = <26>; + node-name = "level2-nrt-wr2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_rd0: level2-rt-read0 { + cell-index = <27>; + node-name = "level2-rt-rd0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr0: level2-rt-wr0 { + cell-index = <28>; + node-name = "level2-rt-wr0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_rt_wr1: level2-rt-wr1 { + cell-index = <29>; + node-name = "level2-rt-wr1"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = ; + }; + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <30>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <31>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt_rd_wr_sum: level3-rt-rd-wr-sum { + cell-index = <32>; + node-name = "level3-rt-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + }; + + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0"; + num-icp = <1>; + num-ipe = <1>; + icp_use_pil; + status = "ok"; + }; + + qcom,cam-i3c-id-table { + compatible = "qcom,cam-i3c-id-table"; + i3c-sensor-id-table = <0x1B0 0x0766>; + i3c-eeprom-id-table = <>; + i3c-actuator-id-table = <>; + i3c-ois-id-table = <>; + status = "disabled"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "ok"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "ok"; + }; + + qcom,camera-main { + compatible = "qcom,camera"; + status = "ok"; + }; + + qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + force_cache_allocs; + status = "ok"; + + msm-cam-smmu-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0860 0x400>, + <&apps_smmu 0x0C60 0x400>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + rt_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x400>, + <&apps_smmu 0x0840 0x480>, + <&apps_smmu 0x08C0 0x480>, + <&apps_smmu 0x0C00 0x400>, + <&apps_smmu 0x0C40 0x480>, + <&apps_smmu 0x0CC0 0x480>; + cam-smmu-label = "icp"; + qcom,iommu-faults = "stall-disable", "non-fatal"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + subregion_support; + status = "ok"; + /* Used for HFI queues/sec heap */ + iova-mem-region-generic-region { + iova-region-name = "icp_hfi"; + iova-region-start = <0x10400000>; + iova-region-len = <0x200000>; + iova-region-id = <0x0>; + }; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "ok"; + }; + + iova-mem-region-qdss { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "ok"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xfc00000>; + iova-region-id = <0x1>; + status = "ok"; + }; + + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2400 0x0020>, + <&apps_smmu 0x2420 0x0020>; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + dma-coherent; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 64 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* start address: 0x100000 */ + /* leaving 1 MB pad at start */ + iova-region-start = <0x100000>; + /* Length: 0xfffe00000 */ + /* leaving 1 MB pad at end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "ok"; + }; + + cam_csid0: qcom,csid0 { + compatible = "qcom,csid692"; + reg = <0x0 0xac7a000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid0", "csid_top"; + reg-cam-base = <0x7a000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid1: qcom,csid1 { + compatible = "qcom,csid692"; + reg = <0x0 0xac7c000 0x0 0xf01>, + <0x0 0xac78000 0x0 0x1000>; + reg-names = "csid1", "csid_top"; + reg-cam-base = <0x7c000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0 { + compatible = "qcom,csid-lite692"; + reg = <0x0 0xac84000 0x0 0xf01>; + reg-names = "csid-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "ok"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1 { + compatible = "qcom,csid-lite692"; + reg = <0x0 0xac88000 0x0 0xf01>; + reg-names = "csid-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "ok"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite3: qcom,csid-lite3 { + cell-index = <5>; + compatible = "qcom,csid-lite692"; + reg-names = "csid-lite3"; + reg = <0x0 0xac90000 0x0 0xf01>; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "csid-lite3"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = + "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = + <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite3_opp_table>; + + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite2: qcom,csid-lite2 { + cell-index = <4>; + compatible = "qcom,csid-lite692"; + reg-names = "csid-lite2"; + reg = <0x0 0xac8c000 0x0 0xf01>; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "csid-lite2"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = + "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = + <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite2_opp_table>; + + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite4: qcom,csid-lite4 { + cell-index = <6>; + compatible = "qcom,csid-lite692"; + reg-names = "csid-lite4"; + reg = <0x0 0xac94000 0x0 0xf01>; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "csid-lite4"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = + "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = + <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite4_opp_table>; + + clock-control-debugfs = "true"; + status = "ok"; + + csid_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_icp: qcom,icp { + compatible = "qcom,cam-icp_v3_0"; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0xac04000 0x0 0x1000>; + reg-names ="icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + src-clock-name = "cam_cc_icp_clk_src"; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "cam_cc_soc_fast_ahb_clk_src", + "cam_cc_icp_ahb_clk", + "cam_cc_icp_clk_src", + "cam_cc_icp_clk"; + clock-rates = <300000000 0 480000000 0>, + <400000000 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + nrt-device; + fw_name = "CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + qos-val = <0xa0a>; + operating-points-v2 = <&icp_opp_table>; + icp-version = <0x0300>; + cam_hw_pid = <12>; + cell-index = <0>; + status = "ok"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0 { + compatible = "qcom,vfe692"; + reg = <0x0 0xac4d000 0x0 0xf000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife0", "cam_camnoc"; + reg-cam-base = <0x4d000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_0_clk", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_ife_0_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <8 16>; + cell-index = <0>; + status = "ok"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1 { + compatible = "qcom,vfe692"; + reg = <0x0 0xac60000 0x0 0xf000>, + <0x0 0xac1a000 0x0 0x9400>; + reg-names = "ife1", "cam_camnoc"; + reg-cam-base = <0x60000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>; + clock-names = "cam_cc_cpas_ife_1_clk", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_ife_1_fast_ahb_clk"; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <9 17>; + cell-index = <1>; + status = "ok"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac84000 0x0 0x1d00>; + reg-names = "ife-lite0"; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <2>; + status = "ok"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac88000 0x0 0x1d00>; + reg-names = "ife-lite1"; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <3>; + status = "ok"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite2: qcom,ife-lite2 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac8c000 0x0 0x1d00>; + reg-names = "ife-lite2"; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite2_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <4>; + status = "ok"; + + vfe_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite3: qcom,ife-lite3 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac90000 0x0 0x1d00>; + reg-names = "ife-lite3"; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite3_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <5>; + status = "ok"; + + vfe_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite4: qcom,ife-lite4 { + compatible = "qcom,vfe-lite692"; + reg = <0x0 0xac94000 0x0 0x1d00>; + reg-names = "ife-lite4"; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupts = ; + interrupt-names = "ife-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite4_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <6>; + status = "ok"; + + vfe_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0 { + compatible = "qcom,cam-ipe"; + reg = <0x0 0xac2d000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x2d000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + src-clock-name = "cam_cc_ipe_clk_src"; + clocks = <&camcc CAM_CC_CPAS_IPE_CLK>, + <&camcc CAM_CC_IPE_AHB_CLK>, + <&camcc CAM_CC_IPE_CLK>, + <&camcc CAM_CC_IPE_CLK_SRC>, + <&camcc CAM_CC_IPE_FAST_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>; + clock-names = "cam_cc_cpas_ipe_clk", + "cam_cc_ipe_ahb_clk", + "cam_cc_ipe_clk", + "cam_cc_ipe_clk_src", + "cam_cc_ipe_fast_ahb_clk", + "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 480000000 0 300000000>, + <0 0 0 600000000 0 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + operating-points-v2 = <&ipe0_opp_table>; + nrt-device; + cam_hw_pid = <14 15>; + cell-index = <0>; + status = "ok"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm0 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x1000>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table0>; + clock-cntl-level = "svs"; + cdm-client-names = "ife0", "dualife0"; + single-context-cdm; + cell-index = <0>; + status = "ok"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm1 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac27000 0x0 0x1000>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x27000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table1>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife1", "dualife1"; + single-context-cdm; + cell-index = <1>; + status = "ok"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm2 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac28000 0x0 0x1000>; + reg-names = "rt-cdm2"; + reg-cam-base = <0x28000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table2>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <2>; + status = "ok"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm3 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac29000 0x0 0x1000>; + reg-names = "rt-cdm3"; + reg-cam-base = <0x29000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table3>; + clock-cntl-level = "svs"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + cell-index = <3>; + status = "ok"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_sfe_lite0: qcom,sfe-lite0 { + compatible = "qcom,sfe-lite692"; + reg = <0x0 0xac74000 0x0 0x1000>; + reg-names = "sfe-lite0"; + reg-cam-base = <0x74000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_0_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_0_CLK>; + clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", + "cam_cc_sfe_lite_0_clk", + "cam_cc_cpas_sfe_lite_0_clk"; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_0_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table0>; + cam_hw_pid = <4>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "ok"; + + cam_sfe_lite_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe_lite1: qcom,sfe-lite1 { + compatible = "qcom,sfe-lite692"; + reg = <0x0 0xac75000 0x0 0x1000>; + reg-names = "sfe-lite1"; + reg-cam-base = <0x75000>; + rt-wrapper-base = <0x4d000>; + interrupts = ; + interrupt-names = "sfe-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_1_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_1_CLK>; + clock-names = "cam_cc_sfe_lite_1_fast_ahb_clk", + "cam_cc_sfe_lite_1_clk", + "cam_cc_cpas_sfe_1_clk"; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_1_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table1>; + cam_hw_pid = <5>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "ok"; + + cam_sfe_lite_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; +}; + +&tlmm { + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* MCLK0 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* MCLK0 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio69"; + function = "cam_mclk"; + }; + + config { + pins = "gpio69"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio69"; + function = "cam_mclk"; + }; + + config { + pins = "gpio69"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl0_active: cci-i2c-scl0-active { + mux { + /* CLK, DATA */ + pins = "gpio58"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio58"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl0_suspend: cci-i2c-scl0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio58"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio58"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_active: cci-i2c-scl1-active { + mux { + /* CLK, DATA */ + pins = "gpio30"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio30"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl1_suspend: cci-i2c-scl1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio30"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio30"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl2_active: cci-i2c-scl2-active { + mux { + /* CLK, DATA */ + pins = "gpio60"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio60"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl2_suspend: cci-i2c-scl2-suspend { + mux { + /* CLK, DATA */ + pins = "gpio60"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio60"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl3_active: cci-i2c-scl3-active { + mux { + pins = "gpio32"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio32"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl3_suspend: cci-i2c-scl3-suspend { + mux { + pins = "gpio32"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio32"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl4_active: cci-i2c-scl4-active { + mux { + /* CLK, DATA */ + pins = "gpio62"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio62"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl4_suspend: cci-i2c-scl4-suspend { + mux { + /* CLK, DATA */ + pins = "gpio62"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio62"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl5_active: cci-i2c-scl5-active { + mux { + /* CLK, DATA */ + pins = "gpio55"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio55"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl5_suspend: cci-i2c-scl5-suspend { + mux { + /* CLK, DATA */ + pins = "gpio55"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio55"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda0_active: cci-i2c-sda0-active { + mux { + /* CLK, DATA */ + pins = "gpio57"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio57"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda0_suspend: cci-i2c-sda0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio57"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio57"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_active: cci-i2c-sda1-active { + mux { + /* CLK, DATA */ + pins = "gpio29"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio29"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda1_suspend: cci-i2c-sda1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio29"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio29"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda2_active: cci-i2c-sda2-active { + mux { + /* CLK, DATA */ + pins = "gpio59"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio59"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda2_suspend: cci-i2c-sda2-suspend { + mux { + /* CLK, DATA */ + pins = "gpio59"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio59"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda3_active: cci-i2c-sda3-active { + mux { + pins = "gpio31"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio31"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda3_suspend: cci-i2c-sda3-suspend { + mux { + pins = "gpio31"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio31"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda4_active: cci-i2c-sda4-active { + mux { + /* CLK, DATA */ + pins = "gpio61"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio61"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda4_suspend: cci-i2c-sda4-suspend { + mux { + /* CLK, DATA */ + pins = "gpio61"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio61"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda5_active: cci-i2c-sda5-active { + mux { + /* CLK, DATA */ + pins = "gpio54"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio54"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda5_suspend: cci-i2c-sda5-suspend { + mux { + /* CLK, DATA */ + pins = "gpio54"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio54"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi new file mode 100644 index 0000000000000..167b85c0e8844 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi @@ -0,0 +1,794 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "ok"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; + + /*cam0-ov9282*/ + rb4_slot0: qcom,cam-sensor16 { + compatible = "qcom,cam-sensor"; + cell-index = <16>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 73 0>, + <&expander2 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0-imx577*/ + qcom,cam-sensor20 { + compatible = "qcom,cam-sensor"; + cell-index = <20>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam20>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 73 0>, + <&expander2 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam20: qcom,eeprom20 { + cell-index = <20>; + compatible = "qcom,eeprom"; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 73 0>, + <&expander2 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + status = "ok"; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "ok"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; + + /*cam1-ov9282*/ + rb4_slot1: qcom,cam-sensor17 { + compatible = "qcom,cam-sensor"; + cell-index = <17>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0-imx577*/ + qcom,cam-sensor19 { + compatible = "qcom,cam-sensor"; + cell-index = <19>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam19>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam0-imx577*/ + qcom,cam-sensor21 { + compatible = "qcom,cam-sensor"; + cell-index = <21>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam21>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam19: qcom,eeprom19 { + compatible = "qcom,eeprom"; + cell-index = <19>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam21: qcom,eeprom21 { + compatible = "qcom,eeprom"; + cell-index = <21>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 68 0>, + <&tlmm 74 0>, + <&expander2 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 75 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <0>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <1>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "ok"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; + + /*cam2-ov9282*/ + rb4_slot2: qcom,cam-sensor18 { + compatible = "qcom,cam-sensor"; + cell-index = <18>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 75 0>, + <&expander2 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + /*cam2-imx577*/ + qcom,cam-sensor22 { + compatible = "qcom,cam-sensor"; + cell-index = <22>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam22>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 75 0>, + <&expander2 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; + + eeprom_cam22: qcom,eeprom22 { + compatible = "qcom,eeprom"; + cell-index = <22>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 69 0>, + <&tlmm 75 0>, + <&expander2 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "ok"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "ok"; + gpios-shared = <609 610 611>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso new file mode 100644 index 0000000000000..3945c77528ccb --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "monaco-camera.dtsi" +#include "monaco-evk-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET */ + mux { + pins = "gpio73"; + function = "gpio"; + }; + + config { + pins = "gpio73"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio74"; + function = "gpio"; + }; + + config { + pins = "gpio74"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + + config { + pins = "gpio75"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET */ + mux { + pins = "gpio73"; + function = "gpio"; + }; + + config { + pins = "gpio73"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio74"; + function = "gpio"; + }; + config { + pins = "gpio74"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + config { + pins = "gpio75"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/qcs8300-ride-camx.dtso b/arch/arm64/boot/dts/qcom/qcs8300-ride-camx.dtso new file mode 100644 index 0000000000000..8f26e6dc070b0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs8300-ride-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "monaco-camera.dtsi" +#include "monaco-camera-sensor.dtsi" From 6b16e04657c060e9c50ee5f06c7048bde40c8172 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Thu, 30 Oct 2025 00:58:58 +0530 Subject: [PATCH 0693/1133] PENDING: arm64: dts: qcom: qcs8300: Update camera PIL region to 7MB The camera firmware size for IoT variant qcs8300 SoC is more than 5MB. Update the PIL memory region size of camera to 7MB to accomodate the same. Signed-off-by: Umang Chheda --- arch/arm64/boot/dts/qcom/monaco.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 35fbee63d4c65..e698d3c759551 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -763,7 +763,7 @@ }; camera_mem: camera-region@95200000 { - reg = <0x0 0x95200000 0x0 0x500000>; + reg = <0x0 0x95200000 0x0 0x700000>; no-map; }; From 7880fba00e815e09727827884a427797e9bd54f7 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 27 Oct 2025 23:48:22 +0530 Subject: [PATCH 0694/1133] QCLINUX: arm64: dts: qcom: Update rbgen2 camx overlay dts - Fix the indentation issue. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi index f6af6827784bd..37ea48e35d09c 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi @@ -620,8 +620,8 @@ qcom,cam-icp { compatible = "qcom,cam-icp"; compat-hw-name = "qcom,a5", - "qcom,ipe0", - "qcom,bps"; + "qcom,ipe0", + "qcom,bps"; num-a5 = <1>; num-ipe = <1>; num-bps = <1>; @@ -643,7 +643,7 @@ qcom,cam-jpeg { compatible = "qcom,cam-jpeg"; compat-hw-name = "qcom,jpegenc", - "qcom,jpegdma"; + "qcom,jpegdma"; num-jpeg-enc = <1>; num-jpeg-dma = <1>; status = "ok"; From bd8db510e2c3c5b9893c7f077b9d2df858512882 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 27 Oct 2025 23:42:23 +0530 Subject: [PATCH 0695/1133] QCLINUX: arm64: dts: qcom: Update Monaco camx overlay dts - Fix the indentation issue. - Update DT clock property name after clock. - Short DT nodes. - Fix indexing issue. - Update gpios shared pin. Signed-off-by: Chandan Kumar Jha --- .../boot/dts/qcom/monaco-camera-sensor.dtsi | 2 +- arch/arm64/boot/dts/qcom/monaco-camera.dtsi | 204 +++++++++--------- 2 files changed, 100 insertions(+), 106 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi index 0023c97edce91..a2a2cd0a27a3a 100644 --- a/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-camera-sensor.dtsi @@ -374,7 +374,7 @@ &soc { qcom,cam-res-mgr { compatible = "qcom,cam-res-mgr"; - gpios-shared = <518 519 520 521>; + gpios-shared = <609 610 611>; status = "ok"; }; }; diff --git a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi index bd619b507831f..f72161e75f7e7 100644 --- a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi @@ -565,8 +565,8 @@ "cam_cc_qdss_debug_xo_clk"; src-clock-name = "cam_cc_fast_ahb_clk_src"; clock-rates = <0 0 0 0 0 0 0 0 0 0 0>, - <0 0 0 80000000 0 0 300000000 0 400000000 0 0>, - <0 0 0 80000000 0 0 400000000 0 400000000 0 0>; + <0 0 0 80000000 0 0 300000000 0 400000000 0 0>, + <0 0 0 80000000 0 0 400000000 0 400000000 0 0>; clock-cntl-level = "suspend", "svs_l1", "nominal"; clock-names-option = "cam_icp_clk"; clocks-option = <&camcc CAM_CC_ICP_CLK>; @@ -679,7 +679,7 @@ }; ife_1_wr_1: ife-1-wr-1 { - cell-index = <3>; + cell-index = <4>; node-name = "ife-1-wr-1"; client-name = "ife1"; traffic-data = ; @@ -693,7 +693,7 @@ }; ife_lite_0_wr_0: ife-lite-0-wr-0 { - cell-index = <4>; + cell-index = <5>; node-name = "ife-lite-0-wr-0"; client-name = "ife2"; traffic-data = ; @@ -707,7 +707,7 @@ }; ife_lite_1_wr_0: ife-lite-1-wr-0 { - cell-index = <5>; + cell-index = <6>; node-name = "ife-lite-1-wr-0"; client-name = "ife3"; traffic-data = ; @@ -721,7 +721,7 @@ }; ife_lite_2_wr_0: ife-lite-2-wr-0 { - cell-index = <6>; + cell-index = <7>; node-name = "ife-lite-2-wr-0"; client-name = "ife4"; traffic-data = ; @@ -735,7 +735,7 @@ }; ife_lite_3_wr_0: ife-lite-3-wr-0 { - cell-index = <7>; + cell-index = <8>; node-name = "ife-lite-3-wr-0"; client-name = "ife5"; traffic-data = ; @@ -749,7 +749,7 @@ }; ife_lite_4_wr_0: ife-lite-4-wr-0 { - cell-index = <8>; + cell-index = <9>; node-name = "ife-lite-4-wr-0"; client-name = "ife6"; traffic-data = ; @@ -763,7 +763,7 @@ }; ipe_0_rd_all: ipe-0-rd-all { - cell-index = <9>; + cell-index = <10>; node-name = "ipe-0-rd-all"; client-name = "ipe0"; traffic-data = ; @@ -774,7 +774,7 @@ }; ipe_0_wr_2: ipe-0-wr-2 { - cell-index = <10>; + cell-index = <11>; node-name = "ipe-0-wr-2"; client-name = "ipe0"; traffic-data = ; @@ -787,7 +787,7 @@ }; ipe_cdm0_all_rd: ipe-cdm0-all-rd { - cell-index = <11>; + cell-index = <12>; node-name = "ipe-cdm0-all-rd"; client-name = "ipe0"; traffic-data = ; @@ -796,7 +796,7 @@ }; rt_cdm0_all_rd_2: rt-cdm0-all-rd-2 { - cell-index = <12>; + cell-index = <13>; node-name = "rt-cdm0-all-rd-2"; client-name = "rt-cdm0"; traffic-data = ; @@ -805,7 +805,7 @@ }; rt_cdm1_all_rd_2: rt-cdm1-all-rd-2 { - cell-index = <13>; + cell-index = <14>; node-name = "rt-cdm1-all-rd-2"; client-name = "rt-cdm1"; traffic-data = ; @@ -814,7 +814,7 @@ }; rt_cdm2_all_rd_2: rt-cdm2-all-rd-2 { - cell-index = <14>; + cell-index = <15>; node-name = "rt-cdm2-all-rd-2"; client-name = "rt-cdm2"; traffic-data = ; @@ -823,7 +823,7 @@ }; rt_cdm3_all_rd_2: rt-cdm3-all-rd-2 { - cell-index = <15>; + cell-index = <16>; node-name = "rt-cdm3-all-rd-2"; client-name = "rt-cdm3"; traffic-data = ; @@ -832,7 +832,7 @@ }; sfe_0_rd_0: sfe-0-rd-0 { - cell-index = <16>; + cell-index = <17>; node-name = "sfe-0-rd-0"; client-name = "sfe0"; traffic-data = ; @@ -842,7 +842,7 @@ }; sfe_1_rd_0: sfe-1-rd-0 { - cell-index = <17>; + cell-index = <18>; node-name = "sfe-1-rd-0"; client-name = "sfe1"; traffic-data = ; @@ -857,28 +857,28 @@ camnoc-max-needed; level1_nrt_rd2: level1-nrt-rd2 { - cell-index = <22>; + cell-index = <19>; node-name = "level1-nrt-rd2"; parent-node = <&level2_nrt_rd2>; traffic-merge-type = ; }; level1_rt_rd0: level1-rt-read0 { - cell-index = <21>; + cell-index = <20>; node-name = "level1-rt-rd0"; parent-node = <&level2_rt_rd0>; traffic-merge-type = ; }; level1_rt_wr0: level1-rt-wr0 { - cell-index = <19>; + cell-index = <21>; node-name = "level1-rt-wr0"; parent-node = <&level2_rt_wr0>; traffic-merge-type = ; }; level1_rt_wr1: level1-rt-wr1 { - cell-index = <20>; + cell-index = <22>; node-name = "level1-rt-wr1"; parent-node = <&level2_rt_wr1>; traffic-merge-type = ; @@ -978,8 +978,7 @@ qcom,cam-icp { compatible = "qcom,cam-icp"; - compat-hw-name = "qcom,icp", - "qcom,ipe0"; + compat-hw-name = "qcom,icp", "qcom,ipe0"; num-icp = <1>; num-ipe = <1>; icp_use_pil; @@ -1023,6 +1022,7 @@ cam-smmu-label = "rt-cdm"; dma-coherent; multiple-client-devices; + rt_cdm_iova_mem_map: iova-mem-map { iova-mem-region-io { /* IO region is approximately 4.0 GB */ @@ -1059,6 +1059,7 @@ iova-region-id = <0x6>; subregion_support; status = "ok"; + /* Used for HFI queues/sec heap */ iova-mem-region-generic-region { iova-region-name = "icp_hfi"; @@ -1096,7 +1097,6 @@ iova-region-id = <0x1>; status = "ok"; }; - }; }; @@ -1298,49 +1298,46 @@ }; }; - cam_csid_lite3: qcom,csid-lite3 { - cell-index = <5>; + cam_csid_lite2: qcom,csid-lite2 { compatible = "qcom,csid-lite692"; - reg-names = "csid-lite3"; - reg = <0x0 0xac90000 0x0 0xf01>; - reg-cam-base = <0x90000>; + reg = <0x0 0xac8c000 0x0 0xf01>; + reg-names = "csid-lite2"; + reg-cam-base = <0x8c000>; rt-wrapper-base = <0x83000>; - interrupt-names = "csid-lite3"; - interrupts = ; + interrupts = ; + interrupt-names = "csid-lite2"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - clock-names = - "cam_cc_cpas_ife_lite_clk", - "cam_cc_ife_lite_ahb_clk", - "cam_cc_ife_lite_csid_clk_src", - "cam_cc_ife_lite_csid_clk", - "cam_cc_ife_lite_cphy_rx_clk", - "cam_cc_ife_lite_clk_src", - "cam_cc_ife_lite_clk"; - clocks = - <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, - <&camcc CAM_CC_IFE_LITE_AHB_CLK>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK>, - <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, - <&camcc CAM_CC_IFE_LITE_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CLK>; - clock-rates = - <0 0 400000000 0 0 400000000 0>, - <0 0 400000000 0 0 480000000 0>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; clock-cntl-level = "svs_l1", "nominal"; src-clock-name = "cam_cc_ife_lite_csid_clk_src"; - operating-points-v2 = <&csid_lite3_opp_table>; - + operating-points-v2 = <&csid_lite2_opp_table>; clock-control-debugfs = "true"; + cell-index = <4>; status = "ok"; - csid_lite3_opp_table: opp-table { + csid_lite2_opp_table: opp-table { compatible = "operating-points-v2"; opp-400000000 { opp-hz = /bits/ 64 <400000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-480000000 { opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_nom>; @@ -1348,49 +1345,46 @@ }; }; - cam_csid_lite2: qcom,csid-lite2 { - cell-index = <4>; + cam_csid_lite3: qcom,csid-lite3 { compatible = "qcom,csid-lite692"; - reg-names = "csid-lite2"; - reg = <0x0 0xac8c000 0x0 0xf01>; - reg-cam-base = <0x8c000>; + reg = <0x0 0xac90000 0x0 0xf01>; + reg-names = "csid-lite3"; + reg-cam-base = <0x90000>; rt-wrapper-base = <0x83000>; - interrupt-names = "csid-lite2"; - interrupts = ; + interrupts = ; + interrupt-names = "csid-lite3"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - clock-names = - "cam_cc_cpas_ife_lite_clk", - "cam_cc_ife_lite_ahb_clk", - "cam_cc_ife_lite_csid_clk_src", - "cam_cc_ife_lite_csid_clk", - "cam_cc_ife_lite_cphy_rx_clk", - "cam_cc_ife_lite_clk_src", - "cam_cc_ife_lite_clk"; - clocks = - <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, - <&camcc CAM_CC_IFE_LITE_AHB_CLK>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK>, - <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, - <&camcc CAM_CC_IFE_LITE_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CLK>; - clock-rates = - <0 0 400000000 0 0 400000000 0>, - <0 0 400000000 0 0 480000000 0>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; clock-cntl-level = "svs_l1", "nominal"; src-clock-name = "cam_cc_ife_lite_csid_clk_src"; - operating-points-v2 = <&csid_lite2_opp_table>; - + operating-points-v2 = <&csid_lite3_opp_table>; clock-control-debugfs = "true"; + cell-index = <5>; status = "ok"; - csid_lite2_opp_table: opp-table { + csid_lite3_opp_table: opp-table { compatible = "operating-points-v2"; opp-400000000 { opp-hz = /bits/ 64 <400000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-480000000 { opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_nom>; @@ -1399,39 +1393,35 @@ }; cam_csid_lite4: qcom,csid-lite4 { - cell-index = <6>; compatible = "qcom,csid-lite692"; - reg-names = "csid-lite4"; reg = <0x0 0xac94000 0x0 0xf01>; + reg-names = "csid-lite4"; reg-cam-base = <0x94000>; rt-wrapper-base = <0x83000>; - interrupt-names = "csid-lite4"; interrupts = ; + interrupt-names = "csid-lite4"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - clock-names = - "cam_cc_cpas_ife_lite_clk", - "cam_cc_ife_lite_ahb_clk", - "cam_cc_ife_lite_csid_clk_src", - "cam_cc_ife_lite_csid_clk", - "cam_cc_ife_lite_cphy_rx_clk", - "cam_cc_ife_lite_clk_src", - "cam_cc_ife_lite_clk"; - clocks = - <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, - <&camcc CAM_CC_IFE_LITE_AHB_CLK>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK>, - <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, - <&camcc CAM_CC_IFE_LITE_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CLK>; - clock-rates = - <0 0 400000000 0 0 400000000 0>, - <0 0 400000000 0 0 480000000 0>; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; clock-cntl-level = "svs_l1", "nominal"; src-clock-name = "cam_cc_ife_lite_csid_clk_src"; operating-points-v2 = <&csid_lite4_opp_table>; - clock-control-debugfs = "true"; + cell-index = <6>; status = "ok"; csid_lite4_opp_table: opp-table { @@ -1441,6 +1431,7 @@ opp-hz = /bits/ 64 <400000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-480000000 { opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_nom>; @@ -1489,6 +1480,7 @@ opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-600000000 { opp-hz = /bits/ 64 <600000000>; required-opps = <&rpmhpd_opp_nom>; @@ -1532,6 +1524,7 @@ opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-600000000 { opp-hz = /bits/ 64 <600000000>; required-opps = <&rpmhpd_opp_nom>; @@ -1575,6 +1568,7 @@ opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_svs_l1>; }; + opp-600000000 { opp-hz = /bits/ 64 <600000000>; required-opps = <&rpmhpd_opp_nom>; From 42ade63d6d24292dc987d4d2cd7e820ca82b512a Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 27 Oct 2025 23:36:51 +0530 Subject: [PATCH 0696/1133] QCLINUX: arm64: dts: qcom: Update Lemans camx overlay dts - Fix the indentation issue. - Update DT clock property name after clock. - Shorted DT nodes. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/lemans-camera.dtsi | 43 +++++++++------------ 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi index 18d78926b1f17..855d29dff618f 100644 --- a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi @@ -743,7 +743,6 @@ "ife5", "ife6", "ipe0", "sfe0", "sfe1", "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", "rt-cdm3", "icp0", "tpg17", "tpg18", "tpg19"; - enable-secure-qos-update; cell-index = <0>; status = "ok"; @@ -817,7 +816,6 @@ parent-node = <&level1_rt_wr0>; }; - ife_1_wr_1: ife-1-wr-1 { cell-index = <4>; node-name = "ife-1-wr-1"; @@ -958,8 +956,7 @@ node-name = "rt-cdm2-all-rd-2"; client-name = "rt-cdm2"; traffic-data = ; - traffic-transaction-type = - ; + traffic-transaction-type = ; parent-node = <&level1_nrt_rd2>; }; @@ -1086,8 +1083,7 @@ level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { cell-index = <30>; node-name = "level3-nrt0-rd-wr-sum"; - traffic-merge-type = - ; + traffic-merge-type = ; qcom,axi-port-mnoc { cam-icc-path-names = "cam_sf_0"; @@ -1097,8 +1093,7 @@ level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { cell-index = <31>; node-name = "level3-nrt1-rd-wr-sum"; - traffic-merge-type = - ; + traffic-merge-type = ; qcom,axi-port-mnoc { cam-icc-path-names = "cam_sf_icp"; @@ -1108,8 +1103,7 @@ level3_rt_rd_wr_sum: level3-rt-rd-wr-sum { cell-index = <32>; node-name = "level3-rt-rd-wr-sum"; - traffic-merge-type = - ; + traffic-merge-type = ; ib-bw-voting-needed; qcom,axi-port-mnoc { @@ -1148,8 +1142,8 @@ status = "ok"; }; - qcom,cam-sync { - compatible = "qcom,cam-sync"; + qcom,camera-main { + compatible = "qcom,camera"; status = "ok"; }; @@ -1274,8 +1268,8 @@ }; }; - qcom,camera-main { - compatible = "qcom,camera"; + qcom,cam-sync { + compatible = "qcom,cam-sync"; status = "ok"; }; @@ -1544,13 +1538,6 @@ interrupts = ; interrupt-names = "csid-lite4"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - clock-names = "cam_cc_cpas_ife_lite_clk", - "cam_cc_ife_lite_ahb_clk", - "cam_cc_ife_lite_csid_clk_src", - "cam_cc_ife_lite_csid_clk", - "cam_cc_ife_lite_cphy_rx_clk", - "cam_cc_ife_lite_clk_src", - "cam_cc_ife_lite_clk"; clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, <&camcc CAM_CC_IFE_LITE_AHB_CLK>, <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, @@ -1558,6 +1545,13 @@ <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, <&camcc CAM_CC_IFE_LITE_CLK_SRC>, <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; clock-rates = <0 0 400000000 0 0 400000000 0>, <0 0 400000000 0 0 480000000 0>; clock-cntl-level = "svs_l1", "nominal"; @@ -2000,7 +1994,6 @@ required-opps = <&rpmhpd_opp_nom>; }; }; - }; qcom,rt-cdm0 { @@ -2140,12 +2133,12 @@ interrupts = ; interrupt-names = "sfe-lite0"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", - "cam_cc_sfe_lite_0_clk", - "cam_cc_cpas_sfe_lite_0_clk"; clocks = <&camcc CAM_CC_SFE_LITE_0_FAST_AHB_CLK>, <&camcc CAM_CC_SFE_LITE_0_CLK>, <&camcc CAM_CC_CPAS_SFE_LITE_0_CLK>; + clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", + "cam_cc_sfe_lite_0_clk", + "cam_cc_cpas_sfe_lite_0_clk"; clock-rates = <0 480000000 300000000>, <0 600000000 400000000>; clock-cntl-level = "svs_l1", "nominal"; From b4ad509ff608743988395f4eeca28494ccc17d91 Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Wed, 24 Dec 2025 14:00:56 +0800 Subject: [PATCH 0697/1133] PENDING: arm64: dts: qcom: change pil camera memory map Add the pil camera carveout region based on v2 memory map. Signed-off-by: Qingqing Zhou Signed-off-by: Xin Liu --- arch/arm64/boot/dts/qcom/talos.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi index 8ed6f2755705c..5cd2397950470 100644 --- a/arch/arm64/boot/dts/qcom/talos.dtsi +++ b/arch/arm64/boot/dts/qcom/talos.dtsi @@ -686,6 +686,11 @@ alignment = <0x0 0x400000>; size = <0x0 0x800000>; }; + + pil_camera_mem: pil-camera-region@97717000 { + reg = <0x0 0x97717000 0x0 0x800000>; + no-map; + }; }; soc: soc@0 { From 7dafc414d236f7435cc89f5f4fb26ccb255cd2d0 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 24 Dec 2025 16:16:57 +0530 Subject: [PATCH 0698/1133] QCLINUX: arm64: dts: qcom: Add Talos camx overlay dts Add CAMX overlay dts file for Talos boards. This change also enables the compilation of the CAMX overlay on Talos boards. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 4 + .../arm64/boot/dts/qcom/qcs615-ride-camx.dtso | 16 + .../boot/dts/qcom/talos-camera-sensor.dtsi | 152 ++ arch/arm64/boot/dts/qcom/talos-camera.dtsi | 1984 +++++++++++++++++ 4 files changed, 2156 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs615-ride-camx.dtso create mode 100644 arch/arm64/boot/dts/qcom/talos-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/talos-camera.dtsi diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 375dec517cc0e..353e447392598 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -532,6 +532,10 @@ monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb +qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb + qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ qcs6490-rb3gen2-vision-mezzanine-camx.dtbo diff --git a/arch/arm64/boot/dts/qcom/qcs615-ride-camx.dtso b/arch/arm64/boot/dts/qcom/qcs615-ride-camx.dtso new file mode 100644 index 0000000000000..a40d8817a7a20 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs615-ride-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "talos-camera.dtsi" +#include "talos-camera-sensor.dtsi" diff --git a/arch/arm64/boot/dts/qcom/talos-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/talos-camera-sensor.dtsi new file mode 100644 index 0000000000000..7e76197614781 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-camera-sensor.dtsi @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci { + /*cam0-imx577*/ + tl_slot0: qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam0>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 28 0>, + <&tlmm 75 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; + + /*cam1-imx577*/ + t1_slot1: qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam1>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst1>; + gpios = <&tlmm 30 0>, + <&tlmm 29 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK1", "CAMIF_RESET1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; + + /*cam0-imx577-eeprom*/ + eeprom_cam0: qcom,eeprom0 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 28 0>, + <&tlmm 75 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; + + /*cam1-imx577-eeprom*/ + eeprom_cam1: qcom,eeprom1 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 30 0>, + <&tlmm 29 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK1", "CAMIF_RESET1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "ok"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/talos-camera.dtsi b/arch/arm64/boot/dts/qcom/talos-camera.dtsi new file mode 100644 index 0000000000000..e2daa14db1e80 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-camera.dtsi @@ -0,0 +1,1984 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac00000 { + compatible = "qcom,cam-icp_v1"; + icp-version = <0x0100>; + reg = <0x0 0xac00000 0x0 0x6000>, + <0x0 0xac10000 0x0 0x8000>, + <0x0 0xac18000 0x0 0x3000>; + reg-names = "icp_qgic", "icp_sierra", "icp_csr"; + reg-cam-base = <0x00000 0x10000 0x18000>; + interrupts = ; + interrupt-names = "a5"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_ICP_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_icp_clk", + "cam_cc_icp_clk_src"; + clock-rates = <0 0 100000000 0 0 0 0 240000000>, + <0 0 200000000 0 0 0 0 360000000>, + <0 0 300000000 0 0 0 0 432000000>, + <0 0 404000000 0 0 0 0 480000000>, + <0 0 404000000 0 0 0 0 540000000>, + <0 0 404000000 0 0 0 0 600000000>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_icp_clk_src"; + operating-points-v2 = <&a5_opp_table>; + fw_name = "CAMERA_ICP.elf"; + ubwc-cfg = <0x73 0x1CF>; + cam_hw_pid = <15>; + cell-index = <0>; + status = "okay"; + + a5_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + qcom,cam-cpas@ac40000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac40000 0x0 0x1000>, + <0x0 0xac42000 0x0 0x5000>; + reg-names = "cam_cpas_top", "cam_camnoc"; + reg-cam-base = <0x40000 0x42000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk"; + clock-rates = <0 0 0 0 0 0>, + <0 0 0 80000000 0 150000000>, + <0 0 0 80000000 0 240000000>, + <0 0 0 80000000 0 265000000>, + <0 0 0 80000000 0 355000000>, + <0 0 0 80000000 0 426000000>; + clock-cntl-level = "suspend", "lowsvs", "svs", + "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_camnoc_axi_clk"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_HF1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cam_ahb", + "cam_hf_0_mnoc", + "cam_hf_1_mnoc", + "cam_sf_0_mnoc"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", + "svs_l1", "nominal", "nominal", + "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "cci0", + "csid0", "csid1", "csid2","ife0", + "ife1", "ife2", "ipe0", "cam-cdm-intf0", + "cpas-cdm0", "bps0", "icp0", "jpeg-dma0", + "jpeg-enc0", "lrmecpas0"; + cell-index = <0>; + status = "okay"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-265000000 { + opp-hz = /bits/ 64 <265000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-355000000 { + opp-hz = /bits/ 64 <355000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-426000000 { + opp-hz = /bits/ 64 <426000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + cpas_cdm0_all_rd: cpas-cdm0-all-rd { + cell-index = <2>; + node-name = "cpas-cdm0-all-rd"; + client-name = "cpas-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read2>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <3>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read3>; + }; + + ife0_linear_pdaf_wr: ife0-linear-pdaf-wr { + cell-index = <4>; + node-name = "ife0-linear-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife0_ubwc_stats_wr: ife0-ubwc-stats-wr { + cell-index = <6>; + node-name = "ife0-ubwc-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ife1_linear_pdaf_wr: ife1-linear-pdaf-wr { + cell-index = <7>; + node-name = "ife1-linear-pdaf-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife1_rdi_pixel_raw_wr: ife1-rdi-pixel-raw-wr { + cell-index = <8>; + node-name = "ife1-rdi-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife1_ubwc_stats_wr: ife1-ubwc-stats-wr { + cell-index = <9>; + node-name = "ife1-ubwc-stats-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_write0>; + }; + + ife2_rdi_wr: ife2-rdi-wr { + cell-index = <10>; + node-name = "ife2-rdi-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_write0>; + }; + + ipe0_all_rd: ipe0-all-rd { + cell-index = <11>; + node-name = "ipe0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_read0>; + }; + + ipe0_ref_wr: ipe0-ref-wr { + cell-index = <12>; + node-name = "ipe0-ref-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + + ipe0_viddisp_wr: ipe0-viddisp-wr { + cell-index = <13>; + node-name = "ipe0-viddisp-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_write0>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <14>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = + ; + parent-node = <&level1_nrt0_read1>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <15>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write1>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <16>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read1>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <17>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write1>; + }; + + lrme0_all_rd: lrme0-all-rd { + cell-index = <18>; + node-name = "lrme0-all-rd"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_read0>; + }; + + lrme0_all_wr: lrme0-all-wr { + cell-index = <19>; + node-name = "lrme0-all-wr"; + client-name = "lrmecpas0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_write0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_read0: level1-nrt0-read0 { + cell-index = <20>; + node-name = "level1-nrt0-read0"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_read1: level1-nrt0-read1 { + cell-index = <21>; + node-name = "level1-nrt0-read1"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_read2: level1-nrt0-read2 { + cell-index = <22>; + node-name = "level1-nrt0-read2"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_read3: level1-nrt0-read3 { + cell-index = <23>; + node-name = "level1-nrt0-read3"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_write0: level1-nrt0-write0 { + cell-index = <24>; + node-name = "level1-nrt0-write0"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_nrt0_write1: level1-nrt0-write1 { + cell-index = <25>; + node-name = "level1-nrt0-write1"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_rt0_write0: level1-rt0-write0 { + cell-index = <26>; + node-name = "level1-rt0-write0"; + parent-node = <&level2_rt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_rt1_write0: level1-rt1-write0 { + cell-index = <27>; + node-name = "level1-rt1-write0"; + parent-node = <&level2_rt1_rd_wr_sum>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + + level2_nrt0_rd_wr_sum: level2-nrt0-rd-wr-sum { + cell-index = <28>; + node-name = "level2-nrt0-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0_mnoc"; + }; + }; + + level2_rt0_rd_wr_sum: level2-rt0-rd-wr-sum { + cell-index = <29>; + node-name = "level2-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0_mnoc"; + }; + }; + + level2_rt1_rd_wr_sum: level2-rt1-rd-wr-sum { + cell-index = <30>; + node-name = "level3-rt1-rd-wr-sum"; + traffic-merge-type = ; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_1_mnoc"; + }; + }; + }; + }; + }; + + qcom,cpas-cdm0@ac48000 { + compatible = "qcom,cam170-cpas-cdm0"; + label = "cpas-cdm"; + reg = <0x0 0xac48000 0x0 0x1000>; + reg-names = "cpas-cdm"; + reg-cam-base = <0x48000>; + interrupts = ; + interrupt-names = "cpas-cdm"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_slow_ahb_clk_src"; + clock-rates = <0 0 0 0 0 80000000>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + operating-points-v2 = <&cpas_cdm_opp_table>; + clock-cntl-level = "svs"; + cdm-client-names = "ife0", "ife1", "ife2", + "ife3", "dualife"; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cpas_cdm_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_cci: qcom,cci@ac4a000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac4a000 0x0 0x4000>; + reg-names = "cci"; + reg-cam-base = <0x4a000>; + interrupts = ; + interrupt-names = "CCI"; + operating-points-v2 = <&cci_opp_table>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_CLK_SRC>, + <&camcc CAM_CC_CCI_CLK>; + clock-names = "cci_clk_src", + "cci_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <0>; + status = "okay"; + + cci_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci: qcom,i2c-custom-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac4e000 { + compatible = "qcom,cam_jpeg_enc_170"; + reg = <0x0 0xac4e000 0x0 0x4000>; + reg-names = "jpege_hw"; + reg-cam-base = <0x4e000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_jpeg_clk_src", + "cam_cc_jpeg_clk"; + clock-rates = <0 0 0 0 0 600000000 0>; + src-clock-name = "cam_cc_jpeg_clk_src"; + operating-points-v2 = <&jpeg_enc_opp_table>; + clock-cntl-level = "turbo"; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac52000{ + compatible = "qcom,cam_jpeg_dma_170"; + reg = <0x0 0xac52000 0x0 0x4000>; + reg-names = "jpegdma_hw"; + reg-cam-base = <0x52000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_jpeg_clk_src", + "cam_cc_jpeg_clk"; + clock-rates = <0 0 0 0 0 600000000 0>; + src-clock-name = "cam_cc_jpeg_clk_src"; + operating-points-v2 = <&jpeg_dma_opp_table>; + clock-cntl-level = "turbo"; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy@ac65000 { + compatible = "qcom,csiphy-v2.0.0", "qcom,csiphy"; + reg = <0x0 0x0ac65000 0x0 0x1000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy0_opp_table>; + reg-cam-base = <0x65000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + csi-vdd-voltage = <1200000>; + mipi-csi-vdd-supply = <&vreg_l11a>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "camnoc_axi_clk", + "soc_ahb_clk", + "slow_ahb_src_clk", + "cpas_ahb_clk", + "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "svs_l1", "turbo"; + clock-rates = <0 0 0 0 269333333 0 269333333 0>, + <0 0 0 0 384000000 0 269333333 0>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-269333333 { + opp-hz = /bits/ 64 <269333333>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy@ac66000 { + compatible = "qcom,csiphy-v2.0.0", "qcom,csiphy"; + reg = <0x0 0xac66000 0x0 0x1000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy1_opp_table>; + reg-cam-base = <0x66000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + csi-vdd-voltage = <1200000>; + mipi-csi-vdd-supply = <&vreg_l11a>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "camnoc_axi_clk", + "soc_ahb_clk", + "slow_ahb_src_clk", + "cpas_ahb_clk", + "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "svs_l1", "turbo"; + clock-rates = <0 0 0 0 269333333 0 269333333 0>, + <0 0 0 0 384000000 0 269333333 0>; + cell-index = <1>; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-269333333 { + opp-hz = /bits/ 64 <269333333>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy@ac67000 { + compatible = "qcom,csiphy-v2.0.0", "qcom,csiphy"; + reg = <0x0 0xac67000 0x0 0x1000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy2_opp_table>; + reg-cam-base = <0x67000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + csi-vdd-voltage = <1200000>; + mipi-csi-vdd-supply = <&vreg_l11a>; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "camnoc_axi_clk", + "soc_ahb_clk", + "slow_ahb_src_clk", + "cpas_ahb_clk", + "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "csi2phytimer_clk_src"; + clock-cntl-level = "svs_l1", "turbo"; + clock-rates = <0 0 0 0 269333333 0 269333333 0>, + <0 0 0 0 384000000 0 269333333 0>; + cell-index = <2>; + status = "okay"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-269333333 { + opp-hz = /bits/ 64 <269333333>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_lrme: qcom,lrme@ac6b000 { + compatible = "qcom,lrme"; + reg = <0x0 0xac6b000 0x0 0xa00>; + reg-names = "lrme"; + reg-cam-base = <0x6b000>; + interrupts = ; + interrupt-names = "lrme"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_LRME_CLK_SRC>, + <&camcc CAM_CC_LRME_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_camnoc_axi_clk", + "cam_cc_lrme_clk_src", + "cam_cc_lrme_clk"; + clock-rates = <0 0 0 0 0 200000000 0>, + <0 0 0 0 0 216000000 0>, + <0 0 0 0 0 300000000 0>, + <0 0 0 0 0 404000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "cam_cc_lrme_clk_src"; + operating-points-v2 = <&lrme_opp_table>; + cam_hw_pid = <6 10>; + cell-index = <0>; + status = "okay"; + + lrme_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-216000000 { + opp-hz = /bits/ 64 <216000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@0x0ac6f000 { + compatible = "qcom,cam-bps"; + reg = <0x0 0xac6f000 0x0 0x3000>; + reg-names = "bps_top"; + reg-cam-base = <0x6f000>; + power-domains = <&camcc BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_AREG_CLK>, + <&camcc CAM_CC_BPS_AXI_CLK>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>; + clock-names = "cam_cc_bps_ahb_clk", + "cam_cc_bps_areg_clk", + "cam_cc_bps_axi_clk", + "cam_cc_bps_clk", + "cam_cc_bps_clk_src"; + clock-rates = <0 0 0 0 200000000>, + <0 0 0 0 360000000>, + <0 0 0 0 432000000>, + <0 0 0 0 480000000>, + <0 0 0 0 540000000>, + <0 0 0 0 600000000>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", + "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + cam_hw_pid = <5 9>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@0x0ac87000 { + compatible = "qcom,cam-ipe"; + reg = <0x0 0xac87000 0x0 0x3000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x87000>; + power-domains = <&camcc IPE_0_GDSC>; + clock-names = "cam_cc_ipe_0_ahb_clk", + "cam_cc_ipe_0_areg_clk", + "cam_cc_ipe_0_axi_clk", + "cam_cc_ipe_0_clk", + "cam_cc_ipe_0_clk_src"; + clocks = <&camcc CAM_CC_IPE_0_AHB_CLK>, + <&camcc CAM_CC_IPE_0_AREG_CLK>, + <&camcc CAM_CC_IPE_0_AXI_CLK>, + <&camcc CAM_CC_IPE_0_CLK>, + <&camcc CAM_CC_IPE_0_CLK_SRC>; + clock-rates = <0 0 0 0 240000000>, + <0 0 0 0 360000000>, + <0 0 0 0 432000000>, + <0 0 0 0 480000000>, + <0 0 0 0 540000000>, + <0 0 0 0 600000000>; + clock-cntl-level = "lowsvs","svs", "svs_l1", + "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_ipe_0_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + cam_hw_pid = <4 8>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_vfe0: qcom,vfe0@acaf000 { + compatible = "qcom,vfe170"; + reg = <0x0 0xacaf000 0x0 0x4000>, + <0x0 0xac42000 0x0 0x5000>; + reg-names = "ife0", "cam_camnoc"; + reg-cam-base = <0xaf000 0x42000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc IFE_0_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_0_axi_clk"; + clock-rates = <0 0 0 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-names-option = "cam_cc_ife_0_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <600000000>; + cam_hw_pid = <1>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb3000 { + compatible = "qcom,csid170"; + reg = <0x0 0xacb3000 0x0 0x1000>; + reg-names = "csid0"; + reg-cam-base = <0xb3000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc IFE_0_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CSID_CLK>, + <&camcc CAM_CC_IFE_0_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CPHY_RX_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_0_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_0_csid_clk", + "cam_cc_ife_0_csid_clk_src", + "cam_cc_ife_0_cphy_rx_clk", + "cam_cc_cphy_rx_clk_src", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_0_axi_clk"; + clock-rates = <0 0 0 0 0 0 100000000 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 200000000 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 404000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 480000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 540000000 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + operating-points-v2 = <&csid0_opp_table>; + src-clock-name = "cam_cc_ife_0_csid_clk_src"; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_vfe1: qcom,vfe1@acb6000 { + compatible = "qcom,vfe170"; + reg = <0x0 0xacb6000 0x0 0x4000>, + <0x0 0xac42000 0x0 0x5000>; + reg-names = "ife1", "cam_camnoc"; + reg-cam-base = <0xb6000 0x42000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc IFE_1_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_1_axi_clk"; + clock-rates = <0 0 0 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-names-option = "cam_cc_ife_1_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <600000000>; + cam_hw_pid = <2>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csid1: qcom,csid1@acba000 { + compatible = "qcom,csid170"; + reg = <0x0 0xacba000 0x0 0x1000>; + reg-names = "csid1"; + reg-cam-base = <0xba000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc IFE_1_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CSID_CLK>, + <&camcc CAM_CC_IFE_1_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CPHY_RX_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_IFE_1_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_1_csid_clk", + "cam_cc_ife_1_csid_clk_src", + "cam_cc_ife_1_cphy_rx_clk", + "cam_cc_cphy_rx_clk_src", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_ife_1_axi_clk"; + clock-rates = <0 0 0 0 0 0 100000000 0 0 0 240000000 0 0>, + <0 0 0 0 0 0 200000000 0 0 0 360000000 0 0>, + <0 0 0 0 0 0 320000000 0 0 0 432000000 0 0>, + <0 0 0 0 0 0 404000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 480000000 0 0 0 540000000 0 0>, + <0 0 0 0 0 0 540000000 0 0 0 600000000 0 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_ife_1_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_vfe_lite: qcom,vfe-lite@acc4000 { + compatible = "qcom,vfe-lite170"; + reg = <0x0 0xacc4000 0x0 0x4000>; + reg-names = "ife-lite0"; + reg-cam-base = <0xc4000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_camnoc_axi_clk"; + clock-rates = <0 0 0 0 0 0 240000000 0>, + <0 0 0 0 0 0 360000000 0>, + <0 0 0 0 0 0 432000000 0>, + <0 0 0 0 0 0 540000000 0>, + <0 0 0 0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "turbo"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + cam_hw_pid = <3>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + cam_csid_lite: qcom,csid-lite@acc8000 { + compatible = "qcom,csid-lite170"; + reg = <0x0 0xacc8000 0x0 0x1000>; + reg-names = "csid-lite0"; + reg-cam-base = <0xc8000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_SOC_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "cam_cc_soc_ahb_clk", + "cam_cc_cpas_ahb_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_cphy_rx_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_camnoc_axi_clk"; + clock-rates = <0 0 0 0 0 0 100000000 0 0 0 240000000 0>, + <0 0 0 0 0 0 200000000 0 0 0 360000000 0>, + <0 0 0 0 0 0 320000000 0 0 0 432000000 0>, + <0 0 0 0 0 0 404000000 0 0 0 540000000 0>, + <0 0 0 0 0 0 480000000 0 0 0 540000000 0>, + <0 0 0 0 0 0 540000000 0 0 0 600000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-320000000 { + opp-hz = /bits/ 64 <320000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-404000000 { + opp-hz = /bits/ 64 <404000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom_l1>; + }; + + opp-540000000 { + opp-hz = /bits/ 64 <540000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", "jpegdma", + "jpegenc", "lrmecdm"; + status = "okay"; + }; + + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + ipe0-mask = <0x1000>; + icp_pc_en; + status = "okay"; + }; + + cam_isp_mgr: qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + cam_jpeg_mgr: qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + cam_lrme_mgr: qcom,cam-lrme { + compatible = "qcom,cam-lrme"; + arch-compat = "lrme"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_qcs615"; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + + msm-cam-icp-fw { + compatible = "qcom,msm-cam-smmu-fw-dev"; + label="icp"; + memory-region = <&pil_camera_mem>; + }; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0c00 0x0>; + cam-smmu-label = "cpas-cdm"; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 3.4 GB */ + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0de2 0x0>, + <&apps_smmu 0x0c80 0x0>, + <&apps_smmu 0x0ca0 0x0>, + <&apps_smmu 0x0d00 0x0>, + <&apps_smmu 0x0d20 0x0>; + cam-smmu-label = "icp"; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-firmware { + /* Firmware region is 8MB */ + iova-region-name = "firmware"; + iova-region-start = <0x0>; + iova-region-len = <0x800000>; + iova-region-id = <0x0>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.3 GB */ + iova-region-name = "io"; + iova-region-start = <0x10C00000>; + iova-region-len = <0xCF300000>; + iova-region-id = <0x3>; + status = "okay"; + }; + + iova-mem-qdss-region { + /* qdss region is approximately 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10B00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-secondary-heap { + /* Secondary heap region is 1MB long */ + iova-region-name = "secheap"; + iova-region-start = <0x10A00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x4>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is 150MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x9600000>; + iova-region-id = <0x1>; + iova-granularity = <0x15>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0820 0x40>, + <&apps_smmu 0x0840 0x00>, + <&apps_smmu 0x0860 0x40>; + cam-smmu-label = "ife"; + multiple-client-devices; + com,iommu-faults = "stall-disable", "non-fatal"; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 3.4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0xd80 0x20>, + <&apps_smmu 0xda0 0x20>; + cam-smmu-label = "jpeg"; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 3.4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-lrme { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0cc0 0x0>, + <&apps_smmu 0x0d40 0x0>; + cam-smmu-label = "lrme"; + + lrme_iova_mem_map: iova-mem-map { + iova-mem-region-shared { + /* Shared region is 100MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x6400000>; + iova-region-id = <0x1>; + status = "okay"; + }; + + /* IO region is approximately 3.3 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0xd800000>; + iova-region-len = <0xd2800000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + + config { + pins = "gpio75"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio29"; + function = "gpio"; + }; + + config { + pins = "gpio29"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst2: cam-sensor-active-rst2 { + /* RESET */ + mux { + pins = "gpio37"; + function = "gpio"; + }; + + config { + pins = "gpio37"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio30"; + function = "cam_mclk"; + }; + + config { + pins = "gpio30"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio30"; + function = "cam_mclk"; + }; + + config { + pins = "gpio30"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* MCLK3 */ + mux { + pins = "gpio28"; + function = "cam_mclk"; + }; + + config { + pins = "gpio28"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* MCLK3 */ + mux { + pins = "gpio28"; + function = "cam_mclk"; + }; + + config { + pins = "gpio28"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + + config { + pins = "gpio75"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio29"; + function = "gpio"; + }; + + config { + pins = "gpio29"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst2: cam-sensor-suspend-rst2 { + /* RESET */ + mux { + pins = "gpio37"; + function = "gpio"; + }; + + config { + pins = "gpio37"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cci_i2c_scl0_active: cci-i2c-scl0-active { + mux { + /* CLK, DATA */ + pins = "gpio33"; + function = "cci_i2c"; + }; + + config { + pins = "gpio33"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl0_suspend: cci-i2c-scl0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio33"; + function = "cci_i2c"; + }; + + config { + pins = "gpio33"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_active: cci-i2c-scl1-active { + mux { + /* CLK, DATA */ + pins = "gpio35"; + function = "cci_i2c"; + }; + + config { + pins = "gpio35"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_suspend: cci-i2c-scl1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio35"; + function = "cci_i2c"; + }; + + config { + pins = "gpio35"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + + cci_i2c_sda0_active: cci-i2c-sda0-active { + mux { + /* CLK, DATA */ + pins = "gpio32"; + function = "cci_i2c"; + }; + + config { + pins = "gpio32"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda0_suspend: cci-i2c-sda0-suspend { + mux { + /* CLK, DATA */ + pins = "gpio32"; + function = "cci_i2c"; + }; + + config { + pins = "gpio32"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_active: cci-i2c-sda1-active { + mux { + /* CLK, DATA */ + pins = "gpio34"; + function = "cci_i2c"; + }; + + config { + pins = "gpio34"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_suspend: cci-i2c-sda1-suspend { + mux { + /* CLK, DATA */ + pins = "gpio34"; + function = "cci_i2c"; + }; + + config { + pins = "gpio34"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; From 9c5635721d1b45721ebe0c55922419a5c5a111c2 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 7 Jan 2026 19:23:37 +0530 Subject: [PATCH 0699/1133] QCLINUX: arm64: dts: qcom: Change rb3gen2 camera firmware path update the path for the camera icp firmware. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi index 37ea48e35d09c..2fadfb9de1fee 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi @@ -32,7 +32,7 @@ clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal"; src-clock-name = "soc_fast_ahb"; operating-points-v2 = <&a5_opp_table>; - fw_name = "CAMERA_ICP_170.elf"; + fw_name = "qcom/qcm6490/CAMERA_ICP_170.elf"; ubwc-ipe-fetch-cfg = <0x7073 0x707b>; ubwc-ipe-write-cfg = <0x161cf 0x161ef>; ubwc-bps-fetch-cfg = <0x7073 0x707b>; From f6f90a6c6860fd482e397ecd0835111de93493b0 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 7 Jan 2026 19:33:18 +0530 Subject: [PATCH 0700/1133] QCLINUX: arm64: dts: qcom: Change monaco camera firmware path update the path for the camera icp firmware. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/monaco-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi index f72161e75f7e7..258ad08ffee2f 100644 --- a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi @@ -1463,7 +1463,7 @@ <400000000 0 600000000 0>; clock-cntl-level = "svs_l1", "nominal"; nrt-device; - fw_name = "CAMERA_ICP"; + fw_name = "qcom/qcs8300/CAMERA_ICP"; ubwc-ipe-fetch-cfg = <0x707b 0x7083>; ubwc-ipe-write-cfg = <0x161ef 0x1620f>; qos-val = <0xa0a>; From 46240a3f0382c0053a894babddd6383ac25e2e23 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 7 Jan 2026 19:32:20 +0530 Subject: [PATCH 0701/1133] QCLINUX: arm64: dts: qcom: Change lemans camera firmware path update the path for the camera icp firmware. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/lemans-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi index 855d29dff618f..a207377cce6c1 100644 --- a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi @@ -1600,7 +1600,7 @@ <400000000 0 600000000 0>; clock-cntl-level = "svs_l1", "nominal"; nrt-device; - fw_name = "CAMERA_ICP"; + fw_name = "qcom/sa8775p/CAMERA_ICP"; ubwc-ipe-fetch-cfg = <0x707b 0x7083>; ubwc-ipe-write-cfg = <0x161ef 0x1620f>; qos-val = <0xa0a>; From 8882ba0aabf781bc4cbc2f3f7f62753947c53343 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 7 Jan 2026 19:30:22 +0530 Subject: [PATCH 0702/1133] QCLINUX: arm64: dts: qcom: Change talos camera firmware path update the path for the camera icp firmware. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/talos-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/talos-camera.dtsi b/arch/arm64/boot/dts/qcom/talos-camera.dtsi index e2daa14db1e80..5a79115547f9a 100644 --- a/arch/arm64/boot/dts/qcom/talos-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-camera.dtsi @@ -43,7 +43,7 @@ clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "nominal_l1", "turbo"; src-clock-name = "cam_cc_icp_clk_src"; operating-points-v2 = <&a5_opp_table>; - fw_name = "CAMERA_ICP.elf"; + fw_name = "qcom/qcs615/CAMERA_ICP.elf"; ubwc-cfg = <0x73 0x1CF>; cam_hw_pid = <15>; cell-index = <0>; From 23d0677ad5465c628237699e5fe141bb5ae606bf Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Fri, 9 Jan 2026 00:54:23 +0530 Subject: [PATCH 0703/1133] QCLINUX: arm64: dts: qcom: talos: add camnoc bandwidth levels Add two new AHB bandwidth levels for the camnoc path and update cam-ahb-num-cases accordingly. This ensures that the DT reflects the full set of supported interconnect bandwidth cases. Signed-off-by: Vikram Sharma --- arch/arm64/boot/dts/qcom/talos-camera.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/talos-camera.dtsi b/arch/arm64/boot/dts/qcom/talos-camera.dtsi index 5a79115547f9a..e0f59fb00a5fc 100644 --- a/arch/arm64/boot/dts/qcom/talos-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-camera.dtsi @@ -134,9 +134,10 @@ "cam_hf_0_mnoc", "cam_hf_1_mnoc", "cam_sf_0_mnoc"; - cam-ahb-num-cases = <7>; + cam-ahb-num-cases = <9>; cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, - <0 300000>, <0 300000>, <0 300000>; + <0 300000>, <0 300000>, <0 300000>, + <0 300000>, <0 300000>; vdd-corners = Date: Fri, 23 Jan 2026 12:57:03 +0530 Subject: [PATCH 0704/1133] QCLINUX: arm64: dts: qcom: disabled vreg_cam1_2p8 regulator Disabled vreg_cam1_2p8 regulator to free GPIOs. Signed-off-by: Nihal Kumar Gupta Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso index 3945c77528ccb..c0fea4bb3dc23 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso @@ -105,3 +105,7 @@ }; }; }; + +&vreg_cam1_2p8 { + status = "disabled"; +}; From f4cccabff36b77b8b0d6827279cada9a17903723 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Thu, 29 Jan 2026 18:26:31 +0530 Subject: [PATCH 0705/1133] QCLINUX: arm64: dts: qcom: Enable IMX577 sensor on lemans Enable imx577 sensor on lemans boards from slot0 to slot3. Signed-off-by: Nihal Kumar Gupta --- .../dts/qcom/lemans-evk-camera-sensor.dtsi | 384 ++++++++++++++++++ 1 file changed, 384 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi index 8eb1026e7da1b..2a650bc52d1fc 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -205,6 +205,47 @@ status = "ok"; }; + /*cam0-cmk_imx577*/ + qcom,cam-sensor27 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam27>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 72 0>, + <&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <27>; + status = "ok"; + }; + eeprom_cam24: qcom,eeprom24 { compatible = "qcom,eeprom"; cam_vio-supply = <&vreg_s4a>; @@ -239,6 +280,41 @@ cell-index = <24>; status = "ok"; }; + + eeprom_cam27: qcom,eeprom27 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + gpios = <&tlmm 72 0>, + <&tlmm 132 0>, + <&pmm8654au_0_gpios 7 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <27>; + status = "ok"; + }; }; &cam_cci1 { @@ -401,6 +477,160 @@ cell-index = <21>; status = "ok"; }; + + /*cam1-imx577*/ + qcom,cam-sensor26 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam26>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <26>; + status = "ok"; + }; + + /*cam1-cmk_imx577*/ + qcom,cam-sensor28 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam28>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <28>; + status = "ok"; + }; + + eeprom_cam26: qcom,eeprom26 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <26>; + status = "ok"; + }; + + eeprom_cam28: qcom,eeprom28 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 73 0>, + <&tlmm 133 0>, + <&pmm8654au_0_gpios 8 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <28>; + status = "ok"; + }; }; &cam_cci2 { @@ -563,6 +793,83 @@ cell-index = <22>; status = "ok"; }; + + /*cam2-cmk_imx577*/ + qcom,cam-sensor29 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam29>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>, + <&tlmm 134 0>, + <&pmm8654au_0_gpios 9 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK2", + "CAMIF_RESET2", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <29>; + status = "ok"; + }; + + eeprom_cam29: qcom,eeprom29 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_suspend_rst2>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 74 0>, + <&tlmm 134 0>, + <&pmm8654au_0_gpios 9 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <29>; + status = "ok"; + }; }; &cam_cci3 { @@ -725,6 +1032,83 @@ cell-index = <23>; status = "ok"; }; + + /*cam3-cmk_imx577*/ + qcom,cam-sensor30 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam30>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + gpios = <&tlmm 75 0>, + <&tlmm 135 0>, + <&pmm8654au_0_gpios 10 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK3", + "CAMIF_RESET3", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <30>; + status = "ok"; + }; + + eeprom_cam30: qcom,eeprom30 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + gpios = <&tlmm 75 0>, + <&tlmm 135 0>, + <&pmm8654au_0_gpios 10 0>; + pinctrl-names = "cam_default", "cam_suspend"; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK3", + "CAM_RESET3", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <30>; + status = "ok"; + }; }; &soc { From 2ba8982fa7b59c72a74afd5a22c6dea9554210cd Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Mon, 2 Feb 2026 15:46:31 +0530 Subject: [PATCH 0706/1133] QCLINUX: arm64: dts: qcom: Add camx overlay for talos evk Add camx overlay for talos EVK baord. Signed-off-by: Vikram Sharma --- arch/arm64/boot/dts/qcom/Makefile | 4 ++++ arch/arm64/boot/dts/qcom/talos-evk-camx.dtso | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/talos-evk-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 353e447392598..cb43ffd2d5045 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -560,3 +560,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtb sa8775p-ride-r3-camx-dtbs:= sa8775p-ride-r3.dtb sa8775p-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3-camx.dtb + +talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/talos-evk-camx.dtso b/arch/arm64/boot/dts/qcom/talos-evk-camx.dtso new file mode 100644 index 0000000000000..a40d8817a7a20 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-evk-camx.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "talos-camera.dtsi" +#include "talos-camera-sensor.dtsi" From 970256f496ee4a76f87c9610556a05b75d53247e Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 2 Feb 2026 22:21:36 +0530 Subject: [PATCH 0707/1133] QCLINUX: arm64: dts: qcom: add node labels and explicit QoS flag in lemans Adds labels to cam-cpas and cam-icp nodes and changes enable-secure-qos-update from boolean to explicit. This change is required for KVM support. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/lemans-camera.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi index a207377cce6c1..d6cce86922c26 100644 --- a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi @@ -667,7 +667,7 @@ status = "ok"; }; - qcom,cam-cpas { + cam_cpas: qcom,cam-cpas { compatible = "qcom,cam-cpas"; label = "cpas"; arch-compat = "cpas_top"; @@ -743,7 +743,7 @@ "ife5", "ife6", "ipe0", "sfe0", "sfe1", "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", "rt-cdm3", "icp0", "tpg17", "tpg18", "tpg19"; - enable-secure-qos-update; + enable-secure-qos-update = <1>; cell-index = <0>; status = "ok"; @@ -1114,7 +1114,7 @@ }; }; - qcom,cam-icp { + cam_icp_firmware: qcom,cam-icp { compatible = "qcom,cam-icp"; compat-hw-name = "qcom,icp", "qcom,ipe0"; num-icp = <1>; From 179e72b4abf9ab25962a03b3eff5ac2bd53c46d2 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 2 Feb 2026 22:38:12 +0530 Subject: [PATCH 0708/1133] QCLINUX: arm64: dts: qcom: add node labels and explicit QoS flag in monaco Adds labels to cam-cpas and cam-icp nodes and changes enable-secure-qos-update from boolean to explicit. This change is required for KVM support. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/monaco-camera.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi index 258ad08ffee2f..8250f66c34526 100644 --- a/arch/arm64/boot/dts/qcom/monaco-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-camera.dtsi @@ -528,7 +528,7 @@ status = "ok"; }; - qcom,cam-cpas { + cam_cpas: qcom,cam-cpas { compatible = "qcom,cam-cpas"; label = "cpas"; arch-compat = "cpas_top"; @@ -605,7 +605,7 @@ "ife5", "ife6", "ipe0", "sfe0", "sfe1", "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", "rt-cdm3", "icp0", "tpg13", "tpg14", "tpg15"; - enable-secure-qos-update; + enable-secure-qos-update = <1>; cell-index = <0>; status = "ok"; @@ -976,7 +976,7 @@ }; }; - qcom,cam-icp { + cam_icp_firmware: qcom,cam-icp { compatible = "qcom,cam-icp"; compat-hw-name = "qcom,icp", "qcom,ipe0"; num-icp = <1>; From 957c4f464025cfb8c83b47830a705bda6047eb1f Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Sat, 7 Feb 2026 15:37:33 +0530 Subject: [PATCH 0709/1133] QCLINUX: arm64: dts: qcom: lemans: Add CamX EL2 overlay Add camx el2 DT overlay for lemans platforms. The overlay updates the ICP firmware node with Secure SMMU SID and disables secure QoS updates for CPAS in EL2/KVM configurations. Wire up the new overlay-built DTBs in the qcom DT Makefile so the corresponding *-camx-el2.dtb targets are generated. Co-developed-by: Ignatius Michael Jihan Signed-off-by: Ignatius Michael Jihan Signed-off-by: Vikram Sharma --- arch/arm64/boot/dts/qcom/Makefile | 4 +++ arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index cb43ffd2d5045..edfcbfab19c5b 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -528,6 +528,10 @@ lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb +lemans-camx-el2-dtbs := lemans-evk-el2.dtb lemans-evk-camx.dtbo lemans-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtb + monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso b/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso new file mode 100644 index 0000000000000..83b5605f026a8 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + /* cam_cpas label -> /soc@0/qcom,cam-cpas * + fragment@0 { + target-path = "/soc@0/qcom,cam-cpas"; + __overlay__ { + enable-secure-qos-update = <0>; + }; + }; + + /* cam_icp_firmware label -> /soc@0/qcom,cam-icp */ + fragment@1 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x08c1 0x0400>; + }; + }; + }; +}; From 7aa225a0220948355895d3b5802d288701f1b04a Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Mon, 2 Mar 2026 16:36:16 +0530 Subject: [PATCH 0710/1133] QCLINUX: arm64: dts: qcom: add labels to sensor DTSI Add DT labels to sensor nodes in the Lemans and Kodiak DTSI files to enable phandle references. Monaco changes are already handled. Signed-off-by: Nihal Kumar Gupta --- arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi | 8 ++++---- .../boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi index 2a650bc52d1fc..e1ee2ba8c78e6 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -125,7 +125,7 @@ }; /*cam0a-ov9282*/ - qcom,cam-sensor1 { + rb8_slot0: qcom,cam-sensor1 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <0>; sensor-position-roll = <0>; @@ -439,7 +439,7 @@ }; /*cam1-ov9282*/ - qcom,cam-sensor21 { + rb8_slot1: qcom,cam-sensor21 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; sensor-position-roll = <0>; @@ -755,7 +755,7 @@ }; /*cam2-ov9282*/ - qcom,cam-sensor22 { + rb8_slot2: qcom,cam-sensor22 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <2>; sensor-position-roll = <0>; @@ -994,7 +994,7 @@ }; /*cam3-ov9282*/ - qcom,cam-sensor23 { + rb8_slot3: qcom,cam-sensor23 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <3>; sensor-position-roll = <0>; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi index 8b75b1a441db4..026b97b58377d 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi @@ -55,7 +55,7 @@ }; /*cam0a-ov9282*/ - qcom,cam-sensor1 { + rb3_slot0a: qcom,cam-sensor1 { compatible = "qcom,cam-sensor"; cell-index = <1>; csiphy-sd-index = <0>; @@ -92,7 +92,7 @@ }; /*cam1-ov9282*/ - qcom,cam-sensor6 { + rb3_slot1: qcom,cam-sensor6 { compatible = "qcom,cam-sensor"; cell-index = <6>; csiphy-sd-index = <1>; @@ -254,7 +254,7 @@ }; /*cam3-imx577*/ - qcom,cam-sensor0 { + rb3_slot3: qcom,cam-sensor0 { compatible = "qcom,cam-sensor"; cell-index = <0>; csiphy-sd-index = <3>; @@ -345,7 +345,7 @@ }; /*cam0b-ov9282*/ - qcom,cam-sensor7 { + rb3_slot0b: qcom,cam-sensor7 { compatible = "qcom,cam-sensor"; cell-index = <7>; csiphy-sd-index = <0>; @@ -383,7 +383,7 @@ }; /*cam2-imx577*/ - qcom,cam-sensor8 { + rb3_slot2: qcom,cam-sensor8 { compatible = "qcom,cam-sensor"; cell-index = <8>; csiphy-sd-index = <2>; From 6763a128f0162e73f8e4a8c56717d63649fd6d97 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Fri, 13 Mar 2026 14:59:50 +0530 Subject: [PATCH 0711/1133] QCLINUX: arm64: dts: qcom: lemans: Fix comment typo in camx EL2 dtso. Fix a typo in the camx EL2 device tree by removing comments all together. The mistake was masked by a later comment terminator. Signed-off-by: Vikram Sharma --- arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso b/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso index 83b5605f026a8..c7ddbc01a0070 100644 --- a/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso +++ b/arch/arm64/boot/dts/qcom/lemans-camx-el2.dtso @@ -7,7 +7,6 @@ /plugin/; / { - /* cam_cpas label -> /soc@0/qcom,cam-cpas * fragment@0 { target-path = "/soc@0/qcom,cam-cpas"; __overlay__ { @@ -15,7 +14,6 @@ }; }; - /* cam_icp_firmware label -> /soc@0/qcom,cam-icp */ fragment@1 { target-path = "/soc@0/qcom,cam-icp"; __overlay__ { From 32f41b526dd5eded47f930754fef383f69f688ea Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Fri, 13 Mar 2026 19:24:42 +0530 Subject: [PATCH 0712/1133] QCLINUX: arm64: dts: qcom: monaco: Add CamX EL2 overlay Add camx el2 DT overlay for lemans platforms. The overlay updates the ICP firmware node with Secure SMMU SID and disables secure QoS updates for CPAS in EL2/KVM configurations. Wire up the new overlay-built DTBs in the qcom DT Makefile so the corresponding *-camx-el2.dtb targets are generated. Signed-off-by: Vikram Sharma --- arch/arm64/boot/dts/qcom/Makefile | 4 +++ arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index edfcbfab19c5b..d854cc14955ec 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -536,6 +536,10 @@ monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb +monaco-camx-el2-dtbs := monaco-evk-el2.dtb monaco-evk-camx.dtbo monaco-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtb + qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso b/arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso new file mode 100644 index 0000000000000..c7ddbc01a0070 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-camx-el2.dtso @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = "/soc@0/qcom,cam-cpas"; + __overlay__ { + enable-secure-qos-update = <0>; + }; + }; + + fragment@1 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x08c1 0x0400>; + }; + }; + }; +}; From 027e40f5466427c007f8e19ba61f197b277c39b3 Mon Sep 17 00:00:00 2001 From: Ignatius Michael Jihan Date: Tue, 7 Apr 2026 11:07:43 +0530 Subject: [PATCH 0713/1133] QCLINUX: arm64: dts: qcom: Add Hamoa camx overlay dts Add CAMX overlay dts file for Hamoa boards. This change also enables the compilation of the CAMX overlay for Hamoa boards. Signed-off-by: Ignatius Michael Jihan --- arch/arm64/boot/dts/qcom/Makefile | 4 + .../boot/dts/qcom/hamoa-camera-camx.dtso | 26 + .../boot/dts/qcom/hamoa-camera-sensor.dtsi | 53 + arch/arm64/boot/dts/qcom/hamoa-camera.dtsi | 2473 +++++++++++++++++ 4 files changed, 2556 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso create mode 100644 arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/hamoa-camera.dtsi diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index d854cc14955ec..bef102d5b17cf 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -524,6 +524,10 @@ dtb-$(CONFIG_ARCH_QCOM) += x1p64100-microsoft-denali.dtb x1p64100-microsoft-dena x1p42100-microsoft-sp12in-el2-dtbs := x1p42100-microsoft-sp12in.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p42100-microsoft-sp12in.dtb x1p42100-microsoft-sp12in-el2.dtb +hamoa-camera-dtbs := hamoa-iot-evk.dtb hamoa-camera-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += hamoa-camera-camx.dtb + lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso b/arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso new file mode 100644 index 0000000000000..d63daf990f2a1 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hamoa-camera.dtsi" +#include "hamoa-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi new file mode 100644 index 0000000000000..7ebfcf1ec3912 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /*cam0-cmk_imx577*/ + qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_suspend_rst1>; + gpios = <&tlmm 97 0>, + <&tlmm 110 0>, + <&tlmm 19 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi new file mode 100644 index 0000000000000..94dd42b380f4e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi @@ -0,0 +1,2473 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac01000 { + compatible = "qcom,cam-icp_v2"; + icp-version = <0x0200>; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0x0ac04000 0x0 0x1000>; + reg-names = "icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + clocks = <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "icp_ahb_clk", + "icp_clk_src", + "icp_clk"; + clock-rates = <0 300000000 0>, + <0 400000000 0>, + <0 480000000 0>, + <0 600000000 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "icp_clk_src"; + operating-points-v2 = <&icp_opp_table>; + clock-control-debugfs = "true"; + fw_name = "qcom/x1e80100/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + ubwc-bps-fetch-cfg = <0x707b 0x7083>; + ubwc-bps-write-cfg = <0x161ef 0x1620f>; + qos-val = <0x00000A0A>; + cam_hw_pid = <3>; + cell-index = <0>; + status = "okay"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cpas: qcom,cam-cpas@ac13000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac13000 0x0 0x1000>, + <0x0 0xac19000 0x0 0xC000>, + <0x0 0xbbf0000 0x0 0x1F00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x13000 0x19000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_ahb_clk", + "gcc_axi_hf_clk", + "gcc_axi_sf_clk", + "cam_cc_slow_ahb_clk_src", + "cpas_ahb_clk", + "cpas_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "camnoc_axi_clk_src", + "camnoc_axi_clk", + "camnoc_axi_nrt_clk", + "camcc_debug_clk"; + clock-rates = < 0 0 0 0 0 0 0 0 0 0 0 0>, + < 0 0 0 64000000 0 0 80000000 0 240000000 0 0 0>, + < 0 0 0 80000000 0 0 100000000 0 300000000 0 0 0>, + < 0 0 0 80000000 0 0 400000000 0 400000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvsd1", "lowsvs", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <400000000>; + src-clock-name = "camnoc_axi_clk_src"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + cam-icc-path-names = "cam_ahb"; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects =<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", + "cam_hf_0", + "cam_sf_0", + "cam_sf_icp"; + rpmh-bcm-info = <12 0x4 0x800 0 4>; + cam-ahb-num-cases = <8>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 76800>, <0 150000>, + <0 150000>, <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", + "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", + "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "csiphy4", + "cci0", "cci1", "csid0", "csid1", "csid2", + "csid3", "ife0", "ife1", "ife2", "ife3", "sfe0", + "ipe0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "cam-cdm-intf0", "bps0", "icp0", + "jpeg-dma0", "jpeg-enc0", "tpg13", "tpg14", + "tpg15"; + cell-index = <0>; + status = "okay"; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_wr>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <2>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_rd>; + }; + + ife0_linear_stats_wr: ife0-linear-stats-wr { + cell-index = <3>; + node-name = "ife0-linear-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife0_pdaf_wr: ife0-pdaf-wr { + cell-index = <4>; + node-name = "ife0-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife0_ubwc_wr: ife0-ubwc-wr { + cell-index = <6>; + node-name = "ife0-ubwc-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife1_linear_stats_wr: ife1-linear-stats-wr { + cell-index = <7>; + node-name = "ife1-linear-stats-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife1_pdaf_wr: ife1-pdaf-wr { + cell-index = <8>; + node-name = "ife1-pdaf-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife1_rdi_pixel_raw_wr: ife1-rdi-pixel-raw-wr { + cell-index = <9>; + node-name = "ife1-rdi-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife1_ubwc_wr: ife1-ubwc-wr { + cell-index = <10>; + node-name = "ife1-ubwc-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife2_rdi_stats_pixel_raw_wr: ife2-rdi-stats-pixel-raw-wr { + cell-index = <11>; + node-name = "ife2-rdi-stats-pixel-raw-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ife3_rdi_stats_pixel_raw_wr: ife3-rdi-stats-pixel-raw-wr { + cell-index = <12>; + node-name = "ife3-rdi-stats-pixel-raw-wr"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ipe0_all_wr: ipe0-all-wr { + cell-index = <13>; + node-name = "ipe0-all-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt0_wr>; + }; + + ipe0_in_rd: ipe0-in-rd { + cell-index = <14>; + node-name = "ipe0-in-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + ipe0_ref_rd: ipe0-ref-rd { + cell-index = <15>; + node-name = "ipe0-ref-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <16>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <17>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <18>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <19>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + rt_cdm0_all_rd: rt-cdm0-all-rd { + cell-index = <20>; + node-name = "rt-cdm0-all-rd"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + rt_cdm1_all_rd: rt-cdm1-all-rd { + cell-index = <21>; + node-name = "rt-cdm1-all-rd"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 0 */ + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <22>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 1 */ + rt_cdm3_all_rd: rt-cdm3-all-rd { + cell-index = <23>; + node-name = "rt-cdm3-all-rd"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + sfe0_all_rd: sfe0-all-rd { + cell-index = <24>; + node-name = "sfe0-all-rd"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_rt0_rd>; + }; + + sfe0_rdi_stats_nrdi_wr: sfe0-rdi-stats-nrdi-wr { + cell-index = <25>; + node-name = "sfe0-rdi-stats-nrdi-wr"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_rd0: level1-nrt0-rd0 { + cell-index = <26>; + node-name = "level1-nrt0-rd0"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_rd1: level1-nrt0-rd1 { + cell-index = <27>; + node-name = "level1-nrt0-rd1"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_wr0: level1-nrt0-wr0 { + cell-index = <28>; + node-name = "level1-nrt0-wr0"; + parent-node = <&level2_nrt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_rd0: level1-rt0-rd0 { + cell-index = <29>; + node-name = "level1-sfe-rd"; + parent-node = <&level2_rt0_rd>; + traffic-merge-type = ; + }; + + level1_rt0_wr0: level1-rt0-wr0 { + cell-index = <30>; + node-name = "level1-ife-ubwc-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr1: level1-rt0-wr1 { + cell-index = <31>; + node-name = "level1-ife-rdi-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr2: level1-rt0-wr2 { + cell-index = <32>; + node-name = "level1-ife-pdaf"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr3: level1-rt0-wr3 { + cell-index = <33>; + node-name = "level1-ife01-linear-stats"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr4: level1-rt0-wr4 { + cell-index = <34>; + node-name = "level1-ifelite"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_nrt0_rd: level2-nrt0-rd { + cell-index = <35>; + node-name = "level2-nrt0-rd"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt0_wr: level2-nrt0-wr { + cell-index = <36>; + node-name = "level2-nrt0-wr"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt1_rd: level2-nrt1-rd { + cell-index = <37>; + node-name = "level2-nrt1-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + bus-width-factor = <4>; + }; + + level2_rt0_rd: level2-rt0-rd { + cell-index = <38>; + node-name = "level2-rt0-rd"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_rt0_wr: level2-rt0-wr { + cell-index = <39>; + node-name = "level2-rt0-wr"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <40>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <41>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { + cell-index = <42>; + node-name = "level3-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cci0: qcom,cci0@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "cci0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + operating-points-v2 = <&cci0_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci0_active>; + pinctrl-1 = <&cci0_suspend>; + pinctrl-2 = <&cci1_active>; + pinctrl-3 = <&cci1_suspend>; + cell-index = <0>; + status = "okay"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cci1: qcom,cci1@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "cci1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci2_active>; + pinctrl-1 = <&cci2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + operating-points-v2 = <&cci1_opp_table>; + cell-index = <1>; + status = "okay"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + qcom,rt-cdm0@ac25000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac25000 0x0 0x400>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x25000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <400000000 0>; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table0>; + nrt-device; + cdm-client-names = "ife0", "dualife0"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <25>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm1@ac26000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x400>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clock-rates = <400000000 0>; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table1>; + nrt-device; + cdm-client-names = "ife1", "dualife1"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <26>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <1>; + status = "okay"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac2a000 { + compatible = "qcom,cam_jpeg_enc_680"; + reg = <0x0 0xac2a000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegenc_hw", "cam_camnoc"; + reg-cam-base = <0x2a000 0x19000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegenc_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_enc_opp_table>; + nrt-device; + cam_hw_pid = <12 14>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac2b000 { + compatible = "qcom,cam_jpeg_dma_680"; + reg = <0x0 0xac2b000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x2b000 0x19000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegdma_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_dma_opp_table>; + nrt-device; + cam_hw_pid = <13 15>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@ac2c000 { + compatible = "qcom,cam-bps680"; + reg = <0x0 0xac2c000 0x0 0xb000>; + reg-names = "bps_top"; + reg-cam-base = <0x2c000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_FAST_AHB_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_CPAS_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_fast_ahb_clk", + "bps_clk_src", + "bps_clk", + "cam_cc_cpas_bps_clk"; + clock-rates = <0 0 160000000 0 0>, + <0 0 200000000 0 0>, + <0 0 400000000 0 0>, + <0 0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <6 7>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@ac42000 { + compatible = "qcom,cam-ipe680"; + reg = <0x0 0xac42000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x42000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_NPS_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_PPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_CLK_SRC>, + <&camcc CAM_CC_IPE_NPS_CLK>, + <&camcc CAM_CC_IPE_PPS_CLK>, + <&camcc CAM_CC_CPAS_IPE_NPS_CLK>; + clock-names = "ipe_nps_ahb_clk", + "ipe_nps_fast_ahb_clk", + "ipe_pps_fast_ahb_clk", + "ipe_nps_clk_src", + "ipe_nps_clk", + "ipe_pps_clk", + "cam_cc_cpas_ipe_nps_clk"; + clock-rates = <0 0 0 304000000 0 0 0>, + <0 0 0 364000000 0 0 0>, + <0 0 0 500000000 0 0 0>, + <0 0 0 600000000 0 0 0>, + <0 0 0 700000000 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + nrt-device; + src-clock-name = "ipe_nps_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <22 23 30>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-304000000 { + opp-hz = /bits/ 64 <304000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-364000000 { + opp-hz = /bits/ 64 <364000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0@ac62000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac62000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x62000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>; + clock-names = "ife_0_fast_ahb", + "ife_0_clk_src", + "ife_0_clk", + "cam_cc_cpas_ife_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <16 4 20 8>; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1@ac71000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac71000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x71000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>; + clock-names = "ife_1_fast_ahb", + "ife_1_clk_src", + "ife_1_clk", + "cam_cc_cpas_ife_1_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <17 5 21 9>; + cell-index = <1>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe0: qcom,sfe0@ac9e000 { + compatible = "qcom,sfe680"; + reg = <0x0 0xac9e000 0x0 0x8000>; + reg-names = "sfe0"; + reg-cam-base = <0x9e000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "sfe"; + power-domains = <&camcc CAM_CC_SFE_0_GDSC>; + clocks = <&camcc CAM_CC_SFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_0_CLK_SRC>, + <&camcc CAM_CC_SFE_0_CLK>, + <&camcc CAM_CC_CPAS_SFE_0_CLK>; + clock-names = "sfe_0_fast_ahb", + "sfe_0_clk_src", + "sfe_0_clk", + "cam_cc_cpas_sfe_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "sfe_0_clk_src"; + operating-points-v2 = <&sfe0_opp_table>; + cam_hw_pid = <10 2>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + sfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb7000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb7000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb7000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid1: qcom,csid1@acb9000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb9000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb9000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0@acc6000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacc6000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0@acc6000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacc6000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <0>; + cell-index = <2>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1@acca000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacca000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "okay"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1@acca000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacca000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <1>; + cell-index = <3>; + status = "okay"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@ace4000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy0_opp_table>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ace6000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace6000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe6000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy1_opp_table>; + cell-index = <1>; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2@ace8000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace8000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe8000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "csi2phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy2_opp_table>; + cell-index = <2>; + status = "okay"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4@acec000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xacec000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xec000>; + interrupts = ; + interrupt-names = "CSIPHY4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy4_opp_table>; + cell-index = <4>; + status = "okay"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acf6000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf6000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xf6000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + cell-index = <13>; + phy-id = <0>; + status = "okay"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acf7000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf7000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xf7000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + cell-index = <14>; + phy-id = <1>; + status = "okay"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acf8000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf8000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xf8000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + cell-index = <15>; + phy-id = <2>; + status = "okay"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm2@acf9000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacf9000 0x0 0x400>; + reg-names = "rt-cdm2"; + reg-cam-base = <0xf9000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table2>; + nrt-device; + cdm-client-names = "ife2"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <24>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <2>; + status = "okay"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm3@acfa000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacfa000 0x0 0x400>; + reg-names = "rt-cdm3"; + reg-cam-base = <0xfa000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table3>; + nrt-device; + cdm-client-names = "ife3"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <27>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <3>; + status = "okay"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc"; + cell-index = <0>; + status = "okay"; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + status = "okay"; + icp_pc_en; + icp_use_pil; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + force_cache_allocs; + need_shared_buffer_padding; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18A0 0x0000>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1800 0x0060>, + <&apps_smmu 0x1820 0x0060>, + <&apps_smmu 0x1840 0x0060>, + <&apps_smmu 0x1860 0x0060>, + <&apps_smmu 0x1900 0x0000>, + <&apps_smmu 0x1980 0x0020>, + <&apps_smmu 0x19A0 0x0020>; + cam-smmu-label = "icp"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-qdss-region { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xFC00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x0060>, + <&apps_smmu 0x0820 0x0060>, + <&apps_smmu 0x0840 0x0060>, + <&apps_smmu 0x0860 0x0060>; + dma-coherent; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18E0 0x0000>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_x1e80100"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_int: cam-sensor-active-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* mclk0 */ + config { + pins = "gpio96"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* mclk0 */ + config { + pins = "gpio96"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* mclk4 */ + config { + pins = "gpio100"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* mclk4 */ + config { + pins = "gpio100"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_suspend_int: cam-sensor-suspend-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + output-low; + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cci0_active: cci0-active { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci0_suspend: cci0-suspend { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + function = "cci_i2c"; + }; + }; + + cci1_active: cci1-active { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci1_suspend: cci1-suspend { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + function = "cci_i2c"; + }; + }; + + cci2_active: cci2-active { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci2_suspend: cci2-suspend { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + function = "cci_i2c"; + }; + }; + + cci3_active: cci3-active { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; + + cci3_suspend: cci3-suspend { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; +}; From 7a4f2c686b7a7bcd3cd9b3a1aa62652f6db91fce Mon Sep 17 00:00:00 2001 From: Ignatius Michael Jihan Date: Tue, 7 Apr 2026 16:37:49 +0530 Subject: [PATCH 0714/1133] QCLINUX: arm64: dts: qcom: align hamoa camera DTB variable naming Rename the hamoa camera DTBs variable to match the hamoa-camera-camx DTB target naming and improve consistency with existing Makefile conventions. Fixes: 9041882f7c4c ("QCLINUX: arm64: dts: qcom: Add hamoa camx overlay dts") Signed-off-by: Ignatius Michael Jihan --- arch/arm64/boot/dts/qcom/Makefile | 4 ++-- .../dts/qcom/{hamoa-camera-camx.dtso => hamoa-evk-camx.dtso} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename arch/arm64/boot/dts/qcom/{hamoa-camera-camx.dtso => hamoa-evk-camx.dtso} (100%) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index bef102d5b17cf..2cb3fb625a6fe 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -524,9 +524,9 @@ dtb-$(CONFIG_ARCH_QCOM) += x1p64100-microsoft-denali.dtb x1p64100-microsoft-dena x1p42100-microsoft-sp12in-el2-dtbs := x1p42100-microsoft-sp12in.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p42100-microsoft-sp12in.dtb x1p42100-microsoft-sp12in-el2.dtb -hamoa-camera-dtbs := hamoa-iot-evk.dtb hamoa-camera-camx.dtbo +hamoa-evk-camx-dtbs := hamoa-iot-evk.dtb hamoa-evk-camx.dtbo -dtb-$(CONFIG_ARCH_QCOM) += hamoa-camera-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtb lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso b/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso similarity index 100% rename from arch/arm64/boot/dts/qcom/hamoa-camera-camx.dtso rename to arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso From 566399e8ccd1b39bb301bdc90abbd181e7906ed3 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 8 Apr 2026 02:13:12 +0530 Subject: [PATCH 0715/1133] PENDING: arm64: dts: qcom: lemans-evk: add overlay for QPS615 ethernet Add an overlay devicetree for Lemans EVK for temporary enablement of the QPS615 PCIE switch's 10GbE and 2.5Gbe ethernet ports. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../boot/dts/qcom/lemans-evk-staging.dtso | 68 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 2cb3fb625a6fe..affe732649fda 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -536,6 +536,8 @@ lemans-camx-el2-dtbs := lemans-evk-el2.dtb lemans-evk-camx.dtbo lemans-camx-el2. dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-staging.dtbo + monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-staging.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-staging.dtso new file mode 100644 index 0000000000000..cf345ec5d06c9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-staging.dtso @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&i2c18 { + eeprom@52 { + nvmem-layout { + mac_addr2: mac-addr@6 { + reg = <0x6 0x6>; + }; + mac_addr3: mac-addr@c { + reg = <0xc 0x6>; + }; + }; + }; +}; + +&pcieport0 { + pcie@0,0 { + pcie@3,0 { + pci@0,0 { + interrupts-extended = <&tlmm 56 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr2>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&tlmm 76 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <221000>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 57 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr3>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&tlmm 77 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr-intn-wol-sig { + pins = "gpio56"; + function = "gpio"; + input-enable; + bias-disable; + }; + napa_intn_wol_sig: napa-intn-wol-sig { + pins = "gpio57"; + function = "gpio"; + input-enable; + bias-disable; + }; + }; +}; From c66efddc0f9573abdc539b8d9dcff0f0bbc22b8f Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 8 Apr 2026 02:19:46 +0530 Subject: [PATCH 0716/1133] PENDING: arm64: dts: qcom: monaco-evk: add overlay for QPS615 ethernet Add an overlay devicetree for Monaco EVK for temporary enablement of the QPS615 PCIE switch's 10GbE and 2.5Gbe ethernet ports. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../boot/dts/qcom/monaco-evk-staging.dtso | 68 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index affe732649fda..86fea01053c03 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -546,6 +546,8 @@ monaco-camx-el2-dtbs := monaco-evk-el2.dtb monaco-evk-camx.dtbo monaco-camx-el2. dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo + qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso new file mode 100644 index 0000000000000..a646b28f6f9d0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&eeprom1 { + nvmem-layout { + mac_addr1: mac-addr@0 { + reg = <0x0 0x6>; + }; + + mac_addr2: mac-addr@6 { + reg = <0x6 0x6>; + }; + }; +}; + +&pcieport0 { + pcie@0,0 { + pcie@3,0 { + pci@0,0 { + interrupts-extended = <&tlmm 40 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr1>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <221000>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 39 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + nvmem-cells = <&mac_addr2>; + nvmem-cell-names = "mac-address"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&expander5 0 GPIO_ACTIVE_HIGH>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr-intn-wol-sig { + pins = "gpio40"; + function = "gpio"; + input-enable; + bias-disable; + }; + + napa_intn_wol_sig: napa-intn-wol-sig { + pins = "gpio39"; + function = "gpio"; + input-enable; + bias-disable; + }; + }; +}; From dc92edd6a9cece4372219712d9ccd9c8e841d8a0 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 8 Apr 2026 02:24:07 +0530 Subject: [PATCH 0717/1133] PENDING: arm64: dts: qcom: rb3gen2: add overlay for QPS615 ethernet Add an overlay devicetree for Rb3Gen2 for temporary enablement of the QPS615 PCIE switch's 10GbE and 2.5Gbe ethernet ports. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../dts/qcom/qcs6490-rb3gen2-staging.dtso | 95 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 86fea01053c03..355531779fa00 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -557,6 +557,8 @@ qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.d dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-staging.dtbo + qcs8300-ride-camx-dtbs:= qcs8300-ride.dtb qcs8300-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso new file mode 100644 index 0000000000000..79f9c055c9776 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +/ { + qep_vreg: qep_vreg { + compatible = "regulator-fixed"; + regulator-name = "qep_vreg"; + gpio = <&pm7325_gpios 8 0>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + }; + + aqr_vreg: aqr_vreg { + compatible = "regulator-fixed"; + regulator-name = "aqr_vreg"; + gpio = <&pm7250b_gpios 4 0>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + }; +}; + +&pcie1_port0 { + pcie@0,0 { + pcie@3,0 { + /* + * PF0: also acts as the QPS615 GPIO controller. + * gpio-controller / #gpio-cells expose the TC956X + * internal GPIO lines (hardware numbers 0-13) so that + * phy-reset-gpios can reference them. + */ + qps615: pci@0,0 { + interrupts-extended = <&tlmm 141 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + phy-supply = <&aqr_vreg>; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&qps615 0 GPIO_ACTIVE_LOW>; + reset-deassert-us = <221000>; + + gpio-controller; + #gpio-cells = <2>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 101 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + phy-supply = <&qep_vreg>; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&qps615 1 GPIO_ACTIVE_LOW>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr_intn_wol_sig { + mux { + pins = "gpio141"; + function = "gpio"; + }; + + config { + pins = "gpio141"; + input-enable; + bias-disable; + }; + }; + + napa_intn_wol_sig: napa_intn_wol_sig { + mux { + pins = "gpio101"; + function = "gpio"; + }; + + config { + pins = "gpio101"; + input-enable; + bias-disable; + }; + }; + }; +}; From d5af6e8880436597bbd1c46cd9b91498d1441f5e Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Mon, 13 Apr 2026 09:41:19 +0530 Subject: [PATCH 0718/1133] PEDNING: arm64: dts: qcom: qcs6490-rb3gen2: fix root node overlay for phy-vreg The staging overlay used a bare "/ {" root node block to define the qep_vreg and aqr_vreg fixed regulators. In a DT overlay, a bare "/ {" creates a new root fragment that is not merged into the base tree's root node; as a result the regulator nodes are never instantiated and the tc956x driver cannot resolve the phy-supply phandle, leading to a failed MDIO probe: tc956x_pci-eth 0001:05:00.1: No PHY found Replace "/ {" with the overlay-correct "&{/} {" syntax so that the fragment is properly applied as an amendment to the base device-tree root node. This ensures the regulator nodes are present at boot and the PHY powers up correctly. Fixes: 00ba37e0f45d ("PENDING: arm64: dts: qcom: rb3gen2: add overlay for QPS615 ethernet") Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso index 79f9c055c9776..6c112224f0ce9 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-staging.dtso @@ -9,7 +9,7 @@ #include #include -/ { +&{/} { qep_vreg: qep_vreg { compatible = "regulator-fixed"; regulator-name = "qep_vreg"; From cd74b75253a08c65e7bf69d08e0c195a173f4888 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 8 Apr 2026 16:36:42 +0800 Subject: [PATCH 0719/1133] PENDING: arm64: qcom: dts: talos: add TGU device in staging dtso Add TGU device for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/talos-staging.dtso | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/talos-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 355531779fa00..d551b67399ed6 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -582,3 +582,5 @@ dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3-camx.dtb talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb + +dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/talos-staging.dtso b/arch/arm64/boot/dts/qcom/talos-staging.dtso new file mode 100644 index 0000000000000..04602073418d4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-staging.dtso @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Talos staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@6b0c000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x6b0c000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From d7d7ddc6e82a8dcf0fd68e1a03cc477214ba4483 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Apr 2026 14:46:05 +0800 Subject: [PATCH 0720/1133] PENDING: arm64: dts: qcom: lemans: add TGU device in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/lemans-staging.dtso | 27 ++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index d551b67399ed6..a9347fd204638 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -538,6 +538,8 @@ dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-staging.dtbo + monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-staging.dtso b/arch/arm64/boot/dts/qcom/lemans-staging.dtso new file mode 100644 index 0000000000000..ad919bfb6b19a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-staging.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Lemans staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@4b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@4b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 7cf45e0738256d0f355126cd697c606546632beb Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Apr 2026 14:59:42 +0800 Subject: [PATCH 0721/1133] PENDING: arm64: dts: qcom: monaco: add TGU device in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/monaco-staging.dtso | 27 ++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index a9347fd204638..53ccc455200f9 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -550,6 +550,8 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo + qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-staging.dtso b/arch/arm64/boot/dts/qcom/monaco-staging.dtso new file mode 100644 index 0000000000000..fc44741b8caab --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-staging.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Monaco staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@4b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@4b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x4b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 564fdefff50b7a69d6a040e10a75cddb1e1b7ff8 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Apr 2026 15:11:57 +0800 Subject: [PATCH 0722/1133] PENDING: arm64: dts: qcom: kodiak: add TGU device in staging dtso Add TGU device for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/kodiak-staging.dtso | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/kodiak-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 53ccc455200f9..66c5f7fa1da87 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -588,3 +588,5 @@ talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += kodiak-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/kodiak-staging.dtso b/arch/arm64/boot/dts/qcom/kodiak-staging.dtso new file mode 100644 index 0000000000000..1d4c6d7d39dd0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/kodiak-staging.dtso @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Kodiak staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@6b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x6b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 25e97ce5a12927bf56bb3619645850e10a699b59 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 22 Apr 2026 16:49:21 +0530 Subject: [PATCH 0723/1133] QCLINUX: arm64: dts: qcom: talos-evk: Switch to interrupt-cells 4 Update Talos EVK camera DT nodes to use 4-cell interrupt specifiers, aligning with upstream Talos GIC changes required for PPI interrupt partitioning. This Change is required to remain compliant with the updated GIC binding, even for SPI-based camera interrupts. Link: https://lore.kernel.org/all/20260108092542.1371-2-yuanjie.yang@oss.qualcomm.com/ Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/talos-camera.dtsi | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/talos-camera.dtsi b/arch/arm64/boot/dts/qcom/talos-camera.dtsi index e0f59fb00a5fc..7d6f1268fa396 100644 --- a/arch/arm64/boot/dts/qcom/talos-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-camera.dtsi @@ -15,7 +15,7 @@ <0x0 0xac18000 0x0 0x3000>; reg-names = "icp_qgic", "icp_sierra", "icp_csr"; reg-cam-base = <0x00000 0x10000 0x18000>; - interrupts = ; + interrupts = ; interrupt-names = "a5"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -92,7 +92,7 @@ <0x0 0xac42000 0x0 0x5000>; reg-names = "cam_cpas_top", "cam_camnoc"; reg-cam-base = <0x40000 0x42000>; - interrupts = ; + interrupts = ; interrupt-names = "cpas_camnoc"; camnoc-axi-min-ib-bw = <3000000000>; power-domains = <&camcc TITAN_TOP_GDSC>; @@ -505,7 +505,7 @@ reg = <0x0 0xac48000 0x0 0x1000>; reg-names = "cpas-cdm"; reg-cam-base = <0x48000>; - interrupts = ; + interrupts = ; interrupt-names = "cpas-cdm"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -545,7 +545,7 @@ reg = <0x0 0xac4a000 0x0 0x4000>; reg-names = "cci"; reg-cam-base = <0x4a000>; - interrupts = ; + interrupts = ; interrupt-names = "CCI"; operating-points-v2 = <&cci_opp_table>; power-domains = <&camcc TITAN_TOP_GDSC>; @@ -642,7 +642,7 @@ reg = <0x0 0xac4e000 0x0 0x4000>; reg-names = "jpege_hw"; reg-cam-base = <0x4e000>; - interrupts = ; + interrupts = ; interrupt-names = "jpeg"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -681,7 +681,7 @@ reg = <0x0 0xac52000 0x0 0x4000>; reg-names = "jpegdma_hw"; reg-cam-base = <0x52000>; - interrupts = ; + interrupts = ; interrupt-names = "jpegdma"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -721,7 +721,7 @@ reg-names = "csiphy"; operating-points-v2 = <&csiphy0_opp_table>; reg-cam-base = <0x65000>; - interrupts = ; + interrupts = ; interrupt-names = "CSIPHY0"; csi-vdd-voltage = <1200000>; mipi-csi-vdd-supply = <&vreg_l11a>; @@ -770,7 +770,7 @@ reg-names = "csiphy"; operating-points-v2 = <&csiphy1_opp_table>; reg-cam-base = <0x66000>; - interrupts = ; + interrupts = ; interrupt-names = "CSIPHY1"; csi-vdd-voltage = <1200000>; mipi-csi-vdd-supply = <&vreg_l11a>; @@ -819,7 +819,7 @@ reg-names = "csiphy"; operating-points-v2 = <&csiphy2_opp_table>; reg-cam-base = <0x67000>; - interrupts = ; + interrupts = ; interrupt-names = "CSIPHY2"; csi-vdd-voltage = <1200000>; mipi-csi-vdd-supply = <&vreg_l11a>; @@ -867,7 +867,7 @@ reg = <0x0 0xac6b000 0x0 0xa00>; reg-names = "lrme"; reg-cam-base = <0x6b000>; - interrupts = ; + interrupts = ; interrupt-names = "lrme"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1056,7 +1056,7 @@ <0x0 0xac42000 0x0 0x5000>; reg-names = "ife0", "cam_camnoc"; reg-cam-base = <0xaf000 0x42000>; - interrupts = ; + interrupts = ; interrupt-names = "ife0"; power-domains = <&camcc IFE_0_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1128,7 +1128,7 @@ reg = <0x0 0xacb3000 0x0 0x1000>; reg-names = "csid0"; reg-cam-base = <0xb3000>; - interrupts = ; + interrupts = ; interrupt-names = "csid0"; power-domains = <&camcc IFE_0_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1211,7 +1211,7 @@ <0x0 0xac42000 0x0 0x5000>; reg-names = "ife1", "cam_camnoc"; reg-cam-base = <0xb6000 0x42000>; - interrupts = ; + interrupts = ; interrupt-names = "ife1"; power-domains = <&camcc IFE_1_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1283,7 +1283,7 @@ reg = <0x0 0xacba000 0x0 0x1000>; reg-names = "csid1"; reg-cam-base = <0xba000>; - interrupts = ; + interrupts = ; interrupt-names = "csid1"; power-domains = <&camcc IFE_1_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1365,7 +1365,7 @@ reg = <0x0 0xacc4000 0x0 0x4000>; reg-names = "ife-lite0"; reg-cam-base = <0xc4000>; - interrupts = ; + interrupts = ; interrupt-names = "ife-lite0"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, @@ -1432,7 +1432,7 @@ reg = <0x0 0xacc8000 0x0 0x1000>; reg-names = "csid-lite0"; reg-cam-base = <0xc8000>; - interrupts = ; + interrupts = ; interrupt-names = "csid-lite0"; power-domains = <&camcc TITAN_TOP_GDSC>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, From d76d7f5b13f427faeac71561f7897b51166f2e16 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Sun, 19 Apr 2026 20:35:15 +0530 Subject: [PATCH 0724/1133] PENDING: arm64: dts: qcom: rb3gen2-industrial-mezzanine: add overlay for QPS615 Add an overlay devicetree to enable Rb3Gen2 industrial board's 4 ethernet ports provided by two QPS615 PCIe Ethernet switches. Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/Makefile | 2 + ...-rb3gen2-industrial-mezzanine-staging.dtso | 119 ++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 66c5f7fa1da87..4776f8a2f08fa 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -563,6 +563,8 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-staging.dtbo + qcs8300-ride-camx-dtbs:= qcs8300-ride.dtb qcs8300-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-staging.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-staging.dtso new file mode 100644 index 0000000000000..edb284558b5a6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-staging.dtso @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&{/} { + qep_vreg: qep_vreg { + compatible = "regulator-fixed"; + regulator-name = "qep_vreg"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&pm7325_gpios 8 0>; + enable-active-high; + }; + + aqr_vreg: aqr_vreg { + compatible = "regulator-fixed"; + regulator-name = "aqr_vreg"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&pm7250b_gpios 4 0>; + enable-active-high; + }; +}; + +&pcie1_port0 { + pcie@0,0 { + pcie@3,0 { + qps615: pci@0,0 { + compatible = "pci1179,0220"; + interrupts-extended = <&tlmm 141 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&aqr_intn_wol_sig>; + phy-reset-gpios = <&qps615 0 GPIO_ACTIVE_LOW>; + phy-supply = <&aqr_vreg>; + reset-deassert-us = <221000>; + + gpio-controller; + #gpio-cells = <2>; + }; + + pci@0,1 { + compatible = "pci1179,0220"; + interrupts-extended = <&tlmm 101 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_intn_wol_sig>; + phy-reset-gpios = <&qps615 1 GPIO_ACTIVE_LOW>; + phy-supply = <&qep_vreg>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&pcie0_port { + pcie@0,0 { + pcie@3,0 { + pci@0,0 { + interrupts-extended = <&tlmm 136 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&rtl_rc0_intn_wol_sig>; + phy-mode = "sgmii"; + phy-reset-gpios = <&tlmm 90 GPIO_ACTIVE_LOW>; + reset-deassert-us = <75000>; + }; + + pci@0,1 { + interrupts-extended = <&tlmm 142 IRQ_TYPE_EDGE_FALLING>; + interrupt-names = "wol_irq"; + pinctrl-names = "default"; + pinctrl-0 = <&napa_rc0_intn_wol_sig>; + phy-reset-gpios = <&tlmm 25 GPIO_ACTIVE_LOW>; + phy-supply = <&qep_vreg>; + reset-deassert-us = <20000>; + }; + }; + }; +}; + +&tlmm { + qps615_intn_wol { + aqr_intn_wol_sig: aqr_intn_wol_sig { + pins = "gpio141"; + function = "gpio"; + input-enable; + bias-disable; + }; + + napa_intn_wol_sig: napa_intn_wol_sig { + pins = "gpio101"; + function = "gpio"; + input-enable; + bias-disable; + }; + + rtl_rc0_intn_wol_sig: rtl_rc0_intn_wol_sig { + pins = "gpio136"; + function = "gpio"; + input-enable; + bias-disable; + }; + + napa_rc0_intn_wol_sig: napa_rc0_intn_wol_sig { + pins = "gpio142"; + function = "gpio"; + input-enable; + bias-disable; + }; + }; +}; From 9d7e4310fa0f8f6bb7537f3d3e98d2c8ac4bd96e Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 28 Apr 2026 14:50:22 +0800 Subject: [PATCH 0725/1133] PENDING: arm64: dts: qcom: glymur: add TGU and ETR in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file and add ETR devices for supporting DDR memory trace. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 + arch/arm64/boot/dts/qcom/glymur-staging.dtso | 201 +++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/glymur-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 4776f8a2f08fa..ef7da9013ea61 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -592,3 +592,5 @@ dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += kodiak-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/glymur-staging.dtso b/arch/arm64/boot/dts/qcom/glymur-staging.dtso new file mode 100644 index 0000000000000..0b95e568e1c00 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-staging.dtso @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Glymur staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + ctcu@10001000 { + compatible = "qcom,glymur-ctcu", "qcom,sa8775p-ctcu"; + reg = <0x0 0x10001000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ctcu_in0: endpoint { + remote-endpoint = <&etr0_out>; + }; + }; + + port@1 { + reg = <1>; + + ctcu_in1: endpoint { + remote-endpoint = <&etr1_out>; + }; + }; + }; + }; + + replicator@10046000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x10046000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + qdss_rep_in: endpoint { + remote-endpoint = <&swao_rep_out0>; + }; + }; + }; + + out-ports { + port { + qdss_rep_out0: endpoint { + remote-endpoint = <&etr_rep_in>; + }; + }; + }; + }; + + tmc@10048000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x10048000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x00e0 0x0000>; + + arm,scatter-gather; + + in-ports { + port { + etr0_in: endpoint { + remote-endpoint = <&etr_rep_out0>; + }; + }; + }; + + out-ports { + port { + etr0_out: endpoint { + remote-endpoint = <&ctcu_in0>; + }; + }; + }; + }; + + replicator@1004e000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x1004e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + port { + etr_rep_in: endpoint { + remote-endpoint = <&qdss_rep_out0>; + }; + }; + }; + + out-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + etr_rep_out0: endpoint { + remote-endpoint = <&etr0_in>; + }; + }; + + port@1 { + reg = <1>; + + etr_rep_out1: endpoint { + remote-endpoint = <&etr1_in>; + }; + }; + }; + }; + + tmc@1004f000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x1004f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + iommus = <&apps_smmu 0x0100 0x0000>; + + arm,scatter-gather; + + in-ports { + port { + etr1_in: endpoint { + remote-endpoint = <&etr_rep_out1>; + }; + }; + }; + + out-ports { + port { + etr1_out: endpoint { + remote-endpoint = <&ctcu_in1>; + }; + }; + }; + }; + + tgu@11c02000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c02000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + replicator@11c06000 { + out-ports { + port@0 { + reg = <0>; + + swao_rep_out0: endpoint { + remote-endpoint = <&qdss_rep_in>; + }; + }; + }; + }; + + tgu@11c0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@11c0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@11c10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11c10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 219b93b9f7d63c00b2de79a05a806251a1bc2dab Mon Sep 17 00:00:00 2001 From: Vishwas Udupa Date: Fri, 3 Apr 2026 02:17:06 -0700 Subject: [PATCH 0726/1133] FROMLIST: arm64: dts: qcom: install DT overlays via dtbs_install Overlay binaries (.dtbo) are currently only built implicitly as dependencies of composite firmware images and are therefore absent from the kernel install output. Even when final DTBs are produced at build time, some distributions rely on standalone DTBOs for runtime selection and application by bootloaders or firmware. Without explicit install targets, DTBOs are not picked up by the standard dtbs_install flow and therefore cannot be packaged alongside DTBs. Add explicit dtb-$(CONFIG_ARCH_QCOM) entries for all DT overlays defined in this Makefile so they are installed via dtbs_install, matching existing DTB install behaviour. Link: https://lore.kernel.org/all/20260428123725.3457865-1-vudupa@qti.qualcomm.com Signed-off-by: Vishwas Udupa --- arch/arm64/boot/dts/qcom/Makefile | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index ef7da9013ea61..24be52f4caa28 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -7,7 +7,9 @@ apq8016-sbc-usb-host-dtbs := apq8016-sbc.dtb apq8016-sbc-usb-host.dtbo dtb-$(CONFIG_ARCH_QCOM) += sar2130p-qar2130p.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-d3-camera-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-d3-camera-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-usb-host.dtb +dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc-usb-host.dtbo dtb-$(CONFIG_ARCH_QCOM) += apq8016-schneider-hmibsc.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8039-t2.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8094-sony-xperia-kitakami-karin_windy.dtb @@ -56,13 +58,16 @@ lemans-evk-camera-csi1-imx577-dtbs := lemans-evk.dtb lemans-evk-camera-csi1-imx5 lemans-evk-camera-dtbs := lemans-evk.dtb lemans-evk-camera.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera-csi1-imx577.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera-csi1-imx577.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camera.dtbo lemans-evk-el2-dtbs := lemans-evk.dtb lemans-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-el2.dtb lemans-evk-ifp-mezzanine-dtbs := lemans-evk.dtb lemans-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-ifp-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += mahua-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += mahua-lenovo-thinkpad-t14s-gen7-lcd.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-fairphone-fp6.dtb @@ -73,6 +78,7 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-evk.dtb monaco-evk-camera-imx577-dtbs := monaco-evk.dtb monaco-evk-camera-imx577.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camera-imx577.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camera-imx577.dtbo monaco-evk-el2-dtbs := monaco-evk.dtb monaco-el2.dtbo @@ -82,6 +88,7 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk-ifp-mezzanine.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-el2.dtb monaco-evk-ifp-mezzanine-dtbs := monaco-evk.dtb monaco-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += msm8216-samsung-fortuna3g.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-acer-a1-724.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-alcatel-idol347.dtb @@ -191,6 +198,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride.dtb qcs615-ride-el2-dtbs := qcs615-ride.dtb talos-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-radxa-dragon-q6a.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb @@ -198,7 +206,9 @@ qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vis qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-minipc-g1iot.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-rubikpi3.dtb @@ -222,6 +232,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride.dtb qcs8300-ride-el2-dtbs := qcs8300-ride.dtb monaco-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8550-aim300-aiot.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs8550-ayntec-odin2mini.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs8550-ayntec-odin2portal.dtb @@ -238,6 +249,7 @@ qcs9100-ride-r3-el2-dtbs := qcs9100-ride-r3.dtb lemans-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qdu1000-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb2210-arduino-imola.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1.dtb @@ -245,6 +257,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1.dtb qrb2210-rb1-vision-mezzanine-dtbs := qrb2210-rb1.dtb qrb2210-rb1-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1-vision-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qrb4210-rb2.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb @@ -252,6 +265,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb qrb5165-rb5-vision-mezzanine-dtbs := qrb5165-rb5.dtb qrb5165-rb5-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5-vision-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5-vision-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qru1000-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8155p-adp.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8295p-adp.dtb @@ -260,6 +274,7 @@ sc7180-acer-aspire1-el2-dtbs := sc7180-acer-aspire1.dtb sc7180-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc7180-acer-aspire1.dtb sc7180-acer-aspire1-el2.dtb sc7180-ecs-liva-qc710-el2-dtbs := sc7180-ecs-liva-qc710.dtb sc7180-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc7180-ecs-liva-qc710.dtb sc7180-ecs-liva-qc710-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += sc7180-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc7180-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1.dtb dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1-lte.dtb @@ -335,6 +350,7 @@ sc8280xp-microsoft-arcata-el2-dtbs := sc8280xp-microsoft-arcata.dtb sc8280xp-el2 dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-microsoft-arcata.dtb sc8280xp-microsoft-arcata-el2.dtb sc8280xp-microsoft-blackrock-el2-dtbs := sc8280xp-microsoft-blackrock.dtb sc8280xp-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-microsoft-blackrock.dtb sc8280xp-microsoft-blackrock-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += sda660-inforce-ifc6560.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm450-lenovo-tbx605f.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm450-motorola-ali.dtb @@ -353,6 +369,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c.dtb sdm845-db845c-navigation-mezzanine-dtbs := sdm845-db845c.dtb sdm845-db845c-navigation-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c-navigation-mezzanine.dtb +dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c-navigation-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += sdm845-google-crosshatch.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-google-blueline.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm845-lg-judyln.dtb @@ -434,7 +451,9 @@ sm8550-hdk-rear-camera-card-dtbs := sm8550-hdk.dtb sm8550-hdk-rear-camera-card.d dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-display-card-rear-camera-card.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-display-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-display-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-rear-camera-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk-rear-camera-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8550-hdk.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8550-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8550-qrd.dtb @@ -448,7 +467,9 @@ sm8650-hdk-rear-camera-card-dtbs := sm8650-hdk.dtb sm8650-hdk-rear-camera-card.d dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-display-card-rear-camera-card.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-display-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-display-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-rear-camera-card.dtb +dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk-rear-camera-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8650-hdk.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += sm8650-qrd.dtb @@ -462,12 +483,14 @@ talos-evk-el2-dtbs := talos-evk.dtb talos-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-el2.dtb talos-evk-usb1-peripheral-dtbs := talos-evk.dtb talos-evk-usb1-peripheral.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-usb1-peripheral.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-usb1-peripheral.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camera-imx577.dtbo talos-evk-camera-imx577-dtbs := talos-evk.dtb talos-evk-camera-imx577.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camera-imx577.dtb talos-evk-lvds-auo,g133han01-dtbs := \ talos-evk.dtb talos-evk-lvds-auo,g133han01.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-lvds-auo,g133han01.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-lvds-auo,g133han01.dtbo talos-evk-rpi-display-2-5in-dtbs := \ talos-evk.dtb talos-evk-rpi-display-2-5in.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-rpi-display-2-5in.dtb @@ -523,6 +546,7 @@ x1p64100-microsoft-denali-el2-dtbs := x1p64100-microsoft-denali.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p64100-microsoft-denali.dtb x1p64100-microsoft-denali-el2.dtb x1p42100-microsoft-sp12in-el2-dtbs := x1p42100-microsoft-sp12in.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p42100-microsoft-sp12in.dtb x1p42100-microsoft-sp12in-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += x1-el2.dtbo hamoa-evk-camx-dtbs := hamoa-iot-evk.dtb hamoa-evk-camx.dtbo From c5599b95f88de7103493ea4ea4cec0d9d652720b Mon Sep 17 00:00:00 2001 From: Vishwas Udupa Date: Thu, 30 Apr 2026 03:53:25 -0700 Subject: [PATCH 0727/1133] QCLINUX: arm64: dts: qcom: Install camx DTBO overlays Install Qualcomm camx DTBO overlay files by adding them to the dtb-$(CONFIG_ARCH_QCOM) build/install list This makes DTBOs available through the standard dtbs_install flow and ensures they are included in distro kernel packages Signed-off-by: Vishwas Udupa --- arch/arm64/boot/dts/qcom/Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 24be52f4caa28..1959a8b530523 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -551,14 +551,17 @@ dtb-$(CONFIG_ARCH_QCOM) += x1-el2.dtbo hamoa-evk-camx-dtbs := hamoa-iot-evk.dtb hamoa-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtbo lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtbo lemans-camx-el2-dtbs := lemans-evk-el2.dtb lemans-evk-camx.dtbo lemans-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-staging.dtbo @@ -567,10 +570,12 @@ dtb-$(CONFIG_ARCH_QCOM) += lemans-staging.dtbo monaco-evk-camx-dtbs := monaco-evk.dtb monaco-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camx.dtbo monaco-camx-el2-dtbs := monaco-evk-el2.dtb monaco-evk-camx.dtbo monaco-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo @@ -579,11 +584,13 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtbo qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ qcs6490-rb3gen2-vision-mezzanine-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-staging.dtbo @@ -592,6 +599,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-staging.dtbo qcs8300-ride-camx-dtbs:= qcs8300-ride.dtb qcs8300-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcs8300-ride-camx.dtbo qcs9100-ride-camx-dtbs:= qcs9100-ride.dtb sa8775p-ride-camx.dtbo @@ -604,6 +612,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3-camx.dtb sa8775p-ride-camx-dtbs:= sa8775p-ride.dtb sa8775p-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtbo sa8775p-ride-r3-camx-dtbs:= sa8775p-ride-r3.dtb sa8775p-ride-camx.dtbo @@ -612,6 +621,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3-camx.dtb talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo From 4b266e6a6efbd6314526f2e0b8a1152b11780816 Mon Sep 17 00:00:00 2001 From: Kripalsinh Rana Date: Tue, 5 May 2026 16:24:45 +0530 Subject: [PATCH 0728/1133] QCLINUX: arm64: dts: qcom: Add kodiak lite camx overlay dts Add CAMX overlay dts file for kodiak lite boards. This change also enables the compilation of the CAMX overlay for kodiak lite boards. Signed-off-by: Kripalsinh Rana --- arch/arm64/boot/dts/qcom/Makefile | 4 +++ .../arm64/boot/dts/qcom/qcs5430-fps-camx.dtso | 32 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs5430-fps-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 1959a8b530523..38d382d4f2f6f 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -586,6 +586,10 @@ qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtbo +qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs5430-fps-camx.dtb + qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ qcs6490-rb3gen2-vision-mezzanine-camx.dtbo diff --git a/arch/arm64/boot/dts/qcom/qcs5430-fps-camx.dtso b/arch/arm64/boot/dts/qcom/qcs5430-fps-camx.dtso new file mode 100644 index 0000000000000..4255147f00ef9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs5430-fps-camx.dtso @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* +* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +*/ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "qcs6490-camera.dtsi" +#include "qcs6490-rb3gen2-camera-sensor.dtsi" + +&cam_csid2 { + status = "disabled"; +}; + +&cam_vfe2 { + status = "disabled"; +}; + +&camss { + status = "disabled"; +}; + +&cci1 { + status = "disabled"; +}; From 0ac6864607023ff45d12cc154522ea6076b6bd6f Mon Sep 17 00:00:00 2001 From: Kripalsinh Rana Date: Tue, 5 May 2026 16:24:45 +0530 Subject: [PATCH 0729/1133] QCLINUX: arm64: dts: qcom: Add kodiak lite camx overlay dts Add CAMX overlay dts file for kodiak lite boards. This change also enables the compilation of the CAMX overlay for kodiak lite boards. Signed-off-by: Kripalsinh Rana --- arch/arm64/boot/dts/qcom/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 38d382d4f2f6f..3a7ed7d38d7ec 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -581,6 +581,10 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo +qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += qcs5430-fps-camx.dtb + qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb From 1c9607e389371769768307a4fb11c2accd78ccd8 Mon Sep 17 00:00:00 2001 From: Kripalsinh Rana Date: Tue, 5 May 2026 16:24:45 +0530 Subject: [PATCH 0730/1133] QCLINUX: arm64: dts: qcom: Add kodiak lite camx overlay dts Add CAMX overlay dts file for kodiak lite boards. This change also enables the compilation of the CAMX overlay for kodiak lite boards. Signed-off-by: Kripalsinh Rana --- arch/arm64/boot/dts/qcom/Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 3a7ed7d38d7ec..2867f8faeb7d7 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -590,10 +590,6 @@ qcs615-ride-camx-dtbs := qcs615-ride.dtb qcs615-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-camx.dtbo -qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo - -dtb-$(CONFIG_ARCH_QCOM) += qcs5430-fps-camx.dtb - qcs6490-rb3gen2-vision-mezzanine-camx-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb \ qcs6490-rb3gen2-vision-mezzanine-camx.dtbo From 165dfdbc50e9dc153e3126767b94c9fc839dde01 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 22 Apr 2026 20:32:50 +0530 Subject: [PATCH 0731/1133] QCLINUX: arm64: dts: qcom: Add Purwa camx overlay dts Add CAMX overlay dts file for purwa boards. This change also enables the compilation of the CAMX overlay for purwa boards. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 4 + arch/arm64/boot/dts/qcom/purwa-camera.dtsi | 2056 ++++++++++++++++++ arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso | 25 + 3 files changed, 2085 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/purwa-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 2867f8faeb7d7..b04d017dd00b5 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -581,6 +581,10 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo +purwa-evk-camx-dtbs := purwa-iot-evk.dtb purwa-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += purwa-evk-camx.dtb + qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs5430-fps-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi new file mode 100644 index 0000000000000..5896e5759e22f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi @@ -0,0 +1,2056 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac01000 { + compatible = "qcom,cam-icp_v2"; + icp-version = <0x0200>; + reg = <0x0 0xac01000 0x0 0x400>, + <0x0 0xac01800 0x0 0x400>, + <0x0 0x0ac04000 0x0 0x1000>; + reg-names = "icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + clocks = <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-names = "icp_ahb_clk", + "icp_clk_src", + "icp_clk"; + clock-rates = <0 300000000 0>, + <0 400000000 0>, + <0 480000000 0>, + <0 600000000 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "icp_clk_src"; + operating-points-v2 = <&icp_opp_table>; + clock-control-debugfs = "true"; + fw_name = "qcom/x1p4x100/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + ubwc-bps-fetch-cfg = <0x707b 0x7083>; + ubwc-bps-write-cfg = <0x161ef 0x1620f>; + qos-val = <0x00000A0A>; + cam_hw_pid = <3>; + cell-index = <0>; + status = "okay"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cpas: qcom,cam-cpas@ac13000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac13000 0x0 0x1000>, + <0x0 0xac19000 0x0 0xC000>, + <0x0 0xbbf0000 0x0 0x1F00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x13000 0x19000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_ahb_clk", + "gcc_axi_hf_clk", + "gcc_axi_sf_clk", + "cam_cc_slow_ahb_clk_src", + "cpas_ahb_clk", + "cpas_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "camnoc_axi_clk_src", + "camnoc_axi_clk", + "camnoc_axi_nrt_clk", + "camcc_debug_clk"; + clock-rates = < 0 0 0 0 0 0 0 0 0 0 0 0>, + < 0 0 0 64000000 0 0 80000000 0 240000000 0 0 0>, + < 0 0 0 80000000 0 0 100000000 0 300000000 0 0 0>, + < 0 0 0 80000000 0 0 400000000 0 400000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvsd1", "lowsvs", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <400000000>; + src-clock-name = "camnoc_axi_clk_src"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + cam-icc-path-names = "cam_ahb"; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects =<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", + "cam_hf_0", + "cam_sf_0", + "cam_sf_icp"; + rpmh-bcm-info = <12 0x4 0x800 0 4>; + cam-ahb-num-cases = <8>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 76800>, <0 150000>, + <0 150000>, <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", + "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", + "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy4", "cci0", "cci1", "csid0", + "csid1", "csid2", "ife0", "ife1", "ife2", "ipe0", + "rt-cdm0", "rt-cdm1", "rt-cdm2", "rt-cdm3", + "cam-cdm-intf0", "bps0", "icp0", "jpeg-dma0", + "jpeg-enc0", "tpg13", "tpg14", "tpg15"; + cell-index = <0>; + status = "okay"; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_wr>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <2>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_rd>; + }; + + ife0_linear_stats_wr: ife0-linear-stats-wr { + cell-index = <3>; + node-name = "ife0-linear-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife0_pdaf_wr: ife0-pdaf-wr { + cell-index = <4>; + node-name = "ife0-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife0_ubwc_wr: ife0-ubwc-wr { + cell-index = <6>; + node-name = "ife0-ubwc-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ipe0_all_wr: ipe0-all-wr { + cell-index = <7>; + node-name = "ipe0-all-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt0_wr>; + }; + + ipe0_in_rd: ipe0-in-rd { + cell-index = <8>; + node-name = "ipe0-in-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + ipe0_ref_rd: ipe0-ref-rd { + cell-index = <9>; + node-name = "ipe0-ref-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <10>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <11>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <12>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <13>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + rt_cdm0_all_rd: rt-cdm0-all-rd { + cell-index = <14>; + node-name = "rt-cdm0-all-rd"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 0 */ + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <15>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 1 */ + rt_cdm3_all_rd: rt-cdm3-all-rd { + cell-index = <16>; + node-name = "rt-cdm3-all-rd"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_rd0: level1-nrt0-rd0 { + cell-index = <17>; + node-name = "level1-nrt0-rd0"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_rd1: level1-nrt0-rd1 { + cell-index = <18>; + node-name = "level1-nrt0-rd1"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_wr0: level1-nrt0-wr0 { + cell-index = <19>; + node-name = "level1-nrt0-wr0"; + parent-node = <&level2_nrt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr0: level1-rt0-wr0 { + cell-index = <20>; + node-name = "level1-ife-ubwc-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr1: level1-rt0-wr1 { + cell-index = <21>; + node-name = "level1-ife-rdi-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr2: level1-rt0-wr2 { + cell-index = <22>; + node-name = "level1-ife-pdaf"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr3: level1-rt0-wr3 { + cell-index = <23>; + node-name = "level1-ife01-linear-stats"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr4: level1-rt0-wr4 { + cell-index = <24>; + node-name = "level1-ifelite"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_nrt0_rd: level2-nrt0-rd { + cell-index = <25>; + node-name = "level2-nrt0-rd"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt0_wr: level2-nrt0-wr { + cell-index = <26>; + node-name = "level2-nrt0-wr"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt1_rd: level2-nrt1-rd { + cell-index = <27>; + node-name = "level2-nrt1-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + bus-width-factor = <4>; + }; + + level2_rt0_rd: level2-rt0-rd { + cell-index = <28>; + node-name = "level2-rt0-rd"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_rt0_wr: level2-rt0-wr { + cell-index = <29>; + node-name = "level2-rt0-wr"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <30>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <31>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { + cell-index = <32>; + node-name = "level3-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cci0: qcom,cci0@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "cci0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + operating-points-v2 = <&cci0_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci0_active>; + pinctrl-1 = <&cci0_suspend>; + pinctrl-2 = <&cci1_active>; + pinctrl-3 = <&cci1_suspend>; + cell-index = <0>; + status = "okay"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cci1: qcom,cci1@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "cci1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci2_active>; + pinctrl-1 = <&cci2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + operating-points-v2 = <&cci1_opp_table>; + cell-index = <1>; + status = "okay"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + qcom,rt-cdm0@ac25000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac25000 0x0 0x400>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x25000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <400000000 0>; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table0>; + nrt-device; + cdm-client-names = "ife0", "dualife0"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <25>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac2a000 { + compatible = "qcom,cam_jpeg_enc_680"; + reg = <0x0 0xac2a000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegenc_hw", "cam_camnoc"; + reg-cam-base = <0x2a000 0x19000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegenc_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_enc_opp_table>; + nrt-device; + cam_hw_pid = <12 14>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac2b000 { + compatible = "qcom,cam_jpeg_dma_680"; + reg = <0x0 0xac2b000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x2b000 0x19000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegdma_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_dma_opp_table>; + nrt-device; + cam_hw_pid = <13 15>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@ac2c000 { + compatible = "qcom,cam-bps680"; + reg = <0x0 0xac2c000 0x0 0xb000>; + reg-names = "bps_top"; + reg-cam-base = <0x2c000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_FAST_AHB_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_CPAS_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_fast_ahb_clk", + "bps_clk_src", + "bps_clk", + "cam_cc_cpas_bps_clk"; + clock-rates = <0 0 160000000 0 0>, + <0 0 200000000 0 0>, + <0 0 400000000 0 0>, + <0 0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <6 7>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@ac42000 { + compatible = "qcom,cam-ipe680"; + reg = <0x0 0xac42000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x42000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_NPS_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_PPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_CLK_SRC>, + <&camcc CAM_CC_IPE_NPS_CLK>, + <&camcc CAM_CC_IPE_PPS_CLK>, + <&camcc CAM_CC_CPAS_IPE_NPS_CLK>; + clock-names = "ipe_nps_ahb_clk", + "ipe_nps_fast_ahb_clk", + "ipe_pps_fast_ahb_clk", + "ipe_nps_clk_src", + "ipe_nps_clk", + "ipe_pps_clk", + "cam_cc_cpas_ipe_nps_clk"; + clock-rates = <0 0 0 304000000 0 0 0>, + <0 0 0 364000000 0 0 0>, + <0 0 0 500000000 0 0 0>, + <0 0 0 600000000 0 0 0>, + <0 0 0 700000000 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + nrt-device; + src-clock-name = "ipe_nps_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <22 23 30>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-304000000 { + opp-hz = /bits/ 64 <304000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-364000000 { + opp-hz = /bits/ 64 <364000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0@ac62000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac62000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x62000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>; + clock-names = "ife_0_fast_ahb", + "ife_0_clk_src", + "ife_0_clk", + "cam_cc_cpas_ife_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <16 4 20 8>; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb7000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb7000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb7000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0@acc6000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacc6000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0@acc6000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacc6000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <0>; + cell-index = <1>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1@acca000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacca000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1@acca000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacca000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <1>; + cell-index = <2>; + status = "okay"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@ace4000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy0_opp_table>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4@acec000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xacec000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xec000>; + interrupts = ; + interrupt-names = "CSIPHY4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l1c_1p2>; + csi-vdd-0p9-supply = <&vreg_l2c_0p8>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 920000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "nominal"; + clock-rates = <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy4_opp_table>; + cell-index = <4>; + status = "okay"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acf6000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf6000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xf6000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + cell-index = <13>; + phy-id = <0>; + status = "okay"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acf7000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf7000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xf7000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + cell-index = <14>; + phy-id = <1>; + status = "okay"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acf8000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf8000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xf8000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + cell-index = <15>; + phy-id = <2>; + status = "okay"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm2@acf9000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacf9000 0x0 0x400>; + reg-names = "rt-cdm2"; + reg-cam-base = <0xf9000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table2>; + nrt-device; + cdm-client-names = "ife2"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <24>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <2>; + status = "okay"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm3@acfa000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacfa000 0x0 0x400>; + reg-names = "rt-cdm3"; + reg-cam-base = <0xfa000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table3>; + nrt-device; + cdm-client-names = "ife3"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <27>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <3>; + status = "okay"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc"; + cell-index = <0>; + status = "okay"; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + status = "okay"; + icp_pc_en; + icp_use_pil; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + force_cache_allocs; + need_shared_buffer_padding; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18A0 0x0000>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1800 0x0060>, + <&apps_smmu 0x1820 0x0060>, + <&apps_smmu 0x1840 0x0060>, + <&apps_smmu 0x1860 0x0060>, + <&apps_smmu 0x1900 0x0000>, + <&apps_smmu 0x1980 0x0020>, + <&apps_smmu 0x19A0 0x0020>; + cam-smmu-label = "icp"; + iova-region-discard = <0xe0000000 0x800000>; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-qdss-region { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + iova-region-discard = <0xe0000000 0x800000>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xFC00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0800 0x0060>, + <&apps_smmu 0x0820 0x0060>, + <&apps_smmu 0x0840 0x0060>, + <&apps_smmu 0x0860 0x0060>; + dma-coherent; + cam-smmu-label = "ife"; + multiple-client-devices; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18E0 0x0000>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_x1e80100"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_int: cam-sensor-active-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* mclk0 */ + config { + pins = "gpio96"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* mclk0 */ + config { + pins = "gpio96"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + + config { + pins = "gpio97"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* mclk4 */ + config { + pins = "gpio100"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* mclk4 */ + config { + pins = "gpio100"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_aon"; + }; + }; + + cam_sensor_suspend_int: cam-sensor-suspend-int { + /* CUSTOM */ + mux { + pins = "gpio19"; + function = "cam_pwe"; + }; + + config { + pins = "gpio19"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio110"; + function = "gpio"; + }; + + config { + pins = "gpio110"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET REAR */ + config { + pins = "gpio237"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + output-low; + }; + + mux { + pins = "gpio237"; + function = "gpio"; + }; + }; + + cci0_active: cci0-active { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci0_suspend: cci0-suspend { + config { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio101","gpio102"; + function = "cci_i2c"; + }; + }; + + cci1_active: cci1-active { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci1_suspend: cci1-suspend { + config { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio103","gpio104"; + function = "cci_i2c"; + }; + }; + + cci2_active: cci2-active { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; // Only 2 + function = "cci_i2c"; + }; + }; + + cci2_suspend: cci2-suspend { + config { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio105","gpio106"; + function = "cci_i2c"; + }; + }; + + cci3_active: cci3-active { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; + + cci3_suspend: cci3-suspend { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "aon_cci"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso new file mode 100644 index 0000000000000..26603aed4eafc --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "purwa-camera.dtsi" + +&camss { + status = "disabled"; +}; From 60e24620bb066aa7652db6bac2ec9ff542f224a0 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 18 May 2026 14:14:20 +0800 Subject: [PATCH 0732/1133] PENDING: arm64: dts: qcom: hamoa: add TGU in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/hamoa-staging.dtso | 35 +++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/hamoa-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index b04d017dd00b5..3da9a20604cc3 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -636,3 +636,5 @@ dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += kodiak-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += hamoa-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/hamoa-staging.dtso b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso new file mode 100644 index 0000000000000..feb3c7c5ccd82 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Hamoa staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@10b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 5451cc3a069fa7e4c54152b075ac23b5284a3bba Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 18 May 2026 14:18:09 +0800 Subject: [PATCH 0733/1133] PENDING: arm64: dts: qcom: sm8750: add TGU in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/sm8750-staging.dtso | 35 ++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/sm8750-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 3da9a20604cc3..543bf9293ad1c 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -638,3 +638,5 @@ dtb-$(CONFIG_ARCH_QCOM) += kodiak-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += sm8750-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/sm8750-staging.dtso b/arch/arm64/boot/dts/qcom/sm8750-staging.dtso new file mode 100644 index 0000000000000..68c477c63a328 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sm8750-staging.dtso @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * SM8750 staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@10b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 77e03db4be8d9b8423255cb5be3a9301408bf9a9 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 18 May 2026 14:21:04 +0800 Subject: [PATCH 0734/1133] PENDING: arm64: dts: qcom: kaanapali: add TGU in staging dtso Add TGU devices for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../boot/dts/qcom/kaanapali-staging.dtso | 43 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/kaanapali-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 543bf9293ad1c..d377f81e76c94 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -640,3 +640,5 @@ dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8750-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += kaanapali-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso b/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso new file mode 100644 index 0000000000000..d7a5b0b084872 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/kaanapali-staging.dtso @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Kaanapali staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@11301000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11301000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@1130e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x1130e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@1130f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x1130f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@11310000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11310000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From d1c701e42cc0813733bba2427c00c66d53b26fef Mon Sep 17 00:00:00 2001 From: Ignatius Michael Jihan Date: Fri, 15 May 2026 19:02:44 +0530 Subject: [PATCH 0735/1133] arm64: dts: qcom: hamoa: add CAMX EL2 overlay Add a device tree overlay to enable EL2 boot support for the Hamoa platform with CAMX configuration. CRs-Fixed: 4538425 Signed-off-by: Ignatius Michael Jihan --- arch/arm64/boot/dts/qcom/Makefile | 4 ++++ arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index d377f81e76c94..64f9af9c02f2b 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -553,6 +553,10 @@ hamoa-evk-camx-dtbs := hamoa-iot-evk.dtb hamoa-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtbo +hamoa-camx-el2-dtbs := hamoa-iot-evk-el2.dtb hamoa-evk-camx.dtbo hamoa-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += hamoa-camx-el2.dtb + lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso b/arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso new file mode 100644 index 0000000000000..5584660dbcfd6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camx-el2.dtso @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x1901 0x0>; + }; + }; + }; +}; From 76fe9f29f723431f4198f08ed52289accafae6c6 Mon Sep 17 00:00:00 2001 From: Ignatius Michael Jihan Date: Fri, 22 May 2026 17:01:49 +0530 Subject: [PATCH 0736/1133] QCLINUX: arm64: dts: qcom: add Purwa CAMX EL2 overlay Add a device tree overlay to enable EL2 boot support for the Purwa platform with CAMX configuration. CRs-Fixed: 4546991 Signed-off-by: Ignatius Michael Jihan --- arch/arm64/boot/dts/qcom/Makefile | 4 ++++ arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 64f9af9c02f2b..8b58715f5e2c8 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -589,6 +589,10 @@ purwa-evk-camx-dtbs := purwa-iot-evk.dtb purwa-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += purwa-evk-camx.dtb +purwa-camx-el2-dtbs := purwa-iot-evk-el2.dtb purwa-evk-camx.dtbo purwa-camx-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += purwa-camx-el2.dtb + qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs5430-fps-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso b/arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso new file mode 100644 index 0000000000000..5584660dbcfd6 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-camx-el2.dtso @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = "/soc@0/qcom,cam-icp"; + __overlay__ { + camera-firmware { + iommus = <&apps_smmu 0x1901 0x0>; + }; + }; + }; +}; From 7e3a9a1dc8f230ad83956a1b25eed4a5eb12df3e Mon Sep 17 00:00:00 2001 From: Vadlamani Manjusha Date: Thu, 21 May 2026 14:32:48 +0530 Subject: [PATCH 0737/1133] QCLINUX: arm64: dts: qcom: Enable combo mode for CSI1 port In order to enable combo mode on CSI1 mode, resources needs to be in shared mode. This change adds required resources under res-mgr node. Signed-off-by: Vadlamani Manjusha --- .../dts/qcom/lemans-evk-camera-sensor.dtsi | 77 +++++-------------- 1 file changed, 19 insertions(+), 58 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi index e1ee2ba8c78e6..959e2690848ff 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -125,7 +125,7 @@ }; /*cam0a-ov9282*/ - rb8_slot0: qcom,cam-sensor1 { + qcom,cam-sensor1 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <0>; sensor-position-roll = <0>; @@ -439,7 +439,7 @@ }; /*cam1-ov9282*/ - rb8_slot1: qcom,cam-sensor21 { + qcom,cam-sensor21 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; sensor-position-roll = <0>; @@ -454,10 +454,8 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; + pinctrl-0 = <&cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_suspend_rst1>; pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 73 0>, <&tlmm 133 0>, @@ -478,14 +476,14 @@ status = "ok"; }; - /*cam1-imx577*/ - qcom,cam-sensor26 { + /*cam1-cmk_imx577*/ + qcom,cam-sensor28 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; sensor-position-roll = <0>; sensor-position-pitch = <0>; sensor-position-yaw = <180>; - eeprom-src = <&eeprom_cam26>; + eeprom-src = <&eeprom_cam28>; cam_vio-supply = <&vreg_s4a>; regulator-names = "cam_vio"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; @@ -515,18 +513,17 @@ clock-names = "cam_clk"; clock-cntl-level = "nominal"; clock-rates = <24000000>; - cell-index = <26>; + cell-index = <28>; status = "ok"; }; - /*cam1-cmk_imx577*/ - qcom,cam-sensor28 { + /*cam1-ov9282*/ + qcom,cam-sensor31 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; sensor-position-roll = <0>; sensor-position-pitch = <0>; sensor-position-yaw = <180>; - eeprom-src = <&eeprom_cam28>; cam_vio-supply = <&vreg_s4a>; regulator-names = "cam_vio"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; @@ -536,13 +533,8 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 73 0>, - <&tlmm 133 0>, + <&expander2 2 0>, <&pmm8654au_0_gpios 8 0>; gpio-reset = <1>; gpio-custom1 = <2>; @@ -556,43 +548,7 @@ clock-names = "cam_clk"; clock-cntl-level = "nominal"; clock-rates = <24000000>; - cell-index = <28>; - status = "ok"; - }; - - eeprom_cam26: qcom,eeprom26 { - compatible = "qcom,eeprom"; - cam_vio-supply = <&vreg_s4a>; - regulator-names = "cam_vio"; - power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000>; - rgltr-max-voltage = <1800000>; - rgltr-load-current = <120000>; - gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 73 0>, - <&tlmm 133 0>, - <&pmm8654au_0_gpios 8 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK1", - "CAM_RESET1", - "CAM_CUSTOM1"; - sensor-mode = <0>; - cci-master = <0>; - clocks = <&camcc CAM_CC_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "nominal"; - clock-rates = <24000000>; - cell-index = <26>; + cell-index = <31>; status = "ok"; }; @@ -755,7 +711,7 @@ }; /*cam2-ov9282*/ - rb8_slot2: qcom,cam-sensor22 { + qcom,cam-sensor22 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <2>; sensor-position-roll = <0>; @@ -994,7 +950,7 @@ }; /*cam3-ov9282*/ - rb8_slot3: qcom,cam-sensor23 { + qcom,cam-sensor23 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <3>; sensor-position-roll = <0>; @@ -1115,6 +1071,11 @@ qcom,cam-res-mgr { compatible = "qcom,cam-res-mgr"; gpios-shared = <518 519 520 521>; + gpios-shared-pinctrl = <633>; + shared-pctrl-gpio-names = "mclk1"; + pinctrl-0 = <&cam_sensor_mclk1_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend>; + pinctrl-names = "mclk1_active", "mclk1_suspend"; status = "ok"; }; }; From 69dcbd59d7930383c262b3d0d0d5f0fff8a44c41 Mon Sep 17 00:00:00 2001 From: Vadlamani Manjusha Date: Mon, 25 May 2026 20:03:32 +0530 Subject: [PATCH 0738/1133] QCLINUX: arm64: dts: qcom: Fix GPIO free and acquire logic Prevent GPIOs managed by pinctrl from being requested and freed via the GPIO framework. Restrict GPIO request/free operations to non-pinctrl GPIOs by adding appropriate conditions. Signed-off-by: Vadlamani Manjusha --- .../dts/qcom/lemans-evk-camera-sensor.dtsi | 266 +++++++----------- 1 file changed, 105 insertions(+), 161 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi index 959e2690848ff..f7005902a98a2 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -125,7 +125,7 @@ }; /*cam0a-ov9282*/ - qcom,cam-sensor1 { + rb8_slot0: qcom,cam-sensor1 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <0>; sensor-position-roll = <0>; @@ -140,20 +140,16 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rst0>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rst0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 72 0>, - <&tlmm 132 0>, + gpios =<&tlmm 132 0>, <&pmm8654au_0_gpios 7 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK0", - "CAMIF_RESET0", + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK0_CLK>; @@ -181,21 +177,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rst0>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rst0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 72 0>, - <&tlmm 132 0>, + gpios =<&tlmm 132 0>, <&pmm8654au_0_gpios 7 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK0", - "CAMIF_RESET0", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK0_CLK>; clock-names = "cam_clk"; @@ -222,21 +214,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rst0>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rst0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 72 0>, - <&tlmm 132 0>, + gpios =<&tlmm 132 0>, <&pmm8654au_0_gpios 7 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK0", - "CAMIF_RESET0", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK0_CLK>; clock-names = "cam_clk"; @@ -257,21 +245,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rst0>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rst0>; + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 72 0>, - <&tlmm 132 0>, + gpios =<&tlmm 132 0>, <&pmm8654au_0_gpios 7 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK0", - "CAMIF_RESET0", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK0_CLK>; clock-names = "cam_clk"; @@ -292,20 +276,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rst0>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rst0>; - gpios = <&tlmm 72 0>, - <&tlmm 132 0>, + pinctrl-0 = <&cam_sensor_mclk0_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios =<&tlmm 132 0>, <&pmm8654au_0_gpios 7 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK0", - "CAMIF_RESET0", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1"; sensor-mode = <0>; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK0_CLK>; @@ -439,7 +420,7 @@ }; /*cam1-ov9282*/ - qcom,cam-sensor21 { + rb8_slot1: qcom,cam-sensor21 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; sensor-position-roll = <0>; @@ -454,9 +435,6 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 73 0>, <&tlmm 133 0>, <&pmm8654au_0_gpios 8 0>; @@ -493,11 +471,6 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 73 0>, <&tlmm 133 0>, <&pmm8654au_0_gpios 8 0>; @@ -535,7 +508,7 @@ gpio-no-mux = <0>; gpios = <&tlmm 73 0>, <&expander2 2 0>, - <&pmm8654au_0_gpios 8 0>; + <&pmm8654au_0_gpios 8 0>; gpio-reset = <1>; gpio-custom1 = <2>; gpio-req-tbl-num = <0 1 2>; @@ -563,11 +536,6 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 73 0>, <&tlmm 133 0>, <&pmm8654au_0_gpios 8 0>; @@ -711,7 +679,7 @@ }; /*cam2-ov9282*/ - qcom,cam-sensor22 { + rb8_slot2: qcom,cam-sensor22 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <2>; sensor-position-roll = <0>; @@ -726,21 +694,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rst2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rst2>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 74 0>, - <&tlmm 134 0>, + gpios = <&tlmm 134 0>, <&pmm8654au_0_gpios 9 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK2", - "CAMIF_RESET2", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET2", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK2_CLK>; clock-names = "cam_clk"; @@ -767,21 +731,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rst2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rst2>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 74 0>, - <&tlmm 134 0>, + gpios = <&tlmm 134 0>, <&pmm8654au_0_gpios 9 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK2", - "CAMIF_RESET2", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET2", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK2_CLK>; clock-names = "cam_clk"; @@ -802,21 +762,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rst2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rst2>; + pinctrl-0 = <&cam_sensor_mclk2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 74 0>, - <&tlmm 134 0>, + gpios = <&tlmm 134 0>, <&pmm8654au_0_gpios 9 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET2", + "CAM_CUSTOM1"; sensor-mode = <0>; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK2_CLK>; @@ -950,7 +906,7 @@ }; /*cam3-ov9282*/ - qcom,cam-sensor23 { + rb8_slot3: qcom,cam-sensor23 { compatible = "qcom,cam-sensor"; csiphy-sd-index = <3>; sensor-position-roll = <0>; @@ -965,21 +921,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_rst3>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_rst3>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 75 0>, - <&tlmm 135 0>, + gpios = <&tlmm 135 0>, <&pmm8654au_0_gpios 10 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK3", - "CAMIF_RESET3", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET3", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK3_CLK>; clock-names = "cam_clk"; @@ -1006,21 +958,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_rst3>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_rst3>; - gpios = <&tlmm 75 0>, - <&tlmm 135 0>, + gpios = <&tlmm 135 0>, <&pmm8654au_0_gpios 10 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK3", - "CAMIF_RESET3", - "CAM_CUSTOM1"; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET3", + "CAM_CUSTOM1"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK3_CLK>; clock-names = "cam_clk"; @@ -1041,21 +989,17 @@ rgltr-max-voltage = <1800000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_rst3>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_rst3>; - gpios = <&tlmm 75 0>, - <&tlmm 135 0>, - <&pmm8654au_0_gpios 10 0>; + pinctrl-0 = <&cam_sensor_mclk3_active>; + pinctrl-1 = <&cam_sensor_mclk3_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK3", - "CAM_RESET3", - "CAM_CUSTOM1"; + gpios = <&tlmm 135 0>, + <&pmm8654au_0_gpios 10 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAMIF_RESET3", + "CAM_CUSTOM1"; sensor-mode = <0>; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK3_CLK>; From c9468b1dc9db5710f179b16a76904d51a65757c7 Mon Sep 17 00:00:00 2001 From: Dipa Ramesh Mantre Date: Tue, 19 May 2026 18:33:38 +0530 Subject: [PATCH 0739/1133] PENDING: arm64: dts: qcom: hamoa: Enable CDSP cooling in staging dtso MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP does not throttle its speed automatically when it reaches high temperatures in hamoa. Set up CDSP cooling by throttling the cdsp when it reaches 105°C. Signed-off-by: Dipa Ramesh Mantre --- arch/arm64/boot/dts/qcom/hamoa-staging.dtso | 82 +++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa-staging.dtso b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso index feb3c7c5ccd82..6a1e106ae8a9a 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-staging.dtso +++ b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso @@ -8,6 +8,8 @@ /dts-v1/; /plugin/; +#include + &soc { tgu@10b0e000 { compatible = "qcom,tgu", "arm,primecell"; @@ -33,3 +35,83 @@ clock-names = "apb_pclk"; }; }; + +&remoteproc_cdsp { + cooling { + compatible = "qcom,qmi-cooling-cdsp"; + + cdsp_tmd0: cdsp-tmd0 { + label = "cdsp_sw"; + #cooling-cells = <2>; + }; + }; +}; + +&thermal_nsp0 { + trips { + nsp0_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp0_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp1 { + trips { + nsp1_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp1_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp2 { + trips { + nsp2_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp2_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp3 { + trips { + nsp3_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp3_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + From c144e3d766049740e9ad8ca25292c0f392f78444 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Mon, 1 Jun 2026 12:39:56 +0530 Subject: [PATCH 0740/1133] QCLINUX: arm64: dts: qcom: Change Purwa camera firmware path Update the path for the camera icp firmware. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/purwa-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi index 5896e5759e22f..fe1057fe97f92 100644 --- a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi @@ -34,7 +34,7 @@ src-clock-name = "icp_clk_src"; operating-points-v2 = <&icp_opp_table>; clock-control-debugfs = "true"; - fw_name = "qcom/x1p4x100/CAMERA_ICP"; + fw_name = "qcom/x1p42100/CAMERA_ICP"; ubwc-ipe-fetch-cfg = <0x707b 0x7083>; ubwc-ipe-write-cfg = <0x161ef 0x1620f>; ubwc-bps-fetch-cfg = <0x707b 0x7083>; From ebece1512e1868f57d1395134cb6130980f79e74 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Thu, 28 May 2026 17:21:27 +0530 Subject: [PATCH 0741/1133] QCLINUX: arm64: dts: qcom: Add Glymur crd camx overlay dts Add CAMX overlay dts file for Glymur crd boards. This change also enables the compilation of the CAMX overlay for Glymur crd boards. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 5 + arch/arm64/boot/dts/qcom/glymur-camera.dtsi | 2454 +++++++++++++++++ arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso | 27 + 3 files changed, 2486 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/glymur-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 8b58715f5e2c8..23dbbddd0cff3 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -548,6 +548,11 @@ x1p42100-microsoft-sp12in-el2-dtbs := x1p42100-microsoft-sp12in.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += x1p42100-microsoft-sp12in.dtb x1p42100-microsoft-sp12in-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += x1-el2.dtbo +glymur-crd-camx-dtbs := glymur-crd.dtb glymur-crd-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += glymur-crd-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += glymur-crd-camx.dtbo + hamoa-evk-camx-dtbs := hamoa-iot-evk.dtb hamoa-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/glymur-camera.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi new file mode 100644 index 0000000000000..9e50200f82830 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi @@ -0,0 +1,2454 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include + +&soc { + cam_icp: qcom,icp@ac00000 { + compatible = "qcom,cam-icp_v2_1"; + icp-version = <0x0201>; + reg = <0x0 0xac01000 0x0 0x1000>, + <0x0 0x0ac04000 0x0 0x1000>; + reg-names = "icp_csr", "icp_wd0"; + reg-cam-base = <0x1000 0x4000>; + interrupts = ; + interrupt-names = "icp"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + clocks = <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "icp_ahb_clk", + "icp_clk_src", + "icp_clk", + "camcc_debug_clk"; + clock-rates = <0 300000000 0 0>, + <0 400000000 0 0>, + <0 480000000 0 0>, + <0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "icp_clk_src"; + operating-points-v2 = <&icp_opp_table>; + clock-control-debugfs = "true"; + fw_name = "qcom/glymur/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + ubwc-bps-fetch-cfg = <0x707b 0x7083>; + ubwc-bps-write-cfg = <0x161ef 0x1620f>; + qos-val = <0x00000A0A>; + cam_hw_pid = <3>; + cell-index = <0>; + status = "okay"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cpas: qcom,cam-cpas@ac13000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0xac13000 0x0 0x1000>, + <0x0 0xac19000 0x0 0xC000>, + <0x0 0xbbf0000 0x0 0x1F00>; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg-cam-base = <0x13000 0x19000 0x0bbf0000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "gcc_ahb_clk", + "gcc_axi_hf_clk", + "gcc_axi_sf_clk", + "cam_cc_slow_ahb_clk_src", + "cpas_ahb_clk", + "cpas_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "camnoc_axi_clk_src", + "camnoc_axi_clk", + "camnoc_axi_nrt_clk", + "camcc_debug_clk"; + clock-rates = < 0 0 0 0 0 0 0 0 0 0 0 0>, + < 0 0 0 64000000 0 0 80000000 0 240000000 0 0 0>, + < 0 0 0 80000000 0 0 100000000 0 300000000 0 0 0>, + < 0 0 0 80000000 0 0 400000000 0 400000000 0 0 0>; + clock-cntl-level = "suspend", "lowsvsd1", "lowsvs", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <400000000>; + src-clock-name = "camnoc_axi_clk_src"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + cam-icc-path-names = "cam_ahb"; + camnoc-axi-clk-bw-margin-perc = <20>; + interconnects =<&hsc_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", + "cam_hf_0", + "cam_sf_0", + "cam_sf_icp"; + rpmh-bcm-info = <12 0x4 0x800 0 4>; + cam-ahb-num-cases = <8>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 76800>, <0 150000>, + <0 150000>, <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", + "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", + "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy4", + "cci0", "cci1", "csid0", "csid1", "csid2", + "csid3", "ife0", "ife1", "ife2", "ife3", + "ipe0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "cam-cdm-intf0", "bps0", "icp0", + "jpeg-dma0", "jpeg-enc0", "tpg13", "tpg14", + "tpg15"; + cell-index = <0>; + status = "okay"; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + bps0_all_rd: bps0-all-rd { + cell-index = <0>; + node-name = "bps0-all-rd"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + bps0_all_wr: bps0-all-wr { + cell-index = <1>; + node-name = "bps0-all-wr"; + client-name = "bps0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_wr>; + }; + + icp0_all_rd: icp0-all-rd { + cell-index = <2>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt1_rd>; + }; + + ife0_linear_stats_wr: ife0-linear-stats-wr { + cell-index = <3>; + node-name = "ife0-linear-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife0_pdaf_wr: ife0-pdaf-wr { + cell-index = <4>; + node-name = "ife0-pdaf-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife0_rdi_pixel_raw_wr: ife0-rdi-pixel-raw-wr { + cell-index = <5>; + node-name = "ife0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife0_ubwc_wr: ife0-ubwc-wr { + cell-index = <6>; + node-name = "ife0-ubwc-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife1_linear_stats_wr: ife1-linear-stats-wr { + cell-index = <7>; + node-name = "ife1-linear-stats-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr3>; + }; + + ife1_pdaf_wr: ife1-pdaf-wr { + cell-index = <8>; + node-name = "ife1-pdaf-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt0_wr2>; + }; + + ife1_rdi_pixel_raw_wr: ife1-rdi-pixel-raw-wr { + cell-index = <9>; + node-name = "ife1-rdi-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr1>; + }; + + ife1_ubwc_wr: ife1-ubwc-wr { + cell-index = <10>; + node-name = "ife1-ubwc-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr0>; + }; + + ife2_rdi_stats_pixel_raw_wr: ife2-rdi-stats-pixel-raw-wr { + cell-index = <11>; + node-name = "ife2-rdi-stats-pixel-raw-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ife3_rdi_stats_pixel_raw_wr: ife3-rdi-stats-pixel-raw-wr { + cell-index = <12>; + node-name = "ife3-rdi-stats-pixel-raw-wr"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ipe0_all_wr: ipe0-all-wr { + cell-index = <13>; + node-name = "ipe0-all-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt0_wr>; + }; + + ipe0_in_rd: ipe0-in-rd { + cell-index = <14>; + node-name = "ipe0-in-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + ipe0_ref_rd: ipe0-ref-rd { + cell-index = <15>; + node-name = "ipe0-ref-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_nrt0_rd>; + }; + + jpeg_dma0_all_rd: jpeg-dma0-all-rd { + cell-index = <16>; + node-name = "jpeg-dma0-all-rd"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_dma0_all_wr: jpeg-dma0-all-wr { + cell-index = <17>; + node-name = "jpeg-dma0-all-wr"; + client-name = "jpeg-dma0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + jpeg_enc0_all_rd: jpeg-enc0-all-rd { + cell-index = <18>; + node-name = "jpeg-enc0-all-rd"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd0>; + }; + + jpeg_enc0_all_wr: jpeg-enc0-all-wr { + cell-index = <19>; + node-name = "jpeg-enc0-all-wr"; + client-name = "jpeg-enc0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_wr0>; + }; + + rt_cdm0_all_rd: rt-cdm0-all-rd { + cell-index = <20>; + node-name = "rt-cdm0-all-rd"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + rt_cdm1_all_rd: rt-cdm1-all-rd { + cell-index = <21>; + node-name = "rt-cdm1-all-rd"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 0 */ + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <22>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + + /* IFE Lite 1 */ + rt_cdm3_all_rd: rt-cdm3-all-rd { + cell-index = <23>; + node-name = "rt-cdm3-all-rd"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd1>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_rd0: level1-nrt0-rd0 { + cell-index = <24>; + node-name = "level1-nrt0-rd0"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_rd1: level1-nrt0-rd1 { + cell-index = <25>; + node-name = "level1-nrt0-rd1"; + parent-node = <&level2_nrt0_rd>; + traffic-merge-type = ; + }; + + level1_nrt0_wr0: level1-nrt0-wr0 { + cell-index = <26>; + node-name = "level1-nrt0-wr0"; + parent-node = <&level2_nrt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_rd0: level1-rt0-rd0 { + cell-index = <27>; + node-name = "level1-sfe-rd"; + parent-node = <&level2_rt0_rd>; + traffic-merge-type = ; + }; + + level1_rt0_wr0: level1-rt0-wr0 { + cell-index = <28>; + node-name = "level1-ife-ubwc-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr1: level1-rt0-wr1 { + cell-index = <29>; + node-name = "level1-ife-rdi-wr"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr2: level1-rt0-wr2 { + cell-index = <30>; + node-name = "level1-ife-pdaf"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr3: level1-rt0-wr3 { + cell-index = <31>; + node-name = "level1-ife01-linear-stats"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + + level1_rt0_wr4: level1-rt0-wr4 { + cell-index = <32>; + node-name = "level1-ifelite"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_nrt0_rd: level2-nrt0-rd { + cell-index = <33>; + node-name = "level2-nrt0-rd"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt0_wr: level2-nrt0-wr { + cell-index = <34>; + node-name = "level2-nrt0-wr"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt1_rd: level2-nrt1-rd { + cell-index = <35>; + node-name = "level2-nrt1-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + bus-width-factor = <4>; + }; + + level2_rt0_rd: level2-rt0-rd { + cell-index = <36>; + node-name = "level2-rt0-rd"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_rt0_wr: level2-rt0-wr { + cell-index = <37>; + node-name = "level2-rt0-wr"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + }; + + level3-nodes { + level-index = <3>; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <38>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <39>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { + cell-index = <40>; + node-name = "level3-rt0-rd-wr-sum"; + traffic-merge-type = ; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cci0: qcom,cci0@ac15000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupts = ; + interrupt-names = "cci0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + operating-points-v2 = <&cci0_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + cell-index = <0>; + status = "okay"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cci1: qcom,cci1@ac16000 { + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0xac16000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x16000>; + interrupts = ; + interrupt-names = "cci1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + operating-points-v2 = <&cci1_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci_i2c_scl2_active &cci_i2c_sda2_active>; + pinctrl-1 = <&cci_i2c_scl2_suspend &cci_i2c_sda2_suspend>; + pinctrl-2 = <&cci3_active>; + pinctrl-3 = <&cci3_suspend>; + cell-index = <1>; + status = "okay"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <0>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + qcom,rt-cdm0@ac25000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac25000 0x0 0x400>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x25000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <400000000 0>; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table0>; + nrt-device; + cdm-client-names = "ife0", "dualife0"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <25>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <0>; + status = "okay"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm1@ac26000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xac26000 0x0 0x400>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clock-rates = <400000000 0>; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table1>; + nrt-device; + cdm-client-names = "ife1", "dualife1"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <26>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <1>; + status = "okay"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_enc: qcom,jpegenc@ac2a000 { + compatible = "qcom,cam_jpeg_enc_680"; + reg = <0x0 0xac2a000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegenc_hw", "cam_camnoc"; + reg-cam-base = <0x2a000 0x19000>; + interrupts = ; + interrupt-names = "jpeg"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegenc_clk_src", + "jpegenc_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegenc_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_enc_opp_table>; + nrt-device; + cam_hw_pid = <12 14>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_enc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_jpeg_dma: qcom,jpegdma@ac2b000 { + compatible = "qcom,cam_jpeg_dma_680"; + reg = <0x0 0xac2b000 0x0 0x1000>, + <0x0 0x0ac19000 0x0 0xc000>; + reg-names = "jpegdma_hw", "cam_camnoc"; + reg-cam-base = <0x2b000 0x19000>; + interrupts = ; + interrupt-names = "jpegdma"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_JPEG_CLK_SRC>, + <&camcc CAM_CC_JPEG_CLK>; + clock-names = "jpegdma_clk_src", + "jpegdma_clk"; + clock-rates = <160000000 0>, + <200000000 0>, + <400000000 0>, + <480000000 0>, + <600000000 0>; + src-clock-name = "jpegdma_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + operating-points-v2 = <&jpeg_dma_opp_table>; + nrt-device; + cam_hw_pid = <13 15>; + cam_hw_rd_mid = <0>; + cam_hw_wr_mid = <1>; + cell-index = <0>; + status = "okay"; + + jpeg_dma_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-48000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_bps: qcom,bps@ac2c000 { + compatible = "qcom,cam-bps680"; + reg = <0x0 0xac2c000 0x0 0xb000>; + reg-names = "bps_top"; + reg-cam-base = <0x2c000>; + power-domains = <&camcc CAM_CC_BPS_GDSC>; + clocks = <&camcc CAM_CC_BPS_AHB_CLK>, + <&camcc CAM_CC_BPS_FAST_AHB_CLK>, + <&camcc CAM_CC_BPS_CLK_SRC>, + <&camcc CAM_CC_BPS_CLK>, + <&camcc CAM_CC_CPAS_BPS_CLK>; + clock-names = "bps_ahb_clk", + "bps_fast_ahb_clk", + "bps_clk_src", + "bps_clk", + "cam_cc_cpas_bps_clk"; + clock-rates = <0 0 160000000 0 0>, + <0 0 200000000 0 0>, + <0 0 400000000 0 0>, + <0 0 600000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "nominal"; + nrt-device; + src-clock-name = "bps_clk_src"; + operating-points-v2 = <&bps_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <6 7>; + cell-index = <0>; + status = "okay"; + + bps_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-160000000 { + opp-hz = /bits/ 64 <160000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@ac42000 { + compatible = "qcom,cam-ipe680"; + reg = <0x0 0xac42000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x42000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + clocks = <&camcc CAM_CC_IPE_NPS_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_PPS_FAST_AHB_CLK>, + <&camcc CAM_CC_IPE_NPS_CLK_SRC>, + <&camcc CAM_CC_IPE_NPS_CLK>, + <&camcc CAM_CC_IPE_PPS_CLK>, + <&camcc CAM_CC_CPAS_IPE_NPS_CLK>; + clock-names = "ipe_nps_ahb_clk", + "ipe_nps_fast_ahb_clk", + "ipe_pps_fast_ahb_clk", + "ipe_nps_clk_src", + "ipe_nps_clk", + "ipe_pps_clk", + "cam_cc_cpas_ipe_nps_clk"; + clock-rates = <0 0 0 304000000 0 0 0>, + <0 0 0 364000000 0 0 0>, + <0 0 0 500000000 0 0 0>, + <0 0 0 600000000 0 0 0>, + <0 0 0 700000000 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + nrt-device; + src-clock-name = "ipe_nps_clk_src"; + operating-points-v2 = <&ipe0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <22 23 30>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-304000000 { + opp-hz = /bits/ 64 <304000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-364000000 { + opp-hz = /bits/ 64 <364000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-700000000 { + opp-hz = /bits/ 64 <700000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0@ac62000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac62000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x62000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>; + clock-names = "ife_0_fast_ahb", + "ife_0_clk_src", + "ife_0_clk", + "cam_cc_cpas_ife_0_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <16 4 20 8>; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1@ac71000 { + compatible = "qcom,vfe680"; + reg = <0x0 0xac71000 0x0 0xf000>, + <0x0 0xac19000 0x0 0xc000>; + reg-names = "ife", "cam_camnoc"; + reg-cam-base = <0x71000 0x19000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>; + clock-names = "ife_1_fast_ahb", + "ife_1_clk_src", + "ife_1_clk", + "cam_cc_cpas_ife_1_clk"; + clock-rates = <0 345600000 0 0>, + <0 432000000 0 0>, + <0 594000000 0 0>, + <0 675000000 0 0>, + <0 727000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "svs", "svs_l1", "nominal"; + src-clock-name = "ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; + clock-rates-option = <594000000>; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <17 5 21 9>; + cell-index = <1>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-345600000 { + opp-hz = /bits/ 64 <345600000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-432000000 { + opp-hz = /bits/ 64 <432000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-594000000 { + opp-hz = /bits/ 64 <594000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-675000000 { + opp-hz = /bits/ 64 <675000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-727000000 { + opp-hz = /bits/ 64 <727000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid0: qcom,csid0@acb7000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb7000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb7000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid1: qcom,csid1@acb9000 { + compatible = "qcom,csid695"; + reg = <0x0 0xacb9000 0x0 0xd00>, + <0x0 0xacb6000 0x0 0x1000>; + reg-names = "csid", "csid_top"; + reg-cam-base = <0xb9000 0xb6000>; + rt-wrapper-base = <0x62000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <1 0 0>; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "csid_clk_src", + "csid_clk", + "csiphy_rx_clk"; + clock-rates = <300000000 0 0>, + <400000000 0 0>, + <480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0@acc6000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacc6000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0@acc6000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacc6000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xc6000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <0>; + cell-index = <2>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1@acca000 { + compatible = "qcom,csid-lite680"; + reg = <0x0 0xacca000 0x0 0xa00>; + reg-names = "csid-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 1 0 0 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb_clk", + "ife_lite_csid_clk_src", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 266666667 0 0 0 0>, + <0 400000000 0 0 0 0>, + <0 480000000 0 0 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "okay"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1@acca000 { + compatible = "qcom,vfe-lite695"; + reg = <0x0 0xacca000 0x0 0x4000>; + reg-names = "ife-lite"; + rt-wrapper-base = <0xc6000>; + reg-cam-base = <0xca000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + shared-clks = <0 0 0 1 0 0>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>; + clock-names = "ife_lite_ahb", + "ife_lite_csid_clk", + "ife_lite_cphy_rx_clk", + "ife_lite_clk_src", + "ife_lite_clk", + "cam_cc_cpas_ife_lite_clk"; + clock-rates = <0 0 0 266666667 0 0>, + <0 0 0 400000000 0 0>, + <0 0 0 480000000 0 0>; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + src-clock-name = "ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <1>; + cell-index = <3>; + status = "okay"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-266666667 { + opp-hz = /bits/ 64 <266666667>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@ace4000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace4000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe4000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l4f_e1_1p08>; + csi-vdd-0p9-supply = <&vreg_l1f_e1_0p82>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 832000>; + rgltr-max-voltage = <1200000 832000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy0_opp_table>; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ace6000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xace6000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xe6000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l4f_e1_1p08>; + csi-vdd-0p9-supply = <&vreg_l1f_e1_0p82>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 832000>; + rgltr-max-voltage = <1200000 832000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy1_opp_table>; + cell-index = <1>; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4@acec000 { + compatible = "qcom,csiphy-v2.1.2", "qcom,csiphy"; + reg = <0x0 0xacec000 0x0 0x2000>; + reg-names = "csiphy"; + reg-cam-base = <0xec000>; + interrupts = ; + interrupt-names = "CSIPHY4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + csi-vdd-1p2-supply = <&vreg_l4f_e1_1p08>; + csi-vdd-0p9-supply = <&vreg_l1f_e1_0p82>; + rgltr-cntrl-support; + rgltr-enable-sync = <1>; + rgltr-min-voltage = <1200000 832000>; + rgltr-max-voltage = <1200000 832000>; + rgltr-load-current = <58900 147000>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "csi4phytimer_clk_src"; + clock-cntl-level = "lowsvsd1", "lowsvs", "nominal"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>; + operating-points-v2 = <&csiphy4_opp_table>; + cell-index = <4>; + status = "okay"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg13: qcom,tpg13@acf6000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf6000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0xf6000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + cell-index = <13>; + phy-id = <0>; + status = "okay"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acf7000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf7000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0xf7000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + cell-index = <14>; + phy-id = <1>; + status = "okay"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acf8000 { + compatible = "qcom,cam-tpg103"; + reg = <0x0 0xacf8000 0x0 0x400>, + <0x0 0xac13000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0xf8000 0x13000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clock-rates = <400000000 0>, + <480000000 0>; + clock-cntl-level = "lowsvs", "nominal"; + src-clock-name = "cphy_rx_clk_src"; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + cell-index = <15>; + phy-id = <2>; + status = "okay"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm2@acf9000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacf9000 0x0 0x400>; + reg-names = "rt-cdm2"; + reg-cam-base = <0xf9000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table2>; + nrt-device; + cdm-client-names = "ife2"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <24>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <2>; + status = "okay"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm3@acfa000 { + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0xacfa000 0x0 0x400>; + reg-names = "rt-cdm3"; + reg-cam-base = <0xfa000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_ife_lite_ahb"; + clock-rates = <80000000 0>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-cntl-level = "nominal"; + operating-points-v2 = <&cdm_cpas_opp_table3>; + nrt-device; + cdm-client-names = "ife3"; + config-fifo; + fifo-depths = <64 0 0 0>; + cam_hw_pid = <27>; + cam-hw-mid = <0>; + single-context-cdm; + cell-index = <3>; + status = "okay"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpegdma", + "jpegenc"; + cell-index = <0>; + status = "okay"; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0", + "qcom,bps"; + num-icp = <1>; + num-ipe = <1>; + num-bps = <1>; + status = "okay"; + icp_pc_en; + icp_use_pil; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + cam_smmu: qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + force_cache_allocs; + need_shared_buffer_padding; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18A0 0x0000>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1800 0x0060>, + <&apps_smmu 0x1820 0x0060>, + <&apps_smmu 0x1840 0x0060>, + <&apps_smmu 0x1860 0x0060>, + <&apps_smmu 0x1900 0x0000>, + <&apps_smmu 0x1980 0x0020>, + <&apps_smmu 0x19A0 0x0020>; + cam-smmu-label = "icp"; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-qdss-region { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x14b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x14400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + status = "okay"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.7 GB */ + iova-region-name = "io"; + iova-region-start = <0x14c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + status = "okay"; + }; + + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x4800000>; + iova-region-len = <0xFC00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0820 0x0000>; + dma-coherent; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-jpeg { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x18E0 0x0000>; + cam-smmu-label = "jpeg"; + dma-coherent; + + jpeg_iova_mem_map: iova-mem-map { + /* IO region is approximately 4.0 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_x1e80100"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + /* RESET REAR */ + config { + pins = "gpio109"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + + mux { + pins = "gpio109"; + function = "gpio"; + }; + }; + + cam_sensor_active_rst4: cam-sensor-active-rst4 { + /* RESET REAR */ + config { + pins = "gpio239"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio239"; + function = "gpio"; + }; + }; + + cam_sensor_suspend_rst4: cam-sensor-suspend-rst4 { + /* RESET REAR */ + config { + pins = "gpio239"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + output-low; + }; + + mux { + pins = "gpio239"; + function = "gpio"; + }; + }; + + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* mclk0 */ + config { + pins = "gpio96"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* mclk0 */ + config { + pins = "gpio96"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* mclk1 */ + config { + pins = "gpio97"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* mclk1 */ + config { + pins = "gpio97"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio97"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* mclk2 */ + config { + pins = "gpio98"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* mclk2 */ + config { + pins = "gpio98"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* mclk3 */ + config { + pins = "gpio99"; + bias-disable; /* No PULL */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio99"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* mclk3 */ + config { + pins = "gpio99"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <6>; /* 6 MA */ + }; + + mux { + pins = "gpio99"; + function = "cam_mclk"; + }; + }; + + cam_sensor_mclk4_active: cam-sensor-mclk4-active { + /* mclk4 */ + config { + pins = "gpio100"; + bias-disable; /* No PULL */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_asc_mclk4"; + }; + }; + + cam_sensor_mclk4_suspend: cam-sensor-mclk4-suspend { + /* mclk4 */ + config { + pins = "gpio100"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <12>; /* 12 MA */ + }; + + mux { + pins = "gpio100"; + function = "cam_asc_mclk4"; + }; + }; + + cci_i2c_sda0_active: cci_i2c_sda0_active { + mux { + /* CLK, DATA */ + pins = "gpio101"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio101"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda0_suspend: cci_i2c_sda0_suspend { + mux { + /* CLK, DATA */ + pins = "gpio101"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio101"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl0_active: cci_i2c_scl0_active { + mux { + /* CLK, DATA */ + pins = "gpio102"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio102"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl0_suspend: cci_i2c_scl0_suspend { + mux { + /* CLK, DATA */ + pins = "gpio102"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio102"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_active: cci_i2c_sda1_active { + mux { + /* CLK, DATA */ + pins = "gpio103"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio103"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda1_suspend: cci_i2c_sda1_suspend { + mux { + /* CLK, DATA */ + pins = "gpio103"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio103"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_active: cci_i2c_scl1_active { + mux { + /* CLK, DATA */ + pins = "gpio104"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio104"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl1_suspend: cci_i2c_scl1_suspend { + mux { + /* CLK, DATA */ + pins = "gpio104"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio104"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda2_active: cci_i2c_sda2_active { + mux { + /* CLK, DATA */ + pins = "gpio105"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio105"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda2_suspend: cci_i2c_sda2_suspend { + mux { + /* CLK, DATA */ + pins = "gpio105"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio105"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl2_active: cci_i2c_scl2_active { + mux { + /* CLK, DATA */ + pins = "gpio106"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio106"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl2_suspend: cci_i2c_scl2_suspend { + mux { + /* CLK, DATA */ + pins = "gpio106"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio106"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci3_active: cci3-active { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "asc_cci"; + }; + }; + + cci3_suspend: cci3-suspend { + config { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + + mux { + /* DATA, CLK */ + pins = "gpio235","gpio236"; + function = "asc_cci"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso new file mode 100644 index 0000000000000..b75789c8aae6b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "glymur-camera.dtsi" + +&cam_icp_firmware { + camera-firmware { + iommus = <&apps_smmu 0x1901 0x0000>; + }; +}; From b07aec45d1b0431be74c08431f51a69be9526d48 Mon Sep 17 00:00:00 2001 From: Ignatius Michael Jihan Date: Fri, 5 Jun 2026 16:54:14 +0530 Subject: [PATCH 0742/1133] QCLINUX: arm64: dts: qcom: added ife lite cpas to purwa camera dtsi Added IFE Lite nodes to CPAS to enable proper voting on these paths. Signed-off-by: Ignatius Michael Jihan --- arch/arm64/boot/dts/qcom/purwa-camera.dtsi | 114 +++++++++++++-------- 1 file changed, 72 insertions(+), 42 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi index fe1057fe97f92..cbc9ec0f83aad 100644 --- a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi @@ -149,8 +149,8 @@ client-id-based; client-names = "csiphy0", "csiphy4", "cci0", "cci1", "csid0", "csid1", "csid2", "ife0", "ife1", "ife2", "ipe0", - "rt-cdm0", "rt-cdm1", "rt-cdm2", "rt-cdm3", - "cam-cdm-intf0", "bps0", "icp0", "jpeg-dma0", + "rt-cdm0", "rt-cdm1", "rt-cdm2", "cam-cdm-intf0", + "bps0", "icp0", "jpeg-dma0", "jpeg-enc0", "tpg13", "tpg14", "tpg15"; cell-index = <0>; status = "okay"; @@ -230,8 +230,38 @@ parent-node = <&level1_rt0_wr0>; }; - ipe0_all_wr: ipe0-all-wr { + ife1_rdi_stats_pixel_raw_wr: ife1-rdi-stats-pixel-raw-wr { cell-index = <7>; + node-name = "ife1-rdi-stats-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ife2_rdi_stats_pixel_raw_wr: ife2-rdi-stats-pixel-raw-wr { + cell-index = <8>; + node-name = "ife2-rdi-stats-pixel-raw-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr4>; + }; + + ipe0_all_wr: ipe0-all-wr { + cell-index = <9>; node-name = "ipe0-all-wr"; client-name = "ipe0"; traffic-data = ; @@ -243,7 +273,7 @@ }; ipe0_in_rd: ipe0-in-rd { - cell-index = <8>; + cell-index = <10>; node-name = "ipe0-in-rd"; client-name = "ipe0"; traffic-data = ; @@ -252,7 +282,7 @@ }; ipe0_ref_rd: ipe0-ref-rd { - cell-index = <9>; + cell-index = <11>; node-name = "ipe0-ref-rd"; client-name = "ipe0"; traffic-data = ; @@ -261,7 +291,7 @@ }; jpeg_dma0_all_rd: jpeg-dma0-all-rd { - cell-index = <10>; + cell-index = <12>; node-name = "jpeg-dma0-all-rd"; client-name = "jpeg-dma0"; traffic-data = ; @@ -270,7 +300,7 @@ }; jpeg_dma0_all_wr: jpeg-dma0-all-wr { - cell-index = <11>; + cell-index = <13>; node-name = "jpeg-dma0-all-wr"; client-name = "jpeg-dma0"; traffic-data = ; @@ -279,7 +309,7 @@ }; jpeg_enc0_all_rd: jpeg-enc0-all-rd { - cell-index = <12>; + cell-index = <14>; node-name = "jpeg-enc0-all-rd"; client-name = "jpeg-enc0"; traffic-data = ; @@ -288,7 +318,7 @@ }; jpeg_enc0_all_wr: jpeg-enc0-all-wr { - cell-index = <13>; + cell-index = <15>; node-name = "jpeg-enc0-all-wr"; client-name = "jpeg-enc0"; traffic-data = ; @@ -297,7 +327,7 @@ }; rt_cdm0_all_rd: rt-cdm0-all-rd { - cell-index = <14>; + cell-index = <16>; node-name = "rt-cdm0-all-rd"; client-name = "rt-cdm0"; traffic-data = ; @@ -306,20 +336,20 @@ }; /* IFE Lite 0 */ - rt_cdm2_all_rd: rt-cdm2-all-rd { - cell-index = <15>; - node-name = "rt-cdm2-all-rd"; - client-name = "rt-cdm2"; + rt_cdm1_all_rd: rt-cdm1-all-rd { + cell-index = <17>; + node-name = "rt-cdm1-all-rd"; + client-name = "rt-cdm1"; traffic-data = ; traffic-transaction-type = ; parent-node = <&level1_nrt0_rd1>; }; /* IFE Lite 1 */ - rt_cdm3_all_rd: rt-cdm3-all-rd { - cell-index = <16>; - node-name = "rt-cdm3-all-rd"; - client-name = "rt-cdm3"; + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <18>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; traffic-data = ; traffic-transaction-type = ; parent-node = <&level1_nrt0_rd1>; @@ -331,56 +361,56 @@ camnoc-max-needed; level1_nrt0_rd0: level1-nrt0-rd0 { - cell-index = <17>; + cell-index = <19>; node-name = "level1-nrt0-rd0"; parent-node = <&level2_nrt0_rd>; traffic-merge-type = ; }; level1_nrt0_rd1: level1-nrt0-rd1 { - cell-index = <18>; + cell-index = <20>; node-name = "level1-nrt0-rd1"; parent-node = <&level2_nrt0_rd>; traffic-merge-type = ; }; level1_nrt0_wr0: level1-nrt0-wr0 { - cell-index = <19>; + cell-index = <21>; node-name = "level1-nrt0-wr0"; parent-node = <&level2_nrt0_wr>; traffic-merge-type = ; }; level1_rt0_wr0: level1-rt0-wr0 { - cell-index = <20>; + cell-index = <22>; node-name = "level1-ife-ubwc-wr"; parent-node = <&level2_rt0_wr>; traffic-merge-type = ; }; level1_rt0_wr1: level1-rt0-wr1 { - cell-index = <21>; + cell-index = <23>; node-name = "level1-ife-rdi-wr"; parent-node = <&level2_rt0_wr>; traffic-merge-type = ; }; level1_rt0_wr2: level1-rt0-wr2 { - cell-index = <22>; + cell-index = <24>; node-name = "level1-ife-pdaf"; parent-node = <&level2_rt0_wr>; traffic-merge-type = ; }; level1_rt0_wr3: level1-rt0-wr3 { - cell-index = <23>; + cell-index = <25>; node-name = "level1-ife01-linear-stats"; parent-node = <&level2_rt0_wr>; traffic-merge-type = ; }; level1_rt0_wr4: level1-rt0-wr4 { - cell-index = <24>; + cell-index = <26>; node-name = "level1-ifelite"; parent-node = <&level2_rt0_wr>; traffic-merge-type = ; @@ -392,7 +422,7 @@ camnoc-max-needed; level2_nrt0_rd: level2-nrt0-rd { - cell-index = <25>; + cell-index = <27>; node-name = "level2-nrt0-rd"; parent-node = <&level3_nrt0_rd_wr_sum>; traffic-merge-type = @@ -400,7 +430,7 @@ }; level2_nrt0_wr: level2-nrt0-wr { - cell-index = <26>; + cell-index = <28>; node-name = "level2-nrt0-wr"; parent-node = <&level3_nrt0_rd_wr_sum>; traffic-merge-type = @@ -408,7 +438,7 @@ }; level2_nrt1_rd: level2-nrt1-rd { - cell-index = <27>; + cell-index = <29>; node-name = "level2-nrt1-rd"; parent-node = <&level3_nrt1_rd_wr_sum>; traffic-merge-type = ; @@ -416,7 +446,7 @@ }; level2_rt0_rd: level2-rt0-rd { - cell-index = <28>; + cell-index = <30>; node-name = "level2-rt0-rd"; parent-node = <&level3_rt0_rd_wr_sum>; traffic-merge-type = @@ -424,7 +454,7 @@ }; level2_rt0_wr: level2-rt0-wr { - cell-index = <29>; + cell-index = <31>; node-name = "level2-rt0-wr"; parent-node = <&level3_rt0_rd_wr_sum>; traffic-merge-type = @@ -437,7 +467,7 @@ level-index = <3>; level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { - cell-index = <30>; + cell-index = <32>; node-name = "level3-nrt0-rd-wr-sum"; traffic-merge-type = ; qcom,axi-port-mnoc { @@ -446,7 +476,7 @@ }; level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { - cell-index = <31>; + cell-index = <33>; node-name = "level3-nrt1-rd-wr-sum"; traffic-merge-type = ; qcom,axi-port-mnoc { @@ -455,7 +485,7 @@ }; level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { - cell-index = <32>; + cell-index = <34>; node-name = "level3-rt0-rd-wr-sum"; traffic-merge-type = ; ib-bw-voting-needed; @@ -1473,14 +1503,14 @@ }; }; - qcom,rt-cdm2@acf9000 { + qcom,rt-cdm1@acf9000 { compatible = "qcom,cam-rt-cdm2_1"; label = "rt-cdm"; reg = <0x0 0xacf9000 0x0 0x400>; - reg-names = "rt-cdm2"; + reg-names = "rt-cdm1"; reg-cam-base = <0xf9000>; interrupts = ; - interrupt-names = "rt-cdm2"; + interrupt-names = "rt-cdm1"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, <&camcc CAM_CC_IFE_LITE_AHB_CLK>; @@ -1497,7 +1527,7 @@ cam_hw_pid = <24>; cam-hw-mid = <0>; single-context-cdm; - cell-index = <2>; + cell-index = <1>; status = "okay"; cdm_cpas_opp_table2: opp-table { @@ -1510,14 +1540,14 @@ }; }; - qcom,rt-cdm3@acfa000 { + qcom,rt-cdm2@acfa000 { compatible = "qcom,cam-rt-cdm2_1"; label = "rt-cdm"; reg = <0x0 0xacfa000 0x0 0x400>; - reg-names = "rt-cdm3"; + reg-names = "rt-cdm2"; reg-cam-base = <0xfa000>; interrupts = ; - interrupt-names = "rt-cdm3"; + interrupt-names = "rt-cdm2"; power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, <&camcc CAM_CC_IFE_LITE_AHB_CLK>; @@ -1534,7 +1564,7 @@ cam_hw_pid = <27>; cam-hw-mid = <0>; single-context-cdm; - cell-index = <3>; + cell-index = <2>; status = "okay"; cdm_cpas_opp_table3: opp-table { From d6ed6587ab4cf112a11f4b39ec29d93402f12aa8 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Fri, 5 Jun 2026 17:49:52 +0530 Subject: [PATCH 0743/1133] QCLINUX: arm64: dts: qcom: monaco-evk: disable unused camera regulators vreg_cam0_2p8 and vreg_cam2_2p8 are not used on the Monaco EVK board. Disable them to prevent unintended regulator enablement. Signed-off-by: Nihal Kumar Gupta --- arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso index c0fea4bb3dc23..0a5265e178feb 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camx.dtso @@ -106,6 +106,14 @@ }; }; +&vreg_cam0_2p8 { + status = "disabled"; +}; + &vreg_cam1_2p8 { status = "disabled"; }; + +&vreg_cam2_2p8 { + status = "disabled"; +}; From 3aeba6821bb9c3ef9ea165cda0418096addaa3c7 Mon Sep 17 00:00:00 2001 From: Sankalp Negi Date: Wed, 10 Jun 2026 10:16:51 -0700 Subject: [PATCH 0744/1133] QCLINUX: dt-bindings: mailbox: qcom-ipcc: Add RTSS client IDs Add IPCC_CLIENT_RTSS0/1/2/3 client ID definitions (27-30) to the qcom-ipcc dt-bindings header for use by the RTSS Mailbox device tree overlay. Signed-off-by: Sankalp Negi --- include/dt-bindings/mailbox/qcom-ipcc.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/dt-bindings/mailbox/qcom-ipcc.h b/include/dt-bindings/mailbox/qcom-ipcc.h index fd85a79381b31..b9f358a9b7aee 100644 --- a/include/dt-bindings/mailbox/qcom-ipcc.h +++ b/include/dt-bindings/mailbox/qcom-ipcc.h @@ -33,6 +33,10 @@ #define IPCC_CLIENT_NSP1 18 #define IPCC_CLIENT_TME 23 #define IPCC_CLIENT_WPSS 24 +#define IPCC_CLIENT_RTSS0 27 +#define IPCC_CLIENT_RTSS1 28 +#define IPCC_CLIENT_RTSS2 29 +#define IPCC_CLIENT_RTSS3 30 #define IPCC_CLIENT_GPDSP0 31 #define IPCC_CLIENT_GPDSP1 32 From 1925d813630d7a4985b453e71164dde78503a785 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 17 Jun 2026 12:11:38 +0530 Subject: [PATCH 0745/1133] QCLINUX: arm64: dts: qcom: Fix ICP IOVA len within 4GB Reduce the ICP iova-region-len to keep the IO region within the valid 4GB addressable range and avoid overflow. This ensures proper IOVA mapping and prevents potential address boundary violations during camera memory configuration. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/glymur-camera.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-camera.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi index 9e50200f82830..c2c6050a47add 100644 --- a/arch/arm64/boot/dts/qcom/glymur-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi @@ -1974,7 +1974,7 @@ /* IO region is approximately 3.7 GB */ iova-region-name = "io"; iova-region-start = <0x14c00000>; - iova-region-len = <0xee300000>; + iova-region-len = <0xeb300000>; iova-region-id = <0x3>; status = "okay"; }; From fe04b555170eefdf21af08b15f67c075af1a943c Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Thu, 4 Jun 2026 23:53:48 +0530 Subject: [PATCH 0746/1133] QCLINUX: arm64: dts: qcom: Enable camera sensor on glymur crd Enable camera sensors OV08X on the Glymur CRD platform. Adds required DT updates to support sensor bring-up and probe on Glymur crd board. Signed-off-by: Chandan Kumar Jha --- .../boot/dts/qcom/glymur-camera-sensor.dtsi | 51 +++++++++++++++++++ arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso | 13 +++++ 2 files changed, 64 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi diff --git a/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi new file mode 100644 index 0000000000000..acf015644f483 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci1 { + /*cam0-ov08x*/ + qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4p>; + cam_vana-supply = <&vreg_l7p>; + regulator-names = "cam_vio", "cam_vana"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000 2800000>; + rgltr-max-voltage = <1800000 2800000>; + rgltr-load-current = <204000 55000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk4_active &cam_sensor_active_rst4>; + pinctrl-1 = <&cam_sensor_mclk4_suspend &cam_sensor_suspend_rst4>; + pinctrl-names = "cam_default", "cam_suspend"; + gpios = <&tlmm 100 0>, + <&tlmm 239 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK4", + "CAMIF_RESET4"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso index b75789c8aae6b..64cea8de94206 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso +++ b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso @@ -19,9 +19,22 @@ #include #include "glymur-camera.dtsi" +#include "glymur-camera-sensor.dtsi" &cam_icp_firmware { camera-firmware { iommus = <&apps_smmu 0x1901 0x0000>; }; }; + +&camss { + status = "disabled"; +}; + +&cci1 { + status = "disabled"; +}; + +&cci1_i2c1 { + status = "disabled"; +}; From f4ead4c5cf9d8c412d2256628f733e1b37b25278 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 18 Jun 2026 14:41:57 +0800 Subject: [PATCH 0747/1133] QCLINUX: arm64: dts: qcom: Add shared X1 staging overlay Move the common Hamoa staging overlay contents into x1-staging.dtsi so they can be shared across X1 platforms. Keep hamoa-staging.dtso as a thin wrapper around the shared include and add purwa-staging.dtso to build an identical staging overlay for Purwa. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 + arch/arm64/boot/dts/qcom/hamoa-staging.dtso | 108 +------------------ arch/arm64/boot/dts/qcom/purwa-staging.dtso | 11 ++ arch/arm64/boot/dts/qcom/x1-staging.dtsi | 113 ++++++++++++++++++++ 4 files changed, 127 insertions(+), 107 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/purwa-staging.dtso create mode 100644 arch/arm64/boot/dts/qcom/x1-staging.dtsi diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 23dbbddd0cff3..1651efde4aa86 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -652,6 +652,8 @@ dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += purwa-staging.dtbo + dtb-$(CONFIG_ARCH_QCOM) += sm8750-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += kaanapali-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/hamoa-staging.dtso b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso index 6a1e106ae8a9a..465e521384842 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-staging.dtso +++ b/arch/arm64/boot/dts/qcom/hamoa-staging.dtso @@ -8,110 +8,4 @@ /dts-v1/; /plugin/; -#include - -&soc { - tgu@10b0e000 { - compatible = "qcom,tgu", "arm,primecell"; - reg = <0x0 0x10b0e000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - }; - - tgu@10b0f000 { - compatible = "qcom,tgu", "arm,primecell"; - reg = <0x0 0x10b0f000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - }; - - tgu@10b10000 { - compatible = "qcom,tgu", "arm,primecell"; - reg = <0x0 0x10b10000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - }; -}; - -&remoteproc_cdsp { - cooling { - compatible = "qcom,qmi-cooling-cdsp"; - - cdsp_tmd0: cdsp-tmd0 { - label = "cdsp_sw"; - #cooling-cells = <2>; - }; - }; -}; - -&thermal_nsp0 { - trips { - nsp0_alert0: trip-point1 { - temperature = <105000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - - cooling-maps { - map0 { - trip = <&nsp0_alert0>; - cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&thermal_nsp1 { - trips { - nsp1_alert0: trip-point1 { - temperature = <105000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - - cooling-maps { - map0 { - trip = <&nsp1_alert0>; - cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&thermal_nsp2 { - trips { - nsp2_alert0: trip-point1 { - temperature = <105000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - - cooling-maps { - map0 { - trip = <&nsp2_alert0>; - cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&thermal_nsp3 { - trips { - nsp3_alert0: trip-point1 { - temperature = <105000>; - hysteresis = <5000>; - type = "passive"; - }; - }; - - cooling-maps { - map0 { - trip = <&nsp3_alert0>; - cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - +#include "x1-staging.dtsi" diff --git a/arch/arm64/boot/dts/qcom/purwa-staging.dtso b/arch/arm64/boot/dts/qcom/purwa-staging.dtso new file mode 100644 index 0000000000000..5ab12052dd80f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-staging.dtso @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Purwa staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +#include "x1-staging.dtsi" diff --git a/arch/arm64/boot/dts/qcom/x1-staging.dtsi b/arch/arm64/boot/dts/qcom/x1-staging.dtsi new file mode 100644 index 0000000000000..24dfda988bd9d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/x1-staging.dtsi @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Shared X1 staging device tree modifications. + */ + +#include + +&soc { + tgu@10b0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@10b10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x10b10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; + +&remoteproc_cdsp { + cooling { + compatible = "qcom,qmi-cooling-cdsp"; + + cdsp_tmd0: cdsp-tmd0 { + label = "cdsp_sw"; + #cooling-cells = <2>; + }; + }; +}; + +&thermal_nsp0 { + trips { + nsp0_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp0_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp1 { + trips { + nsp1_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp1_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp2 { + trips { + nsp2_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp2_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; + +&thermal_nsp3 { + trips { + nsp3_alert0: trip-point1 { + temperature = <105000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&nsp3_alert0>; + cooling-device = <&cdsp_tmd0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; +}; From e0af6f7bac6b7338502f02d43df0b614306b067f Mon Sep 17 00:00:00 2001 From: Tingguo Cheng Date: Tue, 23 Jun 2026 17:13:53 +0800 Subject: [PATCH 0748/1133] QCLINUX: arm64: dts: qcom: hamoa: Add PM8010_M camera regulator dtsi Add hamoa-camera-regulators.dtsi to define the PM8010_M PMIC LDO regulators needed by camera sensor drivers, and include it in both hamoa-evk-camx.dtso and purwa-evk-camx.dtso. L1M supplies the IMX688 AON core domain (DVDD). It is fed by S5J and supports an output range of 1056-1200 mV. L2M supplies the IMX766 core domain (DVDD). It is fed by S5J and supports an output range of 1152-1200 mV. L3M supplies the IMX766 analog domain and OV sensor I/O (AVDD2, DOVDD). It is fed by S4C and is fixed at 1808 mV. L4M supplies the IMX688 AON I/O domain and IMX766 I/O domain (DOVDD). It is fed by S4C and is fixed at 1808 mV. L5M supplies the IMX766 VCM. It is fed by BOB1 and is fixed at 2960 mV. L6M supplies the IMX688 AON analog domain (AVDD2). It is fed by S4C and is fixed at 1808 mV. L7M supplies the camera analog domain (AVDD). It is fed by BOB1 and is fixed at 2912 mV. Signed-off-by: Tingguo Cheng --- .../dts/qcom/hamoa-camera-regulators.dtsi | 69 +++++++++++++++++++ arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso | 1 + arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso | 1 + 3 files changed, 71 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi new file mode 100644 index 0000000000000..ac0f603a0ddad --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&apps_rsc { + /* PM8010_M */ + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l5-supply = <&vreg_bob1>; + vdd-l6-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p1: ldo1 { + regulator-name = "vreg_l1m_1p1"; + regulator-min-microvolt = <1056000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p15: ldo2 { + regulator-name = "vreg_l2m_1p15"; + regulator-min-microvolt = <1152000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l5m_3p0: ldo5 { + regulator-name = "vreg_l5m_3p0"; + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = ; + }; + + vreg_l6m_1p8: ldo6 { + regulator-name = "vreg_l6m_1p8"; + regulator-min-microvolt = <1808000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p9: ldo7 { + regulator-name = "vreg_l7m_2p9"; + regulator-min-microvolt = <2912000>; + regulator-max-microvolt = <2912000>; + regulator-initial-mode = ; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso b/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso index d63daf990f2a1..df773142192eb 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/hamoa-evk-camx.dtso @@ -18,6 +18,7 @@ #include #include +#include "hamoa-camera-regulators.dtsi" #include "hamoa-camera.dtsi" #include "hamoa-camera-sensor.dtsi" diff --git a/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso index 26603aed4eafc..f97d37cf6e1e4 100644 --- a/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso @@ -18,6 +18,7 @@ #include #include +#include "hamoa-camera-regulators.dtsi" #include "purwa-camera.dtsi" &camss { From 36420aeac97707479547ec7fcc9052854ad2baf1 Mon Sep 17 00:00:00 2001 From: shubamm Date: Fri, 26 Jun 2026 12:41:17 +0530 Subject: [PATCH 0749/1133] QCLINUX: arm64: dts: qcom: Add Purwa sensors support Add og0va1b IR/VGA camera sensor node. Add imx688 camera sensor module node Signed-off-by: shubamm --- .../boot/dts/qcom/purwa-camera-sensor.dtsi | 89 +++++++++++++++++++ arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso | 1 + 2 files changed, 90 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi diff --git a/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi new file mode 100644 index 0000000000000..ffd6b1c4d570f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + + /*cam1-og0a1b*/ + qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l7m_2p9>; + regulator-names = "cam_vio", "cam_vana"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 2912000>; + rgltr-max-voltage = <1808000 2912000>; + rgltr-load-current = <120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_suspend_rst0>; + gpios = <&tlmm 96 0>, <&tlmm 109 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; +}; + +&cam_cci1 { + /*cam2-imx688*/ + qcom,cam-sensor4 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l6m_1p8>; + cam_vdig-supply = <&vreg_l1m_1p1>; + cam_v_custom1-supply = <&vreg_l7b_2p8>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", "cam_v_custom1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 1808000 1056000 2800000>; + rgltr-max-voltage = <1808000 1808000 1200000 2800000>; + rgltr-load-current = <120000 120000 120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk4_active &cam_sensor_active_rst4>; + pinctrl-1 = <&cam_sensor_mclk4_suspend &cam_sensor_suspend_rst4>; + gpios = <&tlmm 100 0>, <&tlmm 237 0>, <&tlmm 233 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK4", "CAMIF_RESET4", "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <4>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso index f97d37cf6e1e4..27d1ff2fc2fea 100644 --- a/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/purwa-evk-camx.dtso @@ -20,6 +20,7 @@ #include "hamoa-camera-regulators.dtsi" #include "purwa-camera.dtsi" +#include "purwa-camera-sensor.dtsi" &camss { status = "disabled"; From 8db146e4e4935e417c689600b66d807639e43d7e Mon Sep 17 00:00:00 2001 From: shubamm Date: Fri, 26 Jun 2026 12:41:19 +0530 Subject: [PATCH 0750/1133] QCLINUX: arm64: dts: qcom: Add Hamoa camera sensor support Add og0a1b VGA camera sensor node (cam-sensor1) on CCI0 and imx688 camera sensor node (cam-sensor4) on CCI1 for Hamoa board. og0a1b (cam-sensor1): - MCLK0 / CCI master 0 - 1.8V IO supply (vreg_l4m_1p8), 2.9V analog supply (vreg_l7m_2p9) - GPIO reset: TLMM 109, MCLK: TLMM 96 - Sensor position: yaw=180 (rear-facing) imx688 (cam-sensor4): - MCLK4 / CCI1 master 1 - 1.8V IO supply (vreg_l4m_1p8), 1.8V analog supply (vreg_l6m_1p8) - 1.056V digital supply (vreg_l1m_1p1), 2.8V custom supply (vreg_l7b_2p8) - GPIO reset: TLMM 237, MCLK: TLMM 100, custom GPIO: TLMM 233 - Sensor position: yaw=180 (rear-facing) Signed-off-by: shubamm --- .../boot/dts/qcom/hamoa-camera-sensor.dtsi | 76 ++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi index 7ebfcf1ec3912..a2f821a2b93ff 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi @@ -18,8 +18,8 @@ power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; rgltr-cntrl-support; pwm-switch; - rgltr-min-voltage = <1800000>; - rgltr-max-voltage = <1800000>; + rgltr-min-voltage = <1808000>; + rgltr-max-voltage = <1808000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; pinctrl-names = "cam_default", "cam_suspend"; @@ -43,6 +43,78 @@ cell-index = <0>; status = "okay"; }; + /*cam1-og0a1b*/ + qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l7m_2p9>; + regulator-names = "cam_vio", "cam_vana"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 2912000>; + rgltr-max-voltage = <1808000 2912000>; + rgltr-load-current = <120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_suspend_rst0>; + gpios = <&tlmm 96 0>, <&tlmm 109 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; +}; + +&cam_cci1 { + /*cam2-imx688*/ + qcom,cam-sensor4 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4m_1p8>; + cam_vana-supply = <&vreg_l6m_1p8>; + cam_vdig-supply = <&vreg_l1m_1p1>; + cam_v_custom1-supply = <&vreg_l7b_2p8>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", "cam_v_custom1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1808000 1808000 1056000 2800000>; + rgltr-max-voltage = <1808000 1808000 1200000 2800000>; + rgltr-load-current = <120000 120000 120000 120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk4_active &cam_sensor_active_rst4>; + pinctrl-1 = <&cam_sensor_mclk4_suspend &cam_sensor_suspend_rst4>; + gpios = <&tlmm 100 0>, <&tlmm 237 0>, <&tlmm 233 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK4", "CAMIF_RESET4", "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <4>; + status = "okay"; + }; }; &soc { From 792b1f23aafbbd17480d004d48221cec282559cc Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Mon, 6 Jul 2026 14:35:13 +0800 Subject: [PATCH 0751/1133] PENDING: arm64: dts: qcom: shikra: add TGU in staging dtso Add TGU device for supporting IPCB feature in staging dtso file. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/shikra-staging.dtso | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 1651efde4aa86..42ee03efcd892 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -657,3 +657,5 @@ dtb-$(CONFIG_ARCH_QCOM) += purwa-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8750-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += kaanapali-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += shikra-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/shikra-staging.dtso b/arch/arm64/boot/dts/qcom/shikra-staging.dtso new file mode 100644 index 0000000000000..66add6e4b562f --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-staging.dtso @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Shikra staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@9840000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x9840000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 05f1ee2b95405d2d5a8415f79169e6456bbb115d Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Sun, 3 May 2026 20:39:51 +0530 Subject: [PATCH 0752/1133] PENDING: arm64: dts: qcom: talos-evk: add QPS615 m.2 ethernet staging overlay Add talos-evk-staging.dtso for the QPS615 m.2 e-key daughter card. When installed, the QPS615 PCIe switch replaces the direct WCN7850 WLAN connection at pcie_port0. The overlay: - Enables PCIe with IOMMU mappings (required by QPS615 DMA traffic) - Disables the direct WCN7850 WLAN at pcie_port0 (wifi@0) - Moves WLAN to QPS615 downstream port 1 (pcie@1,0, bus 3 dev 0) - Describes dual Ethernet (TC956X) at QPS615 downstream port 3 (pci@3,0, bus 5 dev 0 fn0/fn1) Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../boot/dts/qcom/talos-evk-staging.dtso | 99 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/talos-evk-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 42ee03efcd892..cfcbce803339a 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -646,6 +646,8 @@ dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += talos-evk-staging.dtbo + dtb-$(CONFIG_ARCH_QCOM) += kodiak-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/talos-evk-staging.dtso b/arch/arm64/boot/dts/qcom/talos-evk-staging.dtso new file mode 100644 index 0000000000000..ec1f40853ccd5 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-evk-staging.dtso @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&pcie { + iommu-map = <0x0 &apps_smmu 0x400 0x1>, + <0x100 &apps_smmu 0x401 0x1>, + <0x208 &apps_smmu 0x402 0x1>, + <0x210 &apps_smmu 0x403 0x1>, + <0x218 &apps_smmu 0x404 0x1>, + <0x300 &apps_smmu 0x405 0x1>, + <0x400 &apps_smmu 0x406 0x1>, + <0x500 &apps_smmu 0x407 0x1>, + <0x501 &apps_smmu 0x408 0x1>; + + status = "okay"; +}; + +/* + * With QPS615 installed, the m.2 E-key slot is occupied by the QPS615 + * PCIe switch (pci1179,0623) rather than the direct WCN7850 WLAN chip. + * + * QPS615 downstream port layout: + * pcie@1,0 (bus 3) — WCN7850 WLAN, moved here from the direct connection + * pcie@2,0 (bus 4) — free downstream port + * pci@3,0 (bus 5) — TC956X dual Ethernet (QPS615 GPIO-reset PHYs) + */ +&pcie_port0 { + wifi@0 { + status = "disabled"; + + pcie@1,0 { + reg = <0x20800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x3 0x3>; + + wifi@0,0 { + compatible = "pci17cb,1103"; + reg = <0x30000 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>; + }; + }; + + pci@3,0 { + reg = <0x21800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x5 0xff>; + compatible = "pci1179,0623"; + + qps615: pci@0,0 { + reg = <0x50000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + + gpio-controller; + #gpio-cells = <2>; + + phy-reset-gpios = <&qps615 0 GPIO_ACTIVE_LOW>; + reset-deassert-us = <221000>; + }; + + pci@0,1 { + reg = <0x50100 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + + phy-reset-gpios = <&qps615 1 GPIO_ACTIVE_LOW>; + reset-deassert-us = <20000>; + }; + }; + }; +}; From 027622a72c849e3205205bcb1cd03c99ee2dd737 Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Tue, 7 Jul 2026 15:29:06 +0530 Subject: [PATCH 0753/1133] QCLINUX: arm64: dts: qcom: Enable og0va1b camera sensor on glymur crd Enable camera sensors og0va1b on the Glymur CRD platform. Adds required DT updates to support sensor bring-up and probe on Glymur crd board. Signed-off-by: Vishal Verma --- .../boot/dts/qcom/glymur-camera-sensor.dtsi | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi index acf015644f483..16aa3dc7816d4 100644 --- a/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi @@ -23,9 +23,6 @@ rgltr-max-voltage = <1800000 2800000>; rgltr-load-current = <204000 55000>; gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk4_active &cam_sensor_active_rst4>; - pinctrl-1 = <&cam_sensor_mclk4_suspend &cam_sensor_suspend_rst4>; - pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 100 0>, <&tlmm 239 0>; gpio-reset = <1>; @@ -41,11 +38,49 @@ cell-index = <0>; status = "okay"; }; + + /*cam1-og0va1b*/ + qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l4p>; + cam_vana-supply = <&vreg_l3p>; + regulator-names = "cam_vio", "cam_vana"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000 2800000>; + rgltr-max-voltage = <1960000 3312000>; + rgltr-load-current = <36000 35000>; + gpio-no-mux = <0>; + gpios = <&tlmm 100 0>, + <&tlmm 109 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK4", + "CAMIF_RESET0"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK4_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; }; &soc { qcom,cam-res-mgr { compatible = "qcom,cam-res-mgr"; + gpios-shared-pinctrl = <760>; + pinctrl-names = "mclk4_active", "mclk4_suspend"; + pinctrl-0 = <&cam_sensor_mclk4_active>; + pinctrl-1 = <&cam_sensor_mclk4_suspend>; + shared-pctrl-gpio-names = "mclk4"; status = "okay"; }; }; From f3739e8f799948d01870a4df9a471c3a24963f07 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 14 Jul 2026 15:41:34 +0800 Subject: [PATCH 0754/1133] QCLINUX: arm64: dts: qcom: glymur: remove ETR and CTCU devices from staging The patch to enable ETR and CTCU devices have been posted on upstream kernel. So remove them from the staging file. Link: https://lore.kernel.org/all/20260714-add-ctcu-etr-for-glymur-v1-1-791de63c0713@oss.qualcomm.com/ Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/glymur-staging.dtso | 158 ------------------- 1 file changed, 158 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/glymur-staging.dtso b/arch/arm64/boot/dts/qcom/glymur-staging.dtso index 0b95e568e1c00..07aa0f8d7bd75 100644 --- a/arch/arm64/boot/dts/qcom/glymur-staging.dtso +++ b/arch/arm64/boot/dts/qcom/glymur-staging.dtso @@ -9,152 +9,6 @@ /plugin/; &soc { - ctcu@10001000 { - compatible = "qcom,glymur-ctcu", "qcom,sa8775p-ctcu"; - reg = <0x0 0x10001000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb"; - - in-ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - ctcu_in0: endpoint { - remote-endpoint = <&etr0_out>; - }; - }; - - port@1 { - reg = <1>; - - ctcu_in1: endpoint { - remote-endpoint = <&etr1_out>; - }; - }; - }; - }; - - replicator@10046000 { - compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; - reg = <0x0 0x10046000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - - in-ports { - port { - qdss_rep_in: endpoint { - remote-endpoint = <&swao_rep_out0>; - }; - }; - }; - - out-ports { - port { - qdss_rep_out0: endpoint { - remote-endpoint = <&etr_rep_in>; - }; - }; - }; - }; - - tmc@10048000 { - compatible = "arm,coresight-tmc", "arm,primecell"; - reg = <0x0 0x10048000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - - iommus = <&apps_smmu 0x00e0 0x0000>; - - arm,scatter-gather; - - in-ports { - port { - etr0_in: endpoint { - remote-endpoint = <&etr_rep_out0>; - }; - }; - }; - - out-ports { - port { - etr0_out: endpoint { - remote-endpoint = <&ctcu_in0>; - }; - }; - }; - }; - - replicator@1004e000 { - compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; - reg = <0x0 0x1004e000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - - in-ports { - port { - etr_rep_in: endpoint { - remote-endpoint = <&qdss_rep_out0>; - }; - }; - }; - - out-ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - etr_rep_out0: endpoint { - remote-endpoint = <&etr0_in>; - }; - }; - - port@1 { - reg = <1>; - - etr_rep_out1: endpoint { - remote-endpoint = <&etr1_in>; - }; - }; - }; - }; - - tmc@1004f000 { - compatible = "arm,coresight-tmc", "arm,primecell"; - reg = <0x0 0x1004f000 0x0 0x1000>; - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; - - iommus = <&apps_smmu 0x0100 0x0000>; - - arm,scatter-gather; - - in-ports { - port { - etr1_in: endpoint { - remote-endpoint = <&etr_rep_out1>; - }; - }; - }; - - out-ports { - port { - etr1_out: endpoint { - remote-endpoint = <&ctcu_in1>; - }; - }; - }; - }; - tgu@11c02000 { compatible = "qcom,tgu", "arm,primecell"; reg = <0x0 0x11c02000 0x0 0x1000>; @@ -163,18 +17,6 @@ clock-names = "apb_pclk"; }; - replicator@11c06000 { - out-ports { - port@0 { - reg = <0>; - - swao_rep_out0: endpoint { - remote-endpoint = <&qdss_rep_in>; - }; - }; - }; - }; - tgu@11c0e000 { compatible = "qcom,tgu", "arm,primecell"; reg = <0x0 0x11c0e000 0x0 0x1000>; From d1375559c38bd6c4301e364e75c9b07b314aac61 Mon Sep 17 00:00:00 2001 From: Vadlamani Manjusha Date: Fri, 3 Jul 2026 11:04:05 +0530 Subject: [PATCH 0755/1133] QCLINUX: arm64: dts: qcom: Removes imx577 sensor dts node of Monaco-evk Removing non-required imx577 sensor node definition for cci1 for monaco-evk. Signed-off-by: Vadlamani Manjusha --- .../dts/qcom/monaco-evk-camera-sensor.dtsi | 75 ------------------- 1 file changed, 75 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi index 167b85c0e8844..8bdf5a555cfe5 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi @@ -399,46 +399,6 @@ status = "ok"; }; - /*cam0-imx577*/ - qcom,cam-sensor19 { - compatible = "qcom,cam-sensor"; - cell-index = <19>; - csiphy-sd-index = <1>; - sensor-position-roll = <0>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - eeprom-src = <&eeprom_cam19>; - regulator-names = "cam_vio"; - power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000>; - rgltr-max-voltage = <1800000>; - rgltr-load-current = <120000>; - gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 68 0>, - <&tlmm 74 0>, - <&expander2 1 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK1", - "CAMIF_RESET1", - "CAM_CUSTOM1"; - cci-master = <0>; - clocks = <&camcc CAM_CC_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "nominal"; - clock-rates = <24000000>; - status = "ok"; - }; - /*cam0-imx577*/ qcom,cam-sensor21 { compatible = "qcom,cam-sensor"; @@ -479,41 +439,6 @@ status = "ok"; }; - eeprom_cam19: qcom,eeprom19 { - compatible = "qcom,eeprom"; - cell-index = <19>; - regulator-names = "cam_vio"; - power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000>; - rgltr-max-voltage = <1800000>; - rgltr-load-current = <120000>; - gpio-no-mux = <0>; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rst1>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rst1>; - pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&tlmm 68 0>, - <&tlmm 74 0>, - <&expander2 1 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAM_MCLK1", - "CAMIF_RESET1", - "CAM_CUSTOM1"; - sensor-mode = <0>; - cci-master = <0>; - clocks = <&camcc CAM_CC_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "nominal"; - clock-rates = <24000000>; - status = "ok"; - }; - eeprom_cam21: qcom,eeprom21 { compatible = "qcom,eeprom"; cell-index = <21>; From 9c1ce0f6f5b1aa1a8f8bdd65372a4bf9cf1a2a1f Mon Sep 17 00:00:00 2001 From: Vadlamani Manjusha Date: Fri, 3 Jul 2026 11:06:00 +0530 Subject: [PATCH 0756/1133] QCLINUX: arm64: dts: qcom: Monaco-EVK Swap RESET and POWER down pins Swap reset and power down pins for MIPI camera on all Monaco-EVK SOCs to to maintain a consistent pin naming convention,since the reset pin mapping differs between MIPI and GMSL cameras. Signed-off-by: Vadlamani Manjusha --- .../dts/qcom/monaco-evk-camera-sensor.dtsi | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi index 8bdf5a555cfe5..b4659d03eb9da 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-evk-camera-sensor.dtsi @@ -147,8 +147,8 @@ &cam_sensor_suspend_rst0>; pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 67 0>, - <&tlmm 73 0>, - <&expander2 0 0>; + <&expander2 0 0>, + <&tlmm 73 0>; gpio-reset = <1>; gpio-custom1 = <2>; gpio-req-tbl-num = <0 1 2>; @@ -187,8 +187,8 @@ &cam_sensor_suspend_rst0>; pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 67 0>, - <&tlmm 73 0>, - <&expander2 0 0>; + <&expander2 0 0>, + <&tlmm 73 0>; gpio-reset = <1>; gpio-custom1 = <2>; gpio-req-tbl-num = <0 1 2>; @@ -221,8 +221,8 @@ &cam_sensor_suspend_rst0>; pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 67 0>, - <&tlmm 73 0>, - <&expander2 0 0>; + <&expander2 0 0>, + <&tlmm 73 0>; gpio-reset = <1>; gpio-custom1 = <2>; gpio-req-tbl-num = <0 1 2>; @@ -382,8 +382,8 @@ &cam_sensor_suspend_rst1>; pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 68 0>, - <&tlmm 74 0>, - <&expander2 1 0>; + <&expander2 1 0>, + <&tlmm 74 0>; gpio-reset = <1>; gpio-custom1 = <2>; gpio-req-tbl-num = <0 1 2>; @@ -422,8 +422,8 @@ &cam_sensor_suspend_rst1>; pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 68 0>, - <&tlmm 74 0>, - <&expander2 1 0>; + <&expander2 1 0>, + <&tlmm 74 0>; gpio-reset = <1>; gpio-custom1 = <2>; gpio-req-tbl-num = <0 1 2>; @@ -456,8 +456,8 @@ &cam_sensor_suspend_rst1>; pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 68 0>, - <&tlmm 74 0>, - <&expander2 1 0>; + <&expander2 1 0>, + <&tlmm 74 0>; gpio-reset = <1>; gpio-custom1 = <2>; gpio-req-tbl-num = <0 1 2>; @@ -617,8 +617,8 @@ &cam_sensor_suspend_rst2>; pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 69 0>, - <&tlmm 75 0>, - <&expander2 2 0>; + <&expander2 2 0>, + <&tlmm 75 0>; gpio-reset = <1>; gpio-custom1 = <2>; gpio-req-tbl-num = <0 1 2>; @@ -657,8 +657,8 @@ &cam_sensor_suspend_rst2>; pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 69 0>, - <&tlmm 75 0>, - <&expander2 2 0>; + <&expander2 2 0>, + <&tlmm 75 0>; gpio-reset = <1>; gpio-custom1 = <2>; gpio-req-tbl-num = <0 1 2>; @@ -691,8 +691,8 @@ &cam_sensor_suspend_rst2>; pinctrl-names = "cam_default", "cam_suspend"; gpios = <&tlmm 69 0>, - <&tlmm 75 0>, - <&expander2 2 0>; + <&expander2 2 0>, + <&tlmm 75 0>; gpio-reset = <1>; gpio-custom1 = <2>; gpio-req-tbl-num = <0 1 2>; From a0b84283744ee8238c46942ebbc696f6962aa2e0 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Fri, 24 Jul 2026 17:35:11 +0530 Subject: [PATCH 0757/1133] QCLINUX: arm64: dts: qcom: Install camx DTBO overlays Install Qualcomm camx DTBO overlay files by adding them to the dtb-$(CONFIG_ARCH_QCOM) build/install list. This makes DTBOs available through the standard dtbs_install flow and ensures they are included in distro kernel packages. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index cfcbce803339a..556e8b2f397ec 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -561,6 +561,7 @@ dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-camx.dtbo hamoa-camx-el2-dtbs := hamoa-iot-evk-el2.dtb hamoa-evk-camx.dtbo hamoa-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += hamoa-camx-el2.dtbo lemans-evk-camx-dtbs := lemans-evk.dtb lemans-evk-camx.dtbo @@ -593,10 +594,12 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo purwa-evk-camx-dtbs := purwa-iot-evk.dtb purwa-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += purwa-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += purwa-evk-camx.dtbo purwa-camx-el2-dtbs := purwa-iot-evk-el2.dtb purwa-evk-camx.dtbo purwa-camx-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += purwa-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += purwa-camx-el2.dtbo qcs5430-fps-camx-dtbs := qcs6490-rb3gen2.dtb qcs5430-fps-camx.dtbo From adedbb9f9addbc93b74d224fdf4e502582886241 Mon Sep 17 00:00:00 2001 From: Nirav Khatri Date: Fri, 14 Aug 2026 11:31:21 +0530 Subject: [PATCH 0758/1133] QCLINUX: arm64: dts: qcom: camera: Add support for rgbir camera Add support for RGBIR camera dt node as sensor 14. Signed-off-by: Nirav Khatri --- .../qcom/qcs6490-rb3gen2-camera-sensor.dtsi | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi index 026b97b58377d..cf8a8f01e49ba 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi @@ -475,6 +475,45 @@ cci-master = <1>; status = "ok"; }; + + /* cam3-connector - ov2778 */ + qcom,cam-sensor14 { + compatible = "qcom,cam-sensor"; + cell-index = <14>; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk3_active + &cam_sensor_active_rst3>; + pinctrl-1 = <&cam_sensor_mclk3_suspend + &cam_sensor_suspend_rst3>; + pinctrl-names = "cam_default", + "cam_suspend"; + gpios = <&tlmm 67 0>, + <&tlmm 78 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAMIF_MCLK3", + "CAM_RESET3"; + sensor-mode = <0>; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK3_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + }; + }; &soc { From 89a7357c6af9946f20d8092f604d3298a1e9fb78 Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Thu, 13 Aug 2026 11:30:15 +0530 Subject: [PATCH 0759/1133] QCLINUX: arm64: dts: qcom: Add flag to enable aggregated CSIPHY Add flag "aggregator-rx" to the Hamoa and Purwa camera dtsi. This change enables the aggregated CSIPHY to enable the GMSL Camera and Per-port feature. Signed-off-by: Vishal Verma --- arch/arm64/boot/dts/qcom/hamoa-camera.dtsi | 4 ++++ arch/arm64/boot/dts/qcom/purwa-camera.dtsi | 2 ++ 2 files changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi index 94dd42b380f4e..eab61a47d1c04 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-camera.dtsi @@ -1636,6 +1636,7 @@ src-clock-name = "csi0phytimer_clk_src"; clock-cntl-level = "nominal"; clock-rates = <480000000 0 400000000 0>; + aggregator-rx; operating-points-v2 = <&csiphy0_opp_table>; cell-index = <0>; status = "okay"; @@ -1678,6 +1679,7 @@ src-clock-name = "csi1phytimer_clk_src"; clock-cntl-level = "nominal"; clock-rates = <480000000 0 400000000 0>; + aggregator-rx; operating-points-v2 = <&csiphy1_opp_table>; cell-index = <1>; status = "okay"; @@ -1720,6 +1722,7 @@ src-clock-name = "csi2phytimer_clk_src"; clock-cntl-level = "nominal"; clock-rates = <480000000 0 400000000 0>; + aggregator-rx; operating-points-v2 = <&csiphy2_opp_table>; cell-index = <2>; status = "okay"; @@ -1762,6 +1765,7 @@ src-clock-name = "csi4phytimer_clk_src"; clock-cntl-level = "nominal"; clock-rates = <480000000 0 400000000 0>; + aggregator-rx; operating-points-v2 = <&csiphy4_opp_table>; cell-index = <4>; status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi index cbc9ec0f83aad..46427e71eb9d3 100644 --- a/arch/arm64/boot/dts/qcom/purwa-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa-camera.dtsi @@ -1333,6 +1333,7 @@ src-clock-name = "csi0phytimer_clk_src"; clock-cntl-level = "nominal"; clock-rates = <480000000 0 400000000 0>; + aggregator-rx; operating-points-v2 = <&csiphy0_opp_table>; cell-index = <0>; status = "okay"; @@ -1375,6 +1376,7 @@ src-clock-name = "csi4phytimer_clk_src"; clock-cntl-level = "nominal"; clock-rates = <480000000 0 400000000 0>; + aggregator-rx; operating-points-v2 = <&csiphy4_opp_table>; cell-index = <4>; status = "okay"; From dfe074015ec27dd92650707362d8d6b344b35cbe Mon Sep 17 00:00:00 2001 From: Vadlamani Manjusha Date: Thu, 9 Jul 2026 15:39:57 +0530 Subject: [PATCH 0760/1133] QCLINUX: arm64: dts: qcom: Add IMX577 DTSI changes to Support CAM1 CAM1 port is currently enabled for OV9282.This change adds DTSI configuration for IMX577 so that CAM1 can also support IMX577 sensor on the hardware platform of QCM6490 Dev. Signed-off-by: Vadlamani Manjusha --- .../qcom/qcs6490-rb3gen2-camera-sensor.dtsi | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi index cf8a8f01e49ba..fb765f2e3d0c7 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-camera-sensor.dtsi @@ -175,6 +175,84 @@ status = "ok"; }; + eeprom_cam1: qcom,eeprom1 { + cell-index = <12>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + gpios = <&tlmm 65 0>, + <&tlmm 21 0>, + <&pm7250b_gpios 3 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-position = <1>; + sensor-mode = <0>; + cci-master = <1>; + status = "okay"; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + }; + + /*cam1-imx577*/ + qcom,cam-sensor12 { + cell-index = <12>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + eeprom-src = <&eeprom_cam1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l18b_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + gpios = <&tlmm 65 0>, + <&tlmm 21 0>, + <&pm7250b_gpios 3 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_CUSTOM1"; + sensor-mode = <0>; + cci-master = <1>; + status = "okay"; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + }; }; &cam_cci1 { From 77adf4bc79e635655066cf55d72862dad8d68ba0 Mon Sep 17 00:00:00 2001 From: Tingguo Cheng Date: Thu, 27 Aug 2026 17:33:13 +0800 Subject: [PATCH 0761/1133] QCLINUX: arm64: dts: qcom: hamoa: Fix PM8010_M LDO min voltage for L3M/L4M/L6M Correct the regulator-min-microvolt for L3M, L4M, and L6M from 1808000 to 1800000. Signed-off-by: Tingguo Cheng --- arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi index ac0f603a0ddad..88d53f33da2a4 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-regulators.dtsi @@ -33,14 +33,14 @@ vreg_l3m_1p8: ldo3 { regulator-name = "vreg_l3m_1p8"; - regulator-min-microvolt = <1808000>; + regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1808000>; regulator-initial-mode = ; }; vreg_l4m_1p8: ldo4 { regulator-name = "vreg_l4m_1p8"; - regulator-min-microvolt = <1808000>; + regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1808000>; regulator-initial-mode = ; }; @@ -54,7 +54,7 @@ vreg_l6m_1p8: ldo6 { regulator-name = "vreg_l6m_1p8"; - regulator-min-microvolt = <1808000>; + regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1808000>; regulator-initial-mode = ; }; From f31b52815cec52676b17d101dd12141972c9681c Mon Sep 17 00:00:00 2001 From: shubamm Date: Tue, 8 Sep 2026 10:10:53 +0530 Subject: [PATCH 0762/1133] QCLINUX: arm64: dts: qcom: Update Hamoa camera sensor regulator voltage Update rgltr-min-voltage for cam-sensor0 (cmk_imx577), cam-sensor1 (og0a1b), and cam-sensor4 (imx688) on the Hamoa board from 1808000 to 1800000 to match the corrected vreg_l3m_1p8/vreg_l4m_1p8/ vreg_l6m_1p8 LDO regulator-min-microvolt value. Signed-off-by: Shubam Mishra --- arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi index a2f821a2b93ff..1b2e16fe68808 100644 --- a/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa-camera-sensor.dtsi @@ -18,7 +18,7 @@ power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; rgltr-cntrl-support; pwm-switch; - rgltr-min-voltage = <1808000>; + rgltr-min-voltage = <1800000>; rgltr-max-voltage = <1808000>; rgltr-load-current = <120000>; gpio-no-mux = <0>; @@ -56,7 +56,7 @@ power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; rgltr-cntrl-support; pwm-switch; - rgltr-min-voltage = <1808000 2912000>; + rgltr-min-voltage = <1800000 2912000>; rgltr-max-voltage = <1808000 2912000>; rgltr-load-current = <120000 120000>; gpio-no-mux = <0>; @@ -94,7 +94,7 @@ power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; rgltr-cntrl-support; pwm-switch; - rgltr-min-voltage = <1808000 1808000 1056000 2800000>; + rgltr-min-voltage = <1800000 1800000 1056000 2800000>; rgltr-max-voltage = <1808000 1808000 1200000 2800000>; rgltr-load-current = <120000 120000 120000 120000>; gpio-no-mux = <0>; From 001ec1c136393a6c78b54fadf1ce705c59c33545 Mon Sep 17 00:00:00 2001 From: Shubam Mishra Date: Thu, 10 Sep 2026 11:47:44 +0530 Subject: [PATCH 0763/1133] QCLINUX: arm64: dts: qcom: purwa: Fix PM8010_M LDO min voltage for L4M/L6M Correct the regulator-min-microvolt for L4M and L6M from 1808000 to 1800000. Signed-off-by: Shubam Mishra --- arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi index ffd6b1c4d570f..c6b319254bace 100644 --- a/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa-camera-sensor.dtsi @@ -20,7 +20,7 @@ power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; rgltr-cntrl-support; pwm-switch; - rgltr-min-voltage = <1808000 2912000>; + rgltr-min-voltage = <1800000 2912000>; rgltr-max-voltage = <1808000 2912000>; rgltr-load-current = <120000 120000>; gpio-no-mux = <0>; @@ -58,7 +58,7 @@ power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; rgltr-cntrl-support; pwm-switch; - rgltr-min-voltage = <1808000 1808000 1056000 2800000>; + rgltr-min-voltage = <1800000 1800000 1056000 2800000>; rgltr-max-voltage = <1808000 1808000 1200000 2800000>; rgltr-load-current = <120000 120000 120000 120000>; gpio-no-mux = <0>; From 59fa8ad7f94430bd2b0f06446d82c49e0b12e877 Mon Sep 17 00:00:00 2001 From: Manibharathi Kandasamy Date: Thu, 10 Sep 2026 18:43:19 +0530 Subject: [PATCH 0764/1133] QCLINUX: arm64: dts: qcom: shikra: Install camx DTBO overlays Add Makefile entries to build and install camera (camx) DTBO overlays for Shikra CQS EVK and IQS EVK board variants. Each composite DTB bundles the respective base platform DTB with the camx overlay, and registers both the merged .dtb and standalone .dtbo. Moving entries at the end to avoid conflicts in Makefile. Signed-off-by: Manibharathi Kandasamy Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/Makefile | 15 + .../boot/dts/qcom/shikra-camera-sensor.dtsi | 457 +++++++ arch/arm64/boot/dts/qcom/shikra-camera.dtsi | 1189 +++++++++++++++++ .../boot/dts/qcom/shikra-cqm-evk-camx.dtso | 41 + .../boot/dts/qcom/shikra-cqs-evk-camx.dtso | 41 + .../boot/dts/qcom/shikra-iqs-evk-camx.dtso | 111 ++ 6 files changed, 1854 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/shikra-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/shikra-cqm-evk-camx.dtso create mode 100644 arch/arm64/boot/dts/qcom/shikra-cqs-evk-camx.dtso create mode 100644 arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 556e8b2f397ec..5025a7692b2f9 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -642,6 +642,21 @@ sa8775p-ride-r3-camx-dtbs:= sa8775p-ride-r3.dtb sa8775p-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3-camx.dtb +shikra-cqs-evk-camx-dtbs := shikra-cqs-evk.dtb shikra-cqs-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-camx.dtbo + +shikra-cqm-evk-camx-dtbs := shikra-cqm-evk.dtb shikra-cqs-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-camx.dtbo + +shikra-iqs-evk-camx-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-camx.dtbo + talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/shikra-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/shikra-camera-sensor.dtsi new file mode 100644 index 0000000000000..42410c14f9b72 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-camera-sensor.dtsi @@ -0,0 +1,457 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include + +&cam_cci0 { + actuator_cam0: qcom,actuator0 { + compatible = "qcom,actuator"; + cci-master = <0>; + cam_vaf-supply = <&pm4125_l15>; + regulator-names = "cam_vaf"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + cell-index = <0>; + status = "okay"; + }; + + actuator_cam1: qcom,actuator1 { + compatible = "qcom,actuator"; + cci-master = <1>; + cam_vaf-supply = <&pm4125_l15>; + regulator-names = "cam_vaf"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + cell-index = <1>; + status = "okay"; + }; + + actuator_cam2: qcom,actuator2 { + compatible = "qcom,actuator"; + cci-master = <1>; + cam_vaf-supply = <&pm4125_l15>; + regulator-names = "cam_vaf"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + cell-index = <2>; + status = "okay"; + }; + + actuator_cam5: qcom,actuator5 { + compatible = "qcom,actuator"; + cci-master = <0>; + cam_vaf-supply = <&pm4125_l15>; + regulator-names = "cam_vaf"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + cell-index = <5>; + status = "okay"; + }; + + /*cam0: OV13B10*/ + sensor_cam0: qcom,cam-sensor0 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam0>; + actuator-src = <&actuator_cam0>; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + gpios = <&tlmm 34 0>, + <&tlmm 32 0>, + <&tlmm 144 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; + + /*cam1: OV13B10 */ + sensor_cam1: qcom,cam-sensor1 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam1>; + actuator-src = <&actuator_cam1>; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + gpios = <&tlmm 35 0>, + <&tlmm 33 0>, + <&tlmm 148 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; + + /*cam2: IMX858 */ + sensor_cam2: qcom,cam-sensor2 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam2>; + actuator-src = <&actuator_cam2>; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + gpios = <&tlmm 35 0>, + <&tlmm 33 0>, + <&tlmm 148 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <19200000>; + cell-index = <2>; + status = "okay"; + }; + + /*cam0: IMX577 - 22pin connector*/ + sensor_cam3: qcom,cam-sensor3 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + gpios = <&tlmm 34 0>, + <&tlmm 32 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0"; + cci-master = <0>; + clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <3>; + status = "okay"; + }; + + /*cam1: IMX577 - 22pin connector*/ + sensor_cam4: qcom,cam-sensor4 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + gpios = <&tlmm 35 0>, + <&tlmm 33 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1"; + cci-master = <1>; + clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <4>; + status = "okay"; + }; + + /*cam5: IMX858*/ + sensor_cam5: qcom,cam-sensor5 { + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam5>; + actuator-src = <&actuator_cam5>; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + gpios = <&tlmm 34 0>, + <&tlmm 32 0>, + <&tlmm 144 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <19200000>; + cell-index = <5>; + status = "okay"; + }; + + /*EEPROM0: OV13B10 */ + eeprom_cam0: qcom,eeprom0 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + gpios = <&tlmm 34 0>, + <&tlmm 32 0>, + <&tlmm 144 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <0>; + status = "okay"; + }; + + /*EEPROM1: OV13B10 */ + eeprom_cam1: qcom,eeprom1 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + gpios = <&tlmm 35 0>, + <&tlmm 33 0>, + <&tlmm 148 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + cell-index = <1>; + status = "okay"; + }; + + /*EEPROM2: IMX858 */ + eeprom_cam2: qcom,eeprom2 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_suspend_rst1>; + gpios = <&tlmm 35 0>, + <&tlmm 33 0>, + <&tlmm 148 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK1", + "CAMIF_RESET1", + "CAM_CUSTOM1"; + cci-master = <1>; + clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <19200000>; + cell-index = <2>; + status = "okay"; + }; + + /*EEPROM5: IMX858 */ + eeprom_cam5: qcom,eeprom5 { + compatible = "qcom,eeprom"; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_suspend_rst0>; + gpios = <&tlmm 34 0>, + <&tlmm 32 0>, + <&tlmm 144 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK0", + "CAMIF_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <19200000>; + cell-index = <5>; + status = "okay"; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-camera.dtsi b/arch/arm64/boot/dts/qcom/shikra-camera.dtsi new file mode 100644 index 0000000000000..3b36b8a2e206d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-camera.dtsi @@ -0,0 +1,1189 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&soc { + cam_cpas: qcom,cam-cpas@5c11000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0x5c11000 0x0 0x1000>, + <0x0 0x5c13000 0x0 0x4000>; + reg-names = "cam_cpas_top", "cam_camnoc"; + reg-cam-base = <0x11000 0x13000>; + interrupts = ; + interrupt-names = "cpas_camnoc"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + clocks = <&gcc GCC_CAMSS_TOP_AHB_CLK>, + <&gcc GCC_CAMSS_TOP_AHB_CLK_SRC>, + <&gcc GCC_CAMSS_AXI_CLK>, + <&gcc GCC_CAMSS_AXI_CLK_SRC>, + <&gcc GCC_CAMSS_NRT_AXI_CLK>, + <&gcc GCC_CAMSS_RT_AXI_CLK>; + clock-names = "gcc_camss_top_ahb_clk", + "gcc_camss_top_ahb_clk_src", + "gcc_camss_axi_clk", + "gcc_camss_axi_clk_src", + "gcc_camss_nrt_axi_clk", + "gcc_camss_rt_axi_clk"; + clock-rates = <0 0 0 0 0 0>, + <0 19200000 0 19200000 0 0>, + <0 80000000 0 150000000 0 0>, + <0 80000000 0 200000000 0 0>, + <0 80000000 0 300000000 0 0>; + clock-cntl-level = "suspend", "lowsvs", "svs", + "svs_l1", "turbo"; + src-clock-name = "gcc_camss_axi_clk_src"; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnects = <&mem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmrt_virt MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI_CH0 0>, + <&mmnrt_virt MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI_CH0 0>; + interconnect-names = "cam_ahb", "cam_hf_0", "cam_sf_0"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 133333>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", + "lowsvs", "lowsvs", "svs", "svs_l1", "svs_l1", + "svs_l1", "nominal", "nominal", "nominal", + "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "cci0", + "csid0", "csid1", "tfe0", + "tfe1", "ope0", "cam-cdm-intf0", + "cpas-cdm0", "ope-cdm0"; + cell-index = <0>; + status = "okay"; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + + cpas_cdm0_all_rd: cpas-cdm0-all-rd { + cell-index = <0>; + node-name = "cpas-cdm0-all-rd"; + client-name = "cpas-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd_wr>; + }; + + ope_cdm0_all_rd: ope-cdm0-all-rd { + cell-index = <1>; + node-name = "ope-cdm0-all-rd"; + client-name = "ope-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_nrt0_rd_wr>; + }; + + ope0_all_rd: ope0-all-rd { + cell-index = <2>; + node-name = "ope0-all-rd"; + client-name = "ope0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_rd_wr>; + }; + + ope0_all_wr: ope0-all-wr { + cell-index = <3>; + node-name = "ope0-all-wr"; + client-name = "ope0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_nrt0_rd_wr>; + }; + + tfe0_all_wr: tfe0-all-wr { + cell-index = <4>; + node-name = "tfe0-all-wr"; + client-name = "tfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr>; + }; + + tfe1_all_wr: tfe1-all-wr { + cell-index = <5>; + node-name = "tfe1-all-wr"; + client-name = "tfe1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt0_wr>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_nrt0_rd_wr: level1-nrt0-rd-wr { + cell-index = <6>; + node-name = "level1-nrt0-rd-wr"; + parent-node = <&level2_nrt0_rd_wr_sum>; + traffic-merge-type = ; + }; + + level1_rt0_wr: level1-rt0-wr { + cell-index = <7>; + node-name = "level1-rt0-wr"; + parent-node = <&level2_rt0_rd_wr_sum>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + + level2_nrt0_rd_wr_sum: level2-nrt0-rd-wr-sum { + cell-index = <8>; + node-name = "level2-nrt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-name = "cam_sf_0"; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level2_rt0_rd_wr_sum: level2-rt0-rd-wr-sum { + cell-index = <9>; + node-name = "level2-rt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-name = "cam_hf_0"; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmpd_opp_turbo>; + }; + }; + }; + + cam_cci0: qcom,cci0@5c1b000 { + compatible = "qcom,cci", "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x5c1b000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x1b000>; + interrupts = ; + interrupt-names = "cci0"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + clocks = <&gcc GCC_CAMSS_CCI_CLK_SRC>, + <&gcc GCC_CAMSS_CCI_0_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clock-rates = <19200000 0>, + <37500000 0>; + clock-cntl-level = "lowsvs", "svs"; + src-clock-name = "cci_0_clk_src"; + operating-points-v2 = <&cci0_opp_table>; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + cell-index = <0>; + status = "okay"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmpd_opp_svs>; + }; + }; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cpas_cdm: qcom,cpas-cdm0@5c23000 { + compatible = "qcom,cam-cpas-cdm2_0"; + label = "cpas-cdm"; + reg = <0x0 0x5c23000 0x0 0x400>; + reg-names = "cpas-cdm0"; + reg-cam-base = <0x23000>; + interrupts = ; + interrupt-names = "cpas-cdm0"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + clocks = <&gcc GCC_CAMSS_TOP_AHB_CLK>; + clock-names = "cam_cc_cpas_top_ahb_clk"; + clock-rates = <19200000>, + <80000000>; + clock-cntl-level = "lowsvs", "svs"; + src-clock-name = "cam_cc_cpas_top_ahb_clk"; + operating-points-v2 = <&cpas_cdm_opp_table>; + cdm-client-names = "tfe0", "tfe1"; + config-fifo; + fifo-depths = <64 64 64 64>; + cell-index = <0>; + status = "okay"; + + cpas_cdm_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + }; + + }; + + cam_ope_cdm: qcom,ope-cdm0@5c42000 { + compatible = "qcom,cam-ope-cdm2_0"; + label = "ope-cdm"; + reg = <0x0 0x5c42000 0x0 0x400>; + reg-names = "ope-cdm0"; + reg-cam-base = <0x42000>; + interrupts = ; + interrupt-names = "ope-cdm0"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + clocks = <&gcc GCC_CAMSS_OPE_AHB_CLK>, + <&gcc GCC_CAMSS_OPE_CLK_SRC>, + <&gcc GCC_CAMSS_OPE_CLK>; + clock-names = "ope_ahb_clk", + "ope_clk_src", + "ope_clk"; + clock-rates = <19200000 19200000 19200000>, + <171428571 200000000 200000000>, + <171428571 266600000 266600000>, + <240000000 465000000 465000000>, + <240000000 580000000 580000000>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "turbo"; + src-clock-name = "ope_clk_src"; + cdm-client-names = "ope"; + operating-points-v2 = <&ope_cdm_opp_table>; + config-fifo; + fifo-depths = <64 64 64 64>; + cell-index = <0>; + status = "okay"; + + ope_cdm_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-266600000 { + opp-hz = /bits/ 64 <266600000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-465000000 { + opp-hz = /bits/ 64 <465000000>; + required-opps = <&rpmpd_opp_nom>; + }; + + opp-580000000 { + opp-hz = /bits/ 64 <580000000>; + required-opps = <&rpmpd_opp_turbo>; + }; + }; + }; + + ope: qcom,ope@5c42000 { + compatible = "qcom,ope"; + reg = <0x0 0x5c42000 0x0 0x400>, + <0x0 0x5c42400 0x0 0x200>, + <0x0 0x5c42600 0x0 0x200>, + <0x0 0x5c42800 0x0 0x4400>, + <0x0 0x5c46c00 0x0 0x190>, + <0x0 0x5c46d90 0x0 0xa00>; + reg-names = "ope_cdm", + "ope_top", + "ope_qos", + "ope_pp", + "ope_bus_rd", + "ope_bus_wr"; + reg-cam-base = <0x42000 0x42400 0x42600 0x42800 0x46c00 0x46d90>; + interrupts = ; + interrupt-names = "ope"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + clocks = <&gcc GCC_CAMSS_OPE_AHB_CLK_SRC>, + <&gcc GCC_CAMSS_OPE_AHB_CLK>, + <&gcc GCC_CAMSS_OPE_CLK_SRC>, + <&gcc GCC_CAMSS_OPE_CLK>; + clock-names = "ope_ahb_clk_src", + "ope_ahb_clk", + "ope_clk_src", + "ope_clk"; + clock-rates = <19200000 0 19200000 0>, + <171428571 0 200000000 0>, + <171428571 0 266600000 0>, + <240000000 0 465000000 0>, + <240000000 0 580000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", "turbo"; + src-clock-name = "ope_clk_src"; + operating-points-v2 = <&ope_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <1 0>; + cell-index = <0>; + status = "okay"; + + ope_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-266600000 { + opp-hz = /bits/ 64 <266600000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-465000000 { + opp-hz = /bits/ 64 <465000000>; + required-opps = <&rpmpd_opp_nom>; + }; + + opp-580000000 { + opp-hz = /bits/ 64 <580000000>; + required-opps = <&rpmpd_opp_turbo>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@5c52000 { + compatible = "qcom,csiphy-v2.0.0", "qcom,csiphy"; + reg = <0x0 0x5c52000 0x0 0x1000>; + reg-names = "csiphy"; + reg-cam-base = <0x52000>; + interrupts = ; + interrupt-names = "csiphy0"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + csi-vdd-1p2-supply = <&pm8150_l11>; + csi-vdd-1p8-supply = <&pm8150_l12>; + regulator-names = "csi-vdd-1p2", "csi-vdd-1p8"; + rgltr-cntrl-support; + rgltr-min-voltage = <1232000 1800000>; + rgltr-max-voltage = <1232000 1800000>; + rgltr-load-current = <1200000 300000>; + shared-clks = <1 0 0 0>; + clocks = <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, + <&gcc GCC_CAMSS_CPHY_0_CLK>, + <&gcc GCC_CAMSS_CSI0PHYTIMER_CLK_SRC>, + <&gcc GCC_CAMSS_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "csi0phytimer_clk_src"; + clock-cntl-level = "svs", "nominal", "turbo"; + clock-rates = <240000000 0 200000000 0>, + <341330000 0 268800000 0>, + <384000000 0 268800000 0>; + operating-points-v2 = <&csiphy0_opp_table>; + aggregator-rx; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-341330000 { + opp-hz = /bits/ 64 <341330000>; + required-opps = <&rpmpd_opp_nom>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_turbo>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@5c53000 { + compatible = "qcom,csiphy-v2.0.0", "qcom,csiphy"; + reg = <0x0 0x5c53000 0x0 0x1000>; + reg-names = "csiphy"; + reg-cam-base = <0x53000>; + interrupts = ; + interrupt-names = "csiphy1"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + csi-vdd-1p2-supply = <&pm8150_l11>; + csi-vdd-1p8-supply = <&pm8150_l12>; + regulator-names = "csi-vdd-1p2", "csi-vdd-1p8"; + rgltr-cntrl-support; + rgltr-min-voltage = <1232000 1800000>; + rgltr-max-voltage = <1232000 1800000>; + rgltr-load-current = <1200000 300000>; + shared-clks = <1 0 0 0>; + clocks = <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, + <&gcc GCC_CAMSS_CPHY_1_CLK>, + <&gcc GCC_CAMSS_CSI1PHYTIMER_CLK_SRC>, + <&gcc GCC_CAMSS_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "csi1phytimer_clk_src"; + clock-cntl-level = "svs", "nominal", "turbo"; + clock-rates = <240000000 0 200000000 0>, + <341330000 0 268800000 0>, + <384000000 0 268800000 0>; + operating-points-v2 = <&csiphy1_opp_table>; + aggregator-rx; + cell-index = <1>; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-341330000 { + opp-hz = /bits/ 64 <341330000>; + required-opps = <&rpmpd_opp_nom>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_turbo>; + }; + }; + }; + + cam_tfe_csid0: qcom,tfe-csid0@5c6e000 { + compatible = "qcom,csid530"; + reg = <0x0 0x5c6e000 0x0 0x1000>, + <0x0 0x5c11000 0x0 0x1000>, + <0x0 0x5c13000 0x0 0x4000>; + reg-names = "csid", "top", "camnoc"; + reg-cam-base = <0x6e000 0x11000 0x13000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + clocks = <&gcc GCC_CAMSS_TFE_0_CSID_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_0_CSID_CLK>, + <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>, + <&gcc GCC_CAMSS_TFE_0_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_0_CLK>; + clock-names = "tfe_csid_clk_src", + "tfe_csid_clk", + "cphy_rx_clk_src", + "tfe_cphy_rx_clk", + "tfe_clk_src", + "tfe_clk"; + clock-rates = <19200000 0 19200000 0 19200000 0>, + <240000000 0 240000000 0 256000000 0>, + <384000000 0 341333333 0 460800000 0>, + <426400000 0 384000000 0 576000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "tfe_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-426400000 { + opp-hz = /bits/ 64 <426400000>; + required-opps = <&rpmpd_opp_turbo>; + }; + }; + }; + + cam_tfe0: qcom,tfe0@5c6e000 { + compatible = "qcom,tfe530"; + reg = <0x0 0x5c6e000 0x0 0x5000>; + reg-names = "tfe0"; + reg-cam-base = <0x6e000>; + interrupts = ; + interrupt-names = "tfe0"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + clocks = <&gcc GCC_CAMSS_TFE_0_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_0_CLK>; + clock-names = "tfe_clk_src", + "tfe_clk"; + clock-rates = <19200000 0>, + <256000000 0>, + <460800000 0>, + <576000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "tfe_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <4>; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-256000000 { + opp-hz = /bits/ 64 <256000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-460800000 { + opp-hz = /bits/ 64 <460800000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-576000000 { + opp-hz = /bits/ 64 <576000000>; + required-opps = <&rpmpd_opp_turbo>; + }; + }; + }; + + cam_tfe_csid1: qcom,tfe-csid1@5c75000 { + compatible = "qcom,csid530"; + reg = <0x0 0x5c75000 0x0 0x1000>, + <0x0 0x5c11000 0x0 0x1000>, + <0x0 0x5c13000 0x0 0x4000>; + reg-names = "csid", "top", "camnoc"; + reg-cam-base = <0x75000 0x11000 0x13000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + clocks = <&gcc GCC_CAMSS_TFE_1_CSID_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_1_CSID_CLK>, + <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_1_CPHY_RX_CLK>, + <&gcc GCC_CAMSS_TFE_1_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_1_CLK>; + clock-names = "tfe_csid_clk_src", + "tfe_csid_clk", + "cphy_rx_clk_src", + "tfe_cphy_rx_clk", + "tfe_clk_src", + "tfe_clk"; + clock-rates = <19200000 0 19200000 0 19200000 0>, + <240000000 0 240000000 0 256000000 0>, + <384000000 0 341333333 0 460800000 0>, + <426400000 0 384000000 0 576000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "tfe_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-426400000 { + opp-hz = /bits/ 64 <426400000>; + required-opps = <&rpmpd_opp_turbo>; + }; + }; + }; + + cam_tfe1: qcom,tfe1@5c75000 { + compatible = "qcom,tfe530"; + reg = <0x0 0x5c75000 0x0 0x5000>; + reg-names = "tfe1"; + reg-cam-base = <0x75000>; + interrupts = ; + interrupt-names = "tfe1"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + clocks = <&gcc GCC_CAMSS_TFE_1_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_1_CLK>; + clock-names = "tfe_clk_src", + "tfe_clk"; + clock-rates = <19200000 0>, + <256000000 0>, + <460800000 0>, + <576000000 0>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "tfe_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <5>; + cell-index = <1>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-256000000 { + opp-hz = /bits/ 64 <256000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-460800000 { + opp-hz = /bits/ 64 <460800000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-576000000 { + opp-hz = /bits/ 64 <576000000>; + required-opps = <&rpmpd_opp_turbo>; + }; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + label = "cam-cdm-intf"; + num-hw-cdm = <2>; + cdm-client-names = "vfe"; + cell-index = <0>; + status = "okay"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "tfe"; + status = "okay"; + }; + + qcom,cam-ope { + compatible = "qcom,cam-ope"; + compat-hw-name = "qcom,ope"; + num-ope = <1>; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + + msm-cam-smmu-cpas-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x600 0x000>; + cam-smmu-label = "cpas-cdm"; + qcom,iommu-faults = "non-fatal"; + qcom,iommu-dma-addr-pool = <0x0 0x7400000 0x0 0xd8c00000>; + cpas_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ope { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x620 0x000>, + <&apps_smmu 0x640 0x000>; + qcom,iommu-faults = "non-fatal"; + multiple-client-devices; + qcom,iommu-dma-addr-pool = <0x0 0x7400000 0x0 0xd8c00000>; + cam-smmu-label = "ope", "ope-cdm"; + ope_iova_mem_map: iova-mem-map { + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + + msm-cam-smmu-tfe { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x400 0x000>; + qcom,iommu-faults = "non-fatal"; + qcom,iommu-dma-addr-pool = <0x0 0x7400000 0x0 0xd8c00000>; + cam-smmu-label = "tfe"; + tfe_iova_mem_map: iova-mem-map { + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0xd8c00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,camera { + compatible = "qcom,camera_shikra"; + status = "okay"; + }; +}; + +&tlmm { + cam_sensor_active_rst0: cam-sensor-active-rst0 { + mux { + pins = "gpio32"; + function = "gpio"; + }; + + config { + pins = "gpio32"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst1: cam-sensor-active-rst1 { + mux { + pins = "gpio33"; + function = "gpio"; + }; + + config { + pins = "gpio33"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + mux { + pins = "gpio34"; + function = "cam_mclk"; + }; + + config { + pins = "gpio34"; + bias-disable; + drive-strength = <2>; + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + mux { + pins = "gpio34"; + function = "cam_mclk"; + }; + + config { + pins = "gpio34"; + bias-pull-down; + drive-strength = <2>; + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + mux { + pins = "gpio35"; + function = "cam_mclk"; + }; + + config { + pins = "gpio35"; + bias-disable; + drive-strength = <2>; + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + mux { + pins = "gpio35"; + function = "cam_mclk"; + }; + + config { + pins = "gpio35"; + bias-pull-down; + drive-strength = <2>; + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + + config { + pins = "gpio96"; + bias-disable; + drive-strength = <2>; + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + mux { + pins = "gpio96"; + function = "cam_mclk"; + }; + + config { + pins = "gpio96"; + bias-pull-down; + drive-strength = <2>; + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + + config { + pins = "gpio98"; + bias-disable; + drive-strength = <2>; + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + mux { + pins = "gpio98"; + function = "cam_mclk"; + }; + + config { + pins = "gpio98"; + bias-pull-down; + drive-strength = <2>; + }; + }; + + cam_sensor_suspend_rst0: cam-sensor-suspend-rst0 { + mux { + pins = "gpio32"; + function = "gpio"; + }; + + config { + pins = "gpio32"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_suspend_rst1: cam-sensor-suspend-rst1 { + mux { + pins = "gpio33"; + function = "gpio"; + }; + + config { + pins = "gpio33"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cci_i2c_scl0_active: cci-i2c-scl0-active { + mux { + pins = "gpio37"; + function = "cci_i2c0"; + }; + + config { + pins = "gpio37"; + bias-pull-up; + drive-strength = <2>; + qcom,i2c_pull; + }; + }; + + cci_i2c_scl0_suspend: cci-i2c-scl0-suspend { + mux { + pins = "gpio37"; + function = "cci_i2c0"; + }; + + config { + pins = "gpio37"; + bias-pull-down; + drive-strength = <2>; + }; + }; + + cci_i2c_scl1_active: cci-i2c-scl1-active { + mux { + pins = "gpio42"; + function = "cci_i2c1"; + }; + + config { + pins = "gpio42"; + bias-pull-up; + drive-strength = <2>; + qcom,i2c_pull; + }; + }; + + cci_i2c_scl1_suspend: cci-i2c-scl1-suspend { + mux { + pins = "gpio42"; + function = "cci_i2c1"; + }; + + config { + pins = "gpio42"; + bias-pull-down; + drive-strength = <2>; + }; + }; + + cci_i2c_sda0_active: cci-i2c-sda0-active { + mux { + pins = "gpio36"; + function = "cci_i2c0"; + }; + + config { + pins = "gpio36"; + bias-pull-up; + drive-strength = <2>; + qcom,i2c_pull; + }; + }; + + cci_i2c_sda0_suspend: cci-i2c-sda0-suspend { + mux { + pins = "gpio36"; + function = "cci_i2c0"; + }; + + config { + pins = "gpio36"; + bias-pull-down; + drive-strength = <2>; + }; + }; + + cci_i2c_sda1_active: cci-i2c-sda1-active { + mux { + pins = "gpio41"; + function = "cci_i2c1"; + }; + + config { + pins = "gpio41"; + bias-pull-up; + drive-strength = <2>; + qcom,i2c_pull; + }; + }; + + cci_i2c_sda1_suspend: cci-i2c-sda1-suspend { + mux { + pins = "gpio41"; + function = "cci_i2c1"; + }; + + config { + pins = "gpio41"; + bias-pull-down; + drive-strength = <2>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk-camx.dtso b/arch/arm64/boot/dts/qcom/shikra-cqm-evk-camx.dtso new file mode 100644 index 0000000000000..a5d55b646470d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk-camx.dtso @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "shikra-camera.dtsi" +#include "shikra-camera-sensor.dtsi" + +&cam_csiphy0 { + csi-vdd-1p2-supply = <&pm4125_l5>; + csi-vdd-1p8-supply = <&pm4125_l13>; +}; + +&cam_csiphy1 { + csi-vdd-1p2-supply = <&pm4125_l5>; + csi-vdd-1p8-supply = <&pm4125_l13>; +}; + +&camss { + status = "disabled"; +}; + +&cci { + status = "disabled"; +}; + +&cci_i2c1 { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk-camx.dtso b/arch/arm64/boot/dts/qcom/shikra-cqs-evk-camx.dtso new file mode 100644 index 0000000000000..a5d55b646470d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk-camx.dtso @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "shikra-camera.dtsi" +#include "shikra-camera-sensor.dtsi" + +&cam_csiphy0 { + csi-vdd-1p2-supply = <&pm4125_l5>; + csi-vdd-1p8-supply = <&pm4125_l13>; +}; + +&cam_csiphy1 { + csi-vdd-1p2-supply = <&pm4125_l5>; + csi-vdd-1p8-supply = <&pm4125_l13>; +}; + +&camss { + status = "disabled"; +}; + +&cci { + status = "disabled"; +}; + +&cci_i2c1 { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso new file mode 100644 index 0000000000000..af65f786f6e2a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "shikra-camera.dtsi" +#include "shikra-camera-sensor.dtsi" + +&actuator_cam0 { + cam_vaf-supply = <&pm8150_s4>; +}; + +&actuator_cam1 { + cam_vaf-supply = <&pm8150_s4>; +}; + +&actuator_cam2 { + cam_vaf-supply = <&pm8150_s4>; +}; + +&actuator_cam5 { + cam_vaf-supply = <&pm8150_s4>; +}; + +&camss { + status = "disabled"; +}; + +&cci { + status = "disabled"; +}; + +&cci_i2c1 { + status = "disabled"; +}; + +&eeprom_cam0 { + cam_vio-supply = <&pm8150_s4>; + gpios = <&tlmm 34 0>, + <&tlmm 32 0>, + <&tlmm 56 0>; +}; + +&eeprom_cam1 { + cam_vio-supply = <&pm8150_s4>; + gpios = <&tlmm 35 0>, + <&tlmm 33 0>, + <&tlmm 64 0>; +}; + +&eeprom_cam2 { + cam_vio-supply = <&pm8150_s4>; + gpios = <&tlmm 35 0>, + <&tlmm 33 0>, + <&tlmm 64 0>; +}; + +&eeprom_cam5 { + cam_vio-supply = <&pm8150_s4>; + gpios = <&tlmm 34 0>, + <&tlmm 32 0>, + <&tlmm 56 0>; +}; + +&sensor_cam0 { + cam_vio-supply = <&pm8150_s4>; + gpios = <&tlmm 34 0>, + <&tlmm 32 0>, + <&tlmm 56 0>; +}; + +&sensor_cam1 { + cam_vio-supply = <&pm8150_s4>; + gpios = <&tlmm 35 0>, + <&tlmm 33 0>, + <&tlmm 64 0>; +}; + +&sensor_cam2 { + cam_vio-supply = <&pm8150_s4>; + gpios = <&tlmm 35 0>, + <&tlmm 33 0>, + <&tlmm 64 0>; +}; + +&sensor_cam3 { + cam_vio-supply = <&pm8150_s4>; +}; + +&sensor_cam4 { + cam_vio-supply = <&pm8150_s4>; +}; + +&sensor_cam5 { + cam_vio-supply = <&pm8150_s4>; + gpios = <&tlmm 34 0>, + <&tlmm 32 0>, + <&tlmm 56 0>; +}; From 36adf9e25ae95db96cae1b105edb2a8fb57f343b Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Fri, 11 Sep 2026 21:08:48 +0530 Subject: [PATCH 0765/1133] QCLINUX : arm64: dts: qcom: Remove sa8775p-ride composite DTB rules sa8775p-ride.dts and sa8775p-ride-r3.dts do not exist in the tree, removed as part of https://github.com/qualcomm-linux/kernel/commit/921f145639e4 Remove the composite-DTB rules and their dtb-y install entries. Signed-off-by: Salendarsingh Gaud --- arch/arm64/boot/dts/qcom/Makefile | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 5025a7692b2f9..1c5425fdf6462 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -633,30 +633,8 @@ qcs9100-ride-r3-camx-dtbs:= qcs9100-ride-r3.dtb sa8775p-ride-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3-camx.dtb -sa8775p-ride-camx-dtbs:= sa8775p-ride.dtb sa8775p-ride-camx.dtbo - -dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-camx.dtbo -sa8775p-ride-r3-camx-dtbs:= sa8775p-ride-r3.dtb sa8775p-ride-camx.dtbo - -dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride-r3-camx.dtb - -shikra-cqs-evk-camx-dtbs := shikra-cqs-evk.dtb shikra-cqs-evk-camx.dtbo - -dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-camx.dtb -dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-camx.dtbo - -shikra-cqm-evk-camx-dtbs := shikra-cqm-evk.dtb shikra-cqs-evk-camx.dtbo - -dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-camx.dtb -dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-camx.dtbo - -shikra-iqs-evk-camx-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-camx.dtbo - -dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-camx.dtb -dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-camx.dtbo - talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb From 74f6130161dbe59a4794ddec3b0334482d579a68 Mon Sep 17 00:00:00 2001 From: Tharik Anwar Date: Fri, 24 Jul 2026 15:23:07 +0530 Subject: [PATCH 0766/1133] QCLINUX: arm64: dts: qcom: Add Camera DT changes for Talos Lyra EVK Add IMX858 and OV13B10 camera support for Talos Lyra EVK over the three CSI ports available on the board. Moving entries at the end to avoid conflicts in Makefile. Signed-off-by: Tharik Anwar Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/Makefile | 3 + .../boot/dts/qcom/talos-camera-lyra-evk.dtsi | 128 +++++ .../qcom/talos-camera-sensor-lyra-evk.dtsi | 502 ++++++++++++++++++ .../boot/dts/qcom/talos-lyra-evk-camx.dtso | 17 + 4 files changed, 650 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/talos-camera-lyra-evk.dtsi create mode 100644 arch/arm64/boot/dts/qcom/talos-camera-sensor-lyra-evk.dtsi create mode 100644 arch/arm64/boot/dts/qcom/talos-lyra-evk-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 1c5425fdf6462..e180932d90f32 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -640,6 +640,9 @@ talos-evk-camx-dtbs := talos-evk.dtb talos-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtb dtb-$(CONFIG_ARCH_QCOM) += talos-evk-camx.dtbo +talos-lyra-evk-camx-dtbs := talos-lyra-evk.dtb talos-lyra-evk-camx.dtbo +dtb-$(CONFIG_ARCH_QCOM) += talos-lyra-evk-camx.dtb + dtb-$(CONFIG_ARCH_QCOM) += talos-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += talos-evk-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/talos-camera-lyra-evk.dtsi b/arch/arm64/boot/dts/qcom/talos-camera-lyra-evk.dtsi new file mode 100644 index 0000000000000..3eef6e070af4c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-camera-lyra-evk.dtsi @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +&tlmm { + cam-sensor-active-rst0 { + /* RESET */ + mux { + pins = "gpio40"; + }; + + config { + pins = "gpio40"; + }; + }; + + cam-sensor-active-rst1 { + /* RESET */ + mux { + pins = "gpio54"; + }; + + config { + pins = "gpio54"; + }; + }; + + cam-sensor-active-rst2 { + /* RESET */ + mux { + pins = "gpio42"; + }; + + config { + pins = "gpio42"; + }; + }; + + cam-sensor-suspend-rst0 { + /* RESET */ + mux { + pins = "gpio40"; + }; + + config { + pins = "gpio40"; + }; + }; + + cam-sensor-suspend-rst1 { + /* RESET */ + mux { + pins = "gpio54"; + }; + + config { + pins = "gpio54"; + }; + }; + + cam-sensor-suspend-rst2 { + /* RESET */ + mux { + pins = "gpio42"; + }; + + config { + pins = "gpio42"; + }; + }; + + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* MCLK */ + mux { + pins = "gpio28"; + function = "cam_mclk"; + }; + + config { + pins = "gpio28"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK */ + mux { + pins = "gpio29"; + function = "cam_mclk"; + }; + + config { + pins = "gpio29"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* MCLK */ + mux { + pins = "gpio28"; + function = "cam_mclk"; + }; + + config { + pins = "gpio28"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK */ + mux { + pins = "gpio29"; + function = "cam_mclk"; + }; + + config { + pins = "gpio29"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/talos-camera-sensor-lyra-evk.dtsi b/arch/arm64/boot/dts/qcom/talos-camera-sensor-lyra-evk.dtsi new file mode 100644 index 0000000000000..0e3e41a365e9e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-camera-sensor-lyra-evk.dtsi @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci { + /*ACTUATOR0: OV13B10*/ + actuator_cam4: qcom,actuator4 { + cell-index = <4>; + compatible = "qcom,actuator"; + cci-master = <0>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + status = "okay"; + }; + + /*EEPROM0: OV13B10*/ + eeprom_cam4: qcom,eeprom4 { + cell-index = <4>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_suspend_rst0>; + gpios = <&tlmm 28 0>, <&tlmm 40 0>, <&expander1 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK4", "CAMIF_RESET4", "CAM_CUSTOM4"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + }; + + /*CAM0: OV13B10*/ + tl_slot4: qcom,cam-sensor4 { + cell-index = <4>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam4>; + actuator-src = <&actuator_cam4>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_suspend_rst0>; + gpios = <&tlmm 28 0>, <&tlmm 40 0>, <&expander1 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK4", "CAMIF_RESET4", "CAM_CUSTOM4"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + }; + + /*ACTUATOR1: OV13B10*/ + actuator_cam5: qcom,actuator5 { + cell-index = <5>; + compatible = "qcom,actuator"; + cci-master = <1>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + status = "okay"; + }; + + /*EEPROM1: OV13B10*/ + eeprom_cam5: qcom,eeprom5 { + cell-index = <5>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_suspend_rst1>; + gpios = <&tlmm 29 0>, <&tlmm 54 0>, <&expander1 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK5", "CAMIF_RESET5", "CAM_CUSTOM5"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + }; + + /*CAM1: OV13B10*/ + tl_slot5: qcom,cam-sensor5 { + cell-index = <5>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam5>; + actuator-src = <&actuator_cam5>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_suspend_rst1>; + gpios = <&tlmm 29 0>, <&tlmm 54 0>, <&expander1 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK5", "CAMIF_RESET5", "CAM_CUSTOM5"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + }; + + /*ACTUATOR2: OV13B10*/ + actuator_cam6: qcom,actuator6 { + cell-index = <6>; + compatible = "qcom,actuator"; + cci-master = <1>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + status = "okay"; + }; + + /*EEPROM2: OV13B10*/ + eeprom_cam6: qcom,eeprom6 { + cell-index = <6>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_active &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend &cam_sensor_suspend_rst2>; + gpios = <&tlmm 30 0>, <&tlmm 42 0>, <&expander1 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK6", "CAMIF_RESET6", "CAM_CUSTOM6"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + }; + + /*CAM2: OV13B10*/ + tl_slot6: qcom,cam-sensor6 { + cell-index = <6>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam6>; + actuator-src = <&actuator_cam6>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_active &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend &cam_sensor_suspend_rst2>; + gpios = <&tlmm 30 0>, <&tlmm 42 0>, <&expander1 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK6", "CAMIF_RESET6", "CAM_CUSTOM6"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + }; + + /*ACTUATOR3: IMX858*/ + actuator_cam7: qcom,actuator7 { + cell-index = <7>; + compatible = "qcom,actuator"; + cci-master = <0>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + status = "okay"; + }; + + /*EEPROM3: IMX858*/ + eeprom_cam7: qcom,eeprom7 { + cell-index = <7>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_suspend_rst0>; + gpios = <&tlmm 28 0>, <&tlmm 40 0>, <&expander1 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK7", "CAMIF_RESET7", "CAM_CUSTOM7"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <19200000>; + status = "okay"; + }; + + /*CAM3: IMX858*/ + tl_slot7: qcom,cam-sensor7 { + cell-index = <7>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam7>; + actuator-src = <&actuator_cam7>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_suspend_rst0>; + gpios = <&tlmm 28 0>, <&tlmm 40 0>, <&expander1 0 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK7", "CAMIF_RESET7", "CAM_CUSTOM7"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <19200000>; + status = "okay"; + }; + + /*ACTUATOR4: IMX858*/ + actuator_cam8: qcom,actuator8 { + cell-index = <8>; + compatible = "qcom,actuator"; + cci-master = <1>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + status = "okay"; + }; + + /*EEPROM4: IMX858*/ + eeprom_cam8: qcom,eeprom8 { + cell-index = <8>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_suspend_rst1>; + gpios = <&tlmm 29 0>, <&tlmm 54 0>, <&expander1 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK8", "CAMIF_RESET8", "CAM_CUSTOM8"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <19200000>; + status = "okay"; + }; + + /*CAM4: IMX858*/ + tl_slot8: qcom,cam-sensor8 { + cell-index = <8>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam8>; + actuator-src = <&actuator_cam8>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_suspend_rst1>; + gpios = <&tlmm 29 0>, <&tlmm 54 0>, <&expander1 1 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK8", "CAMIF_RESET8", "CAM_CUSTOM8"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <19200000>; + status = "okay"; + }; + + /*ACTUATOR5: IMX858*/ + actuator_cam9: qcom,actuator9 { + cell-index = <9>; + compatible = "qcom,actuator"; + cci-master = <1>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + status = "okay"; + }; + + /*EEPROM5: IMX858*/ + eeprom_cam9: qcom,eeprom9 { + cell-index = <9>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_active &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend &cam_sensor_suspend_rst2>; + gpios = <&tlmm 30 0>, <&tlmm 42 0>, <&expander1 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK9", "CAMIF_RESET9", "CAM_CUSTOM9"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <19200000>; + status = "okay"; + }; + + /*CAM5: IMX858*/ + tl_slot9: qcom,cam-sensor9 { + cell-index = <9>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + eeprom-src = <&eeprom_cam9>; + actuator-src = <&actuator_cam9>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <4000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_active &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend &cam_sensor_suspend_rst2>; + gpios = <&tlmm 30 0>, <&tlmm 42 0>, <&expander1 2 0>; + gpio-reset = <1>; + gpio-custom1 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAM_MCLK9", "CAMIF_RESET9", "CAM_CUSTOM9"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <19200000>; + status = "okay"; + }; +}; + +&soc { + vreg_campin: regulator-dbb1 { + compatible = "regulator-fixed"; + regulator-name = "vreg_campin"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/talos-lyra-evk-camx.dtso b/arch/arm64/boot/dts/qcom/talos-lyra-evk-camx.dtso new file mode 100644 index 0000000000000..98cd84ee831e7 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/talos-lyra-evk-camx.dtso @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "talos-camera.dtsi" +#include "talos-camera-lyra-evk.dtsi" +#include "talos-camera-sensor-lyra-evk.dtsi" From 94596cd2f677d6cfd02ad3cdc7f6ded8cae4dd19 Mon Sep 17 00:00:00 2001 From: Tharik Anwar Date: Wed, 12 Aug 2026 18:37:32 +0530 Subject: [PATCH 0767/1133] QCLINUX: arm64: dts: qcom: Add IMX577 Camera DT changes for Talos Lyra EVK Add IMX577 camera support for Talos Lyra EVK over the three CSI ports available on the board. Signed-off-by: Tharik Anwar --- .../qcom/talos-camera-sensor-lyra-evk.dtsi | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/talos-camera-sensor-lyra-evk.dtsi b/arch/arm64/boot/dts/qcom/talos-camera-sensor-lyra-evk.dtsi index 0e3e41a365e9e..5821c76584cb4 100644 --- a/arch/arm64/boot/dts/qcom/talos-camera-sensor-lyra-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/talos-camera-sensor-lyra-evk.dtsi @@ -485,6 +485,102 @@ clock-rates = <19200000>; status = "okay"; }; + + /*CAM6: IMX577*/ + tl_slot10: qcom,cam-sensor10 { + cell-index = <10>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_suspend_rst0>; + gpios = <&tlmm 28 0>, <&tlmm 40 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK10", "CAMIF_RESET10"; + cci-master = <0>; + clocks = <&camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + }; + + /*CAM7: IMX577*/ + tl_slot11: qcom,cam-sensor11 { + cell-index = <11>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk1_active &cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_suspend_rst1>; + gpios = <&tlmm 29 0>, <&tlmm 54 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK11", "CAMIF_RESET11"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + }; + + /*CAM8: IMX577*/ + tl_slot12: qcom,cam-sensor12 { + cell-index = <12>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_s4a>; + regulator-names = "cam_vio"; + power-domains = <&camcc TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-0 = <&cam_sensor_mclk2_active &cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_mclk2_suspend &cam_sensor_suspend_rst2>; + gpios = <&tlmm 30 0>, <&tlmm 42 0>; + gpio-reset = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <1 0>; + gpio-req-tbl-label = "CAM_MCLK12", "CAMIF_RESET12"; + cci-master = <1>; + clocks = <&camcc CAM_CC_MCLK2_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + }; }; &soc { From 76ac2402de64c37619b659fafa56a86363f50f7d Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Fri, 7 Aug 2026 23:46:43 +0530 Subject: [PATCH 0768/1133] QCLINUX: arm64: dts: qcom: nord: Add camx DTBO overlays Add Makefile entries to build and install camera (camx) DTBO overlays for Nord RRD and RIDE SX board variants. Each composite DTB bundles the respective base platform DTB with the camx overlay, and registers both the merged .dtb and standalone .dtbo. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/Makefile | 10 + .../boot/dts/qcom/nord-camera-sensor.dtsi | 598 +++ arch/arm64/boot/dts/qcom/nord-camera.dtsi | 4550 +++++++++++++++++ .../dts/qcom/nord-ride-embedded-camx.dtso | 23 + arch/arm64/boot/dts/qcom/nord-rrd-camx.dtso | 23 + include/dt-bindings/camera/msm-camera.h | 12 + 6 files changed, 5216 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/nord-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/nord-ride-embedded-camx.dtso create mode 100644 arch/arm64/boot/dts/qcom/nord-rrd-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index e180932d90f32..e0d0b681741a1 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -591,6 +591,16 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-staging.dtbo +nord-ride-embedded-camx-dtbs := nord-ride-embedded.dtb nord-ride-embedded-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += nord-ride-embedded-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += nord-ride-embedded-camx.dtbo + +nord-rrd-camx-dtbs := nord-rrd.dtb nord-rrd-camx.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += nord-rrd-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += nord-rrd-camx.dtbo + purwa-evk-camx-dtbs := purwa-iot-evk.dtb purwa-evk-camx.dtbo dtb-$(CONFIG_ARCH_QCOM) += purwa-evk-camx.dtb diff --git a/arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi new file mode 100644 index 0000000000000..2b56d3e17a546 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi @@ -0,0 +1,598 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&cam_cci0 { + /* GMSL deserializer 0 */ + qcom,cam-gmsl-deserializer0 { + cell-index = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l8a_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&pmau0102_h_gpios 6 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET0"; + cci-master = <0>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <2>; + + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <3>; + + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <0>; + csiphy-sd-index = <0>; + status = "okay"; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <1>; + csiphy-sd-index = <0>; + status = "okay"; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <2>; + csiphy-sd-index = <0>; + status = "okay"; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* GMSL deserializer 0 sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <3>; + csiphy-sd-index = <0>; + status = "okay"; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; +}; + +&cam_cci1 { + /* GMSL deserializer 1 */ + qcom,cam-gmsl-deserializer1 { + cell-index = <1>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l8a_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&pmau0102_h_gpios 7 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET1"; + cci-master = <0>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <2>; + + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <3>; + + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <4>; + csiphy-sd-index = <1>; + status = "okay"; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <5>; + csiphy-sd-index = <1>; + status = "okay"; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <1>; + status = "okay"; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* GMSL deserializer 1 sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <1>; + status = "okay"; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + }; + }; +}; + +&cam_cci2 { + /* GMSL deserializer 2 */ + qcom,cam-gmsl-deserializer2 { + cell-index = <2>; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l8a_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&pmau0102_h_gpios 8 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + deser2_port0: endpoint { + remote-endpoint = <&gmsl_sensor8_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser2_port1: endpoint { + remote-endpoint = <&gmsl_sensor9_ep>; + }; + }; + + port@2 { + reg = <2>; + + deser2_port2: endpoint { + remote-endpoint = <&gmsl_sensor10_ep>; + }; + }; + + port@3 { + reg = <3>; + + deser2_port3: endpoint { + remote-endpoint = <&gmsl_sensor11_ep>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 0 */ + qcom,cam-gmsl-sensor8 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <2>; + status = "okay"; + + port { + gmsl_sensor8_ep: endpoint { + remote-endpoint = <&deser2_port0>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 1 */ + qcom,cam-gmsl-sensor9 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <2>; + status = "okay"; + + port { + gmsl_sensor9_ep: endpoint { + remote-endpoint = <&deser2_port1>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 2 */ + qcom,cam-gmsl-sensor10 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <2>; + status = "okay"; + + port { + gmsl_sensor10_ep: endpoint { + remote-endpoint = <&deser2_port2>; + }; + }; + }; + + /* GMSL deserializer 2 sensor 3 */ + qcom,cam-gmsl-sensor11 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <2>; + status = "okay"; + + port { + gmsl_sensor11_ep: endpoint { + remote-endpoint = <&deser2_port3>; + }; + }; + }; +}; + +&cam_cci3 { + /* GMSL deserializer 3 */ + qcom,cam-gmsl-deserializer3 { + cell-index = <3>; + csiphy-sd-index = <3>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l8a_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&pmau0102_h_gpios 9 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET3"; + cci-master = <0>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + deser3_port0: endpoint { + remote-endpoint = <&gmsl_sensor12_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser3_port1: endpoint { + remote-endpoint = <&gmsl_sensor13_ep>; + }; + }; + + port@2 { + reg = <2>; + + deser3_port2: endpoint { + remote-endpoint = <&gmsl_sensor14_ep>; + }; + }; + + port@3 { + reg = <3>; + + deser3_port3: endpoint { + remote-endpoint = <&gmsl_sensor15_ep>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 0 */ + qcom,cam-gmsl-sensor12 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <12>; + csiphy-sd-index = <3>; + status = "okay"; + + port { + gmsl_sensor12_ep: endpoint { + remote-endpoint = <&deser3_port0>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 1 */ + qcom,cam-gmsl-sensor13 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <13>; + csiphy-sd-index = <3>; + status = "okay"; + + port { + gmsl_sensor13_ep: endpoint { + remote-endpoint = <&deser3_port1>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 2 */ + qcom,cam-gmsl-sensor14 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <14>; + csiphy-sd-index = <3>; + status = "okay"; + + port { + gmsl_sensor14_ep: endpoint { + remote-endpoint = <&deser3_port2>; + }; + }; + }; + + /* GMSL deserializer 3 sensor 3 */ + qcom,cam-gmsl-sensor15 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <15>; + csiphy-sd-index = <3>; + status = "okay"; + + port { + gmsl_sensor15_ep: endpoint { + remote-endpoint = <&deser3_port3>; + }; + }; + }; +}; + +&cam_cci4 { + /* GMSL deserializer 4 */ + qcom,cam-gmsl-deserializer4 { + cell-index = <4>; + csiphy-sd-index = <4>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_l8a_1p8>; + regulator-names = "cam_vio"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + gpios = <&pmau0102_h_gpios 10 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET4"; + cci-master = <0>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + deser4_port0: endpoint { + remote-endpoint = <&gmsl_sensor16_ep>; + }; + }; + + port@1 { + reg = <1>; + + deser4_port1: endpoint { + remote-endpoint = <&gmsl_sensor17_ep>; + }; + }; + + port@2 { + reg = <2>; + + deser4_port2: endpoint { + remote-endpoint = <&gmsl_sensor18_ep>; + }; + }; + + port@3 { + reg = <3>; + + deser4_port3: endpoint { + remote-endpoint = <&gmsl_sensor19_ep>; + }; + }; + }; + + /* GMSL deserializer 4 sensor 0 */ + qcom,cam-gmsl-sensor16 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <16>; + csiphy-sd-index = <4>; + status = "okay"; + + port { + gmsl_sensor16_ep: endpoint { + remote-endpoint = <&deser4_port0>; + }; + }; + }; + + /* GMSL deserializer 4 sensor 1 */ + qcom,cam-gmsl-sensor17 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <17>; + csiphy-sd-index = <4>; + status = "okay"; + + port { + gmsl_sensor17_ep: endpoint { + remote-endpoint = <&deser4_port1>; + }; + }; + }; + + /* GMSL deserializer 4 sensor 2 */ + qcom,cam-gmsl-sensor18 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <18>; + csiphy-sd-index = <4>; + status = "okay"; + + port { + gmsl_sensor18_ep: endpoint { + remote-endpoint = <&deser4_port2>; + }; + }; + }; + + /* GMSL deserializer 4 sensor 3 */ + qcom,cam-gmsl-sensor19 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <19>; + csiphy-sd-index = <4>; + status = "okay"; + + port { + gmsl_sensor19_ep: endpoint { + remote-endpoint = <&deser4_port3>; + }; + }; + }; +}; + +&soc { + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/nord-camera.dtsi b/arch/arm64/boot/dts/qcom/nord-camera.dtsi new file mode 100644 index 0000000000000..9c00bb8954f30 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/nord-camera.dtsi @@ -0,0 +1,4550 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include + +&soc { + cam_cpas: qcom,cam-cpas@9a01000 { + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg = <0x0 0x9a01000 0x0 0x1000>, + <0x0 0x9a6b000 0x0 0x9680>, + <0x0 0x9a97000 0x0 0x9000>, + <0x0 0xbbf0000 0x0 0x2f00>; + reg-names = "cam_cpas_top", "cam_camnoc_nrt", "cam_camnoc_rt", "cam_rpmh"; + reg-cam-base = <0x1000 0x6b000 0x97000 0x0bbf0000>; + interrupts = , + ; + interrupt-names = "cpas_camnoc_nrt", "cpas_camnoc_rt"; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&nwgcc NW_GCC_CAMERA_HF_AXI_CLK>, + <&nwgcc NW_GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_TOP_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "nw_gcc_axi_hf_clk", + "nw_gcc_axi_sf_clk", + "cam_cc_slow_ahb_clk_src", + "cpas_ahb_clk", + "cpas_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_top_fast_ahb_clk", + "camnoc_rt_axi_clk_src", + "camnoc_rt_axi_clk", + "camnoc_nrt_axi_clk", + "cam_cc_qdss_debug_xo_clk"; + clock-rates = <0 0 0 0 0 0 0 0 0 0 0>, + <0 0 80000000 0 0 200000000 0 200000000 0 0 0>, + <0 0 80000000 0 0 300000000 0 400000000 0 0 0>, + <0 0 80000000 0 0 400000000 0 400000000 0 0 0>, + <0 0 80000000 0 0 400000000 0 400000000 0 0 0>, + <0 0 80000000 0 0 400000000 0 400000000 0 0 0>; + clock-cntl-level = "suspend", "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "camnoc_rt_axi_clk_src"; + clock-names-option = "cam_cc_icp_0_clk", + "cam_cc_icp_1_clk"; + clocks-option = <&camcc CAM_CC_ICP_0_CLK>, + <&camcc CAM_CC_ICP_1_CLK>; + clock-rates-option = <0 0 0>; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnects = <&hscnoc MASTER_APPSS_PROC 0 &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF 0 &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_RT_CDM_SF 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "cam_ahb", "cam_hf_0", "cam_sf_0", "cam_sf_icp", "cam_sf_cdm"; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, <0 76800>, <0 150000>, <0 150000>, + <0 300000>, <0 300000>, <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", "svs", "svs_l1", + "nominal", "nominal", "nominal", "turbo", "turbo"; + client-id-based; + client-names = "csiphy0", "csiphy1", "csiphy2", "csiphy3", "csiphy4", + "cci0", "cci1", "cci2", "cci3", "cci4", + "csid0", "csid1", "csid2", + "csid3", "csid4", "csid5", "csid6", + "csid7", "csid8", "csid9", "csid10", + "csid11", "csid12", + "ife0", "ife1", "ife2", + "ife3", "ife4", "ife5", "ife6", "ife7", + "ife8", "ife9", "ife10", "ife11", "ife12", + "ipe0", "ipe1", + "sfe0", "sfe1", "sfe2", + "cam-cdm-intf0", "rt-cdm0", "rt-cdm1", "rt-cdm2", + "rt-cdm3", "rt-cdm4", "icp0", "icp1", + "tpg17", "tpg18", "tpg19"; + enable-secure-qos-update = <1>; + cell-index = <0>; + status = "okay"; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + + camera-bus-nodes { + level0-nodes { + level-index = <0>; + icp0_all_rd: icp0-all-rd { + cell-index = <0>; + node-name = "icp0-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_icp_rd>; + }; + + icp1_all_rd: icp1-all-rd { + cell-index = <1>; + node-name = "icp1-all-rd"; + client-name = "icp1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level2_icp_rd>; + }; + + ife_0_ds_stats_wr: ife-0-ds-stats-wr { + cell-index = <2>; + node-name = "ife-0-ds-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_ife_ds_stats_main_ubwc_wr>; + }; + + ife_0_main_ubwc_wr: ife-0-main-ubwc-wr { + cell-index = <3>; + node-name = "ife-0-main-ubwc-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_ife_ds_stats_main_ubwc_wr>; + }; + + ife_0_rdi_pixel_raw_wr: ife-0-rdi-pixel-raw-wr { + cell-index = <4>; + node-name = "ife-0-rdi-pixel-raw-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt4_ife_rdi_pixel_raw_wr>; + }; + + ife_0_stats_wr: ife-0-stats-wr { + cell-index = <5>; + node-name = "ife-0-stats-wr"; + client-name = "ife0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt3_ife_stats_wr>; + }; + + ife_1_ds_stats_wr: ife-1-ds-stats-wr { + cell-index = <6>; + node-name = "ife-1-ds-stats-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_ife_ds_stats_main_ubwc_wr>; + }; + + ife_1_main_ubwc_wr: ife-1-main-ubwc-wr { + cell-index = <7>; + node-name = "ife-1-main-ubwc-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_ife_ds_stats_main_ubwc_wr>; + }; + + ife_1_rdi_pixel_raw_wr: ife-1-rdi-pixel-raw-wr { + cell-index = <8>; + node-name = "ife-1-rdi-pixel-raw-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt4_ife_rdi_pixel_raw_wr>; + }; + + ife_1_stats_wr: ife-1-stats-wr { + cell-index = <9>; + node-name = "ife-1-stats-wr"; + client-name = "ife1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt3_ife_stats_wr>; + }; + + ife_2_ds_stats_wr: ife-2-ds-stats-wr { + cell-index = <10>; + node-name = "ife-2-ds-stats-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_ife_ds_stats_main_ubwc_wr>; + }; + + ife_2_main_ubwc_wr: ife-2-main-ubwc-wr { + cell-index = <11>; + node-name = "ife-2-main-ubwc-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt1_ife_ds_stats_main_ubwc_wr>; + }; + + ife_2_rdi_pixel_raw_wr: ife-2-rdi-pixel-raw-wr { + cell-index = <12>; + node-name = "ife-2-rdi-pixel-raw-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt4_ife_rdi_pixel_raw_wr>; + }; + + ife_2_stats_wr: ife-2-stats-wr { + cell-index = <13>; + node-name = "ife-2-stats-wr"; + client-name = "ife2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt3_ife_stats_wr>; + }; + + ife_lite_0_rdi_wr: ife-lite-0-rdi-wr { + cell-index = <14>; + node-name = "ife-lite-0-rdi-wr"; + client-name = "ife3"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt4_ife_rdi_pixel_raw_wr>; + }; + + ife_lite_1_rdi_wr: ife-lite-1-rdi-wr { + cell-index = <15>; + node-name = "ife-lite-1-rdi-wr"; + client-name = "ife4"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt4_ife_rdi_pixel_raw_wr>; + }; + + ife_lite_2_rdi_wr: ife-lite-2-rdi-wr { + cell-index = <16>; + node-name = "ife-lite-2-rdi-wr"; + client-name = "ife5"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt4_ife_rdi_pixel_raw_wr>; + }; + + ife_lite_3_rdi_wr: ife-lite-3-rdi-wr { + cell-index = <17>; + node-name = "ife-lite-3-rdi-wr"; + client-name = "ife6"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt4_ife_rdi_pixel_raw_wr>; + }; + + ife_lite_4_rdi_wr: ife-lite-4-rdi-wr { + cell-index = <18>; + node-name = "ife-lite-4-rdi-wr"; + client-name = "ife7"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt4_ife_rdi_pixel_raw_wr>; + }; + + ife_lite_5_rdi_wr: ife-lite-5-rdi-wr { + cell-index = <19>; + node-name = "ife-lite-5-rdi-wr"; + client-name = "ife8"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt5_ife_lite_5_9_wr>; + }; + + ife_lite_6_rdi_wr: ife-lite-6-rdi-wr { + cell-index = <20>; + node-name = "ife-lite-6-rdi-wr"; + client-name = "ife9"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt5_ife_lite_5_9_wr>; + }; + + ife_lite_7_rdi_wr: ife-lite-7-rdi-wr { + cell-index = <21>; + node-name = "ife-lite-7-rdi-wr"; + client-name = "ife10"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt5_ife_lite_5_9_wr>; + }; + + ife_lite_8_rdi_wr: ife-lite-8-rdi-wr { + cell-index = <22>; + node-name = "ife-lite-8-rdi-wr"; + client-name = "ife11"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt5_ife_lite_5_9_wr>; + }; + + ife_lite_9_rdi_wr: ife-lite-9-rdi-wr { + cell-index = <23>; + node-name = "ife-lite-9-rdi-wr"; + client-name = "ife12"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt5_ife_lite_5_9_wr>; + }; + + ipe_0_all_rd: ipe-0-all-rd { + cell-index = <24>; + node-name = "ipe-0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_rd>; + }; + + ipe_0_all_wr: ipe-0-all-wr { + cell-index = <25>; + node-name = "ipe-0-all-wr"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_wr>; + }; + + ipe_1_all_rd: ipe-1-all-rd { + cell-index = <26>; + node-name = "ipe-1-all-rd"; + client-name = "ipe1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_rd>; + }; + + ipe_1_all_wr: ipe-1-all-wr { + cell-index = <27>; + node-name = "ipe-1-all-wr"; + client-name = "ipe1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level2_nrt_wr>; + }; + + rt_cdm0_all_rd: rt-cdm0-all-rd { + cell-index = <28>; + node-name = "rt-cdm0-all-rd"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt5_rd>; + }; + + rt_cdm1_all_rd: rt-cdm1-all-rd { + cell-index = <29>; + node-name = "rt-cdm1-all-rd"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt5_rd>; + }; + + rt_cdm2_all_rd: rt-cdm2-all-rd { + cell-index = <30>; + node-name = "rt-cdm2-all-rd"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt5_rd>; + }; + + rt_cdm3_all_rd: rt-cdm3-all-rd { + cell-index = <31>; + node-name = "rt-cdm3-all-rd"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt5_rd>; + }; + + rt_cdm4_all_rd: rt-cdm4-all-rd { + cell-index = <32>; + node-name = "rt-cdm4-all-rd"; + client-name = "rt-cdm4"; + traffic-data = ; + traffic-transaction-type = ; + parent-node = <&level1_rt5_rd>; + }; + + sfe_lite_0_rd_0: sfe-lite-0-rd-0 { + cell-index = <33>; + node-name = "sfe-lite-0-rd-0"; + client-name = "sfe0"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + + sfe_lite_1_rd_0: sfe-lite-1-rd-0 { + cell-index = <34>; + node-name = "sfe-lite-1-rd-0"; + client-name = "sfe1"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + + sfe_lite_2_rd_0: sfe-lite-2-rd-0 { + cell-index = <35>; + node-name = "sfe-lite-2-rd-0"; + client-name = "sfe2"; + traffic-data = ; + traffic-transaction-type = ; + constituent-paths = ; + parent-node = <&level1_rt_rd0>; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + level1_rt_rd0: level1-rt-rd0 { + cell-index = <36>; + node-name = "level1-rt-rd0"; + parent-node = <&level2_rt_rd>; + traffic-merge-type = ; + }; + + level1_rt1_ife_ds_stats_main_ubwc_wr: + level1-rt1-ife-ds-stats-main-ubwc-wr { + cell-index = <37>; + node-name = "level1-rt1-ife-ds-stats-main-ubwc-wr"; + parent-node = <&level2_rt_wr>; + traffic-merge-type = ; + }; + + level1_rt3_ife_stats_wr: level1-rt3-ife-stats-wr { + cell-index = <38>; + node-name = "level1-rt3-ife-stats-wr"; + parent-node = <&level2_rt_wr>; + traffic-merge-type = ; + }; + + level1_rt4_ife_rdi_pixel_raw_wr: level1-rt4-ife-rdi-pixel-raw-wr { + cell-index = <39>; + node-name = "level1-rt4-ife-rdi-pixel-raw-wr"; + parent-node = <&level2_rt_wr>; + traffic-merge-type = ; + }; + + level1_rt5_ife_lite_5_9_wr: level1-rt5-ife-lite-5-9-wr { + cell-index = <40>; + node-name = "level1-rt5-ife-lite-5-9-wr"; + parent-node = <&level2_rt_wr>; + traffic-merge-type = ; + }; + + level1_rt5_rd: level1-rt5-rd { + cell-index = <41>; + node-name = "level1-rt5-rd"; + parent-node = <&level2_cdm_rd>; + traffic-merge-type = ; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + level2_cdm_rd: level2-cdm-rd { + cell-index = <42>; + node-name = "level2-cdm-rd"; + parent-node = <&level3_cdm_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_icp_rd: level2-icp-rd { + cell-index = <43>; + node-name = "level2-icp-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type = ; + }; + + level2_nrt_rd: level2-nrt-rd { + cell-index = <44>; + node-name = "level2-nrt-rd"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_nrt_wr: level2-nrt-wr { + cell-index = <45>; + node-name = "level2-nrt-wr"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_rt_rd: level2-rt-rd { + cell-index = <46>; + node-name = "level2-rt-rd"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = + ; + }; + + level2_rt_wr: level2-rt-wr { + cell-index = <47>; + node-name = "level2-rt-wr"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type = + ; + }; + }; + + level3-nodes { + level-index = <3>; + level3_cdm_rd_wr_sum: level3-cdm-rd-wr-sum { + cell-index = <48>; + node-name = "level3-cdm-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_cdm"; + }; + }; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <49>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <50>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type = ; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + + level3_rt_rd_wr_sum: level3-rt-rd-wr-sum { + cell-index = <51>; + node-name = "level3-rt-rd-wr-sum"; + traffic-merge-type = ; + rt-axi-port; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + }; + }; + + }; + + cam_icp0: qcom,icp0@9a04000 { + compatible = "qcom,cam-icp_v3_0"; + reg = <0x0 0x9a04000 0x0 0x400>, + <0x0 0x9a04800 0x0 0x400>, + <0x0 0x9a07000 0x0 0x1000>; + reg-names = "icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x4000 0x4800 0x7000>; + interrupts = ; + interrupt-names = "icp0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_icp_1_mem>; + src-clock-name = "cam_cc_icp_0_clk_src"; + clocks = <&camcc CAM_CC_ICP_0_AHB_CLK>, + <&camcc CAM_CC_ICP_0_CLK_SRC>, + <&camcc CAM_CC_ICP_0_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "cam_cc_icp_0_ahb_clk", + "cam_cc_icp_0_clk_src", + "cam_cc_icp_0_clk", + "cam_cc_qdss_debug_xo_clk"; + clock-rates = <0 360000000 0 0>, + <0 480000000 0 0>, + <0 600000000 0 0>, + <0 600000000 0 0>, + <0 600000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + nrt-device; + fw_name = "qcom/nord/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x3f083 0x3f083>; + ubwc-ipe-write-cfg = <0x1620F 0x1620F>; + qos-val = <0xa0a>; + operating-points-v2 = <&icp_opp_table>; + icp-version = <0x0300>; + cam_hw_pid = <14>; + fw-pas-id = <33>; + cell-index = <0>; + status = "okay"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_icp1: qcom,icp1@9a14000 { + compatible = "qcom,cam-icp_v3_0"; + reg = <0x0 0x9a14000 0x0 0x400>, + <0x0 0x9a14800 0x0 0x400>, + <0x0 0x9a17000 0x0 0x1000>; + reg-names = "icp_csr", "icp_cirq", "icp_wd0"; + reg-cam-base = <0x14000 0x14800 0x17000>; + interrupts = ; + interrupt-names = "icp1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_icp_2_mem>; + src-clock-name = "cam_cc_icp_1_clk_src"; + clocks = <&camcc CAM_CC_ICP_1_AHB_CLK>, + <&camcc CAM_CC_ICP_1_CLK_SRC>, + <&camcc CAM_CC_ICP_1_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "cam_cc_icp_1_ahb_clk", + "cam_cc_icp_1_clk_src", + "cam_cc_icp_1_clk", + "cam_cc_qdss_debug_xo_clk"; + clock-rates = <0 360000000 0 0>, + <0 480000000 0 0>, + <0 600000000 0 0>, + <0 600000000 0 0>, + <0 600000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + nrt-device; + fw_name = "qcom/nord/CAMERA_ICP1"; + ubwc-ipe-fetch-cfg = <0x3f083 0x3f083>; + ubwc-ipe-write-cfg = <0x1620F 0x1620F>; + qos-val = <0xa0a>; + operating-points-v2 = <&icp1_opp_table>; + icp-version = <0x0300>; + cam_hw_pid = <15>; + cell-index = <1>; + status = "okay"; + + icp1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0@9a2b000 { + compatible = "qcom,cam-ipe"; + reg = <0x0 0x9a2b000 0x0 0x18000>; + reg-names = "ipe0_top"; + reg-cam-base = <0x2b000>; + power-domains = <&camcc CAM_CC_IPE_0_GDSC>; + src-clock-name = "cam_cc_ipe_0_clk_src"; + clocks = <&camcc CAM_CC_IPE_0_AHB_CLK>, + <&camcc CAM_CC_IPE_0_CLK>, + <&camcc CAM_CC_IPE_0_CLK_SRC>, + <&camcc CAM_CC_IPE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_TOP_IPE_0_CLK>; + clock-names = "cam_cc_ipe_0_ahb_clk", + "cam_cc_ipe_0_clk", + "cam_cc_ipe_0_clk_src", + "cam_cc_ipe_0_fast_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_top_ipe_0_clk"; + clock-rates = <0 0 360000000 0 200000000 0>, + <0 0 480000000 0 300000000 0>, + <0 0 650000000 0 400000000 0>, + <0 0 650000000 0 400000000 0>, + <0 0 650000000 0 400000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + operating-points-v2 = <&ipe0_opp_table>; + nrt-device; + cam_hw_pid = <3 7 14 15>; + cell-index = <0>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe1: qcom,ipe1@9a4b000 { + compatible = "qcom,cam-ipe"; + reg = <0x0 0x9a4b000 0x0 0x18000>; + reg-names = "ipe1_top"; + reg-cam-base = <0x4b000>; + power-domains = <&camcc CAM_CC_IPE_1_GDSC>; + src-clock-name = "cam_cc_ipe_1_clk_src"; + clocks = <&camcc CAM_CC_IPE_1_AHB_CLK>, + <&camcc CAM_CC_IPE_1_CLK>, + <&camcc CAM_CC_IPE_1_CLK_SRC>, + <&camcc CAM_CC_IPE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_TOP_IPE_1_CLK>; + clock-names = "cam_cc_ipe_1_ahb_clk", + "cam_cc_ipe_1_clk", + "cam_cc_ipe_1_clk_src", + "cam_cc_ipe_1_fast_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_top_ipe_1_clk"; + clock-rates = <0 0 360000000 0 200000000 0>, + <0 0 480000000 0 300000000 0>, + <0 0 650000000 0 400000000 0>, + <0 0 650000000 0 400000000 0>, + <0 0 650000000 0 400000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + operating-points-v2 = <&ipe1_opp_table>; + nrt-device; + cam_hw_pid = <3 7 14 15>; + cell-index = <1>; + status = "okay"; + + ipe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg17: qcom,tpg17@9a92000 { + compatible = "qcom,cam-tpg104"; + reg = <0x0 0x9a92000 0x0 0x400>, + <0x0 0x9a01000 0x0 0x1000>; + reg-names = "tpg0", "cam_cpas_top"; + reg-cam-base = <0x92000 0x1000>; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg0"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_TPG_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "tpg_csiphy_rx_clk"; + clock-rates = <300000000 0>, + <400000000 0>, + <480000000 0>, + <480000000 0>, + <480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <17>; + phy-id = <0>; + status = "okay"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg18: qcom,tpg18@9a93000 { + compatible = "qcom,cam-tpg104"; + reg = <0x0 0x9a93000 0x0 0x400>, + <0x0 0x9a01000 0x0 0x1000>; + reg-names = "tpg1", "cam_cpas_top"; + reg-cam-base = <0x93000 0x1000>; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg1"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_TPG_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "tpg_csiphy_rx_clk"; + clock-rates = <300000000 0>, + <400000000 0>, + <480000000 0>, + <480000000 0>, + <480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <18>; + phy-id = <1>; + status = "okay"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy_tpg19: qcom,tpg19@9a94000 { + compatible = "qcom,cam-tpg104"; + reg = <0x0 0x9a94000 0x0 0x400>, + <0x0 0x9a01000 0x0 0x1000>; + reg-names = "tpg2", "cam_cpas_top"; + reg-cam-base = <0x94000 0x1000>; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupts = ; + interrupt-names = "tpg2"; + shared-clks = <1 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_TPG_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "tpg_csiphy_rx_clk"; + clock-rates = <300000000 0>, + <400000000 0>, + <480000000 0>, + <480000000 0>, + <480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cphy_rx_clk_src"; + cell-index = <19>; + phy-id = <2>; + status = "okay"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe0: qcom,ife0@9ab1000 { + compatible = "qcom,vfe900"; + reg = <0x0 0x9ab1000 0x0 0x1c000>, + <0x0 0x9a6b000 0x0 0x9680>; + reg-names = "ife0", "cam_camnoc"; + reg-cam-base = <0xb1000 0x6b000>; + rt-wrapper-base = <0xb1000>; + interrupts = ; + interrupt-names = "ife0"; + power-domains = <&camcc CAM_CC_IFE_0_GDSC>; + clocks = <&camcc CAM_CC_IFE_0_MAIN_CLK>, + <&camcc CAM_CC_IFE_0_MAIN_CLK_SRC>, + <&camcc CAM_CC_IFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_PCP_CLK>, + <&camcc CAM_CC_IFE_0_PCP_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_SCALAR_CLK>, + <&camcc CAM_CC_IFE_0_SCALAR_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_0_TMC_CLK>, + <&camcc CAM_CC_IFE_0_TMC_FAST_AHB_CLK>, + <&camcc CAM_CC_TOP_IFE_0_CLK>; + clock-names = "cam_cc_ife_0_main_clk", + "cam_cc_ife_0_main_clk_src", + "cam_cc_ife_0_main_fast_ahb_clk", + "cam_cc_ife_0_pcp_clk", + "cam_cc_ife_0_pcp_fast_ahb_clk", + "cam_cc_ife_0_scalar_clk", + "cam_cc_ife_0_scalar_fast_ahb_clk", + "cam_cc_ife_0_tmc_clk", + "cam_cc_ife_0_tmc_fast_ahb_clk", + "cam_cc_top_ife_0_clk"; + clock-rates = <0 360000000 0 0 0 0 0 0 0 0>, + <0 480000000 0 0 0 0 0 0 0 0>, + <0 650000000 0 0 0 0 0 0 0 0>, + <0 650000000 0 0 0 0 0 0 0 0>, + <0 650000000 0 0 0 0 0 0 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_0_main_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <8 16>; + cell-index = <0>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe1: qcom,ife1@9ad1000 { + compatible = "qcom,vfe900"; + reg = <0x0 0x9ad1000 0x0 0x1c000>, + <0x0 0x9a6b000 0x0 0x9680>; + reg-names = "ife1", "cam_camnoc"; + reg-cam-base = <0xd1000 0x6b000>; + rt-wrapper-base = <0xb1000>; + interrupts = ; + interrupt-names = "ife1"; + power-domains = <&camcc CAM_CC_IFE_1_GDSC>; + clocks = <&camcc CAM_CC_IFE_1_MAIN_CLK>, + <&camcc CAM_CC_IFE_1_MAIN_CLK_SRC>, + <&camcc CAM_CC_IFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_PCP_CLK>, + <&camcc CAM_CC_IFE_1_PCP_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_SCALAR_CLK>, + <&camcc CAM_CC_IFE_1_SCALAR_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_TMC_CLK>, + <&camcc CAM_CC_IFE_1_TMC_FAST_AHB_CLK>, + <&camcc CAM_CC_TOP_IFE_1_CLK>; + clock-names = "cam_cc_ife_1_main_clk", + "cam_cc_ife_1_main_clk_src", + "cam_cc_ife_1_main_fast_ahb_clk", + "cam_cc_ife_1_pcp_clk", + "cam_cc_ife_1_pcp_fast_ahb_clk", + "cam_cc_ife_1_scalar_clk", + "cam_cc_ife_1_scalar_fast_ahb_clk", + "cam_cc_ife_1_tmc_clk", + "cam_cc_ife_1_tmc_fast_ahb_clk", + "cam_cc_top_ife_1_clk"; + clock-rates = <0 360000000 0 0 0 0 0 0 0 0>, + <0 480000000 0 0 0 0 0 0 0 0>, + <0 650000000 0 0 0 0 0 0 0 0>, + <0 650000000 0 0 0 0 0 0 0 0>, + <0 650000000 0 0 0 0 0 0 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_1_main_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <9 17>; + cell-index = <1>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe2: qcom,ife2@9af1000 { + compatible = "qcom,vfe900"; + reg = <0x0 0x9af1000 0x0 0x1c000>, + <0x0 0x9a6b000 0x0 0x9680>; + reg-names = "ife2", "cam_camnoc"; + reg-cam-base = <0xf1000 0x6b000>; + rt-wrapper-base = <0xb1000>; + interrupts = ; + interrupt-names = "ife2"; + power-domains = <&camcc CAM_CC_IFE_2_GDSC>; + clocks = <&camcc CAM_CC_IFE_2_MAIN_CLK>, + <&camcc CAM_CC_IFE_2_MAIN_CLK_SRC>, + <&camcc CAM_CC_IFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_2_PCP_CLK>, + <&camcc CAM_CC_IFE_2_PCP_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_2_SCALAR_CLK>, + <&camcc CAM_CC_IFE_2_SCALAR_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_2_TMC_CLK>, + <&camcc CAM_CC_IFE_2_TMC_FAST_AHB_CLK>, + <&camcc CAM_CC_TOP_IFE_2_CLK>; + clock-names = "cam_cc_ife_2_main_clk", + "cam_cc_ife_2_main_clk_src", + "cam_cc_ife_2_main_fast_ahb_clk", + "cam_cc_ife_2_pcp_clk", + "cam_cc_ife_2_pcp_fast_ahb_clk", + "cam_cc_ife_2_scalar_clk", + "cam_cc_ife_2_scalar_fast_ahb_clk", + "cam_cc_ife_2_tmc_clk", + "cam_cc_ife_2_tmc_fast_ahb_clk", + "cam_cc_top_ife_2_clk"; + clock-rates = <0 360000000 0 0 0 0 0 0 0 0>, + <0 480000000 0 0 0 0 0 0 0 0>, + <0 650000000 0 0 0 0 0 0 0 0>, + <0 650000000 0 0 0 0 0 0 0 0>, + <0 650000000 0 0 0 0 0 0 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_2_main_clk_src"; + operating-points-v2 = <&vfe2_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <10 18>; + cell-index = <2>; + status = "okay"; + + vfe2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid0: qcom,csid0@9b32000 { + compatible = "qcom,csid900"; + reg = <0x0 0x9b32000 0x0 0x5800>; + reg-names = "csid"; + reg-cam-base = <0x132000>; + rt-wrapper-base = <0xb1000>; + interrupts = ; + interrupt-names = "csid0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "csid_csiphy_rx_clk"; + clock-rates = <300000000 300000000 0 0>, + <400000000 400000000 0 0>, + <480000000 480000000 0 0>, + <480000000 480000000 0 0>, + <480000000 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid1: qcom,csid1@9b38800 { + compatible = "qcom,csid900"; + reg = <0x0 0x9b38800 0x0 0x5800>; + reg-names = "csid"; + reg-cam-base = <0x138800>; + rt-wrapper-base = <0xb1000>; + interrupts = ; + interrupt-names = "csid1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "csid_csiphy_rx_clk"; + clock-rates = <300000000 300000000 0 0>, + <400000000 400000000 0 0>, + <480000000 480000000 0 0>, + <480000000 480000000 0 0>, + <480000000 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid2: qcom,csid2@9b3f000 { + compatible = "qcom,csid900"; + reg = <0x0 0x9b3f000 0x0 0x5800>; + reg-names = "csid"; + reg-cam-base = <0x13f000>; + rt-wrapper-base = <0xb1000>; + interrupts = ; + interrupt-names = "csid2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-names = "cphy_rx_clk_src", + "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "csid_csiphy_rx_clk"; + clock-rates = <300000000 300000000 0 0>, + <400000000 400000000 0 0>, + <480000000 480000000 0 0>, + <480000000 480000000 0 0>, + <480000000 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid2_opp_table>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + csid2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe_lite0: qcom,sfe-lite0@9b4c000 { + compatible = "qcom,sfe-lite690"; + reg = <0x0 0x9b4c000 0x0 0x1000>; + reg-names = "sfe-lite0"; + reg-cam-base = <0x14c000>; + rt-wrapper-base = <0xb1000>; + interrupts = ; + interrupt-names = "sfe-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_0_CLK>, + <&camcc CAM_CC_TOP_SFE_LITE_0_CLK>; + clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", + "cam_cc_sfe_lite_0_clk", + "cam_cc_top_sfe_lite_0_clk"; + clock-rates = <0 360000000 0>, + <0 480000000 0>, + <0 650000000 0>, + <0 650000000 0>, + <0 650000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_sfe_lite_0_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table0>; + cam_hw_pid = <4>; + clock-control-debugfs = "true"; + cell-index = <0>; + status = "okay"; + + cam_sfe_lite_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe_lite1: qcom,sfe-lite1@9b4d000 { + compatible = "qcom,sfe-lite690"; + reg = <0x0 0x9b4d000 0x0 0x1000>; + reg-names = "sfe-lite1"; + reg-cam-base = <0x14d000>; + rt-wrapper-base = <0xb1000>; + interrupts = ; + interrupt-names = "sfe-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_1_CLK>, + <&camcc CAM_CC_TOP_SFE_LITE_1_CLK>; + clock-names = "cam_cc_sfe_lite_1_fast_ahb_clk", + "cam_cc_sfe_lite_1_clk", + "cam_cc_top_sfe_lite_1_clk"; + clock-rates = <0 360000000 0>, + <0 480000000 0>, + <0 650000000 0>, + <0 650000000 0>, + <0 650000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_sfe_lite_1_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table1>; + cam_hw_pid = <5>; + clock-control-debugfs = "true"; + cell-index = <1>; + status = "okay"; + + cam_sfe_lite_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe_lite2: qcom,sfe-lite2@9b4e000 { + compatible = "qcom,sfe-lite690"; + reg = <0x0 0x9b4e000 0x0 0x1000>; + reg-names = "sfe-lite2"; + reg-cam-base = <0x14e000>; + rt-wrapper-base = <0xb1000>; + interrupts = ; + interrupt-names = "sfe-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SFE_LITE_2_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_2_CLK>, + <&camcc CAM_CC_TOP_SFE_LITE_2_CLK>; + clock-names = "cam_cc_sfe_lite_2_fast_ahb_clk", + "cam_cc_sfe_lite_2_clk", + "cam_cc_top_sfe_lite_2_clk"; + clock-rates = <0 360000000 0>, + <0 480000000 0>, + <0 650000000 0>, + <0 650000000 0>, + <0 650000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_sfe_lite_2_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table2>; + cam_hw_pid = <6>; + clock-control-debugfs = "true"; + cell-index = <2>; + status = "okay"; + + cam_sfe_lite_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-360000000 { + opp-hz = /bits/ 64 <360000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_cci0: qcom,cci0@9b51000 { + compatible = "qcom,ccu-cci", "simple-bus"; + reg = <0x0 0x9b51000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x151000>; + interrupts = ; + interrupt-names = "CCI0"; + operating-points-v2 = <&cci0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>, + <&camcc CAM_CC_CCU_FAST_AHB_CLK>; + clock-names = "cci_0_clk_src", + "cci_0_clk", + "ccu_fast_ahb_clk"; + clock-rates = <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cci_0_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <0>; + status = "okay"; + + i2c_freq_custom_cci0: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci0: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_cci1: qcom,cci1@9b52000 { + compatible = "qcom,ccu-cci", "simple-bus"; + reg = <0x0 0x9b52000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x152000>; + interrupts = ; + interrupt-names = "CCI1"; + operating-points-v2 = <&cci1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>, + <&camcc CAM_CC_CCU_FAST_AHB_CLK>; + clock-names = "cci_1_clk_src", + "cci_1_clk", + "ccu_fast_ahb_clk"; + clock-rates = <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl2_active &cci_i2c_sda2_active>; + pinctrl-1 = <&cci_i2c_scl2_suspend &cci_i2c_sda2_suspend>; + pinctrl-2 = <&cci_i2c_scl3_active &cci_i2c_sda3_active>; + pinctrl-3 = <&cci_i2c_scl3_suspend &cci_i2c_sda3_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <1>; + status = "okay"; + + i2c_freq_custom_cci1: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci1: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_cci2: qcom,cci2@9b53000 { + compatible = "qcom,ccu-cci", "simple-bus"; + reg = <0x0 0x9b53000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x153000>; + interrupts = ; + interrupt-names = "CCI2"; + operating-points-v2 = <&cci2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_2_CLK_SRC>, + <&camcc CAM_CC_CCI_2_CLK>, + <&camcc CAM_CC_CCU_FAST_AHB_CLK>; + clock-names = "cci_2_clk_src", + "cci_2_clk", + "ccu_fast_ahb_clk"; + clock-rates = <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cci_2_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl4_active &cci_i2c_sda4_active>; + pinctrl-1 = <&cci_i2c_scl4_suspend &cci_i2c_sda4_suspend>; + pinctrl-2 = <&cci_i2c_scl5_active &cci_i2c_sda5_active>; + pinctrl-3 = <&cci_i2c_scl5_suspend &cci_i2c_sda5_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <2>; + status = "okay"; + + i2c_freq_custom_cci2: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci2: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci2: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci2: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + cci2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_cci3: qcom,cci3@9b54000 { + compatible = "qcom,ccu-cci", "simple-bus"; + reg = <0x0 0x9b54000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x154000>; + interrupts = ; + interrupt-names = "CCI3"; + operating-points-v2 = <&cci3_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_3_CLK_SRC>, + <&camcc CAM_CC_CCI_3_CLK>, + <&camcc CAM_CC_CCU_FAST_AHB_CLK>; + clock-names = "cci_3_clk_src", + "cci_3_clk", + "ccu_fast_ahb_clk"; + clock-rates = <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cci_3_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl6_active &cci_i2c_sda6_active>; + pinctrl-1 = <&cci_i2c_scl6_suspend &cci_i2c_sda6_suspend>; + pinctrl-2 = <&cci_i2c_scl7_active &cci_i2c_sda7_active>; + pinctrl-3 = <&cci_i2c_scl7_suspend &cci_i2c_sda7_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <3>; + status = "okay"; + + i2c_freq_custom_cci3: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci3: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci3: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci3: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + cci3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_cci4: qcom,cci4@9b55000 { + compatible = "qcom,ccu-cci", "simple-bus"; + reg = <0x0 0x9b55000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x155000>; + interrupts = ; + interrupt-names = "CCI4"; + operating-points-v2 = <&cci4_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CCI_4_CLK_SRC>, + <&camcc CAM_CC_CCI_4_CLK>, + <&camcc CAM_CC_CCU_FAST_AHB_CLK>; + clock-names = "cci_4_clk_src", + "cci_4_clk", + "ccu_fast_ahb_clk"; + clock-rates = <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>, + <37500000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cci_4_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-0 = <&cci_i2c_scl8_active &cci_i2c_sda8_active>; + pinctrl-1 = <&cci_i2c_scl8_suspend &cci_i2c_sda8_suspend>; + pinctrl-2 = <&cci_i2c_scl9_active &cci_i2c_sda9_active>; + pinctrl-3 = <&cci_i2c_scl9_suspend &cci_i2c_sda9_suspend>; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + cell-index = <4>; + status = "okay"; + + i2c_freq_custom_cci4: qcom,i2c-custom-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci4: qcom,i2c-fast-mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci4: qcom,i2c-fast-plus-mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_100Khz_cci4: qcom,i2c-standard-mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + cci4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0@9c32000 { + compatible = "qcom,csid-lite900"; + reg = <0x0 0x9c32000 0x0 0x2000>; + reg-names = "csid-lite0"; + reg-cam-base = <0x232000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "csid-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0>, + <0 400000000 0 0 400000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + clock-control-debugfs = "true"; + cell-index = <3>; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0@9c34000 { + compatible = "qcom,vfe-lite900"; + reg = <0x0 0x9c34000 0x0 0x1480>; + reg-names = "ife-lite0"; + reg-cam-base = <0x234000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "ife-lite0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_top_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0 0>, + <0 400000000 0 0 400000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <19>; + cell-index = <3>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1@9c37000 { + compatible = "qcom,csid-lite900"; + reg = <0x0 0x9c37000 0x0 0x2000>; + reg-names = "csid-lite1"; + reg-cam-base = <0x237000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "csid-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0>, + <0 400000000 0 0 400000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + clock-control-debugfs = "true"; + cell-index = <4>; + status = "okay"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1@9c39000 { + compatible = "qcom,vfe-lite900"; + reg = <0x0 0x9c39000 0x0 0x1480>; + reg-names = "ife-lite1"; + reg-cam-base = <0x239000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "ife-lite1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_top_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0 0>, + <0 400000000 0 0 400000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <20>; + cell-index = <4>; + status = "okay"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite2: qcom,csid-lite2@9c3c000 { + compatible = "qcom,csid-lite900"; + reg = <0x0 0x9c3c000 0x0 0x2000>; + reg-names = "csid-lite2"; + reg-cam-base = <0x23c000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "csid-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0>, + <0 400000000 0 0 400000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite2_opp_table>; + clock-control-debugfs = "true"; + cell-index = <5>; + status = "okay"; + + csid_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite2: qcom,ife-lite2@9c3e000 { + compatible = "qcom,vfe-lite900"; + reg = <0x0 0x9c3e000 0x0 0x1480>; + reg-names = "ife-lite2"; + reg-cam-base = <0x23e000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "ife-lite2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_top_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0 0>, + <0 400000000 0 0 400000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite2_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <21>; + cell-index = <5>; + status = "okay"; + + vfe_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite3: qcom,csid-lite3@9c41000 { + compatible = "qcom,csid-lite900"; + reg = <0x0 0x9c41000 0x0 0x2000>; + reg-names = "csid-lite3"; + reg-cam-base = <0x241000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "csid-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0>, + <0 400000000 0 0 400000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite3_opp_table>; + clock-control-debugfs = "true"; + cell-index = <6>; + status = "okay"; + + csid_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite3: qcom,ife-lite3@9c43000 { + compatible = "qcom,vfe-lite900"; + reg = <0x0 0x9c43000 0x0 0x1480>; + reg-names = "ife-lite3"; + reg-cam-base = <0x243000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "ife-lite3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_top_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0 0>, + <0 400000000 0 0 400000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite3_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <22>; + cell-index = <6>; + status = "okay"; + + vfe_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite4: qcom,csid-lite4@9c46000 { + compatible = "qcom,csid-lite900"; + reg = <0x0 0x9c46000 0x0 0x2000>; + reg-names = "csid-lite4"; + reg-cam-base = <0x246000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "csid-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0>, + <0 400000000 0 0 400000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite4_opp_table>; + clock-control-debugfs = "true"; + cell-index = <7>; + status = "okay"; + + csid_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite4: qcom,ife-lite4@9c48000 { + compatible = "qcom,vfe-lite900"; + reg = <0x0 0x9c48000 0x0 0x1480>; + reg-names = "ife-lite4"; + reg-cam-base = <0x248000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "ife-lite4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_top_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0 0>, + <0 400000000 0 0 400000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite4_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <23>; + cell-index = <7>; + status = "okay"; + + vfe_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite5: qcom,csid-lite5@9c4b000 { + compatible = "qcom,csid-lite900"; + reg = <0x0 0x9c4b000 0x0 0x2000>; + reg-names = "csid-lite5"; + reg-cam-base = <0x24b000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "csid-lite5"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0>, + <0 400000000 0 0 400000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite5_opp_table>; + clock-control-debugfs = "true"; + cell-index = <8>; + status = "okay"; + + csid_lite5_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite5: qcom,ife-lite5@9c4d000 { + compatible = "qcom,vfe-lite900"; + reg = <0x0 0x9c4d000 0x0 0x1480>; + reg-names = "ife-lite5"; + reg-cam-base = <0x24d000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "ife-lite5"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_top_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0 0>, + <0 400000000 0 0 400000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite5_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <24>; + cell-index = <8>; + status = "okay"; + + vfe_lite5_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite6: qcom,csid-lite6@9c50000 { + compatible = "qcom,csid-lite900"; + reg = <0x0 0x9c50000 0x0 0x2000>; + reg-names = "csid-lite6"; + reg-cam-base = <0x250000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "csid-lite6"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0>, + <0 400000000 0 0 400000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite6_opp_table>; + clock-control-debugfs = "true"; + cell-index = <9>; + status = "okay"; + + csid_lite6_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite6: qcom,ife-lite6@9c52000 { + compatible = "qcom,vfe-lite900"; + reg = <0x0 0x9c52000 0x0 0x1480>; + reg-names = "ife-lite6"; + reg-cam-base = <0x252000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "ife-lite6"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_top_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0 0>, + <0 400000000 0 0 400000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite6_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <25>; + cell-index = <9>; + status = "okay"; + + vfe_lite6_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite7: qcom,csid-lite7@9c55000 { + compatible = "qcom,csid-lite900"; + reg = <0x0 0x9c55000 0x0 0x2000>; + reg-names = "csid-lite7"; + reg-cam-base = <0x255000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "csid-lite7"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0>, + <0 400000000 0 0 400000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite7_opp_table>; + clock-control-debugfs = "true"; + cell-index = <10>; + status = "okay"; + + csid_lite7_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite7: qcom,ife-lite7@9c57000 { + compatible = "qcom,vfe-lite900"; + reg = <0x0 0x9c57000 0x0 0x1480>; + reg-names = "ife-lite7"; + reg-cam-base = <0x257000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "ife-lite7"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_top_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0 0>, + <0 400000000 0 0 400000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite7_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <26>; + cell-index = <10>; + status = "okay"; + + vfe_lite7_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite8: qcom,csid-lite8@9c5a000 { + compatible = "qcom,csid-lite900"; + reg = <0x0 0x9c5a000 0x0 0x2000>; + reg-names = "csid-lite8"; + reg-cam-base = <0x25a000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "csid-lite8"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0>, + <0 400000000 0 0 400000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite8_opp_table>; + clock-control-debugfs = "true"; + cell-index = <11>; + status = "okay"; + + csid_lite8_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite8: qcom,ife-lite8@9c5c000 { + compatible = "qcom,vfe-lite900"; + reg = <0x0 0x9c5c000 0x0 0x1480>; + reg-names = "ife-lite8"; + reg-cam-base = <0x25c000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "ife-lite8"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_top_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0 0>, + <0 400000000 0 0 400000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite8_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + cell-index = <11>; + status = "okay"; + + vfe_lite8_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite9: qcom,csid-lite9@9c5f000 { + compatible = "qcom,csid-lite900"; + reg = <0x0 0x9c5f000 0x0 0x2000>; + reg-names = "csid-lite9"; + reg-cam-base = <0x25f000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "csid-lite9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0>, + <0 400000000 0 0 400000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>, + <0 480000000 0 0 480000000 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite9_opp_table>; + clock-control-debugfs = "true"; + cell-index = <12>; + status = "okay"; + + csid_lite9_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite9: qcom,ife-lite9@9c61000 { + compatible = "qcom,vfe-lite900"; + reg = <0x0 0x9c61000 0x0 0x1480>; + reg-names = "ife-lite9"; + reg-cam-base = <0x261000>; + rt-wrapper-base = <0x231000>; + interrupts = ; + interrupt-names = "ife-lite9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>; + clock-names = "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk", + "cam_cc_top_ife_lite_clk"; + clock-rates = <0 300000000 0 0 300000000 0 0>, + <0 400000000 0 0 400000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>, + <0 480000000 0 0 480000000 0 0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite9_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <28>; + cell-index = <12>; + status = "okay"; + + vfe_lite9_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@9c7b000 { + compatible = "qcom,csiphy-v2.5.0", "qcom,csiphy"; + reg = <0x0 0x9c7b000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy0_opp_table>; + reg-cam-base = <0x27b000>; + interrupts = ; + interrupt-names = "CSIPHY0"; + csi-vdd-1p2-supply = <&vreg_l2h_1p2>; + csi-vdd-0p9-supply = <&vreg_l1h_0p9>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 904000>; + rgltr-max-voltage = <1200000 904000>; + rgltr-load-current = <7070 76340>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>, + <480000000 0 400000000 0>, + <480000000 0 400000000 0>; + aggregator-rx; + cell-index = <0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@9c7d000 { + compatible = "qcom,csiphy-v2.5.0", "qcom,csiphy"; + reg = <0x0 0x9c7d000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy1_opp_table>; + reg-cam-base = <0x27d000>; + interrupts = ; + interrupt-names = "CSIPHY1"; + csi-vdd-1p2-supply = <&vreg_l2h_1p2>; + csi-vdd-0p9-supply = <&vreg_l1h_0p9>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 904000>; + rgltr-max-voltage = <1200000 904000>; + rgltr-load-current = <7070 76340>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>, + <480000000 0 400000000 0>, + <480000000 0 400000000 0>; + cell-index = <1>; + aggregator-rx; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2@9c7f000 { + compatible = "qcom,csiphy-v2.5.0", "qcom,csiphy"; + reg = <0x0 0x9c7f000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy2_opp_table>; + reg-cam-base = <0x27f000>; + interrupts = ; + interrupt-names = "CSIPHY2"; + csi-vdd-1p2-supply = <&vreg_l2h_1p2>; + csi-vdd-0p9-supply = <&vreg_l1h_0p9>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 904000>; + rgltr-max-voltage = <1200000 904000>; + rgltr-load-current = <7070 76340>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>, + <480000000 0 400000000 0>, + <480000000 0 400000000 0>; + cell-index = <2>; + aggregator-rx; + status = "okay"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy3: qcom,csiphy3@9c81000 { + compatible = "qcom,csiphy-v2.5.0", "qcom,csiphy"; + reg = <0x0 0x9c81000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy3_opp_table>; + reg-cam-base = <0x281000>; + interrupts = ; + interrupt-names = "CSIPHY3"; + csi-vdd-1p2-supply = <&vreg_l2h_1p2>; + csi-vdd-0p9-supply = <&vreg_l1h_0p9>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 904000>; + rgltr-max-voltage = <1200000 904000>; + rgltr-load-current = <7070 76340>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy3_clk", + "csi3phytimer_clk_src", + "csi3phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>, + <480000000 0 400000000 0>, + <480000000 0 400000000 0>; + cell-index = <3>; + aggregator-rx; + status = "okay"; + + csiphy3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csiphy4: qcom,csiphy4@9c83000 { + compatible = "qcom,csiphy-v2.5.0", "qcom,csiphy"; + reg = <0x0 0x9c83000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy4_opp_table>; + reg-cam-base = <0x283000>; + interrupts = ; + interrupt-names = "CSIPHY4"; + csi-vdd-1p2-supply = <&vreg_l2h_1p2>; + csi-vdd-0p9-supply = <&vreg_l1h_0p9>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 904000>; + rgltr-max-voltage = <1200000 904000>; + rgltr-load-current = <7070 76340>; + shared-clks = <1 0 0 0>; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", + "csiphy4_clk", + "csi4phytimer_clk_src", + "csi4phytimer_clk"; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + clock-rates = <300000000 0 400000000 0>, + <400000000 0 400000000 0>, + <480000000 0 400000000 0>, + <480000000 0 400000000 0>, + <480000000 0 400000000 0>; + cell-index = <4>; + aggregator-rx; + status = "okay"; + + csiphy4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + icp0: qcom,cam-icp0 { + compatible = "qcom,cam-icp0"; + cell-index = <0>; + compat-hw-name = "qcom,icp0", + "qcom,ipe0"; + num-icp = <1>; + num-ipe = <1>; + icp_pc_en; + icp_use_pil; + status = "okay"; + }; + + icp1: qcom,cam-icp1 { + compatible = "qcom,cam-icp1"; + cell-index = <1>; + compat-hw-name = "qcom,icp1", + "qcom,ipe1"; + num-icp = <1>; + num-ipe = <1>; + icp_pc_en; + icp_use_pil; + status = "okay"; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe"; + status = "okay"; + }; + + qcom,cam-i3c-id-table { + i3c-sensor-id-table = <0x1B0 0x0766>; + i3c-eeprom-id-table = <>; + i3c-actuator-id-table = <>; + i3c-ois-id-table = <>; + status = "disabled"; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + qcom,cam-smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + force_cache_allocs; + status = "okay"; + + msm-cam-smmu-cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu_1 0x0860 0x0>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + rt_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu_1 0x0800 0x0>, + <&apps_smmu_1 0x0840 0x0>, + <&apps_smmu_1 0x08C0 0x0>, + <&apps_smmu_1 0x08C3 0x0>, + <&apps_smmu_1 0x0980 0x0>, + <&apps_smmu_1 0x0983 0x0>; + cam-smmu-label = "icp", "icp1"; + qcom,iommu-faults = "stall-disable", "non-fatal"; + multiple-client-devices; + multiple-same-region-clients = "icp", "icp1"; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-fwuncached-region1 { + /* FW uncached region is 5 MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x24000000>; + iova-region-len = <0x500000>; + iova-region-id = <0x6>; + subregion_support; + status = "okay"; + + /* Used for HFI queues/sec heap */ + iova-mem-region-generic-region { + /* HFI queues/sec region is 2 MB long */ + iova-region-name = "icp_hfi"; + iova-region-start = <0x24100000>; + iova-region-len = <0x200000>; + iova-region-id = <0x0>; + }; + }; + + iova-mem-region-fwuncached-region2 { + /* FW uncached region is 5 MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x24500000>; + iova-region-len = <0x500000>; + iova-region-id = <0x6>; + subregion_support; + status = "okay"; + + /* Used for HFI queues/sec heap */ + /* HFI queues/sec region is 2 MB long */ + iova-mem-region-generic-region { + iova-region-name = "icp_hfi"; + iova-region-start = <0x24600000>; + iova-region-len = <0x200000>; + iova-region-id = <0x0>; + }; + }; + + iova-mem-region-io { + /* IO region is approximately ~3.67GB */ + iova-region-name = "io"; + iova-region-start = <0x24B00000>; + iova-region-len = <0xDB400000>; + iova-region-id = <0x3>; + status = "okay"; + }; + + iova-mem-region-qdss { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x24A00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + + iova-mem-region-shared1 { + /* Shared region is ~250 long */ + iova-region-name = "shared"; + iova-region-start = <0x4800000>; + iova-region-len = <0xFC00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + + iova-mem-region-shared2 { + /* Shared region is ~250 long */ + iova-region-name = "shared"; + iova-region-start = <0x14400000>; + iova-region-len = <0xFC00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu_2 0x1401 0x0020>, + <&apps_smmu_2 0x1460 0x0>; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + dma-coherent; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 4 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* start address: 0x100000 */ + /* leaving 1 MB pad at start */ + iova-region-start = <0x100000>; + /* Length: 0xffe00000 */ + /* leaving 1 MB pad at end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm-cam-smmu-secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,camera-main { + compatible = "qcom,camera_iq10"; + status = "okay"; + }; + + qcom,rt-cdm0 { + compatible = "qcom,cam-rt-cdm3_1"; + label = "rt-cdm"; + reg = <0x0 0x9a85000 0x0 0x1000>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x85000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>; + clock-names = "cam_cc_fast_ahb_clk_src"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <200000000>, + <300000000>, + <400000000>, + <400000000>, + <400000000>; + operating-points-v2 = <&cdm_cpas_opp_table0>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + cdm-client-names = "ife0", "dualife0"; + config-fifo; + fifo-depths = <64 64 64 64 64 64 64 64 64 64>; + cam_hw_pid = <9>; + cam-hw-mid = <0>; + cell-index = <0>; + status = "okay"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm1 { + compatible = "qcom,cam-rt-cdm3_1"; + label = "rt-cdm"; + reg = <0x0 0x9a86000 0x0 0x1000>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x86000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>; + clock-names = "cam_cc_fast_ahb_clk_src"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <200000000>, + <300000000>, + <400000000>, + <400000000>, + <400000000>; + operating-points-v2 = <&cdm_cpas_opp_table1>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + cdm-client-names = "ife1", "dualife1"; + config-fifo; + fifo-depths = <64 64 64 64 64 64 64 64 64 64>; + cam_hw_pid = <10>; + cam-hw-mid = <0>; + cell-index = <1>; + status = "okay"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm2 { + compatible = "qcom,cam-rt-cdm3_1"; + label = "rt-cdm"; + reg = <0x0 0x9a87000 0x0 0x1000>; + reg-names = "rt-cdm2"; + reg-cam-base = <0x87000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>; + clock-names = "cam_cc_fast_ahb_clk_src"; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <200000000>, + <300000000>, + <400000000>, + <400000000>, + <400000000>; + operating-points-v2 = <&cdm_cpas_opp_table2>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + cdm-client-names = "ife2", "dualife2"; + config-fifo; + fifo-depths = <64 64 64 64 64 64 64 64 64 64>; + cam_hw_pid = <11>; + cam-hw-mid = <0>; + cell-index = <2>; + status = "okay"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + qcom,rt-cdm3 { + compatible = "qcom,cam-rt-cdm3_1"; + label = "rt-cdm"; + reg = <0x0 0x9a88000 0x0 0x1000>; + reg-names = "rt-cdm3"; + reg-cam-base = <0x88000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>; + clock-names = "cam_cc_slow_ahb_clk_src"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000>, + <80000000>, + <80000000>, + <80000000>, + <80000000>; + operating-points-v2 = <&cdm_cpas_opp_table3>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + cdm-client-names = "ife3", "ife4", "ife5", "ife6", "ife7"; + config-fifo; + fifo-depths = <64 64 64 64 64 64 64 64 64 64>; + cam_hw_pid = <8>; + cam-hw-mid = <0>; + cell-index = <3>; + status = "okay"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; + + qcom,rt-cdm4 { + compatible = "qcom,cam-rt-cdm3_1"; + label = "rt-cdm"; + reg = <0x0 0x9a89000 0x0 0x1000>; + reg-names = "rt-cdm4"; + reg-cam-base = <0x89000>; + interrupts = ; + interrupt-names = "rt-cdm4"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>; + clock-names = "cam_cc_slow_ahb_clk_src"; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000>, + <80000000>, + <80000000>, + <80000000>, + <80000000>; + operating-points-v2 = <&cdm_cpas_opp_table4>; + clock-cntl-level = "svs", "svs_l1", "nominal", "turbo", "turbo_l1"; + cdm-client-names = "ife8", "ife9", "ife10", "ife11", "ife12"; + config-fifo; + fifo-depths = <64 64 64 64 64 64 64 64 64 64>; + cam_hw_pid = <12>; + cam-hw-mid = <0>; + cell-index = <4>; + status = "okay"; + + cdm_cpas_opp_table4: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + }; + }; +}; + +&tlmm { + cam_sensor_mclk0_active: cam-sensor-mclk0-active { + /* MCLK0 */ + mux { + pins = "gpio72"; + function = "cam_mclk"; + }; + + config { + pins = "gpio72"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam-sensor-mclk0-suspend { + /* MCLK0 */ + mux { + pins = "gpio72"; + function = "cam_mclk"; + }; + + config { + pins = "gpio72"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam-sensor-mclk1-active { + /* MCLK1 */ + mux { + pins = "gpio73"; + function = "cam_mclk"; + }; + + config { + pins = "gpio73"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam-sensor-mclk1-suspend { + /* MCLK1 */ + mux { + pins = "gpio73"; + function = "cam_mclk"; + }; + + config { + pins = "gpio73"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_active: cam-sensor-mclk2-active { + /* MCLK2 */ + mux { + pins = "gpio74"; + function = "cam_mclk"; + }; + + config { + pins = "gpio74"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_suspend: cam-sensor-mclk2-suspend { + /* MCLK2 */ + mux { + pins = "gpio74"; + function = "cam_mclk"; + }; + + config { + pins = "gpio74"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_active: cam-sensor-mclk3-active { + /* MCLK3 */ + mux { + pins = "gpio75"; + function = "cam_mclk"; + }; + + config { + pins = "gpio75"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk3_suspend: cam-sensor-mclk3-suspend { + /* MCLK3 */ + mux { + pins = "gpio75"; + function = "cam_mclk"; + }; + + config { + pins = "gpio75"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + /* TODO : NordAU should support mclk4, if supported then need to add pinctrl */ + cci_i2c_scl0_active: cci-i2c-scl0-active { + mux { + pins = "gpio16"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio16"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_scl0_suspend: cci-i2c-scl0-suspend { + mux { + pins = "gpio16"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio16"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_active: cci-i2c-scl1-active { + mux { + pins = "gpio18"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio18"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_scl1_suspend: cci-i2c-scl1-suspend { + mux { + pins = "gpio18"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio18"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl2_active: cci-i2c-scl2-active { + mux { + pins = "gpio20"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio20"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_scl2_suspend: cci-i2c-scl2-suspend { + mux { + pins = "gpio20"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio20"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl3_active: cci-i2c-scl3-active { + mux { + pins = "gpio22"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio22"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_scl3_suspend: cci-i2c-scl3-suspend { + mux { + pins = "gpio22"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio22"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl4_active: cci-i2c-scl4-active { + mux { + pins = "gpio24"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio24"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_scl4_suspend: cci-i2c-scl4-suspend { + mux { + pins = "gpio24"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio24"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl5_active: cci-i2c-scl5-active { + mux { + pins = "gpio114"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio114"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_scl5_suspend: cci-i2c-scl5-suspend { + mux { + pins = "gpio114"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio114"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl6_active: cci-i2c-scl6-active { + mux { + pins = "gpio116"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio116"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_scl6_suspend: cci-i2c-scl6-suspend { + mux { + pins = "gpio116"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio116"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl7_active: cci-i2c-scl7-active { + mux { + pins = "gpio126"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio126"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_scl7_suspend: cci-i2c-scl7-suspend { + mux { + pins = "gpio126"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio126"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl8_active: cci-i2c-scl8-active { + mux { + pins = "gpio130"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio130"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_scl8_suspend: cci-i2c-scl8-suspend { + mux { + pins = "gpio130"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio130"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl9_active: cci-i2c-scl9-active { + mux { + pins = "gpio132"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio132"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_scl9_suspend: cci-i2c-scl9-suspend { + mux { + pins = "gpio132"; + function = "ccu_i2c_scl"; + }; + + config { + pins = "gpio132"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda0_active: cci-i2c-sda0-active { + mux { + pins = "gpio15"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio15"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_sda0_suspend: cci-i2c-sda0-suspend { + mux { + pins = "gpio15"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio15"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_active: cci-i2c-sda1-active { + mux { + pins = "gpio17"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio17"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_sda1_suspend: cci-i2c-sda1-suspend { + mux { + pins = "gpio17"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio17"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda2_active: cci-i2c-sda2-active { + mux { + pins = "gpio19"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio19"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_sda2_suspend: cci-i2c-sda2-suspend { + mux { + pins = "gpio19"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio19"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda3_active: cci-i2c-sda3-active { + mux { + pins = "gpio21"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio21"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_sda3_suspend: cci-i2c-sda3-suspend { + mux { + pins = "gpio21"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio21"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda4_active: cci-i2c-sda4-active { + mux { + pins = "gpio23"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio23"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_sda4_suspend: cci-i2c-sda4-suspend { + mux { + pins = "gpio23"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio23"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda5_active: cci-i2c-sda5-active { + mux { + pins = "gpio113"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio113"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_sda5_suspend: cci-i2c-sda5-suspend { + mux { + pins = "gpio113"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio113"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda6_active: cci-i2c-sda6-active { + mux { + pins = "gpio115"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio115"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_sda6_suspend: cci-i2c-sda6-suspend { + mux { + pins = "gpio115"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio115"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda7_active: cci-i2c-sda7-active { + mux { + pins = "gpio125"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio125"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_sda7_suspend: cci-i2c-sda7-suspend { + mux { + pins = "gpio125"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio125"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda8_active: cci-i2c-sda8-active { + mux { + pins = "gpio129"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio129"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_sda8_suspend: cci-i2c-sda8-suspend { + mux { + pins = "gpio129"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio129"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda9_active: cci-i2c-sda9-active { + mux { + pins = "gpio131"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio131"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; /* I2C PULL */ + }; + }; + + cci_i2c_sda9_suspend: cci-i2c-sda9-suspend { + mux { + pins = "gpio131"; + function = "ccu_i2c_sda"; + }; + + config { + pins = "gpio131"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded-camx.dtso b/arch/arm64/boot/dts/qcom/nord-ride-embedded-camx.dtso new file mode 100644 index 0000000000000..d471bcb292c38 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded-camx.dtso @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nord-camera.dtsi" +#include "nord-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/nord-rrd-camx.dtso b/arch/arm64/boot/dts/qcom/nord-rrd-camx.dtso new file mode 100644 index 0000000000000..d471bcb292c38 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/nord-rrd-camx.dtso @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nord-camera.dtsi" +#include "nord-camera-sensor.dtsi" + +&camss { + status = "disabled"; +}; diff --git a/include/dt-bindings/camera/msm-camera.h b/include/dt-bindings/camera/msm-camera.h index 97228c26e7040..8fab20cc7b973 100644 --- a/include/dt-bindings/camera/msm-camera.h +++ b/include/dt-bindings/camera/msm-camera.h @@ -18,6 +18,18 @@ #define CAM_CPAS_PATH_DATA_IFE_RDI3 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 7) #define CAM_CPAS_PATH_DATA_IFE_PDAF (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 8) #define CAM_CPAS_PATH_DATA_IFE_PIXEL_RAW (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 9) +#define CAM_CPAS_PATH_DATA_IFE_RDI4 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 10) +#define CAM_CPAS_PATH_DATA_IFE_RDI5 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 11) +#define CAM_CPAS_PATH_DATA_IFE_RDI6 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 12) +#define CAM_CPAS_PATH_DATA_IFE_RDI7 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 13) +#define CAM_CPAS_PATH_DATA_IFE_RDI8 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 14) +#define CAM_CPAS_PATH_DATA_IFE_RDI9 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 15) +#define CAM_CPAS_PATH_DATA_IFE_RDI10 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 16) +#define CAM_CPAS_PATH_DATA_IFE_RDI11 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 17) +#define CAM_CPAS_PATH_DATA_IFE_DS4 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 18) +#define CAM_CPAS_PATH_DATA_IFE_DS16 (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 19) +#define CAM_CPAS_PATH_DATA_IFE_IR (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 20) +#define CAM_CPAS_PATH_DATA_IFE_RS (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 21) #define CAM_CPAS_PATH_DATA_IFE_MAX_OFFSET (CAM_CPAS_PATH_DATA_IFE_START_OFFSET + 31) #define CAM_CPAS_PATH_DATA_IPE_START_OFFSET 32 From be6df8c9f533ff39cc897960d69bf576363c5ded Mon Sep 17 00:00:00 2001 From: Ram Sargar Date: Fri, 18 Sep 2026 05:17:35 +0530 Subject: [PATCH 0769/1133] QCLINUX: dt-bindings: mfd: Add qcom,apsshm-shared-intu schema Add DT schema for the Qualcomm APSS Shared Memory Interrupt Notification Unit (apsshm-shared-intu) syscon block. This block is used to trigger doorbell interrupts that notify special event notifications to one or more subsystems such as RTSS. Signed-off-by: Ram Sargar --- .../bindings/mfd/qcom,apsshm-shared-intu.yaml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/qcom,apsshm-shared-intu.yaml diff --git a/Documentation/devicetree/bindings/mfd/qcom,apsshm-shared-intu.yaml b/Documentation/devicetree/bindings/mfd/qcom,apsshm-shared-intu.yaml new file mode 100644 index 0000000000000..6178be887c4b7 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/qcom,apsshm-shared-intu.yaml @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/qcom,apsshm-shared-intu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm APSS Shared Memory Interrupt Notification Unit registers + +maintainers: + - Ram Sargar + +description: + A block of SoC-level APSS HM CSR registers used to trigger doorbells that + notify special event notifications to one or more subsystems within SOC. + +properties: + compatible: + items: + - enum: + - qcom,sa8775p-apsshm-shared-intu + - qcom,qcs8300-apsshm-shared-intu + - const: syscon + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + apsshm_shared_intu: syscon@17c00000 { + compatible = "qcom,sa8775p-apsshm-shared-intu", "syscon"; + reg = <0x0 0x17c00000 0x0 0x38>; + }; From 04963c496be9073f42c279663cabbeafb07d98a9 Mon Sep 17 00:00:00 2001 From: Ram Sargar Date: Thu, 10 Sep 2026 02:51:28 +0530 Subject: [PATCH 0770/1133] QCLINUX: dt-bindings: mailbox: Add qcom,rtss-mailbox schema Add the DT schema for the RTSS mailbox, which exposes a shared-memory and IPCC doorbell channel between the application processor and the RTSS subsystem, and manages the boot/suspend handshake with RTSS. Signed-off-by: Ram Sargar --- .../bindings/mailbox/qcom,rtss-mailbox.yaml | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/qcom,rtss-mailbox.yaml diff --git a/Documentation/devicetree/bindings/mailbox/qcom,rtss-mailbox.yaml b/Documentation/devicetree/bindings/mailbox/qcom,rtss-mailbox.yaml new file mode 100644 index 0000000000000..f223dc91eb392 --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/qcom,rtss-mailbox.yaml @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mailbox/qcom,rtss-mailbox.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies, Inc. RTSS Mailbox + +maintainers: + - Ram Sargar + +description: + The RTSS mailbox exposes a shared-memory and IPCC doorbell channel between + the application processor and the RTSS subsystem, and manages handshake + with the RTSS subsystem to handle different milestones in mission mode. + +properties: + compatible: + items: + - enum: + - qcom,sa8775p-rtss-mailbox + - qcom,qcs8300-rtss-mailbox + - const: qcom,rtss-mailbox + + qcom,syscon-tcsr-req: + $ref: /schemas/types.yaml#/definitions/phandle-array + items: + - items: + - description: phandle to the TCSR syscon node + - description: offset of the RTSS request register from the syscon base + description: + Reference to the TCSR syscon node and register offset used to write + the boot/suspend handshake magic that RTSS reads. + + qcom,syscon-tcsr-resp: + $ref: /schemas/types.yaml#/definitions/phandle-array + items: + - items: + - description: phandle to the TCSR syscon node + - description: offset of the RTSS response register from the syscon base + description: + Reference to the TCSR syscon node and register offset used to read + back the handshake magic RTSS acknowledges with. + + qcom,syscon-ipc: + $ref: /schemas/types.yaml#/definitions/phandle-array + items: + - items: + - description: phandle to the APSS shared IPC syscon node + - description: offset of the IPC trigger register from the syscon base + description: + Reference to the syscon node and register offset used to trigger the + IPC interrupt that notifies RTSS a TCSR handshake register was updated. + + mboxes: + description: + IPCC mailbox channels used to send interrupts to the RTSS-facing IPCC + client/signal pairs. + + interrupts-extended: + description: + IPCC channels used to receive interrupts from the RTSS-facing IPCC + client/signal pairs. + + memory-region: + items: + - description: reserved-memory carveout for the RTSS mailbox descriptor region + - description: reserved-memory carveout for the OTA region + description: + Reference to the reserved-memory regions used for the mailbox + descriptor and for OTA. + +required: + - compatible + - qcom,syscon-tcsr-req + - qcom,syscon-tcsr-resp + - qcom,syscon-ipc + - mboxes + - interrupts-extended + - memory-region + +additionalProperties: false + +examples: + - | + #include + #include + + rtss-ipcc-mailbox { + compatible = "qcom,sa8775p-rtss-mailbox", "qcom,rtss-mailbox"; + qcom,syscon-tcsr-req = <&tcsr 0x3e02c>; + qcom,syscon-tcsr-resp = <&tcsr 0x3d018>; + qcom,syscon-ipc = <&apsshm_shared_intu 0xc>; + mboxes = <&ipcc1 IPCC_CLIENT_RTSS0 0x2>, + <&ipcc1 IPCC_CLIENT_RTSS1 0x3>; + interrupts-extended = <&ipcc1 IPCC_CLIENT_RTSS0 0x2 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS1 0x3 IRQ_TYPE_EDGE_RISING>; + memory-region = <&sail_mailbox_mem>, <&sail_ota_mem>; + }; From 1f0edde56a26e7f351a1c56d609c21997890f79f Mon Sep 17 00:00:00 2001 From: Ram Sargar Date: Thu, 10 Sep 2026 02:47:17 +0530 Subject: [PATCH 0771/1133] QCLINUX: arm64: dts: qcom: lemans: Add IPCC and syscon nodes for RTSS Mailbox Add ipcc1-4 mailbox nodes, widen the tcsr syscon's reg range to cover both TCSR request/response registers, and add the apss_shared_ipc syscon node for the Lemans platform. These back the syscon/mbox phandle references used by the Lemans RTSS mailbox node (qcom,rtss-mailbox). Signed-off-by: Ram Sargar --- arch/arm64/boot/dts/qcom/lemans.dtsi | 43 +++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 1fdb72fa55184..a5ccdbab597e5 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -1018,6 +1018,42 @@ #mbox-cells = <2>; }; + ipcc1: mailbox@488000 { + compatible = "qcom,sa8775p-ipcc", "qcom,ipcc"; + reg = <0x0 0x00488000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + }; + + ipcc2: mailbox@4a1000 { + compatible = "qcom,sa8775p-ipcc", "qcom,ipcc"; + reg = <0x0 0x004a1000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + }; + + ipcc3: mailbox@4a2000 { + compatible = "qcom,sa8775p-ipcc", "qcom,ipcc"; + reg = <0x0 0x004a2000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + }; + + ipcc4: mailbox@4a3000 { + compatible = "qcom,sa8775p-ipcc", "qcom,ipcc"; + reg = <0x0 0x004a3000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + }; + qfprom: efuse@784000 { compatible = "qcom,sa8775p-qfprom", "qcom,qfprom"; reg = <0x0 0x00784000 0x0 0x3000>; @@ -4633,7 +4669,7 @@ tcsr: syscon@1fc0000 { compatible = "qcom,sa8775p-tcsr", "syscon"; - reg = <0x0 0x1fc0000 0x0 0x30000>; + reg = <0x0 0x1fc0000 0x0 0x40000>; }; gpu: gpu@3d00000 { @@ -7056,6 +7092,11 @@ redistributor-stride = <0x0 0x20000>; }; + apsshm_shared_intu: syscon@17c00000 { + compatible = "qcom,sa8775p-apsshm-shared-intu", "syscon"; + reg = <0x0 0x17c00000 0x0 0x38>; + }; + watchdog@17c10000 { compatible = "qcom,apss-wdt-sa8775p", "qcom,kpss-wdt"; reg = <0x0 0x17c10000 0x0 0x1000>; From 1f667dd3ec2b2e95473512a335bf5545eb9bd6b0 Mon Sep 17 00:00:00 2001 From: Ram Sargar Date: Thu, 10 Sep 2026 02:49:11 +0530 Subject: [PATCH 0772/1133] QCLINUX: arm64: dts: qcom: lemans-staging: Add rtss-mailbox node Add the rtss_mailbox overlay node for the Lemans platform, using ipcc1-ipcc4 and the tcsr/apss_shared_ipc syscon nodes. Place it under &soc, alongside the other simple-bus child nodes in this file. Signed-off-by: Ram Sargar --- arch/arm64/boot/dts/qcom/lemans-staging.dtso | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-staging.dtso b/arch/arm64/boot/dts/qcom/lemans-staging.dtso index ad919bfb6b19a..ce782aa0a0719 100644 --- a/arch/arm64/boot/dts/qcom/lemans-staging.dtso +++ b/arch/arm64/boot/dts/qcom/lemans-staging.dtso @@ -7,8 +7,51 @@ /dts-v1/; /plugin/; +#include +#include +#include +#include &soc { + rtss_mailbox: rtss-ipcc-mailbox { + compatible = "qcom,sa8775p-rtss-mailbox", "qcom,rtss-mailbox"; + qcom,syscon-tcsr-req = <&tcsr 0x3e02c>; + qcom,syscon-tcsr-resp = <&tcsr 0x3d018>; + qcom,syscon-ipc = <&apsshm_shared_intu 0xc>; + mboxes = <&ipcc1 IPCC_CLIENT_RTSS0 0x2>, + <&ipcc1 IPCC_CLIENT_RTSS1 0x3>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x4>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x5>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x6>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x7>, + <&ipcc1 IPCC_CLIENT_RTSS2 0x8>, + <&ipcc1 IPCC_CLIENT_RTSS1 0x9>, + <&ipcc1 IPCC_CLIENT_RTSS2 0xa>, + <&ipcc1 IPCC_CLIENT_RTSS1 0xb>, + <&ipcc1 IPCC_CLIENT_RTSS0 0xc>, + <&ipcc1 IPCC_CLIENT_RTSS0 0xd>, + <&ipcc1 IPCC_CLIENT_RTSS1 0xe>, + <&ipcc1 IPCC_CLIENT_RTSS2 0xf>, + <&ipcc1 IPCC_CLIENT_RTSS3 0x10>; + interrupts-extended = <&ipcc1 IPCC_CLIENT_RTSS0 0x2 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS1 0x3 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x4 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x5 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x6 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x7 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS2 0x8 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS1 0x9 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS2 0xa IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS1 0xb IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0xc IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0xd IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS1 0xe IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS2 0xf IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS3 0x10 IRQ_TYPE_EDGE_RISING>; + memory-region = <&sail_mailbox_mem>, + <&sail_ota_mem>; + }; + tgu@4b0e000 { compatible = "qcom,tgu", "arm,primecell"; reg = <0x0 0x4b0e000 0x0 0x1000>; From fc320373e80e17236549b7649317ffe0dc8d8e56 Mon Sep 17 00:00:00 2001 From: Ram Sargar Date: Thu, 10 Sep 2026 02:50:00 +0530 Subject: [PATCH 0773/1133] QCLINUX: arm64: dts: qcom: monaco: Add IPCC, syscon, and memory nodes for RTSS Mailbox Add ipcc1-4 mailbox nodes, widen the tcsr syscon's reg range to cover both TCSR request/response registers, and add the apss_shared_ipc syscon node for the Monaco platform. These back the syscon/mbox phandle references used by the Monaco RTSS mailbox node (qcom,rtss-mailbox). Reserve the memory regions used by the SAIL/RTSS subsystem for its TZ mailbox, shared-memory mailbox, and OTA buffer on Monaco. These regions back the memory-region references used by the Monaco RTSS mailbox node. Signed-off-by: Ram Sargar --- arch/arm64/boot/dts/qcom/monaco.dtsi | 58 +++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index e698d3c759551..14b6d7d4cd5b6 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -747,6 +747,21 @@ hwlocks = <&tcsr_mutex 3>; }; + tz_sail_mailbox_mem: tz-sail-mailbox@90c00000 { + reg = <0x0 0x90c00000 0x0 0x100000>; + no-map; + }; + + sail_mailbox_mem: sail-ss@90d00000 { + reg = <0x0 0x90d00000 0x0 0x100000>; + no-map; + }; + + sail_ota_mem: sail-ss@90e00000 { + reg = <0x0 0x90e00000 0x0 0x300000>; + no-map; + }; + gunyah_md_mem: gunyah-md-region@91a80000 { reg = <0x0 0x91a80000 0x0 0x80000>; no-map; @@ -919,6 +934,42 @@ #mbox-cells = <2>; }; + ipcc1: mailbox@488000 { + compatible = "qcom,qcs8300-ipcc", "qcom,ipcc"; + reg = <0x0 0x00488000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + }; + + ipcc2: mailbox@4a1000 { + compatible = "qcom,qcs8300-ipcc", "qcom,ipcc"; + reg = <0x0 0x004a1000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + }; + + ipcc3: mailbox@4a2000 { + compatible = "qcom,qcs8300-ipcc", "qcom,ipcc"; + reg = <0x0 0x004a2000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + }; + + ipcc4: mailbox@4a3000 { + compatible = "qcom,qcs8300-ipcc", "qcom,ipcc"; + reg = <0x0 0x004a3000 0x0 0x1000>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + #mbox-cells = <2>; + }; + qfprom: efuse@784000 { compatible = "qcom,qcs8300-qfprom", "qcom,qfprom"; reg = <0x0 0x00784000 0x0 0x2410>; @@ -2746,7 +2797,7 @@ tcsr: syscon@1fc0000 { compatible = "qcom,qcs8300-tcsr", "syscon"; - reg = <0x0 0x1fc0000 0x0 0x30000>; + reg = <0x0 0x1fc0000 0x0 0x40000>; }; remoteproc_adsp: remoteproc@3000000 { @@ -7415,6 +7466,11 @@ #address-cells = <0>; }; + apsshm_shared_intu: syscon@17c00000 { + compatible = "qcom,qcs8300-apsshm-shared-intu", "syscon"; + reg = <0x0 0x17c00000 0x0 0x38>; + }; + watchdog@17c10000 { compatible = "qcom,apss-wdt-qcs8300", "qcom,kpss-wdt"; reg = <0x0 0x17c10000 0x0 0x1000>; From 80dc9a3cdc911203fc23d78aecb55db64ba7ea85 Mon Sep 17 00:00:00 2001 From: Ram Sargar Date: Thu, 10 Sep 2026 02:51:04 +0530 Subject: [PATCH 0774/1133] QCLINUX: arm64: dts: qcom: monaco-staging: Add rtss-mailbox node Add the rtss_mailbox overlay node for the Monaco platform, mirroring the Lemans RTSS mailbox node. Place it under &soc, alongside the other simple-bus child nodes in this file. Signed-off-by: Ram Sargar --- arch/arm64/boot/dts/qcom/monaco-staging.dtso | 42 ++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-staging.dtso b/arch/arm64/boot/dts/qcom/monaco-staging.dtso index fc44741b8caab..ad3c0662cd561 100644 --- a/arch/arm64/boot/dts/qcom/monaco-staging.dtso +++ b/arch/arm64/boot/dts/qcom/monaco-staging.dtso @@ -7,8 +7,50 @@ /dts-v1/; /plugin/; +#include +#include +#include &soc { + rtss_mailbox: rtss-ipcc-mailbox { + compatible = "qcom,qcs8300-rtss-mailbox", "qcom,rtss-mailbox"; + qcom,syscon-tcsr-req = <&tcsr 0x3e02c>; + qcom,syscon-tcsr-resp = <&tcsr 0x3d018>; + qcom,syscon-ipc = <&apsshm_shared_intu 0xc>; + mboxes = <&ipcc1 IPCC_CLIENT_RTSS0 0x2>, + <&ipcc1 IPCC_CLIENT_RTSS1 0x3>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x4>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x5>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x6>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x7>, + <&ipcc1 IPCC_CLIENT_RTSS2 0x8>, + <&ipcc1 IPCC_CLIENT_RTSS1 0x9>, + <&ipcc1 IPCC_CLIENT_RTSS2 0xa>, + <&ipcc1 IPCC_CLIENT_RTSS1 0xb>, + <&ipcc1 IPCC_CLIENT_RTSS0 0xc>, + <&ipcc1 IPCC_CLIENT_RTSS0 0xd>, + <&ipcc1 IPCC_CLIENT_RTSS1 0xe>, + <&ipcc1 IPCC_CLIENT_RTSS2 0xf>, + <&ipcc1 IPCC_CLIENT_RTSS3 0x10>; + interrupts-extended = <&ipcc1 IPCC_CLIENT_RTSS0 0x2 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS1 0x3 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x4 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x5 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x6 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0x7 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS2 0x8 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS1 0x9 IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS2 0xa IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS1 0xb IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0xc IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS0 0xd IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS1 0xe IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS2 0xf IRQ_TYPE_EDGE_RISING>, + <&ipcc1 IPCC_CLIENT_RTSS3 0x10 IRQ_TYPE_EDGE_RISING>; + memory-region = <&sail_mailbox_mem>, + <&sail_ota_mem>; + }; + tgu@4b0e000 { compatible = "qcom,tgu", "arm,primecell"; reg = <0x0 0x4b0e000 0x0 0x1000>; From e0af87b20cbff0c3246464f8354a416f7583d306 Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Mon, 21 Sep 2026 03:16:07 +0530 Subject: [PATCH 0775/1133] QCLINUX: arm64: dts: qcom: glymur-crd: Enable AON camera support Enable AON camera support for glymur-crd. Signed-off-by: Vishal Verma Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi | 1 + arch/arm64/boot/dts/qcom/glymur-camera.dtsi | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi index 16aa3dc7816d4..7cffbf2fece6d 100644 --- a/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi @@ -9,6 +9,7 @@ /*cam0-ov08x*/ qcom,cam-sensor0 { compatible = "qcom,cam-sensor"; + aon-camera-id = ; csiphy-sd-index = <4>; sensor-position-roll = <0>; sensor-position-pitch = <0>; diff --git a/arch/arm64/boot/dts/qcom/glymur-camera.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi index c2c6050a47add..a9189907b4ec2 100644 --- a/arch/arm64/boot/dts/qcom/glymur-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-camera.dtsi @@ -2085,6 +2085,7 @@ pins = "gpio239"; bias-disable; /* No PULL */ drive-strength = <12>; /* 12 MA */ + qcom,apps; }; mux { @@ -2100,6 +2101,7 @@ bias-pull-down; /* PULL DOWN */ drive-strength = <12>; /* 12 MA */ output-low; + qcom,remote; }; mux { @@ -2226,6 +2228,7 @@ pins = "gpio100"; bias-disable; /* No PULL */ drive-strength = <12>; /* 12 MA */ + qcom,apps; }; mux { @@ -2240,6 +2243,7 @@ pins = "gpio100"; bias-pull-down; /* PULL DOWN */ drive-strength = <12>; /* 12 MA */ + qcom,remote; }; mux { @@ -2428,6 +2432,7 @@ pins = "gpio235","gpio236"; bias-pull-up; /* PULL UP*/ drive-strength = <2>; /* 2 MA */ + qcom,apps; }; mux { @@ -2443,6 +2448,7 @@ pins = "gpio235","gpio236"; bias-pull-down; /* PULL DOWN */ drive-strength = <2>; /* 2 MA */ + qcom,remote; }; mux { From b88c7ebe97c37a2139e1c38d71d1d5dfc1da0481 Mon Sep 17 00:00:00 2001 From: Nirav Khatri Date: Mon, 10 Aug 2026 15:01:32 +0530 Subject: [PATCH 0776/1133] QCLINUX: arm64: dts: qcom: qcs6490: add pctrl-idx-mapping for CCI Add pctrl-idx-mapping/pctrl-map-names to both CCI nodes (cam_cci0, cam_cci1). This is needed by the camx-dlkm CCI to determine the number of CCI master instances per node. Signed-off-by: Nirav Khatri --- arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi index 2fadfb9de1fee..f9165ae96219d 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi @@ -858,6 +858,8 @@ clock-rates = <37500000 0>; clock-cntl-level = "lowsvs"; src-clock-name = "cci_0_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; pinctrl-0 = <&cci0_active &cci1_active>; pinctrl-1 = <&cci0_suspend &cci1_suspend>; pinctrl-names = "cam_default", "cam_suspend"; @@ -960,6 +962,8 @@ clock-rates = <37500000 0>; clock-cntl-level = "lowsvs"; src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; pinctrl-0 = <&cci2_active &cci3_active>; pinctrl-1 = <&cci2_suspend &cci3_suspend>; pinctrl-names = "cam_default", "cam_suspend"; From 894066a7dfe18ddc20a351cf0873e78c41b41e0a Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 7 Oct 2026 14:29:48 +0300 Subject: [PATCH 0777/1133] QCLINUX: arm64: dts: qcom: nord: Fix GMSL CCI masters Correct the cci-master index for GMSL deserializer1 and deserializer3 from 0 to 1, and remap the GMSL deserializer2/4 nodes from &cam_cci2/&cam_cci4 to &cam_cci1/&cam_cci2 to match the actual CCI master wiring. Also add gpios-shared for the reset lines used across the GMSL deserializers under qcom,cam-res-mgr. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi index 2b56d3e17a546..0ba75082ad155 100644 --- a/arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi @@ -120,9 +120,7 @@ }; }; }; -}; -&cam_cci1 { /* GMSL deserializer 1 */ qcom,cam-gmsl-deserializer1 { cell-index = <1>; @@ -144,7 +142,7 @@ gpio-req-tbl-num = <0>; gpio-req-tbl-flags = <0>; gpio-req-tbl-label = "CAM_RESET1"; - cci-master = <0>; + cci-master = <1>; status = "okay"; #address-cells = <1>; #size-cells = <0>; @@ -239,7 +237,7 @@ }; }; -&cam_cci2 { +&cam_cci1 { /* GMSL deserializer 2 */ qcom,cam-gmsl-deserializer2 { cell-index = <2>; @@ -354,9 +352,7 @@ }; }; }; -}; -&cam_cci3 { /* GMSL deserializer 3 */ qcom,cam-gmsl-deserializer3 { cell-index = <3>; @@ -378,7 +374,7 @@ gpio-req-tbl-num = <0>; gpio-req-tbl-flags = <0>; gpio-req-tbl-label = "CAM_RESET3"; - cci-master = <0>; + cci-master = <1>; status = "okay"; #address-cells = <1>; #size-cells = <0>; @@ -473,7 +469,7 @@ }; }; -&cam_cci4 { +&cam_cci2 { /* GMSL deserializer 4 */ qcom,cam-gmsl-deserializer4 { cell-index = <4>; @@ -593,6 +589,7 @@ &soc { qcom,cam-res-mgr { compatible = "qcom,cam-res-mgr"; + gpios-shared = <565 566 567 568 569>; status = "okay"; }; }; From 2e8025051e407dbf54ad7781031548d7cffec00e Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 14 Oct 2026 00:06:37 +0530 Subject: [PATCH 0778/1133] QCLINUX: arm64: dts: qcom: nord: Fix SFE-lite compatible string Update the compatible string for cam_sfe_lite0/1/2 from "qcom,sfe-lite690" to "qcom,sfe-lite900" to match the SFE-lite hardware revision actually present on Nord. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/nord-camera.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/nord-camera.dtsi b/arch/arm64/boot/dts/qcom/nord-camera.dtsi index 9c00bb8954f30..309ddecd9c1e4 100644 --- a/arch/arm64/boot/dts/qcom/nord-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-camera.dtsi @@ -1439,7 +1439,7 @@ }; cam_sfe_lite0: qcom,sfe-lite0@9b4c000 { - compatible = "qcom,sfe-lite690"; + compatible = "qcom,sfe-lite900"; reg = <0x0 0x9b4c000 0x0 0x1000>; reg-names = "sfe-lite0"; reg-cam-base = <0x14c000>; @@ -1487,7 +1487,7 @@ }; cam_sfe_lite1: qcom,sfe-lite1@9b4d000 { - compatible = "qcom,sfe-lite690"; + compatible = "qcom,sfe-lite900"; reg = <0x0 0x9b4d000 0x0 0x1000>; reg-names = "sfe-lite1"; reg-cam-base = <0x14d000>; @@ -1535,7 +1535,7 @@ }; cam_sfe_lite2: qcom,sfe-lite2@9b4e000 { - compatible = "qcom,sfe-lite690"; + compatible = "qcom,sfe-lite900"; reg = <0x0 0x9b4e000 0x0 0x1000>; reg-names = "sfe-lite2"; reg-cam-base = <0x14e000>; From 77d52dfa119748f301b8dd22784018d49872ca63 Mon Sep 17 00:00:00 2001 From: Chandu Idavalapati Date: Wed, 14 Oct 2026 17:00:43 +0530 Subject: [PATCH 0779/1133] QCLINUX: arm64: dts: qcom: monza: Added Base camera DT support Add devicetree support for the camera subsystem on MONZA, covering all available camera ports. This includes: - CCI, CSIPHY, CSID, VFE/SFE (lite) nodes for the ISP pipeline - Camera sensor nodes across cam_cci0/1/2 ports Signed-off-by: Chandu Idavalapati --- arch/arm64/boot/dts/qcom/Makefile | 11 + .../qcom/monaco-arduino-monza-camera-el2.dtsi | 14 + .../monaco-arduino-monza-camera-sensor.dtsi | 177 ++ .../dts/qcom/monaco-arduino-monza-camera.dtsi | 2593 +++++++++++++++++ .../qcom/monaco-arduino-monza-camx-el2.dtso | 16 + .../dts/qcom/monaco-arduino-monza-camx.dtso | 15 + 6 files changed, 2826 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera-el2.dtsi create mode 100644 arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera-sensor.dtsi create mode 100644 arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera.dtsi create mode 100644 arch/arm64/boot/dts/qcom/monaco-arduino-monza-camx-el2.dtso create mode 100644 arch/arm64/boot/dts/qcom/monaco-arduino-monza-camx.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index e0d0b681741a1..55381ace194d4 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -76,6 +76,17 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-evk.dtb +monaco-arduino-monza-el2-dtbs := monaco-arduino-monza.dtb monaco-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza-el2.dtb + +monaco-arduino-monza-camx-dtbs := monaco-arduino-monza.dtb monaco-arduino-monza-camx.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza-camx.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza-camx.dtbo + +monaco-arduino-monza-camx-el2-dtbs := monaco-arduino-monza-el2.dtb monaco-arduino-monza-camx.dtbo monaco-arduino-monza-camx-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza-camx-el2.dtb +dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza-camx-el2.dtbo + monaco-evk-camera-imx577-dtbs := monaco-evk.dtb monaco-evk-camera-imx577.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camera-imx577.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-camera-imx577.dtbo diff --git a/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera-el2.dtsi b/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera-el2.dtsi new file mode 100644 index 0000000000000..db2202d980810 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera-el2.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +&cam_cpas { + enable-secure-qos-update = <0>; +}; + +&cam_icp_firmware { + camera-firmware { + iommus = <&apps_smmu 0x08C1 0x0400>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera-sensor.dtsi new file mode 100644 index 0000000000000..d117fe201d37a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera-sensor.dtsi @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include + +&cam_cci0 { + /*cam0-imx577*/ + qcom,cam-sensor23 { + cell-index = <23>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_suspend_rst0>; + gpios = <&tlmm 64 0>, + <&tlmm 24 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAM_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + status = "okay"; + }; + + /*cam1-imx577*/ + qcom,cam-sensor24 { + cell-index = <24>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_suspend_rst0>; + gpios = <&tlmm 64 0>, + <&tlmm 24 1>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAM_RESET0", + "CAM_CUSTOM1"; + cci-master = <0>; + status = "okay"; + }; +}; + +&cam_cci1 { + /*cam2-imx577*/ + qcom,cam-sensor25 { + cell-index = <25>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_suspend_rst1>; + gpios = <&tlmm 75 0>, + <&tlmm 41 0>; + gpio-reset = <0>; + gpio-custom2 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAM_RESET1", + "CAM_CUSTOM2"; + cci-master = <0>; + status = "okay"; + }; + + /*cam3-imx577*/ + qcom,cam-sensor26 { + cell-index = <26>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_suspend_rst1>; + gpios = <&tlmm 75 0>, + <&tlmm 41 1>; + gpio-reset = <0>; + gpio-custom2 = <1>; + gpio-req-tbl-num = <0 1>; + gpio-req-tbl-flags = <0 0>; + gpio-req-tbl-label = "CAM_RESET1", + "CAM_CUSTOM2"; + cci-master = <0>; + status = "okay"; + }; +}; + +&cam_cci2 { + /*cam4-imx577*/ + qcom,cam-sensor27 { + cell-index = <27>; + compatible = "qcom,cam-sensor"; + csiphy-sd-index = <2>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&vreg_campin>; + regulator-names = "cam_vio"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_active_rst2>; + pinctrl-1 = <&cam_sensor_suspend_rst2>; + gpios = <&tlmm 82 0>; + gpio-reset = <0>; + gpio-req-tbl-num = <0>; + gpio-req-tbl-flags = <0>; + gpio-req-tbl-label = "CAM_RESET2"; + cci-master = <0>; + status = "okay"; + }; +}; + +&soc { + vreg_campin: regulator-dbb1 { + compatible = "regulator-fixed"; + regulator-name = "vreg_campin"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "okay"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera.dtsi b/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera.dtsi new file mode 100644 index 0000000000000..50cd23538a77e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camera.dtsi @@ -0,0 +1,2593 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include + +&tlmm { + cci_i2c_sda0_active: cci_i2c_sda0_active { + mux { + /* CLK, DATA */ + pins = "gpio57"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio57"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda0_suspend: cci_i2c_sda0_suspend { + mux { + /* CLK, DATA */ + pins = "gpio57"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio57"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl0_active: cci_i2c_scl0_active { + mux { + /* CLK, DATA */ + pins = "gpio58"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio58"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl0_suspend: cci_i2c_scl0_suspend { + mux { + /* CLK, DATA */ + pins = "gpio58"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio58"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda1_active: cci_i2c_sda1_active { + mux { + /* CLK, DATA */ + pins = "gpio29"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio29"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda1_suspend: cci_i2c_sda1_suspend { + mux { + /* CLK, DATA */ + pins = "gpio29"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio29"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl1_active: cci_i2c_scl1_active { + mux { + /* CLK, DATA */ + pins = "gpio30"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio30"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl1_suspend: cci_i2c_scl1_suspend { + mux { + /* CLK, DATA */ + pins = "gpio30"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio30"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda2_active: cci_i2c_sda2_active { + mux { + /* CLK, DATA */ + pins = "gpio59"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio59"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda2_suspend: cci_i2c_sda2_suspend { + mux { + /* CLK, DATA */ + pins = "gpio59"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio59"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl2_active: cci_i2c_scl2_active { + mux { + /* CLK, DATA */ + pins = "gpio60"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio60"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl2_suspend: cci_i2c_scl2_suspend { + mux { + /* CLK, DATA */ + pins = "gpio60"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio60"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda3_active: cci_i2c_sda3_active { + mux { + pins = "gpio31"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio31"; + bias-disable; + drive-strength = <2>; + input-enable; + }; + }; + + cci_i2c_sda3_suspend: cci_i2c_sda3_suspend { + mux { + pins = "gpio31"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio31"; + bias-disable; + drive-strength = <2>; + input-enable; + }; + }; + + cci_i2c_scl3_active: cci_i2c_scl3_active { + mux { + pins = "gpio32"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio32"; + bias-disable; + drive-strength = <2>; + input-enable; + }; + }; + + cci_i2c_scl3_suspend: cci_i2c_scl3_suspend { + mux { + pins = "gpio32"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio32"; + bias-disable; + drive-strength = <2>; + input-enable; + }; + }; + + cci_i2c_sda4_active: cci_i2c_sda4_active { + mux { + /* CLK, DATA */ + pins = "gpio61"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio61"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda4_suspend: cci_i2c_sda4_suspend { + mux { + /* CLK, DATA */ + pins = "gpio61"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio61"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl4_active: cci_i2c_scl4_active { + mux { + /* CLK, DATA */ + pins = "gpio62"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio62"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl4_suspend: cci_i2c_scl4_suspend { + mux { + /* CLK, DATA */ + pins = "gpio62"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio62"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_sda5_active: cci_i2c_sda5_active { + mux { + /* CLK, DATA */ + pins = "gpio54"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio54"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_sda5_suspend: cci_i2c_sda5_suspend { + mux { + /* CLK, DATA */ + pins = "gpio54"; + function = "cci_i2c_sda"; + }; + + config { + pins = "gpio54"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cci_i2c_scl5_active: cci_i2c_scl5_active { + mux { + /* CLK, DATA */ + pins = "gpio55"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio55"; + bias-pull-up; /* PULL UP*/ + drive-strength = <2>; /* 2 MA */ + qcom,i2c_pull; + }; + }; + + cci_i2c_scl5_suspend: cci_i2c_scl5_suspend { + mux { + /* CLK, DATA */ + pins = "gpio55"; + function = "cci_i2c_scl"; + }; + + config { + pins = "gpio55"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_active: cam_sensor_mclk0_active { + /* MCLK0 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_suspend: cam_sensor_mclk0_suspend { + /* MCLK0 */ + mux { + pins = "gpio67"; + function = "cam_mclk"; + }; + + config { + pins = "gpio67"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_active: cam_sensor_mclk1_active { + /* MCLK1 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_suspend: cam_sensor_mclk1_suspend { + /* MCLK1 */ + mux { + pins = "gpio68"; + function = "cam_mclk"; + }; + + config { + pins = "gpio68"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_active_rst0: cam_sensor_active_rst0 { + /* RESET */ + mux { + pins = "gpio64"; + function = "gpio"; + }; + + config { + pins = "gpio64"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst0: cam_sensor_suspend_rst0 { + /* RESET */ + mux { + pins = "gpio64"; + function = "gpio"; + }; + + config { + pins = "gpio64"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_active_rst1: cam_sensor_active_rst1 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + + config { + pins = "gpio75"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst1: cam_sensor_suspend_rst1 { + /* RESET */ + mux { + pins = "gpio75"; + function = "gpio"; + }; + config { + pins = "gpio75"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + + cam_sensor_active_rst2: cam_sensor_active_rst2 { + /* RESET */ + mux { + pins = "gpio82"; + function = "gpio"; + }; + + config { + pins = "gpio82"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_suspend_rst2: cam_sensor_suspend_rst2 { + /* RESET */ + mux { + pins = "gpio82"; + function = "gpio"; + }; + config { + pins = "gpio82"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + +}; + +&soc { + qcom,camera-main { + compatible = "qcom,camera"; + status = "okay"; + }; + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + status = "okay"; + }; + + qcom,cam-sync { + compatible = "qcom,cam-sync"; + status = "okay"; + }; + + qcom,cam-i3c-id-table { + i3c-sensor-id-table = <0x1B0 0x0766>; + i3c-eeprom-id-table = <>; + i3c-actuator-id-table = <>; + i3c-ois-id-table = <>; + status = "disabled"; + }; + + cam_csiphy_tpg13: qcom,tpg13@acac000 { + cell-index = <13>; + phy-id = <0>; + compatible = "qcom,cam-tpg1031"; + reg-names = "tpg0", "cam_cpas_top"; + reg = <0x0 0x0acac000 0x0 0x0400>, + <0x0 0x0ac11000 0x0 0x1000>; + reg-cam-base = <0xac000 0x11000>; + operating-points-v2 = <&csiphy_tpg0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupt-names = "tpg0"; + interrupts = ; + shared-clks = <1 0>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + status = "okay"; + + csiphy_tpg0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg14: qcom,tpg14@acad000 { + cell-index = <14>; + phy-id = <1>; + compatible = "qcom,cam-tpg1031"; + reg-names = "tpg1", "cam_cpas_top"; + reg = <0x0 0x0acad000 0x0 0x0400>, + <0x0 0x0ac11000 0x0 0x1000>; + reg-cam-base = <0xad000 0x11000>; + operating-points-v2 = <&csiphy_tpg1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupt-names = "tpg1"; + interrupts = ; + shared-clks = <1 0>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + status = "okay"; + + csiphy_tpg1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy_tpg15: qcom,tpg15@acae000 { + cell-index = <15>; + phy-id = <2>; + compatible = "qcom,cam-tpg1031"; + reg-names = "tpg2", "cam_cpas_top"; + reg = <0x0 0x0acae000 0x0 0x0400>, + <0x0 0x0ac11000 0x0 0x1000>; + reg-cam-base = <0xae000 0x11000>; + operating-points-v2 = <&csiphy_tpg2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + interrupt-names = "tpg2"; + interrupts = ; + shared-clks = <1 0>; + clock-names = "cphy_rx_clk_src", + "csid_csiphy_rx_clk"; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-rates = <400000000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cphy_rx_clk_src"; + status = "okay"; + + csiphy_tpg2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy0: qcom,csiphy0@ac9c000 { + cell-index = <0>; + aggregator-rx; + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0x0ac9c000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy0_opp_table>; + reg-cam-base = <0x9c000>; + interrupt-names = "CSIPHY0"; + interrupts = ; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clock-names = "cphy_rx_clk_src", + "csiphy0_clk", + "csi0phytimer_clk_src", + "csi0phytimer_clk"; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + status = "okay"; + + csiphy0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy1: qcom,csiphy1@ac9e000 { + cell-index = <1>; + aggregator-rx; + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0x0ac9e000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy1_opp_table>; + reg-cam-base = <0x9e000>; + interrupt-names = "CSIPHY1"; + interrupts = ; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clock-names = "cphy_rx_clk_src", + "csiphy1_clk", + "csi1phytimer_clk_src", + "csi1phytimer_clk"; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + status = "okay"; + + csiphy1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_csiphy2: qcom,csiphy2@aca0000 { + cell-index = <2>; + aggregator-rx; + compatible = "qcom,csiphy-v1.3.0", "qcom,csiphy"; + reg = <0x0 0x0aca0000 0x0 0x2000>; + reg-names = "csiphy"; + operating-points-v2 = <&csiphy2_opp_table>; + reg-cam-base = <0xa0000>; + interrupt-names = "CSIPHY2"; + interrupts = ; + csi-vdd-1p2-supply = <&vreg_l5a>; + csi-vdd-0p9-supply = <&vreg_l4a>; + regulator-names = "csi-vdd-1p2", "csi-vdd-0p9"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 880000>; + rgltr-max-voltage = <1200000 912000>; + rgltr-load-current = <8900 15900>; + shared-clks = <1 0 0 0>; + clock-names = "cphy_rx_clk_src", + "csiphy2_clk", + "csi2phytimer_clk_src", + "csi2phytimer_clk"; + clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + src-clock-name = "cphy_rx_clk_src"; + clock-cntl-level = "lowsvs"; + clock-rates = <400000000 0 400000000 0>; + status = "okay"; + + csiphy2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + cam_cci0: qcom,cci0@ac13000 { + cell-index = <0>; + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0x0ac13000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x13000>; + interrupt-names = "CCI0"; + interrupts = ; + operating-points-v2 = <&cci0_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cci_0_clk_src", + "cci_0_clk"; + clocks = <&camcc CAM_CC_CCI_0_CLK_SRC>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_0_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci_i2c_scl0_active &cci_i2c_sda0_active>; + pinctrl-1 = <&cci_i2c_scl0_suspend &cci_i2c_sda0_suspend>; + pinctrl-2 = <&cci_i2c_scl1_active &cci_i2c_sda1_active>; + pinctrl-3 = <&cci_i2c_scl1_suspend &cci_i2c_sda1_suspend>; + status = "okay"; + + cci0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_100Khz_cci0: qcom,i2c_standard_mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci0: qcom,i2c_fast_mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_custom_cci0: qcom,i2c_custom_mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci0: qcom,i2c_fast_plus_mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cci1: qcom,cci1@ac14000 { + cell-index = <1>; + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0x0ac14000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x14000>; + interrupt-names = "CCI1"; + interrupts = ; + operating-points-v2 = <&cci1_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cci_1_clk_src", + "cci_1_clk"; + clocks = <&camcc CAM_CC_CCI_1_CLK_SRC>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_1_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0"; + pinctrl-names = "m0_active", "m0_suspend"; + pinctrl-0 = <&cci_i2c_scl2_active &cci_i2c_sda2_active>; + pinctrl-1 = <&cci_i2c_scl2_suspend &cci_i2c_sda2_suspend>; + pinctrl-2 = <&cci_i2c_scl3_active &cci_i2c_sda3_active>; + pinctrl-3 = <&cci_i2c_scl3_suspend &cci_i2c_sda3_suspend>; + status = "okay"; + + cci1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_100Khz_cci1: qcom,i2c_standard_mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci1: qcom,i2c_fast_mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_custom_cci1: qcom,i2c_custom_mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci1: qcom,i2c_fast_plus_mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + cam_cci2: qcom,cci2@ac15000 { + cell-index = <2>; + compatible = "qcom,cci", "simple-bus"; + reg = <0x0 0x0ac15000 0x0 0x1000>; + reg-names = "cci"; + reg-cam-base = <0x15000>; + interrupt-names = "CCI2"; + interrupts = ; + operating-points-v2 = <&cci2_opp_table>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cci_2_clk_src", + "cci_2_clk"; + clocks = <&camcc CAM_CC_CCI_2_CLK_SRC>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-rates = <37500000 0>; + clock-cntl-level = "lowsvs"; + src-clock-name = "cci_2_clk_src"; + pctrl-idx-mapping = ; + pctrl-map-names = "m0", "m1"; + pinctrl-names = "m0_active", "m0_suspend", + "m1_active", "m1_suspend"; + pinctrl-0 = <&cci_i2c_scl4_active &cci_i2c_sda4_active>; + pinctrl-1 = <&cci_i2c_scl4_suspend &cci_i2c_sda4_suspend>; + pinctrl-2 = <&cci_i2c_scl5_active &cci_i2c_sda5_active>; + pinctrl-3 = <&cci_i2c_scl5_suspend &cci_i2c_sda5_suspend>; + status = "okay"; + + cci2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-37500000 { + opp-hz = /bits/ 64 <37500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + + i2c_freq_100Khz_cci2: qcom,i2c_standard_mode { + hw-thigh = <201>; + hw-tlow = <174>; + hw-tsu-sto = <204>; + hw-tsu-sta = <231>; + hw-thd-dat = <22>; + hw-thd-sta = <162>; + hw-tbuf = <227>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_400Khz_cci2: qcom,i2c_fast_mode { + hw-thigh = <38>; + hw-tlow = <56>; + hw-tsu-sto = <40>; + hw-tsu-sta = <40>; + hw-thd-dat = <22>; + hw-thd-sta = <35>; + hw-tbuf = <62>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_custom_cci2: qcom,i2c_custom_mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + + i2c_freq_1Mhz_cci2: qcom,i2c_fast_plus_mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <24>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "okay"; + }; + }; + + qcom,cam_smmu { + compatible = "qcom,msm-cam-smmu", "simple-bus"; + status = "okay"; + force_cache_allocs; + + msm_cam_smmu_ife { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x2400 0x0020>, + <&apps_smmu 0x2420 0x0020>; + cam-smmu-label = "ife", "sfe"; + multiple-client-devices; + dma-coherent; + + ife_iova_mem_map: iova-mem-map { + /* IO region is approximately 64 GB */ + iova-mem-region-io { + iova-region-name = "io"; + /* start address: 0x100000 */ + /* leaving 1 MB pad at start */ + iova-region-start = <0x100000>; + /* Length: 0xfffe00000 */ + /* leaving 1 MB pad at end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm_cam_smmu_icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = + <&apps_smmu 0x0800 0x400>, + <&apps_smmu 0x0840 0x480>, + <&apps_smmu 0x08C0 0x480>, + <&apps_smmu 0x0C00 0x400>, + <&apps_smmu 0x0C40 0x480>, + <&apps_smmu 0x0CC0 0x480>; + cam-smmu-label = "icp"; + qcom,iommu-faults = "stall-disable", "non-fatal"; + dma-coherent; + + icp_iova_mem_map: iova-mem-map { + iova-mem-region-shared { + /* Shared region is ~250MB long */ + iova-region-name = "shared"; + iova-region-start = <0x800000>; + iova-region-len = <0xfc00000>; + iova-region-id = <0x1>; + status = "okay"; + }; + + iova-mem-region-fwuncached-region { + /* FW uncached region is 7MB long */ + iova-region-name = "fw_uncached"; + iova-region-start = <0x10400000>; + iova-region-len = <0x700000>; + iova-region-id = <0x6>; + subregion_support; + status = "okay"; + /* Used for HFI queues/sec heap */ + iova-mem-region-generic-region { + iova-region-name = "icp_hfi"; + iova-region-start = <0x10400000>; + iova-region-len = <0x200000>; + iova-region-id = <0x0>; + }; + }; + + iova-mem-region-io { + /* IO region is approximately 3.8 GB */ + iova-region-name = "io"; + iova-region-start = <0x10c00000>; + iova-region-len = <0xee300000>; + iova-region-id = <0x3>; + status = "okay"; + }; + + iova-mem-qdss-region { + /* QDSS region is appropriate 1MB */ + iova-region-name = "qdss"; + iova-region-start = <0x10b00000>; + iova-region-len = <0x100000>; + iova-region-id = <0x5>; + qdss-phy-addr = <0x16790000>; + status = "okay"; + }; + }; + }; + + msm_cam_smmu_cdm { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x0860 0x400>, + <&apps_smmu 0x0C60 0x400>; + cam-smmu-label = "rt-cdm"; + dma-coherent; + multiple-client-devices; + + rt_cdm_iova_mem_map: iova-mem-map { + iova-mem-region-io { + /* IO region is approximately 4.0 GB */ + iova-region-name = "io"; + /* 1 MB pad for start */ + iova-region-start = <0x100000>; + /* 1 MB pad for end */ + iova-region-len = <0xffe00000>; + iova-region-id = <0x3>; + status = "okay"; + }; + }; + }; + + msm_cam_smmu_secure { + compatible = "qcom,msm-cam-smmu-cb"; + cam-smmu-label = "cam-secure"; + qcom,secure-cb; + }; + }; + + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + cell-index = <0>; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe"; + status = "okay"; + }; + + qcom,rt-cdm0 { + cell-index = <0>; + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0x0ac26000 0x0 0x1000>; + reg-names = "rt-cdm0"; + reg-cam-base = <0x26000>; + interrupts = ; + interrupt-names = "rt-cdm0"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table0>; + clock-cntl-level = "svs"; + cdm-client-names = "ife0", "dualife0"; + single-context-cdm; + status = "okay"; + + cdm_cpas_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm1 { + cell-index = <1>; + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0x0ac27000 0x0 0x1000>; + reg-names = "rt-cdm1"; + reg-cam-base = <0x27000>; + interrupts = ; + interrupt-names = "rt-cdm1"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <300000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table1>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife1", "dualife1"; + single-context-cdm; + status = "okay"; + + cdm_cpas_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm2 { + cell-index = <2>; + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0x0ac28000 0x0 0x1000>; + reg-names = "rt-cdm2"; + reg-cam-base = <0x28000>; + interrupts = ; + interrupt-names = "rt-cdm2"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table2>; + clock-cntl-level = "svs_l1"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + status = "okay"; + + cdm_cpas_opp_table2: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,rt-cdm3 { + cell-index = <3>; + compatible = "qcom,cam-rt-cdm2_1"; + label = "rt-cdm"; + reg = <0x0 0x0ac29000 0x0 0x1000>; + reg-names = "rt-cdm3"; + reg-cam-base = <0x29000>; + interrupts = ; + interrupt-names = "rt-cdm3"; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk"; + clocks = <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + src-clock-name = "cam_cc_slow_ahb_clk_src"; + clock-rates = <80000000 0>; + operating-points-v2 = <&cdm_cpas_opp_table3>; + clock-cntl-level = "svs"; + cdm-client-names = "ife2", "ife3", "ife4", "ife5", "ife6"; + single-context-cdm; + status = "okay"; + + cdm_cpas_opp_table3: opp-table { + compatible = "operating-points-v2"; + + opp-80000000 { + opp-hz = /bits/ 64 <80000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + }; + }; + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "okay"; + }; + + cam_csid0: qcom,csid0 { + cell-index = <0>; + compatible = "qcom,csid692"; + reg-names = "csid0", "csid_top"; + reg = <0x0 0x0ac7a000 0x0 0x0f01>, + <0x0 0x0ac78000 0x0 0x1000>; + reg-cam-base = <0x7a000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupt-names = "csid0"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid0_opp_table>; + clock-control-debugfs = "true"; + status = "okay"; + + csid0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_vfe0: qcom,ife0 { + cell-index = <0>; + compatible = "qcom,vfe692"; + reg-names = "ife0", "cam_camnoc"; + reg = <0x0 0x0ac4d000 0x0 0xf000>, + <0x0 0x0ac1a000 0x0 0x9400>; + reg-cam-base = <0x4d000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupt-names = "ife0"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_0_clk", + "cam_cc_ife_0_clk", + "cam_cc_ife_0_clk_src", + "cam_cc_ife_0_fast_ahb_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_CLK_SRC>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_0_clk_src"; + operating-points-v2 = <&vfe0_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <8 16>; + status = "okay"; + + vfe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid1: qcom,csid1 { + cell-index = <1>; + compatible = "qcom,csid692"; + reg-names = "csid1", "csid_top"; + reg = <0x0 0x0ac7c000 0x0 0x0f01>, + <0x0 0x0ac78000 0x0 0x1000>; + reg-cam-base = <0x7c000 0x78000>; + rt-wrapper-base = <0x4d000>; + interrupt-names = "csid1"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_csid_clk_src", + "cam_cc_csid_clk", + "cam_cc_csid_csiphy_rx_clk"; + clocks = <&camcc CAM_CC_CSID_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>; + clock-rates = <400000000 0 0>; + clock-cntl-level = "svs_l1"; + src-clock-name = "cam_cc_csid_clk_src"; + operating-points-v2 = <&csid1_opp_table>; + clock-control-debugfs = "true"; + status = "okay"; + + csid1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + cam_vfe1: qcom,ife1 { + cell-index = <1>; + compatible = "qcom,vfe692"; + reg-names = "ife1", "cam_camnoc"; + reg = <0x0 0x0ac60000 0x0 0xf000>, + <0x0 0x0ac1a000 0x0 0x9400>; + reg-cam-base = <0x60000 0x1a000>; + rt-wrapper-base = <0x4d000>; + interrupt-names = "ife1"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_1_clk", + "cam_cc_ife_1_clk", + "cam_cc_ife_1_clk_src", + "cam_cc_ife_1_fast_ahb_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_CLK_SRC>, + <&camcc CAM_CC_IFE_1_FAST_AHB_CLK>; + clock-rates = <0 0 480000000 0>, + <0 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_1_clk_src"; + operating-points-v2 = <&vfe1_opp_table>; + clock-control-debugfs = "true"; + ubwc-static-cfg = <0x1026 0x1036>; + cam_hw_pid = <9 17>; + status = "okay"; + + vfe1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite0: qcom,csid-lite0 { + cell-index = <2>; + compatible = "qcom,csid-lite692"; + reg-names = "csid-lite0"; + reg = <0x0 0x0ac84000 0x0 0x0f01>; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "csid-lite0"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite0_opp_table>; + + clock-control-debugfs = "true"; + status = "okay"; + + csid_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite0: qcom,ife-lite0 { + cell-index = <2>; + compatible = "qcom,vfe-lite692"; + reg-names = "ife-lite0"; + reg = <0x0 0x0ac84000 0x0 0x1d00>; + reg-cam-base = <0x84000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "ife-lite0"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite0_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + status = "okay"; + + vfe_lite0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite1: qcom,csid-lite1 { + cell-index = <3>; + compatible = "qcom,csid-lite692"; + reg-names = "csid-lite1"; + reg = <0x0 0x0ac88000 0x0 0x0f01>; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "csid-lite1"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite1_opp_table>; + + clock-control-debugfs = "true"; + status = "okay"; + + csid_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite1: qcom,ife-lite1 { + cell-index = <3>; + compatible = "qcom,vfe-lite692"; + reg-names = "ife-lite1"; + reg = <0x0 0x0ac88000 0x0 0x1d00>; + reg-cam-base = <0x88000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "ife-lite1"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite1_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + status = "okay"; + + vfe_lite1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite2: qcom,csid-lite2 { + cell-index = <4>; + compatible = "qcom,csid-lite692"; + reg-names = "csid-lite2"; + reg = <0x0 0x0ac8c000 0x0 0x0f01>; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "csid-lite2"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite2_opp_table>; + + clock-control-debugfs = "true"; + status = "okay"; + + csid_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite2: qcom,ife-lite2 { + cell-index = <4>; + compatible = "qcom,vfe-lite692"; + reg-names = "ife-lite2"; + reg = <0x0 0x0ac8c000 0x0 0x1d00>; + reg-cam-base = <0x8c000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "ife-lite2"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite2_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + status = "okay"; + + vfe_lite2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite3: qcom,csid-lite3 { + cell-index = <5>; + compatible = "qcom,csid-lite692"; + reg-names = "csid-lite3"; + reg = <0x0 0x0ac90000 0x0 0x0f01>; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "csid-lite3"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite3_opp_table>; + + clock-control-debugfs = "true"; + status = "okay"; + + csid_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite3: qcom,ife-lite3 { + cell-index = <5>; + compatible = "qcom,vfe-lite692"; + reg-names = "ife-lite3"; + reg = <0x0 0x0ac90000 0x0 0x1d00>; + reg-cam-base = <0x90000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "ife-lite3"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite3_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + status = "okay"; + + vfe_lite3_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_csid_lite4: qcom,csid-lite4 { + cell-index = <6>; + compatible = "qcom,csid-lite692"; + reg-names = "csid-lite4"; + reg = <0x0 0x0ac94000 0x0 0x0f01>; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "csid-lite4"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_csid_clk_src"; + operating-points-v2 = <&csid_lite4_opp_table>; + + clock-control-debugfs = "true"; + status = "okay"; + + csid_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_vfe_lite4: qcom,ife-lite4 { + cell-index = <6>; + compatible = "qcom,vfe-lite692"; + reg-names = "ife-lite4"; + reg = <0x0 0x0ac94000 0x0 0x1d00>; + reg-cam-base = <0x94000>; + rt-wrapper-base = <0x83000>; + interrupt-names = "ife-lite4"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_cpas_ife_lite_clk", + "cam_cc_ife_lite_ahb_clk", + "cam_cc_ife_lite_csid_clk_src", + "cam_cc_ife_lite_csid_clk", + "cam_cc_ife_lite_cphy_rx_clk", + "cam_cc_ife_lite_clk_src", + "cam_cc_ife_lite_clk"; + clocks = <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK_SRC>, + <&camcc CAM_CC_IFE_LITE_CLK>; + clock-rates = <0 0 400000000 0 0 400000000 0>, + <0 0 400000000 0 0 480000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_ife_lite_clk_src"; + operating-points-v2 = <&vfe_lite4_opp_table>; + clock-control-debugfs = "true"; + cam_hw_pid = <27>; + status = "okay"; + + vfe_lite4_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe_lite0: qcom,sfe-lite0 { + cell-index = <0>; + compatible = "qcom,sfe-lite692"; + reg-names = "sfe-lite0"; + reg = <0x0 0x0ac74000 0x0 0x1000>; + reg-cam-base = <0x74000>; + rt-wrapper-base = <0x4d000>; + interrupt-names = "sfe-lite0"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_sfe_lite_0_fast_ahb_clk", + "cam_cc_sfe_lite_0_clk", + "cam_cc_cpas_sfe_lite_0_clk"; + clocks = <&camcc CAM_CC_SFE_LITE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_0_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_0_CLK>; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_0_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table0>; + cam_hw_pid = <4>; + clock-control-debugfs = "true"; + status = "okay"; + + cam_sfe_lite_opp_table0: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_sfe_lite1: qcom,sfe-lite1 { + cell-index = <1>; + compatible = "qcom,sfe-lite692"; + reg-names = "sfe-lite1"; + reg = <0x0 0x0ac75000 0x0 0x1000>; + reg-cam-base = <0x75000>; + rt-wrapper-base = <0x4d000>; + interrupt-names = "sfe-lite1"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "cam_cc_sfe_lite_1_fast_ahb_clk", + "cam_cc_sfe_lite_1_clk", + "cam_cc_cpas_sfe_1_clk"; + clocks = <&camcc CAM_CC_SFE_LITE_1_FAST_AHB_CLK>, + <&camcc CAM_CC_SFE_LITE_1_CLK>, + <&camcc CAM_CC_CPAS_SFE_LITE_1_CLK>; + clock-rates = <0 480000000 300000000>, + <0 600000000 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + src-clock-name = "cam_cc_sfe_lite_1_clk"; + operating-points-v2 = <&cam_sfe_lite_opp_table1>; + cam_hw_pid = <5>; + clock-control-debugfs = "true"; + status = "okay"; + + cam_sfe_lite_opp_table1: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_icp_firmware: qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,icp", + "qcom,ipe0"; + num-icp = <1>; + num-ipe = <1>; + icp_use_pil; + status = "okay"; + }; + + cam_icp: qcom,icp { + cell-index = <0>; + compatible = "qcom,cam-icp_v3_0"; + icp-version = <0x0300>; + + reg-names ="icp_csr", "icp_cirq", "icp_wd0"; + reg = <0x0 0x0ac01000 0x0 0x0400>, + <0x0 0x0ac01800 0x0 0x0400>, + <0x0 0x0ac04000 0x0 0x1000>; + reg-cam-base = <0x1000 0x1800 0x4000>; + interrupt-names = "icp"; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + memory-region = <&camera_mem>; + clock-names = "cam_cc_soc_fast_ahb_clk_src", + "cam_cc_icp_ahb_clk", + "cam_cc_icp_clk_src", + "cam_cc_icp_clk"; + src-clock-name = "cam_cc_icp_clk_src"; + clocks = <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_ICP_AHB_CLK>, + <&camcc CAM_CC_ICP_CLK_SRC>, + <&camcc CAM_CC_ICP_CLK>; + clock-rates = <300000000 0 480000000 0>, + <400000000 0 600000000 0>; + clock-cntl-level = "svs_l1", "nominal"; + nrt-device; + fw_name = "qcom/qcs8300/CAMERA_ICP"; + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + qos-val = <0xa0a>; + operating-points-v2 = <&icp_opp_table>; + cam_hw_pid = <12>; + status = "okay"; + + icp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + cam_ipe0: qcom,ipe0 { + cell-index = <0>; + compatible = "qcom,cam-ipe"; + reg-names = "ipe0_top"; + reg = <0x0 0x0ac2d000 0x0 0x018000>; + reg-cam-base = <0x2d000>; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + clock-names = "cam_cc_cpas_ipe_clk", + "cam_cc_ipe_ahb_clk", + "cam_cc_ipe_clk", + "cam_cc_ipe_clk_src", + "cam_cc_ipe_fast_ahb_clk", + "cam_cc_fast_ahb_clk_src"; + src-clock-name = "cam_cc_ipe_clk_src"; + clocks = <&camcc CAM_CC_CPAS_IPE_CLK>, + <&camcc CAM_CC_IPE_AHB_CLK>, + <&camcc CAM_CC_IPE_CLK>, + <&camcc CAM_CC_IPE_CLK_SRC>, + <&camcc CAM_CC_IPE_FAST_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>; + clock-rates = <0 0 0 480000000 0 300000000>, + <0 0 0 600000000 0 400000000>; + clock-cntl-level = "svs_l1", "nominal"; + + operating-points-v2 = <&ipe0_opp_table>; + nrt-device; + cam_hw_pid = <14 15>; + status = "okay"; + + ipe0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + + }; + + cam_cpas: qcom,cam-cpas { + cell-index = <0>; + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + reg-names = "cam_cpas_top", "cam_camnoc", "cam_rpmh"; + reg = <0x0 0x0ac11000 0x0 0x1000>, + <0x0 0x0ac1A000 0x0 0x9400>, + <0x0 0x0bbf0000 0x0 0x1f00>; + reg-cam-base = <0x11000 0x1A000 0x0bbf0000>; + interrupt-names = "cpas_camnoc"; + interrupts = ; + camnoc-axi-min-ib-bw = <3000000000>; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clock-names = "gcc_camera_ahb_clk", + "gcc_camera_hf_axi_clk", + "gcc_camera_sf_axi_clk", + "cam_cc_slow_ahb_clk_src", + "cam_cc_cpas_ahb_clk", + "cam_cc_core_ahb_clk", + "cam_cc_fast_ahb_clk_src", + "cam_cc_cpas_fast_ahb_clk", + "cam_cc_camnoc_axi_clk_src", + "cam_cc_camnoc_axi_clk", + "cam_cc_qdss_debug_xo_clk"; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_FAST_AHB_CLK_SRC>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_CLK_SRC>, + <&camcc CAM_CC_CAMNOC_AXI_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + src-clock-name = "cam_cc_fast_ahb_clk_src"; + clock-rates = <0 0 0 0 0 0 0 0 0 0 0>, + <0 0 0 80000000 0 0 300000000 0 400000000 0 0>, + <0 0 0 80000000 0 0 400000000 0 400000000 0 0>; + clock-cntl-level = "suspend", "svs_l1", "nominal"; + clock-names-option = "cam_icp_clk"; + clocks-option = <&camcc CAM_CC_ICP_CLK>; + clock-rates-option = <480000000>; + operating-points-v2 = <&cpas_opp_table>; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <20>; + cam-icc-path-names = "cam_ahb"; + interconnect-names = "cam_ahb", + "cam_hf_0", + "cam_sf_0", + "cam_sf_icp"; + interconnects = <&gem_noc MASTER_APPSS_PROC 0 + &config_noc SLAVE_CAMERA_CFG 0>, + <&mmss_noc MASTER_CAMNOC_HF 0 + &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_SF 0 + &mc_virt SLAVE_EBI1 0>, + <&mmss_noc MASTER_CAMNOC_ICP 0 + &mc_virt SLAVE_EBI1 0>; + cam-ahb-num-cases = <7>; + cam-ahb-bw-KBps = <0 0>, + <0 76800>, + <0 150000>, + <0 150000>, + <0 300000>, + <0 300000>, + <0 300000>; + vdd-corners = ; + vdd-corner-ahb-mapping = "suspend", + "lowsvs", + "lowsvs", + "svs", + "svs_l1", + "nominal", + "nominal", + "nominal", + "turbo", + "turbo"; + client-id-based; + client-names = "csiphy0", + "csiphy1", + "csiphy2", + "cci0", + "cci1", + "cci2", + "csid0", + "csid1", + "csid2", + "csid3", + "csid4", + "csid5", + "csid6", + "ife0", + "ife1", + "ife2", + "ife3", + "ife4", + "ife5", + "ife6", + "ipe0", + "sfe0", + "sfe1", + "cam-cdm-intf0", + "rt-cdm0", + "rt-cdm1", + "rt-cdm2", + "rt-cdm3", + "icp0", + "tpg13", + "tpg14", + "tpg15"; + + status = "okay"; + enable-secure-qos-update; + + cpas_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + + camera-bus-nodes { + level3-nodes { + level-index = <3>; + + level3_rt_rd_wr_sum: level3-rt-rd-wr-sum { + cell-index = <0>; + node-name = "level3-rt-rd-wr-sum"; + traffic-merge-type =; + ib-bw-voting-needed; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_hf_0"; + }; + }; + + level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { + cell-index = <1>; + node-name = "level3-nrt0-rd-wr-sum"; + traffic-merge-type =; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_0"; + }; + }; + + level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { + cell-index = <2>; + node-name = "level3-nrt1-rd-wr-sum"; + traffic-merge-type =; + + qcom,axi-port-mnoc { + cam-icc-path-names = "cam_sf_icp"; + }; + }; + }; + + level2-nodes { + level-index = <2>; + camnoc-max-needed; + + level2_rt_wr0: level2-rt-wr0 { + cell-index = <3>; + node-name = "level2-rt-wr0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type =; + }; + + level2_rt_wr1: level2-rt-wr1 { + cell-index = <4>; + node-name = "level2-rt-wr1"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type =; + }; + + level2_nrt_wr2: level2-nrt-wr2 { + cell-index = <5>; + node-name = "level2-nrt-wr2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type =; + }; + + level2_rt_rd0: level2-rt-read0 { + cell-index = <6>; + node-name = "level2-rt-rd0"; + parent-node = <&level3_rt_rd_wr_sum>; + traffic-merge-type =; + }; + + level2_nrt_rd1: level2-nrt-rd1 { + cell-index = <7>; + node-name = "level2-nrt-rd1"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type =; + }; + + level2_nrt_rd2: level2-nrt-rd2 { + cell-index = <8>; + node-name = "level2-nrt-rd2"; + parent-node = <&level3_nrt0_rd_wr_sum>; + traffic-merge-type =; + }; + + level2_icp_rd: level2-icp-rd { + cell-index = <9>; + node-name = "level2-icp-rd"; + parent-node = <&level3_nrt1_rd_wr_sum>; + traffic-merge-type =; + }; + }; + + level1-nodes { + level-index = <1>; + camnoc-max-needed; + + level1_rt_wr0: level1-rt-wr0 { + cell-index = <10>; + node-name = "level1-rt-wr0"; + parent-node = <&level2_rt_wr0>; + traffic-merge-type =; + }; + + level1_rt_wr1: level1-rt-wr1 { + cell-index = <11>; + node-name = "level1-rt-wr1"; + parent-node = <&level2_rt_wr1>; + traffic-merge-type =; + }; + + level1_rt_rd0: level1-rt-read0 { + cell-index = <13>; + node-name = "level1-rt-rd0"; + parent-node = <&level2_rt_rd0>; + traffic-merge-type =; + }; + + level1_nrt_rd2: level1-nrt-rd2 { + cell-index = <15>; + node-name = "level1-nrt-rd2"; + parent-node = <&level2_nrt_rd2>; + traffic-merge-type =; + }; + }; + + level0-nodes { + level-index = <0>; + + ife_0_wr_0: ife-0-wr-0 { + cell-index = <16>; + node-name = "ife-0-wr-0"; + client-name = "ife0"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level1_rt_wr0>; + }; + + ife_1_wr_0: ife-1-wr-0 { + cell-index = <17>; + node-name = "ife-1-wr-0"; + client-name = "ife1"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_0_wr_0: ife-lite-0-wr-0 { + cell-index = <18>; + node-name = "ife-lite-0-wr-0"; + client-name = "ife2"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_1_wr_0: ife-lite-1-wr-0 { + cell-index = <19>; + node-name = "ife-lite-1-wr-0"; + client-name = "ife3"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_2_wr_0: ife-lite-2-wr-0 { + cell-index = <20>; + node-name = "ife-lite-2-wr-0"; + client-name = "ife4"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_3_wr_0: ife-lite-3-wr-0 { + cell-index = <21>; + node-name = "ife-lite-3-wr-0"; + client-name = "ife5"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level1_rt_wr0>; + }; + + ife_lite_4_wr_0: ife-lite-4-wr-0 { + cell-index = <22>; + node-name = "ife-lite-4-wr-0"; + client-name = "ife6"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level1_rt_wr0>; + }; + + ife_0_wr_1: ife-0-wr-1 { + cell-index = <23>; + node-name = "ife-0-wr-1"; + client-name = "ife0"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level1_rt_wr1>; + }; + + ife_1_wr_1: ife-1-wr-1 { + cell-index = <24>; + node-name = "ife-1-wr-1"; + client-name = "ife1"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level1_rt_wr1>; + }; + + sfe_0_rd_0: sfe-0-rd-0 { + cell-index = <25>; + node-name = "sfe-0-rd-0"; + client-name = "sfe0"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level1_rt_rd0>; + }; + + sfe_1_rd_0: sfe-1-rd-0 { + cell-index = <26>; + node-name = "sfe-1-rd-0"; + client-name = "sfe1"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level1_rt_rd0>; + }; + + ipe_0_wr_2: ipe-0-wr-2 { + cell-index = <27>; + node-name = "ipe-0-wr-2"; + client-name = "ipe0"; + traffic-data =; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level2_nrt_wr2>; + }; + + ipe_0_rd_all: ipe-0-rd-all { + cell-index = <28>; + node-name = "ipe-0-rd-all"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type =; + constituent-paths =; + parent-node = <&level2_nrt_rd1>; + }; + + rt_cdm0_all_rd_2: rt-cdm0-all-rd-2 { + cell-index = <29>; + node-name = "rt-cdm0-all-rd-2"; + client-name = "rt-cdm0"; + traffic-data = ; + traffic-transaction-type =; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm1_all_rd_2: rt-cdm1-all-rd-2 { + cell-index = <30>; + node-name = "rt-cdm1-all-rd-2"; + client-name = "rt-cdm1"; + traffic-data = ; + traffic-transaction-type =; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm2_all_rd_2: rt-cdm2-all-rd-2 { + cell-index = <31>; + node-name = "rt-cdm2-all-rd-2"; + client-name = "rt-cdm2"; + traffic-data = ; + traffic-transaction-type =; + parent-node = <&level1_nrt_rd2>; + }; + + rt_cdm3_all_rd_2: rt-cdm3-all-rd-2 { + cell-index = <32>; + node-name = "rt-cdm3-all-rd-2"; + client-name = "rt-cdm3"; + traffic-data = ; + traffic-transaction-type =; + parent-node = <&level1_nrt_rd2>; + }; + + ipe_cdm0_all_rd: ipe-cdm0-all-rd { + cell-index = <33>; + node-name = "ipe-cdm0-all-rd"; + client-name = "ipe0"; + traffic-data = ; + traffic-transaction-type =; + parent-node = <&level1_nrt_rd2>; + }; + + icp_all_rd: icp-all-rd { + cell-index = <34>; + node-name = "icp-all-rd"; + client-name = "icp0"; + traffic-data = ; + traffic-transaction-type =; + parent-node = <&level2_icp_rd>; + }; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camx-el2.dtso b/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camx-el2.dtso new file mode 100644 index 0000000000000..50631160d5a79 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camx-el2.dtso @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "monaco-arduino-monza-camera.dtsi" +#include "monaco-arduino-monza-camera-el2.dtsi" +#include "monaco-arduino-monza-camera-sensor.dtsi" diff --git a/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camx.dtso b/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camx.dtso new file mode 100644 index 0000000000000..7862322604a9d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-arduino-monza-camx.dtso @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +/dts-v1/; +/plugin/; + +#include +#include +#include +#include +#include + +#include "monaco-arduino-monza-camera.dtsi" +#include "monaco-arduino-monza-camera-sensor.dtsi" From fca2d2c7cda0b74fdcf742b3cd8c081833c07587 Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Sun, 18 Oct 2026 01:32:12 +0530 Subject: [PATCH 0780/1133] QCLINUX: arm64: dts: qcom: nord: Update vfe-lite reg base address The camera application sends ISP and CSID commands for each lite instance into one shared register range, not two separate ranges. So the ISP and CSID register maps for a given lite instance must both start at the same base address. Right now each vfe-lite node starts at its own base address, different from its matching csid-lite node. Update each vfe-lite0 to vfe-lite9 node to start at the same base address as its matching csid-lite node, and increase its size so it still ends at the same address as before. Other camera dtsi files for this SoC family already map their lite instances the same way. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/nord-camera.dtsi | 40 +++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/nord-camera.dtsi b/arch/arm64/boot/dts/qcom/nord-camera.dtsi index 309ddecd9c1e4..25463807474f9 100644 --- a/arch/arm64/boot/dts/qcom/nord-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-camera.dtsi @@ -2152,9 +2152,9 @@ cam_vfe_lite0: qcom,ife-lite0@9c34000 { compatible = "qcom,vfe-lite900"; - reg = <0x0 0x9c34000 0x0 0x1480>; + reg = <0x0 0x09c32000 0x0 0x3480>; reg-names = "ife-lite0"; - reg-cam-base = <0x234000>; + reg-cam-base = <0x232000>; rt-wrapper-base = <0x231000>; interrupts = ; interrupt-names = "ife-lite0"; @@ -2261,9 +2261,9 @@ cam_vfe_lite1: qcom,ife-lite1@9c39000 { compatible = "qcom,vfe-lite900"; - reg = <0x0 0x9c39000 0x0 0x1480>; + reg = <0x0 0x09c37000 0x0 0x3480>; reg-names = "ife-lite1"; - reg-cam-base = <0x239000>; + reg-cam-base = <0x237000>; rt-wrapper-base = <0x231000>; interrupts = ; interrupt-names = "ife-lite1"; @@ -2370,9 +2370,9 @@ cam_vfe_lite2: qcom,ife-lite2@9c3e000 { compatible = "qcom,vfe-lite900"; - reg = <0x0 0x9c3e000 0x0 0x1480>; + reg = <0x0 0x09c3c000 0x0 0x3480>; reg-names = "ife-lite2"; - reg-cam-base = <0x23e000>; + reg-cam-base = <0x23c000>; rt-wrapper-base = <0x231000>; interrupts = ; interrupt-names = "ife-lite2"; @@ -2479,9 +2479,9 @@ cam_vfe_lite3: qcom,ife-lite3@9c43000 { compatible = "qcom,vfe-lite900"; - reg = <0x0 0x9c43000 0x0 0x1480>; + reg = <0x0 0x09c41000 0x0 0x3480>; reg-names = "ife-lite3"; - reg-cam-base = <0x243000>; + reg-cam-base = <0x241000>; rt-wrapper-base = <0x231000>; interrupts = ; interrupt-names = "ife-lite3"; @@ -2588,9 +2588,9 @@ cam_vfe_lite4: qcom,ife-lite4@9c48000 { compatible = "qcom,vfe-lite900"; - reg = <0x0 0x9c48000 0x0 0x1480>; + reg = <0x0 0x09c46000 0x0 0x3480>; reg-names = "ife-lite4"; - reg-cam-base = <0x248000>; + reg-cam-base = <0x246000>; rt-wrapper-base = <0x231000>; interrupts = ; interrupt-names = "ife-lite4"; @@ -2697,9 +2697,9 @@ cam_vfe_lite5: qcom,ife-lite5@9c4d000 { compatible = "qcom,vfe-lite900"; - reg = <0x0 0x9c4d000 0x0 0x1480>; + reg = <0x0 0x09c4b000 0x0 0x3480>; reg-names = "ife-lite5"; - reg-cam-base = <0x24d000>; + reg-cam-base = <0x24b000>; rt-wrapper-base = <0x231000>; interrupts = ; interrupt-names = "ife-lite5"; @@ -2806,9 +2806,9 @@ cam_vfe_lite6: qcom,ife-lite6@9c52000 { compatible = "qcom,vfe-lite900"; - reg = <0x0 0x9c52000 0x0 0x1480>; + reg = <0x0 0x09c50000 0x0 0x3480>; reg-names = "ife-lite6"; - reg-cam-base = <0x252000>; + reg-cam-base = <0x250000>; rt-wrapper-base = <0x231000>; interrupts = ; interrupt-names = "ife-lite6"; @@ -2915,9 +2915,9 @@ cam_vfe_lite7: qcom,ife-lite7@9c57000 { compatible = "qcom,vfe-lite900"; - reg = <0x0 0x9c57000 0x0 0x1480>; + reg = <0x0 0x09c55000 0x0 0x3480>; reg-names = "ife-lite7"; - reg-cam-base = <0x257000>; + reg-cam-base = <0x255000>; rt-wrapper-base = <0x231000>; interrupts = ; interrupt-names = "ife-lite7"; @@ -3024,9 +3024,9 @@ cam_vfe_lite8: qcom,ife-lite8@9c5c000 { compatible = "qcom,vfe-lite900"; - reg = <0x0 0x9c5c000 0x0 0x1480>; + reg = <0x0 0x09c5a000 0x0 0x3480>; reg-names = "ife-lite8"; - reg-cam-base = <0x25c000>; + reg-cam-base = <0x25a000>; rt-wrapper-base = <0x231000>; interrupts = ; interrupt-names = "ife-lite8"; @@ -3133,9 +3133,9 @@ cam_vfe_lite9: qcom,ife-lite9@9c61000 { compatible = "qcom,vfe-lite900"; - reg = <0x0 0x9c61000 0x0 0x1480>; + reg = <0x0 0x09c5f000 0x0 0x3480>; reg-names = "ife-lite9"; - reg-cam-base = <0x261000>; + reg-cam-base = <0x25f000>; rt-wrapper-base = <0x231000>; interrupts = ; interrupt-names = "ife-lite9"; From eb12d8edf508823077791a9f4a90862febc1353a Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Sun, 18 Oct 2026 23:56:54 +0530 Subject: [PATCH 0781/1133] QCLINUX: arm64: dts: qcom: nord: Fix shared GPIO numbers With the latest kernel, the GPIO controller register base has shifted, so the old shared GPIO numbers now map to the wrong descriptors. This invalid mapping makes the GPIO reset step fail during acquire. Update the shared GPIO numbers for the camera resource manager node to match the new controller register base. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi index 0ba75082ad155..e5fa4fc8d152d 100644 --- a/arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-camera-sensor.dtsi @@ -589,7 +589,7 @@ &soc { qcom,cam-res-mgr { compatible = "qcom,cam-res-mgr"; - gpios-shared = <565 566 567 568 569>; + gpios-shared = <553 554 555 556 557>; status = "okay"; }; }; From 1227f485499e9b87714f90cfbc76520601568809 Mon Sep 17 00:00:00 2001 From: Ganesh Maurya G V Date: Thu, 15 Oct 2026 17:49:15 +0530 Subject: [PATCH 0782/1133] QCLINUX: arm64: dts: qcom: qcs6490-rb3gen2: Add aggregator rx flag support for CSIPHY mux mode Add the aggregator-rx property so the CSIPHY driver knows the link carries aggregated streams. In CSIPHY mux mode it can then configure the receiver for multiple virtual channels instead of assuming a single-sensor link. Signed-off-by: Ganesh Maurya G V --- arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi index f9165ae96219d..524b649b1ceb7 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs6490-camera.dtsi @@ -1387,6 +1387,7 @@ <400000000 0 300000000 0>; clock-cntl-level = "lowsvs", "svs"; src-clock-name = "csi0phytimer_clk_src"; + aggregator-rx; status = "ok"; csiphy0_opp_table: opp-table { @@ -1433,6 +1434,7 @@ clock-cntl-level = "lowsvs", "svs"; clock-rates = <300000000 0 300000000 0>, <400000000 0 300000000 0>; + aggregator-rx; status = "ok"; csiphy1_opp_table: opp-table { @@ -1479,6 +1481,7 @@ clock-cntl-level = "lowsvs", "svs"; clock-rates = <300000000 0 300000000 0>, <400000000 0 300000000 0>; + aggregator-rx; status = "ok"; csiphy2_opp_table: opp-table { @@ -1525,6 +1528,7 @@ clock-cntl-level = "lowsvs", "svs"; clock-rates = <300000000 0 300000000 0>, <400000000 0 300000000 0>; + aggregator-rx; status = "ok"; csiphy3_opp_table: opp-table { @@ -1571,6 +1575,7 @@ clock-cntl-level = "lowsvs", "svs"; clock-rates = <300000000 0 300000000 0>, <400000000 0 300000000 0>; + aggregator-rx; status = "ok"; csiphy4_opp_table: opp-table { From 548bcae6d996640e574445a30379abd28d5ae972 Mon Sep 17 00:00:00 2001 From: Sumukha Kollegal Date: Wed, 7 Oct 2026 17:41:49 -0700 Subject: [PATCH 0783/1133] QCLINUX: arm64: dts: qcom: lemans: Add CCI timer pinctrl for fsync Add pinctrl definitions for cci_timer0-9 in lemans Wire CCI_TIMER0-3 GPIOs into qcom,cam-gmsl-deserializer0/1/2/3 and qcom,cam-res-mgr's shared pinctrl list - required for the GPIO frame synchronization feature. Signed-off-by: Sumukha Kollegal --- arch/arm64/boot/dts/qcom/lemans-camera.dtsi | 260 ++++++++++++++++++ .../dts/qcom/lemans-evk-camera-sensor.dtsi | 87 ++++-- 2 files changed, 328 insertions(+), 19 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi index d6cce86922c26..4a0f26aefcdd3 100644 --- a/arch/arm64/boot/dts/qcom/lemans-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-camera.dtsi @@ -2318,6 +2318,266 @@ }; }; + cci_timer0_active: cci-timer0-active { + mux { + pins = "gpio68"; + function = "cci_timer0"; + }; + + config { + pins = "gpio68"; + bias-disable; + drive-strength = <6>; + }; + }; + + cci_timer0_suspend: cci-timer0-suspend { + mux { + pins = "gpio68"; + function = "cci_timer0"; + }; + + config { + pins = "gpio68"; + bias-pull-down; + drive-strength = <6>; + }; + }; + + cci_timer1_active: cci-timer1-active { + mux { + pins = "gpio69"; + function = "cci_timer1"; + }; + + config { + pins = "gpio69"; + bias-disable; + drive-strength = <6>; + }; + }; + + cci_timer1_suspend: cci-timer1-suspend { + mux { + pins = "gpio69"; + function = "cci_timer1"; + }; + + config { + pins = "gpio69"; + bias-pull-down; + drive-strength = <6>; + }; + }; + + cci_timer2_active: cci-timer2-active { + mux { + pins = "gpio70"; + function = "cci_timer2"; + }; + + config { + pins = "gpio70"; + bias-disable; + drive-strength = <6>; + }; + }; + + cci_timer2_suspend: cci-timer2-suspend { + mux { + pins = "gpio70"; + function = "cci_timer2"; + }; + + config { + pins = "gpio70"; + bias-pull-down; + drive-strength = <6>; + }; + }; + + cci_timer3_active: cci-timer3-active { + mux { + pins = "gpio71"; + function = "cci_timer3"; + }; + + config { + pins = "gpio71"; + bias-disable; + drive-strength = <6>; + }; + }; + + cci_timer3_suspend: cci-timer3-suspend { + mux { + pins = "gpio71"; + function = "cci_timer3"; + }; + + config { + pins = "gpio71"; + bias-pull-down; + drive-strength = <6>; + }; + }; + + cci_timer4_active: cci-timer4-active { + mux { + pins = "gpio52"; + function = "cci_timer4"; + }; + + config { + pins = "gpio52"; + bias-disable; + drive-strength = <6>; + }; + }; + + cci_timer4_suspend: cci-timer4-suspend { + mux { + pins = "gpio52"; + function = "cci_timer4"; + }; + + config { + pins = "gpio52"; + bias-pull-down; + drive-strength = <6>; + }; + }; + + cci_timer5_active: cci-timer5-active { + mux { + pins = "gpio53"; + function = "cci_timer5"; + }; + + config { + pins = "gpio53"; + bias-disable; + drive-strength = <6>; + }; + }; + + cci_timer5_suspend: cci-timer5-suspend { + mux { + pins = "gpio53"; + function = "cci_timer5"; + }; + + config { + pins = "gpio53"; + bias-pull-down; + drive-strength = <6>; + }; + }; + + cci_timer6_active: cci-timer6-active { + mux { + pins = "gpio54"; + function = "cci_timer6"; + }; + + config { + pins = "gpio54"; + bias-disable; + drive-strength = <6>; + }; + }; + + cci_timer6_suspend: cci-timer6-suspend { + mux { + pins = "gpio54"; + function = "cci_timer6"; + }; + + config { + pins = "gpio54"; + bias-pull-down; + drive-strength = <6>; + }; + }; + + cci_timer7_active: cci-timer7-active { + mux { + pins = "gpio55"; + function = "cci_timer7"; + }; + + config { + pins = "gpio55"; + bias-disable; + drive-strength = <6>; + }; + }; + + cci_timer7_suspend: cci-timer7-suspend { + mux { + pins = "gpio55"; + function = "cci_timer7"; + }; + + config { + pins = "gpio55"; + bias-pull-down; + drive-strength = <6>; + }; + }; + + cci_timer8_active: cci-timer8-active { + mux { + pins = "gpio56"; + function = "cci_timer8"; + }; + + config { + pins = "gpio56"; + bias-disable; + drive-strength = <6>; + }; + }; + + cci_timer8_suspend: cci-timer8-suspend { + mux { + pins = "gpio56"; + function = "cci_timer8"; + }; + + config { + pins = "gpio56"; + bias-pull-down; + drive-strength = <6>; + }; + }; + + cci_timer9_active: cci-timer9-active { + mux { + pins = "gpio57"; + function = "cci_timer9"; + }; + + config { + pins = "gpio57"; + bias-disable; + drive-strength = <6>; + }; + }; + + cci_timer9_suspend: cci-timer9-suspend { + mux { + pins = "gpio57"; + function = "cci_timer9"; + }; + + config { + pins = "gpio57"; + bias-pull-down; + drive-strength = <6>; + }; + }; + cci0_active: cci0-active { mux { /* CLK, DATA */ diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi index f7005902a98a2..0e8240b22537b 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-evk-camera-sensor.dtsi @@ -25,11 +25,19 @@ pinctrl-0 = <&cam_sensor_mclk0_active>; pinctrl-1 = <&cam_sensor_mclk0_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&pmm8654au_0_gpios 7 0>; + gpios = <&pmm8654au_0_gpios 7 0>, + <&tlmm 68 0>, + <&tlmm 69 0>, + <&tlmm 70 0>, + <&tlmm 71 0>; gpio-reset = <0>; - gpio-req-tbl-num = <0>; - gpio-req-tbl-flags = <0>; - gpio-req-tbl-label = "CAM_RESET0"; + gpio-req-tbl-num = <0 1 2 3 4>; + gpio-req-tbl-flags = <0 0 0 0 0>; + gpio-req-tbl-label = "CAM_RESET0", + "CCI_TIMER0", + "CCI_TIMER1", + "CCI_TIMER2", + "CCI_TIMER3"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK0_CLK>; clock-names = "cam_clk"; @@ -318,11 +326,20 @@ pinctrl-0 = <&cam_sensor_mclk1_active>; pinctrl-1 = <&cam_sensor_mclk1_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&pmm8654au_0_gpios 8 0>; + gpios = <&pmm8654au_0_gpios 8 0>, + <&tlmm 68 0>, + <&tlmm 69 0>, + <&tlmm 70 0>, + <&tlmm 71 0>; gpio-reset = <0>; - gpio-req-tbl-num = <0>; - gpio-req-tbl-flags = <0>; - gpio-req-tbl-label = "CAM_RESET1"; + gpio-req-tbl-num = <0 1 2 3 4>; + gpio-req-tbl-flags = <0 0 0 0 0>; + gpio-req-tbl-label = "CAM_RESET1", + "CCI_TIMER0", + "CCI_TIMER1", + "CCI_TIMER2", + "CCI_TIMER3"; + cci-master = <0>; clocks = <&camcc CAM_CC_MCLK1_CLK>; clock-names = "cam_clk"; @@ -577,11 +594,19 @@ pinctrl-0 = <&cam_sensor_mclk2_active>; pinctrl-1 = <&cam_sensor_mclk2_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&pmm8654au_0_gpios 9 0>; + gpios = <&pmm8654au_0_gpios 9 0>, + <&tlmm 68 0>, + <&tlmm 69 0>, + <&tlmm 70 0>, + <&tlmm 71 0>; gpio-reset = <0>; - gpio-req-tbl-num = <0>; - gpio-req-tbl-flags = <0>; - gpio-req-tbl-label = "CAM_RESET2"; + gpio-req-tbl-num = <0 1 2 3 4>; + gpio-req-tbl-flags = <0 0 0 0 0>; + gpio-req-tbl-label = "CAM_RESET2", + "CCI_TIMER0", + "CCI_TIMER1", + "CCI_TIMER2", + "CCI_TIMER3"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK2_CLK>; clock-names = "cam_clk"; @@ -804,11 +829,19 @@ pinctrl-0 = <&cam_sensor_mclk3_active>; pinctrl-1 = <&cam_sensor_mclk3_suspend>; pinctrl-names = "cam_default", "cam_suspend"; - gpios = <&pmm8654au_0_gpios 10 0>; + gpios = <&pmm8654au_0_gpios 10 0>, + <&tlmm 68 0>, + <&tlmm 69 0>, + <&tlmm 70 0>, + <&tlmm 71 0>; gpio-reset = <0>; - gpio-req-tbl-num = <0>; - gpio-req-tbl-flags = <0>; - gpio-req-tbl-label = "CAM_RESET3"; + gpio-req-tbl-num = <0 1 2 3 4>; + gpio-req-tbl-flags = <0 0 0 0 0>; + gpio-req-tbl-label = "CAM_RESET3", + "CCI_TIMER0", + "CCI_TIMER1", + "CCI_TIMER2", + "CCI_TIMER3"; cci-master = <0>; clocks = <&camcc CAM_CC_MCLK3_CLK>; clock-names = "cam_clk"; @@ -1015,11 +1048,27 @@ qcom,cam-res-mgr { compatible = "qcom,cam-res-mgr"; gpios-shared = <518 519 520 521>; - gpios-shared-pinctrl = <633>; - shared-pctrl-gpio-names = "mclk1"; + gpios-shared-pinctrl = <633 628 629 630 631>; + shared-pctrl-gpio-names = "mclk1", + "cci_timer0", + "cci_timer1", + "cci_timer2", + "cci_timer3"; pinctrl-0 = <&cam_sensor_mclk1_active>; pinctrl-1 = <&cam_sensor_mclk1_suspend>; - pinctrl-names = "mclk1_active", "mclk1_suspend"; + pinctrl-2 = <&cci_timer0_active>; + pinctrl-3 = <&cci_timer0_suspend>; + pinctrl-4 = <&cci_timer1_active>; + pinctrl-5 = <&cci_timer1_suspend>; + pinctrl-6 = <&cci_timer2_active>; + pinctrl-7 = <&cci_timer2_suspend>; + pinctrl-8 = <&cci_timer3_active>; + pinctrl-9 = <&cci_timer3_suspend>; + pinctrl-names = "mclk1_active", "mclk1_suspend", + "cci_timer0_active", "cci_timer0_suspend", + "cci_timer1_active", "cci_timer1_suspend", + "cci_timer2_active", "cci_timer2_suspend", + "cci_timer3_active", "cci_timer3_suspend"; status = "ok"; }; }; From 9ebb79ad76091f179596945831168919b8516b4d Mon Sep 17 00:00:00 2001 From: Chandan Kumar Jha Date: Wed, 28 Oct 2026 12:47:29 +0530 Subject: [PATCH 0784/1133] QCLINUX: arm64: dts: qcom: shikra: Disable isp_ope in camx overlays isp_ope in shikra.dtsi and the downstream OPE node in shikra-camera.dtsi are assigned the same interrupt number. Since only one camera stack is active at a time, loading the camx overlay while isp_ope stays enabled causes the downstream OPE node to fail probe with a resource-busy error on the shared interrupt. Disable isp_ope in the camx overlays so the downstream OPE node can probe cleanly. Signed-off-by: Chandan Kumar Jha --- arch/arm64/boot/dts/qcom/shikra-cqm-evk-camx.dtso | 4 ++++ arch/arm64/boot/dts/qcom/shikra-cqs-evk-camx.dtso | 4 ++++ arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk-camx.dtso b/arch/arm64/boot/dts/qcom/shikra-cqm-evk-camx.dtso index a5d55b646470d..14b218cfe3869 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk-camx.dtso @@ -39,3 +39,7 @@ &cci_i2c1 { status = "disabled"; }; + +&isp_ope { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk-camx.dtso b/arch/arm64/boot/dts/qcom/shikra-cqs-evk-camx.dtso index a5d55b646470d..14b218cfe3869 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk-camx.dtso @@ -39,3 +39,7 @@ &cci_i2c1 { status = "disabled"; }; + +&isp_ope { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso index af65f786f6e2a..fe69268091aab 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso @@ -74,6 +74,10 @@ <&tlmm 56 0>; }; +&isp_ope { + status = "disabled"; +}; + &sensor_cam0 { cam_vio-supply = <&pm8150_s4>; gpios = <&tlmm 34 0>, From 0c5785804c8e8ea6f698240c046cec3c24d5b7ac Mon Sep 17 00:00:00 2001 From: Manikanta Mylavarapu Date: Mon, 19 Oct 2026 14:23:35 +0530 Subject: [PATCH 0785/1133] PENDING: arm64: dts: qcom: hamoa-evk: add QPS615 Ethernet overlay Add the hamoa-evk staging overlay for the QPS615 M.2 E-key daughter card. With QPS615 installed, the M.2 E-key slot is occupied by the QPS615 PCIe switch (pci1179,0623) instead of a WLAN chip. Describe the QPS615 PCIe switch topology and the dual TC956X Ethernet functions connected through the downstream port. Add GPIO-based PHY reset handling and disable L0s/L1 ASPM for the QPS615 PCIe path. Signed-off-by: Manikanta Mylavarapu --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../boot/dts/qcom/hamoa-evk-staging.dtso | 63 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/hamoa-evk-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 55381ace194d4..8fb034a30e30c 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -674,6 +674,8 @@ dtb-$(CONFIG_ARCH_QCOM) += glymur-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += hamoa-staging.dtbo +dtb-$(CONFIG_ARCH_QCOM) += hamoa-evk-staging.dtbo + dtb-$(CONFIG_ARCH_QCOM) += purwa-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += sm8750-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/hamoa-evk-staging.dtso b/arch/arm64/boot/dts/qcom/hamoa-evk-staging.dtso new file mode 100644 index 0000000000000..02b647b303e38 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/hamoa-evk-staging.dtso @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&pcie4_port0 { + + pci@0,0 { + reg = <0x10000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x2 0xff>; + aspm-no-l1; + aspm-no-l0s; + + pci@3,0 { + reg = <0x21800 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + bus-range = <0x5 0xff>; + aspm-no-l1; + aspm-no-l0s; + + qps615: pci@0,0 { + reg = <0x50000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + aspm-no-l1; + aspm-no-l0s; + + gpio-controller; + #gpio-cells = <2>; + + phy-reset-gpios = <&qps615 0 GPIO_ACTIVE_LOW>; + reset-deassert-us = <221000>; + }; + + pci@0,1 { + reg = <0x50100 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + ranges; + aspm-no-l1; + aspm-no-l0s; + + phy-reset-gpios = <&qps615 1 GPIO_ACTIVE_LOW>; + reset-deassert-us = <20000>; + }; + }; + }; +}; From 185da243522186ac3bab25d1afc8cb131f79aca2 Mon Sep 17 00:00:00 2001 From: Ganesh Maurya G V Date: Wed, 28 Oct 2026 12:03:56 +0530 Subject: [PATCH 0786/1133] QCLINUX: arm64: dts: qcom: glymur-crd: Add aon-camera-id to mono sensor The Bayer and mono cameras share the same resources. Add the 'aon-camera-id' property so that the mono camera subsystem can reclaim the shared resources. Signed-off-by: Ganesh Maurya G V --- arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi index 7cffbf2fece6d..1bf988f8fa8eb 100644 --- a/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur-camera-sensor.dtsi @@ -43,6 +43,7 @@ /*cam1-og0va1b*/ qcom,cam-sensor1 { compatible = "qcom,cam-sensor"; + aon-camera-id = ; csiphy-sd-index = <0>; sensor-position-roll = <0>; sensor-position-pitch = <0>; From 023a4d94fa51174a760911b21b4359f1c9ea3bab Mon Sep 17 00:00:00 2001 From: Eshitha Oyyavuru Date: Thu, 29 Oct 2026 17:29:21 +0530 Subject: [PATCH 0787/1133] PENDING: arm64: dts: qcom: monaco-evk-staging: fix missing Ethernet interfaces On some boards, the MDIO bus fails to discover the PHY because it returns no valid reset values. Port 0 uses an AQR113C PHY with its active-low RST_N pin connected to a TLMM GPIO. Configure the reset GPIO with the correct polarity so the PHY is reset before MDIO discovery. PHY discovery then succeeds on both the affected boards and the boards that were already working. Signed-off-by: Eshitha Oyyavuru --- arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso index a646b28f6f9d0..6e118c9066e9b 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso +++ b/arch/arm64/boot/dts/qcom/monaco-evk-staging.dtso @@ -31,7 +31,7 @@ nvmem-cell-names = "mac-address"; pinctrl-names = "default"; pinctrl-0 = <&aqr_intn_wol_sig>; - phy-reset-gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>; + phy-reset-gpios = <&tlmm 10 GPIO_ACTIVE_LOW>; reset-deassert-us = <221000>; }; From dddd80f34339b8a1f7a7eabe364a30df7826b3e5 Mon Sep 17 00:00:00 2001 From: Muhammad Aksar Date: Thu, 15 Oct 2026 18:32:02 +0530 Subject: [PATCH 0788/1133] QCLINUX: arm64: dts: qcom: shikra: Add changes for AR0544 GMSL Cameras - Added multi-camera support on port 0 and 1. - Sensor: Onsemi AR0544, Ser: MAX96717, Des: MAX96724, Power IC: MAX20086. Signed-off-by: Muhammad Aksar --- .../boot/dts/qcom/shikra-camera-sensor.dtsi | 264 ++++++++++++++++++ .../boot/dts/qcom/shikra-iqs-evk-camx.dtso | 10 + 2 files changed, 274 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-camera-sensor.dtsi b/arch/arm64/boot/dts/qcom/shikra-camera-sensor.dtsi index 42410c14f9b72..5215ec0739119 100644 --- a/arch/arm64/boot/dts/qcom/shikra-camera-sensor.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-camera-sensor.dtsi @@ -447,6 +447,270 @@ cell-index = <5>; status = "okay"; }; + + /* MAX96724 Deserializer 0 */ + deserializer_0: qcom,cam-gmsl-deserializer0 { + #address-cells = <1>; + #size-cells = <0>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_active_rst0>; + pinctrl-1 = <&cam_sensor_suspend_rst0>; + gpios = <&tlmm 32 0>, + <&tlmm 59 0>, + <&tlmm 56 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-custom2 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <0 0 0>; + gpio-req-tbl-label = "CAMIF_RESET0", + "CAM_CUSTOM1", + "CAM_CUSTOM2"; + cci-master = <0>; + clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + + port@0 { + reg = <0>; + deser0_port0: endpoint { + remote-endpoint = <&gmsl_sensor0_ep>; + }; + }; + + port@1 { + reg = <1>; + deser0_port1: endpoint { + remote-endpoint = <&gmsl_sensor1_ep>; + }; + }; + + port@2 { + reg = <2>; + deser0_port2: endpoint { + remote-endpoint = <&gmsl_sensor2_ep>; + }; + }; + + port@3 { + reg = <3>; + deser0_port3: endpoint { + remote-endpoint = <&gmsl_sensor3_ep>; + }; + }; + }; + + /* MAX96724 Deserializer 0 AR0544 Sensor 0 */ + qcom,cam-gmsl-sensor0 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <6>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + + port { + gmsl_sensor0_ep: endpoint { + remote-endpoint = <&deser0_port0>; + }; + }; + }; + + /* MAX96724 Deserializer 0 AR0544 Sensor 1 */ + qcom,cam-gmsl-sensor1 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <7>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + + port { + gmsl_sensor1_ep: endpoint { + remote-endpoint = <&deser0_port1>; + }; + }; + }; + + /* MAX96724 Deserializer 0 AR0544 Sensor 2 */ + qcom,cam-gmsl-sensor2 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <8>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + + port { + gmsl_sensor2_ep: endpoint { + remote-endpoint = <&deser0_port2>; + }; + }; + }; + + /* MAX96724 Deserializer 0 AR0544 Sensor 3 */ + qcom,cam-gmsl-sensor3 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <9>; + csiphy-sd-index = <0>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + + port { + gmsl_sensor3_ep: endpoint { + remote-endpoint = <&deser0_port3>; + }; + }; + }; + + /* MAX96724 Deserializer 1 */ + deserializer_1: qcom,cam-gmsl-deserializer1 { + #address-cells = <1>; + #size-cells = <0>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + cam_vio-supply = <&pm4125_l15>; + regulator-names = "cam_vio"; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <1800000>; + rgltr-max-voltage = <1800000>; + rgltr-load-current = <120000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_active_rst1>; + pinctrl-1 = <&cam_sensor_suspend_rst1>; + gpios = <&tlmm 33 0>, + <&tlmm 58 0>, + <&tlmm 64 0>; + gpio-reset = <0>; + gpio-custom1 = <1>; + gpio-custom2 = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <0 0 0>; + gpio-req-tbl-label = "CAMIF_RESET1", + "CAM_CUSTOM1", + "CAM_CUSTOM2"; + cci-master = <1>; + clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "nominal"; + clock-rates = <24000000>; + status = "okay"; + + port@0 { + reg = <0>; + deser1_port0: endpoint { + remote-endpoint = <&gmsl_sensor4_ep>; + }; + }; + + port@1 { + reg = <1>; + deser1_port1: endpoint { + remote-endpoint = <&gmsl_sensor5_ep>; + }; + }; + + port@2 { + reg = <2>; + deser1_port2: endpoint { + remote-endpoint = <&gmsl_sensor6_ep>; + }; + }; + + port@3 { + reg = <3>; + deser1_port3: endpoint { + remote-endpoint = <&gmsl_sensor7_ep>; + }; + }; + + }; + + /* MAX96724 Deserializer 1 AR0544 Sensor 0 */ + qcom,cam-gmsl-sensor4 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <10>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + + port { + gmsl_sensor4_ep: endpoint { + remote-endpoint = <&deser1_port0>; + }; + }; + }; + + /* MAX96724 Deserializer 1 AR0544 Sensor 1 */ + qcom,cam-gmsl-sensor5 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <11>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + + port { + gmsl_sensor5_ep: endpoint { + remote-endpoint = <&deser1_port1>; + }; + }; + }; + + /* MAX96724 Deserializer 1 AR0544 Sensor 2 */ + qcom,cam-gmsl-sensor6 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <12>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + + port { + gmsl_sensor6_ep: endpoint { + remote-endpoint = <&deser1_port2>; + }; + }; + }; + + /* MAX96724 Deserializer 1 AR0544 Sensor 3 */ + qcom,cam-gmsl-sensor7 { + compatible = "qcom,cam-gmsl-sensor"; + cell-index = <13>; + csiphy-sd-index = <1>; + sensor-position-roll = <0>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + + port { + gmsl_sensor7_ep: endpoint { + remote-endpoint = <&deser1_port3>; + }; + + }; + }; }; &soc { diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso index fe69268091aab..cde67dba1bbe2 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-camx.dtso @@ -46,6 +46,16 @@ status = "disabled"; }; +&deserializer_0 { + cam_vio-supply = <&pm8150_s4>; + +}; + +&deserializer_1 { + cam_vio-supply = <&pm8150_s4>; + +}; + &eeprom_cam0 { cam_vio-supply = <&pm8150_s4>; gpios = <&tlmm 34 0>, From b0fbde384acff145998ed56aacdd990a1f8529a9 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Tue, 3 Nov 2026 03:41:18 +0530 Subject: [PATCH 0789/1133] QCLINUX: arm64: dts: qcom: glymur: Disable csiphy4 in camx overlays csiphy4 in glymur-crd.dtsi and the downstream CSIPHY node in glymur-camera.dtsi are assigned the same interrupt number. Since only one camera stack is active at a time, loading the camx overlay while csiphy4 stays enabled will cause the downstream CSIPHY node to fail probe with a resource-busy error on the shared interrupt. Disable csiphy4 in the camx overlays so the downstream CSIPHY node can probe cleanly. Signed-off-by: Nihal Kumar Gupta --- arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso index 64cea8de94206..a2688a5154cbd 100644 --- a/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso +++ b/arch/arm64/boot/dts/qcom/glymur-crd-camx.dtso @@ -38,3 +38,7 @@ &cci1_i2c1 { status = "disabled"; }; + +&csiphy4 { + status = "disabled"; +}; From 2994b23cb89e5669a35e99218923fd18aeee7831 Mon Sep 17 00:00:00 2001 From: Ayushi Makhija Date: Mon, 23 Mar 2026 16:33:37 +0530 Subject: [PATCH 0790/1133] FROMLIST: arm64: dts: qcom: sm8750-mtp: Set sufficient voltage for panel nt37801 The NT37801 Sepc V1.0 chapter "5.7.1 Power On Sequence" states VDDI=1.65V~1.95V, so set sufficient voltage for panel nt37801. Signed-off-by: Ayushi Makhija Link: https://lore.kernel.org/all/20260323102229.1546504-1-quic_amakhija@quicinc.com/ Signed-off-by: Arpit Saini --- arch/arm64/boot/dts/qcom/sm8750-mtp.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts index 64bc1cec612ef..9ecb40e7e39fb 100644 --- a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts @@ -462,7 +462,7 @@ vreg_l12b_1p8: ldo12 { regulator-name = "vreg_l12b_1p8"; - regulator-min-microvolt = <1200000>; + regulator-min-microvolt = <1650000>; regulator-max-microvolt = <1800000>; regulator-initial-mode = ; regulator-allow-set-load; From cc2ee7862e468bd2fe6e118be47ca8f8097343b9 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Fri, 29 May 2026 19:53:11 +0530 Subject: [PATCH 0791/1133] FROMLIST: arm64: dts: qcom: sm8750: add reboot-mode support Add PSCI SYSTEM_RESET2 reboot-modes for sm8750-mtp and sm8750-qrd for use by the psci-reboot-mode driver. The following modes are defined: - bootloader: reboot into fastboot mode for fastboot flashing. - edl: reboot into emergency download mode for image loading via the Firehose protocol. Link: https://lore.kernel.org/r/20260529-psci_sys_reset-dt-changes-for-pakala-v2-1-1964ebf1924c@oss.qualcomm.com Signed-off-by: Anurag Pateriya --- arch/arm64/boot/dts/qcom/sm8750-mtp.dts | 7 +++++++ arch/arm64/boot/dts/qcom/sm8750-qrd.dts | 7 +++++++ arch/arm64/boot/dts/qcom/sm8750.dtsi | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts index 9ecb40e7e39fb..14d46e98ab71d 100644 --- a/arch/arm64/boot/dts/qcom/sm8750-mtp.dts +++ b/arch/arm64/boot/dts/qcom/sm8750-mtp.dts @@ -1434,3 +1434,10 @@ status = "okay"; }; + +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8750-qrd.dts b/arch/arm64/boot/dts/qcom/sm8750-qrd.dts index 75927e1f7b9ab..012e28b857dd8 100644 --- a/arch/arm64/boot/dts/qcom/sm8750-qrd.dts +++ b/arch/arm64/boot/dts/qcom/sm8750-qrd.dts @@ -1162,3 +1162,10 @@ status = "okay"; }; + +&psci { + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index cf947acc57602..2030ce87952e3 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -262,7 +262,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; From debcb11581c958068fd0dca18fb9a029e97e80ac Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Thu, 18 Jun 2026 05:03:50 -0700 Subject: [PATCH 0792/1133] FROMLIST: arm64: dts: qcom: sm8750: Add camss node Add node for the SM8750 camera subsystem. Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260618-pakala-camera-v2-1-9fbb729fd242@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 203 +++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index 2030ce87952e3..08b3656cf39a2 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -3348,6 +3348,209 @@ #power-domain-cells = <1>; }; + camss: isp@ad27000 { + compatible = "qcom,sm8750-camss"; + + reg = <0x0 0x0ad27000 0x0 0x2b00>, + <0x0 0x0ad2a000 0x0 0x2b00>, + <0x0 0x0ad2d000 0x0 0x2b00>, + <0x0 0x0ad6d000 0x0 0xa00>, + <0x0 0x0ad72000 0x0 0xa00>, + <0x0 0x0ada9000 0x0 0x2000>, + <0x0 0x0adab000 0x0 0x2000>, + <0x0 0x0adad000 0x0 0x2000>, + <0x0 0x0adaf000 0x0 0x2000>, + <0x0 0x0adb1000 0x0 0x2000>, + <0x0 0x0adb3000 0x0 0x2000>, + <0x0 0x0ad8b000 0x0 0x400>, + <0x0 0x0ad8c000 0x0 0x400>, + <0x0 0x0ad8d000 0x0 0x400>, + <0x0 0x0ac86000 0x0 0x10000>, + <0x0 0x0ac96000 0x0 0x10000>, + <0x0 0x0aca6000 0x0 0x10000>, + <0x0 0x0ad6e000 0x0 0x3000>, + <0x0 0x0ad73000 0x0 0x3000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_NRT_ICP_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + + port@1 { + reg = <1>; + }; + + port@2 { + reg = <2>; + }; + + port@3 { + reg = <3>; + }; + + port@4 { + reg = <4>; + }; + + port@5 { + reg = <5>; + }; + }; + + }; + mdss: display-subsystem@ae00000 { compatible = "qcom,sm8750-mdss"; reg = <0x0 0x0ae00000 0x0 0x1000>; From 74d64663e64e14763bc35775229f6b45eee9e7f6 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Thu, 18 Jun 2026 05:03:51 -0700 Subject: [PATCH 0793/1133] FROMLIST: arm64: dts: qcom: sm8750: Add CCI definitions Qualcomm SM8750 SoC has three Camera Control Interface (CCI). Each controller contains two I2C hosts. Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260618-pakala-camera-v2-2-9fbb729fd242@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 282 +++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index 08b3656cf39a2..f992d1a0765b3 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -3348,6 +3348,96 @@ #power-domain-cells = <1>; }; + cci0: cci@ac7b000 { + compatible = "qcom,sm8750-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0ac7b000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci0_0_default &cci0_1_default>; + pinctrl-1 = <&cci0_0_sleep &cci0_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@ac7c000 { + compatible = "qcom,sm8750-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0ac7c000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci1_0_default &cci1_1_default>; + pinctrl-1 = <&cci1_0_sleep &cci1_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci2: cci@ac7d000 { + compatible = "qcom,sm8750-cci", "qcom,msm8996-cci"; + reg = <0x0 0x0ac7d000 0x0 0x1000>; + interrupts = ; + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + clocks = <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CCI_2_CLK>; + clock-names = "ahb", "cci"; + pinctrl-0 = <&cci2_0_default &cci2_1_default>; + pinctrl-1 = <&cci2_0_sleep &cci2_1_sleep>; + pinctrl-names = "default", "sleep"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + cci2_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci2_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + camss: isp@ad27000 { compatible = "qcom,sm8750-camss"; @@ -4123,6 +4213,198 @@ gpio-ranges = <&tlmm 0 0 216>; wakeup-parent = <&pdc>; + cci0_0_default: cci0-0-default-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_0_sleep: cci0-0-sleep-state { + sda-pins { + pins = "gpio113"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio114"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci0_1_default: cci0-1-default-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_1_sleep: cci0-1-sleep-state { + sda-pins { + pins = "gpio115"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio116"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_0_default: cci1-0-default-state { + sda-pins { + pins = "gpio117"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio118"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_0_sleep: cci1-0-sleep-state { + sda-pins { + pins = "gpio117"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio118"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_1_default: cci1-1-default-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio164"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_1_sleep: cci1-1-sleep-state { + sda-pins { + pins = "gpio111"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio164"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_0_default: cci2-0-default-state { + sda-pins { + pins = "gpio112"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio153"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_0_sleep: cci2-0-sleep-state { + sda-pins { + pins = "gpio112"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio153"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci2_1_default: cci2-1-default-state { + sda-pins { + pins = "gpio119"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-up; + }; + + scl-pins { + pins = "gpio120"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci2_1_sleep: cci2-1-sleep-state { + sda-pins { + pins = "gpio119"; + function = "cci_i2c_sda"; + drive-strength = <2>; + bias-pull-down; + }; + + scl-pins { + pins = "gpio120"; + function = "cci_i2c_scl"; + drive-strength = <2>; + bias-pull-down; + }; + }; + hub_i2c0_data_clk: hub-i2c0-data-clk-state { /* SDA, SCL */ pins = "gpio64", "gpio65"; From 1c272022b8e77720ba153ff26e493c79ddd1f1ac Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Thu, 18 Jun 2026 05:03:52 -0700 Subject: [PATCH 0794/1133] FROMLIST: arm64: dts: qcom: sm8750: Add camera MCLK pinctrl Define pinctrl definitions to enable camera master clocks on SM8750. Reviewed-by: Konrad Dybcio Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260618-pakala-camera-v2-3-9fbb729fd242@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 56 ++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index f992d1a0765b3..d6b378cd8e829 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -4213,6 +4213,62 @@ gpio-ranges = <&tlmm 0 0 216>; wakeup-parent = <&pdc>; + cam0_default: cam0-default-state { + pins = "gpio89"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam1_default: cam1-default-state { + pins = "gpio90"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam2_default: cam2-default-state { + pins = "gpio91"; + function = "cam_aon_mclk2"; + drive-strength = <2>; + bias-disable; + }; + + cam3_default: cam3-default-state { + pins = "gpio92"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam4_default: cam4-default-state { + pins = "gpio93"; + function = "cam_aon_mclk4"; + drive-strength = <2>; + bias-disable; + }; + + cam5_default: cam5-default-state { + pins = "gpio94"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam6_default: cam6-default-state { + pins = "gpio95"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + + cam7_default: cam7-default-state { + pins = "gpio96"; + function = "cam_mclk"; + drive-strength = <2>; + bias-disable; + }; + cci0_0_default: cci0-0-default-state { sda-pins { pins = "gpio113"; From 2fcfb6f0f8274f5b50d4e3323f74f964aeedf964 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Fri, 10 Jul 2026 10:39:03 +0800 Subject: [PATCH 0795/1133] FROMLIST: arm64: dts: qcom: sm8750: bind traceNoC on the platform bus The traceNoC node used the "qcom,coresight-tnoc", "arm,primecell" compatible, which places the device on the AMBA bus. To bind an AMBA device, the bus reads the peripheral and component ID registers (PID/CID) at the top of the device's register block and matches them against the primecell ID. The traceNoC exposes the CID registers, but the Component ID value returned by the hardware is 0x00000000 instead of a valid AMBA Component ID, so the match never succeeds, the AMBA probe fails, and the device is left stuck in deferred probe indefinitely. Drop the "arm,primecell" entry and use the standalone "qcom,coresight-tnoc" compatible, which binds via the platform driver by compatible string and does not rely on the component ID register at all. This lets the device probe on hardware that does not return a valid CID, while remaining an Aggregator TNOC that retains ATID functionality. Link: https://lore.kernel.org/all/20260710-fix-tracenoc-probe-issue-v6-4-41eb36fef8d9@oss.qualcomm.com/ Fixes: ebd1eb365cae ("arm64: qcom: dts: sm8750: add coresight nodes") Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index d6b378cd8e829..318f8904fcb3c 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -5713,7 +5713,7 @@ }; tn@109ab000 { - compatible = "qcom,coresight-tnoc", "arm,primecell"; + compatible = "qcom,coresight-tnoc"; reg = <0x0 0x109ab000 0x0 0x4200>; clocks = <&aoss_qmp>; From fa427752be6942178e9c91f92d927e29c758681b Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Wed, 22 Jul 2026 00:00:14 +0530 Subject: [PATCH 0796/1133] FROMLIST: arm64: dts: qcom: pmih0108: Enable BCL sensor node Add Battery Current Limiting (BCL) hardware monitor node for pmih0108 PMIC. The BCL monitors battery voltage and current, providing hardware interrupts when configurable thresholds are violated. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/all/20261005-qcom-bcl-hwmon-v4-11-50b9a8c730b7@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/pmih0108.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pmih0108.dtsi b/arch/arm64/boot/dts/qcom/pmih0108.dtsi index 1c875995d8813..e8af3e5d583cd 100644 --- a/arch/arm64/boot/dts/qcom/pmih0108.dtsi +++ b/arch/arm64/boot/dts/qcom/pmih0108.dtsi @@ -49,6 +49,17 @@ #thermal-sensor-cells = <0>; }; + sensor@4700 { + compatible = "qcom,pmih0108-bcl"; + reg = <0x4700>; + interrupts = <0x7 0x47 0x0 IRQ_TYPE_EDGE_RISING>, + <0x7 0x47 0x1 IRQ_TYPE_EDGE_RISING>, + <0x7 0x47 0x2 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "max-min", + "critical", + "emergency"; + }; + pmih0108_gpios: gpio@8800 { compatible = "qcom,pmih0108-gpio", "qcom,spmi-gpio"; reg = <0x8800>; From fd2b7a18098abc60e9d6d68d1acc238e81504e34 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 22 Sep 2026 18:35:22 +0800 Subject: [PATCH 0797/1133] FROMLIST: arm64: dts: qcom: sm8750: Add CoreSight nodes for APSS debug block The APSS debug block is built with CoreSight devices like ETM, replicator, funnel and TMC ETF. Add dt nodes for these devices to enable ETM trace. The replicator, funnel and TMC ETF nodes in this block are physically powered by the CPU cluster power rail rather than by a dedicated always-on rail. Add a power-domains property referencing the corresponding cluster0_pd/cluster1_pd domain to each of these nodes, so their power state is tied to the CPU cluster domain and the runtime PM core can power the domain on before the devices are accessed and let it be powered off otherwise. Link: https://lore.kernel.org/all/20260922-add-etm-devices-for-multiple-qcom-platforms-v1-2-c2a8c3225a2e@oss.qualcomm.com/ Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 599 +++++++++++++++++++++++++++ 1 file changed, 599 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index 318f8904fcb3c..c9969b60ce806 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -216,6 +216,142 @@ }; }; + etm-0 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&ncc0_0_rep_in>; + }; + }; + }; + }; + + etm-1 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&ncc0_1_rep_in>; + }; + }; + }; + }; + + etm-2 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&ncc0_2_rep_in>; + }; + }; + }; + }; + + etm-3 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&ncc0_3_rep_in>; + }; + }; + }; + }; + + etm-4 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu4>; + qcom,skip-power-up; + + out-ports { + port { + etm4_out: endpoint { + remote-endpoint = <&ncc0_4_rep_in>; + }; + }; + }; + }; + + etm-5 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu5>; + qcom,skip-power-up; + + out-ports { + port { + etm5_out: endpoint { + remote-endpoint = <&ncc0_5_rep_in>; + }; + }; + }; + }; + + etm-6 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu6>; + qcom,skip-power-up; + + out-ports { + port { + etm6_out: endpoint { + remote-endpoint = <&ncc1_0_rep_in>; + }; + }; + }; + }; + + etm-7 { + compatible = "arm,coresight-etm4x-sysreg"; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + cpu = <&cpu7>; + qcom,skip-power-up; + + out-ports { + port { + etm7_out: endpoint { + remote-endpoint = <&ncc1_1_rep_in>; + }; + }; + }; + }; + firmware { scm: scm { compatible = "qcom,scm-sm8750", "qcom,scm"; @@ -5834,6 +5970,14 @@ remote-endpoint = <&tpdm_rdpm_cmb2_out>; }; }; + + port@21 { + reg = <0x21>; + + tn_ag_in33: endpoint { + remote-endpoint = <&apss_funnel_out>; + }; + }; }; out-ports { @@ -6111,6 +6255,461 @@ }; }; + funnel@12080000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x12080000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + apss_funnel_in0: endpoint { + remote-endpoint = <&ncc0_etf_out>; + }; + }; + + port@1 { + reg = <1>; + + apss_funnel_in1: endpoint { + remote-endpoint = <&ncc1_etf_out>; + }; + }; + }; + + out-ports { + port { + apss_funnel_out: endpoint { + remote-endpoint = <&tn_ag_in33>; + }; + }; + }; + }; + + funnel@13401000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x13401000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc0_2_funnel_in2: endpoint { + remote-endpoint = <&ncc0_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_funnel_out: endpoint { + remote-endpoint = <&ncc0_etf_in>; + }; + }; + }; + }; + + tmc@13409000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x13409000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_etf_in: endpoint { + remote-endpoint = <&ncc0_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc0_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in0>; + }; + }; + }; + }; + + funnel@13481000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x13481000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc0_1_funnel_in0: endpoint { + remote-endpoint = <&ncc0_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc0_1_funnel_in1: endpoint { + remote-endpoint = <&ncc0_1_rep_out>; + }; + }; + + port@2 { + reg = <2>; + + ncc0_1_funnel_in2: endpoint { + remote-endpoint = <&ncc0_2_rep_out>; + }; + }; + + port@3 { + reg = <3>; + + ncc0_1_funnel_in3: endpoint { + remote-endpoint = <&ncc0_3_rep_out>; + }; + }; + + port@4 { + reg = <4>; + + ncc0_1_funnel_in4: endpoint { + remote-endpoint = <&ncc0_4_rep_out>; + }; + }; + + port@5 { + reg = <5>; + + ncc0_1_funnel_in5: endpoint { + remote-endpoint = <&ncc0_5_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_funnel_out: endpoint { + remote-endpoint = <&ncc0_2_funnel_in2>; + }; + }; + }; + }; + + replicator@13490000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x13490000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_0_rep_in: endpoint { + remote-endpoint = <&etm0_out>; + }; + }; + }; + + out-ports { + port { + ncc0_0_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in0>; + }; + }; + }; + }; + + replicator@134a0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x134a0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_1_rep_in: endpoint { + remote-endpoint = <&etm1_out>; + }; + }; + }; + + out-ports { + port { + ncc0_1_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in1>; + }; + }; + }; + }; + + replicator@134b0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x134b0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_2_rep_in: endpoint { + remote-endpoint = <&etm2_out>; + }; + }; + }; + + out-ports { + port { + ncc0_2_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in2>; + }; + }; + }; + }; + + replicator@134c0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x134c0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_3_rep_in: endpoint { + remote-endpoint = <&etm3_out>; + }; + }; + }; + + out-ports { + port { + ncc0_3_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in3>; + }; + }; + }; + }; + + replicator@134d0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x134d0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_4_rep_in: endpoint { + remote-endpoint = <&etm4_out>; + }; + }; + }; + + out-ports { + port { + ncc0_4_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in4>; + }; + }; + }; + }; + + replicator@134e0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x134e0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster0_pd>; + + in-ports { + port { + ncc0_5_rep_in: endpoint { + remote-endpoint = <&etm5_out>; + }; + }; + }; + + out-ports { + port { + ncc0_5_rep_out: endpoint { + remote-endpoint = <&ncc0_1_funnel_in5>; + }; + }; + }; + }; + + funnel@13d01000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x13d01000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@2 { + reg = <2>; + + ncc1_2_funnel_in2: endpoint { + remote-endpoint = <&ncc1_1_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_2_funnel_out: endpoint { + remote-endpoint = <&ncc1_etf_in>; + }; + }; + }; + }; + + tmc@13d09000 { + compatible = "arm,coresight-tmc", "arm,primecell"; + reg = <0x0 0x13d09000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + port { + ncc1_etf_in: endpoint { + remote-endpoint = <&ncc1_2_funnel_out>; + }; + }; + }; + + out-ports { + port { + ncc1_etf_out: endpoint { + remote-endpoint = <&apss_funnel_in1>; + }; + }; + }; + }; + + funnel@13d81000 { + compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; + reg = <0x0 0x13d81000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ncc1_1_funnel_in0: endpoint { + remote-endpoint = <&ncc1_0_rep_out>; + }; + }; + + port@1 { + reg = <1>; + + ncc1_1_funnel_in1: endpoint { + remote-endpoint = <&ncc1_1_rep_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_funnel_out: endpoint { + remote-endpoint = <&ncc1_2_funnel_in2>; + }; + }; + }; + }; + + replicator@13d90000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x13d90000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + port { + ncc1_0_rep_in: endpoint { + remote-endpoint = <&etm6_out>; + }; + }; + }; + + out-ports { + port { + ncc1_0_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in0>; + }; + }; + }; + }; + + replicator@13da0000 { + compatible = "arm,coresight-dynamic-replicator", "arm,primecell"; + reg = <0x0 0x13da0000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + power-domains = <&cluster1_pd>; + + in-ports { + port { + ncc1_1_rep_in: endpoint { + remote-endpoint = <&etm7_out>; + }; + }; + }; + + out-ports { + port { + ncc1_1_rep_out: endpoint { + remote-endpoint = <&ncc1_1_funnel_in1>; + }; + }; + }; + }; + apps_smmu: iommu@15000000 { compatible = "qcom,sm8750-smmu-500", "qcom,smmu-500", "arm,mmu-500"; reg = <0x0 0x15000000 0x0 0x100000>; From e3d201deb24f4c26fad27f33284d5010cecf9ec8 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Mon, 2 Nov 2026 14:17:52 +0200 Subject: [PATCH 0798/1133] FROMLIST: arm64: dts: qcom: eliza: Add FastRPC support Describe the FastRPC nodes for both ADSP and CDSP remoteprocs, along with the ADSP remote heap memory region needed by the Audio PD. Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20261102-dts-qcom-eliza-add-fastrpc-v5-1-27ad8db4a47d@oss.qualcomm.com Signed-off-by: Abel Vesa --- arch/arm64/boot/dts/qcom/eliza.dtsi | 160 ++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/eliza.dtsi b/arch/arm64/boot/dts/qcom/eliza.dtsi index a8042291bd075..93e922de53cbd 100644 --- a/arch/arm64/boot/dts/qcom/eliza.dtsi +++ b/arch/arm64/boot/dts/qcom/eliza.dtsi @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -615,6 +616,14 @@ reg = <0x0 0xff800000 0x0 0x180000>; no-map; }; + + adsp_rpc_remote_heap_mem: adsp-rpc-remote-heap { + compatible = "shared-dma-pool"; + alloc-ranges = <0x0 0x00000000 0x1 0x00000000>; + alignment = <0x0 0x400000>; + size = <0x0 0xc00000>; + no-map; + }; }; smp2p-adsp { @@ -2432,6 +2441,69 @@ label = "lpass"; qcom,remote-pid = <2>; + fastrpc { + compatible = "qcom,fastrpc"; + + qcom,glink-channels = "fastrpcglink-apps-dsp"; + + label = "adsp"; + + memory-region = <&adsp_rpc_remote_heap_mem>; + + qcom,vmids = ; + + qcom,non-secure-domain; + + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + + iommus = <&apps_smmu 0x1003 0x80>, + <&apps_smmu 0x1063 0x20>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + + iommus = <&apps_smmu 0x1004 0x80>, + <&apps_smmu 0x1064 0x20>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + + iommus = <&apps_smmu 0x1005 0x80>, + <&apps_smmu 0x1065 0x20>; + dma-coherent; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + + iommus = <&apps_smmu 0x1006 0x80>, + <&apps_smmu 0x1066 0x20>; + dma-coherent; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + + iommus = <&apps_smmu 0x1007 0x40>, + <&apps_smmu 0x1067 0x0>; + dma-coherent; + }; + }; + gpr { compatible = "qcom,gpr"; qcom,glink-channels = "adsp_apps"; @@ -4571,6 +4643,94 @@ label = "cdsp"; qcom,remote-pid = <5>; + + fastrpc { + compatible = "qcom,fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "cdsp"; + qcom,non-secure-domain; + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@1 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <1>; + iommus = <&apps_smmu 0x0c01 0x0>; + dma-coherent; + }; + + compute-cb@2 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <2>; + iommus = <&apps_smmu 0x0c02 0x0>; + dma-coherent; + }; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu 0x0c03 0x0>; + dma-coherent; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu 0x0c04 0x0>; + dma-coherent; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu 0x0c05 0x0>; + dma-coherent; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu 0x0c06 0x0>; + dma-coherent; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + iommus = <&apps_smmu 0x0c07 0x0>; + dma-coherent; + }; + + compute-cb@8 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <8>; + iommus = <&apps_smmu 0x0c08 0x0>; + dma-coherent; + }; + + /* note: secure cb9 in downstream */ + + compute-cb@12 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <12>; + iommus = <&apps_smmu 0x0c0c 0x0>; + dma-coherent; + }; + + compute-cb@13 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <13>; + iommus = <&apps_smmu 0x0c0d 0x0>; + dma-coherent; + }; + + compute-cb@14 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <14>; + iommus = <&apps_smmu 0x0c0e 0x0>; + dma-coherent; + }; + }; }; }; From d93f1f91a365cd7879af7546de8fe4ee1250fe0d Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Mon, 2 Nov 2026 14:10:47 +0200 Subject: [PATCH 0799/1133] FROMLIST: dt-bindings: arm: qcom: Describe Eliza CQS eMMC and UFS variants The Eliza CQS SoM is available with either eMMC or UFS storage, but its compatible and the compatible of the EVK assembly do not identify the storage variant. Both SoMs connect to the same Eliza EVK carrier board. Describe separate compatible strings for each SoM and for the carrier populated with that SoM, so the two hardware configurations can be identified independently. Neither the CQS SoMs nor their corresponding EVK assemblies have been made publicly available. Replacing the storage-neutral compatible strings therefore does not affect existing users. Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20261102-dts-qcom-eliza-add-ufs-variant-v4-1-c92512c7c759@oss.qualcomm.com Signed-off-by: Abel Vesa --- Documentation/devicetree/bindings/arm/qcom.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 121ca557ce1ef..a75963b30186d 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -56,7 +56,16 @@ properties: - const: qcom,apq8084 - items: + - const: qcom,eliza-cqs-evk-emmc - const: qcom,eliza-cqs-evk + - const: qcom,eliza-cqs-som-emmc + - const: qcom,eliza-cqs-som + - const: qcom,eliza + + - items: + - const: qcom,eliza-cqs-evk-ufs + - const: qcom,eliza-cqs-evk + - const: qcom,eliza-cqs-som-ufs - const: qcom,eliza-cqs-som - const: qcom,eliza From 037251a62d206682b877763c8f119a1781f3fb0f Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Mon, 2 Nov 2026 14:10:48 +0200 Subject: [PATCH 0800/1133] FROMLIST: arm64: dts: qcom: eliza-cqs-evk: Move sound card support to Eliza EVK generic The sound card support is the same across all variants of the Eliza EVK. That means we can reuse it even for Eliza CQM EVK later. So move the sound related nodes from Eliza CQS EVK to Eliza EVK generic implementation. Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20261102-dts-qcom-eliza-add-ufs-variant-v4-2-c92512c7c759@oss.qualcomm.com Signed-off-by: Abel Vesa --- arch/arm64/boot/dts/qcom/eliza-cqs-evk.dts | 141 --------------------- arch/arm64/boot/dts/qcom/eliza-evk.dtsi | 139 ++++++++++++++++++++ 2 files changed, 139 insertions(+), 141 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/eliza-cqs-evk.dts b/arch/arm64/boot/dts/qcom/eliza-cqs-evk.dts index 5e4175291f05c..43d428a4ed2df 100644 --- a/arch/arm64/boot/dts/qcom/eliza-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/eliza-cqs-evk.dts @@ -5,151 +5,10 @@ /dts-v1/; -#include - #include "eliza-cqs-som.dtsi" #include "eliza-evk.dtsi" / { model = "Qualcomm Technologies, Inc. Eliza CQS EVK"; compatible = "qcom,eliza-cqs-evk", "qcom,eliza-cqs-som", "qcom,eliza"; - - sound { - compatible = "qcom,eliza-sndcard", "qcom,sm8450-sndcard"; - model = "eliza-cqs-evk"; - - 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", - "VA DMIC4", "vdd-micb", - "VA DMIC5", "vdd-micb", - "VA DMIC6", "vdd-micb", - "VA DMIC7", "vdd-micb"; - - va-dai-link { - link-name = "VA Capture"; - - codec { - sound-dai = <&lpass_vamacro 0>; - }; - - cpu { - sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; - }; - - platform { - sound-dai = <&q6apm>; - }; - }; - - wsa-dai-link { - link-name = "WSA Playback"; - - codec { - sound-dai = <&left_spkr>, <&right_spkr>, - <&swr0 0>, <&lpass_wsamacro 0>; - }; - - cpu { - sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>; - }; - - platform { - sound-dai = <&q6apm>; - }; - }; - }; - - dmic_eldo: regulator-dmic-eldo { - compatible = "regulator-fixed"; - regulator-name = "dmic-eldo"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - gpio = <&pm7550_gpios 8 GPIO_ACTIVE_HIGH>; - enable-active-high; - vin-supply = <&vreg_bob>; - }; -}; - -&lpass_vamacro { - pinctrl-0 = <&dmic01_default>, <&dmic23_default>, - <&dmic45_default>, <&dmic67_default>; - pinctrl-names = "default"; - - vdd-micb-supply = <&dmic_eldo>; - qcom,dmic-sample-rate = <4800000>; -}; - -&swr0 { - pinctrl-0 = <&wsa_swr_active>; - pinctrl-names = "default"; - - status = "okay"; - - /* WSA8845, Speaker Left */ - left_spkr: speaker@0,0 { - compatible = "sdw20217020400"; - reg = <0 0>; - pinctrl-0 = <&spkr_1_sd_n_active>; - pinctrl-names = "default"; - powerdown-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; - vdd-1p8-supply = <&vreg_l7b>; - vdd-io-supply = <&vreg_l7b>; - - #sound-dai-cells = <0>; - sound-name-prefix = "SpkrLeft"; - - /* - * WSA8845 Port 1 (DAC) <=> SWR0 Port 1 (SPKR_L) - * WSA8845 Port 2 (COMP) <=> SWR0 Port 2 (SPKR_L_COMP) - * WSA8845 Port 3 (BOOST) <=> SWR0 Port 3 (SPKR_L_BOOST) - * WSA8845 Port 4 (PBR) <=> SWR0 Port 7 (PBR) - * WSA8845 Port 5 (VISENSE) <=> SWR0 Port 10 (SPKR_L_VI) - * WSA8845 Port 6 (CPS) <=> SWR0 Port 13 (CPS) - */ - qcom,port-mapping = <1 2 3 7 10 13>; - }; - - /* WSA8845, Speaker Right */ - right_spkr: speaker@0,1 { - compatible = "sdw20217020400"; - reg = <0 1>; - pinctrl-0 = <&spkr_2_sd_n_active>; - pinctrl-names = "default"; - powerdown-gpios = <&tlmm 79 GPIO_ACTIVE_LOW>; - vdd-1p8-supply = <&vreg_l7b>; - vdd-io-supply = <&vreg_l7b>; - - #sound-dai-cells = <0>; - sound-name-prefix = "SpkrRight"; - - /* - * WSA8845 Port 1 (DAC) <=> SWR0 Port 4 (SPKR_R) - * WSA8845 Port 2 (COMP) <=> SWR0 Port 5 (SPKR_R_COMP) - * WSA8845 Port 3 (BOOST) <=> SWR0 Port 6 (SPKR_R_BOOST) - * WSA8845 Port 4 (PBR) <=> SWR0 Port 7 (PBR) - * WSA8845 Port 5 (VISENSE) <=> SWR0 Port 11 (SPKR_R_VI) - * WSA8845 Port 6 (CPS) <=> SWR0 Port 13 (CPS) - */ - qcom,port-mapping = <4 5 6 7 11 13>; - }; -}; - -&tlmm { - spkr_1_sd_n_active: spkr-1-sd-n-active-state { - pins = "gpio59"; - function = "gpio"; - drive-strength = <16>; - bias-disable; - }; - - spkr_2_sd_n_active: spkr-2-sd-n-active-state { - pins = "gpio79"; - function = "gpio"; - drive-strength = <16>; - bias-disable; - }; }; diff --git a/arch/arm64/boot/dts/qcom/eliza-evk.dtsi b/arch/arm64/boot/dts/qcom/eliza-evk.dtsi index 6c5cc47a183ea..726fd8dd6c0d0 100644 --- a/arch/arm64/boot/dts/qcom/eliza-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/eliza-evk.dtsi @@ -3,6 +3,8 @@ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ +#include + / { aliases { serial0 = &uart13; @@ -63,6 +65,55 @@ }; }; + sound { + compatible = "qcom,eliza-sndcard", "qcom,sm8450-sndcard"; + model = "eliza-cqs-evk"; + + 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", + "VA DMIC4", "vdd-micb", + "VA DMIC5", "vdd-micb", + "VA DMIC6", "vdd-micb", + "VA DMIC7", "vdd-micb"; + + va-dai-link { + link-name = "VA Capture"; + + codec { + sound-dai = <&lpass_vamacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wsa-dai-link { + link-name = "WSA Playback"; + + codec { + sound-dai = <&left_spkr>, <&right_spkr>, + <&swr0 0>, <&lpass_wsamacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + vreg_0p9: regulator-0v9 { compatible = "regulator-fixed"; regulator-name = "VREG_0P9"; @@ -94,6 +145,16 @@ enable-active-high; }; + dmic_eldo: regulator-dmic-eldo { + compatible = "regulator-fixed"; + regulator-name = "dmic-eldo"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&pm7550_gpios 8 GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vreg_bob>; + }; + connector-0 { compatible = "pcie-m2-e-connector"; vpcie3v3-supply = <&vreg_pcie_m_3p3>; @@ -148,6 +209,15 @@ }; }; +&lpass_vamacro { + pinctrl-0 = <&dmic01_default>, <&dmic23_default>, + <&dmic45_default>, <&dmic67_default>; + pinctrl-names = "default"; + + vdd-micb-supply = <&dmic_eldo>; + qcom,dmic-sample-rate = <4800000>; +}; + &pcie0 { status = "okay"; }; @@ -197,12 +267,81 @@ status = "okay"; }; +&swr0 { + pinctrl-0 = <&wsa_swr_active>; + pinctrl-names = "default"; + + status = "okay"; + + /* WSA8845, Speaker Left */ + left_spkr: speaker@0,0 { + compatible = "sdw20217020400"; + reg = <0 0>; + pinctrl-0 = <&spkr_1_sd_n_active>; + pinctrl-names = "default"; + powerdown-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + vdd-1p8-supply = <&vreg_l7b>; + vdd-io-supply = <&vreg_l7b>; + + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrLeft"; + + /* + * WSA8845 Port 1 (DAC) <=> SWR0 Port 1 (SPKR_L) + * WSA8845 Port 2 (COMP) <=> SWR0 Port 2 (SPKR_L_COMP) + * WSA8845 Port 3 (BOOST) <=> SWR0 Port 3 (SPKR_L_BOOST) + * WSA8845 Port 4 (PBR) <=> SWR0 Port 7 (PBR) + * WSA8845 Port 5 (VISENSE) <=> SWR0 Port 10 (SPKR_L_VI) + * WSA8845 Port 6 (CPS) <=> SWR0 Port 13 (CPS) + */ + qcom,port-mapping = <1 2 3 7 10 13>; + }; + + /* WSA8845, Speaker Right */ + right_spkr: speaker@0,1 { + compatible = "sdw20217020400"; + reg = <0 1>; + pinctrl-0 = <&spkr_2_sd_n_active>; + pinctrl-names = "default"; + powerdown-gpios = <&tlmm 79 GPIO_ACTIVE_LOW>; + vdd-1p8-supply = <&vreg_l7b>; + vdd-io-supply = <&vreg_l7b>; + + #sound-dai-cells = <0>; + sound-name-prefix = "SpkrRight"; + + /* + * WSA8845 Port 1 (DAC) <=> SWR0 Port 4 (SPKR_R) + * WSA8845 Port 2 (COMP) <=> SWR0 Port 5 (SPKR_R_COMP) + * WSA8845 Port 3 (BOOST) <=> SWR0 Port 6 (SPKR_R_BOOST) + * WSA8845 Port 4 (PBR) <=> SWR0 Port 7 (PBR) + * WSA8845 Port 5 (VISENSE) <=> SWR0 Port 11 (SPKR_R_VI) + * WSA8845 Port 6 (CPS) <=> SWR0 Port 13 (CPS) + */ + qcom,port-mapping = <4 5 6 7 11 13>; + }; +}; + &tlmm { sd_cd: sd-cd-state { pins = "gpio58"; function = "gpio"; bias-pull-up; }; + + spkr_1_sd_n_active: spkr-1-sd-n-active-state { + pins = "gpio59"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + spkr_2_sd_n_active: spkr-2-sd-n-active-state { + pins = "gpio79"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; }; &pcie1 { From ed50910c21d82fd12d6f3ca0c1eb06bae846384a Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Mon, 2 Nov 2026 14:10:49 +0200 Subject: [PATCH 0801/1133] FROMLIST: arm64: dts: qcom: eliza: Separate common CQS SoM and eMMC configuration The existing CQS SoM description includes its eMMC storage configuration, while the SoM and EVK filenames and compatibles do not identify the storage variant. The UFS-equipped CQS SoM uses the same EVK carrier and shares the rest of the SoM hardware, so duplicating the existing SoM description would leave two copies of that shared configuration. Keep the common hardware in eliza-cqs-som.dtsi and move the eMMC controller configuration and its 1.8 V I/O supply constraint into eliza-cqs-som-emmc.dtsi. This lets the UFS variant include the common hardware directly without inheriting and disabling eMMC configuration. Rename the existing EVK DTS and its compatible strings to identify the assembly using the eMMC-equipped SoM. The carrier hardware is unchanged. Neither the CQS SoM nor the EVK assembly has been made publicly available, so the DTB rename does not affect existing users. Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20261102-dts-qcom-eliza-add-ufs-variant-v4-3-c92512c7c759@oss.qualcomm.com Signed-off-by: Abel Vesa --- arch/arm64/boot/dts/qcom/Makefile | 2 +- .../boot/dts/qcom/eliza-cqs-evk-emmc.dts | 18 +++++++++++++ arch/arm64/boot/dts/qcom/eliza-cqs-evk.dts | 14 ---------- .../boot/dts/qcom/eliza-cqs-som-emmc.dtsi | 27 +++++++++++++++++++ arch/arm64/boot/dts/qcom/eliza-cqs-som.dtsi | 18 ------------- 5 files changed, 46 insertions(+), 33 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/eliza-cqs-evk-emmc.dts delete mode 100644 arch/arm64/boot/dts/qcom/eliza-cqs-evk.dts create mode 100644 arch/arm64/boot/dts/qcom/eliza-cqs-som-emmc.dtsi diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..1a06b321db203 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -14,7 +14,7 @@ dtb-$(CONFIG_ARCH_QCOM) += apq8094-sony-xperia-kitakami-karin_windy.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8096-db820c.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8096sg-db820c.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8096-ifc6640.dtb -dtb-$(CONFIG_ARCH_QCOM) += eliza-cqs-evk.dtb +dtb-$(CONFIG_ARCH_QCOM) += eliza-cqs-evk-emmc.dtb dtb-$(CONFIG_ARCH_QCOM) += eliza-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += glymur-asus-zenbook-a14-ux3407na.dtb dtb-$(CONFIG_ARCH_QCOM) += glymur-asus-zenbook-a16-ux3607oa.dtb diff --git a/arch/arm64/boot/dts/qcom/eliza-cqs-evk-emmc.dts b/arch/arm64/boot/dts/qcom/eliza-cqs-evk-emmc.dts new file mode 100644 index 0000000000000..36f63dd1637f1 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/eliza-cqs-evk-emmc.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include "eliza-cqs-som-emmc.dtsi" +#include "eliza-evk.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. Eliza CQS EVK (eMMC)"; + compatible = "qcom,eliza-cqs-evk-emmc", + "qcom,eliza-cqs-evk", + "qcom,eliza-cqs-som-emmc", + "qcom,eliza-cqs-som", + "qcom,eliza"; +}; diff --git a/arch/arm64/boot/dts/qcom/eliza-cqs-evk.dts b/arch/arm64/boot/dts/qcom/eliza-cqs-evk.dts deleted file mode 100644 index 43d428a4ed2df..0000000000000 --- a/arch/arm64/boot/dts/qcom/eliza-cqs-evk.dts +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* - * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. - */ - -/dts-v1/; - -#include "eliza-cqs-som.dtsi" -#include "eliza-evk.dtsi" - -/ { - model = "Qualcomm Technologies, Inc. Eliza CQS EVK"; - compatible = "qcom,eliza-cqs-evk", "qcom,eliza-cqs-som", "qcom,eliza"; -}; diff --git a/arch/arm64/boot/dts/qcom/eliza-cqs-som-emmc.dtsi b/arch/arm64/boot/dts/qcom/eliza-cqs-som-emmc.dtsi new file mode 100644 index 0000000000000..af4ade2d4e455 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/eliza-cqs-som-emmc.dtsi @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include "eliza-cqs-som.dtsi" + +&sdhc_1 { + vmmc-supply = <&vreg_l12b>; + vqmmc-supply = <&vreg_l1d>; + pinctrl-0 = <&sdc1_default>; + pinctrl-1 = <&sdc1_sleep>; + pinctrl-names = "default", "sleep"; + mmc-hs400-1_8v; + mmc-hs200-1_8v; + non-removable; + supports-cqe; + no-sdio; + no-sd; + + status = "okay"; +}; + +&vreg_l1d { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +}; diff --git a/arch/arm64/boot/dts/qcom/eliza-cqs-som.dtsi b/arch/arm64/boot/dts/qcom/eliza-cqs-som.dtsi index 03f9192324c73..a378a500d9e01 100644 --- a/arch/arm64/boot/dts/qcom/eliza-cqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/eliza-cqs-som.dtsi @@ -278,8 +278,6 @@ vreg_l1d: ldo1 { regulator-name = "vreg_l1d"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; regulator-initial-mode = ; }; }; @@ -396,22 +394,6 @@ status = "okay"; }; -&sdhc_1 { - vmmc-supply = <&vreg_l12b>; - vqmmc-supply = <&vreg_l1d>; - pinctrl-0 = <&sdc1_default>; - pinctrl-1 = <&sdc1_sleep>; - pinctrl-names = "default", "sleep"; - mmc-hs400-1_8v; - mmc-hs200-1_8v; - non-removable; - supports-cqe; - no-sdio; - no-sd; - - status = "okay"; -}; - &tlmm { gpio-reserved-ranges = <20 4>, /* NFC SPI */ <111 2>, /* WCN UART1 */ From c20b845b1a48a25d47f7bb27c9795d1a61f0d652 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Mon, 2 Nov 2026 14:10:50 +0200 Subject: [PATCH 0802/1133] FROMLIST: arm64: dts: qcom: eliza: Add CQS EVK UFS variant The Eliza CQS SoM is also available with UFS storage instead of eMMC, but the existing description covers only the eMMC-equipped SoM and its EVK assembly. The UFS SoM uses the UFS controller and PHY instead of SDHCI, and its vreg_l1d supply needs a 1.14-1.26 V constraint instead of 1.8 V. These differences are on the SoM; both variants use the same EVK carrier. Describe the UFS controller, PHY supplies and reset GPIO in a dedicated SoM include, along with the variant-specific vreg_l1d voltage constraint. Include eliza-cqs-som.dtsi for the shared hardware so neither storage variant duplicates it or inherits the other's storage configuration. Describe the UFS-equipped EVK assembly by combining the UFS SoM include with the shared Eliza EVK carrier description. Give it a separate DTB and the UFS-specific compatible strings so it can be selected for the corresponding SoM. Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20261102-dts-qcom-eliza-add-ufs-variant-v4-4-c92512c7c759@oss.qualcomm.com Signed-off-by: Abel Vesa --- arch/arm64/boot/dts/qcom/Makefile | 1 + .../arm64/boot/dts/qcom/eliza-cqs-evk-ufs.dts | 18 ++++++++++++ .../boot/dts/qcom/eliza-cqs-som-ufs.dtsi | 29 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/eliza-cqs-evk-ufs.dts create mode 100644 arch/arm64/boot/dts/qcom/eliza-cqs-som-ufs.dtsi diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 1a06b321db203..988e0c10b5146 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -15,6 +15,7 @@ dtb-$(CONFIG_ARCH_QCOM) += apq8096-db820c.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8096sg-db820c.dtb dtb-$(CONFIG_ARCH_QCOM) += apq8096-ifc6640.dtb dtb-$(CONFIG_ARCH_QCOM) += eliza-cqs-evk-emmc.dtb +dtb-$(CONFIG_ARCH_QCOM) += eliza-cqs-evk-ufs.dtb dtb-$(CONFIG_ARCH_QCOM) += eliza-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += glymur-asus-zenbook-a14-ux3407na.dtb dtb-$(CONFIG_ARCH_QCOM) += glymur-asus-zenbook-a16-ux3607oa.dtb diff --git a/arch/arm64/boot/dts/qcom/eliza-cqs-evk-ufs.dts b/arch/arm64/boot/dts/qcom/eliza-cqs-evk-ufs.dts new file mode 100644 index 0000000000000..41239874ee82c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/eliza-cqs-evk-ufs.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; + +#include "eliza-cqs-som-ufs.dtsi" +#include "eliza-evk.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. Eliza CQS EVK (UFS)"; + compatible = "qcom,eliza-cqs-evk-ufs", + "qcom,eliza-cqs-evk", + "qcom,eliza-cqs-som-ufs", + "qcom,eliza-cqs-som", + "qcom,eliza"; +}; diff --git a/arch/arm64/boot/dts/qcom/eliza-cqs-som-ufs.dtsi b/arch/arm64/boot/dts/qcom/eliza-cqs-som-ufs.dtsi new file mode 100644 index 0000000000000..7e99d273fd813 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/eliza-cqs-som-ufs.dtsi @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include "eliza-cqs-som.dtsi" + +&ufs_mem_hc { + reset-gpios = <&tlmm 185 GPIO_ACTIVE_LOW>; + + vcc-supply = <&vreg_l12b>; + vcc-max-microamp = <1300000>; + vccq-supply = <&vreg_l1d>; + vccq-max-microamp = <1200000>; + + status = "okay"; +}; + +&ufs_mem_phy { + vdda-phy-supply = <&vreg_l6b>; + vdda-pll-supply = <&vreg_l4b>; + + status = "okay"; +}; + +&vreg_l1d { + regulator-min-microvolt = <1140000>; + regulator-max-microvolt = <1260000>; +}; From 78ea785788a0b33dd8a3c046e019d2b98b366ef9 Mon Sep 17 00:00:00 2001 From: Zhiyuan Sheng Date: Fri, 30 Oct 2026 11:09:06 +0800 Subject: [PATCH 0803/1133] FROMLIST: arm64: dts: qcom: eliza-evk: Fix M.2 W_DISABLE2# GPIO polarity The W_DISABLE2# signal of the M.2 E key connector is active-low as defined in the PCI Express M.2 Specification. Fix the w-disable2-gpios polarity by using GPIO_ACTIVE_LOW instead of GPIO_ACTIVE_HIGH. Fixes: 073c6a891eb3 ("arm64: dts: qcom: eliza-evk: Add PCIe0 with M.2 E key connector") Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Signed-off-by: Zhiyuan Sheng Link: https://patch.msgid.link/20261030030906.3856759-1-zhiyuan.sheng@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/eliza-evk.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/eliza-evk.dtsi b/arch/arm64/boot/dts/qcom/eliza-evk.dtsi index 726fd8dd6c0d0..02e58a4bc91d4 100644 --- a/arch/arm64/boot/dts/qcom/eliza-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/eliza-evk.dtsi @@ -159,7 +159,7 @@ compatible = "pcie-m2-e-connector"; vpcie3v3-supply = <&vreg_pcie_m_3p3>; w-disable1-gpios = <&tlmm 35 GPIO_ACTIVE_LOW>; - w-disable2-gpios = <&pm8550vs_g_gpios 4 GPIO_ACTIVE_HIGH>; + w-disable2-gpios = <&pm8550vs_g_gpios 4 GPIO_ACTIVE_LOW>; pinctrl-0 = <&m2_w_disable1>, <&m2_w_disable2>; pinctrl-names = "default"; From 3904dd5e0fab9a11820d508a9d17c826d748bb06 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Mon, 21 Sep 2026 17:51:36 +0800 Subject: [PATCH 0804/1133] FROMLIST: arm64: dts: qcom: eliza: Add iris video codec node Describe the Iris video codec hardware found in the Eliza SoC. The iris node is placed at 0xaa00000 with VPU3.3 hardware capabilities. It uses GCC_VIDEO_AXI0 for bus interface, and VIDEO_CC_MVS0C/MVS0 for core and codec clocks respectively, along with SM8650-like AXI bus/XO/core reset support. Signed-off-by: Wangao Wang Reviewed-by: Vikash Garodia Acked-by: Konrad Dybcio Link: https://patch.msgid.link/20260921-add_iris_for_eliza-v2-3-5fe7be8c0230@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/eliza.dtsi | 98 +++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/eliza.dtsi b/arch/arm64/boot/dts/qcom/eliza.dtsi index 93e922de53cbd..ea5cd8fb3a5e2 100644 --- a/arch/arm64/boot/dts/qcom/eliza.dtsi +++ b/arch/arm64/boot/dts/qcom/eliza.dtsi @@ -3429,6 +3429,104 @@ #power-domain-cells = <1>; }; + iris: video-codec@aa00000 { + compatible = "qcom,eliza-iris"; + reg = <0 0xaa00000 0 0xf0000>; + + interrupts = ; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd RPMHPD_MX>, + <&rpmhpd RPMHPD_CX>; + 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_MVP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + memory-region = <&video_mem>; + + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>, + <&videocc VIDEO_CC_XO_CLK_ARES>, + <&videocc VIDEO_CC_MVS0C_CLK_ARES>; + reset-names = "bus", + "xo", + "core"; + + dma-coherent; + + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0x0 0xe0000000>; + + status = "disabled"; + + non-pixel { + iommus = <&apps_smmu 0x1940 0x0>; + iommu-ranges = <0x25800000 0xba800000>; + }; + + pixel { + iommus = <&apps_smmu 0x1947 0x0>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-192000000 { + opp-hz = /bits/ 64 <192000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-366000000 { + opp-hz = /bits/ 64 <366000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-533333333 { + opp-hz = /bits/ 64 <533333333>; + required-opps = <&rpmhpd_opp_turbo>, + <&rpmhpd_opp_svs_l1>; + }; + }; + }; + videocc: clock-controller@aaf0000 { compatible = "qcom,eliza-videocc"; reg = <0x0 0xaaf0000 0x0 0x10000>; From 71498c3fab5ff6a5d2e7b6ad11c50bb4af8ac2fe Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Mon, 21 Sep 2026 17:51:37 +0800 Subject: [PATCH 0805/1133] FROMLIST: arm64: dts: qcom: eliza-mtp: Enable iris video codec The Eliza MTP includes the Iris video codec, but the device tree leaves the node disabled. Mark it as okay so the video codec driver can probe on this board. Reviewed-by: Abel Vesa Signed-off-by: Wangao Wang Link: https://patch.msgid.link/20260921-add_iris_for_eliza-v2-4-5fe7be8c0230@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/eliza-mtp.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/eliza-mtp.dts b/arch/arm64/boot/dts/qcom/eliza-mtp.dts index ee05192adcfb9..e5a698602dfc7 100644 --- a/arch/arm64/boot/dts/qcom/eliza-mtp.dts +++ b/arch/arm64/boot/dts/qcom/eliza-mtp.dts @@ -430,6 +430,10 @@ firmware-name = "qcom/eliza/gen71700_zap.mbn"; }; +&iris { + status = "okay"; +}; + &mdss { status = "okay"; }; From 8b9d593cb3c576e8efa746a599f0510715dc214c Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Mon, 21 Sep 2026 17:51:38 +0800 Subject: [PATCH 0806/1133] FROMLIST: arm64: dts: qcom: eliza-evk: Enable iris video codec The Eliza EVK includes the Iris video codec, but the device tree leaves the node disabled. Mark it as okay so the video codec driver can probe on this board. Signed-off-by: Wangao Wang Link: https://patch.msgid.link/20260921-add_iris_for_eliza-v2-5-5fe7be8c0230@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/eliza-evk.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/eliza-evk.dtsi b/arch/arm64/boot/dts/qcom/eliza-evk.dtsi index 02e58a4bc91d4..b8e8c67c70b03 100644 --- a/arch/arm64/boot/dts/qcom/eliza-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/eliza-evk.dtsi @@ -209,6 +209,10 @@ }; }; +&iris { + status = "okay"; +}; + &lpass_vamacro { pinctrl-0 = <&dmic01_default>, <&dmic23_default>, <&dmic45_default>, <&dmic67_default>; From 59512e01a50f8629d5e9a85cdeaf088720087bba Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Sun, 9 Nov 2025 20:07:24 +0530 Subject: [PATCH 0807/1133] FROMLIST: arm64: dts: qcom: monaco: Add PSCI SYSTEM_RESET2 types Add support for SYSTEM_RESET2 vendor-specific resets as reboot-modes in the psci node. Describe the resets: "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/20251109-arm-psci-system_reset2-vendor-reboots-v17-11-46e085bca4cc@oss.qualcomm.com Signed-off-by: Shivendra Pratap --- arch/arm64/boot/dts/qcom/monaco.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 35fbee63d4c65..7b688b65016f4 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -722,6 +722,11 @@ #power-domain-cells = <0>; domain-idle-states = <&system_sleep>; }; + + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; }; reserved-memory { From 2d850ba29466f61c82d964fbd05fb4a9846faf66 Mon Sep 17 00:00:00 2001 From: Karthik S Date: Wed, 20 May 2026 13:04:46 +0530 Subject: [PATCH 0808/1133] FROMLIST: arm64: dts: qcom: Enable secondary mi2s Enable secondary mi2s to support HDMI audio. Link: https://lore.kernel.org/all/20260413091937.134469-2-kumar.singh@oss.qualcomm.com/ Signed-off-by: Karthik S --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 5 +++ arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 43 ++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index a086ac7cd3ce5..95267c1bac1d9 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -6688,6 +6688,11 @@ function = "mi2s1_ws"; }; + mi2s1_mclk: mi2s1-mclk-state { + pins = "gpio105"; + function = "sec_mi2s"; + }; + sdc1_clk: sdc1-clk-state { pins = "sdc1_clk"; }; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index 6ba5ff1582e45..c5ffaa2611a9b 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -711,6 +711,7 @@ lt9611_codec: hdmi-bridge@2b { compatible = "lontium,lt9611uxc"; reg = <0x2b>; + #sound-dai-cells = <1>; interrupts-extended = <&tlmm 24 IRQ_TYPE_EDGE_FALLING>; reset-gpios = <&pm7250b_gpios 2 GPIO_ACTIVE_HIGH>; @@ -1193,6 +1194,9 @@ compatible = "qcom,qcs6490-rb3gen2-sndcard"; model = "QCS6490-RB3Gen2"; + pinctrl-0 = <&mi2s1_data0>, <&mi2s1_mclk>, <&mi2s1_sclk>, <&mi2s1_ws>; + pinctrl-names = "default"; + audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT", "SpkrRight IN", "WSA_SPK2 OUT", "VA DMIC0", "vdd-micb", @@ -1232,6 +1236,22 @@ sound-dai = <&q6apm>; }; }; + + mi2s1-playback-dai-link { + link-name = "Secondary MI2S Playback"; + + codec { + sound-dai = <<9611_codec 0>; + }; + + cpu { + sound-dai = <&q6apmbedai SECONDARY_MI2S_RX>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; }; &spi3 { @@ -1571,3 +1591,26 @@ compatible = "qcom,qcm6490-lpassaudiocc"; /delete-property/ power-domains; }; + +&mi2s1_data0 { + drive-strength = <8>; + bias-disable; +}; + +&mi2s1_mclk { + drive-strength = <8>; + bias-disable; + output-high; +}; + +&mi2s1_sclk { + drive-strength = <8>; + bias-disable; + output-high; +}; + +&mi2s1_ws { + drive-strength = <8>; + bias-disable; + output-high; +}; From 6449873c913df36d0de4af25edf3cd37c5d3c329 Mon Sep 17 00:00:00 2001 From: Karthik S Date: Wed, 20 May 2026 13:05:53 +0530 Subject: [PATCH 0809/1133] FROMLIST: arm64: dts: qcom: qcs6490: Enable DP audio Add new dai link to enable DP audio. Link: https://lore.kernel.org/all/20260413091937.134469-3-kumar.singh@oss.qualcomm.com/ Signed-off-by: Karthik S --- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index c5ffaa2611a9b..dd5024484fd10 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -1252,6 +1252,22 @@ sound-dai = <&q6apm>; }; }; + + dp-dai-link { + link-name = "DisplayPort0 Playback"; + + codec { + sound-dai = <&mdss_dp>; + }; + + cpu { + sound-dai = <&q6apmbedai DISPLAY_PORT_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; }; &spi3 { From 403fb89e89bc8a18daeff53a5bd7b579aef9a258 Mon Sep 17 00:00:00 2001 From: Karthik S Date: Wed, 20 May 2026 12:35:59 +0530 Subject: [PATCH 0810/1133] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Add WCD headset playback and record for qcs6490-rb3gen2 industrial mezzanine Add WCD playback and capture DAI link to sound node. Add WCD codec node and corresponding soundwire nodes to perform headset playback and record. Link: https://lore.kernel.org/all/20260423071951.3181130-1-karthik.s@oss.qualcomm.com/#t Signed-off-by: Karthik S --- .../qcs6490-rb3gen2-industrial-mezzanine.dtso | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso index 5fa54d7626ddd..de0343a54a4b3 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso @@ -6,6 +6,7 @@ /dts-v1/; /plugin/; #include +#include #include #include @@ -37,6 +38,29 @@ }; / { + wcd9370: audio-codec { + compatible = "qcom,wcd9370-codec"; + + pinctrl-0 = <&wcd_default>; + pinctrl-names = "default"; + + reset-gpios = <&tlmm 83 GPIO_ACTIVE_LOW>; + vdd-buck-supply = <&vph_pwr>; + vdd-rxtx-supply = <&vph_pwr>; + vdd-px-supply = <&vph_pwr>; + vdd-mic-bias-supply = <&vph_pwr>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + qcom,micbias4-microvolt = <1800000>; + qcom,hphl-jack-type-normally-closed = <1>; + qcom,ground-jack-type-normally-closed = <1>; + qcom,rx-device = <&wcd937x_rx>; + qcom,tx-device = <&wcd937x_tx>; + + #sound-dai-cells = <1>; + }; + hdmi-connector { status = "disabled"; }; @@ -137,6 +161,14 @@ status = "disabled"; }; +&lpass_rx_macro { + status = "okay"; +}; + +&lpass_tx_macro { + status = "okay"; +}; + &mdss_dsi0_out { remote-endpoint = <<9211c_in>; }; @@ -335,6 +367,101 @@ }; }; +&sound { + model = "qcs6490-rb3gen2-ia-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 SWR_ADC1", "ADC2_OUTPUT", + "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + 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>; + }; + }; + + 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>; + }; + }; +}; + +&swr0 { + status = "okay"; + + wcd937x_rx: codec@0,4 { + compatible = "sdw20217010a00"; + reg = <0 4>; + + /* + * WCD9370 RX Port 1 (HPH_L/R) <==> SWR1 Port 1 (HPH_L/R) + * WCD9370 RX Port 2 (CLSH) <==> SWR1 Port 2 (CLSH) + * WCD9370 RX Port 3 (COMP_L/R) <==> SWR1 Port 3 (COMP_L/R) + * WCD9370 RX Port 4 (LO) <==> SWR1 Port 4 (LO) + * WCD9370 RX Port 5 (DSD_L/R) <==> SWR1 Port 5 (DSD) + */ + qcom,rx-port-mapping = <1 2 3 4 5>; + + /* + * Static channels mapping between slave and master rx port channels. + * In the order of slave port channels, which is + * hph_l, hph_r, clsh, comp_l, comp_r, lo, dsd_r, dsd_l. + */ + 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>; + + /* + * WCD9370 TX Port 1 (ADC1) <=> SWR2 Port 2 + * WCD9370 TX Port 2 (ADC2, 3) <=> SWR2 Port 2 + * WCD9370 TX Port 3 (DMIC0,1,2,3 & MBHC) <=> SWR2 Port 3 + * WCD9370 TX Port 4 (DMIC4,5,6,7) <=> SWR2 Port 4 + */ + qcom,tx-port-mapping = <1 1 2 3>; + + /* + * Static channel mapping between slave and master tx port channels. + * In the order of slave port channels which is adc1, adc2, adc3, + * mic0, dmic1, mbhc, dmic2, dmic3, dmci4, dmic5, dmic6, dmic7. + */ + qcom,tx-channel-mapping = /bits/ 8 <1 2 1 1 2 3 3 4 1 2 3 4>; + }; +}; + + &tlmm { pcie0_tc9563_resx_n: pcie0-tc9563-resx-state { pins = "gpio78"; @@ -374,6 +501,12 @@ output-enable; }; + wcd_default: wcd-reset-n-active-state { + pins = "gpio83"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; }; &wifi { From bb8b9cccf8d4f0b237df52901bb7369b0a9631e7 Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Thu, 13 Nov 2025 18:35:19 +0530 Subject: [PATCH 0811/1133] FROMLIST: arm64: dts: qcom: monaco-evk: Enable Bluetooth support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's a WCN6855 WiFi/Bluetooth module on an M.2 card. To make Bluetooth work, we need to define the necessary device tree nodes, including UART configuration and power supplies. Since there is no standard M.2 binding in the device tree at present, the PMU is described using dedicated PMU nodes to represent the internal regulators required by the module. The module provides a 3.3V supply, which originates from the main board’s 12V rail. To represent this power hierarchy in the device tree, add a fixed 12V regulator node as the DC-IN source and link it to the 3.3V regulator node. Signed-off-by: Wei Deng Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20251113130519.2647081-1-wei.deng@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/monaco-evk.dts | 71 +++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index 539c9c80a808d..208b90613d7c8 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -225,6 +225,63 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; + + wcn6855-pmu { + compatible = "qcom,wcn6855-pmu"; + + vddio-supply = <&vreg_wcn_3p3>; + vddaon-supply = <&vreg_wcn_3p3>; + vddpmu-supply = <&vreg_wcn_3p3>; + vddpmumx-supply = <&vreg_wcn_3p3>; + vddpmucx-supply = <&vreg_wcn_3p3>; + vddrfa0p95-supply = <&vreg_wcn_3p3>; + vddrfa1p3-supply = <&vreg_wcn_3p3>; + vddrfa1p9-supply = <&vreg_wcn_3p3>; + vddpcielp3-supply = <&vreg_wcn_3p3>; + vddpcielp9-supply = <&vreg_wcn_3p3>; + + 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_1p8: ldo7 { + regulator-name = "vreg_pmu_rfa_1p8"; + }; + + vreg_pmu_pcie_0p9: ldo8 { + regulator-name = "vreg_pmu_pcie_0p9"; + }; + + vreg_pmu_pcie_1p8: ldo9 { + regulator-name = "vreg_pmu_pcie_1p8"; + }; + }; + }; }; &apps_rsc { @@ -921,6 +978,20 @@ remote-endpoint = <&m2_e_uart_ep>; }; }; + + bluetooth: bluetooth { + compatible = "qcom,wcn6855-bt"; + max-speed = <3200000>; + + 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_1p8>; + }; }; &uart6 { From d6d4873a3d0ae467ec4ec6d98c7949dc9ce9128d Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Sun, 9 Aug 2026 17:59:04 +0530 Subject: [PATCH 0812/1133] FROMLIST: arm64: dts: qcom: monaco: Enable CDSP cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP does not throttle its speed automatically when it reaches high temperatures in monaco. Set up CDSP cooling by throttling the cdsp, when it reaches 115°C. Add polling-delay-passive so the governor periodically evaluates the zone during passive cooling and steps up cooling levels when temperature stabilizes below the next trip. Link: https://lore.kernel.org/r/20260809-b4-qmi-tmd-v8-8-b15d47adc379@oss.qualcomm.com Reviewed-by: Daniel Lezcano Reviewed-by: Dmitry Baryshkov Signed-off-by: Gaurav Kohli --- arch/arm64/boot/dts/qcom/monaco.dtsi | 99 ++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 7b688b65016f4..0c1140283a4ba 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -21,6 +21,7 @@ #include #include #include +#include #include / { @@ -7762,6 +7763,8 @@ qcom,smem-states = <&smp2p_cdsp_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <3>; + status = "disabled"; glink-edge { @@ -8194,39 +8197,87 @@ }; nsp-0-0-0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens2 5>; trips { + nsp_0_0_0_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_0_alert0>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens2 6>; trips { + nsp_0_1_0_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_0_alert0>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens2 7>; trips { + nsp_0_2_0_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_0_alert0>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; ddrss-0-thermal { @@ -8314,39 +8365,87 @@ }; nsp-0-0-1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens3 5>; trips { + nsp_0_0_1_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_1_alert0>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens3 6>; trips { + nsp_0_1_1_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_1_alert0>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens3 7>; trips { + nsp_0_2_1_alert0: trip-point0 { + temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + nsp-critical { temperature = <125000>; hysteresis = <1000>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_1_alert0>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; ddrss-1-thermal { From e908f94eeabd1b97c67c78d893fccef454c7d867 Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Wed, 21 Jan 2026 11:37:55 +0530 Subject: [PATCH 0813/1133] WORKAROUND: arm64: dts: qcom: monaco-evk: Remove WCN6855 PMU node to bypass pwrseq flow There is a conflict between the current DTS configuration and the driver behavior for the WCN6855 Bluetooth path. With the PMU node in place, the driver takes the pwrseq code path unintentionally, which leads to Bluetooth failing to power up during an on -> off -> on transition. To unblock function, temporarily remove the WCN6855 PMU node so that the driver follows the non-pwrseq path and avoids the unexpected sequence. This is a TEMPORARY WORKAROUND. Once a proper M.2 binding/solution is upstreamed, will re-submit both DTS and driver changes aligned with the M.2 model. Signed-off-by: Wei Deng --- arch/arm64/boot/dts/qcom/monaco-evk.dts | 73 +++---------------------- 1 file changed, 8 insertions(+), 65 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index 208b90613d7c8..6c7012cb64058 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -225,63 +225,6 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; - - wcn6855-pmu { - compatible = "qcom,wcn6855-pmu"; - - vddio-supply = <&vreg_wcn_3p3>; - vddaon-supply = <&vreg_wcn_3p3>; - vddpmu-supply = <&vreg_wcn_3p3>; - vddpmumx-supply = <&vreg_wcn_3p3>; - vddpmucx-supply = <&vreg_wcn_3p3>; - vddrfa0p95-supply = <&vreg_wcn_3p3>; - vddrfa1p3-supply = <&vreg_wcn_3p3>; - vddrfa1p9-supply = <&vreg_wcn_3p3>; - vddpcielp3-supply = <&vreg_wcn_3p3>; - vddpcielp9-supply = <&vreg_wcn_3p3>; - - 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_1p8: ldo7 { - regulator-name = "vreg_pmu_rfa_1p8"; - }; - - vreg_pmu_pcie_0p9: ldo8 { - regulator-name = "vreg_pmu_pcie_0p9"; - }; - - vreg_pmu_pcie_1p8: ldo9 { - regulator-name = "vreg_pmu_pcie_1p8"; - }; - }; - }; }; &apps_rsc { @@ -983,14 +926,14 @@ compatible = "qcom,wcn6855-bt"; max-speed = <3200000>; - 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_1p8>; + vddrfacmn-supply = <&vreg_wcn_3p3>; + vddaon-supply = <&vreg_wcn_3p3>; + vddwlcx-supply = <&vreg_wcn_3p3>; + vddwlmx-supply = <&vreg_wcn_3p3>; + vddbtcmx-supply = <&vreg_wcn_3p3>; + vddrfa0p8-supply = <&vreg_wcn_3p3>; + vddrfa1p2-supply = <&vreg_wcn_3p3>; + vddrfa1p8-supply = <&vreg_wcn_3p3>; }; }; From 28c0d6a2c988bcdfdd6d84f14c0644b8a65fbb1b Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Thu, 5 Feb 2026 15:35:49 +0530 Subject: [PATCH 0814/1133] WORKAROUND: arm64: dts: qcom: monaco: Disable global IRQ for pcie1 Currently pcie1 global IRQ is blocking a CPU core, due to which ufs is getting blocked and failing. As workaround disable PCIe1 global IRQ for now. Signed-off-by: Krishna Chaitanya Chundru --- arch/arm64/boot/dts/qcom/monaco.dtsi | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 0c1140283a4ba..2de191b52abbd 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -2476,8 +2476,7 @@ , , , - , - ; + ; interrupt-names = "msi0", "msi1", "msi2", @@ -2485,8 +2484,7 @@ "msi4", "msi5", "msi6", - "msi7", - "global"; + "msi7"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; interrupt-map = <0 0 0 1 &intc GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, From 1cb0cfc2be0d7c47d11141f29da5458fe77f7ff9 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Tue, 27 Jan 2026 12:35:52 +0530 Subject: [PATCH 0815/1133] BACKPORT: arm64: dts: qcom: monaco-evk: Enable primary USB controller in host mode Enable primary USB controller in host mode on monaco EVK Platform. Primary USB controller is connected to a Genesys Logic USB HUB GL3590 having 4 ports. The ports of hub that are present on lemans EVK standalone board are used as follows:- 1) port-1 is connected to HD3SS3220 Type-C port controller. 2) port-4 is used for the M.2 E key on corekit. Standard core kit uses UART for Bluetooth. This port is to be used only if user optionally replaces the WiFi card with the NFA765 chip which uses USB for Bluetooth. Remaining 2 ports will become functional when the interface plus mezzanine board is stacked on top of corekit: 3) port-2 is connected to another hub which is present on the mezz through which 4 type-A ports are connected. 4) port-3 is used for the M.2 B key for a 5G card when the mezz is connected. Mark the second USB controller as host only capable and add the HD3SS3220 Type-C port controller along with Type-c connector for controlling vbus supply. In hardware, there are dip switches provided to operate between USB port 0 and port 1 for primary Type-C USB controller. By default, switches will be off operating at USB0 port. After bootup to HLOS, it will be operated in USB1 port. Added support in the software for both HS and SS switches as usb1-hs-high-gpio14 and usb1-ss-high-gpio5. Also, added bootup-high-gpio7 pin for USB1 hub reset to get detected after bootup. Link: https://lore.kernel.org/all/20260210152548.769951-1-loic.poulain@oss.qualcomm.com/ Signed-off-by: Loic Poulain Signed-off-by: Swati Agarwal --- arch/arm64/boot/dts/qcom/monaco-evk.dts | 201 +++++++++++++++++++++++- 1 file changed, 200 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index 6c7012cb64058..e46f955446afe 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -29,6 +29,45 @@ stdout-path = "serial0:115200n8"; }; + connector-1 { + compatible = "usb-c-connector"; + label = "USB1-Type-C"; + data-role = "host"; + power-role = "source"; + + vbus-supply = <&vbus_supply_regulator_1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + usb1_con_ss_ep: endpoint { + remote-endpoint = <&hd3ss3220_1_in_ep>; + }; + }; + + port@1 { + reg = <1>; + + usb1_hs_in: endpoint { + remote-endpoint = <&usb_hub_2_1>; + }; + + }; + + port@2 { + reg = <2>; + + usb1_ss_in: endpoint { + remote-endpoint = <&usb_hub_3_1>; + }; + }; + }; + }; + connector-2 { compatible = "gpio-usb-b-connector", "usb-b-connector"; label = "micro-USB"; @@ -115,6 +154,15 @@ }; }; + vbus_supply_regulator_1: regulator-vbus-supply-1 { + compatible = "regulator-fixed"; + regulator-name = "vbus_supply_1"; + gpio = <&expander1 3 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + }; + usb2_vbus: regulator-usb2-vbus { compatible = "regulator-fixed"; regulator-name = "usb2_vbus"; @@ -503,6 +551,38 @@ }; }; }; + + usb-typec@47 { + compatible = "ti,hd3ss3220"; + reg = <0x47>; + + interrupts = <45 IRQ_TYPE_EDGE_FALLING>; + + id-gpios = <&tlmm 13 GPIO_ACTIVE_HIGH>; + + pinctrl-0 = <&usb1_id>; + pinctrl-names = "default"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + hd3ss3220_1_in_ep: endpoint { + remote-endpoint = <&usb1_con_ss_ep>; + }; + }; + + port@1 { + reg = <1>; + + hd3ss3220_1_out_ep: endpoint { + }; + }; + }; + }; }; &i2c1 { @@ -614,6 +694,13 @@ interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; pinctrl-0 = <&expander5_int>; pinctrl-names = "default"; + + gpio5-hog { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "usb1-ss-high-gpio5"; + }; }; expander6: gpio@3e { @@ -626,6 +713,7 @@ interrupts-extended = <&tlmm 52 IRQ_TYPE_LEVEL_LOW>; pinctrl-0 = <&expander6_int>; pinctrl-names = "default"; + wakeup-source; }; }; @@ -773,6 +861,20 @@ }; &tlmm { + gpio7_hog: gpio7-hog { + gpio-hog; + gpios = <7 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "bootup-high-gpio7"; + }; + + gpio14_hog: gpio14-hog { + gpio-hog; + gpios = <14 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "usb1-hs-high-gpio14"; + }; + pcie0_default_state: pcie0-default-state { wake-pins { pins = "gpio0"; @@ -911,6 +1013,12 @@ function = "gpio"; bias-pull-up; }; + + usb1_id: usb1-id-state { + pins = "gpio13"; + function = "gpio"; + bias-pull-up; + }; }; &uart2 { @@ -963,9 +1071,100 @@ }; &usb_1 { - dr_mode = "peripheral"; + dr_mode = "host"; + + #address-cells = <1>; + #size-cells = <0>; status = "okay"; + + usb_hub_2_x: hub@1 { + compatible = "usb5e3,610"; + reg = <1>; + + peer-hub = <&usb_hub_3_x>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + usb_hub_2_1: endpoint { + remote-endpoint = <&usb1_hs_in>; + }; + }; + + /* + * Port-2 and port-3 are not connected to anything on corekit. + */ + port@2 { + reg = <2>; + + usb_hub_2_2: endpoint { + }; + }; + + port@3 { + reg = <3>; + + usb_hub_2_3: endpoint { + }; + }; + + /* + * Port-4 is connected to M.2 E key connector on corekit. + */ + port@4 { + reg = <4>; + + usb_hub_2_4: endpoint { + }; + }; + }; + }; + + usb_hub_3_x: hub@2 { + compatible = "usb5e3,625"; + reg = <2>; + + peer-hub = <&usb_hub_2_x>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + usb_hub_3_1: endpoint { + remote-endpoint = <&usb1_ss_in>; + }; + }; + + port@2 { + reg = <2>; + + usb_hub_3_2: endpoint { + }; + }; + + port@3 { + reg = <3>; + + usb_hub_3_3: endpoint { + }; + }; + + port@4 { + reg = <4>; + + usb_hub_3_4: endpoint { + }; + }; + }; + }; }; &usb_1_hsphy { From 43c24be4d71bfe629baa15e76877defe39bc55fd Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Mon, 30 Mar 2026 20:59:30 +0530 Subject: [PATCH 0816/1133] PENDING: arm64: dts: qcom: Add EL2 support for Iris for monaco Add support for IRIS on monaco when Linux host running at EL2. Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/monaco-el2.dtso | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-el2.dtso b/arch/arm64/boot/dts/qcom/monaco-el2.dtso index a7e3270f86090..7cae65ae499c3 100644 --- a/arch/arm64/boot/dts/qcom/monaco-el2.dtso +++ b/arch/arm64/boot/dts/qcom/monaco-el2.dtso @@ -13,7 +13,10 @@ }; &iris { - status = "disabled"; + status = "okay"; + video-firmware { + iommus = <&apps_smmu 0x0882 0x0400>; + }; }; &remoteproc_adsp { From 07de5c909e07ab5b7baca7b91904cd5a74a3f2a9 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Mon, 27 Apr 2026 22:35:05 +0530 Subject: [PATCH 0817/1133] FROMLIST: arm64: dts: qcom: monaco-ac-evk: Add IFP mezzanine monaco-ac-evk board supports monaco-evk-ifp-mezzanine attach. Add combined DTB for the same by merging monaco-ac-evk.dtb with monaco-evk-ifp-mezzanine overlay. Signed-off-by: Umang Chheda Link: https://lore.kernel.org/r/20260427170505.1494703-5-umang.chheda@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..0f955551828db 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -80,6 +80,9 @@ monaco-ac-evk-ifp-mezzanine-dtbs := monaco-ac-evk.dtb monaco-evk-ifp-mezzanine.d dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk-ifp-mezzanine.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-el2.dtb + +monaco-ac-evk-ifp-mezzanine-dtbs := monaco-ac-evk.dtb monaco-evk-ifp-mezzanine.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk-ifp-mezzanine.dtb monaco-evk-ifp-mezzanine-dtbs := monaco-evk.dtb monaco-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8216-samsung-fortuna3g.dtb From 61f5c86b9819094e447f065f09ecc57a487d2d63 Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Fri, 17 Apr 2026 13:30:04 +0530 Subject: [PATCH 0818/1133] WORKAROUND: arm64: dts: qcom: monaco-evk: Use refgen regulator for usb2 HS PHY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem Statement:- After the Introduction of commits (1 and 2) ADB goes offline a few seconds after USB enumeration on the micro‑USB (USB2) port. The failure is consistently observed shortly after enumeration, with the following log indicating regulator shutdown: [ 40.220063][ T49] refgen: disabling On RB4, ADB operates over the USB2 HSPHY, which requires three power rails: 0.8 V (vdda‑pll) 1.8 V (vdda18) 3.3 V (vdda33) Based on the current DTS configuration, the USB2 HS PHY regulators are as follows as per monaco power grid: vdda-pll-supply (0.8 V): l7a vdda18-supply (1.8 V): l7c vdda33-supply (3.3 V): l9a However, according to the Monaco power grid analysis, the regulators for the USB2 HS PHY should be: vdda-pll-supply (0.8 V): l4a vdda18-supply (1.8 V): s4a vdda33-supply (3.3 V): l8a This mismatch in regulator assignment results in unstable PHY power, causing ADB to drop offline shortly after USB enumeration. Workaround solution:- As an interim workaround, the refgen regulator is used for the 0.8 V (vdda‑pll) rail instead of l7a. This change restores stable USB2 HS PHY operation and prevents ADB from disconnecting. Presently this is taken as a workaround while we confirm the mismatch in the power grid understanding. 1) fc406be (add Display Serial Interface device nodes) 2) 2c9e4d7 (add refgen regulator) Signed-off-by: Swati Agarwal --- arch/arm64/boot/dts/qcom/monaco-evk.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index e46f955446afe..48efb95550466 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -1191,7 +1191,7 @@ }; &usb_2_hsphy { - vdda-pll-supply = <&vreg_l7a>; + vdda-pll-supply = <&refgen>; vdda18-supply = <&vreg_l7c>; vdda33-supply = <&vreg_l9a>; From e647b62e06e21f6020c582b9cd3708fcd87cdc4b Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Wed, 1 Jul 2026 13:47:13 +0530 Subject: [PATCH 0819/1133] FROMLIST: arm64: dts: qcom: monaco: Move eMMC CQE support from SoC to board DT The Monaco SoC SDHC controller supports both eMMC and SD cards. However, the 'supports-cqe' property (Command Queue Engine) is specific to eMMC and conflicts with SD card operation. Remove 'supports-cqe' from the SoC device tree to ensure compatibility with SD cards. Simultaneously, add the property explicitly to the qcs8300-ride and monaco-monza-som board device tree, as this board uses the controller in eMMC mode. This ensures the SoC definition remains generic while enabling features correctly at the board level. Signed-off-by: Monish Chunara Link: https://lore.kernel.org/r/20260701081715.2580329-2-monish.chunara@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi | 1 + arch/arm64/boot/dts/qcom/monaco.dtsi | 1 - arch/arm64/boot/dts/qcom/qcs8300-ride.dts | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi b/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi index 36af1ad2105d5..a489932c7b1df 100644 --- a/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi @@ -275,6 +275,7 @@ mmc-hs400-1_8v; mmc-hs400-enhanced-strobe; + supports-cqe; no-sd; no-sdio; non-removable; diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 2de191b52abbd..17b1940b9f7cc 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -4847,7 +4847,6 @@ qcom,dll-config = <0x000f64ee>; qcom,ddr-config = <0x80040868>; bus-width = <8>; - supports-cqe; dma-coherent; qcom,ice = <&sdhc_ice>; diff --git a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts index be850a23472fc..54770aa7376d9 100644 --- a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts @@ -721,6 +721,7 @@ vmmc-supply = <&vreg_l8a>; vqmmc-supply = <&vreg_s4a>; + supports-cqe; non-removable; no-sd; no-sdio; From 95606543079774ce0474e7c8ec0c91f697423b3d Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Wed, 1 Jul 2026 13:47:14 +0530 Subject: [PATCH 0820/1133] FROMLIST: arm64: dts: qcom: monaco-evk: Enable SDHCI for SD Card via overlay The monaco EVK board supports either eMMC or SD-card, but only one can be active at a time. Enable the SD Host Controller Interface (SDHCI) on the monaco EVK board to support SD Card for storage via a device tree overlay. This allows eMMC support to be enabled through a separate overlay when required. Signed-off-by: Monish Chunara Link: https://lore.kernel.org/r/20260701081715.2580329-3-monish.chunara@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/Makefile | 4 ++ .../boot/dts/qcom/monaco-evk-sd-card.dtso | 72 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-sd-card.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 0f955551828db..47e4446afbd4c 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -85,6 +85,10 @@ monaco-ac-evk-ifp-mezzanine-dtbs := monaco-ac-evk.dtb monaco-evk-ifp-mezzanine.d dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk-ifp-mezzanine.dtb monaco-evk-ifp-mezzanine-dtbs := monaco-evk.dtb monaco-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtb + +monaco-evk-sd-card-dtbs := monaco-evk.dtb monaco-evk-sd-card.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-sd-card.dtb + dtb-$(CONFIG_ARCH_QCOM) += msm8216-samsung-fortuna3g.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-acer-a1-724.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-alcatel-idol347.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-sd-card.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-sd-card.dtso new file mode 100644 index 0000000000000..bc4ea12587a2e --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-sd-card.dtso @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +/ { + vmmc_sdc: regulator-mmc-sdc { + compatible = "regulator-fixed"; + + regulator-name = "vmmc_sdc"; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + }; + + vreg_sdc: regulator-sdc { + compatible = "regulator-gpio"; + + regulator-name = "vreg_sdc"; + regulator-type = "voltage"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2950000>; + + gpios = <&expander1 7 GPIO_ACTIVE_HIGH>; + states = <1800000 1>, <2950000 0>; + + startup-delay-us = <100>; + }; +}; + +&sdhc_1 { + vmmc-supply = <&vmmc_sdc>; + vqmmc-supply = <&vreg_sdc>; + + pinctrl-0 = <&sdc1_state_on>, <&sd_cd>; + pinctrl-1 = <&sdc1_state_off>, <&sd_cd>; + pinctrl-names = "default", "sleep"; + + cap-sd-highspeed; + no-1-8-v; + + bus-width = <4>; + cd-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; + no-mmc; + no-sdio; + + status = "okay"; +}; + +&sdhc1_opp_table { + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-202000000 { + opp-hz = /bits/ 64 <202000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; +}; + +&tlmm { + sd_cd: sd-cd-state { + pins = "gpio11"; + function = "gpio"; + bias-pull-up; + }; +}; From 94d25fbd440cbf14870f173a2c1388725c9ed81f Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Wed, 1 Jul 2026 13:47:15 +0530 Subject: [PATCH 0821/1133] FROMLIST: arm64: dts: qcom: monaco-evk: Add SDHCI support for eMMC via overlay Enable the SDHCI controller for eMMC functionality on the Monaco EVK using a device tree overlay. Signed-off-by: Monish Chunara Link: https://lore.kernel.org/r/20260701081715.2580329-4-monish.chunara@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/Makefile | 3 ++ arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso | 37 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 47e4446afbd4c..ac6e49c66f680 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -89,6 +89,9 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtb monaco-evk-sd-card-dtbs := monaco-evk.dtb monaco-evk-sd-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-sd-card.dtb +monaco-evk-emmc-dtbs := monaco-evk.dtb monaco-evk-emmc.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-emmc.dtb + dtb-$(CONFIG_ARCH_QCOM) += msm8216-samsung-fortuna3g.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-acer-a1-724.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8916-alcatel-idol347.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso new file mode 100644 index 0000000000000..cb2566ac6923c --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-emmc.dtso @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/ { + vreg_s2s: regulator-vreg-s2s { + compatible = "regulator-fixed"; + regulator-name = "regulator-s2s"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; +}; + +&sdhc_1 { + vmmc-supply = <&vreg_l8a>; + vqmmc-supply = <&vreg_s2s>; + + supports-cqe; + + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + + pinctrl-names = "default", "sleep"; + + non-removable; + + bus-width = <8>; + no-sd; + no-sdio; + + status = "okay"; +}; From d44985dd6e48b34ffd5a3aa2953baf11574f6383 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Sun, 9 Aug 2026 17:59:02 +0530 Subject: [PATCH 0822/1133] FROMLIST: arm64: dts: qcom: lemans: Enable CDSP cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP does not throttle its speed automatically when it reaches high temperatures in lemans. Set up CDSP cooling for both instances by throttling the cdsp, when it reaches 105°C. Reviewed-by: Daniel Lezcano Reviewed-by: Dmitry Baryshkov Signed-off-by: Gaurav Kohli Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260809-b4-qmi-tmd-v8-6-b15d47adc379@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/lemans.dtsi | 125 ++++++++++++++++++++++++--- 1 file changed, 113 insertions(+), 12 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 5dafa124b1416..44445a83636a4 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -21,6 +21,7 @@ #include #include #include +#include #include / { @@ -7781,6 +7782,8 @@ qcom,smem-states = <&smp2p_cdsp0_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <3>; + status = "disabled"; glink-edge { @@ -7920,6 +7923,8 @@ qcom,smem-states = <&smp2p_cdsp1_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <3>; + status = "disabled"; glink-edge { @@ -8768,7 +8773,7 @@ thermal-sensors = <&tsens2 5>; trips { - trip-point0 { + nsp_0_0_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8780,6 +8785,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_0_alert0>; + cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-0-thermal { @@ -8788,7 +8801,7 @@ thermal-sensors = <&tsens2 6>; trips { - trip-point0 { + nsp_0_1_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8800,6 +8813,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_0_alert0>; + cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-0-thermal { @@ -8808,7 +8829,7 @@ thermal-sensors = <&tsens2 7>; trips { - trip-point0 { + nsp_0_2_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8820,6 +8841,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_0_alert0>; + cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-0-0-thermal { @@ -8828,7 +8857,7 @@ thermal-sensors = <&tsens2 8>; trips { - trip-point0 { + nsp_1_0_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8840,6 +8869,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_0_0_alert0>; + cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-1-0-thermal { @@ -8848,7 +8885,7 @@ thermal-sensors = <&tsens2 9>; trips { - trip-point0 { + nsp_1_1_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8860,6 +8897,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_1_0_alert0>; + cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-2-0-thermal { @@ -8868,7 +8913,7 @@ thermal-sensors = <&tsens2 10>; trips { - trip-point0 { + nsp_1_2_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -8880,6 +8925,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_2_0_alert0>; + cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; ddrss-0-thermal { @@ -9022,7 +9075,7 @@ thermal-sensors = <&tsens3 5>; trips { - trip-point0 { + nsp_0_0_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9034,6 +9087,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_0_1_alert0>; + cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-1-1-thermal { @@ -9042,7 +9103,7 @@ thermal-sensors = <&tsens3 6>; trips { - trip-point0 { + nsp_0_1_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9054,6 +9115,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_1_1_alert0>; + cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-0-2-1-thermal { @@ -9062,7 +9131,7 @@ thermal-sensors = <&tsens3 7>; trips { - trip-point0 { + nsp_0_2_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9074,6 +9143,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_0_2_1_alert0>; + cooling-device = <&remoteproc_cdsp0 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-0-1-thermal { @@ -9082,7 +9159,7 @@ thermal-sensors = <&tsens3 8>; trips { - trip-point0 { + nsp_1_0_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9094,6 +9171,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_0_1_alert0>; + cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-1-1-thermal { @@ -9102,7 +9187,7 @@ thermal-sensors = <&tsens3 9>; trips { - trip-point0 { + nsp_1_1_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9114,6 +9199,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_1_1_alert0>; + cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; nsp-1-2-1-thermal { @@ -9122,7 +9215,7 @@ thermal-sensors = <&tsens3 10>; trips { - trip-point0 { + nsp_1_2_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <5000>; type = "passive"; @@ -9134,6 +9227,14 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_1_2_1_alert0>; + cooling-device = <&remoteproc_cdsp1 QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; ddrss-1-thermal { From 65b64a4be84f1c64ac2905500123e270f57c3089 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Wed, 11 Feb 2026 13:49:19 +0530 Subject: [PATCH 0823/1133] PENDING: arm64: dts: qcom: Add EL2 support for Iris for lemans Add support for IRIS on lemans when Linux host running at EL2. Signed-off-by: Vikash Garodia --- arch/arm64/boot/dts/qcom/lemans-el2.dtso | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-el2.dtso b/arch/arm64/boot/dts/qcom/lemans-el2.dtso index ceaab5f55fa2a..e17917e26eee7 100644 --- a/arch/arm64/boot/dts/qcom/lemans-el2.dtso +++ b/arch/arm64/boot/dts/qcom/lemans-el2.dtso @@ -15,7 +15,9 @@ }; &iris { - status = "disabled"; + video-firmware { + iommus = <&apps_smmu 0x0882 0x0400>; + }; }; &remoteproc_adsp { From b81d750034131c4196bce9968c394512c5425ac8 Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Mon, 16 Feb 2026 00:03:25 +0530 Subject: [PATCH 0824/1133] FROMLIST: arm64: dts: qcom: lemans-evk: Enable wakeup for primary USB controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the "wakeup-source" property to the primary port controller node so its interrupt can wake the system from low‑power states on lemans EVK platform. Signed-off-by: Swati Agarwal Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260215183325.3836178-3-swati.agarwal@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/lemans-evk.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index 23cf20f9a1783..bfdebd2cdd4bc 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -641,6 +641,8 @@ pinctrl-0 = <&usb_id>, <&usb0_intr_state>; pinctrl-names = "default"; + wakeup-source; + ports { #address-cells = <1>; #size-cells = <0>; From b93ed62596e4f702f0bce280c29af97bd2c31987 Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Fri, 10 Apr 2026 22:37:06 +0530 Subject: [PATCH 0825/1133] PENDING: arm64: dts: qcom: lemans-ride: Drop video firmware from common As per memory map, video firmware memory region is 7MB for sa8775* variants while it is 16MB for qcs9100* variants. Keeping the 7MB variant of video firmware in ride common DTS does not allow qcs9100* to pick the 16MB variant. Drop it from common and define in respective variant DTS. Signed-off-by: Gourav Kumar Signed-off-by: Vikash Garodia Signed-off-by: Venkata Siva Pavan KumarVenkatapatigari --- arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi | 2 -- arch/arm64/boot/dts/qcom/lemans.dtsi | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi b/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi index 22f764b8d721d..cd052af9c396b 100644 --- a/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi @@ -582,8 +582,6 @@ }; &iris { - firmware-name = "qcom/vpu/vpu30_p4_s6.mbn"; - status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 44445a83636a4..f2c27a12e4913 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -4963,6 +4963,8 @@ memory-region = <&pil_video_mem>; + firmware-name = "qcom/vpu/vpu30_p4_s6_16mb.mbn"; + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; From 1ece77cd48246b9d5ff955fa0075da2b44ec9fda Mon Sep 17 00:00:00 2001 From: Kumar Anurag Date: Sun, 12 Apr 2026 21:37:13 -0700 Subject: [PATCH 0826/1133] FROMLIST: arm64: dts: qcom: lemans: Enable DISPLAY-PORT Add dailinks for DISPLAY-PORT to enable audio functionality on edp0. Signed-off-by: Kumar Anurag Link: https://lore.kernel.org/r/20260413043713.1659-1-kumar.singh@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/lemans-evk.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index bfdebd2cdd4bc..49fa01f8d9d78 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -214,6 +214,22 @@ sound-dai = <&q6apm>; }; }; + + dp0-dai-link { + link-name = "DisplayPort0 Playback"; + + cpu { + sound-dai = <&q6apmbedai DISPLAY_PORT_RX_0>; + }; + + codec { + sound-dai = <&mdss0_dp0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; }; usb0_vbus: regulator-usb0-vbus { From 59a19f78542c84c5b796957bd3e29dcfab977e0b Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Fri, 27 Feb 2026 15:54:04 +0530 Subject: [PATCH 0827/1133] FROMLIST: arm64: dts: qcom: lemans-evk: Move SD card support to overlay The lemans EVK board supports either eMMC or SD-card, but only one can be active at a time. Move the SDHC node for SD card into a dedicated device tree overlay. This decoupling allows the storage medium to be selected dynamically by applying the appropriate overlay for either SD card or eMMC support. Signed-off-by: Monish Chunara Link: https://lore.kernel.org/r/20260227102405.2339544-2-monish.chunara@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/Makefile | 3 +++ .../boot/dts/qcom/lemans-evk-sd-card.dtso | 25 +++++++++++++++++++ arch/arm64/boot/dts/qcom/lemans-evk.dts | 16 ------------ 3 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-sd-card.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..1c5e933606984 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -52,6 +52,9 @@ dtb-$(CONFIG_ARCH_QCOM) += kaanapali-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += kaanapali-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += lemans-evk.dtb +lemans-evk-sd-card-dtbs := lemans-evk.dtb lemans-evk-sd-card.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-sd-card.dtb + lemans-evk-camera-csi1-imx577-dtbs := lemans-evk.dtb lemans-evk-camera-csi1-imx577.dtbo lemans-evk-camera-dtbs := lemans-evk.dtb lemans-evk-camera.dtbo diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-sd-card.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-sd-card.dtso new file mode 100644 index 0000000000000..007ab63473495 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-sd-card.dtso @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&sdhc { + vmmc-supply = <&vmmc_sdc>; + vqmmc-supply = <&vreg_sdc>; + + pinctrl-0 = <&sdc_default>, <&sd_cd>; + pinctrl-1 = <&sdc_sleep>, <&sd_cd>; + pinctrl-names = "default", "sleep"; + + bus-width = <4>; + cd-gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; + no-mmc; + no-sdio; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-evk.dts b/arch/arm64/boot/dts/qcom/lemans-evk.dts index 49fa01f8d9d78..2d8bce4165878 100644 --- a/arch/arm64/boot/dts/qcom/lemans-evk.dts +++ b/arch/arm64/boot/dts/qcom/lemans-evk.dts @@ -980,22 +980,6 @@ status = "okay"; }; -&sdhc { - vmmc-supply = <&vmmc_sdc>; - vqmmc-supply = <&vreg_sdc>; - - pinctrl-0 = <&sdc_default>, <&sd_cd>; - pinctrl-1 = <&sdc_sleep>, <&sd_cd>; - pinctrl-names = "default", "sleep"; - - bus-width = <4>; - cd-gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; - no-mmc; - no-sdio; - - status = "okay"; -}; - &serdes0 { vdda-0p9-supply = <&vreg_l4a>; vdda-1p2-supply = <&vreg_l1c>; From 38a7b411c55ed773b7e1bd184505d0a7a7654e7e Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Fri, 27 Feb 2026 15:54:05 +0530 Subject: [PATCH 0828/1133] FROMLIST: arm64: dts: qcom: lemans-evk: Add SDHCI support for eMMC via overlay Enable the SDHCI controller for eMMC functionality on the lemans EVK using a device tree overlay. Configure the corresponding addresse space and resources for eMMC. Signed-off-by: Monish Chunara Link: https://lore.kernel.org/r/20260227102405.2339544-3-monish.chunara@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/Makefile | 3 + arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso | 64 +++++++++++++++++++ arch/arm64/boot/dts/qcom/lemans.dtsi | 10 ++- 3 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 1c5e933606984..60b76ad17e4af 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -52,6 +52,9 @@ dtb-$(CONFIG_ARCH_QCOM) += kaanapali-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += kaanapali-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += lemans-evk.dtb +lemans-evk-emmc-dtbs := lemans-evk.dtb lemans-evk-emmc.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-emmc.dtb + lemans-evk-sd-card-dtbs := lemans-evk.dtb lemans-evk-sd-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-sd-card.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso new file mode 100644 index 0000000000000..52739d39a1ff8 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-emmc.dtso @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include + +/ { + vmmc_sdc1: regulator-l8c { + compatible = "regulator-fixed"; + regulator-name = "vreg-sdc1"; + + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + }; + + vqmmc_sdc1: regulator-s4a { + compatible = "regulator-fixed"; + regulator-name = "vqmmc-sdc1"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; +}; + +&sdhc { + vmmc-supply = <&vmmc_sdc1>; + vqmmc-supply = <&vqmmc_sdc1>; + + pinctrl-0 = <&sdc_default>, <&sdc_rclk>; + pinctrl-1 = <&sdc_sleep>, <&sdc_rclk_sleep>; + + pinctrl-names = "default", "sleep"; + + supports-cqe; + non-removable; + + qcom,dll-config = <0x000F64EC>; + max-frequency = <50000000>; + + bus-width = <8>; + no-sd; + no-sdio; + + status = "okay"; +}; + +&tlmm { + sdc_rclk: sdc1-rclk-state { + pins = "sdc1_rclk"; + bias-pull-down; + }; + + sdc_rclk_sleep: sdc1-rclk-sleep-state { + pins = "sdc1_rclk"; + drive-strength = <2>; + bias-bus-hold; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index f2c27a12e4913..b4fca3ac772fe 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -4304,7 +4304,9 @@ sdhc: mmc@87c4000 { compatible = "qcom,sa8775p-sdhci", "qcom,sdhci-msm-v5"; - reg = <0x0 0x087c4000 0x0 0x1000>; + reg = <0x0 0x87C4000 0x0 0x1000>, + <0x0 0x87C5000 0x0 0x1000>; + reg-names = "hc", "cqhci"; interrupts = , ; @@ -4312,9 +4314,11 @@ "pwr_irq"; clocks = <&gcc GCC_SDCC1_AHB_CLK>, - <&gcc GCC_SDCC1_APPS_CLK>; + <&gcc GCC_SDCC1_APPS_CLK>, + <&rpmhcc RPMH_CXO_CLK>; clock-names = "iface", - "core"; + "core", + "xo"; interconnects = <&aggre1_noc MASTER_SDC QCOM_ICC_TAG_ALWAYS &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, From 218613ed3391e8bbf70ff2cdfba8c9d39118975c Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Mon, 6 Jul 2026 22:26:37 +0530 Subject: [PATCH 0829/1133] FROMLIST: arm64: dts: qcom: lemans: Add GEM_NOC interconnect for adreno SMMU On Lemans platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Signed-off-by: Bibek Kumar Patro Link: https://lore.kernel.org/r/20260706-smmu_interconnect_addition-v3-4-afdca0125a65@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/lemans.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index b4fca3ac772fe..de9bdd63b9d1a 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -4801,6 +4801,8 @@ , , ; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; serdes0: phy@8901000 { From 7cb842fd7bbcb4d5ae25c71e33d9f20c7d101589 Mon Sep 17 00:00:00 2001 From: Abhinaba Rakshit Date: Mon, 24 Aug 2026 01:17:43 +0530 Subject: [PATCH 0830/1133] FROMLIST: arm64: dts: qcom: lemans: Add OPP-table for ICE UFS device node Qualcomm Inline Crypto Engine (ICE) platform driver now supports an optional OPP-table. Add OPP-table for ICE UFS device nodes for LeMans platform. Reviewed-by: Kuldeep Singh Signed-off-by: Abhinaba Rakshit Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20260824-enable-ice-clock-scaling-v12-6-09271f583dc6@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/lemans.dtsi | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index de9bdd63b9d1a..258b03ee3028d 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -3097,6 +3097,32 @@ clock-names = "core", "iface"; power-domains = <&gcc UFS_PHY_GDSC>; + + operating-points-v2 = <&ice_opp_table>; + + ice_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-75000000 { + opp-hz = /bits/ 64 <75000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; }; cryptobam: dma-controller@1dc4000 { From b7dcbc2ebd4c3ba7ca200f1ffaeb1d71458ac437 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Fri, 31 Jul 2026 23:52:25 +0530 Subject: [PATCH 0831/1133] FROMLIST: arm64: dts: qcom: lemans: Add Iris context bank subnodes The VPU issues DMA through several SMMU streams, and the hardware does not give every stream the same addressable range. The non-pixel stream is restricted to use 0-600MB of IOVA space, while the pixel stream can address the full range: +-----------------------------------------------------------+ | non-pixel stream addressable range (600 MB - 3.5 GB) | | 0x25800000 - 0xe0000000 | +-----------------------------------------------------------+ | pixel stream addressable range (0 - 3.5 GB) | | 0x00000000 - 0xe0000000 | +-----------------------------------------------------------+ A single "iommus" property on the video-codec node puts every stream in one IOMMU domain sharing one IOVA allocator, so nothing keeps a non-pixel buffer above 600 MB. Once an allocation lands below that boundary the hardware faults, which shows up as unhandled SMMU page faults and spontaneous reboots: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Describe the two streams as "non-pixel" and "pixel" subnodes so each gets its own IOMMU domain, with stream 0x0880 becoming non-pixel and 0x0887 becoming pixel. Point the non-pixel subnode at a reserved-memory node whose "iommu-addresses" covers [0, 0x25800000), which excludes the low 600 MB from that domain's IOVA allocator and keeps its allocations above the boundary the stream can address. The reservation node carries no "reg", so it is a pure IOVA carve-out rather than a memory mapping. The pixel stream is left free to use the whole range. The video-codec node also gains '#address-cells' and '#size-cells' of 2, which set the cell widths used to parse the "iommu-addresses" entry that refers to the non-pixel subnode, and an empty "dma-ranges" declaring the 1:1 DMA translation into the parent. Both are described in the common schema change. Fixes: 7bc95052c64f ("arm64: dts: qcom: sa8775p: add support for video node") Cc: stable@vger.kernel.org Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Tested-by: Daniel J Blueman Signed-off-by: Vikash Garodia Link: https://lore.kernel.org/r/20260731-vpu_iommu_iova_handling-v2-10-da52b5228dbd@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/lemans.dtsi | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 258b03ee3028d..f4425261c3af9 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -868,6 +868,10 @@ reg = <0x0 0xdb200000 0x0 0x100000>; no-map; }; + + iris_resv: reservation-iris { + iommu-addresses = <&iris_non_pixel 0x0 0x0 0x0 0x25800000>; + }; }; smp2p-adsp { @@ -5000,12 +5004,23 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x0880 0x0400>, - <&apps_smmu 0x0887 0x0400>; dma-coherent; + #address-cells = <2>; + #size-cells = <2>; + dma-ranges; + status = "disabled"; + iris_non_pixel: non-pixel { + iommus = <&apps_smmu 0x0880 0x0400>; + memory-region = <&iris_resv>; + }; + + iris_pixel: pixel { + iommus = <&apps_smmu 0x0887 0x0400>; + }; + iris_opp_table: opp-table { compatible = "operating-points-v2"; From faf4f3a003247e60db307186ae1310c5905de03f Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Mon, 7 Sep 2026 12:01:12 +0530 Subject: [PATCH 0832/1133] FROMLIST: arm64: dts: qcom: lemans-evk: Add LVDS display overlay The Lemans EVK IFP mezzanine supports LVDS display output using the Lontium LT9211C DSI-to-LVDS bridge. The bridge is connected to the DSI0 output and drives a dual-channel 1920x1080 LVDS panel in VESA-24 mapping. Add a DTBO overlay, lemans-evk-lvds-boe,dv215fhm-r01.dtso, that wires up the LT9211C bridge on I2C1 (address 0x2d) with reset on GPIO37, a panel-lvds node for the boe,dv215fhm-r01 panel (matched against the panel-simple-lvds-dual-ports binding, which supplies the panel's size and timing internally), and an LCD display bias regulator supplied through the GPIO expander. DSI power is provided by vreg_s4a. The overlay is built as a composite DTB combining the base lemans-evk.dtb, the IFP mezzanine overlay, and this LVDS overlay. Link: https://lore.kernel.org/all/20260905-lvds-support-v3-1-b40a1b03f63c@oss.qualcomm.com/ Signed-off-by: Vishnu Saini --- arch/arm64/boot/dts/qcom/Makefile | 4 + .../lemans-evk-lvds-boe,dv215fhm-r01.dtso | 113 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-lvds-boe,dv215fhm-r01.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 60b76ad17e4af..1c0bd49be8aee 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -69,6 +69,10 @@ lemans-evk-el2-dtbs := lemans-evk.dtb lemans-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-el2.dtb lemans-evk-ifp-mezzanine-dtbs := lemans-evk.dtb lemans-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-ifp-mezzanine.dtb + +lemans-evk-lvds-boe,dv215fhm-r01-dtbs := lemans-evk.dtb lemans-evk-ifp-mezzanine.dtbo lemans-evk-lvds-boe,dv215fhm-r01.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-lvds-boe,dv215fhm-r01.dtb + dtb-$(CONFIG_ARCH_QCOM) += mahua-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += mahua-lenovo-thinkpad-t14s-gen7-lcd.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-fairphone-fp6.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-lvds-boe,dv215fhm-r01.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-lvds-boe,dv215fhm-r01.dtso new file mode 100644 index 0000000000000..bd3e13c46a1e7 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-lvds-boe,dv215fhm-r01.dtso @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&{/} { + model = "Qualcomm Technologies, Inc. Lemans EVK LVDS"; + + panel_lvds: panel-lvds { + compatible = "boe,dv215fhm-r01"; + power-supply = <&lcd_disp_bias>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dual-lvds-odd-pixels; + + panel_in_lvds_odd: endpoint { + remote-endpoint = <<9211c_out_odd>; + }; + }; + + port@1 { + reg = <1>; + dual-lvds-even-pixels; + + panel_in_lvds_even: endpoint { + remote-endpoint = <<9211c_out_even>; + }; + }; + }; + }; + + lcd_disp_bias: regulator-lcd-disp-bias { + compatible = "regulator-fixed"; + regulator-name = "lcd_disp_bias"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + gpio = <&expander3 1 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&i2c1 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&qup_i2c1_default>; + + status = "okay"; + + lt9211c_codec: lvds-bridge@2d { + compatible = "lontium,lt9211c"; + reg = <0x2d>; + reset-gpios = <&tlmm 37 GPIO_ACTIVE_HIGH>; + vccio-supply = <&vreg_s4a>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9211c_in: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&mdss0_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9211c_out_odd: endpoint { + remote-endpoint = <&panel_in_lvds_odd>; + }; + }; + + port@3 { + reg = <3>; + + lt9211c_out_even: endpoint { + remote-endpoint = <&panel_in_lvds_even>; + }; + }; + }; + }; +}; + +&mdss0_dsi0 { + vdda-supply = <&vreg_l1c>; + + status = "okay"; +}; + +&mdss0_dsi0_out { + data-lanes = <0 1 2 3>; + remote-endpoint = <<9211c_in>; +}; + +&mdss0_dsi0_phy { + vdds-supply = <&vreg_l4a>; + + status = "okay"; +}; From c801fa818c618ffc24fc4dd99d22868365966d29 Mon Sep 17 00:00:00 2001 From: Shashank Maurya Date: Tue, 8 Sep 2026 11:18:41 +0530 Subject: [PATCH 0833/1133] FROMLIST: arm64: dts: qcom: lemans-evk: Add DSI display overlay Add a DT overlay for the Raspberry Pi 7" DSI touchscreen panel on Lemans EVK, using mdss0_dsi0 with 2 data lanes and the panel MCU on I2C1. Link: https://lore.kernel.org/all/20260907-rpi_dts_overlay-v2-2-a4989322ce00@oss.qualcomm.com/ Signed-off-by: Shashank Maurya --- arch/arm64/boot/dts/qcom/Makefile | 3 + .../lemans-evk-raspberrypi-dsi-7inch.dtso | 83 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-evk-raspberrypi-dsi-7inch.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 1c0bd49be8aee..f3df31d725ef0 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -73,6 +73,9 @@ dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-ifp-mezzanine.dtb lemans-evk-lvds-boe,dv215fhm-r01-dtbs := lemans-evk.dtb lemans-evk-ifp-mezzanine.dtbo lemans-evk-lvds-boe,dv215fhm-r01.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-lvds-boe,dv215fhm-r01.dtb +lemans-evk-raspberrypi-dsi-7inch-dtbs := lemans-evk.dtb lemans-evk-raspberrypi-dsi-7inch.dtbo +dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-raspberrypi-dsi-7inch.dtb + dtb-$(CONFIG_ARCH_QCOM) += mahua-crd.dtb dtb-$(CONFIG_ARCH_QCOM) += mahua-lenovo-thinkpad-t14s-gen7-lcd.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-fairphone-fp6.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-evk-raspberrypi-dsi-7inch.dtso b/arch/arm64/boot/dts/qcom/lemans-evk-raspberrypi-dsi-7inch.dtso new file mode 100644 index 0000000000000..14743b3c38637 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-evk-raspberrypi-dsi-7inch.dtso @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +/dts-v1/; +/plugin/; + +#include + +&{/} { + display_bl: backlight { + compatible = "pwm-backlight"; + power-supply = <®_dsi_touch>; + pwms = <®_backlight 0 255 0>; + }; + + reg_dsi_touch: regulator-touch { + compatible = "regulator-fixed"; + regulator-name = "rpi-dsi-touch"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&expander3 1 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + regulator-always-on; + }; +}; + +&i2c1 { + qcom,load-firmware; + qcom,xfer-mode = <1>; + + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + reg_backlight: reg_backlight@45 { + compatible = "raspberrypi,touchscreen-panel-regulator-v2"; + reg = <0x45>; + + vcc-supply = <®_dsi_touch>; + gpio-controller; + #gpio-cells = <2>; + #pwm-cells = <3>; + }; +}; + +&mdss0_dsi0 { + vdda-supply = <&vreg_l1c>; + + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "raspberrypi,dsi-7inch"; + reg = <0>; + + reset-gpios = <®_backlight 0 GPIO_ACTIVE_LOW>; + power-supply = <®_dsi_touch>; + iovcc-supply = <®_dsi_touch>; + backlight = <&display_bl>; + + port { + panel0_in: endpoint { + remote-endpoint = <&mdss0_dsi0_out>; + }; + }; + }; +}; + +&mdss0_dsi0_out { + remote-endpoint = <&panel0_in>; + data-lanes = <0 1>; +}; + +&mdss0_dsi0_phy { + vdds-supply = <&vreg_l4a>; + + status = "okay"; +}; From f16796c8ff5e175bce361aa95ed846664dacc8fb Mon Sep 17 00:00:00 2001 From: Faruque Ansari Date: Mon, 14 Sep 2026 10:08:47 +0530 Subject: [PATCH 0834/1133] FROMLIST: arm64: dts: qcom: lemans: Add PSCRR NVMEM recorder node The PSCRR NVMEM recorder needs a persistent storage cell to save the power state change reason before shutdown or reset. Without a described NVMEM cell, the recorder has no platform storage where it can preserve that reason for the next boot. Add a pscrr-nvmem layout under the PMIC SDAM and describe a one-byte cell at offset 0x49. The recorder uses the lower six bits of this cell to persist the power state change reason across resets. Link: https://lore.kernel.org/r/20260914-pscrr-provider-v3-3-c45cb16542e8@oss.qualcomm.com Signed-off-by: Faruque Ansari --- arch/arm64/boot/dts/qcom/lemans-pmics.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi b/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi index 4c853053be858..371ba8fd7bde4 100644 --- a/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-pmics.dtsi @@ -238,6 +238,17 @@ reg = <0x48 0x1>; bits = <1 7>; }; + + nvmem-layout { + compatible = "pscrr-nvmem"; + #address-cells = <1>; + #size-cells = <1>; + + reboot_reason_persist: reboot-reason-persist@49 { + reg = <0x49 0x1>; + bits = <0 6>; + }; + }; }; }; From 618eddaeb87af3dd71f734631ec42d409f2c9a75 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Fri, 18 Sep 2026 15:27:45 +0530 Subject: [PATCH 0835/1133] FROMLIST: arm64: dts: qcom: lemans: add RAS error source nodes ARM Reliability, Availability and Serviceability (RAS) enables processor components(for eg cache, tlb etc) to record and signal hardware faults through architected error records and fault handling interrupts. This allows software to detect, report and, where possible, recover from hardware errors. The Lemans CPU subsystem implements RAS error records for the L1/L2 cache hierarchy and the shared L3 caches. Describe these error sources in Device Tree so that the ARM RAS framework can discover them and handle cache-related error reports. Link: https://lore.kernel.org/all/20260918095746.3347893-5-umang.chheda@oss.qualcomm.com/ Co-developed-by: Faruque Ansari Signed-off-by: Umang Chheda Signed-off-by: Faruque Ansari --- arch/arm64/boot/dts/qcom/lemans.dtsi | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index f4425261c3af9..939ef6552af79 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -525,6 +525,36 @@ qcom,bcm-voters = <&apps_bcm_voter>; }; + l2-cache-error { + compatible = "arm,ras-processor"; + arm,num-records = <1>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x1>; + arm,cache-ref = <&l2_0>; + interrupts = ; + interrupt-names = "fhi"; + }; + + l3-cluster0-error { + compatible = "arm,ras-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x2>; + arm,status-reporting = /bits/ 64 <0x2>; + arm,cache-ref = <&l3_0>; + interrupts = ; + interrupt-names = "fhi"; + }; + + l3-cluster1-error { + compatible = "arm,ras-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x2>; + arm,status-reporting = /bits/ 64 <0x2>; + arm,cache-ref = <&l3_1>; + interrupts = ; + interrupt-names = "fhi"; + }; + mc_virt: interconnect-mc-virt { compatible = "qcom,sa8775p-mc-virt"; #interconnect-cells = <2>; From bb49c365a975f3c9b74e5eaac0b8faceb6ea3c92 Mon Sep 17 00:00:00 2001 From: Gopikishan Thawre Date: Fri, 23 Oct 2026 12:01:31 +0530 Subject: [PATCH 0836/1133] FROMLIST: dt-bindings: arm: qcom: Add LeMans Draco EVK board Add the qcom,lemans-draco-evk compatible string for the LeMans Draco EVK board, which pairs the LeMans Draco EVK SoM with a common carrier board. Link: https://lore.kernel.org/all/20261019-lemans-draco-final-changes-bringup-v1-1-dcabe94f1074@oss.qualcomm.com/ Signed-off-by: Gopikishan Thawre --- Documentation/devicetree/bindings/arm/qcom.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index 121ca557ce1ef..18e2b2d48e3d8 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -505,6 +505,7 @@ properties: - items: - enum: - qcom,lemans-evk + - qcom,lemans-draco-evk - qcom,qcs9100-ride - qcom,qcs9100-ride-r3 - const: qcom,qcs9100 From 4530e56ec16786bca86503769a7aa85c5cad0c70 Mon Sep 17 00:00:00 2001 From: Gopikishan Thawre Date: Fri, 23 Oct 2026 12:01:32 +0530 Subject: [PATCH 0837/1133] FROMLIST: arm64: dts: qcom: lemans: Add LeMans Draco EVK SoM platform Introduce the device tree for the SA8775P/QCS9100-based LeMans Draco EVK SoM. The LeMans Draco SoM is a compact compute module integrating the SA8775P SoC, three PMM8654AU PMICs, and essential connectivity, designed to mount on carrier boards. The initial SoM device tree includes basic support for: - RPMH regulators for three PMM8654AU PMICs - QUP firmware paths (qupv3_id_0/1/2) - Remoteproc instances (ADSP, CDSP0/1, GPDSP0/1) with firmware paths - Debug UART (uart10) and board clocks - UFS storage - USB 0, USB 1 (host mode) and USB 2 with HSPHY and QMP PHY supplies - GPU (Adreno 663) with ZAP shader firmware - Video processing unit (iris) Co-developed-by: Kishor Buchi Signed-off-by: Kishor Buchi Link: https://lore.kernel.org/all/20261019-lemans-draco-final-changes-bringup-v1-2-dcabe94f1074@oss.qualcomm.com/ Signed-off-by: Gopikishan Thawre --- .../boot/dts/qcom/lemans-draco-evk-som.dtsi | 401 ++++++++++++++++++ 1 file changed, 401 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-draco-evk-som.dtsi diff --git a/arch/arm64/boot/dts/qcom/lemans-draco-evk-som.dtsi b/arch/arm64/boot/dts/qcom/lemans-draco-evk-som.dtsi new file mode 100644 index 0000000000000..6b7971bcdc934 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-draco-evk-som.dtsi @@ -0,0 +1,401 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include "lemans.dtsi" +#include "lemans-pmics.dtsi" + +/ { + 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 = ; + }; + }; +}; + +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/sa8775p/a663_zap.mbn"; +}; + +&iris { + firmware-name = "qcom/vpu/vpu30_p4_s6_16mb.mbn"; + + status = "okay"; +}; + +&pmm8654au_0_pon_resin { + linux,code = ; + + status = "okay"; +}; + +&qupv3_id_0 { + firmware-name = "qcom/sa8775p/qupv3fw.elf"; + + status = "okay"; +}; + +&qupv3_id_1 { + firmware-name = "qcom/sa8775p/qupv3fw.elf"; + + status = "okay"; +}; + +&qupv3_id_2 { + firmware-name = "qcom/sa8775p/qupv3fw.elf"; + + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/sa8775p/adsp.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp0 { + firmware-name = "qcom/sa8775p/cdsp0.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp1 { + firmware-name = "qcom/sa8775p/cdsp1.mbn"; + + status = "okay"; +}; + +&remoteproc_gpdsp0 { + firmware-name = "qcom/sa8775p/gpdsp0.mbn"; + + status = "okay"; +}; + +&remoteproc_gpdsp1 { + firmware-name = "qcom/sa8775p/gpdsp1.mbn"; + + 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"; +}; + +&usb_0 { + status = "okay"; +}; + +&usb_0_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l6c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + +&usb_0_qmpphy { + vdda-phy-supply = <&vreg_l1c>; + vdda-pll-supply = <&vreg_l7a>; + + status = "okay"; +}; + +&usb_1 { + dr_mode = "host"; + + status = "okay"; +}; + +&usb_1_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l6c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + +&usb_1_qmpphy { + vdda-phy-supply = <&vreg_l1c>; + vdda-pll-supply = <&vreg_l7a>; + + status = "okay"; +}; + +&usb_2 { + status = "okay"; +}; + +&usb_2_hsphy { + vdda-pll-supply = <&vreg_l7a>; + vdda18-supply = <&vreg_l6c>; + vdda33-supply = <&vreg_l9a>; + + status = "okay"; +}; + +&xo_board_clk { + clock-frequency = <38400000>; +}; From 5ebb680b34e8bbe2aa9b69c982244834b077df79 Mon Sep 17 00:00:00 2001 From: Gopikishan Thawre Date: Fri, 23 Oct 2026 12:01:33 +0530 Subject: [PATCH 0838/1133] FROMLIST: arm64: dts: qcom: lemans: Add LeMans Draco EVK board Add the device tree for the LeMans Draco EVK platform which combines the LeMans Draco EVK SoM and Draco carrier board. This device tree adds board-specific peripheral configuration on top of the SoM, including: - I2C GPIO expanders (TCA6416/PCA9534) on i2c2 and i2c18 - EEPROM with MAC address nvmem layout on i2c18 - Native DisplayPort output (DP0-DP3) - Dual Ethernet (ethernet0/ethernet1) with HSGMII PHY over SerDes - ST33HTPM TPM over SPI16 - AMC6821 fan controller on i2c4 Co-developed-by: Vishnu Saini Signed-off-by: Vishnu Saini Co-developed-by: Khalid Faisal Ansari Signed-off-by: Khalid Faisal Ansari Co-developed-by: Ajinkya Inchure Signed-off-by: Ajinkya Inchure Co-developed-by: Anuj Tripathi Signed-off-by: Anuj Tripathi Link: https://lore.kernel.org/all/20261019-lemans-draco-final-changes-bringup-v1-3-dcabe94f1074@oss.qualcomm.com/ Signed-off-by: Gopikishan Thawre --- arch/arm64/boot/dts/qcom/Makefile | 5 + arch/arm64/boot/dts/qcom/lemans-draco-evk.dts | 543 ++++++++++++++++++ 2 files changed, 548 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/lemans-draco-evk.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index f3df31d725ef0..ffe3f67ee97b3 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -51,6 +51,11 @@ dtb-$(CONFIG_ARCH_QCOM) += ipq9650-rdp488.dtb dtb-$(CONFIG_ARCH_QCOM) += kaanapali-mtp.dtb dtb-$(CONFIG_ARCH_QCOM) += kaanapali-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += lemans-evk.dtb +dtb-$(CONFIG_ARCH_QCOM) += lemans-draco-evk.dtb + +lemans-draco-evk-el2-dtbs := lemans-draco-evk.dtb lemans-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += lemans-draco-evk-el2.dtb lemans-evk-emmc-dtbs := lemans-evk.dtb lemans-evk-emmc.dtbo dtb-$(CONFIG_ARCH_QCOM) += lemans-evk-emmc.dtb diff --git a/arch/arm64/boot/dts/qcom/lemans-draco-evk.dts b/arch/arm64/boot/dts/qcom/lemans-draco-evk.dts new file mode 100644 index 0000000000000..930cb6cc23918 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/lemans-draco-evk.dts @@ -0,0 +1,543 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +/dts-v1/; + +#include +#include "lemans-draco-evk-som.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. Lemans Draco EVK"; + compatible = "qcom,lemans-draco-evk", "qcom,qcs9100", + "qcom,sa8775p"; + chassis-type = "embedded"; + + aliases { + ethernet0 = ðernet0; + ethernet1 = ðernet1; + }; + + dp0-connector { + compatible = "dp-connector"; + label = "DP0"; + type = "full-size"; + + dp-pwr-supply = <&vreg_dp0_pwr>; + + port { + dp0_connector_in: endpoint { + remote-endpoint = <&mdss0_dp0_out>; + }; + }; + }; + + dp1-connector { + compatible = "dp-connector"; + label = "DP1"; + type = "full-size"; + + dp-pwr-supply = <&vreg_dp1_pwr>; + + port { + dp1_connector_in: endpoint { + remote-endpoint = <&mdss0_dp1_out>; + }; + }; + }; + + dp2-connector { + compatible = "dp-connector"; + label = "DP2"; + type = "full-size"; + + dp-pwr-supply = <&vreg_dp2_pwr>; + + port { + dp2_connector_in: endpoint { + remote-endpoint = <&mdss1_dp0_out>; + }; + }; + }; + + dp3-connector { + compatible = "dp-connector"; + label = "DP3"; + type = "full-size"; + + dp-pwr-supply = <&vreg_dp3_pwr>; + + port { + dp3_connector_in: endpoint { + remote-endpoint = <&mdss1_dp1_out>; + }; + }; + }; + + vreg_dp0_pwr: regulator-dp0-pwr { + compatible = "regulator-fixed"; + regulator-name = "VREG_DP0_PWR_3P3"; + + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&expander1 7 GPIO_ACTIVE_HIGH>; + }; + + vreg_dp1_pwr: regulator-dp1-pwr { + compatible = "regulator-fixed"; + regulator-name = "VREG_DP1_PWR_3P3"; + + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&expander1 8 GPIO_ACTIVE_HIGH>; + }; + + vreg_dp2_pwr: regulator-dp2-pwr { + compatible = "regulator-fixed"; + regulator-name = "VREG_DP2_PWR_3P3"; + + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&expander1 9 GPIO_ACTIVE_HIGH>; + }; + + vreg_dp3_pwr: regulator-dp3-pwr { + compatible = "regulator-fixed"; + regulator-name = "VREG_DP3_PWR_3P3"; + + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&expander1 10 GPIO_ACTIVE_HIGH>; + }; +}; + +ðernet0 { + phy-handle = <&hsgmii_phy0>; + phy-mode = "2500base-x"; + + pinctrl-0 = <ðernet0_default>; + pinctrl-names = "default"; + + snps,mtl-rx-config = <&mtl_rx_setup>; + snps,mtl-tx-config = <&mtl_tx_setup>; + + nvmem-cells = <&mac_addr0>; + nvmem-cell-names = "mac-address"; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + hsgmii_phy0: ethernet-phy@1c { + compatible = "ethernet-phy-id004d.d101"; + reg = <0x1c>; + reset-gpios = <&pmm8654au_2_gpios 8 GPIO_ACTIVE_LOW>; + reset-assert-us = <11000>; + reset-deassert-us = <70000>; + }; + }; + + mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +ðernet1 { + phy-handle = <&hsgmii_phy1>; + phy-mode = "2500base-x"; + + pinctrl-0 = <ðernet1_default>; + pinctrl-names = "default"; + + snps,mtl-rx-config = <&mtl_rx_setup1>; + snps,mtl-tx-config = <&mtl_tx_setup1>; + + nvmem-cells = <&mac_addr1>; + nvmem-cell-names = "mac-address"; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + hsgmii_phy1: ethernet-phy@1c { + compatible = "ethernet-phy-id004d.d101"; + reg = <0x1c>; + reset-gpios = <&pmm8654au_2_gpios 9 GPIO_ACTIVE_LOW>; + reset-assert-us = <11000>; + reset-deassert-us = <70000>; + }; + }; + + mtl_rx_setup1: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + mtl_tx_setup1: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; +}; + +&i2c2 { + status = "okay"; + + expander0: gpio@20 { + compatible = "ti,tca6416"; + reg = <0x20>; + #gpio-cells = <2>; + gpio-controller; + }; + + expander1: gpio@21 { + compatible = "ti,tca6416"; + reg = <0x21>; + #gpio-cells = <2>; + gpio-controller; + }; + + expander2: gpio@22 { + compatible = "ti,tca6416"; + reg = <0x22>; + #gpio-cells = <2>; + gpio-controller; + }; + + expander3: gpio@23 { + compatible = "ti,tca6416"; + reg = <0x23>; + #gpio-cells = <2>; + gpio-controller; + }; + + expander4: gpio@38 { + compatible = "nxp,pca9534"; + reg = <0x38>; + #gpio-cells = <2>; + gpio-controller; + }; +}; + +&i2c4 { + status = "okay"; + + fan_controller: fan@1a { + compatible = "ti,amc6821"; + reg = <0x1a>; + #pwm-cells = <2>; + + fan { + pwms = <&fan_controller 40000 PWM_POLARITY_INVERTED>; + }; + }; +}; + +&i2c18 { + status = "okay"; + + expander5: gpio@3c { + compatible = "nxp,pca9534"; + reg = <0x3c>; + #gpio-cells = <2>; + gpio-controller; + }; + + eeprom@50 { + compatible = "giantec,gt24c256c", "atmel,24c256"; + reg = <0x50>; + pagesize = <64>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + mac_addr0: mac-addr@0 { + reg = <0x0 0x6>; + }; + + mac_addr1: mac-addr@6 { + reg = <0x6 0x6>; + }; + }; + }; +}; + +&mdss0 { + status = "okay"; +}; + +&mdss0_dp0 { + pinctrl-0 = <&dp0_hot_plug_det>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&mdss0_dp0_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + + remote-endpoint = <&dp0_connector_in>; +}; + +&mdss0_dp0_phy { + vdda-phy-supply = <&vreg_l1c>; + vdda-pll-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&mdss0_dp1 { + pinctrl-0 = <&dp1_hot_plug_det>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&mdss0_dp1_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + + remote-endpoint = <&dp1_connector_in>; +}; + +&mdss0_dp1_phy { + vdda-phy-supply = <&vreg_l1c>; + vdda-pll-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&mdss1 { + status = "okay"; +}; + +&mdss1_dp0 { + pinctrl-0 = <&dp2_hot_plug_det>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&mdss1_dp0_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + + remote-endpoint = <&dp2_connector_in>; +}; + +&mdss1_dp0_phy { + vdda-phy-supply = <&vreg_l1c>; + vdda-pll-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&mdss1_dp1 { + pinctrl-0 = <&dp3_hot_plug_det>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&mdss1_dp1_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + + remote-endpoint = <&dp3_connector_in>; +}; + +&mdss1_dp1_phy { + vdda-phy-supply = <&vreg_l1c>; + vdda-pll-supply = <&vreg_l4a>; + + status = "okay"; +}; + +&qup_i2c4_default { + drive-strength = <6>; + bias-pull-up; +}; + +&serdes0 { + phy-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&serdes1 { + phy-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&spi16 { + status = "okay"; + + tpm@0 { + compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi"; + reg = <0>; + spi-max-frequency = <20000000>; + }; +}; + +&tlmm { + + dp2_hot_plug_det: dp2-hot-plug-det-state { + pins = "gpio104"; + function = "edp2_hot"; + bias-disable; + }; + + dp3_hot_plug_det: dp3-hot-plug-det-state { + pins = "gpio103"; + function = "edp3_hot"; + bias-disable; + }; + + ethernet0_default: ethernet0-default-state { + ethernet0-mdc-pins { + pins = "gpio8"; + function = "emac0_mdc"; + drive-strength = <16>; + bias-pull-up; + }; + + ethernet0-mdio-pins { + pins = "gpio9"; + function = "emac0_mdio"; + drive-strength = <16>; + bias-pull-up; + }; + }; + + ethernet1_default: ethernet1-default-state { + ethernet1-mdc-pins { + pins = "gpio20"; + function = "emac1_mdc"; + drive-strength = <16>; + bias-pull-up; + }; + + ethernet1-mdio-pins { + pins = "gpio21"; + function = "emac1_mdio"; + drive-strength = <16>; + bias-pull-up; + }; + }; + +}; From 5a1c28c6b3892a43c22585958743e7a2f6a6d2d7 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:05:17 +0530 Subject: [PATCH 0839/1133] FROMLIST: arm64: dts: qcom: kodiak: Add GEM_NOC interconnect for adreno SMMU On Kodiak platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-3-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 95267c1bac1d9..1faf29f7417e3 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -3405,6 +3405,8 @@ power-domains = <&gpucc GPU_CC_CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; gfx_0_tbu: tbu@3dd9000 { From f012c75bd26857356f782857b2128251693a6167 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Mon, 3 Aug 2026 17:40:41 +0530 Subject: [PATCH 0840/1133] FROMLIST: arm64: dts: qcom: qcm6490-idp/qcs6490-rb3gen2: Keep wlan_ce_mem and drop redundant wifi memory-region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reserved region wlan_ce_mem is device memory used by the WCN6750 firmware. Deleting it in qcm6490-idp.dts and qcs6490-rb3gen2.dts is erroneous — the region must remain present regardless of whether the underlying OS uses it — so drop the /delete-node/ &wlan_ce_mem; from both board files. Also drop the per-board memory-region override from &wifi. Both wlan_fw_mem and wlan_ce_mem are already assigned to the wifi node in kodiak.dtsi, so the override is redundant. Link: https://lore.kernel.org/lkml/20260803121042.3313824-2-mukesh.ojha@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Signed-off-by: Mukesh Ojha --- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 2 -- arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 2 -- 2 files changed, 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index 419339095ed9f..a168fd2f40f3a 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -25,7 +25,6 @@ /delete-node/ &adsp_mem; /delete-node/ &cdsp_mem; /delete-node/ &video_mem; -/delete-node/ &wlan_ce_mem; /delete-node/ &wpss_mem; /delete-node/ &xbl_mem; @@ -1221,7 +1220,6 @@ }; &wifi { - memory-region = <&wlan_fw_mem>; qcom,calibration-variant = "Qualcomm_qcm6490idp"; status = "okay"; diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts index dd5024484fd10..fc76a86e90aa9 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts @@ -26,7 +26,6 @@ /delete-node/ &adsp_mem; /delete-node/ &cdsp_mem; /delete-node/ &video_mem; -/delete-node/ &wlan_ce_mem; /delete-node/ &wpss_mem; /delete-node/ &xbl_mem; @@ -1509,7 +1508,6 @@ }; &wifi { - memory-region = <&wlan_fw_mem>; qcom,calibration-variant = "Qualcomm_rb3gen2"; status = "okay"; From 9f5c370ad18bbd678a4f3debd1cca21757f19345 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Mon, 3 Aug 2026 17:40:42 +0530 Subject: [PATCH 0841/1133] FROMLIST: arm64: dts: qcom: kodiak: Add EL2 overlay All existing Kodiak board variants run the Gunyah hypervisor, which means Linux can only boot at EL1 on those devices. It is possible to boot Linux at EL2 on these devices [1]. When running under Gunyah, remote processor firmware IOMMU streams are controlled by Gunyah. Without Gunyah, the IOMMU is managed by the consumer of the DeviceTree. Describe the firmware streams for each remote processor in an EL2 overlay. Add an EL2-specific DT overlay and apply it to Kodiak IoT variant devices to produce a -el2.dtb alongside the standard dtb. Modem and media subsystems are not yet supported due to missing dependencies. The GPU zap shader is disabled. In EL2 mode the kernel owns the hardware watchdog, so it is enabled here. The wifi-firmware child node describes the IOMMU stream for the WCN6750 firmware; the &wifi node itself is left untouched so that platforms without WiFi are unaffected by the overlay. [1] https://docs.qualcomm.com/bundle/publicresource/topics/80-70020-4/boot-developer-touchpoints.html#uefi Link: https://lore.kernel.org/lkml/20260803121042.3313824-3-mukesh.ojha@oss.qualcomm.com/ Co-developed-by: Sumit Garg Signed-off-by: Sumit Garg Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Signed-off-by: Mukesh Ojha --- arch/arm64/boot/dts/qcom/Makefile | 12 ++++++++ arch/arm64/boot/dts/qcom/kodiak-el2.dtso | 39 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/kodiak-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..6a0caf9420c52 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -181,7 +181,11 @@ purwa-iot-evk-el2-dtbs := purwa-iot-evk.dtb x1-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += purwa-iot-evk-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += qcm6490-fairphone-fp5.dtb + dtb-$(CONFIG_ARCH_QCOM) += qcm6490-idp.dtb +qcm6490-idp-el2-dtbs := qcm6490-idp.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcm6490-idp-el2.dtb + dtb-$(CONFIG_ARCH_QCOM) += qcm6490-particle-tachyon.dtb dtb-$(CONFIG_ARCH_QCOM) += qcm6490-shift-otter.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb @@ -193,12 +197,20 @@ qcs615-ride-el2-dtbs := qcs615-ride.dtb talos-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-radxa-dragon-q6a.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb +qcs6490-rb3gen2-el2-dtbs := qcs6490-rb3gen2.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-el2.dtb qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine.dtbo qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtb +qcs6490-rb3gen2-industrial-mezzanine-el2-dtbs := qcs6490-rb3gen2-industrial-mezzanine.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-el2.dtb + dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtb +qcs6490-rb3gen2-vision-mezzanine-el2-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb kodiak-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-el2.dtb + dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-minipc-g1iot.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs6490-thundercomm-rubikpi3.dtb diff --git a/arch/arm64/boot/dts/qcom/kodiak-el2.dtso b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso new file mode 100644 index 0000000000000..8daf7f02fd758 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Kodiak specific modifications required to boot in EL2. + */ + +/dts-v1/; +/plugin/; + +&gpu_zap_shader { + status = "disabled"; +}; + +&remoteproc_adsp { + iommus = <&apps_smmu 0x1800 0x0>; +}; + +&remoteproc_cdsp { + iommus = <&apps_smmu 0x11a0 0x0400>; +}; + +&remoteproc_mpss { + status = "disabled"; +}; + +&venus { + status = "disabled"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + wifi-firmware { + iommus = <&apps_smmu 0x1c02 0x1>; + }; +}; From 5b51b07126e758431811e640c107c45922e18eed Mon Sep 17 00:00:00 2001 From: Sarat Addepalli Date: Thu, 18 Jun 2026 12:55:09 +0530 Subject: [PATCH 0842/1133] FROMLIST: arm64: dts: qcom: qcm6490-idp: add and enable IPA node Enable IPA and ensure ipa apps loads the gsi firmware because modem doesn't support IPA FW loading. Link: https://lore.kernel.org/all/20260618124700.2001191-1-sarat.addepalli@oss.qualcomm.com/ Signed-off-by: Sarat Addepalli Signed-off-by: Pavan Kumar M Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/qcm6490-idp.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts index a168fd2f40f3a..ea6526b7c8660 100644 --- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts +++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts @@ -616,6 +616,8 @@ &ipa { firmware-name = "qcom/qcm6490/ipa_fws.mbn"; + qcom,gsi-loader = "self"; + memory-region = <&ipa_fw_mem>; status = "okay"; }; From e0a71de7ff77420e1c23964ce2af5b2110b1f500 Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Date: Thu, 14 May 2026 19:55:47 +0530 Subject: [PATCH 0843/1133] 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. Reviewed-by: Bartosz Golaszewski Reviewed-by: Rob Herring (Arm) Signed-off-by: Shivendra Pratap Link: https://lore.kernel.org/r/20260514-arm-psci-system_reset2-vendor-reboots-v22-6-28a5bde07483@oss.qualcomm.com --- .../devicetree/bindings/arm/psci.yaml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/psci.yaml b/Documentation/devicetree/bindings/arm/psci.yaml index 0d04389c81faa..ab754507f77f0 100644 --- a/Documentation/devicetree/bindings/arm/psci.yaml +++ b/Documentation/devicetree/bindings/arm/psci.yaml @@ -98,6 +98,26 @@ properties: [1] Kernel documentation - ARM idle states bindings Documentation/devicetree/bindings/cpu/idle-states.yaml + reboot-mode: + 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 corresponds to the reset_type + and the values should be provided as per the PSCI SYSTEM_RESET2 + specs. The cookie value is optional and defaulted to zero. + patternProperties: "^power-domain-": $ref: /schemas/power/power-domain.yaml# @@ -137,6 +157,15 @@ allOf: required: - cpu_off - cpu_on + - if: + not: + properties: + compatible: + contains: + const: arm,psci-1.0 + then: + properties: + reboot-mode: false additionalProperties: false @@ -260,4 +289,17 @@ examples: domain-idle-states = <&cluster_ret>, <&cluster_pwrdn>; }; }; + + - |+ + + // Case 5: SYSTEM_RESET2 vendor resets + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + + reboot-mode { + mode-edl = <0x80000000 1>; + mode-bootloader = <0x80010001 2>; + }; + }; ... From 4eddd19eb31ca2522713dc5d27ef8cc3cd4b6f08 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Wed, 22 Jul 2026 00:00:08 +0530 Subject: [PATCH 0844/1133] FROMLIST: arm64: dts: qcom: pm7250b: Enable BCL sensor node Add Battery Current Limiting (BCL) hardware monitor node for pm7250b PMIC. The BCL monitors battery voltage and current, providing hardware interrupts when configurable thresholds are violated. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20260722-qcom-bcl-hwmon-v2-3-febe2805e17b@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/pm7250b.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pm7250b.dtsi b/arch/arm64/boot/dts/qcom/pm7250b.dtsi index 43cab07126c5c..1d358aeda9b2c 100644 --- a/arch/arm64/boot/dts/qcom/pm7250b.dtsi +++ b/arch/arm64/boot/dts/qcom/pm7250b.dtsi @@ -89,6 +89,15 @@ status = "disabled"; }; + sensor@1d00 { + compatible = "qcom,pm7250b-bcl"; + reg = <0x1d00>; + interrupts = , + ; + interrupt-names = "max-min", + "critical"; + }; + pm7250b_temp: temp-alarm@2400 { compatible = "qcom,spmi-temp-alarm"; reg = <0x2400>; From fec05780b1c60256529da6fd7da2631aeee5bf90 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Wed, 22 Jul 2026 00:00:10 +0530 Subject: [PATCH 0845/1133] FROMLIST: arm64: dts: qcom: pm8350c: Enable BCL sensor node Add Battery Current Limiting (BCL) hardware monitor node for pm8350c PMIC. The BCL monitors battery voltage and current, providing hardware interrupts when configurable thresholds are violated. Signed-off-by: Manaf Meethalavalappu Pallikunhi Link: https://lore.kernel.org/r/20260722-qcom-bcl-hwmon-v2-5-febe2805e17b@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/pm8350c.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/pm8350c.dtsi b/arch/arm64/boot/dts/qcom/pm8350c.dtsi index 1a24e6439e36d..8815868f9ad64 100644 --- a/arch/arm64/boot/dts/qcom/pm8350c.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8350c.dtsi @@ -20,6 +20,15 @@ #thermal-sensor-cells = <0>; }; + sensor@4700 { + compatible = "qcom,pm8350c-bcl"; + reg = <0x4700>; + interrupts = <0x2 0x47 0x0 IRQ_TYPE_EDGE_RISING>, + <0x2 0x47 0x1 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "max-min", + "critical"; + }; + pm8350c_gpios: gpio@8800 { compatible = "qcom,pm8350c-gpio", "qcom,spmi-gpio"; reg = <0x8800>; @@ -41,6 +50,7 @@ #pwm-cells = <2>; status = "disabled"; }; + }; }; From 7d9e840e64687098615442882432f4225660f217 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Fri, 17 Jul 2026 15:02:23 +0530 Subject: [PATCH 0846/1133] PENDING: arm64: dts: qcom: kodiak-el2: Add venus firmware sub node A dedicated firmware sub-device is required to map the firmware region to the device's IOMMU mapped stream ID, which is the firmware stream ID, in order to boot the Iris firmware when no hypervisor is present. Enable venus and add the video-firmware sub-device with its IOMMU stream ID for EL2 boot on Kodiak. Signed-off-by: Vishnu Reddy --- arch/arm64/boot/dts/qcom/kodiak-el2.dtso | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/kodiak-el2.dtso b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso index 8daf7f02fd758..05e1b696a6206 100644 --- a/arch/arm64/boot/dts/qcom/kodiak-el2.dtso +++ b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso @@ -25,7 +25,11 @@ }; &venus { - status = "disabled"; + status = "okay"; + + video-firmware { + iommus = <&apps_smmu 0x21a2 0x0>; + }; }; &watchdog { From 31dc12310d6311165b437666ce64ccb59df4bd69 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Sat, 1 Aug 2026 13:07:28 +0530 Subject: [PATCH 0847/1133] FROMLIST: arm64: dts: qcom: sc7280: Add dma-coherent property into venus node While testing with some higher resolution clips, the venus hardware triggers a fault due to wrong input data being received. Corruption was also observed in the captured output when the client dumped it to a file. On debugging, this was traced to the venus node not declaring dma-coherent. As a result, DMA buffers shared between the CPU and the venus video hardware/controller are not guaranteed to be I/O coherent: CPU writes to an input buffer can remain in CPU caches without being visible to the video hardware when it reads the same buffer, so the hardware receives input data that does not match what the CPU wrote. Likewise, on the capture path, data written by the video hardware to the output buffer may not be visible to the CPU, so the client reads stale or partial data, resulting in corruption. Add the dma-coherent property to the venus node so that DMA buffers shared between the CPU and the video hardware and controller remain coherent. Link: https://lore.kernel.org/all/20260801-iris-fixes-dma-pseq-fint-v1-2-aba0cb22f6ab@oss.qualcomm.com/ Fixes: 37613aee2179 ("arm64: dts: qcom: sc7280: Add venus DT node") Cc: stable@vger.kernel.org Signed-off-by: Vishnu Reddy --- arch/arm64/boot/dts/qcom/kodiak.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi index 1faf29f7417e3..1fa638c2127ee 100644 --- a/arch/arm64/boot/dts/qcom/kodiak.dtsi +++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi @@ -5045,6 +5045,8 @@ <&mmss_noc MASTER_VIDEO_P0 0 &mc_virt SLAVE_EBI1 0>; interconnect-names = "cpu-cfg", "video-mem"; + dma-coherent; + iommus = <&apps_smmu 0x2180 0x20>; memory-region = <&video_mem>; From b73b94c9834d04a54638aa61c4912e12c3ccdc88 Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Mon, 7 Sep 2026 11:29:34 +0530 Subject: [PATCH 0848/1133] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Add LVDS display overlay The QCS6490 RB3 Gen2 industrial mezzanine supports LVDS display output using the Lontium LT9211C DSI-to-LVDS bridge as an alternative to the default HDMI output via the LT9611UXC bridge. Add a DTBO overlay, qcs6490-rb3gen2-industrial-mezzanine-lvds-boe,dv215fhm-r01.dtso, that disables HDMI (hdmi-connector and lt9611_codec) and wires up the LT9211C bridge on I2C1 (address 0x29) with reset on GPIO117. The overlay adds a dual-channel panel-lvds node for the boe,dv215fhm-r01 panel, matched against the panel-simple-lvds-dual-ports binding which supplies the panel's size and timing internally. The overlay is built as a composite DTB combining the base qcs6490-rb3gen2.dtb, the industrial mezzanine overlay, and this LVDS overlay. Link: https://lore.kernel.org/all/20260905-lvds-support-v3-3-b40a1b03f63c@oss.qualcomm.com/ Signed-off-by: Vishnu Saini --- arch/arm64/boot/dts/qcom/Makefile | 5 + ...trial-mezzanine-lvds-boe,dv215fhm-r01.dtso | 106 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-lvds-boe,dv215fhm-r01.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 6a0caf9420c52..82394f033b1f5 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -207,6 +207,11 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine.dtb qcs6490-rb3gen2-industrial-mezzanine-el2-dtbs := qcs6490-rb3gen2-industrial-mezzanine.dtb kodiak-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-el2.dtb +qcs6490-rb3gen2-industrial-mezzanine-lvds-boe,dv215fhm-r01-dtbs := \ + qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo \ + qcs6490-rb3gen2-industrial-mezzanine-lvds-boe,dv215fhm-r01.dtbo +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-industrial-mezzanine-lvds-boe,dv215fhm-r01.dtb + dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine.dtb qcs6490-rb3gen2-vision-mezzanine-el2-dtbs := qcs6490-rb3gen2-vision-mezzanine.dtb kodiak-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-vision-mezzanine-el2.dtb diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-lvds-boe,dv215fhm-r01.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-lvds-boe,dv215fhm-r01.dtso new file mode 100644 index 0000000000000..5501ea09f43ba --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine-lvds-boe,dv215fhm-r01.dtso @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&{/} { + model = "Qualcomm Technologies, Inc. Industrial RB3gen2 LVDS"; + + hdmi-connector { + status = "disabled"; + }; + + panel_lvds: panel-lvds { + compatible = "boe,dv215fhm-r01"; + power-supply = <&lcd_disp_bias>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dual-lvds-odd-pixels; + + panel_in_lvds_odd: endpoint { + remote-endpoint = <<9211c_out_odd>; + }; + }; + + port@1 { + reg = <1>; + dual-lvds-even-pixels; + + panel_in_lvds_even: endpoint { + remote-endpoint = <<9211c_out_even>; + }; + }; + }; + }; + + lcd_disp_bias: regulator-lcd-disp-bias { + compatible = "regulator-fixed"; + regulator-name = "lcd_disp_bias"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + vin-supply = <&vreg_l18b_1p8>; + }; +}; + +&i2c1 { + #address-cells = <1>; + #size-cells = <0>; + + status = "okay"; + + lvds_bridge: lvds-bridge@29 { + compatible = "lontium,lt9211c"; + reg = <0x29>; + reset-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>; + vccio-supply = <&vreg_l18b_1p8>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9211c_in: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9211c_out_odd: endpoint { + remote-endpoint = <&panel_in_lvds_odd>; + }; + }; + + port@3 { + reg = <3>; + + lt9211c_out_even: endpoint { + remote-endpoint = <&panel_in_lvds_even>; + }; + }; + }; + }; +}; + +<9611_codec { + status = "disabled"; +}; + +&mdss_dsi0_out { + remote-endpoint = <<9211c_in>; +}; + From 04fd975053b6ed0c653dd70b22932d6edcce755d Mon Sep 17 00:00:00 2001 From: Karthik S Date: Fri, 23 Oct 2026 12:49:38 +0530 Subject: [PATCH 0849/1133] FROMLIST: arm64: dts: qcom: qcs6490-rb3gen2: Fix model name for qcs6490-rb3gen2 industrial mezzanine Fix model name for qcs6490-rb3gen2 industrial mezzanine, which ensures the right topology will be utilised for audio usecases. Link: https://lore.kernel.org/all/20261022125503.1231758-1-karthik.s@oss.qualcomm.com/ Signed-off-by: Karthik S --- .../boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso index de0343a54a4b3..3817d8e5ee776 100644 --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2-industrial-mezzanine.dtso @@ -368,7 +368,7 @@ }; &sound { - model = "qcs6490-rb3gen2-ia-snd-card"; + model = "QCS6490-RB3Gen2-Industrial-Mezz"; audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT", "SpkrRight IN", "WSA_SPK2 OUT", "IN1_HPHL", "HPHL_OUT", From 9f0ccc5f0ac5f1d9f450aa847e132d00dc69e541 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 26 Oct 2026 16:59:35 +0530 Subject: [PATCH 0850/1133] FROMLIST: arm64: dts: qcom: qcs8300: Add GP M/N clock controller Add the GP M/N clock controller and its pin configuration for QCS8300. The controller uses the PDM XO4 and AHB clocks from GCC and routes its output to gpio32. Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/20261026-b4-pdm_clk_gp_mnd_v2-v2-9-ff8e4bc8d567@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/monaco.dtsi | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 17b1940b9f7cc..526a47e33136a 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -4894,6 +4894,20 @@ power-domains = <&rpmhpd RPMHPD_CX>; }; + gp_mn: clock-controller@88d3000 { + compatible = "qcom,qcs8300-gp-mnd", "qcom,sc7280-gp-mnd"; + reg = <0x0 0x088d3000 0x0 0x1000>; + clocks = <&gcc GCC_PDM_XO4_CLK>, + <&gcc GCC_PDM_AHB_CLK>; + clock-names = "pdm_clk", "ahb_clk"; + #clock-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&gp_mn_active>; + assigned-clocks = <&gcc GCC_PDM_XO4_CLK>; + assigned-clock-rates = <4800000>; + status = "disabled"; + }; + usb_1_hsphy: phy@8904000 { compatible = "qcom,qcs8300-usb-hs-phy", "qcom,usb-snps-hs-7nm-phy"; @@ -6460,6 +6474,13 @@ bias-disable; }; + gp_mn_active: gp-mn-active-state { + pins = "gpio32"; + function = "gp_mn"; + drive-strength = <2>; + bias-disable; + }; + hs0_mi2s_active: hs0-mi2s-active-state { pins = "gpio106", "gpio107", "gpio108", "gpio109"; function = "hs0_mi2s"; From 277fbcdc78505916abeed58fd9b8fe95b8c85d2f Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Tue, 26 May 2026 20:05:19 +0530 Subject: [PATCH 0851/1133] FROMLIST: arm64: dts: qcom: monaco: Add GEM_NOC interconnect for adreno SMMU On Monaco platforms, the Adreno SMMU requires a bandwidth vote on the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers are accessible. Without this vote, the SMMU may become unreachable, leading to intermittent probe failures and runtime issues. Add the required interconnect to ensure reliable register access. Link: https://lore.kernel.org/all/20260526-smmu_interconnect_addition-v2-5-2a6d8ca30d63@oss.qualcomm.com/ Signed-off-by: Bibek Kumar Patro --- arch/arm64/boot/dts/qcom/monaco.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 526a47e33136a..d491bbc16e489 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -5129,6 +5129,8 @@ "gpu_cc_hub_aon_clk"; power-domains = <&gpucc GPU_CC_CX_GDSC>; dma-coherent; + interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; }; pmu@9091000 { From e0c28678cf19a292bafc76460d035390ba4f5d5e Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 9 Jul 2026 18:05:56 +0530 Subject: [PATCH 0852/1133] FROMLIST: arm64: dts: qcom: monaco: Move Iris IOMMUs to child nodes The Iris VPU has separate streams with different IOVA constraints. The non-pixel stream must be limited to the 0-600 MB IOVA range, while the pixel stream can use the full IOVA space. Using a single set of IOMMU entries for the Iris node does not describe these per-stream limits and can allow accesses outside the supported range, which may lead to device crashes. One such issue was reported at: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Add non-pixel and pixel child nodes, move each stream ID to its corresponding child node, and add a reserved IOVA range for the non-pixel stream. Link: https://lore.kernel.org/all/20260709-vpu_iommu_iova_handling-v1-10-72bb62cb2dfd@oss.qualcomm.com/ Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Tested-by: Daniel J Blueman --- arch/arm64/boot/dts/qcom/monaco.dtsi | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index d491bbc16e489..b3452b7c8d4f9 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -817,6 +817,10 @@ reg = <0x0 0x9be82000 0x0 0x700000>; no-map; }; + + iris_resv: reservation-iris { + iommu-addresses = <&iris_non_pixel 0x0 0x0 0x0 0x25800000>; + }; }; smp2p-adsp { @@ -5437,12 +5441,22 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x0880 0x0400>, - <&apps_smmu 0x0887 0x0400>; dma-coherent; + #address-cells = <2>; + #size-cells = <2>; + status = "disabled"; + iris_non_pixel: non-pixel { + iommus = <&apps_smmu 0x0880 0x0400>; + memory-region = <&iris_resv>; + }; + + iris_pixel: pixel { + iommus = <&apps_smmu 0x0887 0x0400>; + }; + iris_opp_table: opp-table { compatible = "operating-points-v2"; From 8f6bc7d0b03677db9668b985bbf43b9b9587df16 Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 9 Feb 2026 18:53:38 +0530 Subject: [PATCH 0853/1133] FROMLIST: arm64: dts: qcom: monaco-pmics: Add PON power key and reset inputs Add the Power On (PON) peripheral with power key and reset input support for the PMM8654AU PMIC on Monaco platforms. Link: https://lore.kernel.org/all/20260724-b4-add_pwrkey_and_resin-v6-3-41acc214d93a@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Rakesh Kota --- arch/arm64/boot/dts/qcom/monaco-pmics.dtsi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi b/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi index 361f5163b6d91..af4c76941ef09 100644 --- a/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-pmics.dtsi @@ -44,6 +44,26 @@ #address-cells = <1>; #size-cells = <0>; + pmm8654au_0_pon: pon@1200 { + compatible = "qcom,pmm8654au-pon", "qcom,pmk8350-pon"; + reg = <0x1200>, <0x800>; + reg-names = "hlos", "pbs"; + + pmm8654au_0_pon_pwrkey: pwrkey { + compatible = "qcom,pmm8654au-pwrkey", "qcom,pmk8350-pwrkey"; + interrupts-extended = <&spmi_bus 0x0 0x12 0x7 IRQ_TYPE_EDGE_BOTH>; + linux,code = ; + debounce = <15625>; + }; + + pmm8654au_0_pon_resin: resin { + compatible = "qcom,pmm8654au-resin", "qcom,pmk8350-resin"; + interrupts-extended = <&spmi_bus 0x0 0x12 0x6 IRQ_TYPE_EDGE_BOTH>; + debounce = <15625>; + status = "disabled"; + }; + }; + pmm8620au_0_rtc: rtc@6100 { compatible = "qcom,pmk8350-rtc"; reg = <0x6100>, <0x6200>; From 6f7b95589c87a709028d50408f29601674fa6851 Mon Sep 17 00:00:00 2001 From: Ziyue Zhang Date: Wed, 16 Sep 2026 18:20:22 +0800 Subject: [PATCH 0854/1133] FROMLIST: arm64: dts: qcom: qcs8300: Add qref and refgen supply for PCIe PHYs The QMP PCIe PHYs on QCS8300 require dedicated qref and refgen voltage supplies for stable operation. Without these supplies, the system may occasionally crash. Add vdda-qref-supply and vdda-refgen-supply in the board files (QCS8300-RIDE, Monaco-EVK and Monaco-Monza-SoM), and add refgen-supply in the SoC DTSI (monaco.dtsi) since refgen is an on-chip regulator shared across boards. The PHY driver votes for refgen3 directly as a workaround for a hardware issue where QREF actually depends on refgen3 rather than refgen2 as documented. Fixes: 33967eadb215 ("arm64: dts: qcom: qcs8300-ride: enable pcie0 interface") Fixes: cdb613a84527 ("arm64: dts: qcom: qcs8300-ride: enable pcie1 interface") Fixes: 41e2424651f7 ("arm64: dts: qcom: monaco-evk: Enable PCIe0 and PCIe1.") Fixes: 5238f4e7169f ("arm64: dts: qcom: Add Monaco Monza SoM") Signed-off-by: Ziyue Zhang Link: https://lore.kernel.org/r/20260916102023.2054761-4-ziyue.zhang@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/monaco-evk.dts | 4 ++++ arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi | 4 ++++ arch/arm64/boot/dts/qcom/monaco.dtsi | 4 ++++ arch/arm64/boot/dts/qcom/qcs8300-ride.dts | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index 48efb95550466..5a2423d6795d3 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -755,6 +755,8 @@ &pcie0_phy { vdda-phy-supply = <&vreg_l6a>; vdda-pll-supply = <&vreg_l5a>; + vdda-qref-supply = <&vreg_l4a>; + vdda-refgen-supply = <&vreg_l7a>; status = "okay"; }; @@ -769,6 +771,8 @@ &pcie1_phy { vdda-phy-supply = <&vreg_l6a>; vdda-pll-supply = <&vreg_l5a>; + vdda-qref-supply = <&vreg_l4a>; + vdda-refgen-supply = <&vreg_l7a>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi b/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi index a489932c7b1df..e3fd3b4b01996 100644 --- a/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco-monza-som.dtsi @@ -211,6 +211,8 @@ &pcie0_phy { vdda-phy-supply = <&vreg_l6a>; vdda-pll-supply = <&vreg_l5a>; + vdda-qref-supply = <&vreg_l4a>; + vdda-refgen-supply = <&vreg_l7a>; status = "okay"; }; @@ -223,6 +225,8 @@ &pcie1_phy { vdda-phy-supply = <&vreg_l6a>; vdda-pll-supply = <&vreg_l5a>; + vdda-qref-supply = <&vreg_l4a>; + vdda-refgen-supply = <&vreg_l7a>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index b3452b7c8d4f9..085dd25e3bf00 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -2444,6 +2444,8 @@ #phy-cells = <0>; + refgen-supply = <&refgen>; + status = "disabled"; }; @@ -2633,6 +2635,8 @@ #phy-cells = <0>; + refgen-supply = <&refgen>; + status = "disabled"; }; diff --git a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts index 54770aa7376d9..08f3c0945834a 100644 --- a/arch/arm64/boot/dts/qcom/qcs8300-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs8300-ride.dts @@ -638,6 +638,8 @@ &pcie0_phy { vdda-phy-supply = <&vreg_l6a>; vdda-pll-supply = <&vreg_l5a>; + vdda-qref-supply = <&vreg_l4a>; + vdda-refgen-supply = <&vreg_l7a>; status = "okay"; }; @@ -657,6 +659,8 @@ &pcie1_phy { vdda-phy-supply = <&vreg_l6a>; vdda-pll-supply = <&vreg_l5a>; + vdda-qref-supply = <&vreg_l4a>; + vdda-refgen-supply = <&vreg_l7a>; status = "okay"; }; From 3ddd823e5ad45a9709f9ab1d44e6679183b16631 Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Mon, 7 Sep 2026 11:37:19 +0530 Subject: [PATCH 0855/1133] FROMLIST: arm64: dts: qcom: monaco-evk: Add LVDS display overlay The Monaco-EVK mezzanine supports LVDS display output using the Lontium LT9211C DSI-to-LVDS bridge. The bridge is connected to the DSI0 output and drives a dual-channel 1920x1080 LVDS panel in VESA-24 mapping. Add a DTBO overlay, monaco-evk-lvds-boe,dv215fhm-r01.dtso, that wires up the LT9211C bridge on I2C8 (address 0x2d) with reset on GPIO66, a panel-lvds node for the boe,dv215fhm-r01 panel (matched against the panel-simple-lvds-dual-ports binding, which supplies the panel's size and timing internally), and an LCD display bias regulator supplied through the GPIO expander. DSI power is provided by vreg_l5a. The overlay is built as a composite DTB combining the base monaco-evk.dtb, the IFP mezzanine overlay, and this LVDS overlay. Link: https://lore.kernel.org/all/20260905-lvds-support-v3-2-b40a1b03f63c@oss.qualcomm.com/ Signed-off-by: Vishnu Saini --- arch/arm64/boot/dts/qcom/Makefile | 3 + .../monaco-evk-lvds-boe,dv215fhm-r01.dtso | 114 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-lvds-boe,dv215fhm-r01.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index ac6e49c66f680..32a605a7d7749 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -86,6 +86,9 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk-ifp-mezzanine.dtb monaco-evk-ifp-mezzanine-dtbs := monaco-evk.dtb monaco-evk-ifp-mezzanine.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtb +monaco-evk-lvds-boe,dv215fhm-r01-dtbs := monaco-evk.dtb monaco-evk-ifp-mezzanine.dtbo monaco-evk-lvds-boe,dv215fhm-r01.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-lvds-boe,dv215fhm-r01.dtb + monaco-evk-sd-card-dtbs := monaco-evk.dtb monaco-evk-sd-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-sd-card.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-lvds-boe,dv215fhm-r01.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-lvds-boe,dv215fhm-r01.dtso new file mode 100644 index 0000000000000..b796df28037bf --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-lvds-boe,dv215fhm-r01.dtso @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&{/} { + model = "Qualcomm Technologies, Inc. Monaco EVK LVDS"; + + panel_lvds: panel-lvds { + compatible = "boe,dv215fhm-r01"; + power-supply = <&lcd_disp_bias>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dual-lvds-odd-pixels; + + panel_in_lvds_odd: endpoint { + remote-endpoint = <<9211c_out_odd>; + }; + }; + + port@1 { + reg = <1>; + dual-lvds-even-pixels; + + panel_in_lvds_even: endpoint { + remote-endpoint = <<9211c_out_even>; + }; + }; + }; + }; + + lcd_disp_bias: regulator-lcd-disp-bias { + compatible = "regulator-fixed"; + regulator-name = "lcd_disp_bias"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + gpio = <&expander3 1 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&i2c8 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&qup_i2c8_data_clk>; + + status = "okay"; + + lt9211c_codec: lvds-bridge@2d { + compatible = "lontium,lt9211c"; + reg = <0x2d>; + reset-gpios = <&tlmm 66 GPIO_ACTIVE_HIGH>; + vccio-supply = <&vreg_l5a>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9211c_in: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9211c_out_odd: endpoint { + remote-endpoint = <&panel_in_lvds_odd>; + }; + }; + + port@3 { + reg = <3>; + + lt9211c_out_even: endpoint { + remote-endpoint = <&panel_in_lvds_even>; + }; + }; + }; + }; +}; + +&mdss_dsi0 { + vdda-supply = <&vreg_l5a>; + + status = "okay"; +}; + +&mdss_dsi0_out { + data-lanes = <0 1 2 3>; + remote-endpoint = <<9211c_in>; +}; + +&mdss_dsi0_phy { + vdds-supply = <&vreg_l4a>; + + status = "okay"; +}; + From ec77812b60c63aae3be7530055a89157ab3763a5 Mon Sep 17 00:00:00 2001 From: Shashank Maurya Date: Tue, 8 Sep 2026 10:42:31 +0530 Subject: [PATCH 0856/1133] FROMLIST: arm64: dts: qcom: monaco-evk: Add DSI display overlay Add a DT overlay for the Raspberry Pi 7" DSI touchscreen panel on Monaco EVK, using mdss0_dsi0 with 2 data lanes and the panel MCU on I2C8. Link: https://lore.kernel.org/all/20260907-rpi_dts_overlay-v2-1-a4989322ce00@oss.qualcomm.com/ Signed-off-by: Shashank Maurya --- arch/arm64/boot/dts/qcom/Makefile | 3 + .../monaco-evk-raspberrypi-dsi-7inch.dtso | 82 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/monaco-evk-raspberrypi-dsi-7inch.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 32a605a7d7749..ff7122582757e 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -89,6 +89,9 @@ dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-ifp-mezzanine.dtb monaco-evk-lvds-boe,dv215fhm-r01-dtbs := monaco-evk.dtb monaco-evk-ifp-mezzanine.dtbo monaco-evk-lvds-boe,dv215fhm-r01.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-lvds-boe,dv215fhm-r01.dtb +monaco-evk-raspberrypi-dsi-7inch-dtbs := monaco-evk.dtb monaco-evk-raspberrypi-dsi-7inch.dtbo +dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-raspberrypi-dsi-7inch.dtb + monaco-evk-sd-card-dtbs := monaco-evk.dtb monaco-evk-sd-card.dtbo dtb-$(CONFIG_ARCH_QCOM) += monaco-evk-sd-card.dtb diff --git a/arch/arm64/boot/dts/qcom/monaco-evk-raspberrypi-dsi-7inch.dtso b/arch/arm64/boot/dts/qcom/monaco-evk-raspberrypi-dsi-7inch.dtso new file mode 100644 index 0000000000000..f27b5a4a60934 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/monaco-evk-raspberrypi-dsi-7inch.dtso @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +/dts-v1/; +/plugin/; + +#include + +&{/} { + display_bl: backlight { + compatible = "pwm-backlight"; + power-supply = <®_dsi_touch>; + pwms = <®_backlight 0 50000 0>; + }; + + reg_dsi_touch: regulator-touch { + compatible = "regulator-fixed"; + regulator-name = "rpi-touch"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + gpio = <&expander3 5 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; +}; + +&i2c8 { + qcom,load-firmware; + qcom,xfer-mode = <1>; + + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + reg_backlight: reg_backlight@45 { + compatible = "raspberrypi,touchscreen-panel-regulator-v2"; + reg = <0x45>; + + vcc-supply = <®_dsi_touch>; + gpio-controller; + #gpio-cells = <2>; + #pwm-cells = <3>; + }; +}; + +&mdss_dsi0 { + vdda-supply = <&vreg_l1c>; + + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "raspberrypi,dsi-7inch"; + reg = <0>; + + reset-gpios = <®_backlight 0 GPIO_ACTIVE_LOW>; + power-supply = <®_dsi_touch>; + iovcc-supply = <®_dsi_touch>; + backlight = <&display_bl>; + + port { + panel0_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel0_in>; + data-lanes = <0 1>; +}; + +&mdss_dsi0_phy { + vdds-supply = <&vreg_l4a>; + + status = "okay"; +}; From c192ead0238fe2e7768e4ace593c81ba0fed7d44 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Mon, 5 Oct 2026 20:59:44 +0530 Subject: [PATCH 0857/1133] FROMLIST: arm64: dts: qcom: monaco-evk: Add suspend-only power collapse state To achieve SoC low power mode like chip rail power collapse (CxPC), the Monaco EVK board with four PMICs requires coordinated power-down of CPUSS and the Safety Island (SAIL) subsystem. This deepest system power collapse state is reserved for system-wide suspend (s2idle). Add the system_suspend domain idle state, mark it with system-state, and reference it from the system power domain. Assisted-by: Codex:GPT-6 Signed-off-by: Maulik Shah Acked-by: Kevin Hilman Link: https://lore.kernel.org/r/20261005-s2idle_state-v1-3-3c402c66f388@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/monaco-evk.dts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index 5a2423d6795d3..36cf74e42a75f 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -119,6 +119,19 @@ }; }; + cpus { + domain-idle-states { + system_suspend: domain-suspend { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x4200C344>; + entry-latency-us = <706562>; + exit-latency-us = <706562>; + min-residency-us = <709987>; + system-state; + }; + }; + }; + dmic: audio-codec-0 { compatible = "dmic-codec"; #sound-dai-cells = <0>; @@ -864,6 +877,10 @@ }; }; +&system_pd { + domain-idle-states = <&system_sleep>, <&system_suspend>; +}; + &tlmm { gpio7_hog: gpio7-hog { gpio-hog; From 64a5e9bc714d097a084a8e3391c580488716502a Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Thu, 1 Oct 2026 18:37:53 +0530 Subject: [PATCH 0858/1133] FROMLIST: arm64: dts: qcom: monaco-evk: Add off timing constraints for vreg_l8a UFS on the Monaco EVK can fail to initialize after probe deferral when vreg_l8a is re-enabled before the supply has fully stabilized. This is caused by the increased discharge and recharge time introduced by additional board-level capacitance in the shared power supply design. Add the hardware-required off-on-delay and enable-ramp-delay for vreg_l8a to ensure proper power sequencing and reliable UFS initialization across re-probe scenarios. Additionally, set qcom,regulator-off-debounce-delay-us so that quick disable/enable bounces across probe-defer retries don't power-cycle the rail in hardware at all, rather than needing to wait out the full off-on delay on every retry. Link: https://lore.kernel.org/all/20261001-regulator-off-on-delay-monaco-v1-1-db0fdd69c262@oss.qualcomm.com Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Jishnu Prakash --- arch/arm64/boot/dts/qcom/monaco-evk.dts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-evk.dts b/arch/arm64/boot/dts/qcom/monaco-evk.dts index 36cf74e42a75f..18f988d403321 100644 --- a/arch/arm64/boot/dts/qcom/monaco-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-evk.dts @@ -345,6 +345,9 @@ regulator-initial-mode = ; regulator-allow-set-load; regulator-allowed-modes = ; + regulator-off-on-delay-us = <10000>; + regulator-enable-ramp-delay = <10000>; + qcom,regulator-off-debounce-delay-us = <15000>; }; vreg_l9a: ldo9 { From 34a54dad94674a4743fd56e0f321ea3d18500be3 Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Fri, 18 Sep 2026 15:27:44 +0530 Subject: [PATCH 0859/1133] FROMLIST: arm64: dts: qcom: monaco: add RAS error source nodes ARM Reliability, Availability and Serviceability (RAS) enables processor components(for eg cache, tlb etc) to record and signal hardware faults through architected error records and fault handling interrupts. This allows software to detect, report and, where possible, recover from hardware errors. The Monaco CPU subsystem implements RAS error records for the L1/L2 cache hierarchy and the shared L3 caches. Describe these error sources in Device Tree so that the ARM RAS framework can discover them and handle cache-related error reports. Link: https://lore.kernel.org/all/20260918095746.3347893-4-umang.chheda@oss.qualcomm.com/ Co-developed-by: Faruque Ansari Signed-off-by: Umang Chheda Signed-off-by: Faruque Ansari --- arch/arm64/boot/dts/qcom/monaco.dtsi | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 085dd25e3bf00..22df6cfebf2dd 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -618,6 +618,36 @@ }; }; + l2-cache-error { + compatible = "arm,ras-processor"; + arm,num-records = <1>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x1>; + arm,cache-ref = <&l2_0>; + interrupts = ; + interrupt-names = "fhi"; + }; + + l3-cluster0-error { + compatible = "arm,ras-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x2>; + arm,status-reporting = /bits/ 64 <0x2>; + arm,cache-ref = <&l3_0>; + interrupts = ; + interrupt-names = "fhi"; + }; + + l3-cluster1-error { + compatible = "arm,ras-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x2>; + arm,status-reporting = /bits/ 64 <0x2>; + arm,cache-ref = <&l3_1>; + interrupts = ; + interrupt-names = "fhi"; + }; + memory@80000000 { device_type = "memory"; /* We expect the bootloader to fill in the size */ From 9cd4e72d1b099d3610eb1ec696edfca06403e46e Mon Sep 17 00:00:00 2001 From: Wei Deng Date: Fri, 16 Oct 2026 14:03:29 +0530 Subject: [PATCH 0860/1133] FROMLIST: arm64: dts: qcom: monaco-ac-evk: Describe the PCIe M.2 Key E connector The Monaco AC EVK has a PCIe M.2 Mechanical Key E connector to connect wireless connectivity cards over PCIe and UART interfaces. Hence, describe the connector node and link it with the PCIe 0 Root Port and UART2 nodes through graph port/endpoint. The port/endpoint nodes are defined inline in the board file rather than as empty anchor nodes in the SoC DTSI, so that of_graph_is_present() only returns true for boards that have an M.2 Key E connector present, preventing unintended pwrseq probe on boards with soldered wireless chips (e.g. qcs8300-ride). The connector's 3.3V supply is described as a fixed always-on regulator (vreg_wcn_3p3), which is required by the pcie-m2-e-connector binding. Also add the serial1 = &uart2 alias, which is required for the Bluetooth serdev device to be enumerated on the UART2 interface. Link: https://lore.kernel.org/all/20261021104709.1428234-1-wei.deng@oss.qualcomm.com/ Signed-off-by: Wei Deng --- arch/arm64/boot/dts/qcom/monaco-ac-evk.dts | 60 ++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/monaco-ac-evk.dts b/arch/arm64/boot/dts/qcom/monaco-ac-evk.dts index 6f3c3ffefe340..3780642fe4833 100644 --- a/arch/arm64/boot/dts/qcom/monaco-ac-evk.dts +++ b/arch/arm64/boot/dts/qcom/monaco-ac-evk.dts @@ -21,6 +21,7 @@ ethernet0 = ðernet0; i2c1 = &i2c1; serial0 = &uart7; + serial1 = &uart2; serial2 = &uart6; }; @@ -47,6 +48,38 @@ }; }; + connector-3 { + compatible = "pcie-m2-e-connector"; + vpcie3v3-supply = <&vreg_wcn_3p3>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_pcie_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&pcieport0_ep>; + }; + }; + + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_uart_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&uart2_ep>; + }; + }; + }; + }; + dmic: audio-codec-0 { compatible = "dmic-codec"; #sound-dai-cells = <0>; @@ -91,6 +124,17 @@ enable-active-high; }; + vreg_wcn_3p3: regulator-wcn-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_WCN_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-always-on; + regulator-boot-on; + }; + sound { compatible = "qcom,qcs8275-sndcard"; model = "MONACO-EVK"; @@ -657,6 +701,12 @@ &pcieport0 { reset-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + + port { + pcieport0_ep: endpoint { + remote-endpoint = <&m2_e_pcie_ep>; + }; + }; }; &pcieport1 { @@ -875,6 +925,16 @@ }; }; +&uart2 { + status = "okay"; + + port { + uart2_ep: endpoint { + remote-endpoint = <&m2_e_uart_ep>; + }; + }; +}; + &uart6 { status = "okay"; }; From ee029b3726087b3888edfb1692b24a7d150f483f Mon Sep 17 00:00:00 2001 From: Pablo del Arco Date: Sat, 3 Oct 2026 10:17:56 +0000 Subject: [PATCH 0861/1133] FROMLIST: arm64: dts: qcom: monaco: Add EL2 overlay for monaco-arduino-monza Build an EL2 combined DTB for the Arduino VENTUNO Q (monaco-arduino-monza) from the base DTB and monaco-el2.dtbo, as monaco-evk-el2.dtb already does for the Monaco EVK. The board boots under Gunyah by default. This DTB lets it run Linux at EL2 with KVM when the boot firmware is set up for that. Link: https://lore.kernel.org/all/20261004101849.34191-1-pablodelarco1@gmail.com/ Signed-off-by: Pablo del Arco Reviewed-by: Mukesh Ojha Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index ff7122582757e..0adec4f8295d8 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -68,6 +68,10 @@ dtb-$(CONFIG_ARCH_QCOM) += mahua-lenovo-thinkpad-t14s-gen7-lcd.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-fairphone-fp6.dtb dtb-$(CONFIG_ARCH_QCOM) += milos-nothing-asteroids.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza.dtb + +monaco-arduino-monza-el2-dtbs := monaco-arduino-monza.dtb monaco-el2.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += monaco-arduino-monza-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-ac-evk.dtb dtb-$(CONFIG_ARCH_QCOM) += monaco-evk.dtb From 34ccc2b5ffabf084d8db3d1d19e01f6feb01ec54 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Mon, 9 Feb 2026 14:24:26 +0000 Subject: [PATCH 0862/1133] FROMLIST: arm64: dts: qcom: agatti: add LPASS devices The rxmacro, txmacro, vamacro, soundwire nodes, lpass clock controllers are required to support audio playback and audio capture on sm6115 and its derivatives. Signed-off-by: Alexey Klimov Signed-off-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260209142428.214428-3-srinivas.kandagatla@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/agatti.dtsi | 189 +++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/agatti.dtsi b/arch/arm64/boot/dts/qcom/agatti.dtsi index d9f4cbfd2861c..32d185d0526ff 100644 --- a/arch/arm64/boot/dts/qcom/agatti.dtsi +++ b/arch/arm64/boot/dts/qcom/agatti.dtsi @@ -778,6 +778,42 @@ drive-strength = <8>; }; }; + + lpass_tx_swr_active: lpass-tx-swr-active-state { + clk-pins { + pins = "gpio0"; + function = "swr_tx_clk"; + drive-strength = <10>; + slew-rate = <3>; + bias-disable; + }; + + data-pins { + pins = "gpio1", "gpio2"; + function = "swr_tx_data"; + drive-strength = <10>; + slew-rate = <3>; + bias-bus-hold; + }; + }; + + lpass_rx_swr_active: lpass-rx-swr-active-state { + clk-pins { + pins = "gpio3"; + function = "swr_rx_clk"; + drive-strength = <10>; + slew-rate = <3>; + bias-disable; + }; + + data-pins { + pins = "gpio4", "gpio5"; + function = "swr_rx_data"; + drive-strength = <10>; + slew-rate = <3>; + bias-bus-hold; + }; + }; }; gcc: clock-controller@1400000 { @@ -2246,6 +2282,159 @@ }; }; + rxmacro: codec@a600000 { + compatible = "qcom,sm6115-lpass-rx-macro"; + reg = <0x0 0xa600000 0x0 0x1000>; + + clocks = <&q6afecc LPASS_CLK_ID_RX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_RX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + clock-names = "mclk", + "npl", + "dcodec", + "fsgen"; + assigned-clocks = <&q6afecc LPASS_CLK_ID_RX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_RX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <22579200>, + <22579200>; + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + swr1: soundwire@a610000 { + compatible = "qcom,soundwire-v1.6.0"; + reg = <0x0 0x0a610000 0x0 0x2000>; + interrupts = ; + + clocks = <&rxmacro>; + clock-names = "iface"; + + resets = <&lpass_audiocc 0>; + reset-names = "swr_audio_cgcr"; + + label = "RX"; + qcom,din-ports = <0>; + qcom,dout-ports = <5>; + + qcom,ports-sinterval-low = /bits/ 8 <0x03 0x1f 0x1f 0x07 0x00>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0b 0x01 0x00>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0b 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0x03 0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0x06 0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0x00 0x01 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0x00>; + qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00 0x00>; + + status = "disabled"; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + }; + + + txmacro: codec@a620000 { + compatible = "qcom,sm6115-lpass-tx-macro"; + reg = <0x0 0x0a620000 0x0 0x1000>; + + clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + clock-names = "mclk", + "npl", + "dcodec", + "fsgen"; + assigned-clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <19200000>, + <19200000>; + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + }; + + lpass_audiocc: clock-controller@a6a9000 { + compatible = "qcom,sm6115-lpassaudiocc"; + reg = <0x0 0x0a6a9000 0x0 0x1000>; + #reset-cells = <1>; + }; + + vamacro: codec@a730000 { + compatible = "qcom,sm6115-lpass-va-macro"; + reg = <0x0 0x0a730000 0x0 0x1000>; + + clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_HW_DCODEC_VOTE + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk", + "dcodec", + "npl"; + assigned-clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK + LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <19200000>, + <19200000>; + #clock-cells = <0>; + clock-output-names = "fsgen"; + #sound-dai-cells = <1>; + }; + + swr0: soundwire@a740000 { + compatible = "qcom,soundwire-v1.6.0"; + reg = <0x0 0x0a740000 0x0 0x2000>; + interrupts = , + ; + clocks = <&txmacro>; + clock-names = "iface"; + + resets = <&lpasscc 0>; + reset-names = "swr_audio_cgcr"; + + label = "VA_TX"; + qcom,din-ports = <3>; + qcom,dout-ports = <0>; + + qcom,ports-sinterval-low = /bits/ 8 <0x03 0x03 0x03>; + qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x01>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff>; + qcom,ports-lane-control = /bits/ 8 <0x00 0x00 0x00>; + + status = "disabled"; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + }; + + lpasscc: clock-controller@a7ec000 { + compatible = "qcom,sm6115-lpasscc"; + reg = <0x0 0x0a7ec000 0x0 0x1000>; + #reset-cells = <1>; + }; + remoteproc_adsp: remoteproc@ab00000 { compatible = "qcom,qcm2290-adsp-pas", "qcom,sm6115-adsp-pas"; reg = <0x0 0x0ab00000 0x0 0x100>; From 440738d445b54e2a8da29bc40563347db5051de2 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 9 Feb 2026 14:24:27 +0000 Subject: [PATCH 0863/1133] FROMLIST: arm64: dts: arduino-imola: add support for sound Add support for sound on Arduino UNO Q board, which includes - Headset playback and record. - Lineout Signed-off-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260209142428.214428-4-srinivas.kandagatla@oss.qualcomm.com --- .../boot/dts/qcom/qrb2210-arduino-imola.dts | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts index c472e13fceca4..acc831e02044d 100644 --- a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts +++ b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts @@ -110,6 +110,98 @@ leds = <&ledr>, <&ledg>, <&ledb>; }; + sound { + compatible = "qcom,qrb2210-sndcard"; + model = "Arduino-Imola-HPH-LOUT"; + audio-routing = "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2"; + + mm1-dai-link { + link-name = "MultiMedia1"; + + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>; + }; + }; + + mm2-dai-link { + link-name = "MultiMedia2"; + + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>; + }; + }; + + mm3-dai-link { + link-name = "MultiMedia3"; + + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>; + }; + }; + + hph-playback-dai-link { + link-name = "HPH Playback"; + cpu { + sound-dai = <&q6afedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 0>, <&swr1 0>, <&rxmacro 0>; + }; + }; + + lo-playback-dai-link { + link-name = "LO Playback"; + cpu { + sound-dai = <&q6afedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 0>, <&swr1 0>, <&rxmacro 0>; + }; + }; + + ear-playback-dai-link { + link-name = "Ear Playback"; + cpu { + sound-dai = <&q6afedai RX_CODEC_DMA_RX_0>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 0>, <&swr1 0>, <&rxmacro 0>; + }; + }; + + hph-capture-dai-link { + link-name = "HP Capture"; + cpu { + sound-dai = <&q6afedai TX_CODEC_DMA_TX_3>; + }; + + platform { + sound-dai = <&q6routing>; + }; + + codec { + sound-dai = <&pmic4125_codec 1>, <&swr0 0>, <&txmacro 0>; + }; + }; + }; + vreg_anx_30: regulator-anx-30 { compatible = "regulator-fixed"; regulator-name = "anx30"; @@ -421,6 +513,51 @@ }; }; +&spmi_bus { + pmic@0 { + pmic4125_codec: audio-codec@f000{ + compatible = "qcom,pm4125-codec"; + reg =<0xf000>; + vdd-io-supply = <&pm4125_l15>; + vdd-cp-supply = <&pm4125_s4>; + vdd-pa-vpos-supply = <&pm4125_s4>; + + vdd-mic-bias-supply = <&pm4125_l22>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + + qcom,rx-device = <&pm4125_rx>; + qcom,tx-device = <&pm4125_tx>; + #sound-dai-cells = <1>; + }; + }; +}; + +&swr0 { + pinctrl-0 = <&lpass_tx_swr_active>; + pinctrl-names = "default"; + status = "okay"; + + pm4125_tx: codec@0,3 { + compatible = "sdw20217010c00"; + reg = <0 3>; + qcom,tx-port-mapping = <1 1 2 3>; + }; +}; + +&swr1 { + pinctrl-0 = <&lpass_rx_swr_active>; + pinctrl-names = "default"; + status = "okay"; + + pm4125_rx: codec@0,4 { + compatible = "sdw20217010c00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5>; + }; +}; + &tlmm { jmisc_gpio18: jmisc-gpio18-state { pins = "gpio18"; From 9b67cf2828263b6104082b7c1fe796cc15d47f00 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 9 Feb 2026 14:24:28 +0000 Subject: [PATCH 0864/1133] FROMLIST: arm64: defconfig: Enable Agatti audio drivers Enable reset controller and pm4125 audio codec driver that are required to enable audio support on Qualcomm Agatti SoC based platforms. Signed-off-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260209142428.214428-5-srinivas.kandagatla@oss.qualcomm.com --- arch/arm64/configs/defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7b4985b29b21c..2f7b10c9ca818 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1175,6 +1175,8 @@ CONFIG_SND_SOC_GTM601=m CONFIG_SND_SOC_MAX98090=m CONFIG_SND_SOC_MSM8916_WCD_ANALOG=m CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m +CONFIG_SND_SOC_PM4125_SDW=m +CONFIG_SND_SOC_PCM3168A_I2C=m CONFIG_SND_SOC_RK3308=m CONFIG_SND_SOC_RK817=m CONFIG_SND_SOC_RT5640=m @@ -1485,6 +1487,7 @@ CONFIG_COMMON_CLK_MT8192_SCP_ADSP=y CONFIG_COMMON_CLK_MT8192_VDECSYS=y CONFIG_COMMON_CLK_MT8192_VENCSYS=y CONFIG_COMMON_CLK_QCOM=y +CONFIG_SM_LPASSCC_6115=m CONFIG_QCOM_HFPLL=y CONFIG_CLK_RCAR_USB2_CLOCK_SEL=y CONFIG_CLK_RENESAS_VBATTB=m From 60fd4eb250bac2fc01e2e78cda93f030c6dc8070 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Mon, 2 Nov 2026 16:33:49 +0800 Subject: [PATCH 0865/1133] FROMLIST: power: sequencing: qcom-wcn: increase WCN7850 power-up delay When the WCN7850 is powered up from the Bluetooth side first, i.e. BT_EN is asserted while WLAN_EN is still low, the chip starts from a cold state and is not ready to accept the first HCI command 50 ms after BT_EN goes high. The first command (0xfc00, read QCA version) is lost, hci_qca does not resend it and fails after the 2 s command timeout: Bluetooth: hci0: Reading QCA version information failed (-110) When WLAN is powered first, 50 ms is sufficient, so the failure only shows up in the BT-first ordering. Measured on the affected board by which enable pin rose first: pwup_delay_ms BT-first boots with -110 50 9 9 75 23 0 100 21 0 300 20 0 Raise the power-up delay of WCN7850 to 100 ms. The delay is shared by the Bluetooth and WLAN targets, so WLAN power-up also waits 50 ms longer. Fixes: 2f1630f437df ("power: pwrseq: add a driver for the PMU module on the QCom WCN chipsets") Link: https://lore.kernel.org/all/20261102094800.3225454-1-shuai.zhang@oss.qualcomm.com/ Signed-off-by: Cheng Jiang Signed-off-by: Shuai Zhang --- drivers/power/sequencing/pwrseq-qcom-wcn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/sequencing/pwrseq-qcom-wcn.c b/drivers/power/sequencing/pwrseq-qcom-wcn.c index 636dd7e638917..05ee1785e6346 100644 --- a/drivers/power/sequencing/pwrseq-qcom-wcn.c +++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c @@ -427,7 +427,7 @@ static const char *const pwrseq_wcn7850_vregs[] = { static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn7850_of_data = { .vregs = pwrseq_wcn7850_vregs, .num_vregs = ARRAY_SIZE(pwrseq_wcn7850_vregs), - .pwup_delay_ms = 50, + .pwup_delay_ms = 100, .targets = pwrseq_qcom_wcn_targets, }; From e55ec96c239c414e3b821072b66dddbaa8c285fa Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Thu, 15 Oct 2026 18:08:54 +0800 Subject: [PATCH 0866/1133] FROMLIST: Bluetooth: hci_qca: Reopen port after power on for QCA2066 QCA2066 needs the serial port reopened after the controller is powered on, otherwise the host and the controller run into RTS/CTS synchronization issues. Reopen the port in qca_power_on() for QCA2066, once the controller has been powered on. Link: https://lore.kernel.org/all/20261028111839.2148515-1-shuai.zhang@oss.qualcomm.com/ Signed-off-by: Shuai Zhang --- drivers/bluetooth/hci_qca.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index e9d17772865a0..53cebf0a7c147 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1872,6 +1872,19 @@ static int qca_power_on(struct hci_dev *hdev) ret = qca_regulator_init(hu); break; + case QCA_QCA2066: + qcadev = serdev_device_get_drvdata(hu->serdev); + if (qcadev->bt_en) { + gpiod_set_value_cansleep(qcadev->bt_en, 0); + msleep(50); + gpiod_set_value_cansleep(qcadev->bt_en, 1); + /* Controller needs time to bootup. */ + msleep(50); + } + + ret = qca_port_reopen(hu); + break; + default: qcadev = serdev_device_get_drvdata(hu->serdev); if (qcadev->bt_en) { From ec3185fd26253f81e9d76f15dd1dd95d5e696145 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Wed, 28 Oct 2026 13:40:24 +0800 Subject: [PATCH 0867/1133] FROMLIST: Bluetooth: hci_qca: Don't use the serdev port after a failed reopen If serdev_device_open() fails in qca_port_reopen(), qca_regulator_init() or the qca_setup() retry path, the port is left closed but HCI_UART_PROTO_READY stays set. The error reaches qca_setup(), whose retry loop calls serdev_device_close() again, and hci_uart_close() or hci_uart_unregister_device() close it once more later. The HCI core also calls hci_uart_flush() from hci_dev_close_sync() before hdev->close(), which writes to the closed port. serdev_device_close() and serdev_device_write_flush() have no "not open" check. ttyport_open() clears serport->tty when it fails, so both end up passing NULL to the tty layer, and the runtime PM usage count is dropped once too often. Keep HCI_UART_PROTO_READY in sync with the port state in hci_qca: clear it when the port is closed, set it only after a successful open, and only call serdev_device_close() when it was set. hci_uart_open() already treats the flag as "port is open" and reopens the port when it is clear, so the next power on recovers. Make hci_uart_flush() skip the port flush when the flag is clear, as it already does for the proto flush. Link: https://lore.kernel.org/all/20261028111839.2148515-1-shuai.zhang@oss.qualcomm.com/ Signed-off-by: Shuai Zhang --- drivers/bluetooth/hci_qca.c | 33 +++++++++++++++++++++++++++------ drivers/bluetooth/hci_serdev.c | 6 ++++-- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 53cebf0a7c147..211cb5e2d860b 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1749,6 +1749,27 @@ static bool qca_wakeup(struct hci_dev *hdev) return wakeup; } +static void qca_port_close(struct hci_uart *hu) +{ + /* HCI_UART_PROTO_READY tracks whether the port is open, so a port + * left closed by a failed qca_port_open() is not closed again by + * hci_uart_close() or hci_uart_unregister_device(). + */ + if (test_and_clear_bit(HCI_UART_PROTO_READY, &hu->flags)) + serdev_device_close(hu->serdev); +} + +static int qca_port_open(struct hci_uart *hu) +{ + int ret; + + ret = serdev_device_open(hu->serdev); + if (!ret) + set_bit(HCI_UART_PROTO_READY, &hu->flags); + + return ret; +} + static int qca_port_reopen(struct hci_uart *hu) { int ret; @@ -1758,8 +1779,8 @@ static int qca_port_reopen(struct hci_uart *hu) * Without this, we will have RTS and CTS synchronization * issues. */ - serdev_device_close(hu->serdev); - ret = serdev_device_open(hu->serdev); + qca_port_close(hu); + ret = qca_port_open(hu); if (ret) { bt_dev_err(hu->hdev, "failed to open port"); return ret; @@ -1783,12 +1804,12 @@ static int qca_regulator_init(struct hci_uart *hu) qcadev = serdev_device_get_drvdata(hu->serdev); if (!qcadev->bt_power->vregs_on) { - serdev_device_close(hu->serdev); + qca_port_close(hu); ret = qca_regulator_enable(qcadev); if (ret) return ret; - ret = serdev_device_open(hu->serdev); + ret = qca_port_open(hu); if (ret) { bt_dev_err(hu->hdev, "failed to open port"); return ret; @@ -2084,8 +2105,8 @@ static int qca_setup(struct hci_uart *hu) if (retries < MAX_INIT_RETRIES) { bt_dev_warn(hdev, "Retry BT power ON:%d", retries); if (hu->serdev) { - serdev_device_close(hu->serdev); - ret = serdev_device_open(hu->serdev); + qca_port_close(hu); + ret = qca_port_open(hu); if (ret) { bt_dev_err(hdev, "failed to open port"); return ret; diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 48ba017e219bc..d2c48df341996 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -101,11 +101,13 @@ static int hci_uart_flush(struct hci_dev *hdev) kfree_skb(hu->tx_skb); hu->tx_skb = NULL; } + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) + return 0; + /* Flush any pending characters in the driver and discipline. */ serdev_device_write_flush(hu->serdev); - if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) - hu->proto->flush(hu); + hu->proto->flush(hu); return 0; } From 725e4c518fd05ded0b87329df68378bca01db690 Mon Sep 17 00:00:00 2001 From: Harshal Dev Date: Tue, 6 Oct 2026 17:03:22 +0530 Subject: [PATCH 0868/1133] FROMLIST: tee: qcomtee: Track the object invocation context QCOMTEE needs to distinguish between object invocations arriving from kernel clients and user-space clients in order to correctly marshal UBUF parameters and decide whether certain operations should be permitted. Introduce an enum tee_object_invoke_origin to allow clients to indicate the context of the TEE object invocation, and add a kernel_ctx flag to the QCOMTEE context so the TEE back-end can track it. Reviewed-by: Sumit Garg Reviewed-by: Amirreza Zarrabi Link: https://lore.kernel.org/lkml/20261006-qcom_uefisecapp_migrate_qcomtee-v4-1-bf1c8e2a64ab@oss.qualcomm.com/ Signed-off-by: Harshal Dev --- drivers/tee/qcomtee/call.c | 12 +++++++++--- drivers/tee/qcomtee/qcomtee_object.h | 8 ++++++-- drivers/tee/tee_core.c | 3 ++- include/linux/tee_core.h | 8 +++++++- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c index 4a597eeaf174b..3de54af457193 100644 --- a/drivers/tee/qcomtee/call.c +++ b/drivers/tee/qcomtee/call.c @@ -388,20 +388,26 @@ static int qcomtee_root_object_check(u32 op, struct tee_param *params, * @ctx: TEE context. * @arg: ioctl arguments. * @params: parameters for the object. + * @origin: origin of the object invocation (kernel or user-space). * * Return: On success, returns 0; on failure, returns < 0. */ static int qcomtee_object_invoke(struct tee_context *ctx, struct tee_ioctl_object_invoke_arg *arg, - struct tee_param *params) + struct tee_param *params, + enum tee_object_invoke_origin origin) { struct qcomtee_context_data *ctxdata = ctx->data; struct qcomtee_object *object; + bool kernel_ctx = false; int i, ret, result; if (qcomtee_params_check(params, arg->num_params)) return -EINVAL; + if (origin == TEE_OBJECT_INVOKE_KERNEL) + kernel_ctx = true; + /* First, handle reserved operations: */ if (arg->op == QCOMTEE_MSG_OBJECT_OP_RELEASE) { del_qtee_object(arg->id, ctxdata); @@ -411,7 +417,7 @@ static int qcomtee_object_invoke(struct tee_context *ctx, /* Otherwise, invoke a QTEE object: */ struct qcomtee_object_invoke_ctx *oic __free(kfree) = - qcomtee_object_invoke_ctx_alloc(ctx); + qcomtee_object_invoke_ctx_alloc(ctx, kernel_ctx); if (!oic) return -ENOMEM; @@ -648,7 +654,7 @@ static void qcomtee_get_qtee_feature_list(struct tee_context *ctx, u32 id, int result; struct qcomtee_object_invoke_ctx *oic __free(kfree) = - qcomtee_object_invoke_ctx_alloc(ctx); + qcomtee_object_invoke_ctx_alloc(ctx, true); if (!oic) return; diff --git a/drivers/tee/qcomtee/qcomtee_object.h b/drivers/tee/qcomtee/qcomtee_object.h index d5de02dcef3b9..5f40617361fca 100644 --- a/drivers/tee/qcomtee/qcomtee_object.h +++ b/drivers/tee/qcomtee/qcomtee_object.h @@ -147,6 +147,7 @@ static inline int qcomtee_args_len(struct qcomtee_arg *args) * struct qcomtee_object_invoke_ctx - QTEE context for object invocation. * @ctx: TEE context for this invocation. * @flags: flags for the invocation context. + * @kernel_ctx: flag that indicates this context is owned by a kernel client. * @errno: error code for the invocation. * @object: current object invoked in this callback context. * @u: array of arguments for the current invocation (+1 for ending arg). @@ -159,6 +160,7 @@ static inline int qcomtee_args_len(struct qcomtee_arg *args) struct qcomtee_object_invoke_ctx { struct tee_context *ctx; unsigned long flags; + bool kernel_ctx; int errno; struct qcomtee_object *object; @@ -173,13 +175,15 @@ struct qcomtee_object_invoke_ctx { }; static inline struct qcomtee_object_invoke_ctx * -qcomtee_object_invoke_ctx_alloc(struct tee_context *ctx) +qcomtee_object_invoke_ctx_alloc(struct tee_context *ctx, bool kernel_ctx) { struct qcomtee_object_invoke_ctx *oic; oic = kzalloc_obj(*oic); - if (oic) + if (oic) { oic->ctx = ctx; + oic->kernel_ctx = kernel_ctx; + } return oic; } diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 1aac50c7c1de7..30901390149c8 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -701,7 +701,8 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx, goto out; } - rc = ctx->teedev->desc->ops->object_invoke_func(ctx, &arg, params); + rc = ctx->teedev->desc->ops->object_invoke_func(ctx, &arg, params, + TEE_OBJECT_INVOKE_USERSPACE); if (rc) goto out; diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h index f993d5118edda..bcb5418d6fdc6 100644 --- a/include/linux/tee_core.h +++ b/include/linux/tee_core.h @@ -73,6 +73,11 @@ struct tee_device { struct tee_shm_pool *pool; }; +enum tee_object_invoke_origin { + TEE_OBJECT_INVOKE_USERSPACE, + TEE_OBJECT_INVOKE_KERNEL, +}; + /** * struct tee_driver_ops - driver operations vtable * @get_version: returns version of driver @@ -117,7 +122,8 @@ struct tee_driver_ops { struct tee_param *param); int (*object_invoke_func)(struct tee_context *ctx, struct tee_ioctl_object_invoke_arg *arg, - struct tee_param *param); + struct tee_param *param, + enum tee_object_invoke_origin origin); int (*cancel_req)(struct tee_context *ctx, u32 cancel_id, u32 session); int (*supp_recv)(struct tee_context *ctx, u32 *func, u32 *num_params, struct tee_param *param); From 0d169500d3cce2acb1c13acb2a30a95652cb60a1 Mon Sep 17 00:00:00 2001 From: Amirreza Zarrabi Date: Tue, 6 Oct 2026 17:03:23 +0530 Subject: [PATCH 0869/1133] FROMLIST: tee: Add kernel client object invoke helper Kernel clients can open a TEE context and invoke regular TA commands through tee_client_invoke_func(). However, there is currently no equivalent helper for invoking TEE objects. Add tee_client_object_invoke_func() as a kernel client API for issuing object invocation requests. The helper checks that the backend provides object_invoke_func() before forwarding the request by setting the origin as TEE_OBJECT_INVOKE_KERNEL. This allows TEE backends to support privileged object-based calls from the kernel-space. Co-developed-by: Harshal Dev Signed-off-by: Harshal Dev Reviewed-by: Sumit Garg Link: https://lore.kernel.org/lkml/20261006-qcom_uefisecapp_migrate_qcomtee-v4-2-bf1c8e2a64ab@oss.qualcomm.com/ Reviewed-by: Amirreza Zarrabi Signed-off-by: Amirreza Zarrabi --- drivers/tee/tee_core.c | 12 ++++++++++++ include/linux/tee_drv.h | 13 +++++++++++++ 2 files changed, 25 insertions(+) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 30901390149c8..a03a3d645dd1a 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -1404,6 +1404,18 @@ int tee_client_invoke_func(struct tee_context *ctx, } EXPORT_SYMBOL_GPL(tee_client_invoke_func); +int tee_client_object_invoke_func(struct tee_context *ctx, + struct tee_ioctl_object_invoke_arg *arg, + struct tee_param *param) +{ + if (!ctx->teedev->desc->ops->object_invoke_func) + return -EINVAL; + + return ctx->teedev->desc->ops->object_invoke_func(ctx, arg, param, + TEE_OBJECT_INVOKE_KERNEL); +} +EXPORT_SYMBOL_GPL(tee_client_object_invoke_func); + int tee_client_cancel_req(struct tee_context *ctx, struct tee_ioctl_cancel_arg *arg) { diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index f3c5e106d853e..369c87ad0205f 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -283,6 +283,19 @@ int tee_client_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg, struct tee_param *param); +/** + * tee_client_object_invoke_func() - Invoke a TEE object from kernel space + * @ctx: TEE Context + * @arg: Invoke arguments, see description of + * struct tee_ioctl_object_invoke_arg + * @param: Parameters for the object invocation + * + * Return: On success, returns 0; on failure, returns < 0. + */ +int tee_client_object_invoke_func(struct tee_context *ctx, + struct tee_ioctl_object_invoke_arg *arg, + struct tee_param *param); + /** * tee_client_cancel_req() - Request cancellation of the previous open-session * or invoke-command operations in a Trusted Application From 8c541c2d77a4858cd3dda82814adbed62d996430 Mon Sep 17 00:00:00 2001 From: Amirreza Zarrabi Date: Tue, 6 Oct 2026 17:03:24 +0530 Subject: [PATCH 0870/1133] FROMLIST: tee: qcomtee: Allow object invokes from kernel clients QCOMTEE currently treats UBUF parameters as userspace addresses and applies userspace restrictions when invoking the root object. This is not suitable for object invocation requests issued by kernel clients. Use the kernel_ctx flag to distinguish kernel client requests from userspace requests. For kernel contexts, do not mark UBUF parameters as user addresses, and allow permitted root-object operations to proceed without applying the userspace-only checks. This allows in-kernel users of tee_client_object_invoke_func() to issue object invocation requests through the qcomtee backend. Co-developed-by: Harshal Dev Signed-off-by: Harshal Dev Acked-by: Sumit Garg Reviewed-by: Amirreza Zarrabi Link: https://lore.kernel.org/lkml/20261006-qcom_uefisecapp_migrate_qcomtee-v4-3-bf1c8e2a64ab@oss.qualcomm.com/ Signed-off-by: Amirreza Zarrabi --- drivers/tee/qcomtee/call.c | 38 ++++++++++++++++++---------- drivers/tee/qcomtee/qcomtee_object.h | 5 ++-- include/linux/tee_drv.h | 5 +++- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c index 3de54af457193..c97afaa1b4aaf 100644 --- a/drivers/tee/qcomtee/call.c +++ b/drivers/tee/qcomtee/call.c @@ -193,7 +193,7 @@ int qcomtee_objref_from_arg(struct tee_param *param, struct qcomtee_arg *arg, * @u: QTEE arguments. * @params: TEE parameters. * @num_params: number of elements in the parameter array. - * @ctx: context in which the conversion should happen. + * @oic: context to use for the current invocation. * * It assumes @u has at least @num_params + 1 entries and has been initialized * with %QCOMTEE_ARG_TYPE_INV as &struct qcomtee_arg.type. @@ -202,7 +202,7 @@ int qcomtee_objref_from_arg(struct tee_param *param, struct qcomtee_arg *arg, */ static int qcomtee_params_to_args(struct qcomtee_arg *u, struct tee_param *params, int num_params, - struct tee_context *ctx) + struct qcomtee_object_invoke_ctx *oic) { int i; @@ -210,8 +210,14 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u, switch (params[i].attr) { case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT: - u[i].flags = QCOMTEE_ARG_FLAGS_UADDR; - u[i].b.uaddr = params[i].u.ubuf.uaddr; + if (oic->kernel_ctx) { + u[i].flags = 0; + u[i].b.addr = params[i].u.ubuf.addr; + } else { + u[i].flags = QCOMTEE_ARG_FLAGS_UADDR; + u[i].b.uaddr = params[i].u.ubuf.uaddr; + } + u[i].b.size = params[i].u.ubuf.size; if (params[i].attr == @@ -223,7 +229,7 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u, break; case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT: u[i].type = QCOMTEE_ARG_TYPE_IO; - if (qcomtee_objref_to_arg(&u[i], ¶ms[i], ctx)) + if (qcomtee_objref_to_arg(&u[i], ¶ms[i], oic->ctx)) goto out_failed; break; @@ -260,7 +266,7 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u, * @params: TEE parameters. * @u: QTEE arguments. * @num_params: number of elements in the parameter array. - * @ctx: context in which the conversion should happen. + * @oic: context to use for the current invocation. * * @u should have already been initialized by qcomtee_params_to_args(). * This also represents the end of a QTEE invocation that started with @@ -270,7 +276,7 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u, */ static int qcomtee_params_from_args(struct tee_param *params, struct qcomtee_arg *u, int num_params, - struct tee_context *ctx) + struct qcomtee_object_invoke_ctx *oic) { int i, np; @@ -288,7 +294,8 @@ static int qcomtee_params_from_args(struct tee_param *params, break; case QCOMTEE_ARG_TYPE_OO: /* TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT */ - if (qcomtee_objref_from_arg(¶ms[np], &u[np], ctx)) + if (qcomtee_objref_from_arg(¶ms[np], &u[np], + oic->ctx)) goto out_failed; break; @@ -304,7 +311,7 @@ static int qcomtee_params_from_args(struct tee_param *params, /* Undo qcomtee_objref_from_arg(). */ for (i = 0; i < np; i++) { if (params[i].attr == TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT) - qcomtee_context_del_qtee_object(¶ms[i], ctx); + qcomtee_context_del_qtee_object(¶ms[i], oic->ctx); } /* Release any IO and OO objects not processed. */ @@ -357,7 +364,8 @@ static int qcomtee_params_check(struct tee_param *params, int num_params) } /* Check if an operation on ROOT_QCOMTEE_OBJECT from userspace is permitted. */ -static int qcomtee_root_object_check(u32 op, struct tee_param *params, +static int qcomtee_root_object_check(struct qcomtee_object_invoke_ctx *oic, + u32 op, struct tee_param *params, int num_params) { /* Some privileged operations recognized by QTEE. */ @@ -366,6 +374,9 @@ static int qcomtee_root_object_check(u32 op, struct tee_param *params, op == QCOMTEE_ROOT_OP_ADCI_SHUTDOWN) return -EINVAL; + if (oic->kernel_ctx) + return 0; + /* * QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS is to register with QTEE * by passing a credential object as input OBJREF. TEE_OBJREF_NULL as a @@ -430,7 +441,8 @@ static int qcomtee_object_invoke(struct tee_context *ctx, /* Get an object to invoke. */ if (arg->id == TEE_OBJREF_NULL) { /* Use ROOT if TEE_OBJREF_NULL is invoked. */ - if (qcomtee_root_object_check(arg->op, params, arg->num_params)) + if (qcomtee_root_object_check(oic, arg->op, params, + arg->num_params)) return -EINVAL; object = ROOT_QCOMTEE_OBJECT; @@ -438,7 +450,7 @@ static int qcomtee_object_invoke(struct tee_context *ctx, return -EINVAL; } - ret = qcomtee_params_to_args(u, params, arg->num_params, ctx); + ret = qcomtee_params_to_args(u, params, arg->num_params, oic); if (ret) goto out; @@ -456,7 +468,7 @@ static int qcomtee_object_invoke(struct tee_context *ctx, if (!result) { /* Assume service is UNAVAIL if unable to process the result. */ - if (qcomtee_params_from_args(params, u, arg->num_params, ctx)) + if (qcomtee_params_from_args(params, u, arg->num_params, oic)) result = QCOMTEE_MSG_ERROR_UNAVAIL; } else { /* diff --git a/drivers/tee/qcomtee/qcomtee_object.h b/drivers/tee/qcomtee/qcomtee_object.h index 5f40617361fca..d3740099fae06 100644 --- a/drivers/tee/qcomtee/qcomtee_object.h +++ b/drivers/tee/qcomtee/qcomtee_object.h @@ -113,8 +113,9 @@ struct qcomtee_buffer { * @b: address and size if the type of argument is a buffer. * @o: object instance if the type of argument is an object. * - * &qcomtee_arg.flags only accepts %QCOMTEE_ARG_FLAGS_UADDR for now, which - * states that &qcomtee_arg.b contains a userspace address in uaddr. ++ * If %QCOMTEE_ARG_FLAGS_UADDR is set in &qcomtee_arg.flags then it implies ++ * that &qcomtee_arg.b contains a userspace address in uaddr. ++ * Otherwise, &qcomtee_arg.b contains a kernel address in addr. */ struct qcomtee_arg { enum qcomtee_arg_type type; diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index 369c87ad0205f..367208210a323 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -83,7 +83,10 @@ struct tee_param_memref { }; struct tee_param_ubuf { - void __user *uaddr; + union { + void *addr; + void __user *uaddr; + }; size_t size; }; From 70931e1442ef431ea52d41f1f8ff785772988757 Mon Sep 17 00:00:00 2001 From: Harshal Dev Date: Tue, 6 Oct 2026 17:03:25 +0530 Subject: [PATCH 0871/1133] FROMLIST: tee: Export uuidv5 generation for TEE backends Export the uuidv5() function defined in the TEE core to all TEE backends. This enables the TEE backend drivers to generate a UUID for identifying and registering their secure services on the TEE bus. Reviewed-by: Sumit Garg Reviewed-by: Amirreza Zarrabi Link: https://lore.kernel.org/lkml/20261006-qcom_uefisecapp_migrate_qcomtee-v4-4-bf1c8e2a64ab@oss.qualcomm.com/ Signed-off-by: Harshal Dev --- drivers/tee/tee_core.c | 9 +++++---- include/linux/tee_core.h | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index a03a3d645dd1a..2cfd302d13934 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -135,7 +135,7 @@ static int tee_release(struct inode *inode, struct file *filp) } /** - * uuid_v5() - Calculate UUIDv5 + * tee_generate_uuid_v5() - Calculate UUIDv5 * @uuid: Resulting UUID * @ns: Name space ID for UUIDv5 function * @name: Name for UUIDv5 function @@ -146,8 +146,8 @@ static int tee_release(struct inode *inode, struct file *filp) * This implements section (for SHA-1): * 4.3. Algorithm for Creating a Name-Based UUID */ -static void uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name, - size_t size) +void tee_generate_uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name, + size_t size) { unsigned char hash[SHA1_DIGEST_SIZE]; struct sha1_ctx ctx; @@ -163,6 +163,7 @@ static void uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name, uuid->b[6] = (hash[6] & 0x0F) | 0x50; uuid->b[8] = (hash[8] & 0x3F) | 0x80; } +EXPORT_SYMBOL_GPL(tee_generate_uuid_v5); int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method, const u8 connection_data[TEE_IOCTL_UUID_LEN]) @@ -228,7 +229,7 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method, goto out_free_name; } - uuid_v5(uuid, &tee_client_uuid_ns, name, name_len); + tee_generate_uuid_v5(uuid, &tee_client_uuid_ns, name, name_len); out_free_name: kfree(name); diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h index bcb5418d6fdc6..a3f4f88b84237 100644 --- a/include/linux/tee_core.h +++ b/include/linux/tee_core.h @@ -272,6 +272,21 @@ void tee_device_set_dev_groups(struct tee_device *teedev, int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method, const u8 connection_data[TEE_IOCTL_UUID_LEN]); +/** + * tee_generate_uuid_v5() - Calculate UUIDv5 + * @uuid: Resulting UUID + * @ns: Name space ID for UUIDv5 function + * @name: Name for UUIDv5 function + * @size: Size of name + * + * UUIDv5 is specific in RFC 4122. + * + * This implements section (for SHA-1): + * 4.3. Algorithm for Creating a Name-Based UUID + */ +void tee_generate_uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name, + size_t size); + /** * struct tee_shm_pool - shared memory pool * @ops: operations From e7ea58256fdb10ce771cc23fea4671a188f3703b Mon Sep 17 00:00:00 2001 From: Harshal Dev Date: Tue, 6 Oct 2026 17:03:26 +0530 Subject: [PATCH 0872/1133] FROMLIST: tee: qcomtee: Add support for registering QTEE services on TEE bus QTEE exposes certain secure services implemented either within the QTEE kernel or via pre-loaded Trusted Applications (TAs). Such always-available services can be readily accessed by TEE client drivers via QTEE's object-IPC protocol if the service is registered as a device on the TEE bus. One such service is the EFI-variables service, implemented by the uefisecapp TA which enables kernel clients to access EFI variables at runtime. Maintain a static list of such always-available secure services and add support for the QCOMTEE driver to register these services as devices on the TEE bus during probe. Link: https://lore.kernel.org/lkml/20261006-qcom_uefisecapp_migrate_qcomtee-v4-5-bf1c8e2a64ab@oss.qualcomm.com/ Signed-off-by: Harshal Dev --- drivers/tee/qcomtee/call.c | 161 ++++++++++++++++++++++++++- drivers/tee/qcomtee/core.c | 9 +- drivers/tee/qcomtee/qcomtee.h | 12 ++ drivers/tee/qcomtee/qcomtee_msg.h | 1 + drivers/tee/qcomtee/qcomtee_object.h | 3 +- 5 files changed, 179 insertions(+), 7 deletions(-) diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c index c97afaa1b4aaf..3061bcbd15ab9 100644 --- a/drivers/tee/qcomtee/call.c +++ b/drivers/tee/qcomtee/call.c @@ -676,9 +676,13 @@ static void qcomtee_get_qtee_feature_list(struct tee_context *ctx, u32 id, /* Get ''FeatureVersions Service'' object. */ service = qcomtee_object_get_service(oic, client_env, - QCOMTEE_FEATURE_VER_UID); - if (service == NULL_QCOMTEE_OBJECT) + QCOMTEE_FEATURE_VER_UID, + &result); + if (service == NULL_QCOMTEE_OBJECT) { + if (result) + pr_err("FeatureVersions Service unavailable (%d)\n", result); goto out_failed; + } /* IB: Feature to query. */ u[0].b.addr = &id; @@ -698,6 +702,156 @@ static void qcomtee_get_qtee_feature_list(struct tee_context *ctx, u32 id, qcomtee_object_put(client_env); } +/** + * is_qcomtee_service_available() - Check if the QTEE service identified by the UID + * is available + * @oic: context to use for the current invocation. + * @client_env: Client environment object. + * @service_name: Name of the QTEE service. + * @uid: 32-bit UID of the service. + * + * Returns true if the service exists and is available. + * Returns false if a service is not exposed by QTEE. + */ +static bool is_qcomtee_service_available(struct qcomtee_object_invoke_ctx *oic, + struct qcomtee_object *client_env, + const char *service_name, u32 uid) +{ + struct qcomtee_object *service; + int error = 0; + bool ret = false; + + /* Get service object corresponding to the uid. */ + service = qcomtee_object_get_service(oic, client_env, uid, &error); + if (service != NULL_QCOMTEE_OBJECT) { + qcomtee_object_put(service); + ret = true; + } + + /* When we fail to get the service, QTEE provides the reason. */ + if (error) + pr_debug("%s is unavailable (%d)\n", service_name, error); + + return ret; +} + +/* + * QTEE Service UUID name space identifier + * + * A random UUID that is allocated as a name space identifier for forming UUID's + * representing secure services exposed by QTEE. + */ +static const uuid_t qtee_service_uuid_ns = UUID_INIT(0xe1b48857, 0x6154, 0x49f9, + 0x93, 0x4e, 0xa2, 0xf2, + 0x0a, 0xba, 0x98, 0x42); + +static const struct qtee_service qtee_services[] = { + { "qcom.tz.uefisecapp", + QCOMTEE_UEFI_SEC_UID } +}; + +static void qtee_release_service(struct device *dev) +{ + struct tee_client_device *qtee_service = to_tee_client_device(dev); + + kfree(qtee_service); +} + +/** + * qtee_register_service() - Register a given QTEE service on the TEE bus as a + * TEE client device + * @oic: context to use for the current invocation. + * @client_env: Client environment object. + * @service_name: Name of the QTEE service to be enumerated. + * @uid: 32-bit UID used by QTEE to identify the service. + * + * Returns 0 on success and < 0 on failure. + */ +static int qtee_register_service(struct qcomtee_object_invoke_ctx *oic, + struct qcomtee_object *client_env, + const char *service_name, + const u32 uid) +{ + struct tee_client_device *qtee_service; + uuid_t service_uuid; + int rc; + + if (!is_qcomtee_service_available(oic, client_env, service_name, uid)) + return -EOPNOTSUPP; + + tee_generate_uuid_v5(&service_uuid, &qtee_service_uuid_ns, service_name, + strlen(service_name)); + + qtee_service = kzalloc_obj(*qtee_service); + if (!qtee_service) + return -ENOMEM; + + qtee_service->dev.bus = &tee_bus_type; + qtee_service->dev.release = qtee_release_service; + if (dev_set_name(&qtee_service->dev, "qtee-svc-%pUb", &service_uuid)) { + kfree(qtee_service); + return -ENOMEM; + } + uuid_copy(&qtee_service->id.uuid, &service_uuid); + + rc = device_register(&qtee_service->dev); + if (rc) { + pr_err("QTEE service registration failed, err: %d\n", rc); + put_device(&qtee_service->dev); + return rc; + } + + return 0; +} + +/** + * qtee_register_services() - Enumerate all the secure services exposed by QTEE + * from the static 'qtee_services' list and register them on the TEE bus as + * TEE client devices. + * + * Not all versions of QTEE support a given service. Hence, we try to + * enumerate as many services from the 'qtee_services' list as possible. + * Not being able to enumerate a service shouldn't cause the driver probe + * to fail since none of the services in the list are mandatory for + * establishing communication with QTEE. + * @ctx: TEE context. + */ +static void qtee_register_services(struct tee_context *ctx) +{ + u32 idx; + struct qcomtee_object *client_env; + + struct qcomtee_object_invoke_ctx *oic __free(kfree) = + qcomtee_object_invoke_ctx_alloc(ctx, true); + if (!oic) + return; + + client_env = qcomtee_object_get_client_env(oic); + if (client_env == NULL_QCOMTEE_OBJECT) + return; + + for (idx = 0; idx < ARRAY_SIZE(qtee_services); idx++) + qtee_register_service(oic, client_env, + qtee_services[idx].name, + qtee_services[idx].uid); + + qcomtee_object_put(client_env); +} + +static int qtee_unregister_service(struct device *dev, void *data) +{ + if (!strncmp(dev_name(dev), "qtee-svc", strlen("qtee-svc"))) + device_unregister(dev); + + return 0; +} + +static void qtee_unregister_services(void) +{ + bus_for_each_dev(&tee_bus_type, NULL, NULL, + qtee_unregister_service); +} + static const struct tee_driver_ops qcomtee_ops = { .get_version = qcomtee_get_version, .open = qcomtee_open, @@ -779,6 +933,8 @@ static int qcomtee_probe(struct platform_device *pdev) QTEE_VERSION_GET_MINOR(qcomtee->qtee_version), QTEE_VERSION_GET_PATCH(qcomtee->qtee_version)); + qtee_register_services(qcomtee->ctx); + return 0; err_dest_wq: @@ -808,6 +964,7 @@ static void qcomtee_remove(struct platform_device *pdev) { struct qcomtee *qcomtee = platform_get_drvdata(pdev); + qtee_unregister_services(); teedev_close_context(qcomtee->ctx); /* Wait for RELEASE operations to be processed for QTEE objects. */ tee_device_unregister(qcomtee->teedev); diff --git a/drivers/tee/qcomtee/core.c b/drivers/tee/qcomtee/core.c index 60fe3b5776e36..4a523a95bf0e3 100644 --- a/drivers/tee/qcomtee/core.c +++ b/drivers/tee/qcomtee/core.c @@ -898,19 +898,20 @@ qcomtee_object_get_client_env(struct qcomtee_object_invoke_ctx *oic) struct qcomtee_object * qcomtee_object_get_service(struct qcomtee_object_invoke_ctx *oic, - struct qcomtee_object *client_env, u32 uid) + struct qcomtee_object *client_env, u32 uid, + int *result) { struct qcomtee_arg u[3] = { 0 }; - int ret, result; + int ret; u[0].b.addr = &uid; u[0].b.size = sizeof(uid); u[0].type = QCOMTEE_ARG_TYPE_IB; u[1].type = QCOMTEE_ARG_TYPE_OO; ret = qcomtee_object_do_invoke(oic, client_env, QCOMTEE_CLIENT_ENV_OPEN, - u, &result); + u, result); - if (ret || result) + if (ret || *result) return NULL_QCOMTEE_OBJECT; return u[1].o; diff --git a/drivers/tee/qcomtee/qcomtee.h b/drivers/tee/qcomtee/qcomtee.h index f39bf63fd1c2b..66d305a46c0a9 100644 --- a/drivers/tee/qcomtee/qcomtee.h +++ b/drivers/tee/qcomtee/qcomtee.h @@ -17,6 +17,8 @@ #define QCOMTEE_OBJREF_FLAG_USER BIT(1) #define QCOMTEE_OBJREF_FLAG_MEM BIT(2) +#define QTEE_UUID_NS_NAME_SIZE 128 + /** * struct qcomtee - Main service struct. * @teedev: client device. @@ -39,6 +41,16 @@ struct qcomtee { u32 qtee_version; }; +/** + * struct qtee_service - A secure service exposed by QTEE identified by a 32-bit UID. + * @name: Name of the QTEE service. + * @uid: 32-bit UID used by QTEE to identify the service. + */ +struct qtee_service { + const char *name; + const u32 uid; +}; + void qcomtee_fetch_async_reqs(struct qcomtee_object_invoke_ctx *oic); struct qcomtee_object *qcomtee_idx_erase(struct qcomtee_object_invoke_ctx *oic, u32 idx); diff --git a/drivers/tee/qcomtee/qcomtee_msg.h b/drivers/tee/qcomtee/qcomtee_msg.h index 5d7b21fdd3688..9278a361dc70c 100644 --- a/drivers/tee/qcomtee/qcomtee_msg.h +++ b/drivers/tee/qcomtee/qcomtee_msg.h @@ -105,6 +105,7 @@ union qcomtee_msg_arg { #define QTEE_VERSION_GET_MINOR(x) (((x) >> 12) & 0xffU) #define QTEE_VERSION_GET_PATCH(x) ((x) >> 0 & 0xfffU) +#define QCOMTEE_UEFI_SEC_UID 413 /* Response types as returned from qcomtee_object_invoke_ctx_invoke(). */ /* The message contains a callback request. */ diff --git a/drivers/tee/qcomtee/qcomtee_object.h b/drivers/tee/qcomtee/qcomtee_object.h index d3740099fae06..901ba3565a738 100644 --- a/drivers/tee/qcomtee/qcomtee_object.h +++ b/drivers/tee/qcomtee/qcomtee_object.h @@ -317,6 +317,7 @@ qcomtee_object_get_client_env(struct qcomtee_object_invoke_ctx *oic); struct qcomtee_object * qcomtee_object_get_service(struct qcomtee_object_invoke_ctx *oic, - struct qcomtee_object *client_env, u32 uid); + struct qcomtee_object *client_env, u32 uid, + int *result); #endif /* QCOMTEE_OBJECT_H */ From c0c15f90ca1a61c18c187e7db552fe9b80724908 Mon Sep 17 00:00:00 2001 From: Harshal Dev Date: Tue, 6 Oct 2026 17:03:27 +0530 Subject: [PATCH 0873/1133] FROMLIST: firmware: qcom: Add support for TEE based EFI-var client driver On Qualcomm SoC based platforms, UEFI stores EFI variables within the Replay Protected Memory Block (RPMB) located within either the UFS, eMMC or SPI-NOR storage. The RPMB key which is one-time programmed into the storage controller to allow authentication of the RPMB frames is generated by and only available to the Qualcomm Trusted Execution Environment (QTEE). The legacy QSEECOM protocol used for communicating with the QTEE is deprecated and replaced with the use-case agnostic SMCInvoke protocol starting with the Qualcomm SM8x50 series. On platforms where the QSEECOM driver still probes, it does not support a listener interface with QTEE to enable writing of non-volatile EFI variables to the RPMB for UFS and eMMC storage. Therefore on such platforms, a TEE client driver which communicates with QTEE via the SMCInvoke protocol implemented by the QCOMTEE driver (and registered with the TEE subsystem) must be used to update such EFI variables. Add support for a TEE based uefisecapp client driver which installs efivar operations after obtaining an object reference to the uefisecapp service. This enables the kernel/user-space to access or modify both volatile EFI variables stored by the Secure Application (in-memory) and non-volatile ones stored within RPMB. Link: https://lore.kernel.org/lkml/20261006-qcom_uefisecapp_migrate_qcomtee-v4-6-bf1c8e2a64ab@oss.qualcomm.com/ Signed-off-by: Harshal Dev --- MAINTAINERS | 6 + drivers/firmware/qcom/Kconfig | 31 + drivers/firmware/qcom/Makefile | 1 + drivers/firmware/qcom/qcom_tee_uefisecapp.c | 648 ++++++++++++++++++++ 4 files changed, 686 insertions(+) create mode 100644 drivers/firmware/qcom/qcom_tee_uefisecapp.c diff --git a/MAINTAINERS b/MAINTAINERS index 93abbb315065d..c6fc50ff2c863 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23142,6 +23142,12 @@ L: linux-arm-msm@vger.kernel.org S: Maintained F: drivers/firmware/qcom/qcom_qseecom_uefisecapp.c +QUALCOMM TEE UEFISECAPP DRIVER +M: Harshal Dev +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: drivers/firmware/qcom/qcom_tee_uefisecapp.c + QUALCOMM PINCTRL DRIVERS M: Bartosz Golaszewski L: linux-arm-msm@vger.kernel.org diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index 3ad22f8fc3e5f..694d98fef4f47 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -79,4 +79,35 @@ config QCOM_QSEECOM_UEFISECAPP Select Y here to provide access to EFI variables on the aforementioned platforms. +config QCOM_TEE_UEFISECAPP + tristate "Qualcomm TEE UEFI Secure App client driver" + depends on QCOMTEE + depends on EFI + help + The QSEECOM protocol used for communicating with the Qualcomm Trusted + Execution Environment (QTEE) is deprecated and replaced with the SMCInvoke + protocol starting with the Qualcomm SM8x50 series. On platforms where the + QSEECOM protocol still works (the QSEECOM driver probes) the driver does + not support a listener interface with QTEE to enable writing of + non-volatile EFI variables (via listener requests to Linux) in the Replay + Protected Memory Block (RPMB) located on UFS/eMMC storage. + Therefore on such platforms, the TEE based uefisecapp client driver + (which communicates with QTEE via the SMCInvoke protocol) must be used + to update such EFI variables through the RPMB service hosted in the QTEE + supplicant user-space daemon (github.com/qualcomm/minkipc) which forwards + RPMB packets to the RPMB device. + NOTE: Qualcomm Compute platforms with SPI-NOR storage are an exception to + this scenario. Since they do not have a firmware running on their SPI-NOR + storage controller which must be programmed with a RPMB key, QTEE has a + SPI-NOR driver which holds the key, and so the QSEECOM driver can be used + for updating EFI variables on these platforms because QTEE never makes a + listener request to Linux (QTEE doesn't need the Linux SPI-NOR driver). + + This module provides a TEE client driver for uefisecapp, installing efivar + operations to allow the kernel and user-space access to EFI variables. + + Select m here to provide access to EFI variables on the aforementioned + platforms if your Linux distribution has QTEE supplicant installed and + running. + endmenu diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile index 88ce74d74c3e2..237192b74de3b 100644 --- a/drivers/firmware/qcom/Makefile +++ b/drivers/firmware/qcom/Makefile @@ -9,5 +9,6 @@ CFLAGS_qcom_scm-smc.o := -I$(src) obj-$(CONFIG_QCOM_TZMEM) += qcom_tzmem.o obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o +obj-$(CONFIG_QCOM_TEE_UEFISECAPP) += qcom_tee_uefisecapp.o obj-$(CONFIG_QCOM_PAS) += qcom_pas.o obj-$(CONFIG_QCOM_PAS_TEE) += qcom_pas_tee.o diff --git a/drivers/firmware/qcom/qcom_tee_uefisecapp.c b/drivers/firmware/qcom/qcom_tee_uefisecapp.c new file mode 100644 index 0000000000000..acb1709c0a53f --- /dev/null +++ b/drivers/firmware/qcom/qcom_tee_uefisecapp.c @@ -0,0 +1,648 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include + +#define QCOMTEE_OP_CLIENT_ENV_OPEN 0 +#define QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS 5 + +/* Each service exposed by QTEE is identified by a 32-bit UID */ +#define QCOMTEE_UEFI_SEC_UID 413 + +/* Operations supported by the UEFI Sec App service */ +#define QCOMTEE_UEFI_SEC_OP_GET_VAR 0 +#define QCOMTEE_UEFI_SEC_OP_SET_VAR 1 +#define QCOMTEE_UEFI_SEC_OP_QUERY_VAR_INFO 2 +#define QCOMTEE_UEFI_SEC_OP_GET_NEXT_VAR_NAME 3 + +#define QCOMTEE_GET_VAR_NPARAMS 5 +#define QCOMTEE_SET_VAR_NPARAMS 4 +#define QCOMTEE_QUERY_VAR_NPARAMS 2 +#define QCOMTEE_GET_NEXT_VAR_NPARAMS 4 +#define QCOMTEE_GET_UEFI_SVC_NPARAMS 2 +#define QCOMTEE_GET_CLIENT_ENV_NPARAMS 2 + +/* Error codes returned by the UEFI Sec App service */ +#define QCOMTEE_UEFI_SEC_SUCCESS 0 +#define QCOMTEE_UEFI_SEC_ERROR_INVALID_PARAMETER 10 +#define QCOMTEE_UEFI_SEC_ERROR_UNSUPPORTED 11 +#define QCOMTEE_UEFI_SEC_ERROR_WRITE_PROTECTED 12 +#define QCOMTEE_UEFI_SEC_ERROR_SECURITY_VIOLATION 13 +#define QCOMTEE_UEFI_SEC_ERROR_DEVICE_ERROR 14 +#define QCOMTEE_UEFI_SEC_ERROR_OUT_OF_RESOURCES 15 +#define QCOMTEE_UEFI_SEC_ERROR_VOLUME_CORRUPTED 16 +#define QCOMTEE_UEFI_SEC_ERROR_SIZE_OUT 17 +#define QCOMTEE_UEFI_SEC_ERROR_NOT_FOUND 18 +#define QCOMTEE_UEFI_SEC_ERROR_ALREADY_STARTED 19 + +/* Operations for objects are 32-bit. QCOMTEE transport uses the upper 16 bits. */ +#define QCOMTEE_MSG_OBJECT_OP_MASK GENMASK(15, 0) +#define QCOMTEE_MSG_OBJECT_OP_RELEASE (QCOMTEE_MSG_OBJECT_OP_MASK - 0) + +/** + * struct qcomtee_uefisec_app - An instance of UEFI Secure Application. + * @dev: TEE client device on the TEE bus which represents uefisecapp. + * @ctx: The context opened with the TEE subsystem by the uefisecapp client. + * @uefisec_svc_obj: A TEE object representing the uefisecapp service. + * @efivars: EFI variables registered with the EFI subsystem. + */ +struct qcomtee_uefisec_app { + struct device *dev; + struct tee_context *ctx; + struct tee_param_objref uefisec_svc_obj; + struct efivars efivars; +}; + +#define UEFISECAPP_UUID \ + UUID_INIT(0x01f95dcd, 0x2d7e, 0x58be, \ + 0xa1, 0x43, 0x81, 0x32, 0xa1, 0x72, 0xdb, 0x7d) + +/* Short-hands for these long attribute names */ +#define UBUF_INPUT TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT +#define UBUF_OUTPUT TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT +#define OBJREF_INPUT TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT +#define OBJREF_OUTPUT TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT + +/* Init instance of 'struct tee_param_objref'. */ +#define SET_TEE_PARAM_OBJREF(param, attri, obj_id, obj_flag) do { \ + (param).attr = (attri); \ + (param).u.objref.id = (obj_id); \ + (param).u.objref.flags = (obj_flag); \ + } while (0) + +/* Init instance of 'struct tee_param_ubuf'. */ +#define SET_TEE_PARAM_UBUF(param, attri, ubuff) do { \ + (param).attr = (attri); \ + (param).u.ubuf = (ubuff); \ + } while (0) + +#define TEE_PARAM_UBUF(x) ((struct tee_param_ubuf){ .addr = &(x), sizeof(x) }) + +#define SET_INVOKE_ARG(arg, object_id, opp, nparam) do { \ + (arg).id = (object_id); \ + (arg).op = (opp); \ + (arg).num_params = (nparam); \ + } while (0) + +static inline efi_status_t uefisecapp_err_to_efi_status(u32 err) +{ + switch (err) { + case QCOMTEE_UEFI_SEC_SUCCESS: + return EFI_SUCCESS; + + case QCOMTEE_UEFI_SEC_ERROR_INVALID_PARAMETER: + return EFI_INVALID_PARAMETER; + + case QCOMTEE_UEFI_SEC_ERROR_UNSUPPORTED: + return EFI_UNSUPPORTED; + + case QCOMTEE_UEFI_SEC_ERROR_WRITE_PROTECTED: + return EFI_WRITE_PROTECTED; + + case QCOMTEE_UEFI_SEC_ERROR_SECURITY_VIOLATION: + return EFI_SECURITY_VIOLATION; + + case QCOMTEE_UEFI_SEC_ERROR_DEVICE_ERROR: + return EFI_DEVICE_ERROR; + + case QCOMTEE_UEFI_SEC_ERROR_OUT_OF_RESOURCES: + return EFI_OUT_OF_RESOURCES; + + case QCOMTEE_UEFI_SEC_ERROR_SIZE_OUT: + return EFI_BUFFER_TOO_SMALL; + + case QCOMTEE_UEFI_SEC_ERROR_NOT_FOUND: + return EFI_NOT_FOUND; + + /* No matching on EFI_* list. */ + case QCOMTEE_UEFI_SEC_ERROR_ALREADY_STARTED: /* EFI_ALREADY_STARTED. */ + case QCOMTEE_UEFI_SEC_ERROR_VOLUME_CORRUPTED: /* EFI_VOLUME_CORRUPTED. */ + default: + return EFI_DEVICE_ERROR; + } +} + +static struct qcomtee_uefisec_app uefisec_app; + +static int qcuefi_get_variable(struct tee_param_ubuf in_variable, efi_guid_t *guid, + struct tee_param_ubuf in_attributes, + struct tee_param_ubuf *data, + u32 *out_attributes, u32 *out_errno) +{ + int ret; + struct tee_ioctl_object_invoke_arg inv_arg; + u64 obj_id = uefisec_app.uefisec_svc_obj.id; + struct tee_param param[QCOMTEE_GET_VAR_NPARAMS]; + + struct { + efi_guid_t guid; + u32 in_data_size; + } in_cong = { 0 }; + + struct { + u32 out_data_size; + u32 attributes; + u32 errno; + } out_cong = { 0 }; + + in_cong.guid = *guid; + in_cong.in_data_size = data->size; + + memset(&inv_arg, 0, sizeof(inv_arg)); + memset(¶m, 0, sizeof(param)); + + SET_INVOKE_ARG(inv_arg, obj_id, + QCOMTEE_UEFI_SEC_OP_GET_VAR, + QCOMTEE_GET_VAR_NPARAMS); + SET_TEE_PARAM_UBUF(param[0], UBUF_INPUT, TEE_PARAM_UBUF(in_cong)); + SET_TEE_PARAM_UBUF(param[1], UBUF_INPUT, in_variable); + SET_TEE_PARAM_UBUF(param[2], UBUF_INPUT, in_attributes); + SET_TEE_PARAM_UBUF(param[3], UBUF_OUTPUT, TEE_PARAM_UBUF(out_cong)); + SET_TEE_PARAM_UBUF(param[4], UBUF_OUTPUT, *data); + + ret = tee_client_object_invoke_func(uefisec_app.ctx, &inv_arg, param); + if (ret < 0 || inv_arg.ret != 0) { + dev_err(uefisec_app.dev, "QCOMTEE_UEFI_SEC_OP_GET_VAR invoke ret: %d, err: 0x%x\n", + ret, inv_arg.ret); + return ret ?: inv_arg.ret; + } + + data->size = out_cong.out_data_size; + *out_attributes = out_cong.attributes; + *out_errno = out_cong.errno; + + return ret; +} + +static efi_status_t qcomtee_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid, + u32 *attr, unsigned long *data_size, + void *data) +{ + int ret; + u32 in_attr, out_attributes, out_errno; + struct tee_param_ubuf in_data, in_var, in_attributes; + + if (!name || !guid) + return EFI_INVALID_PARAMETER; + + /* 'attr' can be NULL, however an input attribute is always expected + * by UefiSecApp TA + */ + in_attr = 0; + if (attr) + in_attr = *attr; + + in_data = (struct tee_param_ubuf){ .addr = data, *data_size }; + in_var = (struct tee_param_ubuf){ .addr = name, + (ucs2_strlen(name) + 1) * sizeof(*name) }; + in_attributes = (struct tee_param_ubuf){ .addr = &in_attr, sizeof(u32) }; + + /* On SUCCESS, 'data' member of 'in_data' has already been updated. */ + ret = qcuefi_get_variable(in_var, guid, in_attributes, &in_data, + &out_attributes, &out_errno); + + if (ret) + return EFI_DEVICE_ERROR; + + if (!out_errno || out_errno == QCOMTEE_UEFI_SEC_ERROR_SIZE_OUT) { + /* If 'attr' is NULL 'out_attributes' is not updated. */ + if (attr) + *attr = out_attributes; + + *data_size = in_data.size; + } + + return uefisecapp_err_to_efi_status(out_errno); +} + +static int qcuefi_set_variable(struct tee_param_ubuf in_variable, efi_guid_t *guid, + u32 attributes, struct tee_param_ubuf data, + u32 *out_errno) +{ + int ret; + struct tee_ioctl_object_invoke_arg inv_arg; + u64 obj_id = uefisec_app.uefisec_svc_obj.id; + struct tee_param param[QCOMTEE_SET_VAR_NPARAMS]; + + struct { + efi_guid_t guid; + u32 attributes; + u32 in_data_size; + } in_cong = { 0 }; + + in_cong.guid = *guid; + in_cong.attributes = attributes; + in_cong.in_data_size = data.size; + + memset(&inv_arg, 0, sizeof(inv_arg)); + memset(¶m, 0, sizeof(param)); + + SET_INVOKE_ARG(inv_arg, obj_id, + QCOMTEE_UEFI_SEC_OP_SET_VAR, + QCOMTEE_SET_VAR_NPARAMS); + SET_TEE_PARAM_UBUF(param[0], UBUF_INPUT, TEE_PARAM_UBUF(in_cong)); + SET_TEE_PARAM_UBUF(param[1], UBUF_INPUT, in_variable); + SET_TEE_PARAM_UBUF(param[2], UBUF_INPUT, data); + SET_TEE_PARAM_UBUF(param[3], UBUF_OUTPUT, TEE_PARAM_UBUF(*out_errno)); + + ret = tee_client_object_invoke_func(uefisec_app.ctx, &inv_arg, param); + if (ret < 0 || inv_arg.ret != 0) { + dev_err(uefisec_app.dev, "QCOMTEE_UEFI_SEC_OP_SET_VAR invoke ret: %d, err: 0x%x\n", + ret, inv_arg.ret); + return ret ?: inv_arg.ret; + } + + return ret; +} + +static efi_status_t qcomtee_uefi_set_variable(efi_char16_t *name, efi_guid_t *guid, + u32 attr, unsigned long data_size, + void *data) +{ + int ret; + u32 out_errno; + struct tee_param_ubuf in_data, in_var; + + if (!name || !guid) + return EFI_INVALID_PARAMETER; + + in_data = (struct tee_param_ubuf){ .addr = data, data_size }; + in_var = (struct tee_param_ubuf){ .addr = name, + (ucs2_strlen(name) + 1) * sizeof(*name) }; + + ret = qcuefi_set_variable(in_var, guid, attr, in_data, &out_errno); + if (ret) + return EFI_DEVICE_ERROR; + + return uefisecapp_err_to_efi_status(out_errno); +} + +static int qcuefi_get_next_variable(struct tee_param_ubuf in_variable, efi_guid_t *guid, + struct tee_param_ubuf *out_variable, + efi_guid_t *out_vendor_guid, u32 *out_errno) +{ + int ret; + struct tee_ioctl_object_invoke_arg inv_arg; + u64 obj_id = uefisec_app.uefisec_svc_obj.id; + struct tee_param param[QCOMTEE_GET_NEXT_VAR_NPARAMS]; + + struct { + efi_guid_t guid; + u32 in_data_size; + } in_cong = { 0 }; + + struct { + efi_guid_t guid; + u32 out_data_size; + u32 errno; + } out_cong = { 0 }; + + /* Pass size of available buffer */ + in_cong.in_data_size = out_variable->size; + in_cong.guid = *guid; + + memset(&inv_arg, 0, sizeof(inv_arg)); + memset(¶m, 0, sizeof(param)); + + SET_INVOKE_ARG(inv_arg, obj_id, + QCOMTEE_UEFI_SEC_OP_GET_NEXT_VAR_NAME, + QCOMTEE_GET_NEXT_VAR_NPARAMS); + SET_TEE_PARAM_UBUF(param[0], UBUF_INPUT, TEE_PARAM_UBUF(in_cong)); + SET_TEE_PARAM_UBUF(param[1], UBUF_INPUT, in_variable); + SET_TEE_PARAM_UBUF(param[2], UBUF_OUTPUT, TEE_PARAM_UBUF(out_cong)); + SET_TEE_PARAM_UBUF(param[3], UBUF_OUTPUT, *out_variable); + + ret = tee_client_object_invoke_func(uefisec_app.ctx, &inv_arg, param); + if (ret < 0 || inv_arg.ret != 0) { + dev_err(uefisec_app.dev, "QCOMTEE_UEFI_SEC_OP_GET_NEXT_VAR_NAME invoke ret: %d, err: 0x%x\n", + ret, inv_arg.ret); + return ret ?: inv_arg.ret; + } + + /* UefiSecApp TA does not touch 'out_variable.size'. Update it here. + * On SUCCESS (!out_errno), 'out_data_size' is length of name in 'out_variable.addr'. + * On failure (out_errno == QCOMTEE_UEFI_SEC_ERROR_SIZE_OUT), 'out_data_size' is + * actual name length. + * Otherwise, it's undefined. + */ + out_variable->size = out_cong.out_data_size; + *out_vendor_guid = out_cong.guid; + *out_errno = out_cong.errno; + + return ret; +} + +static efi_status_t qcomtee_uefi_get_next_variable(unsigned long *name_size, + efi_char16_t *name, + efi_guid_t *guid) +{ + int ret; + u32 out_errno; + efi_guid_t out_guid; + struct tee_param_ubuf in_var, out_var; + + if (!name_size || !name || !guid) + return EFI_INVALID_PARAMETER; + + if (*name_size == 0) + return EFI_INVALID_PARAMETER; + + /* For 'in_var', 'name_size' is not necessarily size of 'name'; + * could be size of buffer where 'name' has been stored. TA expects a + * NULL-terminated string in 'name' and ignores the size. + * For 'out_var', 'name_size' is size of buffer pointed by 'name'. + */ + in_var = (struct tee_param_ubuf){ .addr = name, *name_size }; + out_var = (struct tee_param_ubuf){ .addr = name, *name_size }; + + ret = qcuefi_get_next_variable(in_var, guid, &out_var, &out_guid, + &out_errno); + if (ret) + return EFI_DEVICE_ERROR; + + if (!out_errno) + *guid = out_guid; + + if (!out_errno || out_errno == QCOMTEE_UEFI_SEC_ERROR_SIZE_OUT) + *name_size = out_var.size; + + /* On SUCCESS, 'name' stores the next variable name. */ + return uefisecapp_err_to_efi_status(out_errno); +} + +static int qcuefi_query_variable_info(u32 attributes, + u64 *maximum_variable_storage_size, + u64 *remaining_variable_storage_size, + u64 *maximum_variable_size, u32 *out_errno) +{ + int ret; + struct tee_ioctl_object_invoke_arg inv_arg; + u64 obj_id = uefisec_app.uefisec_svc_obj.id; + struct tee_param param[QCOMTEE_QUERY_VAR_NPARAMS]; + + struct { + u64 max_var_storage_size; + u64 remaining_var_storage_size; + u64 maximum_var_size; + u32 errno; + } out_cong = { 0 }; + + memset(&inv_arg, 0, sizeof(inv_arg)); + memset(¶m, 0, sizeof(param)); + + SET_INVOKE_ARG(inv_arg, obj_id, + QCOMTEE_UEFI_SEC_OP_QUERY_VAR_INFO, + QCOMTEE_QUERY_VAR_NPARAMS); + SET_TEE_PARAM_UBUF(param[0], UBUF_INPUT, TEE_PARAM_UBUF(attributes)); + SET_TEE_PARAM_UBUF(param[1], UBUF_OUTPUT, TEE_PARAM_UBUF(out_cong)); + + ret = tee_client_object_invoke_func(uefisec_app.ctx, &inv_arg, param); + if (ret < 0 || inv_arg.ret != 0) { + dev_err(uefisec_app.dev, "QCOMTEE_UEFI_SEC_OP_QUERY_VAR_INFO invoke ret: %d, err: 0x%x\n", + ret, inv_arg.ret); + return ret ?: inv_arg.ret; + } + + *maximum_variable_storage_size = out_cong.max_var_storage_size; + *remaining_variable_storage_size = out_cong.remaining_var_storage_size; + *maximum_variable_size = out_cong.maximum_var_size; + *out_errno = out_cong.errno; + + return ret; +} + +static efi_status_t qcomtee_uefi_query_variable_info(u32 attr, u64 *storage_space, + u64 *remaining_space, + u64 *max_variable_size) +{ + int ret; + u32 out_errno; + u64 maximum_variable_storage_size; + u64 remaining_variable_storage_size; + u64 maximum_variable_size; + + if (!storage_space || !remaining_space || !max_variable_size) + return EFI_INVALID_PARAMETER; + + ret = qcuefi_query_variable_info(attr, + &maximum_variable_storage_size, + &remaining_variable_storage_size, + &maximum_variable_size, + &out_errno); + + if (ret) + return EFI_DEVICE_ERROR; + + if (!out_errno) { + *storage_space = maximum_variable_storage_size; + *remaining_space = remaining_variable_storage_size; + *max_variable_size = maximum_variable_size; + } + + return uefisecapp_err_to_efi_status(out_errno); +} + +/** + * qcomtee_release_object() - Release an object returned by QTEE. + * + * Each object returned by QTEE repesents a secure service exposed to the + * client. Whenever an secure service is opened, QTEE may allocate resources + * on the client's behalf. Therefore, once the client is done accessing the + * secure service, the object representing it should be explicitly released + * so that QTEE can release the associated resources as well. + * + * @ctx: TEE context. + * @object: The object to release. + */ +static void qcomtee_release_object(struct tee_context *ctx, + struct tee_param_objref object) +{ + struct tee_ioctl_object_invoke_arg inv_arg; + + memset(&inv_arg, 0, sizeof(inv_arg)); + SET_INVOKE_ARG(inv_arg, object.id, QCOMTEE_MSG_OBJECT_OP_RELEASE, 0); + tee_client_object_invoke_func(ctx, &inv_arg, NULL); +} + +/** + * qcomtee_get_uefisec_svc_obj() - Get a UEFI Secure App service object to + * begin communication with the service. + * @ctx: TEE context. + * @client_env_obj: The client environment object returned earlier by QTEE. + * @uefisec_svc_obj: The UEFI Secure App service object. + * + * Returns 0 on success. + * Returns < 0 if client environment object invocation failed. + * Returns > 0 if client environment invocation was success but UEFI Secure App + * service object could not be returned for some other reason (represented by the + * returned value) + */ +static int qcomtee_get_uefisec_svc_obj(struct tee_context *ctx, + struct tee_param_objref client_env_obj, + struct tee_param_objref *uefisec_svc_obj) +{ + int ret; + struct tee_ioctl_object_invoke_arg inv_arg; + u64 obj_id = client_env_obj.id; + struct tee_param param[QCOMTEE_GET_UEFI_SVC_NPARAMS]; + u32 uefisec_uid = QCOMTEE_UEFI_SEC_UID; + + memset(&inv_arg, 0, sizeof(inv_arg)); + memset(¶m, 0, sizeof(param)); + + SET_INVOKE_ARG(inv_arg, obj_id, + QCOMTEE_OP_CLIENT_ENV_OPEN, + QCOMTEE_GET_UEFI_SVC_NPARAMS); + SET_TEE_PARAM_UBUF(param[0], UBUF_INPUT, TEE_PARAM_UBUF(uefisec_uid)); + SET_TEE_PARAM_OBJREF(param[1], OBJREF_OUTPUT, 0, 0); + + ret = tee_client_object_invoke_func(ctx, &inv_arg, param); + if (ret < 0 || inv_arg.ret != 0) { + dev_err(uefisec_app.dev, "QCOMTEE_CLIENT_ENV_OPEN invoke ret: %d, err: 0x%x\n", + ret, inv_arg.ret); + return ret ?: inv_arg.ret; + } + + *uefisec_svc_obj = param[1].u.objref; + return ret; +} + +/** + * qcomtee_get_client_env_obj() - Get a client environment object to begin + * object exchange with QTEE. + * @ctx: TEE context. + * @client_env_obj: The client environment object returned by QTEE. + * + * Returns 0 on success. + * Returns < 0 if root object invocation failed. + * Returns > 0 if root object invocation was success but client environment + * object could not be returned for some other reason (represented by the + * returned value) + */ +static int qcomtee_get_client_env_obj(struct tee_context *ctx, + struct tee_param_objref *client_env_obj) +{ + int ret; + struct tee_ioctl_object_invoke_arg inv_arg; + struct tee_param param[QCOMTEE_GET_CLIENT_ENV_NPARAMS]; + + memset(&inv_arg, 0, sizeof(inv_arg)); + memset(¶m, 0, sizeof(param)); + + SET_INVOKE_ARG(inv_arg, TEE_OBJREF_NULL, + QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS, + QCOMTEE_GET_CLIENT_ENV_NPARAMS); + SET_TEE_PARAM_OBJREF(param[0], OBJREF_INPUT, TEE_OBJREF_NULL, 0); + SET_TEE_PARAM_OBJREF(param[1], OBJREF_OUTPUT, 0, 0); + + ret = tee_client_object_invoke_func(ctx, &inv_arg, param); + if (ret < 0 || inv_arg.ret != 0) { + dev_err(uefisec_app.dev, "QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS invoke ret: %d, err: 0x%x\n", + ret, inv_arg.ret); + return ret ?: inv_arg.ret; + } + + *client_env_obj = param[1].u.objref; + return ret; +} + +static const struct efivar_operations qcom_efivar_ops = { + .get_variable = qcomtee_uefi_get_variable, + .set_variable = qcomtee_uefi_set_variable, + .get_next_variable = qcomtee_uefi_get_next_variable, + .query_variable_info = qcomtee_uefi_query_variable_info, +}; + +static int qcomtee_ctx_match(struct tee_ioctl_version_data *ver, + const void *data) +{ + return (ver->impl_id == TEE_IMPL_ID_QTEE); +} + +static int qcomtee_uefisecapp_probe(struct tee_client_device *tee_dev) +{ + int ret, err; + struct tee_param_objref client_env_obj; + struct tee_param_objref uefisec_svc_obj; + + uefisec_app.dev = &tee_dev->dev; + /* Open context with QCOMTEE driver */ + uefisec_app.ctx = tee_client_open_context(NULL, qcomtee_ctx_match, NULL, + NULL); + if (IS_ERR(uefisec_app.ctx)) + return -ENODEV; + + /* Obtain a reference to client_env object to begin object exchange + * with QTEE + */ + ret = qcomtee_get_client_env_obj(uefisec_app.ctx, &client_env_obj); + if (ret) { + err = -EINVAL; + goto err_get_client_env; + } + + /* Obtain a reference to the uefisec_svc object which provides access to + * the EFI var storage. + */ + ret = qcomtee_get_uefisec_svc_obj(uefisec_app.ctx, client_env_obj, + &uefisec_svc_obj); + if (ret) { + err = -EINVAL; + goto err_get_uefisec_svc; + } + uefisec_app.uefisec_svc_obj = uefisec_svc_obj; + + ret = efivars_register(&uefisec_app.efivars, &qcom_efivar_ops); + if (ret) { + err = ret; + goto err_efi_vars_reg; + } + + /* We don't need to keep a reference to this object anymore, we only + * needed it to obtain the uefisec_svc object. + */ + qcomtee_release_object(uefisec_app.ctx, client_env_obj); + return 0; + +err_efi_vars_reg: + qcomtee_release_object(uefisec_app.ctx, uefisec_svc_obj); +err_get_uefisec_svc: + qcomtee_release_object(uefisec_app.ctx, client_env_obj); +err_get_client_env: + tee_client_close_context(uefisec_app.ctx); + + return err; +} + +static void qcomtee_uefisecapp_remove(struct tee_client_device *tee_dev) +{ + efivars_unregister(&uefisec_app.efivars); + qcomtee_release_object(uefisec_app.ctx, uefisec_app.uefisec_svc_obj); + tee_client_close_context(uefisec_app.ctx); +} + +static const struct tee_client_device_id qcomtee_uefisecapp_id_table[] = { + {UEFISECAPP_UUID}, + {} +}; +MODULE_DEVICE_TABLE(tee, qcomtee_uefisecapp_id_table); + +static struct tee_client_driver qcomtee_uefisecapp_driver = { + .id_table = qcomtee_uefisecapp_id_table, + .probe = qcomtee_uefisecapp_probe, + .remove = qcomtee_uefisecapp_remove, + .driver = { + .name = "qcom-tee-uefisecapp", + }, +}; + +module_tee_client_driver(qcomtee_uefisecapp_driver); + +MODULE_AUTHOR("Qualcomm"); +MODULE_DESCRIPTION("TEE client driver for Qualcomm TEE UEFI Secure App"); +MODULE_LICENSE("GPL"); From ca47c24ff8ffec5b13206b7ba0e820d83e720072 Mon Sep 17 00:00:00 2001 From: Harshal Dev Date: Tue, 6 Oct 2026 17:03:28 +0530 Subject: [PATCH 0874/1133] FROMLIST: arm64: defconfig: Enable UefiSecApp TEE client driver for Qualcomm SoCs All Qualcomm SoCs starting from SM8x50 provide access to the Qualcomm Trusted Execution Environment (QTEE) through the SMCInvoke interface implemented by the QCOM-TEE driver. QTEE runs in the Secure World domain on ARM64 CPUs and exposes secure services to Linux running in the Normal World domain. This change enables the UefiSecApp TEE client driver as a module to provide access to UEFI variables on Qualcomm SoCs via the uefisecapp Trusted Application running in QTEE. The TEE client driver communicates with QTEE via the QCOM-TEE driver. Access to UEFI variables has been tested on a Qualcomm RB3Gen2 board via the efivar tool. Link: https://lore.kernel.org/lkml/20261006-qcom_uefisecapp_migrate_qcomtee-v4-7-bf1c8e2a64ab@oss.qualcomm.com/ Signed-off-by: Harshal Dev --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7b4985b29b21c..be80cc1741580 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -277,6 +277,7 @@ CONFIG_IMX_SCU=y CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE=y CONFIG_QCOM_QSEECOM=y CONFIG_QCOM_QSEECOM_UEFISECAPP=y +CONFIG_QCOM_TEE_UEFISECAPP=m CONFIG_EXYNOS_ACPM_PROTOCOL=m CONFIG_TEGRA_BPMP=y CONFIG_ZYNQMP_FIRMWARE_DEBUG=y From 94352c3383a9750f04ac382013c007f168275025 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Mon, 7 Sep 2026 14:58:41 +0530 Subject: [PATCH 0875/1133] FROMLIST: tee: qcomtee: Register qcom.tz.tpm service for discovery Add "qcom.tz.tpm" (QCOMTEE_TPM_UID) to qtee_services[] so the TPM TA is enumerated as a TEE-bus device, allowing a client driver to bind to it via its generated UUID. Signed-off-by: Kuldeep Singh Link: https://lore.kernel.org/lkml/20260907-tpm_qcom_driver-v2-1-71a6b1752da8@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- drivers/tee/qcomtee/call.c | 4 +++- drivers/tee/qcomtee/qcomtee_msg.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c index 3061bcbd15ab9..d4d6f72eb71b7 100644 --- a/drivers/tee/qcomtee/call.c +++ b/drivers/tee/qcomtee/call.c @@ -747,7 +747,9 @@ static const uuid_t qtee_service_uuid_ns = UUID_INIT(0xe1b48857, 0x6154, 0x49f9, static const struct qtee_service qtee_services[] = { { "qcom.tz.uefisecapp", - QCOMTEE_UEFI_SEC_UID } + QCOMTEE_UEFI_SEC_UID }, + { "qcom.tz.tpm", + QCOMTEE_TPM_UID } }; static void qtee_release_service(struct device *dev) diff --git a/drivers/tee/qcomtee/qcomtee_msg.h b/drivers/tee/qcomtee/qcomtee_msg.h index 9278a361dc70c..9fff9dc5fffb2 100644 --- a/drivers/tee/qcomtee/qcomtee_msg.h +++ b/drivers/tee/qcomtee/qcomtee_msg.h @@ -106,6 +106,8 @@ union qcomtee_msg_arg { #define QTEE_VERSION_GET_PATCH(x) ((x) >> 0 & 0xfffU) #define QCOMTEE_UEFI_SEC_UID 413 +#define QCOMTEE_TPM_UID 81 + /* Response types as returned from qcomtee_object_invoke_ctx_invoke(). */ /* The message contains a callback request. */ From 770270755a5a93d6bfdcfcec1c8ef87069ac498b Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Mon, 7 Sep 2026 14:58:42 +0530 Subject: [PATCH 0876/1133] FROMLIST: tpm: Introduce Qualcomm TPM driver Add a TPM chip driver for platforms where a TPM 2.0 instance is implemented by a Trusted Application (TA) running in Qualcomm's Trusted Execution Environment (QTEE), reachable over the QCOMTEE object-IPC transport. The driver discovers the qcom.tz.tpm TEE-bus device, opens a session with the TPM TA, and register with tpm interface. This exposes the TA through the standard /dev/tpm interface and the existing tpm2 command layer. OS need not be aware underlying TPM instance is dTPM or fTPM. Signed-off-by: Kuldeep Singh Link: https://lore.kernel.org/lkml/20260907-tpm_qcom_driver-v2-2-71a6b1752da8@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- drivers/char/tpm/Kconfig | 9 + drivers/char/tpm/Makefile | 1 + drivers/char/tpm/tpm_qcom.c | 354 ++++++++++++++++++++++++++++++++++++ drivers/char/tpm/tpm_qcom.h | 83 +++++++++ 4 files changed, 447 insertions(+) create mode 100644 drivers/char/tpm/tpm_qcom.c create mode 100644 drivers/char/tpm/tpm_qcom.h diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 5f672f2c01b04..05d704ed3632f 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -243,6 +243,15 @@ config TCG_FTPM_TEE help This driver proxies for firmware TPM running in TEE. +config TCG_QCOM + tristate "Qualcomm TEE based TPM Interface" + depends on QCOMTEE + help + This driver provides interface to run TPM instances with Trustzone + having Qualcomm TPM TA running in Qualcomm TEE. + The mechanism uses the object-IPC based transport provided by + QCOMTEE. + config TCG_SVSM tristate "SNP SVSM vTPM interface" depends on AMD_MEM_ENCRYPT diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 5b5cdc0d32e4e..471cbf49afd22 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -45,5 +45,6 @@ obj-$(CONFIG_TCG_CRB) += tpm_crb.o obj-$(CONFIG_TCG_ARM_CRB_FFA) += tpm_crb_ffa.o obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o obj-$(CONFIG_TCG_FTPM_TEE) += tpm_ftpm_tee.o +obj-$(CONFIG_TCG_QCOM) += tpm_qcom.o obj-$(CONFIG_TCG_SVSM) += tpm_svsm.o obj-$(CONFIG_TCG_LOONGSON) += tpm_loongson.o diff --git a/drivers/char/tpm/tpm_qcom.c b/drivers/char/tpm/tpm_qcom.c new file mode 100644 index 0000000000000..ef29c66f18aee --- /dev/null +++ b/drivers/char/tpm/tpm_qcom.c @@ -0,0 +1,354 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "tpm.h" +#include "tpm_qcom.h" + +/* UUID of the QTEE-bus device representing the TPM TA. */ +static const uuid_t tpm_qcom_uuid = + UUID_INIT(0xaabcb593, 0x7083, 0x5536, + 0xac, 0x27, 0x3d, 0x2d, 0x89, 0x41, 0x9d, 0xdb); + +static void tpm_qcom_release_object(struct tee_context *ctx, + struct tee_param_objref object) +{ + struct tee_ioctl_object_invoke_arg inv_arg = {}; + + inv_arg.id = object.id; + inv_arg.op = QCOMTEE_MSG_OBJECT_OP_RELEASE; + inv_arg.num_params = 0; + + tee_client_object_invoke_func(ctx, &inv_arg, NULL); +} + +static int tpm_qcom_get_client_env_obj(struct tee_context *ctx, + struct tee_param_objref *client_env_obj) +{ + struct tee_ioctl_object_invoke_arg inv_arg = {}; + struct tee_param param[2] = {}; + int ret; + + inv_arg.id = TEE_OBJREF_NULL; + inv_arg.op = QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS; + inv_arg.num_params = 2; + + param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT; + param[0].u.objref.id = TEE_OBJREF_NULL; + param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT; + + ret = tee_client_object_invoke_func(ctx, &inv_arg, param); + if (ret < 0 || inv_arg.ret != 0) + return ret ?: inv_arg.ret; + + *client_env_obj = param[1].u.objref; + return ret; +} + +static int tpm_qcom_get_svc_obj(struct tee_context *ctx, + struct tee_param_objref client_env_obj, + struct tee_param_objref *tpm_svc_obj) +{ + struct tee_ioctl_object_invoke_arg inv_arg = {}; + struct tee_param param[2] = {}; + u32 tpm_uid = QCOMTEE_TPM_UID; + int ret; + + inv_arg.id = client_env_obj.id; + inv_arg.op = QCOMTEE_OP_CLIENT_ENV_OPEN; + inv_arg.num_params = 2; + + param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT; + param[0].u.ubuf = (struct tee_param_ubuf){ .addr = &tpm_uid, + .size = sizeof(tpm_uid) }; + param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT; + + ret = tee_client_object_invoke_func(ctx, &inv_arg, param); + if (ret < 0 || inv_arg.ret != 0) + return ret ?: inv_arg.ret; + + *tpm_svc_obj = param[1].u.objref; + return ret; +} + +static int tpm_qcom_send_command(struct tpm_qcom_private *pvt_data, + u32 locality, void *req, size_t req_len, + void *rsp, size_t *rsp_len) +{ + struct tee_ioctl_object_invoke_arg inv_arg = {}; + struct tee_param param[3] = {}; + u8 locality_arg = locality; + int ret; + + inv_arg.id = pvt_data->tpm_svc_obj.id; + inv_arg.op = QCOMTEE_TPM_OP_SEND_COMMAND; + inv_arg.num_params = 3; + + param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT; + param[0].u.ubuf = (struct tee_param_ubuf){ .addr = &locality_arg, + .size = sizeof(locality_arg) }; + param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT; + param[1].u.ubuf = (struct tee_param_ubuf){ .addr = req, .size = req_len }; + param[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT; + param[2].u.ubuf = (struct tee_param_ubuf){ .addr = rsp, .size = *rsp_len }; + + ret = tee_client_object_invoke_func(pvt_data->ctx, &inv_arg, param); + if (ret < 0 || inv_arg.ret != 0) { + dev_err(pvt_data->dev, + "send_command invoke ret: %d, err: 0x%x\n", + ret, inv_arg.ret); + return ret ?: inv_arg.ret; + } + + *rsp_len = param[2].u.ubuf.size; + + return ret; +} + +static int tpm_qcom_get_ta_details(struct tpm_qcom_private *pvt_data) +{ + struct tpm_qcom_ta_version_req ver_req = { + .command_id = QCOMTEE_TPM_GET_TA_VERSION_ID, + }; + struct tpm_qcom_ta_version_rsp ver_rsp; + size_t ver_rsp_len = sizeof(ver_rsp); + struct tpm_qcom_type_req type_req = { + .command_id = QCOMTEE_TPM_TYPE_ID, + }; + struct tpm_qcom_type_rsp type_rsp; + size_t type_rsp_len = sizeof(type_rsp); + int ret; + + ret = tpm_qcom_send_command(pvt_data, 0, &ver_req, sizeof(ver_req), + &ver_rsp, &ver_rsp_len); + if (ret || ver_rsp_len < sizeof(ver_rsp) || ver_rsp.status != 0) { + dev_err(pvt_data->dev, + "failed to query TA version: ret=%d, status=%u\n", + ret, ret ? 0 : ver_rsp.status); + return ret ?: -EIO; + } + + dev_info(pvt_data->dev, "TPM TA version %lu.%lu\n", + FIELD_GET(QCOMTEE_TPM_TA_VERSION_MAJOR, ver_rsp.version_num), + FIELD_GET(QCOMTEE_TPM_TA_VERSION_MINOR, ver_rsp.version_num)); + + ret = tpm_qcom_send_command(pvt_data, 0, &type_req, sizeof(type_req), + &type_rsp, &type_rsp_len); + if (ret || type_rsp_len < sizeof(type_rsp) || type_rsp.status != 0) { + dev_err(pvt_data->dev, + "failed to query TPM type: ret=%d, status=%u\n", + ret, ret ? 0 : type_rsp.status); + return ret ?: -EIO; + } + + switch (type_rsp.tpm_type) { + case QCOMTEE_TPM_TYPE_FTPM: + dev_info(pvt_data->dev, "TPM type: fTPM\n"); + pvt_data->is_dtpm = false; + break; + case QCOMTEE_TPM_TYPE_DTPM: + dev_info(pvt_data->dev, "TPM type: dTPM\n"); + pvt_data->is_dtpm = true; + break; + default: + dev_err(pvt_data->dev, "unsupported TPM type: 0x%08x\n", + type_rsp.tpm_type); + return -EIO; + } + + return 0; +} + +/* fTPM does not implement this command and to be invoked via dtpm only. */ +static void tpm_qcom_transfer(struct tpm_qcom_private *pvt_data, + u32 transfer_state) +{ + struct tpm_qcom_transfer_req req = { + .command_id = QCOMTEE_TPM_TRANSFER_ID, + .transfer_state = transfer_state, + }; + struct tpm_qcom_transfer_rsp rsp; + size_t rsp_len = sizeof(rsp); + int ret; + + ret = tpm_qcom_send_command(pvt_data, 0, &req, sizeof(req), &rsp, + &rsp_len); + if (ret || rsp_len < sizeof(rsp) || rsp.status != 0) + dev_warn(pvt_data->dev, + "transfer state=%u hint failed: ret=%d, status=%u\n", + transfer_state, ret, ret ? 0 : rsp.status); +} + +static int tpm_qcom_cmd_ready(struct tpm_chip *chip) +{ + struct tpm_qcom_private *pvt_data = dev_get_drvdata(chip->dev.parent); + + if (pvt_data->is_dtpm) + tpm_qcom_transfer(pvt_data, QCOMTEE_TPM_TRANSFER_START); + + return 0; +} + +static int tpm_qcom_go_idle(struct tpm_chip *chip) +{ + struct tpm_qcom_private *pvt_data = dev_get_drvdata(chip->dev.parent); + + if (pvt_data->is_dtpm) + tpm_qcom_transfer(pvt_data, QCOMTEE_TPM_TRANSFER_END); + + return 0; +} + +/* + * The raw TPM2 command in @buf is sent directly as send_command's UBUF-in + * param and the raw TPM2 response is read back from its UBUF-out param. + */ +static int tpm_qcom_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, + size_t cmd_len) +{ + struct tpm_qcom_private *pvt_data = dev_get_drvdata(chip->dev.parent); + size_t rsp_len = PAGE_ALIGN(MAX_RESPONSE_SIZE); + size_t copy_len; + int ret; + + if (cmd_len > MAX_COMMAND_SIZE) { + dev_err(&chip->dev, "len=%zd exceeds MAX_COMMAND_SIZE\n", cmd_len); + return -EIO; + } + + u8 *response __free(kfree) = kzalloc(rsp_len, GFP_KERNEL); + if (!response) + return -ENOMEM; + + ret = tpm_qcom_send_command(pvt_data, 0, buf, cmd_len, response, + &rsp_len); + if (ret < 0) { + dev_err(&chip->dev, "send_command failed: ret=%d\n", ret); + return ret; + } + + copy_len = min_t(size_t, bufsiz, rsp_len); + memcpy(buf, response, copy_len); + + return copy_len; +} + +static const struct tpm_class_ops tpm_qcom_ops = { + .flags = TPM_OPS_AUTO_STARTUP, + .send = tpm_qcom_send, + .cmd_ready = tpm_qcom_cmd_ready, + .go_idle = tpm_qcom_go_idle, +}; + +static int tpm_qcom_ctx_match(struct tee_ioctl_version_data *ver, + const void *data) +{ + return (ver->impl_id == TEE_IMPL_ID_QTEE); +} + +static int tpm_qcom_probe(struct tee_client_device *tee_dev) +{ + struct device *dev = &tee_dev->dev; + struct tpm_qcom_private *pvt_data; + struct tee_param_objref client_env_obj; + struct tee_param_objref tpm_svc_obj; + struct tpm_chip *chip; + int rc, err; + + pvt_data = devm_kzalloc(dev, sizeof(*pvt_data), GFP_KERNEL); + if (!pvt_data) + return -ENOMEM; + + dev_set_drvdata(dev, pvt_data); + + pvt_data->ctx = tee_client_open_context(NULL, tpm_qcom_ctx_match, NULL, NULL); + if (IS_ERR(pvt_data->ctx)) + return -ENODEV; + + rc = tpm_qcom_get_client_env_obj(pvt_data->ctx, &client_env_obj); + if (rc) { + err = -EINVAL; + goto out_ctx; + } + + rc = tpm_qcom_get_svc_obj(pvt_data->ctx, client_env_obj, &tpm_svc_obj); + if (rc) { + err = -EINVAL; + goto out_client_env; + } + pvt_data->tpm_svc_obj = tpm_svc_obj; + pvt_data->dev = dev; + + err = tpm_qcom_get_ta_details(pvt_data); + if (err) + goto out_svc_obj; + + chip = tpm_chip_alloc(dev, &tpm_qcom_ops); + if (IS_ERR(chip)) { + dev_err(dev, "tpm_chip_alloc failed\n"); + err = PTR_ERR(chip); + goto out_svc_obj; + } + + pvt_data->chip = chip; + pvt_data->chip->flags |= TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_SYNC; + + err = tpm_chip_register(pvt_data->chip); + if (err) { + dev_err(dev, "tpm_chip_register failed with rc=%d\n", err); + goto out_chip; + } + + tpm_qcom_release_object(pvt_data->ctx, client_env_obj); + return 0; + +out_chip: + put_device(&pvt_data->chip->dev); +out_svc_obj: + tpm_qcom_release_object(pvt_data->ctx, tpm_svc_obj); +out_client_env: + tpm_qcom_release_object(pvt_data->ctx, client_env_obj); +out_ctx: + tee_client_close_context(pvt_data->ctx); + return err; +} + +static void tpm_qcom_remove(struct tee_client_device *tee_dev) +{ + struct tpm_qcom_private *pvt_data = dev_get_drvdata(&tee_dev->dev); + + tpm_chip_unregister(pvt_data->chip); + put_device(&pvt_data->chip->dev); + tpm_qcom_release_object(pvt_data->ctx, pvt_data->tpm_svc_obj); + tee_client_close_context(pvt_data->ctx); +} + +static const struct tee_client_device_id tpm_qcom_id_table[] = { + { tpm_qcom_uuid }, + {} +}; +MODULE_DEVICE_TABLE(tee, tpm_qcom_id_table); + +static struct tee_client_driver tpm_qcom_driver = { + .id_table = tpm_qcom_id_table, + .probe = tpm_qcom_probe, + .remove = tpm_qcom_remove, + .driver = { + .name = "tpm_qcom", + }, +}; + +module_tee_client_driver(tpm_qcom_driver); + +MODULE_DESCRIPTION("TPM driver for Qualcomm TPM TA"); +MODULE_AUTHOR("Kuldeep Singh "); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/tpm/tpm_qcom.h b/drivers/char/tpm/tpm_qcom.h new file mode 100644 index 0000000000000..3945b12643b76 --- /dev/null +++ b/drivers/char/tpm/tpm_qcom.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __TPM_QCOM_H__ +#define __TPM_QCOM_H__ + +#include +#include +#include +#include + +#define QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS 5 +#define QCOMTEE_OP_CLIENT_ENV_OPEN 0 +#define QCOMTEE_MSG_OBJECT_OP_MASK GENMASK(15, 0) +#define QCOMTEE_MSG_OBJECT_OP_RELEASE (QCOMTEE_MSG_OBJECT_OP_MASK - 0) + +#define QCOMTEE_TPM_OP_SEND_COMMAND 0 + +/* UID of the "qcom.tz.tpm" service */ +#define QCOMTEE_TPM_UID 81 + +/* Max buffer size supported by TPM TA */ +#define MAX_COMMAND_SIZE SZ_4K +#define MAX_RESPONSE_SIZE SZ_4K + +#define QCOMTEE_TPM_GET_TA_VERSION_ID 0x0001000 +#define QCOMTEE_TPM_TA_VERSION_MAJOR GENMASK(31, 16) +#define QCOMTEE_TPM_TA_VERSION_MINOR GENMASK(15, 0) + +struct tpm_qcom_ta_version_req { + u32 command_id; +} __packed; + +struct tpm_qcom_ta_version_rsp { + u32 status; + u32 command_id; + u32 version_num; +} __packed; + +#define QCOMTEE_TPM_TYPE_ID 0x0080000 +#define QCOMTEE_TPM_TYPE_DTPM 0x6454504dU +#define QCOMTEE_TPM_TYPE_FTPM 0x6654504dU +#define QCOMTEE_TPM_TYPE_NONE 0x4e6f6e65U + +struct tpm_qcom_type_req { + u32 command_id; +} __packed; + +struct tpm_qcom_type_rsp { + u32 command_id; + u32 status; + u32 tpm_type; +} __packed; + +/* + * dTPM SPI transfer optimization: + * TRANSFER_START before a burst of commands, TRANSFER_END once done. + */ +#define QCOMTEE_TPM_TRANSFER_ID 0x0000002 +#define QCOMTEE_TPM_TRANSFER_END 0 +#define QCOMTEE_TPM_TRANSFER_START 1 + +struct tpm_qcom_transfer_req { + u32 command_id; + u32 transfer_state; +} __packed; + +struct tpm_qcom_transfer_rsp { + u32 command_id; + u32 status; +} __packed; + +struct tpm_qcom_private { + struct tpm_chip *chip; + struct device *dev; + struct tee_context *ctx; + struct tee_param_objref tpm_svc_obj; + bool is_dtpm; +}; + +#endif /* __TPM_QCOM_H__ */ From f6354e29cf822d22c843bbcfce18bb44322732b2 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Mon, 7 Sep 2026 14:58:43 +0530 Subject: [PATCH 0877/1133] FROMLIST: MAINTAINERS: Add Qualcomm TPM driver entry Add a dedicated MAINTAINERS entry for the Qualcomm TPM driver, which uses the Qualcomm TEE interface (qcomtee) to communicate with a TPM Trusted Application running in TrustZone. Signed-off-by: Kuldeep Singh Link: https://lore.kernel.org/lkml/20260907-tpm_qcom_driver-v2-3-71a6b1752da8@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index c6fc50ff2c863..34d19383678f3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23180,6 +23180,13 @@ S: Maintained F: Documentation/tee/qtee.rst F: drivers/tee/qcomtee/ +QUALCOMM TPM DRIVER +M: Kuldeep Singh +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: drivers/char/tpm/tpm_qcom.c +F: drivers/char/tpm/tpm_qcom.h + QUALCOMM TRUST ZONE MEMORY ALLOCATOR M: Bartosz Golaszewski L: linux-arm-msm@vger.kernel.org From 503110b01c9ad2db7a0640aa5381a330e1dcda44 Mon Sep 17 00:00:00 2001 From: Gopikrishna Garmidi Date: Fri, 9 Oct 2026 20:26:38 +0530 Subject: [PATCH 0878/1133] FROMLIST: firmware: qcom: scm: Allow QSEECOM on the Mahua QCB Add the Mahua QCB to the QSEECOM allowlist for enabling access to efivars and the UEFI bootloader. Link: https://lore.kernel.org/all/20261027114955.1266499-3-sivansh.gupta@oss.qualcomm.com/ Signed-off-by: Gopikrishna Garmidi Signed-off-by: Sivansh Gupta --- drivers/firmware/qcom/qcom_scm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 43e250faea75a..eb262928d4c45 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2260,6 +2260,7 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { { .compatible = "qcom,hamoa-iot-evk" }, { .compatible = "qcom,kalambo-crd" }, { .compatible = "qcom,mahua-crd" }, + { .compatible = "qcom,mahua-qcb" }, { .compatible = "qcom,purwa-iot-evk" }, { .compatible = "qcom,sc8180x-primus" }, { .compatible = "qcom,x1e001de-devkit" }, From afe6c72a7a8319c3c05b2a57669ec61a04bd70b4 Mon Sep 17 00:00:00 2001 From: Nilesh Laad Date: Wed, 28 Jan 2026 18:28:20 +0530 Subject: [PATCH 0879/1133] FROMLIST: drm/bridge: lt9611uxc: reset edid_read on disconnect Currently edid_read has value from previous connect session and resulting in drm using older edid before new edid is available in lt9611uxc. Reset edid_read so that correct status is updated and correct edid is available for drm. Link: https://lore.kernel.org/lkml/20260202-lt9611uxc-reset-edid-v2-1-b1e1d72edc90@oss.qualcomm.com/ Signed-off-by: Ravi Agola Signed-off-by: Nilesh Laad --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index b3bb7f2cebb3b..80c82c18b8d2f 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -169,6 +169,9 @@ static void lt9611uxc_hpd_work(struct work_struct *work) connected = lt9611uxc->hdmi_connected; mutex_unlock(<9611uxc->ocm_lock); + if (!connected) + lt9611uxc->edid_read = false; + drm_bridge_hpd_notify(<9611uxc->bridge, connected ? connector_status_connected : From d6a25ebb0041f9486a17ec4877995ea0f96e227b Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Fri, 4 Sep 2026 22:59:21 +0530 Subject: [PATCH 0880/1133] FROMLIST: dt-bindings: display: bridge: lontium,lt9211: Add lt9211c support Add binding for the Lontium LT9211C bridge chip. Link: https://lore.kernel.org/all/20260904-add-lt9211c-bridge-v8-1-36d66168e176@oss.qualcomm.com/ Signed-off-by: Yi Zhang Signed-off-by: Nilesh Laad Signed-off-by: Gopi Botlagunta Reviewed-by: Rob Herring (Arm) Signed-off-by: Vishnu Saini --- .../devicetree/bindings/display/bridge/lontium,lt9211.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml index 7cfe92a8bcd72..de61bda09db96 100644 --- a/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml @@ -4,19 +4,20 @@ $id: http://devicetree.org/schemas/display/bridge/lontium,lt9211.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Lontium LT9211 DSI/LVDS/DPI to DSI/LVDS/DPI bridge. +title: Lontium LT9211/LT9211C DSI/LVDS/DPI to DSI/LVDS/DPI bridge. maintainers: - Marek Vasut description: | - The LT9211 are bridge devices which convert Single/Dual-Link DSI/LVDS + The LT9211 and LT9211C are bridge devices which convert Single/Dual-Link DSI/LVDS or Single DPI to Single/Dual-Link DSI/LVDS or Single DPI. properties: compatible: enum: - lontium,lt9211 + - lontium,lt9211c reg: maxItems: 1 From e1671495c455d78ec366c2bb77777c76a5dc577f Mon Sep 17 00:00:00 2001 From: Abhinav Parihar Date: Thu, 17 Sep 2026 00:28:50 +0530 Subject: [PATCH 0881/1133] FROMLIST: misc: fastrpc: Add cache maintenance for non-coherent platforms Some platforms using fastrpc do not support DMA coherency on HLOS. On such systems, explicit cache maintenance is required to ensure data consistency for RPC argument buffers. Add cache maintenance for argument buffers when operating on non-coherent platforms: - Flush input buffers before invoking RPC to ensure CPU writes are visible to the DSP - Invalidate output buffers after RPC completion to ensure DSP writes are visible to the CPU Introduce helper functions fastrpc_flush_args() and fastrpc_inv_args() to perform the required dma-buf cache operations. These are invoked only when the device is not marked as DMA coherent. The coherency capability is determined using the "dma-coherent" device tree property and stored per session context. This ensures correct data synchronization on platforms lacking DMA coherency, while avoiding unnecessary overhead on coherent systems. Signed-off-by: Abhinav Parihar Link: https://lore.kernel.org/r/20260916185850.3686010-1-abhinav.parihar@oss.qualcomm.com --- drivers/misc/fastrpc.c | 77 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index af18ff1992eed..2d24927e42471 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -215,6 +215,7 @@ struct fastrpc_buf_overlap { u64 mstart; u64 mend; u64 offset; + bool do_cmo; }; struct fastrpc_buf { @@ -290,6 +291,7 @@ struct fastrpc_session_ctx { int sid; bool used; bool valid; + bool coherent; }; struct fastrpc_soc_data { @@ -657,7 +659,9 @@ static int olaps_cmp(const void *a, const void *b) static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) { u64 max_end = 0; + int max_raix = -1; int i; + int inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); for (i = 0; i < ctx->nbufs; ++i) { ctx->olaps[i].start = ctx->args[i].ptr; @@ -677,6 +681,9 @@ static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) if (ctx->olaps[i].end > max_end) { max_end = ctx->olaps[i].end; } else { + if ((max_raix < inbufs && ctx->olaps[i].raix + 1 > inbufs) || + (ctx->olaps[i].raix < inbufs && max_raix + 1 > inbufs)) + ctx->olaps[i].do_cmo = true; ctx->olaps[i].mend = 0; ctx->olaps[i].mstart = 0; } @@ -686,6 +693,7 @@ static void fastrpc_get_buff_overlaps(struct fastrpc_invoke_ctx *ctx) ctx->olaps[i].mstart = ctx->olaps[i].start; ctx->olaps[i].offset = 0; max_end = ctx->olaps[i].end; + max_raix = ctx->olaps[i].raix; } } } @@ -705,6 +713,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( INIT_LIST_HEAD(&ctx->node); ctx->fl = user; + ctx->sc = sc; ctx->nscalars = REMOTE_SCALARS_LENGTH(sc); ctx->nbufs = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc); @@ -730,7 +739,6 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( /* Take a reference to user, released in fastrpc_context_free() */ fastrpc_user_get(user); - ctx->sc = sc; ctx->retval = -1; ctx->pid = current->pid; ctx->client_id = user->client_id; @@ -1069,6 +1077,64 @@ static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx) return 0; } +static void fastrpc_flush_args(struct fastrpc_invoke_ctx *ctx) +{ + union fastrpc_remote_arg *rpra = ctx->rpra; + int i, inbufs, outbufs; + + inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); + outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); + + for (i = 0; i < inbufs + outbufs; ++i) { + int raix = ctx->olaps[i].raix; + struct fastrpc_map *map = ctx->maps[raix]; + + if (raix + 1 > inbufs) + continue; + if (!map || !map->buf) + continue; + + if (rpra[raix].buf.len && (ctx->olaps[i].mstart || ctx->olaps[i].do_cmo)) { + dma_buf_begin_cpu_access(map->buf, DMA_TO_DEVICE); + dma_buf_end_cpu_access(map->buf, DMA_TO_DEVICE); + } + } +} + +static void fastrpc_inv_args(struct fastrpc_invoke_ctx *ctx) +{ + union fastrpc_remote_arg *rpra = ctx->rpra; + int i, inbufs, outbufs; + + inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); + outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); + + for (i = 0; i < inbufs + outbufs; ++i) { + int raix = ctx->olaps[i].raix; + struct fastrpc_map *map = ctx->maps[raix]; + + if (raix + 1 <= inbufs) + continue; + if (!rpra[raix].buf.len) + continue; + if (!map || !map->buf) + continue; + + /* + * Skip invalidation if the argument overlaps with the + * RPC control header page. + */ + if (((uintptr_t)rpra & PAGE_MASK) == + ((uintptr_t)rpra[raix].buf.pv & PAGE_MASK)) + continue; + + if (ctx->olaps[i].mstart || ctx->olaps[i].do_cmo) { + dma_buf_begin_cpu_access(map->buf, DMA_FROM_DEVICE); + dma_buf_end_cpu_access(map->buf, DMA_FROM_DEVICE); + } + } +} + static struct fastrpc_invoke_buf *fastrpc_invoke_buf_start(union fastrpc_remote_arg *pra, int len) { return (struct fastrpc_invoke_buf *)(&pra[len]); @@ -1193,6 +1259,9 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) } } + if (!ctx->fl->sctx->coherent) + fastrpc_flush_args(ctx); + for (i = ctx->nbufs; i < ctx->nscalars; ++i) { list[i].num = ctx->args[i].length ? 1 : 0; list[i].pgidx = i; @@ -1378,6 +1447,8 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, if (err) goto bail; + if (!fl->sctx->coherent) + fastrpc_inv_args(ctx); /* make sure that all CPU memory writes are seen by DSP */ dma_wmb(); /* Send invoke buffer to remote dsp */ @@ -1398,6 +1469,9 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, /* make sure that all memory writes by DSP are seen by CPU */ dma_rmb(); + if (!fl->sctx->coherent) + fastrpc_inv_args(ctx); + /* populate all the output buffers with results */ err = fastrpc_put_args(ctx, kernel); if (err) @@ -2363,6 +2437,7 @@ static int fastrpc_cb_probe(struct platform_device *pdev) sess->used = false; sess->valid = true; sess->dev = dev; + sess->coherent = of_property_read_bool(dev->of_node, "dma-coherent"); dev_set_drvdata(dev, sess); sess->sid = sid; From 5ee4e41ba81043fce7ce258e712998d443a4f7a8 Mon Sep 17 00:00:00 2001 From: Vikram Sharma Date: Thu, 23 Oct 2025 12:28:39 +0530 Subject: [PATCH 0882/1133] QCLINUX: firmware: qcom_scm: Add new scm to update Camera QoS Add new SCM call to program secure camera qos settings. For each NIU camera driver can call this scm API which need each NIU's register offsets, value and number of registers offset that need to be programmed. Signed-off-by: Vikram Sharma --- drivers/firmware/qcom/qcom_scm.c | 45 ++++++++++++++++++++++++++ drivers/firmware/qcom/qcom_scm.h | 3 ++ include/linux/firmware/qcom/qcom_scm.h | 10 ++++++ 3 files changed, 58 insertions(+) diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 43e250faea75a..45cc5e7a24297 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -2509,6 +2509,51 @@ bool qcom_scm_is_available(void) } EXPORT_SYMBOL_GPL(qcom_scm_is_available); +int qcom_scm_camera_update_camnoc_qos(uint32_t use_case_id, + uint32_t cam_qos_cnt, struct qcom_scm_camera_qos *cam_qos) +{ + int ret; + dma_addr_t payload_phys; + u32 *payload_buf = NULL; + u32 payload_size = 0; + + if ((cam_qos_cnt > QCOM_SCM_CAMERA_MAX_QOS_CNT) || (cam_qos_cnt && !cam_qos)) { + pr_err("Invalid input SmartQoS count: %d\n", cam_qos_cnt); + return -EINVAL; + } + + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_CAMERA, + .cmd = QCOM_SCM_CAMERA_UPDATE_CAMNOC_QOS, + .owner = ARM_SMCCC_OWNER_SIP, + .args[0] = use_case_id, + .args[2] = payload_size, + .arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL), + }; + + payload_size = cam_qos_cnt * sizeof(struct qcom_scm_camera_qos); + + /* fill all required qos settings */ + if (use_case_id && payload_size && cam_qos) { + payload_buf = dma_alloc_coherent(__scm->dev, + payload_size, &payload_phys, GFP_KERNEL); + if (!payload_buf) + return -ENOMEM; + + memcpy(payload_buf, cam_qos, payload_size); + desc.args[1] = payload_phys; + desc.args[2] = payload_size; + + } + ret = qcom_scm_call(__scm->dev, &desc, NULL); + + if (payload_buf) + dma_free_coherent(__scm->dev, payload_size, payload_buf, payload_phys); + + return ret; +} +EXPORT_SYMBOL_GPL(qcom_scm_camera_update_camnoc_qos); + static int qcom_scm_fill_irq_fwspec_params(struct irq_fwspec *fwspec, u32 hwirq) { if (hwirq >= GIC_SPI_BASE && hwirq <= GIC_MAX_SPI) { diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h index cf90a565fdfbd..ad21085030c37 100644 --- a/drivers/firmware/qcom/qcom_scm.h +++ b/drivers/firmware/qcom/qcom_scm.h @@ -175,6 +175,9 @@ int qcom_scm_shm_bridge_enable(struct device *scm_dev); #define QCOM_SCM_INTERRUPTED 1 #define QCOM_SCM_WAITQ_SLEEP 2 +#define QCOM_SCM_SVC_CAMERA 0x18 +#define QCOM_SCM_CAMERA_UPDATE_CAMNOC_QOS 0xA + static inline int qcom_scm_remap_error(int err) { switch (err) { diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h index a0a6bc0229c4b..2df624fa08e41 100644 --- a/include/linux/firmware/qcom/qcom_scm.h +++ b/include/linux/firmware/qcom/qcom_scm.h @@ -10,10 +10,12 @@ #include #include +#include #define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) #define QCOM_SCM_CPU_PWR_DOWN_L2_ON 0x0 #define QCOM_SCM_CPU_PWR_DOWN_L2_OFF 0x1 +#define QCOM_SCM_CAMERA_MAX_QOS_CNT 2 #define QCOM_SCM_HDCP_MAX_REQ_CNT 5 struct qcom_scm_hdcp_req { @@ -65,6 +67,14 @@ int qcom_scm_set_cold_boot_addr(void *entry); int qcom_scm_set_warm_boot_addr(void *entry); void qcom_scm_cpu_power_down(u32 flags); +struct qcom_scm_camera_qos { + u32 offset; + u32 val; +}; + +int qcom_scm_camera_update_camnoc_qos(uint32_t use_case_id, + uint32_t qos_cnt, struct qcom_scm_camera_qos *scm_buf); + int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); From 80ff5764e817086f0685af8a7662c161b8331e12 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Thu, 8 Jan 2026 09:42:56 +0530 Subject: [PATCH 0883/1133] QCLINUX: PCI: Disable L1ss through quirk for Qualcomm SA8775P When PCIe L1ss is enabled, WLAN functionality is completly broken. There are some connectivity issues in this platform mostly with CLKREQ# pin. Disable L1ss as workaround untill actual issue get resolved. Signed-off-by: Krishna Chaitanya Chundru --- drivers/pci/quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 7f1f47ea2ee41..20b636dba4874 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2551,6 +2551,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, 0x0451, quirk_disable_aspm_l0s DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PASEMI, 0xa002, quirk_disable_aspm_l0s_l1); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HUAWEI, 0x1105, quirk_disable_aspm_l0s_l1); +static void quirk_disable_aspm_l1ss(struct pci_dev *dev) +{ + pci_disable_link_state(dev, PCIE_LINK_STATE_L1_1 | PCIE_LINK_STATE_L1_2); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_QCOM, 0x1103, quirk_disable_aspm_l1ss); + /* * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain * Link bit cleared after starting the link retrain process to allow this From ddbc2c1c6213df4d53ed12142de26f66e690f369 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 4 Feb 2026 21:40:53 +0530 Subject: [PATCH 0884/1133] WORKAROUND: arm64: dts: qcom: lemans: Disable global IRQ for pcie1 Currently pcie1 global IRQ is blocking a CPU core, due to which ufs is getting blocked and failing. As workaround disable PCIe1 global IRQ for now. Signed-off-by: Krishna Chaitanya Chundru --- arch/arm64/boot/dts/qcom/lemans.dtsi | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 1fdb72fa55184..0aa1e7da92668 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -2879,8 +2879,7 @@ , , , - , - ; + ; interrupt-names = "msi0", "msi1", "msi2", @@ -2888,8 +2887,7 @@ "msi4", "msi5", "msi6", - "msi7", - "global"; + "msi7"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; interrupt-map = <0 0 0 1 &intc GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, From b919a781e1131a8fe985ea3fdc3ebb5f5b0613ad Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Sat, 7 Feb 2026 17:55:39 +0530 Subject: [PATCH 0885/1133] WORKAROUND: scsi: ufs: core: Set uic_cmd_timeout to max It is obsrved that qcs9100-ride fails to boot intermittently due to ufs cmd timeouts. The timeout happens as the ufs threaded-irq fails to schedule within the default UIC_CMD_TIMEOUT_DEFAULT (500 msec) due to console logs spewing at the same moment. Increase timeout to max for now to UIC_CMD_TIMEOUT_MAX (5000 msecs) to allow ufs cmd sequences to complete. Signed-off-by: Shiraz Hashim --- drivers/ufs/core/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index ee643830a57a2..87ef4e14c6961 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -120,7 +120,7 @@ static bool is_mcq_supported(struct ufs_hba *hba) module_param(use_mcq_mode, bool, 0644); MODULE_PARM_DESC(use_mcq_mode, "Control MCQ mode for controllers starting from UFSHCI 4.0. 1 - enable MCQ, 0 - disable MCQ. MCQ is enabled by default"); -static unsigned int uic_cmd_timeout = UIC_CMD_TIMEOUT_DEFAULT; +static unsigned int uic_cmd_timeout = UIC_CMD_TIMEOUT_MAX; static int uic_cmd_timeout_set(const char *val, const struct kernel_param *kp) { From ef2d128fa996a6cfc338c3160169740d9e03b784 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Wed, 4 Mar 2026 12:15:34 +0530 Subject: [PATCH 0886/1133] WORKAROUND: Revert "PCI: dwc: Remove MSI/MSIX capability for Root Port if iMSI-RX is used as MSI controller" commit f5cd8a929c825("PCI: dwc: Remove MSI/MSIX capability for Root Port if iMSI-RX is used as MSI controller") removed MSI & MSIX capability for Root port as dwc controller doesn't support to generate interrupt. Due to this pci framework is falling back to legacy IRQ's. Now controller can generate to interrupts with legacy IRQ's, and actually causing console flood with PCIe continous AER errorsi, these errors will not cause any functional issues. To avoid these errors revert this temporarly untill actual issue got root caused and fixed. Signed-off-by: Krishna Chaitanya Chundru --- drivers/pci/controller/dwc/pcie-designware-host.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 869a39107a81d..806019b91d102 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -1184,17 +1184,6 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp) dw_pcie_dbi_ro_wr_dis(pci); - /* - * The iMSI-RX module does not support receiving MSI or MSI-X generated - * by the Root Port. If iMSI-RX is used as the MSI controller, remove - * the MSI and MSI-X capabilities of the Root Port to allow the drivers - * to fall back to INTx instead. - */ - if (pp->use_imsi_rx && !pp->keep_rp_msi_en) { - dw_pcie_remove_capability(pci, PCI_CAP_ID_MSI); - dw_pcie_remove_capability(pci, PCI_CAP_ID_MSIX); - } - return 0; } EXPORT_SYMBOL_GPL(dw_pcie_setup_rc); From aa11ce905465a530f817257bcd1b8365d96cafed Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Tue, 14 Jul 2026 15:57:00 +0530 Subject: [PATCH 0887/1133] WORKAROUND: iommu/arm-smmu: Work around Qualcomm SMMU-500 TLBIVAL granule issue Qualcomm SMMU-500 has an issue with TLBIVA/TLBIVAL where only the base-page-size entry at the base IOVA is invalidated, leaving stale TLB entries for the rest of the range. This causes use-after-free: after dma_free_coherent() unmaps a large buffer, the device can still access freed physical memory through stale TLB entries. On FastRPC workloads this manifests as ADSP crashes when the ELF loader writes to a freed PA that has been reallocated. Force the TLB invalidation step granule to the minimum page size for all Qualcomm SMMU-500 domains, ensuring each page in the range is individually invalidated. The minimum page size from pgsize_bitmap is used rather than hardcoded 4K to correctly handle 16K and 64K granule configurations. This increases the number of TLB invalidation operations for large ranges, but correctness takes precedence. Signed-off-by: Prakash Gupta Signed-off-by: Sibi Sankar --- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 9 +++++++++ drivers/iommu/arm/arm-smmu/arm-smmu.c | 10 ++++++++++ drivers/iommu/arm/arm-smmu/arm-smmu.h | 1 + 3 files changed, 20 insertions(+) diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index 795e8ec7e8faf..7433842f69f80 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -439,6 +439,15 @@ static int qcom_smmu_init_context(struct arm_smmu_domain *smmu_domain, int cbndx = smmu_domain->cfg.cbndx; smmu_domain->cfg.flush_walk_prefer_tlbiasid = true; + /* + * Qualcomm SMMU-500 has an issue with TLBIVA/TLBIVAL where only + * the base-page-size entry at the base IOVA is invalidated. Glymur + * SoCs boot by default at EL2 and is the currently the only SoC + * affected by it. Force the minimum page granule to ensure the full + * range is covered. + */ + if (of_device_is_compatible(smmu->dev->of_node, "qcom,glymur-smmu-500")) + smmu_domain->cfg.force_min_tlbival_granule = true; client_match = qsmmu->data->client_match; diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index 889a0966d36cd..f4cfa0913f9f3 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -286,6 +286,16 @@ static void arm_smmu_tlb_inv_range_s1(unsigned long iova, size_t size, struct arm_smmu_cfg *cfg = &smmu_domain->cfg; int idx = cfg->cbndx; + /* + * Override the step granule with the minimum supported page size. + * Placed here (rather than in tlb_add_page alone) to cover both + * TLBIVAL and TLBIVA paths. + */ + if (cfg->force_min_tlbival_granule) { + WARN_ON_ONCE(!smmu_domain->domain.pgsize_bitmap); + granule = 1UL << __ffs(smmu_domain->domain.pgsize_bitmap); + } + if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) wmb(); diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h index 26d2e33cd328b..85d1f2d7ec506 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h @@ -359,6 +359,7 @@ struct arm_smmu_cfg { enum arm_smmu_cbar_type cbar; enum arm_smmu_context_fmt fmt; bool flush_walk_prefer_tlbiasid; + bool force_min_tlbival_granule; }; #define ARM_SMMU_INVALID_IRPTNDX 0xff From 8d89b914bd38aaa9ac5c39685953224bde85e233 Mon Sep 17 00:00:00 2001 From: Yushan Li Date: Mon, 12 Oct 2026 18:26:22 +0800 Subject: [PATCH 0888/1133] WORKAROUND: iommu/arm-smmu: Extend TLBIVAL granule workaround to x1e80100 Add "qcom,x1e80100-smmu-500" to the force_min_tlbival_granule check so that Hamoa and Purwa apps_smmu are also covered. Signed-off-by: Yushan Li --- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index 7433842f69f80..43af3229bc111 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -441,12 +441,11 @@ static int qcom_smmu_init_context(struct arm_smmu_domain *smmu_domain, smmu_domain->cfg.flush_walk_prefer_tlbiasid = true; /* * Qualcomm SMMU-500 has an issue with TLBIVA/TLBIVAL where only - * the base-page-size entry at the base IOVA is invalidated. Glymur - * SoCs boot by default at EL2 and is the currently the only SoC - * affected by it. Force the minimum page granule to ensure the full - * range is covered. + * the base-page-size entry at the base IOVA is invalidated. Force + * the minimum page granule to ensure the full range is covered. */ - if (of_device_is_compatible(smmu->dev->of_node, "qcom,glymur-smmu-500")) + if (of_device_is_compatible(smmu->dev->of_node, "qcom,glymur-smmu-500") || + of_device_is_compatible(smmu->dev->of_node, "qcom,x1e80100-smmu-500")) smmu_domain->cfg.force_min_tlbival_granule = true; client_match = qsmmu->data->client_match; From 8ace2a5e425bbac8fcbcf77ba2a50463d8ac67fb Mon Sep 17 00:00:00 2001 From: Jianfeng Liu Date: Wed, 23 Sep 2026 15:42:22 +0800 Subject: [PATCH 0889/1133] FROMLIST: dma-buf: keep DMABUF_DEBUG off by default Commit 143755bdabaa9 ("dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels") fixed a dangling reference in the DMABUF_DEBUG default, which had the side effect of enabling the option (and with it the page-stripping sg_table wrapper handed to importers) on every kernel with DEBUG_KERNEL=y - i.e. virtually every distro kernel. drm/msm is broken by this: it maps imported dma-bufs into the GPU's own pagetables with iommu_map_sgtable(), which needs the struct page of the attachment sg_table, and it fills the GEM object's page array through drm_prime_sg_to_page_array(). With the debug wrapper in place both silently produce garbage (the wrapper zeroes sg->length, so the page iterator yields nothing and an uninitialized array is kept). The VM_BIND map job then fails asynchronously after userspace has already enqueued GPU work referencing the mapping, which shows up as an arm-smmu translation fault from UCHE, e.g.: gpu fault: ttbr0=000000088a889000 iova=000000010741c000 dir=READ type=TRANSLATION source=UCHE This breaks hardware video decode (clapper, chromium) on Adreno systems; bisected on a Snapdragon laptop as v7.3-rc3 good, v7.3-rc4 bad, culprit 143755bdabaa9. Revert the default until importers that legitimately need to build phys-based mappings have been converted. Fixes: 143755bdabaa9 ("dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels") Signed-off-by: Jianfeng Liu Link: https://lore.kernel.org/r/20260923074256.9357-2-liujianfeng1994@gmail.com --- drivers/dma-buf/Kconfig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig index 7efc0f0d07126..b3c581ef4c987 100644 --- a/drivers/dma-buf/Kconfig +++ b/drivers/dma-buf/Kconfig @@ -43,7 +43,14 @@ config UDMABUF config DMABUF_DEBUG bool "DMA-BUF debug checks" depends on DMA_SHARED_BUFFER - default y if DEBUG + # NOTE: keep this default n. The page-stripping sg_table wrapper that + # this option installs for importers breaks drivers that build a + # second-stage IOMMU mapping (phys -> iova) from the attachment sg_table + # and therefore still need the struct page, e.g. drm/msm with its + # per-process GPU pagetables. Until those importers are fixed, making + # this default y breaks hardware video decode and GPU workloads out of + # the box on affected systems. + default n help This option enables additional checks for DMA-BUF importers and exporters. Specifically it validates that importers do not peek at the From 5d786d3550041b15048ab624b4b9d46493685aad Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Mon, 21 Sep 2026 20:43:41 +0530 Subject: [PATCH 0890/1133] FROMLIST: dma-buf: system_heap: align allocation orders to ARM64 hugepage sizes System heap currently uses a fixed allocation order, {8, 4, 0} while requesting pages from the buddy allocator which correspond to 1 MiB, 64 KiB and 4 KiB only on systems using 4 KiB page size. Extending on patch from Juan [1] for ARM64 targets with LPAE, a 1 MiB allocation does not correspond to a PMD block size. For a 4 KiB-granule IOMMU, a 2 MiB allocation can be mapped using a single PMD block entry, reducing IOMMU TLB pressure by requiring fewer translation entries. Use allocation orders corresponding to the ARM64 PMD block and contiguous-PTE sizes for 4 KiB, 16 KiB and 64 KiB page configurations. ARM64 applicable orders are selected for ARM64 targets with default orders being used for rest of the architectures. [1] https://lore.kernel.org/all/20250417201913.2393655-1-jyescas@google.com/ Co-developed-by: Juan Yescas Signed-off-by: Juan Yescas Co-developed-by: Pankaj Patil Signed-off-by: Prakash Gupta Signed-off-by: Pankaj Patil Link: https://lore.kernel.org/all/20260921-dma_buf_improvement-v1-1-23d82e771dec@oss.qualcomm.com/ --- drivers/dma-buf/heaps/system_heap.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index c8959eadc71d1..7a3e26c3dd434 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -57,12 +58,30 @@ struct dma_heap_attachment { | __GFP_COMP) static gfp_t order_flags[] = {HIGH_ORDER_GFP, HIGH_ORDER_GFP, LOW_ORDER_GFP}; /* - * The selection of the orders used for allocation (1MB, 64K, 4K) is designed - * to match with the sizes often found in IOMMUs. Using order 4 pages instead - * of order 0 pages can significantly improve the performance of many IOMMUs - * by reducing TLB pressure and time spent updating page tables. + * For ARM64, allocation orders correspond to the PMD block and CONT PTE + * hugepage sizes for each CPU page granule, which also align with the + * TLB entry sizes of a 4K-granule IOMMU (arm-smmu, arm-smmu-v3). + * Each order = (level_shift - PAGE_SHIFT), derived from: + * PMD_SHIFT = (PAGE_SHIFT - 3) * 2 + 3 + * CONT_PTE_SHIFT = CONFIG_ARM64_CONT_PTE_SHIFT + PAGE_SHIFT + * + * 4K CPU (PAGE_SHIFT=12): PMD=2MiB (21-12=9), CONT_PTE=64KiB (16-12=4) + * 16K CPU (PAGE_SHIFT=14): PMD=32MiB (25-14=11), CONT_PTE=2MiB (21-14=7) + * 64K CPU (PAGE_SHIFT=16): PMD=512MiB (29-16=13), CONT_PTE=2MiB (21-16=5) + */ +#if defined(CONFIG_ARM64) && (PAGE_SIZE == SZ_4K) +static const unsigned int orders[] = {21 - PAGE_SHIFT, 16 - PAGE_SHIFT, 0}; +#elif defined(CONFIG_ARM64) && (PAGE_SIZE == SZ_16K) +static const unsigned int orders[] = {25 - PAGE_SHIFT, 21 - PAGE_SHIFT, 0}; +#elif defined(CONFIG_ARM64) && (PAGE_SIZE == SZ_64K) +static const unsigned int orders[] = {29 - PAGE_SHIFT, 21 - PAGE_SHIFT, 0}; +#else +/* Fallback to default allocation order for non-arm64 architectures + * On 4K-page systems, these orders correspond to 1MiB, 64KiB and 4KiB, + * matching sizes commonly supported by IOMMUs. */ static const unsigned int orders[] = {8, 4, 0}; +#endif #define NUM_ORDERS ARRAY_SIZE(orders) static int system_heap_set_page_decrypted(struct page *page) From de9086c177c698a2dc0bc0d3308cbc42db6ebf6b Mon Sep 17 00:00:00 2001 From: Ram Prakash Gupta Date: Fri, 29 May 2026 13:40:45 +0530 Subject: [PATCH 0891/1133] FROMLIST: mmc: sdhci-msm: Set ice clk rate Set ice clk rate from sdhci msm platform driver, needed for target which are having legacy ice support, and need sdhci msm platform driver to set rate. Link: https://lore.kernel.org/all/20260529081045.2877910-2-ram.gupta@oss.qualcomm.com/ Signed-off-by: Ram Prakash Gupta Signed-off-by: Pradeep P V K --- drivers/mmc/host/sdhci-msm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index aecd425bf0951..bca730e9eea1a 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -286,6 +286,7 @@ struct sdhci_msm_host { /* core, iface, cal and sleep clocks */ struct clk_bulk_data bulk_clks[4]; #ifdef CONFIG_MMC_CRYPTO + struct clk *ice_clk; /* ICE clock */ struct qcom_ice *ice; #endif unsigned long clk_rate; @@ -2714,6 +2715,17 @@ static int sdhci_msm_probe(struct platform_device *pdev) return ret; } +#ifdef CONFIG_MMC_CRYPTO + /* Setup ICE clock */ + msm_host->ice_clk = devm_clk_get(&pdev->dev, "ice"); + if (!IS_ERR(msm_host->ice_clk)) { + /* Vote for max. clk rate for max. performance */ + ret = clk_set_rate(msm_host->ice_clk, INT_MAX); + if (ret) + dev_err(&pdev->dev, "ice clk set rate failed (%d)\n", ret); + } +#endif + /* Setup main peripheral bus clock */ clk = devm_clk_get(&pdev->dev, "iface"); if (IS_ERR(clk)) { From 5746e2840abba60e648953e708537786ae561fe3 Mon Sep 17 00:00:00 2001 From: Nitin Rawat Date: Mon, 1 Jun 2026 05:20:10 +0530 Subject: [PATCH 0892/1133] FROMLIST: scsi: ufs: core: Add UFSHCD_QUIRK_SKIP_DEVICE_RESET quirk Add a new host quirk UFSHCD_QUIRK_SKIP_DEVICE_RESET to allow host controller drivers to skip asserting device reset during UFS power down. When RST_N is asserted, the UFS device firmware wakes up and executes its internal reset routine. This routine initializes multiple hardware blocks and causing the device to draw a large curreny during this time. If the power rail transitions to LPM (Low Power Mode) while the device is still drawing this elevated current, it may trigger an OCP (Over Current Protection) fault in the regulator. For some UFS devices (e.g., Micron), the elevated current draw persists until the reset line is deasserted, making a fixed delay insufficient to prevent OCP. This quirk allows such devices to skip device reset during UFS power down. The device reset will instead be asserted as part of the platform shutdown sequence. Link: https://lore.kernel.org/linux-scsi/20260531235011.1052706-2-nitin.rawat@oss.qualcomm.com/ Signed-off-by: Nitin Rawat Signed-off-by: Pradeep P V K --- include/ufs/ufshcd.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index be62165b785e0..305c689851b95 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -816,7 +816,22 @@ enum ufshcd_quirks { * (EQTR) using Adapt L0L1L2L3 length which is larger than what is * allowed by M-PHY spec ver 6.0. */ + UFSHCD_QUIRK_EXTENDED_TX_EQTR_ADAPT_LENGTH_L0L1L2L3 = 1 << 28, + /* + * Some UFS devices keep drawing larger current after reset is + * asserted until it is deasserted. Asserting device reset + * during UFS power down causes the device firmware to wake up and + * execute its reset routine, drawing current beyond the permissible + * limit for low-power mode (LPM). This may trigger an OCP fault on + * the regulator supplying power to UFS. + * + * Enable this quirk to skip asserting device reset during UFS power + * down. This is handled only in shutdown; the device reset will be + * asserted as part of the platform shutdown sequence. + */ + + UFSHCD_QUIRK_SKIP_DEVICE_RESET = 1 << 29, }; enum ufshcd_caps { From 6ddd3894f8d74cd8d94b55874af13b013c05c561 Mon Sep 17 00:00:00 2001 From: Nitin Rawat Date: Mon, 1 Jun 2026 05:20:11 +0530 Subject: [PATCH 0893/1133] FROMLIST: scsi: ufs: ufs-qcom: Enable SKIP DEVICE RESET Quirk A previous fix [1] addressed an OCP (Over Current Protection) issue during UFS power down (PC=3) by adding a 10ms delay after asserting HWRST. The delay allows the UFS device to complete its reset routine before the power rail transitions to LPM (Low Power Mode). However, this fix is insufficient for certain Micron UFS parts. Unlike other vendors whose reset routine completes within ~10ms, Micron parts continue to draw current beyond the LPM threshold for a longer duration after reset is asserted, specifically until the reset is deasserted (RST_N goes high). No fixed delay can reliably cover this window since there is currently no mechanism for the host to query whether the device reset routine has completed. Enable the UFSHCD_QUIRK_SKIP_DEVICE_RESET quirk to skip device assert reset during UFS power down for Micron parts. For all other vendors, the existing behavior (assert reset + 10ms delay) is preserved. This quirk is applicable only during shutdown. The device reset will be asserted as part of the platform shutdown sequences. [1] commit 5127be409c6c ("scsi: ufs: ufs-qcom: Fix UFS OCP issue during UFS power down (PC=3)") Link: https://lore.kernel.org/linux-scsi/20260531235011.1052706-3-nitin.rawat@oss.qualcomm.com/ Signed-off-by: Nitin Rawat Signed-off-by: Pradeep P V K --- drivers/ufs/host/ufs-qcom.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 27c87e62f8e98..d4eef4b54126d 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -810,9 +810,17 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op, if (!ufs_qcom_is_link_active(hba)) ufs_qcom_disable_lane_clks(host); - - /* reset the connected UFS device during power down */ - if (ufs_qcom_is_link_off(hba) && host->device_reset) { + /* + * For some UFS vendors, skip asserting device reset here. + * These vendor parts keep drawing larger current after reset + * is asserted until it is deasserted, and the 10ms delay is + * not sufficient to prevent OCP (Over Current Protection) + * on the regulator. This is for the powerdown case, so + * the device reset can be asserted later as part of the + * platform shutdown sequence. + */ + if (ufs_qcom_is_link_off(hba) && host->device_reset && + !(hba->quirks & UFSHCD_QUIRK_SKIP_DEVICE_RESET)) { ufs_qcom_device_reset_ctrl(hba, true); /* * After sending the SSU command, asserting the rst_n @@ -1328,6 +1336,19 @@ static struct ufs_dev_quirk ufs_qcom_dev_fixups[] = { static void ufs_qcom_fixup_dev_quirks(struct ufs_hba *hba) { ufshcd_fixup_dev_quirks(hba, ufs_qcom_dev_fixups); + + /* + * Some UFS parts keep drawing larger current after reset is asserted + * until it is deasserted. The 10ms delay added after asserting HWRST + * (as done for other vendors) is not sufficient for these parts. + * + * Skip asserting device reset during UFS power down for these parts + * to prevent OCP (Over Current Protection) fault on the regulator. + * This is handled only in shutdown; the device reset will be asserted + * as part of the platform shutdown sequence. + */ + if (hba->dev_info.wmanufacturerid == UFS_VENDOR_MICRON) + hba->quirks |= UFSHCD_QUIRK_SKIP_DEVICE_RESET; } static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba) From 6897038347bfd74eb270688fdc60dbbdf42dabba Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Mon, 5 Oct 2026 20:59:42 +0530 Subject: [PATCH 0894/1133] FROMLIST: dt-bindings: power: domain-idle-state: Add system-state Some domain idle states require system-wide coordination and are not applicable while the platform is up and running. Add a boolean system-state property to describe these states. Link: https://lore.kernel.org/linux-arm-msm/20261005-s2idle_state-v1-1-3c402c66f388@oss.qualcomm.com/ Assisted-by: Codex:GPT-6 Acked-by: Kevin Hilman Signed-off-by: Maulik Shah --- .../bindings/power/domain-idle-state.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/power/domain-idle-state.yaml b/Documentation/devicetree/bindings/power/domain-idle-state.yaml index 4dd4f59bbbec3..35dab3cd6aedc 100644 --- a/Documentation/devicetree/bindings/power/domain-idle-state.yaml +++ b/Documentation/devicetree/bindings/power/domain-idle-state.yaml @@ -45,6 +45,12 @@ patternProperties: state will yield power benefits, after overcoming the overhead while entering the idle state. + system-state: + description: + When present, this state requires system-wide coordination and is + not applicable while the platform is up and running. + type: boolean + arm,psci-suspend-param: $ref: /schemas/types.yaml#/definitions/uint32 description: | @@ -77,5 +83,13 @@ examples: exit-latency-us = <40>; min-residency-us = <80>; }; + + domain_power_off: domain-power-off { + compatible = "domain-idle-state"; + entry-latency-us = <100>; + exit-latency-us = <200>; + min-residency-us = <1000>; + system-state; + }; }; ... From b7f21fe9ac70c70073531a0a28484ddb8e2262f3 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Mon, 5 Oct 2026 20:59:43 +0530 Subject: [PATCH 0895/1133] FROMLIST: pmdomain: Add support for system-suspend-only states Some domain idle states require system-wide coordination and should not be selected during regular CPU idle. However those states remain valid for system-wide suspend like s2idle. Add a per-state system_state boolean and populate it from the system-state property. Make the genpd governor skip these states during CPU idle. Leave the system wide suspend path unchanged so s2idle can select them. Link: https://lore.kernel.org/linux-arm-msm/20261005-s2idle_state-v1-2-3c402c66f388@oss.qualcomm.com/ Assisted-by: Codex:GPT-6 Acked-by: Kevin Hilman Signed-off-by: Maulik Shah --- drivers/pmdomain/core.c | 1 + drivers/pmdomain/governor.c | 6 ++++++ include/linux/pm_domain.h | 1 + 3 files changed, 8 insertions(+) diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 964e44c2f78f1..9f2e23ff954f2 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -3705,6 +3705,7 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state, &genpd_state->name); if (err) genpd_state->name = state_node->name; + genpd_state->system_state = of_property_read_bool(state_node, "system-state"); genpd_state->power_on_latency_ns = 1000LL * exit_latency; genpd_state->power_off_latency_ns = 1000LL * entry_latency; diff --git a/drivers/pmdomain/governor.c b/drivers/pmdomain/governor.c index 38bba24ec26e3..7684f9eecf853 100644 --- a/drivers/pmdomain/governor.c +++ b/drivers/pmdomain/governor.c @@ -185,6 +185,9 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd, s64 min_off_time_ns; s64 off_on_time_ns; + if (genpd->states[state].system_state) + return false; + off_on_time_ns = genpd->states[state].power_off_latency_ns + genpd->states[state].power_on_latency_ns; @@ -407,6 +410,9 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd) */ i = genpd->state_idx; do { + if (genpd->states[i].system_state) + continue; + if ((idle_duration_ns >= (genpd->states[i].residency_ns + genpd->states[i].power_off_latency_ns)) && (global_constraint >= (genpd->states[i].power_on_latency_ns + diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 14e0e346c610a..d9b3e67042e5c 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -188,6 +188,7 @@ struct genpd_power_state { s64 power_off_latency_ns; s64 power_on_latency_ns; s64 residency_ns; + bool system_state; u64 usage; u64 rejected; u64 above; From 30ecd5d44f41291314945699755e9b8592dafc7c Mon Sep 17 00:00:00 2001 From: Melody Olvera Date: Wed, 15 Oct 2025 16:22:07 +0530 Subject: [PATCH 0896/1133] FROMLIST: dt-bindings: usb: qcom,dwc3: Correct the SM8750 compatible SM8750 does not require an XO clock in the dt as it is the parent of the TCSR refclk_src, so move the compatible to a section where the XO clock is not required. Acked-by: Krzysztof Kozlowski Signed-off-by: Melody Olvera Signed-off-by: Krishna Kurapati Link: https://lore.kernel.org/all/20251015105207.2819689-1-krishna.kurapati@oss.qualcomm.com/#r Signed-off-by: Yash Gupta --- Documentation/devicetree/bindings/usb/qcom,dwc3.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml index a7f58114c02e8..2e2d4562fb03c 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml @@ -227,6 +227,7 @@ allOf: - qcom,sdx65-dwc3 - qcom,sdx75-dwc3 - qcom,sm6350-dwc3 + - qcom,sm8750-dwc3 then: properties: clocks: @@ -366,7 +367,6 @@ allOf: - qcom,sm8450-dwc3 - qcom,sm8550-dwc3 - qcom,sm8650-dwc3 - - qcom,sm8750-dwc3 then: properties: clocks: From 2beea962a24dc27ac64995ad63dfcd78f3fa4072 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Mon, 11 May 2026 15:14:22 +0530 Subject: [PATCH 0897/1133] FROMLIST: usb: dwc3: qcom: Modify interrupt handling for eUSB2 Phy targets eUSB2 targets handle wakeup interrupts differently depending on device speed when operating in host mode. According to the eUSB2 specification, remote wakeup signaling in host mode is detected via different data-line assertions based on the connected device speed. When a low-speed device is connected, the host repeater drives eD+ to logic '1' upon detecting a K-state on the USB lines during remote wakeup (eUSB2 specification, Section 5.5.14). When a full-speed or high-speed device is connected, the host repeater drives eD- to logic '1' upon detecting a K-state on the USB line during remote wakeup (eUSB2 specification, Sections 5.5.15 and 5.5.18). Since the eUSB2 PHY's "DP" and "DM" interrupt lines monitor the eD+ and eD- line states, configure the wakeup interrupts accordingly Link: https://lore.kernel.org/all/20260511094422.3561509-1-krishna.kurapati@oss.qualcomm.com/ Signed-off-by: Krishna Kurapati Signed-off-by: Pratham Pratap --- drivers/usb/dwc3/dwc3-qcom.c | 94 +++++++++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 11 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 4c00b6b87f6d5..8fc4da49059ee 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -62,6 +62,10 @@ static const u32 pwr_evnt_irq_stat_reg[DWC3_QCOM_MAX_PORTS] = { 0x238, }; +struct dwc3_qcom_platform_data { + bool uses_eusb2_phy; +}; + struct dwc3_qcom_port { int qusb2_phy_irq; int dp_hs_phy_irq; @@ -87,6 +91,7 @@ struct dwc3_qcom { struct icc_path *icc_path_apps; enum usb_role current_role; + bool uses_eusb2_phy; }; #define to_dwc3_qcom(d) container_of((d), struct dwc3_qcom, dwc) @@ -274,15 +279,23 @@ static void dwc3_qcom_disable_wakeup_irq(int irq) disable_irq_nosync(irq); } -static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom_port *port) +static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom *qcom, int port_index) { + struct dwc3_qcom_port *port = &qcom->ports[port_index]; + dwc3_qcom_disable_wakeup_irq(port->qusb2_phy_irq); if (port->usb2_speed == USB_SPEED_LOW) { - dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); + if (qcom->uses_eusb2_phy) + dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); + else + dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); } else if ((port->usb2_speed == USB_SPEED_HIGH) || (port->usb2_speed == USB_SPEED_FULL)) { - dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); + if (qcom->uses_eusb2_phy) + dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); + else + dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); } else { dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); @@ -291,8 +304,10 @@ static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom_port *port) dwc3_qcom_disable_wakeup_irq(port->ss_phy_irq); } -static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom_port *port) +static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom *qcom, int port_index) { + struct dwc3_qcom_port *port = &qcom->ports[port_index]; + dwc3_qcom_enable_wakeup_irq(port->qusb2_phy_irq, 0); /* @@ -305,12 +320,20 @@ static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom_port *port) */ if (port->usb2_speed == USB_SPEED_LOW) { - dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, - IRQ_TYPE_EDGE_FALLING); + if (qcom->uses_eusb2_phy) + dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, + IRQ_TYPE_EDGE_RISING); + else + dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, + IRQ_TYPE_EDGE_FALLING); } else if ((port->usb2_speed == USB_SPEED_HIGH) || (port->usb2_speed == USB_SPEED_FULL)) { - dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, - IRQ_TYPE_EDGE_FALLING); + if (qcom->uses_eusb2_phy) + dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, + IRQ_TYPE_EDGE_RISING); + else + dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, + IRQ_TYPE_EDGE_FALLING); } else { dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, IRQ_TYPE_EDGE_RISING); @@ -326,7 +349,7 @@ static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom) int i; for (i = 0; i < qcom->num_ports; i++) - dwc3_qcom_disable_port_interrupts(&qcom->ports[i]); + dwc3_qcom_disable_port_interrupts(qcom, i); } static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) @@ -334,7 +357,7 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) int i; for (i = 0; i < qcom->num_ports; i++) - dwc3_qcom_enable_port_interrupts(&qcom->ports[i]); + dwc3_qcom_enable_port_interrupts(qcom, i); } static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup) @@ -619,6 +642,7 @@ struct dwc3_glue_ops dwc3_qcom_glue_ops = { static int dwc3_qcom_probe(struct platform_device *pdev) { + const struct dwc3_qcom_platform_data *pdata; struct dwc3_probe_data probe_data = {}; struct device *dev = &pdev->dev; struct dwc3_qcom *qcom; @@ -634,6 +658,10 @@ static int dwc3_qcom_probe(struct platform_device *pdev) qcom->dev = &pdev->dev; + pdata = device_get_match_data(dev); + if (pdata) + qcom->uses_eusb2_phy = pdata->uses_eusb2_phy; + qcom->resets = devm_reset_control_array_get_optional_exclusive(dev); if (IS_ERR(qcom->resets)) { return dev_err_probe(&pdev->dev, PTR_ERR(qcom->resets), @@ -848,8 +876,52 @@ static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = { .prepare = pm_sleep_ptr(dwc3_qcom_prepare), }; +static const struct dwc3_qcom_platform_data dwc3_qcom_glymur_pdata = { + .uses_eusb2_phy = true, +}; + static const struct of_device_id dwc3_qcom_of_match[] = { - { .compatible = "qcom,snps-dwc3" }, + { .compatible = "qcom,snps-dwc3", }, + { + .compatible = "qcom,eliza-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,glymur-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,glymur-dwc3-mp", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,kaanapali-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,milos-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,sm8550-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,sm8650-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,sm8750-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,x1e80100-dwc3", + .data = &dwc3_qcom_glymur_pdata, + }, + { + .compatible = "qcom,x1e80100-dwc3-mp", + .data = &dwc3_qcom_glymur_pdata, + }, { } }; MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match); From 1d00a31a31083354bb141c25cebb07a136afd79c Mon Sep 17 00:00:00 2001 From: Nitin Rawat Date: Mon, 13 Jul 2026 23:04:34 +0530 Subject: [PATCH 0898/1133] FROMLIST: scsi: ufs: ufs-qcom: Enable only lane clocks in lane clock APIs ufs_qcom_enable_lane_clks() and ufs_qcom_disable_lane_clks() currently use clk_bulk_prepare_enable()/clk_bulk_disable_unprepare() on the entire host->clks array obtained from devm_clk_bulk_get_all(). This array contains all device clocks, not just lane symbol clocks. Since the UFS core framework already manages the non-lane clocks via the setup_clocks callback, the bulk enable/disable in the lane clock APIs resulted in duplicate reference count increments on those shared clocks. The extra enable counts were never balanced by a corresponding disable from the framework's clock gating path, preventing the clock reference counts from reaching zero and ultimately blocking CXO shutdown during low-power states. Fix this by restricting the lane clock APIs to only prepare/enable and disable/unprepare the three lane symbol clocks (tx_lane0_sync_clk, rx_lane0_sync_clk, rx_lane1_sync_clk), leaving the handling of all other clocks to the UFS core framewore. Link: https://lore.kernel.org/linux-scsi/20260713173434.883386-1-nitin.rawat@oss.qualcomm.com/ Signed-off-by: Nitin Rawat Signed-off-by: Giri Prasad Goriparthi --- drivers/ufs/host/ufs-qcom.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index d4eef4b54126d..2f9ce34aabda4 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -374,7 +374,6 @@ static int ufs_qcom_enable_lane_clks(struct ufs_qcom_host *host) goto out_disable_rx_lane0; host->is_lane_clks_enabled = true; - return 0; out_disable_rx_lane0: From 4d27d6c84174ddc052fe5ac8f8c3531186493277 Mon Sep 17 00:00:00 2001 From: Ziqi Chen Date: Sat, 29 Aug 2026 13:13:54 +0530 Subject: [PATCH 0899/1133] FROMLIST: scsi: ufs: ufs-qcom: Add specified gear support for multi gear scaling The UFS clock frequency and gear speed do not necessarily have a strict one-to-one correspondence on all platforms. Introduce a device tree based configuration interface that allows specifying the HS gear speed for each supported operating frequency via the "opp-level" property in the OPP table. When this property is not configured, the driver falls back to the default frequency-to-gear mapping table. Signed-off-by: Ziqi Chen Signed-off-by: Nitin Rawat Signed-off-by: Giri Prasad Goriparthi --- drivers/ufs/host/ufs-qcom.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 2f9ce34aabda4..640bdc1178dd7 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -2519,8 +2519,9 @@ static unsigned long ufs_qcom_opp_freq_to_clk_freq(struct ufs_hba *hba, bool found = false; opp = dev_pm_opp_find_freq_exact_indexed(hba->dev, freq, 0, true); - if (IS_ERR(opp)) { - dev_err(hba->dev, "Failed to find OPP for exact frequency %lu\n", freq); + if (IS_ERR_OR_NULL(opp)) { + dev_err(hba->dev, "%s: Failed to find OPP for exact frequency %lu\n", + __func__, freq); return 0; } @@ -2548,12 +2549,32 @@ static unsigned long ufs_qcom_opp_freq_to_clk_freq(struct ufs_hba *hba, static u32 ufs_qcom_freq_to_gear_speed(struct ufs_hba *hba, unsigned long freq) { - u32 gear = UFS_HS_DONT_CHANGE; + struct dev_pm_opp *opp; unsigned long unipro_freq; + u32 gear = UFS_HS_DONT_CHANGE; if (!hba->use_pm_opp) return gear; + opp = dev_pm_opp_find_freq_exact_indexed(hba->dev, freq, 0, true); + if (IS_ERR_OR_NULL(opp)) { + dev_err(hba->dev, "%s: Failed to find OPP for exact frequency %lu\n", + __func__, freq); + return gear; + } + + /* Get HS gear speed from 'opp-level' */ + gear = dev_pm_opp_get_level(opp); + dev_pm_opp_put(opp); + + /* + * Greater than max gear means that there is no specified gear configured in DT + * or the specified gear is invalid. + */ + if (gear <= hba->max_pwr_info.info.gear_rx) + return gear; + + gear = UFS_HS_DONT_CHANGE; unipro_freq = ufs_qcom_opp_freq_to_clk_freq(hba, freq, "core_clk_unipro"); switch (unipro_freq) { case 403000000: @@ -2574,7 +2595,8 @@ static u32 ufs_qcom_freq_to_gear_speed(struct ufs_hba *hba, unsigned long freq) gear = UFS_HS_G1; break; default: - dev_err(hba->dev, "%s: Unsupported clock freq : %lu\n", __func__, freq); + dev_err(hba->dev, "%s: Unsupported clock freq [sys_clk: %lu, unipro_clk: %lu]\n", + __func__, freq, unipro_freq); return UFS_HS_DONT_CHANGE; } From 6d3aec444d09544b3b051faf8dd128c23677689c Mon Sep 17 00:00:00 2001 From: Nitin Rawat Date: Sat, 29 Aug 2026 13:13:55 +0530 Subject: [PATCH 0900/1133] FROMLIST: arm64: dts: qcom: Set specified gear configuration for Hamoa Assign the appropriate UFS HS gear speed levels to each OPP frequency entry in the device tree, enabling proper per-frequency gear scaling (G1 at 75MHz, G3 at 150MHz, G5 at 300MHz). Signed-off-by: Nitin Rawat Signed-off-by: Giri Prasad Goriparthi --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 48f47aa6ba3c7..2dfebe799cb1d 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -3943,6 +3943,7 @@ /bits/ 64 <0>, /bits/ 64 <0>, /bits/ 64 <0>; + opp-level = <1>; /* HS-G1 */ required-opps = <&rpmhpd_opp_low_svs>; }; @@ -3955,6 +3956,7 @@ /bits/ 64 <0>, /bits/ 64 <0>, /bits/ 64 <0>; + opp-level = <3>; /* HS-G3 */ required-opps = <&rpmhpd_opp_svs>; }; @@ -3967,6 +3969,7 @@ /bits/ 64 <0>, /bits/ 64 <0>, /bits/ 64 <0>; + opp-level = <5>; /* HS-G5 */ required-opps = <&rpmhpd_opp_nom>; }; }; From cdcc30050ae91f45cbec38b0855b38b7e8c94869 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Thu, 23 Jul 2026 16:24:56 +0530 Subject: [PATCH 0901/1133] FROMLIST: usb: dwc3: qcom: Add support to skip phy management by USB core DWC3 driver does manage phys itself sufficiently for Qualcomm platforms. If xhci-skip-phy-init is not set, the HCD core does a phy_init and phy_ exit is done only when roothub is being destroyed. Due to this, during system suspend in host mode, although phy_exit is done by DWC3 core, the init_count on phy is never down to zero since HCD core also did an init. consequently causing phy's exit routine to not be called. Hence, add support to skip phy management by USB core. Some Exynos platforms still do rely on USB core for phy_calibrate calls, hence disable USB core management for Qualcomm platforms only. Signed-off-by: Krishna Kurapati Acked-by: Thinh Nguyen Link: https://lore.kernel.org/all/20260723-dwc3-skip-init-quirk-v1-1-97682bb44ebd@oss.qualcomm.com/ --- drivers/usb/dwc3/dwc3-qcom.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 8fc4da49059ee..b8323af552c6a 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "core.h" #include "glue.h" @@ -444,6 +445,16 @@ static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data) return IRQ_HANDLED; } +static int dwc3_qcom_set_swnode(struct device *dev) +{ + const struct property_entry props[] = { + PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"), + {} + }; + + return device_create_managed_software_node(dev, props, NULL); +} + static void dwc3_qcom_select_utmi_clk(struct dwc3_qcom *qcom) { /* Configure dwc3 to use UTMI clock as PIPE clock not present */ @@ -721,6 +732,10 @@ static int dwc3_qcom_probe(struct platform_device *pdev) if (ignore_pipe_clk) dwc3_qcom_select_utmi_clk(qcom); + ret = dwc3_qcom_set_swnode(dev); + if (ret) + goto clk_disable; + qcom->mode = usb_get_dr_mode(dev); if (qcom->mode == USB_DR_MODE_HOST) { From 0d01cf27fc9658d854655092337077e422916beb Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Wed, 9 Sep 2026 15:19:10 +0530 Subject: [PATCH 0902/1133] UPSTREAM: Revert "usb: dwc3: qcom: Add support to skip phy management by USB core" This reverts commit be7b1c68cd3e4fc0f5a4e1b85696de1052f21f2f. Commit be7b1c68cd3e ("usb: dwc3: qcom: Add support to skip phy management by USB core") is causing a regression on qualcomm platforms. During role switch it tends to cause the following crash: [ 5.620951] refcount_t: underflow; use-after-free. [ 5.621114] Call trace: [ 5.621115] refcount_warn_saturate+0xd8/0x140 (P) [ 5.621117] kobject_put+0x11c/0x230 [ 5.621121] software_node_notify_remove+0xdc/0xf8 [ 5.621124] device_del+0x1dc/0x328 [ 5.621126] usb_disconnect+0x1d8/0x348 [ 5.621129] usb_remove_hcd+0x100/0x2a8 [ 5.621131] xhci_plat_remove+0x8c/0x170 [ 5.621134] platform_remove+0x28/0x40 [ 5.621135] device_release_driver_internal+0x174/0x290 [ 5.621138] device_release_driver+0x20/0x38 [ 5.621140] bus_remove_device+0x19c/0x1f8 [ 5.621142] device_del+0x1c4/0x328 [ 5.621143] platform_device_unregister+0x34/0xc0 [ 5.621145] dwc3_host_exit+0x50/0x70 [ 5.621146] __dwc3_set_mode+0xa4/0x378 [ 5.644535] Unable to handle kernel paging request at virtual address [ 5.644657] Workqueue: events_freezable __dwc3_set_mode [ 5.644664] pc : __pi_strcmp+0x9c/0x140 [ 5.644668] lr : software_node_property_present+0x60/0x98 [ 5.644697] Call trace: [ 5.644698] __pi_strcmp+0x9c/0x140 (P) [ 5.644700] device_property_present+0x9c/0xc0 [ 5.644703] dwc3_gadget_init+0x230/0x7b0 [ 5.644704] __dwc3_set_mode+0x314/0x378 [ 5.644707] process_scheduled_works+0x1b8/0x538 [ 5.644710] worker_thread+0x1fc/0x2f8 [ 5.644711] kthread+0x114/0x148 [ 5.644713] ret_from_fork+0x10/0x20 Revert skipping of usb core phy management for Qualcomm platforms to avoid the above issues. Reported-by: Val Packett Closes: https://lore.kernel.org/all/f9926203-ee69-4e18-b6c7-95261ba10807@packett.cool/ Signed-off-by: Krishna Kurapati Acked-by: Thinh Nguyen Tested-by: Shawn Guo Link: https://patch.msgid.link/20260909-xhci-fixes-revert-v1-1-7cc97fa0f307@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/dwc3-qcom.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index b8323af552c6a..1745a150def8c 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -445,16 +445,6 @@ static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data) return IRQ_HANDLED; } -static int dwc3_qcom_set_swnode(struct device *dev) -{ - const struct property_entry props[] = { - PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"), - {} - }; - - return device_create_managed_software_node(dev, props, NULL); -} - static void dwc3_qcom_select_utmi_clk(struct dwc3_qcom *qcom) { /* Configure dwc3 to use UTMI clock as PIPE clock not present */ @@ -732,10 +722,6 @@ static int dwc3_qcom_probe(struct platform_device *pdev) if (ignore_pipe_clk) dwc3_qcom_select_utmi_clk(qcom); - ret = dwc3_qcom_set_swnode(dev); - if (ret) - goto clk_disable; - qcom->mode = usb_get_dr_mode(dev); if (qcom->mode == USB_DR_MODE_HOST) { From 36754d5e16e8bbb236c29b11483f0897ae9cda94 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Thu, 23 Jul 2026 16:24:56 +0530 Subject: [PATCH 0903/1133] FROMLIST: usb: dwc3: qcom: Add support to skip phy management by USB core DWC3 driver does manage phys itself sufficiently for Qualcomm platforms. If xhci-skip-phy-init is not set, the HCD core does a phy_init and phy_ exit is done only when roothub is being destroyed. Due to this, during system suspend in host mode, although phy_exit is done by DWC3 core, the init_count on phy is never down to zero since HCD core also did an init. consequently causing phy's exit routine to not be called. Hence, add support to skip phy management by USB core. Some Exynos platforms still do rely on USB core for phy_calibrate calls, hence disable USB core management for Qualcomm platforms only. Link: https://lore.kernel.org/all/20260914-xhci-skip-phy-init-v1-1-9c46b31a5a39@oss.qualcomm.com/#t Signed-off-by: Krishna Kurapati --- drivers/usb/dwc3/dwc3-qcom.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 1745a150def8c..b8323af552c6a 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -445,6 +445,16 @@ static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data) return IRQ_HANDLED; } +static int dwc3_qcom_set_swnode(struct device *dev) +{ + const struct property_entry props[] = { + PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"), + {} + }; + + return device_create_managed_software_node(dev, props, NULL); +} + static void dwc3_qcom_select_utmi_clk(struct dwc3_qcom *qcom) { /* Configure dwc3 to use UTMI clock as PIPE clock not present */ @@ -722,6 +732,10 @@ static int dwc3_qcom_probe(struct platform_device *pdev) if (ignore_pipe_clk) dwc3_qcom_select_utmi_clk(qcom); + ret = dwc3_qcom_set_swnode(dev); + if (ret) + goto clk_disable; + qcom->mode = usb_get_dr_mode(dev); if (qcom->mode == USB_DR_MODE_HOST) { From 5929ee035ff8ad299f49b841ae9ee8cdf89428ad Mon Sep 17 00:00:00 2001 From: Pradeep P V K Date: Fri, 11 Sep 2026 22:12:57 +0530 Subject: [PATCH 0904/1133] FROMLIST: phy: qcom-qmp-ufs: Add Glymur support Add the init sequence tables and config for the UFS QMP phy found in the Glymur SoC. Link: https://lore.kernel.org/all/20260911-glymur_ufs_qcb_enablement-v1-5-b9fc5e2ee99a@oss.qualcomm.com/ Signed-off-by: Pradeep P V K --- drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 99 +++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c index d15db9ab9a90c..f441b26bb8a6f 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c @@ -93,6 +93,59 @@ static const unsigned int ufsphy_v7_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V7_PCS_UFS_POWER_DOWN_CONTROL, }; +static const struct qmp_phy_init_tbl glymur_ufsphy_rx[] = { + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_FO_GAIN_RATE2, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_FO_GAIN_RATE4, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_SO_GAIN_RATE4, 0x04), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x14), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_PI_CONTROLS, 0x07), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_OFFSET_ADAPTOR_CNTRL3, 0x0e), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4, 0x02), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_FASTLOCK_FO_GAIN_RATE4, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_FASTLOCK_SO_GAIN_RATE4, 0x06), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_VGA_CAL_MAN_VAL, 0xce), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_EQU_ADAPTOR_CNTRL4, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B0, 0xce), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B1, 0xce), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B2, 0x18), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B3, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B4, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B6, 0x60), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE_0_1_B7, 0x62), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE2_B3, 0x9a), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE2_B6, 0xe2), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE2_B7, 0x06), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B0, 0x1b), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B1, 0x1b), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B2, 0x98), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B3, 0x9b), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B4, 0x2a), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B5, 0x12), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B7, 0x06), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE3_B8, 0x01), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B0, 0x93), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B1, 0x93), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B2, 0x60), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B3, 0x99), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B4, 0x5f), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B5, 0x92), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B6, 0xe3), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SA_B7, 0x06), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B0, 0x24), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B1, 0x24), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B2, 0xe0), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B3, 0x99), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B4, 0x5f), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B5, 0x92), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B6, 0xfb), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_MODE_RATE4_SB_B7, 0x06), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_SO_SATURATION, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_UCDR_PI_CTRL1, 0x94), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_TERM_BW_CTRL0, 0xfa), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_DLL0_FTUNE_CTRL, 0x30), + QMP_PHY_INIT_CFG(QSERDES_UFS_V7_RX_SIGDET_CAL_TRIM, 0x77), +}; + static const struct qmp_phy_init_tbl milos_ufsphy_serdes[] = { QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9), QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16), @@ -1212,6 +1265,11 @@ struct qmp_ufs { }; /* Regulator bulk data with load values for specific configurations */ +static const struct regulator_bulk_data glymur_ufsphy_vreg_l[] = { + { .supply = "vdda-phy", .init_load_uA = 217130 }, + { .supply = "vdda-pll", .init_load_uA = 18340 }, +}; + static const struct regulator_bulk_data milos_ufsphy_vreg_l[] = { { .supply = "vdda-phy", .init_load_uA = 140120 }, { .supply = "vdda-pll", .init_load_uA = 18340 }, @@ -1324,6 +1382,44 @@ static const struct qmp_ufs_offsets qmp_ufs_offsets_v7 = { .rx2 = 0x3000, }; +static const struct qmp_phy_cfg glymur_ufsphy_cfg = { + .lanes = 2, + + .offsets = &qmp_ufs_offsets_v6, + .max_supported_gear = UFS_HS_G5, + + .tbls = { + .serdes = sm8750_ufsphy_serdes, + .serdes_num = ARRAY_SIZE(sm8750_ufsphy_serdes), + .tx = sm8750_ufsphy_tx, + .tx_num = ARRAY_SIZE(sm8750_ufsphy_tx), + .rx = glymur_ufsphy_rx, + .rx_num = ARRAY_SIZE(glymur_ufsphy_rx), + .pcs = sm8750_ufsphy_pcs, + .pcs_num = ARRAY_SIZE(sm8750_ufsphy_pcs), + }, + + .tbls_hs_b = { + .pcs = sm8750_ufsphy_hs_b_pcs, + .pcs_num = ARRAY_SIZE(sm8750_ufsphy_hs_b_pcs), + }, + + .tbls_hs_overlay[0] = { + .pcs = sm8750_ufsphy_g4_pcs, + .pcs_num = ARRAY_SIZE(sm8750_ufsphy_g4_pcs), + .max_gear = UFS_HS_G4, + }, + .tbls_hs_overlay[1] = { + .pcs = sm8650_ufsphy_g5_pcs, + .pcs_num = ARRAY_SIZE(sm8650_ufsphy_g5_pcs), + .max_gear = UFS_HS_G5, + }, + + .vreg_list = glymur_ufsphy_vreg_l, + .num_vregs = ARRAY_SIZE(glymur_ufsphy_vreg_l), + .regs = ufsphy_v6_regs_layout, +}; + static const struct qmp_phy_cfg milos_ufsphy_cfg = { .lanes = 2, @@ -2371,6 +2467,9 @@ static int qmp_ufs_probe(struct platform_device *pdev) static const struct of_device_id qmp_ufs_of_match_table[] = { { + .compatible = "qcom,glymur-qmp-ufs-phy", + .data = &glymur_ufsphy_cfg, + }, { .compatible = "qcom,hawi-qmp-ufs-phy", .data = &hawi_ufsphy_cfg, }, { From ce8e8ed4dcac055bbbc8588909ca87f86eb723fe Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Thu, 24 Sep 2026 12:12:30 +0530 Subject: [PATCH 0905/1133] Revert "FROMLIST: usb: dwc3: qcom: Add support to skip phy management by USB core" This reverts commit 590cde5f7fa51b93bc0fe01f4f1249816d5c4939. --- drivers/usb/dwc3/dwc3-qcom.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index b8323af552c6a..1745a150def8c 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -445,16 +445,6 @@ static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data) return IRQ_HANDLED; } -static int dwc3_qcom_set_swnode(struct device *dev) -{ - const struct property_entry props[] = { - PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"), - {} - }; - - return device_create_managed_software_node(dev, props, NULL); -} - static void dwc3_qcom_select_utmi_clk(struct dwc3_qcom *qcom) { /* Configure dwc3 to use UTMI clock as PIPE clock not present */ @@ -732,10 +722,6 @@ static int dwc3_qcom_probe(struct platform_device *pdev) if (ignore_pipe_clk) dwc3_qcom_select_utmi_clk(qcom); - ret = dwc3_qcom_set_swnode(dev); - if (ret) - goto clk_disable; - qcom->mode = usb_get_dr_mode(dev); if (qcom->mode == USB_DR_MODE_HOST) { From 1cb69555e79ecb65111499303f2b75656f70624d Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Mon, 14 Sep 2026 20:05:58 +0530 Subject: [PATCH 0906/1133] FROMLIST: usb: dwc3: qcom: Add support to skip phy management by USB core DWC3 driver does manage phys itself sufficiently for Qualcomm platforms. If xhci-skip-phy-init is not set, the HCD core does a phy_init and phy_ exit is done only when roothub is being destroyed. Due to this, during system suspend in host mode, although phy_exit is done by DWC3 core, the init_count on phy is never down to zero since HCD core also did an init. consequently causing phy's exit routine to not be called. Hence, add support to skip phy management by USB core. Some Exynos platforms still do rely on USB core for phy_calibrate calls, hence disable USB core management for Qualcomm platforms only. Acked-by: Thinh Nguyen Signed-off-by: Krishna Kurapati Link: https://lore.kernel.org/all/20260914-xhci-skip-phy-init-v1-1-9c46b31a5a39@oss.qualcomm.com/ --- drivers/usb/dwc3/core.c | 3 +++ drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/dwc3-qcom.c | 1 + drivers/usb/dwc3/glue.h | 2 ++ drivers/usb/dwc3/host.c | 5 ++++- 5 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 517aa7f1486da..d4d7345e010e8 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1694,6 +1694,9 @@ static void dwc3_get_software_properties(struct dwc3 *dwc, if (properties->needs_full_reinit) dwc->needs_full_reinit = true; + if (properties->skip_phy_init) + dwc->skip_phy_init = true; + dwc->gsbuscfg0_reqinfo = DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED; if (properties->gsbuscfg0_reqinfo != diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index e0dee9d287401..86c407973241a 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1415,6 +1415,7 @@ struct dwc3 { unsigned wakeup_configured:1; unsigned suspended:1; unsigned susphy_state:1; + unsigned skip_phy_init:1; u16 imod_interval; diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 1745a150def8c..84cb1c44afb62 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -744,6 +744,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev) probe_data.res = &res; probe_data.ignore_clocks_and_resets = true; probe_data.properties = DWC3_DEFAULT_PROPERTIES; + probe_data.properties.skip_phy_init = true; ret = dwc3_core_probe(&probe_data); if (ret) { ret = dev_err_probe(dev, ret, "failed to register DWC3 Core\n"); diff --git a/drivers/usb/dwc3/glue.h b/drivers/usb/dwc3/glue.h index d738e1739ae01..72c5593e657a9 100644 --- a/drivers/usb/dwc3/glue.h +++ b/drivers/usb/dwc3/glue.h @@ -14,10 +14,12 @@ * @gsbuscfg0_reqinfo: Value to be programmed in the GSBUSCFG0.REQINFO field * @needs_full_reinit: indicate the controller may not remain power during system * pm and need full initialization + * @skip_phy_init: skip xHCI PHY initialization on host init */ struct dwc3_properties { u32 gsbuscfg0_reqinfo; unsigned needs_full_reinit:1; + unsigned skip_phy_init:1; }; #define DWC3_DEFAULT_PROPERTIES ((struct dwc3_properties){ \ diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index 96b588bd08cdc..97bdd09abf271 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -129,7 +129,7 @@ static int dwc3_host_get_irq(struct dwc3 *dwc) int dwc3_host_init(struct dwc3 *dwc) { - struct property_entry props[6]; + struct property_entry props[7]; struct platform_device *xhci; int ret, irq; int prop_idx = 0; @@ -173,6 +173,9 @@ int dwc3_host_init(struct dwc3 *dwc) if (dwc->usb2_lpm_disable) props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb2-lpm-disable"); + if (dwc->skip_phy_init) + props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"); + /** * WORKAROUND: dwc3 revisions <=3.00a have a limitation * where Port Disable command doesn't work. From 6998fc24bc71fe309787b67c0f81559d3317bf73 Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Tue, 31 Mar 2026 17:17:39 +0530 Subject: [PATCH 0907/1133] FROMLIST: dt-bindings: i2c: qcom,i2c-geni: Document multi-owner controller support Document a DeviceTree property to describe QUP-based I2C controllers that are shared with one or more other system processors. On some Qualcomm platforms, a QUP-based I2C controller may be accessed by multiple system processors (for example, APPS and DSP). In such configurations, the operating system must not assume exclusive ownership of the controller or its associated hardware resources. The new qcom,qup-multi-owner property indicates that the controller is externally shared and that the operating system must avoid operations which rely on sole control of the hardware. Link: https://lore.kernel.org/all/20260331114742.2896317-2-mukesh.savaliya@oss.qualcomm.com/ Signed-off-by: Mukesh Kumar Savaliya --- .../devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml index 51534953a69cf..9401dc2d50522 100644 --- a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml +++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml @@ -60,6 +60,13 @@ properties: power-domains: maxItems: 1 + qcom,qup-multi-owner: + type: boolean + description: + Indicates that the QUP-based controller is shared with one or more + other system processors and must not be assumed to have exclusive + ownership by the operating system. + reg: maxItems: 1 From 9d0f6cd473bdf427fa5add791479084c0ad9a591 Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Tue, 31 Mar 2026 17:17:40 +0530 Subject: [PATCH 0908/1133] FROMLIST: dmaengine: qcom: gpi: Add lock/unlock TREs for multi-owner I2C transfers Some platforms use a QUP-based I2C controller in a configuration where the controller is shared with another system processor (described in DT using qcom,qup-multi-owner). In such setups, GPI hardware lock/unlock TREs can be used to serialize access to the controller. Add support to emit lock and unlock TREs around I2C transfers and increase the maximum TRE count to account for the additional elements. Also simplify the client interface by replacing multiple boolean fields (shared flag and message position tracking) with a single lock_action selector (acquire/release/none), as the GPI driver only needs to know whether to emit lock/unlock TREs for a given transfer. Link: https://lore.kernel.org/all/20260331114742.2896317-3-mukesh.savaliya@oss.qualcomm.com/ Signed-off-by: Mukesh Kumar Savaliya --- drivers/dma/qcom/gpi.c | 44 +++++++++++++++++++++++++++++++- include/linux/dma/qcom-gpi-dma.h | 20 ++++++++++++++- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index c41bfac65ddf3..7eb38c6911413 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2020, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -67,6 +68,14 @@ #define TRE_DMA_LEN GENMASK(23, 0) #define TRE_DMA_IMMEDIATE_LEN GENMASK(3, 0) +/* Lock TRE */ +#define TRE_LOCK BIT(0) +#define TRE_MINOR_TYPE GENMASK(19, 16) +#define TRE_MAJOR_TYPE GENMASK(23, 20) + +/* Unlock TRE */ +#define TRE_UNLOCK BIT(8) + /* Register offsets from gpi-top */ #define GPII_n_CH_k_CNTXT_0_OFFS(n, k) (0x20000 + (0x4000 * (n)) + (0x80 * (k))) #define GPII_n_CH_k_CNTXT_0_EL_SIZE GENMASK(31, 24) @@ -518,7 +527,7 @@ struct gpii { bool ieob_set; }; -#define MAX_TRE 3 +#define MAX_TRE 5 struct gpi_desc { struct virt_dma_desc vd; @@ -1625,12 +1634,27 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc, unsigned long flags) { struct gpi_i2c_config *i2c = chan->config; + enum gpi_lock_action lock_action = i2c->lock_action; struct device *dev = chan->gpii->gpi_dev->dev; unsigned int tre_idx = 0; dma_addr_t address; struct gpi_tre *tre; unsigned int i; + /* Optional lock TRE before transfer */ + if (lock_action == GPI_LOCK_ACQUIRE) { + tre = &desc->tre[tre_idx]; + tre_idx++; + + tre->dword[0] = 0; + tre->dword[1] = 0; + tre->dword[2] = 0; + tre->dword[3] = u32_encode_bits(1, TRE_LOCK); + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB); + tre->dword[3] |= u32_encode_bits(0, TRE_MINOR_TYPE); + tre->dword[3] |= u32_encode_bits(3, TRE_MAJOR_TYPE); + } + /* first create config tre if applicable */ if (i2c->set_config) { tre = &desc->tre[tre_idx]; @@ -1690,6 +1714,24 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc, if (!(flags & DMA_PREP_INTERRUPT)) tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_BEI); + + /* If multi-owner and this is the release boundary, chain it */ + if (i2c->lock_action == GPI_LOCK_RELEASE) + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_CHAIN); + } + + /* Optional unlock TRE after transfer */ + if (lock_action == GPI_LOCK_RELEASE && i2c->op != I2C_READ) { + tre = &desc->tre[tre_idx]; + tre_idx++; + + tre->dword[0] = 0; + tre->dword[1] = 0; + tre->dword[2] = 0; + tre->dword[3] = u32_encode_bits(1, TRE_UNLOCK); + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB); + tre->dword[3] |= u32_encode_bits(1, TRE_MINOR_TYPE); + tre->dword[3] |= u32_encode_bits(3, TRE_MAJOR_TYPE); } for (i = 0; i < tre_idx; i++) diff --git a/include/linux/dma/qcom-gpi-dma.h b/include/linux/dma/qcom-gpi-dma.h index 332be28427e47..f10fa93713f96 100644 --- a/include/linux/dma/qcom-gpi-dma.h +++ b/include/linux/dma/qcom-gpi-dma.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2020, Linaro Limited + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #ifndef QCOM_GPI_DMA_H @@ -54,6 +55,21 @@ enum i2c_op { I2C_READ, }; +/** + * enum gpi_lock_action - request lock/unlock TRE sequencing + * @GPI_LOCK_NONE: No lock/unlock TRE requested for this transfer + * @GPI_LOCK_ACQUIRE: Emit a lock TRE before the transfer + * @GPI_LOCK_RELEASE: Emit an unlock TRE after the transfer + * + * Used by protocol drivers for multi-owner controller setups (e.g. when + * DeviceTree indicates the controller is shared via qcom,qup-multi-owner). + */ +enum gpi_lock_action { + GPI_LOCK_NONE = 0, + GPI_LOCK_ACQUIRE, + GPI_LOCK_RELEASE, +}; + /** * struct gpi_i2c_config - i2c config for peripheral * @@ -67,7 +83,8 @@ enum i2c_op { * @set_config: set peripheral config * @rx_len: receive length for buffer * @op: i2c cmd - * @multi_msg: is part of multi i2c r-w msgs + * @muli-msg: is part of multi i2c r-w msgs + * @lock_action: request lock/unlock TRE sequencing for this transfer */ struct gpi_i2c_config { u8 set_config; @@ -81,6 +98,7 @@ struct gpi_i2c_config { u32 rx_len; enum i2c_op op; bool multi_msg; + enum gpi_lock_action lock_action; }; #endif /* QCOM_GPI_DMA_H */ From 60d3b845bd8af11886b9eb89fe359ed5a3490dca Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Tue, 31 Mar 2026 17:17:41 +0530 Subject: [PATCH 0909/1133] FROMLIST: soc: qcom: geni-se: Keep pinctrl active for multi-owner controllers On platforms where a GENI Serial Engine is shared with another system processor, selecting the "sleep" pinctrl state can disrupt ongoing transfers initiated by the other processor. Teach geni_se_resources_off() to skip selecting the pinctrl sleep state when the Serial Engine is marked as shared, while still allowing the rest of the resource shutdown sequence to proceed. This is required for multi-owner configurations (described via DeviceTree with qcom,qup-multi-owner on the protocol controller node). Link: https://lore.kernel.org/all/20260331114742.2896317-4-mukesh.savaliya@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Signed-off-by: Mukesh Kumar Savaliya --- drivers/soc/qcom/qcom-geni-se.c | 15 +++++++++++---- include/linux/soc/qcom/geni-se.h | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 074087c592cc3..3590106c39be4 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -613,10 +613,17 @@ int geni_se_resources_off(struct geni_se *se) if (has_acpi_companion(se->dev)) return 0; - - ret = pinctrl_pm_select_sleep_state(se->dev); - if (ret) - return ret; + /* + * Select the "sleep" pinctrl state only when the serial engine is + * exclusively owned by this system processor. For shared controller + * configurations, another system processor may still be using the pins, + * and switching them to "sleep" can disrupt ongoing transfers. + */ + if (!se->multi_owner) { + ret = pinctrl_pm_select_sleep_state(se->dev); + if (ret) + return ret; + } geni_se_clks_off(se); return 0; diff --git a/include/linux/soc/qcom/geni-se.h b/include/linux/soc/qcom/geni-se.h index b3372a3147a00..6b12040745154 100644 --- a/include/linux/soc/qcom/geni-se.h +++ b/include/linux/soc/qcom/geni-se.h @@ -66,6 +66,7 @@ struct geni_icc_path { * @icc_paths: Array of ICC paths for SE * @pd_list: Power domain list for managing power domains * @has_opp: Indicates if OPP is supported + * @multi_owner: True if SE is shared between multiprocessors. */ struct geni_se { void __iomem *base; @@ -78,6 +79,7 @@ struct geni_se { struct geni_icc_path icc_paths[3]; struct dev_pm_domain_list *pd_list; bool has_opp; + bool multi_owner; }; /* Common SE registers */ From f643af440748cf0ec78cdf725bcb49b8a9b32634 Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Tue, 31 Mar 2026 17:17:42 +0530 Subject: [PATCH 0910/1133] FROMLIST: i2c: qcom-geni: Support multi-owner controllers in GPI mode Some platforms use a QUP-based I2C controller in a configuration where the controller is shared with another system processor. In this setup the operating system must not assume exclusive ownership of the controller or its associated pins. Add support for enabling multi-owner operation when DeviceTree specifies qcom,qup-multi-owner. When enabled, mark the underlying serial engine as shared so the common GENI resource handling avoids selecting the "sleep" pinctrl state, which could disrupt transfers initiated by the other processor. For GPI mode transfers, request lock/unlock TRE sequencing from the GPI driver by setting a single lock_action selector per message, emitting lock before the first message and unlock after the last message (handling the single-message case as well). This serializes access to the shared controller without requiring message-position flags to be passed into the DMA engine layer. Link: https://lore.kernel.org/all/20260331114742.2896317-5-mukesh.savaliya@oss.qualcomm.com/ Signed-off-by: Mukesh Kumar Savaliya --- drivers/i2c/busses/i2c-qcom-geni.c | 31 +++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 50f4fc1330859..76104c174d4fe 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -938,6 +938,14 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i if (i < num - 1) peripheral.stretch = 1; + peripheral.lock_action = GPI_LOCK_NONE; + if (gi2c->se.multi_owner) { + if (i == 0) + peripheral.lock_action = GPI_LOCK_ACQUIRE; + else if (i == num - 1) + peripheral.lock_action = GPI_LOCK_RELEASE; + } + peripheral.addr = msgs[i].addr; if (i > 0 && (!(msgs[i].flags & I2C_M_RD))) peripheral.multi_msg = false; @@ -1126,7 +1134,9 @@ static int geni_i2c_init(struct geni_i2c_dev *gi2c) } if (fifo_disable) { - /* FIFO is disabled, so we can only use GPI DMA */ + /* FIFO is disabled, so we can only use GPI DMA. + * SE can be shared in GSI mode between subsystems, each SS owns a GPII. + */ gi2c->gpi_mode = true; ret = setup_gpi_dma(gi2c); if (ret) @@ -1135,6 +1145,11 @@ static int geni_i2c_init(struct geni_i2c_dev *gi2c) dev_dbg(gi2c->se.dev, "Using GPI DMA mode for I2C\n"); } else { gi2c->gpi_mode = false; + + if (gi2c->se.multi_owner) + dev_err_probe(gi2c->se.dev, -EINVAL, + "I2C sharing not supported in non GSI mode\n"); + tx_depth = geni_se_get_tx_fifo_depth(&gi2c->se); /* I2C Master Hub Serial Elements doesn't have the HW_PARAM_0 register */ @@ -1204,6 +1219,20 @@ static int geni_i2c_probe(struct platform_device *pdev) gi2c->clk_freq_out = I2C_MAX_STANDARD_MODE_FREQ; } + if (of_property_read_bool(pdev->dev.of_node, "qcom,qup-multi-owner")) { + /* + * Multi-owner controller configuration: the controller may be + * used by another system processor. Mark the SE as shared so + * common GENI resource handling can avoid pin state changes + * that would disrupt the other user. + */ + gi2c->se.multi_owner = true; + dev_dbg(&pdev->dev, "I2C controller is shared with another system processor\n"); + } + + if (has_acpi_companion(dev)) + ACPI_COMPANION_SET(&gi2c->adap.dev, ACPI_COMPANION(dev)); + gi2c->irq = platform_get_irq(pdev, 0); if (gi2c->irq < 0) return gi2c->irq; From 586218f318ddd5dd2268201338c9026c00f942d6 Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Mon, 29 Jun 2026 19:11:40 +0530 Subject: [PATCH 0911/1133] FROMLIST: i2c: i2c-qcom-geni: serve transfers during early resume I2C transfers issued during the resume_noirq phase can fail on GENI I2C controllers. Some devices require I2C communication before their resume sequence can complete. One example is a USB Ethernet device attached through PCIe, where device configuration must be restored over I2C before PCIe link initialization can proceed. Since such accesses occur during resume_noirq(), the underlying I2C controller must be able to service transfers at that stage. However, GENI I2C transfers rely on interrupts for command completion, while IRQ handling is still suspended during early resume. Additionally, runtime PM may remain disabled until later in the resume sequence, causing pm_runtime_get_sync() to return -EACCES and preventing controller resources from being enabled. Allow the controller to operate during early resume by requesting the IRQ with IRQF_NO_SUSPEND and IRQF_EARLY_RESUME so completion interrupts can be delivered during the noirq phase. Also restore runtime PM from resume_noirq() when it is disabled and tolerate transient -EACCES failures from pm_runtime_get_sync() during the PM state transition. This enables GENI I2C transfers to complete successfully during the resume_noirq phase and allows dependent devices to finish their resume sequence. Link: https://lore.kernel.org/all/20260629134140.755193-1-mukesh.savaliya@oss.qualcomm.com/ Co-developed-by: Viken Dadhaniya Signed-off-by: Mukesh Kumar Savaliya Signed-off-by: Viken Dadhaniya --- drivers/dma/qcom/gpi.c | 3 ++- drivers/i2c/busses/i2c-qcom-geni.c | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index 7eb38c6911413..5b01cc6e112ef 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -624,7 +624,8 @@ static int gpi_config_interrupts(struct gpii *gpii, enum gpii_irq_settings setti if (!gpii->configured_irq) { ret = devm_request_irq(gpii->gpi_dev->dev, gpii->irq, - gpi_handle_irq, IRQF_TRIGGER_HIGH, + gpi_handle_irq, + IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND | IRQF_EARLY_RESUME, "gpi-dma", gpii); if (ret < 0) { dev_err(gpii->gpi_dev->dev, "error request irq:%d ret:%d\n", diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 76104c174d4fe..46314c23da68f 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -1034,6 +1034,10 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, int ret; ret = pm_runtime_resume_and_get(gi2c->se.dev); + if (ret == -EACCES) { + dev_warn(gi2c->se.dev, "Runtime PM is disabled:%d\n", ret); + ret = 0; + } if (ret < 0) { dev_err(gi2c->se.dev, "error turning SE resources:%d\n", ret); /* Set device in suspended since resume failed */ @@ -1251,7 +1255,8 @@ static int geni_i2c_probe(struct platform_device *pdev) return ret; /* Keep interrupts disabled initially to allow for low-power modes */ - ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN, + ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, + IRQF_NO_AUTOEN | IRQF_NO_SUSPEND | IRQF_EARLY_RESUME, dev_name(dev), gi2c); if (ret) return ret; @@ -1357,7 +1362,12 @@ static int geni_i2c_resume_noirq(struct device *dev) if (ret) return ret; + /* Enforced disable_depth = 0 to actually enable runtime PM during noirq phase */ + if (!pm_runtime_enabled(dev)) + pm_runtime_enable(dev); + i2c_mark_adapter_resumed(&gi2c->adap); + return 0; } From 0178ff29b994a9dae0e81fac978db8f436ccec2e Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Sun, 2 Aug 2026 18:43:30 +0530 Subject: [PATCH 0912/1133] FROMLIST: dt-bindings: i2c: Add Qualcomm I2C target controller QDU1000 and related Qualcomm SoCs include a dedicated I2C target controller that operates exclusively in target mode. It is a distinct IP from the Qualcomm I2C master controllers (GENI, QUP) with a different register interface, so it requires its own binding. Document the MMIO region, interrupt, XO and AHB clocks, interconnect path, and optional pinctrl states for the controller. Link: https://lore.kernel.org/all/20260802-i2c-qcom-slave-v2-1-27653118fa75@oss.qualcomm.com/ Signed-off-by: Viken Dadhaniya --- .../bindings/i2c/qcom,i2c-target.yaml | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/qcom,i2c-target.yaml diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-target.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-target.yaml new file mode 100644 index 0000000000000..1e34e874cc4c3 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-target.yaml @@ -0,0 +1,84 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/qcom,i2c-target.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm I2C Target Controller + +maintainers: + - Mukesh Kumar Savaliya + - Viken Dadhaniya + +description: + Dedicated hardware IP found on Qualcomm SoCs that operates exclusively + as an I2C target (slave) device on the bus. Supports FIFO (PIO) mode + for data transfer. + +properties: + compatible: + enum: + - qcom,qdu1000-i2c-target + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: XO reference clock + - description: AHB bus clock + + clock-names: + items: + - const: xo + - const: ahb + + interconnects: + maxItems: 1 + + interconnect-names: + const: i2c + + pinctrl-0: true + pinctrl-1: true + + pinctrl-names: + items: + - const: default + - const: sleep + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - interconnects + - interconnect-names + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + i2c@88ca000 { + compatible = "qcom,qdu1000-i2c-target"; + reg = <0x88ca000 0x64>; + clocks = <&gcc GCC_SM_BUS_XO_CLK>, <&gcc GCC_SM_BUS_AHB_CLK>; + clock-names = "xo", "ahb"; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + interconnect-names = "i2c"; + interconnects = <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_SMBUS_CFG 0>; + }; +... From 29bb333b0df63430eb8d88c03b63b0923cc2186b Mon Sep 17 00:00:00 2001 From: Viken Dadhaniya Date: Sun, 2 Aug 2026 18:43:31 +0530 Subject: [PATCH 0913/1133] FROMLIST: i2c: qcom-target: Add driver for Qualcomm I2C target controller QDU1000 and related Qualcomm SoCs include a dedicated I2C target controller that operates exclusively in target mode. The existing Qualcomm I2C controller drivers (GENI, QUP) are master-only and cannot serve systems where the SoC must respond as an I2C target on the bus. Register the controller with the Linux I2C slave framework via i2c_algorithm.reg_target and i2c_algorithm.unreg_target so that any standard slave backend (e.g. slave-24c02) can be attached at runtime via i2c_slave_register(). Handle IRQ events for RX FIFO service, clock stretching during read and write phases, STOP and repeated-start conditions, and error recovery with SW reset. Enable the required AHB and XO clocks, vote for interconnect bandwidth, and restore hardware state across suspend and resume using the noirq PM callbacks. Link: https://lore.kernel.org/all/20260802-i2c-qcom-slave-v2-2-27653118fa75@oss.qualcomm.com/ Signed-off-by: Viken Dadhaniya --- MAINTAINERS | 9 + drivers/i2c/busses/Kconfig | 15 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-qcom-target.c | 556 +++++++++++++++++++++++++++ 4 files changed, 581 insertions(+) create mode 100644 drivers/i2c/busses/i2c-qcom-target.c diff --git a/MAINTAINERS b/MAINTAINERS index b9db9686dac54..6e03dbba9df2b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22994,6 +22994,15 @@ S: Maintained F: Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml F: drivers/i2c/busses/i2c-qcom-geni.c +QUALCOMM I2C TARGET CONTROLLER DRIVER +M: Viken Dadhaniya +M: Mukesh Kumar Savaliya +L: linux-i2c@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/i2c/qcom,i2c-target.yaml +F: drivers/i2c/busses/i2c-qcom-target.c + QUALCOMM I2C CCI DRIVER M: Loic Poulain M: Robert Foss diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 275aaa7f35833..33eb7996b85ed 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -1082,6 +1082,21 @@ config I2C_QCOM_GENI This driver can also be built as a module. If so, the module will be called i2c-qcom-geni. +config I2C_QCOM_TARGET + tristate "Qualcomm I2C target controller" + depends on ARCH_QCOM || COMPILE_TEST + depends on COMMON_CLK + depends on INTERCONNECT + select I2C_SLAVE + help + This driver supports I2C target mode on Qualcomm Technologies + SoCs. If you say yes to this option, support will be included + for the built-in I2C target controller on QDU1000 and other + compatible Qualcomm SoCs. + + This driver can also be built as a module. If so, the module + will be called i2c-qcom-target. + config I2C_QUP tristate "Qualcomm QUP based I2C controller" depends on ARCH_QCOM || COMPILE_TEST diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index e5440de0fe149..56ff6996a0898 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -102,6 +102,7 @@ obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o obj-$(CONFIG_I2C_QCOM_CCI) += i2c-qcom-cci.o obj-$(CONFIG_I2C_QCOM_GENI) += i2c-qcom-geni.o +obj-$(CONFIG_I2C_QCOM_TARGET) += i2c-qcom-target.o obj-$(CONFIG_I2C_QUP) += i2c-qup.o obj-$(CONFIG_I2C_RIIC) += i2c-riic.o obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o diff --git a/drivers/i2c/busses/i2c-qcom-target.c b/drivers/i2c/busses/i2c-qcom-target.c new file mode 100644 index 0000000000000..37310146b87e6 --- /dev/null +++ b/drivers/i2c/busses/i2c-qcom-target.c @@ -0,0 +1,556 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register offsets */ +#define I2C_S_DEVICE_ADDR 0x00 +#define I2C_S_IRQ_STATUS 0x08 +#define I2C_S_IRQ_CLR 0x0C +#define I2C_S_IRQ_EN 0x10 +#define I2C_S_CONFIG 0x18 +#define I2C_S_CONTROL 0x1C +#define I2C_S_FIFOS_STATUS 0x20 +#define I2C_S_TX_FIFO 0x24 +#define I2C_S_RX_FIFO 0x28 +#define I2C_S_DEBUG_REG1 0x3C +#define I2C_S_DEBUG_REG2 0x40 +#define I2C_S_SW_RESET_REG 0x4C +#define I2C_S_CLK_LOW_TIMEOUT 0x50 +#define I2C_S_CLK_RELEASE_DELAY_CNT_VAL 0x54 +#define I2C_S_SDA_HOLD_CNT_VAL 0x58 + +/* I2C_S_CONFIG register fields */ +#define I2C_S_CORE_EN BIT(0) + +/* I2C_S_CONTROL register fields */ +#define CLEAR_RX_FIFO BIT(0) +#define CLEAR_TX_FIFO BIT(1) +#define NACK BIT(2) +#define ACK_RESUME BIT(3) + +/* I2C_S_SW_RESET_REG register fields */ +#define SW_RESET BIT(0) + +/* I2C_S_FIFOS_STATUS register fields */ +#define RX_FIFO_COUNT_MASK GENMASK(31, 16) + +/* Interconnect bandwidth vote in bytes per second */ +#define APPS_PROC_TO_I2C_TARGET_VOTE 1190000 + +/** + * enum qcom_i2c_target_irq - IRQ bit positions in I2C_S_IRQ_STATUS + * @STOP_DETECTED: I2C stop condition detected on the bus + * @RX_FIFO_FULL: receive FIFO has reached capacity + * @TX_FIFO_EMPTY: transmit FIFO is empty + * @RX_DATA_AVAIL: receive data is available in the RX FIFO + * @CLOCK_LOW_TIMEOUT: SCL held low longer than the configured timeout + * @STRCH_WR: clock stretching during a write (Rx) phase + * @STRCH_RD: clock stretching during a read (Tx) phase + * @GCA_DETECTED: general call address detected (not used) + * @ERR_CONDITION: unexpected start or stop bit detected (error) + * @RESTART_DETECTED: repeated start condition detected + */ +enum qcom_i2c_target_irq { + STOP_DETECTED, + RX_FIFO_FULL, + TX_FIFO_EMPTY, + RX_DATA_AVAIL, + CLOCK_LOW_TIMEOUT, + STRCH_WR, + STRCH_RD, + GCA_DETECTED, + ERR_CONDITION, + RESTART_DETECTED, +}; + +/* + * TX_FIFO_EMPTY is excluded: this driver fills the TX FIFO one byte at a + * time in response to STRCH_RD (clock-stretch during read phase), so + * TX_FIFO_EMPTY adds no value and would double the interrupt rate. + * GCA (general call address) is unsupported. + */ +#define QCOM_I2C_TARGET_ALL_IRQ (GENMASK(RESTART_DETECTED, STOP_DETECTED) \ + & ~(BIT(GCA_DETECTED) | BIT(TX_FIFO_EMPTY))) + +/* Bit indices for the status bitmask, used with set_bit/test_bit/clear_bit */ +enum qcom_i2c_target_status { + READ_IN_PROGRESS, + WRITE_IN_PROGRESS, +}; + +/** + * struct qcom_i2c_target - Qualcomm I2C target controller private data + * @dev: driver model device node + * @base: base address of HW registers + * @adap: I2C adapter (slave mode) + * @ahb_clk: AHB bus clock + * @xo_clk: XO reference clock + * @icc_path: interconnect bandwidth path + * @slave: currently registered slave backend client; written only + * under disable_irq() in reg_slave()/unreg_slave() so the + * ISR sees a stable pointer for its entire execution + * @status: bitmask of enum qcom_i2c_target_status flags; must be + * unsigned long for set_bit/test_bit/clear_bit; accessed + * only from the ISR and from reg_slave()/unreg_slave() + * under disable_irq(), so no additional lock is needed + * @irq: interrupt line number + */ +struct qcom_i2c_target { + struct device *dev; + void __iomem *base; + struct i2c_adapter adap; + struct clk *ahb_clk; + struct clk *xo_clk; + struct icc_path *icc_path; + struct i2c_client *slave; + unsigned long status; + int irq; +}; + +static void qcom_i2c_target_dump_regs(struct qcom_i2c_target *target) +{ + dev_dbg(target->dev, "I2C_S_DEVICE_ADDR: 0x%x\n", + readl_relaxed(target->base + I2C_S_DEVICE_ADDR)); + dev_dbg(target->dev, "I2C_S_IRQ_STATUS: 0x%x\n", + readl_relaxed(target->base + I2C_S_IRQ_STATUS)); + dev_dbg(target->dev, "I2C_S_CONFIG: 0x%x\n", + readl_relaxed(target->base + I2C_S_CONFIG)); + dev_dbg(target->dev, "I2C_S_IRQ_EN: 0x%x\n", + readl_relaxed(target->base + I2C_S_IRQ_EN)); + dev_dbg(target->dev, "I2C_S_FIFOS_STATUS: 0x%x\n", + readl_relaxed(target->base + I2C_S_FIFOS_STATUS)); + dev_dbg(target->dev, "I2C_S_DEBUG_REG1: 0x%x\n", + readl_relaxed(target->base + I2C_S_DEBUG_REG1)); + dev_dbg(target->dev, "I2C_S_DEBUG_REG2: 0x%x\n", + readl_relaxed(target->base + I2C_S_DEBUG_REG2)); + dev_dbg(target->dev, "I2C_S_CLK_LOW_TIMEOUT: 0x%x\n", + readl_relaxed(target->base + I2C_S_CLK_LOW_TIMEOUT)); + dev_dbg(target->dev, "I2C_S_CLK_RELEASE_DELAY_CNT_VAL: 0x%x\n", + readl_relaxed(target->base + I2C_S_CLK_RELEASE_DELAY_CNT_VAL)); + dev_dbg(target->dev, "I2C_S_SDA_HOLD_CNT_VAL: 0x%x\n", + readl_relaxed(target->base + I2C_S_SDA_HOLD_CNT_VAL)); +} + +static void qcom_i2c_target_hw_init(struct qcom_i2c_target *target) +{ + dev_dbg(target->dev, "HW init: resetting FIFOs, enabling IRQs and core\n"); + writel(CLEAR_TX_FIFO | CLEAR_RX_FIFO, target->base + I2C_S_CONTROL); + writel(QCOM_I2C_TARGET_ALL_IRQ, target->base + I2C_S_IRQ_EN); + writel(I2C_S_CORE_EN, target->base + I2C_S_CONFIG); +} + +static void qcom_i2c_target_write_requested(struct qcom_i2c_target *target) +{ + u8 val = 0; + + if (!test_bit(WRITE_IN_PROGRESS, &target->status)) { + dev_dbg(target->dev, "Write phase started\n"); + set_bit(WRITE_IN_PROGRESS, &target->status); + i2c_slave_event(target->slave, I2C_SLAVE_WRITE_REQUESTED, &val); + } +} + +static int qcom_i2c_target_drain_rx_fifo(struct qcom_i2c_target *target) +{ + unsigned int rx_count; + int i, ret = 0; + u8 val; + + rx_count = FIELD_GET(RX_FIFO_COUNT_MASK, + readl_relaxed(target->base + I2C_S_FIFOS_STATUS)); + + for (i = 0; i < rx_count; i++) { + val = (u8)readl_relaxed(target->base + I2C_S_RX_FIFO); + dev_dbg(target->dev, "Data from RX FIFO: 0x%x\n", val); + ret = i2c_slave_event(target->slave, I2C_SLAVE_WRITE_RECEIVED, &val); + if (ret) + break; + } + + return ret; +} + +static void qcom_i2c_target_hw_reset(struct qcom_i2c_target *target) +{ + /* Clear error bits before SW_RESET; the reset may not be instantaneous */ + writel(BIT(ERR_CONDITION) | BIT(CLOCK_LOW_TIMEOUT), + target->base + I2C_S_IRQ_CLR); + writel(SW_RESET, target->base + I2C_S_SW_RESET_REG); + qcom_i2c_target_hw_init(target); + writel(target->slave->addr, target->base + I2C_S_DEVICE_ADDR); +} + +static irqreturn_t qcom_i2c_target_handle_error(struct qcom_i2c_target *target, u32 irq_stat) +{ + u8 val = 0; + + if (irq_stat & BIT(ERR_CONDITION)) + dev_err(target->dev, "Error condition: unexpected Start/Stop bits\n"); + else + dev_err(target->dev, "Clock low timeout\n"); + qcom_i2c_target_dump_regs(target); + qcom_i2c_target_hw_reset(target); + i2c_slave_event(target->slave, I2C_SLAVE_STOP, &val); + target->status = 0; + return IRQ_HANDLED; +} + +static irqreturn_t qcom_i2c_target_handle_stop(struct qcom_i2c_target *target, u32 irq_stat) +{ + u8 val = 0; + + dev_dbg(target->dev, "Stop bit detected\n"); + /* + * Short-write corner case: WRITE_IN_PROGRESS was never set because + * no RX_DATA_AVAIL or STRCH_WR fired before STOP. Do not call + * qcom_i2c_target_write_requested() here — STOP ends the transaction + * so setting WRITE_IN_PROGRESS now would leave a stale bit after + * target->status is cleared below. + */ + if (!test_bit(WRITE_IN_PROGRESS, &target->status)) { + unsigned int rx_count; + + rx_count = FIELD_GET(RX_FIFO_COUNT_MASK, + readl_relaxed(target->base + I2C_S_FIFOS_STATUS)); + if (rx_count) + i2c_slave_event(target->slave, I2C_SLAVE_WRITE_REQUESTED, + &val); + } + qcom_i2c_target_drain_rx_fifo(target); + i2c_slave_event(target->slave, I2C_SLAVE_STOP, &val); + target->status = 0; + writel(CLEAR_RX_FIFO, target->base + I2C_S_CONTROL); + /* + * STOP terminates the transaction, so any other Rx or clock + * stretch bits latched in this same status read have already + * been serviced by the drain above or are now stale. Ack the + * whole word rather than just STOP_DETECTED; clearing only STOP + * would leave those bits set and immediately re-enter the + * handler, which for a co-asserted STRCH_RD would push a stale + * byte into the TX FIFO. + */ + writel(irq_stat, target->base + I2C_S_IRQ_CLR); + return IRQ_HANDLED; +} + +static void qcom_i2c_target_handle_rx_data(struct qcom_i2c_target *target, u32 rx_irq_bits) +{ + int ret; + + dev_dbg(target->dev, "Rx data event (rx_irq_bits=0x%x)\n", rx_irq_bits); + qcom_i2c_target_write_requested(target); + ret = qcom_i2c_target_drain_rx_fifo(target); + if (ret) + dev_dbg(target->dev, "Backend requested NACK\n"); + writel(ret ? NACK | CLEAR_RX_FIFO : ACK_RESUME, + target->base + I2C_S_CONTROL); + writel(rx_irq_bits, target->base + I2C_S_IRQ_CLR); +} + +static void qcom_i2c_target_handle_strch_rd(struct qcom_i2c_target *target) +{ + enum i2c_slave_event event = I2C_SLAVE_READ_PROCESSED; + u8 val = 0; + + dev_dbg(target->dev, "Clock stretching during read (Tx) phase\n"); + if (!test_bit(READ_IN_PROGRESS, &target->status)) { + set_bit(READ_IN_PROGRESS, &target->status); + /* Repeated-start: master switched direction from write to read */ + clear_bit(WRITE_IN_PROGRESS, &target->status); + event = I2C_SLAVE_READ_REQUESTED; + } + i2c_slave_event(target->slave, event, &val); + dev_dbg(target->dev, "Data to TX FIFO: 0x%x\n", val); + writel(val, target->base + I2C_S_TX_FIFO); + writel(ACK_RESUME, target->base + I2C_S_CONTROL); + writel(BIT(STRCH_RD), target->base + I2C_S_IRQ_CLR); +} + +static irqreturn_t qcom_i2c_target_irq(int irq, void *dev) +{ + struct qcom_i2c_target *target = dev; + u32 irq_stat, rx_bits; + + /* + * Dispatch priority (highest first): + * ERR_CONDITION / CLOCK_LOW_TIMEOUT — hardware error, triggers SW reset + * STOP_DETECTED — end of transaction, clears all state + * STRCH_RD — read-phase data supply + * RX_FIFO_FULL / RX_DATA_AVAIL / + * STRCH_WR — write-phase Rx, coalesced into one drain + * RESTART_DETECTED — repeated start, resets state + */ + irq_stat = readl_relaxed(target->base + I2C_S_IRQ_STATUS); + if (!irq_stat) + return IRQ_NONE; + + dev_dbg(target->dev, "IRQ status: 0x%x\n", irq_stat); + + /* + * Load target->slave once. Both reg_slave() and unreg_slave() disable + * the IRQ before writing the pointer, so it cannot change while this + * handler runs. Sub-handlers may dereference target->slave directly. + */ + if (!READ_ONCE(target->slave)) { + writel(irq_stat, target->base + I2C_S_IRQ_CLR); + return IRQ_HANDLED; + } + + if (irq_stat & (BIT(ERR_CONDITION) | BIT(CLOCK_LOW_TIMEOUT))) + return qcom_i2c_target_handle_error(target, irq_stat); + + if (irq_stat & BIT(STOP_DETECTED)) + return qcom_i2c_target_handle_stop(target, irq_stat); + + if (irq_stat & BIT(STRCH_RD)) + qcom_i2c_target_handle_strch_rd(target); + + /* + * Coalesce all write-phase Rx bits into a single drain+ACK. When the + * RX FIFO fills at threshold, RX_FIFO_FULL, RX_DATA_AVAIL and STRCH_WR + * can all assert in the same irq_stat snapshot. Pass the combined mask + * so ACK_RESUME is written exactly once and all bits are cleared together. + */ + rx_bits = irq_stat & (BIT(RX_FIFO_FULL) | BIT(RX_DATA_AVAIL) | + BIT(STRCH_WR)); + if (rx_bits) + qcom_i2c_target_handle_rx_data(target, rx_bits); + + if (irq_stat & BIT(RESTART_DETECTED)) { + dev_dbg(target->dev, "Repeated start bit detected\n"); + target->status = 0; + writel(ACK_RESUME, target->base + I2C_S_CONTROL); + writel(BIT(RESTART_DETECTED), target->base + I2C_S_IRQ_CLR); + } + + return IRQ_HANDLED; +} + +static int qcom_i2c_target_reg_slave(struct i2c_client *slave) +{ + struct qcom_i2c_target *target = i2c_get_adapdata(slave->adapter); + + if (target->slave) + return -EBUSY; + + if (slave->flags & I2C_CLIENT_TEN) + return -EAFNOSUPPORT; + + disable_irq(target->irq); + WRITE_ONCE(target->slave, slave); + writel(slave->addr, target->base + I2C_S_DEVICE_ADDR); + enable_irq(target->irq); + + return 0; +} + +static int qcom_i2c_target_unreg_slave(struct i2c_client *slave) +{ + struct qcom_i2c_target *target = i2c_get_adapdata(slave->adapter); + + if (!target->slave) + return -EINVAL; + disable_irq(target->irq); + WRITE_ONCE(target->slave, NULL); + target->status = 0; + writel(0, target->base + I2C_S_DEVICE_ADDR); + enable_irq(target->irq); + + return 0; +} + +static int qcom_i2c_target_icc_init(struct qcom_i2c_target *target) +{ + int ret; + + target->icc_path = devm_of_icc_get(target->dev, "i2c"); + if (IS_ERR(target->icc_path)) + return dev_err_probe(target->dev, PTR_ERR(target->icc_path), + "failed to get ICC path\n"); + + /* + * The controller only needs interconnect bandwidth while it is + * powered. The vote is placed here and across resume with + * icc_set_bw(), and dropped with icc_set_bw(path, 0, 0) on suspend + * and remove, so the vote and unvote are always symmetric. + */ + ret = icc_set_bw(target->icc_path, APPS_PROC_TO_I2C_TARGET_VOTE, + APPS_PROC_TO_I2C_TARGET_VOTE); + if (ret) + return dev_err_probe(target->dev, ret, "icc_set_bw failed\n"); + + return 0; +} + +static u32 qcom_i2c_target_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_SLAVE; +} + +static const struct i2c_algorithm qcom_i2c_target_algo = { + .reg_target = qcom_i2c_target_reg_slave, + .unreg_target = qcom_i2c_target_unreg_slave, + .functionality = qcom_i2c_target_func, +}; + +static int qcom_i2c_target_adap_init(struct qcom_i2c_target *target) +{ + target->adap.algo = &qcom_i2c_target_algo; + target->adap.dev.parent = target->dev; + target->adap.dev.of_node = target->dev->of_node; + strscpy(target->adap.name, "qcom-i2c-target", + sizeof(target->adap.name)); + i2c_set_adapdata(&target->adap, target); + + return i2c_add_adapter(&target->adap); +} + +static int qcom_i2c_target_probe(struct platform_device *pdev) +{ + struct qcom_i2c_target *target; + struct device *dev = &pdev->dev; + int ret; + + target = devm_kzalloc(dev, sizeof(*target), GFP_KERNEL); + if (!target) + return -ENOMEM; + + target->dev = dev; + + target->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(target->base)) + return dev_err_probe(dev, PTR_ERR(target->base), + "failed to map registers\n"); + + target->xo_clk = devm_clk_get_enabled(dev, "xo"); + if (IS_ERR(target->xo_clk)) + return dev_err_probe(dev, PTR_ERR(target->xo_clk), + "failed to get and enable XO clock\n"); + + target->ahb_clk = devm_clk_get_enabled(dev, "ahb"); + if (IS_ERR(target->ahb_clk)) + return dev_err_probe(dev, PTR_ERR(target->ahb_clk), + "failed to get and enable AHB clock\n"); + + target->irq = platform_get_irq(pdev, 0); + if (target->irq < 0) + return target->irq; + + ret = qcom_i2c_target_icc_init(target); + if (ret) + return ret; + + ret = devm_request_irq(dev, target->irq, qcom_i2c_target_irq, 0, + dev_name(dev), target); + if (ret) + return dev_err_probe(dev, ret, "request_irq failed for IRQ %d\n", + target->irq); + + qcom_i2c_target_hw_init(target); + + platform_set_drvdata(pdev, target); + + ret = qcom_i2c_target_adap_init(target); + if (ret) + return dev_err_probe(dev, ret, "i2c_add_adapter failed\n"); + + return 0; +} + +static void qcom_i2c_target_remove(struct platform_device *pdev) +{ + struct qcom_i2c_target *target = platform_get_drvdata(pdev); + + disable_irq(target->irq); + i2c_del_adapter(&target->adap); + writel(0, target->base + I2C_S_CONFIG); + icc_set_bw(target->icc_path, 0, 0); +} + +static int qcom_i2c_target_suspend(struct device *dev) +{ + struct qcom_i2c_target *target = dev_get_drvdata(dev); + int ret; + + ret = icc_set_bw(target->icc_path, 0, 0); + if (ret) + dev_err(dev, "icc_set_bw failed on suspend: %d\n", ret); + + clk_disable_unprepare(target->xo_clk); + clk_disable_unprepare(target->ahb_clk); + + return 0; +} + +static int qcom_i2c_target_resume(struct device *dev) +{ + struct qcom_i2c_target *target = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(target->ahb_clk); + if (ret) { + dev_err(dev, "failed to enable AHB clock\n"); + return ret; + } + + ret = clk_prepare_enable(target->xo_clk); + if (ret) { + dev_err(dev, "failed to enable XO clock\n"); + goto err_disable_ahb; + } + + ret = icc_set_bw(target->icc_path, APPS_PROC_TO_I2C_TARGET_VOTE, + APPS_PROC_TO_I2C_TARGET_VOTE); + if (ret) { + dev_err(dev, "icc_set_bw failed\n"); + goto err_disable_xo; + } + + qcom_i2c_target_hw_init(target); + if (target->slave) + writel(target->slave->addr, target->base + I2C_S_DEVICE_ADDR); + + return 0; + +err_disable_xo: + clk_disable_unprepare(target->xo_clk); +err_disable_ahb: + clk_disable_unprepare(target->ahb_clk); + return ret; +} + +static const struct dev_pm_ops qcom_i2c_target_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(qcom_i2c_target_suspend, + qcom_i2c_target_resume) +}; + +static const struct of_device_id qcom_i2c_target_dt_match[] = { + { .compatible = "qcom,qdu1000-i2c-target" }, + {} +}; +MODULE_DEVICE_TABLE(of, qcom_i2c_target_dt_match); + +static struct platform_driver qcom_i2c_target_driver = { + .driver = { + .name = "qcom-i2c-target", + .pm = &qcom_i2c_target_pm_ops, + .of_match_table = qcom_i2c_target_dt_match, + }, + .probe = qcom_i2c_target_probe, + .remove = qcom_i2c_target_remove, +}; +module_platform_driver(qcom_i2c_target_driver); + +MODULE_DESCRIPTION("Qualcomm I2C target controller driver"); +MODULE_AUTHOR("Viken Dadhaniya "); +MODULE_LICENSE("GPL"); From 76d80866bef933a3eff65f38ccb17f1055be8f6d Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 25 Sep 2026 22:22:31 +0530 Subject: [PATCH 0914/1133] FROMLIST: firmware: qcom: pas: Make MDT buffer retention explicit The PAS image initialization path retains metadata whenever a valid qcom_pas_context is supplied, although callers may not need the metadata after initialization. This leaves ownership implicit and causes unused metadata buffers to remain allocated. Add keep_mdt_buf to struct qcom_pas_context and have the generic PAS wrapper release metadata unless the caller requests retention. This applies uniformly to SCM and OP-TEE backends, while qcom_q6v5_pas keeps metadata for subsequent PAS operations. Link: https://lore.kernel.org/lkml/20260925165231.10722-1-mukesh.ojha@oss.qualcomm.com/ Acked-by: Konrad Dybcio Reviewed-by: Sumit Garg Signed-off-by: Mukesh Ojha --- drivers/firmware/qcom/qcom_pas.c | 12 +++++++++--- drivers/firmware/qcom/qcom_scm.c | 2 +- drivers/remoteproc/qcom_q6v5_pas.c | 3 +++ include/linux/firmware/qcom/qcom_pas.h | 1 + 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/qcom/qcom_pas.c b/drivers/firmware/qcom/qcom_pas.c index 24485dd0fa10a..93d78a5c12017 100644 --- a/drivers/firmware/qcom/qcom_pas.c +++ b/drivers/firmware/qcom/qcom_pas.c @@ -60,17 +60,23 @@ EXPORT_SYMBOL_GPL(devm_qcom_pas_context_alloc); * * Return: 0 on success. * - * Upon successful return, the PAS metadata context (@ctx) will be used to - * track the metadata allocation, this needs to be released by invoking + * If @ctx requests metadata retention, the PAS metadata context will track + * the allocation, which needs to be released by invoking * qcom_pas_metadata_release() by the caller. */ int qcom_pas_init_image(u32 pas_id, const void *metadata, size_t size, struct qcom_pas_context *ctx) { + int ret; + if (!ops_ptr) return -ENODEV; - return ops_ptr->init_image(ops_ptr->dev, pas_id, metadata, size, ctx); + ret = ops_ptr->init_image(ops_ptr->dev, pas_id, metadata, size, ctx); + if (!ret && ctx && !ctx->keep_mdt_buf) + qcom_pas_metadata_release(ctx); + + return ret; } EXPORT_SYMBOL_GPL(qcom_pas_init_image); diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 43e250faea75a..54968bc1f1149 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -666,7 +666,7 @@ static int qcom_scm_pas_init_image(struct device *dev, u32 pas_id, ret = __qcom_scm_pas_init_image(dev, pas_id, mdata_phys, &res); if (ret < 0 || !ctx) { dma_free_coherent(dev, size, mdata_buf, mdata_phys); - } else if (ctx) { + } else { ctx->ptr = mdata_buf; ctx->phys = mdata_phys; ctx->size = size; diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index f37b77ae187e9..a5e861bd743b2 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -752,6 +752,7 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) if (IS_ERR(pas->pas_ctx)) return PTR_ERR(pas->pas_ctx); + pas->pas_ctx->keep_mdt_buf = true; if (!pas->dtb_pas_id) return 0; @@ -770,6 +771,8 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) if (IS_ERR(pas->dtb_pas_ctx)) return PTR_ERR(pas->dtb_pas_ctx); + pas->dtb_pas_ctx->keep_mdt_buf = true; + return 0; } diff --git a/include/linux/firmware/qcom/qcom_pas.h b/include/linux/firmware/qcom/qcom_pas.h index fb2ec3be6a169..1d132e89536e6 100644 --- a/include/linux/firmware/qcom/qcom_pas.h +++ b/include/linux/firmware/qcom/qcom_pas.h @@ -22,6 +22,7 @@ struct qcom_pas_context { dma_addr_t phys; ssize_t size; bool use_tzmem; + bool keep_mdt_buf; }; static inline void __iomem *qcom_pas_ctx_map(struct qcom_pas_context *ctx) From 34e92fc9b0f13813515cd3e98dc35d1a4b0dac5c Mon Sep 17 00:00:00 2001 From: Nabige Aala Date: Wed, 30 Sep 2026 16:45:11 +0530 Subject: [PATCH 0915/1133] FROMLIST: arm64: dts: qcom: shikra: Add MDSS display subsystem Add the SoC-level display subsystem nodes for Qualcomm Shikra: MDSS wrapper,DPU display controller, DSI host controller, and 14nm DSI PHY. Qualcomm Shikra uses DPU 6.5 hardware (same as QCM2290). Platform-specific compatible strings are used as the primary match with QCM2290 fallbacks to reuse the existing driver support. The dispcc clock inputs for the DSI byte and pixel PLLs are wired from mdss_dsi0_phy. Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20260930-shikra-dt-changes-v5-1-8eaf658a0e38@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra.dtsi | 206 ++++++++++++++++++++++++++- 1 file changed, 204 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 2623e139196f6..72d7236546b07 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -2803,6 +2804,207 @@ power-domains = <&gpucc GPU_CX_GDSC>; }; + mdss: display-subsystem@5e00000 { + compatible = "qcom,shikra-mdss", "qcom,qcm2290-mdss"; + reg = <0x0 0x05e00000 0x0 0x1000>; + reg-names = "mdss"; + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + clocks = <&gcc GCC_DISP_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", + "bus", + "core"; + + resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; + + power-domains = <&dispcc MDSS_GDSC>; + + iommus = <&apps_smmu 0x420 0x2>; + interconnects = <&mmrt_virt MASTER_MDP_PORT0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ALWAYS_TAG + &config_noc SLAVE_DISPLAY_CFG RPM_ALWAYS_TAG>; + interconnect-names = "mdp0-mem", + "cpu-cfg"; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + mdp: display-controller@5e01000 { + compatible = "qcom,shikra-dpu", "qcom,qcm2290-dpu"; + reg = <0x0 0x05e01000 0x0 0x8f000>, + <0x0 0x05eb0000 0x0 0x3000>; + reg-names = "mdp", + "vbif"; + + interrupt-parent = <&mdss>; + interrupts = <0>; + + clocks = <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "bus", + "iface", + "core", + "lut", + "vsync"; + + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmpd RPMPD_VDDCX>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + dpu_intf1_out: endpoint { + remote-endpoint = <&mdss_dsi0_in>; + }; + }; + }; + + mdp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_min_svs>; + }; + + opp-192000000 { + opp-hz = /bits/ 64 <192000000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-256000000 { + opp-hz = /bits/ 64 <256000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-307200000 { + opp-hz = /bits/ 64 <307200000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_nom>; + }; + }; + }; + + mdss_dsi0: dsi@5e94000 { + compatible = "qcom,shikra-dsi-ctrl", + "qcom,qcm2290-dsi-ctrl", + "qcom,mdss-dsi-ctrl"; + reg = <0x0 0x05e94000 0x0 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>, + <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK>, + <&dispcc DISP_CC_MDSS_ESC0_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>; + assigned-clock-parents = <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>, + <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>; + + operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmpd RPMPD_VDDCX>; + phys = <&mdss_dsi0_phy>; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + dsi_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_min_svs>; + }; + + opp-164000000 { + opp-hz = /bits/ 64 <164000000>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-187500000 { + opp-hz = /bits/ 64 <187500000>; + required-opps = <&rpmpd_opp_svs>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + mdss_dsi0_in: endpoint { + remote-endpoint = <&dpu_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + + mdss_dsi0_out: endpoint { + }; + }; + }; + }; + + mdss_dsi0_phy: phy@5e94400 { + compatible = "qcom,dsi-phy-14nm-2290"; + reg = <0x0 0x05e94400 0x0 0x100>, + <0x0 0x05e94500 0x0 0x300>, + <0x0 0x05e94800 0x0 0x188>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&rpmcc RPM_SMD_XO_CLK_SRC>; + clock-names = "iface", + "ref"; + + power-domains = <&rpmpd RPMPD_VDDMX>; + required-opps = <&rpmpd_opp_nom>; + + #clock-cells = <1>; + #phy-cells = <0>; + + status = "disabled"; + }; + }; + dispcc: clock-controller@5f00000 { compatible = "qcom,shikra-dispcc", "qcom,qcm2290-dispcc"; reg = <0x0 0x05f00000 0x0 0x20000>; @@ -2810,8 +3012,8 @@ <&rpmcc RPM_SMD_XO_A_CLK_SRC>, <&gcc GCC_DISP_GPLL0_CLK_SRC>, <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>, - <0>, - <0>; + <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>, + <&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>; clock-names = "bi_tcxo", "bi_tcxo_ao", "gcc_disp_gpll0_clk_src", From 5fee0f7e17732930f87733e537bc99e74f232154 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Wed, 4 Nov 2026 18:27:05 +0530 Subject: [PATCH 0916/1133] FROMLIST: drm/bridge: add support for lontium lt9211c bridge LT9211C is a Single/Dual-Link DSI/LVDS or Single DPI input to Single-Link/Dual-Link DSI/LVDS or Single DPI output bridge chip. Extend the existing lontium-lt9211 driver to support DSI-to-LVDS bridge configuration by detecting and handling both LT9211 and LT9211C variants from a single driver. Chip detection in lt9211_read_chipid() is extended to identify the LT9211C by its distinct chip ID registers, and cross-checked against the chip type requested by the DT compatible string to catch a mismatched board/compatible combination. Add LT9211C-specific regmap support and use lt9211_chip_data with i2c_get_match_data() to provide per-chip configuration. Five new functions implement the LT9211C DSI-to-LVDS initialisation sequence: lt9211c_configure_rx(), lt9211c_autodetect_rx(), lt9211c_configure_timing(), lt9211c_configure_plls() and lt9211c_configure_tx(). Defer the remaining LT9211C initialization to a work item scheduled from atomic_enable(), since RX auto-detection requires an active DSI stream. Link: https://lore.kernel.org/all/20260924-add-lt9211c-bridge-v9-2-d78b39677a61@oss.qualcomm.com/ Signed-off-by: Yi Zhang Signed-off-by: Nilesh Laad Signed-off-by: Gopi Botlagunta Signed-off-by: Vishnu Saini Tested-by: Philipp Zabel --- drivers/gpu/drm/bridge/lontium-lt9211.c | 838 +++++++++++++++++++++++- 1 file changed, 807 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9211.c b/drivers/gpu/drm/bridge/lontium-lt9211.c index 285cda58f6614..e6c08a7fdc27c 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9211.c +++ b/drivers/gpu/drm/bridge/lontium-lt9211.c @@ -8,6 +8,7 @@ * 1xDSI -> 1xLVDS * * Copyright (C) 2022 Marek Vasut + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include @@ -27,6 +29,7 @@ #include #include #include +#include #define REG_PAGE_CONTROL 0xff #define REG_CHIPID0 0x8100 @@ -36,10 +39,28 @@ #define REG_CHIPID2 0x8102 #define REG_CHIPID2_VALUE 0xe3 +/* LT9211C chip ID values */ +#define REG_CHIPID0_LT9211C_VALUE 0x21 +#define REG_CHIPID1_LT9211C_VALUE 0x03 +#define REG_CHIPID2_LT9211C_VALUE 0xe1 + #define REG_DSI_LANE 0xd000 /* DSI lane count - 0 means 4 lanes ; 1, 2, 3 means 1, 2, 3 lanes. */ #define REG_DSI_LANE_COUNT(n) ((n) & 3) +/* Chip type enum */ +enum lt9211_chip_type { + LT9211, + LT9211C, +}; + +struct lt9211_chip_data { + enum lt9211_chip_type chip_type; + const struct regmap_config *regmap_config; + const char *dsi_type; + unsigned long dsi_mode_flags; +}; + struct lt9211 { struct drm_bridge bridge; struct device *dev; @@ -50,6 +71,15 @@ struct lt9211 { struct regulator *vccio; bool lvds_dual_link; bool lvds_dual_link_even_odd_swap; + const struct lt9211_chip_data *chip_data; + /* LT9211C specific fields */ + struct workqueue_struct *wq; + struct work_struct lt9211_work; + struct drm_crtc *lt9211c_crtc; + struct drm_display_mode lt9211c_mode; + bool lt9211c_bpp24; + bool lt9211c_jeida; + bool lt9211c_de_high; }; static const struct regmap_range lt9211_rw_ranges[] = { @@ -93,6 +123,65 @@ static const struct regmap_config lt9211_regmap_config = { .max_register = 0xda00, }; +static const struct regmap_range lt9211c_rw_ranges[] = { + regmap_reg_range(0xff, 0xff), + regmap_reg_range(0x8100, 0x8182), + regmap_reg_range(0x8200, 0x82aa), + regmap_reg_range(0x8500, 0x85ff), + regmap_reg_range(0x8600, 0x86a0), + regmap_reg_range(0x8700, 0x8746), + regmap_reg_range(0xd000, 0xd0a7), + regmap_reg_range(0xd400, 0xd42c), + regmap_reg_range(0xd800, 0xd838), + regmap_reg_range(0xd9c0, 0xd9d5), +}; + +static const struct regmap_access_table lt9211c_rw_table = { + .yes_ranges = lt9211c_rw_ranges, + .n_yes_ranges = ARRAY_SIZE(lt9211c_rw_ranges), +}; + +static const struct regmap_range_cfg lt9211c_range = { + .name = "lt9211c", + .range_min = 0x0000, + .range_max = 0xda00, + .selector_reg = REG_PAGE_CONTROL, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, +}; + +static const struct regmap_config lt9211c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .rd_table = <9211c_rw_table, + .wr_table = <9211c_rw_table, + .volatile_table = <9211c_rw_table, + .ranges = <9211c_range, + .num_ranges = 1, + .cache_type = REGCACHE_NONE, + .max_register = 0xda00, +}; + +static const struct lt9211_chip_data lt9211_chip_data = { + .chip_type = LT9211, + .regmap_config = <9211_regmap_config, + .dsi_type = "lt9211", + .dsi_mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA | + MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP | + MIPI_DSI_MODE_NO_EOT_PACKET, +}; + +static const struct lt9211_chip_data lt9211c_chip_data = { + .chip_type = LT9211C, + .regmap_config = <9211c_regmap_config, + .dsi_type = "lt9211c", + .dsi_mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM, +}; + static struct lt9211 *bridge_to_lt9211(struct drm_bridge *bridge) { return container_of(bridge, struct lt9211, bridge); @@ -111,6 +200,7 @@ static int lt9211_attach(struct drm_bridge *bridge, static int lt9211_read_chipid(struct lt9211 *ctx) { u8 chipid[3]; + bool is_lt9211, is_lt9211c; int ret; /* Read Chip ID registers and verify the chip can communicate. */ @@ -120,14 +210,22 @@ static int lt9211_read_chipid(struct lt9211 *ctx) return ret; } - /* Test for known Chip ID. */ - if (chipid[0] != REG_CHIPID0_VALUE || chipid[1] != REG_CHIPID1_VALUE) { - dev_err(ctx->dev, "Unknown Chip ID: 0x%02x 0x%02x 0x%02x\n", - chipid[0], chipid[1], chipid[2]); - return -EINVAL; + is_lt9211 = chipid[0] == REG_CHIPID0_VALUE && chipid[1] == REG_CHIPID1_VALUE; + is_lt9211c = chipid[0] == REG_CHIPID0_LT9211C_VALUE && + chipid[1] == REG_CHIPID1_LT9211C_VALUE && + chipid[2] == REG_CHIPID2_LT9211C_VALUE; + + /* Confirm the detected chip matches what the DT compatible requested. */ + if ((ctx->chip_data->chip_type == LT9211 && is_lt9211) || + (ctx->chip_data->chip_type == LT9211C && is_lt9211c)) { + dev_dbg(ctx->dev, "Detected %s chip\n", ctx->chip_data->dsi_type); + return 0; } - return 0; + dev_err(ctx->dev, + "Chip ID 0x%02x 0x%02x 0x%02x does not match compatible '%s'\n", + chipid[0], chipid[1], chipid[2], ctx->chip_data->dsi_type); + return -EINVAL; } static int lt9211_system_init(struct lt9211 *ctx) @@ -454,6 +552,656 @@ static int lt9211_configure_tx(struct lt9211 *ctx, bool jeida, return 0; } +static int lt9211c_configure_rx(struct lt9211 *ctx) +{ + unsigned int pval; + + const struct reg_sequence lt9211c_rx_phy_seq[] = { + { REG_DSI_LANE, REG_DSI_LANE_COUNT(ctx->dsi->lanes) }, + { 0x8201, 0x11 }, + { 0x8218, 0x48 }, + { 0x8201, 0x91 }, + { 0x8202, 0x00 }, + { 0x8203, 0xee }, + { 0x8209, 0x21 }, + { 0x8204, 0x44 }, + { 0x8205, 0xc4 }, + { 0x8206, 0x44 }, + { 0x8213, 0x0c }, + + { 0xd001, 0x00 }, + { 0xd002, 0x0e }, + { 0xd005, 0x00 }, + { 0xd00a, 0x59 }, + { 0xd00b, 0x20 }, + }; + + const struct reg_sequence lt9211c_rx_phy_reset_seq[] = { + { 0x8109, 0xde }, + { 0x8109, 0xdf }, + }; + + const struct reg_sequence lt9211c_rx_clk_sel_seq[] = { + { 0x85e9, 0x88 }, + { 0x8180, 0x51 }, + { 0x8181, 0x10 }, + { 0x8632, 0x03 }, + }; + + const struct reg_sequence lt9211c_rx_input_sel_seq[] = { + { 0xd004, 0x00 }, + { 0xd021, 0x46 }, + }; + + const struct reg_sequence lt9211c_rx_dig_seq[] = { + { 0x853f, 0x08 }, + { 0x8540, 0x04 }, + { 0x8541, 0x03 }, + { 0x8542, 0x02 }, + { 0x8543, 0x01 }, + { 0x8545, 0x04 }, + { 0x8546, 0x03 }, + { 0x8547, 0x02 }, + { 0x8548, 0x01 }, + { 0x8544, 0x00 }, + { 0x8549, 0x00 }, + }; + + int ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_phy_seq, + ARRAY_SIZE(lt9211c_rx_phy_seq)); + if (ret) { + dev_err(ctx->dev, "RX: phy_seq write failed: %d\n", ret); + return ret; + } + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_phy_reset_seq, + ARRAY_SIZE(lt9211c_rx_phy_reset_seq)); + if (ret) { + dev_err(ctx->dev, "RX: phy_reset_seq write failed: %d\n", ret); + return ret; + } + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_clk_sel_seq, + ARRAY_SIZE(lt9211c_rx_clk_sel_seq)); + if (ret) { + dev_err(ctx->dev, "RX: clk_sel_seq write failed: %d\n", ret); + return ret; + } + + ret = regmap_write_bits(ctx->regmap, 0x8180, 0x3, 0x3); + if (ret) + return ret; + + ret = regmap_read(ctx->regmap, 0x8680, &pval); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, (pval & 0xf8)); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, 0x05); + if (ret) + return ret; + + ret = regmap_write_bits(ctx->regmap, 0x8530, 0x17, 0x11); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_input_sel_seq, + ARRAY_SIZE(lt9211c_rx_input_sel_seq)); + if (ret) { + dev_err(ctx->dev, "RX: input_sel_seq write failed: %d\n", ret); + return ret; + } + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_rx_dig_seq, + ARRAY_SIZE(lt9211c_rx_dig_seq)); + if (ret) { + dev_err(ctx->dev, "RX: dig_seq write failed: %d\n", ret); + return ret; + } + + /* Give the chip time to lock onto RX stream. */ + msleep(100); + + return 0; +} + +static int lt9211c_autodetect_rx(struct lt9211 *ctx, + const struct drm_display_mode *mode) +{ + u16 width, height; + u8 buf[5]; + u8 format; + u8 sot[8]; + u8 hs_settle; + int ret; + + /* Read the SOT from the chip. */ + ret = regmap_bulk_read(ctx->regmap, 0xd088, sot, sizeof(sot)); + if (ret) { + dev_err(ctx->dev, "RX: failed to read SOT (0xd088): %d\n", ret); + return ret; + } + + dev_dbg(ctx->dev, "Sot Num = 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + sot[0], sot[2], sot[4], sot[6]); + + dev_dbg(ctx->dev, "Sot Data = 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + sot[1], sot[3], sot[5], sot[7]); + + /* HS Settle Set */ + hs_settle = (sot[0] > 0x10 && sot[0] < 0x50) ? sot[0] - 5 : 0x08; + ret = regmap_write(ctx->regmap, 0xd002, hs_settle); + if (ret) + return ret; + + /* Width/Height/Format Auto-detection */ + ret = regmap_bulk_read(ctx->regmap, 0xd082, buf, sizeof(buf)); + if (ret) + return ret; + + width = (buf[0] << 8) | buf[1]; + height = (buf[3] << 8) | buf[4]; + format = buf[2] & 0xf; + + if (format == 0x3) { /* YUV422 16bit */ + width /= 2; + } else if (format == 0xa) { /* RGB888 24bit */ + width /= 3; + } else { + dev_err(ctx->dev, + "Unsupported DSI format 0x%01x (0xd082=%02x %02x %02x %02x %02x)\n", + format, buf[0], buf[1], buf[2], buf[3], buf[4]); + return -EINVAL; + } + + if (width != mode->hdisplay) { + dev_err(ctx->dev, + "RX: Detected DSI width (%d) does not match mode hdisplay (%d)\n", + width, mode->hdisplay); + return -EINVAL; + } + + if (height != mode->vdisplay) { + dev_err(ctx->dev, + "RX: Detected DSI height (%d) does not match mode vdisplay (%d)\n", + height, mode->vdisplay); + return -EINVAL; + } + + dev_dbg(ctx->dev, "RX: %dx%d format=0x%01x\n", width, height, format); + + return 0; +} + +static int lt9211c_configure_timing(struct lt9211 *ctx, + const struct drm_display_mode *mode) +{ + int ret; + + ret = lt9211_configure_timing(ctx, mode); + if (ret < 0) + return ret; + + return regmap_write(ctx->regmap, 0xd04c, + ((mode->hsync_end - mode->hsync_start) >> 8) & 0xff); +} + +static int lt9211c_configure_plls(struct lt9211 *ctx, + const struct drm_display_mode *mode) +{ + const struct reg_sequence lt9211c_dessc_pll_reset[] = { + { 0x8103, 0xfe, 2000 }, + { 0x8103, 0xff, 0 }, + }; + + const struct reg_sequence lt9211c_pcr_cali_seq[] = { + { 0xd00a, 0x5f }, + { 0xd01e, 0x51 }, + { 0xd023, 0x80 }, + { 0xd024, 0x70 }, + { 0xd025, 0x80 }, + { 0xd02a, 0x10 }, + { 0xd021, 0x4f }, + { 0xd022, 0xf0 }, + { 0xd038, 0x04 }, + { 0xd039, 0x08 }, + { 0xd03a, 0x10 }, + { 0xd03b, 0x20 }, + { 0xd03f, 0x04 }, + { 0xd040, 0x08 }, + { 0xd041, 0x10 }, + { 0xd042, 0x20 }, + { 0xd02b, 0xa0 }, + }; + + const struct reg_sequence lt9211c_pcr_reset_seq[] = { + { 0xd009, 0xdb }, + { 0xd009, 0xdf }, + { 0xd008, 0x80 }, + { 0xd008, 0x00 }, + }; + + unsigned int pval; + unsigned int val; + int ret; + u8 div; + u32 pcr_m; + u32 pcr_k; + u32 pcr_up; + u32 pcr_down; + + /* DeSSC PLL reference clock is 25 MHz XTal. */ + ret = regmap_write(ctx->regmap, 0x8226, 0x20); + if (ret) + return ret; + + /* Prediv = 0 */ + ret = regmap_write(ctx->regmap, 0x8227, 0x40); + if (ret) + return ret; + + if (mode->clock < 44000) { + ret = regmap_write(ctx->regmap, 0x822f, 0x07); + div = 16; + } else if (mode->clock < 88000) { + ret = regmap_write(ctx->regmap, 0x822f, 0x06); + div = 8; + } else if (mode->clock < 176000) { + ret = regmap_write(ctx->regmap, 0x822f, 0x05); + div = 4; + } else { + ret = regmap_write(ctx->regmap, 0x822f, 0x04); + div = 2; + } + + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x822c, mode->clock < 22000 ? 0x01 : 0x00); + if (ret) + return ret; + + pcr_m = (mode->clock * div) / 25; + pcr_k = pcr_m % 1000; + pcr_m /= 1000; + + pcr_up = pcr_m + 1; + pcr_down = pcr_m - 1; + + pcr_k <<= 14; + + ret = regmap_write(ctx->regmap, 0xd008, 0x00); + if (ret < 0) + return ret; + + /* 0xd026: pcr_m */ + ret = regmap_write(ctx->regmap, 0xd026, (u8)pcr_m & 0x7f); + if (ret < 0) + return ret; + + /* 0xd027 0xd028 0xd029: pcr_k */ + ret = regmap_write(ctx->regmap, 0xd027, (pcr_k >> 16) & 0xff); + if (ret < 0) + return ret; + + ret = regmap_write(ctx->regmap, 0xd028, (pcr_k >> 8) & 0xff); + if (ret < 0) + return ret; + + ret = regmap_write(ctx->regmap, 0xd029, pcr_k & 0xff); + if (ret < 0) + return ret; + + /* 0xd02d: pcr_m overflow limit setting */ + ret = regmap_write(ctx->regmap, 0xd02d, pcr_up); + if (ret < 0) + return ret; + + /* 0xd031: pcr_m underflow limit setting */ + ret = regmap_write(ctx->regmap, 0xd031, pcr_down); + if (ret < 0) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_dessc_pll_reset, + ARRAY_SIZE(lt9211c_dessc_pll_reset)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_pcr_cali_seq, + ARRAY_SIZE(lt9211c_pcr_cali_seq)); + if (ret) + return ret; + + if (mode->clock < 44000) + val = 0x60; + else + val = 0x40; + ret = regmap_write(ctx->regmap, 0xd00c, val); + if (ret) + return ret; + ret = regmap_write(ctx->regmap, 0xd01b, 0x00); + if (ret) + return ret; + ret = regmap_write(ctx->regmap, 0xd01c, val); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_pcr_reset_seq, + ARRAY_SIZE(lt9211c_pcr_reset_seq)); + if (ret) + return ret; + + /* PCR stability test takes seconds. */ + ret = regmap_read_poll_timeout(ctx->regmap, 0xd087, pval, + ((pval & 0x18) == 0x18), 20000, 3000000); + if (ret) + dev_err(ctx->dev, "PCR unstable, ret=%i\n", ret); + + ret = regmap_write(ctx->regmap, 0x8180, 0x51); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, 0x00); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0x863f, 0x01); + if (ret) + return ret; + + ret = regmap_read_poll_timeout(ctx->regmap, 0x8640, pval, + ((pval & 0x01) == 0x01), 50000, 250000); + if (ret) + dev_err(ctx->dev, "Video check not stable, ret=%i\n", ret); + + return ret; +} + +static int lt9211c_configure_tx(struct lt9211 *ctx, bool jeida, bool bpp24, + bool de, const struct drm_display_mode *mode) +{ + const struct reg_sequence lt9211c_tx_phy_off_seq[] = { + { 0x8236, 0x00 }, + { 0x8237, 0x00 }, + { 0x8108, 0x6f }, + { 0x8103, 0xbf }, + }; + + const struct reg_sequence lt9211c_tx_phy_seq[] = { + { 0x8236, 0x03 }, + { 0x8237, 0x44 }, + { 0x8238, 0x14 }, + { 0x8239, 0x31 }, + { 0x823a, 0xc8 }, + { 0x823b, 0x00 }, + { 0x823c, 0x0f }, + { 0x8246, 0x40 }, + { 0x8247, 0x40 }, + { 0x8248, 0x40 }, + { 0x8249, 0x40 }, + { 0x824a, 0x40 }, + { 0x824b, 0x40 }, + { 0x824c, 0x40 }, + { 0x824d, 0x40 }, + { 0x824e, 0x40 }, + { 0x824f, 0x40 }, + { 0x8250, 0x40 }, + { 0x8251, 0x40 }, + }; + + const struct reg_sequence lt9211c_tx_mltx_reset[] = { + { 0x8103, 0xbf }, + { 0x8103, 0xff }, + }; + + const struct reg_sequence lt9211c_tx_dig_seq[] = { + { 0x854a, 0x01 }, + { 0x854b, 0x00 }, + { 0x854c, 0x10 }, + { 0x854d, 0x20 }, + { 0x854e, 0x50 }, + { 0x854f, 0x30 }, + { 0x8550, 0x46 }, + { 0x8551, 0x10 }, + { 0x8552, 0x20 }, + { 0x8553, 0x50 }, + { 0x8554, 0x30 }, + { 0x8555, 0x00 }, + { 0x8556, 0x20 }, + + { 0x8568, 0x00 }, + { 0x856e, 0x10 | (de ? BIT(6) : 0) }, + { 0x856f, 0x81 | (jeida ? BIT(6) : 0) | + (ctx->lvds_dual_link ? BIT(4) : 0) | + (bpp24 ? BIT(2) : 0) }, + }; + + const struct reg_sequence lt9211c_tx_ssc_seq[] = { + { 0x8234, 0x00 }, + { 0x856e, 0x10 }, + { 0x8181, 0x15 }, + { 0x871e, 0x00 }, + { 0x8717, 0x02 }, + { 0x8718, 0x04 }, + { 0x8719, 0xd4 }, + { 0x871a, 0x00 }, + { 0x871b, 0x12 }, + { 0x871c, 0x00 }, + { 0x871d, 0x24 }, + { 0x871f, 0x1c }, + { 0x8720, 0x00 }, + { 0x8721, 0x00 }, + { 0x871e, 0x02 }, + }; + + const struct reg_sequence lt9211c_tx_pll_reset_seq[] = { + { 0x810c, 0xfe, 2000 }, + { 0x810c, 0xff, 0 }, + }; + + const struct reg_sequence lt9211c_tx_sw_reset_seq[] = { + { 0x8108, 0x6f, 2000 }, + { 0x8108, 0x7f, 0 }, + }; + + unsigned int pval; + int ret; + u32 phy_clk; + u8 pixclk_div; + u8 pre_div; + u8 div_set; + u8 sericlk_div; + u8 val; + + dev_dbg(ctx->dev, + "dual_link=%d,even_odd_swap=%d,bpp24=%d,jeida=%d,de=%d\n", + ctx->lvds_dual_link, ctx->lvds_dual_link_even_odd_swap, + bpp24, jeida, de); + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_phy_off_seq, + ARRAY_SIZE(lt9211c_tx_phy_off_seq)); + if (ret) + return ret; + + ret = regmap_write_bits(ctx->regmap, 0x8530, 0xc0, 0x40); + if (ret) + return ret; + + /* [7]0:txpll normal work; txpll ref clk sel pix clk */ + ret = regmap_write(ctx->regmap, 0x8230, 0x00); + if (ret) + return ret; + + if (ctx->lvds_dual_link) + phy_clk = (u32)(mode->clock * 7 / 2); + else + phy_clk = (u32)(mode->clock * 7); + + /* 0x8231: prediv sel */ + if (mode->clock < 40000) { + val = 0x28; + pre_div = 1; + } else if (mode->clock < 80000) { + val = 0x29; + pre_div = 2; + } else if (mode->clock < 160000) { + val = 0x2a; + pre_div = 4; + } else if (mode->clock < 320000) { + val = 0x2b; + pre_div = 8; + } else { + val = 0x2f; + pre_div = 16; + } + ret = regmap_write(ctx->regmap, 0x8231, val); + if (ret < 0) + return ret; + + /* 0x8232: serickdiv sel */ + if (phy_clk < 80000) { + val = 0x32; + sericlk_div = 16; + } else if (phy_clk < 160000) { + val = 0x22; + sericlk_div = 8; + } else if (phy_clk < 320000) { + val = 0x12; + sericlk_div = 4; + } else if (phy_clk < 640000) { + val = 0x02; + sericlk_div = 2; + } else { + val = 0x42; + sericlk_div = 1; + } + ret = regmap_write(ctx->regmap, 0x8232, val); + if (ret < 0) + return ret; + + /* + * 0x8233: pix_mux sel & pix_div sel + * To avoid floating point operations, The pixclk_div is enlarged by 10 times + */ + if (mode->clock > 150000) { + val = 0x04; + pixclk_div = 35; + } else { + pixclk_div = + (u8)((phy_clk * sericlk_div * 10) / (mode->clock * 7)); + if (pixclk_div <= 10) + val = 0x00; + else if (pixclk_div <= 20) + val = 0x01; + else if (pixclk_div <= 40) + val = 0x02; + else + val = 0x03; + } + ret = regmap_write(ctx->regmap, 0x8233, val); + if (ret < 0) + return ret; + + ret = regmap_write(ctx->regmap, 0x8234, 0x01); + if (ret < 0) + return ret; + + /* 0x8235: div set */ + div_set = (u8)(phy_clk * sericlk_div / mode->clock / pre_div); + ret = regmap_write(ctx->regmap, 0x8235, div_set); + if (ret < 0) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_ssc_seq, + ARRAY_SIZE(lt9211c_tx_ssc_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_pll_reset_seq, + ARRAY_SIZE(lt9211c_tx_pll_reset_seq)); + if (ret) + return ret; + + ret = regmap_read_poll_timeout(ctx->regmap, 0x8739, pval, pval & 0x04, + 10000, 1000000); + if (ret) { + dev_err(ctx->dev, "TX PLL unstable, ret=%i\n", ret); + return ret; + } + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_phy_seq, + ARRAY_SIZE(lt9211c_tx_phy_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_mltx_reset, + ARRAY_SIZE(lt9211c_tx_mltx_reset)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_dig_seq, + ARRAY_SIZE(lt9211c_tx_dig_seq)); + if (ret) + return ret; + + ret = regmap_multi_reg_write(ctx->regmap, lt9211c_tx_sw_reset_seq, + ARRAY_SIZE(lt9211c_tx_sw_reset_seq)); + if (ret) + return ret; + + return 0; +} + +static void lt9211_work_func(struct work_struct *work) +{ + struct lt9211 *ctx = container_of(work, struct lt9211, lt9211_work); + const struct drm_display_mode *mode = &ctx->lt9211c_mode; + int ret; + + /* wait for vblank irq to correctly configure bridge and autodetect stream */ + ret = drm_crtc_wait_one_vblank(ctx->lt9211c_crtc); + if (ret) { + dev_err(ctx->dev, "LT9211C: wait for vblank failed: %d\n", ret); + return; + } + + ret = lt9211c_configure_rx(ctx); + if (ret) { + dev_err(ctx->dev, "LT9211C: configure_rx failed: %d\n", ret); + return; + } + + ret = lt9211c_autodetect_rx(ctx, mode); + if (ret) { + dev_err(ctx->dev, "LT9211C: autodetect_rx failed: %d\n", ret); + return; + } + + ret = lt9211c_configure_timing(ctx, mode); + if (ret) { + dev_err(ctx->dev, "LT9211C: configure_timing failed: %d\n", ret); + return; + } + + ret = lt9211c_configure_plls(ctx, mode); + if (ret) { + dev_err(ctx->dev, "LT9211C: configure_plls failed: %d\n", ret); + return; + } + + ret = lt9211c_configure_tx(ctx, ctx->lt9211c_jeida, ctx->lt9211c_bpp24, + ctx->lt9211c_de_high, mode); + if (ret) { + dev_err(ctx->dev, "LT9211C: configure_tx failed: %d\n", ret); + return; + } +} + static void lt9211_atomic_enable(struct drm_bridge *bridge, struct drm_atomic_commit *state) { @@ -523,6 +1271,21 @@ static void lt9211_atomic_enable(struct drm_bridge *bridge, if (ret) return; + if (ctx->chip_data->chip_type == LT9211C) { + drm_mode_copy(&ctx->lt9211c_mode, mode); + ctx->lt9211c_bpp24 = lvds_format_24bpp; + ctx->lt9211c_jeida = lvds_format_jeida; + ctx->lt9211c_de_high = !!(bus_flags & DRM_BUS_FLAG_DE_HIGH); + ctx->lt9211c_crtc = crtc; + + /* + * Needs a live DSI stream to auto-detect RX resolution/format; + * defer bridge configuration until vblank inside the work item. + */ + queue_work(ctx->wq, &ctx->lt9211_work); + return; + } + ret = lt9211_system_init(ctx); if (ret) return; @@ -557,6 +1320,9 @@ static void lt9211_atomic_disable(struct drm_bridge *bridge, struct lt9211 *ctx = bridge_to_lt9211(bridge); int ret; + if (ctx->chip_data->chip_type == LT9211C) + cancel_work_sync(&ctx->lt9211_work); + /* * Put the chip in reset, pull nRST line low, * and assure lengthy 10ms reset low timing. @@ -672,14 +1438,13 @@ static int lt9211_parse_dt(struct lt9211 *ctx) static int lt9211_host_attach(struct lt9211 *ctx) { - const struct mipi_dsi_device_info info = { - .type = "lt9211", - .channel = 0, - .node = NULL, - }; struct device *dev = ctx->dev; struct device_node *host_node; struct device_node *endpoint; + struct mipi_dsi_device_info info = { + .channel = 0, + .node = NULL, + }; struct mipi_dsi_device *dsi; struct mipi_dsi_host *host; int dsi_lanes; @@ -698,6 +1463,7 @@ static int lt9211_host_attach(struct lt9211 *ctx) if (dsi_lanes < 0) return dsi_lanes; + strscpy(info.type, ctx->chip_data->dsi_type, sizeof(info.type)); dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) return dev_err_probe(dev, PTR_ERR(dsi), @@ -707,10 +1473,7 @@ static int lt9211_host_attach(struct lt9211 *ctx) dsi->lanes = dsi_lanes; dsi->format = MIPI_DSI_FMT_RGB888; - dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | - MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA | - MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP | - MIPI_DSI_MODE_NO_EOT_PACKET; + dsi->mode_flags = ctx->chip_data->dsi_mode_flags; ret = devm_mipi_dsi_attach(dev, dsi); if (ret < 0) { @@ -721,6 +1484,11 @@ static int lt9211_host_attach(struct lt9211 *ctx) return 0; } +static void lt9211_destroy_wq(void *data) +{ + destroy_workqueue(data); +} + static int lt9211_probe(struct i2c_client *client) { struct device *dev = &client->dev; @@ -748,45 +1516,53 @@ static int lt9211_probe(struct i2c_client *client) if (ret) return ret; - ctx->regmap = devm_regmap_init_i2c(client, <9211_regmap_config); + ctx->chip_data = i2c_get_match_data(client); + if (!ctx->chip_data) + return -ENODEV; + + ctx->regmap = devm_regmap_init_i2c(client, ctx->chip_data->regmap_config); if (IS_ERR(ctx->regmap)) return PTR_ERR(ctx->regmap); - dev_set_drvdata(dev, ctx); - i2c_set_clientdata(client, ctx); - ctx->bridge.of_node = dev->of_node; - drm_bridge_add(&ctx->bridge); + ret = devm_drm_bridge_add(dev, &ctx->bridge); + if (ret) + return ret; ret = lt9211_host_attach(ctx); if (ret) - drm_bridge_remove(&ctx->bridge); - - return ret; -} + return ret; -static void lt9211_remove(struct i2c_client *client) -{ - struct lt9211 *ctx = i2c_get_clientdata(client); + if (ctx->chip_data->chip_type == LT9211C) { + ctx->wq = create_workqueue("lt9211_work"); + if (!ctx->wq) + return -ENOMEM; + /* Register after DSI attach so devres flushes work before freeing ctx->dsi. */ + ret = devm_add_action_or_reset(dev, lt9211_destroy_wq, ctx->wq); + if (ret) + return ret; + INIT_WORK(&ctx->lt9211_work, lt9211_work_func); + } - drm_bridge_remove(&ctx->bridge); + return 0; } static const struct i2c_device_id lt9211_id[] = { - { .name = "lt9211" }, + { .name = "lontium,lt9211", .driver_data = (kernel_ulong_t)<9211_chip_data }, + { .name = "lontium,lt9211c", .driver_data = (kernel_ulong_t)<9211c_chip_data }, { } }; MODULE_DEVICE_TABLE(i2c, lt9211_id); static const struct of_device_id lt9211_match_table[] = { - { .compatible = "lontium,lt9211" }, + { .compatible = "lontium,lt9211", .data = <9211_chip_data }, + { .compatible = "lontium,lt9211c", .data = <9211c_chip_data }, {}, }; MODULE_DEVICE_TABLE(of, lt9211_match_table); static struct i2c_driver lt9211_driver = { .probe = lt9211_probe, - .remove = lt9211_remove, .id_table = lt9211_id, .driver = { .name = "lt9211", From 0a2804d7b402c3d67958b7722cdf30397ba13d5a Mon Sep 17 00:00:00 2001 From: Nilesh Laad Date: Wed, 26 Nov 2025 17:01:18 +0530 Subject: [PATCH 0917/1133] FROMLIST: drm/bridge: lt9611uxc: extend mode valid checks Currently valid mode checks are only for hdisplay and vdisplay, add htotal and vtotal to filter only specific modes. Link:https://lore.kernel.org/lkml/20251126-lt9611uxc-modes-v2-1-34bf9b351921@oss.qualcomm.com/ Signed-off-by: Nilesh Laad Signed-off-by: Mahadevan P --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 36 ++++++++++++---------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index 80c82c18b8d2f..277a59ffff6cb 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -87,7 +87,9 @@ static const struct regmap_config lt9611uxc_regmap_config = { struct lt9611uxc_mode { u16 hdisplay; + u16 htotal; u16 vdisplay; + u16 vtotal; u8 vrefresh; }; @@ -96,22 +98,22 @@ struct lt9611uxc_mode { * Enumerate them here to check whether the mode is supported. */ static struct lt9611uxc_mode lt9611uxc_modes[] = { - { 1920, 1080, 60 }, - { 1920, 1080, 30 }, - { 1920, 1080, 25 }, - { 1366, 768, 60 }, - { 1360, 768, 60 }, - { 1280, 1024, 60 }, - { 1280, 800, 60 }, - { 1280, 720, 60 }, - { 1280, 720, 50 }, - { 1280, 720, 30 }, - { 1152, 864, 60 }, - { 1024, 768, 60 }, - { 800, 600, 60 }, - { 720, 576, 50 }, - { 720, 480, 60 }, - { 640, 480, 60 }, + { 1920, 2200, 1080, 1125, 60 }, + { 1920, 2200, 1080, 1125, 30 }, + { 1920, 2640, 1080, 1125, 25 }, + { 1366, 1792, 768, 798, 60 }, + { 1360, 1792, 768, 795, 60 }, + { 1280, 1688, 1024, 1066, 60 }, + { 1280, 1680, 800, 831, 60 }, + { 1280, 1650, 720, 750, 60 }, + { 1280, 1980, 720, 750, 50 }, + { 1280, 3300, 720, 750, 30 }, + { 1152, 1600, 864, 900, 60 }, + { 1024, 1344, 768, 806, 60 }, + { 800, 1056, 600, 628, 60 }, + { 720, 864, 576, 625, 50 }, + { 720, 858, 480, 525, 60 }, + { 640, 800, 480, 525, 60 }, }; static struct lt9611uxc *bridge_to_lt9611uxc(struct drm_bridge *bridge) @@ -238,7 +240,9 @@ static struct lt9611uxc_mode *lt9611uxc_find_mode(const struct drm_display_mode for (i = 0; i < ARRAY_SIZE(lt9611uxc_modes); i++) { if (lt9611uxc_modes[i].hdisplay == mode->hdisplay && + lt9611uxc_modes[i].htotal == mode->htotal && lt9611uxc_modes[i].vdisplay == mode->vdisplay && + lt9611uxc_modes[i].vtotal == mode->vtotal && lt9611uxc_modes[i].vrefresh == drm_mode_vrefresh(mode)) { return <9611uxc_modes[i]; } From 9d98593b588e42f71887c58cb29fed0d720621e4 Mon Sep 17 00:00:00 2001 From: Nilesh Laad Date: Wed, 26 Nov 2025 18:52:37 +0530 Subject: [PATCH 0918/1133] FROMLIST: drm/bridge: lt9611uxc: add support for 4K@30 resolution Add 3840x2160@30 mode in lt9611uxc modes to add support for 4K@30 resolution. Link:https://lore.kernel.org/r/20251126-lt9611uxc-4k30-v2-1-3de0ea58c24e@oss.qualcomm.com Signed-off-by: Nilesh Laad Signed-off-by: Mahadevan P --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index 277a59ffff6cb..ff1655c737e9d 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -98,6 +98,7 @@ struct lt9611uxc_mode { * Enumerate them here to check whether the mode is supported. */ static struct lt9611uxc_mode lt9611uxc_modes[] = { + { 3840, 4400, 2160, 2250, 30 }, { 1920, 2200, 1080, 1125, 60 }, { 1920, 2200, 1080, 1125, 30 }, { 1920, 2640, 1080, 1125, 25 }, From af38d5e2138484e99add77029ea7e6a306b1dda1 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Fri, 28 Aug 2026 15:13:13 +0530 Subject: [PATCH 0919/1133] FROMLIST: phy: qualcomm: qmp-combo: Add DP COM v8 header and fix register layout Add the new DP-specific QSERDES COM v8 header file and update the register layout to use DP-specific status register offsets for C_READY_STATUS and CMN_STATUS registers. Signed-off-by: Ritesh Kumar Signed-off-by: Mahadevan P Signed-off-by: Nabige Aala Fixes: 5b289913959b ("phy: qualcomm: qmp-combo: Update QMP PHY with Glymur settings") Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20260828-glymur-phy-v3-v3-1-8e73ce7c4636@oss.qualcomm.com --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 187f0cd11f6c3..cd14efc3c59a8 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -52,6 +52,7 @@ #include "phy-qcom-qmp-dp-phy-v5.h" #include "phy-qcom-qmp-dp-phy-v6.h" #include "phy-qcom-qmp-dp-phy-v8.h" +#include "phy-qcom-qmp-qserdes-dp-com-v8.h" #include "phy-qcom-qmp-dp-phy-v10.h" #include "phy-qcom-qmp-usb43-pcs-v8.h" @@ -326,8 +327,8 @@ static const unsigned int qmp_v8_n3_usb43dpphy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_DP_AON_TOGGLE_ENABLE] = QPHY_V8_PCS_AON_DP_AON_TOGGLE_ENABLE, [QPHY_COM_RESETSM_CNTRL] = QSERDES_V8_COM_RESETSM_CNTRL, - [QPHY_COM_C_READY_STATUS] = QSERDES_V8_COM_C_READY_STATUS, - [QPHY_COM_CMN_STATUS] = QSERDES_V8_COM_CMN_STATUS, + [QPHY_COM_C_READY_STATUS] = DP_QSERDES_V8_COM_C_READY_STATUS, + [QPHY_COM_CMN_STATUS] = DP_QSERDES_V8_COM_CMN_STATUS, [QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN, [QPHY_DP_PHY_STATUS] = QSERDES_V8_DP_PHY_STATUS, From 277154e798cf9ea25e2125d53edc9c2b98dc0780 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Fri, 28 Aug 2026 15:13:14 +0530 Subject: [PATCH 0920/1133] FROMLIST: phy: qualcomm: qmp-combo: Update DP PHY common init tables Update common DP PHY serdes and TX initialization tables with corrected PLL control values (MODE0 instead of MODE1), updated SSC step size, reset control, and various TX lane configuration parameters including emphasis levels and driver enable settings. Signed-off-by: Ritesh Kumar Signed-off-by: Mahadevan P Signed-off-by: Nabige Aala Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20260828-glymur-phy-v3-v3-2-8e73ce7c4636@oss.qualcomm.com --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index cd14efc3c59a8..4ed366d1751bd 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -1502,10 +1502,10 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl[] = { }; static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CP_CTRL_MODE0, 0x06), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE1, 0x10), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORECLK_DIV_MODE0, 0x0a), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE0, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), @@ -1520,12 +1520,13 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_BUF_ENABLE, 0x06), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_IVCO, 0x07), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x3b), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_RESETSM_CNTRL, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP_EN, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_CTRL, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_MAP, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_SELECT, 0x30), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORE_CLK_EN, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x56), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x16), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SVS_MODE_CLK_SEL, 0x15), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD1, 0x24), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DCC_CAL_1, 0x40), @@ -1561,26 +1562,26 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_tx_tbl[] = { }; static const struct qmp_phy_init_tbl qmp_v8_n3p_dp_tx_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRANSMITTER_EN_CTRL, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRANSMITTER_EN_CTRL, 0x1a), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_VMODE_CTRL1, 0x40), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_ANA_INTERFACE_SELECT1, 0x07), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_ANA_INTERFACE_SELECT2, 0x18), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCS_INTERFACE_SELECT1, 0x50), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_1, 0x0d), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CLKBUF_ENABLE, 0x07), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CLKBUF_ENABLE, 0x87), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL, 0x0f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_LVL_UPDATE_CTRL, 0x0f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRAN_DRVR_EMP_EN, 0x5f), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_EMP_POST1_LVL, 0x20), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_EMP_POST1_LVL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_EMP_POST1_LVL, 0x2b), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_EMP_POST1_LVL, 0x2b), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_PRE1_EMPH, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_PRE1_EMPH, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_DRV_LVL, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_DRV_LVL, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_HIGHZ_DRVR_EN, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_HIGHZ_DRVR_EN, 0x3f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_2, 0x50), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_3, 0x51), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_DCC_ANA_CTRL2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_DCC_ANA_CTRL2, 0x0c), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_CAL_CTRL, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_RESTRIM_CAL_CTRL, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_POST_CAL_OFFSET, 0x10), From 29e8b85573badd506b50f570daddf2b20d23a384 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Fri, 28 Aug 2026 15:13:15 +0530 Subject: [PATCH 0921/1133] FROMLIST: phy: qualcomm: qmp-combo: Update link rate specific DP PHY tables Update DP PHY initialization tables for all link rates (RBR, HBR, HBR2, HBR3) with corrected VCO calibration codes, lock compare values, SSC step sizes, clock forward config, and bias enable settings for proper PLL programming across different data rates. Signed-off-by: Ritesh Kumar Signed-off-by: Mahadevan P Signed-off-by: Nabige Aala Fixes: d10736db98d2 ("phy: qualcomm: qmp-combo: Add DP offsets and settings for Glymur platforms") Reviewed-by: Konrad Dybcio Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20260828-glymur-phy-v3-v3-3-8e73ce7c4636@oss.qualcomm.com --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 43 ++++++++++++----------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 4ed366d1751bd..71f5e8ccfabeb 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -1754,11 +1754,12 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl_hbr3[] = { static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_rbr[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x05), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x7a), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x8d), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x27), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x83), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x37), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x54), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x06), @@ -1766,16 +1767,17 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_rbr[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x05), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x07), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x30), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xa4), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xa7), }; static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x04), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x21), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xf6), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x18), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x08), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x07), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x46), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0x00), @@ -1792,7 +1794,8 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr2[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x03), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xf6), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x20), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE0, 0x16), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x10), @@ -1802,9 +1805,9 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr2[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x05), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE1_MODE0, 0xae), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x02), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xbf), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x17), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_RESETSM_CNTRL, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x03), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x3f), @@ -1812,8 +1815,8 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr2[] = { static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr3[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x02), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x63), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x25), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x5b), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CP_CTRL_MODE0, 0x06), @@ -1821,7 +1824,7 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr3[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORECLK_DIV_MODE0, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x17), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x18), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x15), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x4f), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE0, 0x00), @@ -1840,19 +1843,19 @@ static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr3[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYS_CLK_CTRL, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_BUF_ENABLE, 0x06), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_IVCO, 0x07), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x3b), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_CTRL, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_MAP, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_SELECT, 0x30), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORE_CLK_EN, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x16), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SVS_MODE_CLK_SEL, 0x15), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x30), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x17), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x05), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD1, 0x24), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x02), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0x84), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0x87), }; static const struct qmp_phy_init_tbl sc8280xp_usb43dp_serdes_tbl[] = { From 3ed1e3ecf75e7ebd633d34d20029664ecf4d7fc2 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Wed, 4 Nov 2026 18:32:17 +0530 Subject: [PATCH 0922/1133] FROMLIST: phy: qualcomm: qmp-combo: Rework DP PHY runtime configuration Rework the DP PHY runtime configuration by: - Extracting common DP PHY initialization sequence into qmp_combo_configure_dp_phy_common() function that is shared between qmp_v456_configure_dp_phy() and qmp_v8_configure_dp_phy() - Adding dp_aux_cfg2 field to qmp_phy_cfg structure to store the hardware-specific AUX_CFG2 register value - Defining named constants (QSERDES_DP_PHY_AUX_CFG2_V456 and QSERDES_DP_PHY_AUX_CFG2_V8) for better code readability and maintainability - Adding validation check to ensure dp_aux_cfg2 is properly configured for all hardware variants - Updating qmp_v8_dp_aux_init() with corrected power-down control and bias enable settings - Modifying qmp_v8_configure_dp_clocks() to add VCO divider programming and update auxless/LFPS timing parameters - Refining qmp_v8_configure_dp_phy() with updated driver enable values, TSYNC override sequence, and additional status checks for proper PHY lock verification Signed-off-by: Ritesh Kumar Signed-off-by: Mahadevan P Signed-off-by: Nabige Aala Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20260828-glymur-phy-v3-v3-4-8e73ce7c4636@oss.qualcomm.com --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 185 ++++++++++++++-------- 1 file changed, 118 insertions(+), 67 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 71f5e8ccfabeb..4c871e9f7f8ed 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -2500,6 +2500,10 @@ static const struct qmp_combo_lane_mapping dp_data_lanes[] = { struct qmp_combo; +/* DP PHY AUX_CFG2 register values for different hardware versions */ +#define QSERDES_DP_PHY_AUX_CFG2_V456 0xa4 +#define QSERDES_DP_PHY_AUX_CFG2_V8 0x06 + struct qmp_combo_offsets { u16 com; u16 txa; @@ -2577,6 +2581,9 @@ struct qmp_phy_cfg { const struct qmp_phy_init_tbl *usb4_pcs_tbl; int usb4_pcs_tbl_num; + /* DP PHY AUX_CFG2 register value (hardware-specific) */ + unsigned int dp_aux_cfg2; + /* resets to be requested */ const char * const *reset_list; int num_resets; @@ -2817,6 +2824,7 @@ static const struct qmp_phy_cfg sar2130p_usb3dpphy_cfg = { .configure_dp_tx = qmp_v4_configure_dp_tx, .configure_dp_clocks = qmp_v3_configure_dp_clocks, .configure_dp_phy = qmp_v4_configure_dp_phy, + .dp_aux_cfg2 = QSERDES_DP_PHY_AUX_CFG2_V456, .regs = qmp_v6_usb3phy_regs_layout, .reset_list = msm8996_usb3phy_reset_l, @@ -2953,6 +2961,7 @@ static const struct qmp_phy_cfg sc8180x_usb3dpphy_cfg = { .configure_dp_tx = qmp_v4_configure_dp_tx, .configure_dp_clocks = qmp_v3_configure_dp_clocks, .configure_dp_phy = qmp_v4_configure_dp_phy, + .dp_aux_cfg2 = QSERDES_DP_PHY_AUX_CFG2_V456, .reset_list = msm8996_usb3phy_reset_l, .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), @@ -2999,6 +3008,7 @@ static const struct qmp_phy_cfg sc8280xp_usb43dpphy_cfg = { .configure_dp_tx = qmp_v4_configure_dp_tx, .configure_dp_clocks = qmp_v3_configure_dp_clocks, .configure_dp_phy = qmp_v4_configure_dp_phy, + .dp_aux_cfg2 = QSERDES_DP_PHY_AUX_CFG2_V456, .reset_list = msm8996_usb3phy_reset_l, .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), @@ -3044,6 +3054,7 @@ static const struct qmp_phy_cfg x1e80100_usb3dpphy_cfg = { .configure_dp_tx = qmp_v4_configure_dp_tx, .configure_dp_clocks = qmp_v3_configure_dp_clocks, .configure_dp_phy = qmp_v4_configure_dp_phy, + .dp_aux_cfg2 = QSERDES_DP_PHY_AUX_CFG2_V456, .reset_list = msm8996_usb3phy_reset_l, .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), @@ -3153,6 +3164,7 @@ static const struct qmp_phy_cfg sm8250_usb3dpphy_cfg = { .configure_dp_tx = qmp_v4_configure_dp_tx, .configure_dp_clocks = qmp_v3_configure_dp_clocks, .configure_dp_phy = qmp_v4_configure_dp_phy, + .dp_aux_cfg2 = QSERDES_DP_PHY_AUX_CFG2_V456, .reset_list = msm8996_usb3phy_reset_l, .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), @@ -3201,6 +3213,7 @@ static const struct qmp_phy_cfg sm8350_usb3dpphy_cfg = { .configure_dp_tx = qmp_v4_configure_dp_tx, .configure_dp_clocks = qmp_v3_configure_dp_clocks, .configure_dp_phy = qmp_v4_configure_dp_phy, + .dp_aux_cfg2 = QSERDES_DP_PHY_AUX_CFG2_V456, .reset_list = msm8996_usb3phy_reset_l, .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), @@ -3248,6 +3261,7 @@ static const struct qmp_phy_cfg sm8475_usb3dpphy_cfg = { .configure_dp_tx = qmp_v4_configure_dp_tx, .configure_dp_clocks = qmp_v3_configure_dp_clocks, .configure_dp_phy = qmp_v4_configure_dp_phy, + .dp_aux_cfg2 = QSERDES_DP_PHY_AUX_CFG2_V456, .regs = qmp_v6_usb3phy_regs_layout, .reset_list = msm8996_usb3phy_reset_l, @@ -3293,6 +3307,7 @@ static const struct qmp_phy_cfg sm8550_usb3dpphy_cfg = { .configure_dp_tx = qmp_v4_configure_dp_tx, .configure_dp_clocks = qmp_v3_configure_dp_clocks, .configure_dp_phy = qmp_v4_configure_dp_phy, + .dp_aux_cfg2 = QSERDES_DP_PHY_AUX_CFG2_V456, .regs = qmp_v6_usb3phy_regs_layout, .reset_list = msm8996_usb3phy_reset_l, @@ -3338,6 +3353,7 @@ static const struct qmp_phy_cfg sm8650_usb3dpphy_cfg = { .configure_dp_tx = qmp_v4_configure_dp_tx, .configure_dp_clocks = qmp_v3_configure_dp_clocks, .configure_dp_phy = qmp_v4_configure_dp_phy, + .dp_aux_cfg2 = QSERDES_DP_PHY_AUX_CFG2_V456, .regs = qmp_v6_usb3phy_regs_layout, .reset_list = msm8996_usb3phy_reset_l, @@ -3383,6 +3399,7 @@ static const struct qmp_phy_cfg sm8750_usb3dpphy_cfg = { .configure_dp_tx = qmp_v4_configure_dp_tx, .configure_dp_clocks = qmp_v3_configure_dp_clocks, .configure_dp_phy = qmp_v4_configure_dp_phy, + .dp_aux_cfg2 = QSERDES_DP_PHY_AUX_CFG2_V456, .regs = qmp_v8_usb3phy_regs_layout, .reset_list = msm8996_usb3phy_reset_l, @@ -3429,6 +3446,8 @@ static const struct qmp_phy_cfg glymur_usb3dpphy_cfg = { .configure_dp_clocks = qmp_v8_configure_dp_clocks, .configure_dp_phy = qmp_v8_configure_dp_phy, + .dp_aux_cfg2 = QSERDES_DP_PHY_AUX_CFG2_V8, + .regs = qmp_v8_n3_usb43dpphy_regs_layout, .reset_list = msm8996_usb3phy_reset_l, .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), @@ -3775,16 +3794,75 @@ static void qmp_v4_dp_aux_init(struct qmp_combo *qmp) qmp->dp_dp_phy + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK); } +static int qmp_combo_configure_dp_phy_common(struct qmp_combo *qmp) +{ + const struct qmp_phy_cfg *cfg = qmp->cfg; + u32 status; + int ret; + + if (!cfg->dp_aux_cfg2) { + dev_err(qmp->dev, "DP AUX CFG2 value not configured\n"); + return -EINVAL; + } + + writel(0x0f, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG_1); + + qmp_combo_configure_dp_mode(qmp); + + writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); + writel(cfg->dp_aux_cfg2, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG2); + + writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); + writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); + + ret = qmp->cfg->configure_dp_clocks(qmp); + if (ret) + return ret; + + writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + writel(0x05, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); + + writel(0x20, qmp->dp_serdes + cfg->regs[QPHY_COM_RESETSM_CNTRL]); + + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_C_READY_STATUS], + status, + ((status & BIT(0)) > 0), + 500, + 10000)) + return -ETIMEDOUT; + + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(0)) > 0), + 500, + 10000)) + return -ETIMEDOUT; + + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(1)) > 0), + 500, + 10000)) + return -ETIMEDOUT; + + return 0; +} + static void qmp_v8_dp_aux_init(struct qmp_combo *qmp) { const struct qmp_phy_cfg *cfg = qmp->cfg; - writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | - DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, - qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); + writel(0x3f, qmp->dp_serdes + QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1); + + writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | + DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | + DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, + qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); /* Turn on BIAS current for PHY/PLL */ - writel(0x1c, qmp->dp_serdes + cfg->regs[QPHY_COM_BIAS_EN_CLKBUFLR_EN]); + writel(0x17, qmp->dp_serdes + cfg->regs[QPHY_COM_BIAS_EN_CLKBUFLR_EN]); writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG0); writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); @@ -3811,8 +3889,8 @@ static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp) writel(0x27, qmp->dp_tx + cfg->regs[QPHY_TX_TX_DRV_LVL]); writel(0x27, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_DRV_LVL]); - writel(0x20, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); - writel(0x20, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); + writel(0x2b, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); + writel(0x2b, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); qmp_combo_configure_dp_swing(qmp); } @@ -3820,48 +3898,41 @@ static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp) static int qmp_v8_configure_dp_clocks(struct qmp_combo *qmp) { const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; - u32 phy_vco_div; unsigned long pixel_freq; - const struct qmp_phy_cfg *cfg = qmp->cfg; switch (dp_opts->link_rate) { case 1620: - phy_vco_div = 0x4; pixel_freq = 1620000000UL / 2; break; case 2700: - phy_vco_div = 0x2; pixel_freq = 2700000000UL / 2; break; case 5400: - phy_vco_div = 0x4; pixel_freq = 5400000000UL / 4; break; case 8100: - phy_vco_div = 0x3; pixel_freq = 8100000000UL / 6; break; default: /* Other link rates aren't supported */ return -EINVAL; } - writel(phy_vco_div, qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_VCO_DIV]); /* disable core reset tsync */ writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); - writel(0x04, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SETUP_CYC); - writel(0x08, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SILENCE_CYC); + writel(0x09, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SETUP_CYC); + writel(0x11, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SILENCE_CYC); writel(0x08, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_CYC); - writel(0x11, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); + writel(0x33, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); writel(0x3e, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); writel(0x05, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TX2_TX3_LANE_CTL); writel(0x05, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TX0_TX1_LANE_CTL); writel(0x01, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_CFG1); - writel(0x11, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); + writel(0x33, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD); writel(0x1f, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LN0_DRV_LVL); - writel(0x1f, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LN1_DRV_LVL); + writel(0x02, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LN1_DRV_LVL); clk_set_rate(qmp->dp_link_hw.clk, dp_opts->link_rate * 100000); clk_set_rate(qmp->dp_pixel_hw.clk, pixel_freq); @@ -3875,48 +3946,10 @@ static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp) u32 status; int ret; - writel(0x0f, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG_1); - - qmp_combo_configure_dp_mode(qmp); - - writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1); - writel(0xa4, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG2); - - writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); - writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); - - ret = qmp->cfg->configure_dp_clocks(qmp); + ret = qmp_combo_configure_dp_phy_common(qmp); if (ret) return ret; - writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); - writel(0x05, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); - writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); - writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); - - writel(0x20, qmp->dp_serdes + cfg->regs[QPHY_COM_RESETSM_CNTRL]); - - if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_C_READY_STATUS], - status, - ((status & BIT(0)) > 0), - 500, - 10000)) - return -ETIMEDOUT; - - if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], - status, - ((status & BIT(0)) > 0), - 500, - 10000)) - return -ETIMEDOUT; - - if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], - status, - ((status & BIT(1)) > 0), - 500, - 10000)) - return -ETIMEDOUT; - writel(0x19, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); if (readl_poll_timeout(qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_STATUS], @@ -4008,7 +4041,7 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) u32 status; int ret; - ret = qmp_v456_configure_dp_phy(qmp); + ret = qmp_combo_configure_dp_phy_common(qmp); if (ret < 0) return ret; @@ -4020,13 +4053,13 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) } else if (dp_opts->lanes == 2) { bias0_en = reverse ? 0x3f : 0x15; bias1_en = reverse ? 0x15 : 0x3f; - drvr0_en = 0x10; - drvr1_en = 0x10; + drvr0_en = 0x30; + drvr1_en = 0x30; } else { bias0_en = 0x3f; bias1_en = 0x3f; - drvr0_en = 0x34; - drvr1_en = 0x34; + drvr0_en = 0x30; + drvr1_en = 0x30; } writel(drvr0_en, qmp->dp_tx + cfg->regs[QPHY_TX_HIGHZ_DRVR_EN]); @@ -4034,6 +4067,15 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) writel(drvr1_en, qmp->dp_tx2 + cfg->regs[QPHY_TX_HIGHZ_DRVR_EN]); writel(bias1_en, qmp->dp_tx2 + cfg->regs[QPHY_TX_TRANSCEIVER_BIAS_EN]); + writel(0x03, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); + writel(0x23, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); + writel(0x22, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); + + writel(0x0a, qmp->dp_tx + QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL); + writel(0x0a, qmp->dp_tx2 + QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL); + + writel(0x3e, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD); + writel(0x08, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); udelay(100); writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); @@ -4041,16 +4083,25 @@ static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp) if (readl_poll_timeout(qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_STATUS], status, - ((status & BIT(1)) > 0), + ((status & BIT(0)) > 0), 500, 10000)) return -ETIMEDOUT; - writel(0x00, qmp->dp_tx + cfg->regs[QPHY_TX_TX_DRV_LVL]); - writel(0x00, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_DRV_LVL]); - writel(0x2b, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); - writel(0x2b, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]); + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(0)) > 0), + 500, + 10000)) + return -ETIMEDOUT; + + if (readl_poll_timeout(qmp->dp_serdes + cfg->regs[QPHY_COM_CMN_STATUS], + status, + ((status & BIT(1)) > 0), + 500, + 10000)) + return -ETIMEDOUT; return 0; } From 3eaa962807b3522f9b9af58c049d178909aa6c4e Mon Sep 17 00:00:00 2001 From: Arpit Saini Date: Wed, 30 Sep 2026 16:45:12 +0530 Subject: [PATCH 0923/1133] FROMLIST: arm64: dts: qcom: shikra-cqs-evk: Enable display and add ili7807s panel Enable the Shikra MDSS display subsystem on the Qualcomm Shikra CQS EVK board and add the DLC0697 MIPI DSI display panel node. Signed-off-by: Nabige Aala Signed-off-by: Arpit Saini Link: https://lore.kernel.org/r/20260930-shikra-dt-changes-v5-2-8eaf658a0e38@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 110 ++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 2ded25c4304e6..2aab335ff0ffc 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -23,6 +23,86 @@ chosen { stdout-path = "serial0:115200n8"; }; + + lcd_bias: regulator-lcd-bias { + compatible = "regulator-fixed"; + regulator-name = "lcd_bias"; + gpio = <&tlmm 151 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&lcd_bias_en>; + pinctrl-names = "default"; + }; + + vreg_disp_n: regulator-vreg-disp-n { + compatible = "regulator-fixed"; + regulator-name = "vreg_disp_n"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + vin-supply = <&lcd_bias>; + }; + + vreg_disp_p: regulator-vreg-disp-p { + compatible = "regulator-fixed"; + regulator-name = "vreg_disp_p"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + vin-supply = <&lcd_bias>; + }; + + vreg_wled: regulator-wled { + compatible = "regulator-fixed"; + regulator-name = "vreg_wled"; + gpio = <&tlmm 91 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm4125_l5>; + + status = "okay"; + + panel@0 { + compatible = "dlc,dlc0697", "ilitek,ili7807s"; + reg = <0>; + + reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + + vddi-supply = <&pm4125_l15>; + avdd-supply = <&vreg_disp_p>; + avee-supply = <&vreg_disp_n>; + wled-supply = <&vreg_wled>; + + pinctrl-0 = <&panel_rst_n &panel_te_pin>; + pinctrl-1 = <&panel_rst_n_suspend>; + pinctrl-names = "default", "sleep"; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; +}; + +&pm4125_l5 { + /* DSI VDDA - must be at NOM voltage for PHY PLL lock */ + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1232000>; + regulator-allow-set-load; }; &pm4125_hs_in { @@ -75,6 +155,36 @@ status = "okay"; }; +&tlmm { + panel_rst_n: panel-rst-n-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + panel_rst_n_suspend: panel-rst-n-suspend-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + panel_te_pin: panel-te-pin-state { + pins = "gpio86"; + function = "mdp_vsync_p"; + drive-strength = <2>; + bias-pull-down; + }; + + lcd_bias_en: lcd-bias-en-state { + pins = "gpio151"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; + &usb_1 { dr_mode = "otg"; }; From 7892111a9f437226c7da7d9a81fbfdd29c7826c9 Mon Sep 17 00:00:00 2001 From: Arpit Saini Date: Wed, 30 Sep 2026 16:45:13 +0530 Subject: [PATCH 0924/1133] FROMLIST: arm64: dts: qcom: shikra-cqm-evk: Enable display and add ili7807s panel Enable the Shikra MDSS display subsystem on the Qualcomm Shikra CQM EVK board and add the DLC0697 MIPI DSI display panel node. Pin pm4125_l5 to 1.232V with regulator-allow-set-load for DSI PHY PLL stability. Signed-off-by: Nabige Aala Signed-off-by: Arpit Saini Link: https://lore.kernel.org/r/20260930-shikra-dt-changes-v5-3-8eaf658a0e38@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 110 ++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index bde3b7d81acec..548cba16f5f37 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -23,12 +23,92 @@ chosen { stdout-path = "serial0:115200n8"; }; + + lcd_bias: regulator-lcd-bias { + compatible = "regulator-fixed"; + regulator-name = "lcd_bias"; + gpio = <&tlmm 151 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&lcd_bias_en>; + pinctrl-names = "default"; + }; + + vreg_disp_n: regulator-vreg-disp-n { + compatible = "regulator-fixed"; + regulator-name = "vreg_disp_n"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + vin-supply = <&lcd_bias>; + }; + + vreg_disp_p: regulator-vreg-disp-p { + compatible = "regulator-fixed"; + regulator-name = "vreg_disp_p"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + vin-supply = <&lcd_bias>; + }; + + vreg_wled: regulator-wled { + compatible = "regulator-fixed"; + regulator-name = "vreg_wled"; + gpio = <&tlmm 91 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; }; &audiocorecc { status = "okay"; }; +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm4125_l5>; + + status = "okay"; + + panel@0 { + compatible = "dlc,dlc0697", "ilitek,ili7807s"; + reg = <0>; + + reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + + vddi-supply = <&pm4125_l15>; + avdd-supply = <&vreg_disp_p>; + avee-supply = <&vreg_disp_n>; + wled-supply = <&vreg_wled>; + + pinctrl-0 = <&panel_rst_n &panel_te_pin>; + pinctrl-1 = <&panel_rst_n_suspend>; + pinctrl-names = "default", "sleep"; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; +}; + +&pm4125_l5 { + /* DSI VDDA - must be at NOM voltage for PHY PLL lock */ + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1232000>; + regulator-allow-set-load; +}; + &pm4125_hs_in { remote-endpoint = <&usb_1_dwc3_hs>; }; @@ -79,6 +159,36 @@ status = "okay"; }; +&tlmm { + panel_rst_n: panel-rst-n-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + panel_rst_n_suspend: panel-rst-n-suspend-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + panel_te_pin: panel-te-pin-state { + pins = "gpio86"; + function = "mdp_vsync_p"; + drive-strength = <2>; + bias-pull-down; + }; + + lcd_bias_en: lcd-bias-en-state { + pins = "gpio151"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; + &usb_1 { dr_mode = "otg"; }; From 627c5a4c251ed3a0bbaf3703bfc537b1f8abb0e5 Mon Sep 17 00:00:00 2001 From: Arpit Saini Date: Wed, 30 Sep 2026 16:45:14 +0530 Subject: [PATCH 0925/1133] FROMLIST: arm64: defconfig: Enable ILI7807S DSI panel driver Enable the ILI7807S 1080x1920 video-mode DSI panel driver as a module, used on the Shikra CQM EVK board and CQS EVK board. Reviewed-by: Dmitry Baryshkov Signed-off-by: Arpit Saini Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20260930-shikra-dt-changes-v5-4-8eaf658a0e38@oss.qualcomm.com --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7b4985b29b21c..0ba04a6b7381f 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1029,6 +1029,7 @@ CONFIG_DRM_PANEL_LVDS=m CONFIG_DRM_PANEL_HIMAX_HX8279=m CONFIG_DRM_PANEL_HIMAX_HX83112A=m CONFIG_DRM_PANEL_HIMAX_HX83112B=m +CONFIG_DRM_PANEL_ILITEK_ILI7807S=m CONFIG_DRM_PANEL_ILITEK_ILI9806E_SPI=m CONFIG_DRM_PANEL_ILITEK_ILI9882T=m CONFIG_DRM_PANEL_KHADAS_TS050=m From c05d3ea98c7c55659e22193bd52ac4499cb88288 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 1 Oct 2026 19:11:56 +0530 Subject: [PATCH 0926/1133] FROMLIST: arm64: dts: qcom: shikra: Add Iris video codec node Add the Iris video codec device tree node for the Shikra platform. Shikra reuses the QCM2290-class video hardware and programming model. The video node is added to describe the Iris based video decoder encoder block, allowing the media driver to probe and initialize the hardware. Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Reviewed-by: Vishnu Reddy Signed-off-by: Vikash Garodia Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20261001-shikra_vpu-v6-1-37143dc1bb9d@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra.dtsi | 61 ++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 72d7236546b07..7ae0f9fb38363 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -2804,6 +2804,67 @@ power-domains = <&gpucc GPU_CX_GDSC>; }; + iris: video-codec@5a00000 { + compatible = "qcom,shikra-venus", "qcom,qcm2290-venus"; + reg = <0x0 0x05a00000 0x0 0x200000>; + interrupts = ; + + power-domains = <&gcc GCC_VENUS_GDSC>, + <&gcc GCC_VCODEC0_GDSC>, + <&rpmpd QCM2290_VDDCX>; + power-domain-names = "venus", + "vcodec0", + "cx"; + operating-points-v2 = <&venus_opp_table>; + + clocks = <&gcc GCC_VIDEO_VENUS_CTL_CLK>, + <&gcc GCC_VIDEO_AHB_CLK>, + <&gcc GCC_VENUS_CTL_AXI_CLK>, + <&gcc GCC_VIDEO_THROTTLE_CORE_CLK>, + <&gcc GCC_VIDEO_VCODEC0_SYS_CLK>, + <&gcc GCC_VCODEC0_AXI_CLK>; + clock-names = "core", + "iface", + "bus", + "throttle", + "vcodec0_core", + "vcodec0_bus"; + + memory-region = <&video_mem>; + interconnects = <&mmnrt_virt MASTER_VIDEO_P0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_VENUS_CFG RPM_ACTIVE_TAG>; + interconnect-names = "video-mem", + "cpu-cfg"; + + iommus = <&apps_smmu 0x780 0x20>; + + venus_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-133333333 { + opp-hz = /bits/ 64 <133333333>; + required-opps = <&rpmpd_opp_low_svs>; + }; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_nom>; + }; + }; + }; + mdss: display-subsystem@5e00000 { compatible = "qcom,shikra-mdss", "qcom,qcm2290-mdss"; reg = <0x0 0x05e00000 0x0 0x1000>; From eaefe7955c87a9fe8b7a7e8f4c10c577085f33f4 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 1 Oct 2026 19:11:57 +0530 Subject: [PATCH 0927/1133] FROMLIST: arm64: dts: qcom: shikra-evk: Enable Iris core Enable video en/decoder on the Shikra EVK board. Reviewed-by: Dmitry Baryshkov Reviewed-by: Vishnu Reddy Signed-off-by: Vikash Garodia Link: https://lore.kernel.org/r/20261001-shikra_vpu-v6-2-37143dc1bb9d@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi index 7fbd6d1de19ad..13036d8cc8ebd 100644 --- a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi @@ -11,6 +11,12 @@ firmware-name = "qcom/shikra/a704_zap.mbn"; }; +&iris { + firmware-name = "qcom/vpu/ar50lt_p1_gen2_s6.mbn"; + + status = "okay"; +}; + &qupv3_0 { firmware-name = "qcom/shikra/qupv3fw.elf"; From d64d700914217a6460201f55477a4b7276988978 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Fri, 30 Oct 2026 18:03:56 +0530 Subject: [PATCH 0928/1133] FROMLIST: soc: qcom: pd-mapper: Add support for the Qualcomm Shikra SoC Add support for the Qualcomm Shikra SoC to the protection domain mapper. All Shikra SoC variants (CQM, CQS, IQS) share the same protection domain requirements: cdsp_root_pd, mpss_root_pd, mpss_wlan_pd. Signed-off-by: Anurag Pateriya Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20261030-shikra_pd-v2-1-09bd0394629b@oss.qualcomm.com --- drivers/soc/qcom/qcom_pd_mapper.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index 64ca99d7fad92..9e456ead9eb35 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -498,6 +498,13 @@ static const struct qcom_pdm_domain_data *sc8280xp_domains[] = { NULL, }; +static const struct qcom_pdm_domain_data *shikra_domains[] = { + &cdsp_root_pd, + &mpss_root_pd, + &mpss_wlan_pd, + NULL, +}; + /* Unlike SDM660, SDM630/636 lack CDSP */ static const struct qcom_pdm_domain_data *sdm630_domains[] = { &adsp_audio_pd, @@ -644,6 +651,7 @@ static const struct of_device_id qcom_pdm_domains[] __maybe_unused = { { .compatible = "qcom,sc7280", .data = sc7280_domains, }, { .compatible = "qcom,sc8180x", .data = sc8180x_domains, }, { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, }, + { .compatible = "qcom,shikra", .data = shikra_domains, }, { .compatible = "qcom,sdm630", .data = sdm630_domains, }, { .compatible = "qcom,sdm636", .data = sdm630_domains, }, { .compatible = "qcom,sda660", .data = sdm660_domains, }, From 7042cc7a1beef8e38e83e4720a4e6e162797f7c6 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:25 +0800 Subject: [PATCH 0929/1133] FROMLIST: drm/msm/dp: add support to send ACT packets for MST Whenever virtual channel slot allocation changes, the DP source must send the action control trigger sequence to notify the sink about the same. This would be applicable during the start and stop of the pixel stream. Add the infrastructure to be able to send ACT packets for the DP controller when operating in MST mode. Add REG_DP_MST_ACT, the ACT trigger register used by this sequence. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-8-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 44 ++++++++++++++++++++++++++++- drivers/gpu/drm/msm/dp/dp_ctrl.h | 5 +++- drivers/gpu/drm/msm/dp/dp_display.c | 3 +- drivers/gpu/drm/msm/dp/dp_display.h | 1 + drivers/gpu/drm/msm/dp/dp_reg.h | 1 + 5 files changed, 51 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index abd3dcdad03c2..8fb487fc5a108 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -142,6 +142,7 @@ struct msm_dp_ctrl_private { bool core_clks_on; bool link_clks_on; bool stream_clks_on[DP_STREAM_MAX]; + bool mst_active; }; static inline u32 msm_dp_read_ahb(const struct msm_dp_ctrl_private *ctrl, u32 offset) @@ -244,6 +245,37 @@ static int msm_dp_aux_link_configure(struct drm_dp_aux *aux, return err; } +int msm_dp_ctrl_mst_send_act(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel) +{ + struct msm_dp_ctrl_private *ctrl; + const struct drm_display_mode *mode; + u32 frame_time_ms; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + if (!ctrl->mst_active) + return 0; + + mode = &panel->msm_dp_mode.drm_mode; + frame_time_ms = DIV_ROUND_UP((u64)mode->htotal * mode->vtotal, + mode->clock) + 1; + + msm_dp_write_link(ctrl, REG_DP_MST_ACT, 0x1); + /* make sure ACT signal is performed */ + wmb(); + + msleep(frame_time_ms); + + /* Hardware clears this bit after sending 4 ACT headers */ + if (msm_dp_read_link(ctrl, REG_DP_MST_ACT)) { + drm_dbg_dp(ctrl->drm_dev, "MST ACT trigger complete failed\n"); + return -EINVAL; + } + + return 0; +} + /* * NOTE: resetting DP controller will also clear any pending HPD related interrupts */ @@ -2617,7 +2649,8 @@ int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, return ret; } -int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel) +int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel, + bool mst_active) { int ret = 0; bool mainlink_ready = false; @@ -2629,6 +2662,8 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + ctrl->mst_active = mst_active; + pixel_rate = panel->msm_dp_mode.drm_mode.clock; if (msm_dp_ctrl->wide_bus_en || panel->msm_dp_mode.out_fmt_is_yuv_420) @@ -2660,6 +2695,10 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); + ret = msm_dp_ctrl_mst_send_act(msm_dp_ctrl, panel); + if (ret) + return ret; + ret = msm_dp_ctrl_wait4video_ready(ctrl); if (ret) return ret; @@ -2697,6 +2736,8 @@ void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); + ctrl->mst_active = false; + msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl); phy_power_off(phy); @@ -2876,6 +2917,7 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link ctrl->link_base = link_base; ctrl->mst2link_base = mst2link_base; ctrl->mst3link_base = mst3link_base; + ctrl->mst_active = false; ret = msm_dp_ctrl_clk_init(&ctrl->msm_dp_ctrl); if (ret) { diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 80d9258501b49..41a69447001cd 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -18,7 +18,8 @@ struct phy; int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); -int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); +int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel, + bool mst_active); int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel, bool force_link_train); @@ -59,4 +60,6 @@ void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl); bool msm_dp_ctrl_stream_clks_on(struct msm_dp_ctrl *dp_ctrl, enum msm_dp_stream_id stream_id); +int msm_dp_ctrl_mst_send_act(struct msm_dp_ctrl *msm_dp_ctrl, + struct msm_dp_panel *panel); #endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 9299ce616fdbc..1f499f24947e9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -676,7 +676,7 @@ static int msm_dp_display_enable(struct msm_dp_display_private *dp, return 0; } - rc = msm_dp_ctrl_on_stream(dp->ctrl, msm_dp_panel); + rc = msm_dp_ctrl_on_stream(dp->ctrl, msm_dp_panel, msm_dp_display->mst_active); if (!rc) msm_dp_display->power_on = true; @@ -1522,6 +1522,7 @@ void msm_dp_display_atomic_disable(struct msm_dp *dp) return; msm_dp_ctrl_push_idle(msm_dp_display->ctrl); + msm_dp_ctrl_mst_send_act(msm_dp_display->ctrl, msm_dp_display->panel); } static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 83117e7619f31..472429d092009 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -19,6 +19,7 @@ struct msm_dp { struct drm_bridge *bridge; bool audio_enabled; bool power_on; + bool mst_active; unsigned int connector_type; bool is_edp; diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index 265da58e064cc..9263e61c794c8 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -330,6 +330,7 @@ #define MMSS_DP1_SDP_CFG3 (0x000004e8) #define REG_DP_DP0_RG (0x000004f8) #define REG_DP_DP1_RG (0x000004fc) +#define REG_DP_MST_ACT (0x00000500) #define MMSS_DP_BIST_ENABLE (0x00000000) #define DP_BIST_ENABLE_DPBIST_EN (0x00000001) From 526582d3b4d15b8659b2e92041fdbf24064c3d42 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:26 +0800 Subject: [PATCH 0930/1133] FROMLIST: drm/msm/dp: add support to enable MST in mainlink control Add support to program the MST enable bit in the mainlink control register when an MST session is active or being disabled. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-9-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 16 ++++++++++++++++ drivers/gpu/drm/msm/dp/dp_reg.h | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 8fb487fc5a108..873b416852030 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -276,6 +276,19 @@ int msm_dp_ctrl_mst_send_act(struct msm_dp_ctrl *msm_dp_ctrl, return 0; } +static void msm_dp_ctrl_mst_config(struct msm_dp_ctrl_private *ctrl, bool enable) +{ + u32 mainlink_ctrl; + + mainlink_ctrl = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL); + if (enable) + mainlink_ctrl |= DP_MAINLINK_CTRL_MST_EN; + else + mainlink_ctrl &= ~DP_MAINLINK_CTRL_MST_EN; + + msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl); +} + /* * NOTE: resetting DP controller will also clear any pending HPD related interrupts */ @@ -2683,6 +2696,8 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * msm_dp_ctrl_lane_mapping(ctrl); msm_dp_setup_peripheral_flush(ctrl); + if (ctrl->mst_active) + msm_dp_ctrl_mst_config(ctrl, true); msm_dp_ctrl_configure_source_params(ctrl, panel); @@ -2733,6 +2748,7 @@ void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, phy = ctrl->phy; msm_dp_ctrl_mainlink_disable(ctrl); + msm_dp_ctrl_mst_config(ctrl, false); msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl, panel); diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index 9263e61c794c8..cc74b1ed628ec 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -128,6 +128,10 @@ #define DP_MAINLINK_FLUSH_MODE_UPDATE_SDP FIELD_PREP(DP_MAINLINK_CTRL_FLUSH_MODE_MASK, 1) #define DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE FIELD_PREP(DP_MAINLINK_CTRL_FLUSH_MODE_MASK, 3) #define DP_MAINLINK_FB_BOUNDARY_SEL (0x02000000) +#define DP_MAINLINK_CTRL_ECF_MODE BIT(26) +#define DP_MAINLINK_CTRL_MST_ACTIVE BIT(8) +#define DP_MAINLINK_CTRL_MST_EN (DP_MAINLINK_CTRL_ECF_MODE | \ + DP_MAINLINK_CTRL_MST_ACTIVE) #define REG_DP_STATE_CTRL (0x00000004) #define DP_STATE_CTRL_LINK_TRAINING_PATTERN1 (0x00000001) From 853d5ea3c799ed30c34de5ee84e0962a4b206aaa Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:27 +0800 Subject: [PATCH 0931/1133] FROMLIST: drm/msm/dp: no need to update tu calculation for mst DP stream is transmitted in transfer units only for SST case, there is no need to calculate and program TU parameters for MST case. Skip the TU programming for MST cases. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-10-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 873b416852030..aec79398548a2 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -2706,7 +2706,8 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * msm_dp_panel_clear_dsc_dto(panel); - msm_dp_ctrl_setup_tr_unit(ctrl, panel); + if (!ctrl->mst_active) + msm_dp_ctrl_setup_tr_unit(ctrl, panel); msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); From 6e0061ede77bdad2d1b86f3e31c254b644448008 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:28 +0800 Subject: [PATCH 0932/1133] FROMLIST: drm/msm/dp: always program MST_FIFO_CONSTANT_FILL for MST use cases As per the hardware programming guide, MST_FIFO_CONSTANT_FILL must always be programmed when operating in MST mode. Ensure the register is configured accordingly. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-11-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 ++ drivers/gpu/drm/msm/dp/dp_panel.c | 12 ++++++++++++ drivers/gpu/drm/msm/dp/dp_panel.h | 2 ++ 3 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index aec79398548a2..e917a0355e231 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -584,6 +584,8 @@ static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl msm_dp_ctrl_config_misc1_misc0(ctrl, panel); msm_dp_panel_timing_cfg(panel, ctrl->msm_dp_ctrl.wide_bus_en); + + msm_dp_panel_mst_async_fifo(panel, ctrl->mst_active); } /* diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index d3468b73fdc32..bc7bad5ca3b18 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -741,6 +741,18 @@ int msm_dp_panel_timing_cfg(struct msm_dp_panel *msm_dp_panel, bool wide_bus_en) return 0; } +void msm_dp_panel_mst_async_fifo(struct msm_dp_panel *msm_dp_panel, bool mst_en) +{ + struct msm_dp_panel_private *panel; + + panel = container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); + + if (mst_en) + msm_dp_write_pn(panel, MMSS_DP_ASYNC_FIFO_CONFIG, 0x01); + else + msm_dp_write_pn(panel, MMSS_DP_ASYNC_FIFO_CONFIG, 0x00); +} + int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel, const struct drm_display_mode *adjusted_mode, u32 bpp) diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index dc046fec24fc7..04938b9d2091f 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -72,6 +72,8 @@ void msm_dp_panel_clear_dsc_dto(struct msm_dp_panel *msm_dp_panel); void msm_dp_panel_enable_vsc_sdp(struct msm_dp_panel *msm_dp_panel, struct dp_sdp *vsc_sdp); void msm_dp_panel_disable_vsc_sdp(struct msm_dp_panel *msm_dp_panel); +void msm_dp_panel_mst_async_fifo(struct msm_dp_panel *msm_dp_panel, bool mst_en); + /** * is_link_rate_valid() - validates the link rate * @bw_code: link rate requested by the sink From a0b6049d4b3d15681c0e9c7b9ae55b6cc02cb2f4 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:29 +0800 Subject: [PATCH 0933/1133] FROMLIST: drm/msm/dp: add support for sending VCPF packets in DP controller The VC Payload Fill (VCPF) sequence is inserted by the DP controller when stream symbols are absent, typically before a stream is disabled. Add support for triggering the VCPF sequence in the MSM DP controller. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-12-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 57 +++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 2 +- drivers/gpu/drm/msm/dp/dp_reg.h | 8 ++++ 4 files changed, 67 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index e917a0355e231..02a417cf260a2 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -65,6 +65,11 @@ (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \ PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK) +#define DP_INTERRUPT_STATUS5 \ + (DP_INTR_DP0_VCPF_SENT | DP_INTR_DP1_VCPF_SENT) +#define DP_INTERRUPT_STATUS5_MASK \ + (DP_INTERRUPT_STATUS5 << DP_INTERRUPT_STATUS_MASK_SHIFT) + #define DP_CTRL_INTR_READY_FOR_VIDEO BIT(0) #define DP_CTRL_INTR_IDLE_PATTERN_SENT BIT(3) @@ -351,6 +356,8 @@ void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl) DP_INTERRUPT_STATUS1_MASK); msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2, DP_INTERRUPT_STATUS2_MASK); + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS5, + DP_INTERRUPT_STATUS5_MASK); } void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl) @@ -360,6 +367,7 @@ void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl) msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS, 0x00); msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2, 0x00); + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS5, 0x00); } static u32 msm_dp_ctrl_get_psr_interrupt(struct msm_dp_ctrl_private *ctrl) @@ -379,6 +387,20 @@ static void msm_dp_ctrl_config_psr_interrupt(struct msm_dp_ctrl_private *ctrl) msm_dp_write_ahb(ctrl, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4); } +static u32 msm_dp_ctrl_get_mst_interrupt(struct msm_dp_ctrl_private *ctrl) +{ + u32 intr, intr_ack; + + intr = msm_dp_read_ahb(ctrl, REG_DP_INTR_STATUS5); + intr &= ~DP_INTERRUPT_STATUS5_MASK; + intr_ack = (intr & DP_INTERRUPT_STATUS5) + << DP_INTERRUPT_STATUS_ACK_SHIFT; + msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS5, + intr_ack | DP_INTERRUPT_STATUS5_MASK); + + return intr; +} + static void msm_dp_ctrl_psr_mainlink_enable(struct msm_dp_ctrl_private *ctrl) { u32 val; @@ -478,6 +500,34 @@ void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl) drm_dbg_dp(ctrl->drm_dev, "mainlink off\n"); } +/* Must be called with msm_dp_mst::mst_lock held */ +void msm_dp_ctrl_push_vcpf(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *msm_dp_panel) +{ + struct msm_dp_ctrl_private *ctrl; + u32 state = 0x0; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + if (!ctrl->mst_active) + state |= DP_STATE_CTRL_PUSH_IDLE; + else if (msm_dp_panel->stream_id == DP_STREAM_0) + state |= DP_STATE_CTRL_DP0_PUSH_VCPF; + else if (msm_dp_panel->stream_id == DP_STREAM_1) + state |= DP_STATE_CTRL_DP1_PUSH_VCPF; + else + state |= DP_MSTLINK_PUSH_VCPF; + + reinit_completion(&ctrl->idle_comp); + + msm_dp_write_stream_link(ctrl, msm_dp_panel->stream_id, REG_DP_STATE_CTRL, state); + + if (!wait_for_completion_timeout(&ctrl->idle_comp, + IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES)) + pr_warn("PUSH_VCPF pattern timedout\n"); + + drm_dbg_dp(ctrl->drm_dev, "vcpf sent\n"); +} + static void msm_dp_ctrl_config_ctrl_streams(struct msm_dp_ctrl_private *ctrl, struct msm_dp_panel *msm_dp_panel) { @@ -2804,6 +2854,13 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, ret = IRQ_HANDLED; } + isr = msm_dp_ctrl_get_mst_interrupt(ctrl); + if (isr & (DP_INTR_DP0_VCPF_SENT | DP_INTR_DP1_VCPF_SENT)) { + drm_dbg_dp(ctrl->drm_dev, "vcpf sent\n"); + complete(&ctrl->idle_comp); + ret = IRQ_HANDLED; + } + /* DP aux isr */ isr = msm_dp_ctrl_get_aux_interrupt(ctrl); if (isr) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 41a69447001cd..84ea37d8db2e3 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -27,6 +27,7 @@ void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl, enum msm_dp_stream_id stream_id); void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_push_vcpf(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl, diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 1f499f24947e9..956841af63523 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1521,7 +1521,7 @@ void msm_dp_display_atomic_disable(struct msm_dp *dp) if (!dp->power_on) return; - msm_dp_ctrl_push_idle(msm_dp_display->ctrl); + msm_dp_ctrl_push_vcpf(msm_dp_display->ctrl, msm_dp_display->panel); msm_dp_ctrl_mst_send_act(msm_dp_display->ctrl, msm_dp_display->panel); } diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index cc74b1ed628ec..e37a05c2963ab 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -42,6 +42,9 @@ #define DP_INTR_FRAME_END BIT(6) #define DP_INTR_CRC_UPDATED BIT(9) +#define DP_INTR_DP0_VCPF_SENT BIT(0) +#define DP_INTR_DP1_VCPF_SENT BIT(3) + #define REG_DP_INTR_STATUS3 (0x00000028) #define REG_DP_INTR_STATUS4 (0x0000002C) @@ -58,6 +61,8 @@ #define PSR_UPDATE_ERROR_MASK (0x00000008) #define PSR_WAKE_ERROR_MASK (0x00000010) +#define REG_DP_INTR_STATUS5 (0x00000034) + #define REG_DP_DP_HPD_CTRL (0x00000000) #define DP_DP_HPD_CTRL_HPD_EN (0x00000001) @@ -143,6 +148,8 @@ #define DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN (0x00000040) #define DP_STATE_CTRL_SEND_VIDEO (0x00000080) #define DP_STATE_CTRL_PUSH_IDLE (0x00000100) +#define DP_STATE_CTRL_DP0_PUSH_VCPF BIT(12) +#define DP_STATE_CTRL_DP1_PUSH_VCPF BIT(14) #define REG_DP_CONFIGURATION_CTRL (0x00000008) #define DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK (0x00000001) @@ -370,6 +377,7 @@ /* Streams 2/3 registers, relative to mst2link_base / mst3link_base. */ #define REG_DP_MSTLINK_STATE_CTRL (0x00000000) +#define DP_MSTLINK_PUSH_VCPF BIT(12) #define REG_DP_MSTLINK_CONFIGURATION_CTRL (0x00000034) #define REG_DP_MSTLINK_TIMESLOT_1_32 (0x00000038) #define REG_DP_MSTLINK_TIMESLOT_33_63 (0x0000003c) From 0b20f19595ed0dca05b6f892da00dddb64f3d8ad Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:30 +0800 Subject: [PATCH 0934/1133] FROMLIST: drm/msm/dp: add support for MST channel slot allocation DP MST streams share 64 MTP slots in a time-multiplexed manner. Add support for calculating the rate governor, slot allocation, and slot reservation in the DP controller. Each MST stream can reserve its slots by calling msm_dp_display_set_stream_info() from its bridge callbacks. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-13-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 187 ++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 4 + drivers/gpu/drm/msm/dp/dp_display.c | 13 ++ drivers/gpu/drm/msm/dp/dp_display.h | 2 + 4 files changed, 206 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 02a417cf260a2..a771104738cdd 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -78,6 +78,7 @@ #define MR_LINK_PRBS7 0x100 #define MR_LINK_CUSTOM80 0x200 #define MR_LINK_TRAINING4 0x40 +#define DP_MAX_TIME_SLOTS 64 enum { DP_TRAINING_NONE, @@ -114,6 +115,12 @@ struct msm_dp_vc_tu_mapping_table { u8 tu_size_minus1; }; +struct msm_dp_mst_ch_slot_info { + u32 start_slot; + u32 tot_slots; + u32 pbn; +}; + struct msm_dp_ctrl_private { struct msm_dp_ctrl msm_dp_ctrl; struct drm_device *drm_dev; @@ -148,6 +155,8 @@ struct msm_dp_ctrl_private { bool link_clks_on; bool stream_clks_on[DP_STREAM_MAX]; bool mst_active; + + struct msm_dp_mst_ch_slot_info mst_ch_info[DP_STREAM_MAX]; }; static inline u32 msm_dp_read_ahb(const struct msm_dp_ctrl_private *ctrl, u32 offset) @@ -294,6 +303,37 @@ static void msm_dp_ctrl_mst_config(struct msm_dp_ctrl_private *ctrl, bool enable msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl); } +static void msm_dp_ctrl_mst_update_timeslot(struct msm_dp_ctrl_private *ctrl, + enum msm_dp_stream_id stream_id, u32 ch_start_slot, + u32 tot_slot_cnt) +{ + u32 slot_reg_1 = 0, slot_reg_2 = 0; + + drm_dbg_dp(ctrl->drm_dev, "stream_id %d, start_slot %d, tot_slot %d\n", + stream_id, ch_start_slot, tot_slot_cnt); + + if (ch_start_slot && tot_slot_cnt) { + u64 mask = GENMASK_ULL(ch_start_slot + tot_slot_cnt - 2, ch_start_slot - 1); + + slot_reg_1 = mask & 0xFFFFFFFF; + slot_reg_2 = (mask >> 32) & 0xFFFFFFFF; + } + + msm_dp_write_stream_link(ctrl, stream_id, REG_DP_DP0_TIMESLOT_1_32, slot_reg_1); + msm_dp_write_stream_link(ctrl, stream_id, REG_DP_DP0_TIMESLOT_33_63, slot_reg_2); +} + +static void msm_dp_ctrl_update_rg(struct msm_dp_ctrl_private *ctrl, + enum msm_dp_stream_id stream_id, u32 x_int, u32 y_frac_enum) +{ + u32 rg = y_frac_enum | (x_int << 16); + + drm_dbg_dp(ctrl->drm_dev, "stream_id: %d x_int:%d y_frac_enum:%d rg:%d\n", + stream_id, x_int, y_frac_enum, rg); + + msm_dp_write_stream_link(ctrl, stream_id, REG_DP_DP0_RG, rg); +} + /* * NOTE: resetting DP controller will also clear any pending HPD related interrupts */ @@ -2678,6 +2718,117 @@ static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl, msm_dp_write_stream_link(ctrl, panel->stream_id, REG_DP_SOFTWARE_NVID, nvid); } +/* + * Calculate MST Rate Governor parameters x_int and y_frac_enum. + * + * The RG paces symbol delivery per MTP via: M = x_int + y_frac_enum/256 + * where M is the target symbol count per MTP across all lanes. + * + * min_slot_cnt = (pclk * bpp/8) / (lclk * lanes) * 64 -- slots at 1.0x BW + * max_slot_cnt = pbn * 54 / (lclk * lanes) -- slots at PBN limit + * raw_target_sc = (min + max) / 2 -- midpoint (~1.003x) + * + * Quantize raw_target_sc to 1/(256*lanes) steps, then: + * M = Chosen_TARGET_Slot_Count * lanes + * x_int = INT(M) + * y_frac_enum = CEIL(256 * MOD(M, 1)) + */ +static void msm_dp_ctrl_mst_calculate_rg(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel, + u32 *p_x_int, u32 *p_y_frac_enum) +{ + u64 min_slot_cnt, max_slot_cnt; + u64 raw_target_sc, target_sc_fixp; + u64 ts_denom, ts_enum, ts_int; + u64 pclk = panel->msm_dp_mode.drm_mode.clock; + u64 lclk = 0; + u64 lanes = ctrl->link->link_params.num_lanes; + u64 bpp = panel->msm_dp_mode.bpp; + u64 pbn = ctrl->mst_ch_info[panel->stream_id].pbn; + u64 numerator, denominator, temp, temp1, temp2; + u32 x_int = 0, y_frac_enum = 0; + u64 target_strm_sym, ts_int_fixp, ts_frac_fixp, y_frac_enum_fixp; + + lclk = ctrl->link->link_params.rate; + + /* min_slot_cnt */ + numerator = pclk * bpp * 64 * 1000; + denominator = lclk * lanes * 8 * 1000; + min_slot_cnt = drm_fixp_from_fraction(numerator, denominator); + + /* max_slot_cnt */ + numerator = pbn * 54 * 1000; + denominator = lclk * lanes; + max_slot_cnt = drm_fixp_from_fraction(numerator, denominator); + + /* raw_target_sc */ + numerator = max_slot_cnt + min_slot_cnt; + denominator = drm_fixp_from_fraction(2, 1); + raw_target_sc = drm_fixp_div(numerator, denominator); + + /* target_sc */ + temp = drm_fixp_from_fraction(256 * lanes, 1); + numerator = drm_fixp_mul(raw_target_sc, temp); + denominator = drm_fixp_from_fraction(256 * lanes, 1); + target_sc_fixp = drm_fixp_div(numerator, denominator); + + ts_enum = 256 * lanes; + ts_denom = drm_fixp_from_fraction(256 * lanes, 1); + ts_int = drm_fixp2int(target_sc_fixp); + + temp = drm_fixp2int_ceil(raw_target_sc); + if (temp != ts_int) { + temp = drm_fixp_from_fraction(ts_int, 1); + temp1 = raw_target_sc - temp; + temp2 = drm_fixp_mul(temp1, ts_denom); + ts_enum = drm_fixp2int(temp2); + } + + /* target_strm_sym */ + ts_int_fixp = drm_fixp_from_fraction(ts_int, 1); + ts_frac_fixp = drm_fixp_from_fraction(ts_enum, drm_fixp2int(ts_denom)); + temp = ts_int_fixp + ts_frac_fixp; + temp1 = drm_fixp_from_fraction(lanes, 1); + target_strm_sym = drm_fixp_mul(temp, temp1); + + /* x_int */ + x_int = drm_fixp2int(target_strm_sym); + + /* y_enum_frac */ + temp = drm_fixp_from_fraction(x_int, 1); + temp1 = target_strm_sym - temp; + temp2 = drm_fixp_from_fraction(256, 1); + y_frac_enum_fixp = drm_fixp_mul(temp1, temp2); + + temp1 = drm_fixp2int(y_frac_enum_fixp); + temp2 = drm_fixp2int_ceil(y_frac_enum_fixp); + + y_frac_enum = (u32)((temp1 == temp2) ? temp1 : temp1 + 1); + + *p_x_int = x_int; + *p_y_frac_enum = y_frac_enum; + + drm_dbg_dp(ctrl->drm_dev, "MST lane_cnt:%llu, rate:%llu x_int:%d, y_frac:%d\n", + lanes, lclk, x_int, y_frac_enum); +} + +static void msm_dp_ctrl_mst_stream_setup(struct msm_dp_ctrl_private *ctrl, + struct msm_dp_panel *panel) +{ + u32 x_int, y_frac_enum; + + if (!ctrl->mst_active) + return; + + drm_dbg_dp(ctrl->drm_dev, "MST stream channel allocation\n"); + + msm_dp_ctrl_mst_timeslot_setup(&ctrl->msm_dp_ctrl); + + msm_dp_ctrl_mst_calculate_rg(ctrl, panel, &x_int, &y_frac_enum); + + msm_dp_ctrl_update_rg(ctrl, panel->stream_id, x_int, y_frac_enum); +} + int msm_dp_ctrl_prepare_stream_on(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel, bool force_link_train) @@ -2761,6 +2912,8 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel * if (!ctrl->mst_active) msm_dp_ctrl_setup_tr_unit(ctrl, panel); + msm_dp_ctrl_mst_stream_setup(ctrl, panel); + msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO); ret = msm_dp_ctrl_mst_send_act(msm_dp_ctrl, panel); @@ -2812,6 +2965,40 @@ void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl, phy_power_off(phy); } +void msm_dp_ctrl_set_mst_channel_info(struct msm_dp_ctrl *msm_dp_ctrl, + enum msm_dp_stream_id stream_id, + u32 start_slot, u32 tot_slots, u32 pbn) +{ + struct msm_dp_ctrl_private *ctrl; + + if (!msm_dp_ctrl || stream_id >= DP_STREAM_MAX) { + DRM_ERROR("invalid input\n"); + return; + } + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + ctrl->mst_ch_info[stream_id].start_slot = start_slot; + ctrl->mst_ch_info[stream_id].tot_slots = tot_slots; + ctrl->mst_ch_info[stream_id].pbn = pbn; +} + +void msm_dp_ctrl_mst_timeslot_setup(struct msm_dp_ctrl *msm_dp_ctrl) +{ + struct msm_dp_ctrl_private *ctrl; + int i; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + if (!ctrl->mst_active) + return; + + for (i = DP_STREAM_0; i < ctrl->num_pixel_clks; i++) { + msm_dp_ctrl_mst_update_timeslot(ctrl, i, ctrl->mst_ch_info[i].start_slot, + ctrl->mst_ch_info[i].tot_slots); + } +} + irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel) { diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 84ea37d8db2e3..e8b445c552f7a 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -63,4 +63,8 @@ bool msm_dp_ctrl_stream_clks_on(struct msm_dp_ctrl *dp_ctrl, enum msm_dp_stream_id stream_id); int msm_dp_ctrl_mst_send_act(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); +void msm_dp_ctrl_mst_timeslot_setup(struct msm_dp_ctrl *msm_dp_ctrl); +void msm_dp_ctrl_set_mst_channel_info(struct msm_dp_ctrl *msm_dp_ctrl, + enum msm_dp_stream_id stream_id, + u32 start_slot, u32 tot_slots, u32 pbn); #endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 956841af63523..6663fdfad7f3b 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -738,6 +738,18 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp, return 0; } +int msm_dp_display_set_stream_info(struct msm_dp *msm_dp_display, struct msm_dp_panel *panel, + u32 start_slot, u32 num_slots, u32 pbn) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + msm_dp_ctrl_set_mst_channel_info(dp->ctrl, panel->stream_id, start_slot, num_slots, pbn); + + return 0; +} + /** * msm_dp_display_mode_valid - callback to determine if specified mode is valid * @dp: Pointer to dp display structure @@ -1522,6 +1534,7 @@ void msm_dp_display_atomic_disable(struct msm_dp *dp) return; msm_dp_ctrl_push_vcpf(msm_dp_display->ctrl, msm_dp_display->panel); + msm_dp_ctrl_mst_timeslot_setup(msm_dp_display->ctrl); msm_dp_ctrl_mst_send_act(msm_dp_display->ctrl, msm_dp_display->panel); } diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 472429d092009..317c19b809ec6 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -43,5 +43,7 @@ void msm_dp_display_atomic_enable(struct msm_dp *dp_display, enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, const struct drm_display_info *info, const struct drm_display_mode *mode); +int msm_dp_display_set_stream_info(struct msm_dp *msm_dp_display, struct msm_dp_panel *panel, + u32 start_slot, u32 num_slots, u32 pbn); #endif /* _DP_DISPLAY_H_ */ From 7a9fd2966c504715b66c038df89f396cfebeaa5f Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:31 +0800 Subject: [PATCH 0935/1133] FROMLIST: drm/msm/dp: replace power_on with active_stream_cnt The power_on boolean cannot represent DP MST, where multiple streams share a single link and its associated resources. Replace power_on with active_stream_cnt and use it to track the lifetime of the shared link. Link initialization is performed when enabling the first stream, while link teardown is deferred until the last stream is disabled. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-14-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_audio.c | 2 +- drivers/gpu/drm/msm/dp/dp_display.c | 38 ++++++++++++++--------------- drivers/gpu/drm/msm/dp/dp_display.h | 2 +- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index df222943ae57f..8118130a3220f 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -284,7 +284,7 @@ int msm_dp_audio_prepare(struct drm_bridge *bridge, * such cases check for connection status and bail out if not * connected. */ - if (!msm_dp_display->power_on) + if (!msm_dp_display->active_stream_cnt) goto end; audio = msm_dp_audio_get_data(msm_dp_display); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 6663fdfad7f3b..21b126ed4308b 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -649,16 +649,16 @@ static int msm_dp_display_prepare_link(struct msm_dp_display_private *dp) if (dp->link->sink_count == 0) return -ENOTCONN; - if (!msm_dp_display->power_on) { + if (!msm_dp_display->active_stream_cnt) { msm_dp_display_host_phy_init(dp); force_link_train = true; - } - rc = msm_dp_ctrl_on_link(dp->ctrl, dp->panel); - if (rc) { - DRM_ERROR("Failed link training (rc=%d)\n", rc); - // TODO: schedule drm_connector_set_link_status_property() - return rc; + rc = msm_dp_ctrl_on_link(dp->ctrl, dp->panel); + if (rc) { + DRM_ERROR("Failed link training (rc=%d)\n", rc); + // TODO: schedule drm_connector_set_link_status_property() + return rc; + } } return msm_dp_ctrl_prepare_stream_on(dp->ctrl, dp->panel, force_link_train); @@ -671,14 +671,10 @@ static int msm_dp_display_enable(struct msm_dp_display_private *dp, struct msm_dp *msm_dp_display = &dp->msm_dp_display; drm_dbg_dp(dp->drm_dev, "sink_count=%d\n", dp->link->sink_count); - if (msm_dp_display->power_on) { - drm_dbg_dp(dp->drm_dev, "Link already setup, return\n"); - return 0; - } rc = msm_dp_ctrl_on_stream(dp->ctrl, msm_dp_panel, msm_dp_display->mst_active); - if (!rc) - msm_dp_display->power_on = true; + + msm_dp_display->active_stream_cnt++; return rc; } @@ -727,13 +723,12 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp, { struct msm_dp *msm_dp_display = &dp->msm_dp_display; - if (!msm_dp_display->power_on) - return 0; - msm_dp_panel_disable_vsc_sdp(msm_dp_panel); msm_dp_ctrl_off_pixel_clk(dp->ctrl, msm_dp_panel->stream_id); + msm_dp_display->active_stream_cnt--; + drm_dbg_dp(dp->drm_dev, "sink count: %d\n", dp->link->sink_count); return 0; } @@ -858,10 +853,10 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp) * if we are reading registers we need the link clocks to be on * however till DP cable is connected this will not happen as we * do not know the resolution to power up with. Hence check the - * power_on status before dumping DP registers to avoid crash due + * active_stream_cnt status before dumping DP registers to avoid crash due * to unclocked access */ - if (!dp->power_on) + if (!dp->active_stream_cnt) return; msm_disp_snapshot_add_block(disp_state, msm_dp_display->ahb_len, @@ -1542,6 +1537,11 @@ static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) { struct msm_dp *msm_dp_display = &dp->msm_dp_display; + if (msm_dp_display->active_stream_cnt) { + drm_dbg_dp(dp->drm_dev, "stream still active, return\n"); + return; + } + /* dongle is still connected but sinks are disconnected */ if (dp->link->sink_count == 0) msm_dp_link_psm_config(dp->link, &dp->panel->link_info, true); @@ -1554,8 +1554,6 @@ static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) else msm_dp_display_host_phy_exit(dp); - msm_dp_display->power_on = false; - pm_runtime_put_sync(&msm_dp_display->pdev->dev); drm_dbg_dp(dp->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 317c19b809ec6..7bd510cecb44c 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -18,7 +18,7 @@ struct msm_dp { struct drm_bridge *next_bridge; struct drm_bridge *bridge; bool audio_enabled; - bool power_on; + u32 active_stream_cnt; bool mst_active; unsigned int connector_type; bool is_edp; From 833ad832b2d7b620b92e0145352efe6a9185041d Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:32 +0800 Subject: [PATCH 0936/1133] FROMLIST: drm/msm/dp: factor out _helper variants of bridge ops accepting a panel The atomic bridge callbacks (set_mode / enable / disable / post_disable) on dp_display currently hard-code dp->panel. For DP MST every stream has its own msm_dp_panel that the MST encoder owns, so the same enable/disable sequence needs to be invokable against an arbitrary panel. Introduce *_helper variants that take struct msm_dp_panel * and reduce the existing atomic_* callbacks to thin wrappers that pass dp->panel. No SST-path behaviour change. Also drop the static qualifier from msm_dp_display_prepare_link() and msm_dp_display_unprepare() and change them to take struct msm_dp * so the upcoming MST encoder code can drive link-level prepare/unprepare uniformly through the public API. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-15-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 126 ++++++++++++++++++---------- drivers/gpu/drm/msm/dp/dp_display.h | 12 +++ 2 files changed, 95 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 21b126ed4308b..9f7688653cb64 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -629,12 +629,14 @@ static int msm_dp_display_set_mode(struct msm_dp *msm_dp_display, return 0; } -static int msm_dp_display_prepare_link(struct msm_dp_display_private *dp) +int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display) { - struct msm_dp *msm_dp_display = &dp->msm_dp_display; + struct msm_dp_display_private *dp; int rc = 0; bool force_link_train = false; + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + drm_dbg_dp(dp->drm_dev, "sink_count=%d\n", dp->link->sink_count); if (msm_dp_display->is_edp) @@ -1459,83 +1461,112 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev, return 0; } -void msm_dp_display_atomic_pre_enable(struct msm_dp *msm_dp_display, - struct drm_atomic_commit *state) +int msm_dp_display_set_mode_helper(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state, + struct drm_encoder *drm_encoder, + struct msm_dp_panel *msm_dp_panel) { - struct msm_dp_display_private *dp; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; - dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - - crtc = drm_atomic_get_new_crtc_for_encoder(state, msm_dp_display->bridge->encoder); + crtc = drm_atomic_get_new_crtc_for_encoder(state, drm_encoder); if (!crtc) - return; + return 0; crtc_state = drm_atomic_get_new_crtc_state(state, crtc); - /* - * The DPU encoder's .atomic_enable() reads the mode's YUV420 / wide bus - * state and runs before the bridge's .atomic_enable(), so the mode must - * be programmed here, in .atomic_pre_enable(). - */ - msm_dp_display_set_mode(msm_dp_display, &crtc_state->adjusted_mode, dp->panel); + return msm_dp_display_set_mode(msm_dp_display, &crtc_state->adjusted_mode, msm_dp_panel); } -void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display, - struct drm_atomic_commit *state) +void msm_dp_display_atomic_pre_enable(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state) { int rc = 0; struct msm_dp_display_private *dp; dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - rc = msm_dp_display_prepare_link(dp); + rc = msm_dp_display_set_mode_helper(msm_dp_display, state, + msm_dp_display->bridge->encoder, dp->panel); if (rc) { - DRM_ERROR("DP display prepare failed, rc=%d\n", rc); + DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc); return; } - rc = msm_dp_display_enable(dp, dp->panel); + rc = msm_dp_display_prepare_link(msm_dp_display); + if (rc) + DRM_ERROR("DP display prepare failed, rc=%d\n", rc); +} + +void msm_dp_display_enable_helper(struct msm_dp *msm_dp_display, struct msm_dp_panel *msm_dp_panel) +{ + int rc = 0; + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + rc = msm_dp_display_enable(dp, msm_dp_panel); if (rc) DRM_ERROR("DP display enable failed, rc=%d\n", rc); rc = msm_dp_display_post_enable(msm_dp_display); if (rc) { DRM_ERROR("DP display post enable failed, rc=%d\n", rc); - msm_dp_display_disable(dp, dp->panel); + msm_dp_display_disable(dp, msm_dp_panel); } drm_dbg_dp(msm_dp_display->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); } -void msm_dp_display_atomic_disable(struct msm_dp *dp) +void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state) { - struct msm_dp_display_private *msm_dp_display; + struct msm_dp_display_private *dp; - msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + msm_dp_display_enable_helper(msm_dp_display, dp->panel); +} + +void msm_dp_display_disable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); /* - * If .atomic_enable() bailed out - link training failure is the common - * case - the mainlink was never brought up and ->power_on stayed false. - * Driving the PUSH_IDLE pattern into a controller that was never - * enabled times out, and .atomic_post_disable() then drops the - * controller's runtime-PM reference without tearing the PHY back down, - * because msm_dp_display_disable() returns early on !power_on. On - * glymur (Snapdragon X2 Elite) that combination is answered by a - * TrustZone-level SOCCP/ADSP force-stop and a silent SoC reset. - * There is nothing to push idle, so leave it alone. + * If .atomic_pre_enable() bailed out - link training failure is the common + * case - the mainlink was never brought up and ->active_stream_cnt stayed + * zero. Driving the VCPF / idle pattern into a controller that was never + * enabled times out, and .atomic_post_disable() then drops the controller's + * runtime-PM reference without tearing the PHY back down, because + * msm_dp_display_disable() returns early when no stream is active. On glymur + * (Snapdragon X2 Elite) that combination is answered by a TrustZone-level + * SOCCP/ADSP force-stop and a silent SoC reset. There is nothing to push, so + * leave it alone. */ - if (!dp->power_on) + if (!msm_dp_display->active_stream_cnt) return; - msm_dp_ctrl_push_vcpf(msm_dp_display->ctrl, msm_dp_display->panel); - msm_dp_ctrl_mst_timeslot_setup(msm_dp_display->ctrl); - msm_dp_ctrl_mst_send_act(msm_dp_display->ctrl, msm_dp_display->panel); + msm_dp_ctrl_push_vcpf(dp->ctrl, msm_dp_panel); + msm_dp_ctrl_mst_timeslot_setup(dp->ctrl); + msm_dp_ctrl_mst_send_act(dp->ctrl, msm_dp_panel); } -static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) +void msm_dp_display_atomic_disable(struct msm_dp *dp) { - struct msm_dp *msm_dp_display = &dp->msm_dp_display; + struct msm_dp_display_private *msm_dp_display; + + msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); + + msm_dp_display_disable_helper(dp, msm_dp_display->panel); +} + +void msm_dp_display_unprepare(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); if (msm_dp_display->active_stream_cnt) { drm_dbg_dp(dp->drm_dev, "stream still active, return\n"); @@ -1555,11 +1586,9 @@ static void msm_dp_display_unprepare(struct msm_dp_display_private *dp) msm_dp_display_host_phy_exit(dp); pm_runtime_put_sync(&msm_dp_display->pdev->dev); - - drm_dbg_dp(dp->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); } -void msm_dp_display_atomic_post_disable(struct msm_dp *dp) +void msm_dp_display_atomic_post_disable_helper(struct msm_dp *dp, struct msm_dp_panel *msm_dp_panel) { struct msm_dp_display_private *msm_dp_display; @@ -1570,7 +1599,18 @@ void msm_dp_display_atomic_post_disable(struct msm_dp *dp) msm_dp_display_audio_notify_disable(msm_dp_display); - msm_dp_display_disable(msm_dp_display, msm_dp_display->panel); + msm_dp_display_disable(msm_dp_display, msm_dp_panel); + + drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type); +} + +void msm_dp_display_atomic_post_disable(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + msm_dp_display_atomic_post_disable_helper(msm_dp_display, dp->panel); msm_dp_display_unprepare(msm_dp_display); } diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 7bd510cecb44c..9ecd5025fe4a4 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -45,5 +45,17 @@ enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, const struct drm_display_mode *mode); int msm_dp_display_set_stream_info(struct msm_dp *msm_dp_display, struct msm_dp_panel *panel, u32 start_slot, u32 num_slots, u32 pbn); +void msm_dp_display_enable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel); +void msm_dp_display_disable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel); +void msm_dp_display_atomic_post_disable_helper(struct msm_dp *msm_dp_display, + struct msm_dp_panel *msm_dp_panel); +int msm_dp_display_set_mode_helper(struct msm_dp *msm_dp_display, + struct drm_atomic_commit *state, + struct drm_encoder *drm_encoder, + struct msm_dp_panel *msm_dp_panel); +int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display); +void msm_dp_display_unprepare(struct msm_dp *dp); #endif /* _DP_DISPLAY_H_ */ From 317564ff502db484c16cf26a0dbb4347fdaa2eb8 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 31 Aug 2026 16:17:33 +0800 Subject: [PATCH 0937/1133] FROMLIST: drm/msm/dp: add link_ready to manage link-level operations In MST mode, multiple streams share the same DP link. Track a link_ready state so msm_dp_display_prepare_link() runs only once per link and repeated calls are skipped. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-16-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 33 ++++++++++++++++++++++------- drivers/gpu/drm/msm/dp/dp_display.h | 1 + 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 9f7688653cb64..0b69d8df823e9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -642,6 +642,10 @@ int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display) if (msm_dp_display->is_edp) msm_dp_hpd_plug_handle(dp); + /* Serialized by modeset lock or mst_lock. */ + if (msm_dp_display->link_ready) + return 0; + rc = pm_runtime_resume_and_get(&msm_dp_display->pdev->dev); if (rc) { DRM_ERROR("failed to pm_runtime_resume\n"); @@ -663,7 +667,11 @@ int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display) } } - return msm_dp_ctrl_prepare_stream_on(dp->ctrl, dp->panel, force_link_train); + rc = msm_dp_ctrl_prepare_stream_on(dp->ctrl, dp->panel, force_link_train); + if (!rc) + msm_dp_display->link_ready = true; + + return rc; } static int msm_dp_display_enable(struct msm_dp_display_private *dp, @@ -1504,14 +1512,16 @@ void msm_dp_display_enable_helper(struct msm_dp *msm_dp_display, struct msm_dp_p dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); - rc = msm_dp_display_enable(dp, msm_dp_panel); - if (rc) - DRM_ERROR("DP display enable failed, rc=%d\n", rc); + if (msm_dp_display->link_ready) { + rc = msm_dp_display_enable(dp, msm_dp_panel); + if (rc) + DRM_ERROR("DP display enable failed, rc=%d\n", rc); - rc = msm_dp_display_post_enable(msm_dp_display); - if (rc) { - DRM_ERROR("DP display post enable failed, rc=%d\n", rc); - msm_dp_display_disable(dp, msm_dp_panel); + rc = msm_dp_display_post_enable(msm_dp_display); + if (rc) { + DRM_ERROR("DP display post enable failed, rc=%d\n", rc); + msm_dp_display_disable(dp, msm_dp_panel); + } } drm_dbg_dp(msm_dp_display->drm_dev, "type=%d Done\n", msm_dp_display->connector_type); @@ -1568,6 +1578,11 @@ void msm_dp_display_unprepare(struct msm_dp *msm_dp_display) dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + if (!msm_dp_display->link_ready) { + drm_dbg_dp(dp->drm_dev, "Link already setup, return\n"); + return; + } + if (msm_dp_display->active_stream_cnt) { drm_dbg_dp(dp->drm_dev, "stream still active, return\n"); return; @@ -1586,6 +1601,8 @@ void msm_dp_display_unprepare(struct msm_dp *msm_dp_display) msm_dp_display_host_phy_exit(dp); pm_runtime_put_sync(&msm_dp_display->pdev->dev); + + msm_dp_display->link_ready = false; } void msm_dp_display_atomic_post_disable_helper(struct msm_dp *dp, struct msm_dp_panel *msm_dp_panel) diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 9ecd5025fe4a4..51eace1d13460 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -20,6 +20,7 @@ struct msm_dp { bool audio_enabled; u32 active_stream_cnt; bool mst_active; + bool link_ready; unsigned int connector_type; bool is_edp; From 17b21c27f286805383f832fd854bdabfecaf1c78 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:34 +0800 Subject: [PATCH 0938/1133] FROMLIST: drm/msm/dp: add msm_dp_display_get_panel() to initialize DP panel Add an API msm_dp_display_get_panel() to initialize and return a DP panel to be used by DP MST module. Since some of the fields of DP panel are private, dp_display module needs to initialize these parts and return the panel back. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-17-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 9 +++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 27 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 2 ++ 4 files changed, 39 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index a771104738cdd..6c2248e3aa17b 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -3133,6 +3133,15 @@ bool msm_dp_ctrl_stream_clks_on(struct msm_dp_ctrl *msm_dp_ctrl, return ctrl->stream_clks_on[stream_id]; } +int msm_dp_ctrl_get_stream_cnt(struct msm_dp_ctrl *msm_dp_ctrl) +{ + struct msm_dp_ctrl_private *ctrl; + + ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); + + return ctrl->num_pixel_clks; +} + struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link, struct drm_dp_aux *aux, struct phy *phy, diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index e8b445c552f7a..111300784edda 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -61,6 +61,7 @@ void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl); void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl); bool msm_dp_ctrl_stream_clks_on(struct msm_dp_ctrl *dp_ctrl, enum msm_dp_stream_id stream_id); +int msm_dp_ctrl_get_stream_cnt(struct msm_dp_ctrl *dp_ctrl); int msm_dp_ctrl_mst_send_act(struct msm_dp_ctrl *msm_dp_ctrl, struct msm_dp_panel *panel); void msm_dp_ctrl_mst_timeslot_setup(struct msm_dp_ctrl *msm_dp_ctrl); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 0b69d8df823e9..8e32bba6ee41e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -533,6 +533,33 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp) return rc; } +struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display, + enum msm_dp_stream_id stream_id) +{ + struct msm_dp_display_private *dp; + struct msm_dp_panel *dp_panel; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + if (stream_id >= msm_dp_ctrl_get_stream_cnt(dp->ctrl)) { + DRM_ERROR("invalid stream_id %d\n", stream_id); + return NULL; + } + + dp_panel = msm_dp_panel_get(&dp->msm_dp_display.pdev->dev, dp->aux, dp->link, + dp->link_base, dp->mst2link_base, dp->mst3link_base, + dp->pixel_base[stream_id]); + + if (IS_ERR(dp_panel)) { + DRM_ERROR("failed to initialize panel\n"); + return NULL; + } + + dp_panel->stream_id = stream_id; + + return dp_panel; +} + static void msm_dp_display_deinit_sub_modules(struct msm_dp_display_private *dp) { msm_dp_audio_put(dp->audio); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 51eace1d13460..4d4349068c2fd 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -59,4 +59,6 @@ int msm_dp_display_set_mode_helper(struct msm_dp *msm_dp_display, int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display); void msm_dp_display_unprepare(struct msm_dp *dp); +struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display, + enum msm_dp_stream_id stream_id); #endif /* _DP_DISPLAY_H_ */ From 68af4126bffc23cac0e74aed423b3cc6501e9b55 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:44 +0530 Subject: [PATCH 0939/1133] FROMLIST: dt-bindings: PCI: qcom: Document the Shikra PCIe Controller Add a dedicated schema for the PCIe controller found on the Shikra platform. Signed-off-by: Sushrut Shree Trivedi Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-2-e1a721eb8943@oss.qualcomm.com --- .../bindings/pci/qcom,shikra-pcie.yaml | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/qcom,shikra-pcie.yaml diff --git a/Documentation/devicetree/bindings/pci/qcom,shikra-pcie.yaml b/Documentation/devicetree/bindings/pci/qcom,shikra-pcie.yaml new file mode 100644 index 0000000000000..f9d1dba9dd2e8 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/qcom,shikra-pcie.yaml @@ -0,0 +1,211 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/qcom,shikra-pcie.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Shikra PCI Express Root Complex + +maintainers: + - Bjorn Andersson + - Manivannan Sadhasivam + +description: + Qualcomm Shikra SoC (and compatible) PCIe root complex controller is based on + the Synopsys DesignWare PCIe IP. + +properties: + compatible: + const: qcom,shikra-pcie + + reg: + minItems: 5 + maxItems: 6 + + reg-names: + minItems: 5 + items: + - const: parf # Qualcomm specific registers + - const: dbi # DesignWare PCIe registers + - const: elbi # External local bus interface registers + - const: atu # ATU address space + - const: config # PCIe configuration space + - const: mhi # MHI registers + + clocks: + minItems: 7 + maxItems: 9 + + clock-names: + minItems: 7 + items: + - const: aux # Auxiliary clock + - const: cfg # Configuration clock + - const: bus_master # Master AXI clock + - const: bus_slave # Slave AXI clock + - const: slave_q2a # Slave Q2A clock + - const: ddrss_memnoc_pcie # PCIe SF MEMNOC clock + - const: tile # PCIe tile SYS NoC clock + - const: qmip_pcie_ahb # QMIP PCIe AHB clock + + interrupts: + minItems: 8 + maxItems: 9 + + interrupt-names: + minItems: 8 + items: + - const: msi0 + - const: msi1 + - const: msi2 + - const: msi3 + - const: msi4 + - const: msi5 + - const: msi6 + - const: msi7 + - const: global + + resets: + minItems: 1 + maxItems: 2 + + reset-names: + minItems: 1 + items: + - const: pci # PCIe core reset + - const: link_down # PCIe link down reset + +required: + - power-domains + - resets + - reset-names + +allOf: + - $ref: qcom,pcie-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + pcie@45e8000 { + device_type = "pci"; + compatible = "qcom,shikra-pcie"; + reg = <0x0 0x045e8000 0x0 0x3000>, + <0x0 0x60000000 0x0 0xf1d>, + <0x0 0x60000f20 0x0 0xa8>, + <0x0 0x60001000 0x0 0x1000>, + <0x0 0x60100000 0x0 0x100000>, + <0x0 0x045eb000 0x0 0x1000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>, + <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>, + <0x03000000 0x4 0x00000000 0x4 0x00000000 0x3 0x0000000>; + bus-range = <0x00 0xff>; + + linux,pci-domain = <0>; + num-lanes = <1>; + + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "msi0", + "msi1", + "msi2", + "msi3", + "msi4", + "msi5", + "msi6", + "msi7", + "global"; + + interrupt-map = <0 0 0 1 &intc 0 0 0 499 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 0 500 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 0 501 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 0 502 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 0x7>; + #interrupt-cells = <1>; + + clocks = <&gcc GCC_PCIE_AUX_CLK>, + <&gcc GCC_PCIE_CFG_AHB_CLK>, + <&gcc GCC_PCIE_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_SLV_AXI_CLK>, + <&gcc GCC_PCIE_SLV_Q2A_AXI_CLK>, + <&gcc GCC_DDRSS_MEMNOC_PCIE_SF_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>, + <&gcc GCC_QMIP_PCIE_CFG_AHB_CLK>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "ddrss_memnoc_pcie", + "tile", + "qmip_pcie_ahb"; + + assigned-clocks = <&gcc GCC_PCIE_AUX_CLK>; + assigned-clock-rates = <19200000>; + + interconnects = <&system_noc MASTER_PCIE2_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_PCIE2_0 RPM_ACTIVE_TAG>; + + interconnect-names = "pcie-mem", + "cpu-pcie"; + + iommu-map = <0x0 &apps_smmu 0x800 0x1>, + <0x100 &apps_smmu 0x801 0x1>; + + resets = <&gcc GCC_PCIE_BCR>; + reset-names = "pci"; + + power-domains = <&gcc GCC_PCIE_GDSC>; + + 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 = <&rpmpd_opp_nom>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* GEN 2 x1 */ + opp-5000000 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + }; + }; + }; From 18ca47a6b7821fac2db302dd4c95d5c456b56590 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 31 Aug 2026 16:17:35 +0800 Subject: [PATCH 0940/1133] FROMLIST: drm/msm/dp: introduce dp_mst_drm module Add the dp_mst_drm module and the core MST manager data structures. Introduce the MST manager object, per-stream encoder state and the initialization path for creating a DRM MST topology manager associated with a DP controller. Also add the registration hooks used to initialize the MST manager during DP device setup. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-18-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/Makefile | 3 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 12 +++++- drivers/gpu/drm/msm/dp/dp_display.c | 19 +++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 4 ++ drivers/gpu/drm/msm/dp/dp_mst_drm.c | 54 +++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_mst_drm.h | 12 ++++++ drivers/gpu/drm/msm/msm_drv.h | 12 ++++++ 7 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_mst_drm.c create mode 100644 drivers/gpu/drm/msm/dp/dp_mst_drm.h diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 1e246616f83f3..48640d9bf7cb5 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -147,7 +147,8 @@ msm-display-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_link.o \ dp/dp_panel.o \ dp/dp_audio.o \ - dp/dp_utils.o + dp/dp_utils.o \ + dp/dp_mst_drm.o msm-display-$(CONFIG_DRM_MSM_HDMI_HDCP) += hdmi/hdmi_hdcp.o diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index da3556eb6ecc2..66cabac0a7264 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -655,7 +655,7 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, struct msm_display_info info; bool yuv_supported; int rc; - int i; + int i, stream_cnt; for (i = 0; i < ARRAY_SIZE(priv->kms->dp); i++) { if (!priv->kms->dp[i]) @@ -678,6 +678,16 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); return rc; } + + stream_cnt = msm_dp_get_mst_max_stream(priv->kms->dp[i]); + + if (stream_cnt > 1) { + rc = msm_dp_mst_register(priv->kms->dp[i]); + if (rc) { + DPU_ERROR("dp_mst_init failed for DP, rc = %d\n", rc); + return rc; + } + } } return 0; diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 8e32bba6ee41e..73ec37f9510f3 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -28,6 +28,7 @@ #include "dp_drm.h" #include "dp_audio.h" #include "dp_debug.h" +#include "dp_mst_drm.h" static bool psr_enabled = false; module_param(psr_enabled, bool, 0); @@ -1281,6 +1282,24 @@ static int msm_dp_display_get_io(struct msm_dp_display_private *display) return 0; } +int msm_dp_get_mst_max_stream(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + return msm_dp_ctrl_get_stream_cnt(dp->ctrl); +} + +int msm_dp_mst_register(struct msm_dp *msm_dp_display) +{ + struct msm_dp_display_private *dp; + + dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + return msm_dp_mst_mgr_init(msm_dp_display, msm_dp_ctrl_get_stream_cnt(dp->ctrl), dp->aux); +} + static int msm_dp_display_probe(struct platform_device *pdev) { int rc = 0; diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 4d4349068c2fd..ca2faf478c957 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -24,6 +24,8 @@ struct msm_dp { unsigned int connector_type; bool is_edp; + void *msm_dp_mst; + struct msm_dp_audio *msm_dp_audio; bool psr_supported; }; @@ -59,6 +61,8 @@ int msm_dp_display_set_mode_helper(struct msm_dp *msm_dp_display, int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display); void msm_dp_display_unprepare(struct msm_dp *dp); +int msm_dp_get_mst_max_stream(struct msm_dp *msm_dp_display); +int msm_dp_mst_register(struct msm_dp *msm_dp_display); struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display, enum msm_dp_stream_id stream_id); #endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c new file mode 100644 index 0000000000000..648d3ec72a1d2 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include + +#include "dp_mst_drm.h" +#include "dp_panel.h" + +struct msm_dp_mst_encoder { + struct drm_encoder *enc; + int stream_id; + struct msm_dp_panel *dp_panel; +}; + +struct msm_dp_mst { + struct drm_dp_mst_topology_mgr mst_mgr; + struct msm_dp_mst_encoder mst_encoders[DP_STREAM_MAX]; + struct msm_dp *msm_dp; + struct drm_dp_aux *dp_aux; + u32 max_streams; +}; + +int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux) +{ + struct drm_device *dev = dp_display->drm_dev; + struct msm_dp_mst *mst; + int ret; + + mst = devm_kzalloc(dev->dev, sizeof(*mst), GFP_KERNEL); + if (!mst) + return -ENOMEM; + + mst->msm_dp = dp_display; + mst->max_streams = max_streams; + mst->dp_aux = drm_aux; + + ret = drm_dp_mst_topology_mgr_init(&mst->mst_mgr, dev, + drm_aux, + 16, + max_streams, + dp_display->connector->base.id); + if (ret) { + drm_err(dev, "[MST] topology manager init failed\n"); + return ret; + } + + dp_display->msm_dp_mst = mst; + return 0; +} diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.h b/drivers/gpu/drm/msm/dp/dp_mst_drm.h new file mode 100644 index 0000000000000..e54d49cf34992 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _DP_MST_DRM_H_ +#define _DP_MST_DRM_H_ + +#include "dp_display.h" + +int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux); + +#endif /* _DP_MST_DRM_H_ */ diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 2840e8a5052d7..70cc6c7bfdbae 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -357,6 +357,8 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_displa bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, const struct drm_display_mode *mode); bool msm_dp_wide_bus_available(const struct msm_dp *dp_display); +int msm_dp_get_mst_max_stream(struct msm_dp *dp_display); +int msm_dp_mst_register(struct msm_dp *dp_display); #else static inline int __init msm_dp_register(void) @@ -389,6 +391,16 @@ static inline bool msm_dp_wide_bus_available(const struct msm_dp *dp_display) return false; } +static inline int msm_dp_get_mst_max_stream(struct msm_dp *dp_display) +{ + return -EINVAL; +} + +static inline int msm_dp_mst_register(struct msm_dp *dp_display) +{ + return -EINVAL; +} + #endif #ifdef CONFIG_DRM_MSM_MDP4 From 167de397195bbe0db3794c607dd4b1e81380bac3 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 31 Aug 2026 16:17:36 +0800 Subject: [PATCH 0941/1133] FROMLIST: drm/msm/dp: add MST connector creation and topology callbacks Register the add_connector topology callback with the DRM MST manager to create DRM connectors dynamically for MST ports as they appear. Each MST port is represented by a DRM connector. The connectors are attached to all available MST stream encoders, allowing encoder assignment to be determined dynamically rather than being permanently associated with a specific stream. This enables MST sink ports to be exposed as DRM connectors. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-19-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_mst_drm.c | 240 ++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c index 648d3ec72a1d2..94a717ba7c827 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -7,10 +7,20 @@ #include #include #include +#include #include "dp_mst_drm.h" #include "dp_panel.h" +#define to_dp_mst_connector(x) \ + container_of((x), struct msm_dp_mst_connector, connector) + +struct msm_dp_mst_connector { + struct drm_connector connector; + struct drm_dp_mst_port *mst_port; + struct msm_dp_mst *dp_mst; +}; + struct msm_dp_mst_encoder { struct drm_encoder *enc; int stream_id; @@ -25,6 +35,235 @@ struct msm_dp_mst { u32 max_streams; }; +static void dp_mst_connector_destroy(struct drm_connector *connector) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + + drm_connector_cleanup(connector); + drm_dp_mst_put_port_malloc(mst_conn->mst_port); + kfree(mst_conn); +} + +static const struct drm_connector_funcs msm_dp_drm_mst_connector_funcs = { + .reset = drm_atomic_helper_connector_reset, + .destroy = dp_mst_connector_destroy, + .fill_modes = drm_helper_probe_single_connector_modes, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +/* DP MST Connector OPs */ +static int +msm_dp_mst_connector_detect(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + bool force) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp *dp_display = mst->msm_dp; + struct device *dev = dp_display->drm_dev->dev; + enum drm_connector_status status = connector_status_disconnected; + int ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return status; + + if (dp_display->mst_active) + status = drm_dp_mst_detect_port(connector, + ctx, &mst->mst_mgr, mst_conn->mst_port); + + pm_runtime_put_autosuspend(dev); + + return status; +} + +static int msm_dp_mst_connector_get_modes(struct drm_connector *connector) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + const struct drm_edid *drm_edid; + int rc; + + drm_edid = drm_dp_mst_edid_read(connector, &mst->mst_mgr, mst_conn->mst_port); + drm_edid_connector_update(connector, drm_edid); + + rc = drm_edid_connector_add_modes(connector); + + drm_edid_free(drm_edid); + + return rc; +} + +static enum drm_mode_status msm_dp_mst_connector_mode_valid(struct drm_connector *connector, + const struct drm_display_mode *mode) +{ + struct msm_dp_mst_connector *mst_conn; + struct drm_dp_mst_port *mst_port; + struct msm_dp *dp_display; + int required_pbn; + + if (drm_connector_is_unregistered(connector)) + return 0; + + mst_conn = to_dp_mst_connector(connector); + mst_port = mst_conn->mst_port; + dp_display = mst_conn->dp_mst->msm_dp; + + /* Use minimum possible bpp (6bpc RGB, 8b10b) to avoid rejecting modes + * that would be feasible at the actual link bpp. mode_valid must not + * depend on negotiated parameters. + */ + required_pbn = drm_dp_calc_pbn_mode(mode->clock, (6 * 3) << 4); + + if (required_pbn > mst_port->full_pbn) { + drm_dbg_dp(dp_display->drm_dev, "mode:%s not supported.\n", mode->name); + return MODE_CLOCK_HIGH; + } + + return msm_dp_display_mode_valid(dp_display, &connector->display_info, mode); +} + +static int msm_dp_mst_connector_atomic_check(struct drm_connector *connector, + struct drm_atomic_commit *state) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + + return drm_dp_atomic_release_time_slots(state, &mst->mst_mgr, mst_conn->mst_port); +} + +static int msm_dp_mst_encoder_stream_id(struct msm_dp_mst *mst, + struct drm_encoder *enc) +{ + int i; + + for (i = 0; i < mst->max_streams; i++) { + if (mst->mst_encoders[i].enc == enc) + return mst->mst_encoders[i].stream_id; + } + return -1; +} + +static struct drm_encoder * +msm_dp_mst_atomic_best_encoder(struct drm_connector *connector, struct drm_atomic_commit *state) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct drm_connector_state *conn_state; + struct drm_connector *iter; + struct drm_connector_list_iter conn_iter; + u32 stream_mask = 0; + u32 i; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (!conn_state) + return NULL; + + if (conn_state->best_encoder) + return conn_state->best_encoder; + + drm_connector_list_iter_begin(connector->dev, &conn_iter); + drm_for_each_connector_iter(iter, &conn_iter) { + struct drm_connector_state *peer_state; + int stream_id; + + if (iter == connector || + iter->funcs != &msm_dp_drm_mst_connector_funcs || + to_dp_mst_connector(iter)->dp_mst != mst) + continue; + + peer_state = drm_atomic_get_new_connector_state(state, iter) ?: iter->state; + if (!peer_state || !peer_state->crtc || !peer_state->best_encoder) + continue; + + stream_id = msm_dp_mst_encoder_stream_id(mst, peer_state->best_encoder); + if (stream_id >= 0 && stream_id < mst->max_streams) + stream_mask |= BIT(stream_id); + } + drm_connector_list_iter_end(&conn_iter); + + for (i = 0; i < mst->max_streams; i++) { + if (!(stream_mask & BIT(i))) { + conn_state->best_encoder = mst->mst_encoders[i].enc; + return mst->mst_encoders[i].enc; + } + } + + return NULL; +} + +/* DRM MST callbacks */ +static const struct drm_connector_helper_funcs msm_dp_drm_mst_connector_helper_funcs = { + .get_modes = msm_dp_mst_connector_get_modes, + .detect_ctx = msm_dp_mst_connector_detect, + .mode_valid = msm_dp_mst_connector_mode_valid, + .atomic_best_encoder = msm_dp_mst_atomic_best_encoder, + .atomic_check = msm_dp_mst_connector_atomic_check, +}; + +static struct drm_connector * +msm_dp_mst_add_connector(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, const char *pathprop) +{ + struct msm_dp_mst *mst = container_of(mgr, struct msm_dp_mst, mst_mgr); + struct drm_device *dev = mst->msm_dp->drm_dev; + struct msm_dp_mst_connector *mst_conn; + struct drm_connector *connector; + int rc, i; + + mst_conn = kzalloc_obj(*mst_conn); + if (!mst_conn) + return NULL; + + connector = &mst_conn->connector; + rc = drm_connector_dynamic_init(dev, connector, + &msm_dp_drm_mst_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort, NULL); + if (rc) + goto err_free; + + mst_conn->dp_mst = mst; + + drm_connector_helper_add(connector, &msm_dp_drm_mst_connector_helper_funcs); + connector->funcs->reset(connector); + + /* add all encoders as possible encoders */ + for (i = 0; i < mst->max_streams; i++) { + rc = drm_connector_attach_encoder(connector, mst->mst_encoders[i].enc); + if (rc) { + drm_err(dev, "[MST] failed to attach encoder:%u to conn:%d rc:%d\n", + mst->mst_encoders[i].enc->base.id, + connector->base.id, rc); + goto err_connector; + } + } + + mst_conn->mst_port = port; + drm_dp_mst_get_port_malloc(port); + + drm_object_attach_property(&connector->base, + dev->mode_config.path_property, 0); + drm_object_attach_property(&connector->base, + dev->mode_config.tile_property, 0); + drm_connector_set_path_property(connector, pathprop); + + drm_dbg_kms(dev, "[MST] add_connector done conn:%d max_streams:%u\n", + connector->base.id, mst->max_streams); + + return connector; + +err_connector: + drm_connector_cleanup(connector); +err_free: + kfree(mst_conn); + return NULL; +} + +static const struct drm_dp_mst_topology_cbs msm_dp_mst_drm_cbs = { + .add_connector = msm_dp_mst_add_connector, +}; + int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux) { struct drm_device *dev = dp_display->drm_dev; @@ -35,6 +274,7 @@ int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct drm_d if (!mst) return -ENOMEM; + mst->mst_mgr.cbs = &msm_dp_mst_drm_cbs; mst->msm_dp = dp_display; mst->max_streams = max_streams; mst->dp_aux = drm_aux; From 1ca800351aefd34a47f512296a1bc8615f166c0a Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 31 Aug 2026 16:17:37 +0800 Subject: [PATCH 0942/1133] FROMLIST: drm/msm/dpu: pass msm_display_info to dpu_encoder_get_intf() Derive the controller ID from disp_info->h_tile_instance[index] instead of passing it separately to dpu_encoder_get_intf(). This removes a redundant argument and keeps all interface selection parameters in msm_display_info. No functional change. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-20-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 0a6be69a3e83b..5e1c98371181d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1435,15 +1435,16 @@ static void dpu_encoder_virt_atomic_disable(struct drm_encoder *drm_enc, static struct dpu_hw_intf *dpu_encoder_get_intf(const struct dpu_mdss_cfg *catalog, struct dpu_rm *dpu_rm, - enum dpu_intf_type type, u32 controller_id) + struct msm_display_info *disp_info, int index) { int i = 0; + u32 controller_id = disp_info->h_tile_instance[index]; - if (type == INTF_WB) + if (disp_info->intf_type == INTF_WB) return NULL; for (i = 0; i < catalog->intf_count; i++) { - if (catalog->intf[i].type == type + if (catalog->intf[i].type == disp_info->intf_type && catalog->intf[i].controller_id == controller_id) { return dpu_rm_get_intf(dpu_rm, catalog->intf[i].id); } @@ -2672,8 +2673,7 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, i, controller_id, phys_params.split_role); phys_params.hw_intf = dpu_encoder_get_intf(dpu_kms->catalog, &dpu_kms->rm, - disp_info->intf_type, - controller_id); + disp_info, i); if (disp_info->intf_type == INTF_WB && controller_id < WB_MAX) phys_params.hw_wb = dpu_rm_get_wb(&dpu_kms->rm, controller_id); From 972b41213e5e797abd1ebe17d3a51e2c51872302 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:45 +0530 Subject: [PATCH 0943/1133] FROMLIST: dt-bindings: PCI: Add bindings for endpoint gpios Add devicetree bindings for TC9563 GPIO's which are used to control endpoint power and reset. Signed-off-by: Sushrut Shree Trivedi Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-3-e1a721eb8943@oss.qualcomm.com --- .../bindings/pci/toshiba,tc9563.yaml | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml b/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml index c4ebb99f50c37..e2b2a1e76a7a1 100644 --- a/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml +++ b/Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml @@ -26,6 +26,11 @@ properties: reg: maxItems: 1 + gpio-controller: true + + '#gpio-cells': + const: 2 + resx-gpios: maxItems: 1 description: @@ -89,6 +94,17 @@ $defs: type: object properties: + reset-gpios: + description: + Specify the TC9563 GPIO used to reset the endpoint + connected to the particular TC9563 downstream port. + + ep-pwr-en-gpios: + description: + Specify the TC9563 GPIO used for enabling power to + the endpoint connected to the particular TC9563 + downstream port. + toshiba,tx-amplitude-microvolt: description: Change Tx Margin setting for low power consumption. @@ -124,7 +140,7 @@ examples: #address-cells = <3>; #size-cells = <2>; - pcie@0 { + tc9563: pcie@0 { device_type = "pci"; reg = <0x0 0x0 0x0 0x0 0x0>; @@ -140,6 +156,7 @@ examples: device_type = "pci"; #address-cells = <3>; #size-cells = <2>; + #gpio-cells = <2>; ranges; bus-range = <0x02 0xff>; @@ -183,6 +200,8 @@ examples: reset-gpios = <&tc9563 3 GPIO_ACTIVE_LOW>; toshiba,tx-amplitude-microvolt = <10>; + ep-pwr-en-gpios = <&tc9563 2 GPIO_ACTIVE_HIGH>; + reset-gpios = <&tc9563 5 GPIO_ACTIVE_LOW>; }; pcie@3,0 { From 04684c9136f6dde25bb6aedab313c68fa95fcb11 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 31 Aug 2026 16:17:38 +0800 Subject: [PATCH 0944/1133] FROMLIST: drm/msm/dpu: use stream_id to select MST interfaces For MST, multiple streams can share the same DP controller, making (controller_id, intf_type) insufficient to uniquely identify a DPU interface. Add stream_id to msm_display_info and use it to select the matching interface for a stream. For DSI, eDP and SST configurations, stream_id remains zero and behavior is unchanged. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-21-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 7 ++++--- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 5e1c98371181d..a8dcc8c684eb2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1437,17 +1437,18 @@ static struct dpu_hw_intf *dpu_encoder_get_intf(const struct dpu_mdss_cfg *catal struct dpu_rm *dpu_rm, struct msm_display_info *disp_info, int index) { - int i = 0; + int i = 0, cnt = 0; u32 controller_id = disp_info->h_tile_instance[index]; + int stream_id = disp_info->stream_id; if (disp_info->intf_type == INTF_WB) return NULL; for (i = 0; i < catalog->intf_count; i++) { if (catalog->intf[i].type == disp_info->intf_type - && catalog->intf[i].controller_id == controller_id) { + && catalog->intf[i].controller_id == controller_id + && cnt++ == stream_id) return dpu_rm_get_intf(dpu_rm, catalog->intf[i].id); - } } return NULL; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index 4942097e76137..9972e209bd580 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -28,6 +28,7 @@ * @h_tile_instance: Controller instance used per tile. Number of elements is * based on num_of_h_tiles * @is_cmd_mode Boolean to indicate if the CMD mode is requested + * @stream_id stream id for which the interface needs to be acquired * @vsync_source: Source of the TE signal for DSI CMD devices */ struct msm_display_info { @@ -35,6 +36,7 @@ struct msm_display_info { uint32_t num_of_h_tiles; uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; bool is_cmd_mode; + int stream_id; enum dpu_vsync_source vsync_source; }; From 613c3eb80f3588d8f942ce0fdcc2ae2ffe0057fb Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:46 +0530 Subject: [PATCH 0945/1133] FROMLIST: PCI: qcom: Add support for Shikra Add support for the single PCIe controller on Shikra platform which is capable of Gen2x1 operation. Signed-off-by: Sushrut Shree Trivedi Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-4-e1a721eb8943@oss.qualcomm.com --- 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 d903f10211c23..01fceda12e6b4 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -2613,6 +2613,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,shikra-pcie", .data = &cfg_1_9_0 }, { } }; From 6e2f96c5e67ce69140a16a5257aa5312ee7bf5fc Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 31 Aug 2026 16:17:39 +0800 Subject: [PATCH 0946/1133] FROMLIST: drm/msm/dpu: add per-stream MST encoders Unlike SST, where a DP controller is represented by a single encoder, MST requires an encoder instance for each stream. Create one DRM encoder per MST stream, associate it with a stream ID, and initialize it with MST-specific encoder helper callbacks. This establishes the per-stream encoder infrastructure required for DP MST support. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-22-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 23 ++++++++++++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 15 ++++++++++++++ drivers/gpu/drm/msm/dp/dp_mst_drm.c | 20 ++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_mst_drm.h | 2 ++ drivers/gpu/drm/msm/msm_drv.h | 9 ++++++++ 5 files changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index a8dcc8c684eb2..802cb62fc0102 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2742,6 +2742,24 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { .atomic_enable = dpu_encoder_virt_atomic_enable, }; +static void dpu_encoder_mst_atomic_enable(struct drm_encoder *enc, + struct drm_atomic_commit *state) +{ + dpu_encoder_virt_atomic_enable(enc, state); +} + +static void dpu_encoder_mst_atomic_disable(struct drm_encoder *enc, + struct drm_atomic_commit *state) +{ + dpu_encoder_virt_atomic_disable(enc, state); +} + +static const struct drm_encoder_helper_funcs dpu_mst_encoder_helper_funcs = { + .atomic_mode_set = dpu_encoder_virt_atomic_mode_set, + .atomic_enable = dpu_encoder_mst_atomic_enable, + .atomic_disable = dpu_encoder_mst_atomic_disable, +}; + static const struct drm_encoder_funcs dpu_encoder_funcs = { .debugfs_init = dpu_encoder_debugfs_init, }; @@ -2767,7 +2785,10 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev, if (IS_ERR(dpu_enc)) return ERR_CAST(dpu_enc); - drm_encoder_helper_add(&dpu_enc->base, &dpu_encoder_helper_funcs); + if (drm_enc_mode == DRM_MODE_ENCODER_DPMST) + drm_encoder_helper_add(&dpu_enc->base, &dpu_mst_encoder_helper_funcs); + else + drm_encoder_helper_add(&dpu_enc->base, &dpu_encoder_helper_funcs); spin_lock_init(&dpu_enc->enc_spinlock); dpu_enc->enabled = false; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 66cabac0a7264..d6182cec06d58 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -688,6 +688,21 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, return rc; } } + + for (int stream_id = 0; stream_cnt > 1 && stream_id < stream_cnt; stream_id++) { + info.stream_id = stream_id; + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DPMST, &info); + if (IS_ERR(encoder)) { + DPU_ERROR("encoder init failed for dp mst display\n"); + return PTR_ERR(encoder); + } + + rc = msm_dp_mst_attach_encoder(priv->kms->dp[i], stream_id, encoder); + if (rc) { + DPU_ERROR("dp_mst attach_encoder failed, rc = %d\n", rc); + return rc; + } + } } return 0; diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c index 94a717ba7c827..93536b6936cbd 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -145,6 +145,26 @@ static int msm_dp_mst_encoder_stream_id(struct msm_dp_mst *mst, return -1; } +int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, + struct drm_encoder *encoder) +{ + struct msm_dp_mst *mst = dp_display->msm_dp_mst; + struct msm_dp_panel *dp_panel; + + dp_panel = msm_dp_display_get_panel(dp_display, stream_id); + if (!dp_panel) { + drm_err(dp_display->drm_dev, + "[MST] failed to allocate panel for stream %d\n", stream_id); + return -ENOMEM; + } + + mst->mst_encoders[stream_id].enc = encoder; + mst->mst_encoders[stream_id].stream_id = stream_id; + mst->mst_encoders[stream_id].dp_panel = dp_panel; + + return 0; +} + static struct drm_encoder * msm_dp_mst_atomic_best_encoder(struct drm_connector *connector, struct drm_atomic_commit *state) { diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.h b/drivers/gpu/drm/msm/dp/dp_mst_drm.h index e54d49cf34992..89f73b1db2e77 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.h @@ -8,5 +8,7 @@ #include "dp_display.h" int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux); +int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, + struct drm_encoder *encoder); #endif /* _DP_MST_DRM_H_ */ diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 70cc6c7bfdbae..d60a4c4e0bb41 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -359,6 +359,8 @@ bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display, bool msm_dp_wide_bus_available(const struct msm_dp *dp_display); int msm_dp_get_mst_max_stream(struct msm_dp *dp_display); int msm_dp_mst_register(struct msm_dp *dp_display); +int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, + struct drm_encoder *encoder); #else static inline int __init msm_dp_register(void) @@ -401,6 +403,13 @@ static inline int msm_dp_mst_register(struct msm_dp *dp_display) return -EINVAL; } +static inline int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, + unsigned int stream_id, + struct drm_encoder *encoder) +{ + return -EINVAL; +} + #endif #ifdef CONFIG_DRM_MSM_MDP4 From dc0c284ceec6823a442ca57fb500c5f9e70239b4 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:49 +0530 Subject: [PATCH 0947/1133] FROMLIST: arm64: dts: qcom: shikra: Add PCIe PHY and controller nodes Shikra supports single PCIe instance with 5GT/s x1 lane. Add PCIe controller and PHY node for this single instance. Signed-off-by: Sushrut Shree Trivedi Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-7-e1a721eb8943@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra.dtsi | 154 +++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 7ae0f9fb38363..3df542f35dd0b 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1344,6 +1344,160 @@ reg = <0x0 0x04454000 0x0 0x1000>; }; + pcie: pcie@45e8000 { + device_type = "pci"; + compatible = "qcom,shikra-pcie"; + reg = <0x0 0x045e8000 0x0 0x3000>, + <0x0 0x60000000 0x0 0xf1d>, + <0x0 0x60000f20 0x0 0xa8>, + <0x0 0x60001000 0x0 0x1000>, + <0x0 0x60100000 0x0 0x100000>, + <0x0 0x045eb000 0x0 0x1000>; + reg-names = "parf", + "dbi", + "elbi", + "atu", + "config", + "mhi"; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>, + <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>, + <0x03000000 0x4 0x00000000 0x4 0x00000000 0x3 0x0000000>; + bus-range = <0x00 0xff>; + + linux,pci-domain = <0>; + num-lanes = <1>; + + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "msi0", + "msi1", + "msi2", + "msi3", + "msi4", + "msi5", + "msi6", + "msi7", + "global"; + + interrupt-map = <0 0 0 1 &intc 0 0 0 499 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc 0 0 0 500 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc 0 0 0 501 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc 0 0 0 502 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map-mask = <0 0 0 0x7>; + #interrupt-cells = <1>; + + clocks = <&gcc GCC_PCIE_AUX_CLK>, + <&gcc GCC_PCIE_CFG_AHB_CLK>, + <&gcc GCC_PCIE_MSTR_AXI_CLK>, + <&gcc GCC_PCIE_SLV_AXI_CLK>, + <&gcc GCC_PCIE_SLV_Q2A_AXI_CLK>, + <&gcc GCC_DDRSS_MEMNOC_PCIE_SF_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>, + <&gcc GCC_QMIP_PCIE_CFG_AHB_CLK>; + clock-names = "aux", + "cfg", + "bus_master", + "bus_slave", + "slave_q2a", + "ddrss_memnoc_pcie", + "tile", + "qmip_pcie_ahb"; + + assigned-clocks = <&gcc GCC_PCIE_AUX_CLK>; + assigned-clock-rates = <19200000>; + + interconnects = <&system_noc MASTER_PCIE2_0 RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>, + <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_PCIE2_0 RPM_ACTIVE_TAG>; + + interconnect-names = "pcie-mem", + "cpu-pcie"; + + iommu-map = <0x0 &apps_smmu 0x800 0x1>, + <0x100 &apps_smmu 0x801 0x1>; + + resets = <&gcc GCC_PCIE_BCR>; + reset-names = "pci"; + + power-domains = <&gcc GCC_PCIE_GDSC>; + + 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 = <&rpmpd_opp_nom>; + opp-peak-kBps = <250000 1>; + opp-level = <1>; + }; + + /* GEN 2 x1 */ + opp-5000000 { + opp-hz = /bits/ 64 <5000000>; + required-opps = <&rpmpd_opp_nom>; + opp-peak-kBps = <500000 1>; + opp-level = <2>; + }; + }; + + pcie_port0: pcie@0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + bus-range = <0x01 0x8>; + + phys = <&pcie_phy>; + }; + }; + + pcie_phy: phy@45ee000 { + compatible = "qcom,shikra-qmp-gen2x1-pcie-phy"; + reg = <0x0 0x045ee000 0x0 0x1000>; + + clocks = <&gcc GCC_PCIE_AUX_CLK>, + <&gcc GCC_PCIE_CFG_AHB_CLK>, + <&gcc GCC_PCIE_CLKREF_EN>, + <&gcc GCC_PCIE_RCHNG_PHY_CLK>, + <&gcc GCC_PCIE_PIPE_CLK>; + clock-names = "aux", + "cfg_ahb", + "ref", + "refgen", + "pipe"; + + resets = <&gcc GCC_PCIE_PHY_BCR>; + reset-names = "phy"; + + assigned-clocks = <&gcc GCC_PCIE_RCHNG_PHY_CLK>; + assigned-clock-rates = <100000000>; + + #clock-cells = <0>; + clock-output-names = "pcie_pipe_clk"; + + #phy-cells = <0>; + + status = "disabled"; + }; + rpm_msg_ram: sram@45f0000 { compatible = "qcom,rpm-msg-ram", "mmio-sram"; reg = <0x0 0x045f0000 0x0 0x7000>; From 310a3b3a349294fa21002615da31d26bf8906af6 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 31 Aug 2026 16:17:40 +0800 Subject: [PATCH 0948/1133] FROMLIST: drm/msm/dp: add atomic stream handling for MST Add the atomic check, enable and disable operations for MST streams. Reserve VC payload bandwidth based on the negotiated link parameters, and update the MST payload when enabling or disabling each DP stream. Serialize stream updates that access the shared MST link state. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-23-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 11 ++ drivers/gpu/drm/msm/dp/dp_mst_drm.c | 162 ++++++++++++++++++++ drivers/gpu/drm/msm/msm_drv.h | 19 +++ 3 files changed, 192 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 802cb62fc0102..edf30d7d3d169 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2745,16 +2745,27 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { static void dpu_encoder_mst_atomic_enable(struct drm_encoder *enc, struct drm_atomic_commit *state) { + msm_dp_mst_stream_enable(enc, state); dpu_encoder_virt_atomic_enable(enc, state); } static void dpu_encoder_mst_atomic_disable(struct drm_encoder *enc, struct drm_atomic_commit *state) { + msm_dp_mst_stream_disable(enc, state); dpu_encoder_virt_atomic_disable(enc, state); + msm_dp_mst_stream_post_disable(enc, state); +} + +static int dpu_encoder_mst_atomic_check(struct drm_encoder *enc, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + return msm_dp_mst_stream_atomic_check(enc, crtc_state, conn_state); } static const struct drm_encoder_helper_funcs dpu_mst_encoder_helper_funcs = { + .atomic_check = dpu_encoder_mst_atomic_check, .atomic_mode_set = dpu_encoder_virt_atomic_mode_set, .atomic_enable = dpu_encoder_mst_atomic_enable, .atomic_disable = dpu_encoder_mst_atomic_disable, diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c index 93536b6936cbd..03f9c95ca6860 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -33,6 +33,9 @@ struct msm_dp_mst { struct msm_dp *msm_dp; struct drm_dp_aux *dp_aux; u32 max_streams; + /* Serializes concurrent stream link-state access across streams. */ + struct mutex mst_lock; + struct msm_dp_link_info link_info; }; static void dp_mst_connector_destroy(struct drm_connector *connector) @@ -133,6 +136,18 @@ static int msm_dp_mst_connector_atomic_check(struct drm_connector *connector, return drm_dp_atomic_release_time_slots(state, &mst->mst_mgr, mst_conn->mst_port); } +static struct msm_dp_panel *msm_dp_mst_panel_from_encoder(struct msm_dp_mst *mst, + struct drm_encoder *enc) +{ + int i; + + for (i = 0; i < mst->max_streams; i++) { + if (mst->mst_encoders[i].enc == enc) + return mst->mst_encoders[i].dp_panel; + } + return NULL; +} + static int msm_dp_mst_encoder_stream_id(struct msm_dp_mst *mst, struct drm_encoder *enc) { @@ -145,6 +160,152 @@ static int msm_dp_mst_encoder_stream_id(struct msm_dp_mst *mst, return -1; } +void msm_dp_mst_stream_enable(struct drm_encoder *encoder, + struct drm_atomic_commit *state) +{ + struct drm_connector *connector = + drm_atomic_get_new_connector_for_encoder(state, encoder); + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp *dp_display = mst->msm_dp; + struct msm_dp_panel *panel = msm_dp_mst_panel_from_encoder(mst, encoder); + struct drm_dp_mst_port *port = mst_conn->mst_port; + struct drm_dp_mst_topology_state *mst_state = + drm_atomic_get_new_mst_topology_state(state, &mst->mst_mgr); + struct drm_dp_mst_atomic_payload *payload = + drm_atomic_get_mst_payload_state(mst_state, port); + int rc; + + guard(mutex)(&mst->mst_lock); + + drm_connector_get(connector); + panel->connector = connector; + + rc = msm_dp_display_set_mode_helper(dp_display, state, encoder, panel); + if (rc) { + drm_err(dp_display->drm_dev, + "[MST] stream:%u set_mode failed rc=%d\n", panel->stream_id, rc); + return; + } + + rc = msm_dp_display_prepare_link(dp_display); + if (rc) { + drm_err(dp_display->drm_dev, + "[MST] stream:%u prepare_link failed rc=%d\n", panel->stream_id, rc); + msm_dp_display_unprepare(dp_display); + return; + } + + drm_dp_mst_update_slots(mst_state, DP_CAP_ANSI_8B10B); + + rc = drm_dp_add_payload_part1(&mst->mst_mgr, mst_state, payload); + if (rc) + return; + + msm_dp_display_set_stream_info(mst->msm_dp, panel, + payload->vc_start_slot, + payload->time_slots, payload->pbn); + drm_dbg_kms(dp_display->drm_dev, + "[MST] stream:%u timeslots vc_start:%d slots:%d pbn:%d\n", + panel->stream_id, payload->vc_start_slot, + payload->time_slots, payload->pbn); + + msm_dp_display_enable_helper(dp_display, panel); + + drm_dp_check_act_status(&mst->mst_mgr); + + drm_dp_add_payload_part2(&mst->mst_mgr, payload); +} + +void msm_dp_mst_stream_disable(struct drm_encoder *encoder, + struct drm_atomic_commit *state) +{ + struct drm_connector *connector = drm_atomic_get_old_connector_for_encoder(state, encoder); + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp_panel *panel = msm_dp_mst_panel_from_encoder(mst, encoder); + struct drm_dp_mst_topology_state *old_mst_state = + drm_atomic_get_old_mst_topology_state(state, &mst->mst_mgr); + struct drm_dp_mst_topology_state *new_mst_state = + drm_atomic_get_new_mst_topology_state(state, &mst->mst_mgr); + struct drm_dp_mst_atomic_payload *old_payload = + drm_atomic_get_mst_payload_state(old_mst_state, mst_conn->mst_port); + struct drm_dp_mst_atomic_payload *new_payload = + drm_atomic_get_mst_payload_state(new_mst_state, mst_conn->mst_port); + + guard(mutex)(&mst->mst_lock); + + drm_dp_remove_payload_part1(&mst->mst_mgr, new_mst_state, new_payload); + + drm_dp_remove_payload_part2(&mst->mst_mgr, new_mst_state, old_payload, new_payload); + + msm_dp_display_set_stream_info(mst->msm_dp, panel, 0, 0, 0); + drm_dbg_kms(mst->msm_dp->drm_dev, + "[MST] stream:%u timeslots vc_start:%d slots:%d pbn:%d\n", + panel->stream_id, new_payload->vc_start_slot, + new_payload->time_slots, new_payload->pbn); + + msm_dp_display_disable_helper(mst->msm_dp, panel); + + drm_dp_check_act_status(&mst->mst_mgr); +} + +void msm_dp_mst_stream_post_disable(struct drm_encoder *encoder, + struct drm_atomic_commit *state) +{ + struct drm_connector *connector = drm_atomic_get_old_connector_for_encoder(state, encoder); + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct msm_dp_panel *panel = msm_dp_mst_panel_from_encoder(mst, encoder); + + guard(mutex)(&mst->mst_lock); + + msm_dp_display_atomic_post_disable_helper(mst->msm_dp, panel); + + if (!mst->msm_dp->mst_active) + msm_dp_display_unprepare(mst->msm_dp); + + panel->connector = NULL; + + drm_connector_put(connector); +} + +int msm_dp_mst_stream_atomic_check(struct drm_encoder *enc, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct msm_dp_mst_connector *mst_conn = to_dp_mst_connector(conn_state->connector); + struct msm_dp_mst *mst = mst_conn->dp_mst; + struct drm_dp_mst_topology_state *mst_state; + int bpp, pbn, slots; + + if (!conn_state->crtc) + return 0; + + if (!drm_atomic_crtc_needs_modeset(crtc_state) || !crtc_state->active) + return 0; + + bpp = (conn_state->connector->display_info.bpc * 3) ?: 24; /* fallback: assume 8bpc */ + pbn = drm_dp_calc_pbn_mode(crtc_state->mode.clock, bpp << 4); + + mst_state = drm_atomic_get_mst_topology_state(crtc_state->state, &mst->mst_mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + + if (!dfixed_trunc(mst_state->pbn_div)) { + mst_state->pbn_div = + drm_dp_get_vc_payload_bw(mst->link_info.rate, + mst->link_info.num_lanes); + } + + slots = drm_dp_atomic_find_time_slots(crtc_state->state, &mst->mst_mgr, + mst_conn->mst_port, pbn); + if (slots < 0) + return slots; + + return 0; +} + int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, struct drm_encoder *encoder) { @@ -309,6 +470,7 @@ int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct drm_d return ret; } + mutex_init(&mst->mst_lock); dp_display->msm_dp_mst = mst; return 0; } diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index d60a4c4e0bb41..e5e4baea3faca 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -361,6 +361,12 @@ int msm_dp_get_mst_max_stream(struct msm_dp *dp_display); int msm_dp_mst_register(struct msm_dp *dp_display); int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, struct drm_encoder *encoder); +void msm_dp_mst_stream_enable(struct drm_encoder *enc, struct drm_atomic_commit *state); +void msm_dp_mst_stream_disable(struct drm_encoder *enc, struct drm_atomic_commit *state); +void msm_dp_mst_stream_post_disable(struct drm_encoder *enc, struct drm_atomic_commit *state); +int msm_dp_mst_stream_atomic_check(struct drm_encoder *enc, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state); #else static inline int __init msm_dp_register(void) @@ -410,6 +416,19 @@ static inline int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, return -EINVAL; } +static inline void msm_dp_mst_stream_enable(struct drm_encoder *enc, + struct drm_atomic_commit *state) {} +static inline void msm_dp_mst_stream_disable(struct drm_encoder *enc, + struct drm_atomic_commit *state) {} +static inline void msm_dp_mst_stream_post_disable(struct drm_encoder *enc, + struct drm_atomic_commit *state) {} +static inline int msm_dp_mst_stream_atomic_check(struct drm_encoder *enc, + struct drm_crtc_state *cs, + struct drm_connector_state *cos) +{ + return -EINVAL; +} + #endif #ifdef CONFIG_DRM_MSM_MDP4 From 8734e106c9dc341e134e1c585f7d9bffb526d383 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:41 +0800 Subject: [PATCH 0949/1133] FROMLIST: drm/msm/dp: add HPD callback for dp MST Add HPD callback for the MST module which shall be invoked from the dp_display's HPD handler to perform MST specific operations in case of HPD. In MST case, route the HPD messages to MST module. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-24-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 26 +++++++++++++---- drivers/gpu/drm/msm/dp/dp_mst_drm.c | 44 +++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_mst_drm.h | 1 + 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 73ec37f9510f3..2afb463ba51ba 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -417,6 +417,9 @@ static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp) dp->msm_dp_display.connector_type, dp->link->sink_count); + if (dp->plugged && dp->msm_dp_display.mst_active) + return 0; + guard(mutex)(&dp->plugged_lock); ret = pm_runtime_resume_and_get(&pdev->dev); @@ -508,6 +511,7 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp) { u32 sink_request; int rc = 0; + struct msm_dp *msm_dp_display = &dp->msm_dp_display; guard(mutex)(&dp->plugged_lock); @@ -516,6 +520,11 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp) dp->msm_dp_display.connector_type, dp->link->sink_count); + if (msm_dp_display->mst_active) { + msm_dp_mst_display_hpd_irq(&dp->msm_dp_display); + return 0; + } + /* check for any test request issued by sink */ rc = msm_dp_link_process_request(dp->link); if (!rc) { @@ -1063,10 +1072,16 @@ static irqreturn_t msm_dp_display_irq_thread(int irq, void *dev_id) drm_bridge_hpd_notify(dp->msm_dp_display.bridge, connector_status_connected); - /* Send HPD as connected and distinguish it in the notifier */ - if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) - drm_bridge_hpd_notify(dp->msm_dp_display.bridge, - connector_status_connected); + /* Temporary until DRM IRQ support is finalized, then switch to + * drm_bridge_hpd_notify(). + */ + if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) { + if (dp->msm_dp_display.mst_active) + msm_dp_irq_hpd_handle(dp); + else + drm_bridge_hpd_notify(dp->msm_dp_display.bridge, + connector_status_connected); + } ret = IRQ_HANDLED; @@ -1742,7 +1757,8 @@ void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, msm_dp_hpd_plug_handle(dp); } } else { - msm_dp_hpd_unplug_handle(dp); + if (hpd_link_status == ISR_DISCONNECTED) + msm_dp_hpd_unplug_handle(dp); } pm_runtime_put_sync(&msm_dp_display->pdev->dev); diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c index 03f9c95ca6860..2e625a7db9819 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -35,6 +35,8 @@ struct msm_dp_mst { u32 max_streams; /* Serializes concurrent stream link-state access across streams. */ struct mutex mst_lock; + /* Serializes HPD IRQ handling between IRQ handler and poll_hpd_irq. */ + struct mutex hpd_irq_lock; struct msm_dp_link_info link_info; }; @@ -326,6 +328,39 @@ int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, return 0; } +void msm_dp_mst_display_hpd_irq(struct msm_dp *dp_display) +{ + int rc; + struct msm_dp_mst *mst = dp_display->msm_dp_mst; + u8 ack[8] = {}; + u8 esi[4]; + unsigned int esi_res = DP_SINK_COUNT_ESI + 1; + bool handled; + + guard(mutex)(&mst->hpd_irq_lock); + + rc = drm_dp_dpcd_read_data(mst->dp_aux, DP_SINK_COUNT_ESI, esi, 4); + if (rc < 0) { + DRM_ERROR("DPCD sink status read failed, rlen=%d\n", rc); + return; + } + + drm_dbg_dp(dp_display->drm_dev, "MST HPD IRQ: esi=%*ph\n", 4, esi); + + rc = drm_dp_mst_hpd_irq_handle_event(&mst->mst_mgr, esi, ack, &handled); + + if (handled) { + rc = drm_dp_dpcd_write_byte(mst->dp_aux, esi_res, ack[1]); + if (rc < 0) { + DRM_ERROR("DPCD esi_res failed. rc=%d\n", rc); + return; + } + + drm_dp_mst_hpd_irq_send_new_request(&mst->mst_mgr); + } + drm_dbg_dp(dp_display->drm_dev, "MST display hpd_irq handled:%d rc:%d\n", handled, rc); +} + static struct drm_encoder * msm_dp_mst_atomic_best_encoder(struct drm_connector *connector, struct drm_atomic_commit *state) { @@ -441,8 +476,16 @@ msm_dp_mst_add_connector(struct drm_dp_mst_topology_mgr *mgr, return NULL; } +static void msm_dp_mst_poll_hpd_irq(struct drm_dp_mst_topology_mgr *mgr) +{ + struct msm_dp_mst *mst = container_of(mgr, struct msm_dp_mst, mst_mgr); + + msm_dp_mst_display_hpd_irq(mst->msm_dp); +} + static const struct drm_dp_mst_topology_cbs msm_dp_mst_drm_cbs = { .add_connector = msm_dp_mst_add_connector, + .poll_hpd_irq = msm_dp_mst_poll_hpd_irq, }; int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux) @@ -471,6 +514,7 @@ int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct drm_d } mutex_init(&mst->mst_lock); + mutex_init(&mst->hpd_irq_lock); dp_display->msm_dp_mst = mst; return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.h b/drivers/gpu/drm/msm/dp/dp_mst_drm.h index 89f73b1db2e77..8546214cbca16 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.h @@ -10,5 +10,6 @@ int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux); int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, struct drm_encoder *encoder); +void msm_dp_mst_display_hpd_irq(struct msm_dp *dp_display); #endif /* _DP_MST_DRM_H_ */ From e0bb0c4be0f28fa9edfb9fac07904d62694cef6b Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 31 Aug 2026 16:17:42 +0800 Subject: [PATCH 0950/1133] FROMLIST: drm/msm/dp: wire MST helpers into atomic check and commit paths Call drm_dp_mst_atomic_check() from msm_atomic_check() so MST-specific state, such as connector and topology changes, is validated as part of the atomic check. Hook the MST helpers into atomic_commit_setup() and atomic_commit_tail() to support non-blocking atomic commits for DisplayPort MST, and ensure MST commits properly wait for dependencies. For SST, non-blocking commits are already handled via commit_tail(), which waits for dependencies in the DRM core. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-25-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/msm_atomic.c | 14 +++++++++++++- drivers/gpu/drm/msm/msm_drv.h | 1 + drivers/gpu/drm/msm/msm_kms.c | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index a8babf1dbe0d3..e70e5088cfe53 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -4,6 +4,7 @@ * Author: Rob Clark */ +#include #include #include @@ -207,7 +208,11 @@ int msm_atomic_check(struct drm_device *dev, struct drm_atomic_commit *state) if (ret) return ret; - return drm_atomic_helper_check(dev, state); + ret = drm_atomic_helper_check(dev, state); + if (ret) + return ret; + + return drm_dp_mst_atomic_check(state); } void msm_atomic_commit_tail(struct drm_atomic_commit *state) @@ -221,6 +226,8 @@ void msm_atomic_commit_tail(struct drm_atomic_commit *state) trace_msm_atomic_commit_tail_start(async, crtc_mask); + drm_dp_mst_atomic_wait_for_dependencies(state); + kms->funcs->enable_commit(kms); /* @@ -322,3 +329,8 @@ void msm_atomic_commit_tail(struct drm_atomic_commit *state) trace_msm_atomic_commit_tail_finish(async, crtc_mask); } + +int msm_atomic_commit_setup(struct drm_atomic_commit *state) +{ + return drm_dp_mst_atomic_setup_commit(state); +} diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index e5e4baea3faca..d5ee2e32ad1d1 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -211,6 +211,7 @@ int msm_atomic_init_pending_timer(struct msm_pending_timer *timer, struct msm_kms *kms, int crtc_idx); void msm_atomic_destroy_pending_timer(struct msm_pending_timer *timer); void msm_atomic_commit_tail(struct drm_atomic_commit *state); +int msm_atomic_commit_setup(struct drm_atomic_commit *state); int msm_atomic_check(struct drm_device *dev, struct drm_atomic_commit *state); struct drm_atomic_commit *msm_atomic_state_alloc(struct drm_device *dev); diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c index e5d0ea6294484..33ab30300e16d 100644 --- a/drivers/gpu/drm/msm/msm_kms.c +++ b/drivers/gpu/drm/msm/msm_kms.c @@ -29,6 +29,7 @@ static const struct drm_mode_config_funcs mode_config_funcs = { static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = { .atomic_commit_tail = msm_atomic_commit_tail, + .atomic_commit_setup = msm_atomic_commit_setup, }; static irqreturn_t msm_irq(int irq, void *arg) From 3069e56ff4ffe47bc40b0bf3ed296d953bf0e0d7 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:43 +0800 Subject: [PATCH 0951/1133] FROMLIST: drm/msm/dp: mark the SST bridge disconnected when mst is active The bridge detect function is only applicable for SST. In MST mode, connector detection is handled by MST bridges. Skip detection for the SST bridge when MST is active, matching the behavior of other DP MST implementations. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-26-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 2afb463ba51ba..ca33ef9cfe8d1 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -966,6 +966,10 @@ enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge, priv = container_of(dp, struct msm_dp_display_private, msm_dp_display); guard(mutex)(&priv->plugged_lock); + + if (dp->mst_active) + return status; + ret = pm_runtime_resume_and_get(&dp->pdev->dev); if (ret) { DRM_ERROR("failed to pm_runtime_resume\n"); From 38a8ba7153352bb30cbcc6efa3e6f83819eac330 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:50 +0530 Subject: [PATCH 0952/1133] FROMLIST: arm64: dts: qcom: shikra-evk: Add TC9563 PCIe switch node for PCIe Add a node for the TC9563 PCIe switch connected to PCIe. The switch has three downstream ports.Two embedded Ethernet devices are present on one of the downstream ports. All the ports present in the node represent the downstream ports and embedded endpoints. Power to the TC9563 is supplied through two LDO regulators, which are on by default and are added as fixed regulators. TC9563 can be configured through I2C. Signed-off-by: Sushrut Shree Trivedi Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-8-e1a721eb8943@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 154 +++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi index 13036d8cc8ebd..6511ac6ec9889 100644 --- a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi @@ -3,6 +3,32 @@ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ +/ { + aliases { + i2c3 = &i2c3; + }; + + vreg_0p9: regulator-0v9 { + compatible = "regulator-fixed"; + regulator-name = "VREG_0P9"; + + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-always-on; + regulator-boot-on; + }; + + vreg_1p8: regulator-1v8 { + compatible = "regulator-fixed"; + regulator-name = "VREG_1P8"; + + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; +}; + &gpu { status = "okay"; }; @@ -11,12 +37,116 @@ firmware-name = "qcom/shikra/a704_zap.mbn"; }; +&i2c3 { + status = "okay"; +}; + &iris { firmware-name = "qcom/vpu/ar50lt_p1_gen2_s6.mbn"; status = "okay"; }; +&pcie { + wake-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>; + + iommu-map = <0x0 &apps_smmu 0x0800 0x1>, + <0x100 &apps_smmu 0x0801 0x1>, + <0x208 &apps_smmu 0x0802 0x1>, + <0x210 &apps_smmu 0x0803 0x1>, + <0x218 &apps_smmu 0x0804 0x1>, + <0x300 &apps_smmu 0x0805 0x1>, + <0x400 &apps_smmu 0x0806 0x1>, + <0x500 &apps_smmu 0x0807 0x1>, + <0x501 &apps_smmu 0x0808 0x1>; + + pinctrl-0 = <&pcie_default_state>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie_port0 { + + tc9563: pcie@0,0 { + compatible = "pci1179,0623"; + reg = <0x10000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + #gpio-cells = <2>; + gpio-controller; + + device_type = "pci"; + ranges; + bus-range = <0x2 0xff>; + + vddc-supply = <&vreg_0p9>; + vdd18-supply = <&vreg_1p8>; + vdd09-supply = <&vreg_0p9>; + vddio1-supply = <&vreg_1p8>; + vddio2-supply = <&vreg_1p8>; + vddio18-supply = <&vreg_1p8>; + + i2c-parent = <&i2c3 0x77>; + + resx-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&tc9563_resx_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>; + + ep-pwr-en-gpios = <&tc9563 2 GPIO_ACTIVE_HIGH>; + reset-gpios = <&tc9563 5 GPIO_ACTIVE_LOW>; + }; + + pcie@2,0 { + reg = <0x21000 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + ranges; + bus-range = <0x4 0xff>; + + ep-pwr-en-gpios = <&tc9563 4 GPIO_ACTIVE_HIGH>; + reset-gpios = <&tc9563 3 GPIO_ACTIVE_LOW>; + }; + + 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; + }; + }; + }; +}; + &qupv3_0 { firmware-name = "qcom/shikra/qupv3fw.elf"; @@ -44,6 +174,30 @@ }; }; +&tlmm { + pcie_default_state:pcie-default-state{ + clkreq-pins{ + pins="gpio117"; + function="pcie0_clk_req_n"; + drive-strength=<2>; + bias-pull-up; + }; + + wake-pins{ + pins="gpio119"; + function="gpio"; + drive-strength=<2>; + bias-pull-up; + }; + }; + + tc9563_resx_n: tc9563-resx-state { + pins = "gpio118"; + function = "gpio"; + bias-disable; + }; +}; + &uart0 { status = "okay"; }; From d68712cba59a0ea8db2fb8379e4fb4c881919f46 Mon Sep 17 00:00:00 2001 From: Sushrut Shree Trivedi Date: Wed, 1 Jul 2026 00:32:51 +0530 Subject: [PATCH 0953/1133] FROMLIST: arm64: dts: qcom: shikra-(cqm/cqs/iqs)-evk: Enable PCIe PHY node Enable the PCIe PHY for the single PCIe intance on the Shikra CQS, CQM and the IQS platforms. IQS platform uses a different powergrid than CQS/CQM which explain the different PHY supplies for IQS variant. Signed-off-by: Sushrut Shree Trivedi Link: https://lore.kernel.org/r/20260701-shikra-upstream-v1-9-e1a721eb8943@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 7 +++++++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 7 +++++++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 548cba16f5f37..76bfe94db25b4 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -109,6 +109,13 @@ regulator-allow-set-load; }; +&pcie_phy { + vdda-phy-supply = <&pm4125_l13>; + vdda-pll-supply = <&pm4125_l9>; + + status = "okay"; +}; + &pm4125_hs_in { remote-endpoint = <&usb_1_dwc3_hs>; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 2aab335ff0ffc..794d9e69de07b 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -98,6 +98,13 @@ status = "okay"; }; +&pcie_phy { + vdda-phy-supply = <&pm4125_l13>; + vdda-pll-supply = <&pm4125_l9>; + + status = "okay"; +}; + &pm4125_l5 { /* DSI VDDA - must be at NOM voltage for PHY PLL lock */ regulator-min-microvolt = <1232000>; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 5df30ad8211f8..f7993407b8b47 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -25,6 +25,13 @@ }; }; +&pcie_phy { + vdda-phy-supply = <&pm8150_l12>; + vdda-pll-supply = <&pm8150_l9>; + + status = "okay"; +}; + &remoteproc_cdsp { firmware-name = "qcom/shikra/cdsp.mbn"; From 94ca3218d0979d8e524fcb365e0436211e20f366 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Tue, 14 Jul 2026 11:02:31 +0530 Subject: [PATCH 0954/1133] FROMLIST: dt-bindings: net: qcom,bam-dmux: Add qcom,shikra-bam-dmux compatible On platforms where the modem DMAs into the BAM-DMUX RX data buffers and the XPU enforces per-region access control, each individually DMA-mapped RX buffer consumes an XPU resource group. With only ~16 groups available, the per-buffer mappings exhaust the table and inbound transfers fault. Add qcom,shikra-bam-dmux as an additional compatible for the Shikra SoC, paired with the generic qcom,bam-dmux fallback, so the driver can match on it via its of_device_id table. Co-developed-by: Deepak Kumar Singh Signed-off-by: Deepak Kumar Singh Signed-off-by: Vishnu Santhosh Link: https://lore.kernel.org/r/20260714-qcom-bam-dmux-vmid-ext-v1-1-3f29da7cca76@oss.qualcomm.com --- Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml b/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml index 33746c238513d..27f0fdf285c17 100644 --- a/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml +++ b/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml @@ -22,7 +22,13 @@ description: | properties: compatible: - const: qcom,bam-dmux + oneOf: + - const: qcom,bam-dmux + - items: + - enum: + # Shikra + - qcom,shikra-bam-dmux + - const: qcom,bam-dmux interrupts: description: From c06d2b3c5076b7ad74a1f3a05091525da80c67a1 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Tue, 14 Jul 2026 11:02:32 +0530 Subject: [PATCH 0955/1133] FROMLIST: net: wwan: qcom_bam_dmux: Alloc RX buffers as a single coherent block On Qualcomm SoCs where the modem (e.g. the mDSP on Shikra, VMID 43 / NAV) is the AXI master for BAM-DMUX RX transfers and the XPU enforces per-region access control, each individually DMA-mapped RX buffer requires its own XPU resource group (RG). With ~16 RGs available, the 32 per-buffer dma_map_single() calls exhaust the table and the first inbound transfer faults with an XPU violation. BAM-DMUX is a singleton (exactly one instance per SoC), so the destination VMID does not need to be a DT property; it is looked up from the compatible string's match data instead. Add struct bam_dmux_data with a single vmid field, and a shikra_data instance hardcoding QCOM_SCM_VMID_NAV for qcom,shikra-bam-dmux. When match data is present, allocate all BAM_DMUX_NUM_SKB RX buffers as a single contiguous dma_alloc_coherent() block and SCM-assign that block to HLOS plus the VMID once at probe. This reduces RG consumption from 32 to 1. The block is never reclaimed across a modem power cycle (bam_dmux_power_off() does not touch it), so the probe-time assignment covers every subsequent restart without re-assigning or reclaiming. It is reclaimed to HLOS only once, at remove or on a probe error, and if that reclaim fails it is leaked rather than returned to the page allocator. Each rx_skbs[] slot is pre-assigned its virtual and DMA address from the block, so no per-buffer mapping is needed at power-on. Because the coherent block is not page-backed, received payload is copied into a regular netdev skb before handoff to the network stack; this is an unavoidable extra copy on the XPU-enforced RX path. Platforms without match data are unaffected: rx_virt stays NULL, no coherent memory is allocated, and the per-buffer dma_map_single() path is unchanged. Co-developed-by: Deepak Kumar Singh Signed-off-by: Deepak Kumar Singh Signed-off-by: Vishnu Santhosh Link: https://lore.kernel.org/r/20260714-qcom-bam-dmux-vmid-ext-v1-2-3f29da7cca76@oss.qualcomm.com --- drivers/net/wwan/Kconfig | 1 + drivers/net/wwan/qcom_bam_dmux.c | 134 ++++++++++++++++++++++++++++--- 2 files changed, 125 insertions(+), 10 deletions(-) diff --git a/drivers/net/wwan/Kconfig b/drivers/net/wwan/Kconfig index 958dbc7347fa8..1b133c5623161 100644 --- a/drivers/net/wwan/Kconfig +++ b/drivers/net/wwan/Kconfig @@ -65,6 +65,7 @@ config MHI_WWAN_MBIM config QCOM_BAM_DMUX tristate "Qualcomm BAM-DMUX WWAN network driver" depends on (DMA_ENGINE && PM && QCOM_SMEM_STATE) || COMPILE_TEST + select QCOM_SCM help The BAM Data Multiplexer provides access to the network data channels of modems integrated into many older Qualcomm SoCs, e.g. Qualcomm diff --git a/drivers/net/wwan/qcom_bam_dmux.c b/drivers/net/wwan/qcom_bam_dmux.c index cc6ace8d64371..247230b720e60 100644 --- a/drivers/net/wwan/qcom_bam_dmux.c +++ b/drivers/net/wwan/qcom_bam_dmux.c @@ -9,10 +9,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -62,6 +64,7 @@ struct bam_dmux_skb_dma { struct bam_dmux *dmux; struct sk_buff *skb; dma_addr_t addr; + void *rx_virt; /* non-NULL: slot in the coherent RX block */ }; struct bam_dmux { @@ -75,6 +78,10 @@ struct bam_dmux { struct completion pc_ack_completion; struct dma_chan *rx, *tx; + /* Single coherent block backing all RX buffers, NULL if unused */ + void *rx_buf; + dma_addr_t rx_buf_dma; + u64 rx_buf_perms; /* SCM source-VMID bitmask of rx_buf */ struct bam_dmux_skb_dma rx_skbs[BAM_DMUX_NUM_SKB]; struct bam_dmux_skb_dma tx_skbs[BAM_DMUX_NUM_SKB]; spinlock_t tx_lock; /* Protect tx_skbs, tx_next_skb */ @@ -92,6 +99,10 @@ struct bam_dmux_netdev { u8 ch; }; +struct bam_dmux_data { + u32 vmid; +}; + static void bam_dmux_pc_vote(struct bam_dmux *dmux, bool enable) { reinit_completion(&dmux->pc_ack_completion); @@ -111,6 +122,9 @@ static bool bam_dmux_skb_dma_map(struct bam_dmux_skb_dma *skb_dma, { struct device *dev = skb_dma->dmux->dev; + if (skb_dma->rx_virt) /* coherent RX slot: addr pre-assigned */ + return true; + skb_dma->addr = dma_map_single(dev, skb_dma->skb->data, skb_dma->skb->len, dir); if (dma_mapping_error(dev, skb_dma->addr)) { dev_err(dev, "Failed to DMA map buffer\n"); @@ -124,6 +138,9 @@ static bool bam_dmux_skb_dma_map(struct bam_dmux_skb_dma *skb_dma, static void bam_dmux_skb_dma_unmap(struct bam_dmux_skb_dma *skb_dma, enum dma_data_direction dir) { + if (skb_dma->rx_virt) /* coherent RX slot: nothing to unmap */ + return; + dma_unmap_single(skb_dma->dmux->dev, skb_dma->addr, skb_dma->skb->len, dir); skb_dma->addr = 0; } @@ -468,9 +485,10 @@ static bool bam_dmux_skb_dma_submit_rx(struct bam_dmux_skb_dma *skb_dma) { struct bam_dmux *dmux = skb_dma->dmux; struct dma_async_tx_descriptor *desc; + size_t len = skb_dma->rx_virt ? BAM_DMUX_BUFFER_SIZE : skb_dma->skb->len; desc = dmaengine_prep_slave_single(dmux->rx, skb_dma->addr, - skb_dma->skb->len, DMA_DEV_TO_MEM, + len, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); if (!desc) { dev_err(dmux->dev, "Failed to prepare RX DMA buffer\n"); @@ -485,6 +503,10 @@ static bool bam_dmux_skb_dma_submit_rx(struct bam_dmux_skb_dma *skb_dma) static bool bam_dmux_skb_dma_queue_rx(struct bam_dmux_skb_dma *skb_dma, gfp_t gfp) { + /* Coherent RX slots have rx_virt and addr pre-assigned at probe. */ + if (skb_dma->rx_virt) + return bam_dmux_skb_dma_submit_rx(skb_dma); + if (!skb_dma->skb) { skb_dma->skb = __netdev_alloc_skb(NULL, BAM_DMUX_BUFFER_SIZE, gfp); if (!skb_dma->skb) @@ -499,9 +521,10 @@ static bool bam_dmux_skb_dma_queue_rx(struct bam_dmux_skb_dma *skb_dma, gfp_t gf static void bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma) { struct bam_dmux *dmux = skb_dma->dmux; - struct sk_buff *skb = skb_dma->skb; - struct bam_dmux_hdr *hdr = (struct bam_dmux_hdr *)skb->data; + struct bam_dmux_hdr *hdr = skb_dma->rx_virt ? skb_dma->rx_virt : + (struct bam_dmux_hdr *)skb_dma->skb->data; struct net_device *netdev = dmux->netdevs[hdr->ch]; + struct sk_buff *skb; if (!netdev || !netif_running(netdev)) { dev_warn(dmux->dev, "Data for inactive channel %u\n", hdr->ch); @@ -514,10 +537,18 @@ static void bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma) return; } - skb_dma->skb = NULL; /* Hand over to network stack */ - - skb_pull(skb, sizeof(*hdr)); - skb_trim(skb, hdr->len); + if (skb_dma->rx_virt) { + /* Coherent block is not page-backed: copy out to a real skb */ + skb = netdev_alloc_skb(netdev, hdr->len); + if (!skb) + return; + skb_put_data(skb, (u8 *)skb_dma->rx_virt + sizeof(*hdr), hdr->len); + } else { + skb = skb_dma->skb; + skb_dma->skb = NULL; /* Hand over to network stack */ + skb_pull(skb, sizeof(*hdr)); + skb_trim(skb, hdr->len); + } skb->dev = netdev; /* Only Raw-IP/QMAP is supported by this driver */ @@ -574,10 +605,14 @@ static void bam_dmux_rx_callback(void *data) { struct bam_dmux_skb_dma *skb_dma = data; struct bam_dmux *dmux = skb_dma->dmux; - struct sk_buff *skb = skb_dma->skb; - struct bam_dmux_hdr *hdr = (struct bam_dmux_hdr *)skb->data; + struct bam_dmux_hdr *hdr; - bam_dmux_skb_dma_unmap(skb_dma, DMA_FROM_DEVICE); + if (skb_dma->rx_virt) { + hdr = skb_dma->rx_virt; /* coherent RX: no skb to unmap */ + } else { + bam_dmux_skb_dma_unmap(skb_dma, DMA_FROM_DEVICE); + hdr = (struct bam_dmux_hdr *)skb_dma->skb->data; + } if (hdr->magic != BAM_DMUX_HDR_MAGIC) { dev_err(dmux->dev, "Invalid magic in header: %#x\n", hdr->magic); @@ -644,6 +679,9 @@ static void bam_dmux_free_skbs(struct bam_dmux_skb_dma skbs[], for (i = 0; i < BAM_DMUX_NUM_SKB; i++) { struct bam_dmux_skb_dma *skb_dma = &skbs[i]; + if (skb_dma->rx_virt) /* coherent block freed at remove */ + continue; + if (skb_dma->addr) bam_dmux_skb_dma_unmap(skb_dma, dir); if (skb_dma->skb) { @@ -762,6 +800,71 @@ static int __maybe_unused bam_dmux_runtime_resume(struct device *dev) return 0; } +static int bam_dmux_alloc_coherent_rx(struct bam_dmux *dmux) +{ + struct device *dev = dmux->dev; + const struct bam_dmux_data *data = of_device_get_match_data(dev); + size_t size = BAM_DMUX_NUM_SKB * BAM_DMUX_BUFFER_SIZE; + u64 src = BIT_ULL(QCOM_SCM_VMID_HLOS); + struct qcom_scm_vmperm dst[2]; + int i, ret; + + if (!data) + return 0; + + if (!qcom_scm_is_available()) + return -EPROBE_DEFER; + + dst[0].vmid = QCOM_SCM_VMID_HLOS; + dst[0].perm = QCOM_SCM_PERM_RW; + dst[1].vmid = data->vmid; + dst[1].perm = QCOM_SCM_PERM_RW; + + dmux->rx_buf = dma_alloc_coherent(dev, size, &dmux->rx_buf_dma, GFP_KERNEL); + if (!dmux->rx_buf) + return -ENOMEM; + + for (i = 0; i < BAM_DMUX_NUM_SKB; i++) { + dmux->rx_skbs[i].rx_virt = dmux->rx_buf + i * BAM_DMUX_BUFFER_SIZE; + dmux->rx_skbs[i].addr = dmux->rx_buf_dma + i * BAM_DMUX_BUFFER_SIZE; + } + + ret = qcom_scm_assign_mem(dmux->rx_buf_dma, size, &src, dst, ARRAY_SIZE(dst)); + if (ret) { + dev_err(dev, "SCM assign RX block failed: %d\n", ret); + dma_free_coherent(dev, size, dmux->rx_buf, dmux->rx_buf_dma); + dmux->rx_buf = NULL; + return ret; + } + dmux->rx_buf_perms = src; + + return 0; +} + +static void bam_dmux_free_coherent_rx(struct bam_dmux *dmux) +{ + struct qcom_scm_vmperm hlos = { + .vmid = QCOM_SCM_VMID_HLOS, + .perm = QCOM_SCM_PERM_RW, + }; + size_t size = BAM_DMUX_NUM_SKB * BAM_DMUX_BUFFER_SIZE; + + if (!dmux->rx_buf) + return; + + if (dmux->rx_buf_perms) { + if (qcom_scm_assign_mem(dmux->rx_buf_dma, size, &dmux->rx_buf_perms, + &hlos, 1)) { + dev_err(dmux->dev, "SCM reclaim RX block failed; leaking\n"); + return; + } + dmux->rx_buf_perms = 0; + } + + dma_free_coherent(dmux->dev, size, dmux->rx_buf, dmux->rx_buf_dma); + dmux->rx_buf = NULL; +} + static int bam_dmux_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -809,6 +912,10 @@ static int bam_dmux_probe(struct platform_device *pdev) dmux->tx_skbs[i].dmux = dmux; } + ret = bam_dmux_alloc_coherent_rx(dmux); + if (ret) + return ret; + /* Runtime PM manages our own power vote. * Note that the RX path may be active even if we are runtime suspended, * since it is controlled by the remote side. @@ -845,6 +952,7 @@ static int bam_dmux_probe(struct platform_device *pdev) err_disable_pm: pm_runtime_disable(dev); pm_runtime_dont_use_autosuspend(dev); + bam_dmux_free_coherent_rx(dmux); return ret; } @@ -879,13 +987,19 @@ static void bam_dmux_remove(struct platform_device *pdev) disable_irq(dmux->pc_irq); bam_dmux_power_off(dmux); bam_dmux_free_skbs(dmux->tx_skbs, DMA_TO_DEVICE); + bam_dmux_free_coherent_rx(dmux); } static const struct dev_pm_ops bam_dmux_pm_ops = { SET_RUNTIME_PM_OPS(bam_dmux_runtime_suspend, bam_dmux_runtime_resume, NULL) }; +static const struct bam_dmux_data shikra_data = { + .vmid = QCOM_SCM_VMID_NAV, +}; + static const struct of_device_id bam_dmux_of_match[] = { + { .compatible = "qcom,shikra-bam-dmux", .data = &shikra_data }, { .compatible = "qcom,bam-dmux" }, { /* sentinel */ } }; From d2fd0e91668ccfb52b8ca8914ba0b67763812ee4 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Tue, 14 Jul 2026 10:30:22 +0530 Subject: [PATCH 0956/1133] FROMLIST: dt-bindings: dma: qcom,bam-dma: Add optional qcom,vmid property A SoC can have multiple BAM DMA instances. Some of these BAMs are powered by a remote processor that enforces XPU (eXternal Protection Unit) access control and reads the per-channel descriptor FIFOs as an AXI master under that remote processor's execution environment, so their FIFOs must be accessible to the remote processor's VMID; other BAM instances on the same SoC are not behind such a remote processor and must not have this property set. Add an optional qcom,vmid property listing the destination VMID(s) that the affected BAM instance's descriptor FIFOs must be accessible to. HLOS is always the source owner and must not be listed. Co-developed-by: Deepak Kumar Singh Signed-off-by: Deepak Kumar Singh Signed-off-by: Vishnu Santhosh Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20260714-qcom-bam-dma-vmid-ext-v1-1-cef87c57b7dc@oss.qualcomm.com --- .../devicetree/bindings/dma/qcom,bam-dma.yaml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml b/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml index e72adc172af10..c90d47d4a2543 100644 --- a/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml +++ b/Documentation/devicetree/bindings/dma/qcom,bam-dma.yaml @@ -12,6 +12,15 @@ maintainers: allOf: - $ref: dma-controller.yaml# + - if: + not: + properties: + compatible: + contains: + const: qcom,shikra-bam-dma + then: + properties: + qcom,vmid: false properties: compatible: @@ -29,6 +38,8 @@ properties: - enum: # SDM845, SM6115, SM8150, SM8250 and QCM2290 - qcom,bam-v1.7.4 + # Shikra + - qcom,shikra-bam-dma - const: qcom,bam-v1.7.0 clocks: @@ -81,6 +92,21 @@ properties: Indicates that the bam is powered up by a remote processor but must be initialized by the local processor. + qcom,vmid: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 8 + items: + minimum: 1 + maximum: 63 + description: + Destination VMIDs of the remote processor(s) that read the per-channel + descriptor FIFOs as an AXI master. When present, the driver SCM-assigns + each FIFO to these VMIDs so the remote access does not trigger an XPU + violation. HLOS is always retained as the source owner and must not be + listed. Optional even when the qcom,shikra-bam-dma compatible is + present; not valid on any other compatible in this schema. + reg: maxItems: 1 From 52724a21b1e7866cf738f8ae3805013ab30f5748 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Tue, 14 Jul 2026 10:30:23 +0530 Subject: [PATCH 0957/1133] FROMLIST: dmaengine: qcom: bam_dma: SCM-assign descriptor FIFOs to a remote VMID On Qualcomm SoCs where the BAM is powered by a remote processor that enforces XPU access control (e.g. the mDSP on Shikra, VMID 43 / NAV), the BAM reads the descriptor FIFO as an AXI master under the remote execution environment. Without an SCM grant for the remote VMID, the first descriptor enqueue faults with an XPU violation. Parse the optional qcom,vmid DT property as a list of destination VMIDs. When present, SCM-assign each channel's descriptor FIFO to HLOS plus the listed VMIDs; num_vmids being non-zero is derived purely from qcom,vmid, a board-integration property, not from the per-SoC IP data, and is distinct from qcom,powered-remotely. A BAM with configured VMIDs has two properties that shape the channel lifecycle: 1. The remote firmware owns the BAM's power and reset. It may remove power during error recovery before the driver releases its channels, so any pipe/block register access at teardown can raise a synchronous external abort, and a local reset is redundant as the remote re-initialises the hardware on the next power-on. 2. TZ does not revoke the SCM grant when the remote powers down. A FIFO assigned once stays assigned across every power cycle, and re-assigning or reclaiming it while the remote is mid-teardown is rejected by TZ with -EINVAL. Handle both by keeping the descriptor FIFO as a persistent resource on such BAMs: allocate and SCM-assign it once on the first bam_alloc_chan(), keep it (and its grant) across power cycles, and reclaim it to HLOS and free it only once in bam_dma_remove(). If the final reclaim fails the remote still has access, so the buffer is leaked rather than returned to the page allocator; the source-VMID bitmask stored by qcom_scm_assign_mem() drives that reclaim. bam_free_chan() on such a BAM therefore only drops local channel state (clear ->initialized, decrement active_channels) with no MMIO and no SCM call, so the block and pipe are re-initialised on the next power-on while power is present. The bam_chan_init_hw() pipe reset in bam_dma_terminate_all() is likewise skipped. reclaiming the FIFO is an SCM call, not a register access, so bam_dma_remove() stays safe. Platforms that do not set qcom,vmid keep num_vmids 0, make no SCM call, and leave the alloc/free and register-access paths unchanged. Co-developed-by: Deepak Kumar Singh Signed-off-by: Deepak Kumar Singh Signed-off-by: Vishnu Santhosh Link: https://lore.kernel.org/r/20260714-qcom-bam-dma-vmid-ext-v1-2-cef87c57b7dc@oss.qualcomm.com --- drivers/dma/qcom/Kconfig | 1 + drivers/dma/qcom/bam_dma.c | 197 ++++++++++++++++++++++++++++++++++--- 2 files changed, 182 insertions(+), 16 deletions(-) diff --git a/drivers/dma/qcom/Kconfig b/drivers/dma/qcom/Kconfig index c71b0b5d536bd..8f20b33bce84d 100644 --- a/drivers/dma/qcom/Kconfig +++ b/drivers/dma/qcom/Kconfig @@ -15,6 +15,7 @@ config QCOM_BAM_DMA depends on ARCH_QCOM || (COMPILE_TEST && OF && ARM) select DMA_ENGINE select DMA_VIRTUAL_CHANNELS + select QCOM_SCM help Enable support for the QCOM BAM DMA controller. This controller provides DMA capabilities for a variety of on-chip devices. diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index f67a93a37d48c..0b0f94389c923 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "../dmaengine.h" #include "../virt-dma.h" @@ -389,6 +390,9 @@ struct bam_chan { struct bam_desc_hw *fifo_virt; dma_addr_t fifo_phys; + /* SCM source-VMID bitmask of the FIFO, 0 if not SCM-assigned */ + u64 fifo_src_perms; + /* fifo markers */ unsigned short head; /* start of active descriptor entries */ unsigned short tail; /* end of active descriptor entries */ @@ -423,6 +427,10 @@ struct bam_device { const struct reg_offset_data *layout; + /* destination VMIDs for SCM assignment of descriptor FIFOs */ + u32 *vmids; + int num_vmids; + struct clk *bamclk; int irq; @@ -559,6 +567,126 @@ static void bam_chan_init_hw(struct bam_chan *bchan, bchan->tail = 0; } +/** + * bam_parse_vmids - Parse the optional qcom,vmid property + * @bdev: bam device + * + * Reads the list of destination VMIDs from qcom,vmid, if present. HLOS is + * always the source owner and must not be listed. Absent property leaves + * num_vmids 0. + */ +static int bam_parse_vmids(struct bam_device *bdev) +{ + struct device *dev = bdev->dev; + int n, i, ret; + + n = of_property_count_u32_elems(dev->of_node, "qcom,vmid"); + if (n == -EINVAL) + return 0; + + if (n < 0) + return n; + + if (!qcom_scm_is_available()) + return -EPROBE_DEFER; + + bdev->vmids = devm_kcalloc(dev, n, sizeof(*bdev->vmids), GFP_KERNEL); + if (!bdev->vmids) + return -ENOMEM; + + ret = of_property_read_u32_array(dev->of_node, "qcom,vmid", + bdev->vmids, n); + if (ret) + return ret; + + for (i = 0; i < n; i++) { + if (bdev->vmids[i] == QCOM_SCM_VMID_HLOS) { + dev_err(dev, "qcom,vmid must not include HLOS (%u)\n", + QCOM_SCM_VMID_HLOS); + return -EINVAL; + } + } + + bdev->num_vmids = n; + + return 0; +} + +/** + * bam_assign_fifo - SCM-assign a channel's descriptor FIFO to the remote VMIDs + * @bdev: bam device + * @bchan: bam channel + * + * Grants HLOS plus the configured qcom,vmid VMIDs access to the FIFO, so + * the remote EE can read it. The updated source-VMID bitmask is stored in + * bchan->fifo_src_perms for bam_fifo_can_free() to reverse. + */ +static int bam_assign_fifo(struct bam_device *bdev, struct bam_chan *bchan) +{ + struct qcom_scm_vmperm *dst __free(kfree) = NULL; + u64 src = BIT_ULL(QCOM_SCM_VMID_HLOS); + int i, ret; + + if (!bdev->num_vmids) + return 0; + + dst = kcalloc(bdev->num_vmids + 1, sizeof(*dst), GFP_KERNEL); + if (!dst) + return -ENOMEM; + + dst[0].vmid = QCOM_SCM_VMID_HLOS; + dst[0].perm = QCOM_SCM_PERM_RW; + + for (i = 0; i < bdev->num_vmids; i++) { + dst[i + 1].vmid = bdev->vmids[i]; + dst[i + 1].perm = QCOM_SCM_PERM_RW; + } + + ret = qcom_scm_assign_mem(bchan->fifo_phys, BAM_DESC_FIFO_SIZE, + &src, dst, bdev->num_vmids + 1); + if (ret) { + dev_err(bdev->dev, "SCM assign fifo chan %u failed: %d\n", + bchan->id, ret); + return ret; + } + + bchan->fifo_src_perms = src; + + return 0; +} + +/** + * bam_fifo_can_free - Reclaim a channel's descriptor FIFO to HLOS + * @bdev: bam device + * @bchan: bam channel + * + * Returns true if the FIFO may now be freed. On SCM failure the remote VMID + * still has access, so the caller must leak the buffer instead of freeing it. + */ +static bool bam_fifo_can_free(struct bam_device *bdev, struct bam_chan *bchan) +{ + struct qcom_scm_vmperm hlos = { + .vmid = QCOM_SCM_VMID_HLOS, + .perm = QCOM_SCM_PERM_RW, + }; + int ret; + + if (!bchan->fifo_src_perms) + return true; + + ret = qcom_scm_assign_mem(bchan->fifo_phys, BAM_DESC_FIFO_SIZE, + &bchan->fifo_src_perms, &hlos, 1); + if (ret) { + dev_err(bdev->dev, "SCM reclaim fifo chan %u failed: %d; leaking\n", + bchan->id, ret); + return false; + } + + bchan->fifo_src_perms = 0; + + return true; +} + /** * bam_alloc_chan - Allocate channel resources for DMA channel. * @chan: specified channel @@ -570,16 +698,29 @@ static int bam_alloc_chan(struct dma_chan *chan) struct bam_chan *bchan = to_bam_chan(chan); struct bam_device *bdev = bchan->bdev; - if (bchan->fifo_virt) - return 0; - - /* allocate FIFO descriptor space, but only if necessary */ - bchan->fifo_virt = dma_alloc_wc(bdev->dev, BAM_DESC_FIFO_SIZE, - &bchan->fifo_phys, GFP_KERNEL); - + /* + * Remote-owned BAMs keep the FIFO allocated and SCM-assigned to the + * remote VMID across power cycles (see bam_free_chan), so allocate and + * assign it only once; the block and pipe are still re-initialised on + * every power-on below. + */ if (!bchan->fifo_virt) { - dev_err(bdev->dev, "Failed to allocate desc fifo\n"); - return -ENOMEM; + /* allocate FIFO descriptor space, but only if necessary */ + bchan->fifo_virt = dma_alloc_wc(bdev->dev, BAM_DESC_FIFO_SIZE, + &bchan->fifo_phys, GFP_KERNEL); + if (!bchan->fifo_virt) { + dev_err(bdev->dev, "Failed to allocate desc fifo\n"); + return -ENOMEM; + } + + if (bam_assign_fifo(bdev, bchan)) { + dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, + bchan->fifo_virt, bchan->fifo_phys); + bchan->fifo_virt = NULL; + return -EIO; + } + } else if (!bdev->num_vmids) { + return 0; } if (bdev->active_channels++ == 0 && bdev->powered_remotely) @@ -613,12 +754,29 @@ static void bam_free_chan(struct dma_chan *chan) goto err; } + /* + * Remote-owned BAMs (qcom,vmid) keep the descriptor FIFO allocated and + * SCM-assigned across power cycles: the remote may already have cut + * power, so pipe-register access would fault, and TZ still holds the + * grant for the next restart (the FIFO is reclaimed and freed once in + * bam_dma_remove). Only drop local channel state here so the block and + * pipe are re-initialised on the next power-on; skip all MMIO. + */ + if (bdev->num_vmids) { + scoped_guard(spinlock_irqsave, &bchan->vc.lock) + bchan->initialized = 0; + bdev->active_channels--; + goto err; + } + scoped_guard(spinlock_irqsave, &bchan->vc.lock) bam_reset_channel(bchan); - dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, bchan->fifo_virt, - bchan->fifo_phys); + if (bam_fifo_can_free(bdev, bchan)) + dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, + bchan->fifo_virt, bchan->fifo_phys); bchan->fifo_virt = NULL; + bdev->active_channels--; /* mask irq for pipe/channel */ val = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE)); @@ -628,7 +786,7 @@ static void bam_free_chan(struct dma_chan *chan) /* disable irq */ writel_relaxed(0, bam_addr(bdev, bchan->id, BAM_P_IRQ_EN)); - if (--bdev->active_channels == 0 && bdev->powered_remotely) { + if (bdev->active_channels == 0 && bdev->powered_remotely) { /* s/w reset bam */ val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL)); val |= BAM_SW_RST; @@ -767,7 +925,9 @@ static int bam_dma_terminate_all(struct dma_chan *chan) if (!list_empty(&bchan->desc_list)) { async_desc = list_first_entry(&bchan->desc_list, struct bam_async_desc, desc_node); - bam_chan_init_hw(bchan, async_desc->dir); + /* Remote-owned BAM: pipe reset may fault, skip it. */ + if (!bchan->bdev->num_vmids) + bam_chan_init_hw(bchan, async_desc->dir); } list_for_each_entry_safe(async_desc, tmp, @@ -1282,6 +1442,10 @@ static int bam_dma_probe(struct platform_device *pdev) bdev->powered_remotely = of_property_read_bool(pdev->dev.of_node, "qcom,powered-remotely"); + ret = bam_parse_vmids(bdev); + if (ret) + return ret; + if (bdev->controlled_remotely || bdev->powered_remotely) bdev->bamclk = devm_clk_get_optional(bdev->dev, "bam_clk"); else @@ -1421,9 +1585,10 @@ static void bam_dma_remove(struct platform_device *pdev) if (!bdev->channels[i].fifo_virt) continue; - dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, - bdev->channels[i].fifo_virt, - bdev->channels[i].fifo_phys); + if (bam_fifo_can_free(bdev, &bdev->channels[i])) + dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, + bdev->channels[i].fifo_virt, + bdev->channels[i].fifo_phys); } tasklet_kill(&bdev->task); From 98c1ae6a40e58c4703396b78d3fc86b68655d20b Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Thu, 15 Oct 2026 14:45:28 +0530 Subject: [PATCH 0958/1133] FROMLIST: arm64: dts: qcom: shikra-iqs-evk: Add LT9611UXD HDMI bridge support Enable the Shikra MDSS display subsystem on the Qualcomm Shikra IQS EVK board and add the Lontium LT9611UXD DSI-to-HDMI bridge node. The LT9611UXD is connected via I2C (bus 4, address 0x41), powered by a GPIO-controlled 3.3V regulator (PM8150 GPIO4) and an always-on 1.8V rail. Reset is on GPIO76 and interrupt on GPIO85. The bridge receives DSI output from MDSS and drives an HDMI-A connector, with the link wired as: DPU -> DSI0 -> LT9611UXD -> HDMI. Regulator and pinctrl labels use generic board-level names (vreg_disp_3p3, bridge_irq_pin, bridge_rst_pin) to decouple them from the bridge chip. Signed-off-by: Mohit Dsor Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20261015-shikra-work-v5-1-5e075222b60a@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 109 ++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index f7993407b8b47..e6caba5030979 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -8,6 +8,7 @@ #include "shikra-iqs-som.dtsi" #include "shikra-evk.dtsi" #include +#include / { model = "Qualcomm Technologies, Inc. Shikra IQS EVK"; @@ -23,6 +24,98 @@ chosen { stdout-path = "serial0:115200n8"; }; + + hdmi_connector: hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <&hdmi_connector_out>; + }; + }; + }; + + vreg_disp_3p3: regulator-disp-3p3 { + compatible = "regulator-fixed"; + regulator-name = "vreg_disp_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pm8150_gpios 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&lcd_bias_en>; + pinctrl-names = "default"; + }; +}; + +&i2c4 { + status = "okay"; + + hdmi_bridge: hdmi-bridge@41 { + compatible = "lontium,lt9611uxd"; + reg = <0x41>; + interrupts-extended = <&tlmm 85 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&tlmm 76 GPIO_ACTIVE_LOW>; + vcc-supply = <&vreg_disp_3p3>; + vdd-supply = <&pm8150_s4>; + + pinctrl-0 = <&bridge_rst_pin &bridge_irq_pin>; + pinctrl-names = "default"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + bridge_dsi_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + hdmi_connector_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm8150_l11>; + + status = "okay"; +}; + +&mdss_dsi0_out { + remote-endpoint = <&bridge_dsi_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; +}; + +&pm8150_gpios { + lcd_bias_en: lcd-bias-en-state { + pins = "gpio4"; + function = PMIC_GPIO_FUNC_NORMAL; + bias-disable; + }; +}; + +&pm8150_l11 { + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1232000>; + regulator-allow-set-load; }; &pcie_phy { @@ -74,6 +167,22 @@ status = "okay"; }; +&tlmm { + bridge_rst_pin: bridge-rst-state { + pins = "gpio76"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + bridge_irq_pin: bridge-irq-state { + pins = "gpio85"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; + &usb_1_hsphy { vdd-supply = <&pm8150_l4>; vdda-pll-supply = <&pm8150_l12>; From 12c46197cd95dd98090ccabb9fb41bef8d3ae913 Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Thu, 15 Oct 2026 14:45:29 +0530 Subject: [PATCH 0959/1133] FROMLIST: arm64: defconfig: Enable LT9611C bridge driver Enable the Lontium LT9611C(EX/UXD) DSI-to-HDMI bridge driver as a module. The LT9611C family supports single or dual MIPI DSI input and outputs HDMI, and is used on multiple ARM64 platforms. Reviewed-by: Dmitry Baryshkov Signed-off-by: Mohit Dsor Link: https://lore.kernel.org/r/20261015-shikra-work-v5-2-5e075222b60a@oss.qualcomm.com --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 0ba04a6b7381f..c05e97be90ee4 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -980,6 +980,7 @@ CONFIG_DRM_I2C_NXP_TDA998X=m CONFIG_DRM_ITE_IT6263=m CONFIG_DRM_LONTIUM_LT8912B=m CONFIG_DRM_LONTIUM_LT9611=m +CONFIG_DRM_LONTIUM_LT9611C=m CONFIG_DRM_LONTIUM_LT9611UXC=m CONFIG_DRM_LONTIUM_LT8713SX=m CONFIG_DRM_ITE_IT66121=m From 7539bb96d1e2d936d125ffb0636fb7995f6a0d58 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Sun, 20 Sep 2026 08:58:15 +0530 Subject: [PATCH 0960/1133] FROMLIST: arm64: dts: qcom: shikra: Add BAM-DMUX support Add the SMSM state entries, BAM-DMUX node, and BAM DMA controller needed to provide modem data channels on Shikra. Reserve a 256 KiB restricted DMA pool and reference it from both the BAM-DMUX and BAM DMA nodes. Set qcom,vmid to NAV so the BAM-DMUX driver can grant the modem access to the complete pool before requesting the DMA channels. The 256 KiB pool provides space for BAM-DMUX RX and TX buffers and BAM descriptor FIFOs, with additional headroom. Place the BAM-DMUX node below the modem remoteproc so userspace can associate the resulting network interfaces with the owning remoteproc through the device hierarchy. Co-developed-by: Deepak Kumar Singh Signed-off-by: Deepak Kumar Singh Signed-off-by: Vishnu Santhosh Link: https://lore.kernel.org/r/20260920-qcom-shikra-dts-bam-dmux-v3-1-91474d507d61@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra.dtsi | 51 ++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 3df542f35dd0b..b41157279763c 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -452,6 +453,13 @@ #size-cells = <2>; ranges; + bam_dmux_pool: restricted-dma-pool { + compatible = "restricted-dma-pool"; + size = <0x0 0x40000>; + alignment = <0x0 0x40000>; + alloc-ranges = <0x0 0x80000000 0x0 0x80000000>; + }; + hyp_mem: hyp@80000000 { reg = <0x0 0x80000000 0x0 0x1600000>; no-map; @@ -600,6 +608,23 @@ }; }; + smsm { + compatible = "qcom,smsm"; + #address-cells = <1>; + #size-cells = <0>; + mboxes = <0>, <&apcs_glb 13>; + apps_smsm: apps@0 { + reg = <0>; + #qcom,smem-state-cells = <1>; + }; + modem_smsm: modem@1 { + reg = <1>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + soc: soc@0 { compatible = "simple-bus"; @@ -2550,6 +2575,20 @@ qcom,remote-pid = <1>; label = "mpss"; }; + + bam_dmux: bam-dmux { + compatible = "qcom,bam-dmux"; + interrupt-parent = <&modem_smsm>; + interrupts = <1 IRQ_TYPE_EDGE_BOTH>, + <11 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "pc", "pc-ack"; + qcom,smem-states = <&apps_smsm 1>, <&apps_smsm 11>; + qcom,smem-state-names = "pc", "pc-ack"; + dmas = <&bam_dmux_dma 4>, <&bam_dmux_dma 5>; + dma-names = "tx", "rx"; + memory-region = <&bam_dmux_pool>; + qcom,vmid = ; + }; }; remoteproc_cdsp: remoteproc@b300000 { @@ -4440,6 +4479,18 @@ #reset-cells = <1>; }; + bam_dmux_dma: dma-controller@6044000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x0 0x06044000 0x0 0x19000>; + interrupts = ; + #dma-cells = <1>; + qcom,ee = <0>; + num-channels = <6>; + qcom,num-ees = <1>; + qcom,powered-remotely; + memory-region = <&bam_dmux_pool>; + }; + sram@c11e000 { compatible = "qcom,shikra-imem", "mmio-sram"; reg = <0x0 0x0c11e000 0x0 0x1000>; From 983bdc3a6d3dad22e7b33f5e6ec3681eb9fe6a0f Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Fri, 22 May 2026 18:13:59 +0530 Subject: [PATCH 0961/1133] PENDING: arm64: dts: qcom: shikra: add reboot-mode support Add reboot-mode child nodes to shikra-evk.dtsi to configure fastboot (mode-bootloader) and EDL (mode-edl) reboot modes, since all EVK board DTS files include this shared DTSI. Signed-off-by: Anurag Pateriya --- arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 7 +++++++ arch/arm64/boot/dts/qcom/shikra.dtsi | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi index 6511ac6ec9889..1991186ed4353 100644 --- a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi @@ -147,6 +147,13 @@ }; }; +&psci { + reboot-mode { + mode-bootloader = <0x10001 0x2>; + mode-edl = <0 0x1>; + }; +}; + &qupv3_0 { firmware-name = "qcom/shikra/qupv3fw.elf"; diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index b41157279763c..46658328e98bf 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -359,7 +359,7 @@ interrupts = ; }; - psci { + psci: psci { compatible = "arm,psci-1.0"; method = "smc"; }; From 12a59b2dc17c1a8067c8441131854df54e3f6966 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Tue, 14 Jul 2026 14:01:53 +0530 Subject: [PATCH 0962/1133] FROMLIST: arm64: dts: qcom: shikra: Add qcom,vmid to BAM-DMA node On the Qualcomm Shikra SoC the mDSP (VMID 43 / QCOM_SCM_VMID_NAV) is the AXI master for BAM descriptor FIFO accesses. The XPU enforces per-region access control; without an SCM assignment granting NAV access, the first DMA transfer triggers an XPU violation. Add qcom,vmid = to the bam_dmux_dma controller node so bam_dma SCM-assigns each channel descriptor FIFO at allocation. BAM-DMUX itself is a singleton and no longer needs a DT property for its destination VMID: the driver now selects QCOM_SCM_VMID_NAV internally via the qcom,shikra-bam-dmux compatible's match data. Co-developed-by: Deepak Kumar Singh Signed-off-by: Deepak Kumar Singh Signed-off-by: Vishnu Santhosh Link: https://lore.kernel.org/r/20260714-b4-qcom-shikra-dts-bam-dmux-vmid-ext-v1-1-5b19da8d7735@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 46658328e98bf..6b9b700f2132b 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -2577,7 +2577,7 @@ }; bam_dmux: bam-dmux { - compatible = "qcom,bam-dmux"; + compatible = "qcom,shikra-bam-dmux", "qcom,bam-dmux"; interrupt-parent = <&modem_smsm>; interrupts = <1 IRQ_TYPE_EDGE_BOTH>, <11 IRQ_TYPE_EDGE_BOTH>; @@ -4480,7 +4480,7 @@ }; bam_dmux_dma: dma-controller@6044000 { - compatible = "qcom,bam-v1.7.0"; + compatible = "qcom,shikra-bam-dma", "qcom,bam-v1.7.0"; reg = <0x0 0x06044000 0x0 0x19000>; interrupts = ; #dma-cells = <1>; @@ -4489,6 +4489,7 @@ qcom,num-ees = <1>; qcom,powered-remotely; memory-region = <&bam_dmux_pool>; + qcom,vmid = ; }; sram@c11e000 { From 1ba3c1c539a4385c43cb7c29d6a44c202b31cfe4 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 11 Jun 2026 20:45:51 +0530 Subject: [PATCH 0963/1133] FROMLIST: arm64: defconfig: Enable Qualcomm QAIF and WSA885X-I2C drivers Enable the QAIF CPU DAI and WSA885X I2C codec as modules in arm64 defconfig. These options are required to exercise the Shikra EVK audio paths enabled by the preceding DTS changes. Link: https://lore.kernel.org/all/20260616201315.2565115-9-mohammad.rafi.shaik@oss.qualcomm.com/ Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/configs/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index c05e97be90ee4..f592d1d1d52f0 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1121,6 +1121,7 @@ CONFIG_SND_SOC_QCOM=m CONFIG_SND_SOC_APQ8016_SBC=m CONFIG_SND_SOC_QDSP6_USB=m CONFIG_SND_SOC_MSM8996=m +CONFIG_SND_SOC_QCOM_QAIF=m CONFIG_SND_SOC_SDM845=m CONFIG_SND_SOC_SM8250=m CONFIG_SND_SOC_SC8280XP=m @@ -1199,6 +1200,7 @@ CONFIG_SND_SOC_WM8978=m CONFIG_SND_SOC_WSA881X=m CONFIG_SND_SOC_WSA883X=m CONFIG_SND_SOC_WSA884X=m +CONFIG_SND_SOC_WSA885X=m CONFIG_SND_SOC_NAU8822=m CONFIG_SND_SOC_LPASS_WSA_MACRO=m CONFIG_SND_SOC_LPASS_VA_MACRO=m From 5d2b88a635a172e9bc18f067df50d59ea0ef21a8 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 24 Aug 2026 23:48:39 +0530 Subject: [PATCH 0964/1133] FROMLIST: arm64: defconfig: Enable Qualcomm PM4125 audio codec as module Enable the Qualcomm PM4125 audio codec as a loadable module, as it is now required on the Shikra evk platform. Link: https://lore.kernel.org/all/20260620070442.3908242-1-mohammad.rafi.shaik@oss.qualcomm.com/ Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index f592d1d1d52f0..9730ceec4f210 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1178,6 +1178,7 @@ CONFIG_SND_SOC_GTM601=m CONFIG_SND_SOC_MAX98090=m CONFIG_SND_SOC_MSM8916_WCD_ANALOG=m CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m +CONFIG_SND_SOC_PM4125_SDW=m CONFIG_SND_SOC_RK3308=m CONFIG_SND_SOC_RK817=m CONFIG_SND_SOC_RT5640=m From 73eb6578ad83a4dc0e19dc12eb91f131647d8c95 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 01:53:13 +0530 Subject: [PATCH 0965/1133] FROMLIST: dt-bindings: net: ti,dp83867: add supply properties The DP83867 PHY has four distinct power supplies: VDDA2P5 -- 2.5V analog supply VDD1P0 -- 1.0V digital supply VDDA1P8 -- 1.8V analog supply VDDIO -- I/O supply, which can be 3.3V or 2.5V or 1.8V The DP83867E/IS/CS datasheet (section 8.3) describes two power supply configurations - "two-supply" and "three-supply". 1. Two-Supply Configuration: VDDA2P5 and VDD1P0 connected, and the VDDA1P8 pins are left unconnected. 2. Three-Supply Configuration: VDDA2P5, VDD1P0 and VDDA1P8 are all connected. VDDIO is a separate fourth supply present in both configurations. The datasheet specifies that it can either be 1.8V or 2.5V or 3.3V. Some embedded board design expose a GPIO-controlled regulator to control any one or more of these supplies. Therefore, document all four of the available supply properties. Link: https://lore.kernel.org/netdev/20260908-shikra_ethernet-v2-1-bbe3389d0652@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- .../devicetree/bindings/net/ti,dp83867.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/net/ti,dp83867.yaml b/Documentation/devicetree/bindings/net/ti,dp83867.yaml index 4bc1f98fd9fe5..e78f08ded3d0d 100644 --- a/Documentation/devicetree/bindings/net/ti,dp83867.yaml +++ b/Documentation/devicetree/bindings/net/ti,dp83867.yaml @@ -118,6 +118,20 @@ properties: Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h for applicable values. + vdda-2p5-supply: + description: 2.5V analog supply (connected to the VDDA2P5 pins). + + vdd-1p0-supply: + description: 1.0V digital core supply (connected to the VDD1P0 pins). + + vdda-1p8-supply: + description: 1.8V analog supply (connected to the VDDA1P8 pins). + + vddio-supply: + description: | + I/O supply (connected to the VDDIO pins). The supply can be 1.8V, + 2.5V or 3.3V. + required: - reg From d1846e3b26225d202344c6b216abc1d7d52eeb4c Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 01:53:14 +0530 Subject: [PATCH 0966/1133] FROMLIST: net: phy: dp83867: add regulator supply management Some embedded board designs use GPIO-controlled regulators for the DP83867 power rails. Add dp83867_power_on() to enable all four supply domains at probe time. Absent supplies are silently skipped, so boards that do not describe them are unaffected. When any supply is newly enabled the driver sleeps for 200 ms before returning. This satisfies the post power-up stabilisation requirement mentioned in section 6.6 of the DP83867E/IS/CS datasheet. Link: https://lore.kernel.org/all/20261017-shikra_ethernet-v3-1-26a8beb44b8f@oss.qualcomm.com Signed-off-by: Mohd Ayaan Anwar --- drivers/net/phy/dp83867.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index a3cd5cb11ea0a..ed2aa7da7c387 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -730,11 +731,42 @@ static int dp83867_resume(struct phy_device *phydev) return 0; } +static int dp83867_power_on(struct phy_device *phydev) +{ +#ifdef CONFIG_OF + static const char * const supply_names[] = { + "vdda-2p5", "vdd-1p0", "vdda-1p8", "vddio", + }; + struct device *dev = &phydev->mdio.dev; + u32 count = 0; + int i, ret; + + for (i = 0; i < ARRAY_SIZE(supply_names); i++) { + ret = devm_regulator_get_enable_optional(dev, supply_names[i]); + if (!ret) + count++; + else if (ret != -ENODEV) + return dev_err_probe(dev, ret, + "failed to enable %s supply\n", + supply_names[i]); + } + + /* Datasheet section 6.6 suggests a 200ms post power-up stabilization */ + if (count) + fsleep(200000); +#endif + return 0; +} + static int dp83867_probe(struct phy_device *phydev) { struct dp83867_private *dp83867; int ret; + ret = dp83867_power_on(phydev); + if (ret) + return ret; + dp83867 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83867), GFP_KERNEL); if (!dp83867) From 22bc67147f2b0d06d13718fe55618641e018829d Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 16:11:50 +0530 Subject: [PATCH 0967/1133] FROMLIST: arm64: dts: qcom: shikra-iqs-som: fix GPIO138 reservation The GPIO mappings on the IQS variant differ from the CQ variants. GPIO138 is connected to the RGMII1_RX_CTL pin rather than the NFC ESE Secure IO pin; the latter is connected to GPIO49. This incorrect reservation causes the probe of the second Ethernet port to fail: shikra-tlmm 500000.pinctrl: error -EINVAL: pin-138 (5d20000.ethernet) shikra-tlmm 500000.pinctrl: error -EINVAL: could not request pin 138 (GPIO_138) from group gpio138 on device 500000.pinctrl qcom-ethqos 5d20000.ethernet: Error applying setting, reverse things back Replace gpio138 with gpio49 in the reserved list. Link: https://lore.kernel.org/linux-arm-msm/20260908-shikra_ethernet_dts-v1-1-69c0c5c7c124@oss.qualcomm.com/ Fixes: 779aead2dace ("arm64: dts: qcom: shikra: Add gpio-reserved-ranges to tlmm") Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi index ebc3052d57a99..9f5818e351ef1 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi @@ -333,7 +333,7 @@ &tlmm { gpio-reserved-ranges = <6 4>, /* Fingerprint SPI */ <30 2>, /* NFC SPI */ - <138 1>, /* NFC Secure IO */ + <49 1>, /* NFC Secure IO */ <155 11>; /* eMMC Boot */ sw_ctrl_default: sw-ctrl-default-state { From 3c57d3766ba64a62a2a8b7e4b65d8c32ca71b061 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 16:18:43 +0530 Subject: [PATCH 0968/1133] FROMLIST: arm64: dts: qcom: shikra: add ethernet nodes Add the two Gigabit Ethernet controllers present on Shikra (ethernet0 at 0x5d00000, ethernet1 at 0x5d20000). Both nodes are left disabled; board files supply the PHY details. Link: https://lore.kernel.org/linux-arm-msm/20260908-shikra_ethernet_dts-v1-2-69c0c5c7c124@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/shikra.dtsi | 266 +++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 6b9b700f2132b..61df194840079 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -659,6 +659,56 @@ gpio-ranges = <&tlmm 0 0 165>; wakeup-parent = <&mpm>; + ethernet0_default: ethernet0-default-state { + rgmii-rx-pins { + pins = "gpio121", "gpio122", "gpio123", + "gpio124", "gpio125", "gpio126"; + function = "rgmii"; + drive-strength = <16>; + bias-disable; + }; + + rgmii-tx-pins { + pins = "gpio127", "gpio128", "gpio129", + "gpio130", "gpio131", "gpio132"; + function = "rgmii"; + drive-strength = <16>; + bias-pull-up; + }; + + rgmii-mdio-pins { + pins = "gpio133", "gpio134"; + function = "rgmii"; + drive-strength = <16>; + bias-pull-up; + }; + }; + + ethernet1_default: ethernet1-default-state { + rgmii-rx-pins { + pins = "gpio137", "gpio138", "gpio139", + "gpio140", "gpio141", "gpio142"; + function = "rgmii"; + drive-strength = <16>; + bias-disable; + }; + + rgmii-tx-pins { + pins = "gpio143", "gpio144", "gpio145", + "gpio146", "gpio147", "gpio148"; + function = "rgmii"; + drive-strength = <16>; + bias-pull-up; + }; + + rgmii-mdio-pins { + pins = "gpio149", "gpio150"; + function = "rgmii"; + drive-strength = <16>; + bias-pull-up; + }; + }; + qup_i2c0_data_clk: qup-i2c0-data-clk-state { /* SDA, SCL */ pins = "gpio2", "gpio3"; @@ -2537,6 +2587,222 @@ }; }; + ethernet0: ethernet@5d00000 { + compatible = "qcom,shikra-ethqos"; + reg = <0x0 0x05d00000 0x0 0x10000>, + <0x0 0x05d16000 0x0 0x100>; + reg-names = "stmmaceth", "rgmii"; + + interrupts = ; + interrupt-names = "macirq"; + + clocks = <&gcc GCC_EMAC0_AXI_CLK>, + <&gcc GCC_EMAC0_AHB_CLK>, + <&gcc GCC_EMAC0_PTP_CLK>, + <&gcc GCC_EMAC0_RGMII_CLK>, + <&gcc GCC_EMAC0_AXI_SYS_NOC_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>; + clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii", + "axi-noc", "pcie-tile-axi-noc"; + + power-domains = <&gcc GCC_EMAC0_GDSC>; + resets = <&gcc GCC_EMAC0_BCR>; + iommus = <&apps_smmu 0x0380 0x0007>; + + interconnects = <&mem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_EMAC0_CFG QCOM_ICC_TAG_ALWAYS>, + <&system_noc MASTER_EMAC_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-mac", "mac-mem"; + + operating-points-v2 = <&emac0_opp_table>; + + snps,tso; + snps,pbl = <32>; + rx-fifo-depth = <16384>; + tx-fifo-depth = <16384>; + + snps,mtl-rx-config = <&emac0_mtl_rx_setup>; + snps,mtl-tx-config = <&emac0_mtl_tx_setup>; + + status = "disabled"; + + emac0_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-120000000 { + opp-hz = /bits/ 64 <120000000>; + required-opps = <&rpmpd_opp_svs>; + }; + }; + + emac0_mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + emac0_mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; + }; + + ethernet1: ethernet@5d20000 { + compatible = "qcom,shikra-ethqos"; + reg = <0x0 0x05d20000 0x0 0x10000>, + <0x0 0x05d36000 0x0 0x100>; + reg-names = "stmmaceth", "rgmii"; + + interrupts = ; + interrupt-names = "macirq"; + + clocks = <&gcc GCC_EMAC1_AXI_CLK>, + <&gcc GCC_EMAC1_AHB_CLK>, + <&gcc GCC_EMAC1_PTP_CLK>, + <&gcc GCC_EMAC1_RGMII_CLK>, + <&gcc GCC_EMAC1_AXI_SYS_NOC_CLK>, + <&gcc GCC_PCIE_TILE_AXI_SYS_NOC_CLK>; + clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii", + "axi-noc", "pcie-tile-axi-noc"; + + power-domains = <&gcc GCC_EMAC1_GDSC>; + resets = <&gcc GCC_EMAC1_BCR>; + iommus = <&apps_smmu 0x03a0 0x0007>; + + interconnects = <&mem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_EMAC1_CFG QCOM_ICC_TAG_ALWAYS>, + <&system_noc MASTER_EMAC_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-mac", "mac-mem"; + + operating-points-v2 = <&emac1_opp_table>; + + snps,tso; + snps,pbl = <32>; + rx-fifo-depth = <16384>; + tx-fifo-depth = <16384>; + + snps,mtl-rx-config = <&emac1_mtl_rx_setup>; + snps,mtl-tx-config = <&emac1_mtl_tx_setup>; + + status = "disabled"; + + emac1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-120000000 { + opp-hz = /bits/ 64 <120000000>; + required-opps = <&rpmpd_opp_svs>; + }; + }; + + emac1_mtl_rx_setup: rx-queues-config { + snps,rx-queues-to-use = <4>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + snps,priority = <0x1>; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + }; + + emac1_mtl_tx_setup: tx-queues-config { + snps,tx-queues-to-use = <4>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + + queue3 { + snps,avb-algorithm; + snps,send_slope = <0x1000>; + snps,idle_slope = <0x1000>; + snps,high_credit = <0x3e800>; + snps,low_credit = <0xffc18000>; + }; + }; + }; + remoteproc_mpss: remoteproc@6080000 { compatible = "qcom,shikra-mpss-pas"; reg = <0x0 0x06080000 0x0 0x100>; From c2ab54808e4f954dffb0f6aecc3ba802ed216ea0 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 16:20:51 +0530 Subject: [PATCH 0969/1133] FROMLIST: arm64: dts: qcom: shikra-cqm-evk: enable the first Ethernet port Enable ethernet0 for the Shikra CQM EVK board with its DP83867 RGMII PHY. The PHY is powered on using a GPIO-controlled 2.5V regulator. Link: https://lore.kernel.org/linux-arm-msm/20260908-shikra_ethernet_dts-v1-3-69c0c5c7c124@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 76bfe94db25b4..759091a87c265 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -33,6 +33,17 @@ pinctrl-names = "default"; }; + rgmii_phy_supply: regulator-rgmii-phy { + compatible = "regulator-fixed"; + regulator-name = "rgmii-phy-pwr"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + gpio = <&tlmm 149 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&rgmii_phy_pwr_default>; + pinctrl-names = "default"; + }; + vreg_disp_n: regulator-vreg-disp-n { compatible = "regulator-fixed"; regulator-name = "vreg_disp_n"; @@ -61,6 +72,31 @@ status = "okay"; }; +ðernet0 { + phy-handle = <&rgmii_phy>; + phy-mode = "rgmii-id"; + + pinctrl-0 = <ðernet0_default>; + pinctrl-names = "default"; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rgmii_phy: ethernet-phy@7 { + compatible = "ethernet-phy-id2000.a231"; + reg = <0x7>; + reset-gpios = <&tlmm 135 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + vdda-2p5-supply = <&rgmii_phy_supply>; + }; + }; +}; + &mdss { status = "okay"; }; @@ -194,6 +230,14 @@ drive-strength = <2>; bias-disable; }; + + rgmii_phy_pwr_default: rgmii-phy-pwr-default-state { + pins = "gpio149"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + output-low; + }; }; &usb_1 { From 50a94f10a625135fea76c3c6a42e709e34b59c72 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 16:22:48 +0530 Subject: [PATCH 0970/1133] FROMLIST: arm64: dts: qcom: shikra-cqs-evk: enable the first Ethernet port Enable ethernet0 for the Shikra CQS EVK board with its DP83867 RGMII PHY. The PHY is powered on using a GPIO-controlled 2.5V regulator. Link: https://lore.kernel.org/linux-arm-msm/20260908-shikra_ethernet_dts-v1-4-69c0c5c7c124@oss.qualcomm.com/ Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 794d9e69de07b..90e75a62a7ef8 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -33,6 +33,17 @@ pinctrl-names = "default"; }; + rgmii_phy_supply: regulator-rgmii-phy { + compatible = "regulator-fixed"; + regulator-name = "rgmii-phy-pwr"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + gpio = <&tlmm 149 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&rgmii_phy_pwr_default>; + pinctrl-names = "default"; + }; + vreg_disp_n: regulator-vreg-disp-n { compatible = "regulator-fixed"; regulator-name = "vreg_disp_n"; @@ -57,6 +68,31 @@ }; }; +ðernet0 { + phy-handle = <&rgmii_phy>; + phy-mode = "rgmii-id"; + + pinctrl-0 = <ðernet0_default>; + pinctrl-names = "default"; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rgmii_phy: ethernet-phy@7 { + compatible = "ethernet-phy-id2000.a231"; + reg = <0x7>; + reset-gpios = <&tlmm 135 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + vdda-2p5-supply = <&rgmii_phy_supply>; + }; + }; +}; + &mdss { status = "okay"; }; @@ -190,6 +226,14 @@ drive-strength = <2>; bias-disable; }; + + rgmii_phy_pwr_default: rgmii-phy-pwr-default-state { + pins = "gpio149"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + output-low; + }; }; &usb_1 { From b007edde5cc07a17b23a03ec4a012ef9c2ed9b5c Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Tue, 8 Sep 2026 16:25:06 +0530 Subject: [PATCH 0971/1133] FROMLIST: arm64: dts: qcom: shikra-iqs-evk: enable both Ethernet ports Enable ethernet0 and ethernet1 on the IQS EVK with their respective TI DP83867 RGMII PHYs. Both PHYs are powered by GPIO-controlled 2.5V regulators. Link: https://lore.kernel.org/linux-arm-msm/20260908-shikra_ethernet_dts-v1-5-69c0c5c7c124@oss.qualcomm.com Signed-off-by: Mohd Ayaan Anwar --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 87 +++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index e6caba5030979..74da9ef6459fa 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -44,10 +44,81 @@ gpio = <&pm8150_gpios 4 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-0 = <&lcd_bias_en>; + }; + + rgmii_phy0_supply: regulator-rgmii-phy0 { + compatible = "regulator-fixed"; + regulator-name = "rgmii-phy0-pwr"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + gpio = <&tlmm 66 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&rgmii_phy0_pwr_default>; + pinctrl-names = "default"; + }; + + rgmii_phy1_supply: regulator-rgmii-phy1 { + compatible = "regulator-fixed"; + regulator-name = "rgmii-phy1-pwr"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + gpio = <&tlmm 53 GPIO_ACTIVE_HIGH>; + enable-active-high; + pinctrl-0 = <&rgmii_phy1_pwr_default>; pinctrl-names = "default"; }; }; +ðernet0 { + phy-handle = <&rgmii_phy0>; + phy-mode = "rgmii-id"; + + pinctrl-0 = <ðernet0_default>; + pinctrl-names = "default"; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rgmii_phy0: ethernet-phy@7 { + compatible = "ethernet-phy-id2000.a231"; + reg = <0x7>; + reset-gpios = <&tlmm 135 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + vdda-2p5-supply = <&rgmii_phy0_supply>; + }; + }; +}; + +ðernet1 { + phy-handle = <&rgmii_phy1>; + phy-mode = "rgmii-id"; + + pinctrl-0 = <ðernet1_default>; + pinctrl-names = "default"; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rgmii_phy1: ethernet-phy@7 { + compatible = "ethernet-phy-id2000.a231"; + reg = <0x7>; + reset-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + vdda-2p5-supply = <&rgmii_phy1_supply>; + }; + }; +}; + &i2c4 { status = "okay"; @@ -181,6 +252,22 @@ drive-strength = <2>; bias-disable; }; + + rgmii_phy0_pwr_default: rgmii-phy0-pwr-default-state { + pins = "gpio66"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + output-low; + }; + + rgmii_phy1_pwr_default: rgmii-phy1-pwr-default-state { + pins = "gpio53"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + output-low; + }; }; &usb_1_hsphy { From c67696e8e66579ff6c8ea32719b8c0e80cb9f202 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Mon, 7 Sep 2026 17:33:36 +0530 Subject: [PATCH 0972/1133] FROMLIST: dt-bindings: crypto: Adjust Shikra compatible hierarchy Shikra reuses the same QCE integration as Agatti and should follow the corresponding binding requirements too. Move the Shikra compatible to the appropriate binding hierarchy (matching qcom,qcm2290-qce) to reflect the underlying hardware description. Fixes: 45834ff95a6f ("dt-bindings: crypto: qcom-qce: Document the Shikra crypto engine") Signed-off-by: Kuldeep Singh Link: https://lore.kernel.org/linux-arm-msm/20260907-b4-shikra_crypto_changse-v6-1-0676f61894b3@oss.qualcomm.com/ Signed-off-by: Roopak Houji --- Documentation/devicetree/bindings/crypto/qcom-qce.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml index 5a653757ee752..fcf725bfa36b1 100644 --- a/Documentation/devicetree/bindings/crypto/qcom-qce.yaml +++ b/Documentation/devicetree/bindings/crypto/qcom-qce.yaml @@ -39,6 +39,7 @@ properties: - qcom,msm8996-qce - qcom,qcm2290-qce - qcom,sdm845-qce + - qcom,shikra-qce - qcom,sm6115-qce - const: qcom,ipq4019-qce - const: qcom,qce @@ -54,7 +55,6 @@ properties: - qcom,qcs8300-qce - qcom,sa8775p-qce - qcom,sc7280-qce - - qcom,shikra-qce - qcom,sm6350-qce - qcom,sm8250-qce - qcom,sm8350-qce @@ -133,6 +133,7 @@ allOf: contains: enum: - qcom,qcm2290-qce + - qcom,shikra-qce - qcom,sm6115-qce then: properties: From 8a862fb63ede17316edd4fb96f23461253dca939 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 10 Sep 2026 17:39:55 +0530 Subject: [PATCH 0973/1133] FROMLIST: clk: qcom: smd-rpm: Skip proxy votes on clocks for QCM2290 clk_smd_rpm_handoff() votes both active and sleep RPM resource states for every clock, keeping them non-zero until a consumer takes over. If there is no consumer, those clocks will remain active in the idle scenario as well, and the sleep vote is never cleared, blocking XO shutdown. Introduce the skip_clks_handoff flag to handle this on QCM2290 clocks, keeping other targets unaffected. Link: https://lore.kernel.org/r/20260910-clk-smd-rpm-skip-proxy-v1-1-1cb5694a99d9@oss.qualcomm.com Fixes: 00f64b58874e ("clk: qcom: Add support for SMD-RPM Clocks") Signed-off-by: Imran Shaik --- drivers/clk/qcom/clk-smd-rpm.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 487d715ed5d21..b78c8cc730b59 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -183,6 +183,7 @@ struct rpm_smd_clk_desc { const struct clk_smd_rpm ** const icc_clks; size_t num_icc_clks; bool scaling_before_handover; + bool skip_clks_handoff; }; static DEFINE_MUTEX(rpm_smd_clk_lock); @@ -1280,7 +1281,8 @@ static const struct rpm_smd_clk_desc rpm_clk_qcm2290 = { .clks = qcm2290_clks, .num_clks = ARRAY_SIZE(qcm2290_clks), .icc_clks = qcm2290_icc_clks, - .num_icc_clks = ARRAY_SIZE(qcm2290_icc_clks) + .num_icc_clks = ARRAY_SIZE(qcm2290_icc_clks), + .skip_clks_handoff = true, }; static const struct of_device_id rpm_smd_clk_match_table[] = { @@ -1358,13 +1360,15 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) goto err; } - for (i = 0; i < num_clks; i++) { - if (!rpm_smd_clks[i]) - continue; + if (!desc->skip_clks_handoff) { + for (i = 0; i < num_clks; i++) { + if (!rpm_smd_clks[i]) + continue; - ret = clk_smd_rpm_handoff(rpm_smd_clks[i]); - if (ret) - goto err; + ret = clk_smd_rpm_handoff(rpm_smd_clks[i]); + if (ret) + goto err; + } } for (i = 0; i < desc->num_icc_clks; i++) { From c68b6fa79e66efec08f4a86675147de65ff41a3f Mon Sep 17 00:00:00 2001 From: Akash Kumar Date: Fri, 18 Sep 2026 12:03:53 +0530 Subject: [PATCH 0974/1133] FROMLIST: dt-bindings: usb: Add Cypress cypd6129/cypd6229 Type-C controller Add the device-tree binding documentation for the Cypress cypd6129 and cypd6229 dual Type-C PD controllers. These are used on Shikra CQM/CQS/IQS platforms to handle usb-role-switch for the USB Type-C ports over an I2C interface, similarly to the existing cypd4226 binding. cypd6229 is a variant of cypd6129 and is described with a "cypress,cypd6129" fallback compatible string. Link: https://lore.kernel.org/all/20260821-shikra-usb-dt-v7-apply-v2-1-030647f06285@oss.qualcomm.com/ Signed-off-by: Akash Kumar Signed-off-by: Akash Kumar --- .../bindings/usb/cypress,cypd6129.yaml | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/cypress,cypd6129.yaml diff --git a/Documentation/devicetree/bindings/usb/cypress,cypd6129.yaml b/Documentation/devicetree/bindings/usb/cypress,cypd6129.yaml new file mode 100644 index 0000000000000..43e2c1902fd1b --- /dev/null +++ b/Documentation/devicetree/bindings/usb/cypress,cypd6129.yaml @@ -0,0 +1,107 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/cypress,cypd6129.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cypress cypd6129/cypd6229 Type-C Controller + +maintainers: + - Akash Kumar + +description: + The Cypress cypd6129 and cypd6229 are dual Type-C PD controllers that are + controlled via an I2C interface. + +properties: + compatible: + oneOf: + - const: cypress,cypd6129 + - items: + - const: cypress,cypd6229 + - const: cypress,cypd6129 + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + pinctrl-0: true + pinctrl-1: true + + pinctrl-names: + minItems: 1 + items: + - const: default + - const: sleep + + wakeup-source: + description: enable IRQ remote wakeup, see power/wakeup-source.txt + type: boolean + +patternProperties: + '^connector@[01]$': + $ref: /schemas/connector/usb-connector.yaml# + required: + - reg + +required: + - compatible + - reg + - interrupts + +anyOf: + - required: + - connector@0 + - required: + - connector@1 + +additionalProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + typec@40 { + compatible = "cypress,cypd6129"; + reg = <0x40>; + interrupts-extended = <&tlmm 136 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&usb0_intr_state>; + pinctrl-names = "default"; + wakeup-source; + + #address-cells = <1>; + #size-cells = <0>; + + connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + label = "USB-C"; + data-role = "dual"; + power-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + endpoint { + remote-endpoint = <&usb_role_switch0>; + }; + }; + }; + }; + }; + }; From 7160dc9165ede9a0bb9f94c9589824ac4b93e42d Mon Sep 17 00:00:00 2001 From: Akash Kumar Date: Fri, 18 Sep 2026 12:07:20 +0530 Subject: [PATCH 0975/1133] FROMLIST: usb: typec: ucsi: ccg: Add support for cypd6129/cypd6229 Add cypd6129 and cypd6229 compatible strings to the of_device_id match table so the driver binds to boards describing these Cypress PD controllers in their device tree. No other driver changes are needed since the chip is accessed through the same generic UCSI/HPI I2C register protocol as the existing cypd4226 support. Link: https://lore.kernel.org/all/20260820145036.2035641-3-akash.kumar@oss.qualcomm.com/ Signed-off-by: Akash Kumar Signed-off-by: Akash Kumar --- drivers/usb/typec/ucsi/ucsi_ccg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index 3f12db95c7f46..34fde72fe0a6e 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -1556,6 +1556,8 @@ static void ucsi_ccg_remove(struct i2c_client *client) static const struct of_device_id ucsi_ccg_of_match_table[] = { { .compatible = "cypress,cypd4226", }, + { .compatible = "cypress,cypd6129", }, + { .compatible = "cypress,cypd6229", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, ucsi_ccg_of_match_table); From 7a63bb41f8ede019ae0a3725aecf4c614d00b07c Mon Sep 17 00:00:00 2001 From: Akash Kumar Date: Fri, 18 Sep 2026 12:12:25 +0530 Subject: [PATCH 0976/1133] FROMLIST: phy: qcom: qmp-usbc: Add qmp configuration for Shikra Add init sequence and phy configuration for the Super Speed port on Shikra SoC. Also since Shikra uses 3 resets, add support for the third reset and configure Shikra platform data to use 3 resets. Link: https://lore.kernel.org/all/20260504170659.282532-5-krishna.kurapati@oss.qualcomm.com/ Signed-off-by: Krishna Kurapati Reviewed-by: Dmitry Baryshkov Signed-off-by: Akash Kumar --- drivers/phy/qualcomm/phy-qcom-qmp-usbc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c index 548ec97373ac3..e6a24f9f38056 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c @@ -2056,6 +2056,9 @@ static const struct of_device_id qmp_usbc_of_match_table[] = { }, { .compatible = "qcom,shikra-qmp-usb3-dp-phy", .data = &shikra_usb3dp_phy_cfg, + }, { + .compatible = "qcom,shikra-qmp-usb3-phy", + .data = &qcs615_usb3phy_cfg, }, { .compatible = "qcom,sm6115-qmp-usb3-phy", .data = &qcm2290_usb3phy_cfg, From b27668444a5d8682a22f17fb2ab364475969b0f4 Mon Sep 17 00:00:00 2001 From: Akash Kumar Date: Fri, 18 Sep 2026 12:22:41 +0530 Subject: [PATCH 0977/1133] FROMLIST: arm64: dts: qcom: shikra: Wire up usb-role-switch for USB Type-C ports On Shikra CQS/CQM platforms, usb-role-switch is handled by PM4125 on the primary Type-C port and Cypress PD controller CYPD6129 on the second Type-C port. On Shikra IQS platform, usb-role-switch is handled by Cypress PD controller CYPD6129 on both Type-C ports. Add the CYPD6129 typec node under i2c3, wire its connector endpoints to the corresponding DWC3 controller ports via remote-endpoint phandles, and switch the associated USB controllers to OTG mode so role switching can take effect. Link: https://lore.kernel.org/linux-arm-msm/20260821-shikra-usb-dt-v7-apply-v2-3-030647f06285@oss.qualcomm.com/ Signed-off-by: Akash Kumar Signed-off-by: Akash Kumar --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 65 +++++++++++- arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 45 ++++++++ arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 65 +++++++++++- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 105 ++++++++++++++++++- 4 files changed, 267 insertions(+), 13 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 759091a87c265..106f3ce838706 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -97,6 +97,43 @@ }; }; +&i2c3 { + status = "okay"; + + typec@40 { + compatible = "cypress,cypd6129"; + reg = <0x40>; + interrupts-extended = <&tlmm 136 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&usb0_intr_state>; + pinctrl-names = "default"; + wakeup-source; + + #address-cells = <1>; + #size-cells = <0>; + + ccg_typec_con0: connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + label = "USB-C"; + data-role = "dual"; + power-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ucsi_ccg_port: endpoint { + remote-endpoint = <&usb_2_dwc3_hs>; + }; + }; + }; + }; + }; +}; + &mdss { status = "okay"; }; @@ -238,9 +275,17 @@ bias-disable; output-low; }; + + usb0_intr_state: usb0-intr-state { + pins = "gpio136"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; }; &usb_1 { + /delete-property/ dr_mode; dr_mode = "otg"; }; @@ -256,9 +301,20 @@ status = "okay"; }; -&usb_qmpphy { - vdda-phy-supply = <&pm4125_l8>; +&usb_2 { + /delete-property/ dr_mode; + + port { + usb_2_dwc3_hs: endpoint { + remote-endpoint = <&ucsi_ccg_port>; + }; + }; +}; + +&usb_2_hsphy { + vdd-supply = <&pm4125_l12>; vdda-pll-supply = <&pm4125_l13>; + vdda-phy-dpdm-supply = <&pm4125_l21>; status = "okay"; }; @@ -267,10 +323,9 @@ remote-endpoint = <&pm4125_ss_in>; }; -&usb_2_hsphy { - vdd-supply = <&pm4125_l12>; +&usb_qmpphy { + vdda-phy-supply = <&pm4125_l8>; vdda-pll-supply = <&pm4125_l13>; - vdda-phy-dpdm-supply = <&pm4125_l21>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi index 95eb7255fb227..47ff2c8032652 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -205,6 +205,51 @@ status = "okay"; }; +&pm4125_typec { + status = "okay"; + + connector { + compatible = "usb-c-connector"; + + power-role = "dual"; + data-role = "dual"; + self-powered; + + typec-power-opmode = "default"; + pd-disable; + + vbus-supply = <&pm4125_vbus>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + pm4125_hs_in: endpoint { + }; + }; + + port@1 { + reg = <1>; + + pm4125_ss_in: endpoint { + }; + }; + }; + }; +}; + +&pm4125_vbus { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-min-microamp = <500000>; + regulator-max-microamp = <500000>; + + status = "okay"; +}; + &pm8005_regulators { status = "disabled"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 90e75a62a7ef8..737a5e411c6f7 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -93,6 +93,43 @@ }; }; +&i2c3 { + status = "okay"; + + typec@40 { + compatible = "cypress,cypd6129"; + reg = <0x40>; + interrupts-extended = <&tlmm 136 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&usb0_intr_state>; + pinctrl-names = "default"; + wakeup-source; + + #address-cells = <1>; + #size-cells = <0>; + + ccg_typec_con0: connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + label = "USB-C"; + data-role = "dual"; + power-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ucsi_ccg_port: endpoint { + remote-endpoint = <&usb_2_dwc3_hs>; + }; + }; + }; + }; + }; +}; + &mdss { status = "okay"; }; @@ -234,9 +271,17 @@ bias-disable; output-low; }; + + usb0_intr_state: usb0-intr-state { + pins = "gpio136"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; }; &usb_1 { + /delete-property/ dr_mode; dr_mode = "otg"; }; @@ -252,9 +297,20 @@ status = "okay"; }; -&usb_qmpphy { - vdda-phy-supply = <&pm4125_l8>; +&usb_2 { + /delete-property/ dr_mode; + + port { + usb_2_dwc3_hs: endpoint { + remote-endpoint = <&ucsi_ccg_port>; + }; + }; +}; + +&usb_2_hsphy { + vdd-supply = <&pm4125_l12>; vdda-pll-supply = <&pm4125_l13>; + vdda-phy-dpdm-supply = <&pm4125_l21>; status = "okay"; }; @@ -263,10 +319,9 @@ remote-endpoint = <&pm4125_ss_in>; }; -&usb_2_hsphy { - vdd-supply = <&pm4125_l12>; +&usb_qmpphy { + vdda-phy-supply = <&pm4125_l8>; vdda-pll-supply = <&pm4125_l13>; - vdda-phy-dpdm-supply = <&pm4125_l21>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 74da9ef6459fa..650e54a172da2 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -119,6 +119,72 @@ }; }; +&i2c3 { + status = "okay"; + + typec@40 { + compatible = "cypress,cypd6229", "cypress,cypd6129"; + reg = <0x40>; + interrupts-extended = <&tlmm 50 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&usb0_intr_state>; + pinctrl-names = "default"; + wakeup-source; + + #address-cells = <1>; + #size-cells = <0>; + + ccg_typec_con0: connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + label = "USB2-Type-C"; + data-role = "dual"; + power-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ucsi_ccg_port0_hs: endpoint { + remote-endpoint = <&usb_2_dwc3_hs>; + }; + }; + }; + }; + + ccg_typec_con1: connector@1 { + compatible = "usb-c-connector"; + reg = <1>; + label = "USB3-Type-C"; + data-role = "dual"; + power-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + ucsi_ccg_port_1_hs: endpoint { + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + ucsi_ccg_port_1_ss: endpoint { + remote-endpoint = <&usb_qmpphy_out>; + }; + }; + }; + }; + }; +}; + &i2c4 { status = "okay"; @@ -268,6 +334,23 @@ bias-disable; output-low; }; + + usb0_intr_state: usb0-intr-state { + pins = "gpio50"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; +}; + +&usb_1 { + /delete-property/ dr_mode; + + status = "okay"; +}; + +&usb_1_dwc3_hs { + remote-endpoint = <&ucsi_ccg_port_1_hs>; }; &usb_1_hsphy { @@ -278,11 +361,16 @@ status = "okay"; }; -&usb_qmpphy { - vdda-phy-supply = <&pm8150_l6>; - vdda-pll-supply = <&pm8150_l12>; +&usb_2 { + /delete-property/ dr_mode; status = "okay"; + + port { + usb_2_dwc3_hs: endpoint { + remote-endpoint = <&ucsi_ccg_port0_hs>; + }; + }; }; &usb_2_hsphy { @@ -292,3 +380,14 @@ status = "okay"; }; + +&usb_qmpphy { + vdda-phy-supply = <&pm8150_l6>; + vdda-pll-supply = <&pm8150_l12>; + + status = "okay"; +}; + +&usb_qmpphy_out { + remote-endpoint = <&ucsi_ccg_port_1_ss>; +}; From ad2899753d356bdb48864177533f5ca0c218364e Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Wed, 4 Nov 2026 19:33:30 +0530 Subject: [PATCH 0978/1133] FROMLIST: dt-bindings: remoteproc: Move iommus constraint to SoC-specific bindings The `iommus` property constraint in qcom,pas-common.yaml is too restrictive with `maxItems: 1`, preventing SoCs that require multiple IOMMU entries from being properly described. Remove `iommus` constraint from qcom,pas-common.yaml and add it to SoC-specific binding files that have EL2 support and require IOMMU configuration: - qcom,sa8775p-pas.yaml: Add `iommus: maxItems: 1` for all sa8775p and qcs8300 remoteproc compatibles (lemans-el2, monaco-el2) - qcom,sm8150-pas.yaml: Add `iommus: maxItems: 1` for qcs615 remoteproc compatibles (talos-el2) - qcom,sm8550-pas.yaml: Add `iommus: maxItems: 1` for x1e80100 remoteproc compatibles (x1-el2) This allows each SoC to define its own IOMMU requirements while maintaining backward compatibility. Link: https://lore.kernel.org/r/20261104-shikra-el2-v4-1-97e7019debff@oss.qualcomm.com Signed-off-by: Komal Bajaj --- .../bindings/remoteproc/qcom,pas-common.yaml | 3 --- .../bindings/remoteproc/qcom,sa8775p-pas.yaml | 6 ++++++ .../bindings/remoteproc/qcom,sm8150-pas.yaml | 12 ++++++++++++ .../bindings/remoteproc/qcom,sm8550-pas.yaml | 12 ++++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml index f75cab6b4ed95..4662fe4cff62f 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml @@ -32,9 +32,6 @@ properties: minItems: 5 maxItems: 6 - iommus: - maxItems: 1 - power-domains: minItems: 1 maxItems: 3 diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml index dda2d144b7206..711c2f723b179 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml @@ -106,6 +106,8 @@ allOf: items: - const: lcx - const: lmx + iommus: + maxItems: 1 - if: properties: @@ -126,6 +128,8 @@ allOf: - const: cx - const: mxc - const: nsp + iommus: + maxItems: 1 - if: properties: @@ -144,6 +148,8 @@ allOf: items: - const: cx - const: mxc + iommus: + maxItems: 1 unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml index 5a7c5f8c92d17..e643e44a47395 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml @@ -178,6 +178,18 @@ allOf: - const: lcx - const: lmx + - if: + properties: + compatible: + contains: + enum: + - qcom,qcs615-adsp-pas + - qcom,qcs615-cdsp-pas + then: + properties: + iommus: + maxItems: 1 + unevaluatedProperties: false examples: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index 99e9aeeb4f62c..dd81ecdb8dc49 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -317,6 +317,18 @@ allOf: - const: mx - const: nsp + - if: + properties: + compatible: + contains: + enum: + - qcom,x1e80100-adsp-pas + - qcom,x1e80100-cdsp-pas + then: + properties: + iommus: + maxItems: 1 + unevaluatedProperties: false examples: From a2883a90f14d93c9de59be54f95feebdc50c819b Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Wed, 4 Nov 2026 19:33:31 +0530 Subject: [PATCH 0979/1133] FROMLIST: dt-bindings: remoteproc: qcom,shikra-pas: Add iommus constraints Add iommus constraints for Shikra PAS compatible: - qcom,shikra-cdsp-pas: maxItems: 1 - qcom,shikra-lpaicp-pas: minItems: 3, maxItems: 3 CDSP uses single IOMMU stream, while LPAICP firmware uses three. These are needed to describe the firmware streams when Linux boots at EL2 without the hypervisor. Link: https://lore.kernel.org/r/20261104-shikra-el2-v4-2-97e7019debff@oss.qualcomm.com Signed-off-by: Komal Bajaj --- .../devicetree/bindings/remoteproc/qcom,shikra-pas.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,shikra-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,shikra-pas.yaml index 34a2f15e93616..8c8a7616d4787 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,shikra-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,shikra-pas.yaml @@ -112,6 +112,8 @@ allOf: maxItems: 1 firmware-name: maxItems: 1 + iommus: + maxItems: 1 power-domains: items: - description: CX power domain @@ -134,6 +136,9 @@ allOf: minItems: 2 firmware-name: minItems: 2 + iommus: + minItems: 3 + maxItems: 3 power-domains: false power-domain-names: false From c0ef73d4005dd6a19d08879db6452aea8f3da9bd Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Wed, 4 Nov 2026 19:33:32 +0530 Subject: [PATCH 0980/1133] FROMLIST: arm64: dts: qcom: shikra: Add EL2 overlay for remoteproc SMMU mappings Shikra boards currently boot Linux under a hypervisor, where the remote processor firmware IOMMU streams are managed by the hypervisor. When booting Linux directly at EL2 without the hypervisor, the IOMMU is instead managed by the consumer of this DeviceTree, so the firmware streams for each remote processor need to be described explicitly. Add an EL2-specific DT overlay and apply it to all Shikra EVK variants devices to produce an -el2.dtb alongside the "normal" dtb. Co-developed-by: Bibek Kumar Patro Signed-off-by: Bibek Kumar Patro Reviewed-by: Abel Vesa Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20261104-shikra-el2-v4-3-97e7019debff@oss.qualcomm.com Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/Makefile | 11 +++++++++ arch/arm64/boot/dts/qcom/shikra-el2.dtso | 29 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 88230c4e00ea9..296c53b826879 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -373,9 +373,20 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm850-lenovo-yoga-c630.dtb dtb-$(CONFIG_ARCH_QCOM) += sdm850-samsung-w737.dtb dtb-$(CONFIG_ARCH_QCOM) += sdx75-idp.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk.dtb + +shikra-cqm-evk-el2-dtbs := shikra-cqm-evk.dtb shikra-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-el2.dtb + dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk.dtb + +shikra-cqs-evk-el2-dtbs := shikra-cqs-evk.dtb shikra-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-el2.dtb + dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk.dtb +shikra-iqs-evk-el2-dtbs := shikra-iqs-evk.dtb shikra-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-el2.dtb + shikra-cqm-evk-imx577-camera-dtbs := shikra-cqm-evk.dtb shikra-cqm-cqs-evk-imx577-camera.dtbo shikra-cqs-evk-imx577-camera-dtbs := shikra-cqs-evk.dtb shikra-cqm-cqs-evk-imx577-camera.dtbo shikra-iqs-evk-imx577-camera-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-imx577-camera.dtbo diff --git a/arch/arm64/boot/dts/qcom/shikra-el2.dtso b/arch/arm64/boot/dts/qcom/shikra-el2.dtso new file mode 100644 index 0000000000000..a0f7c4a635ada --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-el2.dtso @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Shikra specific modifications required to boot in EL2. + */ + +/dts-v1/; +/plugin/; + +&gpu_zap_shader { + status = "disabled"; +}; + +&remoteproc_cdsp { + iommus = <&apps_smmu 0x0200 0x0>; +}; + +&remoteproc_lpaicp { + iommus = <&apps_smmu 0x0360 0x0005>, + <&apps_smmu 0x0366 0x0000>, + <&apps_smmu 0x00e7 0x0000>; +}; + +&wifi { + wifi-firmware { + iommus = <&apps_smmu 0x01a2 0x0001>; + }; +}; From 246767d0b62c24f1b61f9eef40a2307fd415f376 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Mon, 21 Sep 2026 14:14:00 +0530 Subject: [PATCH 0981/1133] WORKAROUND: arm64: dts: qcom: rename shikra cqm evk imx577 dtso Rename shikra-cqm-cqs-evk-imx577-camera.dtso to shikra-cqm-evk-imx577-camera.dtso. This is a workaround to align with QLI2.0 and meta-qcom naming. After the release, we will switch back to the latest file names. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/Makefile | 4 ++-- ...k-imx577-camera.dtso => shikra-cqm-evk-imx577-camera.dtso} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename arch/arm64/boot/dts/qcom/{shikra-cqm-cqs-evk-imx577-camera.dtso => shikra-cqm-evk-imx577-camera.dtso} (100%) diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 296c53b826879..c9ecb57045ff0 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -387,8 +387,8 @@ dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk.dtb shikra-iqs-evk-el2-dtbs := shikra-iqs-evk.dtb shikra-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-el2.dtb -shikra-cqm-evk-imx577-camera-dtbs := shikra-cqm-evk.dtb shikra-cqm-cqs-evk-imx577-camera.dtbo -shikra-cqs-evk-imx577-camera-dtbs := shikra-cqs-evk.dtb shikra-cqm-cqs-evk-imx577-camera.dtbo +shikra-cqm-evk-imx577-camera-dtbs := shikra-cqm-evk.dtb shikra-cqm-evk-imx577-camera.dtbo +shikra-cqs-evk-imx577-camera-dtbs := shikra-cqs-evk.dtb shikra-cqm-evk-imx577-camera.dtbo shikra-iqs-evk-imx577-camera-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-imx577-camera.dtbo dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-imx577-camera.dtb diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-cqs-evk-imx577-camera.dtso b/arch/arm64/boot/dts/qcom/shikra-cqm-evk-imx577-camera.dtso similarity index 100% rename from arch/arm64/boot/dts/qcom/shikra-cqm-cqs-evk-imx577-camera.dtso rename to arch/arm64/boot/dts/qcom/shikra-cqm-evk-imx577-camera.dtso From 50fc0e3be780b60d155312a9c065f66e449e71c9 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Fri, 24 Jul 2026 14:42:13 +0200 Subject: [PATCH 0982/1133] FROMLIST: arm64: dts: qcom: agatti: Add OPE node Add the Offline Processing Engine (OPE) device tree node for the Agatti platform (QCM2290). The node describes the five register regions (top, bus_read, bus_write, pipeline, qos), clocks, interrupt, interconnects, IOMMU mappings, and OPP table. Signed-off-by: Loic Poulain Link: https://lore.kernel.org/all/20261103-camss-isp-ope-v13-7-c2cbf15a39b1@oss.qualcomm.com/ --- arch/arm64/boot/dts/qcom/agatti.dtsi | 77 ++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/agatti.dtsi b/arch/arm64/boot/dts/qcom/agatti.dtsi index d9f4cbfd2861c..8f2b451b8f6e8 100644 --- a/arch/arm64/boot/dts/qcom/agatti.dtsi +++ b/arch/arm64/boot/dts/qcom/agatti.dtsi @@ -1990,6 +1990,83 @@ }; }; + isp_ope: isp@5c42000 { + compatible = "qcom,qcm2290-camss-ope"; + + reg = <0x0 0x5c42000 0x0 0x400>, + <0x0 0x5c42400 0x0 0x200>, + <0x0 0x5c42600 0x0 0x200>, + <0x0 0x5c42800 0x0 0x4400>, + <0x0 0x5c46c00 0x0 0x190>, + <0x0 0x5c46d90 0x0 0xa00>; + reg-names = "cdm", + "top", + "qos", + "pipeline", + "bus_read", + "bus_write"; + + clocks = <&gcc GCC_CAMSS_AXI_CLK>, + <&gcc GCC_CAMSS_OPE_CLK>, + <&gcc GCC_CAMSS_OPE_AHB_CLK>, + <&gcc GCC_CAMSS_NRT_AXI_CLK>, + <&gcc GCC_CAMSS_TOP_AHB_CLK>; + clock-names = "axi", + "core", + "iface", + "nrt", + "top"; + + interrupts = ; + + interconnects = <&bimc MASTER_APPSS_PROC RPM_ACTIVE_TAG + &config_noc SLAVE_CAMERA_CFG RPM_ACTIVE_TAG>, + <&mmnrt_virt MASTER_CAMNOC_SF RPM_ALWAYS_TAG + &bimc SLAVE_EBI1 RPM_ALWAYS_TAG>; + interconnect-names = "config", + "data"; + + iommus = <&apps_smmu 0x800 0x0>, + <&apps_smmu 0x820 0x0>, + <&apps_smmu 0x840 0x0>; + + operating-points-v2 = <&ope_opp_table>; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>, + <&rpmpd QCM2290_VDDCX>; + power-domain-names = "camss", + "cx"; + + ope_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_min_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-266600000 { + opp-hz = /bits/ 64 <266600000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-465000000 { + opp-hz = /bits/ 64 <465000000>; + required-opps = <&rpmpd_opp_nom>; + }; + + opp-580000000 { + opp-hz = /bits/ 64 <580000000>; + required-opps = <&rpmpd_opp_turbo>; + turbo-mode; + }; + }; + }; + mdss: display-subsystem@5e00000 { compatible = "qcom,qcm2290-mdss"; reg = <0x0 0x05e00000 0x0 0x1000>; From 9d17337202569ab5d89e0f65dac8350d5f867e30 Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Fri, 31 Jul 2026 17:57:44 +0530 Subject: [PATCH 0983/1133] FROMLIST: arm64: dts: qcom: shikra: Add OPE node Add the Offline Processing Engine (OPE) device tree node for Shikra. The node describes the six register regions (cdm, top, qos, pipeline, bus_read, bus_write), clocks, interrupt, interconnects, IOMMU mappings, and OPP table. OPE is a memory-to-memory block with no board-level dependencies, so the node is left enabled for all Shikra boards. Signed-off-by: Nihal Kumar Gupta Signed-off-by: Loic Poulain Link: https://lore.kernel.org/all/20261103-camss-isp-ope-v13-8-c2cbf15a39b1@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra.dtsi | 79 ++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 61df194840079..61a88ad8f1220 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -3525,6 +3525,85 @@ }; }; + isp_ope: isp@5c42000 { + compatible = "qcom,shikra-camss-ope", "qcom,qcm2290-camss-ope"; + + reg = <0x0 0x5c42000 0x0 0x400>, + <0x0 0x5c42400 0x0 0x200>, + <0x0 0x5c42600 0x0 0x200>, + <0x0 0x5c42800 0x0 0x4400>, + <0x0 0x5c46c00 0x0 0x190>, + <0x0 0x5c46d90 0x0 0xa00>; + reg-names = "cdm", + "top", + "qos", + "pipeline", + "bus_read", + "bus_write"; + + clocks = <&gcc GCC_CAMSS_AXI_CLK>, + <&gcc GCC_CAMSS_OPE_CLK>, + <&gcc GCC_CAMSS_OPE_AHB_CLK>, + <&gcc GCC_CAMSS_NRT_AXI_CLK>, + <&gcc GCC_CAMSS_TOP_AHB_CLK>; + clock-names = "axi", + "core", + "iface", + "nrt", + "top"; + + interrupts = ; + + interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG + &config_noc SLAVE_CAMERA_CFG RPM_ACTIVE_TAG>, + <&mmnrt_virt MASTER_CAMNOC_SF RPM_ALWAYS_TAG + &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>; + interconnect-names = "config", + "data"; + + iommus = <&apps_smmu 0x600 0x0>, + <&apps_smmu 0x620 0x0>, + <&apps_smmu 0x640 0x0>; + + operating-points-v2 = <&ope_opp_table>; + power-domains = <&gcc GCC_CAMSS_TOP_GDSC>, + <&rpmpd RPMPD_VDDCX>; + power-domain-names = "camss", + "cx"; + + status = "okay"; + + ope_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmpd_opp_min_svs>; + }; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp-266600000 { + opp-hz = /bits/ 64 <266600000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-465000000 { + opp-hz = /bits/ 64 <465000000>; + required-opps = <&rpmpd_opp_nom>; + }; + + opp-580000000 { + opp-hz = /bits/ 64 <580000000>; + required-opps = <&rpmpd_opp_turbo>; + turbo-mode; + }; + }; + }; + dispcc: clock-controller@5f00000 { compatible = "qcom,shikra-dispcc", "qcom,qcm2290-dispcc"; reg = <0x0 0x05f00000 0x0 0x20000>; From 1090088bd5d598934d3100873f3c9ecd5c4a66d9 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Tue, 22 Sep 2026 11:09:31 +0800 Subject: [PATCH 0984/1133] FROMLIST: arm64: dts: qcom: shikra: Switch CPU ETMs to MMIO-based probing The etm0-etm3 nodes are declared with "arm,coresight-etm4x-sysreg" but do not implement self-hosted system-register trace access on this SoC: ID_AA64DFR0_EL1.TraceVer reads as 0 on the affected CPUs, so etm4_init_sysreg_access() correctly reports the access mechanism as unavailable and the ETMv4 driver fails to probe with -EINVAL. The CPU ETMs have a memory-mapped aperture, so switch each node to the standard "arm,coresight-etm4x", "arm,primecell" compatible with its MMIO reg range. Link: https://lore.kernel.org/all/20260922-fix-etm-probe-issue-on-shikra-v1-1-56d25e9bbe17@oss.qualcomm.com/ Fixes: eed738c6dd0c ("arm64: dts: qcom: shikra: Add coresight nodes") Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/shikra.dtsi | 140 ++++++++++++++------------- 1 file changed, 72 insertions(+), 68 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 61a88ad8f1220..ffbd85130c605 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -168,74 +168,6 @@ }; }; - etm0 { - compatible = "arm,coresight-etm4x-sysreg"; - - clocks = <&rpmcc RPM_SMD_QDSS_CLK>; - clock-names = "apb_pclk"; - cpu = <&cpu0>; - qcom,skip-power-up; - - out-ports { - port { - etm0_out: endpoint { - remote-endpoint = <&funnel_cpuss0_in0>; - }; - }; - }; - }; - - etm1 { - compatible = "arm,coresight-etm4x-sysreg"; - - clocks = <&rpmcc RPM_SMD_QDSS_CLK>; - clock-names = "apb_pclk"; - cpu = <&cpu1>; - qcom,skip-power-up; - - out-ports { - port { - etm1_out: endpoint { - remote-endpoint = <&funnel_cpuss0_in1>; - }; - }; - }; - }; - - etm2 { - compatible = "arm,coresight-etm4x-sysreg"; - - clocks = <&rpmcc RPM_SMD_QDSS_CLK>; - clock-names = "apb_pclk"; - cpu = <&cpu2>; - qcom,skip-power-up; - - out-ports { - port { - etm2_out: endpoint { - remote-endpoint = <&funnel_cpuss0_in2>; - }; - }; - }; - }; - - etm3 { - compatible = "arm,coresight-etm4x-sysreg"; - - clocks = <&rpmcc RPM_SMD_QDSS_CLK>; - clock-names = "apb_pclk"; - cpu = <&cpu3>; - qcom,skip-power-up; - - out-ports { - port { - etm3_out: endpoint { - remote-endpoint = <&funnel_cpuss0_in3>; - }; - }; - }; - }; - firmware { scm { compatible = "qcom,scm-shikra", "qcom,scm"; @@ -4541,6 +4473,24 @@ label = "cti_apss_pe0"; }; + etm@9040000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x0 0x09040000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + cpu = <&cpu0>; + qcom,skip-power-up; + + out-ports { + port { + etm0_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in0>; + }; + }; + }; + }; + cti@90e0000 { compatible = "arm,coresight-cti", "arm,primecell"; reg = <0x0 0x090e0000 0x0 0x1000>; @@ -4559,6 +4509,24 @@ label = "cti_apss_pe1"; }; + etm@9140000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x0 0x09140000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + cpu = <&cpu1>; + qcom,skip-power-up; + + out-ports { + port { + etm1_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in1>; + }; + }; + }; + }; + cti@9220000 { compatible = "arm,coresight-cti", "arm,primecell"; reg = <0x0 0x09220000 0x0 0x1000>; @@ -4568,6 +4536,24 @@ label = "cti_apss_pe2"; }; + etm@9240000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x0 0x09240000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + cpu = <&cpu2>; + qcom,skip-power-up; + + out-ports { + port { + etm2_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in2>; + }; + }; + }; + }; + cti@9320000 { compatible = "arm,coresight-cti", "arm,primecell"; reg = <0x0 0x09320000 0x0 0x1000>; @@ -4577,6 +4563,24 @@ label = "cti_apss_pe3"; }; + etm@9340000 { + compatible = "arm,coresight-etm4x", "arm,primecell"; + reg = <0x0 0x09340000 0x0 0x1000>; + + clocks = <&rpmcc RPM_SMD_QDSS_CLK>; + clock-names = "apb_pclk"; + cpu = <&cpu3>; + qcom,skip-power-up; + + out-ports { + port { + etm3_out: endpoint { + remote-endpoint = <&funnel_cpuss0_in3>; + }; + }; + }; + }; + funnel@9800000 { compatible = "arm,coresight-dynamic-funnel", "arm,primecell"; reg = <0x0 0x09800000 0x0 0x1000>; From 6d36cbee48e6907c627786477bc62dac0365c5a3 Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Tue, 22 Sep 2026 17:54:36 +0530 Subject: [PATCH 0985/1133] FROMLIST: arm64: dts: qcom: shikra-iqs-som: Correct PM8150 L10 voltage range Update the PM8150 L10 regulator maximum voltage from 3.544 V to 3.3 V, matching the supported voltage range for the Shikra IQS SoM. Link: https://lore.kernel.org/all/20260922-fix_l10_max-v1-1-d0c99f063bf4@oss.qualcomm.com/ Signed-off-by: Rakesh Kota --- arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi index 9f5818e351ef1..a0e7c4d962c30 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi @@ -285,7 +285,7 @@ pm8150_l10: l10 { regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <3544000>; + regulator-max-microvolt = <3300000>; }; pm8150_l11: l11 { From 17561ab57a7ddc28f7c432e456ea16c6fd841d2f Mon Sep 17 00:00:00 2001 From: Dipa Ramesh Mantre Date: Fri, 11 Sep 2026 10:33:04 +0530 Subject: [PATCH 0986/1133] FROMLIST: arm64: dts: qcom: shikra: Enable CDSP & Modem cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the CDSP/Modem does not throttle its speed automatically when it reaches high temperatures in shikra. Set up CDSP/Modem cooling by throttling the CDSP and modem when they reach 115°C using the QMI TMD cooling device framework. Link: https://lore.kernel.org/r/20260911-shikra_qmi_tmd-v1-2-96c1cca82f30@oss.qualcomm.com Signed-off-by: Dipa Ramesh Mantre --- arch/arm64/boot/dts/qcom/shikra.dtsi | 71 ++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index ffbd85130c605..073361f1a3cee 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -2765,6 +2766,8 @@ qcom,smem-states = <&modem_smp2p_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <3>; + status = "disabled"; glink-edge { @@ -2819,6 +2822,8 @@ qcom,smem-states = <&cdsp_smp2p_out 0>; qcom,smem-state-names = "stop"; + #cooling-cells = <3>; + status = "disabled"; glink-edge { @@ -5224,6 +5229,8 @@ }; nsp-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens0 7>; trips { @@ -5233,15 +5240,31 @@ type = "hot"; }; - nsp-critical { + nsp_alert1: nsp-alert1 { temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + + nsp-critical { + temperature = <118000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&nsp_alert1>; + cooling-device = <&remoteproc_cdsp QCOM_TMD_CDSP_SW + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; mdmss0-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens0 8>; trips { @@ -5251,15 +5274,37 @@ type = "hot"; }; - mdmss0-critical { + mdmss0_alert1: mdmss0-alert1 { temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + + mdmss0-critical { + temperature = <118000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&mdmss0_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_PA + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + + map1 { + trip = <&mdmss0_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_MODEM + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; mdmss1-thermal { + polling-delay-passive = <200>; + thermal-sensors = <&tsens0 9>; trips { @@ -5269,12 +5314,32 @@ type = "hot"; }; - mdmss1-critical { + mdmss1_alert1: mdmss1-alert1 { temperature = <115000>; + hysteresis = <5000>; + type = "passive"; + }; + + mdmss1-critical { + temperature = <118000>; hysteresis = <0>; type = "critical"; }; }; + + cooling-maps { + map0 { + trip = <&mdmss1_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_PA + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + + map1 { + trip = <&mdmss1_alert1>; + cooling-device = <&remoteproc_mpss QCOM_TMD_MODEM + THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; camera-thermal { From 8480641c872ee14c55ab114160673aa53a667707 Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Thu, 1 Oct 2026 19:19:19 +0530 Subject: [PATCH 0987/1133] FROMLIST: arm64: dts: qcom: shikra-evk: Add GPIO expanders Add the EVK GPIO expander definitions on the I2C3 bus. Describe the TCA9538 and TCA9539 expanders used by EVK boards. Co-developed-by: Faruque Ansari Signed-off-by: Faruque Ansari Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20261001-shikra-gpio-expander-v3-1-d30c1e8067db@oss.qualcomm.com Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra-evk.dtsi | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi index 1991186ed4353..bcc6cc0def6e4 100644 --- a/arch/arm64/boot/dts/qcom/shikra-evk.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-evk.dtsi @@ -39,6 +39,34 @@ &i2c3 { status = "okay"; + + expander0: gpio@20 { + compatible = "ti,tca9539"; + reg = <0x20>; + #gpio-cells = <2>; + gpio-controller; + }; + + expander1: gpio@21 { + compatible = "ti,tca9539"; + reg = <0x21>; + #gpio-cells = <2>; + gpio-controller; + }; + + expander2: gpio@38 { + compatible = "ti,tca9538"; + reg = <0x38>; + #gpio-cells = <2>; + gpio-controller; + }; + + expander3: gpio@3c { + compatible = "ti,tca9538"; + reg = <0x3c>; + #gpio-cells = <2>; + gpio-controller; + }; }; &iris { From fa40a1f54f29bd6166c43ac42f7393a90ef34199 Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Tue, 6 Oct 2026 16:44:04 +0530 Subject: [PATCH 0988/1133] FROMLIST: arm64: dts: qcom: shikra: Correct QCE node configuration Shikra is derived from Agatti and uses the same QCE integration. Update the QCE node to match the underlying hardware implementation by adjusting the fallback compatible and related properties, including clocks and clock-names. Since cryptobam is marked qcom,controlled-remotely, its clocks are managed remotely and hence don't specify explicitly. Link: https://lore.kernel.org/lkml/20261006-shikra_qce_fix-v1-2-8ac54d81edb4@oss.qualcomm.com/ Fixes: 099cd05d200b ("arm64: dts: qcom: shikra: Add ICE, TRNG and QCE nodes") Tested-by: Wenjia Zhang #on shikra device Signed-off-by: Kuldeep Singh Signed-off-by: Roopak Houji --- arch/arm64/boot/dts/qcom/shikra.dtsi | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 073361f1a3cee..b4d35d7ff1511 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1275,7 +1275,7 @@ }; crypto: crypto@1b3a000 { - compatible = "qcom,shikra-qce", "qcom,sm8150-qce", "qcom,qce"; + compatible = "qcom,shikra-qce", "qcom,ipq4019-qce", "qcom,qce"; reg = <0x0 0x01b3a000 0x0 0x6000>; dmas = <&cryptobam 4>, <&cryptobam 5>; dma-names = "rx", "tx"; @@ -1286,9 +1286,8 @@ <&apps_smmu 0x96 0x0011>, <&apps_smmu 0x98 0x0001>, <&apps_smmu 0x9f 0x0>; - interconnects = <&system_noc MASTER_CRYPTO_CORE0 0 - &mc_virt SLAVE_EBI_CH0 0>; - interconnect-names = "memory"; + clocks = <&rpmcc RPM_SMD_CE1_CLK>; + clock-names = "core"; }; qfprom: efuse@1b44000 { From 76e832c776c0acf295df97aa4a495e364f858aab Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Thu, 8 Oct 2026 14:08:05 +0800 Subject: [PATCH 0989/1133] FROMLIST: arm64: dts: qcom: shikra: Mark tpdm_dcc device as failed The tpdm_dcc device cannot work properly on secure devices because its required clock cannot be enabled due to a hardware issue. Mark the node with status = "fail" to reflect this. Link: https://lore.kernel.org/all/20261008-remove_tpdm_dcc_device-v1-1-48574c6ae6c2@oss.qualcomm.com/ Fixes: eed738c6dd0c ("arm64: dts: qcom: shikra: Add coresight nodes") Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/shikra.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index b4d35d7ff1511..bfa017e4010b3 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -3606,6 +3606,12 @@ label = "tpdm_dcc"; qcom,cmb-element-bits = <32>; + /* + * Clock cannot be properly enabled on secure devices + * due to a hardware issue + */ + status = "fail"; + out-ports { port { tpdm_dcc_out: endpoint { From 3190f1e49758babbff53ae78c1a9ec52c16ca586 Mon Sep 17 00:00:00 2001 From: Gaurav Kohli Date: Thu, 24 Sep 2026 19:52:32 +0530 Subject: [PATCH 0990/1133] FROMLIST: arm64: dts: qcom: shikra: Drop CPU critical trips Shikra firmware handles CPU thermal mitigation up to 117 C, while Linux CPU critical trips trigger at 115 C. This can shut the system down before firmware reaches the end of its mitigation range. Drop the critical trips from the CPU thermal zones and leave the hot trips, non-CPU critical trips and GPUSS passive cooling map unchanged. Signed-off-by: Gaurav Kohli Link: https://lore.kernel.org/r/20260924-shikra_crit_trip-v1-1-730c48fa998e@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra.dtsi | 42 ---------------------------- 1 file changed, 42 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index bfa017e4010b3..60bed61a63076 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -5120,12 +5120,6 @@ hysteresis = <5000>; type = "hot"; }; - - cpu00-critical { - temperature = <115000>; - hysteresis = <0>; - type = "critical"; - }; }; }; @@ -5138,12 +5132,6 @@ hysteresis = <5000>; type = "hot"; }; - - cpu01-critical { - temperature = <115000>; - hysteresis = <0>; - type = "critical"; - }; }; }; @@ -5156,12 +5144,6 @@ hysteresis = <5000>; type = "hot"; }; - - cpu10-critical { - temperature = <115000>; - hysteresis = <0>; - type = "critical"; - }; }; }; @@ -5174,12 +5156,6 @@ hysteresis = <5000>; type = "hot"; }; - - cpu11-critical { - temperature = <115000>; - hysteresis = <0>; - type = "critical"; - }; }; }; @@ -5192,12 +5168,6 @@ hysteresis = <5000>; type = "hot"; }; - - cpuss0-critical { - temperature = <115000>; - hysteresis = <0>; - type = "critical"; - }; }; }; @@ -5392,12 +5362,6 @@ hysteresis = <5000>; type = "hot"; }; - - cpu02-critical { - temperature = <115000>; - hysteresis = <0>; - type = "critical"; - }; }; }; @@ -5410,12 +5374,6 @@ hysteresis = <5000>; type = "hot"; }; - - cpuss1-critical { - temperature = <115000>; - hysteresis = <0>; - type = "critical"; - }; }; }; }; From f660d6ebaf4679952ba2ce5f8d9c1c65bcd8dfbf Mon Sep 17 00:00:00 2001 From: Umang Chheda Date: Fri, 18 Sep 2026 15:27:46 +0530 Subject: [PATCH 0991/1133] FROMLIST: arm64: dts: qcom: shikra: add RAS error source nodes ARM Reliability, Availability and Serviceability (RAS) enables processor components (for eg cache, tlb etc) to record and signal hardware faults through architected error records and fault handling interrupts. This allows software to detect, report and, where possible, recover from hardware errors. The Shikra CPU subsystem implements RAS error records for the L1/L2 cache hierarchy and the shared L3 caches. Describe these error sources in Device Tree so that the ARM RAS framework can discover them and handle cache-related error reports. Co-developed-by: Faruque Ansari Signed-off-by: Faruque Ansari Signed-off-by: Umang Chheda Link: https://lore.kernel.org/r/20260918095746.3347893-6-umang.chheda@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra.dtsi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 60bed61a63076..1938a0a5271c9 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -267,6 +267,26 @@ }; }; + l2-cache-error { + compatible = "arm,ras-processor"; + arm,num-records = <1>; + arm,record-impl = /bits/ 64 <0x1>; + arm,status-reporting = /bits/ 64 <0x1>; + arm,cache-ref = <&l2_3>; + interrupts = ; + interrupt-names = "fhi"; + }; + + l3-cache-error { + compatible = "arm,ras-processor"; + arm,num-records = <2>; + arm,record-impl = /bits/ 64 <0x2>; + arm,status-reporting = /bits/ 64 <0x2>; + arm,cache-ref = <&l3>; + interrupts = ; + interrupt-names = "fhi"; + }; + modem-etm0 { compatible = "arm,coresight-dummy-source"; From 752114751c22d75cc2082887d8001cbda96f743b Mon Sep 17 00:00:00 2001 From: Mohit Dsor Date: Wed, 21 Oct 2026 19:51:44 +0530 Subject: [PATCH 0992/1133] FROMLIST: arm64: dts: qcom: shikra-cqm-evk, shikra-cqs-evk: Add HDMI overlay Add a DT overlay for CQM and CQS, to enable HDMI output when LT9611UXD DSI-to-HDMI daughter card connected to PDISP1 DSI0 on carrier card. LT9611UXD is connected through I2C4, with reset and interrupt connected to tlmm GPIO76 and GPIO85. Disable the default DSI0 panel dt nodes and enable LT9611UXD bridge for HDMI output. Link: https://lore.kernel.org/all/20261021-shikra_display_overlays-v1-1-adaea735999f@oss.qualcomm.com/ Signed-off-by: Mohit Dsor Signed-off-by: Vishnu Saini --- arch/arm64/boot/dts/qcom/Makefile | 6 ++ .../dts/qcom/shikra-cqm-cqs-evk-hdmi.dtso | 90 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-cqm-cqs-evk-hdmi.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index c9ecb57045ff0..43dadf0d95d83 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -394,6 +394,12 @@ shikra-iqs-evk-imx577-camera-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-imx577-ca dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-imx577-camera.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-imx577-camera.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-imx577-camera.dtb + +shikra-cqm-evk-hdmi-dtbs := shikra-cqm-evk.dtb shikra-cqm-cqs-evk-hdmi.dtbo +shikra-cqs-evk-hdmi-dtbs := shikra-cqs-evk.dtb shikra-cqm-cqs-evk-hdmi.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-hdmi.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-hdmi.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4250-oneplus-billie2.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4450-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += sm6115-fxtec-pro1x.dtb diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-cqs-evk-hdmi.dtso b/arch/arm64/boot/dts/qcom/shikra-cqm-cqs-evk-hdmi.dtso new file mode 100644 index 0000000000000..a7b77114061a5 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-cqs-evk-hdmi.dtso @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&{/} { + model = "Qualcomm Technologies, Inc. Shikra CQM/S EVK HDMI"; + + hdmi-connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_connector_out: endpoint { + remote-endpoint = <&hdmi_bridge_out>; + }; + }; + }; +}; + +&i2c4 { + #address-cells = <1>; + #size-cells = <0>; + + status = "okay"; + + hdmi-bridge@41 { + compatible = "lontium,lt9611uxd"; + reg = <0x41>; + interrupts-extended = <&tlmm 85 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&tlmm 76 GPIO_ACTIVE_LOW>; + vcc-supply = <&lcd_bias>; + vdd-supply = <&pm4125_l15>; + pinctrl-0 = <&bridge_irq_pin &bridge_rst_pin>; + pinctrl-names = "default"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + hdmi_bridge_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + hdmi_bridge_out: endpoint { + remote-endpoint = <&hdmi_connector_out>; + }; + }; + }; + }; +}; + +&mdss_dsi0 { + panel@0 { + status = "disabled"; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&hdmi_bridge_in>; +}; + +&tlmm { + bridge_rst_pin: bridge-rst-state { + pins = "gpio76"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + bridge_irq_pin: bridge-irq-state { + pins = "gpio85"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; +}; From 40b7f204e96f9d3a4d3c05b483034f596b13ba4e Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Wed, 21 Oct 2026 19:51:45 +0530 Subject: [PATCH 0993/1133] FROMLIST: arm64: dts: qcom: shikra-iqs-evk: Add DLC0697 panel overlay Add a DT overlay for IQS, to enable DLC0697 panel when DLC daughter card connected to PDISP1 DSI0 on carrier card. Configure DLC0697 reset GPIO, supplies, pinctrl states and GPIO backlight controlled through PM8150 GPIO 1. Disable the default HDMI bridge and connector in favour of the DSI panel. Link: https://lore.kernel.org/all/20261021-shikra_display_overlays-v1-2-adaea735999f@oss.qualcomm.com/ Signed-off-by: Vishnu Saini --- arch/arm64/boot/dts/qcom/Makefile | 3 + .../dts/qcom/shikra-iqs-evk-dlc-panel.dtso | 78 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-iqs-evk-dlc-panel.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 43dadf0d95d83..9de24c894d1a6 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -397,9 +397,12 @@ dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-imx577-camera.dtb shikra-cqm-evk-hdmi-dtbs := shikra-cqm-evk.dtb shikra-cqm-cqs-evk-hdmi.dtbo shikra-cqs-evk-hdmi-dtbs := shikra-cqs-evk.dtb shikra-cqm-cqs-evk-hdmi.dtbo +shikra-iqs-evk-dlc-panel-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-dlc-panel.dtbo dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-hdmi.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-hdmi.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-dlc-panel.dtb + dtb-$(CONFIG_ARCH_QCOM) += sm4250-oneplus-billie2.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4450-qrd.dtb dtb-$(CONFIG_ARCH_QCOM) += sm6115-fxtec-pro1x.dtb diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-dlc-panel.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-dlc-panel.dtso new file mode 100644 index 0000000000000..2542abe59d340 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-dlc-panel.dtso @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&{/} { + model = "Qualcomm Technologies, Inc. Shikra IQS EVK DLC Panel"; + + backlight: backlight { + compatible = "gpio-backlight"; + gpios = <&pm8150_gpios 1 GPIO_ACTIVE_HIGH>; + default-on; + }; +}; + +&hdmi_bridge { + status = "disabled"; +}; + +&hdmi_connector { + status = "disabled"; +}; + +&mdss_dsi0 { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "dlc,dlc0697", "ilitek,ili7807s"; + reg = <0>; + backlight = <&backlight>; + reset-gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + vddi-supply = <&pm8150_l15>; + avdd-supply = <&vreg_disp_3p3>; + avee-supply = <&vreg_disp_3p3>; + pinctrl-0 = <&panel_rst_n &panel_te_pin>; + pinctrl-1 = <&panel_rst_n_suspend>; + pinctrl-names = "default", "sleep"; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; +}; + +&tlmm { + panel_rst_n: panel-rst-n-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + }; + + panel_rst_n_suspend: panel-rst-n-suspend-state { + pins = "gpio3"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + panel_te_pin: panel-te-pin-state { + pins = "gpio86"; + function = "mdp_vsync_p"; + drive-strength = <2>; + bias-pull-down; + }; +}; From 58ac1e6bcc98d682c6fb57f5758d8abcf5d8b73f Mon Sep 17 00:00:00 2001 From: Anand Tiwari Date: Wed, 21 Oct 2026 19:51:46 +0530 Subject: [PATCH 0994/1133] FROMLIS: arm64: dts: qcom: shikra-iqs-evk: Add AUO G133HAN01 LVDS panel overlay Add a DT overlay for IQS, to enable LVDS interface when LVDS daughter card is connected to PDISP1 DSI0 on carrier card. There is SN65DSI84 DSI-to-LVDS bridge on the daughter card which is connected through I2C3 with reset and interrupt connected to tlmm GPIO76 and GPIO85. Backlight is connected to gpio87 with pdm_pwm functionality. Currently this is not supported in linux-next yet, so pull the gpio high. Enable support for AUO G133HAN01 LVDS panel connected to this daughter card and disable the default HDMI bridge and connector in favour of the LVDS panel. Signed-off-by: Anand Tiwari Signed-off-by: Vishnu Saini Link: https://lore.kernel.org/r/20261021-shikra_display_overlays-v1-3-adaea735999f@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../shikra-iqs-evk-lvds-auo,g133han01.dtso | 127 ++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-iqs-evk-lvds-auo,g133han01.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 9de24c894d1a6..d1d5446929b6a 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -398,10 +398,12 @@ dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-imx577-camera.dtb shikra-cqm-evk-hdmi-dtbs := shikra-cqm-evk.dtb shikra-cqm-cqs-evk-hdmi.dtbo shikra-cqs-evk-hdmi-dtbs := shikra-cqs-evk.dtb shikra-cqm-cqs-evk-hdmi.dtbo shikra-iqs-evk-dlc-panel-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-dlc-panel.dtbo +shikra-iqs-evk-lvds-auo,g133han01-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-lvds-auo,g133han01.dtbo dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-hdmi.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-hdmi.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-dlc-panel.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-lvds-auo,g133han01.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4250-oneplus-billie2.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4450-qrd.dtb diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-lvds-auo,g133han01.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-lvds-auo,g133han01.dtso new file mode 100644 index 0000000000000..80b9dcc920612 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-lvds-auo,g133han01.dtso @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&{/} { + backlight { + compatible = "gpio-backlight"; + gpios = <&pm8150_gpios 1 GPIO_ACTIVE_HIGH>; + default-on; + pinctrl-0 = <&backlight_pwm>; + pinctrl-names = "default"; + }; + + panel-lvds { + compatible = "auo,g133han01"; + power-supply = <&vreg_lvds_3p3>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dual-lvds-odd-pixels; + + lvds_panel_out_a: endpoint { + remote-endpoint = <&sn65dsi84_out_a>; + }; + }; + + port@1 { + reg = <1>; + dual-lvds-even-pixels; + + lvds_panel_out_b: endpoint { + remote-endpoint = <&sn65dsi84_out_b>; + }; + }; + }; + }; + + vreg_bridge_1p8: regulator-bridge-1p8 { + compatible = "regulator-fixed"; + regulator-name = "vreg_bridge_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vreg_lvds_3p3: regulator-lvds-3p3 { + compatible = "regulator-fixed"; + regulator-name = "vreg_lvds_3p3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&hdmi_bridge { + status = "disabled"; +}; + +&hdmi_connector { + status = "disabled"; +}; + +&i2c3 { + #address-cells = <1>; + #size-cells = <0>; + + bridge@2c { + compatible = "ti,sn65dsi84"; + reg = <0x2c>; + enable-gpios = <&tlmm 76 GPIO_ACTIVE_HIGH>; + interrupts-extended = <&tlmm 85 IRQ_TYPE_EDGE_FALLING>; + vcc-supply = <&vreg_bridge_1p8>; + pinctrl-0 = <&bridge_irq_pin &bridge_rst_pin>; + pinctrl-names = "default"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + sn65dsi84_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + data-lanes = <1 2 3 4>; + }; + }; + + port@2 { + reg = <2>; + + sn65dsi84_out_a: endpoint { + remote-endpoint = <&lvds_panel_out_a>; + }; + }; + + port@3 { + reg = <3>; + + sn65dsi84_out_b: endpoint { + remote-endpoint = <&lvds_panel_out_b>; + }; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&sn65dsi84_in>; +}; + +&tlmm { + backlight_pwm: backlight-pwm-state { + pins = "gpio87"; + function = "gpio"; + bias-pull-up; + }; +}; From f8fd4ecf2a8431d22c53277a4208029f444d46e3 Mon Sep 17 00:00:00 2001 From: Shashank Maurya Date: Wed, 21 Oct 2026 19:51:48 +0530 Subject: [PATCH 0995/1133] FROMLIST: arm64: dts: qcom: shikra-iqs-evk: Add RPi 7-inch DSI panel overlay Add a DT overlay to enable Raspberry Pi 7-inch DSI panel connected to DSI 22pin on the carrier card. DSI0 from SOC is routed through MUX which can be selected by DIP switch S1016.5 ON for enabling this 22-pin JDISP1 DSI0 connector. Add the regulator and backlight controller at I2C4 address 0x45, Goodix GT911 touch controller, panel power and reset control, and a 2-lane DSI connection. Disable the default HDMI bridge and connector in favour of the RPi DSI panel. Link: https://lore.kernel.org/all/20261021-shikra_display_overlays-v1-5-adaea735999f@oss.qualcomm.com/ Signed-off-by: Shashank Maurya Signed-off-by: Vishnu Saini --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../shikra-iqs-evk-raspberrypi-dsi-7inch.dtso | 91 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-iqs-evk-raspberrypi-dsi-7inch.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index d1d5446929b6a..67801cad77f51 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -399,11 +399,13 @@ shikra-cqm-evk-hdmi-dtbs := shikra-cqm-evk.dtb shikra-cqm-cqs-evk-hdmi.dtbo shikra-cqs-evk-hdmi-dtbs := shikra-cqs-evk.dtb shikra-cqm-cqs-evk-hdmi.dtbo shikra-iqs-evk-dlc-panel-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-dlc-panel.dtbo shikra-iqs-evk-lvds-auo,g133han01-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-lvds-auo,g133han01.dtbo +shikra-iqs-evk-raspberrypi-dsi-7inch-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-raspberrypi-dsi-7inch.dtbo dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-hdmi.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-hdmi.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-dlc-panel.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-lvds-auo,g133han01.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-raspberrypi-dsi-7inch.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4250-oneplus-billie2.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4450-qrd.dtb diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-raspberrypi-dsi-7inch.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-raspberrypi-dsi-7inch.dtso new file mode 100644 index 0000000000000..383dc5aadcfd9 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-raspberrypi-dsi-7inch.dtso @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&{/} { + model = "Qualcomm Technologies, Inc. Shikra IQS EVK Raspberry Pi 7inch DSI Panel"; + + display_bl: backlight { + compatible = "pwm-backlight"; + power-supply = <®_display>; + pwms = <&mcu 0 255 0>; + }; + + reg_display: regulator-display { + compatible = "regulator-fixed"; + regulator-name = "rpi-display"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + reg_dsi_touch: regulator-dsi-touch { + compatible = "regulator-fixed"; + gpio = <&mcu 1 GPIO_ACTIVE_HIGH>; + regulator-name = "rpi-touch"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <50000>; + enable-active-high; + }; +}; + +&hdmi_bridge { + status = "disabled"; +}; + +&hdmi_connector { + status = "disabled"; +}; + +&i2c4 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + mcu: gpio@45 { + compatible = "raspberrypi,touchscreen-panel-regulator-v2"; + reg = <0x45>; + gpio-controller; + #gpio-cells = <2>; + #pwm-cells = <3>; + }; + + touchscreen@5d { + compatible = "goodix,gt911"; + reg = <0x5d>; + AVDD28-supply = <®_dsi_touch>; + touchscreen-size-x = <720>; + touchscreen-size-y = <1280>; + }; +}; + +&mdss_dsi0 { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "raspberrypi,dsi-7inch", "ilitek,ili9881c"; + reg = <0>; + reset-gpios = <&mcu 0 GPIO_ACTIVE_LOW>; + power-supply = <®_display>; + iovcc-supply = <&pm8150_s4>; + backlight = <&display_bl>; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + data-lanes = <0 1>; + remote-endpoint = <&panel_in>; +}; From 0418a8035aa425da5f53ccbed29b200a324e3009 Mon Sep 17 00:00:00 2001 From: Shashank Maurya Date: Wed, 21 Oct 2026 19:51:50 +0530 Subject: [PATCH 0996/1133] FROMLIST: arm64: dts: qcom: shikra-iqs-evk: Add Waveshare 8-inch DSI panel overlay Add a DT overlay to enable Waveshare 8-inch DSI panel connected to DSI 22pin on the carrier card. DSI0 from SOC is routed through MUX which can be selected by DIP switch S1016.5 ON, for enabling this 22-pin JDISP1 DSI0 connector. Add the JD9365DA-H3 panel, GPIO expander at I2C4 address 0x45 for panel power, reset and backlight, and the Goodix GT9271 touch controller. Disable the default HDMI bridge and connector in favour of the Waveshare DSI panel. Link: https://lore.kernel.org/all/20261021-shikra_display_overlays-v1-7-adaea735999f@oss.qualcomm.com/ Signed-off-by: Shashank Maurya Signed-off-by: Vishnu Saini --- arch/arm64/boot/dts/qcom/Makefile | 2 + .../shikra-iqs-evk-waveshare-dsi-8inch.dtso | 77 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-iqs-evk-waveshare-dsi-8inch.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 67801cad77f51..e21d9d401463b 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -400,12 +400,14 @@ shikra-cqs-evk-hdmi-dtbs := shikra-cqs-evk.dtb shikra-cqm-cqs-evk-hdmi.dtbo shikra-iqs-evk-dlc-panel-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-dlc-panel.dtbo shikra-iqs-evk-lvds-auo,g133han01-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-lvds-auo,g133han01.dtbo shikra-iqs-evk-raspberrypi-dsi-7inch-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-raspberrypi-dsi-7inch.dtbo +shikra-iqs-evk-waveshare-dsi-8inch-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-waveshare-dsi-8inch.dtbo dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-hdmi.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-hdmi.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-dlc-panel.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-lvds-auo,g133han01.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-raspberrypi-dsi-7inch.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-waveshare-dsi-8inch.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4250-oneplus-billie2.dtb dtb-$(CONFIG_ARCH_QCOM) += sm4450-qrd.dtb diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-waveshare-dsi-8inch.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-waveshare-dsi-8inch.dtso new file mode 100644 index 0000000000000..d0aa115681ffd --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-waveshare-dsi-8inch.dtso @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&{/} { + model = "Qualcomm Technologies, Inc. Shikra IQS EVK Waveshare 8inch DSI Panel"; + + panel_avdd: regulator-panel-avdd { + compatible = "regulator-fixed"; + regulator-name = "panel-avdd"; + gpios = <&wsgpio 0 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + panel_iovcc: regulator-panel-iovcc { + compatible = "regulator-fixed"; + regulator-name = "panel-iovcc"; + gpios = <&wsgpio 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&hdmi_bridge { + status = "disabled"; +}; + +&hdmi_connector { + status = "disabled"; +}; + +&i2c4 { + #address-cells = <1>; + #size-cells = <0>; + + wsgpio: gpio@45 { + compatible = "waveshare,dsi-touch-gpio"; + reg = <0x45>; + gpio-controller; + #gpio-cells = <2>; + }; + + touchscreen@5d { + compatible = "goodix,gt9271"; + reg = <0x5d>; + reset-gpios = <&wsgpio 9 GPIO_ACTIVE_HIGH>; + }; +}; + +&mdss_dsi0 { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "waveshare,8.0-dsi-touch-a", "jadard,jd9365da-h3"; + reg = <0>; + reset-gpios = <&wsgpio 1 GPIO_ACTIVE_LOW>; + vccio-supply = <&panel_iovcc>; + vdd-supply = <&panel_avdd>; + backlight = <&wsgpio>; + + port { + panel_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; +}; + +&mdss_dsi0_out { + remote-endpoint = <&panel_in>; +}; From 29c1ad43b45c6a548e85818e3c62d17e87cf633a Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Thu, 27 Aug 2026 00:08:31 +0530 Subject: [PATCH 0997/1133] PENDING: arm64: dts: qcom: shikra: Add EL2 support for Iris Add support for IRIS on shikra when Linux host running at EL2. Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/shikra-el2.dtso | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-el2.dtso b/arch/arm64/boot/dts/qcom/shikra-el2.dtso index a0f7c4a635ada..8bbf099e9d5e3 100644 --- a/arch/arm64/boot/dts/qcom/shikra-el2.dtso +++ b/arch/arm64/boot/dts/qcom/shikra-el2.dtso @@ -12,6 +12,12 @@ status = "disabled"; }; +&iris { + video-firmware { + iommus = <&apps_smmu 0x07a2 0x0>; + }; +}; + &remoteproc_cdsp { iommus = <&apps_smmu 0x0200 0x0>; }; From a2e9d93d676ca5ae4b9f995827b84795b7b20104 Mon Sep 17 00:00:00 2001 From: Linghui Wu Date: Mon, 19 Oct 2026 05:48:29 +0000 Subject: [PATCH 0998/1133] FROMLIST: arm64: dts: qcom: shikra: enable WCN SW_CTRL wakeup The WCN3988 SW_CTRL signal can wake the application processor on the Shikra CQM, CQS and IQS EVKs. Mark the WCN power sequencer as a wakeup source so the driver uses the existing SW_CTRL GPIO as a dedicated wake IRQ. Link: https://lore.kernel.org/r/20261019093911.3199891-4-linghui.wu@oss.qualcomm.com Signed-off-by: Linghui Wu --- arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 1 + arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi index 47ff2c8032652..80af80c565f73 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -102,6 +102,7 @@ pinctrl-names = "default"; swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + wakeup-source; vddio-supply = <&pm4125_l7>; vddxo-supply = <&pm4125_l13>; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi index a0e7c4d962c30..983af97c6080d 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-som.dtsi @@ -85,6 +85,7 @@ pinctrl-names = "default"; swctrl-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; + wakeup-source; vddio-supply = <&pm8150_s4>; vddxo-supply = <&pm8150_l12>; From c213762d113bc6019e72a418ec678cb852612c3d Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 26 Oct 2026 17:49:45 +0530 Subject: [PATCH 0999/1133] FROMLIST: arm64: dts: qcom: shikra: Add QAIF CPU node for audio Add the QAIF CPU endpoint in shikra.dtsi so board files can connect LPASS front-end links to backend codecs. Describe the MMIO region, interrupt, IOMMU mapping and required clocks for the QAIF block. Link: https://lore.kernel.org/all/20261026-shikra_audio_dts-v4-v4-1-cfebe0809467@oss.qualcomm.com/ Reviewed-by: Konrad Dybcio Co-developed-by: Harendra Gautam Signed-off-by: Harendra Gautam Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/boot/dts/qcom/shikra.dtsi | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 1938a0a5271c9..f3f7f9ec1e8cb 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -19,6 +19,7 @@ #include #include #include +#include #include / { @@ -3581,6 +3582,40 @@ #power-domain-cells = <1>; }; + qaif_cpu: audio@a000000 { + compatible = "qcom,shikra-qaif-cpu"; + reg = <0x0 0x0a000000 0x0 0x20000>; + + interrupts = ; + + clocks = <&gcc GCC_LPASS_CONFIG_CLK>, + <&gcc GCC_LPASS_CORE_AXIM_CLK>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_CLK>, + <&audiocorecc AUDIO_CORE_CC_AUD_DMA_MEM_CLK>, + <&audiocorecc AUDIO_CORE_CC_BUS_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF0_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF1_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF2_IBIT_CLK>, + <&audiocorecc AUDIO_CORE_CC_AIF_IF3_IBIT_CLK>; + clock-names = "lpass_config", + "lpass_core_axim", + "aud_dma", + "aud_dma_mem", + "bus", + "aif_if0_ibit", + "aif_if1_ibit", + "aif_if2_ibit", + "aif_if3_ibit"; + + iommus = <&apps_smmu 0x1c0 0x0>; + + #sound-dai-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + ctcu@8001000 { compatible = "qcom,shikra-ctcu", "qcom,sa8775p-ctcu"; reg = <0x0 0x08001000 0x0 0x1000>; From 533e498840e56b7ee778b5f15be7fc9c96590740 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 26 Oct 2026 17:14:30 +0530 Subject: [PATCH 1000/1133] FROMLIST: arm64: dts: qcom: shikra: Add gpr node Add GPR (Generic Packet Router) node along with APM (Audio Process Manager) and PRM (Proxy Resource Manager) audio services. Add a dedicated MDSP carveout memory region for audio usecases on Shikra and mark both existing audio heap and MDSP carveout regions as shared DMA pools. Update the Q6 APM DAI node to reference multiple memory regions, where index 0 is used for control path buffers and index 1 is used for MDSP data path buffers. This separation ensures proper memory allocation and access for APM communication between APSS and MDSP. Also add shared-dma-pool compatibility to the existing audio heap region to align with upstream DMA pool usage. Reviewed-by: Konrad Dybcio Co-developed-by: Ajay Kumar Nandam Signed-off-by: Ajay Kumar Nandam Signed-off-by: Mohammad Rafi Shaik Link: https://lore.kernel.org/r/20261026-shikra_audio_dts-v4-v4-2-cfebe0809467@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra.dtsi | 49 +++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index f3f7f9ec1e8cb..a83f1cf21c236 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include @@ -438,7 +440,14 @@ }; audio_heap_mem: audio-heap@86200000 { - reg = <0x0 0x86200000 0x0 0x100000>; + compatible = "shared-dma-pool"; + reg = <0x0 0x86200000 0x0 0x40000>; + no-map; + }; + + audio_mdsp_carveout_mem: audio-mdsp-carveout@86240000 { + compatible = "shared-dma-pool"; + reg = <0x0 0x86240000 0x0 0x100000>; no-map; }; @@ -2795,6 +2804,44 @@ mboxes = <&apcs_glb 12>; qcom,remote-pid = <1>; label = "mpss"; + + gpr: gpr { + compatible = "qcom,gpr"; + qcom,glink-channels = "modem_apps"; + qcom,domain = ; + qcom,intents = <200 20>; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + q6apm: service@1 { + compatible = "qcom,q6apm"; + reg = ; + #sound-dai-cells = <0>; + + q6apmbedai: bedais { + compatible = "qcom,q6apm-lpass-dais"; + #sound-dai-cells = <1>; + }; + + q6apmdai: dais { + compatible = "qcom,q6apm-dais"; + memory-region = <&audio_heap_mem + &audio_mdsp_carveout_mem>; + }; + }; + + q6prm: service@2 { + compatible = "qcom,q6prm"; + reg = ; + + q6prmcc: clock-controller { + compatible = "qcom,q6prm-lpass-clocks"; + #clock-cells = <2>; + }; + }; + }; }; bam_dmux: bam-dmux { From fd41ee7f5b3433706a4e78b5ee237fa652290910 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 26 Oct 2026 17:14:31 +0530 Subject: [PATCH 1001/1133] FROMLIST: arm64: dts: qcom: shikra: Add soundwire and macro nodes Add SoC-level SoundWire masters and LPASS RX/VA macro nodes, along with DMIC and SWR pinctrl states required by the audio data path. Signed-off-by: Mohammad Rafi Shaik Link: https://lore.kernel.org/r/20261026-shikra_audio_dts-v4-v4-3-cfebe0809467@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra.dtsi | 172 +++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index a83f1cf21c236..3a650e5b6c5ea 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1089,6 +1089,70 @@ drive-strength = <2>; bias-pull-up; }; + + dmic01_default: dmic01-default-state { + clk-pins { + pins = "gpio96"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio97"; + function = "dmic"; + drive-strength = <8>; + bias-disable; + }; + }; + + dmic23_default: dmic23-default-state { + clk-pins { + pins = "gpio98"; + function = "dmic"; + drive-strength = <8>; + output-high; + }; + + data-pins { + pins = "gpio99"; + function = "dmic"; + drive-strength = <8>; + bias-disable; + }; + }; + + tx_swr_active: tx-swr-active-state { + clk-pins { + pins = "gpio105"; + function = "swr0_tx"; + drive-strength = <8>; + bias-disable; + }; + + data-pins { + pins = "gpio106"; + function = "swr0_tx"; + drive-strength = <8>; + bias-bus-hold; + }; + }; + + rx_swr_active: rx-swr-active-state { + clk-pins { + pins = "gpio107"; + function = "swr0_rx"; + drive-strength = <8>; + bias-disable; + }; + + data-pins { + pins = "gpio108", "gpio109"; + function = "swr0_rx"; + drive-strength = <8>; + bias-bus-hold; + }; + }; }; pmu@c91000 { @@ -4924,6 +4988,114 @@ label = "cti_apss_2"; }; + rxmacro: codec@a040000 { + compatible = "qcom,shikra-lpass-rx-macro"; + reg = <0x0 0x0a040000 0x0 0x1000>; + + clocks = <&audiocorecc AUDIO_CORE_CC_RX_MCLK_CLK>, + <&audiocorecc AUDIO_CORE_CC_RX_MCLK_2X_CLK>, + <&vamacro>; + clock-names = "mclk", + "npl", + "fsgen"; + + #clock-cells = <0>; + clock-output-names = "mclk"; + #sound-dai-cells = <1>; + + status = "disabled"; + }; + + swr0: soundwire@a060000 { + compatible = "qcom,shikra-soundwire"; + reg = <0x0 0x0a060000 0x0 0x10000>; + + interrupts = ; + + clocks = <&rxmacro>; + clock-names = "iface"; + label = "RX"; + + pinctrl-0 = <&rx_swr_active>; + pinctrl-names = "default"; + + qcom,din-ports = <0>; + qcom,dout-ports = <5>; + + resets = <&audiocore_csr AUDIO_CORE_CSR_RX_SWR_CGCR>; + reset-names = "swr_audio_cgcr"; + + qcom,ports-sinterval-low = /bits/ 8 <0x03 0x1f 0x1f 0x07 0x00>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0b 0x01 0x00>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0b 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0x03 0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0x06 0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0x00 0x01 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0x00>; + qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00 0x00>; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + + status = "disabled"; + }; + + vamacro: codec@a078000 { + compatible = "qcom,shikra-lpass-va-macro"; + reg = <0x0 0x0a078000 0x0 0x2000>; + + clocks = <&audiocorecc AUDIO_CORE_CC_TX_MCLK_CLK>, + <&audiocorecc AUDIO_CORE_CC_TX_MCLK_2X_CLK>; + clock-names = "mclk", + "npl"; + + #clock-cells = <0>; + clock-output-names = "fsgen"; + #sound-dai-cells = <1>; + + status = "disabled"; + }; + + swr1: soundwire@a080000 { + compatible = "qcom,shikra-soundwire"; + reg = <0x0 0x0a080000 0x0 0x10000>; + + interrupts = , + ; + interrupt-names = "core", "wakeup"; + + clocks = <&vamacro>; + clock-names = "iface"; + label = "VA_TX"; + + pinctrl-0 = <&tx_swr_active>; + pinctrl-names = "default"; + + qcom,din-ports = <4>; + qcom,dout-ports = <0>; + + resets = <&audiocore_csr AUDIO_CORE_CSR_TX_SWR_CGCR>; + reset-names = "swr_audio_cgcr"; + + qcom,ports-sinterval-low = /bits/ 8 <0x01 0x03 0x03 0x03>; + qcom,ports-offset1 = /bits/ 8 <0x00 0x01 0x01 0x01>; + qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x00 0x00>; + qcom,ports-hstart = /bits/ 8 <0xff 0xff 0xff 0xff>; + qcom,ports-hstop = /bits/ 8 <0xff 0xff 0xff 0xff>; + qcom,ports-word-length = /bits/ 8 <0xff 0xff 0xff 0xff>; + qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0xff 0xff>; + qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff>; + qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00>; + + #sound-dai-cells = <1>; + #address-cells = <2>; + #size-cells = <0>; + + status = "disabled"; + }; + audiocorecc: clock-controller@a0a0000 { compatible = "qcom,shikra-audiocorecc"; reg = <0x0 0x0a0a0000 0x0 0x10000>; From 66ccfd530a63e3ef25ffb9849ba3aa956ecf21ef Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 26 Oct 2026 17:14:32 +0530 Subject: [PATCH 1002/1133] FROMLIST: arm64: dts: qcom: shikra-cqm-evk: Enable sound card support Enable the sound card on the shikra-cqm-evk platform, including the PM4125 (Rouleur) headset codec, WSA885x external speaker path, and QAIF backend links. Also enable the required LPASS macro and SoundWire nodes, along with the necessary pinctrl configurations for DMIC and I2S interfaces. Signed-off-by: Mohammad Rafi Shaik Link: https://lore.kernel.org/r/20261026-shikra_audio_dts-v4-v4-4-cfebe0809467@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts | 195 +++++++++++++++++++ arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi | 5 + 2 files changed, 200 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts index 106f3ce838706..10af5c4cf780a 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-evk.dts @@ -66,6 +66,85 @@ gpio = <&tlmm 91 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + sound: sound { + compatible = "qcom,shikra-cqm-sndcard"; + model = "shikra-cqm-evk"; + + audio-routing = "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC1", "MIC BIAS1", + "AMIC2", "MIC BIAS2", + "AMIC3", "MIC BIAS3", + "VA SWR_ADC0", "ADC1_OUTPUT", + "VA SWR_ADC1", "ADC2_OUTPUT", + "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + pinctrl-0 = <&i2s2_default>, <&dmic_eldo_en_default>; + pinctrl-names = "default"; + + headset-capture-dai-link { + link-name = "Headphones Capture"; + + codec { + sound-dai = <&pmic4125_codec 1>, + <&swr1 0>, + <&vamacro 0>; + }; + + cpu { + sound-dai = <&qaif_cpu VA_CODEC_DMA_TX_1>; + }; + }; + + headset-playback-dai-link { + link-name = "Headphones Playback"; + + codec { + sound-dai = <&pmic4125_codec 0>, + <&swr0 0>, + <&rxmacro 0>; + }; + + cpu { + sound-dai = <&qaif_cpu RX_CODEC_DMA_RX_1>; + }; + }; + + wsa-speaker-dai-link { + link-name = "WSA Speaker Playback"; + + codec { + sound-dai = <&wsa8855>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; + }; + + cpu { + sound-dai = <&qaif_cpu AIF_TDM_RX_2>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-tx-mask = <1 1>; + }; + }; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + + codec { + sound-dai = <&vamacro 0>; + }; + + cpu { + sound-dai = <&qaif_cpu VA_CODEC_DMA_TX_0>; + }; + }; + }; }; &audiocorecc { @@ -189,6 +268,27 @@ status = "okay"; }; +&i2c3 { + status = "okay"; + + wsa8855: speaker@c { + compatible = "qcom,wsa8855"; + reg = <0x0c>; + + pinctrl-0 = <&wsa8855_spkr_sd_n>; + pinctrl-names = "default"; + + powerdown-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + interrupt-parent = <&tlmm>; + interrupts = <77 IRQ_TYPE_EDGE_FALLING>; + vdd-1p8-supply = <&pm4125_l15>; + vdd-io-supply = <&pm4125_l15>; + qcom,battery-config = "1s"; + + #sound-dai-cells = <0>; + }; +}; + &pm4125_hs_in { remote-endpoint = <&usb_1_dwc3_hs>; }; @@ -197,6 +297,20 @@ remote-endpoint = <&usb_qmpphy_out>; }; +&qaif_cpu { + status = "okay"; + + aif@b5 { + reg = ; + dai-format = "dsp_a"; + dai-tdm-slot-width = <32>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-tx-mask = <1 1>; + qcom,qaif-aif-lane-map = <1 0>; + }; +}; + &remoteproc_cdsp { firmware-name = "qcom/shikra/cdsp.mbn"; @@ -216,6 +330,10 @@ status = "okay"; }; +&rxmacro { + status = "okay"; +}; + &sdhc_1 { vmmc-supply = <&pm4125_l20>; vqmmc-supply = <&pm4125_l14>; @@ -329,3 +447,80 @@ status = "okay"; }; + +&spmi_bus { + pmic@0 { + pmic4125_codec: audio-codec@f000 { + compatible = "qcom,pm4125-codec"; + reg = <0xf000>; + vdd-io-supply = <&pm4125_l15>; + vdd-cp-supply = <&pm4125_s1>; + vdd-pa-vpos-supply = <&pm4125_s1>; + + vdd-mic-bias-supply = <&pm4125_l22>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + + qcom,rx-device = <&pm4125_rx>; + qcom,tx-device = <&pm4125_tx>; + #sound-dai-cells = <1>; + + status = "okay"; + }; + }; +}; + +&swr0 { + status = "okay"; + + pm4125_rx: codec@0,4 { + compatible = "sdw20217010c00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5>; + }; +}; + +&swr1 { + status = "okay"; + + pm4125_tx: codec@0,3 { + compatible = "sdw20217010c00"; + reg = <0 3>; + qcom,tx-port-mapping = <2 3>; + }; +}; + +&tlmm { + dmic_eldo_en_default: dmic-eldo-default-active-state { + pins = "gpio71"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + i2s2_default: i2s2-default-active-state { + pins = "gpio100", "gpio101", "gpio102", "gpio103"; + function = "i2s2"; + drive-strength = <8>; + output-high; + bias-disable; + }; + + wsa8855_spkr_sd_n: wsa8855-spkr-sd-n-active-state { + pins = "gpio2"; + function = "gpio"; + input-disable; + output-enable; + }; +}; + +&vamacro { + pinctrl-0 = <&dmic01_default>, <&dmic23_default>; + pinctrl-names = "default"; + + qcom,dmic-sample-rate = <4800000>; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi index 80af80c565f73..96018e9b3486c 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra-cqm-som.dtsi @@ -300,6 +300,11 @@ regulators { compatible = "qcom,rpm-pm2250-regulators"; + pm4125_s1: s1 { + regulator-min-microvolt = <1396000>; + regulator-max-microvolt = <1396000>; + }; + pm4125_s2: s2 { regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1200000>; From 7a97af5d6ab813cd9f9f6c8e6bdb281fb7873996 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 26 Oct 2026 17:59:57 +0530 Subject: [PATCH 1003/1133] FROMLIST: arm64: dts: qcom: shikra-cqs-evk: Enable sound card support Enable the sound card on the shikra-cqs-evk platform, including the PM4125 (Rouleur) headset codec, WSA885x speaker amp. Also enable the required LPASS macro and SoundWire nodes, along with the necessary pinctrl configurations for DMIC and I2S interfaces. Also enable the required LPASS macro along with the necessary pinctrl configurations for DMIC and I2S interfaces. Link: https://lore.kernel.org/all/20261026-shikra_audio_dts-v4-v4-5-cfebe0809467@oss.qualcomm.com/ Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts | 224 ++++++++++++++++++++ 1 file changed, 224 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts index 737a5e411c6f7..fbd32190052af 100644 --- a/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-cqs-evk.dts @@ -66,6 +66,125 @@ gpio = <&tlmm 91 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + sound { + compatible = "qcom,shikra-cqs-sndcard"; + model = "shikra-cqs-evk"; + + pinctrl-0 = <&i2s2_default>, <&dmic_eldo_en_default>; + pinctrl-names = "default"; + + audio-routing = "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb", + "VA SWR_ADC0", "ADC1_OUTPUT", + "VA SWR_ADC1", "ADC2_OUTPUT", + "AMIC1", "MIC BIAS1", + "AMIC2", "MIC BIAS2", + "AMIC3", "MIC BIAS3", + "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT"; + + wcd-playback-dai-link { + link-name = "Headphones Playback"; + + codec { + sound-dai = <&pmic4125_codec 0>, + <&swr0 0>, + <&rxmacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_1>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-capture-dai-link { + link-name = "Headphones capture"; + + codec { + sound-dai = <&pmic4125_codec 1>, + <&swr1 0>, + <&vamacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_1>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + + codec { + sound-dai = <&vamacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wsa-playback-dai-link { + link-name = "WSA Playback"; + + codec { + sound-dai = <&wsa8855>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; + }; + + cpu { + sound-dai = <&q6apmbedai AIF_TDM_RX_2>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-rx-mask = <1 1>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; +}; + +&gpr { + status = "okay"; +}; + +&i2c3 { + status = "okay"; + + wsa8855: speaker@c { + compatible = "qcom,wsa8855"; + reg = <0x0c>; + + pinctrl-0 = <&wsa8855_spkr_sd_n>; + pinctrl-names = "default"; + + powerdown-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + interrupt-parent = <&tlmm>; + interrupts = <77 IRQ_TYPE_EDGE_FALLING>; + vdd-1p8-supply = <&pm4125_l15>; + vdd-io-supply = <&pm4125_l15>; + qcom,battery-config = "1s"; + + #sound-dai-cells = <0>; + }; }; ðernet0 { @@ -193,6 +312,16 @@ remote-endpoint = <&usb_qmpphy_out>; }; +&q6apmbedai { + #address-cells = <1>; + #size-cells = <0>; + dai@183 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_QAIF_IF2_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; +}; + &remoteproc_cdsp { firmware-name = "qcom/shikra/cdsp.mbn"; @@ -212,6 +341,18 @@ status = "okay"; }; +&rxmacro { + clocks = <&q6prmcc LPASS_CLK_ID_RX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&q6prmcc LPASS_CLK_ID_RX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>, + <&vamacro>; + + clock-names = "mclk", + "npl", + "fsgen"; + + status = "okay"; +}; + &sdhc_1 { vmmc-supply = <&pm4125_l20>; vqmmc-supply = <&pm4125_l14>; @@ -325,3 +466,86 @@ status = "okay"; }; + +&spmi_bus { + pmic@0 { + pmic4125_codec: audio-codec@f000 { + compatible = "qcom,pm4125-codec"; + reg = <0xf000>; + vdd-io-supply = <&pm4125_l15>; + vdd-cp-supply = <&pm4125_s1>; + vdd-pa-vpos-supply = <&pm4125_s1>; + + vdd-mic-bias-supply = <&pm4125_l22>; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + + qcom,rx-device = <&pm4125_rx>; + qcom,tx-device = <&pm4125_tx>; + #sound-dai-cells = <1>; + + status = "okay"; + }; + }; +}; + +&swr0 { + status = "okay"; + + pm4125_rx: codec@0,4 { + compatible = "sdw20217010c00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5 >; + }; +}; + +&swr1 { + status = "okay"; + + pm4125_tx: codec@0,3 { + compatible = "sdw20217010c00"; + reg = <0 3>; + qcom,tx-port-mapping = <2 3>; + }; +}; + +&tlmm { + dmic_eldo_en_default: dmic-eldo-default-active-state { + pins = "gpio71"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + i2s2_default: i2s2-default-active-state { + pins = "gpio100", "gpio101", "gpio102", "gpio103"; + function = "i2s2"; + drive-strength = <8>; + bias-disable; + }; + + wsa8855_spkr_sd_n: wsa8855-spkr-sd-n-active-state { + pins = "gpio2"; + function = "gpio"; + drive-strength = <8>; + input-disable; + output-enable; + }; +}; + +&vamacro { + pinctrl-0 = <&dmic01_default>, <&dmic23_default>; + pinctrl-names = "default"; + + 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>; + clock-names = "mclk", + "npl"; + + qcom,dmic-sample-rate = <4800000>; + + status = "okay"; +}; + From 7f1adef2357a63363b9c821f108a4bea7876f648 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 26 Oct 2026 18:01:09 +0530 Subject: [PATCH 1004/1133] FROMLIST: arm64: dts: qcom: shikra-iqs-evk: Enable sound card support Enable the IQS EVK audio card using MAX98091 on I2S0 for primary playback/capture and VA DMIC capture through q6apm backend links. Add board clock and pinctrl states required for codec IRQ, external mclk and digital mic routing. Link: https://lore.kernel.org/all/20261026-shikra_audio_dts-v4-v4-6-cfebe0809467@oss.qualcomm.com/ Co-developed-by: Ajay Kumar Nandam Signed-off-by: Ajay Kumar Nandam Signed-off-by: Mohammad Rafi Shaik --- arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 159 ++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 650e54a172da2..668889cdd0690 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -67,6 +67,120 @@ pinctrl-0 = <&rgmii_phy1_pwr_default>; pinctrl-names = "default"; }; + + sound { + compatible = "qcom,shikra-iqs-sndcard"; + model = "shikra-iqs-evk"; + + pinctrl-0 = <&i2s0_default>, <&ext_mclk2_active>; + pinctrl-names = "default"; + + audio-routing = "IN34", "Headset Mic", + "Headset Mic", "MICBIAS", + "DMICL", "Int Mic", + "Int Mic", "MICBIAS", + "Headphone", "HPL", + "Headphone", "HPR", + "Speaker", "SPKL", + "Speaker", "SPKR", + "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + pri-i2s-playback-dai-link { + link-name = "Analog Playback"; + + codec { + sound-dai = <&max98091>; + }; + + cpu { + sound-dai = <&q6apmbedai AIF_MI2S_RX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + pri-i2s-capture-dai-link { + link-name = "Analog Capture"; + + codec { + sound-dai = <&max98091>; + }; + + cpu { + sound-dai = <&q6apmbedai AIF_MI2S_TX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + va-dmic-dai-link { + link-name = "VA DMIC Capture"; + + codec { + sound-dai = <&vamacro 0>; + }; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; +}; + +&gpr { + status = "okay"; +}; + +&i2c3 { + status = "okay"; + + max98091: audio-codec@10 { + compatible = "maxim,max98091"; + reg = <0x10>; + + pinctrl-0 = <&max98091_default>; + pinctrl-names = "default"; + + interrupts-extended = <&tlmm 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&q6prmcc LPASS_CLK_ID_MCLK_2 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "mclk"; + assigned-clocks = <&q6prmcc LPASS_CLK_ID_MCLK_2 LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + assigned-clock-rates = <12288000>; + #sound-dai-cells = <0>; + }; +}; + +&q6apmbedai { + #address-cells = <1>; + #size-cells = <0>; + + dai@153 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_QAIF_IF0_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; +}; + +&q6apmbedai { + #address-cells = <1>; + #size-cells = <0>; + + dai@154 { + reg = ; + clocks = <&q6prmcc LPASS_CLK_ID_QAIF_IF0_IBIT LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "bclk"; + }; }; ðernet0 { @@ -391,3 +505,48 @@ &usb_qmpphy_out { remote-endpoint = <&ucsi_ccg_port_1_ss>; }; + +&tlmm { + dmic_eldo_en_default: dmic-eldo-default-active-state { + pins = "gpio71"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + + ext_mclk2_active: ext-mclk2-state { + pins = "gpio110"; + function = "ext_mclk"; + drive-strength = <8>; + bias-disable; + }; + + i2s0_default: i2s0-default-active-state { + pins = "gpio105", "gpio106", "gpio107", "gpio108", "gpio109"; + function = "i2s0"; + drive-strength = <8>; + bias-disable; + }; + + max98091_default: max98091-default-state { + pins = "gpio28"; + function = "gpio"; + bias-pull-up; + }; +}; + +&vamacro { + 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>; + clock-names = "mclk", + "npl"; + + pinctrl-0 = <&dmic01_default>, <&dmic23_default>, <&dmic_eldo_en_default>; + pinctrl-names = "default"; + + qcom,dmic-sample-rate = <4800000>; + + status = "okay"; +}; + From 8caa99f28f06ec41ae84cec1af513ce524aacc0b Mon Sep 17 00:00:00 2001 From: Linghui Wu Date: Tue, 13 Oct 2026 12:55:27 +0800 Subject: [PATCH 1005/1133] FROMLIST: arm64: dts: qcom: shikra-iqs: add M.2 Wi-Fi and Bluetooth overlay Add an overlay for M.2 Key-E Wi-Fi and Bluetooth modules on the Qualcomm Shikra IQS EVK. The M.2 variant uses the external module connected through the Key-E connector instead of the onboard WCN3988 devices. Disable the onboard Wi-Fi and Bluetooth nodes when the overlay is selected so the device tree matches the hardware variant and does not probe the unavailable onboard connectivity path. Describe the PCIe and UART connections through the M.2 connector, the 3.3 V supply, the W_DISABLE signals and the PCIe reset signal. The Wi-Fi PCIe path was tested on a Shikra IQS EVK with a QCC2072 module. The overlay was applied, the link trained at Gen2 x1 and the endpoint enumerated. Bluetooth UART and HCI runtime validation is pending. Link: https://lore.kernel.org/r/20261020020925.3915548-1-linghui.wu@oss.qualcomm.com Co-developed-by: Wei Deng Signed-off-by: Wei Deng Signed-off-by: Linghui Wu --- arch/arm64/boot/dts/qcom/Makefile | 1 + .../dts/qcom/shikra-iqs-evk-m2-wifi-bt.dtso | 105 ++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/shikra-iqs-evk-m2-wifi-bt.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index e21d9d401463b..a7a6472538c4a 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -394,6 +394,7 @@ shikra-iqs-evk-imx577-camera-dtbs := shikra-iqs-evk.dtb shikra-iqs-evk-imx577-ca dtb-$(CONFIG_ARCH_QCOM) += shikra-cqm-evk-imx577-camera.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-imx577-camera.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-imx577-camera.dtb +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-m2-wifi-bt.dtbo shikra-cqm-evk-hdmi-dtbs := shikra-cqm-evk.dtb shikra-cqm-cqs-evk-hdmi.dtbo shikra-cqs-evk-hdmi-dtbs := shikra-cqs-evk.dtb shikra-cqm-cqs-evk-hdmi.dtbo diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk-m2-wifi-bt.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-m2-wifi-bt.dtso new file mode 100644 index 0000000000000..985c728dd693d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk-m2-wifi-bt.dtso @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2026 Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +#include + +&{/} { + m2_keye_3p3: regulator-m2-keye-3p3 { + compatible = "regulator-fixed"; + regulator-name = "VREG_3P3_KEYE"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&qps_gpio_expander 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + wifi-bt-connector { + compatible = "pcie-m2-e-connector"; + + vpcie3v3-supply = <&m2_keye_3p3>; + w-disable1-gpios = <&tlmm 61 GPIO_ACTIVE_LOW>; + w-disable2-gpios = <&tlmm 60 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_pcie_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&pcie_port0_ep>; + }; + }; + + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + + m2_e_uart_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&uart8_ep>; + }; + }; + }; + }; +}; + +&{/wcn3988-pmu} { + status = "disabled"; +}; + +&i2c3 { + qps_gpio_expander: gpio@3c { + compatible = "nxp,pca9534"; + reg = <0x3c>; + gpio-controller; + #gpio-cells = <2>; + }; +}; + +&pcie { + iommu-map = <0x0 &apps_smmu 0x0800 0x0 0x1>, + <0x100 &apps_smmu 0x0801 0x0 0x1>; + vddpe-3v3-supply = <&m2_keye_3p3>; +}; + +&pcie_port0 { + compatible = "pciclass,0604"; + reset-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>; + + port { + pcie_port0_ep: endpoint { + remote-endpoint = <&m2_e_pcie_ep>; + }; + }; +}; + +&tc9563 { + status = "disabled"; +}; + +&uart8 { + bluetooth { + status = "disabled"; + }; + + port { + uart8_ep: endpoint { + remote-endpoint = <&m2_e_uart_ep>; + }; + }; +}; + +&wifi { + status = "disabled"; +}; From 1fec39842bbe3cb9fe7500cf22e166a9a47f299e Mon Sep 17 00:00:00 2001 From: Faiyaz Mohammed Date: Wed, 14 Oct 2026 21:26:19 +0530 Subject: [PATCH 1006/1133] FROMLIST: arm64: dts: qcom: shikra: add LCP/SRP ECC interrupt to LLCC node Add a second interrupt for LCP/SRP DDR DRAM ECC reporting and interrupt-names ("llcc-ecc", "llcc-lcp-ecc") to the Shikra LLCC node, as required by the updated DT binding. Signed-off-by: Faiyaz Mohammed Link: https://lore.kernel.org/r/20261014-master-v1-4-aba3cfcfbac9@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/shikra.dtsi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index 3a650e5b6c5ea..b06bca1d8699e 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -1211,7 +1211,9 @@ reg-names = "llcc0_base", "llcc1_base", "llcc_broadcast_base"; - interrupts = ; + interrupts = , + ; + interrupt-names = "llcc-ecc", "llcc-lcp-ecc"; }; gcc: clock-controller@1400000 { From 30d1b545cf2e13cfd1fa8baca24d04d5cd5d7cdb Mon Sep 17 00:00:00 2001 From: Sneh Mankad Date: Tue, 27 Oct 2026 18:41:09 +0530 Subject: [PATCH 1007/1133] FROMLIST: irqchip: irq-qcom-mpm: Register MPM with cpu_pm for RPM notification MPM irqchip needs to notify RPM (Resource Power Manager) processor to read the latest wake up capable interrupts when the CPU cluster is entering the deepest idle state. This is done by sending IPC interrupt to RPM and is implemented as .power_off() callback by registering MPM as parent power domain to CPU cluster. Such implementation earlier introduced a hard probe dependency between MPM irqchip and CPU cluster power domains. That is MPM irqchip needs to finish probe before PSCI power domains are probed. The above problem has since been resolved after bd7f488a8e5d ("cpuidle: psci: Fix support for probe deferral by dropping the faux device") / [1]. However, it makes sense to remodel the RPM notification in MPM irqchip due to general consistency. MPM is not really a power domain provider, all it needs is a notification when CPU cluster is going to power collapse to carry out the RPM notification. We can register for CPU_PM notifications for that purpose. This way we can avoid such unrelated dependencies. We cannot register MPM under CPU cluster power domain and rely on GENPD notifications here, since that way cluster low power modes will be blocked whenever some consumer of MPM, and in turn MPM itself, are runtime active. This will add another unnecessary dependency for CPU cluster low power modes. For now as first step, register with cpu_pm as a fallback to manage RPM notification. Trigger the RPM notification when the last CPU in CPU cluster goes to power collapse. [1] https://lore.kernel.org/all/20260909134240.685115374@linuxfoundation.org Signed-off-by: Sneh Mankad Link: https://lore.kernel.org/all/20261027-b4-shikra_lpm_addition-v3-1-424abcdcf824@oss.qualcomm.com Signed-off-by: Ricardo Salveti --- drivers/irqchip/irq-qcom-mpm.c | 104 ++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 26 deletions(-) diff --git a/drivers/irqchip/irq-qcom-mpm.c b/drivers/irqchip/irq-qcom-mpm.c index 8c575d7ce8a17..b6caea90e9f41 100644 --- a/drivers/irqchip/irq-qcom-mpm.c +++ b/drivers/irqchip/irq-qcom-mpm.c @@ -4,6 +4,7 @@ * Copyright (c) 2010-2020, The Linux Foundation. All rights reserved. */ +#include #include #include #include @@ -85,6 +86,8 @@ struct qcom_mpm_priv { unsigned int reg_stride; struct irq_domain *domain; struct generic_pm_domain genpd; + struct notifier_block mpm_pm; + atomic_t cpus_in_pm; }; static u32 qcom_mpm_read(struct qcom_mpm_priv *priv, unsigned int reg, @@ -292,10 +295,8 @@ static irqreturn_t qcom_mpm_handler(int irq, void *dev_id) return ret; } -static int mpm_pd_power_off(struct generic_pm_domain *genpd) +static int handle_rpm_notification(struct qcom_mpm_priv *priv) { - struct qcom_mpm_priv *priv = container_of(genpd, struct qcom_mpm_priv, - genpd); int i, ret; for (i = 0; i < priv->reg_stride; i++) @@ -307,10 +308,52 @@ static int mpm_pd_power_off(struct generic_pm_domain *genpd) return ret; mbox_client_txdone(priv->mbox_chan, 0); - return 0; } +static int mpm_pd_power_off(struct generic_pm_domain *genpd) +{ + struct qcom_mpm_priv *priv = container_of(genpd, struct qcom_mpm_priv, + genpd); + + return handle_rpm_notification(priv); +} + +static int mpm_cpu_pm_callback(struct notifier_block *nfb, unsigned long action, void *v) +{ + struct qcom_mpm_priv *priv = container_of(nfb, struct qcom_mpm_priv, mpm_pm); + int cpus_in_pm; + + switch (action) { + case CPU_PM_ENTER: + cpus_in_pm = atomic_inc_return(&priv->cpus_in_pm); + /* + * NOTE: comments for num_online_cpus() point out that it's + * only a snapshot so we need to be careful. It should be OK + * for us to use, though. It's important for us not to miss + * if we're the last CPU going down so it would only be a + * problem if a CPU went offline right after we did the check + * AND that CPU was not idle AND that CPU was the last non-idle + * CPU. That can't happen. CPUs would have to come out of idle + * before the CPU could go offline. + */ + if (cpus_in_pm < num_online_cpus()) + return NOTIFY_OK; + break; + case CPU_PM_ENTER_FAILED: + case CPU_PM_EXIT: + atomic_dec(&priv->cpus_in_pm); + return NOTIFY_OK; + default: + return NOTIFY_DONE; + } + + if (handle_rpm_notification(priv)) + return NOTIFY_BAD; + + return NOTIFY_OK; +} + static bool gic_hwirq_is_mapped(struct mpm_gic_map *maps, int cnt, u32 hwirq) { int i; @@ -415,26 +458,6 @@ static int qcom_mpm_probe(struct platform_device *pdev, struct device_node *pare if (irq < 0) return irq; - genpd = &priv->genpd; - genpd->flags = GENPD_FLAG_IRQ_SAFE; - genpd->power_off = mpm_pd_power_off; - - genpd->name = devm_kasprintf(dev, GFP_KERNEL, "%s", dev_name(dev)); - if (!genpd->name) - return -ENOMEM; - - ret = pm_genpd_init(genpd, NULL, false); - if (ret) { - dev_err(dev, "failed to init genpd: %d\n", ret); - return ret; - } - - ret = of_genpd_add_provider_simple(np, genpd); - if (ret) { - dev_err(dev, "failed to add genpd provider: %d\n", ret); - goto remove_genpd; - } - priv->mbox_client.dev = dev; priv->mbox_client.knows_txdone = true; priv->mbox_chan = mbox_request_channel(&priv->mbox_client, 0); @@ -444,6 +467,35 @@ static int qcom_mpm_probe(struct platform_device *pdev, struct device_node *pare return ret; } + if (of_find_property(np, "#power-domain-cells", NULL)) { + genpd = &priv->genpd; + genpd->flags = GENPD_FLAG_IRQ_SAFE; + genpd->power_off = mpm_pd_power_off; + + genpd->name = devm_kasprintf(dev, GFP_KERNEL, "%s", dev_name(dev)); + if (!genpd->name) + return -ENOMEM; + + ret = pm_genpd_init(genpd, NULL, false); + if (ret) { + dev_err(dev, "failed to init genpd: %d\n", ret); + return ret; + } + + ret = of_genpd_add_provider_simple(np, genpd); + if (ret) { + dev_err(dev, "failed to add genpd provider: %d\n", ret); + goto remove_genpd; + } + } else { + priv->mpm_pm.notifier_call = mpm_cpu_pm_callback; + ret = cpu_pm_register_notifier(&priv->mpm_pm); + if (ret) { + dev_err(dev, "failed to register for CPU_PM notifications: %d\n", ret); + return ret; + } + } + parent_domain = irq_find_host(parent); if (!parent_domain) { dev_err(dev, "failed to find MPM parent domain\n"); @@ -471,10 +523,10 @@ static int qcom_mpm_probe(struct platform_device *pdev, struct device_node *pare remove_domain: irq_domain_remove(priv->domain); -free_mbox: - mbox_free_channel(priv->mbox_chan); remove_genpd: pm_genpd_remove(genpd); +free_mbox: + mbox_free_channel(priv->mbox_chan); return ret; } From c9ab62f332ab0e4495f8f14d83c9ecefa5371474 Mon Sep 17 00:00:00 2001 From: Sneh Mankad Date: Tue, 27 Oct 2026 18:41:10 +0530 Subject: [PATCH 1008/1133] FROMLIST: arm64: dts: qcom: shikra: Add CPU idle states Add idle states for the CPUs as well as the whole cluster. This enables deeper-than-WFI cpuidle. Remove #power-domain-cells from MPM device so that the driver follows the cpu_pm notifications path to handle RPM notification. This avoids other probe dependencies that arise due to MPM being a power domain provider. Signed-off-by: Sneh Mankad Link: https://lore.kernel.org/all/20261027-b4-shikra_lpm_addition-v3-2-424abcdcf824@oss.qualcomm.com Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/shikra.dtsi | 93 +++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi index b06bca1d8699e..f096469fb9845 100644 --- a/arch/arm64/boot/dts/qcom/shikra.dtsi +++ b/arch/arm64/boot/dts/qcom/shikra.dtsi @@ -53,6 +53,8 @@ compatible = "arm,cortex-a55"; reg = <0x0 0x0>; enable-method = "psci"; + power-domains = <&cpu_pd0>; + power-domain-names = "psci"; next-level-cache = <&l3>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; @@ -71,6 +73,8 @@ compatible = "arm,cortex-a55"; reg = <0x0 0x100>; enable-method = "psci"; + power-domains = <&cpu_pd1>; + power-domain-names = "psci"; next-level-cache = <&l3>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; @@ -89,6 +93,8 @@ compatible = "arm,cortex-a55"; reg = <0x0 0x200>; enable-method = "psci"; + power-domains = <&cpu_pd2>; + power-domain-names = "psci"; next-level-cache = <&l3>; capacity-dmips-mhz = <1024>; dynamic-power-coefficient = <100>; @@ -107,6 +113,8 @@ compatible = "arm,cortex-a78c"; reg = <0x0 0x300>; enable-method = "psci"; + power-domains = <&cpu_pd3>; + power-domain-names = "psci"; next-level-cache = <&l2_3>; capacity-dmips-mhz = <1946>; dynamic-power-coefficient = <489>; @@ -150,6 +158,61 @@ }; }; + idle-states { + entry-method = "psci"; + + little_cpu_sleep_0: cpu-sleep-0-0 { + compatible = "arm,idle-state"; + idle-state-name = "little-power-down"; + arm,psci-suspend-param = <0x40000003>; + entry-latency-us = <549>; + exit-latency-us = <901>; + min-residency-us = <1774>; + local-timer-stop; + }; + + little_cpu_sleep_1: cpu-sleep-0-1 { + compatible = "arm,idle-state"; + idle-state-name = "little-pll-power-down"; + arm,psci-suspend-param = <0x40000004>; + entry-latency-us = <702>; + exit-latency-us = <915>; + min-residency-us = <4001>; + local-timer-stop; + }; + + big_cpu_sleep_0: cpu-sleep-1-0 { + compatible = "arm,idle-state"; + idle-state-name = "big-power-down"; + arm,psci-suspend-param = <0x40000003>; + entry-latency-us = <523>; + exit-latency-us = <1244>; + min-residency-us = <2207>; + local-timer-stop; + }; + + big_cpu_sleep_1: cpu-sleep-1-1 { + compatible = "arm,idle-state"; + idle-state-name = "big-pll-power-down"; + arm,psci-suspend-param = <0x40000004>; + entry-latency-us = <526>; + exit-latency-us = <1854>; + min-residency-us = <5555>; + local-timer-stop; + }; + }; + + domain_idle_states: domain-idle-states { + cluster_sleep_apss_off: cluster-sleep-0 { + compatible = "domain-idle-state"; + idle-state-name = "cluster-power-down"; + arm,psci-suspend-param = <0x41000044>; + entry-latency-us = <2752>; + exit-latency-us = <3038>; + min-residency-us = <6118>; + }; + }; + l3: l3-cache { compatible = "cache"; cache-level = <3>; @@ -318,6 +381,35 @@ psci: psci { compatible = "arm,psci-1.0"; method = "smc"; + + cpu_pd0: power-domain-cpu0 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&little_cpu_sleep_0>, <&little_cpu_sleep_1>; + }; + + cpu_pd1: power-domain-cpu1 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&little_cpu_sleep_0>, <&little_cpu_sleep_1>; + }; + + cpu_pd2: power-domain-cpu2 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&little_cpu_sleep_0>, <&little_cpu_sleep_1>; + }; + + cpu_pd3: power-domain-cpu3 { + #power-domain-cells = <0>; + power-domains = <&cluster_pd>; + domain-idle-states = <&big_cpu_sleep_0>, <&big_cpu_sleep_1>; + }; + + cluster_pd: power-domain-cluster { + #power-domain-cells = <0>; + domain-idle-states = <&cluster_sleep_apss_off>; + }; }; rpm: remoteproc { @@ -391,7 +483,6 @@ mboxes = <&apcs_glb 1>; interrupt-controller; #interrupt-cells = <2>; - #power-domain-cells = <0>; interrupt-parent = <&intc>; qcom,mpm-pin-count = <96>; qcom,mpm-pin-map = <2 275>, /* TSENS0 uplow */ From 060ada3de854242259c93d493cbc1d96d2ec133b Mon Sep 17 00:00:00 2001 From: Karthik S Date: Thu, 22 Oct 2026 12:20:38 +0530 Subject: [PATCH 1009/1133] FROMLIST: arm64: dts: qcom: shikra-iqs: Add LT9611UXD HDMI audio overlay Add a device tree overlay for Shikra IQS EVK boards that use the LT9611UXD HDMI bridge as an I2S audio codec instead of the MAX98091. The overlay reconfigures the sound card compatible to qcom,shikra-iqs-lt9611uxd-sndcard, overrides the primary I2S playback codec to LT9611UXD, disables the capture DAI link, and disables the MAX98091 codec node. Add a node label to the sound node in shikra-iqs-evk.dts to allow the overlay to reference it, and wire up the new composite DTB in the Makefile. Link: https://lore.kernel.org/all/20261022074220.989787-3-karthik.s@oss.qualcomm.com/ Signed-off-by: Karthik S --- arch/arm64/boot/dts/qcom/Makefile | 3 ++ arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts | 2 +- .../dts/qcom/shikra-iqs-lt9611uxd-evk.dtso | 36 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/qcom/shikra-iqs-lt9611uxd-evk.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index a7a6472538c4a..d3b330af090d2 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -384,6 +384,9 @@ dtb-$(CONFIG_ARCH_QCOM) += shikra-cqs-evk-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk.dtb +shikra-iqs-lt9611uxd-evk-dtbs := shikra-iqs-evk.dtb shikra-iqs-lt9611uxd-evk.dtbo +dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-lt9611uxd-evk.dtb + shikra-iqs-evk-el2-dtbs := shikra-iqs-evk.dtb shikra-el2.dtbo dtb-$(CONFIG_ARCH_QCOM) += shikra-iqs-evk-el2.dtb diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts index 668889cdd0690..565f5fa0d0301 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-evk.dts @@ -68,7 +68,7 @@ pinctrl-names = "default"; }; - sound { + sound: sound { compatible = "qcom,shikra-iqs-sndcard"; model = "shikra-iqs-evk"; diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-lt9611uxd-evk.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-lt9611uxd-evk.dtso new file mode 100644 index 0000000000000..e308552e92064 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-lt9611uxd-evk.dtso @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +/* Board subtype 0: LT9611UXD as I2S audio codec, no MAX98091 */ + +<9611uxd { + #sound-dai-cells = <1>; +}; + +&sound { + compatible = "qcom,shikra-iqs-lt9611uxd-sndcard"; + model = "shikra-iqs-lt9611uxd-evk"; + audio-routing = "VA DMIC0", "vdd-micb", + "VA DMIC1", "vdd-micb", + "VA DMIC2", "vdd-micb", + "VA DMIC3", "vdd-micb"; + + pri-i2s-playback-dai-link { + codec { + sound-dai = <<9611uxd 0>; + }; + }; + + pri-i2s-capture-dai-link { + status = "disabled"; + }; +}; + +&max98091 { + status = "disabled"; +}; From 60c8bf43305b71209326ed97d14053dd6dea869e Mon Sep 17 00:00:00 2001 From: Komal Bajaj Date: Wed, 4 Nov 2026 20:05:53 +0530 Subject: [PATCH 1010/1133] WORKAROUND: arm64: dts: qcom: shikra-iqs: Fix LT9611UXD overlay label The LT9611UXD HDMI audio overlay references the bridge node through the <9611uxd label, but the shikra-iqs-evk base DT defines it as hdmi_bridge. dtc cannot resolve the missing label when applying the overlay and fails with FDT_ERR_NOTFOUND, breaking the shikra-iqs-lt9611uxd-evk.dtb build. Use the &hdmi_bridge label for both the #sound-dai-cells fragment and the sound-dai reference in the playback link. Signed-off-by: Komal Bajaj --- arch/arm64/boot/dts/qcom/shikra-iqs-lt9611uxd-evk.dtso | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/shikra-iqs-lt9611uxd-evk.dtso b/arch/arm64/boot/dts/qcom/shikra-iqs-lt9611uxd-evk.dtso index e308552e92064..51f41623fd007 100644 --- a/arch/arm64/boot/dts/qcom/shikra-iqs-lt9611uxd-evk.dtso +++ b/arch/arm64/boot/dts/qcom/shikra-iqs-lt9611uxd-evk.dtso @@ -8,7 +8,7 @@ /* Board subtype 0: LT9611UXD as I2S audio codec, no MAX98091 */ -<9611uxd { +&hdmi_bridge { #sound-dai-cells = <1>; }; @@ -22,7 +22,7 @@ pri-i2s-playback-dai-link { codec { - sound-dai = <<9611uxd 0>; + sound-dai = <&hdmi_bridge 0>; }; }; From c24c9463e5129b791dc13a86cdcd2a2e97f05787 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:44 +0800 Subject: [PATCH 1011/1133] FROMLIST: drm/msm/dp: enable MST on capable sinks MST topology discovery requires the sink to operate in MST mode. Enable MST on sinks that advertise MST capability and are connected to a multi-stream capable DP controller. Once MST is enabled, downstream sink discovery and EDID retrieval are handled through the MST topology rather than the primary DP connector. Activate the MST topology manager on connect and disable it on disconnect to track the sink topology lifecycle. Snapshot the negotiated link parameters when MST is enabled so subsequent MST payload allocation can derive bandwidth information from a stable link configuration. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-27-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 59 +++++++++++++++++++++++++---- drivers/gpu/drm/msm/dp/dp_display.h | 2 + drivers/gpu/drm/msm/dp/dp_mst_drm.c | 18 +++++++++ drivers/gpu/drm/msm/dp/dp_mst_drm.h | 1 + 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index ca33ef9cfe8d1..721b541fa0c83 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -270,6 +271,29 @@ static int msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd return lttpr_count; } +static void msm_dp_display_mst_enable(struct msm_dp_display_private *dp) +{ + struct msm_dp *msm_dp = &dp->msm_dp_display; + int ret; + + /* Clear any pre-existing MST state before enabling MST. */ + ret = drm_dp_dpcd_write_byte(dp->aux, DP_MSTM_CTRL, 0); + if (ret < 0) { + DRM_ERROR("failed to clear DP_MSTM_CTRL, ret=%d\n", ret); + return; + } + + ret = drm_dp_dpcd_write_byte(dp->aux, DP_MSTM_CTRL, + DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); + if (ret < 0) { + DRM_ERROR("sink MST enablement failed\n"); + return; + } + + msm_dp->mst_active = true; + msm_dp_mst_display_set_mgr_state(msm_dp, true); +} + static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) { struct drm_connector *connector = dp->msm_dp_display.connector; @@ -288,14 +312,17 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) if (rc) goto end; - drm_edid = drm_edid_read_ddc(connector, &dp->aux->ddc); - drm_edid_connector_update(connector, drm_edid); + if (msm_dp_ctrl_get_stream_cnt(dp->ctrl) <= 1 || + !drm_dp_read_mst_cap(dp->aux, dp->panel->dpcd)) { + drm_edid = drm_edid_read_ddc(connector, &dp->aux->ddc); + drm_edid_connector_update(connector, drm_edid); - if (!drm_edid) { - DRM_ERROR("panel edid read failed\n"); - /* check edid read fail is due to unplug */ - if (!msm_dp_aux_is_link_connected(dp->aux)) - return -ETIMEDOUT; + if (!drm_edid) { + DRM_ERROR("panel edid read failed\n"); + /* check edid read fail is due to unplug */ + if (!msm_dp_aux_is_link_connected(dp->aux)) + return -ETIMEDOUT; + } } msm_dp_link_process_request(dp->link); @@ -317,6 +344,10 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) */ msm_dp_link_psm_config(dp->link, &dp->panel->link_info, false); + if (msm_dp_ctrl_get_stream_cnt(dp->ctrl) > 1 && + drm_dp_read_mst_cap(dp->aux, dp->panel->dpcd)) + msm_dp_display_mst_enable(dp); + msm_dp_link_reset_phy_params_vx_px(dp->link); end: @@ -492,6 +523,11 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp) dp->panel->dpcd, dp->panel->downstream_ports); + if (dp->msm_dp_display.mst_active) { + msm_dp_mst_display_set_mgr_state(&dp->msm_dp_display, false); + dp->msm_dp_display.mst_active = false; + } + /* signal the disconnect event early to ensure proper teardown */ msm_dp_display_handle_plugged_change(&dp->msm_dp_display, false); @@ -570,6 +606,15 @@ struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display, return dp_panel; } +void msm_dp_display_get_link_info(struct msm_dp *msm_dp_display, + struct msm_dp_link_info *link_info) +{ + struct msm_dp_display_private *dp = + container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display); + + memcpy(link_info, &dp->link->link_caps, sizeof(*link_info)); +} + static void msm_dp_display_deinit_sub_modules(struct msm_dp_display_private *dp) { msm_dp_audio_put(dp->audio); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index ca2faf478c957..96b53d5b60902 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -65,4 +65,6 @@ int msm_dp_get_mst_max_stream(struct msm_dp *msm_dp_display); int msm_dp_mst_register(struct msm_dp *msm_dp_display); struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display, enum msm_dp_stream_id stream_id); +void msm_dp_display_get_link_info(struct msm_dp *msm_dp_display, + struct msm_dp_link_info *link_info); #endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c index 2e625a7db9819..b2905c894ce56 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -328,6 +328,24 @@ int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, return 0; } +int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state) +{ + struct msm_dp_mst *mst = dp_display->msm_dp_mst; + int rc; + + rc = drm_dp_mst_topology_mgr_set_mst(&mst->mst_mgr, state); + if (rc < 0) { + drm_err(dp_display->drm_dev, + "[MST] failed to set topology mgr state to %d rc:%d\n", state, rc); + } + + if (state) + msm_dp_display_get_link_info(dp_display, &mst->link_info); + + drm_dbg_kms(dp_display->drm_dev, "[MST] set_mgr_state state:%d\n", state); + return rc; +} + void msm_dp_mst_display_hpd_irq(struct msm_dp *dp_display) { int rc; diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.h b/drivers/gpu/drm/msm/dp/dp_mst_drm.h index 8546214cbca16..4a5707dd50a9b 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.h @@ -10,6 +10,7 @@ int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux); int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, struct drm_encoder *encoder); +int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state); void msm_dp_mst_display_hpd_irq(struct msm_dp *dp_display); #endif /* _DP_MST_DRM_H_ */ From 1cf1d7e6f50370ecbc176935fc1c4896df60838c Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Mon, 31 Aug 2026 16:17:45 +0800 Subject: [PATCH 1012/1133] FROMLIST: drm/msm/dp: mark the SST bridge disconnected when an MST-capable sink is present When a DP cable is already attached at boot, msm_dp_bridge_detect() runs from the connector notify path before MST has been activated on the sink. The DPCD capability read at that point already indicates that the sink supports MST. Return connector_status_disconnected from the SST bridge whenever the controller supports multi-stream (stream_cnt > 1) and the sink reports MST capability, so that connector detection is handled by MST connectors instead of the SST bridge. Signed-off-by: Abhinav Kumar Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-28-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 721b541fa0c83..48810997a7003 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1059,6 +1059,10 @@ enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge, status = connector_status_disconnected; } + /* Mark SST connector as disconnected in DP boot-up case*/ + if (msm_dp_ctrl_get_stream_cnt(priv->ctrl) > 1 && drm_dp_read_mst_cap(priv->aux, dpcd)) + status = connector_status_disconnected; + end: /* * If we detected the DPRX, leave the controller on so that it doesn't From 1738337ad4cd17b444fdc9c5c3b13257edd170f8 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 31 Aug 2026 16:17:46 +0800 Subject: [PATCH 1013/1133] FROMLIST: drm/msm/dp: mark the SST connector disconnected when MST is enabled When MST becomes active, the initial HPD plug notification updates the SST connector state to connected. However, the subsequent SST connector detect path reports disconnected while MST is enabled. This connected -> disconnected transition is then observed by the polling logic and may result in an unnecessary hotplug event. Set the SST connector state to disconnected immediately after MST is initialized so that the detect path does not introduce a transient state change. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260831-msm-dp-mst-v6-29-c91d35d6fb9e@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 48810997a7003..a02106218b559 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -291,6 +291,10 @@ static void msm_dp_display_mst_enable(struct msm_dp_display_private *dp) } msm_dp->mst_active = true; + + scoped_guard(mutex, &msm_dp->connector->dev->mode_config.mutex) + msm_dp->connector->status = connector_status_disconnected; + msm_dp_mst_display_set_mgr_state(msm_dp, true); } From f7a4f95ec6be41c4d9bbeb59d1de503216f0e41f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:02 +0300 Subject: [PATCH 1014/1133] FROMLIST: drm/connector: report out-of-band IRQ_HPD events The DisplayPort standard defines a special kind of events called IRQ. These events are used to notify DP Source about the events on the Sink side. It is extremely important for DP MST handling, where the MST events are reported through this IRQ. In case of the USB-C DP AltMode there is no actual HPD pulse, but the events are reported through the bits in the AltMode VDOs. Rename drm_connector_oob_hotplug_event() to drm_connector_dp_oob_status() and extend its interface to report IRQ events to the DisplayPort Sink drivers. Acked-by: Heikki Krogerus Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-1-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/drm_connector.c | 20 ++++++++++++-------- drivers/usb/typec/altmodes/displayport.c | 23 +++++++++++++++-------- include/drm/drm_connector.h | 21 +++++++++++++++++++-- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 893716a9e4895..f2a9eecf1e25c 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -3821,20 +3821,24 @@ struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode) } /** - * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector + * drm_connector_dp_oob_status - Report out-of-band hotplug event to DisplayPort connector * @connector_fwnode: fwnode_handle to report the event on * @status: hot plug detect logical state + * @extra_status: additional information provided by the sink without changing + * the HPD state (or in addition to such a change). * - * On some hardware a hotplug event notification may come from outside the display - * driver / device. An example of this is some USB Type-C setups where the hardware - * muxes the DisplayPort data and aux-lines but does not pass the altmode HPD - * status bit to the GPU's DP HPD pin. + * In some cases when DisplayPort signals are being routed through the USB + * Type-C port the hotplug event notifications come from outside of the display + * driver / device. In this case hardware muxes the DisplayPort data and + * AUX-lines but does not pass the altmode HPD status bit to the GPU's DP HPD + * pin. * * This function can be used to report these out-of-band events after obtaining * a drm_connector reference through calling drm_connector_find_by_fwnode(). */ -void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, - enum drm_connector_status status) +void drm_connector_dp_oob_status(struct fwnode_handle *connector_fwnode, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_connector *connector; @@ -3847,7 +3851,7 @@ void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, drm_connector_put(connector); } -EXPORT_SYMBOL(drm_connector_oob_hotplug_event); +EXPORT_SYMBOL(drm_connector_dp_oob_status); /** * drm_connector_get_color_format - Return connector color format of @conn_state diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 51c92dd887aba..344a13c2a296a 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -187,9 +187,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp) dp->pending_irq_hpd = true; } } else { - drm_connector_oob_hotplug_event(dp->connector_fwnode, + drm_connector_dp_oob_status(dp->connector_fwnode, hpd ? connector_status_connected : - connector_status_disconnected); + connector_status_disconnected, + (hpd && irq_hpd) ? DRM_CONNECTOR_DP_IRQ_HPD : + DRM_CONNECTOR_NO_EXTRA_STATUS); dp->hpd = hpd; sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); if (hpd && irq_hpd) { @@ -211,8 +213,11 @@ static int dp_altmode_configured(struct dp_altmode *dp) * configuration is complete to signal HPD. */ if (dp->pending_hpd) { - drm_connector_oob_hotplug_event(dp->connector_fwnode, - connector_status_connected); + drm_connector_dp_oob_status(dp->connector_fwnode, + connector_status_connected, + dp->pending_irq_hpd ? + DRM_CONNECTOR_DP_IRQ_HPD : + DRM_CONNECTOR_NO_EXTRA_STATUS); sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); dp->pending_hpd = false; if (dp->pending_irq_hpd) { @@ -396,8 +401,9 @@ static int dp_altmode_vdm(struct typec_altmode *alt, dp->data.status = 0; dp->data.conf = 0; if (dp->hpd) { - drm_connector_oob_hotplug_event(dp->connector_fwnode, - connector_status_disconnected); + drm_connector_dp_oob_status(dp->connector_fwnode, + connector_status_disconnected, + DRM_CONNECTOR_NO_EXTRA_STATUS); dp->hpd = false; sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); } @@ -844,8 +850,9 @@ void dp_altmode_remove(struct typec_altmode *alt) typec_altmode_put_plug(dp->plug_prime); if (dp->connector_fwnode) { - drm_connector_oob_hotplug_event(dp->connector_fwnode, - connector_status_disconnected); + drm_connector_dp_oob_status(dp->connector_fwnode, + connector_status_disconnected, + DRM_CONNECTOR_NO_EXTRA_STATUS); fwnode_handle_put(dp->connector_fwnode); } diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 2ee7c59329aae..80a2da4541b0b 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -92,6 +92,22 @@ enum drm_connector_status { connector_status_unknown = 3, }; +/** + * enum drm_connector_status_extra - additional events sent by the sink / + * display together or in replacement of the HPD status changes. + */ +enum drm_connector_status_extra { + /** + * @DRM_CONNECTOR_NO_EXTRA_STATUS: No additional status reported. + */ + DRM_CONNECTOR_NO_EXTRA_STATUS, + /** + * @DRM_CONNECTOR_DP_IRQ_HPD: DisplayPort Sink has sent the + * IRQ_HPD (either by the HPD short pulse or via the AltMode event). + */ + DRM_CONNECTOR_DP_IRQ_HPD, +}; + /** * enum drm_connector_registration_state - userspace registration status for * a &drm_connector @@ -2848,8 +2864,9 @@ drm_connector_hdmi_scrambler_supported(const struct drm_connector *connector) connector->hdmi.funcs->supported_hdmi_ver >= HDMI_VERSION_2_0; } -void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode, - enum drm_connector_status status); +void drm_connector_dp_oob_status(struct fwnode_handle *connector_fwnode, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); enum drm_connector_color_format drm_connector_get_color_format(const struct drm_connector_state *conn_state); const char *drm_get_connector_type_name(unsigned int connector_type); From 1b84259aff687d486a73d3fbd0bb114b3aa1c198 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:03 +0300 Subject: [PATCH 1015/1133] FROMLIST: drm/connector: pass down IRQ_HPD to the drivers The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Extend drm_connector_funcs::oob_hotplug_event() to pass the notifications about the IRQ_HPD events down to the individual drivers, letting them handle those as required. Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-2-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/display/drm_bridge_connector.c | 17 ++++++++++------- drivers/gpu/drm/drm_connector.c | 2 +- drivers/gpu/drm/i915/display/intel_dp.c | 3 ++- include/drm/drm_connector.h | 3 ++- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 81f3e26f6fdf5..b0fc2dddf9008 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -142,7 +142,8 @@ struct drm_bridge_connector { */ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_bridge_connector *bridge_connector = to_drm_bridge_connector(connector); @@ -155,7 +156,8 @@ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector, } static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bridge_connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_connector *connector = &drm_bridge_connector->base; struct drm_device *dev = connector->dev; @@ -164,7 +166,7 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri connector->status = status; mutex_unlock(&dev->mode_config.mutex); - drm_bridge_connector_hpd_notify(connector, status); + drm_bridge_connector_hpd_notify(connector, status, extra_status); drm_kms_helper_connector_hotplug_event(connector); } @@ -172,16 +174,17 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri static void drm_bridge_connector_hpd_cb(void *cb_data, enum drm_connector_status status) { - drm_bridge_connector_handle_hpd(cb_data, status); + drm_bridge_connector_handle_hpd(cb_data, status, DRM_CONNECTOR_NO_EXTRA_STATUS); } static void drm_bridge_connector_oob_hotplug_event(struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct drm_bridge_connector *bridge_connector = to_drm_bridge_connector(connector); - drm_bridge_connector_handle_hpd(bridge_connector, status); + drm_bridge_connector_handle_hpd(bridge_connector, status, extra_status); } static void drm_bridge_connector_enable_hpd(struct drm_connector *connector) @@ -301,7 +304,7 @@ static int drm_bridge_connector_detect_ctx(struct drm_connector *connector, return ret; } - drm_bridge_connector_hpd_notify(connector, status); + drm_bridge_connector_hpd_notify(connector, status, DRM_CONNECTOR_NO_EXTRA_STATUS); } else { switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DPI: diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index f2a9eecf1e25c..e6cc031781fa8 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -3847,7 +3847,7 @@ void drm_connector_dp_oob_status(struct fwnode_handle *connector_fwnode, return; if (connector->funcs->oob_hotplug_event) - connector->funcs->oob_hotplug_event(connector, status); + connector->funcs->oob_hotplug_event(connector, status, extra_status); drm_connector_put(connector); } diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index d8c0d9381471d..85173009a5344 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6841,7 +6841,8 @@ static int intel_dp_connector_atomic_check(struct drm_connector *_connector, } static void intel_dp_oob_hotplug_event(struct drm_connector *_connector, - enum drm_connector_status hpd_state) + enum drm_connector_status hpd_state, + enum drm_connector_status_extra extra_status) { struct intel_connector *connector = to_intel_connector(_connector); struct intel_display *display = to_intel_display(connector); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 80a2da4541b0b..9e879d4473c9f 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1974,7 +1974,8 @@ struct drm_connector_funcs { * has been received from a source outside the display driver / device. */ void (*oob_hotplug_event)(struct drm_connector *connector, - enum drm_connector_status status); + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); /** * @debugfs_init: From bc54a5e2e4aeb19d0d60130dac1ab80ffbf41834 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:04 +0300 Subject: [PATCH 1016/1133] FROMLIST: drm/bridge: aux-hpd: let drivers pass IRQ_HPD events The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Let users of aux-hpd, the UCSI and PMIC GLINK drivers pass the IRQ_HPD events to the DisplayPort drivers. The drm_aux_hpd_bridge_notify() is kept to ease merging of the series, preventing extra cross-tree merges. It will be removed once all drivers are converted. The drm_bridge_hpd_notify() function is kept for the drivers which only care about the connector status and will always pass DRM_CONNECTOR_NO_EXTRA_STATUS as the extra status. Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-3-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/aux-hpd-bridge.c | 11 +++++++---- drivers/gpu/drm/drm_bridge.c | 15 +++++++++------ include/drm/bridge/aux-bridge.h | 13 +++++++++++-- include/drm/drm_bridge.h | 22 ++++++++++++++++++++-- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c index a2e525aa57887..e8a3786bd199b 100644 --- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c +++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c @@ -137,16 +137,19 @@ struct device *drm_dp_hpd_bridge_register(struct device *parent, struct device_n EXPORT_SYMBOL_GPL(drm_dp_hpd_bridge_register); /** - * drm_aux_hpd_bridge_notify - notify hot plug detection events + * drm_aux_hpd_bridge_notify_extra - notify hot plug detection events * @dev: device created for the HPD bridge * @status: output connection status + * @extra_status: extra status bits like DRM_CONNECTOR_DP_IRQ_HPD * * A wrapper around drm_bridge_hpd_notify() that is used to report hot plug * detection events for bridges created via drm_dp_hpd_bridge_register(). * * This function shall be called in a context that can sleep. */ -void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) +void drm_aux_hpd_bridge_notify_extra(struct device *dev, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct auxiliary_device *adev = to_auxiliary_dev(dev); struct drm_aux_hpd_bridge_data *data = auxiliary_get_drvdata(adev); @@ -154,9 +157,9 @@ void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status sta if (!data) return; - drm_bridge_hpd_notify(&data->bridge, status); + drm_bridge_hpd_notify_extra(&data->bridge, status, extra_status); } -EXPORT_SYMBOL_GPL(drm_aux_hpd_bridge_notify); +EXPORT_SYMBOL_GPL(drm_aux_hpd_bridge_notify_extra); static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge, struct drm_encoder *encoder, diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 1b4ee746acb95..ad0d7749de1d8 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -1615,25 +1615,28 @@ void drm_bridge_hpd_disable(struct drm_bridge *bridge) EXPORT_SYMBOL_GPL(drm_bridge_hpd_disable); /** - * drm_bridge_hpd_notify - notify hot plug detection events + * drm_bridge_hpd_notify_extra - notify hot plug detection and sink IRQ events * @bridge: bridge control structure * @status: output connection status + * @extra_status: additional status recorded by the sink * * Bridge drivers shall call this function to report hot plug events when they - * detect a change in the output status, when hot plug detection has been - * enabled by drm_bridge_hpd_enable(). + * detect a change in the output status or when the sink has reported extra HPD + * status events (like the IRQ_HPD in case of the DisplayPort), when hot plug + * detection has been enabled by drm_bridge_hpd_enable(). * * This function shall be called in a context that can sleep. */ -void drm_bridge_hpd_notify(struct drm_bridge *bridge, - enum drm_connector_status status) +void drm_bridge_hpd_notify_extra(struct drm_bridge *bridge, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { mutex_lock(&bridge->hpd_mutex); if (bridge->hpd_cb) bridge->hpd_cb(bridge->hpd_data, status); mutex_unlock(&bridge->hpd_mutex); } -EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify); +EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify_extra); #ifdef CONFIG_OF /** diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h index c2f5a855512f3..f9a86886b0dfa 100644 --- a/include/drm/bridge/aux-bridge.h +++ b/include/drm/bridge/aux-bridge.h @@ -25,7 +25,9 @@ struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, str int devm_drm_dp_hpd_bridge_add(struct device *dev, struct auxiliary_device *adev); struct device *drm_dp_hpd_bridge_register(struct device *parent, struct device_node *np); -void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status); +void drm_aux_hpd_bridge_notify_extra(struct device *dev, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); #else static inline struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, struct device_node *np) @@ -44,9 +46,16 @@ static inline struct device *drm_dp_hpd_bridge_register(struct device *parent, return NULL; } -static inline void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) +static inline void drm_aux_hpd_bridge_notify_extra(struct device *dev, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { } #endif +static inline void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) +{ + drm_aux_hpd_bridge_notify_extra(dev, status, DRM_CONNECTOR_NO_EXTRA_STATUS); +} + #endif diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 1981d24a700d2..fdbe437e39a88 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -1519,8 +1519,26 @@ void drm_bridge_hpd_enable(struct drm_bridge *bridge, enum drm_connector_status status), void *data); void drm_bridge_hpd_disable(struct drm_bridge *bridge); -void drm_bridge_hpd_notify(struct drm_bridge *bridge, - enum drm_connector_status status); +void drm_bridge_hpd_notify_extra(struct drm_bridge *bridge, + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); + +/** + * drm_bridge_hpd_notify - notify hot plug detection events + * @bridge: bridge control structure + * @status: output connection status + * + * Bridge drivers shall call this function to report hot plug events when they + * detect a change in the output status, when hot plug detection has been + * enabled by drm_bridge_hpd_enable(). + * + * This function shall be called in a context that can sleep. + */ +static inline void drm_bridge_hpd_notify(struct drm_bridge *bridge, + enum drm_connector_status status) +{ + drm_bridge_hpd_notify_extra(bridge, status, DRM_CONNECTOR_NO_EXTRA_STATUS); +} void drm_bridge_debugfs_params(struct dentry *root); void drm_bridge_debugfs_encoder_params(struct dentry *root, struct drm_encoder *encoder); From e1554758e35cbc51bb49171923de652efb52571a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:05 +0300 Subject: [PATCH 1017/1133] FROMLIST: drm/bridge: pass extra events to the HPD callback The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Bridge drivers report these events through the drm_bridge_hpd_notify_extra(). Pass down the extra status to the HPD callback, specified during the drm_bridge_hpd_enable(), letting underlying drivers (e.g. drm_bridge_connector) to receive these events. Signed-off-by: Dmitry Baryshkov Acked-by: Francesco Dolcini # lt8912b Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-4-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/chrontel-ch7033.c | 3 ++- drivers/gpu/drm/bridge/lontium-lt8912b.c | 3 ++- drivers/gpu/drm/bridge/ti-tfp410.c | 3 ++- drivers/gpu/drm/display/drm_bridge_connector.c | 5 +++-- drivers/gpu/drm/drm_bridge.c | 5 +++-- include/drm/drm_bridge.h | 6 ++++-- 6 files changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c index 4bc64b2885f71..7700c76dee893 100644 --- a/drivers/gpu/drm/bridge/chrontel-ch7033.c +++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c @@ -258,7 +258,8 @@ static const struct drm_connector_helper_funcs ch7033_connector_helper_funcs = { .best_encoder = ch7033_connector_best_encoder, }; -static void ch7033_hpd_event(void *arg, enum drm_connector_status status) +static void ch7033_hpd_event(void *arg, enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct ch7033_priv *priv = arg; diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c index a4d05dcba9e09..75716862b5c41 100644 --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c @@ -506,7 +506,8 @@ static int lt8912_attach_dsi(struct lt8912 *lt) return 0; } -static void lt8912_bridge_hpd_cb(void *data, enum drm_connector_status status) +static void lt8912_bridge_hpd_cb(void *data, enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct lt8912 *lt = data; diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c index 629ff7095e872..a96705a58b3fd 100644 --- a/drivers/gpu/drm/bridge/ti-tfp410.c +++ b/drivers/gpu/drm/bridge/ti-tfp410.c @@ -110,7 +110,8 @@ static void tfp410_hpd_work_func(struct work_struct *work) drm_helper_hpd_irq_event(dvi->bridge.dev); } -static void tfp410_hpd_callback(void *arg, enum drm_connector_status status) +static void tfp410_hpd_callback(void *arg, enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct tfp410 *dvi = arg; diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index b0fc2dddf9008..17abb21ade9d2 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -172,9 +172,10 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri } static void drm_bridge_connector_hpd_cb(void *cb_data, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { - drm_bridge_connector_handle_hpd(cb_data, status, DRM_CONNECTOR_NO_EXTRA_STATUS); + drm_bridge_connector_handle_hpd(cb_data, status, extra_status); } static void drm_bridge_connector_oob_hotplug_event(struct drm_connector *connector, diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index ad0d7749de1d8..4f406c6761974 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -1557,7 +1557,8 @@ EXPORT_SYMBOL_GPL(drm_bridge_edid_read); */ void drm_bridge_hpd_enable(struct drm_bridge *bridge, void (*cb)(void *data, - enum drm_connector_status status), + enum drm_connector_status status, + enum drm_connector_status_extra extra_status), void *data) { if (!(bridge->ops & DRM_BRIDGE_OP_HPD)) @@ -1633,7 +1634,7 @@ void drm_bridge_hpd_notify_extra(struct drm_bridge *bridge, { mutex_lock(&bridge->hpd_mutex); if (bridge->hpd_cb) - bridge->hpd_cb(bridge->hpd_data, status); + bridge->hpd_cb(bridge->hpd_data, status, extra_status); mutex_unlock(&bridge->hpd_mutex); } EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify_extra); diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index fdbe437e39a88..7a5bdae8f8fcf 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -1207,7 +1207,8 @@ struct drm_bridge { * @hpd_cb: Hot plug detection callback, registered with * drm_bridge_hpd_enable(). */ - void (*hpd_cb)(void *data, enum drm_connector_status status); + void (*hpd_cb)(void *data, enum drm_connector_status status, + enum drm_connector_status_extra extra_status); /** * @hpd_data: Private data passed to the Hot plug detection callback * @hpd_cb. @@ -1516,7 +1517,8 @@ const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge, struct drm_connector *connector); void drm_bridge_hpd_enable(struct drm_bridge *bridge, void (*cb)(void *data, - enum drm_connector_status status), + enum drm_connector_status status, + enum drm_connector_status_extra extra_status), void *data); void drm_bridge_hpd_disable(struct drm_bridge *bridge); void drm_bridge_hpd_notify_extra(struct drm_bridge *bridge, From c59e804fe683f0433c6859160b33d43c3c27ea55 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:06 +0300 Subject: [PATCH 1018/1133] FROMLIST: drm/bridge: pass down IRQ_HPD to the drivers The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Pass down the extra status to the bridge drivers via the hpd_notify() callback, letting DP bridges to act accordingly. Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-5-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 3 ++- drivers/gpu/drm/display/drm_bridge_connector.c | 2 +- drivers/gpu/drm/meson/meson_encoder_hdmi.c | 3 ++- drivers/gpu/drm/msm/dp/dp_display.c | 3 ++- drivers/gpu/drm/msm/dp/dp_drm.h | 3 ++- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 3 ++- include/drm/drm_bridge.h | 3 ++- 7 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index ff1655c737e9d..85e4f0e60c261 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -437,7 +437,8 @@ static const struct drm_edid *lt9611uxc_bridge_edid_read(struct drm_bridge *brid static void lt9611uxc_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { const struct drm_edid *drm_edid; diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 17abb21ade9d2..915e13e05a21e 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -151,7 +151,7 @@ static void drm_bridge_connector_hpd_notify(struct drm_connector *connector, /* Notify all bridges in the pipeline of hotplug events. */ drm_for_each_bridge_in_chain(bridge_connector->encoder, bridge) { if (bridge->funcs->hpd_notify) - bridge->funcs->hpd_notify(bridge, connector, status); + bridge->funcs->hpd_notify(bridge, connector, status, extra_status); } } diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c index c4355c5cc340d..3b9c10cc0b743 100644 --- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c +++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c @@ -323,7 +323,8 @@ static int meson_encoder_hdmi_atomic_check(struct drm_bridge *bridge, static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index a02106218b559..2a8ab6e06dd41 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1787,7 +1787,8 @@ void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge) void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(bridge); struct msm_dp *msm_dp_display = msm_dp_bridge->msm_dp_display; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index da412c788503c..f6b96c27408af 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -31,6 +31,7 @@ void msm_dp_bridge_hpd_enable(struct drm_bridge *bridge); void msm_dp_bridge_hpd_disable(struct drm_bridge *bridge); void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status); + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); #endif /* _DP_DRM_H_ */ diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index bd6c4d2dcdc86..0815f15703e9b 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -429,7 +429,8 @@ static void hdmi4_bridge_disable(struct drm_bridge *bridge, static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status) + enum drm_connector_status status, + enum drm_connector_status_extra extra_status) { struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 7a5bdae8f8fcf..644cd85823eb0 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -509,7 +509,8 @@ struct drm_bridge_funcs { */ void (*hpd_notify)(struct drm_bridge *bridge, struct drm_connector *connector, - enum drm_connector_status status); + enum drm_connector_status status, + enum drm_connector_status_extra extra_status); /** * @hpd_enable: From d270bafb51c42a7028ffb79bf16c6ebc689502aa Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:07 +0300 Subject: [PATCH 1019/1133] FROMLIST: drm/msm: dp: handle the IRQ_HPD events reported by USB-C The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side, for example DP MST events. Let the MSM DisplayPort driver properly track and handle IRQ_HPD delivered over the OOB events (e.g. from the USB-C AltMode handler). Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-6-30b62b335487@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 2a8ab6e06dd41..784383d65cf4e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1806,11 +1806,12 @@ void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, msm_dp_display->connector_type, hpd_link_status, status); if (status == connector_status_connected) { - if (hpd_link_status == ISR_HPD_REPLUG_COUNT) { + if (hpd_link_status == ISR_IRQ_HPD_PULSE_COUNT || + extra_status == DRM_CONNECTOR_DP_IRQ_HPD) { + msm_dp_irq_hpd_handle(dp); + } else if (hpd_link_status == ISR_HPD_REPLUG_COUNT) { msm_dp_hpd_unplug_handle(dp); msm_dp_hpd_plug_handle(dp); - } else if (hpd_link_status == ISR_IRQ_HPD_PULSE_COUNT) { - msm_dp_irq_hpd_handle(dp); } else { msm_dp_hpd_plug_handle(dp); } From 6190658413b4cb878feec99fbe8658a0fef22a65 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:08 +0300 Subject: [PATCH 1020/1133] FROMLIST: soc: qcom: pmic-glink-altmode: pass down HPD_IRQ events The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Pass IRQ_HPD events from the firmware to the HPD bridge, letting those to be delivered to the DisplayPort driver. Reviewed-by: Konrad Dybcio Acked-by: Bjorn Andersson Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-7-30b62b335487@oss.qualcomm.com/ --- drivers/soc/qcom/pmic_glink_altmode.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 465e5d2316a04..e903d4910e9c8 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -374,7 +374,11 @@ static void pmic_glink_altmode_worker(struct work_struct *work) else conn_status = connector_status_disconnected; - drm_aux_hpd_bridge_notify(&alt_port->bridge->dev, conn_status); + drm_aux_hpd_bridge_notify_extra(&alt_port->bridge->dev, + conn_status, + alt_port->hpd_irq ? + DRM_CONNECTOR_DP_IRQ_HPD : + DRM_CONNECTOR_NO_EXTRA_STATUS); } else if (alt_port->mux_ctrl == MUX_CTRL_STATE_TUNNELING) { if (alt_port->svid == USB_TYPEC_TBT_SID) pmic_glink_altmode_enable_tbt(altmode, alt_port); From e73edf61545c9144800c26116b2c6fa627b9f11b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 8 Jun 2026 00:33:09 +0300 Subject: [PATCH 1021/1133] FROMLIST: usb: typec: ucsi: huawei-gaokun: pass down HPD_IRQ events The DisplayPort standard defines a special kind of HPD events called IRQ_HPD. These events are used to notify DP Source about the events on the Sink side. Pass IRQ_HPD events from the EC to the HPD bridge, letting those to be delivered to the DisplayPort driver. Reviewed-by: Pengyu Luo Acked-by: Heikki Krogerus Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/all/20260608-hpd-irq-events-v4-8-30b62b335487@oss.qualcomm.com/ --- drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c b/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c index 57b37fca150c2..cb0312e2b8dc2 100644 --- a/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c +++ b/drivers/usb/typec/ucsi/ucsi_huawei_gaokun.c @@ -316,10 +316,13 @@ static void gaokun_ucsi_handle_usb_mode(struct gaokun_ucsi_port *port) /* UCSI callback .connector_status() have set orientation */ if (port->bridge && port->svid == USB_TYPEC_DP_SID) - drm_aux_hpd_bridge_notify(&port->bridge->dev, - port->hpd_state ? - connector_status_connected : - connector_status_disconnected); + drm_aux_hpd_bridge_notify_extra(&port->bridge->dev, + port->hpd_state ? + connector_status_connected : + connector_status_disconnected, + port->hpd_irq ? + DRM_CONNECTOR_DP_IRQ_HPD : + DRM_CONNECTOR_NO_EXTRA_STATUS); gaokun_ec_ucsi_pan_ack(uec->ec, port->idx); } From b5fd19bb12edd657ae97b30403b77bb29ccef755 Mon Sep 17 00:00:00 2001 From: Ravi Agola Date: Wed, 22 Jul 2026 18:12:31 +0530 Subject: [PATCH 1022/1133] FROMLIST: drm/bridge: lt9611uxc: support displays with up to 4 EDID blocks The LT9611UXC bridge can fetch only 2 EDID blocks at a time, which previously limited EDID reading to 2 blocks and prevented support for displays exposing more than 2 EDID blocks. Add driver support to fetch up to 4 EDID blocks by re-triggering EDID access after the first 2 blocks are read. For block 0 and 2, set the EDID ready flag in 0xb028 so the bridge can expose the corresponding EDID blocks, then retry the read until the expected EDID is fetched. Reset the edid_read flag on HPD disconnect so that the next connect event triggers a fresh EDID fetch. Increase EDID wait time from 500ms to 1000ms, On Qualcomm rb3gen2 platform sometimes edid read interrupt is coming 600-650 ms after HPD interrupt resulting in edid read failure. Signed-off-by: Ravi Agola Link: https://lore.kernel.org/all/20260722-lt9611usc_edid34_misc_next-v3-1-7ec2bba6ff8e@oss.qualcomm.com/ Signed-off-by: Vishnu Saini --- drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 80 ++++++++++++++++++---- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index 85e4f0e60c261..880314b2b0714 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -28,7 +28,7 @@ #include #define EDID_BLOCK_SIZE 128 -#define EDID_NUM_BLOCKS 2 +#define EDID_NUM_BLOCKS 4 #define FW_FILE "lt9611uxc_fw.bin" @@ -170,6 +170,8 @@ static void lt9611uxc_hpd_work(struct work_struct *work) mutex_lock(<9611uxc->ocm_lock); connected = lt9611uxc->hdmi_connected; + if (!connected) + lt9611uxc->edid_read = false; mutex_unlock(<9611uxc->ocm_lock); if (!connected) @@ -388,13 +390,39 @@ lt9611uxc_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connect static int lt9611uxc_wait_for_edid(struct lt9611uxc *lt9611uxc) { return wait_event_interruptible_timeout(lt9611uxc->wq, lt9611uxc->edid_read, - msecs_to_jiffies(500)); + msecs_to_jiffies(1000)); +} + +static int lt9611uxc_read_edid_block(struct lt9611uxc *lt9611uxc, unsigned int block, + u8 *buf, size_t len) +{ + int ret; + + lt9611uxc_lock(lt9611uxc); + + regmap_write(lt9611uxc->regmap, 0xb00a, (block % 2) * EDID_BLOCK_SIZE); + + ret = regmap_noinc_read(lt9611uxc->regmap, 0xb0b0, buf, len); + if (ret) { + dev_err(lt9611uxc->dev, "edid block %d read failed: %d\n", block, ret); + lt9611uxc_unlock(lt9611uxc); + return -EINVAL; + } + lt9611uxc_unlock(lt9611uxc); + + return ret; } static int lt9611uxc_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) { struct lt9611uxc *lt9611uxc = data; - int ret; + int ret = 0; + int retry_cnt = 10; + unsigned int edid_ready_flag = 0; + bool header_matched; + bool edid_valid = false; + const u8 edid_header[8] = { 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x00 }; if (len > EDID_BLOCK_SIZE) return -EINVAL; @@ -402,20 +430,48 @@ static int lt9611uxc_get_edid_block(void *data, u8 *buf, unsigned int block, siz if (block >= EDID_NUM_BLOCKS) return -EINVAL; - lt9611uxc_lock(lt9611uxc); + if (block == 0 || block == 2) { - regmap_write(lt9611uxc->regmap, 0xb00b, 0x10); + lt9611uxc_lock(lt9611uxc); - regmap_write(lt9611uxc->regmap, 0xb00a, block * EDID_BLOCK_SIZE); + edid_ready_flag = (block == 0) ? BIT(0) : BIT(1); - ret = regmap_noinc_read(lt9611uxc->regmap, 0xb0b0, buf, len); - if (ret) - dev_err(lt9611uxc->dev, "edid read failed: %d\n", ret); + /* + * Set the EDID ready flag so that lt9611uxc can fetch correct EDID block + */ + regmap_write(lt9611uxc->regmap, 0xb028, edid_ready_flag); - lt9611uxc_unlock(lt9611uxc); + lt9611uxc_unlock(lt9611uxc); - return 0; -}; + do { + msleep(100); + ret = lt9611uxc_read_edid_block(lt9611uxc, block, buf, len); + if (ret) + break; + /* + * Compare first 8 bytes of EDID header for block 0 and block 2 + * to confirm EDID read successfully + */ + header_matched = (memcmp(edid_header, buf, 8) == 0); + edid_valid = (block == 0 && header_matched) || + (block == 2 && !header_matched); + if (edid_valid) + break; + + } while (retry_cnt-- > 0); + + if (!ret && !edid_valid) + ret = -ETIMEDOUT; + } else { + ret = lt9611uxc_read_edid_block(lt9611uxc, block, buf, len); + + lt9611uxc_lock(lt9611uxc); + regmap_write(lt9611uxc->regmap, 0xb028, 0x00); + lt9611uxc_unlock(lt9611uxc); + } + + return ret; +} static const struct drm_edid *lt9611uxc_bridge_edid_read(struct drm_bridge *bridge, struct drm_connector *connector) From 28dd8ba5fe4c0c5f94153cf000dd33cfb93a3df4 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 20 Jul 2026 16:43:54 +0800 Subject: [PATCH 1023/1133] FROMLIST: drm/msm/mdss: Enable INT2_GDSC alongside CORE_GDSC Kaanapali (SM8750) and Glymur use two display power domains. CORE_GDSC powers the main display hardware while INT2_GDSC powers a subset of SSPP blocks (VIG2/VIG3/DMA5/DMA6). The MDSS driver currently relies on the default runtime PM handling and does not enable the secondary INT2_GDSC. As a result, display pipes backed by INT2_GDSC remain inaccessible. Attach and manage both power domains explicitly and enable them during MDSS runtime PM activation. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260720-msm_gdsc2-v1-2-4687866d6cb0@oss.qualcomm.com/ --- drivers/gpu/drm/msm/msm_mdss.c | 53 +++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index e69b122f2687a..fb0261ae9c789 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,7 @@ struct msm_mdss { struct icc_path *mdp_path[2]; u32 num_mdp_paths; struct icc_path *reg_bus_path; + struct dev_pm_domain_list *pd_list; }; static int msm_mdss_parse_data_bus_icc_path(struct device *dev, @@ -248,6 +250,21 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss) int ret, i; u32 hw_rev; + /* + * Platforms with two power domains (e.g. Kaanapali, Glymur) need both + * GDSCs enabled explicitly; the core framework only auto-attaches a + * single power domain. + */ + if (msm_mdss->pd_list) { + ret = pm_runtime_resume_and_get(msm_mdss->pd_list->pd_devs[0]); + if (ret < 0) + return ret; + + ret = pm_runtime_resume_and_get(msm_mdss->pd_list->pd_devs[1]); + if (ret < 0) + goto err_put_core; + } + /* * Several components have AXI clocks that can only be turned on if * the interconnect is enabled (non-zero bandwidth). Let's make sure @@ -270,7 +287,7 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss) ret = clk_bulk_prepare_enable(msm_mdss->num_clocks, msm_mdss->clocks); if (ret) { dev_err(msm_mdss->dev, "clock enable failed, ret:%d\n", ret); - return ret; + goto err_put_int2; } /* @@ -291,6 +308,14 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss) /* else UBWC 1.0 or none, no params to program */ return ret; + +err_put_int2: + if (msm_mdss->pd_list) + pm_runtime_put_sync(msm_mdss->pd_list->pd_devs[1]); +err_put_core: + if (msm_mdss->pd_list) + pm_runtime_put_sync(msm_mdss->pd_list->pd_devs[0]); + return ret; } static int msm_mdss_disable(struct msm_mdss *msm_mdss) @@ -305,6 +330,11 @@ static int msm_mdss_disable(struct msm_mdss *msm_mdss) if (msm_mdss->reg_bus_path) icc_set_bw(msm_mdss->reg_bus_path, 0, 0); + if (msm_mdss->pd_list) { + pm_runtime_put_sync(msm_mdss->pd_list->pd_devs[1]); + pm_runtime_put_sync(msm_mdss->pd_list->pd_devs[0]); + } + return 0; } @@ -436,6 +466,27 @@ static struct msm_mdss *msm_mdss_init(struct platform_device *pdev, bool is_mdp5 irq_set_chained_handler_and_data(irq, msm_mdss_irq, msm_mdss); + /* + * When two power domains are listed in DT, the core framework does not + * auto-attach either of them. Attach and manage both explicitly so + * that INT2_GDSC (needed for VIG2/VIG3) is enabled alongside the main + * CORE_GDSC. Single-domain platforms are unaffected. + */ + if (of_count_phandle_with_args(pdev->dev.of_node, "power-domains", + "#power-domain-cells") > 1) { + static const char * const mdss_pd_names[] = { "core", "int2" }; + static const struct dev_pm_domain_attach_data pd_data = { + .pd_names = mdss_pd_names, + .num_pd_names = ARRAY_SIZE(mdss_pd_names), + .pd_flags = PD_FLAG_NO_DEV_LINK, + }; + + ret = devm_pm_domain_attach_list(&pdev->dev, &pd_data, + &msm_mdss->pd_list); + if (ret < 0) + return ERR_PTR(ret); + } + pm_runtime_enable(&pdev->dev); return msm_mdss; From 4f0a6188cfeb7462a6300685863a75f1a7412a84 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Sun, 2 Aug 2026 16:57:34 +0800 Subject: [PATCH 1024/1133] FROMLIST: dt-bindings: display: msm: Allow two MDSS power domains Kaanapali (SM8750) and Glymur use two display power domains. CORE_GDSC powers the main display hardware while INT2_GDSC powers a subset of SSPP blocks. Allow the MDSS bindings to describe both power domains and their corresponding power-domain-names values. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260720-msm_gdsc2-v1-1-4687866d6cb0@oss.qualcomm.com/ --- .../bindings/display/msm/mdss-common.yaml | 3 ++- .../bindings/display/msm/qcom,glymur-mdss.yaml | 13 ++++++++++++- .../bindings/display/msm/qcom,kaanapali-mdss.yaml | 13 ++++++++++++- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/mdss-common.yaml b/Documentation/devicetree/bindings/display/msm/mdss-common.yaml index c6305a6e03346..c0b650ffd9ef8 100644 --- a/Documentation/devicetree/bindings/display/msm/mdss-common.yaml +++ b/Documentation/devicetree/bindings/display/msm/mdss-common.yaml @@ -31,7 +31,8 @@ properties: const: mdss power-domains: - maxItems: 1 + minItems: 1 + maxItems: 2 clocks: minItems: 2 diff --git a/Documentation/devicetree/bindings/display/msm/qcom,glymur-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,glymur-mdss.yaml index 64dde43373ac7..685bedb26a124 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,glymur-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,glymur-mdss.yaml @@ -38,6 +38,16 @@ properties: - const: mdp0-mem - const: cpu-cfg + power-domains: + items: + - description: MDSS core GDSC power domain + - description: MDSS INT2 GDSC power domain + + power-domain-names: + items: + - const: core + - const: int2 + patternProperties: "^display-controller@[0-9a-f]+$": type: object @@ -95,7 +105,8 @@ examples: resets = <&disp_cc_mdss_core_bcr>; - power-domains = <&mdss_gdsc>; + power-domains = <&mdss_gdsc>, <&mdss_int2_gdsc>; + power-domain-names = "core", "int2"; iommus = <&apps_smmu 0x1c00 0x2>; diff --git a/Documentation/devicetree/bindings/display/msm/qcom,kaanapali-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,kaanapali-mdss.yaml index 9f935defd6b12..088010f464c3d 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,kaanapali-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,kaanapali-mdss.yaml @@ -40,6 +40,16 @@ properties: - const: mdp0-mem - const: cpu-cfg + power-domains: + items: + - description: MDSS core GDSC power domain + - description: MDSS INT2 GDSC power domain + + power-domain-names: + items: + - const: core + - const: int2 + patternProperties: "^display-controller@[0-9a-f]+$": type: object @@ -89,7 +99,8 @@ examples: <&disp_cc_mdss_ahb_swi_clk>; resets = <&disp_cc_mdss_core_bcr>; - power-domains = <&mdss_gdsc>; + power-domains = <&mdss_gdsc>, <&mdss_int2_gdsc>; + power-domain-names = "core", "int2"; iommus = <&apps_smmu 0x800 0x2>; From 675d611ee9af9e9af377a9e947d7d7446bc589da Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Thu, 30 Jul 2026 18:16:26 +0530 Subject: [PATCH 1025/1133] FROMLIST: drm/atomic-helper: tear down HPD/polling in drm_atomic_helper_shutdown() drm_atomic_helper_shutdown() disables all CRTCs but leaves output polling and IRQ-driven hot-plug detection running. On reboot, a late DP hot-plug-detect (HPD) IRQ can fire after apps_smmu has already disabled translation for the display subsystem, causing the HPD thread to kick off a new modeset that drives DPU/DP hardware and DMA through a stale IOMMU mapping. drm_atomic_helper_shutdown() disables all CRTCs first, but a pending HPD IRQ thread wakes up afterwards, reads the DPCD, and fires an unsolicited hotplug event that triggers a second atomic commit turning the display back on -- right as the IOMMU is disabling translation: systemd-shutdown[1]: Rebooting. msm_dpu: drm_atomic_commit: committing (shutdown disabling CRTCs) arm-smmu 3da0000.iommu: disabling translation msm_dpu: drm_dp_read_dpcd_caps (late HPD IRQ thread wakes up) msm_dpu: drm_sysfs_connector_hotplug_event: DP-1 hotplug event msm_dpu: drm_client_modeset_probe: DP-1 found preferred mode msm_dpu: drm_atomic_commit: committing (unsolicited, re-enables display) dpu_crtc_commit_kickoff: crtc94 first commit arm-smmu 15200000.iommu: disabling translation drm_kms_helper_poll_fini() tears down this: it stops the output poll worker and calls each connector's &drm_connector_helper_funcs.disable_hpd, which for HPD-capable bridges masks the interrupt in hardware. Reported on Qualcomm platforms such as lemans-evk and monaco-evk during reboot stress testing. Assisted-by: Claude:claude-sonnet-5 Link: https://lore.kernel.org/all/20260730-dpshutdown-v2-1-441fc5543bed@oss.qualcomm.com/ Signed-off-by: Mahadevan P --- drivers/gpu/drm/drm_atomic_helper.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9d006f98413a5..0bcbe6eb337c8 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -3676,6 +3677,8 @@ EXPORT_SYMBOL(drm_atomic_helper_reset_crtc); * * This is just a convenience wrapper around drm_atomic_helper_disable_all(), * and it is the atomic version of drm_helper_force_disable_all(). + * + * This also tears down output polling and HPD via drm_kms_helper_poll_fini(). */ void drm_atomic_helper_shutdown(struct drm_device *dev) { @@ -3685,6 +3688,8 @@ void drm_atomic_helper_shutdown(struct drm_device *dev) if (dev == NULL) return; + drm_kms_helper_poll_fini(dev); + DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); ret = drm_atomic_helper_disable_all(dev, &ctx); From 441e43295d7737194163a3fd800427566b2a5733 Mon Sep 17 00:00:00 2001 From: Saurabh Anand Date: Wed, 19 Aug 2026 14:01:43 +0530 Subject: [PATCH 1026/1133] FROMLIST: phy: qcom: qmp-combo: delay Type-C mux switch while DP PHY is initializing The Type-C mux switch guard only checked dp_powered_on, which is set in qmp_combo_dp_power_on(). However there is a race window between qmp_combo_dp_init() and qmp_combo_dp_power_on() during which dp_init_count is non-zero but dp_powered_on is still false. A Type-C orientation change arriving in this window would proceed with the mux switch while the DP PHY is mid-initialization, corrupting the PHY state. Extend the guard to also block the mux switch when dp_init_count is non-zero, covering the full period from dp_init through dp_power_on. Link: https://lore.kernel.org/all/20260824-qcom-dp-typec-reconnect-fixes-v1-1-2825e5bf8a96@oss.qualcomm.com/ Signed-off-by: Saurabh Anand --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 4c871e9f7f8ed..88a9748f8ca24 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -5220,7 +5220,8 @@ static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_s return 0; } - if (qmp->qmpphy_mode != QMPPHY_MODE_USB3_ONLY && qmp->dp_powered_on) { + if (qmp->qmpphy_mode != QMPPHY_MODE_USB3_ONLY && + (qmp->dp_powered_on || qmp->dp_init_count)) { dev_dbg(qmp->dev, "typec_mux_set: DP PHY is still in use, delaying switch\n"); return 0; } From 6b850a6d809309295caa8f635604907953965fe8 Mon Sep 17 00:00:00 2001 From: Saurabh Anand Date: Wed, 19 Aug 2026 14:11:26 +0530 Subject: [PATCH 1027/1133] FROMLIST: drm/msm/dp: clear force_link_train flag when link training succeeds msm_dp_display_prepare_link() sets force_link_train = true before calling msm_dp_ctrl_on_link(). On success the flag was never cleared, so msm_dp_ctrl_prepare_stream_on() would unconditionally trigger a second link retrain even though the link was already trained. Clear force_link_train on the success path so that msm_dp_ctrl_prepare_stream_on() only retrains when the channel EQ check fails, as intended. Link: https://lore.kernel.org/all/20260824-qcom-dp-typec-reconnect-fixes-v1-2-2825e5bf8a96@oss.qualcomm.com/ Signed-off-by: Saurabh Anand --- drivers/gpu/drm/msm/dp/dp_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 784383d65cf4e..ccd24cfa05266 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -750,6 +750,8 @@ int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display) DRM_ERROR("Failed link training (rc=%d)\n", rc); // TODO: schedule drm_connector_set_link_status_property() return rc; + } else { + force_link_train = false; } } From 89e9d08c35cc213022e758f6bc596cbce0f616fa Mon Sep 17 00:00:00 2001 From: Saurabh Anand Date: Wed, 19 Aug 2026 14:14:57 +0530 Subject: [PATCH 1028/1133] FROMLIST: drm/msm/dp: skip LTTPR init when no LTTPRs are present drm_dp_lttpr_count() returns 0 when no LTTPRs are detected and a negative value on error. The previous code passed the result directly to drm_dp_lttpr_init() without checking, which would call into the LTTPR transparency-mode setup with a zero or negative repeater count. Add an early return for lttpr_count <= 0 to skip the init entirely when there are no repeaters in the link, matching the expected usage of drm_dp_lttpr_init(). Link: https://lore.kernel.org/all/20260824-qcom-dp-typec-reconnect-fixes-v1-3-2825e5bf8a96@oss.qualcomm.com/ Signed-off-by: Saurabh Anand --- drivers/gpu/drm/msm/dp/dp_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index ccd24cfa05266..0b6654524dbfa 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -262,6 +262,10 @@ static int msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd return 0; lttpr_count = drm_dp_lttpr_count(dp->link->lttpr_common_caps); + + if (lttpr_count <= 0) + return 0; + rc = drm_dp_lttpr_init(dp->aux, lttpr_count); if (rc) { DRM_ERROR("failed to set LTTPRs transparency mode, rc=%d\n", rc); From 738ccad185db2bc01d742b179c6f013eeaa5d26f Mon Sep 17 00:00:00 2001 From: Saurabh Anand Date: Wed, 19 Aug 2026 14:44:05 +0530 Subject: [PATCH 1029/1133] FROMLIST: drm/msm/dp: continue link training downgrade when cable is still plugged During a Type-C reconnect the AUX channel may report link-disconnected transiently while the physical cable is still present. The link training retry loop in msm_dp_ctrl_on_link() was aborting immediately on any msm_dp_aux_is_link_connected() failure, preventing the rate/lane downgrade path from running. When the display is known to be plugged (msm_dp_ctrl->plugged), an AUX link-disconnected status is likely a transient glitch rather than a true unplug. Allow the downgrade loop to continue in that case by requiring both conditions before breaking out of the retry loop: AUX reports disconnected and the display is not plugged. The plugged state is snapshotted from dp_display into msm_dp_ctrl just before msm_dp_ctrl_on_link() is called, so the retry loop has an accurate view of cable presence at the time link training started. Link: https://lore.kernel.org/all/20260824-qcom-dp-typec-reconnect-fixes-v1-4-2825e5bf8a96@oss.qualcomm.com/ Signed-off-by: Saurabh Anand --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 4 ++-- drivers/gpu/drm/msm/dp/dp_ctrl.h | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 6c2248e3aa17b..7e890f79b4bc3 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -2564,7 +2564,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, break; } else if (training_step == DP_TRAINING_1) { /* link train_1 failed */ - if (!msm_dp_aux_is_link_connected(ctrl->aux)) + if (!msm_dp_aux_is_link_connected(ctrl->aux) && !msm_dp_ctrl->plugged) break; drm_dp_dpcd_read_link_status(ctrl->aux, link_status); @@ -2589,7 +2589,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, } } else if (training_step == DP_TRAINING_2) { /* link train_2 failed */ - if (!msm_dp_aux_is_link_connected(ctrl->aux)) + if (!msm_dp_aux_is_link_connected(ctrl->aux) && !msm_dp_ctrl->plugged) break; drm_dp_dpcd_read_link_status(ctrl->aux, link_status); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 111300784edda..ca138a3b44c5c 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -12,6 +12,7 @@ struct msm_dp_ctrl { bool wide_bus_en; + bool plugged; }; struct phy; diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 0b6654524dbfa..72a9c9c6477e8 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -748,6 +748,7 @@ int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display) if (!msm_dp_display->active_stream_cnt) { msm_dp_display_host_phy_init(dp); force_link_train = true; + dp->ctrl->plugged = dp->plugged; rc = msm_dp_ctrl_on_link(dp->ctrl, dp->panel); if (rc) { From cf3b19dfbe349e7621209f2b050bfd2e830a57dc Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Mon, 3 Aug 2026 16:43:08 +0800 Subject: [PATCH 1030/1133] FROMLIST: drm/bridge: aux-hpd-bridge: replay last HPD status on hpd_enable If a downstream consumer (e.g. drm_bridge_connector attached by the msm/dp driver) registers its HPD callback after an upstream driver has already reported a HPD event through drm_aux_hpd_bridge_notify(), the notification is dropped because bridge->hpd_cb is still NULL. This can affect any user of drm_aux_hpd_bridge_notify() whose downstream consumer arms HPD only after upstream events have started. The race has been observed on Qualcomm X1E-based laptops during boot, when pmic_glink_altmode reports the initial USB-C DP connection state before the DP driver has finished probing and enabled HPD handling on the bridge. The consumer then never observes the initial connected state and the external display remains dark. Cache the last HPD status reported through drm_aux_hpd_bridge_notify() and replay it when HPD is enabled by the downstream consumer. The replay is deferred to a work item so that the replayed HPD notification is delivered outside drm_bridge_hpd_enable()'s call context. This follows the same pattern as display-connector, which also defers an initial HPD notification from .hpd_enable(), but reuses the cached status since aux-hpd-bridge cannot re-detect sink presence on its own. Fixes: e560518a6c2e ("drm/bridge: implement generic DP HPD bridge") Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260803-drm-usbdp-preboot-v1-1-2539b362be00@oss.qualcomm.com/ --- drivers/gpu/drm/bridge/aux-hpd-bridge.c | 61 ++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c index e8a3786bd199b..bf0ebef1fcac9 100644 --- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c +++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -18,6 +19,17 @@ static DEFINE_IDA(drm_aux_hpd_bridge_ida); struct drm_aux_hpd_bridge_data { struct drm_bridge bridge; struct device *dev; + + /* + * Last HPD status pushed through drm_aux_hpd_bridge_notify(). + * Replayed from .hpd_enable so that consumers registering their + * callback after the initial notification are caught up. + * + * Accessed lockless from the notify path (writer) and hpd_work + * (reader) - use WRITE_ONCE()/READ_ONCE(). + */ + enum drm_connector_status last_status; + struct work_struct hpd_work; }; static void drm_aux_hpd_bridge_release(struct device *dev) @@ -157,6 +169,16 @@ void drm_aux_hpd_bridge_notify_extra(struct device *dev, if (!data) return; + /* + * Only cache real connection state changes. IRQ_HPD-only events + * (sink attention on an already-connected link) pass + * connector_status_unknown and must not clobber the last real + * connected/disconnected state, otherwise the replay from + * .hpd_enable would be skipped. + */ + if (status != connector_status_unknown) + WRITE_ONCE(data->last_status, status); + drm_bridge_hpd_notify_extra(&data->bridge, status, extra_status); } EXPORT_SYMBOL_GPL(drm_aux_hpd_bridge_notify_extra); @@ -168,11 +190,45 @@ static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge, return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL; } +static void drm_aux_hpd_bridge_hpd_work(struct work_struct *work) +{ + struct drm_aux_hpd_bridge_data *data = + container_of(work, struct drm_aux_hpd_bridge_data, hpd_work); + enum drm_connector_status status = READ_ONCE(data->last_status); + + if (status == connector_status_unknown) + return; + + drm_bridge_hpd_notify(&data->bridge, status); +} + +/* + * Deferred to a work because drm_bridge_hpd_notify() takes + * bridge->hpd_mutex which is already held by drm_bridge_hpd_enable(). + */ +static void drm_aux_hpd_bridge_hpd_enable(struct drm_bridge *bridge) +{ + struct drm_aux_hpd_bridge_data *data = + container_of(bridge, struct drm_aux_hpd_bridge_data, bridge); + + schedule_work(&data->hpd_work); +} + +static void drm_aux_hpd_bridge_hpd_disable(struct drm_bridge *bridge) +{ + struct drm_aux_hpd_bridge_data *data = + container_of(bridge, struct drm_aux_hpd_bridge_data, bridge); + + cancel_work_sync(&data->hpd_work); +} + static const struct drm_bridge_funcs drm_aux_hpd_bridge_funcs = { .atomic_create_state = drm_atomic_helper_bridge_create_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, - .attach = drm_aux_hpd_bridge_attach, + .attach = drm_aux_hpd_bridge_attach, + .hpd_enable = drm_aux_hpd_bridge_hpd_enable, + .hpd_disable = drm_aux_hpd_bridge_hpd_disable, }; static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev, @@ -195,6 +251,9 @@ static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev, data->bridge.interlace_allowed = true; data->bridge.ycbcr_420_allowed = true; + data->last_status = connector_status_unknown; + INIT_WORK(&data->hpd_work, drm_aux_hpd_bridge_hpd_work); + auxiliary_set_drvdata(auxdev, data); return devm_drm_bridge_add(data->dev, &data->bridge); From 3c0716cc4867f044822f9d77cc29ea3754e83e62 Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Thu, 3 Sep 2026 08:10:37 +0530 Subject: [PATCH 1031/1133] FROMLIST: arm64: defconfig: Enable Lontium LT9211 driver Lontium LT9211 driver is extended to support LT9211C bridge, which is available on qualcomm ifp mezzanine boards of lemans/monaco and QCS6490 RB3GEN2 Industrial Kit. Link: https://lore.kernel.org/all/20260907-for-next-lt9211-defconfig-v2-1-c9af0c085b78@oss.qualcomm.com/ Signed-off-by: Vishnu Saini --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 7b4985b29b21c..5d966980b175f 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -979,6 +979,7 @@ CONFIG_DRM_FSL_LDB=m CONFIG_DRM_I2C_NXP_TDA998X=m CONFIG_DRM_ITE_IT6263=m CONFIG_DRM_LONTIUM_LT8912B=m +CONFIG_DRM_LONTIUM_LT9211=m CONFIG_DRM_LONTIUM_LT9611=m CONFIG_DRM_LONTIUM_LT9611UXC=m CONFIG_DRM_LONTIUM_LT8713SX=m From f51c5887560e46a8889ba070f591f2767c2b19f9 Mon Sep 17 00:00:00 2001 From: Sunyun Yang Date: Thu, 3 Sep 2026 00:50:33 +0530 Subject: [PATCH 1032/1133] FROMLIST: dt-bindings: bridge: Add Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver LT9611C(EX/UXD) is an I2C-controlled chip that Receiver signal/dual port mipi dsi and output hdmi, differences in hardware features: - LT9611C: supports 1-port mipi dsi to hdmi 1.4 - LT9611EX: supports 2-port mipi dsi to hdmi 1.4 - LT9611UXD: supports 2-port mipi dsi to hdmi 1.4/2.0 Link: https://lore.kernel.org/dri-devel/20260903-lt9611c-v7-v12-1-9414d2b3bd6d@oss.qualcomm.com/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sunyun Yang Signed-off-by: Mohit Dsor --- .../display/bridge/lontium,lt9611.yaml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml index 429a06057ae85..194aeaac601f3 100644 --- a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml @@ -4,19 +4,23 @@ $id: http://devicetree.org/schemas/display/bridge/lontium,lt9611.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Lontium LT9611(UXC) 2 Port MIPI to HDMI Bridge +title: Lontium LT9611(UXC/C/EX/UXD) 2 Port MIPI DSI to HDMI Bridge maintainers: - Vinod Koul description: | - The LT9611 and LT9611UXC are bridge devices which convert DSI to HDMI + The LT9611, LT9611UXC, LT9611C, LT9611EX, and LT9611UXD + are bridge devices which convert DSI to HDMI properties: compatible: enum: - lontium,lt9611 + - lontium,lt9611c + - lontium,lt9611ex - lontium,lt9611uxc + - lontium,lt9611uxd reg: maxItems: 1 @@ -78,6 +82,16 @@ required: allOf: - $ref: /schemas/sound/dai-common.yaml# + - if: + properties: + compatible: + contains: + const: lontium,lt9611c + then: + properties: + ports: + properties: + port@1: false unevaluatedProperties: false From 21fe7e0a730874abc07033745f5c52bea4ff0ee5 Mon Sep 17 00:00:00 2001 From: Sunyun Yang Date: Thu, 3 Sep 2026 00:50:34 +0530 Subject: [PATCH 1033/1133] FROMLIST: drm/bridge: Add Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver LT9611C(EX/UXD) is an I2C-controlled chip that Receiver signal/dual port mipi dsi and output hdmi, differences in hardware features: Link: https://lore.kernel.org/dri-devel/20260903-lt9611c-v7-v12-2-9414d2b3bd6d@oss.qualcomm.com/ Reviewed-by: Dmitry Baryshkov Signed-off-by: Sunyun Yang Co-developed-by: Mohit Dsor Signed-off-by: Mohit Dsor --- .../ABI/testing/sysfs-lontium-firmware | 10 + drivers/gpu/drm/bridge/Kconfig | 17 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/lontium-lt9611c.c | 1290 +++++++++++++++++ 4 files changed, 1318 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-lontium-firmware create mode 100644 drivers/gpu/drm/bridge/lontium-lt9611c.c diff --git a/Documentation/ABI/testing/sysfs-lontium-firmware b/Documentation/ABI/testing/sysfs-lontium-firmware new file mode 100644 index 0000000000000..8700933ba0f02 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-lontium-firmware @@ -0,0 +1,10 @@ +What: /sys/bus/i2c/drivers//.../firmware +Date: July 2026 +KernelVersion: 7.3 +Contact: Mohit Dsor +Description: + Read: Returns the current firmware version loaded on the + Lontium bridge chip in hex format (e.g. "0x0105"). + + Write: Triggers a firmware upgrade of the chip using the + firmware file loaded via the firmware loader. diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index c7da6b02d7b6b..0a66831fb4827 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -177,6 +177,23 @@ config DRM_LONTIUM_LT9611 HDMI signals Please say Y if you have such hardware. +config DRM_LONTIUM_LT9611C + tristate "Lontium LT9611C DSI/HDMI bridge" + select SND_SOC_HDMI_CODEC if SND_SOC + depends on OF && I2C + select CRC8 + select FW_LOADER + select DRM_KMS_HELPER + select DRM_MIPI_DSI + select DRM_DISPLAY_HELPER + select DRM_DISPLAY_HDMI_STATE_HELPER + select REGMAP_I2C + help + Driver for the Lontium LT9611C(EX/UXD) DSI to HDMI bridge chip. + It converts single or dual MIPI DSI and I2S signals to HDMI + output. Supports HDMI 1.4 (LT9611C/EX) and HDMI 2.0 (LT9611UXD). + Say Y if you have hardware using this chip. + config DRM_LONTIUM_LT9611UXC tristate "Lontium LT9611UXC DSI/HDMI bridge" select SND_SOC_HDMI_CODEC if SND_SOC diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 15cc821d85b7e..f322f3f89f6bf 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_DRM_ITE_IT6505) += ite-it6505.o obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o obj-$(CONFIG_DRM_LONTIUM_LT9211) += lontium-lt9211.o obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o +obj-$(CONFIG_DRM_LONTIUM_LT9611C) += lontium-lt9611c.o obj-$(CONFIG_DRM_LONTIUM_LT9611UXC) += lontium-lt9611uxc.o obj-$(CONFIG_DRM_LONTIUM_LT8713SX) += lontium-lt8713sx.o obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c new file mode 100644 index 0000000000000..ef1e9726fdd3c --- /dev/null +++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c @@ -0,0 +1,1290 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2026 Lontium Semiconductor, Inc. + * Copyright (C) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FW_SIZE (64 * 1024) +#define LT_PAGE_SIZE 256 +#define FW_FILE "Lontium/lt9611c_fw.bin" +#define LT9611C_CRC_POLYNOMIAL 0x31 +#define LT9611C_PAGE_CONTROL 0xff +#define LT9611C_INFOFRAME_MAX_SIZE 32 +#define LT9611C_CMD_HDR_SIZE 4 +#define LT9611C_CMD_Y0_SIZE 1 /* Y0 echo byte in ACK response */ +#define LT9611C_EDID_BUF_SIZE 32 + +struct lt9611c_cmd_hdr { + u8 func; + u8 type; + u8 seq; + u8 sep; +}; + +/* lt9611c_cmd_hdr.func values */ +#define LT9611C_FUNC_WRITE 0x57 /* 'W' */ +#define LT9611C_FUNC_READ 0x52 /* 'R' */ +#define LT9611C_FUNC_ACK 0x41 /* 'A' */ + +/* lt9611c_cmd_hdr.type values */ +#define LT9611C_TYPE_MIPI 0x4d /* 'M' */ +#define LT9611C_TYPE_LVDS 0x4c /* 'L' */ +#define LT9611C_TYPE_HDMI 0x48 /* 'H' */ +#define LT9611C_TYPE_AUDIO 0x41 /* 'A' */ +#define LT9611C_TYPE_CUSTOM 0x43 /* 'C' */ + +/* lt9611c_cmd_hdr.sep is always ':' */ +#define LT9611C_CMD_SEP 0x3a /* ':' */ + +struct lt9611c_cmd { + struct lt9611c_cmd_hdr hdr; + const u8 *data; + size_t data_len; +}; + +struct lt9611c_rsp { + struct lt9611c_cmd_hdr hdr; + u8 *data; + unsigned int data_len; +}; + +enum lt9611_chip_type { + CHIP_LT9611C = 0, + CHIP_LT9611EX, + CHIP_LT9611UXD, +}; + +struct lt9611c_chip_data { + enum lt9611_chip_type chip_type; + unsigned long long max_tmds_rate; +}; + +static const struct lt9611c_chip_data lt9611c_chip_data[] = { + [CHIP_LT9611C] = { CHIP_LT9611C, 340000000 }, + [CHIP_LT9611EX] = { CHIP_LT9611EX, 340000000 }, + [CHIP_LT9611UXD] = { CHIP_LT9611UXD, 600000000 }, +}; + +struct lt9611c { + struct device *dev; + struct i2c_client *client; + struct drm_bridge bridge; + struct regmap *regmap; + struct mutex mcu_lock; + struct work_struct work; + struct gpio_desc *reset_gpio; + struct regulator_bulk_data supplies[2]; + int fw_version; + const struct lt9611c_chip_data *cdata; + bool hdmi_connected; +}; + +DECLARE_CRC8_TABLE(lt9611c_crc8_table); + +static const struct regmap_range_cfg lt9611c_ranges[] = { + { + .name = "register_range", + .range_min = 0, + .range_max = 0xfe9c, + .selector_reg = LT9611C_PAGE_CONTROL, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, + }, +}; + +static const struct regmap_config lt9611c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xfe9c, + .ranges = lt9611c_ranges, + .num_ranges = ARRAY_SIZE(lt9611c_ranges), +}; + +static int lt9611c_read_write_flow(struct lt9611c *lt9611c, + const struct lt9611c_cmd *cmd, + struct lt9611c_rsp *rsp) +{ + int ret; + unsigned int i; + unsigned int temp; + unsigned int max_params = 0xe0dd - 0xe0b0 + 1; + + regmap_write(lt9611c->regmap, 0xe0de, 0x01); + + ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, + temp == 0x01, 1000, 200 * 1000); + if (ret) + return -ETIMEDOUT; + + ret = regmap_bulk_write(lt9611c->regmap, 0xe0b0, &cmd->hdr, + LT9611C_CMD_HDR_SIZE); + if (ret) + return ret; + + for (i = 0; cmd->data && i < cmd->data_len && + (LT9611C_CMD_HDR_SIZE + i) < max_params; i++) + regmap_write(lt9611c->regmap, + 0xe0b0 + LT9611C_CMD_HDR_SIZE + i, cmd->data[i]); + + regmap_write(lt9611c->regmap, 0xe0de, 0x02); + + ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp, + temp == 0x02, 1000, 200 * 1000); + if (ret) + return -ETIMEDOUT; + + ret = regmap_bulk_read(lt9611c->regmap, 0xe085, + &rsp->hdr, LT9611C_CMD_HDR_SIZE); + if (ret) + return ret; + + + if (rsp->data && rsp->data_len) + ret = regmap_bulk_read(lt9611c->regmap, + 0xe085 + LT9611C_CMD_HDR_SIZE, + rsp->data, rsp->data_len); + + return ret; +} + +static void lt9611c_lock(struct lt9611c *lt9611c) +{ + mutex_lock(<9611c->mcu_lock); + regmap_write(lt9611c->regmap, 0xe0ee, 0x01); +} + +static void lt9611c_unlock(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe0ee, 0x00); + mutex_unlock(<9611c->mcu_lock); +} + +static void lt9611c_config_parameters(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write_paras[] = { + REG_SEQ0(0xe0ee, 0x01), + REG_SEQ0(0xe103, 0x3f), /* fifo rst */ + REG_SEQ0(0xe103, 0xff), + REG_SEQ0(0xe05e, 0xc1), + REG_SEQ0(0xe058, 0x00), + REG_SEQ0(0xe059, 0x50), + REG_SEQ0(0xe05a, 0x10), + REG_SEQ0(0xe05a, 0x00), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write_paras, ARRAY_SIZE(seq_write_paras)); +} + +static void lt9611c_wren(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe05a, 0x04); + regmap_write(lt9611c->regmap, 0xe05a, 0x00); +} + +static void lt9611c_wrdi(struct lt9611c *lt9611c) +{ + regmap_write(lt9611c->regmap, 0xe05a, 0x08); + regmap_write(lt9611c->regmap, 0xe05a, 0x00); +} + +static void lt9611c_erase_op(struct lt9611c *lt9611c, u32 addr) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe0ee, 0x01), + REG_SEQ0(0xe05a, 0x04), + REG_SEQ0(0xe05a, 0x00), + REG_SEQ0(0xe05b, (addr >> 16) & 0xff), + REG_SEQ0(0xe05c, (addr >> 8) & 0xff), + REG_SEQ0(0xe05d, addr & 0xff), + REG_SEQ0(0xe05a, 0x01), + REG_SEQ0(0xe05a, 0x00), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static unsigned int read_flash_reg_status(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe103, 0x3f), + REG_SEQ0(0xe103, 0xff), + REG_SEQ0(0xe05e, 0x40), + REG_SEQ0(0xe056, 0x05), + REG_SEQ0(0xe055, 0x25), + REG_SEQ0(0xe055, 0x01), + REG_SEQ0(0xe058, 0x21), + }; + unsigned int status; + int ret; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); + ret = regmap_read(lt9611c->regmap, 0xe05f, &status); + if (ret) + return 0xff; + + return status; +} + +static void lt9611c_crc_to_sram(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe051, 0x00), + REG_SEQ0(0xe055, 0xc0), + REG_SEQ0(0xe055, 0x80), + REG_SEQ0(0xe05e, 0xc0), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void lt9611c_data_to_sram(struct lt9611c *lt9611c) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe051, 0xff), + REG_SEQ0(0xe055, 0x80), + REG_SEQ0(0xe05e, 0xc0), + REG_SEQ0(0xe058, 0x21), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static void lt9611c_sram_to_flash(struct lt9611c *lt9611c, size_t addr) +{ + const struct reg_sequence seq_write[] = { + REG_SEQ0(0xe05b, (addr >> 16) & 0xff), + REG_SEQ0(0xe05c, (addr >> 8) & 0xff), + REG_SEQ0(0xe05d, addr & 0xff), + REG_SEQ0(0xe05a, 0x30), + REG_SEQ0(0xe05a, 0x00), + }; + + regmap_multi_reg_write(lt9611c->regmap, seq_write, ARRAY_SIZE(seq_write)); +} + +static int lt9611c_block_erase(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + unsigned int block_num; + unsigned int flash_status = 0; + u32 flash_addr = 0; + int ret; + + for (block_num = 0; block_num < 2; block_num++) { + flash_addr = block_num * 0x008000; + lt9611c_erase_op(lt9611c, flash_addr); + msleep(100); + ret = read_poll_timeout(read_flash_reg_status, flash_status, + !(flash_status & 0x01), + 50 * USEC_PER_MSEC, 2500 * USEC_PER_MSEC, + false, lt9611c); + if (ret) { + dev_err(dev, "flash erase timeout for block %u\n", block_num); + return ret; + } + } + + return 0; +} + +static int lt9611c_write_data(struct lt9611c *lt9611c, const struct firmware *fw, size_t addr) +{ + struct device *dev = lt9611c->dev; + unsigned int npages; + size_t size = fw->size; + const u8 *data = fw->data; + + npages = DIV_ROUND_UP(size, LT_PAGE_SIZE); + if (npages * LT_PAGE_SIZE > FW_SIZE) { + dev_err(dev, "firmware size out of range\n"); + return -EINVAL; + } + + dev_dbg(dev, "%u pages, total size %zu byte\n", npages, size); + + for (unsigned int num = 0; num < npages; num++) { + lt9611c_data_to_sram(lt9611c); + + for (unsigned int i = 0; i < LT_PAGE_SIZE; i++) { + size_t index = num * LT_PAGE_SIZE + i; + u8 value = (index < size) ? data[index] : 0xff; + int ret; + + ret = regmap_write(lt9611c->regmap, 0xe059, value); + if (ret < 0) { + dev_err(dev, "write error at page %u, index %u\n", num, i); + return ret; + } + } + + lt9611c_wren(lt9611c); + lt9611c_sram_to_flash(lt9611c, addr); + + addr += LT_PAGE_SIZE; + } + + lt9611c_wrdi(lt9611c); + + return 0; +} + +static int lt9611c_write_crc(struct lt9611c *lt9611c, u8 fw_crc, size_t addr) +{ + struct device *dev = lt9611c->dev; + int ret; + + lt9611c_crc_to_sram(lt9611c); + ret = regmap_write(lt9611c->regmap, 0xe059, fw_crc); + if (ret < 0) { + dev_err(dev, "failed to write crc\n"); + return ret; + } + + lt9611c_wren(lt9611c); + lt9611c_sram_to_flash(lt9611c, addr); + lt9611c_wrdi(lt9611c); + + dev_dbg(dev, "crc 0x%02x written to flash at addr 0x%zx\n", fw_crc, addr); + + return 0; +} + +static void lt9611c_reset(struct lt9611c *lt9611c) +{ + gpiod_set_value_cansleep(lt9611c->reset_gpio, 1); + usleep_range(10000, 12000); + + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); + msleep(400); +} + +static int lt9611c_upgrade_result(struct lt9611c *lt9611c, u8 fw_crc) +{ + struct device *dev = lt9611c->dev; + unsigned int crc_result; + int ret; + + regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + ret = regmap_read(lt9611c->regmap, 0xe021, &crc_result); + if (ret) + return dev_err_probe(dev, ret, "failed to read firmware crc\n"); + + if (crc_result != fw_crc) { + dev_err(dev, "lt9611c fw upgrade failed, expected crc=0x%02x, read crc=0x%02x\n", + fw_crc, crc_result); + return -EIO; + } + + dev_info(dev, "lt9611c firmware upgrade success, crc=0x%02x\n", crc_result); + return 0; +} + +static int lt9611c_firmware_upgrade(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + const struct firmware *fw; + u8 *buffer; + size_t total_size = FW_SIZE - 1; + u8 fw_crc; + int ret; + + ret = request_firmware(&fw, FW_FILE, dev); + if (ret) + return dev_err_probe(dev, ret, "failed to load '%s'\n", FW_FILE); + + if (fw->size > total_size) { + dev_err(dev, "firmware too large (%zu > %zu)\n", fw->size, total_size); + ret = -EINVAL; + goto out_release_fw; + } + dev_dbg(dev, "firmware size: %zu bytes\n", fw->size); + + buffer = kzalloc(total_size, GFP_KERNEL); + if (!buffer) { + ret = -ENOMEM; + goto out_release_fw; + } + + memcpy(buffer, fw->data, fw->size); + memset(buffer + fw->size, 0xff, total_size - fw->size); + + fw_crc = crc8(lt9611c_crc8_table, buffer, total_size, 0); + kfree(buffer); + + dev_info(dev, "starting firmware upgrade, size: %zu bytes, crc: 0x%02x\n", + fw->size, fw_crc); + + /* hardware access requires mcu_lock */ + lt9611c_lock(lt9611c); + + lt9611c_config_parameters(lt9611c); + ret = lt9611c_block_erase(lt9611c); + if (ret < 0) + goto out_unlock; + + ret = lt9611c_write_data(lt9611c, fw, 0); + if (ret < 0) { + dev_err(dev, "failed to write firmware data\n"); + goto out_unlock; + } + + ret = lt9611c_write_crc(lt9611c, fw_crc, FW_SIZE - 1); + if (ret < 0) { + dev_err(dev, "failed to write firmware crc\n"); + goto out_unlock; + } + + lt9611c_reset(lt9611c); + ret = lt9611c_upgrade_result(lt9611c, fw_crc); + +out_unlock: + lt9611c_unlock(lt9611c); +out_release_fw: + release_firmware(fw); + return ret; +} + +static struct lt9611c *bridge_to_lt9611c(struct drm_bridge *bridge) +{ + return container_of(bridge, struct lt9611c, bridge); +} + +static const struct lt9611c *bridge_to_lt9611c_const(const struct drm_bridge *bridge) +{ + return container_of_const(bridge, struct lt9611c, bridge); +} + +static irqreturn_t lt9611c_irq_thread_handler(int irq, void *dev_id) +{ + struct lt9611c *lt9611c = dev_id; + struct device *dev = lt9611c->dev; + int ret; + unsigned int irq_status; + + guard(mutex)(<9611c->mcu_lock); + + ret = regmap_read(lt9611c->regmap, 0xe084, &irq_status); + if (ret) { + dev_err(dev, "failed to read irq status: %d\n", ret); + return IRQ_HANDLED; + } + + if (!(irq_status & BIT(0))) + return IRQ_NONE; + + /* Clear interrupt: hardware requires two writes with delay */ + regmap_write(lt9611c->regmap, 0xe0df, irq_status & BIT(0)); + usleep_range(10000, 12000); + regmap_write(lt9611c->regmap, 0xe0df, irq_status & (~BIT(0))); + + schedule_work(<9611c->work); + + return IRQ_HANDLED; +} + +static void lt9611c_hpd_work(struct work_struct *work) +{ + struct lt9611c *lt9611c = container_of(work, struct lt9611c, work); + struct device *dev = lt9611c->dev; + static const u8 hpd_data[] = { 0x00 }; + struct lt9611c_cmd cmd = { + .hdr = { LT9611C_FUNC_READ, LT9611C_TYPE_HDMI, 0x31, LT9611C_CMD_SEP }, + .data = hpd_data, + .data_len = 1, + }; + u8 hpd_status; + struct lt9611c_rsp rsp = { .data = &hpd_status, .data_len = 1 }; + bool connected; + int ret; + + /* Added delay as need time to reflect hpd after interrupt*/ + msleep(200); + + mutex_lock(<9611c->mcu_lock); + ret = lt9611c_read_write_flow(lt9611c, &cmd, &rsp); + if (ret) + dev_err(dev, "failed to read HPD status\n"); + else + lt9611c->hdmi_connected = (hpd_status == 0x02); + + connected = lt9611c->hdmi_connected; + mutex_unlock(<9611c->mcu_lock); + + drm_bridge_hpd_notify(<9611c->bridge, + connected ? connector_status_connected : + connector_status_disconnected); +} + +static int lt9611c_regulator_init(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + int ret; + + lt9611c->supplies[0].supply = "vcc"; + lt9611c->supplies[1].supply = "vdd"; + + ret = devm_regulator_bulk_get(dev, 2, lt9611c->supplies); + if (ret) + return ret; + + return regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); +} + +static struct mipi_dsi_device *lt9611c_attach_dsi(struct lt9611c *lt9611c, + struct device_node *dsi_node) +{ + const struct mipi_dsi_device_info info = { "lt9611c", 0, NULL }; + struct mipi_dsi_device *dsi; + struct mipi_dsi_host *host; + struct device *dev = lt9611c->dev; + int ret; + + host = of_find_mipi_dsi_host_by_node(dsi_node); + if (!host) + return ERR_PTR(dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n")); + + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + if (IS_ERR(dsi)) + return ERR_PTR(dev_err_probe(dev, PTR_ERR(dsi), "failed to create dsi device\n")); + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_VIDEO_HSE; + + ret = devm_mipi_dsi_attach(dev, dsi); + if (ret < 0) + return ERR_PTR(dev_err_probe(dev, ret, "failed to attach dsi to host\n")); + + return dsi; +} + +static int lt9611c_bridge_attach(struct drm_bridge *bridge, + struct drm_encoder *encoder, + enum drm_bridge_attach_flags flags) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) + return -EINVAL; + + return drm_bridge_attach(encoder, lt9611c->bridge.next_bridge, bridge, flags); +} + +static enum drm_mode_status +lt9611c_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge, + const struct drm_display_mode *mode, + unsigned long long tmds_rate) +{ + const struct lt9611c *lt9611c = bridge_to_lt9611c_const(bridge); + + if (tmds_rate > lt9611c->cdata->max_tmds_rate) + return MODE_CLOCK_HIGH; + + if (tmds_rate < 25000000) + return MODE_CLOCK_LOW; + + return MODE_OK; +} + +static void lt9611c_video_setup(struct lt9611c *lt9611c, + const struct drm_display_mode *mode) +{ + struct device *dev = lt9611c->dev; + int ret; + struct { + __be16 htotal; + __be16 hactive; + __be16 hfront_porch; + __be16 hsync_len; + __be16 hback_porch; + __be16 vtotal; + __be16 vactive; + __be16 vfront_porch; + __be16 vsync_len; + __be16 vback_porch; + u8 framerate; + u8 vic; + } timing_data; + struct lt9611c_rsp rsp = {}; + struct lt9611c_cmd cmd = { + .hdr = { LT9611C_FUNC_WRITE, LT9611C_TYPE_MIPI, 0x33, LT9611C_CMD_SEP }, + .data = (u8 *)&timing_data, + .data_len = sizeof(timing_data), + }; + + guard(mutex)(<9611c->mcu_lock); + + timing_data.htotal = cpu_to_be16(mode->htotal); + timing_data.hactive = cpu_to_be16(mode->hdisplay); + timing_data.hfront_porch = cpu_to_be16(mode->hsync_start - mode->hdisplay); + timing_data.hsync_len = cpu_to_be16(mode->hsync_end - mode->hsync_start); + timing_data.hback_porch = cpu_to_be16(mode->htotal - mode->hsync_end); + timing_data.vtotal = cpu_to_be16(mode->vtotal); + timing_data.vactive = cpu_to_be16(mode->vdisplay); + timing_data.vfront_porch = cpu_to_be16(mode->vsync_start - mode->vdisplay); + timing_data.vsync_len = cpu_to_be16(mode->vsync_end - mode->vsync_start); + timing_data.vback_porch = cpu_to_be16(mode->vtotal - mode->vsync_end); + timing_data.framerate = drm_mode_vrefresh(mode); + timing_data.vic = drm_match_cea_mode(mode); + + dev_dbg(dev, "hactive=%d, vactive=%d\n", mode->hdisplay, mode->vdisplay); + dev_dbg(dev, "framerate=%d\n", timing_data.framerate); + dev_dbg(dev, "vic = 0x%02x\n", timing_data.vic); + + ret = lt9611c_read_write_flow(lt9611c, &cmd, &rsp); + if (ret) + dev_err(dev, "video set failed\n"); +} + +static void lt9611c_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_commit *state) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_display_mode *mode; + + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); + if (WARN_ON(!connector)) + return; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!conn_state)) + return; + + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (WARN_ON(!crtc_state)) + return; + + mode = &crtc_state->adjusted_mode; + + lt9611c_video_setup(lt9611c, mode); +} + +static enum drm_connector_status +lt9611c_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + struct device *dev = lt9611c->dev; + int ret; + bool connected = false; + static const u8 hpd_data[] = { 0x00 }; + struct lt9611c_cmd cmd = { + .hdr = { LT9611C_FUNC_READ, LT9611C_TYPE_HDMI, 0x31, LT9611C_CMD_SEP }, + .data = hpd_data, + .data_len = 1, + }; + u8 hpd_status; + struct lt9611c_rsp rsp = { .data = &hpd_status, .data_len = 1 }; + + guard(mutex)(<9611c->mcu_lock); + + ret = lt9611c_read_write_flow(lt9611c, &cmd, &rsp); + if (ret) + dev_err(dev, "failed to read HPD status (err=%d)\n", ret); + else + connected = (hpd_status == 0x02); + + lt9611c->hdmi_connected = connected; + + return connected ? connector_status_connected : + connector_status_disconnected; +} + +static int lt9611c_get_edid_block(void *data, u8 *buf, + unsigned int block, size_t len) +{ + struct lt9611c *lt9611c = data; + struct device *dev = lt9611c->dev; + u8 edid_raw[LT9611C_CMD_Y0_SIZE + LT9611C_EDID_BUF_SIZE]; + u8 y0; + int ret, i, offset = 0; + struct lt9611c_cmd cmd = { + .hdr = { LT9611C_FUNC_READ, LT9611C_TYPE_HDMI, 0x33, LT9611C_CMD_SEP }, + }; + struct lt9611c_rsp rsp = { + .data = edid_raw, + .data_len = LT9611C_CMD_Y0_SIZE + LT9611C_EDID_BUF_SIZE, + }; + + if (len != 128) + return -EINVAL; + guard(mutex)(<9611c->mcu_lock); + + for (i = 0; i < 4; i++) { + y0 = block * 4 + i; + cmd.data = &y0; + cmd.data_len = 1; + ret = lt9611c_read_write_flow(lt9611c, &cmd, &rsp); + if (ret) { + dev_err(dev, "Failed to read EDID block %u packet %d\n", + block, i); + return ret; + } + memcpy(buf + offset, &edid_raw[LT9611C_CMD_Y0_SIZE], LT9611C_EDID_BUF_SIZE); + offset += LT9611C_EDID_BUF_SIZE; + } + + return 0; +} + +static const struct drm_edid *lt9611c_bridge_edid_read(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + return drm_edid_read_custom(connector, lt9611c_get_edid_block, lt9611c); +} + +static int lt9611c_write_infoframe(struct lt9611c *lt9611c, u8 type, + const u8 *buffer, size_t len) +{ + u8 extra[1 + LT9611C_INFOFRAME_MAX_SIZE]; + struct lt9611c_rsp rsp = {}; + struct lt9611c_cmd cmd = { + .hdr = { LT9611C_FUNC_WRITE, LT9611C_TYPE_HDMI, 0x35, LT9611C_CMD_SEP }, + }; + + if (WARN_ON(len > LT9611C_INFOFRAME_MAX_SIZE)) + return -EINVAL; + + extra[0] = type; + memcpy(&extra[1], buffer, len); + cmd.data = extra; + cmd.data_len = 1 + len; + + lockdep_assert_held(<9611c->mcu_lock); + + return lt9611c_read_write_flow(lt9611c, &cmd, &rsp); +} + +static int lt9611c_clear_infoframe(struct lt9611c *lt9611c, u8 type) +{ + u8 clear_data = type; + struct lt9611c_cmd cmd = { + .hdr = { LT9611C_FUNC_WRITE, LT9611C_TYPE_HDMI, 0x42, LT9611C_CMD_SEP }, + .data = &clear_data, + .data_len = 1, + }; + struct lt9611c_rsp rsp = {}; + + lockdep_assert_held(<9611c->mcu_lock); + + return lt9611c_read_write_flow(lt9611c, &cmd, &rsp); +} + +static int lt9611c_hdmi_write_avi_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + guard(mutex)(<9611c->mcu_lock); + return lt9611c_write_infoframe(lt9611c, 0x01, buffer, len); +} + +static int lt9611c_hdmi_clear_avi_infoframe(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + guard(mutex)(<9611c->mcu_lock); + return lt9611c_clear_infoframe(lt9611c, 0x01); +} + +static int lt9611c_hdmi_write_hdmi_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + guard(mutex)(<9611c->mcu_lock); + return lt9611c_write_infoframe(lt9611c, 0x04, buffer, len); +} + +static int lt9611c_hdmi_clear_hdmi_infoframe(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + guard(mutex)(<9611c->mcu_lock); + return lt9611c_clear_infoframe(lt9611c, 0x04); +} + +static int lt9611c_hdmi_write_audio_infoframe(struct drm_bridge *bridge, + const u8 *buffer, size_t len) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + guard(mutex)(<9611c->mcu_lock); + return lt9611c_write_infoframe(lt9611c, 0x02, buffer, len); +} + +static int lt9611c_hdmi_clear_audio_infoframe(struct drm_bridge *bridge) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + + guard(mutex)(<9611c->mcu_lock); + return lt9611c_clear_infoframe(lt9611c, 0x02); +} + +static int lt9611c_hdmi_audio_prepare(struct drm_bridge *bridge, + struct drm_connector *connector, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms) +{ + struct lt9611c *lt9611c = bridge_to_lt9611c(bridge); + u8 audio_extra[2]; + struct lt9611c_rsp rsp = {}; + int ret; + struct lt9611c_cmd cmd = { + .hdr = { LT9611C_FUNC_WRITE, LT9611C_TYPE_HDMI, 0x36, LT9611C_CMD_SEP }, + .data = audio_extra, + .data_len = ARRAY_SIZE(audio_extra) }; + + if (hparms->sample_width == 32) + return -EINVAL; + + switch (fmt->fmt) { + case HDMI_I2S: + audio_extra[0] = 0x01; + break; + case HDMI_SPDIF: + audio_extra[0] = 0x02; + break; + default: + return -EINVAL; + } + + audio_extra[1] = hparms->channels; + + mutex_lock(<9611c->mcu_lock); + ret = lt9611c_read_write_flow(lt9611c, &cmd, &rsp); + mutex_unlock(<9611c->mcu_lock); + if (ret < 0) { + dev_err(lt9611c->dev, "set audio info failed!\n"); + return ret; + } + + return drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, + &hparms->cea); +} + +static void lt9611c_hdmi_audio_shutdown(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector); +} + +static const struct drm_bridge_funcs lt9611c_bridge_funcs = { + .attach = lt9611c_bridge_attach, + .detect = lt9611c_bridge_detect, + .edid_read = lt9611c_bridge_edid_read, + .atomic_enable = lt9611c_bridge_atomic_enable, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_create_state = drm_atomic_helper_bridge_create_state, + + .hdmi_tmds_char_rate_valid = lt9611c_hdmi_tmds_char_rate_valid, + .hdmi_write_avi_infoframe = lt9611c_hdmi_write_avi_infoframe, + .hdmi_clear_avi_infoframe = lt9611c_hdmi_clear_avi_infoframe, + .hdmi_write_hdmi_infoframe = lt9611c_hdmi_write_hdmi_infoframe, + .hdmi_clear_hdmi_infoframe = lt9611c_hdmi_clear_hdmi_infoframe, + .hdmi_write_audio_infoframe = lt9611c_hdmi_write_audio_infoframe, + .hdmi_clear_audio_infoframe = lt9611c_hdmi_clear_audio_infoframe, + + .hdmi_audio_prepare = lt9611c_hdmi_audio_prepare, + .hdmi_audio_shutdown = lt9611c_hdmi_audio_shutdown, +}; + +static int lt9611c_parse_dt(struct device *dev, + struct lt9611c *lt9611c, + struct device_node **dsi0_node, + struct device_node **dsi1_node) +{ + int ret; + + *dsi0_node = of_graph_get_remote_node(dev->of_node, 0, -1); + if (!*dsi0_node) + return dev_err_probe(dev, -ENODEV, "failed to get remote node for primary dsi\n"); + + *dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1); + + if (*dsi1_node && lt9611c->cdata->chip_type == CHIP_LT9611C) { + ret = dev_err_probe(dev, -EINVAL, + "LT9611C does not support dual DSI\n"); + goto err_put_dsi1; + } + + lt9611c->bridge.next_bridge = of_drm_get_bridge_by_endpoint(dev->of_node, 2, -1); + if (IS_ERR(lt9611c->bridge.next_bridge)) { + ret = PTR_ERR(lt9611c->bridge.next_bridge); + goto err_put_dsi1; + } + + return 0; + +err_put_dsi1: + of_node_put(*dsi1_node); + of_node_put(*dsi0_node); + return ret; +} + +static int lt9611c_read_version(struct lt9611c *lt9611c) +{ + u8 buf[2]; + int ret; + + ret = regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + if (ret) + return ret; + + ret = regmap_bulk_read(lt9611c->regmap, 0xe080, buf, ARRAY_SIZE(buf)); + if (ret) + return ret; + + return (buf[0] << 8) | buf[1]; +} + +static int lt9611c_read_chipid(struct lt9611c *lt9611c) +{ + struct device *dev = lt9611c->dev; + u8 chipid[2]; + int ret; + + ret = regmap_write(lt9611c->regmap, 0xe0ee, 0x01); + if (ret) + return ret; + + ret = regmap_bulk_read(lt9611c->regmap, 0xe100, chipid, 2); + if (ret) + return ret; + + if (chipid[0] != 0x23 || chipid[1] != 0x06) { + dev_err(dev, "ChipID: 0x%02x 0x%02x\n", chipid[0], chipid[1]); + return -ENODEV; + } + + return 0; +} + +static ssize_t firmware_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + dev_warn(dev, "starting firmware upgrade — display will be disrupted\n"); + + ret = lt9611c_firmware_upgrade(lt9611c); + if (ret < 0) { + dev_err(dev, "upgrade failure\n"); + return ret; + } + + lt9611c_lock(lt9611c); + lt9611c->fw_version = lt9611c_read_version(lt9611c); + lt9611c_unlock(lt9611c); + + if (lt9611c->fw_version < 0) + dev_warn(dev, "upgrade succeeded but failed to read new fw version\n"); + else + dev_info(dev, "firmware upgrade succeeded, version: 0x%04x\n", + lt9611c->fw_version); + + return len; +} + +static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + + return sysfs_emit(buf, "0x%04x\n", lt9611c->fw_version); +} + +static DEVICE_ATTR_RW(firmware); + +static struct attribute *lt9611c_attrs[] = { + &dev_attr_firmware.attr, + NULL, +}; + +static const struct attribute_group lt9611c_attr_group = { + .attrs = lt9611c_attrs, +}; + +static const struct attribute_group *lt9611c_attr_groups[] = { + <9611c_attr_group, + NULL, +}; + +static int lt9611c_probe(struct i2c_client *client) +{ + struct lt9611c *lt9611c; + struct device *dev = &client->dev; + struct device_node *dsi0_node __free(device_node) = NULL; + struct device_node *dsi1_node __free(device_node) = NULL; + struct mipi_dsi_device *dsi; + bool fw_updated = false; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return dev_err_probe(dev, -ENODEV, "device doesn't support I2C\n"); + + lt9611c = devm_drm_bridge_alloc(dev, struct lt9611c, bridge, <9611c_bridge_funcs); + if (IS_ERR(lt9611c)) + return dev_err_probe(dev, PTR_ERR(lt9611c), "drm bridge alloc failed.\n"); + + lt9611c->dev = dev; + lt9611c->client = client; + i2c_set_clientdata(client, lt9611c); + + const struct lt9611c_chip_data *cdata = i2c_get_match_data(client); + + if (!cdata) + return dev_err_probe(dev, -EINVAL, "no match data for device\n"); + + lt9611c->cdata = cdata; + + ret = devm_mutex_init(dev, <9611c->mcu_lock); + if (ret) + return dev_err_probe(dev, ret, "failed to init mutex\n"); + + lt9611c->regmap = devm_regmap_init_i2c(client, <9611c_regmap_config); + if (IS_ERR(lt9611c->regmap)) + return dev_err_probe(dev, PTR_ERR(lt9611c->regmap), "regmap i2c init failed\n"); + + ret = lt9611c_parse_dt(dev, lt9611c, &dsi0_node, &dsi1_node); + if (ret) + return dev_err_probe(dev, ret, "failed to parse device tree\n"); + + lt9611c->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(lt9611c->reset_gpio)) { + ret = PTR_ERR(lt9611c->reset_gpio); + return ret; + } + + ret = lt9611c_regulator_init(lt9611c); + if (ret < 0) + return ret; + + lt9611c_reset(lt9611c); + + lt9611c_lock(lt9611c); + + ret = lt9611c_read_chipid(lt9611c); + if (ret < 0) { + dev_err(dev, "failed to read chip id.\n"); + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } + +retry: + lt9611c->fw_version = lt9611c_read_version(lt9611c); + if (lt9611c->fw_version < 0) { + dev_err(dev, "failed to read fw version\n"); + ret = -EOPNOTSUPP; + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } else if (lt9611c->fw_version == 0) { + if (!fw_updated) { + fw_updated = true; + lt9611c_unlock(lt9611c); + ret = lt9611c_firmware_upgrade(lt9611c); + if (ret < 0) + goto err_disable_regulators; + lt9611c_lock(lt9611c); + goto retry; + + } else { + dev_err(dev, "fw version 0x%04x, update failed\n", lt9611c->fw_version); + ret = -EOPNOTSUPP; + lt9611c_unlock(lt9611c); + goto err_disable_regulators; + } + } + + lt9611c_unlock(lt9611c); + dev_dbg(dev, "current version:0x%04x", lt9611c->fw_version); + + INIT_WORK(<9611c->work, lt9611c_hpd_work); + + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, + lt9611c_irq_thread_handler, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT | + IRQF_NO_AUTOEN, + "lt9611c", lt9611c); + if (ret) { + dev_err(dev, "failed to request irq\n"); + goto err_disable_regulators; + } + + lt9611c->bridge.of_node = client->dev.of_node; + lt9611c->bridge.ops = DRM_BRIDGE_OP_DETECT | + DRM_BRIDGE_OP_EDID | + DRM_BRIDGE_OP_HPD | + DRM_BRIDGE_OP_HDMI | + DRM_BRIDGE_OP_HDMI_AUDIO; + lt9611c->bridge.type = DRM_MODE_CONNECTOR_HDMIA; + + lt9611c->bridge.vendor = "Lontium"; + lt9611c->bridge.product = "LT9611C"; + + lt9611c->bridge.hdmi_audio_dev = dev; + lt9611c->bridge.hdmi_audio_max_i2s_playback_channels = 8; + lt9611c->bridge.hdmi_audio_dai_port = 2; + + drm_bridge_add(<9611c->bridge); + + /* Attach primary DSI */ + dsi = lt9611c_attach_dsi(lt9611c, dsi0_node); + if (IS_ERR(dsi)) { + ret = PTR_ERR(dsi); + goto err_remove_bridge; + } + + /* Attach secondary DSI, if specified */ + if (dsi1_node) { + dsi = lt9611c_attach_dsi(lt9611c, dsi1_node); + if (IS_ERR(dsi)) { + ret = PTR_ERR(dsi); + goto err_remove_bridge; + } + } + + lt9611c->hdmi_connected = false; + enable_irq(client->irq); + + return 0; + +err_remove_bridge: + drm_bridge_remove(<9611c->bridge); + cancel_work_sync(<9611c->work); + +err_disable_regulators: + regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + + return ret; +} + +static void lt9611c_remove(struct i2c_client *client) +{ + struct lt9611c *lt9611c = i2c_get_clientdata(client); + + disable_irq(client->irq); + cancel_work_sync(<9611c->work); + drm_bridge_remove(<9611c->bridge); + regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); +} + +static int lt9611c_bridge_suspend(struct device *dev) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + disable_irq(lt9611c->client->irq); + cancel_work_sync(<9611c->work); + + gpiod_set_value_cansleep(lt9611c->reset_gpio, 1); + + ret = regulator_bulk_disable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) { + dev_err(lt9611c->dev, "regulator bulk disable failed.\n"); + gpiod_set_value_cansleep(lt9611c->reset_gpio, 0); + enable_irq(lt9611c->client->irq); + return ret; + } + + return 0; +} + +static int lt9611c_bridge_resume(struct device *dev) +{ + struct lt9611c *lt9611c = dev_get_drvdata(dev); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(lt9611c->supplies), lt9611c->supplies); + if (ret) { + dev_err(lt9611c->dev, "regulator bulk enable failed.\n"); + return ret; + } + lt9611c_reset(lt9611c); + enable_irq(lt9611c->client->irq); + + return ret; +} + +static const struct dev_pm_ops lt9611c_bridge_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(lt9611c_bridge_suspend, + lt9611c_bridge_resume) +}; + +static struct i2c_device_id lt9611c_id[] = { + { "lt9611c", (kernel_ulong_t)<9611c_chip_data[CHIP_LT9611C] }, + { "lt9611ex", (kernel_ulong_t)<9611c_chip_data[CHIP_LT9611EX] }, + { "lt9611uxd", (kernel_ulong_t)<9611c_chip_data[CHIP_LT9611UXD] }, + { /* sentinel */ } +}; + +static const struct of_device_id lt9611c_match_table[] = { + { .compatible = "lontium,lt9611c", .data = <9611c_chip_data[CHIP_LT9611C] }, + { .compatible = "lontium,lt9611ex", .data = <9611c_chip_data[CHIP_LT9611EX] }, + { .compatible = "lontium,lt9611uxd", .data = <9611c_chip_data[CHIP_LT9611UXD] }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, lt9611c_match_table); + +static struct i2c_driver lt9611c_driver = { + .driver = { + .name = "lt9611c", + .of_match_table = lt9611c_match_table, + .pm = <9611c_bridge_pm_ops, + .dev_groups = lt9611c_attr_groups, + }, + .probe = lt9611c_probe, + .remove = lt9611c_remove, + .id_table = lt9611c_id, +}; + +static int __init lt9611c_init(void) +{ + crc8_populate_msb(lt9611c_crc8_table, LT9611C_CRC_POLYNOMIAL); + return i2c_add_driver(<9611c_driver); +} +module_init(lt9611c_init); + +static void __exit lt9611c_exit(void) +{ + i2c_del_driver(<9611c_driver); +} +module_exit(lt9611c_exit); + +MODULE_AUTHOR("SunYun Yang "); +MODULE_DESCRIPTION("Lontium LT9611C(EX/UXD) MIPI DSI to HDMI driver"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FW_FILE); From 0e2fd8cd6d8df5c2e020054463680b90d6f8e04a Mon Sep 17 00:00:00 2001 From: Anand Tiwari Date: Mon, 14 Sep 2026 21:32:57 +0530 Subject: [PATCH 1034/1133] FROMLIST: drm: bridge: ti-sn65dsi83: Fix DSI mode flags for stable LVDS output The current DSI mode configuration enables VIDEO_BURST and disables horizontal front porch (HFP) and back porch (HBP) transmission using MIPI_DSI_MODE_VIDEO_NO_HFP and MIPI_DSI_MODE_VIDEO_NO_HBP. However, the SN65DSI83/84 bridge relies on receiving full horizontal timing information over DSI in order to correctly reconstruct the LVDS output timings. When HFP and HBP are not transmitted, the bridge cannot recreate the required timing parameters, resulting in unstable or missing display output on some panels. Additionally, while burst mode is supported by the hardware, its use depends on continuous clock behavior from the DSI host. In practice, burst mode may introduce instability depending on the host controller implementation, as the DSI link may transition to low-power state between bursts. In testing, removing burst mode and ensuring full horizontal timing transmission results in stable LVDS output across affected panels. Update the DSI mode flags to: - Drop MIPI_DSI_MODE_VIDEO_BURST - Drop MIPI_DSI_MODE_VIDEO_NO_HFP - Drop MIPI_DSI_MODE_VIDEO_NO_HBP This aligns with common system configurations where non-burst mode is preferred and full timing information is transmitted over DSI. Link: https://lore.kernel.org/all/20260412053811.662461-2-tessolveupstream@gmail.com/ Signed-off-by: Sudarshan Shetty Signed-off-by: Anand Tiwari --- drivers/gpu/drm/bridge/ti-sn65dsi83.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index eb5b249cc43c7..4c848ed7f7bd2 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -973,8 +973,8 @@ static int sn65dsi83_host_attach(struct sn65dsi83 *ctx) dsi->lanes = dsi_lanes; dsi->format = MIPI_DSI_FMT_RGB888; - dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | - MIPI_DSI_MODE_VIDEO_NO_HSA | MIPI_DSI_MODE_NO_EOT_PACKET; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_NO_HSA | + MIPI_DSI_MODE_NO_EOT_PACKET; ret = devm_mipi_dsi_attach(dev, dsi); if (ret < 0) { From 5b6e76cdf4f97ca534c5ecadeaa852198cb66a51 Mon Sep 17 00:00:00 2001 From: Arpit Saini Date: Thu, 24 Sep 2026 16:03:46 +0530 Subject: [PATCH 1035/1133] FROMLIST: drm/bridge: anx7625: Fix register access in low-power mode The INTERFACE_CHANGE_INT_MASK register was accessed outside the Type-C initialization path added for minimal Type-C support. On platforms without Type-C support, this causes the driver to access the RX-P0 I2C client while the ANX7625 is in its low-power configuration. The access fails during probe and results in errors such as: [drm:i2c_access_workaround.isra.0 [anx7625]] *ERROR* fail to access i2c id=3f :39 [drm:anx7625_i2c_probe [anx7625]] *ERROR* fail to write i2c id=3f :43 Keep the interrupt-mask update within the low-power-mode check block. Link: https://lore.kernel.org/all/20260924-latest_tag-v1-1-7150d373f042@oss.qualcomm.com/ Fixes: f81455b2d332 ("drm: bridge: anx7625: implement minimal Type-C support") Reported-by: Salendarsingh Gaud Signed-off-by: Arpit Saini --- drivers/gpu/drm/bridge/analogix/anx7625.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index c3af88e14f8b2..00f2132c7c473 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -2930,11 +2930,11 @@ static int anx7625_i2c_probe(struct i2c_client *client) pm_runtime_get_sync(dev); _anx7625_hpd_polling(platform, 5000 * 100); - } - if (platform->pdata.intp_irq) - anx7625_reg_write(platform, platform->i2c.rx_p0_client, - INTERFACE_CHANGE_INT_MASK, 0); + if (platform->pdata.intp_irq) + anx7625_reg_write(platform, platform->i2c.rx_p0_client, + INTERFACE_CHANGE_INT_MASK, 0); + } /* After getting runtime handle */ ret = anx7625_typec_register(platform); From ac09c8f93eb15ec7ced61b6244fd751552c99092 Mon Sep 17 00:00:00 2001 From: Shashank Maurya Date: Tue, 22 Sep 2026 21:01:59 +0530 Subject: [PATCH 1036/1133] FROMLIST: dt-bindings: regulator: rpi-panel-v2: Add vcc-supply property Add an optional vcc-supply property to the Raspberry Pi 7" touchscreen panel V2 regulator binding. The panel controller MCU is powered from an external power rail, which has to be supplied before any I2C communication can take place. The property is optional so that existing device trees which do not describe the supply remain valid. Link: https://lore.kernel.org/all/20260922-rpi_reg-v3-1-9214321c4070@oss.qualcomm.com/ Signed-off-by: Shashank Maurya Acked-by: Krzysztof Kozlowski Signed-off-by: Vishnu Saini --- .../raspberrypi,7inch-touchscreen-panel-regulator-v2.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/raspberrypi,7inch-touchscreen-panel-regulator-v2.yaml b/Documentation/devicetree/bindings/regulator/raspberrypi,7inch-touchscreen-panel-regulator-v2.yaml index 37b9ed371b67d..3e2cbcad64906 100644 --- a/Documentation/devicetree/bindings/regulator/raspberrypi,7inch-touchscreen-panel-regulator-v2.yaml +++ b/Documentation/devicetree/bindings/regulator/raspberrypi,7inch-touchscreen-panel-regulator-v2.yaml @@ -35,6 +35,9 @@ properties: const: 3 description: See ../../pwm/pwm.yaml for description of the cell formats. + vcc-supply: + description: Regulator supplying power to the panel controller. + additionalProperties: false required: @@ -55,6 +58,7 @@ examples: gpio-controller; #gpio-cells = <2>; #pwm-cells = <3>; + vcc-supply = <&vcc_reg>; }; }; From b4818ec4f469136700f6a8cc5bc5552ee27ea05f Mon Sep 17 00:00:00 2001 From: Shashank Maurya Date: Tue, 22 Sep 2026 21:02:00 +0530 Subject: [PATCH 1037/1133] FROMLIST: regulator: rpi-panel-v2: Add vcc-supply support The Raspberry Pi 7" touchscreen panel V2 MCU is powered from an external power rail which has to be enabled before any I2C register access is attempted. Use devm_regulator_get() to obtain the vcc supply and enable it at the start of probe. devm_regulator_get() returns a dummy regulator when the supply is not described in the device tree, so device trees without a vcc-supply property keep working as before. Link: https://lore.kernel.org/all/20260922-rpi_reg-v3-2-9214321c4070@oss.qualcomm.com/ Signed-off-by: Shashank Maurya Signed-off-by: Vishnu Saini --- drivers/regulator/rpi-panel-v2-regulator.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/regulator/rpi-panel-v2-regulator.c b/drivers/regulator/rpi-panel-v2-regulator.c index 30b78aa75ee38..e54d675962e71 100644 --- a/drivers/regulator/rpi-panel-v2-regulator.c +++ b/drivers/regulator/rpi-panel-v2-regulator.c @@ -11,6 +11,7 @@ #include #include #include +#include /* I2C registers of the microcontroller. */ #define REG_ID 0x01 @@ -66,10 +67,21 @@ static int rpi_panel_v2_i2c_probe(struct i2c_client *i2c) .parent = &i2c->dev, .reg_set_base = REG_POWERON, }; + struct regulator *vcc; struct regmap *regmap; struct pwm_chip *pc; int ret; + vcc = devm_regulator_get(&i2c->dev, "vcc"); + if (IS_ERR(vcc)) + return dev_err_probe(&i2c->dev, PTR_ERR(vcc), + "Failed to get vcc supply\n"); + + ret = regulator_enable(vcc); + if (ret) + return dev_err_probe(&i2c->dev, ret, + "Failed to enable vcc supply\n"); + pc = devm_pwmchip_alloc(&i2c->dev, 1, 0); if (IS_ERR(pc)) return PTR_ERR(pc); From da4c4379b08d29933142335166d87cf68f3a619f Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Sat, 26 Sep 2026 17:20:45 +0800 Subject: [PATCH 1038/1133] FROMLIST: drm/msm/dp: move link capabilities to dp_link Link rate, lane count and VSC SDP support describe capabilities of the physical DP link rather than an individual panel. While SST has only one panel per link, MST creates multiple stream panels sharing the same upstream link. Keeping link capabilities in struct msm_dp_panel would require each stream panel to maintain a copy of the same link state, mixing shared link capabilities with per-panel state. Move the capabilities to struct msm_dp_link so that SST and MST use the same link state. Rename link_info to link_caps to distinguish the link capabilities from link_params used during link training. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260929-msm-dp-mst-v7-23-4b81473185e7@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 6 +++--- drivers/gpu/drm/msm/dp/dp_debug.c | 6 +++--- drivers/gpu/drm/msm/dp/dp_display.c | 8 ++++---- drivers/gpu/drm/msm/dp/dp_link.h | 2 ++ drivers/gpu/drm/msm/dp/dp_panel.c | 22 ++++++++++++---------- drivers/gpu/drm/msm/dp/dp_panel.h | 2 -- 6 files changed, 24 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 7e890f79b4bc3..a4ff996799779 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1732,7 +1732,7 @@ static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl, return -1; ctrl->link->link_params.num_lanes /= 2; - ctrl->link->link_params.rate = panel->link_info.rate; + ctrl->link->link_params.rate = ctrl->link->link_caps.rate; ctrl->link->phy_params.p_level = 0; ctrl->link->phy_params.v_level = 0; @@ -2530,7 +2530,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl); - rate = panel->link_info.rate; + rate = ctrl->link->link_caps.rate; pixel_rate = panel->msm_dp_mode.drm_mode.clock; msm_dp_ctrl_core_clk_enable(&ctrl->msm_dp_ctrl); @@ -2543,7 +2543,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl, } else { ctrl->link->link_params.rate = rate; ctrl->link->link_params.num_lanes = - panel->link_info.num_lanes; + ctrl->link->link_caps.num_lanes; if (panel->msm_dp_mode.out_fmt_is_yuv_420) pixel_rate >>= 1; } diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 00fb1a7ba40ed..2a9ce77843bba 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -38,11 +38,11 @@ static int msm_dp_debug_show(struct seq_file *seq, void *p) seq_printf(seq, "\tname = %s\n", DEBUG_NAME); seq_printf(seq, "\tdrm_dp_link\n\t\trate = %u\n", - debug->panel->link_info.rate); + debug->link->link_caps.rate); seq_printf(seq, "\t\tnum_lanes = %u\n", - debug->panel->link_info.num_lanes); + debug->link->link_caps.num_lanes); seq_printf(seq, "\t\tcapabilities = %lu\n", - debug->panel->link_info.capabilities); + debug->link->link_caps.capabilities); seq_printf(seq, "\tdp_panel_info:\n\t\tactive = %dx%d\n", drm_mode->hdisplay, drm_mode->vdisplay); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 72a9c9c6477e8..93a8ed32bcbad 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -350,7 +350,7 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) * set sink to normal operation mode -- D0 * before dpcd read */ - msm_dp_link_psm_config(dp->link, &dp->panel->link_info, false); + msm_dp_link_psm_config(dp->link, &dp->link->link_caps, false); if (msm_dp_ctrl_get_stream_cnt(dp->ctrl) > 1 && drm_dp_read_mst_cap(dp->aux, dp->panel->dpcd)) @@ -873,7 +873,7 @@ enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, } msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); - link_info = &msm_dp_display->panel->link_info; + link_info = &msm_dp_display->link->link_caps; is_yuv_420 = drm_mode_is_420_only(&dp->connector->display_info, mode); @@ -881,7 +881,7 @@ enum drm_mode_status msm_dp_display_mode_valid(struct msm_dp *dp, * YUV 420 is carried over DP by signalling the colorimetry through a * VSC SDP, so a 420-only mode cannot be driven without VSC SDP support. */ - if (is_yuv_420 && !msm_dp_display->panel->vsc_sdp_supported) + if (is_yuv_420 && !msm_dp_display->link->vsc_sdp_supported) return MODE_NO_420; link_pclk_khz = is_yuv_420 ? mode_pclk_khz / 2 : mode_pclk_khz; @@ -1715,7 +1715,7 @@ void msm_dp_display_unprepare(struct msm_dp *msm_dp_display) /* dongle is still connected but sinks are disconnected */ if (dp->link->sink_count == 0) - msm_dp_link_psm_config(dp->link, &dp->panel->link_info, true); + msm_dp_link_psm_config(dp->link, &dp->link->link_caps, true); msm_dp_ctrl_off_link(dp->ctrl, dp->panel); diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index 76125e9c07e9c..80116d5c58be1 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -75,7 +75,9 @@ struct msm_dp_link { struct msm_dp_link_test_video test_video; struct msm_dp_link_test_audio test_audio; struct msm_dp_link_phy_params phy_params; + struct msm_dp_link_info link_caps; struct msm_dp_link_info link_params; + bool vsc_sdp_supported; u32 lane_map[DP_MAX_NUM_DP_LANES]; u32 max_dp_lanes; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index bc7bad5ca3b18..dd650b3dc9172 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -193,13 +193,14 @@ static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel) if (rc) return rc; - msm_dp_panel->vsc_sdp_supported = drm_dp_vsc_sdp_supported(panel->aux, dpcd); - link_info = &msm_dp_panel->link_info; + link = panel->link; + link->vsc_sdp_supported = drm_dp_vsc_sdp_supported(panel->aux, dpcd); + link_info = &link->link_caps; + memset(link_info, 0, sizeof(*link_info)); link_info->revision = dpcd[DP_DPCD_REV]; major = (link_info->revision >> 4) & 0x0f; minor = link_info->revision & 0x0f; - link = panel->link; drm_dbg_dp(panel->drm_dev, "max_lanes=%d max_link_rate=%d\n", link->max_dp_lanes, link->max_dp_link_rate); @@ -308,13 +309,15 @@ static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel) static u32 msm_dp_panel_get_supported_bpp(struct msm_dp_panel *msm_dp_panel, u32 mode_edid_bpp, u32 mode_pclk_khz) { + struct msm_dp_panel_private *panel = + container_of(msm_dp_panel, struct msm_dp_panel_private, msm_dp_panel); const struct msm_dp_link_info *link_info; const u32 max_supported_bpp = 30, min_supported_bpp = 18; u32 bpp, data_rate_khz; bpp = min(mode_edid_bpp, max_supported_bpp); - link_info = &msm_dp_panel->link_info; + link_info = &panel->link->link_caps; data_rate_khz = link_info->num_lanes * link_info->rate * 8; do { @@ -346,12 +349,12 @@ int msm_dp_panel_read_link_caps(struct msm_dp_panel *msm_dp_panel, return rc; } - bw_code = drm_dp_link_rate_to_bw_code(msm_dp_panel->link_info.rate); + bw_code = drm_dp_link_rate_to_bw_code(panel->link->link_caps.rate); if (!is_link_rate_valid(bw_code) || - !is_lane_count_valid(msm_dp_panel->link_info.num_lanes) || + !is_lane_count_valid(panel->link->link_caps.num_lanes) || (bw_code > msm_dp_panel->max_bw_code)) { - DRM_ERROR("Illegal link rate=%d lane=%d\n", msm_dp_panel->link_info.rate, - msm_dp_panel->link_info.num_lanes); + DRM_ERROR("Illegal link rate=%d lane=%d\n", panel->link->link_caps.rate, + panel->link->link_caps.num_lanes); return -EINVAL; } @@ -770,7 +773,7 @@ int msm_dp_panel_init_panel_info(struct msm_dp_panel *msm_dp_panel, !!(adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC); msm_dp_panel->msm_dp_mode.out_fmt_is_yuv_420 = drm_mode_is_420_only(&msm_dp_panel->connector->display_info, adjusted_mode) && - msm_dp_panel->vsc_sdp_supported; + panel->link->vsc_sdp_supported; drm_mode = &msm_dp_panel->msm_dp_mode.drm_mode; @@ -837,4 +840,3 @@ struct msm_dp_panel *msm_dp_panel_get(struct device *dev, struct drm_dp_aux *aux return msm_dp_panel; } - diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 04938b9d2091f..59136264166fa 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -41,12 +41,10 @@ struct msm_dp_panel { u8 dpcd[DP_RECEIVER_CAP_SIZE]; u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; - struct msm_dp_link_info link_info; struct drm_connector *connector; struct msm_dp_display_mode msm_dp_mode; struct msm_dp_panel_psr psr_cap; bool video_test; - bool vsc_sdp_supported; u32 hw_revision; enum msm_dp_stream_id stream_id; From 8eed4d8427914d20d8f8715c3ef6f9247210a887 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Sun, 13 Sep 2026 18:01:28 +0800 Subject: [PATCH 1039/1133] FROMLIST: drm/bridge_connector: suppress hotplug for IRQ_HPD without status changes DP IRQ_HPD does not necessarily indicate a display connection change. It can also signal link status changes or pending MST messages, which need bridge-side handling but do not necessarily require userspace to reprobe the connector. Currently, the HPD handler sends a hotplug event for every notification, without distinguishing ordinary HPD from IRQ_HPD. This causes IRQ_HPD notifications with no connection change to trigger unnecessary connector reprobes. However, filtering out all IRQ_HPD notifications would also discard hotplug events for downstream display connection changes on a DP branch, where upstream HPD can remain asserted. The decision therefore needs to use the actual connector status after handling the notification, rather than the raw HPD status reported by the event. Pass the event to the bridge chain first, then call the bridge .detect() callback to update connector->status. Fall back to the reported status when no .detect() callback is available. For IRQ_HPD, send a hotplug event only when the connector status changes, suppressing IRQ-only notifications while preserving notifications for downstream connection changes. Keep hotplug events unconditional for ordinary HPD notifications. An earlier detect may already have updated the connection status before subsequent plug handling reads the EDID, so a reprobe is still needed. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260929-msm-dp-mst-v7-25-4b81473185e7@oss.qualcomm.com/ --- drivers/gpu/drm/display/drm_bridge_connector.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 915e13e05a21e..d6931ba31c8a2 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -160,15 +160,28 @@ static void drm_bridge_connector_handle_hpd(struct drm_bridge_connector *drm_bri enum drm_connector_status_extra extra_status) { struct drm_connector *connector = &drm_bridge_connector->base; + struct drm_bridge *detect = drm_bridge_connector->bridge_detect; struct drm_device *dev = connector->dev; + enum drm_connector_status old_status, new_status; + bool level_hpd; + bool changed; + + level_hpd = extra_status == DRM_CONNECTOR_NO_EXTRA_STATUS; mutex_lock(&dev->mode_config.mutex); - connector->status = status; + old_status = connector->status; mutex_unlock(&dev->mode_config.mutex); drm_bridge_connector_hpd_notify(connector, status, extra_status); - drm_kms_helper_connector_hotplug_event(connector); + mutex_lock(&dev->mode_config.mutex); + new_status = detect ? detect->funcs->detect(detect, connector) : status; + connector->status = new_status; + changed = new_status != old_status; + mutex_unlock(&dev->mode_config.mutex); + + if (changed || level_hpd) + drm_kms_helper_connector_hotplug_event(connector); } static void drm_bridge_connector_hpd_cb(void *cb_data, From 68efaa8e2c569cc63434c2aefdc03c7e43a42056 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Sun, 13 Sep 2026 19:26:59 +0800 Subject: [PATCH 1040/1133] FROMLIST: drm/bridge_connector: avoid detect-based HPD notifications for DisplayPort When MST is active, the SST connector reports disconnected even though the physical DP link is still connected. drm_bridge_connector_detect() forwards this result to the bridge chain as an HPD notification. On MSM DP, this notification invokes unplug handling and tears down the active link and MST topology while the cable is still plugged in. For DisplayPort connectors with an HPD source, stop notifying the bridge chain from the detect path. Plug, unplug and IRQ_HPD notifications remain handled through the existing HPD event path. Preserve detect-based notifications for other connector types and for DisplayPort connectors without an HPD source. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260929-msm-dp-mst-v7-26-4b81473185e7@oss.qualcomm.com/ --- drivers/gpu/drm/display/drm_bridge_connector.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index d6931ba31c8a2..a9150b53cde4a 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -318,7 +318,16 @@ static int drm_bridge_connector_detect_ctx(struct drm_connector *connector, return ret; } - drm_bridge_connector_hpd_notify(connector, status, DRM_CONNECTOR_NO_EXTRA_STATUS); + /* + * A DP SST connector can report disconnected while MST is active. + * Use the HPD event path to notify its bridges, rather than turning + * that detect result into an unplug event. Preserve detect-based + * notifications for other connector types and DP without HPD. + */ + if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort || + !bridge_connector->bridge_hpd) + drm_bridge_connector_hpd_notify(connector, status, + DRM_CONNECTOR_NO_EXTRA_STATUS); } else { switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DPI: From 1a3894ab62e5a8f862e6a91db2df2e505c785e90 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Sun, 20 Sep 2026 22:56:52 +0800 Subject: [PATCH 1041/1133] FROMLIST: drm/msm/dp: wake threaded handler for HPD IRQs The primary IRQ handler latches HPD status for the threaded handler before servicing DP controller interrupts. When an HPD interrupt was pending, the handler set its return value to IRQ_WAKE_THREAD and then ORed it with msm_dp_ctrl_isr()'s return value. If the controller ISR returned IRQ_HANDLED, the primary handler returned IRQ_HANDLED | IRQ_WAKE_THREAD instead. The IRQ core wakes an action's thread only when its primary handler returns IRQ_WAKE_THREAD exactly. In that case, the HPD status was latched for the threaded handler, but the handler itself was not woken. Return IRQ_WAKE_THREAD directly whenever an unmasked HPD interrupt is pending, after servicing controller interrupts in hardirq context, while retaining the existing IRQ_HANDLED fallback for non-HPD interrupts. Also report STATUS2 interrupts as handled. msm_dp_ctrl_get_interrupt() acknowledges every pending STATUS2 source, including sources that need no additional action, so they must not be reported as IRQ_NONE. Fixes: 5043357e75ba ("drm/msm/dp: rework HPD handling") Cc: stable@vger.kernel.org # v7.2+ Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260929-msm-dp-mst-v7-33-4b81473185e7@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 3 +++ drivers/gpu/drm/msm/dp/dp_display.c | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index a4ff996799779..037eb1e89f012 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -3028,6 +3028,9 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl, } isr = msm_dp_ctrl_get_interrupt(ctrl); + /* All status2 sources are ACKed by msm_dp_ctrl_get_interrupt(). */ + if (isr & DP_INTERRUPT_STATUS2) + ret = IRQ_HANDLED; if (isr & DP_CTRL_INTR_READY_FOR_VIDEO) { drm_dbg_dp(ctrl->drm_dev, "dp_video_ready\n"); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 93a8ed32bcbad..b81efecc9fb20 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1097,23 +1097,24 @@ static irqreturn_t msm_dp_display_irq_handler(int irq, void *dev_id) u32 hpd_isr_status; unsigned long flags; irqreturn_t ret = IRQ_HANDLED; + bool hpd_irq_pending; hpd_isr_status = msm_dp_aux_get_hpd_intr_status(dp->aux); + hpd_irq_pending = hpd_isr_status & DP_DP_HPD_INT_MASK; - if (hpd_isr_status & 0x0F) { + if (hpd_irq_pending) { drm_dbg_dp(dp->drm_dev, "type=%d isr=0x%x\n", dp->msm_dp_display.connector_type, hpd_isr_status); spin_lock_irqsave(&dp->irq_thread_lock, flags); dp->hpd_isr_status |= hpd_isr_status; - ret = IRQ_WAKE_THREAD; spin_unlock_irqrestore(&dp->irq_thread_lock, flags); } /* DP controller isr */ ret |= msm_dp_ctrl_isr(dp->ctrl, dp->panel); - return ret; + return hpd_irq_pending ? IRQ_WAKE_THREAD : ret; } static irqreturn_t msm_dp_display_irq_thread(int irq, void *dev_id) From 399dd5baad52033466f1398848729c9278c1c82e Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Wed, 23 Sep 2026 16:42:47 +0800 Subject: [PATCH 1042/1133] FROMLIST: drm/msm/dp: order IRQ HPD handling with plug state changes IRQ HPD can be reported with a plug or unplug event. For plug + IRQ HPD, initialize the link through the plug path before handling the IRQ. This ensures that the link and MST state are ready for IRQ processing. For unplug + IRQ HPD, ignore the IRQ because the link is being torn down and the IRQ may be stale. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260929-msm-dp-mst-v7-34-4b81473185e7@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index b81efecc9fb20..8eab99005aeb2 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1140,7 +1140,10 @@ static irqreturn_t msm_dp_display_irq_thread(int irq, void *dev_id) /* Temporary until DRM IRQ support is finalized, then switch to * drm_bridge_hpd_notify(). */ - if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) { + /* Do not access a link torn down by an unplug latched after an IRQ. */ + if ((hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) && + (!(hpd_isr_status & DP_DP_HPD_UNPLUG_INT_MASK) || + (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK))) { if (dp->msm_dp_display.mst_active) msm_dp_irq_hpd_handle(dp); else @@ -1816,6 +1819,9 @@ void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge, if (status == connector_status_connected) { if (hpd_link_status == ISR_IRQ_HPD_PULSE_COUNT || extra_status == DRM_CONNECTOR_DP_IRQ_HPD) { + if (!dp->plugged) + msm_dp_hpd_plug_handle(dp); + msm_dp_irq_hpd_handle(dp); } else if (hpd_link_status == ISR_HPD_REPLUG_COUNT) { msm_dp_hpd_unplug_handle(dp); From 0c9b776876099cb257fc6c5e78327c129c888c11 Mon Sep 17 00:00:00 2001 From: Yongxing Mou Date: Thu, 24 Sep 2026 15:22:31 +0800 Subject: [PATCH 1043/1133] FROMLIST: soc: qcom: pmic-glink-altmode: skip retimer reset on DP IRQ A DP HPD IRQ reports a sink-side event and does not imply a Type-C routing change. Reprogramming the retimer for every IRQ can reset or disturb its datapath while link training or video transmission is in progress, causing intermittent DisplayPort link failures. Cache the successfully programmed DP retimer mode, HPD level, and orientation. When an IRQ arrives with the same state, leave the retimer untouched while continuing to notify DRM so MST sink IRQ handling is preserved. Invalidate the cache on non-DP modes and after a failed retimer update so later DP transitions are always configured. Signed-off-by: Yongxing Mou Link: https://lore.kernel.org/all/20260929-msm-dp-mst-v7-35-4b81473185e7@oss.qualcomm.com/ --- drivers/soc/qcom/pmic_glink_altmode.c | 38 ++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index e903d4910e9c8..5ae554dc01d9a 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -121,6 +121,12 @@ struct pmic_glink_altmode_port { u8 hpd_state; u8 hpd_irq; u8 mux_ctrl; + + /* Last DP state successfully programmed into the retimer. */ + bool retimer_dp_valid; + u8 retimer_dp_mode; + bool retimer_dp_hpd_state; + enum typec_orientation retimer_dp_orientation; }; #define work_to_altmode(w) container_of((w), struct pmic_glink_altmode, enable_work) @@ -180,6 +186,7 @@ static void pmic_glink_altmode_enable_dp(struct pmic_glink_altmode *altmode, bool hpd_irq) { struct typec_displayport_data dp_data = {}; + bool retimer_state_unchanged; int ret; dp_data.status = DP_STATUS_ENABLED; @@ -200,10 +207,31 @@ static void pmic_glink_altmode_enable_dp(struct pmic_glink_altmode *altmode, port->retimer_state.alt = &port->dp_alt; port->retimer_state.data = &dp_data; port->retimer_state.mode = TYPEC_MODAL_STATE(mode); + retimer_state_unchanged = port->retimer_dp_valid && + port->retimer_dp_mode == mode && + port->retimer_dp_hpd_state == hpd_state && + port->retimer_dp_orientation == port->orientation; + + /* + * An HPD IRQ is a sink-side DP interrupt, not a Type-C routing change. + * Avoid rewriting an already configured retimer while DP link training or + * video transmission is in progress. The DRM HPD IRQ notification below + * is deliberately still delivered. + */ + if (hpd_irq && retimer_state_unchanged) + return; ret = typec_retimer_set(port->typec_retimer, &port->retimer_state); - if (ret) + if (ret) { + /* A failed write may have left the retimer only partly configured. */ + port->retimer_dp_valid = false; dev_err(altmode->dev, "failed to setup retimer to DP: %d\n", ret); + } else { + port->retimer_dp_valid = true; + port->retimer_dp_mode = mode; + port->retimer_dp_hpd_state = hpd_state; + port->retimer_dp_orientation = port->orientation; + } } static void pmic_glink_altmode_enable_tbt(struct pmic_glink_altmode *altmode, @@ -214,6 +242,8 @@ static void pmic_glink_altmode_enable_tbt(struct pmic_glink_altmode *altmode, u32 cable_speed; int ret; + port->retimer_dp_valid = false; + /* Device Discover Mode VDO */ tbt_data.device_mode = TBT_MODE; tbt_data.device_mode |= TBT_SET_ADAPTER(TBT_ADAPTER_TBT3); @@ -271,6 +301,8 @@ static void pmic_glink_altmode_enable_usb4(struct pmic_glink_altmode *altmode, struct enter_usb_data data = {}; int ret; + port->retimer_dp_valid = false; + data.eudo = FIELD_PREP(EUDO_USB_MODE_MASK, EUDO_USB_MODE_USB4); if (tbt->usb_speed == 0) { @@ -307,6 +339,8 @@ static void pmic_glink_altmode_enable_usb(struct pmic_glink_altmode *altmode, { int ret; + port->retimer_dp_valid = false; + port->state.alt = NULL; port->state.data = NULL; port->state.mode = TYPEC_STATE_USB; @@ -329,6 +363,8 @@ static void pmic_glink_altmode_safe(struct pmic_glink_altmode *altmode, { int ret; + port->retimer_dp_valid = false; + port->state.alt = NULL; port->state.data = NULL; port->state.mode = TYPEC_STATE_SAFE; From f70afd122f59e54a80f80358951ecfe562018186 Mon Sep 17 00:00:00 2001 From: Balaji Kalkonda Date: Mon, 5 Oct 2026 12:54:26 +0530 Subject: [PATCH 1044/1133] FROMLIST: dt-bindings: display/msm: dp-controller: Add Kaanapali Add DisplayPort controller for Qualcomm Kaanapali SoC which so far looks fully compatible with earlier SM8650 variant. Signed-off-by: Balaji Kalkonda Signed-off-by: Mahadevan P Link: https://lore.kernel.org/all/20261005-kaanapali_dp-v1-1-6faeac3a6d59@oss.qualcomm.com/ --- .../devicetree/bindings/display/msm/dp-controller.yaml | 1 + .../bindings/display/msm/qcom,kaanapali-mdss.yaml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 094a6383bb779..8bb0f6e15942f 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -19,6 +19,7 @@ properties: oneOf: - enum: - qcom,glymur-dp + - qcom,kaanapali-dp - qcom,sa8775p-dp - qcom,sc7180-dp - qcom,sc7280-dp diff --git a/Documentation/devicetree/bindings/display/msm/qcom,kaanapali-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,kaanapali-mdss.yaml index 088010f464c3d..41b4e637b0960 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,kaanapali-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,kaanapali-mdss.yaml @@ -58,6 +58,12 @@ patternProperties: compatible: const: qcom,kaanapali-dpu + "^displayport-controller@[0-9a-f]+$": + type: object + properties: + compatible: + const: qcom,kaanapali-dp + "^dsi@[0-9a-f]+$": type: object additionalProperties: true From 5b77714f6caa2c3e743fa7c77b90f53cb4fb54fb Mon Sep 17 00:00:00 2001 From: Balaji Kalkonda Date: Mon, 5 Oct 2026 12:54:27 +0530 Subject: [PATCH 1045/1133] FROMLIST: drm/msm/dp: Add DisplayPort controller for Kaanapali The Qualcomm Kaanapali platform comes with a DisplayPort controller with a different base offset than the previous SM8650 SoC, add support for this in the DisplayPort driver. Signed-off-by: Balaji Kalkonda Signed-off-by: Mahadevan P Link: https://lore.kernel.org/all/20261005-kaanapali_dp-v1-2-6faeac3a6d59@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 8eab99005aeb2..95554d61ff3a3 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -160,6 +160,11 @@ static const struct msm_dp_desc msm_dp_desc_sm8650[] = { {} }; +static const struct msm_dp_desc msm_dp_desc_kaanapali[] = { + { .io_start = 0x09ad2000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, + {} +}; + static const struct msm_dp_desc msm_dp_desc_x1e80100[] = { { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, { .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true }, @@ -170,6 +175,7 @@ static const struct msm_dp_desc msm_dp_desc_x1e80100[] = { static const struct of_device_id msm_dp_dt_match[] = { { .compatible = "qcom,glymur-dp", .data = &msm_dp_desc_glymur }, + { .compatible = "qcom,kaanapali-dp", .data = &msm_dp_desc_kaanapali }, { .compatible = "qcom,sa8775p-dp", .data = &msm_dp_desc_sa8775p }, { .compatible = "qcom,sc7180-dp", .data = &msm_dp_desc_sc7180 }, { .compatible = "qcom,sc7280-dp", .data = &msm_dp_desc_sc7280 }, From ff83c5ea6a7ab036724ce749e2d211aa1e7718cf Mon Sep 17 00:00:00 2001 From: Arpit Saini Date: Tue, 6 Oct 2026 18:43:53 +0530 Subject: [PATCH 1046/1133] FROMLIST: drm/msm/dsi: fix AHB clock staying enabled across suspend pm_clk_suspend()/resume() only call clk_disable()/clk_enable() for the AHB ("iface") clock, never clk_unprepare(), so prepare_count never reaches 0. The clock (and its source) stays reported as enabled through s2idle suspend even though the display stack is fully suspended: disp_cc_mdss_ahb_clk [19200000] -> disp_cc_mdss_ahb_clk_src [19200000] -> bi_tcxo [19200000] -> xo-board [76800000] disp_cc_mdss_ahb_clk_src [19200000] -> bi_tcxo [19200000] -> xo-board [76800000] Calling clk_prepare_enable()/clk_disable_unprepare() directly from the PHY's runtime_suspend/runtime_resume is not safe either, since it can deadlock against the PHY's own PLL clocks taking the global CCF prepare_lock during clk_prepare()/clk_unprepare(). Fix this by moving clk_prepare()/clk_unprepare() out of the runtime PM path. clk_enable()/clk_disable() (spinlock only) stay in runtime_suspend/runtime_resume. clk_prepare()/clk_unprepare() move to suspend_late/resume_early, avoiding the prepare_lock collision and actually dropping prepare_count to 0. DPM_FLAG_NO_DIRECT_COMPLETE ensures these hooks always run on sleep. Fixes: 0b3ccb76b95b ("drm/msm/dsi: Fix 14nm DSI PHY PLL Lock issue") Link: https://lore.kernel.org/all/20261006-dsi-ahb-clk-suspend-fix-v1-1-67da848e1b0a@oss.qualcomm.com/ Signed-off-by: Arpit Saini --- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 132 ++++++++++++++++++++++++-- drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 4 + 2 files changed, 127 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 1fb3899b88bf2..3a8b5e23f6017 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -3,9 +3,9 @@ * Copyright (c) 2015, The Linux Foundation. All rights reserved. */ +#include #include #include -#include #include #include @@ -610,6 +610,105 @@ static int dsi_phy_get_id(struct msm_dsi_phy *phy) return -EINVAL; } +static int dsi_phy_prepare_ahb_clk(struct msm_dsi_phy *phy) +{ + int ret; + + if (clk_is_enabled_when_prepared(phy->ahb_clk) || phy->ahb_clk_prepared) + return 0; + + ret = clk_prepare(phy->ahb_clk); + if (!ret) + phy->ahb_clk_prepared = true; + + return ret; +} + +static void dsi_phy_unprepare_ahb_clk(struct msm_dsi_phy *phy) +{ + if (phy->ahb_clk_prepared) { + clk_unprepare(phy->ahb_clk); + phy->ahb_clk_prepared = false; + } +} + +static int dsi_phy_runtime_suspend(struct device *dev) +{ + struct msm_dsi_phy *phy = dev_get_drvdata(dev); + + if (phy->ahb_clk_enabled) { + clk_disable(phy->ahb_clk); + phy->ahb_clk_enabled = false; + } + + if (clk_is_enabled_when_prepared(phy->ahb_clk)) + dsi_phy_unprepare_ahb_clk(phy); + + return 0; +} + +static int dsi_phy_runtime_resume(struct device *dev) +{ + struct msm_dsi_phy *phy = dev_get_drvdata(dev); + int ret; + + if (clk_is_enabled_when_prepared(phy->ahb_clk)) { + ret = clk_prepare_enable(phy->ahb_clk); + if (ret) + return ret; + + phy->ahb_clk_prepared = true; + } else { + /* Do not enable an unprepared clock after a failed system resume. */ + if (!phy->ahb_clk_prepared) + return -EIO; + + ret = clk_enable(phy->ahb_clk); + if (ret) + return ret; + } + + phy->ahb_clk_enabled = true; + + return 0; +} + +static int dsi_phy_suspend_late(struct device *dev) +{ + struct msm_dsi_phy *phy = dev_get_drvdata(dev); + int ret; + + ret = pm_runtime_force_suspend(dev); + if (ret) + return ret; + + /* Runtime PM is quiesced, so it is safe to release preparation now. */ + dsi_phy_unprepare_ahb_clk(phy); + + return 0; +} + +static int dsi_phy_resume_early(struct device *dev) +{ + struct msm_dsi_phy *phy = dev_get_drvdata(dev); + int ret, resume_ret; + + ret = dsi_phy_prepare_ahb_clk(phy); + /* Balance force_suspend even if restoring preparation failed. */ + resume_ret = pm_runtime_force_resume(dev); + + return ret ?: resume_ret; +} + +static void dsi_phy_release_ahb_clk(void *data) +{ + struct msm_dsi_phy *phy = data; + + /* Runtime PM is either not enabled yet or has already been quiesced. */ + dsi_phy_runtime_suspend(&phy->pdev->dev); + dsi_phy_unprepare_ahb_clk(phy); +} + static int dsi_phy_driver_probe(struct platform_device *pdev) { struct msm_dsi_phy *phy; @@ -683,17 +782,31 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) platform_set_drvdata(pdev, phy); - ret = devm_pm_runtime_enable(dev); + phy->ahb_clk = msm_clk_get(pdev, "iface"); + if (IS_ERR(phy->ahb_clk)) + return dev_err_probe(dev, PTR_ERR(phy->ahb_clk), + "Unable to get iface clk\n"); + + /* + * As a clock provider, the PHY can be runtime-resumed with the CCF + * prepare_lock held. Keep clocks with separate enable operations + * prepared across runtime PM, and only unprepare them during system + * sleep (dsi_phy_suspend_late()/dsi_phy_resume_early()). + */ + ret = dsi_phy_prepare_ahb_clk(phy); if (ret) - return ret; + return dev_err_probe(dev, ret, "Unable to prepare iface clk\n"); - ret = devm_pm_clk_create(dev); + ret = devm_add_action_or_reset(dev, dsi_phy_release_ahb_clk, phy); if (ret) return ret; - ret = pm_clk_add(dev, "iface"); - if (ret < 0) - return dev_err_probe(dev, ret, "Unable to get iface clk\n"); + /* Even a runtime-suspended PHY must release preparation for sleep. */ + dev_pm_set_driver_flags(dev, DPM_FLAG_NO_DIRECT_COMPLETE); + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; if (phy->cfg->ops.pll_init) { ret = phy->cfg->ops.pll_init(phy); @@ -712,7 +825,8 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) } static const struct dev_pm_ops dsi_phy_pm_ops = { - SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) + RUNTIME_PM_OPS(dsi_phy_runtime_suspend, dsi_phy_runtime_resume, NULL) + LATE_SYSTEM_SLEEP_PM_OPS(dsi_phy_suspend_late, dsi_phy_resume_early) }; static struct platform_driver dsi_phy_platform_driver = { @@ -720,7 +834,7 @@ static struct platform_driver dsi_phy_platform_driver = { .driver = { .name = "msm_dsi_phy", .of_match_table = dsi_phy_dt_match, - .pm = &dsi_phy_pm_ops, + .pm = pm_ptr(&dsi_phy_pm_ops), }, }; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h index f5d3e806f8fd5..77ae08dcff4b4 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h @@ -106,6 +106,10 @@ struct msm_dsi_phy { phys_addr_t lane_size; int id; + struct clk *ahb_clk; + bool ahb_clk_prepared; + bool ahb_clk_enabled; + struct regulator_bulk_data *supplies; struct msm_dsi_dphy_timing timing; From 1ef6b3a4ae5395914f6eb79c501121da04cd7723 Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Thu, 8 Oct 2026 22:53:47 +0530 Subject: [PATCH 1047/1133] FROMLIST: drm/msm/dpu: split modes a single layer mixer cannot clock The layer mixer count is picked purely from the mode width, via the MAX_HDISPLAY_SPLIT threshold. Width is only half of what constrains a mixer: it also processes one pixel per core clock cycle, so a mode narrow enough to stay under the width threshold can still demand a higher pixel rate than one mixer sustains. A 1080 wide panel at a few hundred Hz is enough to get there. Such a mode is currently given a single mixer and then has to be clocked past the maximum core clock rate, which that mixer cannot do. Factor the decision out into dpu_crtc_num_lm_for_mode() and have it ask for a second mixer when the adjusted mode clock does not fit the maximum core clock rate, in addition to the existing width test. Modes that already fit within one mixer are unaffected, so the only decisions that change are the ones that could not be driven as they were. Assisted-by: LLM Link: https://lore.kernel.org/all/20261008-lm_fixes_final-v4-1-fa986071c3c1@oss.qualcomm.com/ Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 25 +++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 77a2d1f6700d0..0b51a4c5db577 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1376,6 +1376,25 @@ static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct drm_crtc_state #define MAX_CHANNELS_PER_CRTC PIPES_PER_PLANE #define MAX_HDISPLAY_SPLIT 1080 +static u32 dpu_crtc_num_lm_for_mode(struct dpu_kms *dpu_kms, + const struct drm_display_mode *mode) +{ + u64 mode_clk; + + if (!dpu_kms->catalog->caps->has_3d_merge) + return 1; + + if (mode->hdisplay > MAX_HDISPLAY_SPLIT) + return 2; + + mode_clk = dpu_core_perf_adjusted_mode_clk(mode->clock, + dpu_kms->perf.perf_cfg); + if (mode_clk * 1000 > dpu_kms->perf.max_core_clk_rate) + return 2; + + return 1; +} + static struct msm_display_topology dpu_crtc_get_topology( struct drm_crtc *crtc, struct dpu_kms *dpu_kms, @@ -1409,8 +1428,8 @@ static struct msm_display_topology dpu_crtc_get_topology( * enabled. This is because in cases where CWB is enabled, num_intf will * count both the WB and real-time phys encoders. * - * For non-DSC CWB usecases, have the num_lm be decided by the - * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check. + * For non-DSC CWB usecases, have the num_lm be decided by + * dpu_crtc_num_lm_for_mode(). */ if (topology.num_intf == 2 && !topology.cwb_enabled) @@ -1419,7 +1438,7 @@ static struct msm_display_topology dpu_crtc_get_topology( topology.num_lm = 2; else if (dpu_kms->catalog->caps->has_3d_merge && topology.num_dsc == 0) - topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; + topology.num_lm = dpu_crtc_num_lm_for_mode(dpu_kms, mode); else topology.num_lm = 1; From e5746062b3ea814b4a0f0e52a5a2643ea98ae5d3 Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Thu, 8 Oct 2026 22:53:48 +0530 Subject: [PATCH 1048/1133] FROMLIST: drm/msm/dpu: do not assume a merged datapath when validating mode clock dpu_crtc_mode_valid() halves the adjusted mode clock whenever the hardware has a 3d_mux block, assuming the mode will be driven by two layer mixers. Modes no wider than MAX_HDISPLAY_SPLIT are driven by a single mixer, so for those the check permits twice the pixel rate the datapath can sustain. Divide by the mixer count the mode will really be driven by, as reported by dpu_crtc_num_lm_for_mode(). Split modes still get the halved rate, single mixer modes are held to what one mixer sustains, and parts without a 3d_mux divide by one. Assisted-by: LLM Link: https://lore.kernel.org/all/20261008-lm_fixes_final-v4-2-fa986071c3c1@oss.qualcomm.com/ Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 0b51a4c5db577..209b25dbeb6c8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1631,8 +1631,7 @@ static enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc, adjusted_mode_clk = dpu_core_perf_adjusted_mode_clk(mode->clock, dpu_kms->perf.perf_cfg); - if (dpu_kms->catalog->caps->has_3d_merge) - adjusted_mode_clk /= 2; + adjusted_mode_clk /= dpu_crtc_num_lm_for_mode(dpu_kms, mode); /* * The given mode, adjusted for the perf clock factor, should not exceed From 062db35048b9a05358d14e4ed53071789766178c Mon Sep 17 00:00:00 2001 From: Jessica Zhang Date: Thu, 8 Oct 2026 22:53:49 +0530 Subject: [PATCH 1049/1133] FROMLIST: drm/msm/dpu: check mode against PINGPONG or DSC max width LM block doesn't have a hardware buffer (unlike PINGPONG and DSC encoders). As such, don't use ephemeral max_mixer_width and MAX_HDISPLAY_SPLIT to validate requested modes. Instead use PP and DSC buffer widths. While on the DPU 8.x+ supports a max linewidth of 8960 for PINGPONG_0, there is some additional logic that needs to be added to the resource manager to specifically try and reserve PINGPONG_0 for modes that are greater than 5k. The layer-mixer count for a merge-capable, non-DSC mode is chosen by dpu_crtc_num_lm_for_mode(); feed the PINGPONG/DSC derived width to it as the split threshold in place of the removed MAX_HDISPLAY_SPLIT, so the pixel-rate floor added earlier keeps high-refresh modes that now fit within a single PINGPONG buffer split across two mixers. [MP: rebased on msm-next; fed PINGPONG/DSC width into dpu_crtc_num_lm_for_mode() instead of open-coding the width test] Link: https://lore.kernel.org/all/20261008-lm_fixes_final-v4-3-fa986071c3c1@oss.qualcomm.com/ Signed-off-by: Jessica Zhang Tested-by: Xilin Wu [DB: reworked to drop catalog changes, updated commit message] Signed-off-by: Dmitry Baryshkov Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 54 +++++++++++++++---- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 7 +++ 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 209b25dbeb6c8..41f986ca2a683 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -758,6 +758,22 @@ void dpu_crtc_complete_commit(struct drm_crtc *crtc) _dpu_crtc_complete_flip(crtc); } +static int msm_display_get_max_pingpong_width(struct dpu_kms *dpu_kms) +{ + /* + * Note: While, for DPU 8.x+, PINGPONG_0 can technically support up to + * 8k resolutions, this requires reworking the RM to try to reserve + * PINGPONG_0 for modes greater than 5k. + * + * Once this additional logic is implemented, we can probably drop this + * helper and use the reserved PINGPONG's max_linewidth + */ + if (dpu_kms->catalog->mdss_ver->core_major_ver < 6) + return DPU_1_x_MAX_PINGPONG_WIDTH; + else + return DPU_6_x_MAX_PINGPONG_WIDTH; +} + static int _dpu_crtc_check_and_setup_lm_bounds(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -765,13 +781,14 @@ static int _dpu_crtc_check_and_setup_lm_bounds(struct drm_crtc *crtc, struct drm_display_mode *adj_mode = &state->adjusted_mode; u32 crtc_split_width = adj_mode->hdisplay / cstate->num_mixers; struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); + int max_pingpong_width = msm_display_get_max_pingpong_width(dpu_kms); int i; /* if we cannot merge 2 LMs (no 3d mux) better to fail earlier * before even checking the width after the split */ if (!dpu_kms->catalog->caps->has_3d_merge && - adj_mode->hdisplay > dpu_kms->catalog->caps->max_mixer_width) + adj_mode->hdisplay > max_pingpong_width) return -E2BIG; for (i = 0; i < cstate->num_mixers; i++) { @@ -783,7 +800,7 @@ static int _dpu_crtc_check_and_setup_lm_bounds(struct drm_crtc *crtc, trace_dpu_crtc_setup_lm_bounds(DRMID(crtc), i, r); - if (drm_rect_width(r) > dpu_kms->catalog->caps->max_mixer_width) + if (drm_rect_width(r) > max_pingpong_width) return -E2BIG; } @@ -1374,17 +1391,17 @@ static int dpu_crtc_reassign_planes(struct drm_crtc *crtc, struct drm_crtc_state } #define MAX_CHANNELS_PER_CRTC PIPES_PER_PLANE -#define MAX_HDISPLAY_SPLIT 1080 static u32 dpu_crtc_num_lm_for_mode(struct dpu_kms *dpu_kms, - const struct drm_display_mode *mode) + const struct drm_display_mode *mode, + u32 max_hdisplay_split) { u64 mode_clk; if (!dpu_kms->catalog->caps->has_3d_merge) return 1; - if (mode->hdisplay > MAX_HDISPLAY_SPLIT) + if (mode->hdisplay > max_hdisplay_split) return 2; mode_clk = dpu_core_perf_adjusted_mode_clk(mode->clock, @@ -1403,6 +1420,7 @@ static struct msm_display_topology dpu_crtc_get_topology( struct drm_display_mode *mode = &crtc_state->adjusted_mode; struct msm_display_topology topology = {0}; struct drm_encoder *drm_enc; + u32 max_hdisplay_split; drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state, @@ -1410,6 +1428,19 @@ static struct msm_display_topology dpu_crtc_get_topology( topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state); + max_hdisplay_split = msm_display_get_max_pingpong_width(dpu_kms); + + if (topology.num_dsc > 0) { + u32 max_dsc_encoder_width; + + if (dpu_kms->catalog->mdss_ver->core_major_ver < 6) + max_dsc_encoder_width = DPU_1_x_MAX_DSC_ENCODER_WIDTH; + else + max_dsc_encoder_width = DPU_8_x_MAX_DSC_ENCODER_WIDTH; + + max_hdisplay_split = min(max_hdisplay_split, max_dsc_encoder_width); + } + /* * Datapath topology selection * @@ -1438,7 +1469,8 @@ static struct msm_display_topology dpu_crtc_get_topology( topology.num_lm = 2; else if (dpu_kms->catalog->caps->has_3d_merge && topology.num_dsc == 0) - topology.num_lm = dpu_crtc_num_lm_for_mode(dpu_kms, mode); + topology.num_lm = dpu_crtc_num_lm_for_mode(dpu_kms, mode, + max_hdisplay_split); else topology.num_lm = 1; @@ -1619,19 +1651,21 @@ static enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) { struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc); + int max_pingpong_width = msm_display_get_max_pingpong_width(dpu_kms); u64 adjusted_mode_clk; /* if there is no 3d_mux block we cannot merge LMs so we cannot * split the large layer into 2 LMs, filter out such modes */ if (!dpu_kms->catalog->caps->has_3d_merge && - mode->hdisplay > dpu_kms->catalog->caps->max_mixer_width) + mode->hdisplay > max_pingpong_width) return MODE_BAD_HVALUE; adjusted_mode_clk = dpu_core_perf_adjusted_mode_clk(mode->clock, dpu_kms->perf.perf_cfg); - adjusted_mode_clk /= dpu_crtc_num_lm_for_mode(dpu_kms, mode); + adjusted_mode_clk /= dpu_crtc_num_lm_for_mode(dpu_kms, mode, + max_pingpong_width); /* * The given mode, adjusted for the perf clock factor, should not exceed @@ -1641,10 +1675,10 @@ static enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc, return MODE_CLOCK_HIGH; /* - * max crtc width is equal to the max mixer width * 2 and max height is 4K + * max crtc width is equal to the max pingpong width * 2 and max height is 4K */ return drm_mode_validate_size(mode, - 2 * dpu_kms->catalog->caps->max_mixer_width, + 2 * max_pingpong_width, 4096); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index f45faf87333e8..71e1a404e25f9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -24,6 +24,13 @@ #define DPU_MAX_IMG_WIDTH 0x3fff #define DPU_MAX_IMG_HEIGHT 0x3fff +#define DPU_1_x_MAX_PINGPONG_WIDTH 4096 +#define DPU_6_x_MAX_PINGPONG_WIDTH 5120 +#define DPU_8_x_MAX_PINGPONG_0_WIDTH 8960 + +#define DPU_1_x_MAX_DSC_ENCODER_WIDTH 2048 +#define DPU_8_x_MAX_DSC_ENCODER_WIDTH 2560 + #define CRTC_DUAL_MIXERS 2 #define MAX_XIN_COUNT 16 From 823f675cee881fd758850a960c6c843d95af626c Mon Sep 17 00:00:00 2001 From: Jessica Zhang Date: Thu, 8 Oct 2026 22:53:50 +0530 Subject: [PATCH 1050/1133] FROMLIST: drm/msm/dpu: filter writeback modes using writeback maxlinewidth Maximum width of the writeback mode is limited by the hardware buffer in the WB block rather than by the LM properties (LM doesn't have an actual buffer). Use the actual hardware limit (the writeback maxlinewidth) to filter modes. Link: https://lore.kernel.org/all/20261008-lm_fixes_final-v4-4-fa986071c3c1@oss.qualcomm.com/ Signed-off-by: Jessica Zhang [DB: fixed commit message] Signed-off-by: Dmitry Baryshkov Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c index e7b09013ae4c8..a31b6e2f5cf7c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c @@ -15,14 +15,7 @@ static int dpu_wb_conn_get_modes(struct drm_connector *connector) struct msm_drm_private *priv = dev->dev_private; struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); - /* - * We should ideally be limiting the modes only to the maxlinewidth but - * on some chipsets this will allow even 4k modes to be added which will - * fail the per SSPP bandwidth checks. So, till we have dual-SSPP support - * and source split support added lets limit the modes based on max_mixer_width - * as 4K modes can then be supported. - */ - return drm_add_modes_noedid(connector, dpu_kms->catalog->caps->max_mixer_width, + return drm_add_modes_noedid(connector, dpu_kms->catalog->wb->maxlinewidth, dev->mode_config.max_height); } From 7a4f94ca071ef46432a75c5c13bdf5b5a00f284b Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Thu, 8 Oct 2026 22:53:52 +0530 Subject: [PATCH 1051/1133] FROMLIST: drm/msm/dpu: limit the mode width to a pipe if the LM has no source split Layer mixers without DPU_MIXER_SOURCESPLIT stage one pipe per blend level, so a plane is fetched by a single pipe of at most max_linewidth pixels. max_mixer_width used to reject wider modes. Now that the mode is checked against the PINGPONG width (4096/5120), keep max_linewidth as an extra bound when source split isn't available. Assisted-by: LLM Link: https://lore.kernel.org/all/20261008-lm_fixes_final-v4-6-fa986071c3c1@oss.qualcomm.com/ Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 41f986ca2a683..c2ebeef0b01f0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -791,6 +791,10 @@ static int _dpu_crtc_check_and_setup_lm_bounds(struct drm_crtc *crtc, adj_mode->hdisplay > max_pingpong_width) return -E2BIG; + if (!test_bit(DPU_MIXER_SOURCESPLIT, &dpu_kms->catalog->mixer[0].features) && + adj_mode->hdisplay > dpu_kms->catalog->caps->max_linewidth) + return -E2BIG; + for (i = 0; i < cstate->num_mixers; i++) { struct drm_rect *r = &cstate->lm_bounds[i]; r->x1 = crtc_split_width * i; @@ -1661,6 +1665,10 @@ static enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc, mode->hdisplay > max_pingpong_width) return MODE_BAD_HVALUE; + if (!test_bit(DPU_MIXER_SOURCESPLIT, &dpu_kms->catalog->mixer[0].features) && + mode->hdisplay > dpu_kms->catalog->caps->max_linewidth) + return MODE_BAD_HVALUE; + adjusted_mode_clk = dpu_core_perf_adjusted_mode_clk(mode->clock, dpu_kms->perf.perf_cfg); From c0d35ef92145f16858855a2d6e74da42d4ffe50e Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Sat, 10 Oct 2026 19:08:21 +0530 Subject: [PATCH 1052/1133] FROMLIST: drm/msm/dpu: keep SSPP priority order for split planes on DPU < 5.0 Before DPU 5.0, the layer mixer places the higher priority SSPP on the left of a source-split pair. Priority follows the SSPP index (VIG, RGB, DMA), while allocation prefers DMA, RGB, then VIG. Swap the two SSPPs when the right one has the lower index. Both are reserved with the same requirements. Same-SSPP parallel multirect already puts RECT_0, the higher priority rectangle, on the left. Fixes: 8c62a31607f6 ("drm/msm/dpu: allow using two SSPP blocks for a single plane") Assisted-by: LLM Link: https://lore.kernel.org/all/20261010-pipe_order-v1-1-9d8bd29fd78a@oss.qualcomm.com/ Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 1a471cdf767b1..fe43ea9ae8647 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1245,6 +1245,10 @@ static int dpu_plane_assign_resource_in_stage(struct dpu_sw_pipe *pipe, r_pipe->multirect_index = DPU_SSPP_RECT_SOLO; r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE; + if (dpu_kms->catalog->mdss_ver->core_major_ver < 5 && + r_pipe->sspp->idx < pipe->sspp->idx) + swap(pipe->sspp, r_pipe->sspp); + return 0; } From 58dad91224bb989593a054fbe95660c7e40ba85a Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Sat, 10 Oct 2026 19:08:22 +0530 Subject: [PATCH 1053/1133] FROMLIST: drm/msm/dpu: add SSPP op to program the source split order DPU 5.0 introduced SRC_SPLIT_ORDER in bit 4 of SSPP_SRC_OP_MODE and SSPP_SRC_OP_MODE_REC1. For source-split pairs using legacy CTL routing, this field identifies the left source with 0 and the right source with 1. Add a setup_src_split_order() operation for the SSPP register layout used on DPU 5.0 through 12.x. Select SSPP_SRC_OP_MODE for SOLO or RECT0 and SSPP_SRC_OP_MODE_REC1 for RECT1, and update only the ordering bit. Assisted-by: LLM Link: https://lore.kernel.org/all/20261010-pipe_order-v1-2-9d8bd29fd78a@oss.qualcomm.com/ Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 35 +++++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 11 +++++++ 2 files changed, 46 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index b5e50fc1916f6..f6ec883f90664 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -84,6 +84,7 @@ #define MDSS_MDP_OP_IGC_EN BIT(16) #define MDSS_MDP_OP_FLIP_UD BIT(14) #define MDSS_MDP_OP_FLIP_LR BIT(13) +#define MDSS_MDP_OP_SRC_SPLIT_ORDER BIT(4) #define MDSS_MDP_OP_BWC_EN BIT(0) #define MDSS_MDP_OP_PE_OVERRIDE BIT(31) #define MDSS_MDP_OP_BWC_LOSSLESS (0 << 1) @@ -260,6 +261,38 @@ static void dpu_hw_sspp_setup_format(struct dpu_sw_pipe *pipe, ubwc_ctrl_off, ubwc_error_off); } +void dpu_hw_setup_src_split_order_impl(struct dpu_hw_sspp *ctx, + u32 op_mode_off, bool right) +{ + u32 opmode; + + opmode = DPU_REG_READ(&ctx->hw, op_mode_off); + if (right) + opmode |= MDSS_MDP_OP_SRC_SPLIT_ORDER; + else + opmode &= ~MDSS_MDP_OP_SRC_SPLIT_ORDER; + + DPU_REG_WRITE(&ctx->hw, op_mode_off, opmode); +} + +static void dpu_hw_sspp_setup_src_split_order(struct dpu_sw_pipe *pipe, + bool right) +{ + struct dpu_hw_sspp *ctx = pipe->sspp; + u32 op_mode_off; + + if (!ctx) + return; + + if (pipe->multirect_index == DPU_SSPP_RECT_SOLO || + pipe->multirect_index == DPU_SSPP_RECT_0) + op_mode_off = SSPP_SRC_OP_MODE; + else + op_mode_off = SSPP_SRC_OP_MODE_REC1; + + dpu_hw_setup_src_split_order_impl(ctx, op_mode_off, right); +} + void dpu_hw_setup_format_impl(struct dpu_sw_pipe *pipe, const struct msm_format *fmt, u32 flags, struct dpu_hw_sspp *ctx, u32 op_mode_off, u32 unpack_pat_off, u32 format_off, u32 ubwc_ctrl_off, @@ -636,6 +669,8 @@ static void _setup_layer_ops(struct dpu_hw_sspp *c, c->ops.setup_sourceaddress = dpu_hw_sspp_setup_sourceaddress; c->ops.setup_solidfill = dpu_hw_sspp_setup_solidfill; c->ops.setup_pe = dpu_hw_sspp_setup_pe_config; + if (mdss_rev->core_major_ver >= 5) + c->ops.setup_src_split_order = dpu_hw_sspp_setup_src_split_order; if (test_bit(DPU_SSPP_QOS, &features)) { c->ops.setup_qos_lut = dpu_hw_sspp_setup_qos_lut; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h index 69d68cc916b2e..9b9ea2e00a00d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h @@ -236,6 +236,14 @@ struct dpu_hw_sspp_ops { void (*setup_multirect)(struct dpu_sw_pipe *pipe); + /** + * @setup_src_split_order: program the position of the pipe within + * a source split pair + * @pipe: Pointer to pipe context + * @right: true if the pipe fetches the right half of the pair + */ + void (*setup_src_split_order)(struct dpu_sw_pipe *pipe, bool right); + /** * @setup_sharpening: setup sharpening * @ctx: Pointer to pipe context @@ -349,6 +357,9 @@ void dpu_hw_setup_multirect_impl(struct dpu_sw_pipe *pipe, struct dpu_hw_sspp *ctx, u32 op_mode_off); +void dpu_hw_setup_src_split_order_impl(struct dpu_hw_sspp *ctx, + u32 op_mode_off, bool right); + void dpu_hw_setup_format_impl(struct dpu_sw_pipe *pipe, const struct msm_format *fmt, u32 flags, struct dpu_hw_sspp *ctx, u32 op_mode_off, u32 unpack_pat_off, u32 format_off, From 37340b8345d718f124e72edd908d2a2e06565a3d Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Sat, 10 Oct 2026 19:08:23 +0530 Subject: [PATCH 1054/1133] FROMLIST: drm/msm/dpu: program the source split order for split planes Virtual planes can use two SSPPs when a plane exceeds the single-pipe width or clock limit and parallel multirect cannot be used. Program SRC_SPLIT_ORDER during mixer setup from the pipes' destination X positions. Set the bit for the right source and clear it for the left source or a source without a sibling. Fixes: 8c62a31607f6 ("drm/msm/dpu: allow using two SSPP blocks for a single plane") Assisted-by: LLM Link: https://lore.kernel.org/all/20261010-pipe_order-v1-3-9d8bd29fd78a@oss.qualcomm.com/ Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index c2ebeef0b01f0..11f403d3577b0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -434,6 +434,18 @@ static void _dpu_crtc_blend_setup_pipe(struct drm_crtc *crtc, mixer[lm_idx].lm_ctl->ops.update_pending_flush_sspp(mixer[lm_idx].lm_ctl, sspp_idx); } +static bool _dpu_crtc_pipe_is_right(const struct dpu_plane_state *pstate, + unsigned int pipe_idx) +{ + unsigned int other_idx = pipe_idx ^ 1; + + if (!pstate->pipe[other_idx].sspp) + return false; + + return pstate->pipe_cfg[pipe_idx].dst_rect.x1 > + pstate->pipe_cfg[other_idx].dst_rect.x1; +} + static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct dpu_crtc *dpu_crtc, struct dpu_crtc_mixer *mixer, struct dpu_hw_stage_cfg *stage_cfg) @@ -443,10 +455,13 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct drm_plane_state *state; struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state); struct dpu_plane_state *pstate = NULL; + struct dpu_sw_pipe *pipe; const struct msm_format *format; struct dpu_hw_ctl *ctl = mixer->lm_ctl; u32 lm_idx, stage, i, pipe_idx, head_pipe_in_stage, lms_in_pair; bool bg_alpha_enable = false; + bool src_split = test_bit(DPU_MIXER_SOURCESPLIT, + &mixer->hw_lm->cap->features); DECLARE_BITMAP(active_fetch, SSPP_MAX); DECLARE_BITMAP(active_pipes, SSPP_MAX); @@ -475,6 +490,10 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, pipe_idx = i + head_pipe_in_stage; if (!pstate->pipe[pipe_idx].sspp) continue; + pipe = &pstate->pipe[pipe_idx]; + if (src_split && pipe->sspp->ops.setup_src_split_order) + pipe->sspp->ops.setup_src_split_order(pipe, + _dpu_crtc_pipe_is_right(pstate, pipe_idx)); lms_in_pair = min(cstate->num_mixers - (stage * PIPES_PER_STAGE), PIPES_PER_STAGE); set_bit(pstate->pipe[pipe_idx].sspp->idx, active_fetch); From fb7ef3c7f8b738d13c553a156f20af2af64297ad Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Sat, 10 Oct 2026 19:08:24 +0530 Subject: [PATCH 1055/1133] FROMLIST: drm/msm/dpu: add source split order op for DPU 13.x DPU 13.x places the SSPP op-mode register in separate REC0 and REC1 banks. Add the source split order operation for this layout, using the shared helper to update SRC_SPLIT_ORDER in the selected bank. Assisted-by: LLM Link: https://lore.kernel.org/all/20261010-pipe_order-v1-4-9d8bd29fd78a@oss.qualcomm.com/ Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp_v13.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp_v13.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp_v13.c index f8f96ad971d78..bdf1201d81344 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp_v13.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp_v13.c @@ -149,6 +149,19 @@ static void dpu_hw_sspp_setup_format_v13(struct dpu_sw_pipe *pipe, unpack_pat_off, format_off, ubwc_ctrl_off, ubwc_err_off); } +static void dpu_hw_sspp_setup_src_split_order_v13(struct dpu_sw_pipe *pipe, + bool right) +{ + struct dpu_hw_sspp *ctx = pipe->sspp; + u32 offset; + + if (!ctx) + return; + + offset = dpu_hw_sspp_calculate_rect_off(pipe->multirect_index, ctx); + dpu_hw_setup_src_split_order_impl(ctx, offset + SSPP_REC_SRC_OP_MODE, right); +} + static void dpu_hw_sspp_setup_pe_config_v13(struct dpu_hw_sspp *ctx, struct dpu_hw_pixel_ext *pe_ext) { @@ -299,6 +312,7 @@ void dpu_hw_sspp_init_v13(struct dpu_hw_sspp *c, c->ops.setup_sourceaddress = dpu_hw_sspp_setup_sourceaddress_v13; c->ops.setup_solidfill = dpu_hw_sspp_setup_solidfill_v13; c->ops.setup_pe = dpu_hw_sspp_setup_pe_config_v13; + c->ops.setup_src_split_order = dpu_hw_sspp_setup_src_split_order_v13; if (test_bit(DPU_SSPP_QOS, &features)) { c->ops.setup_qos_lut = dpu_hw_sspp_setup_qos_lut_v13; From 13cd1ce1298a628fda47c7ae7898db85b3c3e31e Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Fri, 11 Sep 2026 21:06:35 +0530 Subject: [PATCH 1056/1133] FROMLIST: drm/msm/dpu: Add support for DPU 12.1 on Nord Add the DPU catalog entry for the Qualcomm Nord SoC (MDSS 12.1, DPU 1499A). Nord is DP-only with no DSI, and provides 8 DSPP blocks, 2 writeback blocks, 8 interfaces and 2 DP controllers. Extend enum dpu_intf with INTF_9 and INTF_10, which Nord is the first platform to use. Note: register addresses and xin_id values in the catalog are borrowed from sm8750 and precedent platforms and are marked with FIXME(REG_ADDR) and FIXME(XIU_MAP); they need verification against a real Nord register map before production use. Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20260911-nord-drv-dt-v1-4-e25c073cf1b6@oss.qualcomm.com (cherry picked from commit f8942157ebc982616939bf4d62b0389b01318503) Signed-off-by: Mahadevan P --- .../drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h | 588 ++++++++++++++++++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 + .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 + 5 files changed, 593 insertions(+) create mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h new file mode 100644 index 0000000000000..8eb18752f3c4b --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h @@ -0,0 +1,588 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. + */ + +#ifndef _DPU_12_1_NORD_H +#define _DPU_12_1_NORD_H + +/* + * NORD DPU 12.1 catalog header. Generated from hardware summary YAML for + * MDSS 12.1 - DPU 1499A (Nordschleife). This is a DP-only chip with no DSI. + * + * All register addresses and xin_id values below are borrowed from the + * reference chip (sm8750, MDSS 12.0) and precedent chips (Lemans, Glymur). + * Nord's YAML provides only block counts and feature statements, not addresses. + * See FIXME(REG_ADDR) markers throughout for borrowed values requiring + * verification against a real Nord register map before production use. + * + * Key differences vs sm8750: + * - 8 DSPP blocks (4 full + 4 lite) vs sm8750's 4 + * - 2 writeback blocks (WB1, WB2) vs sm8750's 1 (WB2) + * - 8 interfaces (INTF_0,3,4,6,7,8,9,10) vs sm8750's 4 (INTF_0,1,2,3) + * - 2 DP controllers (DP0, DP1) vs sm8750's 1 (DP0 only) + * - No DSI (removed entirely) + */ + +static const struct dpu_caps nord_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0xb, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 8192, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, +}; + +static const struct dpu_mdp_cfg nord_mdp = { + .name = "top_0", + .base = 0, .len = 0x494, + .clk_ctrls = { + [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, + }, +}; + +static const struct dpu_ctl_cfg nord_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x15000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, { + .name = "ctl_1", .id = CTL_1, + .base = 0x16000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, { + .name = "ctl_2", .id = CTL_2, + .base = 0x17000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, { + .name = "ctl_3", .id = CTL_3, + .base = 0x18000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, { + .name = "ctl_4", .id = CTL_4, + .base = 0x19000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, { + .name = "ctl_5", .id = CTL_5, + .base = 0x1a000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), + }, +}; + +static const struct dpu_sspp_cfg nord_sspp[] = { + { + .name = "sspp_0", .id = SSPP_VIG0, + .base = 0x4000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 0, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_1", .id = SSPP_VIG1, + .base = 0x6000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 4, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_2", .id = SSPP_VIG2, + .base = 0x8000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 8, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_3", .id = SSPP_VIG3, + .base = 0xa000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 12, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_8", .id = SSPP_DMA0, + .base = 0x24000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 1, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_9", .id = SSPP_DMA1, + .base = 0x26000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 5, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_10", .id = SSPP_DMA2, + .base = 0x28000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 9, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_11", .id = SSPP_DMA3, + .base = 0x2a000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 13, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_12", .id = SSPP_DMA4, + .base = 0x2c000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 14, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_13", .id = SSPP_DMA5, + .base = 0x2e000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 15, + .type = SSPP_TYPE_DMA, + }, +}; + +static const struct dpu_lm_cfg nord_lm[] = { + { + .name = "lm_0", .id = LM_0, + .base = 0x44000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_1, + .pingpong = PINGPONG_0, + .dspp = DSPP_0, + }, { + .name = "lm_1", .id = LM_1, + .base = 0x45000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_0, + .pingpong = PINGPONG_1, + .dspp = DSPP_1, + }, { + .name = "lm_2", .id = LM_2, + .base = 0x46000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_3, + .pingpong = PINGPONG_2, + .dspp = DSPP_2, + }, { + .name = "lm_3", .id = LM_3, + .base = 0x47000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_2, + .pingpong = PINGPONG_3, + .dspp = DSPP_3, + }, { + .name = "lm_4", .id = LM_4, + .base = 0x48000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_5, + .pingpong = PINGPONG_4, + }, { + .name = "lm_5", .id = LM_5, + .base = 0x49000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_4, + .pingpong = PINGPONG_5, + }, { + .name = "lm_6", .id = LM_6, + .base = 0x4a000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_7, + .pingpong = PINGPONG_6, + }, { + .name = "lm_7", .id = LM_7, + .base = 0x4b000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_6, + .pingpong = PINGPONG_7, + }, +}; + +/* + * Nord has 8 DSPP blocks: 4 full-featured (DSPP0-3) and 4 lite variants + * (DSPP4-7). The driver has no separate lite-DSPP struct, so all 8 are + * modeled with the same dpu_dspp_cfg/dpu_dspp_sblk structure. Lite variants + * have reduced features, but this is handled at runtime via feature flags, + * not via separate catalog entries. + * FIXME(REG_ADDR): DSPP4-7 base addresses extended via 0x2000 stride from + * sm8750's DSPP3 base (0x5a000). Verify against real Nord register map. + */ +static const struct dpu_dspp_cfg nord_dspp[] = { + { + .name = "dspp_0", .id = DSPP_0, + .base = 0x54000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_1", .id = DSPP_1, + .base = 0x56000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_2", .id = DSPP_2, + .base = 0x58000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_3", .id = DSPP_3, + .base = 0x5a000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_4", .id = DSPP_4, + .base = 0x5c000, .len = 0x1800, /* FIXME(REG_ADDR): lite variant */ + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_5", .id = DSPP_5, + .base = 0x5e000, .len = 0x1800, /* FIXME(REG_ADDR): lite variant */ + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_6", .id = DSPP_6, + .base = 0x60000, .len = 0x1800, /* FIXME(REG_ADDR): lite variant */ + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_7", .id = DSPP_7, + .base = 0x62000, .len = 0x1800, /* FIXME(REG_ADDR): lite variant */ + .sblk = &sm8750_dspp_sblk, + }, +}; + +static const struct dpu_pingpong_cfg nord_pp[] = { + { + .name = "pingpong_0", .id = PINGPONG_0, + .base = 0x69000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + }, { + .name = "pingpong_1", .id = PINGPONG_1, + .base = 0x6a000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), + }, { + .name = "pingpong_2", .id = PINGPONG_2, + .base = 0x6b000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + }, { + .name = "pingpong_3", .id = PINGPONG_3, + .base = 0x6c000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), + }, { + .name = "pingpong_4", .id = PINGPONG_4, + .base = 0x6d000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), + }, { + .name = "pingpong_5", .id = PINGPONG_5, + .base = 0x6e000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), + }, { + .name = "pingpong_6", .id = PINGPONG_6, + .base = 0x6f000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 20), + }, { + .name = "pingpong_7", .id = PINGPONG_7, + .base = 0x70000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 21), + }, { + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, + .base = 0x66000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_4, + }, { + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, + .base = 0x66400, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_4, + }, { + .name = "pingpong_cwb_2", .id = PINGPONG_CWB_2, + .base = 0x7e000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_5, + }, { + .name = "pingpong_cwb_3", .id = PINGPONG_CWB_3, + .base = 0x7e400, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_5, + }, +}; + +static const struct dpu_merge_3d_cfg nord_merge_3d[] = { + { + .name = "merge_3d_0", .id = MERGE_3D_0, + .base = 0x4e000, .len = 0x1c, + }, { + .name = "merge_3d_1", .id = MERGE_3D_1, + .base = 0x4f000, .len = 0x1c, + }, { + .name = "merge_3d_2", .id = MERGE_3D_2, + .base = 0x50000, .len = 0x1c, + }, { + .name = "merge_3d_3", .id = MERGE_3D_3, + .base = 0x51000, .len = 0x1c, + }, { + .name = "merge_3d_4", .id = MERGE_3D_4, + .base = 0x66700, .len = 0x1c, + }, { + .name = "merge_3d_5", .id = MERGE_3D_5, + .base = 0x7e700, .len = 0x1c, + }, +}; + +/* + * NOTE: Each display compression engine (DCE) contains dual hard + * slice DSC encoders so both share same base address but with + * its own different sub block address. Nord retains sm8750's + * topology of 8 DSC instances (2 per DCE × 4). + */ +static const struct dpu_dsc_cfg nord_dsc[] = { + { + .name = "dce_0_0", .id = DSC_0, + .base = 0x80000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_0_1", .id = DSC_1, + .base = 0x80000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_1_0", .id = DSC_2, + .base = 0x81000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_1_1", .id = DSC_3, + .base = 0x81000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_2_0", .id = DSC_4, + .base = 0x82000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_2_1", .id = DSC_5, + .base = 0x82000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_3_0", .id = DSC_6, + .base = 0x83000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_3_1", .id = DSC_7, + .base = 0x83000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, +}; + +/* + * Nord has 2 writeback blocks: WB2 (matches sm8750) and WB1 (new). + * WB1 base and xin_id are inferred via stride from existing WB pattern. + * FIXME(REG_ADDR): WB1 base address inferred as 0x65000 - 0x2c8 stride. + * FIXME(XIU_MAP): WB1 xin_id set to 7; verify against real hardware map. + */ +static const struct dpu_wb_cfg nord_wb[] = { + { + .name = "wb_1", .id = WB_1, + .base = 0x64800, .len = 0x2c8, /* FIXME(REG_ADDR): inferred */ + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), + .xin_id = 7, /* FIXME(XIU_MAP): inferred */ + .maxlinewidth = 4096, + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 3), + }, { + .name = "wb_2", .id = WB_2, + .base = 0x65000, .len = 0x2c8, + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), + .xin_id = 6, + .maxlinewidth = 4096, + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), + }, +}; + +static const struct dpu_cwb_cfg nord_cwb[] = { + { + .name = "cwb_0", .id = CWB_0, + .base = 0x66200, .len = 0x20, + }, + { + .name = "cwb_1", .id = CWB_1, + .base = 0x66600, .len = 0x20, + }, + { + .name = "cwb_2", .id = CWB_2, + .base = 0x7e200, .len = 0x20, + }, + { + .name = "cwb_3", .id = CWB_3, + .base = 0x7e600, .len = 0x20, + }, +}; + +/* + * Nord has 8 active interfaces (INTF_0,3,4,6,7,8,9,10) with no DSI. + * DP0 connects to INTF_0, INTF_3, INTF_6, INTF_7 (4 ports for MST). + * DP1 connects to INTF_4, INTF_8, INTF_9, INTF_10 (4 ports for MST). + * Interfaces 1, 2, 5 are skipped (removed from sm8750). + * All interface base addresses extend the stride from sm8750. + * FIXME(REG_ADDR): INTF_4,6,7,8,9,10 addresses inferred via 0x1000 stride. + */ +static const struct dpu_intf_cfg nord_intf[] = { + { + .name = "intf_0", .id = INTF_0, + .base = 0x34000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), + }, { + .name = "intf_3", .id = INTF_3, + .base = 0x37000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), + }, { + .name = "intf_4", .id = INTF_4, + .base = 0x38000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x1000 */ + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21), + }, { + .name = "intf_6", .id = INTF_6, + .base = 0x3a000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x3000 */ + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, /* second pair for DP0 MST */ + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23), + }, { + .name = "intf_7", .id = INTF_7, + .base = 0x3b000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x4000 */ + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, /* third pair for DP0 MST */ + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 0), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 1), + }, { + .name = "intf_8", .id = INTF_8, + .base = 0x3c000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x5000 */ + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, /* second pair for DP1 MST */ + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 2), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 3), + }, { + .name = "intf_9", .id = INTF_9, + .base = 0x3d000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x6000 */ + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, /* third pair for DP1 MST */ + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 4), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 5), + }, { + .name = "intf_10", .id = INTF_10, + .base = 0x3e000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x7000 */ + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, /* fourth pair for DP1 MST */ + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 6), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 7), + }, +}; + +static const struct dpu_perf_cfg nord_perf_data = { + .max_bw_low = 18900000, + .max_bw_high = 28500000, + .min_core_ib = 2500000, + .min_llcc_ib = 0, + .min_dram_ib = 800000, + .min_prefill_lines = 35, + .danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0}, + .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(sc7180_qos_linear), + .entries = sc7180_qos_linear + }, + {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), + .entries = sc7180_qos_macrotile + }, + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), + .entries = sc7180_qos_nrt + }, + /* TODO: macrotile-qseed is different from macrotile */ + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; + +static const struct dpu_mdss_version nord_mdss_ver = { + .core_major_ver = 12, + .core_minor_ver = 1, +}; + +const struct dpu_mdss_cfg dpu_nord_cfg = { + .mdss_ver = &nord_mdss_ver, + .caps = &nord_dpu_caps, + .mdp = &nord_mdp, + .cdm = &dpu_cdm_5_x, + .ctl_count = ARRAY_SIZE(nord_ctl), + .ctl = nord_ctl, + .sspp_count = ARRAY_SIZE(nord_sspp), + .sspp = nord_sspp, + .mixer_count = ARRAY_SIZE(nord_lm), + .mixer = nord_lm, + .dspp_count = ARRAY_SIZE(nord_dspp), + .dspp = nord_dspp, + .pingpong_count = ARRAY_SIZE(nord_pp), + .pingpong = nord_pp, + .dsc_count = ARRAY_SIZE(nord_dsc), + .dsc = nord_dsc, + .merge_3d_count = ARRAY_SIZE(nord_merge_3d), + .merge_3d = nord_merge_3d, + .wb_count = ARRAY_SIZE(nord_wb), + .wb = nord_wb, + .cwb_count = ARRAY_SIZE(nord_cwb), + .cwb = nord_cwb, + .intf_count = ARRAY_SIZE(nord_intf), + .intf = nord_intf, + .vbif = &sm8650_vbif, + .perf = &nord_perf_data, +}; + +#endif diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 107150a8553fe..75ae3026593f3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -798,6 +798,7 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = { #include "catalog/dpu_10_2_milos.h" #include "catalog/dpu_12_0_sm8750.h" +#include "catalog/dpu_12_1_nord.h" #include "catalog/dpu_12_2_glymur.h" #include "catalog/dpu_12_4_eliza.h" #include "catalog/dpu_13_0_kaanapali.h" diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 71e1a404e25f9..61242695b1b86 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -779,6 +779,7 @@ extern const struct dpu_mdss_cfg dpu_msm8937_cfg; extern const struct dpu_mdss_cfg dpu_msm8953_cfg; extern const struct dpu_mdss_cfg dpu_msm8996_cfg; extern const struct dpu_mdss_cfg dpu_msm8998_cfg; +extern const struct dpu_mdss_cfg dpu_nord_cfg; extern const struct dpu_mdss_cfg dpu_sar2130p_cfg; extern const struct dpu_mdss_cfg dpu_sdm630_cfg; extern const struct dpu_mdss_cfg dpu_sdm660_cfg; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h index 0e65bf5ddc4a6..7eccb4d2c65ef 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h @@ -226,6 +226,8 @@ enum dpu_intf { INTF_6, INTF_7, INTF_8, + INTF_9, + INTF_10, INTF_MAX }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index d6182cec06d58..1785ee61e23f0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1514,6 +1514,7 @@ static const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,msm8953-mdp5", .data = &dpu_msm8953_cfg, }, { .compatible = "qcom,msm8996-mdp5", .data = &dpu_msm8996_cfg, }, { .compatible = "qcom,msm8998-dpu", .data = &dpu_msm8998_cfg, }, + { .compatible = "qcom,nord-dpu", .data = &dpu_nord_cfg, }, { .compatible = "qcom,qcm2290-dpu", .data = &dpu_qcm2290_cfg, }, { .compatible = "qcom,sa8775p-dpu", .data = &dpu_sa8775p_cfg, }, { .compatible = "qcom,sar2130p-dpu", .data = &dpu_sar2130p_cfg, }, From b8c951466fd32952935d9395c9741c9955a28df5 Mon Sep 17 00:00:00 2001 From: Jessica Zhang Date: Thu, 8 Oct 2026 22:53:51 +0530 Subject: [PATCH 1057/1133] BACKPORT: drm/msm/dpu: remove max_mixer_width from catalog Remove the now-unused max_mixer_width field from the HW catalog. It doesn't represent an actual hardware constraint. [MP: rebased on msm-next; also drop the field from the milos, eliza and kaanapali catalogs added since v3] Link: https://lore.kernel.org/all/20261008-lm_fixes_final-v4-5-fa986071c3c1@oss.qualcomm.com/ Signed-off-by: Jessica Zhang Reviewed-by: Dmitry Baryshkov Signed-off-by: Dmitry Baryshkov (cherry picked from commit a0bd29c81f90e5f2789abb51bd9f2c86b32298cd) [Mahadevan: extend the cleanup to dpu_12_1_nord.h after importing the Nord DPU catalog into the DRM topic; align Jessica's author email with her existing sign-off.] Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_2_milos.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_4_eliza.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_13_0_kaanapali.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h | 1 - drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 2 -- 35 files changed, 36 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h index 2eef5f69832fd..b7ec821c8f52c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h @@ -8,7 +8,6 @@ #define _DPU_10_0_SM8650_H static const struct dpu_caps sm8650_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_2_milos.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_2_milos.h index 1aa8aea4e3525..760936b71c717 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_2_milos.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_2_milos.h @@ -9,7 +9,6 @@ #define _DPU_10_2_MILOS_H static const struct dpu_caps milos_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x7, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h index 3889eb8a54288..c01caa1e18892 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h @@ -9,7 +9,6 @@ #define _DPU_12_0_SM8750_H static const struct dpu_caps sm8750_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h index 8eb18752f3c4b..0d494ea350037 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h @@ -26,7 +26,6 @@ */ static const struct dpu_caps nord_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h index 4eb4a0e9803ea..0e76320c52861 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_2_glymur.h @@ -7,7 +7,6 @@ #define _DPU_12_2_GLYMUR_H static const struct dpu_caps glymur_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_4_eliza.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_4_eliza.h index b93d328889727..46f534ada6382 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_4_eliza.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_4_eliza.h @@ -4,7 +4,6 @@ #define _DPU_12_4_ELIZA_H static const struct dpu_caps eliza_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_13_0_kaanapali.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_13_0_kaanapali.h index 85f455a9f29c8..1fb53cd9ac153 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_13_0_kaanapali.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_13_0_kaanapali.h @@ -7,7 +7,6 @@ #define _DPU_13_0_KAANAPALI_H static const struct dpu_caps kaanapali_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h index 4ff7b397f8089..c9ec48b135c12 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_14_msm8937.h @@ -7,7 +7,6 @@ #define _DPU_1_14_MSM8937_H static const struct dpu_caps msm8937_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_blendstages = 0x4, .max_linewidth = DEFAULT_DPU_LINE_WIDTH, .pixel_ram_size = 40 * 1024, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h index 1518c3d39ce83..af664c7accb51 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_15_msm8917.h @@ -7,7 +7,6 @@ #define _DPU_1_14_MSM8917_H static const struct dpu_caps msm8917_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_blendstages = 0x4, .max_linewidth = DEFAULT_DPU_LINE_WIDTH, .pixel_ram_size = 16 * 1024, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h index 859a97e8c07eb..bc8a108e5674f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_16_msm8953.h @@ -7,7 +7,6 @@ #define _DPU_1_16_MSM8953_H static const struct dpu_caps msm8953_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_blendstages = 0x4, .max_linewidth = DEFAULT_DPU_LINE_WIDTH, .pixel_ram_size = 40 * 1024, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h index 67910a2f68801..e9770a3a453fb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h @@ -9,7 +9,6 @@ #define _DPU_1_7_MSM8996_H static const struct dpu_caps msm8996_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x7, .has_src_split = true, .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h index 67c1463d3bd6c..6fd2f202f7b31 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h @@ -8,7 +8,6 @@ #define _DPU_3_0_MSM8998_H static const struct dpu_caps msm8998_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x7, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h index 84344029819f7..80de77b6cbc79 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h @@ -7,7 +7,6 @@ #define _DPU_3_2_SDM660_H static const struct dpu_caps sdm660_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x7, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h index ef5777aee5876..bb889d56ea256 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h @@ -7,7 +7,6 @@ #define _DPU_3_3_SDM630_H static const struct dpu_caps sdm630_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_blendstages = 0x7, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h index b608d2bb6d48b..0e47fc3e9779b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h @@ -8,7 +8,6 @@ #define _DPU_4_0_SDM845_H static const struct dpu_caps sdm845_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h index 9729a65d3e3a4..f0a7d61740020 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h @@ -8,7 +8,6 @@ #define _DPU_5_0_SM8150_H static const struct dpu_caps sm8150_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h index fb18de029e80d..2d70802c7c3c9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h @@ -8,7 +8,6 @@ #define _DPU_5_1_SC8180X_H static const struct dpu_caps sc8180x_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h index 92a614686cb60..7d8a83282f80c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_2_sm7150.h @@ -8,7 +8,6 @@ #define _DPU_5_2_SM7150_H static const struct dpu_caps sm7150_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h index 87488d3ed95f3..6dac4b8019b72 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_3_sm6150.h @@ -7,7 +7,6 @@ #define _DPU_5_3_SM6150_H static const struct dpu_caps sm6150_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x9, .has_dim_layer = true, .has_idle_pc = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h index 64be51e301591..5280a496277ad 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h @@ -9,7 +9,6 @@ #define _DPU_5_4_SM6125_H static const struct dpu_caps sm6125_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x6, .has_dim_layer = true, .has_idle_pc = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h index 0e311d54ef188..87c88190e6d3f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h @@ -8,7 +8,6 @@ #define _DPU_6_0_SM8250_H static const struct dpu_caps sm8250_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h index d6f7ee24ca933..4109875e1cc2d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h @@ -8,7 +8,6 @@ #define _DPU_6_2_SC7180_H static const struct dpu_caps sc7180_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x9, .has_dim_layer = true, .has_idle_pc = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h index 20a2e9ff5cc99..7da39cb0866e9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h @@ -8,7 +8,6 @@ #define _DPU_6_3_SM6115_H static const struct dpu_caps sm6115_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_blendstages = 0x4, .has_dim_layer = true, .has_idle_pc = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h index dd891703e35f8..5bad15f4242b3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_4_sm6350.h @@ -9,7 +9,6 @@ #define _DPU_6_4_SM6350_H static const struct dpu_caps sm6350_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x7, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h index 7ae7530aa3b08..dae242521f99b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h @@ -8,7 +8,6 @@ #define _DPU_6_5_QCM2290_H static const struct dpu_caps qcm2290_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_blendstages = 0x4, .has_dim_layer = true, .has_idle_pc = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h index fc7ceac859bec..8a0315028f88a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_9_sm6375.h @@ -9,7 +9,6 @@ #define _DPU_6_9_SM6375_H static const struct dpu_caps sm6375_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_LINE_WIDTH, .max_mixer_blendstages = 0x4, .has_dim_layer = true, .has_idle_pc = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h index d06c14f05faf8..1fd795b5dae4c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h @@ -8,7 +8,6 @@ #define _DPU_7_0_SM8350_H static const struct dpu_caps sm8350_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h index 99b8a890fddc7..bdad3fea65e2e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h @@ -8,7 +8,6 @@ #define _DPU_7_2_SC7280_H static const struct dpu_caps sc7280_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x7, .has_dim_layer = true, .has_idle_pc = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h index 0ba907711d36b..96f8f1763a179 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h @@ -8,7 +8,6 @@ #define _DPU_8_0_SC8280XP_H static const struct dpu_caps sc8280xp_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 11, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h index 170a709f987c7..f62d5bb5be481 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h @@ -8,7 +8,6 @@ #define _DPU_8_1_SM8450_H static const struct dpu_caps sm8450_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h index 9cc5e22e12282..dcb27b6fe475c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h @@ -7,7 +7,6 @@ #define _DPU_8_4_SA8775P_H static const struct dpu_caps sa8775p_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h index b3d0f221807b1..d37f64866d8e4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h @@ -8,7 +8,6 @@ #define _DPU_9_0_SM8550_H static const struct dpu_caps sm8550_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h index 7effe7120a56d..e041cab8505c8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_1_sar2130p.h @@ -8,7 +8,6 @@ #define _DPU_9_1_SAR2130P_H static const struct dpu_caps sar2130p_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h index 7b3febf8742d7..a6eae4ebc55b7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h @@ -7,7 +7,6 @@ #define _DPU_9_2_X1E80100_H static const struct dpu_caps x1e80100_dpu_caps = { - .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, .has_src_split = true, .has_dim_layer = true, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 61242695b1b86..b3dce2a972d4c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -273,7 +273,6 @@ struct dpu_rotation_cfg { /** * struct dpu_caps - define DPU capabilities - * @max_mixer_width max layer mixer line width support. * @max_mixer_blendstages max layer mixer blend stages or * supported z order * @has_src_split source split feature status @@ -286,7 +285,6 @@ struct dpu_rotation_cfg { * @max_vdeci_exp max vertical decimation supported (max is 2^value) */ struct dpu_caps { - u32 max_mixer_width; u32 max_mixer_blendstages; bool has_src_split; bool has_dim_layer; From 19016b56260e5fd80793ae5df0ffe6c057bb910b Mon Sep 17 00:00:00 2001 From: Vishnu Saini Date: Sat, 24 Oct 2026 12:52:24 +0530 Subject: [PATCH 1058/1133] FROMLIST: dt-bindings: display: panel: ilitek,ili7807s: Allow backlight property The DLC0697 panel is lit by a separate backlight device, which is referenced from the panel node through the common 'backlight' property. Declare 'backlight: true' so the property is explicitly allowed by the schema. Link: https://lore.kernel.org/r/20261025-dlc_backlight-v1-1-1d1c49c3e101@oss.qualcomm.com Signed-off-by: Vishnu Saini --- .../devicetree/bindings/display/panel/ilitek,ili7807s.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili7807s.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili7807s.yaml index ba8c5bbf8ffc4..46b941c18565d 100644 --- a/Documentation/devicetree/bindings/display/panel/ilitek,ili7807s.yaml +++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili7807s.yaml @@ -23,6 +23,8 @@ properties: maxItems: 1 description: DSI virtual channel + backlight: true + vddi-supply: description: I/O voltage supply (1.8V) From 91a2fb74642d30cbec28daa8a9e8598ff600faae Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 4 Mar 2026 15:34:48 +0200 Subject: [PATCH 1059/1133] FROMLIST: drm/msm: restore GEM-related IOCTLs for KMS devices The MSM GBM backend uses MSM_GEM_NEW to allocate GEM buffers from the KMS driver, imports them into the GPU driver (msm or kgsl) and then uses them for rendering / blending. Commit 98f11fd1cf92 ("drm/msm: Take the ioctls away from the KMS-only driver") dropped all IOCTLs from the MSM KMS devices, pointing out the need to use dumb buffers, however dumb buffers should not be used by the GPU for rendering. Restore GEM-related IOCTLs for the KMS devices. Fixes: 98f11fd1cf92 ("drm/msm: Take the ioctls away from the KMS-only driver") Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260304-msm-restore-ioctls-v1-1-b28f9231fcd2@oss.qualcomm.com/ CRs-Fixed: 4733485 Signed-off-by: Mahadevan P --- drivers/gpu/drm/msm/msm_drv.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 5e8f3ce26b32c..c9b5de618ee2f 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -884,6 +884,14 @@ static const struct drm_ioctl_desc msm_ioctls[] = { DRM_IOCTL_DEF_DRV(MSM_PERFCNTR_CONFIG, msm_ioctl_perfcntr_config, DRM_RENDER_ALLOW), }; +static const struct drm_ioctl_desc msm_kms_ioctls[] = { + DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_INFO, msm_ioctl_gem_info, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_PREP, msm_ioctl_gem_cpu_prep, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_FINI, msm_ioctl_gem_cpu_fini, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_MADVISE, msm_ioctl_gem_madvise, DRM_RENDER_ALLOW), +}; + static void msm_show_fdinfo(struct drm_printer *p, struct drm_file *file) { struct drm_device *dev = file->minor->dev; @@ -951,6 +959,8 @@ static const struct drm_driver msm_kms_driver = { #endif MSM_FBDEV_DRIVER_OPS, .show_fdinfo = msm_show_fdinfo, + .ioctls = msm_kms_ioctls, + .num_ioctls = ARRAY_SIZE(msm_kms_ioctls), .fops = &fops, .name = "msm-kms", .desc = "MSM Snapdragon DRM", From 29c839eed9785e2eeb471105dc5fa4398abfe8cf Mon Sep 17 00:00:00 2001 From: Guo Chen Date: Tue, 3 Nov 2026 19:21:28 +0800 Subject: [PATCH 1060/1133] FROMLIST: PM: EM: Exclude boost frequencies from inefficiency ranking em_compute_costs() ranks all the frequencies of the table, boost ones included. A non-boost frequency can be marked inefficient only because a faster boost frequency has a lower or equal cost, e.g. 3.9 GHz 4.0 GHz (cost C) 4.1 GHz (boost, cost C) With boost disabled 4.1 GHz cannot be selected, but 4.0 GHz is still skipped by governors rounding down to efficient frequencies (e.g. ondemand with CPUFREQ_RELATION_HE), which land on 3.9 GHz instead of the best selectable frequency. Several frequencies can be affected. Exclude the boost frequencies from the ranking in em_compute_costs() and keep them all efficient, using the highest non-boost frequency of the CPUFreq table, returned by the new helper cpufreq_table_max_nonboost_freq(), as the boundary. Fixes: c8ed99533dbc ("PM: EM: Mark inefficient states") Link: https://lore.kernel.org/linux-pm/20261103-em-rank-boost-separately-v2-1-5a13d1b38d37@oss.qualcomm.com/ Signed-off-by: Guo Chen Signed-off-by: Xin Liu --- include/linux/cpufreq.h | 24 ++++++++++++++++++++++++ kernel/power/energy_model.c | 16 ++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index d3d0d9d02aa4a..c93316141a113 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -1155,6 +1155,24 @@ cpufreq_table_set_inefficient(struct cpufreq_policy *policy, return -EINVAL; } +static inline unsigned int +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy) +{ + struct cpufreq_frequency_table *pos; + unsigned int max = 0; + + if (!policy->freq_table) + return 0; + + /* The table may be unsorted, scan all of it for the highest one. */ + cpufreq_for_each_valid_entry(pos, policy->freq_table) { + if (!(pos->flags & CPUFREQ_BOOST_FREQ) && pos->frequency > max) + max = pos->frequency; + } + + return max; +} + static inline int parse_perf_domain(int cpu, const char *list_name, const char *cell_name, struct of_phandle_args *args) @@ -1219,6 +1237,12 @@ cpufreq_table_set_inefficient(struct cpufreq_policy *policy, return -EINVAL; } +static inline unsigned int +cpufreq_table_max_nonboost_freq(struct cpufreq_policy *policy) +{ + return 0; +} + static inline int of_perf_domain_get_sharing_cpumask(int pcpu, const char *list_name, const char *cell_name, struct cpumask *cpumask, struct of_phandle_args *pargs) diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c index d19a65461ae80..5b1d095fd3767 100644 --- a/kernel/power/energy_model.c +++ b/kernel/power/energy_model.c @@ -255,15 +255,24 @@ static int em_compute_costs(struct device *dev, struct em_perf_state *table, unsigned long flags) { unsigned long prev_cost = ULONG_MAX; + struct cpufreq_policy *policy; + unsigned int max_nonboost = 0; int i, ret; /* This is needed only for CPUs and EAS skip other devices */ if (!_is_cpu_device(dev)) return 0; + policy = cpufreq_cpu_get(dev->id); + if (policy) { + max_nonboost = cpufreq_table_max_nonboost_freq(policy); + cpufreq_cpu_put(policy); + } + /* Compute the cost of each performance state. */ for (i = nr_states - 1; i >= 0; i--) { unsigned long power_res, cost; + bool boost = max_nonboost && table[i].frequency > max_nonboost; if ((flags & EM_PERF_DOMAIN_ARTIFICIAL) && cb->get_cost) { ret = cb->get_cost(dev, table[i].frequency, &cost); @@ -284,6 +293,13 @@ static int em_compute_costs(struct device *dev, struct em_perf_state *table, table[i].flags = EM_PERF_STATE_INEFFICIENT; dev_dbg(dev, "EM: OPP:%lu is inefficient\n", table[i].frequency); + } else if (boost) { + /* + * Keep all boost states efficient. Resetting prev_cost + * also keeps the highest non-boost state efficient, + * then rank the rest on their own. + */ + prev_cost = ULONG_MAX; } else { prev_cost = table[i].cost; } From 76d931c3492454b30c4b41543f46ed127075657f Mon Sep 17 00:00:00 2001 From: Gaole Zhang Date: Fri, 24 Jul 2026 01:13:33 +0800 Subject: [PATCH 1061/1133] FROMLIST: wifi: ath12k: Add EHT capabilities to scan probe frame ath12k hardware scan Probe Request frames do not include the EHT Capabilities element. Without this element, an AP cannot identify the STA as EHT-capable during active scanning and may omit EHT-related information from its Probe Response. This can result in incomplete scan information and prevent userspace from correctly determining the AP's EHT capabilities. For firmware to include the EHT Capabilities element in scan Probe Request frames, two conditions are required: - The scan channel must have WMI_CHAN_INFO_ALLOW_EHT set, which allows firmware to add the EHT Capabilities element to Probe Request frames. - The EHT Capabilities element must be configured on the vdev through WMI_VDEV_SET_IE_CMDID, so firmware can use it when building Probe Request frames. Set WMI_CHAN_INFO_ALLOW_EHT for channels when 11be is supported by firmware and not disabled by ACPI. Also configure the EHT Capabilities element before each hardware scan when the element is present in the mac80211 scan IE buffer. Firmware retains the configured element in the vdev context until it is replaced or the vdev is deleted. However, ath12k scans may either reuse an already started vdev or create a temporary scan vdev that is cleaned up after scan completion. Sending WMI_VDEV_SET_IE_CMDID for each scan request ensures correct behavior in both cases. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3 Signed-off-by: Gaole Zhang Link: https://lore.kernel.org/all/20261009095538.2718979-1-gaole.zhang@oss.qualcomm.com/ --- drivers/net/wireless/ath/ath12k/core.h | 6 ++++ drivers/net/wireless/ath/ath12k/mac.c | 27 ++++++++++++-- drivers/net/wireless/ath/ath12k/reg.c | 4 +++ drivers/net/wireless/ath/ath12k/wmi.c | 50 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 21 +++++++++++ 5 files changed, 106 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 99d71dab7c04c..a8d96a5ef4286 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -1382,6 +1382,12 @@ static inline struct ath12k *ath12k_ah_to_ar(struct ath12k_hw *ah, u8 radio_idx) return &ah->radio[radio_idx]; } +static inline bool ath12k_is_11be_enabled(struct ath12k_base *ab) +{ + return test_bit(WMI_TLV_SERVICE_11BE, ab->wmi_ab.svc_map) && + !ath12k_acpi_get_disable_11be(ab); +} + static inline struct ath12k_hw *ath12k_ar_to_ah(struct ath12k *ar) { return ar->ah; diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 70ed852a2d0a2..e32f788a09c6a 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -5705,6 +5705,25 @@ ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar) return ATH12K_FIRST_SCAN_LINK; } +static int ath12k_mac_set_scan_eht_cap_ie(struct ath12k *ar, + struct ath12k_link_vif *arvif, + const u8 *ies, size_t ies_len) +{ + const struct element *eht_cap; + + lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); + + eht_cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_CAPABILITY, ies, + ies_len); + if (!eht_cap || eht_cap->datalen <= 1) + return 0; + + return ath12k_wmi_vdev_set_ie(ar, arvif->vdev_id, + WLAN_EID_EXTENSION, + eht_cap->data, eht_cap->datalen, + WMI_SET_VDEV_IE_BAND_ALL); +} + static int ath12k_mac_initiate_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *hw_req, @@ -5821,6 +5840,11 @@ static int ath12k_mac_initiate_hw_scan(struct ieee80211_hw *hw, goto exit; } arg->extraie.len = req->ie_len; + ret = ath12k_mac_set_scan_eht_cap_ie(ar, arvif, req->ie, + req->ie_len); + if (ret) + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "failed to set eht cap ie, ret %d\n", ret); } if (req->n_ssids) { @@ -9086,8 +9110,7 @@ static void ath12k_mac_copy_eht_cap(struct ath12k *ar, memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap)); - if (!(test_bit(WMI_TLV_SERVICE_11BE, ar->ab->wmi_ab.svc_map)) || - ath12k_acpi_get_disable_11be(ar->ab)) + if (!ath12k_is_11be_enabled(ar->ab)) return; eht_cap->has_eht = true; diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c index 7cf3dbc4fc8a9..ac60515492680 100644 --- a/drivers/net/wireless/ath/ath12k/reg.c +++ b/drivers/net/wireless/ath/ath12k/reg.c @@ -140,6 +140,7 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait) enum nl80211_band band; int num_channels = 0; int i, ret = 0; + bool has_eht; if (ar->ah->state == ATH12K_HW_STATE_RESTARTING) return 0; @@ -180,6 +181,8 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait) ch = arg->channel; + has_eht = ath12k_is_11be_enabled(ar->ab); + for (band = 0; band < NUM_NL80211_BANDS; band++) { if (!(ar->mac.sbands[band].channels && bands[band])) continue; @@ -201,6 +204,7 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait) ch->allow_ht = true; ch->allow_vht = true; ch->allow_he = true; + ch->allow_eht = has_eht; ch->dfs_set = !!(channel->flags & IEEE80211_CHAN_RADAR); diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 75b259990c79e..f41138a7c68e8 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -2005,6 +2005,54 @@ int ath12k_wmi_p2p_go_bcn_ie(struct ath12k *ar, u32 vdev_id, return ret; } +int ath12k_wmi_vdev_set_ie(struct ath12k *ar, u32 vdev_id, u32 ie_id, + const u8 *ie, size_t ie_len, u32 band) +{ + struct ath12k_wmi_pdev *wmi = ar->wmi; + struct wmi_vdev_set_ie_cmd *cmd; + struct sk_buff *skb; + struct wmi_tlv *tlv; + size_t aligned_len; + int ret, len; + void *ptr; + + aligned_len = roundup(ie_len, sizeof(u32)); + len = sizeof(*cmd) + TLV_HDR_SIZE + aligned_len; + + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + ptr = skb->data; + cmd = ptr; + cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_SET_IE_CMD, + sizeof(*cmd)); + cmd->vdev_id = cpu_to_le32(vdev_id); + cmd->ie_id = cpu_to_le32(ie_id); + cmd->ie_len = cpu_to_le32(ie_len); + cmd->ie_source = cpu_to_le32(WMI_SET_VDEV_IE_SOURCE_HOST); + cmd->band = cpu_to_le32(band); + + ath12k_dbg(ar->ab, ATH12K_DBG_WMI, + "WMI set ie vdev_id %u ie_id %u ie_len %zu band %u\n", + vdev_id, ie_id, ie_len, band); + + ptr += sizeof(*cmd); + tlv = ptr; + tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, aligned_len); + memcpy(tlv->value, ie, ie_len); + + ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_SET_IE_CMDID); + if (ret) { + ath12k_warn(ar->ab, + "failed to send WMI_VDEV_SET_IE_CMDID for vdev %u ie %u: %d\n", + vdev_id, ie_id, ret); + dev_kfree_skb(skb); + } + + return ret; +} + int ath12k_wmi_bcn_tmpl(struct ath12k_link_vif *arvif, struct ieee80211_mutable_offsets *offs, struct sk_buff *bcn, @@ -2946,6 +2994,8 @@ int ath12k_wmi_send_scan_chan_list_cmd(struct ath12k *ar, chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_ALLOW_VHT); else if (channel_arg->allow_ht) chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_ALLOW_HT); + if (channel_arg->allow_eht) + chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_ALLOW_EHT); if (channel_arg->half_rate) chan_info->info |= cpu_to_le32(WMI_CHAN_INFO_HALF_RATE); if (channel_arg->quarter_rate) diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index b508aa759bd8d..5d0afbf0bd0c8 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -3074,6 +3074,7 @@ struct ath12k_wmi_channel_arg { allow_ht:1, allow_vht:1, allow_he:1, + allow_eht:1, set_agile:1, psc_channel:1; u32 phy_mode; @@ -3694,6 +3695,7 @@ struct ath12k_wmi_scan_cancel_arg { #define WMI_CHAN_INFO_DFS_FREQ2 BIT(16) #define WMI_CHAN_INFO_ALLOW_HE BIT(17) #define WMI_CHAN_INFO_PSC BIT(18) +#define WMI_CHAN_INFO_ALLOW_EHT BIT(21) #define WMI_CHAN_REG_INFO1_MIN_PWR GENMASK(7, 0) #define WMI_CHAN_REG_INFO1_MAX_PWR GENMASK(15, 8) @@ -3845,6 +3847,23 @@ struct wmi_p2p_go_set_beacon_ie_cmd { __le32 ie_buf_len; } __packed; +#define WMI_SET_VDEV_IE_SOURCE_HOST 0 + +enum wmi_set_vdev_ie_band { + WMI_SET_VDEV_IE_BAND_ALL, + WMI_SET_VDEV_IE_BAND_2_4GHZ, + WMI_SET_VDEV_IE_BAND_5GHZ, +}; + +struct wmi_vdev_set_ie_cmd { + __le32 tlv_header; + __le32 vdev_id; + __le32 ie_id; + __le32 ie_len; + __le32 ie_source; + __le32 band; +} __packed; + struct wmi_vdev_install_key_cmd { __le32 tlv_header; __le32 vdev_id; @@ -6583,6 +6602,8 @@ int ath12k_wmi_pdev_resume(struct ath12k *ar, u32 pdev_id); int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar, struct ath12k_wmi_peer_assoc_arg *arg); +int ath12k_wmi_vdev_set_ie(struct ath12k *ar, u32 vdev_id, u32 ie_id, + const u8 *ie, size_t ie_len, u32 band); int ath12k_wmi_vdev_install_key(struct ath12k *ar, struct wmi_vdev_install_key_arg *arg); int ath12k_wmi_pdev_bss_chan_info_request(struct ath12k *ar, From 0c3688bb79815d6f6eefc03b79f3556cda4f18c6 Mon Sep 17 00:00:00 2001 From: Prashanth K Date: Thu, 22 Oct 2026 10:56:02 +0530 Subject: [PATCH 1062/1133] FROMLIST: usb: dwc3: qcom: check for hcd in dwc3_qcom_read_usb2_speed Currently dwc->xhci is not cleared if xhci_plat_probe() fails. During system suspend, dwc3_qcom_read_usb2_speed() checks dwc->xhci and assumes xhci is initialised. Since the probe failed, hcd will be null, and the subsequent access results in a NULL pointer dereference Unable to handle kernel NULL pointer dereference at virtual address 0000000000000058 Call trace: dwc3_qcom_pm_suspend dpm_run_callback device_suspend dpm_suspend dpm_suspend_start suspend_devices_and_enter pm_suspend Explicitly check the hcd pointer in dwc3_qcom_read_usb2_speed before accessing it. Link: https://lore.kernel.org/all/20261022052602.2335652-1-prashanth.k@oss.qualcomm.com/ Fixes: 6895ea55c385 ("usb: dwc3: qcom: Configure wakeup interrupts during suspend") Signed-off-by: Prashanth K Reviewed-by: Peter Chen --- drivers/usb/dwc3/dwc3-qcom.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 84cb1c44afb62..3f217e45094d4 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -239,7 +239,7 @@ static bool dwc3_qcom_is_host(struct dwc3_qcom *qcom) static enum usb_device_speed dwc3_qcom_read_usb2_speed(struct dwc3_qcom *qcom, int port_index) { - struct usb_device *udev; + struct usb_device *udev = NULL; struct usb_hcd __maybe_unused *hcd; struct dwc3 *dwc = &qcom->dwc; @@ -249,9 +249,8 @@ static enum usb_device_speed dwc3_qcom_read_usb2_speed(struct dwc3_qcom *qcom, i hcd = platform_get_drvdata(dwc->xhci); #ifdef CONFIG_USB - udev = usb_hub_find_child(hcd->self.root_hub, port_index + 1); -#else - udev = NULL; + if (hcd) + udev = usb_hub_find_child(hcd->self.root_hub, port_index + 1); #endif if (!udev) return USB_SPEED_UNKNOWN; From 60661dee2a3402f793cd9a583d5ce9f2a9a44631 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Mon, 2 Nov 2026 22:20:23 +0530 Subject: [PATCH 1063/1133] FROMLIST: usb: dwc3: qcom: Defer VBUS override update during system suspend dwc3_qcom_set_role_notifier() updates the VBUS override in QSCRATCH synchronously, from the context of the usb_role_switch_set_role() caller. The glue assumes that role switches only happen from a freezable workqueue, but that holds for the dwc3 core's mode switch, not for this notifier: the UCSI connector work, for one, runs on the non-freezable system workqueue. On SM8750, when the USB cable is unplugged while the system is in s2idle, the UCSI connector work for the change runs before the devices have resumed. It switches the role to USB_ROLE_NONE, and the notifier accesses QSCRATCH while the glue clocks are still off, before dwc3_qcom_pm_resume() turns them back on. The access does not complete and the SoC resets. pm_runtime_resume_and_get() does not prevent this: runtime PM is disabled at that point and the device is still marked active, so it returns success without resuming anything. While the glue is suspended for system sleep, only record the VBUS override update and apply it from dwc3_qcom_pm_resume() once the clocks are on. Apply it after the core has resumed, since resuming the gadget enables the override and the role switch is the more recent event. Serialize the notifier against the system suspend and resume callbacks with a mutex, so that a role switch can't run while the core or the glue is being suspended or resumed. Link: https://lore.kernel.org/all/20261022224220.480-1-tvlad744@gmail.com/ Fixes: 21188e8d6d75 ("usb: dwc3: qcom: Implement glue callbacks to facilitate runtime suspend") Cc: stable@vger.kernel.org Signed-off-by: Vladyslav Tymoshchuk Signed-off-by: Krishna Kurapati --- drivers/usb/dwc3/dwc3-qcom.c | 60 +++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 3f217e45094d4..9f750d56d9646 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -93,6 +93,11 @@ struct dwc3_qcom { enum usb_role current_role; bool uses_eusb2_phy; + + /* Serializes the role notifier against system suspend and resume */ + struct mutex role_lock; + bool vbus_override_pending; + bool vbus_override; }; #define to_dwc3_qcom(d) container_of((d), struct dwc3_qcom, dwc) @@ -587,10 +592,29 @@ static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_rol { struct dwc3_qcom *qcom = to_dwc3_qcom(dwc); struct device_node *eud_node; + bool enable; + + guard(mutex)(&qcom->role_lock); if (qcom->current_role == next_role) return; + enable = qcom->current_role != USB_ROLE_DEVICE; + + /* + * Not every caller of usb_role_switch_set_role() is frozen during + * system sleep, e.g. the UCSI connector work can run in the noirq + * resume phase. The glue clocks are off then and runtime PM can't + * turn them on, so leave QSCRATCH alone and let + * dwc3_qcom_pm_resume() apply the update. + */ + if (qcom->pm_suspended) { + qcom->vbus_override_pending = true; + qcom->vbus_override = enable; + qcom->current_role = next_role; + return; + } + if (pm_runtime_resume_and_get(qcom->dev)) { dev_dbg(qcom->dev, "Failed to resume device\n"); return; @@ -603,18 +627,12 @@ static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_rol of_node_put(eud_node); } - if (qcom->current_role == USB_ROLE_DEVICE) - dwc3_qcom_vbus_override_enable(qcom, false); - else if (qcom->current_role != USB_ROLE_DEVICE) - dwc3_qcom_vbus_override_enable(qcom, true); + qcom->vbus_override_pending = false; + dwc3_qcom_vbus_override_enable(qcom, enable); pm_runtime_mark_last_busy(qcom->dev); pm_runtime_put_sync(qcom->dev); - /* - * Current role changes via usb_role_switch_set_role callback protected - * internally by mutex lock. - */ qcom->current_role = next_role; } @@ -662,6 +680,10 @@ static int dwc3_qcom_probe(struct platform_device *pdev) if (pdata) qcom->uses_eusb2_phy = pdata->uses_eusb2_phy; + ret = devm_mutex_init(dev, &qcom->role_lock); + if (ret) + return ret; + qcom->resets = devm_reset_control_array_get_optional_exclusive(dev); if (IS_ERR(qcom->resets)) { return dev_err_probe(&pdev->dev, PTR_ERR(qcom->resets), @@ -795,6 +817,12 @@ static int dwc3_qcom_pm_suspend(struct device *dev) if (ret) return ret; + /* + * A role switch that comes in now waits until the glue is suspended + * and is then deferred, see dwc3_qcom_set_role_notifier(). + */ + guard(mutex)(&qcom->role_lock); + ret = dwc3_qcom_suspend(qcom, wakeup); if (ret) return ret; @@ -811,6 +839,8 @@ static int dwc3_qcom_pm_resume(struct device *dev) bool wakeup = device_may_wakeup(dev); int ret; + guard(mutex)(&qcom->role_lock); + ret = dwc3_qcom_resume(qcom, wakeup); if (ret) return ret; @@ -818,10 +848,18 @@ static int dwc3_qcom_pm_resume(struct device *dev) qcom->pm_suspended = false; ret = dwc3_pm_resume(&qcom->dwc); - if (ret) - return ret; - return 0; + /* + * Apply a VBUS override update from a role switch that came in while + * suspended. Do it after the core has resumed, as resuming the gadget + * enables the override and the role switch is the more recent event. + */ + if (qcom->vbus_override_pending) { + dwc3_qcom_vbus_override_enable(qcom, qcom->vbus_override); + qcom->vbus_override_pending = false; + } + + return ret; } static void dwc3_qcom_complete(struct device *dev) From d57b9ca11b3961b4aafe7ceb40bf5b2292504c62 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 2 Nov 2026 14:58:36 +0100 Subject: [PATCH 1064/1133] FROMLIST: phy: qcom: qmp-combo: Update Glymur USB3 settings Update the settings to match the latest hardware reference guide. Link: https://lore.kernel.org/all/20261102-topic-usb3_sequence-v1-1-5b144f5e6865@oss.qualcomm.com/ Signed-off-by: Konrad Dybcio Signed-off-by: Krishna Kurapati --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 54 +++++++++++------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index a36e309958454..7671dc1dac9e9 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -311,7 +311,7 @@ static const struct qmp_phy_init_tbl glymur_usb43dp_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE1, 0xaa), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE1, 0x01), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x13), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE1, 0xff), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE1_MODE1, 0x4d), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE1, 0x03), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x95), @@ -332,11 +332,11 @@ static const struct qmp_phy_init_tbl glymur_usb43dp_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0xaa), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x01), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_HS_SWITCH_SEL_1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE0, 0xff), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE1_MODE0, 0x4d), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x03), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BG_TIMER, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_EN_CENTER, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_EN_CENTER, 0x01), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_PER1, 0x62), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_PER2, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_BUF_ENABLE, 0x0a), @@ -351,11 +351,11 @@ static const struct qmp_phy_init_tbl glymur_usb43dp_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x76), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SVS_MODE_CLK_SEL, 0x0a), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x01), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_SPARE_FOR_ECO, 0x40), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_SPARE_FOR_ECO, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DCC_CAL_1, 0x40), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DCC_CAL_2, 0x01), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DCC_CAL_3, 0x60), - QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PSM_CAL_EN, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PSM_CAL_EN, 0x25), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x33), QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xaf), }; @@ -380,7 +380,7 @@ static const struct qmp_phy_init_tbl glymur_usb43dp_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_ALIGN_DETECT_CONFIG2, 0x30), QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_PCS_TX_RX_CONFIG, 0x0c), QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_EQ_CONFIG1, 0x4b), - QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_EQ_CONFIG5, 0x10), + QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_EQ_CONFIG5, 0x00), }; static const struct qmp_phy_init_tbl glymur_usb43dp_pcs_usb_tbl[] = { @@ -389,17 +389,17 @@ static const struct qmp_phy_init_tbl glymur_usb43dp_pcs_usb_tbl[] = { }; static const struct qmp_phy_init_tbl glymur_usb43dp_lalb_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CLKBUF_ENABLE, 0x81), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CLKBUF_ENABLE, 0x85), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_LVL_UPDATE_CTRL, 0x0d), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL1, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL2, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL3, 0x80), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL4, 0x8D), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL4, 0x8e), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRANSMITTER_EN_CTRL, 0x13), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_1, 0x0c), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_2, 0x40), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_3, 0x11), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_4, 0x11), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_4, 0x01), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_CAL_CTRL, 0x20), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_RESTRIM_CAL_CTRL, 0x02), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_POST_CAL_OFFSET, 0x10), @@ -415,14 +415,14 @@ static const struct qmp_phy_init_tbl glymur_usb43dp_lalb_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE_0_1_B5, 0x26), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE_0_1_B6, 0x12), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE_0_1_B7, 0x2a), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B0, 0x4c), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B1, 0xc4), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B2, 0x38), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B0, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B1, 0x93), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B2, 0x7c), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B3, 0x64), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B4, 0x0c), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B5, 0x4b), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B4, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B5, 0x57), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B6, 0x12), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B7, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B7, 0x1a), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_DCC_ANA_CTRL2, 0x0c), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT1_RATE1, 0x26), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT2_RATE1, 0x26), @@ -434,15 +434,15 @@ static const struct qmp_phy_init_tbl glymur_usb43dp_lalb_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_CODE_OVRD_RATE2, 0x03), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF1_RATE1, 0x15), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF2_RATE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF1_RATE2, 0x22), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF1_RATE2, 0x19), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF2_RATE2, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CODE_OVRD_RATE_2_3, 0x22), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND1_RATE1, 0xff), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND2_RATE1, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND1_RATE2, 0xff), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND2_RATE2, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_LOWER_FREQ_DIFF_BND_RATE1, 0x07), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_LOWER_FREQ_DIFF_BND_RATE2, 0x09), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_LOWER_FREQ_DIFF_BND_RATE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_LOWER_FREQ_DIFF_BND_RATE2, 0x0a), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_SUMMER_CAL_SPD_MODE_RATE_0123, 0x2f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_IVCM_CAL_CODE_OVERRIDE_RATE1, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_IVCM_CAL_CODE_OVERRIDE_RATE2, 0x00), @@ -461,17 +461,17 @@ static const struct qmp_phy_init_tbl glymur_usb43dp_lalb_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V8_LALB_FREQ_LOCK_DET_DLY_RATE2, 0x32), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_CP_CUR_FLL_RATE1, 0x07), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_CP_CUR_FLL_RATE2, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_CP_CUR_PLL_RATE1, 0x02), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_CP_CUR_PLL_RATE2, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_CP_CUR_PLL_RATE1, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_CP_CUR_PLL_RATE2, 0x05), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_CCODE_RATE_01, 0x76), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_CCODE_RATE_23, 0x67), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_CCODE_RATE_23, 0x55), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_FAST_RATE_0_1, 0x20), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_FAST_RATE_2_3, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_FAST_RATE_2_3, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_FLL_RATE_0_1, 0x33), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_FLL_RATE_2_3, 0x43), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_PLL_RATE_0_1, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_PLL_RATE_2_3, 0x51), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_FLL_DIV_RATIO_RATE_0123, 0xe5), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_FLL_DIV_RATIO_RATE_0123, 0xd5), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_CAP_CODE_RATE_0123, 0xf5), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_TYPE_CONFIG, 0x1f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_EN_LOWFREQ, 0x07), @@ -479,8 +479,8 @@ static const struct qmp_phy_init_tbl glymur_usb43dp_lalb_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V8_LALB_GM_CAL_EN, 0x1f), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_GM_CAL_RES_RATE0_1, 0x88), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_GM_CAL_RES_RATE2_3, 0x88), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_AUX_CLK_CTRL, 0x20), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_EOM_CTRL1, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_AUX_CLK_CTRL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_EOM_CTRL1, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_EQU_ADAPTOR_CNTRL2, 0x0a), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_EQU_ADAPTOR_CNTRL3, 0x0a), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_EQU_ADAPTOR_CNTRL4, 0xaa), @@ -495,7 +495,7 @@ static const struct qmp_phy_init_tbl glymur_usb43dp_lalb_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_IQTUNE_CTRL, 0x00), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_IQTUNE_MAN_INDEX, 0x10), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_IQTUNE_DIV2_CTRL_RATE0123, 0x1C), - QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_CAP_CODE_OVRD_MUXES, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_CAP_CODE_OVRD_MUXES, 0x1c), QMP_PHY_INIT_CFG(QSERDES_V8_LALB_DIG_BKUP_CTRL16, 0x37), }; From dd0f225c14e2f9f6389df3000192132dd2e9264e Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 2 Nov 2026 14:58:37 +0100 Subject: [PATCH 1065/1133] FROMLIST: phy: qcom: qmp-combo: Update SC8280XP USB3 PCS settings Update the settings to match the latest hardware reference guide. Link: https://lore.kernel.org/all/20261102-topic-usb3_sequence-v1-2-5b144f5e6865@oss.qualcomm.com/ Signed-off-by: Konrad Dybcio Signed-off-by: Krishna Kurapati --- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 7671dc1dac9e9..d183ce977a47e 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -1788,20 +1788,21 @@ static const struct qmp_phy_init_tbl sc8280xp_usb43dp_rx_tbl[] = { static const struct qmp_phy_init_tbl sc8280xp_usb43dp_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), - QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG1, 0xd0), - QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG2, 0x07), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG1, 0xc4), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG2, 0x89), QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG3, 0x20), QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG6, 0x13), QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21), - QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0xaa), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x33), QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_CONFIG, 0x0a), - QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG1, 0x88), - QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG2, 0x13), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG1, 0xd4), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG2, 0x30), QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCS_TX_RX_CONFIG, 0x0c), QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG1, 0x4b), QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG5, 0x10), QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_POWER_STATE_CONFIG1, 0x68), }; static const struct qmp_phy_init_tbl x1e80100_usb43dp_serdes_tbl[] = { From 7f719520897f8084ce6eab5a81f2c734abb20587 Mon Sep 17 00:00:00 2001 From: Jie Gan Date: Wed, 4 Nov 2026 17:40:45 +0800 Subject: [PATCH 1066/1133] QCLINUX: arm64: dts: qcom: nord-staging: Add TGU nodes Add the nord staging overlay with the TGU devices at 0x11a0e000, 0x11a0f000 and 0x11a10000, and build it as nord-staging.dtbo. Signed-off-by: Jie Gan --- arch/arm64/boot/dts/qcom/Makefile | 2 ++ arch/arm64/boot/dts/qcom/nord-staging.dtso | 35 ++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/nord-staging.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 8fb034a30e30c..17e1bed56df61 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -683,3 +683,5 @@ dtb-$(CONFIG_ARCH_QCOM) += sm8750-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += kaanapali-staging.dtbo dtb-$(CONFIG_ARCH_QCOM) += shikra-staging.dtbo + +dtb-$(CONFIG_ARCH_QCOM) += nord-staging.dtbo diff --git a/arch/arm64/boot/dts/qcom/nord-staging.dtso b/arch/arm64/boot/dts/qcom/nord-staging.dtso new file mode 100644 index 0000000000000..2c95662bd1fef --- /dev/null +++ b/arch/arm64/boot/dts/qcom/nord-staging.dtso @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Nord staging overlay - add staging-specific device tree modifications here. + */ + +/dts-v1/; +/plugin/; + +&soc { + tgu@11a0e000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11a0e000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@11a0f000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11a0f000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; + + tgu@11a10000 { + compatible = "qcom,tgu", "arm,primecell"; + reg = <0x0 0x11a10000 0x0 0x1000>; + + clocks = <&aoss_qmp>; + clock-names = "apb_pclk"; + }; +}; From 1ec6c248dd47b9233f588f01737bbf6ea999c588 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Thu, 5 Nov 2026 14:20:18 +0800 Subject: [PATCH 1067/1133] FROMLIST: Bluetooth: hci_qca: WCN3988: Drop baudrate change vendor event Firmware download on the WCN3988 sometimes fails and is retried: Bluetooth: hci0: QCA TLV response size mismatch Bluetooth: hci0: QCA Failed to request file: qca/apbtfw11.tlv (-84) The vendor event answering the baudrate change command can arrive late and is then taken as the response of the last firmware segment, which waits for any vendor event. Its length is 2 instead of the expected 3: < HCI Command: Vendor (0x3f|0x0000) plen 220 (last segment) > HCI Event: Vendor (0xff) plen 2 92 01 Drop and wait for this event on the WCN3988. Link: https://lore.kernel.org/all/20261104095026.3414666-1-shuai.zhang@oss.qualcomm.com/ Signed-off-by: Shuai Zhang Co-Authored-By: Claude Sonnet 5.5 --- drivers/bluetooth/hci_qca.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 211cb5e2d860b..74da369569c8b 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1524,6 +1524,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) } switch (soc_type) { + case QCA_WCN3988: case QCA_WCN3990: reinit_completion(&qca->drop_ev_comp); set_bit(QCA_DROP_VENDOR_EVENT, &qca->flags); @@ -1560,6 +1561,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) } switch (soc_type) { + case QCA_WCN3988: case QCA_WCN3990: /* Wait for the controller to send the vendor event * for the baudrate change command. From e0a9ffa7067605f0b1341d4f4b587c42e55890d4 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Sat, 26 Sep 2026 12:04:12 +0530 Subject: [PATCH 1068/1133] FROMLIST: arm64: dts: qcom: sm8750: Add Iris context bank subnodes The VPU issues DMA through several SMMU streams, and the hardware does not give every stream the same addressable range. The non-pixel stream cannot address the low 600MB of IOVA space, while the pixel stream can address the full range: +-----------------------------------------------------------+ | non-pixel stream addressable range (600 MB - 3.5 GB) | | 0x25800000 - 0xe0000000 | +-----------------------------------------------------------+ | pixel stream addressable range (0 - 3.5 GB) | | 0x00000000 - 0xe0000000 | +-----------------------------------------------------------+ A single "iommus" property on the video-codec node puts every stream in one IOMMU domain sharing one IOVA allocator, so nothing restricts a non-pixel buffer to avoid 0 to 600MB. Once an allocation lands below that boundary the hardware faults, which shows up as unhandled SMMU page faults and spontaneous reboots: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Given that the address range restriction is for specific VPU stream, it should be ideally be moved to that stream. To achieve the same, a subset of streams is now represented as subnodes, so that each can be associated with its respective addressable range. The design was discussed and agreed by mainatiners here https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org In the past, this limitation was addressed with an iommu-map approach, with the iris driver dynamically creating the devices. That approach was later concluded to be a hack to avoid having subnodes, and was NAKed by the iommu maintainers. It was discussed in detail here: https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org/ The video-codec node includes address-cells, size-cells and dma-ranges to declare 1:1 mapping for DMA translation to the parent. Link: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-9-0322ca5dc10c@oss.qualcomm.com/ Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index c9969b60ce806..b4df113e43908 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -3382,8 +3382,6 @@ "vcodec0_core_freerun"; dma-coherent; - iommus = <&apps_smmu 0x1940 0>, - <&apps_smmu 0x1947 0>; interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY &config_noc SLAVE_VENUS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, @@ -3416,6 +3414,10 @@ "core", "vcodec0_core"; + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0x0 0xe0000000>; + /* * IRIS firmware is signed by vendors, only * enable in boards where the proper signed firmware @@ -3423,6 +3425,15 @@ */ status = "disabled"; + non-pixel { + iommus = <&apps_smmu 0x1940 0x0>; + iommu-ranges = <0x25800000 0xba800000>; + }; + + pixel { + iommus = <&apps_smmu 0x1947 0x0>; + }; + iris_opp_table: opp-table { compatible = "operating-points-v2"; From 7508c2759a920179b0431b7696a248d602a27eed Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Wed, 4 Nov 2026 23:21:52 +0530 Subject: [PATCH 1069/1133] Revert "FROMLIST: arm64: dts: qcom: monaco: Move Iris IOMMUs to child nodes" This reverts commit e0c28678cf19a292bafc76460d035390ba4f5d5e. The reverted patch is replaced by "arm64: dts: qcom: monaco: Add Iris context bank subnodes", which is part of v5 sub-node series. It describes the per-stream IOVA limits of the VPU using the context bank sub-node design agreed with the maintainers from sub-node series v3 onwards. The dt-schema change for this has also been accepted upstream: https://github.com/devicetree-org/dt-schema/pull/207 Drop the earlier approach from sub-node series v2, so that only one version of the Iris IOMMU description is carried. As part of tech/mm/video being rebased on 7.4-rc1, the latest series of video patches are getting pulled in. This revert keeps the rebased tech/mm/video and the dt branches aligned together. Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/monaco.dtsi | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 22df6cfebf2dd..2d957d9ab96ed 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -847,10 +847,6 @@ reg = <0x0 0x9be82000 0x0 0x700000>; no-map; }; - - iris_resv: reservation-iris { - iommu-addresses = <&iris_non_pixel 0x0 0x0 0x0 0x25800000>; - }; }; smp2p-adsp { @@ -5475,22 +5471,12 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; + iommus = <&apps_smmu 0x0880 0x0400>, + <&apps_smmu 0x0887 0x0400>; dma-coherent; - #address-cells = <2>; - #size-cells = <2>; - status = "disabled"; - iris_non_pixel: non-pixel { - iommus = <&apps_smmu 0x0880 0x0400>; - memory-region = <&iris_resv>; - }; - - iris_pixel: pixel { - iommus = <&apps_smmu 0x0887 0x0400>; - }; - iris_opp_table: opp-table { compatible = "operating-points-v2"; From b132d5e94f4a3d112f09220ea528268a07a7b3cf Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Sat, 26 Sep 2026 12:04:10 +0530 Subject: [PATCH 1070/1133] FROMLIST: arm64: dts: qcom: monaco: Add Iris context bank subnodes The VPU issues DMA through several SMMU streams, and the hardware does not give every stream the same addressable range. The non-pixel stream cannot address the low 600MB of IOVA space, while the pixel stream can address the full range: +-----------------------------------------------------------+ | non-pixel stream addressable range (600 MB - 3.5 GB) | | 0x25800000 - 0xe0000000 | +-----------------------------------------------------------+ | pixel stream addressable range (0 - 3.5 GB) | | 0x00000000 - 0xe0000000 | +-----------------------------------------------------------+ A single "iommus" property on the video-codec node puts every stream in one IOMMU domain sharing one IOVA allocator, so nothing restricts a non-pixel buffer to avoid 0 to 600MB. Once an allocation lands below that boundary the hardware faults, which shows up as unhandled SMMU page faults and spontaneous reboots: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Given that the address range restriction is for specific VPU stream, it should be ideally be moved to that stream. To achieve the same, a subset of streams is now represented as subnodes, so that each can be associated with its respective addressable range. The design was discussed and agreed by mainatiners here https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org In the past, this limitation was addressed with an iommu-map approach, with the iris driver dynamically creating the devices. That approach was later concluded to be a hack to avoid having subnodes, and was NAKed by the iommu maintainers. It was discussed in detail here: https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org/ The video-codec node includes address-cells, size-cells and dma-ranges to declare 1:1 mapping for DMA translation to the parent. Link: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-11-0322ca5dc10c@oss.qualcomm.com/ Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Link: https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org --- arch/arm64/boot/dts/qcom/monaco.dtsi | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi index 2d957d9ab96ed..aa719538d012a 100644 --- a/arch/arm64/boot/dts/qcom/monaco.dtsi +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi @@ -5471,12 +5471,23 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x0880 0x0400>, - <&apps_smmu 0x0887 0x0400>; dma-coherent; + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0x0 0xe0000000>; + status = "disabled"; + non-pixel { + iommus = <&apps_smmu 0x0880 0x0400>; + iommu-ranges = <0x25800000 0xba800000>; + }; + + pixel { + iommus = <&apps_smmu 0x0887 0x0400>; + }; + iris_opp_table: opp-table { compatible = "operating-points-v2"; From d8b308aafb7cdf13d240cd10b5ef9ae69113cb4e Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Wed, 4 Nov 2026 23:18:09 +0530 Subject: [PATCH 1071/1133] Revert "FROMLIST: arm64: dts: qcom: lemans: Add Iris context bank subnodes" This reverts commit b7dcbc2ebd4c3ba7ca200f1ffaeb1d71458ac437. The reverted patch is replaced by "arm64: dts: qcom: lemans: Add Iris context bank subnodes", which is part of v5 sub-node series. It describes the per-stream IOVA limits of the VPU using the context bank sub-node design agreed with the maintainers from sub-node series v3 onwards. The dt-schema change for this has also been accepted upstream: https://github.com/devicetree-org/dt-schema/pull/207 Drop the earlier approach from sub-node series v2, so that only one version of the Iris IOMMU description is carried. As part of tech/mm/video being rebased on 7.4-rc1, the latest series of video patches are getting pulled in. This revert keeps the rebased tech/mm/video and the dt branches aligned together. Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/lemans.dtsi | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 939ef6552af79..709ee088ce398 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -898,10 +898,6 @@ reg = <0x0 0xdb200000 0x0 0x100000>; no-map; }; - - iris_resv: reservation-iris { - iommu-addresses = <&iris_non_pixel 0x0 0x0 0x0 0x25800000>; - }; }; smp2p-adsp { @@ -5034,23 +5030,12 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; + iommus = <&apps_smmu 0x0880 0x0400>, + <&apps_smmu 0x0887 0x0400>; dma-coherent; - #address-cells = <2>; - #size-cells = <2>; - dma-ranges; - status = "disabled"; - iris_non_pixel: non-pixel { - iommus = <&apps_smmu 0x0880 0x0400>; - memory-region = <&iris_resv>; - }; - - iris_pixel: pixel { - iommus = <&apps_smmu 0x0887 0x0400>; - }; - iris_opp_table: opp-table { compatible = "operating-points-v2"; From d0291c6f1b4a0ff657a0c463ff46c5b4c95c9404 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Sat, 26 Sep 2026 12:04:09 +0530 Subject: [PATCH 1072/1133] FROMLIST: arm64: dts: qcom: lemans: Add Iris context bank subnodes The VPU issues DMA through several SMMU streams, and the hardware does not give every stream the same addressable range. The non-pixel stream cannot address the low 600MB of IOVA space, while the pixel stream can address the full range: +-----------------------------------------------------------+ | non-pixel stream addressable range (600 MB - 3.5 GB) | | 0x25800000 - 0xe0000000 | +-----------------------------------------------------------+ | pixel stream addressable range (0 - 3.5 GB) | | 0x00000000 - 0xe0000000 | +-----------------------------------------------------------+ A single "iommus" property on the video-codec node puts every stream in one IOMMU domain sharing one IOVA allocator, so nothing restricts a non-pixel buffer to avoid 0 to 600MB. Once an allocation lands below that boundary the hardware faults, which shows up as unhandled SMMU page faults and spontaneous reboots: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Given that the address range restriction is for specific VPU stream, it should be ideally be moved to that stream. To achieve the same, a subset of streams is now represented as subnodes, so that each can be associated with its respective addressable range. The design was discussed and agreed by mainatiners here https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org In the past, this limitation was addressed with an iommu-map approach, with the iris driver dynamically creating the devices. That approach was later concluded to be a hack to avoid having subnodes, and was NAKed by the iommu maintainers. It was discussed in detail here: https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org/ The video-codec node includes address-cells, size-cells and dma-ranges to declare 1:1 mapping for DMA translation to the parent. Link: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-10-0322ca5dc10c@oss.qualcomm.com/ Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/lemans.dtsi | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 709ee088ce398..b4722197f1788 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -5030,12 +5030,23 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x0880 0x0400>, - <&apps_smmu 0x0887 0x0400>; dma-coherent; + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0x0 0xe0000000>; + status = "disabled"; + non-pixel { + iommus = <&apps_smmu 0x0880 0x0400>; + iommu-ranges = <0x25800000 0xba800000>; + }; + + pixel { + iommus = <&apps_smmu 0x0887 0x0400>; + }; + iris_opp_table: opp-table { compatible = "operating-points-v2"; From b566edfae812101c0d63965c746092099c083b42 Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Mon, 2 Nov 2026 20:31:43 +0530 Subject: [PATCH 1073/1133] Revert "FROMLIST: arm64: dts: qcom: hamoa: Move Iris IOMMUs to sub nodes" This reverts commit ed2db86860d4b3b2c1c743b70fd0622cf3521712. The reverted patch is replaced by "arm64: dts: qcom: hamoa: Add Iris context bank subnodes", which is part of v5 sub-node series. It describes the per-stream IOVA limits of the VPU using the context bank sub-node design agreed with the maintainers from sub-node series v3 onwards. The dt-schema change for this has also been accepted upstream: https://github.com/devicetree-org/dt-schema/pull/207 Drop the earlier approach from sub-node series v2, so that only one version of the Iris IOMMU description is carried. As part of tech/mm/video being rebased on 7.4-rc1, the latest series of video patches are getting pulled in. This revert keeps the rebased tech/mm/video and the dt branches aligned together. Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 48cc6c89b541a..ff62e97237b4f 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -869,10 +869,6 @@ hwlocks = <&tcsr_mutex 3>; no-map; }; - - iris_resv: reservation-iris { - iommu-addresses = <&iris_non_pixel 0x0 0x0 0x0 0x25800000>; - }; }; csiphy_mxc_opp_table: opp-table-mxc { @@ -5733,11 +5729,10 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; + iommus = <&apps_smmu 0x1940 0>, + <&apps_smmu 0x1947 0>; dma-coherent; - #address-cells = <2>; - #size-cells = <2>; - /* * IRIS firmware is signed by vendors, only * enable on boards where the proper signed firmware @@ -5745,15 +5740,6 @@ */ status = "disabled"; - iris_non_pixel: non-pixel { - iommus = <&apps_smmu 0x1940 0x0>; - memory-region = <&iris_resv>; - }; - - iris_pixel: pixel { - iommus = <&apps_smmu 0x1947 0x0>; - }; - iris_opp_table: opp-table { compatible = "operating-points-v2"; From 41f3035af5e3ed5df14f57fe9ddae12013a0c084 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Sat, 26 Sep 2026 12:04:07 +0530 Subject: [PATCH 1074/1133] FROMLIST: arm64: dts: qcom: hamoa: Add Iris context bank subnodes The VPU issues DMA through several SMMU streams, and the hardware does not give every stream the same addressable range. The non-pixel stream cannot address the low 600MB of IOVA space, while the pixel stream can address the full range: +-----------------------------------------------------------+ | non-pixel stream addressable range (600 MB - 3.5 GB) | | 0x25800000 - 0xe0000000 | +-----------------------------------------------------------+ | pixel stream addressable range (0 - 3.5 GB) | | 0x00000000 - 0xe0000000 | +-----------------------------------------------------------+ A single "iommus" property on the video-codec node puts every stream in one IOMMU domain sharing one IOVA allocator, so nothing restricts a non-pixel buffer to avoid 0 to 600MB. Once an allocation lands below that boundary the hardware faults, which shows up as unhandled SMMU page faults and spontaneous reboots: https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Given that the address range restriction is for specific VPU stream, it should be ideally be moved to that stream. To achieve the same, a subset of streams is now represented as subnodes, so that each can be associated with its respective addressable range. The design was discussed and agreed by mainatiners here https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org In the past, this limitation was addressed with an iommu-map approach, with the iris driver dynamically creating the devices. That approach was later concluded to be a hack to avoid having subnodes, and was NAKed by the iommu maintainers. It was discussed in detail here: https://lore.kernel.org/all/c7b956a9-d3e8-4e18-b780-5d08f5cd2ca1@kernel.org/ The video-codec node includes address-cells, size-cells and dma-ranges to declare 1:1 mapping for DMA translation to the parent. Link: https://lore.kernel.org/all/20260926-vpu_iommu_iova_handling-v5-8-0322ca5dc10c@oss.qualcomm.com/ Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index ff62e97237b4f..6d73af0e205a1 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -5729,10 +5729,12 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x1940 0>, - <&apps_smmu 0x1947 0>; dma-coherent; + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0x0 0xe0000000>; + /* * IRIS firmware is signed by vendors, only * enable on boards where the proper signed firmware @@ -5740,6 +5742,15 @@ */ status = "disabled"; + non-pixel { + iommus = <&apps_smmu 0x1940 0x0>; + iommu-ranges = <0x25800000 0xba800000>; + }; + + pixel { + iommus = <&apps_smmu 0x1947 0x0>; + }; + iris_opp_table: opp-table { compatible = "operating-points-v2"; From 899dffa402ff712c6247bb6fbc783743621d39c3 Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Tue, 3 Nov 2026 16:32:53 +0530 Subject: [PATCH 1075/1133] Revert "FROMLIST: arm64: dts: qcom: hawi: add iris video codec node" This reverts commit d1b68f8c7fb9e227e97321bebcaab6b5f947d284. The reverted patch is replaced by "arm64: dts: qcom: hawi: add iris video codec node", which is part of v5 sub-node series. It describes the per-stream IOVA limits of the VPU using the context bank sub-node design agreed with the maintainers from sub-node series v3 onwards. The dt-schema change for this has also been accepted upstream: https://github.com/devicetree-org/dt-schema/pull/207 Drop the earlier approach from sub-node series v2, so that only one version of the Iris IOMMU description is carried. As part of tech/mm/video being rebased on 7.4-rc1, the latest series of video patches are getting pulled in. This revert keeps the rebased tech/mm/video and the dt branches aligned together. Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/hawi.dtsi | 158 ----------------------------- 1 file changed, 158 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hawi.dtsi b/arch/arm64/boot/dts/qcom/hawi.dtsi index 60bf7366faaab..ab8ed2775cda9 100644 --- a/arch/arm64/boot/dts/qcom/hawi.dtsi +++ b/arch/arm64/boot/dts/qcom/hawi.dtsi @@ -445,10 +445,6 @@ no-map; }; - iris_resv: reservation-iris { - iommu-addresses = <&iris_non_pixel 0x0 0x0 0x0 0x32000000>; - }; - adsp_rpc_remote_heap_mem: adsp-rpc-remote-heap { compatible = "shared-dma-pool"; alloc-ranges = <0x0 0x0 0x1 0x0>; @@ -3455,160 +3451,6 @@ power-domains = <&gcc GCC_UFS_PHY_GDSC>; }; - iris: video-codec@2000000 { - compatible = "qcom,hawi-iris"; - reg = <0x0 0x02000000 0x0 0xf0000>; - - interrupts = ; - - power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, - <&videocc VIDEO_CC_MVS0_GDSC>, - <&rpmhpd RPMHPD_MXC>, - <&rpmhpd RPMHPD_MMCX>, - <&videocc VIDEO_CC_MVS0_VPP0_GDSC>, - <&videocc VIDEO_CC_MVS0_VPP1_GDSC>, - <&videocc VIDEO_CC_MVS0A_GDSC>, - <&videocc VIDEO_CC_MM_INT_GDSC>, - <&videocc VIDEO_CC_AXI0_CX_INT_GDSC>; - power-domain-names = "venus", - "vcodec0", - "mxc", - "mmcx", - "vpp0", - "vpp1", - "apv", - "mm-int", - "cx-int"; - - clocks = <&gcc GCC_VIDEO_AXI0_CLK>, - <&gcc GCC_VIDEO_AXI0C_CLK>, - <&videocc VIDEO_CC_MVS0C_CLK>, - <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, - <&videocc VIDEO_CC_MVS0C_CTL_FREERUN_CLK>, - <&videocc VIDEO_CC_MVS0C_DEBUG_CLK>, - <&videocc VIDEO_CC_CX_AXI0_CLK>, - <&videocc VIDEO_CC_MVS0_CLK>, - <&videocc VIDEO_CC_MVS0_VPP0_CLK>, - <&videocc VIDEO_CC_MVS0_VPP1_CLK>, - <&videocc VIDEO_CC_MVS0_VPP0_VPP1_GATING_CLK>, - <&videocc VIDEO_CC_MVS0A_CLK>, - <&videocc VIDEO_CC_MVS0B_CLK>; - clock-names = "iface", - "ifacec", - "core", - "core_freerun", - "core_ctl_freerun", - "core_debug", - "cx_iface", - "vcodec0_core", - "vcodec_vpp0", - "vcodec_vpp1", - "vcodec_vpp0_vpp1_gating", - "vcodec_apv", - "vcodec_bse"; - - operating-points-v2 = <&iris_opp_table>; - - interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY - &config_noc SLAVE_IRIS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, - <&mmss_noc MASTER_VIDEO_MVP QCOM_ICC_TAG_ALWAYS - &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; - interconnect-names = "cpu-cfg", - "video-mem"; - - memory-region = <&video_mem>; - - resets = <&gcc GCC_VIDEO_AXI0C_CLK_ARES>, - <&videocc VIDEO_CC_MVS0C_CTL_FREERUN_CLK_ARES>; - reset-names = "bus0", - "core"; - - dma-coherent; - - #address-cells = <2>; - #size-cells = <2>; - - status = "disabled"; - - iris_non_pixel: non-pixel { - iommus = <&apps_smmu 0x1540 0x0000>, - <&apps_smmu 0x1620 0x0000>, - <&apps_smmu 0x1544 0x0000>; - memory-region = <&iris_resv>; - }; - - iris_pixel: pixel { - iommus = <&apps_smmu 0x1543 0x0000>; - }; - - iris_opp_table: opp-table { - compatible = "operating-points-v2"; - - opp-150000000 { - opp-hz = /bits/ 64 <150000000 150000000 - 150000000 225000000>; - required-opps = <&rpmhpd_opp_low_svs_d2>, - <&rpmhpd_opp_low_svs_d2>; - }; - - opp-285000000 { - opp-hz = /bits/ 64 <285000000 240000000 - 240000000 360000000>; - required-opps = <&rpmhpd_opp_low_svs>, - <&rpmhpd_opp_low_svs_d0>; - }; - - opp-338000000 { - opp-hz = /bits/ 64 <338000000 338000000 - 338000000 507000000>; - required-opps = <&rpmhpd_opp_low_svs>, - <&rpmhpd_opp_low_svs>; - }; - - opp-420000000 { - opp-hz = /bits/ 64 <420000000 420000000 - 420000000 630000000>; - required-opps = <&rpmhpd_opp_svs_l1>, - <&rpmhpd_opp_svs>; - }; - - opp-444000000 { - opp-hz = /bits/ 64 <444000000 444000000 - 444000000 666000000>; - required-opps = <&rpmhpd_opp_svs_l1>, - <&rpmhpd_opp_svs_l1>; - }; - - opp-560000000 { - opp-hz = /bits/ 64 <560000000 533000000 - 533000000 800000000>; - required-opps = <&rpmhpd_opp_svs_l1>, - <&rpmhpd_opp_nom>; - }; - - opp-630000000 { - opp-hz = /bits/ 64 <630000000 630000000 - 630000000 1104000000>; - required-opps = <&rpmhpd_opp_nom>, - <&rpmhpd_opp_turbo>; - }; - - opp-800000000 { - opp-hz = /bits/ 64 <800000000 710000000 - 710000000 1260000000>; - required-opps = <&rpmhpd_opp_turbo>, - <&rpmhpd_opp_turbo_l1>; - }; - - opp-1000000000 { - opp-hz = /bits/ 64 <1000000000 710000000 - 850000000 1260000000>; - required-opps = <&rpmhpd_opp_turbo>, - <&rpmhpd_opp_turbo_l3>; - }; - }; - }; - videocc: clock-controller@20f0000 { compatible = "qcom,hawi-videocc"; reg = <0x0 0x020f0000 0x0 0x10000>; From f7bc734febd8b06c310d5098b13fa0681f644f80 Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 11:27:56 +0800 Subject: [PATCH 1076/1133] FROMLIST: arm64: dts: qcom: hawi: add iris video codec node Add the iris video codec device node for the hawi SoC, describing the register space, interrupt, nine power domains (including the VPU5x-specific mm-int and cx-int domains), thirteen clocks, two interconnect paths for CPU config and video memory bandwidth, IOMMU mappings, and the operating point table covering 150 MHz through 1000 MHz. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_hawi-v2-6-016ec3d24b79@oss.qualcomm.com/ Signed-off-by: Wangao Wang Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio --- arch/arm64/boot/dts/qcom/hawi.dtsi | 155 +++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hawi.dtsi b/arch/arm64/boot/dts/qcom/hawi.dtsi index ab8ed2775cda9..c3a52fc35fe76 100644 --- a/arch/arm64/boot/dts/qcom/hawi.dtsi +++ b/arch/arm64/boot/dts/qcom/hawi.dtsi @@ -3451,6 +3451,161 @@ power-domains = <&gcc GCC_UFS_PHY_GDSC>; }; + iris: video-codec@2000000 { + compatible = "qcom,hawi-iris"; + reg = <0x0 0x02000000 0x0 0xf0000>; + + interrupts = ; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc VIDEO_CC_MVS0_VPP0_GDSC>, + <&videocc VIDEO_CC_MVS0_VPP1_GDSC>, + <&videocc VIDEO_CC_MVS0A_GDSC>, + <&videocc VIDEO_CC_MM_INT_GDSC>, + <&videocc VIDEO_CC_AXI0_CX_INT_GDSC>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vpp0", + "vpp1", + "apv", + "mm-int", + "cx-int"; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&gcc GCC_VIDEO_AXI0C_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0C_CTL_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0C_DEBUG_CLK>, + <&videocc VIDEO_CC_CX_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&videocc VIDEO_CC_MVS0_VPP0_CLK>, + <&videocc VIDEO_CC_MVS0_VPP1_CLK>, + <&videocc VIDEO_CC_MVS0_VPP0_VPP1_GATING_CLK>, + <&videocc VIDEO_CC_MVS0A_CLK>, + <&videocc VIDEO_CC_MVS0B_CLK>; + clock-names = "iface", + "ifacec", + "core", + "core_freerun", + "core_ctl_freerun", + "core_debug", + "cx_iface", + "vcodec0_core", + "vcodec_vpp0", + "vcodec_vpp1", + "vcodec_vpp0_vpp1_gating", + "vcodec_apv", + "vcodec_bse"; + + operating-points-v2 = <&iris_opp_table>; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_IRIS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_VIDEO_MVP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + memory-region = <&video_mem>; + + resets = <&gcc GCC_VIDEO_AXI0C_CLK_ARES>, + <&videocc VIDEO_CC_MVS0C_CTL_FREERUN_CLK_ARES>; + reset-names = "bus0", + "core"; + + dma-coherent; + + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0x0 0xffc00000>; + + status = "disabled"; + + iris_non_pixel: non-pixel { + iommus = <&apps_smmu 0x1540 0x0000>, + <&apps_smmu 0x1620 0x0000>, + <&apps_smmu 0x1544 0x0000>; + iommu-ranges = <0x32000000 0xcdc00000>; + }; + + iris_pixel: pixel { + iommus = <&apps_smmu 0x1543 0x0000>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-150000000 { + opp-hz = /bits/ 64 <150000000 150000000 + 150000000 225000000>; + required-opps = <&rpmhpd_opp_low_svs_d2>, + <&rpmhpd_opp_low_svs_d2>; + }; + + opp-285000000 { + opp-hz = /bits/ 64 <285000000 240000000 + 240000000 360000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs_d0>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 + 338000000 507000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-420000000 { + opp-hz = /bits/ 64 <420000000 420000000 + 420000000 630000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 + 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-560000000 { + opp-hz = /bits/ 64 <560000000 533000000 + 533000000 800000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_nom>; + }; + + opp-630000000 { + opp-hz = /bits/ 64 <630000000 630000000 + 630000000 1104000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo>; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000 710000000 + 710000000 1260000000>; + required-opps = <&rpmhpd_opp_turbo>, + <&rpmhpd_opp_turbo_l1>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000 710000000 + 850000000 1260000000>; + required-opps = <&rpmhpd_opp_turbo>, + <&rpmhpd_opp_turbo_l3>; + }; + }; + }; + videocc: clock-controller@20f0000 { compatible = "qcom,hawi-videocc"; reg = <0x0 0x020f0000 0x0 0x10000>; From 2c95b505b17baf365eabdcd4f8fa256d3fddbe2f Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Thu, 29 Oct 2026 11:47:26 +0800 Subject: [PATCH 1077/1133] FROMLIST: arm64: dts: qcom: nord: Add display subsystem nodes Add the MDSS, DPU, DP controller and eDP PHY nodes for the Qualcomm Nord SoC. Nord has two independent display subsystems, MDSS0 at 0xae00000 and MDSS1 at 0x8c00000, each with two DP controllers and two eDP PHYs. Nord is DP-only, so no DSI nodes are added. Wire the DP PHY outputs into the dispcc0 and dispcc1 clock inputs, which were previously stubbed with zeroes, and add the eDP0-3 hot-plug-detect pinctrl states. Signed-off-by: Ritesh Kumar Signed-off-by: Nabige Aala Tested-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261029034728.633495-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 407 +++++++++++++++++++- arch/arm64/boot/dts/qcom/nord.dtsi | 264 +++++++++++++ 2 files changed, 663 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 1f639b898e3d3..81a0195aadc37 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -381,6 +381,373 @@ pinctrl-names = "default"; }; +&mdss0 { + power-domains = <&dispcc0 MDSS_DISP_CC_MDSS_CORE_GDSC>; + + clocks = <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&nwgcc NW_GCC_DISP_0_HF_AXI_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_MDP_CLK>; + + resets = <&dispcc0 MDSS_DISP_CC_MDSS_CORE_BCR>; + + interconnects = <&mmss_noc MASTER_MDP0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "mdp0-mem", + "cpu-cfg"; + + mdss0_dp0_phy: phy@fc3a00 { + compatible = "qcom,nord-dp-phy"; + reg = <0x0 0x0fc3a00 0x0 0x1d0>, + <0x0 0x0fc3200 0x0 0x128>, + <0x0 0x0fc3600 0x0 0x128>, + <0x0 0x0fc3000 0x0 0x200>; + + clocks = <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&tcsrcc TCSR_DP_TX_0_CLKREF_EN>; + clock-names = "aux", + "cfg_ahb", + "ref"; + + #clock-cells = <1>; + #phy-cells = <0>; + + power-domains = <&rpmhpd RPMHPD_MX>; + + status = "disabled"; + }; + + mdss0_dp1_phy: phy@fc6a00 { + compatible = "qcom,nord-dp-phy"; + reg = <0x0 0x0fc6a00 0x0 0x200>, + <0x0 0x0fc6200 0x0 0xd0>, + <0x0 0x0fc6600 0x0 0xd0>, + <0x0 0x0fc6000 0x0 0x1c8>; + + clocks = <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_AUX_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&tcsrcc TCSR_DP_TX_1_CLKREF_EN>; + clock-names = "aux", + "cfg_ahb", + "ref"; + + #clock-cells = <1>; + #phy-cells = <0>; + + power-domains = <&rpmhpd RPMHPD_MX>; + + status = "disabled"; + }; +}; + +&mdss0_mdp { + clocks = <&nwgcc NW_GCC_DISP_0_HF_AXI_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_MDP_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "nrt_bus", + "iface", + "lut", + "core", + "vsync"; + + assigned-clocks = <&dispcc0 MDSS_DISP_CC_MDSS_VSYNC_CLK>; + assigned-clock-rates = <19200000>; + + operating-points-v2 = <&mdp_opp_table>; + + power-domains = <&rpmhpd RPMHPD_MMCX>; + + mdp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-417000000 { + opp-hz = /bits/ 64 <417000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-532000000 { + opp-hz = /bits/ 64 <532000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + + opp-710000000 { + opp-hz = /bits/ 64 <710000000>; + required-opps = <&rpmhpd_opp_turbo_l1>; + }; + }; +}; + +&mdss0_dp0 { + clocks = <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_LINK_INTF_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL1_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL2_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL3_CLK>; + clock-names = "core_iface", + "core_aux", + "ctrl_link", + "ctrl_link_iface", + "stream_pixel", + "stream_1_pixel", + "stream_2_pixel", + "stream_3_pixel"; + + assigned-clocks = <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL1_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL2_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL3_CLK_SRC>; + assigned-clock-parents = <&mdss0_dp0_phy 0>, + <&mdss0_dp0_phy 1>, + <&mdss0_dp0_phy 1>, + <&mdss0_dp0_phy 1>, + <&mdss0_dp0_phy 1>; + + phys = <&mdss0_dp0_phy>; + phy-names = "dp"; + + operating-points-v2 = <&dp_opp_table>; + + power-domains = <&rpmhpd RPMHPD_MMCX>; + + pinctrl-0 = <&dp0_hot_plug_det>; + pinctrl-names = "default"; + + dp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-162000000 { + opp-hz = /bits/ 64 <162000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-270000000 { + opp-hz = /bits/ 64 <270000000>; + required-opps = <&rpmhpd_opp_low_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>; + }; + }; +}; + +&mdss0_dp1 { + clocks = <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_AUX_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_LINK_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_LINK_INTF_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL0_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL1_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL2_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL3_CLK>; + clock-names = "core_iface", + "core_aux", + "ctrl_link", + "ctrl_link_iface", + "stream_pixel", + "stream_1_pixel", + "stream_2_pixel", + "stream_3_pixel"; + + assigned-clocks = <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_LINK_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL0_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL1_CLK_SRC>; + assigned-clock-parents = <&mdss0_dp1_phy 0>, + <&mdss0_dp1_phy 1>, + <&mdss0_dp1_phy 1>; + + phys = <&mdss0_dp1_phy>; + phy-names = "dp"; + + operating-points-v2 = <&dp_opp_table>; + + power-domains = <&rpmhpd RPMHPD_MMCX>; + + pinctrl-0 = <&dp1_hot_plug_det>; + pinctrl-names = "default"; +}; + +&mdss1 { + power-domains = <&dispcc1 MDSS_DISP_CC_MDSS_CORE_GDSC>; + + clocks = <&dispcc1 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&nwgcc NW_GCC_DISP_1_HF_AXI_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_MDP_CLK>; + + resets = <&dispcc1 MDSS_DISP_CC_MDSS_CORE_BCR>; + + interconnects = <&mmss_noc MASTER_MDP1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_DISPLAY_1_CFG QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "mdp0-mem", + "cpu-cfg"; + + mdss1_dp0_phy: phy@fc9a00 { + compatible = "qcom,nord-dp-phy"; + reg = <0x0 0x0fc9a00 0x0 0x1d0>, + <0x0 0x0fc9200 0x0 0x128>, + <0x0 0x0fc9600 0x0 0x128>, + <0x0 0x0fc9000 0x0 0x200>; + + clocks = <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&tcsrcc TCSR_DP_TX_2_CLKREF_EN>; + clock-names = "aux", + "cfg_ahb", + "ref"; + + #clock-cells = <1>; + #phy-cells = <0>; + + power-domains = <&rpmhpd RPMHPD_MX>; + + status = "disabled"; + }; + + mdss1_dp1_phy: phy@fcca00 { + compatible = "qcom,nord-dp-phy"; + reg = <0x0 0x0fcca00 0x0 0x200>, + <0x0 0x0fcc200 0x0 0xd0>, + <0x0 0x0fcc600 0x0 0xd0>, + <0x0 0x0fcc000 0x0 0x1c8>; + + clocks = <&dispcc1 MDSS_DISP_CC_MDSS_DPTX1_AUX_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&tcsrcc TCSR_DP_TX_3_CLKREF_EN>; + clock-names = "aux", + "cfg_ahb", + "ref"; + + #clock-cells = <1>; + #phy-cells = <0>; + + power-domains = <&rpmhpd RPMHPD_MX>; + + status = "disabled"; + }; +}; + +&mdss1_mdp { + clocks = <&nwgcc NW_GCC_DISP_1_HF_AXI_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_MDP_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "nrt_bus", + "iface", + "lut", + "core", + "vsync"; + + assigned-clocks = <&dispcc1 MDSS_DISP_CC_MDSS_VSYNC_CLK>; + assigned-clock-rates = <19200000>; + + operating-points-v2 = <&mdp_opp_table>; + + power-domains = <&rpmhpd RPMHPD_MMCX>; +}; + +&mdss1_dp0 { + clocks = <&dispcc1 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_LINK_INTF_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_PIXEL1_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_PIXEL2_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_PIXEL3_CLK>; + clock-names = "core_iface", + "core_aux", + "ctrl_link", + "ctrl_link_iface", + "stream_pixel", + "stream_1_pixel", + "stream_2_pixel", + "stream_3_pixel"; + + assigned-clocks = <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK_SRC>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_PIXEL1_CLK_SRC>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_PIXEL2_CLK_SRC>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX0_PIXEL3_CLK_SRC>; + assigned-clock-parents = <&mdss1_dp0_phy 0>, + <&mdss1_dp0_phy 1>, + <&mdss1_dp0_phy 1>, + <&mdss1_dp0_phy 1>, + <&mdss1_dp0_phy 1>; + + phys = <&mdss1_dp0_phy>; + phy-names = "dp"; + + operating-points-v2 = <&dp_opp_table>; + + power-domains = <&rpmhpd RPMHPD_MMCX>; + + pinctrl-0 = <&dp2_hot_plug_det>; + pinctrl-names = "default"; +}; + +&mdss1_dp1 { + clocks = <&dispcc1 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX1_AUX_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX1_LINK_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX1_LINK_INTF_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX1_PIXEL0_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX1_PIXEL1_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX1_PIXEL2_CLK>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX1_PIXEL3_CLK>; + clock-names = "core_iface", + "core_aux", + "ctrl_link", + "ctrl_link_iface", + "stream_pixel", + "stream_1_pixel", + "stream_2_pixel", + "stream_3_pixel"; + + assigned-clocks = <&dispcc1 MDSS_DISP_CC_MDSS_DPTX1_LINK_CLK_SRC>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX1_PIXEL0_CLK_SRC>, + <&dispcc1 MDSS_DISP_CC_MDSS_DPTX1_PIXEL1_CLK_SRC>; + assigned-clock-parents = <&mdss1_dp1_phy 0>, + <&mdss1_dp1_phy 1>, + <&mdss1_dp1_phy 1>; + + phys = <&mdss1_dp1_phy>; + phy-names = "dp"; + + operating-points-v2 = <&dp_opp_table>; + + power-domains = <&rpmhpd RPMHPD_MMCX>; + + pinctrl-0 = <&dp3_hot_plug_det>; + pinctrl-names = "default"; +}; + &pcie0 { clocks = <&gcc GCC_PCIE_A_AUX_CLK>, <&gcc GCC_PCIE_A_CFG_AHB_CLK>, @@ -1929,10 +2296,10 @@ <0>, <0>, <0>, - <0>, - <0>, - <0>, - <0>, + <&mdss1_dp0_phy 0>, + <&mdss1_dp0_phy 1>, + <&mdss1_dp1_phy 0>, + <&mdss1_dp1_phy 1>, <0>, <0>, <0>, @@ -1997,10 +2364,10 @@ <0>, <0>, <0>, - <0>, - <0>, - <0>, - <0>, + <&mdss0_dp0_phy 0>, + <&mdss0_dp0_phy 1>, + <&mdss0_dp1_phy 0>, + <&mdss0_dp1_phy 1>, <0>, <0>, <0>, @@ -2163,6 +2530,30 @@ bias-disable; }; + dp0_hot_plug_det: dp0-hot-plug-det-state { + pins = "gpio51"; + function = "edp0_hot"; + bias-disable; + }; + + dp1_hot_plug_det: dp1-hot-plug-det-state { + pins = "gpio52"; + function = "edp1_hot"; + bias-disable; + }; + + dp2_hot_plug_det: dp2-hot-plug-det-state { + pins = "gpio53"; + function = "edp2_hot"; + bias-disable; + }; + + dp3_hot_plug_det: dp3-hot-plug-det-state { + pins = "gpio54"; + function = "edp3_hot"; + bias-disable; + }; + pcie0_default: pcie0-default-state { wake-pins { pins = "gpio0"; diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 4f288613464d3..3cd7fecdcae73 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -2433,6 +2433,138 @@ }; }; + mdss1: display-subsystem@8c00000 { + compatible = "qcom,nord-mdss"; + reg = <0x0 0x08c00000 0x0 0x1000>; + reg-names = "mdss"; + + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + iommus = <&apps_smmu_1 0x400 0x2>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + mdss1_mdp: display-controller@8c01000 { + compatible = "qcom,nord-dpu"; + reg = <0x0 0x08c01000 0x0 0x8f000>, + <0x0 0x08cb0000 0x0 0x3000>; + reg-names = "mdp", + "vbif"; + + interrupt-parent = <&mdss1>; + interrupts = <0>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + dpu1_intf0_out: endpoint { + remote-endpoint = <&mdss1_dp0_in>; + }; + }; + + port@1 { + reg = <1>; + + dpu1_intf4_out: endpoint { + remote-endpoint = <&mdss1_dp1_in>; + }; + }; + }; + }; + + mdss1_dp0: displayport-controller@8d54000 { + compatible = "qcom,nord-dp"; + reg = <0x0 0x08d54000 0x0 0x200>, + <0x0 0x08d54200 0x0 0x200>, + <0x0 0x08d55000 0x0 0xc00>, + <0x0 0x08d56000 0x0 0x400>, + <0x0 0x08d57000 0x0 0x400>, + <0x0 0x08d58000 0x0 0x400>, + <0x0 0x08d59000 0x0 0x400>, + <0x0 0x08d5a000 0x0 0x600>, + <0x0 0x08d5b000 0x0 0x600>; + + interrupts-extended = <&mdss1 12>; + + #sound-dai-cells = <0>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + mdss1_dp0_in: endpoint { + remote-endpoint = <&dpu1_intf0_out>; + }; + }; + + port@1 { + reg = <1>; + + mdss1_dp0_out: endpoint { + }; + }; + }; + }; + + mdss1_dp1: displayport-controller@8d5c000 { + compatible = "qcom,nord-dp"; + reg = <0x0 0x08d5c000 0x0 0x200>, + <0x0 0x08d5c200 0x0 0x200>, + <0x0 0x08d5d000 0x0 0xc00>, + <0x0 0x08d5e000 0x0 0x400>, + <0x0 0x08d5f000 0x0 0x400>, + <0x0 0x08d60000 0x0 0x400>, + <0x0 0x08d61000 0x0 0x400>, + <0x0 0x08d62000 0x0 0x600>, + <0x0 0x08d63000 0x0 0x600>; + + interrupts-extended = <&mdss1 13>; + + #sound-dai-cells = <0>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + mdss1_dp1_in: endpoint { + remote-endpoint = <&dpu1_intf4_out>; + }; + }; + + port@1 { + reg = <1>; + + mdss1_dp1_out: endpoint { + }; + }; + }; + }; + }; + ipcc0: mailbox@9007000 { compatible = "qcom,nord-ipcc", "qcom,ipcc"; @@ -2593,6 +2725,138 @@ status = "disabled"; }; + mdss0: display-subsystem@ae00000 { + compatible = "qcom,nord-mdss"; + reg = <0x0 0x0ae00000 0x0 0x1000>; + reg-names = "mdss"; + + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + iommus = <&apps_smmu_1 0x3e0 0x2>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + status = "disabled"; + + mdss0_mdp: display-controller@ae01000 { + compatible = "qcom,nord-dpu"; + reg = <0x0 0x0ae01000 0x0 0x8f000>, + <0x0 0x0aeb0000 0x0 0x3000>; + reg-names = "mdp", + "vbif"; + + interrupt-parent = <&mdss0>; + interrupts = <0>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + dpu_intf0_out: endpoint { + remote-endpoint = <&mdss0_dp0_in>; + }; + }; + + port@1 { + reg = <1>; + + dpu_intf4_out: endpoint { + remote-endpoint = <&mdss0_dp1_in>; + }; + }; + }; + }; + + mdss0_dp0: displayport-controller@af54000 { + compatible = "qcom,nord-dp"; + reg = <0x0 0x0af54000 0x0 0x200>, + <0x0 0x0af54200 0x0 0x200>, + <0x0 0x0af55000 0x0 0xc00>, + <0x0 0x0af56000 0x0 0x400>, + <0x0 0x0af57000 0x0 0x400>, + <0x0 0x0af58000 0x0 0x400>, + <0x0 0x0af59000 0x0 0x400>, + <0x0 0x0af5a000 0x0 0x600>, + <0x0 0x0af5b000 0x0 0x600>; + + interrupts-extended = <&mdss0 12>; + + #sound-dai-cells = <0>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + mdss0_dp0_in: endpoint { + remote-endpoint = <&dpu_intf0_out>; + }; + }; + + port@1 { + reg = <1>; + + mdss0_dp0_out: endpoint { + }; + }; + }; + }; + + mdss0_dp1: displayport-controller@af5c000 { + compatible = "qcom,nord-dp"; + reg = <0x0 0x0af5c000 0x0 0x200>, + <0x0 0x0af5c200 0x0 0x200>, + <0x0 0x0af5d000 0x0 0xc00>, + <0x0 0x0af5e000 0x0 0x400>, + <0x0 0x0af5f000 0x0 0x400>, + <0x0 0x0af60000 0x0 0x400>, + <0x0 0x0af61000 0x0 0x400>, + <0x0 0x0af62000 0x0 0x600>, + <0x0 0x0af63000 0x0 0x600>; + + interrupts-extended = <&mdss0 13>; + + #sound-dai-cells = <0>; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + mdss0_dp1_in: endpoint { + remote-endpoint = <&dpu_intf4_out>; + }; + }; + + port@1 { + reg = <1>; + + mdss0_dp1_out: endpoint { + }; + }; + }; + }; + }; + pdc: interrupt-controller@b220000 { compatible = "qcom,nord-pdc", "qcom,pdc"; From f53053f61c12d179027a637f92c468837a78c3d9 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Thu, 29 Oct 2026 11:47:27 +0800 Subject: [PATCH 1078/1133] FROMLIST: arm64: dts: qcom: nord-ride-embedded: Enable eDP0-3 display output Enable both MDSS instances, the four DP controllers and the eDP0-3 PHYs on the Nord Ride Embedded board and describe the eDP0-3 connectors, their 4 data lanes and supported link frequencies. Signed-off-by: Ritesh Kumar Signed-off-by: Nabige Aala Reviewed-by: Konrad Dybcio Tested-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261029034728.633495-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- .../boot/dts/qcom/nord-ride-embedded.dts | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index 906c3b0bd12a6..b743d62788660 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -57,6 +57,54 @@ }; }; + dp0_connector: connector-dp0 { + compatible = "dp-connector"; + label = "eDP0"; + type = "full-size"; + + port { + dp0_connector_in: endpoint { + remote-endpoint = <&mdss0_dp0_out>; + }; + }; + }; + + dp1_connector: connector-dp1 { + compatible = "dp-connector"; + label = "eDP1"; + type = "full-size"; + + port { + dp1_connector_in: endpoint { + remote-endpoint = <&mdss0_dp1_out>; + }; + }; + }; + + dp2_connector: connector-dp2 { + compatible = "dp-connector"; + label = "eDP2"; + type = "full-size"; + + port { + dp2_connector_in: endpoint { + remote-endpoint = <&mdss1_dp0_out>; + }; + }; + }; + + dp3_connector: connector-dp3 { + compatible = "dp-connector"; + label = "eDP3"; + type = "full-size"; + + port { + dp3_connector_in: endpoint { + remote-endpoint = <&mdss1_dp1_out>; + }; + }; + }; + /* * MAX9892 click-and-pop suppressors on the PCM1681 line outputs. All * three parts are muted by a single CLICK_POP_MUTE_N line, so describe @@ -743,6 +791,82 @@ }; }; +&mdss0 { + status = "okay"; +}; + +&mdss0_dp0 { + status = "okay"; +}; + +&mdss0_dp0_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + remote-endpoint = <&dp0_connector_in>; +}; + +&mdss0_dp0_phy { + vdda-phy-supply = <&vreg_l2h_1p2>; + vdda-pll-supply = <&vreg_l1h_0p9>; + + status = "okay"; +}; + +&mdss0_dp1 { + status = "okay"; +}; + +&mdss0_dp1_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + remote-endpoint = <&dp1_connector_in>; +}; + +&mdss0_dp1_phy { + vdda-phy-supply = <&vreg_l2h_1p2>; + vdda-pll-supply = <&vreg_l1h_0p9>; + + status = "okay"; +}; + +&mdss1 { + status = "okay"; +}; + +&mdss1_dp0 { + status = "okay"; +}; + +&mdss1_dp0_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + remote-endpoint = <&dp2_connector_in>; +}; + +&mdss1_dp0_phy { + vdda-phy-supply = <&vreg_l2h_1p2>; + vdda-pll-supply = <&vreg_l1h_0p9>; + + status = "okay"; +}; + +&mdss1_dp1 { + status = "okay"; +}; + +&mdss1_dp1_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + remote-endpoint = <&dp3_connector_in>; +}; + +&mdss1_dp1_phy { + vdda-phy-supply = <&vreg_l2h_1p2>; + vdda-pll-supply = <&vreg_l1h_0p9>; + + status = "okay"; +}; + &pmau0102_i_gpios { usb_pd_int_default: usb-pd-int-state { pins = "gpio8"; From e6f2f8984c3dc69c21a0039d99e08b05bc976e01 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Thu, 29 Oct 2026 11:47:28 +0800 Subject: [PATCH 1079/1133] FROMLIST: arm64: dts: qcom: nord-rrd: Enable eDP0/1 display output Enable the MDSS, DP0/1 controllers and eDP0/1 PHYs on the Nord RRD board and describe the eDP0/1 connector, its 4 data lanes and supported link frequencies. Signed-off-by: Ritesh Kumar Signed-off-by: Nabige Aala Reviewed-by: Konrad Dybcio Tested-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261029034728.633495-4-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 62 +++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index 597c5b9cf6364..560e7c4f5729d 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -57,6 +57,30 @@ }; }; + dp0_connector: connector-dp0 { + compatible = "dp-connector"; + label = "eDP0"; + type = "full-size"; + + port { + dp0_connector_in: endpoint { + remote-endpoint = <&mdss0_dp0_out>; + }; + }; + }; + + dp1_connector: connector-dp1 { + compatible = "dp-connector"; + label = "eDP1"; + type = "full-size"; + + port { + dp1_connector_in: endpoint { + remote-endpoint = <&mdss0_dp1_out>; + }; + }; + }; + /* * MAX9892 click-and-pop suppressors on the PCM1681 line outputs. Both * parts are muted by a single CLICK_POP_MUTE_N line, so describe them @@ -690,6 +714,44 @@ }; }; +&mdss0 { + status = "okay"; +}; + +&mdss0_dp0 { + status = "okay"; +}; + +&mdss0_dp0_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + remote-endpoint = <&dp0_connector_in>; +}; + +&mdss0_dp0_phy { + vdda-phy-supply = <&vreg_l2h_1p2>; + vdda-pll-supply = <&vreg_l1h_0p9>; + + status = "okay"; +}; + +&mdss0_dp1 { + status = "okay"; +}; + +&mdss0_dp1_out { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + remote-endpoint = <&dp1_connector_in>; +}; + +&mdss0_dp1_phy { + vdda-phy-supply = <&vreg_l2h_1p2>; + vdda-pll-supply = <&vreg_l1h_0p9>; + + status = "okay"; +}; + &pmau0102_i_gpios { usb_pd_int_default: usb-pd-int-state { pins = "gpio8"; From ce17c6decdde282fe1c1a69d78f418b7fc0f4b27 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Sun, 20 Sep 2026 17:10:51 +0800 Subject: [PATCH 1080/1133] FROMLIST: arm64: dts: qcom: nord: Add camss node Add the camera subsystem node for the Nord SoC with its 5 CSIPHY, 3 CSID plus 10 CSID lite and 3 IFE plus 10 IFE lite blocks, along with their clocks, interrupts, interconnects, SMMU stream IDs and power domains. Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/r/20260920091053.2214965-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 64 +++++++++++ arch/arm64/boot/dts/qcom/nord.dtsi | 121 ++++++++++++++++++++ 2 files changed, 185 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 81a0195aadc37..592a750cec271 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -77,6 +77,70 @@ status = "okay"; }; +&camss { + clocks = <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&nwgcc NW_GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_TOP_AHB_CLK>, + <&camcc CAM_CC_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_TOP_IFE_0_CLK>, + <&camcc CAM_CC_TOP_IFE_1_CLK>, + <&camcc CAM_CC_TOP_IFE_2_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_0_MAIN_CLK>, + <&camcc CAM_CC_IFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_MAIN_CLK>, + <&camcc CAM_CC_IFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_2_MAIN_CLK>, + <&camcc CAM_CC_IFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_TPG_CSIPHY_RX_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_rt_axi", + "csid", + "csid_csiphy_rx", + "gcc_axi_hf", + "top_ahb", + "top_fast_ahb", + "top_ife0", + "top_ife1", + "top_ife2", + "top_ife_lite", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "tpg_csiphy_rx", + "qdss_debug_xo"; + + interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc"; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_IFE_1_GDSC>, + <&camcc CAM_CC_IFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + +}; + &i2c0 { clocks = <&segcc SE_GCC_QUPV3_WRAP0_S0_CLK>; clock-names = "se"; diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 3cd7fecdcae73..b9a81b9c4fdac 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -2625,6 +2625,127 @@ #iommu-cells = <1>; }; + camss: isp@9b32000 { + compatible = "qcom,nord-camss"; + + reg = <0 0x09b32000 0 0x2000>, + <0 0x09b38800 0 0x2000>, + <0 0x09b3f000 0 0x2000>, + <0 0x09c32000 0 0x1000>, + <0 0x09c37000 0 0x1000>, + <0 0x09c3c000 0 0x1000>, + <0 0x09c41000 0 0x1000>, + <0 0x09c46000 0 0x1000>, + <0 0x09c4b000 0 0x1000>, + <0 0x09c50000 0 0x1000>, + <0 0x09c55000 0 0x1000>, + <0 0x09c5a000 0 0x1000>, + <0 0x09c5f000 0 0x1000>, + <0 0x09a92000 0 0x400>, + <0 0x09a93000 0 0x400>, + <0 0x09a94000 0 0x400>, + <0 0x09ab1000 0 0x4000>, + <0 0x09ad1000 0 0x4000>, + <0 0x09af1000 0 0x4000>, + <0 0x09c34000 0 0x2000>, + <0 0x09c39000 0 0x2000>, + <0 0x09c3e000 0 0x2000>, + <0 0x09c43000 0 0x2000>, + <0 0x09c48000 0 0x2000>, + <0 0x09c4d000 0 0x2000>, + <0 0x09c52000 0 0x2000>, + <0 0x09c57000 0 0x2000>, + <0 0x09c5c000 0 0x2000>, + <0 0x09c61000 0 0x2000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_lite2", + "csid_lite3", + "csid_lite4", + "csid_lite5", + "csid_lite6", + "csid_lite7", + "csid_lite8", + "csid_lite9", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1", + "vfe_lite2", + "vfe_lite3", + "vfe_lite4", + "vfe_lite5", + "vfe_lite6", + "vfe_lite7", + "vfe_lite8", + "vfe_lite9"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_lite2", + "csid_lite3", + "csid_lite4", + "csid_lite5", + "csid_lite6", + "csid_lite7", + "csid_lite8", + "csid_lite9", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1", + "vfe_lite2", + "vfe_lite3", + "vfe_lite4", + "vfe_lite5", + "vfe_lite6", + "vfe_lite7", + "vfe_lite8", + "vfe_lite9"; + + iommus = <&apps_smmu_2 0x1401 0x20>, + <&apps_smmu_2 0x1460 0x00>; + + status = "disabled"; + }; + usb_2: usb@a200000 { compatible = "qcom,nord-dwc3", "qcom,snps-dwc3"; From b85fe04b062a2867f79a0d17492b2ad12f6e1920 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Sun, 20 Sep 2026 17:10:52 +0800 Subject: [PATCH 1081/1133] FROMLIST: arm64: dts: qcom: nord-rrd: Enable camss support Enable camss support on the Nord RRD board. Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/r/20260920091053.2214965-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index 560e7c4f5729d..3deee2b174691 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -598,6 +598,10 @@ }; }; +&camss { + status = "okay"; +}; + &i2c7 { clock-frequency = <400000>; From e51f7c2a4c65a1ba2b0a492e67cfca298f77780c Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 20 Sep 2026 17:10:53 +0800 Subject: [PATCH 1082/1133] FROMLIST: arm64: dts: qcom: nord-ride-embedded: Enable camss support Enable camss support on the Nord Ride Embedded board. Link: https://lore.kernel.org/r/20260920091053.2214965-4-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-ride-embedded.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index b743d62788660..3096e6b85e80d 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -639,6 +639,10 @@ }; }; +&camss { + status = "okay"; +}; + &i2c9 { clock-frequency = <400000>; From 7b741d386302a08c181800372e99b57c0cd4d7d0 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Sat, 19 Sep 2026 10:14:56 +0530 Subject: [PATCH 1083/1133] FROMLIST: arm64: dts: qcom: nord: Add iris video node Add iris video codec to nord SoC, which comes with significantly different powering up sequence than previous platforms, thus different clocks and resets. Signed-off-by: Vishnu Reddy Link: https://lore.kernel.org/r/20260919-nord-iris-v1-2-94428761ec06@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 114 ++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 592a750cec271..45dfaad397e0a 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -2402,6 +2402,120 @@ #power-domain-cells = <1>; }; + iris: video-codec@aa00000 { + compatible = "qcom,nord-iris", "qcom,glymur-iris"; + reg = <0x0 0x0aa00000 0x0 0xf0000>; + + clocks = <&nwgcc NW_GCC_VIDEO_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&nwgcc NW_GCC_VIDEO_AXI0C_CLK>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK>, + <&nwgcc NW_GCC_VIDEO_AXI1_CLK>, + <&videocc VIDEO_CC_MVS1_CLK>, + <&videocc VIDEO_CC_MVS1_FREERUN_CLK>; + clock-names = "core_iface", + "core", + "vcodec0_core", + "vcodec0_iface", + "core_freerun", + "vcodec0_core_freerun", + "vcodec1_iface", + "vcodec1_core", + "vcodec1_core_freerun"; + + dma-coherent; + + interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_VENUS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_VIDEO_MVP0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + interrupts = ; + + memory-region = <&video_mem>; + + operating-points-v2 = <&iris_opp_table>; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc VIDEO_CC_MVS1_GDSC>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vcodec1"; + + resets = <&nwgcc NW_GCC_VIDEO_AXI0_CLK_ARES>, + <&nwgcc NW_GCC_VIDEO_AXI0C_CLK_ARES>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK_ARES>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK_ARES>, + <&nwgcc NW_GCC_VIDEO_AXI1_CLK_ARES>, + <&videocc VIDEO_CC_MVS1_FREERUN_CLK_ARES>; + reset-names = "core_bus", + "vcodec0_bus", + "core", + "vcodec0_core", + "vcodec1_bus", + "vcodec1_core"; + + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0x0 0xffe00000>; + + status = "disabled"; + + non-pixel { + iommus = <&apps_smmu_1 0x0940 0x20>, + <&apps_smmu_1 0x0944 0x0>, + <&apps_smmu_1 0x0960 0x20>; + iommu-ranges = <0x25800000 0xda600000>; + }; + + pixel { + iommus = <&apps_smmu_1 0x0943 0x0>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000 240000000 360000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-435000000 { + opp-hz = /bits/ 64 <435000000 435000000 652500000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000 480000000 720000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_nom>; + }; + + opp-533333333 { + opp-hz = /bits/ 64 <533333333 533333333 800000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo>; + }; + + opp-560000000 { + opp-hz = /bits/ 64 <560000000 560000000 840000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo_l1>; + }; + }; + }; + videocc: clock-controller@aaf0000 { compatible = "qcom,nord-videocc"; reg = <0x0 0x0aaf0000 0x0 0x10000>; From d63c199c2c7fd930583b7db89b6864e43f5bba2f Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Sat, 19 Sep 2026 10:14:57 +0530 Subject: [PATCH 1084/1133] FROMLIST: arm64: dts: qcom: nord-ride-embedded: Enable iris video codec node The iris hardware block is described in the nord SoC DTSI, and enabling it here allows the media iris driver to probe and use the video codec functionality. Signed-off-by: Vishnu Reddy Link: https://lore.kernel.org/r/20260919-nord-iris-v1-3-94428761ec06@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/nord-ride-embedded.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index 3096e6b85e80d..f2f3c06ebf6eb 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -795,6 +795,12 @@ }; }; +&iris { + firmware-name = "qcom/vpu/vpu36_p4_s7.mbn"; + + status = "okay"; +}; + &mdss0 { status = "okay"; }; From 061682c7d44338ee655f03db8c01d70d81ed69d5 Mon Sep 17 00:00:00 2001 From: Vishnu Reddy Date: Sat, 19 Sep 2026 10:14:58 +0530 Subject: [PATCH 1085/1133] FROMLIST: arm64: dts: qcom: nord-rrd: Enable iris video codec node The iris hardware block is described in the nord SoC DTSI, and enabling it here allows the media iris driver to probe and use the video codec functionality. Signed-off-by: Vishnu Reddy Link: https://lore.kernel.org/r/20260919-nord-iris-v1-4-94428761ec06@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index 3deee2b174691..b671dbc35afc1 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -718,6 +718,12 @@ }; }; +&iris { + firmware-name = "qcom/vpu/vpu36_p4_s7.mbn"; + + status = "okay"; +}; + &mdss0 { status = "okay"; }; From 374866b48231d1df9df3b297c15242ba3836826e Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 7 Oct 2026 17:45:55 +0800 Subject: [PATCH 1086/1133] FIXUP: arm64: dts: qcom: nord: Fix iris AXI clock and reset order The iris node lists NW_GCC_VIDEO_AXI0_CLK as "core_iface" and NW_GCC_VIDEO_AXI0C_CLK as "vcodec0_iface", the reverse of what the glymur-iris binding and glymur.dtsi describe: AXI0C is the controller (MVS0C) bus clock and AXI0 is the vcodec0 (MVS0) one. The resets are swapped the same way. The first boot works because power-on enables both clock groups. On runtime suspend, however, powering off vcodec0 gates the controller's AXI clock before the controller NoC low-power handshake runs, so the controller is not shut down cleanly and never comes back on the next resume: qcom-iris aa00000.video-codec: error booting up iris firmware qcom-iris aa00000.video-codec: failed to resume Opening the video device then fails with -EBUSY. Swap the two AXI clocks and the two AXI resets so each name refers to the right block, matching glymur.dtsi. This is a fixup for: "arm64: dts: qcom: nord: Add iris video node" Assisted-by: LLM Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 45dfaad397e0a..8b0d13270f705 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -2406,10 +2406,10 @@ compatible = "qcom,nord-iris", "qcom,glymur-iris"; reg = <0x0 0x0aa00000 0x0 0xf0000>; - clocks = <&nwgcc NW_GCC_VIDEO_AXI0_CLK>, + clocks = <&nwgcc NW_GCC_VIDEO_AXI0C_CLK>, <&videocc VIDEO_CC_MVS0C_CLK>, <&videocc VIDEO_CC_MVS0_CLK>, - <&nwgcc NW_GCC_VIDEO_AXI0C_CLK>, + <&nwgcc NW_GCC_VIDEO_AXI0_CLK>, <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, <&videocc VIDEO_CC_MVS0_FREERUN_CLK>, <&nwgcc NW_GCC_VIDEO_AXI1_CLK>, @@ -2451,8 +2451,8 @@ "mmcx", "vcodec1"; - resets = <&nwgcc NW_GCC_VIDEO_AXI0_CLK_ARES>, - <&nwgcc NW_GCC_VIDEO_AXI0C_CLK_ARES>, + resets = <&nwgcc NW_GCC_VIDEO_AXI0C_CLK_ARES>, + <&nwgcc NW_GCC_VIDEO_AXI0_CLK_ARES>, <&videocc VIDEO_CC_MVS0C_FREERUN_CLK_ARES>, <&videocc VIDEO_CC_MVS0_FREERUN_CLK_ARES>, <&nwgcc NW_GCC_VIDEO_AXI1_CLK_ARES>, From ac7974e9a36038dd58f061fb8ef615caeffc003f Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 23 Sep 2026 05:34:17 +0530 Subject: [PATCH 1087/1133] FROMLIST: dt-bindings: phy: qcom,sa8775p-dwmac-sgmii-phy: add Nord compatible Add the qcom,nord-dwmac-sgmii-phy compatible to the Qualcomm DWMAC SGMII PHY binding. Signed-off-by: Mohd Ayaan Anwar Reviewed-by: Bartosz Golaszewski Acked-by: Lorenzo Bianconi Tested-by: Zhangfei Gao Link: https://lore.kernel.org/r/20260923-nord_ethernet_serdes-v1-1-f8ac1c487882@oss.qualcomm.com --- .../devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml index e573abcb937df..f2df9983d9536 100644 --- a/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml @@ -21,6 +21,7 @@ properties: - qcom,qcs8300-dwmac-sgmii-phy - const: qcom,sa8775p-dwmac-sgmii-phy - const: qcom,sa8775p-dwmac-sgmii-phy + - const: qcom,nord-dwmac-sgmii-phy reg: items: From ea8f5750d42a04f7945b1875a642150751261e25 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 23 Sep 2026 05:34:18 +0530 Subject: [PATCH 1088/1133] FROMLIST: phy: qcom: sgmii-eth: prepare for additional PHY modes Prepare the SGMII Ethernet PHY driver for PHY modes that require a different SerDes programming sequence. Move the SGMII readiness checks into a helper so additional modes can provide their own status checks, and select the initial interface mode through per-compatible match data rather than hardcoding SGMII during probe. This does not change existing SA8775P behavior. Signed-off-by: Mohd Ayaan Anwar Acked-by: Lorenzo Bianconi Tested-by: Zhangfei Gao Link: https://lore.kernel.org/r/20260923-nord_ethernet_serdes-v1-2-f8ac1c487882@oss.qualcomm.com --- drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 70 +++++++++++++++-------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c index 7137200c3f310..029dafacee785 100644 --- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c +++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c @@ -41,6 +41,10 @@ struct qcom_dwmac_sgmii_phy_data { phy_interface_t interface; }; +struct qcom_dwmac_sgmii_phy_match_data { + phy_interface_t default_interface; +}; + static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap) { regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01); @@ -227,47 +231,31 @@ qcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg, val & bit, 1500, 750000); } -static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy) +static int qcom_dwmac_sgmii_phy_poll_sgmii_ready(struct device *dev, + struct regmap *regmap) { - struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); - struct device *dev = phy->dev.parent; - - switch (data->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_1000BASEX: - /* 1.25Gbps mode */ - qcom_dwmac_sgmii_phy_init_1g(data->regmap); - break; - case PHY_INTERFACE_MODE_2500BASEX: - /* 3.125Gbps mode */ - qcom_dwmac_sgmii_phy_init_2p5g(data->regmap); - break; - default: - return -EINVAL; - } - - if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, + if (qcom_dwmac_sgmii_phy_poll_status(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_C_READY_STATUS, QSERDES_COM_C_READY)) { dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out"); return -ETIMEDOUT; } - if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, + if (qcom_dwmac_sgmii_phy_poll_status(regmap, QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS, QSERDES_PCS_READY)) { dev_err(dev, "PCS_READY timed-out"); return -ETIMEDOUT; } - if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, + if (qcom_dwmac_sgmii_phy_poll_status(regmap, QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS, QSERDES_PCS_SGMIIPHY_READY)) { dev_err(dev, "SGMIIPHY_READY timed-out"); return -ETIMEDOUT; } - if (qcom_dwmac_sgmii_phy_poll_status(data->regmap, + if (qcom_dwmac_sgmii_phy_poll_status(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CMN_STATUS, QSERDES_COM_C_PLL_LOCKED)) { dev_err(dev, "PLL Lock Status timed-out"); @@ -277,6 +265,28 @@ static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy) return 0; } +static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy) +{ + struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); + struct device *dev = phy->dev.parent; + + switch (data->interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + /* 1.25Gbps mode */ + qcom_dwmac_sgmii_phy_init_1g(data->regmap); + break; + case PHY_INTERFACE_MODE_2500BASEX: + /* 3.125Gbps mode */ + qcom_dwmac_sgmii_phy_init_2p5g(data->regmap); + break; + default: + return -EINVAL; + } + + return qcom_dwmac_sgmii_phy_poll_sgmii_ready(dev, data->regmap); +} + static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy) { struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); @@ -374,6 +384,7 @@ static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = { static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev) { + const struct qcom_dwmac_sgmii_phy_match_data *match_data; struct qcom_dwmac_sgmii_phy_data *data; struct device *dev = &pdev->dev; struct phy_provider *provider; @@ -385,7 +396,11 @@ static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev) if (!data) return -ENOMEM; - data->interface = PHY_INTERFACE_MODE_SGMII; + match_data = device_get_match_data(dev); + if (!match_data) + return -EINVAL; + + data->interface = match_data->default_interface; base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) @@ -419,8 +434,15 @@ static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev) return 0; } +static const struct qcom_dwmac_sgmii_phy_match_data sa8775p_match_data = { + .default_interface = PHY_INTERFACE_MODE_SGMII, +}; + static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = { - { .compatible = "qcom,sa8775p-dwmac-sgmii-phy" }, + { + .compatible = "qcom,sa8775p-dwmac-sgmii-phy", + .data = &sa8775p_match_data, + }, { }, }; MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match); From 351bc344b94addca7846aa2b6e483b33ea75b037 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Wed, 23 Sep 2026 05:34:19 +0530 Subject: [PATCH 1089/1133] FROMLIST: phy: qcom: sgmii-eth: add Nord USXGMII support Nord uses a QMP v7 SerDes block which is an updated version of the SGMII SerDes PHY IP. The SGMII SerDes PHY supports multiple operating modes by programming different SerDes line rates. The driver currently handles SGMII and 2500BASE-X configurations only. Add support for configuring the SerDes to operate at 10.3125 Gbaud, enabling both USXGMII and 10GBASE-R PHY interface modes. Finally, add a driver compatible for Nord. Select USXGMII as the initial interface mode for Nord. phy_power_on() can run before the consumer calls set_mode(), so this ensures that the first calibration selects the 10.3125 Gbaud programming sequence. Signed-off-by: Mohd Ayaan Anwar Acked-by: Lorenzo Bianconi Tested-by: Zhangfei Gao Link: https://lore.kernel.org/r/20260923-nord_ethernet_serdes-v1-3-f8ac1c487882@oss.qualcomm.com --- drivers/phy/qualcomm/phy-qcom-qmp-pcs-sgmii.h | 5 + .../qualcomm/phy-qcom-qmp-qserdes-com-v7.h | 2 + .../qualcomm/phy-qcom-qmp-qserdes-txrx-v7.h | 9 + drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 166 +++++++++++++++++- 4 files changed, 177 insertions(+), 5 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-sgmii.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-sgmii.h index 4d8c962f5e0f5..67ab2fe085de3 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-sgmii.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-sgmii.h @@ -10,11 +10,16 @@ #define QPHY_PCS_POWER_DOWN_CONTROL 0x004 #define QPHY_PCS_SW_RESET 0x008 #define QPHY_PCS_LINE_RESET_TIME 0x00c +#define QPHY_PCS_RETIME_BUFFER_EN 0x018 #define QPHY_PCS_TX_LARGE_AMP_DRV_LVL 0x020 +#define QPHY_PCS_TX_LARGE_AMP_POST_EMP_LVL 0x024 #define QPHY_PCS_TX_SMALL_AMP_DRV_LVL 0x028 +#define QPHY_PCS_TX_SMALL_AMP_POST_EMP_LVL 0x02c +#define QPHY_PCS_RX_SIGDET_CTRL2 0x08c #define QPHY_PCS_PCS_READY_STATUS 0x094 #define QPHY_PCS_TX_MID_TERM_CTRL1 0x0d8 #define QPHY_PCS_TX_MID_TERM_CTRL2 0x0dc +#define QPHY_PCS_SGMII_MISC_CTRL7 0x114 #define QPHY_PCS_SGMII_MISC_CTRL8 0x118 #endif diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v7.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v7.h index 7430f49214779..e8b4a26b361ad 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v7.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v7.h @@ -58,6 +58,7 @@ #define QSERDES_V7_COM_CLK_ENABLE1 0xe0 #define QSERDES_V7_COM_SYS_CLK_CTRL 0xe4 #define QSERDES_V7_COM_SYSCLK_BUF_ENABLE 0xe8 +#define QSERDES_V7_COM_PLL_EN 0xec #define QSERDES_V7_COM_PLL_IVCO 0xf4 #define QSERDES_V7_COM_PLL_IVCO_MODE1 0xf8 #define QSERDES_V7_COM_SYSCLK_EN_SEL 0x110 @@ -75,6 +76,7 @@ #define QSERDES_V7_COM_CMN_MISC_1 0x184 #define QSERDES_V7_COM_CMN_MODE 0x188 #define QSERDES_V7_COM_PLL_VCO_DC_LEVEL_CTRL 0x198 +#define QSERDES_V7_COM_BIN_VCOCAL_HSCLK_SEL_1 0x19c #define QSERDES_V7_COM_AUTO_GAIN_ADJ_CTRL_1 0x1a4 #define QSERDES_V7_COM_AUTO_GAIN_ADJ_CTRL_2 0x1a8 #define QSERDES_V7_COM_AUTO_GAIN_ADJ_CTRL_3 0x1ac diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v7.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v7.h index 6ab943ff57ff6..0c38d62284e4d 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v7.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v7.h @@ -7,9 +7,11 @@ #define QCOM_PHY_QMP_QSERDES_TXRX_V7_H_ #define QSERDES_V7_TX_CLKBUF_ENABLE 0x08 +#define QSERDES_V7_TX_TX_EMP_POST1_LVL 0x0c #define QSERDES_V7_TX_RESET_TSYNC_EN 0x1c #define QSERDES_V7_TX_PRE_STALL_LDO_BOOST_EN 0x20 #define QSERDES_V7_TX_TX_BAND 0x24 +#define QSERDES_V7_TX_SLEW_CNTL 0x28 #define QSERDES_V7_TX_INTERFACE_SELECT 0x2c #define QSERDES_V7_TX_RES_CODE_LANE_TX 0x34 #define QSERDES_V7_TX_RES_CODE_LANE_RX 0x38 @@ -35,26 +37,32 @@ #define QSERDES_V7_RX_UCDR_FASTLOCK_COUNT_LOW 0x3c #define QSERDES_V7_RX_UCDR_FASTLOCK_COUNT_HIGH 0x40 #define QSERDES_V7_RX_UCDR_PI_CONTROLS 0x44 +#define QSERDES_V7_RX_UCDR_PI_CTRL2 0x48 #define QSERDES_V7_RX_UCDR_SB2_THRESH1 0x4c #define QSERDES_V7_RX_UCDR_SB2_THRESH2 0x50 #define QSERDES_V7_RX_UCDR_SB2_GAIN1 0x54 #define QSERDES_V7_RX_UCDR_SB2_GAIN2 0x58 #define QSERDES_V7_RX_AUX_DATA_TCOARSE_TFINE 0x60 +#define QSERDES_V7_RX_RX_TERM_BW 0x80 #define QSERDES_V7_RX_TX_ADAPT_PRE_THRESH1 0xc4 #define QSERDES_V7_RX_TX_ADAPT_PRE_THRESH2 0xc8 #define QSERDES_V7_RX_TX_ADAPT_POST_THRESH 0xcc #define QSERDES_V7_RX_VGA_CAL_CNTRL1 0xd4 #define QSERDES_V7_RX_VGA_CAL_CNTRL2 0xd8 #define QSERDES_V7_RX_GM_CAL 0xdc +#define QSERDES_V7_RX_RX_EQU_ADAPTOR_CNTRL1 0xe8 #define QSERDES_V7_RX_RX_EQU_ADAPTOR_CNTRL2 0xec #define QSERDES_V7_RX_RX_EQU_ADAPTOR_CNTRL3 0xf0 #define QSERDES_V7_RX_RX_EQU_ADAPTOR_CNTRL4 0xf4 #define QSERDES_V7_RX_RX_IDAC_TSETTLE_LOW 0xf8 #define QSERDES_V7_RX_RX_IDAC_TSETTLE_HIGH 0xfc +#define QSERDES_V7_RX_RX_IDAC_MEASURE_TIME 0x100 #define QSERDES_V7_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110 +#define QSERDES_V7_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x114 #define QSERDES_V7_RX_SIGDET_ENABLES 0x118 #define QSERDES_V7_RX_SIGDET_CNTRL 0x11c #define QSERDES_V7_RX_SIGDET_DEGLITCH_CNTRL 0x124 +#define QSERDES_V7_RX_RX_BAND 0x128 #define QSERDES_V7_RX_RX_MODE_00_LOW 0x15c #define QSERDES_V7_RX_RX_MODE_00_HIGH 0x160 #define QSERDES_V7_RX_RX_MODE_00_HIGH2 0x164 @@ -75,6 +83,7 @@ #define QSERDES_V7_RX_DCC_CTRL1 0x1a8 #define QSERDES_V7_RX_VTH_CODE 0x1b0 #define QSERDES_V7_RX_SIGDET_CAL_CTRL1 0x1e4 +#define QSERDES_V7_RX_SIGDET_CAL_CTRL2_AND_CDR_LOCK_EDGE 0x1e8 #define QSERDES_V7_RX_SIGDET_CAL_TRIM 0x1f8 #endif diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c index 029dafacee785..3c68bfe0ea443 100644 --- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c +++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c @@ -15,7 +15,9 @@ #include "phy-qcom-qmp-pcs-sgmii.h" #include "phy-qcom-qmp-qserdes-com-v5.h" +#include "phy-qcom-qmp-qserdes-com-v7.h" #include "phy-qcom-qmp-qserdes-txrx-v5.h" +#include "phy-qcom-qmp-qserdes-txrx-v7.h" #define QSERDES_QMP_PLL 0x0 #define QSERDES_RX 0x600 @@ -221,6 +223,114 @@ static void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap) regmap_write(regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01); } +static void qcom_dwmac_sgmii_phy_init_10g(struct regmap *regmap) +{ + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_POWER_DOWN_CONTROL, 0x01); + + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_BG_TIMER, 0x0A); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_PLL_IVCO, 0x0F); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x07); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_CLK_ENABLE1, 0x0F); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_CP_CTRL_MODE0, 0x08); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_PLL_RCTRL_MODE0, 0x16); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_PLL_CCTRL_MODE0, 0x36); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_INTEGLOOP_GAIN0_MODE0, 0x1F); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_INTEGLOOP_GAIN1_MODE0, 0x00); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_PLL_EN, 0x03); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_SYSCLK_EN_SEL, 0x1A); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_LOCK_CMP1_MODE0, 0x23); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_LOCK_CMP2_MODE0, 0x43); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_DEC_START_MODE0, 0x43); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_DIV_FRAC_START1_MODE0, 0x00); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_DIV_FRAC_START2_MODE0, 0x38); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_DIV_FRAC_START3_MODE0, 0x02); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_VCO_TUNE1_MODE0, 0xE6); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_VCO_TUNE2_MODE0, 0x01); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_VCO_TUNE_INITVAL2, 0x00); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_HSCLK_SEL_1, 0x00); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_HSCLK_HS_SWITCH_SEL_1, 0x00); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_PLL_CORE_CLK_DIV_MODE0, 0x04); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_CORE_CLK_EN, 0x30); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_CMN_CONFIG_1, 0x16); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xD7); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0F); + regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V7_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x11); + + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_CLKBUF_ENABLE, 0x0D); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_TX_BAND, 0x04); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_SLEW_CNTL, 0x08); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_RES_CODE_LANE_OFFSET_TX, 0x09); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_RES_CODE_LANE_OFFSET_RX, 0x09); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_LANE_MODE_1, 0xF5); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_LANE_MODE_2, 0x06); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_LANE_MODE_3, 0x3F); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_LANE_MODE_4, 0x3F); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_LANE_MODE_5, 0x5F); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_RCV_DETECT_LVL_2, 0x12); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_TRAN_DRVR_EMP_EN, 0x0F); + regmap_write(regmap, QSERDES_TX + QSERDES_V7_TX_TX_EMP_POST1_LVL, 0x2B); + + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_UCDR_FO_GAIN, 0x0D); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_UCDR_SO_GAIN, 0x03); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_UCDR_PI_CONTROLS, 0x81); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_UCDR_PI_CTRL2, 0x81); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_UCDR_SB2_THRESH1, 0x11); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_UCDR_SB2_THRESH2, 0x22); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_TERM_BW, 0x03); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_VGA_CAL_CNTRL2, 0x08); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_GM_CAL, 0x0F); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_EQU_ADAPTOR_CNTRL4, 0x5A); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_IDAC_TSETTLE_LOW, 0x80); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_IDAC_TSETTLE_HIGH, 0x01); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_IDAC_MEASURE_TIME, 0x20); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_SIGDET_CNTRL, 0x0F); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_SIGDET_DEGLITCH_CNTRL, 0x1E); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_BAND, 0x18); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_00_LOW, 0x1F); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_00_HIGH, 0xBF); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_00_HIGH2, 0xFF); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_00_HIGH3, 0xDF); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_00_HIGH4, 0xEF); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_01_LOW, 0xE5); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_01_HIGH, 0xC8); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_01_HIGH2, 0xC8); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_01_HIGH3, 0x14); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_01_HIGH4, 0xB6); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_10_LOW, 0xE0); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_10_HIGH, 0xC8); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_10_HIGH2, 0xC8); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_10_HIGH3, 0x3B); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_RX_MODE_10_HIGH4, 0xB7); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_DCC_CTRL1, 0x0C); + + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_LINE_RESET_TIME, 0x00); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_SMALL_AMP_DRV_LVL, 0x03); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_LARGE_AMP_DRV_LVL, 0x1A); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_SMALL_AMP_POST_EMP_LVL, 0x00); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_LARGE_AMP_POST_EMP_LVL, 0x0B); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL1, 0x83); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_SIGDET_CAL_CTRL1, 0x00); + regmap_write(regmap, QSERDES_RX + QSERDES_V7_RX_SIGDET_CAL_CTRL2_AND_CDR_LOCK_EDGE, 0x00); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_RX_SIGDET_CTRL2, 0xCC); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SGMII_MISC_CTRL7, 0x00); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SGMII_MISC_CTRL8, 0x14); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_RETIME_BUFFER_EN, 0x01); + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00); + + regmap_write(regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01); +} + static inline int qcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg, unsigned int bit) @@ -265,6 +375,40 @@ static int qcom_dwmac_sgmii_phy_poll_sgmii_ready(struct device *dev, return 0; } +static int qcom_dwmac_sgmii_phy_poll_usxgmii_ready(struct device *dev, + struct regmap *regmap) +{ + if (qcom_dwmac_sgmii_phy_poll_status(regmap, + QSERDES_QMP_PLL + QSERDES_V7_COM_C_READY_STATUS, + QSERDES_COM_C_READY)) { + dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out"); + return -ETIMEDOUT; + } + + if (qcom_dwmac_sgmii_phy_poll_status(regmap, + QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS, + QSERDES_PCS_READY)) { + dev_err(dev, "PCS_READY timed-out"); + return -ETIMEDOUT; + } + + if (qcom_dwmac_sgmii_phy_poll_status(regmap, + QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS, + QSERDES_PCS_SGMIIPHY_READY)) { + dev_err(dev, "SGMIIPHY_READY timed-out"); + return -ETIMEDOUT; + } + + if (qcom_dwmac_sgmii_phy_poll_status(regmap, + QSERDES_QMP_PLL + QSERDES_V7_COM_CMN_STATUS, + QSERDES_COM_C_PLL_LOCKED)) { + dev_err(dev, "PLL Lock Status timed-out"); + return -ETIMEDOUT; + } + + return 0; +} + static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy) { struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy); @@ -275,16 +419,19 @@ static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy) case PHY_INTERFACE_MODE_1000BASEX: /* 1.25Gbps mode */ qcom_dwmac_sgmii_phy_init_1g(data->regmap); - break; + return qcom_dwmac_sgmii_phy_poll_sgmii_ready(dev, data->regmap); case PHY_INTERFACE_MODE_2500BASEX: /* 3.125Gbps mode */ qcom_dwmac_sgmii_phy_init_2p5g(data->regmap); - break; + return qcom_dwmac_sgmii_phy_poll_sgmii_ready(dev, data->regmap); + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + /* 10.3125Gbps mode */ + qcom_dwmac_sgmii_phy_init_10g(data->regmap); + return qcom_dwmac_sgmii_phy_poll_usxgmii_ready(dev, data->regmap); default: return -EINVAL; } - - return qcom_dwmac_sgmii_phy_poll_sgmii_ready(dev, data->regmap); } static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy) @@ -340,7 +487,9 @@ static int qcom_dwmac_sgmii_phy_validate(struct phy *phy, enum phy_mode mode, if (submode == PHY_INTERFACE_MODE_SGMII || submode == PHY_INTERFACE_MODE_1000BASEX || - submode == PHY_INTERFACE_MODE_2500BASEX) + submode == PHY_INTERFACE_MODE_2500BASEX || + submode == PHY_INTERFACE_MODE_USXGMII || + submode == PHY_INTERFACE_MODE_10GBASER) return 0; return -EINVAL; @@ -434,12 +583,19 @@ static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev) return 0; } +static const struct qcom_dwmac_sgmii_phy_match_data nord_match_data = { + .default_interface = PHY_INTERFACE_MODE_USXGMII, +}; + static const struct qcom_dwmac_sgmii_phy_match_data sa8775p_match_data = { .default_interface = PHY_INTERFACE_MODE_SGMII, }; static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = { { + .compatible = "qcom,nord-dwmac-sgmii-phy", + .data = &nord_match_data, + }, { .compatible = "qcom,sa8775p-dwmac-sgmii-phy", .data = &sa8775p_match_data, }, From d3fbe6cb71611d4fc605c73f1ad357941babea5e Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Sun, 1 Nov 2026 16:04:11 +0800 Subject: [PATCH 1090/1133] FROMLIST: arm64: dts: qcom: nord: Add Ethernet support Describe both Nord 10-Gbps Ethernet controllers, including their XPCS and SerDes blocks, clocks, resets, power domains, interconnects, SMMU streams and DMA queues. Signed-off-by: Mohd Ayaan Anwar Link: https://lore.kernel.org/r/20261101080413.1428016-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 124 +++++++++ arch/arm64/boot/dts/qcom/nord.dtsi | 282 ++++++++++++++++++++ 2 files changed, 406 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 8b0d13270f705..2768e18e72ae1 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -141,6 +141,60 @@ }; +ðernet0 { + clocks = <&segcc SE_GCC_EMAC0_AXI_CLK>, + <&segcc SE_GCC_EMAC0_CNOC_APB_CLK>, + <&segcc SE_GCC_EMAC0_PTP_CLK>, + <&segcc SE_GCC_EMAC0_PHY_AUX_CLK>, + <&segcc SE_GCC_EEE_EMAC0_CLK>; + clock-names = "stmmaceth", + "pclk", + "ptp_ref", + "phyaux", + "eee"; + + resets = <&segcc SE_GCC_EMAC0_BCR>; + + power-domains = <&segcc SE_GCC_EMAC0_GDSC>; + + interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_PS_ETH_0 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc_tile MASTER_EMAC_0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-mac", + "mac-mem"; + + phys = <&serdes0>; + phy-names = "serdes"; +}; + +ðernet1 { + clocks = <&segcc SE_GCC_EMAC1_AXI_CLK>, + <&segcc SE_GCC_EMAC1_CNOC_APB_CLK>, + <&segcc SE_GCC_EMAC1_PTP_CLK>, + <&segcc SE_GCC_EMAC1_PHY_AUX_CLK>, + <&segcc SE_GCC_EEE_EMAC1_CLK>; + clock-names = "stmmaceth", + "pclk", + "ptp_ref", + "phyaux", + "eee"; + + resets = <&segcc SE_GCC_EMAC1_BCR>; + + power-domains = <&segcc SE_GCC_EMAC1_GDSC>; + + interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS + &config_noc SLAVE_PS_ETH_1 QCOM_ICC_TAG_ALWAYS>, + <&aggre2_noc_tile MASTER_EMAC_1 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-mac", + "mac-mem"; + + phys = <&serdes1>; + phy-names = "serdes"; +}; + &i2c0 { clocks = <&segcc SE_GCC_QUPV3_WRAP0_S0_CLK>; clock-names = "se"; @@ -2314,6 +2368,30 @@ status = "disabled"; }; + serdes0: phy@88f8000 { + compatible = "qcom,nord-dwmac-sgmii-phy"; + reg = <0x0 0x088f8000 0x0 0x4000>; + + clocks = <&tcsrcc TCSR_UX_SGMII_0_CLKREF_EN>; + clock-names = "sgmi_ref"; + + #phy-cells = <0>; + + status = "disabled"; + }; + + serdes1: phy@88fc000 { + compatible = "qcom,nord-dwmac-sgmii-phy"; + reg = <0x0 0x088fc000 0x0 0x4000>; + + clocks = <&tcsrcc TCSR_UX_SGMII_1_CLKREF_EN>; + clock-names = "sgmi_ref"; + + #phy-cells = <0>; + + status = "disabled"; + }; + negcc: clock-controller@8900000 { compatible = "qcom,nord-negcc"; reg = <0x0 0x08900000 0x0 0xf4200>; @@ -2732,6 +2810,38 @@ bias-disable; }; + ethernet0_default: ethernet0-default-state { + mdc-pins { + pins = "gpio47"; + function = "emac0_mdc"; + drive-strength = <16>; + bias-pull-up; + }; + + mdio-pins { + pins = "gpio48"; + function = "emac0_mdio"; + drive-strength = <16>; + bias-pull-up; + }; + }; + + ethernet1_default: ethernet1-default-state { + mdc-pins { + pins = "gpio49"; + function = "emac1_mdc"; + drive-strength = <16>; + bias-pull-up; + }; + + mdio-pins { + pins = "gpio50"; + function = "emac1_mdio"; + drive-strength = <16>; + bias-pull-up; + }; + }; + pcie0_default: pcie0-default-state { wake-pins { pins = "gpio0"; @@ -3858,3 +3968,17 @@ }; }; }; + +&xpcs0 { + clocks = <&segcc SE_GCC_EMAC0_CNOC_APB_CLK>; + clock-names = "csr"; + + power-domains = <&segcc SE_GCC_EMAC0_GDSC>; +}; + +&xpcs1 { + clocks = <&segcc SE_GCC_EMAC1_CNOC_APB_CLK>; + clock-names = "csr"; + + power-domains = <&segcc SE_GCC_EMAC1_GDSC>; +}; diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index b9a81b9c4fdac..02249a3099e1b 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -1931,6 +1931,288 @@ reg = <0x0 0x010c3000 0x0 0x1000>; }; + ethernet0: ethernet@1a00000 { + compatible = "qcom,nord-ethqos"; + + reg = <0x0 0x01a00000 0x0 0x14000>, + <0x0 0x01a7f000 0x0 0x1000>; + reg-names = "stmmaceth", + "rgmii"; + + interrupts = , + ; + interrupt-names = "macirq", + "eth_lpi"; + + iommus = <&apps_smmu_2 0x1201 0x2>, + <&apps_smmu_2 0x1202 0x0>, + <&apps_smmu_2 0x1203 0x2>, + <&apps_smmu_2 0x1204 0x0>, + <&apps_smmu_2 0x1205 0x2>, + <&apps_smmu_2 0x1206 0x0>, + <&apps_smmu_2 0x1207 0x2>, + <&apps_smmu_2 0x1208 0x0>, + <&apps_smmu_2 0x1209 0x0>, + <&apps_smmu_2 0x120a 0x0>; + + pcs-handle = <&xpcs0>; + + dma-coherent; + + rx-fifo-depth = <98304>; + tx-fifo-depth = <98304>; + + snps,tso; + snps,pbl = <16>; + snps,axi-config = <&emac0_axi_setup>; + snps,mtl-rx-config = <&emac0_mtl_rx>; + snps,mtl-tx-config = <&emac0_mtl_tx>; + + status = "disabled"; + + emac0_axi_setup: stmmac-axi-config { + snps,wr_osr_lmt = <16>; + snps,rd_osr_lmt = <16>; + snps,blen = <0 0 0 0 16 0 0>; + }; + + emac0_mtl_rx: rx-queues-config { + snps,rx-queues-to-use = <8>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + + queue4 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x4>; + }; + + queue5 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x5>; + }; + + queue6 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x6>; + }; + + queue7 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x7>; + }; + }; + + emac0_mtl_tx: tx-queues-config { + snps,tx-queues-to-use = <8>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,dcb-algorithm; + }; + + queue3 { + snps,dcb-algorithm; + }; + + queue4 { + snps,dcb-algorithm; + }; + + queue5 { + snps,dcb-algorithm; + }; + + queue6 { + snps,dcb-algorithm; + }; + + queue7 { + snps,dcb-algorithm; + }; + }; + }; + + xpcs0: xpcs@1a14000 { + compatible = "qcom,nord-dw-xpcs"; + + reg = <0x0 0x01a14000 0x0 0x5100>; + reg-names = "direct"; + reg-io-width = <4>; + + status = "disabled"; + }; + + ethernet1: ethernet@1a80000 { + compatible = "qcom,nord-ethqos"; + + reg = <0x0 0x01a80000 0x0 0x14000>, + <0x0 0x01aff000 0x0 0x1000>; + reg-names = "stmmaceth", + "rgmii"; + + interrupts = , + ; + interrupt-names = "macirq", + "eth_lpi"; + + iommus = <&apps_smmu_2 0x11c1 0x8>, + <&apps_smmu_2 0x11c2 0x1>, + <&apps_smmu_2 0x11c3 0x1>, + <&apps_smmu_2 0x11c4 0x3>, + <&apps_smmu_2 0x11c5 0x3>, + <&apps_smmu_2 0x11c6 0x3>, + <&apps_smmu_2 0x11c7 0x3>, + <&apps_smmu_2 0x11c8 0x2>, + <&apps_smmu_2 0x11c9 0x8>, + <&apps_smmu_2 0x11ca 0x2>; + + pcs-handle = <&xpcs1>; + + dma-coherent; + + rx-fifo-depth = <98304>; + tx-fifo-depth = <98304>; + + snps,tso; + snps,pbl = <16>; + snps,axi-config = <&emac1_axi_setup>; + snps,mtl-rx-config = <&emac1_mtl_rx>; + snps,mtl-tx-config = <&emac1_mtl_tx>; + + status = "disabled"; + + emac1_axi_setup: stmmac-axi-config { + snps,wr_osr_lmt = <16>; + snps,rd_osr_lmt = <16>; + snps,blen = <0 0 0 0 16 0 0>; + }; + + emac1_mtl_rx: rx-queues-config { + snps,rx-queues-to-use = <8>; + snps,rx-sched-sp; + + queue0 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x0>; + snps,route-up; + }; + + queue1 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x1>; + snps,route-ptp; + }; + + queue2 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x2>; + snps,route-avcp; + }; + + queue3 { + snps,avb-algorithm; + snps,map-to-dma-channel = <0x3>; + snps,priority = <0xc>; + }; + + queue4 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x4>; + }; + + queue5 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x5>; + }; + + queue6 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x6>; + }; + + queue7 { + snps,dcb-algorithm; + snps,map-to-dma-channel = <0x7>; + }; + }; + + emac1_mtl_tx: tx-queues-config { + snps,tx-queues-to-use = <8>; + + queue0 { + snps,dcb-algorithm; + }; + + queue1 { + snps,dcb-algorithm; + }; + + queue2 { + snps,dcb-algorithm; + }; + + queue3 { + snps,dcb-algorithm; + }; + + queue4 { + snps,dcb-algorithm; + }; + + queue5 { + snps,dcb-algorithm; + }; + + queue6 { + snps,dcb-algorithm; + }; + + queue7 { + snps,dcb-algorithm; + }; + }; + }; + + xpcs1: xpcs@1a94000 { + compatible = "qcom,nord-dw-xpcs"; + + reg = <0x0 0x01a94000 0x0 0x5100>; + reg-names = "direct"; + reg-io-width = <4>; + + status = "disabled"; + }; + pcie0: pci@1b80000 { compatible = "qcom,nord-pcie", "qcom,pcie-sa8775p"; From ee391f9b465c12f4888b7278f41737a8b32833b4 Mon Sep 17 00:00:00 2001 From: Mohd Ayaan Anwar Date: Sun, 1 Nov 2026 16:04:12 +0800 Subject: [PATCH 1091/1133] FROMLIST: arm64: dts: qcom: nord-ride-embedded: Enable Ethernet Enable both Ethernet ports on Nord Ride in fixed-link USXGMII 10-Gbps mode for connection to the onboard firmware driven Ethernet switch. Signed-off-by: Mohd Ayaan Anwar Link: https://lore.kernel.org/r/20261101080413.1428016-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- .../boot/dts/qcom/nord-ride-embedded.dts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index f2f3c06ebf6eb..b54306ecad04b 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -643,6 +643,28 @@ status = "okay"; }; +ðernet0 { + phy-mode = "usxgmii"; + + status = "okay"; + + fixed-link { + speed = <10000>; + full-duplex; + }; +}; + +ðernet1 { + phy-mode = "usxgmii"; + + status = "okay"; + + fixed-link { + speed = <10000>; + full-duplex; + }; +}; + &i2c9 { clock-frequency = <400000>; @@ -1025,6 +1047,20 @@ firmware-name = "qcom/nord/soccp.mbn"; }; +&serdes0 { + vdda-0p9-supply = <&vreg_l1h_0p9>; + vdda-1p2-supply = <&vreg_l2h_1p2>; + + status = "okay"; +}; + +&serdes1 { + vdda-0p9-supply = <&vreg_l1h_0p9>; + vdda-1p2-supply = <&vreg_l2h_1p2>; + + status = "okay"; +}; + &uart15 { status = "okay"; }; @@ -1138,3 +1174,11 @@ status = "okay"; }; + +&xpcs0 { + status = "okay"; +}; + +&xpcs1 { + status = "okay"; +}; From 750b6c57ec7b6a0cd7c4cbf5f595a2307a866204 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Sun, 1 Nov 2026 16:04:13 +0800 Subject: [PATCH 1092/1133] FROMLIST: arm64: dts: qcom: nord-rrd: Enable Ethernet Enable both Ethernet ports on the Nord RRD board, each connected over USXGMII to an Aquantia AQR113C PHY managed through the controller's MDIO bus. Co-developed-by: Bartosz Golaszewski Signed-off-by: Bartosz Golaszewski Signed-off-by: Zhangfei Gao Link: https://lore.kernel.org/r/20261101080413.1428016-4-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 88 +++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index b671dbc35afc1..a12760a18412c 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -602,6 +602,56 @@ status = "okay"; }; +ðernet0 { + pinctrl-0 = <ðernet0_default>, <ðernet0_phy_int>; + pinctrl-names = "default"; + + phy-mode = "usxgmii"; + phy-handle = <&sgmii_phy0>; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + sgmii_phy0: ethernet-phy@0 { + compatible = "ethernet-phy-id31c3.1c12"; + reg = <0x0>; + interrupts-extended = <&tlmm 141 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&pmau0102_e_gpios 5 GPIO_ACTIVE_LOW>; + reset-assert-us = <11000>; + reset-deassert-us = <70000>; + }; + }; +}; + +ðernet1 { + pinctrl-0 = <ðernet1_default>, <ðernet1_phy_int>; + pinctrl-names = "default"; + + phy-mode = "usxgmii"; + phy-handle = <&sgmii_phy1>; + + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + sgmii_phy1: ethernet-phy@8 { + compatible = "ethernet-phy-id31c3.1c12"; + reg = <0x8>; + interrupts-extended = <&tlmm 55 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&pmau0102_f_gpios 7 GPIO_ACTIVE_LOW>; + reset-assert-us = <11000>; + reset-deassert-us = <70000>; + }; + }; +}; + &i2c7 { clock-frequency = <400000>; @@ -910,10 +960,40 @@ firmware-name = "qcom/nord/soccp.mbn"; }; +&serdes0 { + vdda-0p9-supply = <&vreg_l1h_0p9>; + vdda-1p2-supply = <&vreg_l2h_1p2>; + + status = "okay"; +}; + +&serdes1 { + vdda-0p9-supply = <&vreg_l1h_0p9>; + vdda-1p2-supply = <&vreg_l2h_1p2>; + + status = "okay"; +}; + &spi16 { status = "okay"; }; +&tlmm { + ethernet0_phy_int: ethernet0-phy-int-state { + pins = "gpio141"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + + ethernet1_phy_int: ethernet1-phy-int-state { + pins = "gpio55"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; +}; + &uart4 { status = "okay"; }; @@ -1025,3 +1105,11 @@ status = "okay"; }; + +&xpcs0 { + status = "okay"; +}; + +&xpcs1 { + status = "okay"; +}; From ae63b139d319c58942e021fdc91fb263f9b47309 Mon Sep 17 00:00:00 2001 From: Shivam Rawat Date: Fri, 9 Oct 2026 02:36:35 +0530 Subject: [PATCH 1093/1133] FROMLIST: drm/msm/a6xx: Add Adreno 753 support Adreno 753 is the primary GPU in the Qualcomm Nord SoC and belongs to the A7xx Gen3 family. It is derived from A750 and shares the same IP-level configuration: protected registers, pwrup/IFPC register lists, GBIF CX registers, gmu_cgc_mode, 3MB GMEM, bus BCMs and preemption record size. The differences visible to the KMD are the chip id (0x43051701), the GMU chip id (0x70d0000) and the gen71300 SQE and GMU firmware. The Nord primary GPU is the same as A750 but has a different chip id, so it needs its own catalog entry. Add a new catalog entry for this GPU and an adreno_is_a753() helper. HW clock gating is not working at the moment, so it is kept disabled for now. Signed-off-by: Shivam Rawat Signed-off-by: Akhil P Oommen Link: https://lore.kernel.org/r/20261009-nord-gpu1-v1-1-a06a6c57bde7@oss.qualcomm.com --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 6 ++-- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 5 +++- drivers/gpu/drm/msm/adreno/a7xx_catalog.c | 35 +++++++++++++++++++++++ drivers/gpu/drm/msm/adreno/adreno_gpu.h | 5 ++++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 662f09bec9d52..982c66df78156 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -1045,7 +1045,7 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) for (int i = 0; (gbif_cx && gbif_cx[i].offset); i++) gpu_write(gpu, gbif_cx[i].offset, gbif_cx[i].value); - if (adreno_is_a8xx(adreno_gpu)) { + if (adreno_is_a8xx(adreno_gpu) || adreno_is_a753(adreno_gpu)) { gpu_write(gpu, REG_A6XX_GBIF_CX_CONFIG, 0x20023000); gmu_write(gmu, REG_A6XX_GMU_MRC_GBIF_QOS_CTRL, 0x33); } else if (adreno_is_a722(adreno_gpu)) @@ -1221,7 +1221,9 @@ static int a6xx_gmu_secure_init(struct a6xx_gpu *a6xx_gpu) if (test_bit(GMU_STATUS_SECURE_INIT, &gmu->status)) return 0; - if (adreno_is_a750(adreno_gpu) || adreno_is_a8xx(adreno_gpu)) { + if (adreno_is_a750(adreno_gpu) || + adreno_is_a753(adreno_gpu) || + adreno_is_a8xx(adreno_gpu)) { /* * Assume that if qcom scm isn't available, that whatever * replacement allows writing the fuse register ourselves. diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 92e8c8abb86da..a34f5f4e8bf80 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -651,6 +651,9 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state) if (!(adreno_gpu->info->a6xx->hwcg || adreno_is_a7xx(adreno_gpu))) return; + if (adreno_is_a753(adreno_gpu)) + state = false; + if (adreno_is_a630(adreno_gpu)) clock_cntl_on = 0x8aa8aa02; else if (adreno_is_a610(adreno_gpu) || adreno_is_a612(adreno_gpu)) @@ -1421,7 +1424,7 @@ static int hw_init(struct msm_gpu *gpu) BIT(6) | BIT(5) | BIT(3) | BIT(2) | BIT(1)); } - if (adreno_is_a750(adreno_gpu)) { + if (adreno_is_a750(adreno_gpu) || adreno_is_a753(adreno_gpu)) { /* Disable ubwc merged UFC request feature */ gpu_rmw(gpu, REG_A6XX_RB_CMP_DBG_ECO_CNTL, BIT(19), BIT(19)); diff --git a/drivers/gpu/drm/msm/adreno/a7xx_catalog.c b/drivers/gpu/drm/msm/adreno/a7xx_catalog.c index 6f704898cea6e..9465ffa3dd12e 100644 --- a/drivers/gpu/drm/msm/adreno/a7xx_catalog.c +++ b/drivers/gpu/drm/msm/adreno/a7xx_catalog.c @@ -451,6 +451,41 @@ static const struct adreno_info a7xx_gpus[] = { }, }, .preempt_record_size = 3572 * SZ_1K, + }, { + .chip_ids = ADRENO_CHIP_IDS(0x43051701), /* "C523v2" */ + .family = ADRENO_7XX_GEN3, + .fw = { + [ADRENO_FW_SQE] = "gen71300_sqe.fw", + [ADRENO_FW_GMU] = "gen71300_gmu.bin", + }, + .gmem = 3 * SZ_1M, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_HAS_HW_APRIV | + ADRENO_QUIRK_PREEMPTION | + ADRENO_QUIRK_IFPC, + .funcs = &a7xx_gpu_funcs, + .a6xx = &(const struct a6xx_info) { + .protect = &a730_protect, + .pwrup_reglist = &a7xx_pwrup_reglist, + .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist, + .ifpc_reglist = &a750_ifpc_reglist, + .gbif_cx = a640_gbif, + .gmu_chipid = 0x70d0000, + .gmu_cgc_mode = 0x00020202, + .bcms = (const struct a6xx_bcm[]) { + { .name = "SH0", .buswidth = 16 }, + { .name = "MC0", .buswidth = 4 }, + { + .name = "ACV", + .fixed = true, + .perfmode = BIT(2), + .perfmode_bw = 10687500, + }, + { /* sentinel */ }, + }, + }, + .preempt_record_size = 3572 * SZ_1K, }, { .chip_ids = ADRENO_CHIP_IDS(0x43030c00), .family = ADRENO_7XX_GEN2, diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 4b2156825bdf2..2911d440ab177 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -559,6 +559,11 @@ static inline int adreno_is_a750(struct adreno_gpu *gpu) return gpu->info->chip_ids[0] == 0x43051401; } +static inline int adreno_is_a753(struct adreno_gpu *gpu) +{ + return gpu->info->chip_ids[0] == 0x43051701; +} + static inline int adreno_is_x185(struct adreno_gpu *gpu) { return gpu->info->chip_ids[0] == 0x43050c01; From 06bb9e3e73db0245861879821ec0ffda8eff5773 Mon Sep 17 00:00:00 2001 From: Shivam Rawat Date: Fri, 9 Oct 2026 02:36:36 +0530 Subject: [PATCH 1094/1133] FROMLIST: dt-bindings: display/msm: Document Adreno 753 GPU/GMU Adreno 753 is the primary GPU in the Qualcomm Nord SoC and belongs to the A7xx Gen3 family. It is very similar to A750 and has the same register layout. Document the qcom,adreno-43051701 GPU compatible and add a separate constraint block for the qcom,adreno-gmu-753.1 GMU describing its registers and clocks. Signed-off-by: Shivam Rawat Signed-off-by: Akhil P Oommen Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20261009-nord-gpu1-v1-2-a06a6c57bde7@oss.qualcomm.com --- .../devicetree/bindings/display/msm/gmu.yaml | 33 +++++++++++++++++++ .../devicetree/bindings/display/msm/gpu.yaml | 1 + 2 files changed, 34 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/gmu.yaml b/Documentation/devicetree/bindings/display/msm/gmu.yaml index 07f0e547b43c1..6b28694624cf1 100644 --- a/Documentation/devicetree/bindings/display/msm/gmu.yaml +++ b/Documentation/devicetree/bindings/display/msm/gmu.yaml @@ -301,6 +301,39 @@ allOf: required: - qcom,qmp + - if: + properties: + compatible: + contains: + const: qcom,adreno-gmu-753.1 + then: + properties: + reg: + items: + - description: Core GMU registers + - description: Resource controller registers + - description: GMU PDC registers + reg-names: + items: + - const: gmu + - const: rscc + - const: gmu_pdc + clocks: + items: + - description: GPU AHB clock + - description: GMU clock + - description: GPU CX clock + - description: GPU AXI clock + - description: GPU MEMNOC clock + - description: GMU HUB clock + clock-names: + items: + - const: ahb + - const: gmu + - const: cxo + - const: axi + - const: memnoc + - const: hub - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/display/msm/gpu.yaml b/Documentation/devicetree/bindings/display/msm/gpu.yaml index c30de7feb4473..3c90a09febe70 100644 --- a/Documentation/devicetree/bindings/display/msm/gpu.yaml +++ b/Documentation/devicetree/bindings/display/msm/gpu.yaml @@ -451,6 +451,7 @@ allOf: - qcom,adreno-43050a01 - qcom,adreno-43050c01 - qcom,adreno-43051401 + - qcom,adreno-43051701 - qcom,adreno-44010000 - qcom,adreno-44050001 - qcom,adreno-44050a01 From 85ca137e1dd5a8dbb4e4214c75cbd280e21f11ec Mon Sep 17 00:00:00 2001 From: Shivam Rawat Date: Fri, 9 Oct 2026 02:36:37 +0530 Subject: [PATCH 1095/1133] PENDING: arm64: dts: qcom: nord: Add Adreno 753 GPU and GMU nodes Nord SoC integrates an Adreno 753 GPU as its primary GPU, belonging to the A7xx Gen3 family, along with its Graphics Management Unit (GMU). Add the GPU and GMU nodes together with their OPP tables. The GPU sits behind adreno_smmu_0 and uses the gen71300 zap shader, while the GMU is clocked and powered from GPUCC. Unlike previous Adreno SoCs, where the GMU AXI clock comes from the single global clock controller, Nord splits its GCC into four blocks (GCC, SE_GCC, NE_GCC and NW_GCC). The GPU's AXI clock, NW_GCC_HSCNOC_GPU_AXI_CLK, is provided by NW_GCC, so the GMU node references nwgcc directly. Following the existing Nord split, the SoC-invariant properties (reg, interrupts, iommus, zap-shader) live in nord.dtsi with both nodes disabled, while nord-embedded.dtsi adds the clocks, power domains, interconnects and OPP tables that are only managed by the OS on the Embedded (non-GearVM) variant. Signed-off-by: Shivam Rawat Signed-off-by: Akhil P Oommen Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 79 +++++++++++++++++++++ arch/arm64/boot/dts/qcom/nord.dtsi | 43 +++++++++++ 2 files changed, 122 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 2768e18e72ae1..953b8c033c738 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -195,6 +195,85 @@ phy-names = "serdes"; }; +&gmu_0 { + clocks = <&gpucc GPU_CC_AHB_CLK>, + <&gpucc GPU_CC_CX_GMU_CLK>, + <&gpucc GPU_CC_CXO_CLK>, + <&nwgcc NW_GCC_HSCNOC_GPU_AXI_CLK>, + <&gpucc GPU_CC_MEMNOC_GFX_CLK>, + <&gpucc GPU_CC_HUB_CX_INT_CLK>; + clock-names = "ahb", + "gmu", + "cxo", + "axi", + "memnoc", + "hub"; + + power-domains = <&gpucc GPU_CC_CX_GDSC>, + <&gpucc GPU_CC_GX_GDSC>; + power-domain-names = "cx", + "gx"; + + operating-points-v2 = <&gmu_opp_table_0>; + + gmu_opp_table_0: opp-table { + compatible = "operating-points-v2"; + + opp-416666000 { + opp-hz = /bits/ 64 <416666000>; + opp-level = ; + }; + + opp-625000000 { + opp-hz = /bits/ 64 <625000000>; + opp-level = ; + }; + }; +}; + +&gpu_0 { + operating-points-v2 = <&gpu_opp_table_0>; + + interconnects = <&hscnoc MASTER_GFX3D QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "gfx-mem"; + + gpu_opp_table_0: opp-table { + compatible = "operating-points-v2-adreno", + "operating-points-v2"; + + opp-468000000 { + opp-hz = /bits/ 64 <468000000>; + opp-level = ; + opp-peak-kBps = <781250>; + }; + + opp-625000000 { + opp-hz = /bits/ 64 <625000000>; + opp-level = ; + opp-peak-kBps = <6075000>; + }; + + opp-735000000 { + opp-hz = /bits/ 64 <735000000>; + opp-level = ; + opp-peak-kBps = <8175000>; + }; + + opp-854000000 { + opp-hz = /bits/ 64 <854000000>; + opp-level = ; + opp-peak-kBps = <10687500>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-level = ; + opp-peak-kBps = <12450000>; + }; + }; +}; + &i2c0 { clocks = <&segcc SE_GCC_QUPV3_WRAP0_S0_CLK>; clock-names = "se"; diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 02249a3099e1b..9c1e394c57502 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -2549,6 +2549,49 @@ reg = <0x0 0x01f60000 0x0 0xa0000>; }; + gpu_0: gpu@3d00000 { + compatible = "qcom,adreno-43051701", "qcom,adreno"; + reg = <0x0 0x03d00000 0x0 0x40000>, + <0x0 0x03d9e000 0x0 0x2000>, + <0x0 0x03d61000 0x0 0x800>; + reg-names = "kgsl_3d0_reg_memory", + "cx_mem", + "cx_dbgc"; + + interrupts = ; + + iommus = <&adreno_smmu_0 0 0x0>, + <&adreno_smmu_0 1 0x0>; + + qcom,gmu = <&gmu_0>; + #cooling-cells = <2>; + + status = "disabled"; + + gpu_0_zap_shader: zap-shader { + memory-region = <&gpu_microcode_mem>; + }; + }; + + gmu_0: gmu@3d6a000 { + compatible = "qcom,adreno-gmu-753.1", "qcom,adreno-gmu"; + reg = <0x0 0x03d6a000 0x0 0x35000>, + <0x0 0x03d50000 0x0 0x10000>, + <0x0 0x0b2a0000 0x0 0x10000>; + reg-names = "gmu", + "rscc", + "gmu_pdc"; + + interrupts = , + ; + interrupt-names = "hfi", + "gmu"; + + iommus = <&adreno_smmu_0 5 0x0>; + + status = "disabled"; + }; + adreno_smmu_0: iommu@3da0000 { compatible = "qcom,nord-smmu-500", "qcom,adreno-smmu", From b3792d599a65e020c7bf4f07028f4bdd58a75235 Mon Sep 17 00:00:00 2001 From: Aastha Pandey Date: Fri, 9 Oct 2026 02:36:38 +0530 Subject: [PATCH 1096/1133] PENDING: arm64: dts: qcom: nord: Add GPU cooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the CPU, the GPU does not throttle its speed automatically when it reaches high temperatures. Set up GPU cooling on Nord by throttling the Adreno 753 GPU when it reaches 105°C. Label the passive trip points of the GPU thermal zones, map them to the GPU as a cooling device, and add a passive polling delay so the thermal framework can monitor the zones while throttling. The thermal zones and the GPU node are both described in nord.dtsi, so do it there. On the GearVM variant the GPU node stays disabled, no cooling device gets registered for it, and the maps are simply left unbound. Signed-off-by: Aastha Pandey Signed-off-by: Akhil P Oommen Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord.dtsi | 177 +++++++++++++++++++++++------ 1 file changed, 145 insertions(+), 32 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 9c1e394c57502..9764bd2224099 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include #include "nord-ipcc.h" @@ -9558,12 +9559,12 @@ }; gpuss-0-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens6 1>; trips { - trip-point0 { + gpuss0_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9575,15 +9576,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss0_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-1-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens6 2>; trips { - trip-point0 { + gpuss1_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9595,15 +9603,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss1_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-2-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens6 3>; trips { - trip-point0 { + gpuss2_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9615,15 +9630,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss2_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpu-0-0-0-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens6 4>; trips { - trip-point0 { + gpu_0_0_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9635,6 +9657,13 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpu_0_0_0_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-1-0-thermal { @@ -9778,12 +9807,12 @@ }; gpuss-0-1-1-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens6 12>; trips { - trip-point0 { + gpuss_0_1_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9795,15 +9824,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_0_1_1_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-1-1-1-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens6 13>; trips { - trip-point0 { + gpuss_1_1_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9815,15 +9851,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_1_1_1_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-2-1-1-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens6 14>; trips { - trip-point0 { + gpuss_2_1_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9835,15 +9878,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_2_1_1_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpu-0-1-1-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens6 15>; trips { - trip-point0 { + gpu_0_1_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9855,6 +9905,13 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpu_0_1_1_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; amux-7-thermal { @@ -9878,12 +9935,12 @@ }; gpuss-0-1-0-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens7 1>; trips { - trip-point0 { + gpuss_0_1_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9895,15 +9952,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_0_1_0_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-1-1-0-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens7 2>; trips { - trip-point0 { + gpuss_1_1_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9915,15 +9979,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_1_1_0_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-2-1-0-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens7 3>; trips { - trip-point0 { + gpuss_2_1_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9935,15 +10006,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_2_1_0_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpu-0-1-0-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens7 4>; trips { - trip-point0 { + gpu_0_1_0_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -9955,6 +10033,13 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpu_0_1_0_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-1-2-thermal { @@ -10098,12 +10183,12 @@ }; gpuss-0-1-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens7 12>; trips { - trip-point0 { + gpuss_0_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -10115,15 +10200,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_0_1_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-1-0-1-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens7 13>; trips { - trip-point0 { + gpuss_1_0_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -10135,15 +10227,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_1_0_1_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpuss-2-0-1-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens7 14>; trips { - trip-point0 { + gpuss_2_0_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -10155,15 +10254,22 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpuss_2_0_1_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; gpu-0-0-1-thermal { - polling-delay-passive = <0>; + polling-delay-passive = <10>; polling-delay = <0>; thermal-sensors = <&tsens7 15>; trips { - trip-point0 { + gpu_0_0_1_alert0: trip-point0 { temperature = <105000>; hysteresis = <10000>; type = "passive"; @@ -10175,6 +10281,13 @@ type = "passive"; }; }; + + cooling-maps { + map0 { + trip = <&gpu_0_0_1_alert0>; + cooling-device = <&gpu_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; }; }; From 9a9ef62216cb033d9e8a36650f6673f5452efba7 Mon Sep 17 00:00:00 2001 From: Shivam Rawat Date: Fri, 9 Oct 2026 02:36:39 +0530 Subject: [PATCH 1097/1133] PENDING: arm64: dts: qcom: nord-rrd: Enable Adreno 753 GPU Enable the Adreno 753 GPU on the Nord RRD board and provide the firmware path for its zap shader. Signed-off-by: Shivam Rawat Signed-off-by: Akhil P Oommen Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-rrd.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-rrd.dts b/arch/arm64/boot/dts/qcom/nord-rrd.dts index a12760a18412c..94ac73add0e26 100644 --- a/arch/arm64/boot/dts/qcom/nord-rrd.dts +++ b/arch/arm64/boot/dts/qcom/nord-rrd.dts @@ -652,6 +652,18 @@ }; }; +&gmu_0 { + status = "okay"; +}; + +&gpu_0 { + status = "okay"; +}; + +&gpu_0_zap_shader { + firmware-name = "qcom/nord/gen71300_zap.mbn"; +}; + &i2c7 { clock-frequency = <400000>; From e1663ec821499b7d1d782ece2a79eb81f7a337da Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 11 Oct 2026 14:26:09 +0800 Subject: [PATCH 1098/1133] PENDING: arm64: dts: qcom: nord-ride-embedded: Enable Adreno 753 GPU Enable the Adreno 753 GPU on the Nord Ride Embedded board and provide the firmware path for its zap shader. Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-ride-embedded.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index b54306ecad04b..859da790b0787 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -665,6 +665,18 @@ }; }; +&gmu_0 { + status = "okay"; +}; + +&gpu_0 { + status = "okay"; +}; + +&gpu_0_zap_shader { + firmware-name = "qcom/nord/gen71300_zap.mbn"; +}; + &i2c9 { clock-frequency = <400000>; From ebeef9828790a9dfc4fe9cc575d707442774bb12 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 28 Oct 2026 20:34:45 +0800 Subject: [PATCH 1099/1133] FROMLIST: gpio: shared-proxy: Fix race between concurrent first users The proxy lets a consumer set the line direction and reset the default value and vote tally only when usecnt == 1, i.e. when it is the sole requester. But request() and direction_output() take the descriptor mutex separately. When two consumers probe concurrently, both request the line before either configures it, both see usecnt == 2, both fall into the shared path, read back the still unconfigured direction (input) and fail with -EPERM. On Nord RRD the two DAC supplies are reg-fixed-voltage regulators sharing tlmm GPIO 41. They probe asynchronously and intermittently both fail, leaving the codecs without supplies: reg-fixed-voltage regulator-3p3-dac: setup of GPIO (default) failed: -1 reg-fixed-voltage regulator-5p0-dac: setup of GPIO (default) failed: -1 Requesting the line is not evidence that a consumer has claimed it. Instead, count proxies that have actually configured the line (set its direction or voted for a value) in a new cfgcnt, with a per-proxy configured flag, and allow (re)initialization only while no other proxy has done so. A consumer obtained with GPIOD_ASIS that votes via gpiod_set_value() without ever setting the direction counts as configured, so a later user can never reset def_val/votecnt behind its vote. The count is dropped when the proxy frees the line. Fixes: e992d54c6f97 ("gpio: shared-proxy: implement the shared GPIO proxy driver") Link: https://lore.kernel.org/r/20261028123448.510401-2-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- drivers/gpio/gpio-shared-proxy.c | 78 ++++++++++++++++++++++++++++---- drivers/gpio/gpiolib-shared.h | 1 + 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-shared-proxy.c b/drivers/gpio/gpio-shared-proxy.c index bc69b8729d196..2e9ccd8a8d835 100644 --- a/drivers/gpio/gpio-shared-proxy.c +++ b/drivers/gpio/gpio-shared-proxy.c @@ -21,9 +21,37 @@ struct gpio_shared_proxy_data { struct gpio_chip gc; struct gpio_shared_desc *shared_desc; struct device *dev; + bool configured; bool voted_change; }; +/* + * A proxy may (re)initialize the line - set its direction and reset the + * default value and the vote tally - only while no other proxy has set the + * direction or voted for a value. Requesting the line is not enough: consumers + * may request concurrently, so counting requests lets every one of them + * conclude that it is not first. + */ +static bool gpio_shared_proxy_may_init(struct gpio_shared_proxy_data *proxy) +{ + unsigned int cfgcnt = proxy->shared_desc->cfgcnt; + + lockdep_assert_held(&proxy->shared_desc->mutex); + + return !cfgcnt || (cfgcnt == 1 && proxy->configured); +} + +static void gpio_shared_proxy_mark_configured(struct gpio_shared_proxy_data *proxy) +{ + lockdep_assert_held(&proxy->shared_desc->mutex); + + if (proxy->configured) + return; + + proxy->configured = true; + proxy->shared_desc->cfgcnt++; +} + static int gpio_shared_proxy_set_unlocked(struct gpio_shared_proxy_data *proxy, int value) { @@ -117,6 +145,11 @@ static void gpio_shared_proxy_free(struct gpio_chip *gc, unsigned int offset) proxy->shared_desc->usecnt--; + if (proxy->configured) { + proxy->configured = false; + shared_desc->cfgcnt--; + } + dev_dbg(proxy->dev, "Shared GPIO freed, number of users: %u\n", proxy->shared_desc->usecnt); } @@ -131,7 +164,7 @@ static int gpio_shared_proxy_set_config(struct gpio_chip *gc, guard(mutex)(&shared_desc->mutex); - if (shared_desc->usecnt > 1) { + if (!gpio_shared_proxy_may_init(proxy)) { if (shared_desc->cfg != cfg) { dev_dbg(proxy->dev, "Shared GPIO's configuration already set, accepting changes but users may conflict!!\n"); @@ -155,15 +188,21 @@ static int gpio_shared_proxy_direction_input(struct gpio_chip *gc, struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc); struct gpio_shared_desc *shared_desc = proxy->shared_desc; struct gpio_desc *desc = shared_desc->desc; - int dir; + int ret, dir; guard(mutex)(&shared_desc->mutex); - if (shared_desc->usecnt == 1) { + if (gpio_shared_proxy_may_init(proxy)) { dev_dbg(proxy->dev, - "Only one user of this shared GPIO, allowing to set direction to input\n"); + "No other user configured this shared GPIO, allowing to set direction to input\n"); + + ret = gpiod_direction_input(desc); + if (ret) + return ret; - return gpiod_direction_input(desc); + gpio_shared_proxy_mark_configured(proxy); + + return 0; } dir = gpiod_get_direction(desc); @@ -176,6 +215,8 @@ static int gpio_shared_proxy_direction_input(struct gpio_chip *gc, return -EPERM; } + gpio_shared_proxy_mark_configured(proxy); + return 0; } @@ -189,18 +230,20 @@ static int gpio_shared_proxy_direction_output(struct gpio_chip *gc, guard(mutex)(&shared_desc->mutex); - if (shared_desc->usecnt == 1) { + if (gpio_shared_proxy_may_init(proxy)) { dev_dbg(proxy->dev, - "Only one user of this shared GPIO, allowing to set direction to output with value '%s'\n", + "No other user configured this shared GPIO, allowing to set direction to output with value '%s'\n", str_high_low(value)); ret = gpiod_direction_output(desc, value); if (ret) return ret; + /* Only this proxy can have voted, so the tally is ours to reset */ shared_desc->def_val = value; shared_desc->votecnt = 0; proxy->voted_change = false; + gpio_shared_proxy_mark_configured(proxy); return 0; } @@ -215,7 +258,13 @@ static int gpio_shared_proxy_direction_output(struct gpio_chip *gc, return -EPERM; } - return gpio_shared_proxy_set_unlocked(proxy, value); + ret = gpio_shared_proxy_set_unlocked(proxy, value); + if (ret) + return ret; + + gpio_shared_proxy_mark_configured(proxy); + + return 0; } static int gpio_shared_proxy_get_cansleep(struct gpio_chip *gc, @@ -230,10 +279,21 @@ static int gpio_shared_proxy_set_cansleep(struct gpio_chip *gc, unsigned int offset, int value) { struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc); + int ret; guard(mutex)(&proxy->shared_desc->mutex); - return gpio_shared_proxy_set_unlocked(proxy, value); + /* + * A GPIOD_ASIS consumer may vote without ever setting the direction; + * count it as configured so a later user can't reset its vote. + */ + ret = gpio_shared_proxy_set_unlocked(proxy, value); + if (ret) + return ret; + + gpio_shared_proxy_mark_configured(proxy); + + return 0; } static int gpio_shared_proxy_get_direction(struct gpio_chip *gc, diff --git a/drivers/gpio/gpiolib-shared.h b/drivers/gpio/gpiolib-shared.h index 618756f6c6aaf..ae10506b7029f 100644 --- a/drivers/gpio/gpiolib-shared.h +++ b/drivers/gpio/gpiolib-shared.h @@ -41,6 +41,7 @@ struct gpio_shared_desc { struct gpio_desc *desc; unsigned long cfg; unsigned int usecnt; + unsigned int cfgcnt; unsigned int votecnt; int def_val; struct mutex mutex; /* serializes all proxy operations on this descriptor */ From 9e2147b91da6c9d6c2c66f759d0a2c8936ab5b43 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 28 Oct 2026 20:34:46 +0800 Subject: [PATCH 1100/1133] FROMLIST: gpio: shared-proxy: Drop the vote of a released proxy on write failure When a proxy that voted for a value change frees the line, it calls gpio_shared_proxy_set_unlocked() to withdraw its vote. If it is the last voter and restoring the default value fails, that function returns early, leaving votecnt incremented and voted_change set. The consumer is gone, but its vote is not. The line is held at the non-default value for all remaining users, since votecnt can never drop to zero again. And the proxy data outlives the request, so voted_change is still set when the line is requested again. If another user has reinitialized the line in between, resetting votecnt to 0, the stale proxy's next vote for the default value decrements votecnt from 0 and underflows it. Drop the vote unconditionally on release, after reporting the failure, since the consumer is going away regardless. Fixes: e992d54c6f97 ("gpio: shared-proxy: implement the shared GPIO proxy driver") Link: https://lore.kernel.org/r/20261028123448.510401-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- drivers/gpio/gpio-shared-proxy.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-shared-proxy.c b/drivers/gpio/gpio-shared-proxy.c index 2e9ccd8a8d835..4eae3c9a5168e 100644 --- a/drivers/gpio/gpio-shared-proxy.c +++ b/drivers/gpio/gpio-shared-proxy.c @@ -138,9 +138,13 @@ static void gpio_shared_proxy_free(struct gpio_chip *gc, unsigned int offset) if (proxy->voted_change) { ret = gpio_shared_proxy_set_unlocked(proxy, shared_desc->def_val); - if (ret) + if (ret) { dev_err(proxy->dev, "Failed to unset the shared GPIO value on release: %d\n", ret); + /* The consumer is going away regardless, drop its vote */ + shared_desc->votecnt--; + proxy->voted_change = false; + } } proxy->shared_desc->usecnt--; From 0c099b3f48d346954463c387dc61267ee2392181 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 28 Oct 2026 20:34:47 +0800 Subject: [PATCH 1101/1133] FROMLIST: gpio: shared-proxy: Drive the default value when no votes are cast A consumer that requests a shared line with GPIOD_ASIS never calls direction_output(), so def_val keeps its initial value of 0. If the line was left high, for instance by the bootloader, a later gpiod_set_value(0) from that consumer matches def_val and the proxy treats it as withdrawing a vote it never cast. It returns success without writing the hardware, and the line stays high. The consumer has no way to tell. Its request to drive the line low is silently ignored until it first votes for high and then withdraws that vote. When the requested value is the default and no votes are outstanding, write it to the hardware instead of returning early. With votes outstanding the request remains a no-op, as the line must stay at the voted value. Do this for all lines, not only GPIOD_ASIS ones. A line configured via direction_output() can be left at the non-default value as well: when a proxy releases the line and restoring the default fails, its vote is dropped regardless, leaving votecnt at 0 with the line at the voted value. The write lets any remaining user bring it back to the default. In the common case it is a redundant write of the value the line already has, and it only happens when a proxy that has not voted sets the default. Fixes: e992d54c6f97 ("gpio: shared-proxy: implement the shared GPIO proxy driver") Link: https://lore.kernel.org/r/20261028123448.510401-4-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- drivers/gpio/gpio-shared-proxy.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-shared-proxy.c b/drivers/gpio/gpio-shared-proxy.c index 4eae3c9a5168e..75d0d617941f2 100644 --- a/drivers/gpio/gpio-shared-proxy.c +++ b/drivers/gpio/gpio-shared-proxy.c @@ -85,9 +85,16 @@ gpio_shared_proxy_set_unlocked(struct gpio_shared_proxy_data *proxy, int value) } /* Desired value is the default. */ - if (!proxy->voted_change) - /* We didn't vote for change previously, nothing to do. */ + if (!proxy->voted_change) { + /* + * With no votes outstanding the line should be at the + * default, but a GPIOD_ASIS line may have been left at the + * opposite value. Drive it there. + */ + if (!shared_desc->votecnt) + ret = gpiod_set_value_cansleep(desc, shared_desc->def_val); goto out; + } /* We previously voted for change. */ if (shared_desc->votecnt == 1) { From 4be33e0ac5c62c81a832957246e57fa179c73f83 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 28 Oct 2026 20:34:48 +0800 Subject: [PATCH 1102/1133] FROMLIST: gpio: shared-proxy: Drop the vote when switching to input A proxy that is the only one to have configured a shared line may reinitialize it. When it sets the direction to output, the proxy resets the vote tally, but when it sets the direction to input, it leaves any vote it cast in place, although an input line carries no value. That vote outlives its meaning. When the consumer releases the line, gpio_shared_proxy_free() tries to withdraw it by writing the default value, which gpiolib refuses on an input line: Failed to unset the shared GPIO value on release: -1 This happens, for instance, when a consumer votes for a change with gpiod_set_value() after setting the line to output and then switches it to input. Clear the vote when the proxy reinitializes the line as input, as the output path already does. No other proxy can hold a vote at that point: voting marks a proxy configured, and a proxy that frees the line drops its vote. Fixes: e992d54c6f97 ("gpio: shared-proxy: implement the shared GPIO proxy driver") Link: https://lore.kernel.org/r/20261028123448.510401-5-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- drivers/gpio/gpio-shared-proxy.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpio/gpio-shared-proxy.c b/drivers/gpio/gpio-shared-proxy.c index 75d0d617941f2..b2f2301e9e64c 100644 --- a/drivers/gpio/gpio-shared-proxy.c +++ b/drivers/gpio/gpio-shared-proxy.c @@ -211,6 +211,9 @@ static int gpio_shared_proxy_direction_input(struct gpio_chip *gc, if (ret) return ret; + /* An input carries no value, drop any vote this proxy cast */ + shared_desc->votecnt = 0; + proxy->voted_change = false; gpio_shared_proxy_mark_configured(proxy); return 0; From 2b3b231502b05363894af7e9198cc1705463b4dc Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 8 Oct 2026 16:56:40 +0800 Subject: [PATCH 1103/1133] FROMLIST: arm64: dts: qcom: nord: Wire UFS PHY symbol clocks to NEGCC Pass UFS PHY symbol clocks to NEGCC rather than leaving the NEGCC UFS symbol muxes orphaned. Reviewed-by: Taniya Das Reviewed-by: Abel Vesa Reviewed-by: Konrad Dybcio Reviewed-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20261008085640.3512895-1-shengchao.guo@oss.qualcomm.com Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 953b8c033c738..bd70f5e51ce10 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -2476,9 +2476,9 @@ reg = <0x0 0x08900000 0x0 0xf4200>; clocks = <&bi_tcxo_div2>, <&sleep_clk>, - <0>, - <0>, - <0>, + <&ufs_mem_phy 0>, + <&ufs_mem_phy 1>, + <&ufs_mem_phy 2>, <&usb_1_qmpphy QMP_USB43DP_USB3_PIPE_CLK>, <&usb_0_qmpphy QMP_USB43DP_USB3_PIPE_CLK>; #clock-cells = <1>; From f05791bdf69102c5779391b3f88f3fb33b059be3 Mon Sep 17 00:00:00 2001 From: Navya Malempati Date: Tue, 8 Sep 2026 13:43:08 +0530 Subject: [PATCH 1104/1133] FROMLIST: soc: qcom: qcom_stats: Add support for NSP subsystem stats Add SMEM items for four NSP subsystems stats which are present in Nord SoC. Rename CDSP stats as CDSP_NSP as both use same PID and SMEM item id. Add new entries for NSP1/2/3. Signed-off-by: Navya Malempati Reviewed-by: Maulik Shah Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20260908-nord_stats-v1-1-a55adb083d65@oss.qualcomm.com --- drivers/soc/qcom/qcom_stats.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom_stats.c b/drivers/soc/qcom/qcom_stats.c index 3422d6df7b51f..d3dd6d98a3242 100644 --- a/drivers/soc/qcom/qcom_stats.c +++ b/drivers/soc/qcom/qcom_stats.c @@ -43,8 +43,11 @@ static const struct subsystem_data subsystems[] = { { "modem", 605, 1 }, { "wpss", 605, 13 }, { "adsp", 606, 2 }, - { "cdsp", 607, 5 }, + { "cdsp_nsp", 607, 5 }, { "cdsp1", 607, 12 }, + { "cdsp_nsp_1", 607, 69 }, + { "cdsp_nsp_2", 607, 133 }, + { "cdsp_nsp_3", 607, 197 }, { "gpdsp0", 607, 17 }, { "gpdsp1", 607, 18 }, { "soccp", 607, 19 }, From 95017b9312bca57566964b5f71de520a0ade25a3 Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Mon, 5 Oct 2026 23:13:03 +0530 Subject: [PATCH 1105/1133] PENDING: arm64: dts: qcom: nord-ride-embedded: disable mdss1 Disable MDSS1 and its related nodes on the Nord Ride platform: MDSS1, its DP controllers (mdss1_dp0/mdss1_dp1), the DP2/DP3 PHYs and the eDP2/eDP3 connectors routed to them. Signed-off-by: Mahadevan P --- arch/arm64/boot/dts/qcom/nord-ride-embedded.dts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts index 859da790b0787..08b7de615ccf5 100644 --- a/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts +++ b/arch/arm64/boot/dts/qcom/nord-ride-embedded.dts @@ -86,6 +86,8 @@ label = "eDP2"; type = "full-size"; + status = "disabled"; + port { dp2_connector_in: endpoint { remote-endpoint = <&mdss1_dp0_out>; @@ -98,6 +100,8 @@ label = "eDP3"; type = "full-size"; + status = "disabled"; + port { dp3_connector_in: endpoint { remote-endpoint = <&mdss1_dp1_out>; @@ -874,11 +878,11 @@ }; &mdss1 { - status = "okay"; + status = "disabled"; }; &mdss1_dp0 { - status = "okay"; + status = "disabled"; }; &mdss1_dp0_out { @@ -891,11 +895,11 @@ vdda-phy-supply = <&vreg_l2h_1p2>; vdda-pll-supply = <&vreg_l1h_0p9>; - status = "okay"; + status = "disabled"; }; &mdss1_dp1 { - status = "okay"; + status = "disabled"; }; &mdss1_dp1_out { @@ -908,7 +912,7 @@ vdda-phy-supply = <&vreg_l2h_1p2>; vdda-pll-supply = <&vreg_l1h_0p9>; - status = "okay"; + status = "disabled"; }; &pmau0102_i_gpios { From d5a09d23e56dd36e955d9018248e36925cb97a1a Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Tue, 6 Oct 2026 08:41:49 +0200 Subject: [PATCH 1106/1133] FROMLIST: firmware: qcom: pas_tee: handle a NULL resource table Stopping a remote processor clears its cached resource table pointer but leaves the size set. On restart, qcom_pas_tee_get_rsc_table() copies from NULL when the firmware has no resource table: pc : __pi_memcpy_generic+0x110/0x22c lr : qcom_pas_tee_get_rsc_table+0xf0/0x244 Zero the input size when the table is NULL so the copy is skipped. Fixes: b6f7978da0c4 ("firmware: qcom: Add a PAS TEE service") Signed-off-by: Jorge Ramirez-Ortiz Reviewed-by: Sumit Garg Link: https://lore.kernel.org/r/20261006064747.2454980-1-jorge.ramirez@oss.qualcomm.com --- drivers/firmware/qcom/qcom_pas_tee.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/qcom_pas_tee.c b/drivers/firmware/qcom/qcom_pas_tee.c index ac33a00687aa1..a52a7df385ff0 100644 --- a/drivers/firmware/qcom/qcom_pas_tee.c +++ b/drivers/firmware/qcom/qcom_pas_tee.c @@ -230,12 +230,15 @@ static void *qcom_pas_tee_get_rsc_table(struct device *dev, }, [1] = { .attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT, - .u.memref.size = input_rt_size, } }; void *rt_buf = NULL; int ret; + if (!input_rt) + input_rt_size = 0; + param[1].u.memref.size = input_rt_size; + ret = tee_client_invoke_func(data->ctx, &inv_arg, param); if (ret < 0 || inv_arg.ret != 0) { dev_err(dev, "PAS get RT failed, pas_id: %d, ret: %d, err: 0x%x\n", From b13e6a38d4145d6ce23abe1978573550abb1098a Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Wed, 7 Oct 2026 12:29:25 +0530 Subject: [PATCH 1107/1133] PENDING: arm64: dts: qcom: nord: Add EL2 overlay for remoteproc SMMU mappings When running Linux directly at EL2, the SMMU is owned by the kernel. This overlay provides the firmware-loading stream IDs for each remote processor, allowing the kernel to program the SMMU directly instead of relying on the hypervisor for IOMMU configuration. The overlay is applied to nord-ride-embedded and nord-rrd device trees. This is an RFC (Request for Comments). Signed-off-by: Anurag Pateriya --- arch/arm64/boot/dts/qcom/Makefile | 7 +++++ .../boot/dts/qcom/nord-embedded-el2.dtso | 27 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index b77bbc5030d8c..e2bf4cd45f20b 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -175,7 +175,14 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-poplar.dtb dtb-$(CONFIG_ARCH_QCOM) += msm8998-xiaomi-sagit.dtb dtb-$(CONFIG_ARCH_QCOM) += nord-ride.dtb dtb-$(CONFIG_ARCH_QCOM) += nord-ride-embedded.dtb + +nord-ride-embedded-el2-dtbs := nord-ride-embedded.dtb nord-embedded-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += nord-ride-embedded-el2.dtb + dtb-$(CONFIG_ARCH_QCOM) += nord-rrd.dtb + +nord-rrd-el2-dtbs := nord-rrd.dtb nord-embedded-el2.dtbo +dtb-$(CONFIG_ARCH_QCOM) += nord-rrd-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += purwa-iot-evk.dtb purwa-iot-evk-el2-dtbs := purwa-iot-evk.dtb x1-el2.dtbo diff --git a/arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso b/arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso new file mode 100644 index 0000000000000..73c46fb9e5ad1 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +/dts-v1/; +/plugin/; + +&remoteproc_adsp { + iommus = <&apps_smmu_0 0x09e0 0x0>; +}; + +&remoteproc_cdsp0 { + iommus = <&apps_smmu_2 0x0360 0x0>; +}; + +&remoteproc_cdsp1 { + iommus = <&apps_smmu_2 0x0760 0x0>; +}; + +&remoteproc_cdsp2 { + iommus = <&apps_smmu_2 0x0b60 0x0>; +}; + +&remoteproc_cdsp3 { + iommus = <&apps_smmu_2 0x0f60 0x0>; +}; From 7a6227bc802a2ed7f37fb837b0344d4e8742f5c7 Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Sun, 11 Oct 2026 11:10:43 +0530 Subject: [PATCH 1108/1133] PENDING: arm64: dts: qcom: nord-embedded-el2: Add SOCCP iommus Co-Authored-By: Claude Sonnet 5 Signed-off-by: Anurag Pateriya --- arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso b/arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso index 73c46fb9e5ad1..1ea08269e9aa1 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso +++ b/arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso @@ -25,3 +25,8 @@ &remoteproc_cdsp3 { iommus = <&apps_smmu_2 0x0f60 0x0>; }; +&remoteproc_soccp { + iommus = <&apps_smmu_0 0x1960 0x5>, + <&apps_smmu_0 0x1966 0x0>; +}; + From 211acb2b889746a25a8330a17b782c3000268d65 Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Fri, 23 Oct 2026 17:28:25 +0530 Subject: [PATCH 1109/1133] PENDING: arm64: dts: qcom: nord: Add EL2 support for Iris Add support for IRIS on nord when Linux host running at EL2. Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso b/arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso index 1ea08269e9aa1..54c7fa52fb399 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso +++ b/arch/arm64/boot/dts/qcom/nord-embedded-el2.dtso @@ -6,6 +6,12 @@ /dts-v1/; /plugin/; +&iris { + video-firmware { + iommus = <&apps_smmu_1 0x0962 0x0000>; + }; +}; + &remoteproc_adsp { iommus = <&apps_smmu_0 0x09e0 0x0>; }; From fcf1215c198450d332d7fc2587d40d61c34bae8c Mon Sep 17 00:00:00 2001 From: Anurag Pateriya Date: Wed, 12 Aug 2026 14:16:12 +0530 Subject: [PATCH 1110/1133] PENDING: arm64: dts: qcom: nord: Add reboot-mode for EDL and bootloader Add the reboot-mode node under psci with vendor-specific SYSTEM_RESET2 parameters for EDL and bootloader. This lets userspace request "reboot bootloader" and "reboot edl" via the standard reboot-mode framework. Signed-off-by: Anurag Pateriya --- arch/arm64/boot/dts/qcom/nord.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/nord.dtsi b/arch/arm64/boot/dts/qcom/nord.dtsi index 9764bd2224099..f3c50225bf81f 100644 --- a/arch/arm64/boot/dts/qcom/nord.dtsi +++ b/arch/arm64/boot/dts/qcom/nord.dtsi @@ -547,6 +547,11 @@ #power-domain-cells = <0>; domain-idle-states = <&domain_ss3>; }; + + reboot-mode { + mode-bootloader = <0x80010001 0x2>; + mode-edl = <0x80000000 0x1>; + }; }; reserved_memory: reserved-memory { From b19aeb85a0efa3d6679bbbdb8c4c70287e49aa9b Mon Sep 17 00:00:00 2001 From: Vinayak Katoch Date: Thu, 29 Oct 2026 20:11:45 +0530 Subject: [PATCH 1111/1133] FROMLIST: arm64: dts: qcom: sm8750: Fix iommu stream ID masks for CDSP compute CBs The stream ID masks of compute-cb@12 and compute-cb@14 are wrong, so these two context banks fail to probe. Fix the masks: - compute-cb@12: SID 0x0c2c, mask 0x20 -> 0x0 - compute-cb@14: SID 0x0c0e, mask 0x20 -> 0x40 Link: https://lore.kernel.org/all/20261029-sm8750-fix-sid-masks-v1-1-5ed50a1a0342@oss.qualcomm.com/ Fixes: 58471055ae76 ("arm64: dts: qcom: sm8750: Add CDSP") Cc: stable@vger.kernel.org Signed-off-by: Vinayak Katoch --- arch/arm64/boot/dts/qcom/sm8750.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi index b4df113e43908..d6caf061e136b 100644 --- a/arch/arm64/boot/dts/qcom/sm8750.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi @@ -7648,7 +7648,7 @@ compatible = "qcom,fastrpc-compute-cb"; reg = <12>; iommus = <&apps_smmu 0x196c 0x0>, - <&apps_smmu 0x0c2c 0x20>, + <&apps_smmu 0x0c2c 0x0>, <&apps_smmu 0x0c0c 0x40>, <&apps_smmu 0x19cc 0x0>; dma-coherent; @@ -7669,7 +7669,7 @@ compatible = "qcom,fastrpc-compute-cb"; reg = <14>; iommus = <&apps_smmu 0x196e 0x0>, - <&apps_smmu 0x0c0e 0x20>, + <&apps_smmu 0x0c0e 0x40>, <&apps_smmu 0x19ce 0x0>; dma-coherent; }; From dbd0f708205d26bff49cfb3090f9d0c6c4c29cf6 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Sun, 18 Oct 2026 19:15:44 -0700 Subject: [PATCH 1112/1133] FROMLIST: arm64: dts: qcom: glymur: Set snps,resume-hs-terminations for USB controllers The DWC3 controllers on Glymur are paired with the M31 eUSB2 PHY. According to HPG, host-mode USB2 L2/L1 resume with this PHY, GUCTL1[10] (RESUME_OPMODE_HS_HOST) must be set. Without this bit setting, USB2 HS device cannot be reset after it is runtime resumed. For example, after: echo on > /sys/bus/usb/devices/1-1/power/control PORTSC.PR never clears (PORTSC = 0xe11) and the hub driver fails with "port_wait_reset: err = -16". Set snps,resume-hs-terminations on all Glymur USB controllers. This makes dwc3 core set GUCTL1[10] and fixes the issue, tested on Glymur CRD. Link: https://lore.kernel.org/all/20261019021547.1694088-2-peter.chen@oss.qualcomm.com/ Tested-by: Krishna Kurapati krishna.kurapati@oss.qualcomm.com Reviewed-by: Konrad Dybcio Fixes: 4eee57dd4df9 ("arm64: dts: qcom: glymur: Add USB related nodes") Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Peter Chen Reviewed-by: Abel Vesa Signed-off-by: Krishna Kurapati --- arch/arm64/boot/dts/qcom/glymur.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi index b86047cc23187..fc05d82627e3c 100644 --- a/arch/arm64/boot/dts/qcom/glymur.dtsi +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi @@ -5645,6 +5645,7 @@ tx-fifo-resize; snps,dis_u2_susphy_quirk; snps,dis_enblslpm_quirk; + snps,resume-hs-terminations; usb-role-switch; wakeup-source; @@ -5735,6 +5736,7 @@ tx-fifo-resize; snps,dis_u2_susphy_quirk; snps,dis_enblslpm_quirk; + snps,resume-hs-terminations; usb-role-switch; wakeup-source; @@ -5825,6 +5827,7 @@ tx-fifo-resize; snps,dis_u2_susphy_quirk; snps,dis_enblslpm_quirk; + snps,resume-hs-terminations; usb-role-switch; wakeup-source; @@ -5914,6 +5917,7 @@ tx-fifo-resize; snps,dis_u2_susphy_quirk; snps,dis_enblslpm_quirk; + snps,resume-hs-terminations; maximum-speed = "high-speed"; @@ -6003,6 +6007,7 @@ tx-fifo-resize; snps,dis_u2_susphy_quirk; snps,dis_enblslpm_quirk; + snps,resume-hs-terminations; dr_mode = "host"; wakeup-source; From e4006cbe0b19e9f4b9bcca045107f2ec375f4e2f Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Thu, 5 Nov 2026 15:17:54 +0530 Subject: [PATCH 1113/1133] Revert "FROMLIST: drm/msm/dpu: Add support for DPU 12.1 on Nord" This reverts commit 13cd1ce1298a628fda47c7ae7898db85b3c3e31e. Remove the v1 Nord DPU catalog before applying the complete v2 display and eDP PHY series. Resolve the catalog's modify/delete conflict by removing the v1 file, which was subsequently changed only to drop its obsolete max_mixer_width initializer. Keep the existing LM cleanup in place; the replacement v2 catalog must not reintroduce that field. Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-0-a2ab9af954d2@oss.qualcomm.com/ Signed-off-by: Mahadevan P --- .../drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h | 587 ------------------ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 - .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 - drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 - 5 files changed, 592 deletions(-) delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h deleted file mode 100644 index 0d494ea350037..0000000000000 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h +++ /dev/null @@ -1,587 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. - * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. - */ - -#ifndef _DPU_12_1_NORD_H -#define _DPU_12_1_NORD_H - -/* - * NORD DPU 12.1 catalog header. Generated from hardware summary YAML for - * MDSS 12.1 - DPU 1499A (Nordschleife). This is a DP-only chip with no DSI. - * - * All register addresses and xin_id values below are borrowed from the - * reference chip (sm8750, MDSS 12.0) and precedent chips (Lemans, Glymur). - * Nord's YAML provides only block counts and feature statements, not addresses. - * See FIXME(REG_ADDR) markers throughout for borrowed values requiring - * verification against a real Nord register map before production use. - * - * Key differences vs sm8750: - * - 8 DSPP blocks (4 full + 4 lite) vs sm8750's 4 - * - 2 writeback blocks (WB1, WB2) vs sm8750's 1 (WB2) - * - 8 interfaces (INTF_0,3,4,6,7,8,9,10) vs sm8750's 4 (INTF_0,1,2,3) - * - 2 DP controllers (DP0, DP1) vs sm8750's 1 (DP0 only) - * - No DSI (removed entirely) - */ - -static const struct dpu_caps nord_dpu_caps = { - .max_mixer_blendstages = 0xb, - .has_src_split = true, - .has_dim_layer = true, - .has_idle_pc = true, - .has_3d_merge = true, - .max_linewidth = 8192, - .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, -}; - -static const struct dpu_mdp_cfg nord_mdp = { - .name = "top_0", - .base = 0, .len = 0x494, - .clk_ctrls = { - [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, - }, -}; - -static const struct dpu_ctl_cfg nord_ctl[] = { - { - .name = "ctl_0", .id = CTL_0, - .base = 0x15000, .len = 0x1000, - .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), - }, { - .name = "ctl_1", .id = CTL_1, - .base = 0x16000, .len = 0x1000, - .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), - }, { - .name = "ctl_2", .id = CTL_2, - .base = 0x17000, .len = 0x1000, - .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), - }, { - .name = "ctl_3", .id = CTL_3, - .base = 0x18000, .len = 0x1000, - .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), - }, { - .name = "ctl_4", .id = CTL_4, - .base = 0x19000, .len = 0x1000, - .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), - }, { - .name = "ctl_5", .id = CTL_5, - .base = 0x1a000, .len = 0x1000, - .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), - }, -}; - -static const struct dpu_sspp_cfg nord_sspp[] = { - { - .name = "sspp_0", .id = SSPP_VIG0, - .base = 0x4000, .len = 0x344, - .features = VIG_SDM845_MASK_SDMA, - .sblk = &dpu_vig_sblk_qseed3_3_4, - .xin_id = 0, - .type = SSPP_TYPE_VIG, - }, { - .name = "sspp_1", .id = SSPP_VIG1, - .base = 0x6000, .len = 0x344, - .features = VIG_SDM845_MASK_SDMA, - .sblk = &dpu_vig_sblk_qseed3_3_4, - .xin_id = 4, - .type = SSPP_TYPE_VIG, - }, { - .name = "sspp_2", .id = SSPP_VIG2, - .base = 0x8000, .len = 0x344, - .features = VIG_SDM845_MASK_SDMA, - .sblk = &dpu_vig_sblk_qseed3_3_4, - .xin_id = 8, - .type = SSPP_TYPE_VIG, - }, { - .name = "sspp_3", .id = SSPP_VIG3, - .base = 0xa000, .len = 0x344, - .features = VIG_SDM845_MASK_SDMA, - .sblk = &dpu_vig_sblk_qseed3_3_4, - .xin_id = 12, - .type = SSPP_TYPE_VIG, - }, { - .name = "sspp_8", .id = SSPP_DMA0, - .base = 0x24000, .len = 0x344, - .features = DMA_SDM845_MASK_SDMA, - .sblk = &dpu_dma_sblk, - .xin_id = 1, - .type = SSPP_TYPE_DMA, - }, { - .name = "sspp_9", .id = SSPP_DMA1, - .base = 0x26000, .len = 0x344, - .features = DMA_SDM845_MASK_SDMA, - .sblk = &dpu_dma_sblk, - .xin_id = 5, - .type = SSPP_TYPE_DMA, - }, { - .name = "sspp_10", .id = SSPP_DMA2, - .base = 0x28000, .len = 0x344, - .features = DMA_SDM845_MASK_SDMA, - .sblk = &dpu_dma_sblk, - .xin_id = 9, - .type = SSPP_TYPE_DMA, - }, { - .name = "sspp_11", .id = SSPP_DMA3, - .base = 0x2a000, .len = 0x344, - .features = DMA_SDM845_MASK_SDMA, - .sblk = &dpu_dma_sblk, - .xin_id = 13, - .type = SSPP_TYPE_DMA, - }, { - .name = "sspp_12", .id = SSPP_DMA4, - .base = 0x2c000, .len = 0x344, - .features = DMA_CURSOR_SDM845_MASK_SDMA, - .sblk = &dpu_dma_sblk, - .xin_id = 14, - .type = SSPP_TYPE_DMA, - }, { - .name = "sspp_13", .id = SSPP_DMA5, - .base = 0x2e000, .len = 0x344, - .features = DMA_CURSOR_SDM845_MASK_SDMA, - .sblk = &dpu_dma_sblk, - .xin_id = 15, - .type = SSPP_TYPE_DMA, - }, -}; - -static const struct dpu_lm_cfg nord_lm[] = { - { - .name = "lm_0", .id = LM_0, - .base = 0x44000, .len = 0x400, - .features = MIXER_MSM8998_MASK, - .sblk = &sm8750_lm_sblk, - .lm_pair = LM_1, - .pingpong = PINGPONG_0, - .dspp = DSPP_0, - }, { - .name = "lm_1", .id = LM_1, - .base = 0x45000, .len = 0x400, - .features = MIXER_MSM8998_MASK, - .sblk = &sm8750_lm_sblk, - .lm_pair = LM_0, - .pingpong = PINGPONG_1, - .dspp = DSPP_1, - }, { - .name = "lm_2", .id = LM_2, - .base = 0x46000, .len = 0x400, - .features = MIXER_MSM8998_MASK, - .sblk = &sm8750_lm_sblk, - .lm_pair = LM_3, - .pingpong = PINGPONG_2, - .dspp = DSPP_2, - }, { - .name = "lm_3", .id = LM_3, - .base = 0x47000, .len = 0x400, - .features = MIXER_MSM8998_MASK, - .sblk = &sm8750_lm_sblk, - .lm_pair = LM_2, - .pingpong = PINGPONG_3, - .dspp = DSPP_3, - }, { - .name = "lm_4", .id = LM_4, - .base = 0x48000, .len = 0x400, - .features = MIXER_MSM8998_MASK, - .sblk = &sm8750_lm_sblk, - .lm_pair = LM_5, - .pingpong = PINGPONG_4, - }, { - .name = "lm_5", .id = LM_5, - .base = 0x49000, .len = 0x400, - .features = MIXER_MSM8998_MASK, - .sblk = &sm8750_lm_sblk, - .lm_pair = LM_4, - .pingpong = PINGPONG_5, - }, { - .name = "lm_6", .id = LM_6, - .base = 0x4a000, .len = 0x400, - .features = MIXER_MSM8998_MASK, - .sblk = &sm8750_lm_sblk, - .lm_pair = LM_7, - .pingpong = PINGPONG_6, - }, { - .name = "lm_7", .id = LM_7, - .base = 0x4b000, .len = 0x400, - .features = MIXER_MSM8998_MASK, - .sblk = &sm8750_lm_sblk, - .lm_pair = LM_6, - .pingpong = PINGPONG_7, - }, -}; - -/* - * Nord has 8 DSPP blocks: 4 full-featured (DSPP0-3) and 4 lite variants - * (DSPP4-7). The driver has no separate lite-DSPP struct, so all 8 are - * modeled with the same dpu_dspp_cfg/dpu_dspp_sblk structure. Lite variants - * have reduced features, but this is handled at runtime via feature flags, - * not via separate catalog entries. - * FIXME(REG_ADDR): DSPP4-7 base addresses extended via 0x2000 stride from - * sm8750's DSPP3 base (0x5a000). Verify against real Nord register map. - */ -static const struct dpu_dspp_cfg nord_dspp[] = { - { - .name = "dspp_0", .id = DSPP_0, - .base = 0x54000, .len = 0x1800, - .sblk = &sm8750_dspp_sblk, - }, { - .name = "dspp_1", .id = DSPP_1, - .base = 0x56000, .len = 0x1800, - .sblk = &sm8750_dspp_sblk, - }, { - .name = "dspp_2", .id = DSPP_2, - .base = 0x58000, .len = 0x1800, - .sblk = &sm8750_dspp_sblk, - }, { - .name = "dspp_3", .id = DSPP_3, - .base = 0x5a000, .len = 0x1800, - .sblk = &sm8750_dspp_sblk, - }, { - .name = "dspp_4", .id = DSPP_4, - .base = 0x5c000, .len = 0x1800, /* FIXME(REG_ADDR): lite variant */ - .sblk = &sm8750_dspp_sblk, - }, { - .name = "dspp_5", .id = DSPP_5, - .base = 0x5e000, .len = 0x1800, /* FIXME(REG_ADDR): lite variant */ - .sblk = &sm8750_dspp_sblk, - }, { - .name = "dspp_6", .id = DSPP_6, - .base = 0x60000, .len = 0x1800, /* FIXME(REG_ADDR): lite variant */ - .sblk = &sm8750_dspp_sblk, - }, { - .name = "dspp_7", .id = DSPP_7, - .base = 0x62000, .len = 0x1800, /* FIXME(REG_ADDR): lite variant */ - .sblk = &sm8750_dspp_sblk, - }, -}; - -static const struct dpu_pingpong_cfg nord_pp[] = { - { - .name = "pingpong_0", .id = PINGPONG_0, - .base = 0x69000, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_0, - .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), - }, { - .name = "pingpong_1", .id = PINGPONG_1, - .base = 0x6a000, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_0, - .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), - }, { - .name = "pingpong_2", .id = PINGPONG_2, - .base = 0x6b000, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_1, - .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), - }, { - .name = "pingpong_3", .id = PINGPONG_3, - .base = 0x6c000, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_1, - .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), - }, { - .name = "pingpong_4", .id = PINGPONG_4, - .base = 0x6d000, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_2, - .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), - }, { - .name = "pingpong_5", .id = PINGPONG_5, - .base = 0x6e000, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_2, - .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), - }, { - .name = "pingpong_6", .id = PINGPONG_6, - .base = 0x6f000, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_3, - .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 20), - }, { - .name = "pingpong_7", .id = PINGPONG_7, - .base = 0x70000, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_3, - .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 21), - }, { - .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, - .base = 0x66000, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_4, - }, { - .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, - .base = 0x66400, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_4, - }, { - .name = "pingpong_cwb_2", .id = PINGPONG_CWB_2, - .base = 0x7e000, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_5, - }, { - .name = "pingpong_cwb_3", .id = PINGPONG_CWB_3, - .base = 0x7e400, .len = 0, - .sblk = &sc7280_pp_sblk, - .merge_3d = MERGE_3D_5, - }, -}; - -static const struct dpu_merge_3d_cfg nord_merge_3d[] = { - { - .name = "merge_3d_0", .id = MERGE_3D_0, - .base = 0x4e000, .len = 0x1c, - }, { - .name = "merge_3d_1", .id = MERGE_3D_1, - .base = 0x4f000, .len = 0x1c, - }, { - .name = "merge_3d_2", .id = MERGE_3D_2, - .base = 0x50000, .len = 0x1c, - }, { - .name = "merge_3d_3", .id = MERGE_3D_3, - .base = 0x51000, .len = 0x1c, - }, { - .name = "merge_3d_4", .id = MERGE_3D_4, - .base = 0x66700, .len = 0x1c, - }, { - .name = "merge_3d_5", .id = MERGE_3D_5, - .base = 0x7e700, .len = 0x1c, - }, -}; - -/* - * NOTE: Each display compression engine (DCE) contains dual hard - * slice DSC encoders so both share same base address but with - * its own different sub block address. Nord retains sm8750's - * topology of 8 DSC instances (2 per DCE × 4). - */ -static const struct dpu_dsc_cfg nord_dsc[] = { - { - .name = "dce_0_0", .id = DSC_0, - .base = 0x80000, .len = 0x8, - .features = BIT(DPU_DSC_NATIVE_42x_EN), - .sblk = &sm8750_dsc_sblk_0, - }, { - .name = "dce_0_1", .id = DSC_1, - .base = 0x80000, .len = 0x8, - .features = BIT(DPU_DSC_NATIVE_42x_EN), - .sblk = &sm8750_dsc_sblk_1, - }, { - .name = "dce_1_0", .id = DSC_2, - .base = 0x81000, .len = 0x8, - .features = BIT(DPU_DSC_NATIVE_42x_EN), - .sblk = &sm8750_dsc_sblk_0, - }, { - .name = "dce_1_1", .id = DSC_3, - .base = 0x81000, .len = 0x8, - .features = BIT(DPU_DSC_NATIVE_42x_EN), - .sblk = &sm8750_dsc_sblk_1, - }, { - .name = "dce_2_0", .id = DSC_4, - .base = 0x82000, .len = 0x8, - .features = BIT(DPU_DSC_NATIVE_42x_EN), - .sblk = &sm8750_dsc_sblk_0, - }, { - .name = "dce_2_1", .id = DSC_5, - .base = 0x82000, .len = 0x8, - .features = BIT(DPU_DSC_NATIVE_42x_EN), - .sblk = &sm8750_dsc_sblk_1, - }, { - .name = "dce_3_0", .id = DSC_6, - .base = 0x83000, .len = 0x8, - .features = BIT(DPU_DSC_NATIVE_42x_EN), - .sblk = &sm8750_dsc_sblk_0, - }, { - .name = "dce_3_1", .id = DSC_7, - .base = 0x83000, .len = 0x8, - .features = BIT(DPU_DSC_NATIVE_42x_EN), - .sblk = &sm8750_dsc_sblk_1, - }, -}; - -/* - * Nord has 2 writeback blocks: WB2 (matches sm8750) and WB1 (new). - * WB1 base and xin_id are inferred via stride from existing WB pattern. - * FIXME(REG_ADDR): WB1 base address inferred as 0x65000 - 0x2c8 stride. - * FIXME(XIU_MAP): WB1 xin_id set to 7; verify against real hardware map. - */ -static const struct dpu_wb_cfg nord_wb[] = { - { - .name = "wb_1", .id = WB_1, - .base = 0x64800, .len = 0x2c8, /* FIXME(REG_ADDR): inferred */ - .features = WB_SDM845_MASK, - .format_list = wb2_formats_rgb_yuv, - .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), - .xin_id = 7, /* FIXME(XIU_MAP): inferred */ - .maxlinewidth = 4096, - .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 3), - }, { - .name = "wb_2", .id = WB_2, - .base = 0x65000, .len = 0x2c8, - .features = WB_SDM845_MASK, - .format_list = wb2_formats_rgb_yuv, - .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), - .xin_id = 6, - .maxlinewidth = 4096, - .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), - }, -}; - -static const struct dpu_cwb_cfg nord_cwb[] = { - { - .name = "cwb_0", .id = CWB_0, - .base = 0x66200, .len = 0x20, - }, - { - .name = "cwb_1", .id = CWB_1, - .base = 0x66600, .len = 0x20, - }, - { - .name = "cwb_2", .id = CWB_2, - .base = 0x7e200, .len = 0x20, - }, - { - .name = "cwb_3", .id = CWB_3, - .base = 0x7e600, .len = 0x20, - }, -}; - -/* - * Nord has 8 active interfaces (INTF_0,3,4,6,7,8,9,10) with no DSI. - * DP0 connects to INTF_0, INTF_3, INTF_6, INTF_7 (4 ports for MST). - * DP1 connects to INTF_4, INTF_8, INTF_9, INTF_10 (4 ports for MST). - * Interfaces 1, 2, 5 are skipped (removed from sm8750). - * All interface base addresses extend the stride from sm8750. - * FIXME(REG_ADDR): INTF_4,6,7,8,9,10 addresses inferred via 0x1000 stride. - */ -static const struct dpu_intf_cfg nord_intf[] = { - { - .name = "intf_0", .id = INTF_0, - .base = 0x34000, .len = 0x4bc, - .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_0, - .prog_fetch_lines_worst_case = 24, - .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), - .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), - }, { - .name = "intf_3", .id = INTF_3, - .base = 0x37000, .len = 0x4bc, - .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ - .prog_fetch_lines_worst_case = 24, - .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), - .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), - }, { - .name = "intf_4", .id = INTF_4, - .base = 0x38000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x1000 */ - .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_1, - .prog_fetch_lines_worst_case = 24, - .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20), - .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21), - }, { - .name = "intf_6", .id = INTF_6, - .base = 0x3a000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x3000 */ - .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_0, /* second pair for DP0 MST */ - .prog_fetch_lines_worst_case = 24, - .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22), - .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23), - }, { - .name = "intf_7", .id = INTF_7, - .base = 0x3b000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x4000 */ - .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_0, /* third pair for DP0 MST */ - .prog_fetch_lines_worst_case = 24, - .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 0), - .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 1), - }, { - .name = "intf_8", .id = INTF_8, - .base = 0x3c000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x5000 */ - .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_1, /* second pair for DP1 MST */ - .prog_fetch_lines_worst_case = 24, - .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 2), - .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 3), - }, { - .name = "intf_9", .id = INTF_9, - .base = 0x3d000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x6000 */ - .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_1, /* third pair for DP1 MST */ - .prog_fetch_lines_worst_case = 24, - .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 4), - .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 5), - }, { - .name = "intf_10", .id = INTF_10, - .base = 0x3e000, .len = 0x4bc, /* FIXME(REG_ADDR): new, stride +0x7000 */ - .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_1, /* fourth pair for DP1 MST */ - .prog_fetch_lines_worst_case = 24, - .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 6), - .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 7), - }, -}; - -static const struct dpu_perf_cfg nord_perf_data = { - .max_bw_low = 18900000, - .max_bw_high = 28500000, - .min_core_ib = 2500000, - .min_llcc_ib = 0, - .min_dram_ib = 800000, - .min_prefill_lines = 35, - .danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0}, - .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff}, - .qos_lut_tbl = { - {.nentry = ARRAY_SIZE(sc7180_qos_linear), - .entries = sc7180_qos_linear - }, - {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), - .entries = sc7180_qos_macrotile - }, - {.nentry = ARRAY_SIZE(sc7180_qos_nrt), - .entries = sc7180_qos_nrt - }, - /* TODO: macrotile-qseed is different from macrotile */ - }, - .cdp_cfg = { - {.rd_enable = 1, .wr_enable = 1}, - {.rd_enable = 1, .wr_enable = 0} - }, - .clk_inefficiency_factor = 105, - .bw_inefficiency_factor = 120, -}; - -static const struct dpu_mdss_version nord_mdss_ver = { - .core_major_ver = 12, - .core_minor_ver = 1, -}; - -const struct dpu_mdss_cfg dpu_nord_cfg = { - .mdss_ver = &nord_mdss_ver, - .caps = &nord_dpu_caps, - .mdp = &nord_mdp, - .cdm = &dpu_cdm_5_x, - .ctl_count = ARRAY_SIZE(nord_ctl), - .ctl = nord_ctl, - .sspp_count = ARRAY_SIZE(nord_sspp), - .sspp = nord_sspp, - .mixer_count = ARRAY_SIZE(nord_lm), - .mixer = nord_lm, - .dspp_count = ARRAY_SIZE(nord_dspp), - .dspp = nord_dspp, - .pingpong_count = ARRAY_SIZE(nord_pp), - .pingpong = nord_pp, - .dsc_count = ARRAY_SIZE(nord_dsc), - .dsc = nord_dsc, - .merge_3d_count = ARRAY_SIZE(nord_merge_3d), - .merge_3d = nord_merge_3d, - .wb_count = ARRAY_SIZE(nord_wb), - .wb = nord_wb, - .cwb_count = ARRAY_SIZE(nord_cwb), - .cwb = nord_cwb, - .intf_count = ARRAY_SIZE(nord_intf), - .intf = nord_intf, - .vbif = &sm8650_vbif, - .perf = &nord_perf_data, -}; - -#endif diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 75ae3026593f3..107150a8553fe 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -798,7 +798,6 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = { #include "catalog/dpu_10_2_milos.h" #include "catalog/dpu_12_0_sm8750.h" -#include "catalog/dpu_12_1_nord.h" #include "catalog/dpu_12_2_glymur.h" #include "catalog/dpu_12_4_eliza.h" #include "catalog/dpu_13_0_kaanapali.h" diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index b3dce2a972d4c..ea36360c05d85 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -777,7 +777,6 @@ extern const struct dpu_mdss_cfg dpu_msm8937_cfg; extern const struct dpu_mdss_cfg dpu_msm8953_cfg; extern const struct dpu_mdss_cfg dpu_msm8996_cfg; extern const struct dpu_mdss_cfg dpu_msm8998_cfg; -extern const struct dpu_mdss_cfg dpu_nord_cfg; extern const struct dpu_mdss_cfg dpu_sar2130p_cfg; extern const struct dpu_mdss_cfg dpu_sdm630_cfg; extern const struct dpu_mdss_cfg dpu_sdm660_cfg; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h index 7eccb4d2c65ef..0e65bf5ddc4a6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h @@ -226,8 +226,6 @@ enum dpu_intf { INTF_6, INTF_7, INTF_8, - INTF_9, - INTF_10, INTF_MAX }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 1785ee61e23f0..d6182cec06d58 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1514,7 +1514,6 @@ static const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,msm8953-mdp5", .data = &dpu_msm8953_cfg, }, { .compatible = "qcom,msm8996-mdp5", .data = &dpu_msm8996_cfg, }, { .compatible = "qcom,msm8998-dpu", .data = &dpu_msm8998_cfg, }, - { .compatible = "qcom,nord-dpu", .data = &dpu_nord_cfg, }, { .compatible = "qcom,qcm2290-dpu", .data = &dpu_qcm2290_cfg, }, { .compatible = "qcom,sa8775p-dpu", .data = &dpu_sa8775p_cfg, }, { .compatible = "qcom,sar2130p-dpu", .data = &dpu_sar2130p_cfg, }, From 11d7b4b9135f34dd97ca01518bae43a9347b7ac0 Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Mon, 12 Oct 2026 19:02:11 +0530 Subject: [PATCH 1114/1133] FROMLIST: dt-bindings: phy: qcom,edp-phy: Add DP PHY compatible for Nord Nord relocates several PHY/QSERDES registers relative to existing SoCs, so it cannot reuse an existing compatible. Add qcom,nord-dp-phy to the compatible list. Nord also needs a dedicated ref clock besides aux and cfg_ahb, so add it to the allOf condition that requires three clocks (aux, cfg_ahb, ref). Signed-off-by: Mahadevan P Signed-off-by: Nabige Aala Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-1-a2ab9af954d2@oss.qualcomm.com/ --- Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml index 0bf8bf4f66acf..0ff07ddcb76f2 100644 --- a/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml @@ -19,6 +19,7 @@ properties: oneOf: - enum: - qcom,glymur-dp-phy + - qcom,nord-dp-phy - qcom,sa8775p-edp-phy - qcom,sc7280-edp-phy - qcom,sc8180x-edp-phy @@ -74,6 +75,7 @@ allOf: compatible: enum: - qcom,glymur-dp-phy + - qcom,nord-dp-phy - qcom,sa8775p-edp-phy - qcom,x1e80100-dp-phy then: From cbc253211c5743e9d76dcce197737e85c1a69c98 Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Mon, 12 Oct 2026 19:02:12 +0530 Subject: [PATCH 1115/1133] FROMLIST: dt-bindings: display: msm: Document the Nord DiplayPort controller Nord uses MDSS 12.1 with two independent DP controller instances, each exposing two DP cores at new IO offsets. None of the existing compatibles match this layout, so add qcom,nord-dp. Signed-off-by: Mahadevan P Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-2-a2ab9af954d2@oss.qualcomm.com/ --- .../devicetree/bindings/display/msm/dp-controller.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 8bb0f6e15942f..b2d1f82417503 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -20,6 +20,7 @@ properties: - enum: - qcom,glymur-dp - qcom,kaanapali-dp + - qcom,nord-dp - qcom,sa8775p-dp - qcom,sc7180-dp - qcom,sc7280-dp @@ -210,6 +211,7 @@ allOf: contains: enum: - qcom,glymur-dp + - qcom,nord-dp - qcom,sa8775p-dp - qcom,x1e80100-dp then: @@ -316,6 +318,7 @@ allOf: enum: # these platforms support 4 stream MST on first DP, # 2 streams MST on the second one. + - qcom,nord-dp - qcom,sa8775p-dp then: properties: From 01048f070f5c593a4bae6b2bd5c4c78dcce63826 Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Mon, 12 Oct 2026 19:02:13 +0530 Subject: [PATCH 1116/1133] FROMLIST: dt-bindings: display/msm: Document Nord MDSS Nord has a new MDSS 12.1 revision with DPU 1499A and two independent, DP-only display interface controllers (no DSI), which no existing schema describes. Add a dedicated qcom,nord-mdss binding to document. Assisted-by: LLM Signed-off-by: Mahadevan P Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-3-a2ab9af954d2@oss.qualcomm.com/ --- .../bindings/display/msm/qcom,nord-mdss.yaml | 396 ++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/msm/qcom,nord-mdss.yaml diff --git a/Documentation/devicetree/bindings/display/msm/qcom,nord-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,nord-mdss.yaml new file mode 100644 index 0000000000000..abd80dae4e7f5 --- /dev/null +++ b/Documentation/devicetree/bindings/display/msm/qcom,nord-mdss.yaml @@ -0,0 +1,396 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/msm/qcom,nord-mdss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Nord display subsystem (MDSS) + +maintainers: + - Mahadevan P + +description: + Nord display subsystem consists of MDSS (display controller), DPU 1499A + (display processing unit), and display interface controllers (DP only, no DSI). + This is MDSS 12.1, DP-only, with 2 independent DP controllers. + +$ref: /schemas/display/msm/mdss-common.yaml# + +properties: + compatible: + const: qcom,nord-mdss + + clocks: + items: + - description: Display AHB + - description: Display hf AXI + - description: Display core + + clock-names: + items: + - const: iface + - const: bus + - const: core + + iommus: + maxItems: 1 + + interconnects: + items: + - description: Interconnect path from mdp0 port to the data bus + - description: Interconnect path from CPU to the reg bus + + interconnect-names: + items: + - const: mdp0-mem + - const: cpu-cfg + +patternProperties: + "^display-controller@[0-9a-f]+$": + type: object + additionalProperties: true + properties: + compatible: + const: qcom,nord-dpu + + "^displayport-controller@[0-9a-f]+$": + type: object + additionalProperties: true + properties: + compatible: + const: qcom,nord-dp + + "^phy@[0-9a-f]+$": + type: object + additionalProperties: true + properties: + compatible: + const: qcom,nord-dp-phy + +required: + - compatible + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + #include + + display-subsystem@ae00000 { + compatible = "qcom,nord-mdss"; + reg = <0x0ae00000 0x1000>; + reg-names = "mdss"; + + power-domains = <&dispcc0 MDSS_DISP_CC_MDSS_CORE_GDSC>; + clocks = <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&nwgcc NW_GCC_DISP_0_HF_AXI_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", "bus", "core"; + resets = <&dispcc0 MDSS_DISP_CC_MDSS_CORE_BCR>; + + interconnects = <&mmss_noc MASTER_MDP0 QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ACTIVE_ONLY>; + interconnect-names = "mdp0-mem", "cpu-cfg"; + + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + iommus = <&apps_smmu_1 0x3e0 0x2>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + display-controller@ae01000 { + compatible = "qcom,nord-dpu"; + reg = <0x0ae01000 0x8f000>, + <0x0aeb0000 0x3000>; + reg-names = "mdp", "vbif"; + + clocks = <&nwgcc NW_GCC_DISP_0_HF_AXI_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_MDP_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "nrt_bus", "iface", "lut", "core", "vsync"; + + assigned-clocks = <&dispcc0 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>; + }; + }; + + port@1 { + reg = <1>; + dpu_intf4_out: endpoint { + remote-endpoint = <&mdss_dp1_in>; + }; + }; + }; + + mdp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-417000000 { + opp-hz = /bits/ 64 <417000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-532000000 { + opp-hz = /bits/ 64 <532000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&rpmhpd_opp_turbo>; + }; + + opp-710000000 { + opp-hz = /bits/ 64 <710000000>; + required-opps = <&rpmhpd_opp_turbo_l1>; + }; + }; + }; + + displayport-controller@af54000 { + compatible = "qcom,nord-dp"; + + reg = <0xaf54000 0x200>, + <0xaf54200 0x200>, + <0xaf55000 0xc00>, + <0xaf56000 0x400>, + <0xaf57000 0x400>, + <0xaf58000 0x400>, + <0xaf59000 0x400>, + <0xaf5a000 0x600>, + <0xaf5b000 0x600>; + + clocks = <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_LINK_INTF_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL1_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL2_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL3_CLK>; + clock-names = "core_iface", "core_aux", + "ctrl_link", "ctrl_link_iface", + "stream_pixel", "stream_1_pixel", + "stream_2_pixel", "stream_3_pixel"; + + assigned-clocks = <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_LINK_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL1_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL2_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_PIXEL3_CLK_SRC>; + assigned-clock-parents = <&dp0_phy 0>, + <&dp0_phy 1>, + <&dp0_phy 1>, + <&dp0_phy 1>, + <&dp0_phy 1>; + + interrupt-parent = <&mdss>; + interrupts = <12>; + + phys = <&dp0_phy>; + phy-names = "dp"; + + operating-points-v2 = <&dp_opp_table>; + power-domains = <&rpmhpd RPMHPD_MMCX>; + + #sound-dai-cells = <0>; + + 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-162000000 { + opp-hz = /bits/ 64 <162000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-270000000 { + opp-hz = /bits/ 64 <270000000>; + required-opps = <&rpmhpd_opp_low_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>; + }; + }; + }; + + displayport-controller@af5c000 { + compatible = "qcom,nord-dp"; + + reg = <0xaf5c000 0x200>, + <0xaf5c200 0x200>, + <0xaf5d000 0xc00>, + <0xaf5e000 0x400>, + <0xaf5f000 0x400>, + <0xaf60000 0x400>, + <0xaf61000 0x400>, + <0xaf62000 0x600>, + <0xaf63000 0x600>; + + clocks = <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_AUX_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_LINK_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_LINK_INTF_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL0_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL1_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL2_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL3_CLK>; + clock-names = "core_iface", "core_aux", + "ctrl_link", "ctrl_link_iface", + "stream_pixel", "stream_1_pixel", + "stream_2_pixel", "stream_3_pixel"; + + assigned-clocks = <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_LINK_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL0_CLK_SRC>, + <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_PIXEL1_CLK_SRC>; + assigned-clock-parents = <&dp1_phy 0>, + <&dp1_phy 1>, + <&dp1_phy 1>; + + interrupt-parent = <&mdss>; + interrupts = <13>; + + phys = <&dp1_phy>; + phy-names = "dp"; + + operating-points-v2 = <&dp1_opp_table>; + power-domains = <&rpmhpd RPMHPD_MMCX>; + + #sound-dai-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdss_dp1_in: endpoint { + remote-endpoint = <&dpu_intf4_out>; + }; + }; + + port@1 { + reg = <1>; + mdss_dp1_out: endpoint { }; + }; + }; + + dp1_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-162000000 { + opp-hz = /bits/ 64 <162000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-270000000 { + opp-hz = /bits/ 64 <270000000>; + required-opps = <&rpmhpd_opp_low_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>; + }; + }; + }; + + dp0_phy: phy@fc3a00 { + compatible = "qcom,nord-dp-phy"; + + reg = <0xfc3a00 0x1d0>, + <0xfc3200 0x128>, + <0xfc3600 0x128>, + <0xfc3000 0x200>; + + clocks = <&dispcc0 MDSS_DISP_CC_MDSS_DPTX0_AUX_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&tcsrcc TCSR_DP_TX_0_CLKREF_EN>; + clock-names = "aux", "cfg_ahb", "ref"; + + #clock-cells = <1>; + #phy-cells = <0>; + + power-domains = <&rpmhpd RPMHPD_MX>; + }; + + dp1_phy: phy@fc6a00 { + compatible = "qcom,nord-dp-phy"; + + reg = <0xfc6a00 0x200>, + <0xfc6200 0xd0>, + <0xfc6600 0xd0>, + <0xfc6000 0x1c8>; + + clocks = <&dispcc0 MDSS_DISP_CC_MDSS_DPTX1_AUX_CLK>, + <&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>, + <&tcsrcc TCSR_DP_TX_1_CLKREF_EN>; + clock-names = "aux", "cfg_ahb", "ref"; + + #clock-cells = <1>; + #phy-cells = <0>; + + power-domains = <&rpmhpd RPMHPD_MX>; + }; + }; From 0e9147ca2b6c8fa7b1fb388af178ded6ce1e6211 Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Mon, 12 Oct 2026 19:02:14 +0530 Subject: [PATCH 1117/1133] BACKPORT: drm/msm/dpu: Add support for DPU 12.1 on Nord Add the DPU catalog entry for the Qualcomm Nord SoC (MDSS 12.1, DPU 1499A). Nord is DP-only with no DSI, and provides 8 DSPP blocks, 2 writeback blocks, 8 interfaces and 2 DP controllers. Extend enum dpu_intf with INTF_9 and INTF_10, which Nord is the first platform to use. The new entries are inserted before MDP_INTF1_TEAR_INTR and MDP_INTF2_TEAR_INTR in enum dpu_hw_intr_reg, preserving the contiguous MDP_INTF0_INTR..MDP_INTF10_INTR block that the MDP_INTFn_INTR() macro relies on for correct index arithmetic. Corresponding register entries are added to dpu_intr_set_7xxx (required for Nord, which has core_major_ver = 12) and dpu_intr_set_13xx (for consistency and to avoid a latent bug on future 13xx-family SoCs that use INTF 9 or 10). [Mahadevan: omit the obsolete max_mixer_width initializer to retain the LM catalog cleanup already present on tech/mm/drm.] Assisted-by: LLM Signed-off-by: Mahadevan P Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-4-a2ab9af954d2@oss.qualcomm.com/ --- .../drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h | 543 ++++++++++++++++++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 + .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 1 + .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 20 + .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 + 7 files changed, 570 insertions(+) create mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h new file mode 100644 index 0000000000000..e261ea271ee7c --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_1_nord.h @@ -0,0 +1,543 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _DPU_12_1_NORD_H +#define _DPU_12_1_NORD_H + + +static const struct dpu_caps nord_dpu_caps = { + .max_mixer_blendstages = 0xb, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 8192, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, +}; + +static const struct dpu_mdp_cfg nord_mdp = { + .name = "top_0", + .base = 0, .len = 0x494, + .clk_ctrls = { + [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 }, + }, +}; + +static const struct dpu_ctl_cfg nord_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x15000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, { + .name = "ctl_1", .id = CTL_1, + .base = 0x16000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, { + .name = "ctl_2", .id = CTL_2, + .base = 0x17000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, { + .name = "ctl_3", .id = CTL_3, + .base = 0x18000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, { + .name = "ctl_4", .id = CTL_4, + .base = 0x19000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, { + .name = "ctl_5", .id = CTL_5, + .base = 0x1a000, .len = 0x1000, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), + }, +}; + +static const struct dpu_sspp_cfg nord_sspp[] = { + { + .name = "sspp_0", .id = SSPP_VIG0, + .base = 0x4000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 0, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_1", .id = SSPP_VIG1, + .base = 0x6000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 4, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_2", .id = SSPP_VIG2, + .base = 0x8000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 8, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_3", .id = SSPP_VIG3, + .base = 0xa000, .len = 0x344, + .features = VIG_SDM845_MASK_SDMA, + .sblk = &dpu_vig_sblk_qseed3_3_4, + .xin_id = 12, + .type = SSPP_TYPE_VIG, + }, { + .name = "sspp_8", .id = SSPP_DMA0, + .base = 0x24000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 1, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_9", .id = SSPP_DMA1, + .base = 0x26000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 5, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_10", .id = SSPP_DMA2, + .base = 0x28000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 9, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_11", .id = SSPP_DMA3, + .base = 0x2a000, .len = 0x344, + .features = DMA_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 13, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_12", .id = SSPP_DMA4, + .base = 0x2c000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 14, + .type = SSPP_TYPE_DMA, + }, { + .name = "sspp_13", .id = SSPP_DMA5, + .base = 0x2e000, .len = 0x344, + .features = DMA_CURSOR_SDM845_MASK_SDMA, + .sblk = &dpu_dma_sblk, + .xin_id = 15, + .type = SSPP_TYPE_DMA, + }, +}; + +static const struct dpu_lm_cfg nord_lm[] = { + { + .name = "lm_0", .id = LM_0, + .base = 0x44000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_1, + .pingpong = PINGPONG_0, + .dspp = DSPP_0, + }, { + .name = "lm_1", .id = LM_1, + .base = 0x45000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_0, + .pingpong = PINGPONG_1, + .dspp = DSPP_1, + }, { + .name = "lm_2", .id = LM_2, + .base = 0x46000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_3, + .pingpong = PINGPONG_2, + .dspp = DSPP_2, + }, { + .name = "lm_3", .id = LM_3, + .base = 0x47000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_2, + .pingpong = PINGPONG_3, + .dspp = DSPP_3, + }, { + .name = "lm_4", .id = LM_4, + .base = 0x48000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_5, + .pingpong = PINGPONG_4, + .dspp = DSPP_4, + }, { + .name = "lm_5", .id = LM_5, + .base = 0x49000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_4, + .pingpong = PINGPONG_5, + .dspp = DSPP_5, + }, { + .name = "lm_6", .id = LM_6, + .base = 0x4a000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_7, + .pingpong = PINGPONG_6, + .dspp = DSPP_6, + }, { + .name = "lm_7", .id = LM_7, + .base = 0x4b000, .len = 0x400, + .features = MIXER_MSM8998_MASK, + .sblk = &sm8750_lm_sblk, + .lm_pair = LM_6, + .pingpong = PINGPONG_7, + .dspp = DSPP_7, + }, +}; + +static const struct dpu_dspp_cfg nord_dspp[] = { + { + .name = "dspp_0", .id = DSPP_0, + .base = 0x54000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_1", .id = DSPP_1, + .base = 0x56000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_2", .id = DSPP_2, + .base = 0x58000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_3", .id = DSPP_3, + .base = 0x5a000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_4", .id = DSPP_4, + .base = 0x5c000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_5", .id = DSPP_5, + .base = 0x5e000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_6", .id = DSPP_6, + .base = 0x60000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, { + .name = "dspp_7", .id = DSPP_7, + .base = 0x62000, .len = 0x1800, + .sblk = &sm8750_dspp_sblk, + }, +}; + +static const struct dpu_pingpong_cfg nord_pp[] = { + { + .name = "pingpong_0", .id = PINGPONG_0, + .base = 0x69000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + }, { + .name = "pingpong_1", .id = PINGPONG_1, + .base = 0x6a000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_0, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), + }, { + .name = "pingpong_2", .id = PINGPONG_2, + .base = 0x6b000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + }, { + .name = "pingpong_3", .id = PINGPONG_3, + .base = 0x6c000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_1, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), + }, { + .name = "pingpong_4", .id = PINGPONG_4, + .base = 0x6d000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), + }, { + .name = "pingpong_5", .id = PINGPONG_5, + .base = 0x6e000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_2, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), + }, { + .name = "pingpong_6", .id = PINGPONG_6, + .base = 0x6f000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 20), + }, { + .name = "pingpong_7", .id = PINGPONG_7, + .base = 0x70000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_3, + .intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 21), + }, { + .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0, + .base = 0x66000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_4, + }, { + .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1, + .base = 0x66400, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_4, + }, { + .name = "pingpong_cwb_2", .id = PINGPONG_CWB_2, + .base = 0x7e000, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_5, + }, { + .name = "pingpong_cwb_3", .id = PINGPONG_CWB_3, + .base = 0x7e400, .len = 0, + .sblk = &sc7280_pp_sblk, + .merge_3d = MERGE_3D_5, + }, +}; + +static const struct dpu_merge_3d_cfg nord_merge_3d[] = { + { + .name = "merge_3d_0", .id = MERGE_3D_0, + .base = 0x4e000, .len = 0x1c, + }, { + .name = "merge_3d_1", .id = MERGE_3D_1, + .base = 0x4f000, .len = 0x1c, + }, { + .name = "merge_3d_2", .id = MERGE_3D_2, + .base = 0x50000, .len = 0x1c, + }, { + .name = "merge_3d_3", .id = MERGE_3D_3, + .base = 0x51000, .len = 0x1c, + }, { + .name = "merge_3d_4", .id = MERGE_3D_4, + .base = 0x66700, .len = 0x1c, + }, { + .name = "merge_3d_5", .id = MERGE_3D_5, + .base = 0x7e700, .len = 0x1c, + }, +}; + +static const struct dpu_dsc_cfg nord_dsc[] = { + { + .name = "dce_0_0", .id = DSC_0, + .base = 0x80000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_0_1", .id = DSC_1, + .base = 0x80000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_1_0", .id = DSC_2, + .base = 0x81000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_1_1", .id = DSC_3, + .base = 0x81000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_2_0", .id = DSC_4, + .base = 0x82000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_2_1", .id = DSC_5, + .base = 0x82000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, { + .name = "dce_3_0", .id = DSC_6, + .base = 0x83000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_0, + }, { + .name = "dce_3_1", .id = DSC_7, + .base = 0x83000, .len = 0x8, + .features = BIT(DPU_DSC_NATIVE_42x_EN), + .sblk = &sm8750_dsc_sblk_1, + }, +}; + +static const struct dpu_wb_cfg nord_wb[] = { + { + .name = "wb_1", .id = WB_1, + .base = 0x64800, .len = 0x2c8, + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), + .xin_id = 7, + .maxlinewidth = 4096, + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 3), + }, { + .name = "wb_2", .id = WB_2, + .base = 0x65000, .len = 0x2c8, + .features = WB_SDM845_MASK, + .format_list = wb2_formats_rgb_yuv, + .num_formats = ARRAY_SIZE(wb2_formats_rgb_yuv), + .xin_id = 6, + .maxlinewidth = 4096, + .intr_wb_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 4), + }, +}; + +static const struct dpu_cwb_cfg nord_cwb[] = { + { + .name = "cwb_0", .id = CWB_0, + .base = 0x66200, .len = 0x20, + }, + { + .name = "cwb_1", .id = CWB_1, + .base = 0x66600, .len = 0x20, + }, + { + .name = "cwb_2", .id = CWB_2, + .base = 0x7e200, .len = 0x20, + }, + { + .name = "cwb_3", .id = CWB_3, + .base = 0x7e600, .len = 0x20, + }, +}; + +static const struct dpu_intf_cfg nord_intf[] = { + { + .name = "intf_0", .id = INTF_0, + .base = 0x34000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 24), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 25), + }, { + .name = "intf_3", .id = INTF_3, + .base = 0x37000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), + }, { + .name = "intf_4", .id = INTF_4, + .base = 0x38000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21), + }, { + .name = "intf_6", .id = INTF_6, + .base = 0x3a000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23), + }, { + .name = "intf_7", .id = INTF_7, + .base = 0x3b000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_0, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 0), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 1), + }, { + .name = "intf_8", .id = INTF_8, + .base = 0x3c000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 2), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 3), + }, { + .name = "intf_9", .id = INTF_9, + .base = 0x3d000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 4), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 5), + }, { + .name = "intf_10", .id = INTF_10, + .base = 0x3e000, .len = 0x4bc, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_1, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 6), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 7), + }, +}; + +static const struct dpu_perf_cfg nord_perf_data = { + .max_bw_low = 18900000, + .max_bw_high = 28500000, + .min_core_ib = 2500000, + .min_llcc_ib = 0, + .min_dram_ib = 800000, + .min_prefill_lines = 35, + .danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0}, + .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(sc7180_qos_linear), + .entries = sc7180_qos_linear + }, + {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), + .entries = sc7180_qos_macrotile + }, + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), + .entries = sc7180_qos_nrt + }, + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; + +static const struct dpu_mdss_version nord_mdss_ver = { + .core_major_ver = 12, + .core_minor_ver = 1, +}; + +const struct dpu_mdss_cfg dpu_nord_cfg = { + .mdss_ver = &nord_mdss_ver, + .caps = &nord_dpu_caps, + .mdp = &nord_mdp, + .cdm = &dpu_cdm_5_x, + .ctl_count = ARRAY_SIZE(nord_ctl), + .ctl = nord_ctl, + .sspp_count = ARRAY_SIZE(nord_sspp), + .sspp = nord_sspp, + .mixer_count = ARRAY_SIZE(nord_lm), + .mixer = nord_lm, + .dspp_count = ARRAY_SIZE(nord_dspp), + .dspp = nord_dspp, + .pingpong_count = ARRAY_SIZE(nord_pp), + .pingpong = nord_pp, + .dsc_count = ARRAY_SIZE(nord_dsc), + .dsc = nord_dsc, + .merge_3d_count = ARRAY_SIZE(nord_merge_3d), + .merge_3d = nord_merge_3d, + .wb_count = ARRAY_SIZE(nord_wb), + .wb = nord_wb, + .cwb_count = ARRAY_SIZE(nord_cwb), + .cwb = nord_cwb, + .intf_count = ARRAY_SIZE(nord_intf), + .intf = nord_intf, + .vbif = &sm8650_vbif, + .perf = &nord_perf_data, +}; + +#endif diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 107150a8553fe..75ae3026593f3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -798,6 +798,7 @@ static const struct dpu_qos_lut_entry sc7180_qos_nrt[] = { #include "catalog/dpu_10_2_milos.h" #include "catalog/dpu_12_0_sm8750.h" +#include "catalog/dpu_12_1_nord.h" #include "catalog/dpu_12_2_glymur.h" #include "catalog/dpu_12_4_eliza.h" #include "catalog/dpu_13_0_kaanapali.h" diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index ea36360c05d85..b3dce2a972d4c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -777,6 +777,7 @@ extern const struct dpu_mdss_cfg dpu_msm8937_cfg; extern const struct dpu_mdss_cfg dpu_msm8953_cfg; extern const struct dpu_mdss_cfg dpu_msm8996_cfg; extern const struct dpu_mdss_cfg dpu_msm8998_cfg; +extern const struct dpu_mdss_cfg dpu_nord_cfg; extern const struct dpu_mdss_cfg dpu_sar2130p_cfg; extern const struct dpu_mdss_cfg dpu_sdm630_cfg; extern const struct dpu_mdss_cfg dpu_sdm660_cfg; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index 5b7cd5241f450..c9c297ca080c5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -206,6 +206,16 @@ static const struct dpu_intr_reg dpu_intr_set_7xxx[] = { MDP_INTF_REV_7xxx_INTR_EN(8), MDP_INTF_REV_7xxx_INTR_STATUS(8) }, + [MDP_INTF9_INTR] = { + MDP_INTF_REV_7xxx_INTR_CLEAR(9), + MDP_INTF_REV_7xxx_INTR_EN(9), + MDP_INTF_REV_7xxx_INTR_STATUS(9) + }, + [MDP_INTF10_INTR] = { + MDP_INTF_REV_7xxx_INTR_CLEAR(10), + MDP_INTF_REV_7xxx_INTR_EN(10), + MDP_INTF_REV_7xxx_INTR_STATUS(10) + }, }; /* @@ -282,6 +292,16 @@ static const struct dpu_intr_reg dpu_intr_set_13xx[] = { MDP_INTF_REV_13xx_INTR_EN(8), MDP_INTF_REV_13xx_INTR_STATUS(8) }, + [MDP_INTF9_INTR] = { + MDP_INTF_REV_13xx_INTR_CLEAR(9), + MDP_INTF_REV_13xx_INTR_EN(9), + MDP_INTF_REV_13xx_INTR_STATUS(9) + }, + [MDP_INTF10_INTR] = { + MDP_INTF_REV_13xx_INTR_CLEAR(10), + MDP_INTF_REV_13xx_INTR_EN(10), + MDP_INTF_REV_13xx_INTR_STATUS(10) + }, }; #define DPU_IRQ_MASK(irq_idx) (BIT(DPU_IRQ_BIT(irq_idx))) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h index 142358a105c59..7b8a04f8d2091 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h @@ -27,6 +27,8 @@ enum dpu_hw_intr_reg { MDP_INTF6_INTR, MDP_INTF7_INTR, MDP_INTF8_INTR, + MDP_INTF9_INTR, + MDP_INTF10_INTR, MDP_INTF1_TEAR_INTR, MDP_INTF2_TEAR_INTR, MDP_AD4_0_INTR, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h index 0e65bf5ddc4a6..7eccb4d2c65ef 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h @@ -226,6 +226,8 @@ enum dpu_intf { INTF_6, INTF_7, INTF_8, + INTF_9, + INTF_10, INTF_MAX }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index d6182cec06d58..1785ee61e23f0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1514,6 +1514,7 @@ static const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,msm8953-mdp5", .data = &dpu_msm8953_cfg, }, { .compatible = "qcom,msm8996-mdp5", .data = &dpu_msm8996_cfg, }, { .compatible = "qcom,msm8998-dpu", .data = &dpu_msm8998_cfg, }, + { .compatible = "qcom,nord-dpu", .data = &dpu_nord_cfg, }, { .compatible = "qcom,qcm2290-dpu", .data = &dpu_qcm2290_cfg, }, { .compatible = "qcom,sa8775p-dpu", .data = &dpu_sa8775p_cfg, }, { .compatible = "qcom,sar2130p-dpu", .data = &dpu_sar2130p_cfg, }, From 908c3cac5d70978c7e5b44cc6a7a1947a65acc04 Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Mon, 12 Oct 2026 19:02:15 +0530 Subject: [PATCH 1118/1133] FROMLIST: drm/msm: mdss: Add support for MDSS on Nord Add Mobile Display Subsystem (MDSS) support for the Nord platform. Signed-off-by: Mahadevan P Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-5-a2ab9af954d2@oss.qualcomm.com/ --- drivers/gpu/drm/msm/msm_mdss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index fb0261ae9c789..17bce191790bb 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -597,6 +597,7 @@ static const struct of_device_id mdss_dt_match[] = { { .compatible = "qcom,kaanapali-mdss", .data = &data_57k }, { .compatible = "qcom,milos-mdss", .data = &data_14k }, { .compatible = "qcom,msm8998-mdss", .data = &data_76k8 }, + { .compatible = "qcom,nord-mdss", .data = &data_57k }, { .compatible = "qcom,qcm2290-mdss", .data = &data_76k8 }, { .compatible = "qcom,qcs8300-mdss", .data = &data_74k }, { .compatible = "qcom,sa8775p-mdss", .data = &data_74k }, From f5621caafbc1a80fb1ece9354f41abc31e154f9b Mon Sep 17 00:00:00 2001 From: Mahadevan P Date: Mon, 12 Oct 2026 19:02:16 +0530 Subject: [PATCH 1119/1133] FROMLIST: drm/msm/dp: Add support for DP controllers on Nord Add the Nord DP desc and compatible. Nord is supporting the four DP cotnrollers, two per MDSS instance. Signed-off-by: Mahadevan P Signed-off-by: Nabige Aala Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-6-a2ab9af954d2@oss.qualcomm.com/ --- drivers/gpu/drm/msm/dp/dp_display.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 95554d61ff3a3..2eede93bd43bb 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -112,6 +112,14 @@ static const struct msm_dp_desc msm_dp_desc_glymur[] = { {} }; +static const struct msm_dp_desc msm_dp_desc_nord[] = { + { .io_start = 0x0af54000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, + { .io_start = 0x0af5c000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true }, + { .io_start = 0x08d54000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, + { .io_start = 0x08d5c000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true }, + {} +}; + static const struct msm_dp_desc msm_dp_desc_sa8775p[] = { { .io_start = 0x0af54000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, { .io_start = 0x0af5c000, .id = MSM_DP_CONTROLLER_1, .wide_bus_supported = true }, @@ -176,6 +184,7 @@ static const struct msm_dp_desc msm_dp_desc_x1e80100[] = { static const struct of_device_id msm_dp_dt_match[] = { { .compatible = "qcom,glymur-dp", .data = &msm_dp_desc_glymur }, { .compatible = "qcom,kaanapali-dp", .data = &msm_dp_desc_kaanapali }, + { .compatible = "qcom,nord-dp", .data = &msm_dp_desc_nord }, { .compatible = "qcom,sa8775p-dp", .data = &msm_dp_desc_sa8775p }, { .compatible = "qcom,sc7180-dp", .data = &msm_dp_desc_sc7180 }, { .compatible = "qcom,sc7280-dp", .data = &msm_dp_desc_sc7280 }, From f4b672ce8ee335e7dbcd546a4fbef90f38cccf27 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Mon, 12 Oct 2026 19:02:17 +0530 Subject: [PATCH 1120/1133] FROMLIST: phy: qcom: edp: Add Nord-specific register offsets Nord relocates several DP PHY and QSERDES v8 COM registers relative to existing SoCs. Add Nord-specific defines for the relocated and new-only registers in phy-qcom-qmp-qserdes-dp-com-v8.h and phy-qcom-edp.c so Nord sequences can reference them by name. Assisted-by: LLM Signed-off-by: Ritesh Kumar Signed-off-by: Nabige Aala Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-7-a2ab9af954d2@oss.qualcomm.com/ --- drivers/phy/qualcomm/phy-qcom-edp.c | 7 +++++++ drivers/phy/qualcomm/phy-qcom-qmp-qserdes-dp-com-v8.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c index a3c893f72908f..d5c6835b6c704 100644 --- a/drivers/phy/qualcomm/phy-qcom-edp.c +++ b/drivers/phy/qualcomm/phy-qcom-edp.c @@ -42,8 +42,15 @@ #define DP_PHY_VCO_DIV 0x0074 #define DP_PHY_TX0_TX1_LANE_CTL 0x007c #define DP_PHY_TX2_TX3_LANE_CTL 0x00a0 +#define DP_PHY_TX2_TX3_LANE_CTL_NORD 0x00c0 #define DP_PHY_STATUS 0x00e0 +#define DP_PHY_STATUS_NORD 0x0110 +#define DP_PHY_LDO_CFG_NORD 0x00f0 + +#define DP_PHY_TX_LN0_DRV_LVL_NORD 0x00e4 +#define DP_PHY_TX_LN1_DRV_LVL_NORD 0x00e8 +#define TXn_TX_BAND_NORD 0x0024 /* LANE_TXn registers */ #define TXn_CLKBUF_ENABLE 0x0000 diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-dp-com-v8.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-dp-com-v8.h index 93edabb830af7..008b17222a8da 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-dp-com-v8.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-dp-com-v8.h @@ -48,5 +48,8 @@ #define DP_QSERDES_V8_COM_CLK_FWD_CONFIG_1 0x2f4 #define DP_QSERDES_V8_COM_CMN_STATUS 0x314 #define DP_QSERDES_V8_COM_C_READY_STATUS 0x33c +#define DP_QSERDES_V8_COM_SVS_MODE_CLK_SEL_NORD 0x17c +#define DP_QSERDES_V8_COM_CMN_STATUS_NORD 0x1d0 +#define DP_QSERDES_V8_COM_C_READY_STATUS_NORD 0x1f8 #endif From 35231ea52196256fba92a92fe339c6bb9bf0b890 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Mon, 12 Oct 2026 19:02:18 +0530 Subject: [PATCH 1121/1133] FROMLIST: phy: qcom: edp: Generalize power-on path for per-SoC overrides Nord has a different register layout that the existing hard-coded power-on path cannot accommodate. Introduce qcom_edp_tx_res_entry and replace open-coded TX resistor writes with a data-driven loop that also handles base=2 (PHY/edp base) for Nord. Add phy_status_reg, bias1_en_2lane, tx2_tx3_lane_ctl, tx_res_cfg, cmn_status_reg and c_ready_status_reg to qcom_edp_phy_cfg, and make com_clk_fwd_cfg optional. No functional change for existing SoCs. Assisted-by: LLM Signed-off-by: Ritesh Kumar Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-8-a2ab9af954d2@oss.qualcomm.com/ --- drivers/phy/qualcomm/phy-qcom-edp.c | 82 +++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c index d5c6835b6c704..c5df1086607f0 100644 --- a/drivers/phy/qualcomm/phy-qcom-edp.c +++ b/drivers/phy/qualcomm/phy-qcom-edp.c @@ -81,6 +81,15 @@ struct qcom_edp_swing_pre_emph_cfg { struct qcom_edp; +struct qcom_edp_tx_res_entry { + u8 base; + u32 offset; + u32 val; +}; + +#define QCOM_EDP_TX_RES_ENTRY_END { .offset = 0, .val = 0, .base = 0xff } +#define qcom_edp_tx_res_entry_is_end(e) ((e)->base == 0xff) + struct phy_ver_ops { int (*com_power_on)(const struct qcom_edp *edp); int (*com_resetsm_cntrl)(const struct qcom_edp *edp); @@ -98,6 +107,12 @@ struct qcom_edp_phy_cfg { const struct qcom_edp_swing_pre_emph_cfg *dp_swing_pre_emph_cfg; const struct qcom_edp_swing_pre_emph_cfg *edp_swing_pre_emph_cfg; const struct phy_ver_ops *ver_ops; + u32 phy_status_reg; + u8 bias1_en_2lane; + u32 tx2_tx3_lane_ctl; + const struct qcom_edp_tx_res_entry *tx_res_cfg; + u32 cmn_status_reg; + u32 c_ready_status_reg; }; struct qcom_edp { @@ -313,9 +328,11 @@ static int qcom_edp_phy_init(struct phy *phy) memcpy(aux_cfg, edp->cfg->aux_cfg, sizeof(aux_cfg)); - ret = edp->cfg->ver_ops->com_clk_fwd_cfg(edp); - if (ret) - return ret; + if (edp->cfg->ver_ops->com_clk_fwd_cfg) { + ret = edp->cfg->ver_ops->com_clk_fwd_cfg(edp); + if (ret) + return ret; + } writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, @@ -672,6 +689,16 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v4 = { .com_ldo_config = qcom_edp_ldo_config_v4, }; +static const struct qcom_edp_tx_res_entry tx_res_cfg_default[] = { + { 0, TXn_RES_CODE_LANE_OFFSET_TX0, 0x11 }, + { 0, TXn_RES_CODE_LANE_OFFSET_TX1, 0x11 }, + { 1, TXn_RES_CODE_LANE_OFFSET_TX0, 0x11 }, + { 1, TXn_RES_CODE_LANE_OFFSET_TX1, 0x11 }, + { 0, TXn_TX_EMP_POST1_LVL, 0x10 }, + { 1, TXn_TX_EMP_POST1_LVL, 0x10 }, + QCOM_EDP_TX_RES_ENTRY_END, +}; + static const struct qcom_edp_phy_cfg sa8775p_dp_phy_cfg = { .is_edp = false, .aux_cfg = edp_phy_aux_cfg_v5, @@ -679,6 +706,9 @@ static const struct qcom_edp_phy_cfg sa8775p_dp_phy_cfg = { .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg, .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg, .ver_ops = &qcom_edp_phy_ops_v4, + .phy_status_reg = DP_PHY_STATUS, + .tx2_tx3_lane_ctl = DP_PHY_TX2_TX3_LANE_CTL, + .tx_res_cfg = tx_res_cfg_default, }; static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = { @@ -687,6 +717,9 @@ static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = { .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg, .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v3, .ver_ops = &qcom_edp_phy_ops_v3, + .phy_status_reg = DP_PHY_STATUS, + .tx2_tx3_lane_ctl = DP_PHY_TX2_TX3_LANE_CTL, + .tx_res_cfg = tx_res_cfg_default, }; static const struct qcom_edp_phy_cfg sc8180x_dp_phy_cfg = { @@ -695,6 +728,9 @@ static const struct qcom_edp_phy_cfg sc8180x_dp_phy_cfg = { .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg_v2, .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v2, .ver_ops = &qcom_edp_phy_ops_v3, + .phy_status_reg = DP_PHY_STATUS, + .tx2_tx3_lane_ctl = DP_PHY_TX2_TX3_LANE_CTL, + .tx_res_cfg = tx_res_cfg_default, }; static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = { @@ -703,6 +739,9 @@ static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = { .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg, .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg, .ver_ops = &qcom_edp_phy_ops_v4, + .phy_status_reg = DP_PHY_STATUS, + .tx2_tx3_lane_ctl = DP_PHY_TX2_TX3_LANE_CTL, + .tx_res_cfg = tx_res_cfg_default, }; static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = { @@ -712,6 +751,9 @@ static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = { .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg, .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg, .ver_ops = &qcom_edp_phy_ops_v4, + .phy_status_reg = DP_PHY_STATUS, + .tx2_tx3_lane_ctl = DP_PHY_TX2_TX3_LANE_CTL, + .tx_res_cfg = tx_res_cfg_default, }; static int qcom_edp_phy_power_on_v6(const struct qcom_edp *edp) @@ -913,6 +955,9 @@ static struct qcom_edp_phy_cfg x1e80100_phy_cfg = { .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg, .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg, .ver_ops = &qcom_edp_phy_ops_v6, + .phy_status_reg = DP_PHY_STATUS, + .tx2_tx3_lane_ctl = DP_PHY_TX2_TX3_LANE_CTL, + .tx_res_cfg = tx_res_cfg_default, }; static int qcom_edp_com_configure_ssc_v8(const struct qcom_edp *edp) @@ -1045,8 +1090,8 @@ static int qcom_edp_phy_com_resetsm_cntrl_v8(const struct qcom_edp *edp) writel(0x20, edp->pll + DP_QSERDES_V8_COM_RESETSM_CNTRL); - return readl_poll_timeout(edp->pll + DP_QSERDES_V8_COM_C_READY_STATUS, - val, val & BIT(0), 500, 10000); + return readl_poll_timeout(edp->pll + edp->cfg->c_ready_status_reg, + val, val & BIT(0), 500, 10000); } static int qcom_edp_com_clk_fwd_cfg_v8(const struct qcom_edp *edp) @@ -1074,8 +1119,8 @@ static int qcom_edp_phy_power_on_v8(const struct qcom_edp *edp) edp->edp + DP_PHY_PD_CTL); writel(0xfc, edp->edp + DP_PHY_MODE); - return readl_poll_timeout(edp->pll + DP_QSERDES_V8_COM_CMN_STATUS, - val, val & BIT(7), 5, 200); + return readl_poll_timeout(edp->pll + edp->cfg->cmn_status_reg, + val, val & BIT(7), 5, 200); } static const struct phy_ver_ops qcom_edp_phy_ops_v8 = { @@ -1094,6 +1139,11 @@ static struct qcom_edp_phy_cfg glymur_phy_cfg = { .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg_v8, .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg, .ver_ops = &qcom_edp_phy_ops_v8, + .phy_status_reg = DP_PHY_STATUS, + .tx2_tx3_lane_ctl = DP_PHY_TX2_TX3_LANE_CTL, + .tx_res_cfg = tx_res_cfg_default, + .cmn_status_reg = DP_QSERDES_V8_COM_CMN_STATUS, + .c_ready_status_reg = DP_QSERDES_V8_COM_C_READY_STATUS, }; static int qcom_edp_phy_power_on(struct phy *phy) @@ -1128,7 +1178,7 @@ static int qcom_edp_phy_power_on(struct phy *phy) /* TX Lane configuration */ writel(0x05, edp->edp + DP_PHY_TX0_TX1_LANE_CTL); - writel(0x05, edp->edp + DP_PHY_TX2_TX3_LANE_CTL); + writel(0x05, edp->edp + edp->cfg->tx2_tx3_lane_ctl); /* TX-0 register configuration */ writel(0x03, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN); @@ -1166,13 +1216,13 @@ static int qcom_edp_phy_power_on(struct phy *phy) writel(0x00, edp->tx1 + TXn_TX_POL_INV); writel(0x10, edp->tx0 + TXn_TX_DRV_LVL_OFFSET); writel(0x10, edp->tx1 + TXn_TX_DRV_LVL_OFFSET); - writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX0); - writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX1); - writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX0); - writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX1); + for (const struct qcom_edp_tx_res_entry *e = edp->cfg->tx_res_cfg; + !qcom_edp_tx_res_entry_is_end(e); e++) { + void __iomem *base = e->base == 2 ? edp->edp : + e->base ? edp->tx1 : edp->tx0; - writel(0x10, edp->tx0 + TXn_TX_EMP_POST1_LVL); - writel(0x10, edp->tx1 + TXn_TX_EMP_POST1_LVL); + writel(e->val, base + e->offset); + } writel(0x1f, edp->tx0 + TXn_TX_DRV_LVL); writel(0x1f, edp->tx1 + TXn_TX_DRV_LVL); @@ -1184,7 +1234,7 @@ static int qcom_edp_phy_power_on(struct phy *phy) cfg1 = 0x1; } else if (edp->dp_opts.lanes == 2) { bias0_en = 0x03; - bias1_en = 0x00; + bias1_en = edp->cfg->bias1_en_2lane; drvr0_en = 0x04; drvr1_en = 0x07; cfg1 = 0x3; @@ -1207,7 +1257,7 @@ static int qcom_edp_phy_power_on(struct phy *phy) writel(0x19, edp->edp + DP_PHY_CFG); - ret = readl_poll_timeout(edp->edp + DP_PHY_STATUS, + ret = readl_poll_timeout(edp->edp + edp->cfg->phy_status_reg, val, val & BIT(1), 500, 10000); if (ret) return ret; From 315426c3d7635201b95035e16a8c9224e405bd65 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Mon, 12 Oct 2026 19:02:19 +0530 Subject: [PATCH 1122/1133] FROMLIST: phy: qcom: edp: Add Nord voltage-swing and pre-emphasis tables Nord requires different TX voltage-swing and pre-emphasis levels for both eDP and DP modes. Add four pairs of 4x4 tables covering RBR/HBR and HBR2/HBR3 for each mode, sourced from HPG Tables 2-2, 2-4, 2-6-a and 2-6-b, and wrap them in qcom_edp_swing_pre_emph_cfg descriptors. The eDP RBR/HBR swing table reuses the existing edp_swing_hbr_rbr directly; all other tables are new. Assisted-by: LLM Signed-off-by: Ritesh Kumar Signed-off-by: Nabige Aala Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-9-a2ab9af954d2@oss.qualcomm.com/ --- drivers/phy/qualcomm/phy-qcom-edp.c | 64 +++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c index c5df1086607f0..c63f721702b17 100644 --- a/drivers/phy/qualcomm/phy-qcom-edp.c +++ b/drivers/phy/qualcomm/phy-qcom-edp.c @@ -1538,6 +1538,70 @@ static int qcom_edp_phy_probe(struct platform_device *pdev) return PTR_ERR_OR_ZERO(phy_provider); } +static const u8 nord_edp_pre_emp_hbr_rbr[4][4] = { + { 0x05, 0x11, 0x17, 0x1d }, + { 0x05, 0x11, 0x18, 0xff }, + { 0x06, 0x11, 0xff, 0xff }, + { 0x00, 0xff, 0xff, 0xff }, +}; + +static const u8 nord_edp_swing_hbr2_hbr3[4][4] = { + { 0x0b, 0x11, 0x17, 0x1c }, + { 0x10, 0x19, 0x1f, 0xff }, + { 0x19, 0x1f, 0xff, 0xff }, + { 0x1f, 0xff, 0xff, 0xff }, +}; + +static const u8 nord_edp_pre_emp_hbr2_hbr3[4][4] = { + { 0x0c, 0x15, 0x19, 0x1e }, + { 0x0b, 0x15, 0x19, 0xff }, + { 0x0e, 0x14, 0xff, 0xff }, + { 0x0d, 0xff, 0xff, 0xff }, +}; + +static const struct qcom_edp_swing_pre_emph_cfg nord_edp_swing_pre_emph_cfg = { + .swing_hbr_rbr = &edp_swing_hbr_rbr, + .swing_hbr3_hbr2 = &nord_edp_swing_hbr2_hbr3, + .pre_emphasis_hbr_rbr = &nord_edp_pre_emp_hbr_rbr, + .pre_emphasis_hbr3_hbr2 = &nord_edp_pre_emp_hbr2_hbr3, +}; + +static const u8 nord_dp_swing_hbr2_hbr3[4][4] = { + { 0x02, 0x12, 0x16, 0x1a }, + { 0x09, 0x19, 0x1f, 0xff }, + { 0x10, 0x1f, 0xff, 0xff }, + { 0x1f, 0xff, 0xff, 0xff }, +}; + +static const u8 nord_dp_pre_emp_hbr2_hbr3[4][4] = { + { 0x00, 0x0c, 0x15, 0x1b }, + { 0x02, 0x0e, 0x16, 0xff }, + { 0x02, 0x11, 0xff, 0xff }, + { 0x04, 0xff, 0xff, 0xff }, +}; + +static const u8 nord_dp_swing_hbr_rbr[4][4] = { + { 0x07, 0x0f, 0x16, 0x1f }, + { 0x11, 0x1e, 0x1f, 0xff }, + { 0x16, 0x1f, 0xff, 0xff }, + { 0x1f, 0xff, 0xff, 0xff }, +}; + +static const u8 nord_dp_pre_emp_hbr_rbr[4][4] = { + { 0x00, 0x0e, 0x15, 0x1a }, + { 0x00, 0x0e, 0x15, 0xff }, + { 0x00, 0x0e, 0xff, 0xff }, + { 0x02, 0xff, 0xff, 0xff }, +}; + +static const struct qcom_edp_swing_pre_emph_cfg nord_dp_swing_pre_emph_cfg = { + .swing_hbr_rbr = &nord_dp_swing_hbr_rbr, + .swing_hbr3_hbr2 = &nord_dp_swing_hbr2_hbr3, + .pre_emphasis_hbr_rbr = &nord_dp_pre_emp_hbr_rbr, + .pre_emphasis_hbr3_hbr2 = &nord_dp_pre_emp_hbr2_hbr3, +}; + + static const struct of_device_id qcom_edp_phy_match_table[] = { { .compatible = "qcom,glymur-dp-phy", .data = &glymur_phy_cfg, }, { .compatible = "qcom,sa8775p-edp-phy", .data = &sa8775p_dp_phy_cfg, }, From f05953fb1a101d9201babe49efabe7d12c9c5e49 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Mon, 12 Oct 2026 19:02:20 +0530 Subject: [PATCH 1123/1133] FROMLIST: phy: qcom: edp: Add Nord spread-spectrum clocking configuration callback Nord requires different SSC register values compared to existing SoCs. Add qcom_edp_com_configure_ssc_nord() which programs SSC_PER1/2 with fixed values and link-rate-dependent SSC_STEP_SIZE1/2 for RBR, HBR, HBR2 and HBR3, per HPG Table 2-9. Assisted-by: LLM Signed-off-by: Ritesh Kumar Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-10-a2ab9af954d2@oss.qualcomm.com/ --- drivers/phy/qualcomm/phy-qcom-edp.c | 36 +++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c index c63f721702b17..66c31684c48ed 100644 --- a/drivers/phy/qualcomm/phy-qcom-edp.c +++ b/drivers/phy/qualcomm/phy-qcom-edp.c @@ -1601,6 +1601,42 @@ static const struct qcom_edp_swing_pre_emph_cfg nord_dp_swing_pre_emph_cfg = { .pre_emphasis_hbr3_hbr2 = &nord_dp_pre_emp_hbr2_hbr3, }; +static int qcom_edp_com_configure_ssc_nord(const struct qcom_edp *edp) +{ + const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts; + u32 step1; + u32 step2; + + switch (dp_opts->link_rate) { + case 1620: + step1 = 0x83; + step2 = 0x02; + break; + + case 2700: + case 5400: + step1 = 0x18; + step2 = 0x02; + break; + + case 8100: + step1 = 0x5b; + step2 = 0x02; + break; + + default: + return -EINVAL; + } + + writel(0x01, edp->pll + DP_QSERDES_V8_COM_SSC_EN_CENTER); + writel(0x00, edp->pll + DP_QSERDES_V8_COM_SSC_ADJ_PER1); + writel(0x6b, edp->pll + DP_QSERDES_V8_COM_SSC_PER1); + writel(0x02, edp->pll + DP_QSERDES_V8_COM_SSC_PER2); + writel(step1, edp->pll + DP_QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0); + writel(step2, edp->pll + DP_QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0); + + return 0; +} static const struct of_device_id qcom_edp_phy_match_table[] = { { .compatible = "qcom,glymur-dp-phy", .data = &glymur_phy_cfg, }, From 450c07c364e0ae14cee3a28230e8dfa57d49e5c2 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Mon, 12 Oct 2026 19:02:21 +0530 Subject: [PATCH 1124/1133] FROMLIST: phy: qcom: edp: Add Nord PLL configuration callback Nord uses a 38.4 MHz CXO reference with a different QSERDES v8 COM register layout and PLL coefficients. Add qcom_edp_com_configure_pll_nord() which programs all QSERDES COM PLL registers with link-rate-dependent values for RBR, HBR, HBR2 and HBR3, per HPG Table 2-1-d. Assisted-by: LLM Signed-off-by: Ritesh Kumar Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-11-a2ab9af954d2@oss.qualcomm.com/ --- drivers/phy/qualcomm/phy-qcom-edp.c | 103 ++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c index 66c31684c48ed..3e857d1056680 100644 --- a/drivers/phy/qualcomm/phy-qcom-edp.c +++ b/drivers/phy/qualcomm/phy-qcom-edp.c @@ -1638,6 +1638,109 @@ static int qcom_edp_com_configure_ssc_nord(const struct qcom_edp *edp) return 0; } +static int qcom_edp_com_configure_pll_nord(const struct qcom_edp *edp) +{ + const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts; + u32 div_frac_start2_mode0; + u32 div_frac_start3_mode0; + u32 dec_start_mode0; + u32 lock_cmp1_mode0; + u32 lock_cmp2_mode0; + u32 lock_cmp_en; + u32 hsclk_sel; + u32 code1_mode0; + u32 code2_mode0; + u32 core_clk_div_mode0 = 0x14; + + switch (dp_opts->link_rate) { + case 1620: + hsclk_sel = 0x0c; + dec_start_mode0 = 0x54; + div_frac_start2_mode0 = 0x00; + div_frac_start3_mode0 = 0x06; + lock_cmp1_mode0 = 0x37; + lock_cmp2_mode0 = 0x04; + lock_cmp_en = 0x04; + code1_mode0 = 0x8d; + code2_mode0 = 0x27; + break; + + case 2700: + hsclk_sel = 0x04; + dec_start_mode0 = 0x46; + div_frac_start2_mode0 = 0x00; + div_frac_start3_mode0 = 0x05; + lock_cmp1_mode0 = 0x07; + lock_cmp2_mode0 = 0x07; + lock_cmp_en = 0x08; + code1_mode0 = 0xf6; + code2_mode0 = 0x20; + break; + + case 5400: + hsclk_sel = 0x01; + dec_start_mode0 = 0x46; + div_frac_start2_mode0 = 0x00; + div_frac_start3_mode0 = 0x05; + lock_cmp1_mode0 = 0x0f; + lock_cmp2_mode0 = 0x0e; + lock_cmp_en = 0x08; + code1_mode0 = 0xf6; + code2_mode0 = 0x20; + break; + + case 8100: + hsclk_sel = 0x03; + dec_start_mode0 = 0x4f; + div_frac_start2_mode0 = 0xa0; + div_frac_start3_mode0 = 0x01; + lock_cmp1_mode0 = 0x17; + lock_cmp2_mode0 = 0x15; + lock_cmp_en = 0x08; + code1_mode0 = 0x14; + code2_mode0 = 0x25; + core_clk_div_mode0 = 0x0a; + break; + + default: + return -EINVAL; + } + + writel(0x01, edp->pll + DP_QSERDES_V8_COM_SVS_MODE_CLK_SEL_NORD); + writel(0x0b, edp->pll + DP_QSERDES_V8_COM_SYSCLK_EN_SEL); + writel(0x02, edp->pll + DP_QSERDES_V8_COM_SYS_CLK_CTRL); + writel(0x0c, edp->pll + DP_QSERDES_V8_COM_CLK_ENABLE1); + writel(0x06, edp->pll + DP_QSERDES_V8_COM_SYSCLK_BUF_ENABLE); + writel(0x30, edp->pll + DP_QSERDES_V8_COM_CLK_SELECT); + writel(hsclk_sel, edp->pll + DP_QSERDES_V8_COM_HSCLK_SEL_1); + writel(0x07, edp->pll + DP_QSERDES_V8_COM_PLL_IVCO); + writel(lock_cmp_en, edp->pll + DP_QSERDES_V8_COM_LOCK_CMP_EN); + writel(0x36, edp->pll + DP_QSERDES_V8_COM_PLL_CCTRL_MODE0); + writel(0x16, edp->pll + DP_QSERDES_V8_COM_PLL_RCTRL_MODE0); + writel(0x06, edp->pll + DP_QSERDES_V8_COM_CP_CTRL_MODE0); + writel(dec_start_mode0, edp->pll + DP_QSERDES_V8_COM_DEC_START_MODE0); + writel(0x00, edp->pll + DP_QSERDES_V8_COM_DIV_FRAC_START1_MODE0); + writel(div_frac_start2_mode0, edp->pll + DP_QSERDES_V8_COM_DIV_FRAC_START2_MODE0); + writel(div_frac_start3_mode0, edp->pll + DP_QSERDES_V8_COM_DIV_FRAC_START3_MODE0); + writel(0x12, edp->pll + DP_QSERDES_V8_COM_CMN_CONFIG_1); + writel(0x3f, edp->pll + DP_QSERDES_V8_COM_INTEGLOOP_GAIN0_MODE0); + writel(0x00, edp->pll + DP_QSERDES_V8_COM_INTEGLOOP_GAIN1_MODE0); + writel(0x00, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE_MAP); + writel(lock_cmp1_mode0, edp->pll + DP_QSERDES_V8_COM_LOCK_CMP1_MODE0); + writel(lock_cmp2_mode0, edp->pll + DP_QSERDES_V8_COM_LOCK_CMP2_MODE0); + writel(0x0a, edp->pll + DP_QSERDES_V8_COM_BG_TIMER); + writel(core_clk_div_mode0, edp->pll + DP_QSERDES_V8_COM_CORECLK_DIV_MODE0); + writel(0x00, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE_CTRL); + writel(0x1f, edp->pll + DP_QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN); + writel(0x0f, edp->pll + DP_QSERDES_V8_COM_CORE_CLK_EN); + writel(0xa0, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE1_MODE0); + writel(0x01, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE2_MODE0); + writel(code1_mode0, edp->pll + DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0); + writel(code2_mode0, edp->pll + DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0); + + return 0; +} + static const struct of_device_id qcom_edp_phy_match_table[] = { { .compatible = "qcom,glymur-dp-phy", .data = &glymur_phy_cfg, }, { .compatible = "qcom,sa8775p-edp-phy", .data = &sa8775p_dp_phy_cfg, }, From 209e00c73f1b7d9be6fa2dd7babcf9d0d4795289 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Mon, 12 Oct 2026 19:02:22 +0530 Subject: [PATCH 1125/1133] FROMLIST: phy: qcom: edp: Add Nord PHY configuration data tables Add Nord-specific AUX channel, VCO divider, LDO and TX resistor calibration data: edp_phy_aux_cfg_nord[], edp_phy_vco_div_cfg_nord[], qcom_edp_ldo_config_nord() and tx_res_cfg_nord[], sourced from HPG Tables 2-1-a, 2-1-b and 2-1-d. Signed-off-by: Ritesh Kumar Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-12-a2ab9af954d2@oss.qualcomm.com/ --- drivers/phy/qualcomm/phy-qcom-edp.c | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c index 3e857d1056680..cb5f6e0ae607b 100644 --- a/drivers/phy/qualcomm/phy-qcom-edp.c +++ b/drivers/phy/qualcomm/phy-qcom-edp.c @@ -1741,6 +1741,39 @@ static int qcom_edp_com_configure_pll_nord(const struct qcom_edp *edp) return 0; } +static const u8 edp_phy_aux_cfg_nord[DP_AUX_CFG_SIZE] = { + 0x00, 0x13, 0xa4, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03, 0x02, 0x02, 0x04, +}; + +static const u8 edp_phy_vco_div_cfg_nord[4] = { + 0x00, 0x00, 0x02, 0x01, +}; + +static int qcom_edp_ldo_config_nord(const struct qcom_edp *edp) +{ + const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts; + + writel(0xd0, edp->tx0 + TXn_LDO_CONFIG); + writel(dp_opts->lanes > 2 ? 0xd0 : 0x00, edp->tx1 + TXn_LDO_CONFIG); + writel(0x03, edp->edp + DP_PHY_LDO_CFG_NORD); + + return 0; +} + +static const struct qcom_edp_tx_res_entry tx_res_cfg_nord[] = { + { 0, TXn_RES_CODE_LANE_OFFSET_TX0, 0x06 }, + { 0, TXn_RES_CODE_LANE_OFFSET_TX1, 0x06 }, + { 1, TXn_RES_CODE_LANE_OFFSET_TX0, 0x06 }, + { 1, TXn_RES_CODE_LANE_OFFSET_TX1, 0x06 }, + { 0, TXn_TX_EMP_POST1_LVL, 0x06 }, + { 1, TXn_TX_EMP_POST1_LVL, 0x06 }, + { 0, TXn_TX_BAND_NORD, 0x05 }, + { 1, TXn_TX_BAND_NORD, 0x05 }, + { 2, DP_PHY_TX_LN0_DRV_LVL_NORD, 0x12 }, + { 2, DP_PHY_TX_LN1_DRV_LVL_NORD, 0x12 }, + QCOM_EDP_TX_RES_ENTRY_END, +}; + static const struct of_device_id qcom_edp_phy_match_table[] = { { .compatible = "qcom,glymur-dp-phy", .data = &glymur_phy_cfg, }, { .compatible = "qcom,sa8775p-edp-phy", .data = &sa8775p_dp_phy_cfg, }, From 56814926567d8bfce29ea9a7892be2455e74fdd2 Mon Sep 17 00:00:00 2001 From: Ritesh Kumar Date: Mon, 12 Oct 2026 19:02:23 +0530 Subject: [PATCH 1126/1133] FROMLIST: phy: qcom: edp: Add Nord phy_cfg, ops and OF compatible Wire up Nord-specific callbacks into qcom_edp_phy_ops_nord and assemble nord_edp_phy_cfg with all Nord-specific values: AUX/VCO tables, swing/pre-emphasis tables, relocated status register offsets and TX lane control. Register "qcom,nord-dp-phy" in the OF match table so the driver binds to Nord DP PHY device-tree nodes. Signed-off-by: Ritesh Kumar Signed-off-by: Nabige Aala Link: https://lore.kernel.org/r/20261012-nord-drv-dt-v2-13-a2ab9af954d2@oss.qualcomm.com/ --- drivers/phy/qualcomm/phy-qcom-edp.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c index cb5f6e0ae607b..87400d61323a6 100644 --- a/drivers/phy/qualcomm/phy-qcom-edp.c +++ b/drivers/phy/qualcomm/phy-qcom-edp.c @@ -1774,6 +1774,30 @@ static const struct qcom_edp_tx_res_entry tx_res_cfg_nord[] = { QCOM_EDP_TX_RES_ENTRY_END, }; +static const struct phy_ver_ops qcom_edp_phy_ops_nord = { + .com_power_on = qcom_edp_phy_power_on_v8, + .com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v8, + .com_bias_en_clkbuflr = qcom_edp_com_bias_en_clkbuflr_v8, + .com_configure_pll = qcom_edp_com_configure_pll_nord, + .com_configure_ssc = qcom_edp_com_configure_ssc_nord, + .com_ldo_config = qcom_edp_ldo_config_nord, +}; + +static const struct qcom_edp_phy_cfg nord_edp_phy_cfg = { + .is_edp = false, + .aux_cfg = edp_phy_aux_cfg_nord, + .vco_div_cfg = edp_phy_vco_div_cfg_nord, + .dp_swing_pre_emph_cfg = &nord_dp_swing_pre_emph_cfg, + .edp_swing_pre_emph_cfg = &nord_edp_swing_pre_emph_cfg, + .ver_ops = &qcom_edp_phy_ops_nord, + .phy_status_reg = DP_PHY_STATUS_NORD, + .bias1_en_2lane = 0x03, + .tx2_tx3_lane_ctl = DP_PHY_TX2_TX3_LANE_CTL_NORD, + .tx_res_cfg = tx_res_cfg_nord, + .cmn_status_reg = DP_QSERDES_V8_COM_CMN_STATUS_NORD, + .c_ready_status_reg = DP_QSERDES_V8_COM_C_READY_STATUS_NORD, +}; + static const struct of_device_id qcom_edp_phy_match_table[] = { { .compatible = "qcom,glymur-dp-phy", .data = &glymur_phy_cfg, }, { .compatible = "qcom,sa8775p-edp-phy", .data = &sa8775p_dp_phy_cfg, }, @@ -1782,6 +1806,7 @@ static const struct of_device_id qcom_edp_phy_match_table[] = { { .compatible = "qcom,sc8280xp-dp-phy", .data = &sc8280xp_dp_phy_cfg, }, { .compatible = "qcom,sc8280xp-edp-phy", .data = &sc8280xp_edp_phy_cfg, }, { .compatible = "qcom,x1e80100-dp-phy", .data = &x1e80100_phy_cfg, }, + { .compatible = "qcom,nord-dp-phy", .data = &nord_edp_phy_cfg, }, { } }; MODULE_DEVICE_TABLE(of, qcom_edp_phy_match_table); From ee52f4c7ed0f62e41f0b25e741ca05a7a00ce02a Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Tue, 3 Nov 2026 10:58:09 +0530 Subject: [PATCH 1127/1133] Revert "FROMLIST: arm64: dts: qcom: kaanapali: add iris video node" This reverts commit a8c6c009624b273fa8820a65a8fc79cfa3c7d9a4. The reverted patch is replaced by "arm64: dts: qcom: kaanapali: add iris video node", which is part of v5 sub-node series. It describes the per-stream IOVA limits of the VPU using the context bank sub-node design agreed with the maintainers from sub-node series v3 onwards. The dt-schema change for this has also been accepted upstream: https://github.com/devicetree-org/dt-schema/pull/207 Drop the earlier approach from sub-node series v2, so that only one version of the Iris IOMMU description is carried. As part of tech/mm/video being rebased on 7.4-rc1, the latest series of video patches are getting pulled in. This revert keeps the rebased tech/mm/video and the dt branches aligned together. Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 146 ------------------------ 1 file changed, 146 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index 990d9c860594c..a738d5ad6a8f6 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -570,10 +570,6 @@ qcom,client-id = <1>; qcom,vmid = ; }; - - iris_resv: reservation-iris { - iommu-addresses = <&iris_non_pixel 0x0 0x25800000>; - }; }; smp2p-adsp { @@ -2787,148 +2783,6 @@ #reset-cells = <1>; }; - iris: video-codec@2000000 { - compatible = "qcom,kaanapali-iris"; - reg = <0x0 0x02000000 0x0 0xf0000>; - - clocks = <&gcc GCC_VIDEO_AXI0_CLK>, - <&videocc VIDEO_CC_MVS0C_CLK>, - <&videocc VIDEO_CC_MVS0_CLK>, - <&gcc GCC_VIDEO_AXI1_CLK>, - <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, - <&videocc VIDEO_CC_MVS0_FREERUN_CLK>, - <&videocc VIDEO_CC_MVS0B_CLK>, - <&videocc VIDEO_CC_MVS0_VPP0_CLK>, - <&videocc VIDEO_CC_MVS0_VPP1_CLK>, - <&videocc VIDEO_CC_MVS0A_CLK>; - clock-names = "iface", - "core", - "vcodec0_core", - "iface1", - "core_freerun", - "vcodec0_core_freerun", - "vcodec_bse", - "vcodec_vpp0", - "vcodec_vpp1", - "vcodec_apv"; - - dma-coherent; - - 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_MVP QCOM_ICC_TAG_ALWAYS - &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; - interconnect-names = "cpu-cfg", - "video-mem"; - - interrupts = ; - - memory-region = <&video_mem>; - - operating-points-v2 = <&iris_opp_table>; - - power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, - <&videocc VIDEO_CC_MVS0_GDSC>, - <&rpmhpd RPMHPD_MXC>, - <&rpmhpd RPMHPD_MMCX>, - <&videocc VIDEO_CC_MVS0_VPP0_GDSC>, - <&videocc VIDEO_CC_MVS0_VPP1_GDSC>, - <&videocc VIDEO_CC_MVS0A_GDSC>; - power-domain-names = "venus", - "vcodec0", - "mxc", - "mmcx", - "vpp0", - "vpp1", - "apv"; - - resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>, - <&gcc GCC_VIDEO_AXI1_CLK_ARES>, - <&videocc VIDEO_CC_MVS0C_FREERUN_CLK_ARES>, - <&videocc VIDEO_CC_MVS0_FREERUN_CLK_ARES>; - reset-names = "bus0", - "bus1", - "core", - "vcodec0_core"; - - #address-cells = <1>; - #size-cells = <1>; - dma-ranges = <0x0 0x0 0x0 0xffc00000>; - - status = "disabled"; - - iris_non_pixel: non-pixel { - iommus = <&apps_smmu 0x1940 0x0>, - <&apps_smmu 0x1944 0x0>, - <&apps_smmu 0x1a20 0x0>; - memory-region = <&iris_resv>; - }; - - pixel { - iommus = <&apps_smmu 0x1943 0x0>; - }; - - iris_opp_table: opp-table { - compatible = "operating-points-v2"; - - opp-240000000 { - opp-hz = /bits/ 64 <240000000 240000000 - 240000000 360000000>; - required-opps = <&rpmhpd_opp_low_svs_d1>, - <&rpmhpd_opp_low_svs_d1>; - }; - - opp-338000000 { - opp-hz = /bits/ 64 <338000000 338000000 - 338000000 507000000>; - required-opps = <&rpmhpd_opp_low_svs>, - <&rpmhpd_opp_low_svs>; - }; - - opp-420000000 { - opp-hz = /bits/ 64 <420000000 420000000 - 420000000 630000000>; - required-opps = <&rpmhpd_opp_svs>, - <&rpmhpd_opp_svs>; - }; - - opp-444000000 { - opp-hz = /bits/ 64 <444000000 444000000 - 444000000 666000000>; - required-opps = <&rpmhpd_opp_svs>, - <&rpmhpd_opp_svs_l1>; - }; - - opp-533000000 { - opp-hz = /bits/ 64 <533000000 533000000 - 533000000 800000000>; - required-opps = <&rpmhpd_opp_svs>, - <&rpmhpd_opp_nom>; - }; - - opp-630000000 { - opp-hz = /bits/ 64 <630000000 630000000 - 630000000 1104000000>; - required-opps = <&rpmhpd_opp_svs_l1>, - <&rpmhpd_opp_turbo>; - }; - - opp-800000000 { - opp-hz = /bits/ 64 <800000000 630000000 - 630000000 1260000000>; - required-opps = <&rpmhpd_opp_svs_l1>, - <&rpmhpd_opp_turbo_l0>; - }; - - opp-1000000000 { - opp-hz = /bits/ 64 <1000000000 630000000 - 850000000 1260000000>; - required-opps = <&rpmhpd_opp_nom>, - <&rpmhpd_opp_turbo_l1>; - }; - }; - }; - videocc: clock-controller@20f0000 { compatible = "qcom,kaanapali-videocc"; reg = <0x0 0x020f0000 0x0 0x10000>; From 328e6308fce02a33f802dc8084d2cf4b9fa184c3 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 1 Oct 2026 20:47:25 +0530 Subject: [PATCH 1128/1133] FROMLIST: arm64: dts: qcom: kaanapali: add iris video node Add iris video codec to kaanapali SoC, which comes with significantly different powering up sequence than previous iris generation, thus different clocks, power domains and resets. Link: https://lore.kernel.org/all/20261001-kaanapali-iris-v4-5-642f9ac5e699@oss.qualcomm.com/ Co-developed-by: Vishnu Reddy Signed-off-by: Vishnu Reddy Signed-off-by: Vikash Garodia Acked-by: Konrad Dybcio Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/kaanapali.dtsi | 142 ++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi index a738d5ad6a8f6..486215612e2fa 100644 --- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi +++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi @@ -2783,6 +2783,148 @@ #reset-cells = <1>; }; + iris: video-codec@2000000 { + compatible = "qcom,kaanapali-iris"; + reg = <0x0 0x02000000 0x0 0xf0000>; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&gcc GCC_VIDEO_AXI1_CLK>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0B_CLK>, + <&videocc VIDEO_CC_MVS0_VPP0_CLK>, + <&videocc VIDEO_CC_MVS0_VPP1_CLK>, + <&videocc VIDEO_CC_MVS0A_CLK>; + clock-names = "iface", + "core", + "vcodec0_core", + "iface1", + "core_freerun", + "vcodec0_core_freerun", + "vcodec_bse", + "vcodec_vpp0", + "vcodec_vpp1", + "vcodec_apv"; + + dma-coherent; + + 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_MVP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + interrupts = ; + + memory-region = <&video_mem>; + + operating-points-v2 = <&iris_opp_table>; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc VIDEO_CC_MVS0_VPP0_GDSC>, + <&videocc VIDEO_CC_MVS0_VPP1_GDSC>, + <&videocc VIDEO_CC_MVS0A_GDSC>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vpp0", + "vpp1", + "apv"; + + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>, + <&gcc GCC_VIDEO_AXI1_CLK_ARES>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK_ARES>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK_ARES>; + reset-names = "bus0", + "bus1", + "core", + "vcodec0_core"; + + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0x0 0xffc00000>; + + status = "disabled"; + + non-pixel { + iommus = <&apps_smmu 0x1940 0x0>, + <&apps_smmu 0x1944 0x0>, + <&apps_smmu 0x1a20 0x0>; + iommu-ranges = <0x25800000 0xda400000>; + }; + + pixel { + iommus = <&apps_smmu 0x1943 0x0>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000 240000000 + 240000000 360000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 + 338000000 507000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-420000000 { + opp-hz = /bits/ 64 <420000000 420000000 + 420000000 630000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 + 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-533000000 { + opp-hz = /bits/ 64 <533000000 533000000 + 533000000 800000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_nom>; + }; + + opp-630000000 { + opp-hz = /bits/ 64 <630000000 630000000 + 630000000 1104000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo>; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000 630000000 + 630000000 1260000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo_l0>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000 630000000 + 850000000 1260000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo_l1>; + }; + }; + }; + videocc: clock-controller@20f0000 { compatible = "qcom,kaanapali-videocc"; reg = <0x0 0x020f0000 0x0 0x10000>; From 79f82ff5bf7d0bc83ecf3e83f33ace6c38f1ca29 Mon Sep 17 00:00:00 2001 From: Gourav Kumar Date: Tue, 3 Nov 2026 16:38:28 +0530 Subject: [PATCH 1129/1133] Revert "FROMLIST: arm64: dts: qcom: maili: add iris video codec node" This reverts commit fb0c1fca6809c66a965ef609e1870b749f4578b5. The reverted patch is replaced by "arm64: dts: qcom: maili: add iris video codec node", which is part of v5 sub-node series. It describes the per-stream IOVA limits of the VPU using the context bank sub-node design agreed with the maintainers from sub-node series v3 onwards. The dt-schema change for this has also been accepted upstream: https://github.com/devicetree-org/dt-schema/pull/207 Drop the earlier approach from sub-node series v2, so that only one version of the Iris IOMMU description is carried. As part of tech/mm/video being rebased on 7.4-rc1, the latest series of video patches are getting pulled in. This revert keeps the rebased tech/mm/video and the dt branches aligned together. Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/maili.dtsi | 129 ---------------------------- 1 file changed, 129 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/maili.dtsi b/arch/arm64/boot/dts/qcom/maili.dtsi index ba5b453e3de4e..bd9181031b37c 100644 --- a/arch/arm64/boot/dts/qcom/maili.dtsi +++ b/arch/arm64/boot/dts/qcom/maili.dtsi @@ -433,10 +433,6 @@ reg = <0x0 0xbd500000 0x0 0xf00000>; no-map; }; - - iris_resv: reservation-iris { - iommu-addresses = <&iris_non_pixel 0x0 0x0 0x0 0x25800000>; - }; }; smp2p-adsp { @@ -3640,131 +3636,6 @@ power-domains = <&gcc GCC_UFS_PHY_GDSC>; }; - iris: video-codec@2000000 { - compatible = "qcom,maili-iris"; - reg = <0x0 0x02000000 0x0 0xf0000>; - - interrupts = ; - - power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, - <&videocc VIDEO_CC_MVS0_GDSC>, - <&rpmhpd RPMHPD_MXC>, - <&rpmhpd RPMHPD_MMCX>, - <&videocc VIDEO_CC_MVS0_VPP0_GDSC>; - power-domain-names = "venus", - "vcodec0", - "mxc", - "mmcx", - "vpp0"; - - clocks = <&gcc GCC_VIDEO_AXI0_CLK>, - <&videocc VIDEO_CC_MVS0C_CLK>, - <&videocc VIDEO_CC_MVS0_CLK>, - <&gcc GCC_VIDEO_AXI0C_CLK>, - <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, - <&videocc VIDEO_CC_MVS0_FREERUN_CLK>, - <&videocc VIDEO_CC_MVS0B_CLK>, - <&videocc VIDEO_CC_MVS0_VPP0_CLK>; - clock-names = "iface", - "core", - "vcodec0_core", - "iface1", - "core_freerun", - "vcodec0_core_freerun", - "vcodec_bse", - "vcodec_vpp0"; - - operating-points-v2 = <&iris_opp_table>; - - interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY - &config_noc SLAVE_IRIS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, - <&mmss_noc MASTER_VIDEO_MVP QCOM_ICC_TAG_ALWAYS - &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; - interconnect-names = "cpu-cfg", - "video-mem"; - - memory-region = <&video_mem>; - - resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>, - <&gcc GCC_VIDEO_AXI0C_CLK_ARES>, - <&videocc VIDEO_CC_MVS0C_FREERUN_CLK_ARES>, - <&videocc VIDEO_CC_MVS0_FREERUN_CLK_ARES>; - reset-names = "bus0", - "bus1", - "core", - "vcodec0_core"; - - dma-coherent; - - #address-cells = <2>; - #size-cells = <2>; - - status = "disabled"; - - iris_non_pixel: non-pixel { - iommus = <&apps_smmu 0x1540 0x0000>, - <&apps_smmu 0x1620 0x0000>, - <&apps_smmu 0x1544 0x0000>; - memory-region = <&iris_resv>; - }; - - iris_pixel: pixel { - iommus = <&apps_smmu 0x1543 0x0000>; - }; - - iris_opp_table: opp-table { - compatible = "operating-points-v2"; - - opp-240000000 { - opp-hz = /bits/ 64 <240000000 240000000 360000000>; - required-opps = <&rpmhpd_opp_low_svs_d2>, - <&rpmhpd_opp_low_svs_d1>; - }; - - opp-338000000 { - opp-hz = /bits/ 64 <338000000 338000000 507000000>; - required-opps = <&rpmhpd_opp_low_svs_d1>, - <&rpmhpd_opp_low_svs>; - }; - - opp-420000000 { - opp-hz = /bits/ 64 <420000000 420000000 630000000>; - required-opps = <&rpmhpd_opp_svs>, - <&rpmhpd_opp_svs>; - }; - - opp-444000000 { - opp-hz = /bits/ 64 <444000000 444000000 666000000>; - required-opps = <&rpmhpd_opp_svs>, - <&rpmhpd_opp_svs_l1>; - }; - - opp-600000000 { - opp-hz = /bits/ 64 <600000000 533000000 800000000>; - required-opps = <&rpmhpd_opp_svs_l1>, - <&rpmhpd_opp_nom>; - }; - - opp-630000000 { - opp-hz = /bits/ 64 <630000000 630000000 1104000000>; - required-opps = <&rpmhpd_opp_svs_l1>, - <&rpmhpd_opp_turbo>; - }; - - opp-800000000 { - opp-hz = /bits/ 64 <800000000 630000000 1260000000>; - required-opps = <&rpmhpd_opp_svs_l1>, - <&rpmhpd_opp_turbo_l1>; - }; - - opp-1000000000 { - opp-hz = /bits/ 64 <1000000000 800000000 1260000000>; - required-opps = <&rpmhpd_opp_nom>, - <&rpmhpd_opp_turbo_l3>; - }; - }; - }; - videocc: clock-controller@20f0000 { compatible = "qcom,maili-videocc"; reg = <0x0 0x020f0000 0x0 0x10000>; From a636cc5acc55ec249a3b758093745138ee2c2c5a Mon Sep 17 00:00:00 2001 From: Wangao Wang Date: Wed, 23 Sep 2026 10:41:15 +0800 Subject: [PATCH 1130/1133] FROMLIST: arm64: dts: qcom: maili: add iris video codec node Add the iris video codec device node for the maili SoC, describing the register space, interrupt, five power domains, eight clocks, two interconnect paths for CPU config and video memory bandwidth, IOMMU Mappings, and the operating point table covering 240 MHz to 1000 MHz. Link: https://lore.kernel.org/linux-arm-msm/20260923-add_iris_for_maili-v2-6-7223738e330d@oss.qualcomm.com/ Signed-off-by: Wangao Wang Signed-off-by: Gourav Kumar --- arch/arm64/boot/dts/qcom/maili.dtsi | 126 ++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/maili.dtsi b/arch/arm64/boot/dts/qcom/maili.dtsi index bd9181031b37c..675531600eee5 100644 --- a/arch/arm64/boot/dts/qcom/maili.dtsi +++ b/arch/arm64/boot/dts/qcom/maili.dtsi @@ -3636,6 +3636,132 @@ power-domains = <&gcc GCC_UFS_PHY_GDSC>; }; + iris: video-codec@2000000 { + compatible = "qcom,maili-iris"; + reg = <0x0 0x02000000 0x0 0xf0000>; + + interrupts = ; + + power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, + <&videocc VIDEO_CC_MVS0_GDSC>, + <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>, + <&videocc VIDEO_CC_MVS0_VPP0_GDSC>; + power-domain-names = "venus", + "vcodec0", + "mxc", + "mmcx", + "vpp0"; + + clocks = <&gcc GCC_VIDEO_AXI0_CLK>, + <&videocc VIDEO_CC_MVS0C_CLK>, + <&videocc VIDEO_CC_MVS0_CLK>, + <&gcc GCC_VIDEO_AXI0C_CLK>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK>, + <&videocc VIDEO_CC_MVS0B_CLK>, + <&videocc VIDEO_CC_MVS0_VPP0_CLK>; + clock-names = "iface", + "core", + "vcodec0_core", + "iface1", + "core_freerun", + "vcodec0_core_freerun", + "vcodec_bse", + "vcodec_vpp0"; + + operating-points-v2 = <&iris_opp_table>; + + interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc SLAVE_IRIS_CFG QCOM_ICC_TAG_ACTIVE_ONLY>, + <&mmss_noc MASTER_VIDEO_MVP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "cpu-cfg", + "video-mem"; + + memory-region = <&video_mem>; + + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>, + <&gcc GCC_VIDEO_AXI0C_CLK_ARES>, + <&videocc VIDEO_CC_MVS0C_FREERUN_CLK_ARES>, + <&videocc VIDEO_CC_MVS0_FREERUN_CLK_ARES>; + reset-names = "bus0", + "bus1", + "core", + "vcodec0_core"; + + dma-coherent; + + #address-cells = <1>; + #size-cells = <1>; + dma-ranges = <0x0 0x0 0x0 0xffc00000>; + + status = "disabled"; + + iris_non_pixel: non-pixel { + iommus = <&apps_smmu 0x1540 0x0000>, + <&apps_smmu 0x1620 0x0000>, + <&apps_smmu 0x1544 0x0000>; + iommu-ranges = <0x25800000 0xda400000>; + }; + + iris_pixel: pixel { + iommus = <&apps_smmu 0x1543 0x0000>; + }; + + iris_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-240000000 { + opp-hz = /bits/ 64 <240000000 240000000 360000000>; + required-opps = <&rpmhpd_opp_low_svs_d2>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-338000000 { + opp-hz = /bits/ 64 <338000000 338000000 507000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs>; + }; + + opp-420000000 { + opp-hz = /bits/ 64 <420000000 420000000 630000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs>; + }; + + opp-444000000 { + opp-hz = /bits/ 64 <444000000 444000000 666000000>; + required-opps = <&rpmhpd_opp_svs>, + <&rpmhpd_opp_svs_l1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000 533000000 800000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_nom>; + }; + + opp-630000000 { + opp-hz = /bits/ 64 <630000000 630000000 1104000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo>; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000 630000000 1260000000>; + required-opps = <&rpmhpd_opp_svs_l1>, + <&rpmhpd_opp_turbo_l1>; + }; + + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000 800000000 1260000000>; + required-opps = <&rpmhpd_opp_nom>, + <&rpmhpd_opp_turbo_l3>; + }; + }; + }; + videocc: clock-controller@20f0000 { compatible = "qcom,maili-videocc"; reg = <0x0 0x020f0000 0x0 0x10000>; From cfd317155051812cff93e825ee2a84f44550aba9 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Thu, 5 Nov 2026 21:58:51 +0530 Subject: [PATCH 1131/1133] Revert "FROMLIST: phy: qualcomm: phy-qcom-eusb2-repeater: Fix SMB Power leakage issue" Compilation issue due to 1b6603de9a71908ead619c6e8a397cac0e6625c3 Revert to fix compilation issue. This reverts commit 92757057bb4a1c54f4cd80727e56b11c3b99c1fd. Signed-off-by: Salendarsingh Gaud --- drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c b/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c index d25de9db926f8..89bc1c89fc85e 100644 --- a/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c +++ b/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c @@ -227,10 +227,7 @@ static int eusb2_repeater_set_mode(struct phy *phy, static int eusb2_repeater_exit(struct phy *phy) { struct eusb2_repeater *rptr = phy_get_drvdata(phy); - struct regmap *regmap = rptr->regmap; - u32 base = rptr->base; - regmap_write(regmap, base + EUSB2_EN_CTL1, 0); return regulator_bulk_disable(rptr->cfg->num_vregs, rptr->vregs); } From eb388ff028eb5a8a7d8d7f965df2f076cb1778ae Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Thu, 5 Nov 2026 22:56:48 +0530 Subject: [PATCH 1132/1133] FROMLIST: media: qcom: camss: Add CAMSS Offline Processing Engine driver Add an image processing driver for the Qualcomm Offline Processing Engine (OPE). OPE is a memory-to-memory ISP block that converts raw Bayer frames to YUV, performing white balance, demosaic, chroma enhancement, color correction and downscaling. The hardware architecture consists of Fetch Engines and Write Engines, connected through intermediate pipeline modules for pix processing. The driver exposes three video nodes per pipeline instance: - ope_input: Bayer RAW input (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - ope_disp_output: YUV output (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - ope_params: ISP parameters (V4L2_BUF_TYPE_META_OUTPUT) Hardware features: - Stripe-based processing (up to 336 pixels wide per stripe) - White balance (CLC_WB) - Demosaic / Bayer-to-RGB (CLC_DEMO) - Color correction matrix (CLC_CC) - Gamma LUT (CLC_GAMMA) - RGB-to-YUV conversion (CLC_CHROMA_ENHAN) - MN downscaler for chroma and luma planes Default configuration values are based on public standards such as BT.601. Processing Model: OPE processes frames in stripes of up to 336 pixels. Therefore, frames must be split into stripes for processing. Each stripe is configured after the previous one has been acquired (double buffered registers). To minimize inter-stripe latency, stripe configurations are generated ahead of time. The driver is split into three source files under the ope/ directory: - core.c: the OPE m2m driver itself: probe, power management, V4L2/media device setup, format handling, stripe generation and hardware programming. - pipeline.c/.h: a small declarative media-controller topology builder. Drivers describe their entire media graph, entities (video devices, subdevs, or base entities), their pads, and the links between them, in a static descriptor table. The builder validates the table, allocates and registers all entities, and creates all MC pad links. It is kept generic but currently only used by OPE. - params.c/.h: V4L2 ISP parameter buffer validation and dispatch. It wraps the extensible V4L2 ISP parameters buffer format, validating the buffer size and each per-block header before forwarding every block to its driver-supplied handler. A userspace libcamera support can be found at: https://github.com/jwrdegoede/libcamera/commits/camss_pipeline_v2.2/ A test tool, camss-isp-m2m, can be found at: https://github.com/loicpoulain/camss-isp-m2m-test Link: https://lore.kernel.org/all/20261102-camss-isp-ope-v12-6-702254689feb@oss.qualcomm.com/ Assisted-by: LLM Co-developed-by: Hans de Goede Signed-off-by: Hans de Goede Link: https://github.com/jwrdegoede/libcamera/commits/camss_pipeline_v2.1/ Link: https://github.com/loicpoulain/camss-isp-m2m-test Signed-off-by: Loic Poulain Co-developed-by: Nihal Kumar Gupta Signed-off-by: Nihal Kumar Gupta --- drivers/media/platform/qcom/camss/ope/core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/qcom/camss/ope/core.c b/drivers/media/platform/qcom/camss/ope/core.c index b266153aaca4f..b94df843f13ae 100644 --- a/drivers/media/platform/qcom/camss/ope/core.c +++ b/drivers/media/platform/qcom/camss/ope/core.c @@ -2809,6 +2809,7 @@ static bool ope_state_is_busy(struct v4l2_subdev *sd, struct v4l2_subdev_state * } static int ope_proc_set_fmt(struct v4l2_subdev *sd, + const struct v4l2_subdev_client_info *ci, struct v4l2_subdev_state *state, struct v4l2_subdev_format *fmt) { @@ -2871,6 +2872,7 @@ static int ope_proc_enum_mbus_code(struct v4l2_subdev *sd, } static int ope_proc_get_selection(struct v4l2_subdev *sd, + const struct v4l2_subdev_client_info *ci, struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel) { @@ -2912,6 +2914,7 @@ static int ope_proc_get_selection(struct v4l2_subdev *sd, } static int ope_proc_set_selection(struct v4l2_subdev *sd, + const struct v4l2_subdev_client_info *ci, struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel) { @@ -2954,6 +2957,7 @@ static const struct v4l2_subdev_ops ope_proc_ops = { /* -------- disp subdev ops -------- */ static int ope_disp_set_fmt(struct v4l2_subdev *sd, + const struct v4l2_subdev_client_info *ci, struct v4l2_subdev_state *state, struct v4l2_subdev_format *fmt) { From d7a1466f8c3247b7fe7d846a87098de42d151c00 Mon Sep 17 00:00:00 2001 From: Salendarsingh Gaud Date: Thu, 5 Nov 2026 14:28:51 +0000 Subject: [PATCH 1133/1133] Add qcom-next log files for 20261105 Adding merge log file and topic_SHA1 file Signed-off-by: Salendarsingh Gaud --- qcom-next/merge.log | 515 +++++++++++++++++++++++++++++++++++ qcom-next/qcom-next.sha.conf | 50 ++++ qcom-next/topic_SHA1 | 45 +++ 3 files changed, 610 insertions(+) create mode 100644 qcom-next/merge.log create mode 100644 qcom-next/qcom-next.sha.conf 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..ffc56bf87f321 --- /dev/null +++ b/qcom-next/merge.log @@ -0,0 +1,515 @@ +Verified existence of local and remote repos: Success +/opt/actions-runner/_work/kernel-config/kernel-config/kernel-topics /opt/actions-runner/_work/kernel-config/kernel-config/kernel-topics +Reuse-Recorded-Resolution: Enabled +Downloaded shared rerere cache +Local tree is clean +Removing old remotes ... +The remote kernel https://***@github.com/qualcomm-linux/kernel.git is no longer tracked. +Delete it [Y/n]? The remote origin https://github.com/qualcomm-linux/kernel-topics is no longer tracked. +Delete it [Y/n]? Done, removed 2 old remote(s). +Adding new remotes... +Adding remote baseline https://github.com/qualcomm-linux/kernel.git qcom-next-staging +Updating baseline +Adding remote tech/bsp/clk https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/clk +Updating tech/bsp/clk +Adding remote tech/bsp/devfreq https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/devfreq +Updating tech/bsp/devfreq +Adding remote tech/bsp/ec https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/ec +Updating tech/bsp/ec +Adding remote tech/bsp/interconnect https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/interconnect +Updating tech/bsp/interconnect +Adding remote tech/bsp/sched https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/sched +Updating tech/bsp/sched +Adding remote tech/security/firmware-smc https://github.com/qualcomm-linux/kernel-topics.git tech/security/firmware-smc +Updating tech/security/firmware-smc +Adding remote tech/bsp/soc-infra https://github.com/qualcomm-linux/kernel-topics.git tech/bsp/soc-infra +Updating tech/bsp/soc-infra +Adding remote tech/bus/pci/all https://github.com/qualcomm-linux/kernel-topics.git tech/bus/pci/all +Updating tech/bus/pci/all +Adding remote tech/bus/usb/all https://github.com/qualcomm-linux/kernel-topics.git tech/bus/usb/all +Updating tech/bus/usb/all +Adding remote tech/debug/hwtracing https://github.com/qualcomm-linux/kernel-topics.git tech/debug/hwtracing +Updating tech/debug/hwtracing +Adding remote tech/debug/rdbg https://github.com/qualcomm-linux/kernel-topics.git tech/debug/rdbg +Updating tech/debug/rdbg +Adding remote tech/pmic/all https://github.com/qualcomm-linux/kernel-topics.git tech/pmic/all +Updating tech/pmic/all +Adding remote tech/mem/all https://github.com/qualcomm-linux/kernel-topics.git tech/mem/all +Updating tech/mem/all +Adding remote tech/mm/audio/all https://github.com/qualcomm-linux/kernel-topics.git tech/mm/audio/all +Updating tech/mm/audio/all +Adding remote tech/mm/camss https://github.com/qualcomm-linux/kernel-topics.git tech/mm/camss +Updating tech/mm/camss +Adding remote tech/mm/drm https://github.com/qualcomm-linux/kernel-topics.git tech/mm/drm +Updating tech/mm/drm +Adding remote tech/mm/fastrpc https://github.com/qualcomm-linux/kernel-topics.git tech/mm/fastrpc +Updating tech/mm/fastrpc +Adding remote tech/mm/phy https://github.com/qualcomm-linux/kernel-topics.git tech/mm/phy +Updating tech/mm/phy +Adding remote tech/mm/video https://github.com/qualcomm-linux/kernel-topics.git tech/mm/video +Updating tech/mm/video +Adding remote tech/mm/gpu https://github.com/qualcomm-linux/kernel-topics.git tech/mm/gpu +Updating tech/mm/gpu +Adding remote tech/net/ath https://github.com/qualcomm-linux/kernel-topics.git tech/net/ath +Updating tech/net/ath +Adding remote tech/net/eth https://github.com/qualcomm-linux/kernel-topics.git tech/net/eth +Updating tech/net/eth +Adding remote tech/net/bluetooth https://github.com/qualcomm-linux/kernel-topics.git tech/net/bluetooth +Updating tech/net/bluetooth +Adding remote tech/pm/power https://github.com/qualcomm-linux/kernel-topics.git tech/pm/power +Updating tech/pm/power +Adding remote tech/pm/thermal https://github.com/qualcomm-linux/kernel-topics.git tech/pm/thermal +Updating tech/pm/thermal +Adding remote tech/security/crypto https://github.com/qualcomm-linux/kernel-topics.git tech/security/crypto +Updating tech/security/crypto +Adding remote tech/security/optee-next https://github.com/qualcomm-linux/kernel-topics.git tech/security/optee-next +Updating tech/security/optee-next +Adding remote tech/storage/nvmem https://github.com/qualcomm-linux/kernel-topics.git tech/storage/nvmem +Updating tech/storage/nvmem +Adding remote tech/storage/all https://github.com/qualcomm-linux/kernel-topics.git tech/storage/all +Updating tech/storage/all +Adding remote tech/virt/gunyah https://github.com/qualcomm-linux/kernel-topics.git tech/virt/gunyah +Updating tech/virt/gunyah +Adding remote tech/all/dt/qcs6490 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs6490 +Updating tech/all/dt/qcs6490 +Adding remote tech/all/dt/qcs9100 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs9100 +Updating tech/all/dt/qcs9100 +Adding remote tech/all/dt/qcs8300 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs8300 +Updating tech/all/dt/qcs8300 +Adding remote tech/all/dt/qcs615 https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/qcs615 +Updating tech/all/dt/qcs615 +Adding remote tech/all/dt/eliza https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/eliza +Updating tech/all/dt/eliza +Adding remote tech/all/dt/hamoa https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/hamoa +Updating tech/all/dt/hamoa +Adding remote tech/all/dt/glymur https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/glymur +Updating tech/all/dt/glymur +Adding remote tech/all/dt/kaanapali https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/kaanapali +Updating tech/all/dt/kaanapali +Adding remote tech/all/dt/pakala https://github.com/qualcomm-linux/kernel-topics.git tech/all/dt/pakala +Updating tech/all/dt/pakala +Adding remote tech/all/hawi https://github.com/qualcomm-linux/kernel-topics.git tech/all/hawi +Updating tech/all/hawi +Adding remote tech/all/maili https://github.com/qualcomm-linux/kernel-topics.git tech/all/maili +Updating tech/all/maili +Adding remote tech/all/shikra https://github.com/qualcomm-linux/kernel-topics.git tech/all/shikra +Updating tech/all/shikra +Adding remote tech/all/config https://github.com/qualcomm-linux/kernel-topics.git tech/all/config +Updating tech/all/config +Adding remote tech/overlay/dt https://github.com/qualcomm-linux/kernel-topics.git tech/overlay/dt +Updating tech/overlay/dt +Adding remote tech/all/workaround https://github.com/qualcomm-linux/kernel-topics.git tech/all/workaround +Updating tech/all/workaround +Adding remote tech/mproc/all https://github.com/qualcomm-linux/kernel-topics.git tech/mproc/all +Updating tech/mproc/all +Adding remote tech/noup/debug/all https://github.com/qualcomm-linux/kernel-topics.git tech/noup/debug/all +Updating tech/noup/debug/all +Adding remote tech/hwe/unoq https://github.com/qualcomm-linux/kernel-topics.git tech/hwe/unoq +Updating tech/hwe/unoq +Adding remote early/hwe/nord https://github.com/qualcomm-linux/kernel-topics.git early/hwe/nord +Updating early/hwe/nord +Done, added 50 new remote(s). +Updating the remotes ... +Updating tech/bsp/clk +Updating tech/bsp/devfreq +Updating tech/bsp/ec +Updating tech/bsp/interconnect +Updating tech/bsp/sched +Updating tech/security/firmware-smc +Updating tech/bsp/soc-infra +Updating tech/bus/pci/all +Updating tech/bus/usb/all +Updating tech/debug/hwtracing +Updating tech/debug/rdbg +Updating tech/pmic/all +Updating tech/mem/all +Updating tech/mm/audio/all +Updating tech/mm/camss +Updating tech/mm/drm +Updating tech/mm/fastrpc +Updating tech/mm/phy +Updating tech/mm/video +Updating tech/mm/gpu +Updating tech/net/ath +Updating tech/net/eth +Updating tech/net/bluetooth +Updating tech/pm/power +Updating tech/pm/thermal +Updating tech/security/crypto +Updating tech/security/optee-next +Updating tech/storage/nvmem +Updating tech/storage/all +Updating tech/virt/gunyah +Updating tech/all/dt/qcs6490 +Updating tech/all/dt/qcs9100 +Updating tech/all/dt/qcs8300 +Updating tech/all/dt/qcs615 +Updating tech/all/dt/eliza +Updating tech/all/dt/hamoa +Updating tech/all/dt/glymur +Updating tech/all/dt/kaanapali +Updating tech/all/dt/pakala +Updating tech/all/hawi +Updating tech/all/maili +Updating tech/all/shikra +Updating tech/all/config +Updating tech/overlay/dt +Updating tech/all/workaround +Updating tech/mproc/all +Updating tech/noup/debug/all +Updating tech/hwe/unoq +Updating early/hwe/nord +Done, updated 0 remote(s). +Updating baseline ... +Fetching baseline +latest tag/id is 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4 +Done, updated baseline. +Latest tag is 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4 +Create a new integration branch based on 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4 +Merging topic branches... +------------------------------------------ + ** Merging topic branch: tech/bsp/clk/tech/bsp/clk +Merge successful : tech/bsp/clk : 443bd58712afe0094e67d3e5b4ea04689f32f296 : 9 +------------------------------------------ + ** Merging topic branch: tech/bsp/devfreq/tech/bsp/devfreq +Merge successful : tech/bsp/devfreq : 7acfd264490b6f6c62b367a81f1ef793f3dad92b : 8 +------------------------------------------ + ** Merging topic branch: tech/bsp/ec/tech/bsp/ec +Merge successful : tech/bsp/ec : c46f06d11b1192572b2841acb93e111c84692f8a : 2 +------------------------------------------ + ** Merging topic branch: tech/bsp/interconnect/tech/bsp/interconnect +Merge successful : tech/bsp/interconnect : 81fc6e2c356d01f1606ae1323b1b1ef3b6db0ad2 : 1 +------------------------------------------ + ** Merging topic branch: tech/bsp/sched/tech/bsp/sched +Merge successful : tech/bsp/sched : 40b3c1f97688b9bef9e26072c625af3a2c97dde4 : 2 +------------------------------------------ + ** Merging topic branch: tech/security/firmware-smc/tech/security/firmware-smc +Merge successful : tech/security/firmware-smc : 503110b01c9ad2db7a0640aa5381a330e1dcda44 : 11 +------------------------------------------ + ** Merging topic branch: tech/bsp/soc-infra/tech/bsp/soc-infra +Merge successful : tech/bsp/soc-infra : 76d80866bef933a3eff65f38ccb17f1055be8f6d : 33 +------------------------------------------ + ** Merging topic branch: tech/bus/pci/all/tech/bus/pci/all +Merge successful : tech/bus/pci/all : 29bb333b0df63430eb8d88c03b63b0923cc2186b : 38 +------------------------------------------ + ** Merging topic branch: tech/bus/usb/all/tech/bus/usb/all +Merge successful : tech/bus/usb/all : dd0f225c14e2f9f6389df3000192132dd2e9264e : 51 +------------------------------------------ + ** Merging topic branch: tech/debug/hwtracing/tech/debug/hwtracing +Merge failed, manual merge +No files need merging +[qcom-next 22e6e01578f1] Merge remote-tracking branch tech/debug/hwtracing into qcom-next + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + +Merge successful : tech/debug/hwtracing : f7bba91bd0777bc4b9851b7d4e334bbac070c636 : 20 +------------------------------------------ + ** Merging topic branch: tech/debug/rdbg/tech/debug/rdbg +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/pmic/all/tech/pmic/all +Merge successful : tech/pmic/all : d517c3e1ca6db876b9d2c1946971c27fcae3649f : 23 +------------------------------------------ + ** Merging topic branch: tech/mem/all/tech/mem/all +Merge successful : tech/mem/all : 5d786d3550041b15048ab624b4b9d46493685aad : 8 +------------------------------------------ + ** Merging topic branch: tech/mm/audio/all/tech/mm/audio/all +Merge successful : tech/mm/audio/all : f084244afa64d3895a83fda8bcd596f5ccda1c8e : 41 +------------------------------------------ + ** Merging topic branch: tech/mm/camss/tech/mm/camss +Merge successful : tech/mm/camss : eb388ff028eb5a8a7d8d7f965df2f076cb1778ae : 34 +------------------------------------------ + ** Merging topic branch: tech/mm/drm/tech/mm/drm +Merge successful : tech/mm/drm : 56814926567d8bfce29ea9a7892be2455e74fdd2 : 91 +------------------------------------------ + ** Merging topic branch: tech/mm/fastrpc/tech/mm/fastrpc +Merge successful : tech/mm/fastrpc : e808ccd13031b5c166064e9593d04384e03881b6 : 9 +------------------------------------------ + ** 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 : 1e05914014b4c8c9dca3bd62c8c31b2878daacfb : 45 +------------------------------------------ + ** Merging topic branch: tech/mm/gpu/tech/mm/gpu +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/net/ath/tech/net/ath +Merge successful : tech/net/ath : 76d931c3492454b30c4b41543f46ed127075657f : 9 +------------------------------------------ + ** Merging topic branch: tech/net/eth/tech/net/eth +Merge successful : tech/net/eth : 4d556571888481060b98d3f7202311ab0cbedc54 : 18 +------------------------------------------ + ** Merging topic branch: tech/net/bluetooth/tech/net/bluetooth +Merge failed, manual merge +No files need merging +[qcom-next 57d36f743226] Merge remote-tracking branch tech/net/bluetooth into qcom-next + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + +Merge successful : tech/net/bluetooth : 1ec6c248dd47b9233f588f01737bbf6ea999c588 : 11 +------------------------------------------ + ** Merging topic branch: tech/pm/power/tech/pm/power +Merge successful : tech/pm/power : 29c839eed9785e2eeb471105dc5fa4398abfe8cf : 13 +------------------------------------------ + ** Merging topic branch: tech/pm/thermal/tech/pm/thermal +Merge failed, manual merge +No files need merging +[qcom-next 8fe1a536df8c] Merge remote-tracking branch tech/pm/thermal into qcom-next + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + +Merge successful : tech/pm/thermal : 000ea55a2de3fd3f37da06c7f080a2de60eedcb3 : 4 +------------------------------------------ + ** Merging topic branch: tech/security/crypto/tech/security/crypto +Merge successful : tech/security/crypto : 973a3815c26105147c2957fe2ad61d589392d261 : 27 +------------------------------------------ + ** Merging topic branch: tech/security/optee-next/tech/security/optee-next +Merge successful : tech/security/optee-next : 6c0433249d6f06d5a3ff3b2e1936d35b145b548f : 2 +------------------------------------------ + ** Merging topic branch: tech/storage/nvmem/tech/storage/nvmem +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/storage/all/tech/storage/all +Merge successful : tech/storage/all : 5929ee035ff8ad299f49b841ae9ee8cdf89428ad : 7 +------------------------------------------ + ** Merging topic branch: tech/virt/gunyah/tech/virt/gunyah +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs6490/tech/all/dt/qcs6490 +Merge failed, manual merge +No files need merging +[qcom-next d519b94cbc1e] Merge remote-tracking branch tech/all/dt/qcs6490 into qcom-next + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + +Merge successful : tech/all/dt/qcs6490 : 04fd975053b6ed0c653dd70b22932d6edcce755d : 20 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs9100/tech/all/dt/qcs9100 +Merge successful : tech/all/dt/qcs9100 : d0291c6f1b4a0ff657a0c463ff46c5b4c95c9404 : 20 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs8300/tech/all/dt/qcs8300 +Merge successful : tech/all/dt/qcs8300 : b132d5e94f4a3d112f09220ea528268a07a7b3cf : 26 +------------------------------------------ + ** Merging topic branch: tech/all/dt/qcs615/tech/all/dt/qcs615 +Merge successful : tech/all/dt/qcs615 : dbe132cf4a9f45b0b30d903d20d2dc39a521c575 : 16 +------------------------------------------ + ** Merging topic branch: tech/all/dt/eliza/tech/all/dt/eliza +Merge successful : tech/all/dt/eliza : 8b9d593cb3c576e8efa746a599f0510715dc214c : 9 +------------------------------------------ + ** Merging topic branch: tech/all/dt/hamoa/tech/all/dt/hamoa +Merge successful : tech/all/dt/hamoa : 41f3035af5e3ed5df14f57fe9ddae12013a0c084 : 29 +------------------------------------------ + ** Merging topic branch: tech/all/dt/glymur/tech/all/dt/glymur +Merge successful : tech/all/dt/glymur : dbd0f708205d26bff49cfb3090f9d0c6c4c29cf6 : 31 +------------------------------------------ + ** Merging topic branch: tech/all/dt/kaanapali/tech/all/dt/kaanapali +Merge successful : tech/all/dt/kaanapali : 328e6308fce02a33f802dc8084d2cf4b9fa184c3 : 19 +------------------------------------------ + ** Merging topic branch: tech/all/dt/pakala/tech/all/dt/pakala +Merge successful : tech/all/dt/pakala : b19aeb85a0efa3d6679bbbdb8c4c70287e49aa9b : 10 +------------------------------------------ + ** Merging topic branch: tech/all/hawi/tech/all/hawi +Merge successful : tech/all/hawi : f7bc734febd8b06c310d5098b13fa0681f644f80 : 16 +------------------------------------------ + ** Merging topic branch: tech/all/maili/tech/all/maili +Merge failed, manual merge +No files need merging +[qcom-next aa2acb12ecc7] Merge remote-tracking branch tech/all/maili into qcom-next + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + +Merge successful : tech/all/maili : a636cc5acc55ec249a3b758093745138ee2c2c5a : 17 +------------------------------------------ + ** Merging topic branch: tech/all/shikra/tech/all/shikra +Merge failed, manual merge +No files need merging +[qcom-next e1cfcd5e35b1] Merge remote-tracking branch tech/all/shikra into qcom-next + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + +Merge successful : tech/all/shikra : 60c8bf43305b71209326ed97d14053dd6dea869e : 71 +------------------------------------------ + ** Merging topic branch: tech/all/config/tech/all/config +Merge failed, manual merge +No files need merging +[qcom-next 779cc62c9730] Merge remote-tracking branch tech/all/config into qcom-next + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + +Merge successful : tech/all/config : 5d707d020e4ab97f1cc12bcd525132b83d6b8937 : 91 +------------------------------------------ + ** Merging topic branch: tech/overlay/dt/tech/overlay/dt +Merge failed, manual merge +No files need merging +[qcom-next 4d0d5f47c779] Merge remote-tracking branch tech/overlay/dt into qcom-next + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + +Merge successful : tech/overlay/dt : 7f719520897f8084ce6eab5a81f2c734abb20587 : 102 +------------------------------------------ + ** Merging topic branch: tech/all/workaround/tech/all/workaround +Merge successful : tech/all/workaround : 8d89b914bd38aaa9ac5c39685953224bde85e233 : 7 +------------------------------------------ + ** Merging topic branch: tech/mproc/all/tech/mproc/all +Nothing to merge: Already up to date. +------------------------------------------ + ** Merging topic branch: tech/noup/debug/all/tech/noup/debug/all +Merge failed, manual merge +No files need merging +[qcom-next 3147476ebf77] Merge remote-tracking branch tech/noup/debug/all into qcom-next + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + +Merge successful : tech/noup/debug/all : 42fa88a1f9146b247d093067c4a72bfd65b5402e : 38 +------------------------------------------ + ** Merging topic branch: tech/hwe/unoq/tech/hwe/unoq +Merge failed, manual merge +No files need merging +[qcom-next f1461a2df893] Merge remote-tracking branch tech/hwe/unoq into qcom-next + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + +Merge successful : tech/hwe/unoq : 9b67cf2828263b6104082b7c1fe796cc15d47f00 : 3 +------------------------------------------ + ** Merging topic branch: early/hwe/nord/early/hwe/nord +Merge failed, manual merge +No files need merging +[qcom-next ee061585d27e] Merge remote-tracking branch early/hwe/nord into qcom-next + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + +Merge successful : early/hwe/nord : fcf1215c198450d332d7fc2587d40d61c34bae8c : 89 +Done, merged 43 topic(s). +[main d451160] New rr-cache entries from ci-merge + Committer: Ubuntu +Your name and email address were configured automatically based +on your username and hostname. Please check that they are accurate. +You can suppress this message by setting them explicitly. Run the +following command and follow the instructions in your editor to edit +your configuration file: + + git config --global --edit + +After doing this, you may fix the identity used for this commit with: + + git commit --amend --reset-author + + 7 files changed, 11780 insertions(+) + create mode 100644 rr-cache/0af1d9b67d0c5300e87a90ef5bcb93f32aa37745/thisimage + create mode 100644 rr-cache/11c5af6ff019a6cb80412794ba4df6fceade52a2/thisimage + create mode 100644 rr-cache/1b46faa3373630ecda103b9d50135cc4fec8a3b0/thisimage + create mode 100644 rr-cache/6da1f234e5b26ad8575eaea8861fff4c3adafe78/thisimage + create mode 100644 rr-cache/c433563b0aa290c5e86f659f2a597146ddc5a6b5/thisimage + create mode 100644 rr-cache/c5eef8ed64b120b3b196d6c047fec4a0b4715d31/thisimage + create mode 100644 rr-cache/e79936003ea5260ff47bec2fc0e50995033c88a2/thisimage diff --git a/qcom-next/qcom-next.sha.conf b/qcom-next/qcom-next.sha.conf new file mode 100644 index 0000000000000..2ae08d666e254 --- /dev/null +++ b/qcom-next/qcom-next.sha.conf @@ -0,0 +1,50 @@ +tech/bsp/clk b6621533052784e753ea37738f720695d47222de +tech/bsp/devfreq 0837ca4afab5ff6397284116dfad794b0b7884d5 +tech/bsp/interconnect 81fc6e2c356d01f1606ae1323b1b1ef3b6db0ad2 +tech/bsp/sched 9c2e4b84127fad717127330d24ab248fa60324c6 +tech/security/firmware-smc 16b0235a686da585922566fe2aeee447e100fbfd +tech/bsp/soc-infra c79b7bc726ac4cfdd9d5389505e287a5c30a9156 +tech/bsp/pinctrl 79149ef6a826d6237346aa74eca65ccbe19d761f +tech/bsp/remoteproc 8c716bcd0b5eca15711a114434340d2f89cbf4d1 +tech/bus/peripherals c191e3d5ebc7f7b700781e0cbcf7b4bd25b05e5f +tech/bus/pci/all 0f23f88df0447832289aa3c01f2762dde003e467 +tech/bus/usb/dwc 6f2460005b7a8909fcc9668e9abcf76050d6198e +tech/bus/usb/phy b94824df2da48cbe95cc99a0fdd2bd309605f79e +tech/debug/hwtracing fae0f798a947b7949522d5657e4b40a1cc92b12c +tech/pmic/misc e7bb3661d7c0c0d4b88fd96951d0a698a46953fd +tech/mem/iommu d196108aa9efb3b713e8847dbc656556792423af +tech/mm/audio/all 5ba9defcdea6979d696f7555d7e6420475cca9f7 +tech/mm/camss 73f9fb01d656af2a2fa0b71b117b05da1f7f7a71 +tech/mm/drm d42e9c7c4e0caadcc5e6a509bf011880f29bdbde +tech/mm/fastrpc fab5742543b3ac30feddcc3e21abf5c5367813e3 +tech/mm/video bbe1a02c8deab96676f5b1d9e0c802eb409854a6 +tech/mm/gpu e065d5a06609e29946cba06a8c42b5e084c16e98 +tech/net/ath 722be84e35d87fe00bb909de896bfdc67bc5a064 +tech/net/bluetooth e352848cad1444a9125ebad6768024cc8a9cc0c4 +tech/pm/pmdomain 16a7451c692b445766f0aef4187677ca93740e54 +tech/pm/power 179ed4395ab2afda9df20c8346bc965b708dbaef +tech/pm/thermal 2602b17df1dab5715e2b1625738e1983a053ad02 +tech/security/crypto 4c71afd9e46a785c7c00563832fb1550503b011c +tech/security/ice dc34f45bbd867d317614efdfeae9274d6c956454 +tech/security/optee-next 9babb9ac3b6294a7b1417877627895d62414eaac +tech/storage/all cb6192d423c77eba8073f625b128b9eb384e72fa +tech/all/dt/qcs6490 fdf8383bd714781dfce69bc0755844fe85389788 +tech/all/dt/qcs9100 3e3223b1d5284537c11ac9ff48f78031b8a62ea4 +tech/all/dt/qcs8300 6a513e3822028da35889d58dd755152132440a6b +tech/all/dt/qcs615 c3eea9f1b49f374d19aee3339200cef537b6173b +tech/all/dt/agatti 2ca1b63b35a7e70a4a80398286211dee17729739 +tech/all/dt/eliza fd76dfcc600a56ed9bc6d4f1b5d3e5d26238a767 +tech/all/dt/hamoa 75cc2f2d7cf468c995c05b6d26bded9ae53f43b9 +tech/all/dt/glymur e69025f64fe7a2f25c1ae07e1e9cf5be2ffdfaf3 +tech/all/dt/kaanapali b395c116269253fd3bf457e69cdc734077358900 +tech/all/dt/pakala 9cdd195c9736e629a1051563b7eae5ca38e22c66 +tech/all/hawi d594f58798e89b9ea294c299eb725f19571feeb1 +tech/all/shikra 5e50e3f38d74115b604e10cde8a7a9e78ec2dbea +tech/all/config 00643d8f2c8db627db4976c147aa20f822305173 +tech/overlay/dt ae50c5146c969f41bf22be07c136bd0e63fd7886 +tech/all/workaround ebc94067be183f4418b5f496e269d6eb11723bcb +tech/noup/debug/all 9f1e8aefe2eaa112abe0bbb5e9f67284effa3d8d +tech/hwe/unoq a2d85fe547167dbd8fc59618907c20a6f17d2e5a +early/hwe/nord e1575acc858d929ad55ce3886d8d39c31a2d1736 +early/hwe/staging/nord 972aee417789d729b864fbc6ac51a362b268988c +tech/mem/dma-buf f153776ee5585e03809e3820c09f2ae8a1ec67d9 diff --git a/qcom-next/topic_SHA1 b/qcom-next/topic_SHA1 new file mode 100644 index 0000000000000..5f3babf3fbb2e --- /dev/null +++ b/qcom-next/topic_SHA1 @@ -0,0 +1,45 @@ +Name SHA Commits +------------------------------------------------------------------------------------ +tech/bsp/clk 443bd58712afe0094e67d3e5b4ea04689f32f296 9 +tech/bsp/devfreq 7acfd264490b6f6c62b367a81f1ef793f3dad92b 8 +tech/bsp/ec c46f06d11b1192572b2841acb93e111c84692f8a 2 +tech/bsp/interconnect 81fc6e2c356d01f1606ae1323b1b1ef3b6db0ad2 1 +tech/bsp/sched 40b3c1f97688b9bef9e26072c625af3a2c97dde4 2 +tech/security/firmware-smc 503110b01c9ad2db7a0640aa5381a330e1dcda44 11 +tech/bsp/soc-infra 76d80866bef933a3eff65f38ccb17f1055be8f6d 33 +tech/bus/pci/all 29bb333b0df63430eb8d88c03b63b0923cc2186b 38 +tech/bus/usb/all dd0f225c14e2f9f6389df3000192132dd2e9264e 51 +tech/debug/hwtracing f7bba91bd0777bc4b9851b7d4e334bbac070c636 20 +tech/pmic/all d517c3e1ca6db876b9d2c1946971c27fcae3649f 23 +tech/mem/all 5d786d3550041b15048ab624b4b9d46493685aad 8 +tech/mm/audio/all f084244afa64d3895a83fda8bcd596f5ccda1c8e 41 +tech/mm/camss eb388ff028eb5a8a7d8d7f965df2f076cb1778ae 34 +tech/mm/drm 56814926567d8bfce29ea9a7892be2455e74fdd2 91 +tech/mm/fastrpc e808ccd13031b5c166064e9593d04384e03881b6 9 +tech/mm/video 1e05914014b4c8c9dca3bd62c8c31b2878daacfb 45 +tech/net/ath 76d931c3492454b30c4b41543f46ed127075657f 9 +tech/net/eth 4d556571888481060b98d3f7202311ab0cbedc54 18 +tech/net/bluetooth 1ec6c248dd47b9233f588f01737bbf6ea999c588 11 +tech/pm/power 29c839eed9785e2eeb471105dc5fa4398abfe8cf 13 +tech/pm/thermal 000ea55a2de3fd3f37da06c7f080a2de60eedcb3 4 +tech/security/crypto 973a3815c26105147c2957fe2ad61d589392d261 27 +tech/security/optee-next 6c0433249d6f06d5a3ff3b2e1936d35b145b548f 2 +tech/storage/all 5929ee035ff8ad299f49b841ae9ee8cdf89428ad 7 +tech/all/dt/qcs6490 04fd975053b6ed0c653dd70b22932d6edcce755d 20 +tech/all/dt/qcs9100 d0291c6f1b4a0ff657a0c463ff46c5b4c95c9404 20 +tech/all/dt/qcs8300 b132d5e94f4a3d112f09220ea528268a07a7b3cf 26 +tech/all/dt/qcs615 dbe132cf4a9f45b0b30d903d20d2dc39a521c575 16 +tech/all/dt/eliza 8b9d593cb3c576e8efa746a599f0510715dc214c 9 +tech/all/dt/hamoa 41f3035af5e3ed5df14f57fe9ddae12013a0c084 29 +tech/all/dt/glymur dbd0f708205d26bff49cfb3090f9d0c6c4c29cf6 31 +tech/all/dt/kaanapali 328e6308fce02a33f802dc8084d2cf4b9fa184c3 19 +tech/all/dt/pakala b19aeb85a0efa3d6679bbbdb8c4c70287e49aa9b 10 +tech/all/hawi f7bc734febd8b06c310d5098b13fa0681f644f80 16 +tech/all/maili a636cc5acc55ec249a3b758093745138ee2c2c5a 17 +tech/all/shikra 60c8bf43305b71209326ed97d14053dd6dea869e 71 +tech/all/config 5d707d020e4ab97f1cc12bcd525132b83d6b8937 91 +tech/overlay/dt 7f719520897f8084ce6eab5a81f2c734abb20587 102 +tech/all/workaround 8d89b914bd38aaa9ac5c39685953224bde85e233 7 +tech/noup/debug/all 42fa88a1f9146b247d093067c4a72bfd65b5402e 38 +tech/hwe/unoq 9b67cf2828263b6104082b7c1fe796cc15d47f00 3 +early/hwe/nord fcf1215c198450d332d7fc2587d40d61c34bae8c 89