From nobody Thu Apr 2 23:55:49 2026 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 37EB52E2DD2 for ; Thu, 26 Mar 2026 01:04:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774487066; cv=none; b=Hr7YcY8CAYi6N/KksgJ3LbOqwXjCo3cKWiXmaOK0dkmw8TKz2Fou6P3AG+t15kEYv6slwAjhn6PiLgP4FT+eZ7t5HPCT+UTk6NwKHB8BIvL6u29cNRFXwZ5eVCGm2eYSw/JhOYUu8dFNOy1jGeFZfbGWFfyy8M3Gg5bXUNo6M/s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774487066; c=relaxed/simple; bh=qGmgHk355RdMVEd5Dw2LrYt4qWgKg67NpTd8E0fFkWo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XIsYVlb7Ffc35R+RhZa1EJYeAHUVuXh0CY+LY0iTMXa0797dVNIXah2ANV3jEmtPlFPgyVQgPM/AzFkNx+hpDqhvZCNwgj/ERmZF8ggOzdIHCNWs6e7grV1SVTN+QfLKeS/V8rrsF1nXznq+6wqCjWmqfB7EXs7//nr9eyETze4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=L0/Xn3bd; arc=none smtp.client-ip=209.85.128.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="L0/Xn3bd" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-486fb439299so3990345e9.0 for ; Wed, 25 Mar 2026 18:04:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1774487063; x=1775091863; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=26uXUdPFSZi5gxCtVHWZmoe+sZRz0mTOQs6SpMuS8Do=; b=L0/Xn3bdJ4MgL4A+NdNiZiZmBBBWtea+FeLwDl2LocNelfGnYC6EvI+E7UjZsA5MW4 Rt8CBCr9oW16akIFo8VH+Y5LyuYgDITsj0SkcRjTXIVAylaplRgPWrccoY4b0as5MHH+ WqAkKl0LlN0LRCtA1x2i0RopdnO3ETD/+Itc29J5NIS7kbTYfsW2YmNDnLPNk1/JQVii YkygeuYfw82DVcmt+AjqYRBsStfTUDJM8nnveOYfsf3JdZ7+wYpjSonhcPYtUm6L4c67 rbULI7adWfhnubiptEAlKnDFgRqbRhbedQfJmhEQxrdv6SmsqfLUJnRgURe74r2oVkoZ p4dQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774487063; x=1775091863; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=26uXUdPFSZi5gxCtVHWZmoe+sZRz0mTOQs6SpMuS8Do=; b=V5hnezFSBd/RKVpajrD1X9gPqLzE5VxcUfTwjLfX4dQJIbpv7NbtQf10OuQsEvrt1l wNl7popTm+Q3R4vfpYJciBH5+tBctDcwBy8+KhSu8jaxQB2159HFUCNka69COX+iFGbR G06eN+LSB/IljqC7fEs+d1BxEoY/0bQ+5Y/5woUHO0SfZTcrRbkkUIpi9S7rpAHqOI0T KH+rja+q38ngKeVUGVJ32ONQpYZn8UnFExKc9p4MYjH2BSKTYZlZvxqMn7uNUeYQlre0 BiKkUsgpTOHnb0iLSR4A6AEcY09HUohbF4msopWHeVbM4CqSLD9xP5bCl8mJ/wE2uAzI gNgw== X-Forwarded-Encrypted: i=1; AJvYcCWuZJVrjVot7Xq8elyVcX0hPoW1RI1uCKLaSEkErEo3E1v7HT84vLdYrL310iDW+MS3ytvq1QJhSBAGR9E=@vger.kernel.org X-Gm-Message-State: AOJu0YyVS4X41221gKjSwTmNxfBTtRjYH5L7L/m8DRznWHKxQRULZW+G CSzvxshWYOnVRsQ/Cq0/X/3u6dbBW9cxrijJAFUcPgRUGqSfrereYyxqtcV+AZcA7f0= X-Gm-Gg: ATEYQzzuh9KimA2QncFkovJg+1tM7f7Llhxz9TzU3znTDqGjv7lDAv8aAM+c6ebZtk5 7NUqssOnb2EPz6GbLBCyb3AHsSBHVjGtKhE910hp0mBNckuiAIX9tcXK/WEkyR07rCXV/hiT6cu QqX76/k0kt/i7cGg9+dhfYLfzzrUHOTUhigo0IAlxhsnURIv7lxWzAl6X8pZEE49DqgI7PVvbmt PSCQrUXiR80YfGILj7bFDm6hNP1bakufgxyq55paVDtfMOB3//j5BKj0Bxee3X24boCNVCqjCHl yuTpfW7N/WuNc7nh6oYBd+8kngWdw7hSKcavRylb5Pl30s0D/sF5wXK/lzNCOvJPdhC6tZIHW3W ZxKT/2RgCoXSZRbXG+AEWpz0MmfDFgAvt4KB2GjnAazc7//n7309/WJdGYXGQ5gWiJPa38x0SB8 N6ihUvLkY4DUJbDs1V+mGxKA80bCULj7sKH+A= X-Received: by 2002:a05:600c:1913:b0:480:3ad0:93bf with SMTP id 5b1f17b1804b1-48716061795mr79375885e9.24.1774487063444; Wed, 25 Mar 2026 18:04:23 -0700 (PDT) Received: from [192.168.0.35] ([109.76.163.154]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48711701804sm168552605e9.4.2026.03.25.18.04.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Mar 2026 18:04:23 -0700 (PDT) From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:04:43 +0000 Subject: [PATCH v5 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260326-x1e-csi2-phy-v5-1-0c0fc7f5c01b@linaro.org> References: <20260326-x1e-csi2-phy-v5-0-0c0fc7f5c01b@linaro.org> In-Reply-To: <20260326-x1e-csi2-phy-v5-0-0c0fc7f5c01b@linaro.org> To: Vinod Koul , Kishon Vijay Abraham I , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Neil Armstrong Cc: Bryan O'Donoghue , Vladimir Zapolskiy , linux-arm-msm@vger.kernel.org, linux-phy@lists.infradead.org, linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Bryan O'Donoghue X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=5552; i=bryan.odonoghue@linaro.org; h=from:subject:message-id; bh=qGmgHk355RdMVEd5Dw2LrYt4qWgKg67NpTd8E0fFkWo=; b=owEBbQKS/ZANAwAKASJxO7Ohjcg6AcsmYgBpxIY0MZlUEWyTdMRZlCTbN3IGMZ1OmF0GctovG PPJu0g0ymaJAjMEAAEKAB0WIQTmk/sqq6Nt4Rerb7QicTuzoY3IOgUCacSGNAAKCRAicTuzoY3I OunUD/9TscQxTa6h7cse7W5SIw1NapN227nZz5NYSjlP/BYNTHIhE/Qq1KWhIng4lD7LqpiSk+K CSmPTdCHNMjwLN2qfLvJJ2rLKmp/MVhyS3HnCguGTtbPo5Zr3llI6i7lx1xH5GRUrv4IqR8dnJu RJK6xLNimF6KUkcaeOuKI0wgESN/uwZHHiDz6YDRGzoUsXDMmWh6ukngta/9pNW+y/om25KYmYJ m/v7J6B79MZb6p4zl+tgYCTQfDGTl8mBdbPKmrEGifYb8wThhkDOvV0qbgLSrMyj2gXAYCf1YCJ NzKiPl/IjRoTSLBjZnYRRoguKHtDC1FvZY9T7R8uHpTQkqOGPGM0aUDP/bbMXT9AnHAd74yRC+S rIf/7Hj6HPoGbM8Z+FhNORcQQ8Fe0jimSpHLqYBgs8SP6rbonTMPyBI6pBi8qLQPzhDqAekVsyU hCdNaYpj8JGAvpj7B3abTHc5Bs+4NH+9YfutPaDSKljnudyiiEeHLs3agAQ0q8v18vE1x/ciQin bMyV/emVaO0hldzh2wkO1xHHwZPGWNRVTkNXGyF/V6xczZV5n7wG4LHsz8W/ZGAgexxSKRwtvlh VX3wvTa7lG1G3fran7TU+VhB6fkPui+uT0GOLmt1hWt56YlqSX0Gw8kwZutAm0oZHJK+JnZ9dJA A0I4Ty72Xqvci6g== X-Developer-Key: i=bryan.odonoghue@linaro.org; a=openpgp; fpr=E693FB2AABA36DE117AB6FB422713BB3A18DC83A Add a base schema initially compatible with x1e80100 to describe MIPI CSI2 PHY devices. The hardware can support both CPHY, DPHY and a special split-mode DPHY. We capture those modes as: - PHY_QCOM_CSI2_MODE_DPHY - PHY_QCOM_CSI2_MODE_CPHY - PHY_QCOM_CSI2_MODE_SPLIT_DPHY The CSIPHY devices have their own pinouts on the SoC as well as their own individual voltage rails. The need to model voltage rails on a per-PHY basis leads us to define CSIPHY devices as individual nodes. Two nice outcomes in terms of schema and DT arise from this change. 1. The ability to define on a per-PHY basis voltage rails. 2. The ability to require those voltage. We have had a complete bodge upstream for this where a single set of voltage rail for all CSIPHYs has been buried inside of CAMSS. Much like the I2C bus which is dedicated to Camera sensors - the CCI bus in CAMSS parlance, the CSIPHY devices should be individually modelled. Signed-off-by: Bryan O'Donoghue --- .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 130 +++++++++++++++++= ++++ include/dt-bindings/phy/phy-qcom-mipi-csi2.h | 15 +++ 2 files changed, 145 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.y= aml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml new file mode 100644 index 0000000000000..63114151104b4 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml @@ -0,0 +1,130 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/qcom,x1e80100-csi2-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm CSI2 PHY + +maintainers: + - Bryan O'Donoghue + +description: + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 senso= rs + to Qualcomm's Camera CSI Decoder. The PHY supports both C-PHY and D-PHY + modes. + +properties: + compatible: + const: qcom,x1e80100-csi2-phy + + reg: + maxItems: 1 + + "#phy-cells": + const: 1 + description: + The single cell specifies the PHY operating mode. + See include/dt-bindings/phy/phy-qcom-mipi-csi2.h for valid values. + + clocks: + maxItems: 2 + + clock-names: + items: + - const: core + - const: timer + + interrupts: + maxItems: 1 + + operating-points-v2: + maxItems: 1 + + power-domains: + items: + - description: MXC or MXA voltage rail + - description: MMCX voltage rail + + power-domain-names: + items: + - const: mx + - const: mmcx + + vdda-0p9-supply: + description: Phandle to a 0.9V regulator supply to a PHY. + + vdda-1p2-supply: + description: Phandle to 1.2V regulator supply to a PHY. + +required: + - compatible + - reg + - "#phy-cells" + - clocks + - clock-names + - interrupts + - operating-points-v2 + - power-domains + - power-domain-names + - vdda-0p9-supply + - vdda-1p2-supply + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + + csiphy4: csiphy@ace4000 { + compatible =3D "qcom,x1e80100-csi2-phy"; + reg =3D <0x0ace4000 0x2000>; + #phy-cells =3D <1>; + + clocks =3D <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names =3D "core", + "timer"; + + operating-points-v2 =3D <&csiphy_opp_table>; + + interrupts =3D ; + + power-domains =3D <&rpmhpd RPMHPD_MX>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names =3D "mx", + "mmcx"; + + vdda-0p9-supply =3D <&vreg_l2c_0p8>; + vdda-1p2-supply =3D <&vreg_l1c_1p2>; + }; + + csiphy_opp_table: opp-table { + compatible =3D "operating-points-v2"; + + opp-300000000 { + opp-hz =3D /bits/ 64 <300000000>; + required-opps =3D <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz =3D /bits/ 64 <400000000>; + required-opps =3D <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz =3D /bits/ 64 <480000000>; + required-opps =3D <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + + isp@acb7000 { + phys =3D <&csiphy4 PHY_QCOM_CSI2_MODE_DPHY>; + }; diff --git a/include/dt-bindings/phy/phy-qcom-mipi-csi2.h b/include/dt-bind= ings/phy/phy-qcom-mipi-csi2.h new file mode 100644 index 0000000000000..fa48fd75c58d8 --- /dev/null +++ b/include/dt-bindings/phy/phy-qcom-mipi-csi2.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Qualcomm MIPI CSI2 PHY constants + * + * Copyright (C) 2026 Linaro Limited + */ + +#ifndef __DT_BINDINGS_PHY_MIPI_CSI2__ +#define __DT_BINDINGS_PHY_MIPI_CSI2__ + +#define PHY_QCOM_CSI2_MODE_DPHY 0 +#define PHY_QCOM_CSI2_MODE_CPHY 1 +#define PHY_QCOM_CSI2_MODE_SPLIT_DPHY 2 + +#endif /* __DT_BINDINGS_PHY_MIPI_CSI2__ */ --=20 2.52.0 From nobody Thu Apr 2 23:55:49 2026 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 21BBC2F7AAB for ; Thu, 26 Mar 2026 01:04:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774487070; cv=none; b=rIvdsBpYKprj/H2ulbiDC44+DJPG0YbsOii6LTuVWHeIAKSStWRj6glqNyPbtsRii/0xCC7lcu5u8iKwpyZBynsa/IJpaLvJry7n8KpB/lFeUCyzfNbDhQBsEmtiXluln+mzTv62MFAwu040z+hzDu9U+6dFOG1oKyfQ7JlH6mo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774487070; c=relaxed/simple; bh=TqezVeeEQo/legF7X0Kem09CiboVcyRzP7Se4joiNuQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ayQGYn8Pt8IQ58ya+LuCpgRGOLhXylPm/mseNBEYlkO20cSxqlWCmCWXR0dZUYkbTrOYhYvCYhTtyuhZ7d3udGEpjZIcK/zO2b7GaonWiJMkoU6LvXywIwUnVpFro+xGd9/BSAX4UYg0LpPOR/OliUjVU3klgpIEtJbbj/JNgdE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=kDpYQdrN; arc=none smtp.client-ip=209.85.128.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="kDpYQdrN" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-487035181a7so2648215e9.2 for ; Wed, 25 Mar 2026 18:04:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1774487065; x=1775091865; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=BB+ReCt4inB+t9iSZSdhXYKBpk10XEv4DEysRtzRw/I=; b=kDpYQdrNy8Tyr8sdTgUFeAGHNCSOEKdn0Z+BLX0AeKxyA0/VYh4DgA5+w1ghE1Do6x Wc6J397GkMIp6eWvqHnf9MzUg2FArIW5dSkVxmMwtDz7Dbg9NMIW1FT2a4JJb0NpFnvB dheyka5FWeDjDxak+U6QaxqL0VAaEyXf3xizR0zDAfblHaXjF50AWlPVfbo3hd8FGZSG kIjU8Gv/+Igp+kbmFlWvjsLFoWzAvrQHPf/hKjMNvAcqYb5FhimZ1iexEx31KPOLrEGk D8JY+LsYVyC+5h5F65Ep0mfVwz8xVr/5J/kPff4NR21uoI4vzAWQzjPs0q2b9S14Lylz PERA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774487065; x=1775091865; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=BB+ReCt4inB+t9iSZSdhXYKBpk10XEv4DEysRtzRw/I=; b=PwmHWbDiv1Yi2rQyRk/75k2hfRLzwCvJoG/bznuV7lbXUGS27rX7MiJrw+Fdcd18Uj +YHcTH030vtg5TRd/D4pK+tWjGGy6ehyEud8FaezO53prI9y0kVamvqqv2CHgGPdbCKA sGqoTgfirOT+FMwIWBa32UHDmAotGrq39UNcJnw1ogRumK3CtgZ78NPiOA7DXop5rjzj Pkzeciswk3Q2QkBv8Fz3SYMSRMXc9MTtmopdidqoSO9lUCIEGbtEEXRZR/WsO6ncAZLq HcDxraI5YZ9cVWntzdC8oxpFrvUn9CCn1cO7T+dfqXzzvs7woMz/+JLbYoZLQfe34Z97 q5uA== X-Forwarded-Encrypted: i=1; AJvYcCWcqIWmAmBZrS6poqhnrUMPJNP1Aa7ZR3SLwf2wePYIW5jO5iDvwWx4dzWkguVSRq2ZfNJk+moWGPaCb1I=@vger.kernel.org X-Gm-Message-State: AOJu0YwQa712eLil+sZGNud6kEcCOIANFvjtb+hue0X4dMQb0cTTfkz4 2MwmBN2oEkA8Gh0nc/FsNXqNY9bk3i1eqQZuxX370ikDciKglBYDrqJmncHYD0/WWHc= X-Gm-Gg: ATEYQzxtZBs4xj2jBXrRGhK5W/DZIVw39hPnr1tcN2dc5A7Habtb/vbE0C2Ww2q8n+6 ig7MSGx7Y8g7KbfzP3FN1fcvfX8Z5BOfVcnNEKkutjGVvQpeGYiLTrUzyah2XLTBqEl8u0Liz2r wxQGIYV0c863S83bhwhnzo2RKIKRjvDsCdJObCGNgyRbbthSotrFcyt+SFir7nTk3FyCZL0Lm9S LZ8AN5FB35LAUCHuvEdc7O29ZtRxihoGQ7kdhc1me4iqEg9FwIjE8pVxt/+CLlzfD2VY2oZwyYs cIJ7j5R+IZhUF77nwJJd3l8JqI6JOI++9+JsYApNl0nvBL+GPWbgFnal92oEUGioosgJvoyGI/W pPOXEMuBcXuMrCv4c+jpjfertJ2wk24nJ34+65ivYy2w4MB0+nN15Nyl4sYE2WPndxEBI3mT3lM kBu/8rR7DiIWLI65h82+3RxiY89quETro2+oA= X-Received: by 2002:a05:600c:8b16:b0:485:3b5b:eb8 with SMTP id 5b1f17b1804b1-4871605068amr74413035e9.26.1774487065249; Wed, 25 Mar 2026 18:04:25 -0700 (PDT) Received: from [192.168.0.35] ([109.76.163.154]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48711701804sm168552605e9.4.2026.03.25.18.04.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Mar 2026 18:04:24 -0700 (PDT) From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:04:44 +0000 Subject: [PATCH v5 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260326-x1e-csi2-phy-v5-2-0c0fc7f5c01b@linaro.org> References: <20260326-x1e-csi2-phy-v5-0-0c0fc7f5c01b@linaro.org> In-Reply-To: <20260326-x1e-csi2-phy-v5-0-0c0fc7f5c01b@linaro.org> To: Vinod Koul , Kishon Vijay Abraham I , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Neil Armstrong Cc: Bryan O'Donoghue , Vladimir Zapolskiy , linux-arm-msm@vger.kernel.org, linux-phy@lists.infradead.org, linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Bryan O'Donoghue X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=32399; i=bryan.odonoghue@linaro.org; h=from:subject:message-id; bh=TqezVeeEQo/legF7X0Kem09CiboVcyRzP7Se4joiNuQ=; b=owEBbQKS/ZANAwAKASJxO7Ohjcg6AcsmYgBpxIY0zh/PCHRa8g002YEuFGO2SqfZ+mrjzpJMo qthokDCtfeJAjMEAAEKAB0WIQTmk/sqq6Nt4Rerb7QicTuzoY3IOgUCacSGNAAKCRAicTuzoY3I OvgwD/4kOjhhntT1z8U+b+fDIU9Dex/jlcjWLzKoucuMh6X1vx1mzL5SsB+tvss5OAic/DZVhYQ /NAjn+Ye9KYvoLfCmAFjR7hyZMyXM8OSdD/tMC2NsG7Tungwoi/911vgf8egU1f/I0m/iMwjs+g Ce+rULff5vqS/IPANMJGAFQBirO2jqyZZDsq9g0S3hkCL/or8cARQSkgxWeaQqj7pzDojgNMZrf 3UNe8RhaJfhXvd9Xi9/KLGHy7lcIRErvlucP4t0g+ko4oYCU4MkuT7asSKRnoXNmjOvlVphuPCm I5voYGmyb/l07S3f5xAoKDKFkYKyunDm0iE6Q8BhSZQBLxaCefLDu+De5dthkpz/0gcU45Zshsy NFm90+Szse9y0lSAuyDfA7nhNfbhkKiENOWfjTYf8NI+GnWJvg5bbiTu9GtxrcoE9Sk7vsJP3jZ LVZB0XKTBzzFaVx6W9UpuStDgaptXeiwpWhdB2pblxdJBG/cEeCoaq2Gd8yYLxXEWuLvNyrHJWa rnq+tK6uoQDyc6VgJoaUa8K6LaEyTWFHR1bbI+pcpiid6epy4PsDZv/FnibkaOTqHWjbV1RFC92 WQlDjwP7Yb1jUNWco5w9FPtHmF7DgZ8k3NoQJPW5GaxNIsrHlWRgjFpUjiaG97a+LfrWFS4HM8y FTTBNAaf2sMa50g== X-Developer-Key: i=bryan.odonoghue@linaro.org; a=openpgp; fpr=E693FB2AABA36DE117AB6FB422713BB3A18DC83A Add a new MIPI CSI2 driver in DPHY mode initially. The entire set of existing CAMSS CSI PHY init sequences are imported in order to save time and effort in later patches. The following devices are supported in this drop: "qcom,x1e80100-csi2-phy" In-line with other PHY drivers the process node is included in the name. Data-lane and clock lane positioning and polarity selection via newly amended struct phy_configure_opts_mipi_dphy{} is supported. The Qualcomm 3PH class of PHYs can do both DPHY and CPHY mode. For now only DPHY is supported. In porting some of the logic over from camss-csiphy*.c to here its also possible to rationalise some of the code. In particular use of regulator_bulk and clk_bulk as well as dropping the seemingly useless and unused interrupt handler. The PHY sequences and a lot of the logic that goes with them are well proven in CAMSS and mature so the main thing to watch out for here is how to get the right sequencing of regulators, clocks and register-writes. The register init sequence table is imported verbatim from the existing CAMSS csiphy driver. A follow-up series will rework the table to extract the repetitive per-lane pattern into a loop. Signed-off-by: Bryan O'Donoghue --- MAINTAINERS | 11 + drivers/phy/qualcomm/Kconfig | 13 + drivers/phy/qualcomm/Makefile | 5 + drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 361 +++++++++++++++++= ++++ drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c | 298 +++++++++++++++++ drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 95 ++++++ 6 files changed, 783 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 62ccdc72384d4..fe19722355d94 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21542,6 +21542,17 @@ S: Maintained F: Documentation/devicetree/bindings/media/qcom,*-iris.yaml F: drivers/media/platform/qcom/iris/ =20 +QUALCOMM MIPI CSI2 PHY DRIVER +M: Bryan O'Donoghue +L: linux-phy@lists.infradead.org +L: linux-media@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/phy/qcom,*-csi2-phy.yaml +F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.c +F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.h +F: include/dt-bindings/phy/phy-qcom-mipi-csi2* + QUALCOMM NAND CONTROLLER DRIVER M: Manivannan Sadhasivam L: linux-mtd@lists.infradead.org diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index 60a0ead127fa9..ea33025a40fd0 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -28,6 +28,19 @@ config PHY_QCOM_EDP Enable this driver to support the Qualcomm eDP PHY found in various Qualcomm chipsets. =20 +config PHY_QCOM_MIPI_CSI2 + tristate "Qualcomm MIPI CSI2 PHY driver" + depends on ARCH_QCOM || COMPILE_TEST + depends on OF + depends on COMMON_CLK + select GENERIC_PHY + select GENERIC_PHY_MIPI_DPHY + help + Enable this to support the MIPI CSI2 PHY driver found in various + Qualcomm chipsets. This PHY is used to connect MIPI CSI2 + camera sensors to the CSI Decoder in the Qualcomm Camera Subsystem + CAMSS. + config PHY_QCOM_IPQ4019_USB tristate "Qualcomm IPQ4019 USB PHY driver" depends on OF && (ARCH_QCOM || COMPILE_TEST) diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index b71a6a0bed3f1..382cb594b06b6 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -6,6 +6,11 @@ obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) +=3D phy-qcom-ipq4019-u= sb.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) +=3D phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_QCOM_M31_USB) +=3D phy-qcom-m31.o obj-$(CONFIG_PHY_QCOM_M31_EUSB) +=3D phy-qcom-m31-eusb2.o + +phy-qcom-mipi-csi2-objs +=3D phy-qcom-mipi-csi2-core.o \ + phy-qcom-mipi-csi2-3ph-dphy.o +obj-$(CONFIG_PHY_QCOM_MIPI_CSI2) +=3D phy-qcom-mipi-csi2.o + obj-$(CONFIG_PHY_QCOM_PCIE2) +=3D phy-qcom-pcie2.o =20 obj-$(CONFIG_PHY_QCOM_QMP_COMBO) +=3D phy-qcom-qmp-combo.o phy-qcom-qmp-us= bc.o diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/p= hy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c new file mode 100644 index 0000000000000..b1eb2b28b2da2 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c @@ -0,0 +1,361 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm MSM Camera Subsystem - CSIPHY Module 3phase v1.0 + * + * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2016-2025 Linaro Ltd. + */ + +#include +#include +#include +#include + +#include "phy-qcom-mipi-csi2.h" + +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(offset, n) ((offset) + 0x4 * (n)) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET BIT(0) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE BIT(7) +#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 + 0x= 4 * (n)) + +/* + * 3 phase CSI has 19 common status regs with only 0-10 being used + * and 11-18 being reserved. + */ +#define CSI_COMMON_STATUS_NUM 11 +/* + * There are a number of common control registers + * The offset to clear the CSIPHY IRQ status starts @ 22 + * So to clear CSI_COMMON_STATUS0 this is CSI_COMMON_CONTROL22, STATUS1 is + * CONTROL23 and so on + */ +#define CSI_CTRL_STATUS_INDEX 22 + +/* + * There are 43 COMMON_CTRL registers with regs after # 33 being reserved + */ +#define CSI_CTRL_MAX 33 + +#define CSIPHY_DEFAULT_PARAMS 0 +#define CSIPHY_SETTLE_CNT_LOWER_BYTE 2 +#define CSIPHY_SKEW_CAL 7 + +/* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */ +static const struct +mipi_csi2phy_lane_regs lane_regs_x1e80100[] =3D { + /* Power up lanes 2ph mode */ + {.reg_addr =3D 0x1014, .reg_data =3D 0xd5, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x101c, .reg_data =3D 0x7a, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x1018, .reg_data =3D 0x01, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + + {.reg_addr =3D 0x0094, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x00a0, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0090, .reg_data =3D 0x0f, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0098, .reg_data =3D 0x08, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0094, .reg_data =3D 0x07, .delay_us =3D 0x01, .param_typ= e =3D CSIPHY_DEFAULT_PARAMS}, + {.reg_addr =3D 0x0030, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0000, .reg_data =3D 0x8e, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0038, .reg_data =3D 0xfe, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x002c, .reg_data =3D 0x01, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0034, .reg_data =3D 0x0f, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x001c, .reg_data =3D 0x0a, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0014, .reg_data =3D 0x60, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x003c, .reg_data =3D 0xb8, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0004, .reg_data =3D 0x0c, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0020, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0008, .reg_data =3D 0x10, .param_type =3D CSIPHY_SETTLE_= CNT_LOWER_BYTE}, + {.reg_addr =3D 0x0010, .reg_data =3D 0x52, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0094, .reg_data =3D 0xd7, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x005c, .reg_data =3D 0x00, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x0060, .reg_data =3D 0xbd, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x0064, .reg_data =3D 0x7f, .param_type =3D CSIPHY_SKEW_CA= L}, + + {.reg_addr =3D 0x0e94, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0ea0, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e90, .reg_data =3D 0x0f, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e98, .reg_data =3D 0x08, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e94, .reg_data =3D 0x07, .delay_us =3D 0x01, .param_ty= pe =3D CSIPHY_DEFAULT_PARAMS}, + {.reg_addr =3D 0x0e30, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e28, .reg_data =3D 0x04, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e00, .reg_data =3D 0x80, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e0c, .reg_data =3D 0xff, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e38, .reg_data =3D 0x1f, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e2c, .reg_data =3D 0x01, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e34, .reg_data =3D 0x0f, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e1c, .reg_data =3D 0x0a, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e14, .reg_data =3D 0x60, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e3c, .reg_data =3D 0xb8, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e04, .reg_data =3D 0x0c, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e20, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0e08, .reg_data =3D 0x10, .param_type =3D CSIPHY_SETTLE_= CNT_LOWER_BYTE}, + {.reg_addr =3D 0x0e10, .reg_data =3D 0x52, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + + {.reg_addr =3D 0x0494, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x04a0, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0490, .reg_data =3D 0x0f, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0498, .reg_data =3D 0x08, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0494, .reg_data =3D 0x07, .delay_us =3D 0x01, .param_ty= pe =3D CSIPHY_DEFAULT_PARAMS}, + {.reg_addr =3D 0x0430, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0400, .reg_data =3D 0x8e, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0438, .reg_data =3D 0xfe, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x042c, .reg_data =3D 0x01, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0434, .reg_data =3D 0x0f, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x041c, .reg_data =3D 0x0a, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0414, .reg_data =3D 0x60, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x043c, .reg_data =3D 0xb8, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0404, .reg_data =3D 0x0c, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0420, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0408, .reg_data =3D 0x10, .param_type =3D CSIPHY_SETTLE_= CNT_LOWER_BYTE}, + {.reg_addr =3D 0x0410, .reg_data =3D 0x52, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0494, .reg_data =3D 0xd7, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x045c, .reg_data =3D 0x00, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x0460, .reg_data =3D 0xbd, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x0464, .reg_data =3D 0x7f, .param_type =3D CSIPHY_SKEW_CA= L}, + + {.reg_addr =3D 0x0894, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x08a0, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0890, .reg_data =3D 0x0f, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0898, .reg_data =3D 0x08, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0894, .reg_data =3D 0x07, .delay_us =3D 0x01, .param_ty= pe =3D CSIPHY_DEFAULT_PARAMS}, + {.reg_addr =3D 0x0830, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0800, .reg_data =3D 0x8e, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0838, .reg_data =3D 0xfe, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x082c, .reg_data =3D 0x01, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0834, .reg_data =3D 0x0f, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x081c, .reg_data =3D 0x0a, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0814, .reg_data =3D 0x60, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x083c, .reg_data =3D 0xb8, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0804, .reg_data =3D 0x0c, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0820, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0808, .reg_data =3D 0x10, .param_type =3D CSIPHY_SETTLE_= CNT_LOWER_BYTE}, + {.reg_addr =3D 0x0810, .reg_data =3D 0x52, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0894, .reg_data =3D 0xd7, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x085c, .reg_data =3D 0x00, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x0860, .reg_data =3D 0xbd, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x0864, .reg_data =3D 0x7f, .param_type =3D CSIPHY_SKEW_CA= L}, + + {.reg_addr =3D 0x0c94, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0ca0, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c90, .reg_data =3D 0x0f, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c98, .reg_data =3D 0x08, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c94, .reg_data =3D 0x07, .delay_us =3D 0x01, .param_ty= pe =3D CSIPHY_DEFAULT_PARAMS}, + {.reg_addr =3D 0x0c30, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c00, .reg_data =3D 0x8e, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c38, .reg_data =3D 0xfe, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c2c, .reg_data =3D 0x01, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c34, .reg_data =3D 0x0f, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c1c, .reg_data =3D 0x0a, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c14, .reg_data =3D 0x60, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c3c, .reg_data =3D 0xb8, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c04, .reg_data =3D 0x0c, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c20, .reg_data =3D 0x00, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c08, .reg_data =3D 0x10, .param_type =3D CSIPHY_SETTLE_= CNT_LOWER_BYTE}, + {.reg_addr =3D 0x0c10, .reg_data =3D 0x52, .param_type =3D CSIPHY_DEFAULT= _PARAMS}, + {.reg_addr =3D 0x0c94, .reg_data =3D 0xd7, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x0c5c, .reg_data =3D 0x00, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x0c60, .reg_data =3D 0xbd, .param_type =3D CSIPHY_SKEW_CA= L}, + {.reg_addr =3D 0x0c64, .reg_data =3D 0x7f, .param_type =3D CSIPHY_SKEW_CA= L}, +}; + +static inline const struct mipi_csi2phy_device_regs * +csi2phy_dev_to_regs(struct mipi_csi2phy_device *csi2phy) +{ + return &csi2phy->soc_cfg->reg_info; +} + +static void phy_qcom_mipi_csi2_hw_version_read(struct mipi_csi2phy_device = *csi2phy) +{ + const struct mipi_csi2phy_device_regs *regs =3D csi2phy_dev_to_regs(csi2p= hy); + u32 tmp; + + writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); + + tmp =3D readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 12)); + csi2phy->hw_version =3D tmp; + + tmp =3D readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 13)); + csi2phy->hw_version |=3D (tmp << 8) & 0xFF00; + + tmp =3D readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 14)); + csi2phy->hw_version |=3D (tmp << 16) & 0xFF0000; + + tmp =3D readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 15)); + csi2phy->hw_version |=3D (tmp << 24) & 0xFF000000; + + dev_dbg_once(csi2phy->dev, "CSIPHY 3PH HW Version =3D 0x%08x\n", csi2phy-= >hw_version); +} + +/* + * phy_qcom_mipi_csi2_reset - Perform software reset on CSIPHY module + * @phy_qcom_mipi_csi2: CSIPHY device + */ +static void phy_qcom_mipi_csi2_reset(struct mipi_csi2phy_device *csi2phy) +{ + const struct mipi_csi2phy_device_regs *regs =3D csi2phy_dev_to_regs(csi2p= hy); + + writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET, + csi2phy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_= offset, 0)); + usleep_range(5000, 8000); + writel(0x0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); +} + +/* + * phy_qcom_mipi_csi2_settle_cnt_calc - Calculate settle count value + * + * Helper function to calculate settle count value. This is + * based on the CSI2 T_hs_settle parameter which in turn + * is calculated based on the CSI2 transmitter link frequency. + * + * Return settle count value or 0 if the CSI2 link frequency + * is not available + */ +static u8 phy_qcom_mipi_csi2_settle_cnt_calc(s64 link_freq, u32 timer_clk_= rate) +{ + u32 t_hs_prepare_max_ps; + u32 timer_period_ps; + u32 t_hs_settle_ps; + u8 settle_cnt; + u32 ui_ps; + + if (link_freq <=3D 0) + return 0; + + ui_ps =3D div_u64(PSEC_PER_SEC, link_freq); + ui_ps /=3D 2; + t_hs_prepare_max_ps =3D 85000 + 6 * ui_ps; + t_hs_settle_ps =3D t_hs_prepare_max_ps; + + timer_period_ps =3D div_u64(PSEC_PER_SEC, timer_clk_rate); + settle_cnt =3D t_hs_settle_ps / timer_period_ps - 6; + + return settle_cnt; +} + +static void +phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy, + u8 settle_cnt) +{ + const struct mipi_csi2phy_device_regs *regs =3D csi2phy_dev_to_regs(csi2p= hy); + const struct mipi_csi2phy_lane_regs *r =3D regs->init_seq; + int i, array_size =3D regs->lane_array_size; + u32 val; + + for (i =3D 0; i < array_size; i++, r++) { + switch (r->param_type) { + case CSIPHY_SETTLE_CNT_LOWER_BYTE: + val =3D settle_cnt & 0xff; + break; + case CSIPHY_SKEW_CAL: + /* TODO: support application of skew from dt flag */ + continue; + default: + val =3D r->reg_data; + break; + } + writel(val, csi2phy->base + r->reg_addr); + if (r->delay_us) + udelay(r->delay_us); + } +} + +static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi= 2phy, + struct mipi_csi2phy_stream_cfg *cfg) +{ + const struct mipi_csi2phy_device_regs *regs =3D csi2phy_dev_to_regs(csi2p= hy); + struct mipi_csi2phy_lanes_cfg *lane_cfg =3D &cfg->lane_cfg; + u8 settle_cnt; + u8 val; + int i; + + settle_cnt =3D phy_qcom_mipi_csi2_settle_cnt_calc(cfg->link_freq, csi2phy= ->timer_clk_rate); + + val =3D CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; + for (i =3D 0; i < cfg->num_data_lanes; i++) + val |=3D BIT(lane_cfg->data[i].pos * 2); + + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); + + val =3D CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); + + val =3D 0x02; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 7)); + + val =3D 0x00; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); + + phy_qcom_mipi_csi2_gen2_config_lanes(csi2phy, settle_cnt); + + /* IRQ_MASK registers - disable all interrupts */ + for (i =3D CSI_COMMON_STATUS_NUM; i < CSI_CTRL_STATUS_INDEX; i++) { + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, i)); + } + + return 0; +} + +static void +phy_qcom_mipi_csi2_lanes_disable(struct mipi_csi2phy_device *csi2phy, + struct mipi_csi2phy_stream_cfg *cfg) +{ + const struct mipi_csi2phy_device_regs *regs =3D csi2phy_dev_to_regs(csi2p= hy); + + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); + + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); +} + +static const struct mipi_csi2phy_hw_ops phy_qcom_mipi_csi2_ops_3ph_1_0 =3D= { + .hw_version_read =3D phy_qcom_mipi_csi2_hw_version_read, + .reset =3D phy_qcom_mipi_csi2_reset, + .lanes_enable =3D phy_qcom_mipi_csi2_lanes_enable, + .lanes_disable =3D phy_qcom_mipi_csi2_lanes_disable, +}; + +static const char * const x1e_clks[] =3D { + "core", + "timer" +}; + +static const char * const x1e_supplies[] =3D { + "vdda-0p9", + "vdda-1p2" +}; + +static const char * const x1e_genpd_names[] =3D { + "mx", + "mmcx", +}; + +const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e =3D { + .ops =3D &phy_qcom_mipi_csi2_ops_3ph_1_0, + .reg_info =3D { + .init_seq =3D lane_regs_x1e80100, + .lane_array_size =3D ARRAY_SIZE(lane_regs_x1e80100), + .common_regs_offset =3D 0x1000, + }, + .supply_names =3D (const char **)x1e_supplies, + .num_supplies =3D ARRAY_SIZE(x1e_supplies), + .clk_names =3D (const char **)x1e_clks, + .num_clk =3D ARRAY_SIZE(x1e_clks), + .opp_clk =3D x1e_clks[0], + .timer_clk =3D x1e_clks[1], + .genpd_names =3D (const char **)x1e_genpd_names, + .num_genpd_names =3D ARRAY_SIZE(x1e_genpd_names), +}; diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/q= ualcomm/phy-qcom-mipi-csi2-core.c new file mode 100644 index 0000000000000..47acf0d586a15 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025, Linaro Ltd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "phy-qcom-mipi-csi2.h" + +static int +phy_qcom_mipi_csi2_set_clock_rates(struct mipi_csi2phy_device *csi2phy, + s64 link_freq) +{ + struct device *dev =3D csi2phy->dev; + unsigned long opp_rate =3D link_freq / 4; + struct dev_pm_opp *opp; + long timer_rate; + int ret; + + opp =3D dev_pm_opp_find_freq_ceil(dev, &opp_rate); + if (IS_ERR(opp)) { + dev_err(csi2phy->dev, "Couldn't find ceiling for %lld Hz\n", + link_freq); + return PTR_ERR(opp); + } + + for (int i =3D 0; i < csi2phy->num_pds; i++) { + unsigned int perf =3D dev_pm_opp_get_required_pstate(opp, i); + + ret =3D dev_pm_genpd_set_performance_state(csi2phy->pds[i], perf); + if (ret) { + dev_err(csi2phy->dev, "Couldn't set perf state %u\n", + perf); + dev_pm_opp_put(opp); + return ret; + } + } + dev_pm_opp_put(opp); + + ret =3D dev_pm_opp_set_rate(dev, opp_rate); + if (ret) { + dev_err(csi2phy->dev, "dev_pm_opp_set_rate() fail\n"); + return ret; + } + + timer_rate =3D clk_round_rate(csi2phy->timer_clk, link_freq / 4); + if (timer_rate < 0) + return timer_rate; + + ret =3D clk_set_rate(csi2phy->timer_clk, timer_rate); + if (ret) + return ret; + + csi2phy->timer_clk_rate =3D timer_rate; + + return 0; +} + +static int phy_qcom_mipi_csi2_configure(struct phy *phy, + union phy_configure_opts *opts) +{ + struct mipi_csi2phy_device *csi2phy =3D phy_get_drvdata(phy); + struct phy_configure_opts_mipi_dphy *dphy_cfg =3D &opts->mipi_dphy; + struct mipi_csi2phy_stream_cfg *stream_cfg =3D &csi2phy->stream_cfg; + int ret; + int i; + + ret =3D phy_mipi_dphy_config_validate(dphy_cfg); + if (ret) + return ret; + + if (dphy_cfg->lanes < 1 || dphy_cfg->lanes > CSI2_MAX_DATA_LANES) + return -EINVAL; + + stream_cfg->link_freq =3D dphy_cfg->hs_clk_rate; + stream_cfg->num_data_lanes =3D dphy_cfg->lanes; + + for (i =3D 0; i < stream_cfg->num_data_lanes; i++) { + stream_cfg->lane_cfg.data[i].pol =3D dphy_cfg->lane_polarities[i]; + stream_cfg->lane_cfg.data[i].pos =3D dphy_cfg->lane_positions[i]; + } + + stream_cfg->lane_cfg.clk.pol =3D dphy_cfg->clock_lane_polarity; + stream_cfg->lane_cfg.clk.pos =3D dphy_cfg->clock_lane_position; + + return 0; +} + +static int phy_qcom_mipi_csi2_power_on(struct phy *phy) +{ + struct mipi_csi2phy_device *csi2phy =3D phy_get_drvdata(phy); + const struct mipi_csi2phy_hw_ops *ops =3D csi2phy->soc_cfg->ops; + struct device *dev =3D &phy->dev; + int ret; + + ret =3D regulator_bulk_enable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + if (ret) + return ret; + + ret =3D phy_qcom_mipi_csi2_set_clock_rates(csi2phy, csi2phy->stream_cfg.l= ink_freq); + if (ret) + goto poweroff_phy; + + ret =3D clk_bulk_prepare_enable(csi2phy->soc_cfg->num_clk, + csi2phy->clks); + if (ret) { + dev_err(dev, "failed to enable clocks, %d\n", ret); + goto poweroff_phy; + } + + ops->reset(csi2phy); + + ops->hw_version_read(csi2phy); + + return ops->lanes_enable(csi2phy, &csi2phy->stream_cfg); + +poweroff_phy: + regulator_bulk_disable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + + return ret; +} + +static int phy_qcom_mipi_csi2_power_off(struct phy *phy) +{ + struct mipi_csi2phy_device *csi2phy =3D phy_get_drvdata(phy); + int i; + + for (i =3D 0; i < csi2phy->num_pds; i++) + dev_pm_genpd_set_performance_state(csi2phy->pds[i], 0); + + clk_bulk_disable_unprepare(csi2phy->soc_cfg->num_clk, + csi2phy->clks); + regulator_bulk_disable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + + return 0; +} + +static const struct phy_ops phy_qcom_mipi_csi2_ops =3D { + .configure =3D phy_qcom_mipi_csi2_configure, + .power_on =3D phy_qcom_mipi_csi2_power_on, + .power_off =3D phy_qcom_mipi_csi2_power_off, + .owner =3D THIS_MODULE, +}; + +static struct phy *qcom_csi2_phy_xlate(struct device *dev, + const struct of_phandle_args *args) +{ + struct mipi_csi2phy_device *csi2phy =3D dev_get_drvdata(dev); + + if (args->args[0] !=3D PHY_QCOM_CSI2_MODE_DPHY) { + dev_err(csi2phy->dev, "mode %d -EOPNOTSUPP\n", args->args[0]); + return ERR_PTR(-EOPNOTSUPP); + } + + csi2phy->phy_mode =3D args->args[0]; + + return csi2phy->phy; +} + +static int phy_qcom_mipi_csi2_probe(struct platform_device *pdev) +{ + unsigned int i, num_clk, num_supplies, num_pds; + struct mipi_csi2phy_device *csi2phy; + struct phy_provider *phy_provider; + struct device *dev =3D &pdev->dev; + struct phy *generic_phy; + int ret; + + csi2phy =3D devm_kzalloc(dev, sizeof(*csi2phy), GFP_KERNEL); + if (!csi2phy) + return -ENOMEM; + + csi2phy->dev =3D dev; + dev_set_drvdata(dev, csi2phy); + + csi2phy->soc_cfg =3D device_get_match_data(&pdev->dev); + + if (!csi2phy->soc_cfg) + return -EINVAL; + + num_clk =3D csi2phy->soc_cfg->num_clk; + csi2phy->clks =3D devm_kzalloc(dev, sizeof(*csi2phy->clks) * num_clk, GFP= _KERNEL); + if (!csi2phy->clks) + return -ENOMEM; + + num_pds =3D csi2phy->soc_cfg->num_genpd_names; + if (!num_pds) + return -EINVAL; + + csi2phy->pds =3D devm_kzalloc(dev, sizeof(*csi2phy->pds) * num_pds, GFP_K= ERNEL); + if (!csi2phy->pds) + return -ENOMEM; + + for (i =3D 0; i < num_pds; i++) { + csi2phy->pds[i] =3D dev_pm_domain_attach_by_name(dev, + csi2phy->soc_cfg->genpd_names[i]); + if (IS_ERR(csi2phy->pds[i])) { + return dev_err_probe(dev, PTR_ERR(csi2phy->pds[i]), + "Failed to attach %s\n", + csi2phy->soc_cfg->genpd_names[i]); + } + } + csi2phy->num_pds =3D num_pds; + + for (i =3D 0; i < num_clk; i++) + csi2phy->clks[i].id =3D csi2phy->soc_cfg->clk_names[i]; + + ret =3D devm_clk_bulk_get(dev, num_clk, csi2phy->clks); + if (ret) + return dev_err_probe(dev, ret, "Failed to get clocks\n"); + + csi2phy->timer_clk =3D devm_clk_get(dev, csi2phy->soc_cfg->timer_clk); + if (IS_ERR(csi2phy->timer_clk)) { + return dev_err_probe(dev, PTR_ERR(csi2phy->timer_clk), + "Failed to get timer clock\n"); + } + + ret =3D devm_pm_opp_set_clkname(dev, csi2phy->soc_cfg->opp_clk); + if (ret) + return dev_err_probe(dev, ret, "Failed to set opp clkname\n"); + + ret =3D devm_pm_opp_of_add_table(dev); + if (ret && ret !=3D -ENODEV) + return dev_err_probe(dev, ret, "invalid OPP table in device tree\n"); + + num_supplies =3D csi2phy->soc_cfg->num_supplies; + csi2phy->supplies =3D devm_kzalloc(dev, sizeof(*csi2phy->supplies) * num_= supplies, + GFP_KERNEL); + if (!csi2phy->supplies) + return -ENOMEM; + + for (i =3D 0; i < num_supplies; i++) + csi2phy->supplies[i].supply =3D csi2phy->soc_cfg->supply_names[i]; + + ret =3D devm_regulator_bulk_get(dev, num_supplies, csi2phy->supplies); + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulator supplies\n"); + + csi2phy->base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(csi2phy->base)) + return PTR_ERR(csi2phy->base); + + generic_phy =3D devm_phy_create(dev, NULL, &phy_qcom_mipi_csi2_ops); + if (IS_ERR(generic_phy)) { + ret =3D PTR_ERR(generic_phy); + return dev_err_probe(dev, ret, "failed to create phy\n"); + } + csi2phy->phy =3D generic_phy; + + phy_set_drvdata(generic_phy, csi2phy); + + phy_provider =3D devm_of_phy_provider_register(dev, qcom_csi2_phy_xlate); + if (!IS_ERR(phy_provider)) + dev_dbg(dev, "Registered MIPI CSI2 PHY device\n"); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id phy_qcom_mipi_csi2_of_match_table[] =3D { + { .compatible =3D "qcom,x1e80100-csi2-phy", .data =3D &mipi_csi2_dphy_4nm= _x1e }, + { } +}; +MODULE_DEVICE_TABLE(of, phy_qcom_mipi_csi2_of_match_table); + +static struct platform_driver phy_qcom_mipi_csi2_driver =3D { + .probe =3D phy_qcom_mipi_csi2_probe, + .driver =3D { + .name =3D "qcom-mipi-csi2-phy", + .of_match_table =3D phy_qcom_mipi_csi2_of_match_table, + }, +}; + +module_platform_driver(phy_qcom_mipi_csi2_driver); + +MODULE_DESCRIPTION("Qualcomm MIPI CSI2 PHY driver"); +MODULE_AUTHOR("Bryan O'Donoghue "); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h b/drivers/phy/qualco= mm/phy-qcom-mipi-csi2.h new file mode 100644 index 0000000000000..27607dea412f1 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * + * Qualcomm MIPI CSI2 CPHY/DPHY driver + * + * Copyright (C) 2025 Linaro Ltd. + */ +#ifndef __PHY_QCOM_MIPI_CSI2_H__ +#define __PHY_QCOM_MIPI_CSI2_H__ + +#include + +#define CSI2_MAX_DATA_LANES 4 + +struct mipi_csi2phy_lane { + u8 pos; + u8 pol; +}; + +struct mipi_csi2phy_lanes_cfg { + struct mipi_csi2phy_lane data[CSI2_MAX_DATA_LANES]; + struct mipi_csi2phy_lane clk; +}; + +struct mipi_csi2phy_stream_cfg { + s64 link_freq; + u8 num_data_lanes; + struct mipi_csi2phy_lanes_cfg lane_cfg; +}; + +struct mipi_csi2phy_device; + +struct mipi_csi2phy_hw_ops { + void (*hw_version_read)(struct mipi_csi2phy_device *csi2phy_dev); + void (*reset)(struct mipi_csi2phy_device *csi2phy_dev); + int (*lanes_enable)(struct mipi_csi2phy_device *csi2phy_dev, + struct mipi_csi2phy_stream_cfg *cfg); + void (*lanes_disable)(struct mipi_csi2phy_device *csi2phy_dev, + struct mipi_csi2phy_stream_cfg *cfg); +}; + +struct mipi_csi2phy_lane_regs { + const s32 reg_addr; + const s32 reg_data; + const u32 delay_us; + const u32 param_type; +}; + +struct mipi_csi2phy_device_regs { + const struct mipi_csi2phy_lane_regs *init_seq; + const int lane_array_size; + const u32 common_regs_offset; +}; + +struct mipi_csi2phy_soc_cfg { + const struct mipi_csi2phy_hw_ops *ops; + const struct mipi_csi2phy_device_regs reg_info; + + const char ** const supply_names; + const unsigned int num_supplies; + + const char ** const clk_names; + const unsigned int num_clk; + + const char * const opp_clk; + const char * const timer_clk; + + const char ** const genpd_names; + const unsigned int num_genpd_names; +}; + +struct mipi_csi2phy_device { + struct device *dev; + u8 phy_mode; + + struct phy *phy; + void __iomem *base; + + struct clk_bulk_data *clks; + struct clk *timer_clk; + u32 timer_clk_rate; + + struct regulator_bulk_data *supplies; + struct device **pds; + unsigned int num_pds; + + const struct mipi_csi2phy_soc_cfg *soc_cfg; + struct mipi_csi2phy_stream_cfg stream_cfg; + + u32 hw_version; +}; + +extern const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e; + +#endif /* __PHY_QCOM_MIPI_CSI2_H__ */ --=20 2.52.0