* [PATCH v3 0/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver
@ 2026-02-26 12:34 Bryan O'Donoghue
2026-02-26 12:34 ` [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema Bryan O'Donoghue
2026-02-26 12:34 ` [PATCH v3 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver Bryan O'Donoghue
0 siblings, 2 replies; 25+ messages in thread
From: Bryan O'Donoghue @ 2026-02-26 12:34 UTC (permalink / raw)
To: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Neil Armstrong
Cc: Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm,
linux-phy, linux-media, devicetree, linux-kernel,
Bryan O'Donoghue
v3:
- Resending this to make clear this submission is additive to x1e/Hamoa
The existing bindings and code will continue to work
Bindings are added only, nothing is subtracted from existing ABI.
- Link to v2: https://lore.kernel.org/r/20260225-x1e-csi2-phy-v2-0-7756edb67ea9@linaro.org
v2:
In this updated version
- Added operating-point support
The csiphy clock sets the OPP prior to setting the rate
for csiphy and csiphy_timer - Konrad
- Combo mode
Combo mode in CAMSS yaml has been added. Right now
no code has been changed in the PHY driver to support it as
I don't have hardware to test. In principle though it can
be supported. - Vladimir
- CSIPHY init sequences
I left these as their "magic number formats". With my diminished
status as a non-qcom VPN person - I can no longer see what the bits
map to. Moreover this is the situation any non-VPN community member
will be in when submitting CSIPHY sequences derived from downstream.
I think it is perfectly reasonable to take public CSIPHY init sequences
as magic numbers. If someone with bit-level access wants to enumerate
the bits that's fine but, it shouldn't gate in the interim. - Konrad/bod
- Sensor endpoints
I've stuck to the format used by every other CSIPHY in upstream.
Sensor endpoints hit the CAMSS/CSID endpoint not a endpoint in the PHY.
Given the proposed changes to CAMSS though to support "combo mode" I
think this should achieve the same outcome - multiple sensors on the one
PHY without introducing endpoints into the PHY that no other CSIPHY in
upstream currently has.
- Bitmask of enabled lanes
Work needs to be done in the v4l2 layer to really support this.
I propose making a separate series dedicated to non-linear bit
interpretation after merging this so as to contain the scope of the
series to something more bite (byte haha) sized. - Konrad/bod
- Link to v1: https://lore.kernel.org/r/20250710-x1e-csi2-phy-v1-0-74acbb5b162b@linaro.org
v1:
This short series adds a CSI2 MIPI PHY driver, initially supporting D-PHY
mode. The core logic and init sequences come directly from CAMSS and are
working on at least five separate x1e devices.
The rationale to instantiate CSI2 PHYs as standalone devices instead of as
sub-nodes of CAMSS is as follows.
1. Precedence
CAMSS has a dedicated I2C bus called CCI Camera Control Interface.
We model this controller as its own separate device in devicetree.
This makes sense and CCI/I2C is a well defined bus type already modelled
in Linux.
MIPI CSI2 PHY devices similarly fit into a well defined separate
bus/device structure.
Contrast to another CAMSS component such as VFE, CSID or TPG these
components only interact with other CAMSS inputs/outputs unlike CSIPHY
which interacts with non-SoC components.
2. Hardware pinouts and rails
The CSI2 PHY has its own data/clock lanes out from the SoC and indeed
has its own incoming power-rails.
3. Other devicetree schemas
There are several examples throughout the kernel of CSI PHYs modeled as
standalone devices which one assumes follows the same reasoning as given
above.
I've been working on this on-and-off since the end of April:
Link: https://lore.kernel.org/linux-media/c5cf0155-f839-4db9-b865-d39b56bb1e0a@linaro.org
There is another proposal to have the PHYs be subdevices of CAMSS but, I
believe we should go with a "full fat" PHY to match best practices in
drivers/phy/qualcomm/*.
Using the standard PHY API and the parameter passing that goes with it
allows us to move away from custom interfaces in CAMSS and to conform more
clearly to established PHY paradigms such as the QMP combo PHY.
Looking at existing compat strings I settled on
"qcom,x1e80100-mipi-csi2-combo-phy" deliberately omitting reference to the
fact the PHY is built on a four nano-meter process node, which seems to
match recent submissions to QMP PHY.
My first pass at this driver included support for the old two phase
devices:
Link: https://git.codelinaro.org/bryan.odonoghue/kernel/-/commit/a504c28d109296c93470340cfe7281231f573bcb#b6e59ed7db94c9da22e492bb03fcda6a4300983c
I realised that the device tree schema changes required to support a
comprehensive conversion of all CAMSS to this driver would be an
almost certainly be unacceptable ABI break or at the very least an enormous
amount of work and verification so I instead aimed to support just one new
SoC in the submission.
I've retained the callback indirections give us scope to add in another type of
future PHY including potentially adding in the 2PH later on.
This driver is tested and working on x1e/Hamoa and has been tested as not
breaking sc8280xp/Makena and sm8250/Kona.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
Bryan O'Donoghue (2):
dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver
.../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 114 ++++++
MAINTAINERS | 11 +
drivers/phy/qualcomm/Kconfig | 13 +
drivers/phy/qualcomm/Makefile | 5 +
drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 384 +++++++++++++++++++++
drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c | 307 ++++++++++++++++
drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 102 ++++++
7 files changed, 936 insertions(+)
---
base-commit: c824345288d11e269ce41b36c105715bc2286050
change-id: 20250710-x1e-csi2-phy-f6434b651d3a
Best regards,
--
Bryan O'Donoghue <bryan.odonoghue@linaro.org>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 25+ messages in thread* [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-02-26 12:34 [PATCH v3 0/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver Bryan O'Donoghue @ 2026-02-26 12:34 ` Bryan O'Donoghue 2026-02-27 9:41 ` Krzysztof Kozlowski 2026-03-03 1:51 ` Vijay Kumar Tumati 2026-02-26 12:34 ` [PATCH v3 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver Bryan O'Donoghue 1 sibling, 2 replies; 25+ messages in thread From: Bryan O'Donoghue @ 2026-02-26 12:34 UTC (permalink / raw) To: Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel, Bryan O'Donoghue Add a base schema initially compatible with x1e80100 to describe MIPI CSI2 PHY devices. The hardware can support both C-PHY and D-PHY modes. 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 <bryan.odonoghue@linaro.org> --- .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 114 +++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml new file mode 100644 index 0000000000000..c937d26ccbda9 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml @@ -0,0 +1,114 @@ +# 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 <bod@kernel.org> + +description: + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 sensors + 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 + + clocks: + maxItems: 4 + + clock-names: + items: + - const: csiphy + - const: csiphy_timer + - const: camnoc_axi + - const: cpas_ahb + + interrupts: + maxItems: 1 + + operating-points-v2: + maxItems: 1 + + power-domains: + maxItems: 1 + + vdda-0p8-supply: + description: Phandle to a 0.8V 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 + - vdda-0p8-supply + - vdda-1p2-supply + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/clock/qcom,x1e80100-camcc.h> + #include <dt-bindings/clock/qcom,x1e80100-gcc.h> + #include <dt-bindings/phy/phy.h> + + csiphy@ace4000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0x0ace4000 0x2000>; + #phy-cells = <1>; + + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>; + clock-names = "csiphy", + "csiphy_timer", + "camnoc_axi", + "cpas_ahb"; + + operating-points-v2 = <&csiphy_opp_table>; + + interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + vdda-0p8-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + }; + + csiphy_opp_table: opp-table-csiphy { + 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_low_svs>; + }; + }; -- 2.52.0 -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-02-26 12:34 ` [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema Bryan O'Donoghue @ 2026-02-27 9:41 ` Krzysztof Kozlowski 2026-02-27 9:47 ` Bryan O'Donoghue 2026-03-03 1:51 ` Vijay Kumar Tumati 1 sibling, 1 reply; 25+ messages in thread From: Krzysztof Kozlowski @ 2026-02-27 9:41 UTC (permalink / raw) To: Bryan O'Donoghue Cc: Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On Thu, Feb 26, 2026 at 12:34:25PM +0000, Bryan O'Donoghue wrote: > Add a base schema initially compatible with x1e80100 to describe MIPI CSI2 > PHY devices. > > The hardware can support both C-PHY and D-PHY modes. 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 <bryan.odonoghue@linaro.org> > --- > .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 114 +++++++++++++++++++++ > 1 file changed, 114 insertions(+) > > diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml > new file mode 100644 > index 0000000000000..c937d26ccbda9 > --- /dev/null > +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml > @@ -0,0 +1,114 @@ > +# 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 Qualcomm SoC CSI2 PHY > + > +maintainers: > + - Bryan O'Donoghue <bod@kernel.org> > + > +description: > + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 sensors > + to Qualcomm's Camera CSI Decoder. The PHY supports both C-PHY and D-PHY > + modes. So just to be clear: this is not MIPI CSI, but only the CSI PHY? There are no ports here, which seems fine for the phy and will be in the MIPI CSI block? > + > +properties: > + compatible: > + const: qcom,x1e80100-csi2-phy > + > + reg: > + maxItems: 1 > + > + "#phy-cells": > + const: 1 > + > + clocks: > + maxItems: 4 > + > + clock-names: > + items: > + - const: csiphy probably: core or iface > + - const: csiphy_timer timer > + - const: camnoc_axi axi or noc > + - const: cpas_ahb bus, ahb or cpas, depending whether this is only one ahb or this is bus of some cpas subblock See also: https://lore.kernel.org/all/20260115-sm6150_evk-v3-2-81526dd15543@oss.qualcomm.com/ > + > + interrupts: > + maxItems: 1 > + > + operating-points-v2: Just true. It is not an array. > + maxItems: 1 Also opp-table like in other schemas. > + > + power-domains: > + maxItems: 1 > + > + vdda-0p8-supply: > + description: Phandle to a 0.8V 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 > + - vdda-0p8-supply > + - vdda-1p2-supply > + > +additionalProperties: false > + > +examples: > + - | > + #include <dt-bindings/interrupt-controller/arm-gic.h> > + #include <dt-bindings/clock/qcom,x1e80100-camcc.h> > + #include <dt-bindings/clock/qcom,x1e80100-gcc.h> > + #include <dt-bindings/phy/phy.h> > + > + csiphy@ace4000 { phy@ or csi-phy@ > + compatible = "qcom,x1e80100-csi2-phy"; > + reg = <0x0ace4000 0x2000>; > + #phy-cells = <1>; > + > + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, > + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, > + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, > + <&camcc CAM_CC_CPAS_AHB_CLK>; > + clock-names = "csiphy", > + "csiphy_timer", > + "camnoc_axi", > + "cpas_ahb"; > + > + operating-points-v2 = <&csiphy_opp_table>; > + > + interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>; > + > + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; > + > + vdda-0p8-supply = <&vreg_l2c_0p8>; > + vdda-1p2-supply = <&vreg_l1c_1p2>; > + }; > + > + csiphy_opp_table: opp-table-csiphy { Drop entire node, not relevant here. Best regards, Krzysztof -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-02-27 9:41 ` Krzysztof Kozlowski @ 2026-02-27 9:47 ` Bryan O'Donoghue 0 siblings, 0 replies; 25+ messages in thread From: Bryan O'Donoghue @ 2026-02-27 9:47 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 27/02/2026 09:41, Krzysztof Kozlowski wrote: > On Thu, Feb 26, 2026 at 12:34:25PM +0000, Bryan O'Donoghue wrote: >> Add a base schema initially compatible with x1e80100 to describe MIPI CSI2 >> PHY devices. >> >> The hardware can support both C-PHY and D-PHY modes. 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 <bryan.odonoghue@linaro.org> >> --- >> .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 114 +++++++++++++++++++++ >> 1 file changed, 114 insertions(+) >> >> diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml >> new file mode 100644 >> index 0000000000000..c937d26ccbda9 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml >> @@ -0,0 +1,114 @@ >> +# 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 > > Qualcomm SoC CSI2 PHY > > >> + >> +maintainers: >> + - Bryan O'Donoghue <bod@kernel.org> >> + >> +description: >> + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 sensors >> + to Qualcomm's Camera CSI Decoder. The PHY supports both C-PHY and D-PHY >> + modes. > > So just to be clear: this is not MIPI CSI, but only the CSI PHY? There > are no ports here, which seems fine for the phy and will be in the MIPI > CSI block? CAMSS ports map to the CSID - CSI Decoder yes. > >> + >> +properties: >> + compatible: >> + const: qcom,x1e80100-csi2-phy >> + >> + reg: >> + maxItems: 1 >> + >> + "#phy-cells": >> + const: 1 >> + >> + clocks: >> + maxItems: 4 >> + >> + clock-names: >> + items: >> + - const: csiphy > > probably: core or iface > >> + - const: csiphy_timer > > timer > >> + - const: camnoc_axi > > axi or noc > >> + - const: cpas_ahb > > bus, ahb or cpas, depending whether this is only one ahb or this is bus of > some cpas subblock > > See also: https://lore.kernel.org/all/20260115-sm6150_evk-v3-2-81526dd15543@oss.qualcomm.com/ > > >> + >> + interrupts: >> + maxItems: 1 >> + >> + operating-points-v2: > > Just true. It is not an array. LOL I asked a chatbot to review my submission and it told me to change this from true to a list. €90 subscription well spent... Thanks for review. --- bod -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-02-26 12:34 ` [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema Bryan O'Donoghue 2026-02-27 9:41 ` Krzysztof Kozlowski @ 2026-03-03 1:51 ` Vijay Kumar Tumati 2026-03-03 9:27 ` Bryan O'Donoghue ` (2 more replies) 1 sibling, 3 replies; 25+ messages in thread From: Vijay Kumar Tumati @ 2026-03-03 1:51 UTC (permalink / raw) To: Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel Hi Bryan, On 2/26/2026 4:34 AM, Bryan O'Donoghue wrote: > Add a base schema initially compatible with x1e80100 to describe MIPI CSI2 > PHY devices. > > The hardware can support both C-PHY and D-PHY modes. 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 <bryan.odonoghue@linaro.org> > --- > .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 114 +++++++++++++++++++++ > 1 file changed, 114 insertions(+) > > diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml > new file mode 100644 > index 0000000000000..c937d26ccbda9 > --- /dev/null > +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml > @@ -0,0 +1,114 @@ > +# 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 <bod@kernel.org> > + > +description: > + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 sensors > + 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 > + > + clocks: > + maxItems: 4 > + > + clock-names: > + items: > + - const: csiphy > + - const: csiphy_timer > + - const: camnoc_axi > + - const: cpas_ahb > + > + interrupts: > + maxItems: 1 > + > + operating-points-v2: > + maxItems: 1 > + > + power-domains: > + maxItems: 1 > + > + vdda-0p8-supply: > + description: Phandle to a 0.8V 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 > + - vdda-0p8-supply > + - vdda-1p2-supply > + > +additionalProperties: false > + > +examples: > + - | > + #include <dt-bindings/interrupt-controller/arm-gic.h> > + #include <dt-bindings/clock/qcom,x1e80100-camcc.h> > + #include <dt-bindings/clock/qcom,x1e80100-gcc.h> > + #include <dt-bindings/phy/phy.h> > + > + csiphy@ace4000 { > + compatible = "qcom,x1e80100-csi2-phy"; > + reg = <0x0ace4000 0x2000>; > + #phy-cells = <1>; > + > + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, > + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, > + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, > + <&camcc CAM_CC_CPAS_AHB_CLK>; > + clock-names = "csiphy", > + "csiphy_timer", > + "camnoc_axi", > + "cpas_ahb"; > + > + operating-points-v2 = <&csiphy_opp_table>; > + > + interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>; > + > + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; As we are cleaning up the PHY device nodes, we should consider fixing the power domains as well. Although TOP GDSC is defined as a power domain, it is not the power source for the PHY devices. Rather, it is the MMCX, MXC and optionally MXA based on the architecture (Refer to 'Voltage rail' column for PHY clocks in IPCAT). There is no parent-child relationship between the TOP GDSC and these in the clock driver and it was just working as the required power rails are getting enabled by/for other MM devices. > + > + vdda-0p8-supply = <&vreg_l2c_0p8>; > + vdda-1p2-supply = <&vreg_l1c_1p2>; > + }; > + > + csiphy_opp_table: opp-table-csiphy { > + 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_low_svs>; > + }; > + }; > Thanks, Vijay. -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 1:51 ` Vijay Kumar Tumati @ 2026-03-03 9:27 ` Bryan O'Donoghue 2026-03-03 18:08 ` Vijay Kumar Tumati 2026-03-03 9:30 ` Bryan O'Donoghue 2026-03-03 22:31 ` Dmitry Baryshkov 2 siblings, 1 reply; 25+ messages in thread From: Bryan O'Donoghue @ 2026-03-03 9:27 UTC (permalink / raw) To: Vijay Kumar Tumati, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 03/03/2026 01:51, Vijay Kumar Tumati wrote: > Hi Bryan, > > On 2/26/2026 4:34 AM, Bryan O'Donoghue wrote: >> Add a base schema initially compatible with x1e80100 to describe MIPI CSI2 >> PHY devices. >> >> The hardware can support both C-PHY and D-PHY modes. 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 <bryan.odonoghue@linaro.org> >> --- >> .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 114 +++++++++++++++++++++ >> 1 file changed, 114 insertions(+) >> >> diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml >> new file mode 100644 >> index 0000000000000..c937d26ccbda9 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml >> @@ -0,0 +1,114 @@ >> +# 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 <bod@kernel.org> >> + >> +description: >> + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 sensors >> + 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 >> + >> + clocks: >> + maxItems: 4 >> + >> + clock-names: >> + items: >> + - const: csiphy >> + - const: csiphy_timer >> + - const: camnoc_axi >> + - const: cpas_ahb >> + >> + interrupts: >> + maxItems: 1 >> + >> + operating-points-v2: >> + maxItems: 1 >> + >> + power-domains: >> + maxItems: 1 >> + >> + vdda-0p8-supply: >> + description: Phandle to a 0.8V 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 >> + - vdda-0p8-supply >> + - vdda-1p2-supply >> + >> +additionalProperties: false >> + >> +examples: >> + - | >> + #include <dt-bindings/interrupt-controller/arm-gic.h> >> + #include <dt-bindings/clock/qcom,x1e80100-camcc.h> >> + #include <dt-bindings/clock/qcom,x1e80100-gcc.h> >> + #include <dt-bindings/phy/phy.h> >> + >> + csiphy@ace4000 { >> + compatible = "qcom,x1e80100-csi2-phy"; >> + reg = <0x0ace4000 0x2000>; >> + #phy-cells = <1>; >> + >> + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, >> + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, >> + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, >> + <&camcc CAM_CC_CPAS_AHB_CLK>; >> + clock-names = "csiphy", >> + "csiphy_timer", >> + "camnoc_axi", >> + "cpas_ahb"; >> + >> + operating-points-v2 = <&csiphy_opp_table>; >> + >> + interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>; >> + >> + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; > As we are cleaning up the PHY device nodes, we should consider fixing > the power domains as well. Although TOP GDSC is defined as a power > domain, it is not the power source for the PHY devices. Rather, it is > the MMCX, MXC and optionally MXA based on the architecture (Refer to > 'Voltage rail' column for PHY clocks in IPCAT). Feel free to send me a qcom laptop and I will :) From memory though I _thought_ only the TOP was required for the PHY. I'd be grateful if you could confirm yourself in ipcat. - TITAN_TOP_GDSC - MXC - MMCX - MXA - first time I've heard of this rail, from memory I don't remember having seen this in ipcat when I could do so. There is no > parent-child relationship between the TOP GDSC and these in the clock > driver and it was just working as the required power rails are getting > enabled by/for other MM devices. Well only the GDSC is supplied by the clock controller. >> + >> + vdda-0p8-supply = <&vreg_l2c_0p8>; >> + vdda-1p2-supply = <&vreg_l1c_1p2>; >> + }; >> + >> + csiphy_opp_table: opp-table-csiphy { >> + 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_low_svs>; >> + }; >> + }; >> > Thanks, > Vijay. -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 9:27 ` Bryan O'Donoghue @ 2026-03-03 18:08 ` Vijay Kumar Tumati 2026-03-03 18:58 ` Vijay Kumar Tumati 0 siblings, 1 reply; 25+ messages in thread From: Vijay Kumar Tumati @ 2026-03-03 18:08 UTC (permalink / raw) To: Bryan O'Donoghue, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 3/3/2026 1:27 AM, Bryan O'Donoghue wrote: > On 03/03/2026 01:51, Vijay Kumar Tumati wrote: >> Hi Bryan, >> >> On 2/26/2026 4:34 AM, Bryan O'Donoghue wrote: >>> Add a base schema initially compatible with x1e80100 to describe MIPI >>> CSI2 >>> PHY devices. >>> >>> The hardware can support both C-PHY and D-PHY modes. 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 <bryan.odonoghue@linaro.org> >>> --- >>> .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 114 +++++++++ >>> ++++++++++++ >>> 1 file changed, 114 insertions(+) >>> >>> diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100- >>> csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100- >>> csi2-phy.yaml >>> new file mode 100644 >>> index 0000000000000..c937d26ccbda9 >>> --- /dev/null >>> +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml >>> @@ -0,0 +1,114 @@ >>> +# 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 <bod@kernel.org> >>> + >>> +description: >>> + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 >>> sensors >>> + 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 >>> + >>> + clocks: >>> + maxItems: 4 >>> + >>> + clock-names: >>> + items: >>> + - const: csiphy >>> + - const: csiphy_timer >>> + - const: camnoc_axi >>> + - const: cpas_ahb >>> + >>> + interrupts: >>> + maxItems: 1 >>> + >>> + operating-points-v2: >>> + maxItems: 1 >>> + >>> + power-domains: >>> + maxItems: 1 >>> + >>> + vdda-0p8-supply: >>> + description: Phandle to a 0.8V 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 >>> + - vdda-0p8-supply >>> + - vdda-1p2-supply >>> + >>> +additionalProperties: false >>> + >>> +examples: >>> + - | >>> + #include <dt-bindings/interrupt-controller/arm-gic.h> >>> + #include <dt-bindings/clock/qcom,x1e80100-camcc.h> >>> + #include <dt-bindings/clock/qcom,x1e80100-gcc.h> >>> + #include <dt-bindings/phy/phy.h> >>> + >>> + csiphy@ace4000 { >>> + compatible = "qcom,x1e80100-csi2-phy"; >>> + reg = <0x0ace4000 0x2000>; >>> + #phy-cells = <1>; >>> + >>> + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, >>> + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, >>> + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, >>> + <&camcc CAM_CC_CPAS_AHB_CLK>; >>> + clock-names = "csiphy", >>> + "csiphy_timer", >>> + "camnoc_axi", >>> + "cpas_ahb"; >>> + >>> + operating-points-v2 = <&csiphy_opp_table>; >>> + >>> + interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>; >>> + >>> + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; >> As we are cleaning up the PHY device nodes, we should consider fixing >> the power domains as well. Although TOP GDSC is defined as a power >> domain, it is not the power source for the PHY devices. Rather, it is >> the MMCX, MXC and optionally MXA based on the architecture (Refer to >> 'Voltage rail' column for PHY clocks in IPCAT). > > Feel free to send me a qcom laptop and I will :) :) > > From memory though I _thought_ only the TOP was required for the PHY. > I'd be grateful if you could confirm yourself in ipcat. > > - TITAN_TOP_GDSC > - MXC > - MMCX > - MXA - first time I've heard of this rail, from memory I don't remember > having seen this in ipcat when I could do so. MCX and MMCX are comminly required power domains across the PHYs but a subset of PHYs have the dependency on MXA. > > There is no >> parent-child relationship between the TOP GDSC and these in the clock >> driver and it was just working as the required power rails are getting >> enabled by/for other MM devices. > > Well only the GDSC is supplied by the clock controller. Right, GDSC is controlled by the CAMCC to suspend the subsystems. But the actual power supply and the voltage rails are under the control of the RPMH. So the clients need to enable and vote for the required perf corner as the core clocks scale up/down to be independent of the other subsystems sharing those voltage rails. > >>> + >>> + vdda-0p8-supply = <&vreg_l2c_0p8>; >>> + vdda-1p2-supply = <&vreg_l1c_1p2>; >>> + }; >>> + >>> + csiphy_opp_table: opp-table-csiphy { >>> + 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_low_svs>; >>> + }; >>> + }; >>> >> Thanks, >> Vijay. > Thanks, Vijay. -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 18:08 ` Vijay Kumar Tumati @ 2026-03-03 18:58 ` Vijay Kumar Tumati 2026-03-03 22:53 ` Bryan O'Donoghue 0 siblings, 1 reply; 25+ messages in thread From: Vijay Kumar Tumati @ 2026-03-03 18:58 UTC (permalink / raw) To: Bryan O'Donoghue, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 3/3/2026 10:08 AM, Vijay Kumar Tumati wrote: > > > On 3/3/2026 1:27 AM, Bryan O'Donoghue wrote: >> On 03/03/2026 01:51, Vijay Kumar Tumati wrote: >>> Hi Bryan, >>> >>> On 2/26/2026 4:34 AM, Bryan O'Donoghue wrote: >>>> Add a base schema initially compatible with x1e80100 to describe >>>> MIPI CSI2 >>>> PHY devices. >>>> >>>> The hardware can support both C-PHY and D-PHY modes. 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 <bryan.odonoghue@linaro.org> >>>> --- >>>> .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 114 ++++++++ >>>> + ++++++++++++ >>>> 1 file changed, 114 insertions(+) >>>> >>>> diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100- >>>> csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100- >>>> csi2-phy.yaml >>>> new file mode 100644 >>>> index 0000000000000..c937d26ccbda9 >>>> --- /dev/null >>>> +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml >>>> @@ -0,0 +1,114 @@ >>>> +# 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 <bod@kernel.org> >>>> + >>>> +description: >>>> + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI >>>> CSI2 sensors >>>> + 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 >>>> + >>>> + clocks: >>>> + maxItems: 4 >>>> + >>>> + clock-names: >>>> + items: >>>> + - const: csiphy >>>> + - const: csiphy_timer >>>> + - const: camnoc_axi >>>> + - const: cpas_ahb >>>> + >>>> + interrupts: >>>> + maxItems: 1 >>>> + >>>> + operating-points-v2: >>>> + maxItems: 1 >>>> + >>>> + power-domains: >>>> + maxItems: 1 >>>> + >>>> + vdda-0p8-supply: >>>> + description: Phandle to a 0.8V 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 >>>> + - vdda-0p8-supply >>>> + - vdda-1p2-supply >>>> + >>>> +additionalProperties: false >>>> + >>>> +examples: >>>> + - | >>>> + #include <dt-bindings/interrupt-controller/arm-gic.h> >>>> + #include <dt-bindings/clock/qcom,x1e80100-camcc.h> >>>> + #include <dt-bindings/clock/qcom,x1e80100-gcc.h> >>>> + #include <dt-bindings/phy/phy.h> >>>> + >>>> + csiphy@ace4000 { >>>> + compatible = "qcom,x1e80100-csi2-phy"; >>>> + reg = <0x0ace4000 0x2000>; >>>> + #phy-cells = <1>; >>>> + >>>> + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, >>>> + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, >>>> + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, >>>> + <&camcc CAM_CC_CPAS_AHB_CLK>; >>>> + clock-names = "csiphy", >>>> + "csiphy_timer", >>>> + "camnoc_axi", >>>> + "cpas_ahb"; >>>> + >>>> + operating-points-v2 = <&csiphy_opp_table>; >>>> + >>>> + interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>; >>>> + >>>> + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; >>> As we are cleaning up the PHY device nodes, we should consider fixing >>> the power domains as well. Although TOP GDSC is defined as a power >>> domain, it is not the power source for the PHY devices. Rather, it is >>> the MMCX, MXC and optionally MXA based on the architecture (Refer to >>> 'Voltage rail' column for PHY clocks in IPCAT). >> >> Feel free to send me a qcom laptop and I will :) > :) >> >> From memory though I _thought_ only the TOP was required for the PHY. >> I'd be grateful if you could confirm yourself in ipcat. >> >> - TITAN_TOP_GDSC >> - MXC >> - MMCX >> - MXA - first time I've heard of this rail, from memory I don't remember >> having seen this in ipcat when I could do so. > MCX and MMCX are comminly required power domains across the PHYs but a > subset of PHYs have the dependency on MXA. Actually, it's a bit more complicated on this target as cam_cc_cphy_rx_clk_src also depends on MXA, which means all the CBCs connected this RCG do as well. >> >> There is no >>> parent-child relationship between the TOP GDSC and these in the clock >>> driver and it was just working as the required power rails are getting >>> enabled by/for other MM devices. >> >> Well only the GDSC is supplied by the clock controller. > Right, GDSC is controlled by the CAMCC to suspend the subsystems. But > the actual power supply and the voltage rails are under the control of > the RPMH. So the clients need to enable and vote for the required perf > corner as the core clocks scale up/down to be independent of the other > subsystems sharing those voltage rails. >> >>>> + >>>> + vdda-0p8-supply = <&vreg_l2c_0p8>; >>>> + vdda-1p2-supply = <&vreg_l1c_1p2>; >>>> + }; >>>> + >>>> + csiphy_opp_table: opp-table-csiphy { >>>> + 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_low_svs>; >>>> + }; >>>> + }; >>>> >>> Thanks, >>> Vijay. >> > Thanks, > Vijay. -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 18:58 ` Vijay Kumar Tumati @ 2026-03-03 22:53 ` Bryan O'Donoghue 2026-03-03 23:17 ` Vijay Kumar Tumati 0 siblings, 1 reply; 25+ messages in thread From: Bryan O'Donoghue @ 2026-03-03 22:53 UTC (permalink / raw) To: Vijay Kumar Tumati, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 03/03/2026 18:58, Vijay Kumar Tumati wrote: >>> - TITAN_TOP_GDSC >>> - MXC >>> - MMCX >>> - MXA - first time I've heard of this rail, from memory I don't remember >>> having seen this in ipcat when I could do so. >> MCX and MMCX are comminly required power domains across the PHYs but a >> subset of PHYs have the dependency on MXA. > Actually, it's a bit more complicated on this target as > cam_cc_cphy_rx_clk_src also depends on MXA, which means all the CBCs > connected this RCG do as well. Right but that's something to model in the clock-controller then not the PHY. i.e. if a clock depends on MXA then the clock controller should represent that dependency - not the PHY that depends on the clock. camcc on hamoa looks like this camcc: clock-controller@ade0000 { compatible = "qcom,x1e80100-camcc"; reg = <0 0x0ade0000 0 0x20000>; clocks = <&gcc GCC_CAMERA_AHB_CLK>, <&bi_tcxo_div2>, <&bi_tcxo_ao_div2>, <&sleep_clk>; power-domains = <&rpmhpd RPMHPD_MXC>, <&rpmhpd RPMHPD_MMCX>; required-opps = <&rpmhpd_opp_low_svs>, <&rpmhpd_opp_low_svs>; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; }; So... we may need to add MXA here, probably do based on what you've said but I believe TITAN_TOP_GDSC is the only power-domain we need to list for the PHYs themselves, as what you've described above is a clock power dependency which we basically already capture in the clock controller - absent the MXA - which is apparently always on... Sidenote, is MXA required for videocc too ? videocc: clock-controller@aaf0000 { compatible = "qcom,x1e80100-videocc"; reg = <0 0x0aaf0000 0 0x10000>; clocks = <&bi_tcxo_div2>, <&gcc GCC_VIDEO_AHB_CLK>; power-domains = <&rpmhpd RPMHPD_MMCX>, <&rpmhpd RPMHPD_MXC>; required-opps = <&rpmhpd_opp_low_svs>, <&rpmhpd_opp_low_svs>; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; }; --- bod -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 22:53 ` Bryan O'Donoghue @ 2026-03-03 23:17 ` Vijay Kumar Tumati 2026-03-03 23:26 ` Bryan O'Donoghue 0 siblings, 1 reply; 25+ messages in thread From: Vijay Kumar Tumati @ 2026-03-03 23:17 UTC (permalink / raw) To: Bryan O'Donoghue, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 3/3/2026 2:53 PM, Bryan O'Donoghue wrote: > On 03/03/2026 18:58, Vijay Kumar Tumati wrote: >>>> - TITAN_TOP_GDSC >>>> - MXC >>>> - MMCX >>>> - MXA - first time I've heard of this rail, from memory I don't >>>> remember >>>> having seen this in ipcat when I could do so. >>> MCX and MMCX are comminly required power domains across the PHYs but >>> a subset of PHYs have the dependency on MXA. >> Actually, it's a bit more complicated on this target as >> cam_cc_cphy_rx_clk_src also depends on MXA, which means all the CBCs >> connected this RCG do as well. > > Right but that's something to model in the clock-controller then not the > PHY. > > i.e. if a clock depends on MXA then the clock controller should > represent that dependency - not the PHY that depends on the clock. > > camcc on hamoa looks like this > > camcc: clock-controller@ade0000 { > compatible = "qcom,x1e80100-camcc"; > reg = <0 0x0ade0000 0 0x20000>; > clocks = <&gcc GCC_CAMERA_AHB_CLK>, > <&bi_tcxo_div2>, > <&bi_tcxo_ao_div2>, > <&sleep_clk>; > power-domains = <&rpmhpd RPMHPD_MXC>, > <&rpmhpd RPMHPD_MMCX>; > required-opps = <&rpmhpd_opp_low_svs>, > <&rpmhpd_opp_low_svs>; > #clock-cells = <1>; > #reset-cells = <1>; > #power-domain-cells = <1>; > }; > > So... we may need to add MXA here, probably do based on what you've said > but I believe TITAN_TOP_GDSC is the only power-domain we need to list > for the PHYs themselves, as what you've described above is a clock power > dependency which we basically already capture in the clock controller - > absent the MXA - which is apparently always on... > > Sidenote, is MXA required for videocc too ? > > videocc: clock-controller@aaf0000 { > compatible = "qcom,x1e80100-videocc"; > reg = <0 0x0aaf0000 0 0x10000>; > clocks = <&bi_tcxo_div2>, > <&gcc GCC_VIDEO_AHB_CLK>; > power-domains = <&rpmhpd RPMHPD_MMCX>, > <&rpmhpd RPMHPD_MXC>; > required-opps = <&rpmhpd_opp_low_svs>, > <&rpmhpd_opp_low_svs>; > #clock-cells = <1>; > #reset-cells = <1>; > #power-domain-cells = <1>; > }; > > --- > bod Well, the current upstream clock driver (at least for CAMCC) enables these power domains at the min level but they do not scale them. So even if we add MXA in the camcc device, they won't be scaled per the PHY core clocks. For example, if you are running PHY at TURBO, the power supplies may still be at the min level or scaled individually according to the requests from other sub systems. If we need this to be controlled from the clock driver directly, we will need multiple performance states for the TOP GDSC.However, this GDSC enables all the clocks in Titan, each with it's own voltage rail connections, so a bit complicated but can be discussed with the clock driver team. Sorry, I do not know about videocc. Thanks, Vijay. -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 23:17 ` Vijay Kumar Tumati @ 2026-03-03 23:26 ` Bryan O'Donoghue 2026-03-03 23:50 ` Vijay Kumar Tumati 0 siblings, 1 reply; 25+ messages in thread From: Bryan O'Donoghue @ 2026-03-03 23:26 UTC (permalink / raw) To: Vijay Kumar Tumati, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 03/03/2026 23:17, Vijay Kumar Tumati wrote: > Sorry, I do not know about videocc. I think Iris does those itself see: iris: video-codec@aa00000 { compatible = "qcom,x1e80100-iris", "qcom,sm8550-iris"; reg = <0 0x0aa00000 0 0xf0000>; interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, <&videocc VIDEO_CC_MVS0_GDSC>, <&rpmhpd RPMHPD_MXC>, <&rpmhpd RPMHPD_MMCX>; power-domain-names = "venus", "vcodec0", "mxc", "mmcx"; Still not getting an especially clear picture on what _levels_ you are proposing here for MXA - here are the three opps we have for the PHY. Sorry I don't get how turbo is coming into this .. + csiphy_opp_table: opp-table-csiphy { + 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_low_svs>; + }; + }; --- bod -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 23:26 ` Bryan O'Donoghue @ 2026-03-03 23:50 ` Vijay Kumar Tumati 2026-03-04 0:02 ` Bryan O'Donoghue 0 siblings, 1 reply; 25+ messages in thread From: Vijay Kumar Tumati @ 2026-03-03 23:50 UTC (permalink / raw) To: Bryan O'Donoghue, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 3/3/2026 3:26 PM, Bryan O'Donoghue wrote: > On 03/03/2026 23:17, Vijay Kumar Tumati wrote: >> Sorry, I do not know about videocc. > > I think Iris does those itself see: > > iris: video-codec@aa00000 { > compatible = "qcom,x1e80100-iris", > "qcom,sm8550-iris"; > > reg = <0 0x0aa00000 0 0xf0000>; > interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; > > power-domains = <&videocc VIDEO_CC_MVS0C_GDSC>, > <&videocc VIDEO_CC_MVS0_GDSC>, > <&rpmhpd RPMHPD_MXC>, > <&rpmhpd RPMHPD_MMCX>; > power-domain-names = "venus", > "vcodec0", > "mxc", > "mmcx"; > > Still not getting an especially clear picture on what _levels_ you are > proposing here for MXA - here are the three opps we have for the PHY. > > Sorry I don't get how turbo is coming into this .. Sure, I was just giving an example. I haven't looked a lot into the IPCAT / clock corners of this target particularly. Someone needs to check the clock plan, understand which PHYs require which power domains and add that in the following OPP table and as for scaling you can use the same RPMH levels for all those power domains. Btw, if you had defined the below OPP table for TOP GDSC, I think that is wrong. It only has two perf states (on and off) and doesn't need OPP scaling. If you look at the Iris driver, they link only the mxc and mmcx power domains to the OPP table using 'PD_FLAG_REQUIRED_OPP, not the GDSCs. > > + csiphy_opp_table: opp-table-csiphy { > + 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_low_svs>; > + }; > + }; > > --- > bod Thanks, Vijay. -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 23:50 ` Vijay Kumar Tumati @ 2026-03-04 0:02 ` Bryan O'Donoghue 2026-03-04 0:15 ` Vijay Kumar Tumati 0 siblings, 1 reply; 25+ messages in thread From: Bryan O'Donoghue @ 2026-03-04 0:02 UTC (permalink / raw) To: Vijay Kumar Tumati, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 03/03/2026 23:50, Vijay Kumar Tumati wrote: > Sure, I was just giving an example. I haven't looked a lot into the > IPCAT / clock corners of this target particularly. Someone needs to > check the clock plan, I mean, feel free. understand which PHYs require which power domains > and add that in the following OPP table and as for scaling you can use > the same RPMH levels for all those power domains. Btw, if you had > defined the below OPP table for TOP GDSC, I think that is wrong. It only > has two perf states (on and off) and doesn't need OPP scaling. If you > look at the Iris driver, they link only the mxc and mmcx power domains > to the OPP table using 'PD_FLAG_REQUIRED_OPP, not the GDSCs. >> >> + csiphy_opp_table: opp-table-csiphy { >> + 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_low_svs>; >> + }; >> + }; >> >> --- >> bod Yes, we should scale the MX*, that's incorrect. csiphy_mxc_opp_table: opp-table-csiphy-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-csiphy-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>; }; opp-480000000 { opp-hz = /bits/ 64 <480000000>; required-opps = <&rpmhpd_opp_low_svs>, <&rpmhpd_opp_low_svs>; }; }; csiphy0: phy@ace4000 { power-domains = <&rpmhpd RPMHPD_MXC>, <&rpmhpd RPMHPD_MMCX>; operating-points-v2 = <&csiphy_mxc_opp_table>; ... }; csiphy4: phy@acec000 { power-domains = <&rpmhpd RPMHPD_MXA>, <&rpmhpd RPMHPD_MMCX>; operating-points-v2 = <&csiphy_mxa_opp_table>; ... }; --- bod -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-04 0:02 ` Bryan O'Donoghue @ 2026-03-04 0:15 ` Vijay Kumar Tumati 0 siblings, 0 replies; 25+ messages in thread From: Vijay Kumar Tumati @ 2026-03-04 0:15 UTC (permalink / raw) To: Bryan O'Donoghue, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 3/3/2026 4:02 PM, Bryan O'Donoghue wrote: > On 03/03/2026 23:50, Vijay Kumar Tumati wrote: >> Sure, I was just giving an example. I haven't looked a lot into the >> IPCAT / clock corners of this target particularly. Someone needs to >> check the clock plan, > > I mean, feel free. > > understand which PHYs require which power domains >> and add that in the following OPP table and as for scaling you can use >> the same RPMH levels for all those power domains. Btw, if you had >> defined the below OPP table for TOP GDSC, I think that is wrong. It >> only has two perf states (on and off) and doesn't need OPP scaling. If >> you look at the Iris driver, they link only the mxc and mmcx power >> domains to the OPP table using 'PD_FLAG_REQUIRED_OPP, not the GDSCs. >>> >>> + csiphy_opp_table: opp-table-csiphy { >>> + 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_low_svs>; >>> + }; >>> + }; >>> >>> --- >>> bod > > Yes, we should scale the MX*, that's incorrect. > > csiphy_mxc_opp_table: opp-table-csiphy-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-csiphy-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>; > }; > > opp-480000000 { > opp-hz = /bits/ 64 <480000000>; > required-opps = <&rpmhpd_opp_low_svs>, > <&rpmhpd_opp_low_svs>; > }; > }; > > csiphy0: phy@ace4000 { > power-domains = <&rpmhpd RPMHPD_MXC>, > <&rpmhpd RPMHPD_MMCX>; > operating-points-v2 = <&csiphy_mxc_opp_table>; > ... > }; > > csiphy4: phy@acec000 { > power-domains = <&rpmhpd RPMHPD_MXA>, > <&rpmhpd RPMHPD_MMCX>; > operating-points-v2 = <&csiphy_mxa_opp_table>; > ... > }; > > --- > bod Yes, something like this based on this target architecture. A couple things though. You will still need to have the GDSC as a power domain and attach to it, just skip that from registering with the OPP framework . As I mentioned, if the RCG, 'cam_cc_cphy_rx_clk_src' depends on MXA (actually, I just checked for X1E80100 and it seems to require all three), the children of those (all CSIPHY clocks) indirectly depend on all three power domains. Additionally, This is the RCG for CSID and CSID Lite RX clocks as well but we can deal with those when we refactor the CSID nodes. Thanks, Vijay. -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 1:51 ` Vijay Kumar Tumati 2026-03-03 9:27 ` Bryan O'Donoghue @ 2026-03-03 9:30 ` Bryan O'Donoghue 2026-03-03 12:34 ` Konrad Dybcio 2026-03-03 18:03 ` Vijay Kumar Tumati 2026-03-03 22:31 ` Dmitry Baryshkov 2 siblings, 2 replies; 25+ messages in thread From: Bryan O'Donoghue @ 2026-03-03 9:30 UTC (permalink / raw) To: Bryan O'Donoghue, Vijay Kumar Tumati, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 03/03/2026 09:27, Bryan O'Donoghue wrote: > - MXA - first time I've heard of this rail, from memory I don't remember > having seen this in ipcat when I could do so. Yeah no MXA isn't a required vote. https://lore.kernel.org/linux-arm-msm/9ff1645f-b2c9-4c1a-ae2d-96af416b08d9@oss.qualcomm.com/ --- bod -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 9:30 ` Bryan O'Donoghue @ 2026-03-03 12:34 ` Konrad Dybcio 2026-03-03 14:56 ` Bryan O'Donoghue 2026-03-03 18:03 ` Vijay Kumar Tumati 1 sibling, 1 reply; 25+ messages in thread From: Konrad Dybcio @ 2026-03-03 12:34 UTC (permalink / raw) To: Bryan O'Donoghue, Bryan O'Donoghue, Vijay Kumar Tumati, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 3/3/26 10:30 AM, Bryan O'Donoghue wrote: > On 03/03/2026 09:27, Bryan O'Donoghue wrote: >> - MXA - first time I've heard of this rail, from memory I don't remember >> having seen this in ipcat when I could do so. > > Yeah no MXA isn't a required vote. That depends on the use case. MXA is always-on (that's the 'A' in the name, as opposed to 'C' for 'Collapsible'), but it's not always at the required performance state (svs, nom, etc.). For some clock controllers specifically, there is no need to put them into the picture, as the rail may be unconnected altogether, or only used for some retention mechanisms (which only require the rail to be enabled and nothing more) Konrad > > https://lore.kernel.org/linux-arm-msm/9ff1645f-b2c9-4c1a-ae2d-96af416b08d9@oss.qualcomm.com/ > > --- > bod > > -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 12:34 ` Konrad Dybcio @ 2026-03-03 14:56 ` Bryan O'Donoghue 2026-03-04 10:32 ` Konrad Dybcio 0 siblings, 1 reply; 25+ messages in thread From: Bryan O'Donoghue @ 2026-03-03 14:56 UTC (permalink / raw) To: Konrad Dybcio, Bryan O'Donoghue, Bryan O'Donoghue, Vijay Kumar Tumati, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 03/03/2026 12:34, Konrad Dybcio wrote: > That depends on the use case. > > MXA is always-on (that's the 'A' in the name, as opposed to 'C' > for 'Collapsible'), but it's not always at the required performance > state (svs, nom, etc.). For some clock controllers specifically, there > is no need to put them into the picture, as the rail may be unconnected > altogether, or only used for some retention mechanisms (which only > require the rail to be enabled and nothing more) Does this rail have an OPP table you can share ? --- bod -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 14:56 ` Bryan O'Donoghue @ 2026-03-04 10:32 ` Konrad Dybcio 0 siblings, 0 replies; 25+ messages in thread From: Konrad Dybcio @ 2026-03-04 10:32 UTC (permalink / raw) To: Bryan O'Donoghue, Bryan O'Donoghue, Bryan O'Donoghue, Vijay Kumar Tumati, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 3/3/26 3:56 PM, Bryan O'Donoghue wrote: > On 03/03/2026 12:34, Konrad Dybcio wrote: >> That depends on the use case. >> >> MXA is always-on (that's the 'A' in the name, as opposed to 'C' >> for 'Collapsible'), but it's not always at the required performance >> state (svs, nom, etc.). For some clock controllers specifically, there >> is no need to put them into the picture, as the rail may be unconnected >> altogether, or only used for some retention mechanisms (which only >> require the rail to be enabled and nothing more) > > Does this rail have an OPP table you can share ? Camera clocks on X1 (mclks and the fixed PLL2, which is exclusively used to derive MCLKs) that potentially depend on this rail (awaiting Taniya's opinion on the other thread [1]) would only need LOWSVS_D1 for all of their configurations (ftbl_cam_cc_mclk0_clk_src[]) i.e. let's wait for a definitive answer as there's a lot of layers.. [1] https://lore.kernel.org/linux-arm-msm/382725b5-1e72-44b2-b9ae-38aea1f7a976@oss.qualcomm.com/ Konrad -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 9:30 ` Bryan O'Donoghue 2026-03-03 12:34 ` Konrad Dybcio @ 2026-03-03 18:03 ` Vijay Kumar Tumati 1 sibling, 0 replies; 25+ messages in thread From: Vijay Kumar Tumati @ 2026-03-03 18:03 UTC (permalink / raw) To: Bryan O'Donoghue, Bryan O'Donoghue, Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 3/3/2026 1:30 AM, Bryan O'Donoghue wrote: > On 03/03/2026 09:27, Bryan O'Donoghue wrote: >> - MXA - first time I've heard of this rail, from memory I don't remember >> having seen this in ipcat when I could do so. > > Yeah no MXA isn't a required vote. > > https://lore.kernel.org/linux-arm-msm/9ff1645f-b2c9-4c1a-ae2d-96af416b08d9@oss.qualcomm.com/ If I am not wrong, CAMCC only enables the power domains that source the CAMCC block and it's register access. And for that, it only needs those power domains to be just enabled without any performance vote. Based on her comment, if MXA is always enabled (at min level), probably CAMCC driver doesn't need to enable or scale it explicitly. However, the camera devices that actually depend on this power domain for their core functionality need to scale this per the core clock corner. I can double check though. > > --- > bod > Thanks, Vijay. -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 1:51 ` Vijay Kumar Tumati 2026-03-03 9:27 ` Bryan O'Donoghue 2026-03-03 9:30 ` Bryan O'Donoghue @ 2026-03-03 22:31 ` Dmitry Baryshkov 2026-03-03 23:24 ` Vijay Kumar Tumati 2 siblings, 1 reply; 25+ messages in thread From: Dmitry Baryshkov @ 2026-03-03 22:31 UTC (permalink / raw) To: Vijay Kumar Tumati Cc: Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On Mon, Mar 02, 2026 at 05:51:24PM -0800, Vijay Kumar Tumati wrote: > Hi Bryan, > > On 2/26/2026 4:34 AM, Bryan O'Donoghue wrote: > > + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; > As we are cleaning up the PHY device nodes, we should consider fixing the > power domains as well. Although TOP GDSC is defined as a power domain, it is > not the power source for the PHY devices. Rather, it is the MMCX, MXC and > optionally MXA based on the architecture (Refer to 'Voltage rail' column for > PHY clocks in IPCAT). There is no > parent-child relationship between the TOP GDSC and these in the clock driver > and it was just working as the required power rails are getting enabled > by/for other MM devices. Which domains are required to access CSI PHY registers? > > + > > + vdda-0p8-supply = <&vreg_l2c_0p8>; > > + vdda-1p2-supply = <&vreg_l1c_1p2>; > > + }; > > + -- With best wishes Dmitry -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 22:31 ` Dmitry Baryshkov @ 2026-03-03 23:24 ` Vijay Kumar Tumati 2026-03-03 23:49 ` Dmitry Baryshkov 0 siblings, 1 reply; 25+ messages in thread From: Vijay Kumar Tumati @ 2026-03-03 23:24 UTC (permalink / raw) To: Dmitry Baryshkov Cc: Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 3/3/2026 2:31 PM, Dmitry Baryshkov wrote: > On Mon, Mar 02, 2026 at 05:51:24PM -0800, Vijay Kumar Tumati wrote: >> Hi Bryan, >> >> On 2/26/2026 4:34 AM, Bryan O'Donoghue wrote: >>> + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; >> As we are cleaning up the PHY device nodes, we should consider fixing the >> power domains as well. Although TOP GDSC is defined as a power domain, it is >> not the power source for the PHY devices. Rather, it is the MMCX, MXC and >> optionally MXA based on the architecture (Refer to 'Voltage rail' column for >> PHY clocks in IPCAT). There is no >> parent-child relationship between the TOP GDSC and these in the clock driver >> and it was just working as the required power rails are getting enabled >> by/for other MM devices. > > Which domains are required to access CSI PHY registers? PHY register access requires the PHY core clock, cam_top_ahb clock. So in my understanding, we need to trace these clocks in the topology backwards up until at least the RCG, and all the voltage rails powering these clocks will be the required power domains. Having said that, just register access works even if the voltage rails are configured to the min level, which camcc does already. > >>> + >>> + vdda-0p8-supply = <&vreg_l2c_0p8>; >>> + vdda-1p2-supply = <&vreg_l1c_1p2>; >>> + }; >>> + > Thanks, Vijay. -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 23:24 ` Vijay Kumar Tumati @ 2026-03-03 23:49 ` Dmitry Baryshkov 2026-03-03 23:51 ` Vijay Kumar Tumati 0 siblings, 1 reply; 25+ messages in thread From: Dmitry Baryshkov @ 2026-03-03 23:49 UTC (permalink / raw) To: Vijay Kumar Tumati Cc: Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On Tue, Mar 03, 2026 at 03:24:16PM -0800, Vijay Kumar Tumati wrote: > > > On 3/3/2026 2:31 PM, Dmitry Baryshkov wrote: > > On Mon, Mar 02, 2026 at 05:51:24PM -0800, Vijay Kumar Tumati wrote: > > > Hi Bryan, > > > > > > On 2/26/2026 4:34 AM, Bryan O'Donoghue wrote: > > > > + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; > > > As we are cleaning up the PHY device nodes, we should consider fixing the > > > power domains as well. Although TOP GDSC is defined as a power domain, it is > > > not the power source for the PHY devices. Rather, it is the MMCX, MXC and > > > optionally MXA based on the architecture (Refer to 'Voltage rail' column for > > > PHY clocks in IPCAT). There is no > > > parent-child relationship between the TOP GDSC and these in the clock driver > > > and it was just working as the required power rails are getting enabled > > > by/for other MM devices. > > > > Which domains are required to access CSI PHY registers? > PHY register access requires the PHY core clock, cam_top_ahb clock. So in my > understanding, we need to trace these clocks in the topology backwards up > until at least the RCG, and all the voltage rails powering these clocks will > be the required power domains. Having said that, just register access works > even if the voltage rails are configured to the min level, which camcc does > already. Are they not gated by the GDSC? > > > > > > + > > > > + vdda-0p8-supply = <&vreg_l2c_0p8>; > > > > + vdda-1p2-supply = <&vreg_l1c_1p2>; > > > > + }; > > > > + > > > Thanks, > Vijay. -- With best wishes Dmitry -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema 2026-03-03 23:49 ` Dmitry Baryshkov @ 2026-03-03 23:51 ` Vijay Kumar Tumati 0 siblings, 0 replies; 25+ messages in thread From: Vijay Kumar Tumati @ 2026-03-03 23:51 UTC (permalink / raw) To: Dmitry Baryshkov Cc: Bryan O'Donoghue, Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On 3/3/2026 3:49 PM, Dmitry Baryshkov wrote: > On Tue, Mar 03, 2026 at 03:24:16PM -0800, Vijay Kumar Tumati wrote: >> >> >> On 3/3/2026 2:31 PM, Dmitry Baryshkov wrote: >>> On Mon, Mar 02, 2026 at 05:51:24PM -0800, Vijay Kumar Tumati wrote: >>>> Hi Bryan, >>>> >>>> On 2/26/2026 4:34 AM, Bryan O'Donoghue wrote: >>>>> + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; >>>> As we are cleaning up the PHY device nodes, we should consider fixing the >>>> power domains as well. Although TOP GDSC is defined as a power domain, it is >>>> not the power source for the PHY devices. Rather, it is the MMCX, MXC and >>>> optionally MXA based on the architecture (Refer to 'Voltage rail' column for >>>> PHY clocks in IPCAT). There is no >>>> parent-child relationship between the TOP GDSC and these in the clock driver >>>> and it was just working as the required power rails are getting enabled >>>> by/for other MM devices. >>> >>> Which domains are required to access CSI PHY registers? >> PHY register access requires the PHY core clock, cam_top_ahb clock. So in my >> understanding, we need to trace these clocks in the topology backwards up >> until at least the RCG, and all the voltage rails powering these clocks will >> be the required power domains. Having said that, just register access works >> even if the voltage rails are configured to the min level, which camcc does >> already. > > Are they not gated by the GDSC? All the Titan CAMCC clocks are gated by the TOP GDSC, yes. > >>> >>>>> + >>>>> + vdda-0p8-supply = <&vreg_l2c_0p8>; >>>>> + vdda-1p2-supply = <&vreg_l1c_1p2>; >>>>> + }; >>>>> + >>> >> Thanks, >> Vijay. > Thanks, Vijay. -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v3 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver 2026-02-26 12:34 [PATCH v3 0/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver Bryan O'Donoghue 2026-02-26 12:34 ` [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema Bryan O'Donoghue @ 2026-02-26 12:34 ` Bryan O'Donoghue 2026-02-27 1:40 ` Dmitry Baryshkov 1 sibling, 1 reply; 25+ messages in thread From: Bryan O'Donoghue @ 2026-02-26 12:34 UTC (permalink / raw) To: Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong Cc: Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel, Bryan O'Donoghue 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. At the moment we follow the assignment of lane positions - the bitmap of physical input lanes to logical lane numbers as a linear list per the existing DPHY @lanes data-member. This is fine for us in upstream at the moment since we also map the lanes contiguously but, our hardware can support different lane mappings so we should in the future extend out the DPHY structure to capture the mapping. 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. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> --- MAINTAINERS | 11 + drivers/phy/qualcomm/Kconfig | 13 + drivers/phy/qualcomm/Makefile | 5 + drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 384 +++++++++++++++++++++ drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c | 307 ++++++++++++++++ drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 102 ++++++ 6 files changed, 822 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/ +QUALCOMM MIPI CSI2 PHY DRIVER +M: Bryan O'Donoghue <bod@kernel.org> +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 <mani@kernel.org> 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. +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) += phy-qcom-ipq4019-usb.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o obj-$(CONFIG_PHY_QCOM_M31_EUSB) += phy-qcom-m31-eusb2.o + +phy-qcom-mipi-csi2-objs += phy-qcom-mipi-csi2-core.o \ + phy-qcom-mipi-csi2-3ph-dphy.o +obj-$(CONFIG_PHY_QCOM_MIPI_CSI2) += phy-qcom-mipi-csi2.o + obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c new file mode 100644 index 0000000000000..f9f3451e9a5e1 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-phy_qcom_mipi_csi2-3ph-1-0.c + * + * 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 <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/time64.h> + +#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 + 0x4 * (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_LANE_ENABLE 1 +#define CSIPHY_SETTLE_CNT_LOWER_BYTE 2 +#define CSIPHY_SETTLE_CNT_HIGHER_BYTE 3 +#define CSIPHY_DNP_PARAMS 4 +#define CSIPHY_2PH_REGS 5 +#define CSIPHY_3PH_REGS 6 +#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[] = { + /* Power up lanes 2ph mode */ + {.reg_addr = 0x1014, .reg_data = 0xD5, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x101C, .reg_data = 0x7A, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x1018, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + + {.reg_addr = 0x0094, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x00A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0090, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0098, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0094, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0030, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0000, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0038, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x002C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0034, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x001C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0014, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x003C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0004, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0020, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0008, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0010, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0094, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x005C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0060, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0064, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0E94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0EA0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E28, .reg_data = 0x04, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E00, .reg_data = 0x80, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E0C, .reg_data = 0xFF, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E38, .reg_data = 0x1F, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E2C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E34, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E1C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E3C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E04, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0E08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0E10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + + {.reg_addr = 0x0494, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x04A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0490, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0498, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0494, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0430, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0400, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0438, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x042C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0434, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x041C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0414, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x043C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0404, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0420, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0408, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0410, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0494, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x045C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0460, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0464, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0894, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x08A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0890, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0898, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0894, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0830, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0800, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0838, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x082C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0834, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x081C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0814, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x083C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0804, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0820, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0808, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0810, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0894, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x085C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0860, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0864, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0C94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0CA0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C00, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C38, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C2C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C34, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C1C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C3C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C04, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0C10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0C94, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0C5C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0C60, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0C64, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, +}; + +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 = csi2phy_dev_to_regs(csi2phy); + 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 = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 12)); + csi2phy->hw_version = tmp; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 13)); + csi2phy->hw_version |= (tmp << 8) & 0xFF00; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 14)); + csi2phy->hw_version |= (tmp << 16) & 0xFF0000; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 15)); + csi2phy->hw_version |= (tmp << 24) & 0xFF000000; + + dev_dbg_once(csi2phy->dev, "CSIPHY 3PH HW Version = 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 = csi2phy_dev_to_regs(csi2phy); + + 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 <= 0) + return 0; + + ui_ps = div_u64(PSEC_PER_SEC, link_freq); + ui_ps /= 2; + t_hs_prepare_max_ps = 85000 + 6 * ui_ps; + t_hs_settle_ps = t_hs_prepare_max_ps; + + timer_period_ps = div_u64(PSEC_PER_SEC, timer_clk_rate); + settle_cnt = 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 = csi2phy_dev_to_regs(csi2phy); + const struct mipi_csi2phy_lane_regs *r = regs->init_seq; + int i, array_size = regs->lane_array_size; + u32 val; + + for (i = 0; i < array_size; i++, r++) { + switch (r->param_type) { + case CSIPHY_SETTLE_CNT_LOWER_BYTE: + val = settle_cnt & 0xff; + break; + case CSIPHY_SKEW_CAL: + /* TODO: support application of skew from dt flag */ + continue; + default: + val = 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 *csi2phy, + struct mipi_csi2phy_stream_cfg *cfg) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + struct mipi_csi2phy_lanes_cfg *lane_cfg = &cfg->lane_cfg; + u8 settle_cnt; + u8 val; + int i; + + settle_cnt = phy_qcom_mipi_csi2_settle_cnt_calc(cfg->link_freq, csi2phy->timer_clk_rate); + + val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; + for (i = 0; i < cfg->num_data_lanes; i++) + val |= BIT(lane_cfg->data[i].pos * 2); + + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); + + val = 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 = 0x02; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 7)); + + val = 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 = 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 = csi2phy_dev_to_regs(csi2phy); + + 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 = { + .hw_version_read = phy_qcom_mipi_csi2_hw_version_read, + .reset = phy_qcom_mipi_csi2_reset, + .lanes_enable = phy_qcom_mipi_csi2_lanes_enable, + .lanes_disable = phy_qcom_mipi_csi2_lanes_disable, +}; + +static const struct mipi_csi2phy_clk_freq zero = { 0 }; + +static const struct mipi_csi2phy_clk_freq dphy_4nm_x1e_csiphy = { + .freq = { + 300000000, 400000000, 480000000 + }, + .num_freq = 3, +}; + +static const struct mipi_csi2phy_clk_freq dphy_4nm_x1e_csiphy_timer = { + .freq = { + 266666667, 400000000 + }, + .num_freq = 2, +}; + +static const char * const x1e_clks[] = { + "camnoc_axi", + "cpas_ahb", + "csiphy", + "csiphy_timer" +}; + +const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e = { + .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, + .generation = GEN2, + }, + .supply_names = (const char *[]){ + "vdda-0p8", + "vdda-1p2" + }, + .num_supplies = 2, + .clk_names = (const char **)x1e_clks, + .num_clk = ARRAY_SIZE(x1e_clks), + .opp_clk = x1e_clks[2], + .timer_clk = x1e_clks[3], + .clk_freq = { + zero, + zero, + dphy_4nm_x1e_csiphy, + dphy_4nm_x1e_csiphy_timer, + }, +}; diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c new file mode 100644 index 0000000000000..454144f81b719 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025, Linaro Ltd. + */ +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/pm_opp.h> +#include <linux/phy/phy.h> +#include <linux/phy/phy-mipi-dphy.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/reset.h> +#include <linux/slab.h> + +#include "phy-qcom-mipi-csi2.h" + +#define CAMSS_CLOCK_MARGIN_NUMERATOR 105 +#define CAMSS_CLOCK_MARGIN_DENOMINATOR 100 + +static inline void phy_qcom_mipi_csi2_add_clock_margin(u64 *rate) +{ + *rate *= CAMSS_CLOCK_MARGIN_NUMERATOR; + *rate = div_u64(*rate, CAMSS_CLOCK_MARGIN_DENOMINATOR); +} + +static int +phy_qcom_mipi_csi2_set_clock_rates(struct mipi_csi2phy_device *csi2phy, + s64 link_freq) +{ + const struct mipi_csi2phy_soc_cfg *soc_cfg = csi2phy->soc_cfg; + unsigned long rates[MAX_CSI2PHY_CLKS] = {0}; + struct device *dev = csi2phy->dev; + unsigned long vote_freq = 0; + int i, j; + int ret; + + for (i = 0; i < soc_cfg->num_clk; i++) { + const struct mipi_csi2phy_clk_freq *clk_freq = &soc_cfg->clk_freq[i]; + const char *clk_name = soc_cfg->clk_names[i]; + struct clk *clk = csi2phy->clks[i].clk; + u64 min_rate = link_freq / 4; + long round_rate; + + phy_qcom_mipi_csi2_add_clock_margin(&min_rate); + + /* This clock should be enabled only not set */ + if (!clk_freq->num_freq) + continue; + + for (j = 0; j < clk_freq->num_freq; j++) + if (min_rate < clk_freq->freq[j]) + break; + + if (j == clk_freq->num_freq) { + dev_err(dev, + "Pixel clock %llu is too high for %s\n", + min_rate, clk_name); + return -EINVAL; + } + + /* if sensor pixel clock is not available + * set highest possible CSIPHY clock rate + */ + if (min_rate == 0) + j = clk_freq->num_freq - 1; + + round_rate = clk_round_rate(clk, clk_freq->freq[j]); + if (round_rate < 0) { + dev_err(dev, "clk round rate failed: %ld\n", + round_rate); + return -EINVAL; + } + + rates[i] = round_rate; + + if (!strcmp(clk_name, soc_cfg->timer_clk)) + csi2phy->timer_clk_rate = round_rate; + + if (!strcmp(clk_name, soc_cfg->opp_clk)) + vote_freq = round_rate; + } + + if (!vote_freq) { + dev_err(dev, "Unable to find operating point frequency\n"); + return -ENODEV; + }; + + dev_dbg(dev, "OPP freq: %lu Hz\n", vote_freq); + + ret = dev_pm_opp_set_rate(dev, vote_freq); + if (ret < 0) { + dev_err(dev, "Failed to set OPP rate: %d\n", ret); + return ret; + } + + for (i = 0; i < soc_cfg->num_clk; i++) { + if (rates[i] == 0) + continue; + + dev_dbg(dev, "Setting clk %s to %lu Hz\n", + soc_cfg->clk_names[i], rates[i]); + + ret = clk_set_rate(csi2phy->clks[i].clk, rates[i]); + if (ret < 0) { + dev_err(dev, "clk_set_rate failed for %s: %d\n", + soc_cfg->clk_names[i], ret); + return ret; + } + } + + return 0; +} + +static int phy_qcom_mipi_csi2_configure(struct phy *phy, + union phy_configure_opts *opts) +{ + struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); + struct phy_configure_opts_mipi_dphy *dphy_cfg_opts = &opts->mipi_dphy; + struct mipi_csi2phy_stream_cfg *stream_cfg = &csi2phy->stream_cfg; + int ret; + int i; + + ret = phy_mipi_dphy_config_validate(dphy_cfg_opts); + if (ret) + return ret; + + if (dphy_cfg_opts->lanes < 1 || dphy_cfg_opts->lanes > CSI2_MAX_DATA_LANES) + return -EINVAL; + + stream_cfg->combo_mode = 0; + stream_cfg->link_freq = dphy_cfg_opts->hs_clk_rate; + stream_cfg->num_data_lanes = dphy_cfg_opts->lanes; + + /* + * phy_configure_opts_mipi_dphy.lanes starts from zero to + * the maximum number of enabled lanes. + * + * TODO: add support for bitmask of enabled lanes and polarities + * of those lanes to the phy_configure_opts_mipi_dphy struct. + * For now take the polarities as zero and the position as fixed + * this is fine as no current upstream implementation maps otherwise. + */ + for (i = 0; i < stream_cfg->num_data_lanes; i++) { + stream_cfg->lane_cfg.data[i].pol = 0; + stream_cfg->lane_cfg.data[i].pos = i; + } + + stream_cfg->lane_cfg.clk.pol = 0; + stream_cfg->lane_cfg.clk.pos = 7; + + return 0; +} + +static int phy_qcom_mipi_csi2_power_on(struct phy *phy) +{ + struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); + const struct mipi_csi2phy_hw_ops *ops = csi2phy->soc_cfg->ops; + struct device *dev = &phy->dev; + int ret; + + ret = regulator_bulk_enable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + if (ret) + return ret; + + ret = phy_qcom_mipi_csi2_set_clock_rates(csi2phy, csi2phy->stream_cfg.link_freq); + if (ret) + goto poweroff_phy; + + ret = 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 = phy_get_drvdata(phy); + + 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 = { + .configure = phy_qcom_mipi_csi2_configure, + .power_on = phy_qcom_mipi_csi2_power_on, + .power_off = phy_qcom_mipi_csi2_power_off, + .owner = THIS_MODULE, +}; + +static int phy_qcom_mipi_csi2_probe(struct platform_device *pdev) +{ + unsigned int i, num_clk, num_supplies; + struct mipi_csi2phy_device *csi2phy; + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + struct phy *generic_phy; + int ret; + + csi2phy = devm_kzalloc(dev, sizeof(*csi2phy), GFP_KERNEL); + if (!csi2phy) + return -ENOMEM; + + csi2phy->dev = dev; + csi2phy->soc_cfg = device_get_match_data(&pdev->dev); + + if (!csi2phy->soc_cfg) + return -EINVAL; + + num_clk = csi2phy->soc_cfg->num_clk; + csi2phy->clks = devm_kzalloc(dev, sizeof(*csi2phy->clks) * num_clk, GFP_KERNEL); + if (!csi2phy->clks) + return -ENOMEM; + + for (i = 0; i < num_clk; i++) + csi2phy->clks[i].id = csi2phy->soc_cfg->clk_names[i]; + + ret = devm_clk_bulk_get(dev, num_clk, csi2phy->clks); + if (ret) + return dev_err_probe(dev, ret, "Failed to get clocks\n"); + + ret = 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 = devm_pm_opp_of_add_table(dev); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "invalid OPP table in device tree\n"); + + num_supplies = csi2phy->soc_cfg->num_supplies; + csi2phy->supplies = devm_kzalloc(dev, sizeof(*csi2phy->supplies) * num_supplies, + GFP_KERNEL); + if (!csi2phy->supplies) + return -ENOMEM; + + for (i = 0; i < num_supplies; i++) + csi2phy->supplies[i].supply = csi2phy->soc_cfg->supply_names[i]; + + ret = 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 = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(csi2phy->base)) + return PTR_ERR(csi2phy->base); + + generic_phy = devm_phy_create(dev, NULL, &phy_qcom_mipi_csi2_ops); + if (IS_ERR(generic_phy)) { + ret = PTR_ERR(generic_phy); + return dev_err_probe(dev, ret, "failed to create phy\n"); + } + csi2phy->phy = generic_phy; + + phy_set_drvdata(generic_phy, csi2phy); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_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[] = { + { .compatible = "qcom,x1e80100-csi2-phy", .data = &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 = { + .probe = phy_qcom_mipi_csi2_probe, + .driver = { + .name = "qcom-mipi-csi2-phy", + .of_match_table = 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 <bryan.odonoghue@linaro.org>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h new file mode 100644 index 0000000000000..4f3a245ba6a53 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h @@ -0,0 +1,102 @@ +/* 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 <linux/phy/phy.h> + +#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 { + u8 combo_mode; + 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; + enum { + GEN1 = 0, + GEN1_660, + GEN1_670, + GEN2, + } generation; +}; + +#define MAX_CSI2PHY_CLKS 8 +struct mipi_csi2phy_clk_freq { + u32 num_freq; + u32 freq[MAX_CSI2PHY_CLKS]; +}; + +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 struct mipi_csi2phy_clk_freq clk_freq[]; +}; + +struct mipi_csi2phy_device { + struct device *dev; + + struct phy *phy; + void __iomem *base; + + struct clk_bulk_data *clks; + struct regulator_bulk_data *supplies; + u32 timer_clk_rate; + + 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__ */ -- 2.52.0 -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH v3 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver 2026-02-26 12:34 ` [PATCH v3 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver Bryan O'Donoghue @ 2026-02-27 1:40 ` Dmitry Baryshkov 0 siblings, 0 replies; 25+ messages in thread From: Dmitry Baryshkov @ 2026-02-27 1:40 UTC (permalink / raw) To: Bryan O'Donoghue Cc: Vinod Koul, Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel On Thu, Feb 26, 2026 at 12:34:26PM +0000, Bryan O'Donoghue wrote: > 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. At > the moment we follow the assignment of lane positions - the bitmap of > physical input lanes to logical lane numbers as a linear list per the > existing DPHY @lanes data-member. > > This is fine for us in upstream at the moment since we also map the lanes > contiguously but, our hardware can support different lane mappings so we > should in the future extend out the DPHY structure to capture the mapping. > > 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. > > Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> > --- > MAINTAINERS | 11 + > drivers/phy/qualcomm/Kconfig | 13 + > drivers/phy/qualcomm/Makefile | 5 + > drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 384 +++++++++++++++++++++ > drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c | 307 ++++++++++++++++ > drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 102 ++++++ > 6 files changed, 822 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/ > > +QUALCOMM MIPI CSI2 PHY DRIVER > +M: Bryan O'Donoghue <bod@kernel.org> > +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 <mani@kernel.org> > 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. > > +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) += phy-qcom-ipq4019-usb.o > obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o > obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o > obj-$(CONFIG_PHY_QCOM_M31_EUSB) += phy-qcom-m31-eusb2.o > + > +phy-qcom-mipi-csi2-objs += phy-qcom-mipi-csi2-core.o \ > + phy-qcom-mipi-csi2-3ph-dphy.o > +obj-$(CONFIG_PHY_QCOM_MIPI_CSI2) += phy-qcom-mipi-csi2.o > + > obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o > > obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o > diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c > new file mode 100644 > index 0000000000000..f9f3451e9a5e1 > --- /dev/null > +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c > @@ -0,0 +1,384 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * camss-phy_qcom_mipi_csi2-3ph-1-0.c And it doesn't match the driver anymore. Please drop it. > + * > + * 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 <linux/delay.h> > +#include <linux/interrupt.h> > +#include <linux/io.h> > +#include <linux/time64.h> > + > +#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 + 0x4 * (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_LANE_ENABLE 1 Unused > +#define CSIPHY_SETTLE_CNT_LOWER_BYTE 2 > +#define CSIPHY_SETTLE_CNT_HIGHER_BYTE 3 Unused > +#define CSIPHY_DNP_PARAMS 4 > +#define CSIPHY_2PH_REGS 5 > +#define CSIPHY_3PH_REGS 6 Both are unused > +#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[] = { > + /* Power up lanes 2ph mode */ > + {.reg_addr = 0x1014, .reg_data = 0xD5, .param_type = CSIPHY_DEFAULT_PARAMS}, As you are moving the driver, it might also make sense to split / rework the huge table with the code sequence. The code is easier to adapt. As you can see in the tables, there are repetitive code patterns, which correspond to the lane programming. Once that is extracted, it would be much, much easier to manipulate the data. It's fine if you are just moving the data with the intention of improving it later, but then please state so in the commit message. Also, please use low-case hex, I think it was a recommended practice nowadays. > + {.reg_addr = 0x101C, .reg_data = 0x7A, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x1018, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, > + > + {.reg_addr = 0x0094, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x00A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0090, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0098, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0094, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0030, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0000, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0038, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x002C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0034, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x001C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0014, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x003C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0004, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0020, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0008, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, > + {.reg_addr = 0x0010, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0094, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x005C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x0060, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x0064, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, > + > + {.reg_addr = 0x0E94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0EA0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E28, .reg_data = 0x04, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E00, .reg_data = 0x80, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E0C, .reg_data = 0xFF, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E38, .reg_data = 0x1F, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E2C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E34, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E1C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E3C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E04, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0E08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, > + {.reg_addr = 0x0E10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, > + > + {.reg_addr = 0x0494, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x04A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0490, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0498, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0494, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0430, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0400, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0438, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x042C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0434, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x041C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0414, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x043C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0404, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0420, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0408, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, > + {.reg_addr = 0x0410, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0494, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x045C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x0460, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x0464, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, > + > + {.reg_addr = 0x0894, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x08A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0890, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0898, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0894, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0830, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0800, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0838, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x082C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0834, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x081C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0814, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x083C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0804, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0820, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0808, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, > + {.reg_addr = 0x0810, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0894, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x085C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x0860, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x0864, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, > + > + {.reg_addr = 0x0C94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0CA0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C00, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C38, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C2C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C34, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C1C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C3C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C04, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, > + {.reg_addr = 0x0C10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, > + {.reg_addr = 0x0C94, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x0C5C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x0C60, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, > + {.reg_addr = 0x0C64, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, > +}; > + > +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 = csi2phy_dev_to_regs(csi2phy); > + 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 = readl_relaxed(csi2phy->base + > + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 12)); > + csi2phy->hw_version = tmp; > + > + tmp = readl_relaxed(csi2phy->base + > + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 13)); > + csi2phy->hw_version |= (tmp << 8) & 0xFF00; > + > + tmp = readl_relaxed(csi2phy->base + > + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 14)); > + csi2phy->hw_version |= (tmp << 16) & 0xFF0000; > + > + tmp = readl_relaxed(csi2phy->base + > + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 15)); > + csi2phy->hw_version |= (tmp << 24) & 0xFF000000; > + > + dev_dbg_once(csi2phy->dev, "CSIPHY 3PH HW Version = 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 = csi2phy_dev_to_regs(csi2phy); > + > + 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 <= 0) > + return 0; > + > + ui_ps = div_u64(PSEC_PER_SEC, link_freq); > + ui_ps /= 2; > + t_hs_prepare_max_ps = 85000 + 6 * ui_ps; > + t_hs_settle_ps = t_hs_prepare_max_ps; > + > + timer_period_ps = div_u64(PSEC_PER_SEC, timer_clk_rate); > + settle_cnt = 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 = csi2phy_dev_to_regs(csi2phy); > + const struct mipi_csi2phy_lane_regs *r = regs->init_seq; > + int i, array_size = regs->lane_array_size; > + u32 val; > + > + for (i = 0; i < array_size; i++, r++) { > + switch (r->param_type) { > + case CSIPHY_SETTLE_CNT_LOWER_BYTE: > + val = settle_cnt & 0xff; > + break; > + case CSIPHY_SKEW_CAL: > + /* TODO: support application of skew from dt flag */ > + continue; > + default: > + val = 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 *csi2phy, > + struct mipi_csi2phy_stream_cfg *cfg) > +{ > + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); > + struct mipi_csi2phy_lanes_cfg *lane_cfg = &cfg->lane_cfg; > + u8 settle_cnt; > + u8 val; > + int i; > + > + settle_cnt = phy_qcom_mipi_csi2_settle_cnt_calc(cfg->link_freq, csi2phy->timer_clk_rate); > + > + val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; > + for (i = 0; i < cfg->num_data_lanes; i++) > + val |= BIT(lane_cfg->data[i].pos * 2); > + > + writel(val, csi2phy->base + > + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); > + > + val = 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 = 0x02; > + writel(val, csi2phy->base + > + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 7)); > + > + val = 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 = 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 = csi2phy_dev_to_regs(csi2phy); > + > + 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 = { > + .hw_version_read = phy_qcom_mipi_csi2_hw_version_read, > + .reset = phy_qcom_mipi_csi2_reset, > + .lanes_enable = phy_qcom_mipi_csi2_lanes_enable, > + .lanes_disable = phy_qcom_mipi_csi2_lanes_disable, > +}; > + > +static const struct mipi_csi2phy_clk_freq zero = { 0 }; > + > +static const struct mipi_csi2phy_clk_freq dphy_4nm_x1e_csiphy = { > + .freq = { > + 300000000, 400000000, 480000000 > + }, > + .num_freq = 3, > +}; > + > +static const struct mipi_csi2phy_clk_freq dphy_4nm_x1e_csiphy_timer = { > + .freq = { > + 266666667, 400000000 > + }, > + .num_freq = 2, As you are migrating to a modern codebase, these values should be set via the OPP tables instead. > +}; > + > +static const char * const x1e_clks[] = { > + "camnoc_axi", > + "cpas_ahb", > + "csiphy", > + "csiphy_timer" > +}; > + > +const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e = { > + .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, > + .generation = GEN2, Does this generation match anything in the actual hardware? > + }, > + .supply_names = (const char *[]){ > + "vdda-0p8", > + "vdda-1p2" > + }, > + .num_supplies = 2, > + .clk_names = (const char **)x1e_clks, > + .num_clk = ARRAY_SIZE(x1e_clks), > + .opp_clk = x1e_clks[2], > + .timer_clk = x1e_clks[3], > + .clk_freq = { > + zero, > + zero, > + dphy_4nm_x1e_csiphy, > + dphy_4nm_x1e_csiphy_timer, > + }, > +}; > diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c > new file mode 100644 > index 0000000000000..454144f81b719 > --- /dev/null > +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c > @@ -0,0 +1,307 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2025, Linaro Ltd. > + */ > +#include <linux/clk.h> > +#include <linux/delay.h> > +#include <linux/err.h> > +#include <linux/io.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/of.h> > +#include <linux/pm_opp.h> > +#include <linux/phy/phy.h> > +#include <linux/phy/phy-mipi-dphy.h> > +#include <linux/platform_device.h> > +#include <linux/pm_runtime.h> > +#include <linux/regmap.h> > +#include <linux/regulator/consumer.h> > +#include <linux/reset.h> > +#include <linux/slab.h> > + > +#include "phy-qcom-mipi-csi2.h" > + > +#define CAMSS_CLOCK_MARGIN_NUMERATOR 105 > +#define CAMSS_CLOCK_MARGIN_DENOMINATOR 100 > + > +static inline void phy_qcom_mipi_csi2_add_clock_margin(u64 *rate) > +{ > + *rate *= CAMSS_CLOCK_MARGIN_NUMERATOR; > + *rate = div_u64(*rate, CAMSS_CLOCK_MARGIN_DENOMINATOR); > +} > + > +static int > +phy_qcom_mipi_csi2_set_clock_rates(struct mipi_csi2phy_device *csi2phy, > + s64 link_freq) > +{ > + const struct mipi_csi2phy_soc_cfg *soc_cfg = csi2phy->soc_cfg; > + unsigned long rates[MAX_CSI2PHY_CLKS] = {0}; > + struct device *dev = csi2phy->dev; > + unsigned long vote_freq = 0; > + int i, j; > + int ret; > + > + for (i = 0; i < soc_cfg->num_clk; i++) { > + const struct mipi_csi2phy_clk_freq *clk_freq = &soc_cfg->clk_freq[i]; > + const char *clk_name = soc_cfg->clk_names[i]; > + struct clk *clk = csi2phy->clks[i].clk; > + u64 min_rate = link_freq / 4; > + long round_rate; > + > + phy_qcom_mipi_csi2_add_clock_margin(&min_rate); > + > + /* This clock should be enabled only not set */ > + if (!clk_freq->num_freq) > + continue; > + > + for (j = 0; j < clk_freq->num_freq; j++) > + if (min_rate < clk_freq->freq[j]) > + break; > + > + if (j == clk_freq->num_freq) { > + dev_err(dev, > + "Pixel clock %llu is too high for %s\n", > + min_rate, clk_name); > + return -EINVAL; > + } > + > + /* if sensor pixel clock is not available > + * set highest possible CSIPHY clock rate > + */ > + if (min_rate == 0) > + j = clk_freq->num_freq - 1; > + > + round_rate = clk_round_rate(clk, clk_freq->freq[j]); > + if (round_rate < 0) { > + dev_err(dev, "clk round rate failed: %ld\n", > + round_rate); > + return -EINVAL; > + } All of this code looks like a poor man's implementation of the OPP handling, finding the highest possible clock rate, etc. > + > + rates[i] = round_rate; > + > + if (!strcmp(clk_name, soc_cfg->timer_clk)) > + csi2phy->timer_clk_rate = round_rate; > + > + if (!strcmp(clk_name, soc_cfg->opp_clk)) > + vote_freq = round_rate; > + } > + > + if (!vote_freq) { > + dev_err(dev, "Unable to find operating point frequency\n"); > + return -ENODEV; > + }; > + > + dev_dbg(dev, "OPP freq: %lu Hz\n", vote_freq); > + > + ret = dev_pm_opp_set_rate(dev, vote_freq); > + if (ret < 0) { > + dev_err(dev, "Failed to set OPP rate: %d\n", ret); > + return ret; > + } > + > + for (i = 0; i < soc_cfg->num_clk; i++) { > + if (rates[i] == 0) > + continue; > + > + dev_dbg(dev, "Setting clk %s to %lu Hz\n", > + soc_cfg->clk_names[i], rates[i]); > + > + ret = clk_set_rate(csi2phy->clks[i].clk, rates[i]); > + if (ret < 0) { > + dev_err(dev, "clk_set_rate failed for %s: %d\n", > + soc_cfg->clk_names[i], ret); > + return ret; > + } > + } > + > + return 0; > +} > + -- With best wishes Dmitry -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2026-03-04 10:32 UTC | newest] Thread overview: 25+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-02-26 12:34 [PATCH v3 0/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver Bryan O'Donoghue 2026-02-26 12:34 ` [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema Bryan O'Donoghue 2026-02-27 9:41 ` Krzysztof Kozlowski 2026-02-27 9:47 ` Bryan O'Donoghue 2026-03-03 1:51 ` Vijay Kumar Tumati 2026-03-03 9:27 ` Bryan O'Donoghue 2026-03-03 18:08 ` Vijay Kumar Tumati 2026-03-03 18:58 ` Vijay Kumar Tumati 2026-03-03 22:53 ` Bryan O'Donoghue 2026-03-03 23:17 ` Vijay Kumar Tumati 2026-03-03 23:26 ` Bryan O'Donoghue 2026-03-03 23:50 ` Vijay Kumar Tumati 2026-03-04 0:02 ` Bryan O'Donoghue 2026-03-04 0:15 ` Vijay Kumar Tumati 2026-03-03 9:30 ` Bryan O'Donoghue 2026-03-03 12:34 ` Konrad Dybcio 2026-03-03 14:56 ` Bryan O'Donoghue 2026-03-04 10:32 ` Konrad Dybcio 2026-03-03 18:03 ` Vijay Kumar Tumati 2026-03-03 22:31 ` Dmitry Baryshkov 2026-03-03 23:24 ` Vijay Kumar Tumati 2026-03-03 23:49 ` Dmitry Baryshkov 2026-03-03 23:51 ` Vijay Kumar Tumati 2026-02-26 12:34 ` [PATCH v3 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver Bryan O'Donoghue 2026-02-27 1:40 ` Dmitry Baryshkov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox