forked from Minki/linux
phy-for-6.1
- New support: - Bjorn Andersson provided Qualcomm SC8280XP eDP & DP and USB3 UNI phy support - Chris Morgan added Rockchip rk3568 inno dsidphy support - Colin Foster converted ocelot-serdes phy binding to yaml - Geert Uytterhoeven converted Renesas gen2-usb phy binding to yaml - Horatiu Vultur added RGMII suport in lan966x driver - Konrad Dybcio provided Qualcomm SM6375 usb snps-femto-v2 bindings - Michael Riesch added support for rockchip rk356x csi-dphya - Richard Acayan provided Qualcomm sdm670 usb2 bindings - Vincent Shih provided new Sunplus USB2 PHY driver - Updates: - Chunfeng Yun provided Mediatek hdmi, ufs, tphy and xsphy updates to use bitfield helpers. - Dmitry Baryshkov & Johan Hovold continued with Qualcomm qmp phy driver split and cleanup. More patches are under review and expected that next cycle might see completion of this activity. - Roger Quadros added support for TI wiz driver for j7200 10g - Sandeep Maheswaram added support in Qualcomm femto phy driver to override params to help with tuning - Siddharth Vadapalli added SGMII support in TI wiz driver - Yuan Can did bunch of dev_err_probe simplification -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmNAI0YACgkQfBQHDyUj g0f1Og//T7iaDW6Psq8hOkQE756JwrIxjJRHuNxnVDOpdjN7XTrXYE46pFyjMrkx hVHd1QDQMLkLsGNPzt2QdJ7i3xwSJ/iPeskfqvWgEJdKUP+AtGTSkyOiyikadcy5 rdaG0OrBhMiQNMvAnS3zmYL/tqZeOxvjisYsevlPDNQAINqF2AFl2ravbc3kLxnb 5zAAWwv11oVYVONTqUfd4gW7KsU2de8wU6UY9jk1iJaWT1u9O8EmDEXbOHONhcTN tA52Yw1PJXsurbpgtJIgUec6IIqHM0iG2/VS5l4UJTtddzNYhihFFTtD6noSiDCM Wzijf/uFJDckDakzwYPf6XSw+Y9Md1JkNlQQ/I+DzL0TddJZvu10RNtmwZQVbhWN SvgGsPKsjMFf3av8N4/gjnYHcWdAOU7Rz0hd1k6KqkzbUrbWWUoExpW9yCFCjN7i rAQ+7wG4UwNkbaOz0ZOBtDzDUn2gE2mH366eZHZ25FhdRwzxMKW5O/uJF0oOcSf6 o5ln1G7/5Ml0RT9OChj+vkiRP0/lOUrC40HyHaEmohPKGPkFcGUznEI6X3soqhlC xUNlY3FF1NeU5eHthnUXPOMySurK72VEVLTrVSCZzmFZPkN34UjdU/adKnzCO2+9 un2EKfAtPlXEQKxqc13JtZ5AXmZZ3GIstdjXWWcgPthJ6h5FbIg= =N3+u -----END PGP SIGNATURE----- Merge tag 'phy-for-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy Pull phy updates from Vinod Koul: "This contains bunch of new device support and one new Sunplus driver along with updates which include another big round of qmp phy conversion. New support: - Qualcomm SC8280XP eDP & DP and USB3 UNI phy (Bjorn Andersson) - Rockchip rk3568 inno dsidphy (Chris Morgan) - ocelot-serdes phy yaml binding (Colin Foster) - Renesas gen2-usb phy yaml binding (Geert Uytterhoeven) - RGMII suport in lan966x driver (Horatiu Vultur) - Qualcomm SM6375 usb snps-femto-v2 bindings (Konrad Dybcio) - Rockchip rk356x csi-dphya (Michael Riesch) - Qualcomm sdm670 usb2 bindings (Richard Acayan) - Sunplus USB2 PHY (Vincent Shih) Updates: - Mediatek hdmi, ufs, tphy and xsphy updates to use bitfield helpers (Chunfeng Yun) - Continued Qualcomm qmp phy driver split and cleanup. More patches are under review and expected that next cycle might see completion of this activity (Dmitry Baryshkov & Johan Hovold) - TI wiz driver support for j7200 10g (Roger Quadros) - Qualcomm femto phy driver support for override params to help with tuning (Sandeep Maheswaram) - SGMII support in TI wiz driver (Siddharth Vadapalli) - dev_err_probe simplification (Yuan Can)" * tag 'phy-for-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (170 commits) phy: phy-mtk-dp: make array driving_params static const dt-bindings: phy: qcom,qusb2: document sdm670 compatible phy: qcom-qmp-pcie: fix resource mapping for SDM845 QHP PHY phy: rockchip-snps-pcie3: only look for rockchip,pipe-grf on rk3588 phy: tegra: xusb: Enable usb role switch attribute phy: mediatek: fix build warning of FIELD_PREP() phy: qcom-qmp-usb: Use dev_err_probe() to simplify code phy: qcom-qmp-ufs: Use dev_err_probe() to simplify code phy: qcom-qmp-pcie-msm8996: Use dev_err_probe() to simplify code phy: qcom-qmp-combo: Use dev_err_probe() to simplify code phy: qualcomm: call clk_disable_unprepare in the error handling phy: intel: Use dev_err_probe() to simplify code phy: tegra: xusb: Use dev_err_probe() to simplify code phy: qcom-snps: Use dev_err_probe() to simplify code phy: qcom-qusb2: Use dev_err_probe() to simplify code phy: qcom-qmp-pcie: Use dev_err_probe() to simplify code phy: ti: phy-j721e-wiz: fix reference leaks in wiz_probe() phy: mediatek: mipi: remove register access helpers phy: mediatek: mipi: mt8183: use common helper to access registers phy: mediatek: mipi: mt8183: use GENMASK to generate bits mask ...
This commit is contained in:
commit
33e591dee9
@ -54,6 +54,12 @@ patternProperties:
|
||||
description:
|
||||
Clock provider for TI EHRPWM nodes.
|
||||
|
||||
"phy@[0-9a-f]+$":
|
||||
type: object
|
||||
$ref: /schemas/phy/ti,phy-gmii-sel.yaml#
|
||||
description:
|
||||
The phy node corresponding to the ethernet MAC.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -32,6 +32,7 @@ properties:
|
||||
patternProperties:
|
||||
"^pcie-phy@[0-9]+$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: >
|
||||
PCIe PHY child nodes
|
||||
|
||||
|
@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
title: Cadence DPHY Rx Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Pratyush Yadav <p.yadav@ti.com>
|
||||
- Pratyush Yadav <pratyush@kernel.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
title: Cadence DPHY Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Pratyush Yadav <p.yadav@ti.com>
|
||||
- Pratyush Yadav <pratyush@kernel.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -163,6 +163,7 @@ patternProperties:
|
||||
- PHY_TYPE_USB3
|
||||
- PHY_TYPE_PCIE
|
||||
- PHY_TYPE_SATA
|
||||
- PHY_TYPE_SGMII
|
||||
|
||||
nvmem-cells:
|
||||
items:
|
||||
@ -218,6 +219,16 @@ patternProperties:
|
||||
minimum: 1
|
||||
maximum: 15
|
||||
|
||||
mediatek,pre-emphasis:
|
||||
description:
|
||||
The level of pre-emphasis which used to widen the eye opening and
|
||||
boost eye swing, the unit step is about 4.16% increment; e.g. the
|
||||
level 1 means amplitude increases about 4.16%, the level 2 is about
|
||||
8.3% etc. (U2 phy)
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 1
|
||||
maximum: 3
|
||||
|
||||
mediatek,bc12:
|
||||
description:
|
||||
Specify the flag to enable BC1.2 if support it
|
||||
|
@ -0,0 +1,56 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/mscc,vsc7514-serdes.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microsemi Ocelot SerDes muxing
|
||||
|
||||
maintainers:
|
||||
- Alexandre Belloni <alexandre.belloni@bootlin.com>
|
||||
- UNGLinuxDriver@microchip.com
|
||||
|
||||
description: |
|
||||
On Microsemi Ocelot, there is a handful of registers in HSIO address
|
||||
space for setting up the SerDes to switch port muxing.
|
||||
|
||||
A SerDes X can be "muxed" to work with switch port Y or Z for example.
|
||||
One specific SerDes can also be used as a PCIe interface.
|
||||
|
||||
Hence, a SerDes represents an interface, be it an Ethernet or a PCIe one.
|
||||
|
||||
There are two kinds of SerDes: SERDES1G supports 10/100Mbps in
|
||||
half/full-duplex and 1000Mbps in full-duplex mode while SERDES6G supports
|
||||
10/100Mbps in half/full-duplex and 1000/2500Mbps in full-duplex mode.
|
||||
|
||||
Also, SERDES6G number (aka "macro") 0 is the only interface supporting
|
||||
QSGMII.
|
||||
|
||||
This is a child of the HSIO syscon ("mscc,ocelot-hsio", see
|
||||
Documentation/devicetree/bindings/mips/mscc.txt) on the Microsemi Ocelot.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mscc,vsc7514-serdes
|
||||
|
||||
"#phy-cells":
|
||||
const: 2
|
||||
description: |
|
||||
The first number defines the input port to use for a given SerDes macro.
|
||||
The second defines the macro to use. They are defined in
|
||||
dt-bindings/phy/phy-ocelot-serdes.h
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties:
|
||||
false
|
||||
|
||||
examples:
|
||||
- |
|
||||
serdes: serdes {
|
||||
compatible = "mscc,vsc7514-serdes";
|
||||
#phy-cells = <2>;
|
||||
};
|
@ -1,43 +0,0 @@
|
||||
Microsemi Ocelot SerDes muxing driver
|
||||
-------------------------------------
|
||||
|
||||
On Microsemi Ocelot, there is a handful of registers in HSIO address
|
||||
space for setting up the SerDes to switch port muxing.
|
||||
|
||||
A SerDes X can be "muxed" to work with switch port Y or Z for example.
|
||||
One specific SerDes can also be used as a PCIe interface.
|
||||
|
||||
Hence, a SerDes represents an interface, be it an Ethernet or a PCIe one.
|
||||
|
||||
There are two kinds of SerDes: SERDES1G supports 10/100Mbps in
|
||||
half/full-duplex and 1000Mbps in full-duplex mode while SERDES6G supports
|
||||
10/100Mbps in half/full-duplex and 1000/2500Mbps in full-duplex mode.
|
||||
|
||||
Also, SERDES6G number (aka "macro") 0 is the only interface supporting
|
||||
QSGMII.
|
||||
|
||||
This is a child of the HSIO syscon ("mscc,ocelot-hsio", see
|
||||
Documentation/devicetree/bindings/mips/mscc.txt) on the Microsemi Ocelot.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be "mscc,vsc7514-serdes"
|
||||
- #phy-cells : from the generic phy bindings, must be 2.
|
||||
The first number defines the input port to use for a given
|
||||
SerDes macro. The second defines the macro to use. They are
|
||||
defined in dt-bindings/phy/phy-ocelot-serdes.h
|
||||
|
||||
Example:
|
||||
|
||||
serdes: serdes {
|
||||
compatible = "mscc,vsc7514-serdes";
|
||||
#phy-cells = <2>;
|
||||
};
|
||||
|
||||
ethernet {
|
||||
port1 {
|
||||
phy-handle = <&phy_foo>;
|
||||
/* Link SERDES1G_5 to port1 */
|
||||
phys = <&serdes 1 SERDES1G_5>;
|
||||
};
|
||||
};
|
@ -13,6 +13,7 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- rockchip,px30-usb2phy
|
||||
- rockchip,rk3128-usb2phy
|
||||
- rockchip,rk3228-usb2phy
|
||||
- rockchip,rk3308-usb2phy
|
||||
- rockchip,rk3328-usb2phy
|
||||
|
@ -77,6 +77,8 @@ patternProperties:
|
||||
connector:
|
||||
type: object
|
||||
$ref: /schemas/connector/usb-connector.yaml
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
vbus-supply: true
|
||||
|
||||
|
@ -19,6 +19,8 @@ properties:
|
||||
enum:
|
||||
- qcom,sc7280-edp-phy
|
||||
- qcom,sc8180x-edp-phy
|
||||
- qcom,sc8280xp-dp-phy
|
||||
- qcom,sc8280xp-edp-phy
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
@ -0,0 +1,189 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/qcom,msm8996-qmp-pcie-phy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm QMP PHY controller (MSM8996 PCIe)
|
||||
|
||||
maintainers:
|
||||
- Vinod Koul <vkoul@kernel.org>
|
||||
|
||||
description:
|
||||
QMP PHY controller supports physical layer functionality for a number of
|
||||
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,msm8996-qmp-pcie-phy
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: serdes
|
||||
|
||||
"#address-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
"#size-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
ranges: true
|
||||
|
||||
clocks:
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
|
||||
resets:
|
||||
maxItems: 3
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
- const: cfg
|
||||
|
||||
vdda-phy-supply: true
|
||||
|
||||
vdda-pll-supply: true
|
||||
|
||||
vddp-ref-clk-supply: true
|
||||
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
type: object
|
||||
description: one child node per PHY provided by this block
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TX
|
||||
- description: RX
|
||||
- description: PCS
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: PIPE clock
|
||||
|
||||
clock-names:
|
||||
deprecated: true
|
||||
items:
|
||||
- enum:
|
||||
- pipe0
|
||||
- pipe1
|
||||
- pipe2
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: PHY reset
|
||||
|
||||
reset-names:
|
||||
deprecated: true
|
||||
items:
|
||||
- enum:
|
||||
- lane0
|
||||
- lane1
|
||||
- lane2
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
clock-output-names:
|
||||
maxItems: 1
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- reg
|
||||
- clocks
|
||||
- resets
|
||||
- "#clock-cells"
|
||||
- clock-output-names
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8996.h>
|
||||
pcie_phy: phy-wrapper@34000 {
|
||||
compatible = "qcom,msm8996-qmp-pcie-phy";
|
||||
reg = <0x34000 0x488>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x34000 0x4000>;
|
||||
|
||||
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
|
||||
<&gcc GCC_PCIE_PHY_CFG_AHB_CLK>,
|
||||
<&gcc GCC_PCIE_CLKREF_CLK>;
|
||||
clock-names = "aux", "cfg_ahb", "ref";
|
||||
|
||||
resets = <&gcc GCC_PCIE_PHY_BCR>,
|
||||
<&gcc GCC_PCIE_PHY_COM_BCR>,
|
||||
<&gcc GCC_PCIE_PHY_COM_NOCSR_BCR>;
|
||||
reset-names = "phy", "common", "cfg";
|
||||
|
||||
vdda-phy-supply = <&vreg_l28a_0p925>;
|
||||
vdda-pll-supply = <&vreg_l12a_1p8>;
|
||||
|
||||
pciephy_0: phy@1000 {
|
||||
reg = <0x1000 0x130>,
|
||||
<0x1200 0x200>,
|
||||
<0x1400 0x1dc>;
|
||||
|
||||
clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
|
||||
resets = <&gcc GCC_PCIE_0_PHY_BCR>;
|
||||
|
||||
#clock-cells = <0>;
|
||||
clock-output-names = "pcie_0_pipe_clk_src";
|
||||
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pciephy_1: phy@2000 {
|
||||
reg = <0x2000 0x130>,
|
||||
<0x2200 0x200>,
|
||||
<0x2400 0x1dc>;
|
||||
|
||||
clocks = <&gcc GCC_PCIE_1_PIPE_CLK>;
|
||||
resets = <&gcc GCC_PCIE_1_PHY_BCR>;
|
||||
|
||||
#clock-cells = <0>;
|
||||
clock-output-names = "pcie_1_pipe_clk_src";
|
||||
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pciephy_2: phy@3000 {
|
||||
reg = <0x3000 0x130>,
|
||||
<0x3200 0x200>,
|
||||
<0x3400 0x1dc>;
|
||||
|
||||
clocks = <&gcc GCC_PCIE_2_PIPE_CLK>;
|
||||
resets = <&gcc GCC_PCIE_2_PHY_BCR>;
|
||||
|
||||
#clock-cells = <0>;
|
||||
clock-output-names = "pcie_2_pipe_clk_src";
|
||||
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
296
Documentation/devicetree/bindings/phy/qcom,qmp-pcie-phy.yaml
Normal file
296
Documentation/devicetree/bindings/phy/qcom,qmp-pcie-phy.yaml
Normal file
@ -0,0 +1,296 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/qcom,qmp-pcie-phy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm QMP PHY controller (PCIe)
|
||||
|
||||
maintainers:
|
||||
- Vinod Koul <vkoul@kernel.org>
|
||||
|
||||
description:
|
||||
QMP PHY controller supports physical layer functionality for a number of
|
||||
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,ipq6018-qmp-pcie-phy
|
||||
- qcom,ipq8074-qmp-gen3-pcie-phy
|
||||
- qcom,ipq8074-qmp-pcie-phy
|
||||
- qcom,msm8998-qmp-pcie-phy
|
||||
- qcom,sc8180x-qmp-pcie-phy
|
||||
- qcom,sdm845-qhp-pcie-phy
|
||||
- qcom,sdm845-qmp-pcie-phy
|
||||
- qcom,sdx55-qmp-pcie-phy
|
||||
- qcom,sm8250-qmp-gen3x1-pcie-phy
|
||||
- qcom,sm8250-qmp-gen3x2-pcie-phy
|
||||
- qcom,sm8250-qmp-modem-pcie-phy
|
||||
- qcom,sm8450-qmp-gen3x1-pcie-phy
|
||||
- qcom,sm8450-qmp-gen4x2-pcie-phy
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: serdes
|
||||
|
||||
"#address-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
"#size-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
ranges: true
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
reset-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
vdda-phy-supply: true
|
||||
|
||||
vdda-pll-supply: true
|
||||
|
||||
vddp-ref-clk-supply: true
|
||||
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
type: object
|
||||
description: single PHY-provider child node
|
||||
properties:
|
||||
reg:
|
||||
minItems: 3
|
||||
maxItems: 6
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: PIPE clock
|
||||
|
||||
clock-names:
|
||||
deprecated: true
|
||||
items:
|
||||
- const: pipe0
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
clock-output-names:
|
||||
maxItems: 1
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- reg
|
||||
- clocks
|
||||
- "#clock-cells"
|
||||
- clock-output-names
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8998-qmp-pcie-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
resets:
|
||||
maxItems: 2
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq6018-qmp-pcie-phy
|
||||
- qcom,ipq8074-qmp-gen3-pcie-phy
|
||||
- qcom,ipq8074-qmp-pcie-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 2
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
resets:
|
||||
maxItems: 2
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sc8180x-qmp-pcie-phy
|
||||
- qcom,sdm845-qhp-pcie-phy
|
||||
- qcom,sdm845-qmp-pcie-phy
|
||||
- qcom,sdx55-qmp-pcie-phy
|
||||
- qcom,sm8250-qmp-gen3x1-pcie-phy
|
||||
- qcom,sm8250-qmp-gen3x2-pcie-phy
|
||||
- qcom,sm8250-qmp-modem-pcie-phy
|
||||
- qcom,sm8450-qmp-gen3x1-pcie-phy
|
||||
- qcom,sm8450-qmp-gen4x2-pcie-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
- const: refgen
|
||||
resets:
|
||||
maxItems: 1
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm8250-qmp-gen3x2-pcie-phy
|
||||
- qcom,sm8250-qmp-modem-pcie-phy
|
||||
- qcom,sm8450-qmp-gen4x2-pcie-phy
|
||||
then:
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TX lane 1
|
||||
- description: RX lane 1
|
||||
- description: PCS
|
||||
- description: TX lane 2
|
||||
- description: RX lane 2
|
||||
- description: PCS_MISC
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sc8180x-qmp-pcie-phy
|
||||
- qcom,sdm845-qmp-pcie-phy
|
||||
- qcom,sdx55-qmp-pcie-phy
|
||||
- qcom,sm8250-qmp-gen3x1-pcie-phy
|
||||
- qcom,sm8450-qmp-gen3x1-pcie-phy
|
||||
then:
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TX
|
||||
- description: RX
|
||||
- description: PCS
|
||||
- description: PCS_MISC
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq6018-qmp-pcie-phy
|
||||
- qcom,ipq8074-qmp-pcie-phy
|
||||
- qcom,msm8998-qmp-pcie-phy
|
||||
- qcom,sdm845-qhp-pcie-phy
|
||||
then:
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TX
|
||||
- description: RX
|
||||
- description: PCS
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-sm8250.h>
|
||||
phy-wrapper@1c0e000 {
|
||||
compatible = "qcom,sm8250-qmp-gen3x2-pcie-phy";
|
||||
reg = <0x01c0e000 0x1c0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x01c0e000 0x1000>;
|
||||
|
||||
clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
|
||||
<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
|
||||
<&gcc GCC_PCIE_WIGIG_CLKREF_EN>,
|
||||
<&gcc GCC_PCIE1_PHY_REFGEN_CLK>;
|
||||
clock-names = "aux", "cfg_ahb", "ref", "refgen";
|
||||
|
||||
resets = <&gcc GCC_PCIE_1_PHY_BCR>;
|
||||
reset-names = "phy";
|
||||
|
||||
vdda-phy-supply = <&vreg_l10c_0p88>;
|
||||
vdda-pll-supply = <&vreg_l6b_1p2>;
|
||||
|
||||
phy@200 {
|
||||
reg = <0x200 0x170>,
|
||||
<0x400 0x200>,
|
||||
<0xa00 0x1f0>,
|
||||
<0x600 0x170>,
|
||||
<0x800 0x200>,
|
||||
<0xe00 0xf4>;
|
||||
|
||||
clocks = <&gcc GCC_PCIE_1_PIPE_CLK>;
|
||||
|
||||
#clock-cells = <0>;
|
||||
clock-output-names = "pcie_1_pipe_clk";
|
||||
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
@ -1,502 +0,0 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/phy/qcom,qmp-phy.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcomm QMP PHY controller
|
||||
|
||||
maintainers:
|
||||
- Vinod Koul <vkoul@kernel.org>
|
||||
|
||||
description:
|
||||
QMP phy controller supports physical layer functionality for a number of
|
||||
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,ipq6018-qmp-pcie-phy
|
||||
- qcom,ipq6018-qmp-usb3-phy
|
||||
- qcom,ipq8074-qmp-gen3-pcie-phy
|
||||
- qcom,ipq8074-qmp-pcie-phy
|
||||
- qcom,ipq8074-qmp-usb3-phy
|
||||
- qcom,msm8996-qmp-pcie-phy
|
||||
- qcom,msm8996-qmp-ufs-phy
|
||||
- qcom,msm8996-qmp-usb3-phy
|
||||
- qcom,msm8998-qmp-pcie-phy
|
||||
- qcom,msm8998-qmp-ufs-phy
|
||||
- qcom,msm8998-qmp-usb3-phy
|
||||
- qcom,qcm2290-qmp-usb3-phy
|
||||
- qcom,sc7180-qmp-usb3-phy
|
||||
- qcom,sc8180x-qmp-pcie-phy
|
||||
- qcom,sc8180x-qmp-ufs-phy
|
||||
- qcom,sc8180x-qmp-usb3-phy
|
||||
- qcom,sc8280xp-qmp-ufs-phy
|
||||
- qcom,sdm845-qhp-pcie-phy
|
||||
- qcom,sdm845-qmp-pcie-phy
|
||||
- qcom,sdm845-qmp-ufs-phy
|
||||
- qcom,sdm845-qmp-usb3-phy
|
||||
- qcom,sdm845-qmp-usb3-uni-phy
|
||||
- qcom,sm6115-qmp-ufs-phy
|
||||
- qcom,sm6350-qmp-ufs-phy
|
||||
- qcom,sm8150-qmp-ufs-phy
|
||||
- qcom,sm8150-qmp-usb3-phy
|
||||
- qcom,sm8150-qmp-usb3-uni-phy
|
||||
- qcom,sm8250-qmp-ufs-phy
|
||||
- qcom,sm8250-qmp-gen3x1-pcie-phy
|
||||
- qcom,sm8250-qmp-gen3x2-pcie-phy
|
||||
- qcom,sm8250-qmp-modem-pcie-phy
|
||||
- qcom,sm8250-qmp-usb3-phy
|
||||
- qcom,sm8250-qmp-usb3-uni-phy
|
||||
- qcom,sm8350-qmp-ufs-phy
|
||||
- qcom,sm8350-qmp-usb3-phy
|
||||
- qcom,sm8350-qmp-usb3-uni-phy
|
||||
- qcom,sm8450-qmp-gen3x1-pcie-phy
|
||||
- qcom,sm8450-qmp-gen4x2-pcie-phy
|
||||
- qcom,sm8450-qmp-ufs-phy
|
||||
- qcom,sm8450-qmp-usb3-phy
|
||||
- qcom,sdx55-qmp-pcie-phy
|
||||
- qcom,sdx55-qmp-usb3-uni-phy
|
||||
- qcom,sdx65-qmp-usb3-uni-phy
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: Address and length of PHY's common serdes block.
|
||||
- description: Address and length of PHY's DP_COM control block.
|
||||
|
||||
"#clock-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
"#address-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
"#size-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
ranges: true
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
reset-names:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
vdda-phy-supply:
|
||||
description:
|
||||
Phandle to a regulator supply to PHY core block.
|
||||
|
||||
vdda-pll-supply:
|
||||
description:
|
||||
Phandle to 1.8V regulator supply to PHY refclk pll block.
|
||||
|
||||
vddp-ref-clk-supply:
|
||||
description:
|
||||
Phandle to a regulator supply to any specific refclk pll block.
|
||||
|
||||
#Required nodes:
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
type: object
|
||||
description:
|
||||
Each device node of QMP phy is required to have as many child nodes as
|
||||
the number of lanes the PHY has.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sdm845-qmp-usb3-uni-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Phy aux clock.
|
||||
- description: Phy config clock.
|
||||
- description: 19.2 MHz ref clk.
|
||||
- description: Phy common block aux clock.
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
- const: com_aux
|
||||
resets:
|
||||
items:
|
||||
- description: reset of phy block.
|
||||
- description: phy common block reset.
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sdx55-qmp-usb3-uni-phy
|
||||
- qcom,sdx65-qmp-usb3-uni-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Phy aux clock.
|
||||
- description: Phy config clock.
|
||||
- description: 19.2 MHz ref clk.
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
resets:
|
||||
items:
|
||||
- description: reset of phy block.
|
||||
- description: phy common block reset.
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8996-qmp-pcie-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Phy aux clock.
|
||||
- description: Phy config clock.
|
||||
- description: 19.2 MHz ref clk.
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
resets:
|
||||
items:
|
||||
- description: reset of phy block.
|
||||
- description: phy common block reset.
|
||||
- description: phy's ahb cfg block reset.
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
- const: cfg
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq8074-qmp-usb3-phy
|
||||
- qcom,msm8996-qmp-usb3-phy
|
||||
- qcom,msm8998-qmp-pcie-phy
|
||||
- qcom,msm8998-qmp-usb3-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Phy aux clock.
|
||||
- description: Phy config clock.
|
||||
- description: 19.2 MHz ref clk.
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
resets:
|
||||
items:
|
||||
- description: reset of phy block.
|
||||
- description: phy common block reset.
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8996-qmp-ufs-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: 19.2 MHz ref clk.
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
resets:
|
||||
items:
|
||||
- description: PHY reset in the UFS controller.
|
||||
reset-names:
|
||||
items:
|
||||
- const: ufsphy
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8998-qmp-ufs-phy
|
||||
- qcom,sdm845-qmp-ufs-phy
|
||||
- qcom,sm6350-qmp-ufs-phy
|
||||
- qcom,sm8150-qmp-ufs-phy
|
||||
- qcom,sm8250-qmp-ufs-phy
|
||||
- qcom,sc8180x-qmp-ufs-phy
|
||||
- qcom,sc8280xp-qmp-ufs-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: 19.2 MHz ref clk.
|
||||
- description: Phy reference aux clock.
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
- const: ref_aux
|
||||
resets:
|
||||
items:
|
||||
- description: PHY reset in the UFS controller.
|
||||
reset-names:
|
||||
items:
|
||||
- const: ufsphy
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq6018-qmp-pcie-phy
|
||||
- qcom,ipq8074-qmp-gen3-pcie-phy
|
||||
- qcom,ipq8074-qmp-pcie-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Phy aux clock.
|
||||
- description: Phy config clock.
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
resets:
|
||||
items:
|
||||
- description: reset of phy block.
|
||||
- description: phy common block reset.
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sc8180x-qmp-pcie-phy
|
||||
- qcom,sdm845-qhp-pcie-phy
|
||||
- qcom,sdm845-qmp-pcie-phy
|
||||
- qcom,sdx55-qmp-pcie-phy
|
||||
- qcom,sm8250-qmp-gen3x1-pcie-phy
|
||||
- qcom,sm8250-qmp-gen3x2-pcie-phy
|
||||
- qcom,sm8250-qmp-modem-pcie-phy
|
||||
- qcom,sm8450-qmp-gen3x1-pcie-phy
|
||||
- qcom,sm8450-qmp-gen4x2-pcie-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Phy aux clock.
|
||||
- description: Phy config clock.
|
||||
- description: 19.2 MHz ref clk.
|
||||
- description: Phy refgen clk.
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
- const: refgen
|
||||
resets:
|
||||
items:
|
||||
- description: reset of phy block.
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm8150-qmp-usb3-phy
|
||||
- qcom,sm8150-qmp-usb3-uni-phy
|
||||
- qcom,sm8250-qmp-usb3-uni-phy
|
||||
- qcom,sm8350-qmp-usb3-uni-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Phy aux clock.
|
||||
- description: 19.2 MHz ref clk source.
|
||||
- description: 19.2 MHz ref clk.
|
||||
- description: Phy common block aux clock.
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: ref_clk_src
|
||||
- const: ref
|
||||
- const: com_aux
|
||||
resets:
|
||||
items:
|
||||
- description: reset of phy block.
|
||||
- description: phy common block reset.
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm8250-qmp-usb3-phy
|
||||
- qcom,sm8350-qmp-usb3-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Phy aux clock.
|
||||
- description: 19.2 MHz ref clk.
|
||||
- description: Phy common block aux clock.
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: ref_clk_src
|
||||
- const: com_aux
|
||||
resets:
|
||||
items:
|
||||
- description: reset of phy block.
|
||||
- description: phy common block reset.
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,qcm2290-qmp-usb3-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Phy config clock.
|
||||
- description: 19.2 MHz ref clk.
|
||||
- description: Phy common block aux clock.
|
||||
clock-names:
|
||||
items:
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
- const: com_aux
|
||||
resets:
|
||||
items:
|
||||
- description: phy_phy reset.
|
||||
- description: reset of phy block.
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy_phy
|
||||
- const: phy
|
||||
required:
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-sdm845.h>
|
||||
usb_2_qmpphy: phy-wrapper@88eb000 {
|
||||
compatible = "qcom,sdm845-qmp-usb3-uni-phy";
|
||||
reg = <0x088eb000 0x18c>;
|
||||
#clock-cells = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x088eb000 0x2000>;
|
||||
|
||||
clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK >,
|
||||
<&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
|
||||
<&gcc GCC_USB3_SEC_CLKREF_CLK>,
|
||||
<&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>;
|
||||
clock-names = "aux", "cfg_ahb", "ref", "com_aux";
|
||||
|
||||
resets = <&gcc GCC_USB3PHY_PHY_SEC_BCR>,
|
||||
<&gcc GCC_USB3_PHY_SEC_BCR>;
|
||||
reset-names = "phy", "common";
|
||||
|
||||
vdda-phy-supply = <&vdda_usb2_ss_1p2>;
|
||||
vdda-pll-supply = <&vdda_usb2_ss_core>;
|
||||
|
||||
usb_2_ssphy: phy@200 {
|
||||
reg = <0x200 0x128>,
|
||||
<0x400 0x1fc>,
|
||||
<0x800 0x218>,
|
||||
<0x600 0x70>;
|
||||
#clock-cells = <0>;
|
||||
#phy-cells = <0>;
|
||||
clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
|
||||
clock-names = "pipe0";
|
||||
clock-output-names = "usb3_uni_phy_pipe_clk_src";
|
||||
};
|
||||
};
|
240
Documentation/devicetree/bindings/phy/qcom,qmp-ufs-phy.yaml
Normal file
240
Documentation/devicetree/bindings/phy/qcom,qmp-ufs-phy.yaml
Normal file
@ -0,0 +1,240 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/qcom,qmp-ufs-phy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm QMP PHY controller (UFS)
|
||||
|
||||
maintainers:
|
||||
- Vinod Koul <vkoul@kernel.org>
|
||||
|
||||
description:
|
||||
QMP PHY controller supports physical layer functionality for a number of
|
||||
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,msm8996-qmp-ufs-phy
|
||||
- qcom,msm8998-qmp-ufs-phy
|
||||
- qcom,sc8180x-qmp-ufs-phy
|
||||
- qcom,sc8280xp-qmp-ufs-phy
|
||||
- qcom,sdm845-qmp-ufs-phy
|
||||
- qcom,sm6115-qmp-ufs-phy
|
||||
- qcom,sm6350-qmp-ufs-phy
|
||||
- qcom,sm8150-qmp-ufs-phy
|
||||
- qcom,sm8250-qmp-ufs-phy
|
||||
- qcom,sm8350-qmp-ufs-phy
|
||||
- qcom,sm8450-qmp-ufs-phy
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: serdes
|
||||
|
||||
"#address-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
"#size-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
ranges: true
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: ufsphy
|
||||
|
||||
vdda-phy-supply: true
|
||||
|
||||
vdda-pll-supply: true
|
||||
|
||||
vddp-ref-clk-supply: true
|
||||
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
type: object
|
||||
description: single PHY-provider child node
|
||||
properties:
|
||||
reg:
|
||||
minItems: 3
|
||||
maxItems: 6
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- reg
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8996-qmp-ufs-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8998-qmp-ufs-phy
|
||||
- qcom,sc8180x-qmp-ufs-phy
|
||||
- qcom,sc8280xp-qmp-ufs-phy
|
||||
- qcom,sdm845-qmp-ufs-phy
|
||||
- qcom,sm6115-qmp-ufs-phy
|
||||
- qcom,sm6350-qmp-ufs-phy
|
||||
- qcom,sm8150-qmp-ufs-phy
|
||||
- qcom,sm8250-qmp-ufs-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 2
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
- const: ref_aux
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm8450-qmp-ufs-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
- const: ref_aux
|
||||
- const: qref
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8998-qmp-ufs-phy
|
||||
- qcom,sc8280xp-qmp-ufs-phy
|
||||
- qcom,sdm845-qmp-ufs-phy
|
||||
- qcom,sm6350-qmp-ufs-phy
|
||||
- qcom,sm8150-qmp-ufs-phy
|
||||
- qcom,sm8250-qmp-ufs-phy
|
||||
- qcom,sm8350-qmp-ufs-phy
|
||||
- qcom,sm8450-qmp-ufs-phy
|
||||
then:
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TX lane 1
|
||||
- description: RX lane 1
|
||||
- description: PCS
|
||||
- description: TX lane 2
|
||||
- description: RX lane 2
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sc8180x-qmp-ufs-phy
|
||||
then:
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TX
|
||||
- description: RX
|
||||
- description: PCS
|
||||
- description: PCS_MISC
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8996-qmp-ufs-phy
|
||||
- qcom,sm6115-qmp-ufs-phy
|
||||
then:
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TX
|
||||
- description: RX
|
||||
- description: PCS
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
phy-wrapper@1d87000 {
|
||||
compatible = "qcom,sc8280xp-qmp-ufs-phy";
|
||||
reg = <0x01d87000 0xe10>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x01d87000 0x1000>;
|
||||
|
||||
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_UFS_PHY_PHY_AUX_CLK>;
|
||||
clock-names = "ref", "ref_aux";
|
||||
|
||||
resets = <&ufs_mem_hc 0>;
|
||||
reset-names = "ufsphy";
|
||||
|
||||
vdda-phy-supply = <&vreg_l6b>;
|
||||
vdda-pll-supply = <&vreg_l3b>;
|
||||
|
||||
phy@400 {
|
||||
reg = <0x400 0x108>,
|
||||
<0x600 0x1e0>,
|
||||
<0xc00 0x1dc>,
|
||||
<0x800 0x108>,
|
||||
<0xa00 0x1e0>;
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
401
Documentation/devicetree/bindings/phy/qcom,qmp-usb-phy.yaml
Normal file
401
Documentation/devicetree/bindings/phy/qcom,qmp-usb-phy.yaml
Normal file
@ -0,0 +1,401 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/qcom,qmp-usb-phy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm QMP PHY controller (USB)
|
||||
|
||||
maintainers:
|
||||
- Vinod Koul <vkoul@kernel.org>
|
||||
|
||||
description:
|
||||
QMP PHY controller supports physical layer functionality for a number of
|
||||
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,ipq6018-qmp-usb3-phy
|
||||
- qcom,ipq8074-qmp-usb3-phy
|
||||
- qcom,msm8996-qmp-usb3-phy
|
||||
- qcom,msm8998-qmp-usb3-phy
|
||||
- qcom,qcm2290-qmp-usb3-phy
|
||||
- qcom,sc7180-qmp-usb3-phy
|
||||
- qcom,sc8180x-qmp-usb3-phy
|
||||
- qcom,sc8280xp-qmp-usb3-uni-phy
|
||||
- qcom,sdm845-qmp-usb3-phy
|
||||
- qcom,sdm845-qmp-usb3-uni-phy
|
||||
- qcom,sdx55-qmp-usb3-uni-phy
|
||||
- qcom,sdx65-qmp-usb3-uni-phy
|
||||
- qcom,sm8150-qmp-usb3-phy
|
||||
- qcom,sm8150-qmp-usb3-uni-phy
|
||||
- qcom,sm8250-qmp-usb3-phy
|
||||
- qcom,sm8250-qmp-usb3-uni-phy
|
||||
- qcom,sm8350-qmp-usb3-phy
|
||||
- qcom,sm8350-qmp-usb3-uni-phy
|
||||
- qcom,sm8450-qmp-usb3-phy
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: serdes
|
||||
- description: DP_COM
|
||||
|
||||
"#address-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
"#size-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
ranges: true
|
||||
|
||||
clocks:
|
||||
minItems: 3
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
minItems: 3
|
||||
maxItems: 4
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 2
|
||||
|
||||
reset-names:
|
||||
maxItems: 2
|
||||
|
||||
vdda-phy-supply: true
|
||||
|
||||
vdda-pll-supply: true
|
||||
|
||||
vddp-ref-clk-supply: true
|
||||
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
type: object
|
||||
description: single PHY-provider child node
|
||||
properties:
|
||||
reg:
|
||||
minItems: 3
|
||||
maxItems: 6
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: PIPE clock
|
||||
|
||||
clock-names:
|
||||
deprecated: true
|
||||
items:
|
||||
- const: pipe0
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
clock-output-names:
|
||||
maxItems: 1
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- reg
|
||||
- clocks
|
||||
- "#clock-cells"
|
||||
- clock-output-names
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sc7180-qmp-usb3-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
- const: com_aux
|
||||
resets:
|
||||
maxItems: 1
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sdm845-qmp-usb3-uni-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
- const: com_aux
|
||||
resets:
|
||||
maxItems: 2
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq8074-qmp-usb3-phy
|
||||
- qcom,msm8996-qmp-usb3-phy
|
||||
- qcom,msm8998-qmp-usb3-phy
|
||||
- qcom,sdx55-qmp-usb3-uni-phy
|
||||
- qcom,sdx65-qmp-usb3-uni-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
resets:
|
||||
maxItems: 2
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sc8280xp-qmp-usb3-uni-phy
|
||||
- qcom,sm8150-qmp-usb3-phy
|
||||
- qcom,sm8150-qmp-usb3-uni-phy
|
||||
- qcom,sm8250-qmp-usb3-uni-phy
|
||||
- qcom,sm8350-qmp-usb3-uni-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: ref_clk_src
|
||||
- const: ref
|
||||
- const: com_aux
|
||||
resets:
|
||||
maxItems: 2
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm8250-qmp-usb3-phy
|
||||
- qcom,sm8350-qmp-usb3-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: ref_clk_src
|
||||
- const: com_aux
|
||||
resets:
|
||||
maxItems: 2
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: common
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,qcm2290-qmp-usb3-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: cfg_ahb
|
||||
- const: ref
|
||||
- const: com_aux
|
||||
resets:
|
||||
maxItems: 2
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy_phy
|
||||
- const: phy
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sc8280xp-qmp-usb3-uni-phy
|
||||
then:
|
||||
required:
|
||||
- power-domains
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sdm845-qmp-usb3-phy
|
||||
- qcom,sm8150-qmp-usb3-phy
|
||||
- qcom,sm8350-qmp-usb3-phy
|
||||
- qcom,sm8450-qmp-usb3-phy
|
||||
then:
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TX lane 1
|
||||
- description: RX lane 1
|
||||
- description: PCS
|
||||
- description: TX lane 2
|
||||
- description: RX lane 2
|
||||
- description: PCS_MISC
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8998-qmp-usb3-phy
|
||||
then:
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TX lane 1
|
||||
- description: RX lane 1
|
||||
- description: PCS
|
||||
- description: TX lane 2
|
||||
- description: RX lane 2
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq6018-qmp-usb3-phy
|
||||
- qcom,ipq8074-qmp-usb3-phy
|
||||
- qcom,qcm2290-qmp-usb3-phy
|
||||
- qcom,sc7180-qmp-usb3-phy
|
||||
- qcom,sc8180x-qmp-usb3-phy
|
||||
- qcom,sdx55-qmp-usb3-uni-phy
|
||||
- qcom,sdx65-qmp-usb3-uni-phy
|
||||
- qcom,sm8150-qmp-usb3-uni-phy
|
||||
- qcom,sm8250-qmp-usb3-phy
|
||||
then:
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TX
|
||||
- description: RX
|
||||
- description: PCS
|
||||
- description: PCS_MISC
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8996-qmp-usb3-phy
|
||||
- qcom,sc8280xp-qmp-usb3-uni-phy
|
||||
- qcom,sm8250-qmp-usb3-uni-phy
|
||||
- qcom,sm8350-qmp-usb3-uni-phy
|
||||
then:
|
||||
patternProperties:
|
||||
"^phy@[0-9a-f]+$":
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: TX
|
||||
- description: RX
|
||||
- description: PCS
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-sdm845.h>
|
||||
usb_2_qmpphy: phy-wrapper@88eb000 {
|
||||
compatible = "qcom,sdm845-qmp-usb3-uni-phy";
|
||||
reg = <0x088eb000 0x18c>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x088eb000 0x2000>;
|
||||
|
||||
clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK >,
|
||||
<&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
|
||||
<&gcc GCC_USB3_SEC_CLKREF_CLK>,
|
||||
<&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>;
|
||||
clock-names = "aux", "cfg_ahb", "ref", "com_aux";
|
||||
|
||||
resets = <&gcc GCC_USB3PHY_PHY_SEC_BCR>,
|
||||
<&gcc GCC_USB3_PHY_SEC_BCR>;
|
||||
reset-names = "phy", "common";
|
||||
|
||||
vdda-phy-supply = <&vdda_usb2_ss_1p2>;
|
||||
vdda-pll-supply = <&vdda_usb2_ss_core>;
|
||||
|
||||
usb_2_ssphy: phy@200 {
|
||||
reg = <0x200 0x128>,
|
||||
<0x400 0x1fc>,
|
||||
<0x800 0x218>,
|
||||
<0x600 0x70>;
|
||||
|
||||
clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
|
||||
|
||||
#clock-cells = <0>;
|
||||
clock-output-names = "usb3_uni_phy_pipe_clk_src";
|
||||
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
@ -16,6 +16,7 @@ properties:
|
||||
- qcom,sc7180-qmp-usb3-dp-phy
|
||||
- qcom,sc7280-qmp-usb3-dp-phy
|
||||
- qcom,sc8180x-qmp-usb3-dp-phy
|
||||
- qcom,sc8280xp-qmp-usb43dp-phy
|
||||
- qcom,sdm845-qmp-usb3-dp-phy
|
||||
- qcom,sm8250-qmp-usb3-dp-phy
|
||||
reg:
|
||||
@ -30,9 +31,6 @@ properties:
|
||||
- const: dp_com
|
||||
- const: dp
|
||||
|
||||
"#clock-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
"#address-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
@ -55,6 +53,9 @@ properties:
|
||||
- const: ref
|
||||
- const: com_aux
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: reset of phy block.
|
||||
@ -81,6 +82,7 @@ properties:
|
||||
patternProperties:
|
||||
"^usb3-phy@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description:
|
||||
The USB3 PHY.
|
||||
|
||||
@ -99,6 +101,7 @@ patternProperties:
|
||||
- description: pipe clock
|
||||
|
||||
clock-names:
|
||||
deprecated: true
|
||||
items:
|
||||
- const: pipe0
|
||||
|
||||
@ -115,12 +118,12 @@ patternProperties:
|
||||
required:
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
- '#phy-cells'
|
||||
|
||||
"^dp-phy@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description:
|
||||
The DP PHY.
|
||||
|
||||
@ -147,7 +150,6 @@ patternProperties:
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
@ -160,6 +162,17 @@ required:
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sc8280xp-qmp-usb43dp-phy
|
||||
then:
|
||||
required:
|
||||
- power-domains
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-sdm845.h>
|
||||
@ -169,7 +182,6 @@ examples:
|
||||
<0x088e8000 0x10>,
|
||||
<0x088ea000 0x40>;
|
||||
reg-names = "usb", "dp_com", "dp";
|
||||
#clock-cells = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x088e9000 0x2000>;
|
||||
@ -197,7 +209,6 @@ examples:
|
||||
#clock-cells = <0>;
|
||||
#phy-cells = <0>;
|
||||
clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
|
||||
clock-names = "pipe0";
|
||||
clock-output-names = "usb3_phy_pipe_clk_src";
|
||||
};
|
||||
|
||||
|
@ -30,6 +30,7 @@ properties:
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sc7180-qusb2-phy
|
||||
- qcom,sdm670-qusb2-phy
|
||||
- qcom,sdm845-qusb2-phy
|
||||
- qcom,sm6350-qusb2-phy
|
||||
- const: qcom,qusb2-v2-phy
|
||||
|
@ -20,6 +20,7 @@ properties:
|
||||
- qcom,sc7280-usb-hs-phy
|
||||
- qcom,sc8180x-usb-hs-phy
|
||||
- qcom,sc8280xp-usb-hs-phy
|
||||
- qcom,sm6375-usb-hs-phy
|
||||
- qcom,sm8150-usb-hs-phy
|
||||
- qcom,sm8250-usb-hs-phy
|
||||
- qcom,sm8350-usb-hs-phy
|
||||
@ -53,6 +54,94 @@ properties:
|
||||
vdda33-supply:
|
||||
description: phandle to the regulator 3.3V supply node.
|
||||
|
||||
qcom,hs-disconnect-bp:
|
||||
description:
|
||||
This adjusts the voltage level for the threshold used to
|
||||
detect a disconnect event at the host.
|
||||
The hardware accepts only discrete values. The value closest to the
|
||||
provided input will be chosen as the override value for this param.
|
||||
minimum: -272
|
||||
maximum: 2156
|
||||
|
||||
qcom,squelch-detector-bp:
|
||||
description:
|
||||
This adjusts the voltage level for the threshold used to
|
||||
detect valid high-speed data.
|
||||
The hardware accepts only discrete values. The value closest to the
|
||||
provided input will be chosen as the override value for this param.
|
||||
minimum: -2090
|
||||
maximum: 1590
|
||||
|
||||
qcom,hs-amplitude-bp:
|
||||
description:
|
||||
This adjusts the high-speed DC level voltage.
|
||||
The hardware accepts only discrete values. The value closest to the
|
||||
provided input will be chosen as the override value for this param.
|
||||
minimum: -660
|
||||
maximum: 2670
|
||||
|
||||
qcom,pre-emphasis-duration-bp:
|
||||
description:
|
||||
This signal controls the duration for which the
|
||||
HS pre-emphasis current is sourced onto DP<#> or DM<#>.
|
||||
The HS Transmitter pre-emphasis duration is defined in terms of
|
||||
unit amounts. One unit of pre-emphasis duration is approximately
|
||||
650 ps and is defined as 1X pre-emphasis duration.
|
||||
The hardware accepts only discrete values. The value closest to the
|
||||
provided input will be chosen as the override value for this param.
|
||||
minimum: 10000
|
||||
maximum: 20000
|
||||
|
||||
qcom,pre-emphasis-amplitude-bp:
|
||||
description:
|
||||
This signal controls the amount of current sourced to
|
||||
DP<#> and DM<#> after a J-to-K or K-to-J transition.
|
||||
The HS Transmitter pre-emphasis current is defined in terms of unit
|
||||
amounts. One unit amount is approximately 2 mA and is defined as
|
||||
1X pre-emphasis current.
|
||||
The hardware accepts only discrete values. The value closest to the
|
||||
provided input will be chosen as the override value for this param.
|
||||
minimum: 10000
|
||||
maximum: 40000
|
||||
|
||||
qcom,hs-rise-fall-time-bp:
|
||||
description:
|
||||
This adjusts the rise/fall times of the high-speed waveform.
|
||||
The hardware accepts only discrete values. The value closest to the
|
||||
provided input will be chosen as the override value for this param.
|
||||
minimum: -4100
|
||||
maximum: 5430
|
||||
|
||||
qcom,hs-crossover-voltage-microvolt:
|
||||
description:
|
||||
This adjusts the voltage at which the DP<#> and DM<#>
|
||||
signals cross while transmitting in HS mode.
|
||||
The hardware accepts only discrete values. The value closest to the
|
||||
provided input will be chosen as the override value for this param.
|
||||
minimum: -31000
|
||||
maximum: 28000
|
||||
|
||||
qcom,hs-output-impedance-micro-ohms:
|
||||
description:
|
||||
In some applications, there can be significant series resistance
|
||||
on the D+ and D- paths between the transceiver and cable. This adjusts
|
||||
the driver source impedance to compensate for added series
|
||||
resistance on the USB. The hardware accepts only discrete values. The
|
||||
value closest to the provided input will be chosen as the override value
|
||||
for this param.
|
||||
minimum: -2300000
|
||||
maximum: 6100000
|
||||
|
||||
qcom,ls-fs-output-impedance-bp:
|
||||
description:
|
||||
This adjusts the low- and full-speed single-ended source
|
||||
impedance while driving high. The following adjustment values are based
|
||||
on nominal process, voltage, and temperature.
|
||||
The hardware accepts only discrete values. The value closest to the
|
||||
provided input will be chosen as the override value for this param.
|
||||
minimum: -1053
|
||||
maximum: 1310
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -1,112 +0,0 @@
|
||||
* Renesas R-Car generation 2 USB PHY
|
||||
|
||||
This file provides information on what the device node for the R-Car generation
|
||||
2 USB PHY contains.
|
||||
|
||||
Required properties:
|
||||
- compatible: "renesas,usb-phy-r8a7742" if the device is a part of R8A7742 SoC.
|
||||
"renesas,usb-phy-r8a7743" if the device is a part of R8A7743 SoC.
|
||||
"renesas,usb-phy-r8a7744" if the device is a part of R8A7744 SoC.
|
||||
"renesas,usb-phy-r8a7745" if the device is a part of R8A7745 SoC.
|
||||
"renesas,usb-phy-r8a77470" if the device is a part of R8A77470 SoC.
|
||||
"renesas,usb-phy-r8a7790" if the device is a part of R8A7790 SoC.
|
||||
"renesas,usb-phy-r8a7791" if the device is a part of R8A7791 SoC.
|
||||
"renesas,usb-phy-r8a7794" if the device is a part of R8A7794 SoC.
|
||||
"renesas,rcar-gen2-usb-phy" for a generic R-Car Gen2 or
|
||||
RZ/G1 compatible device.
|
||||
|
||||
When compatible with the generic version, nodes must list the
|
||||
SoC-specific version corresponding to the platform first
|
||||
followed by the generic version.
|
||||
|
||||
- reg: offset and length of the register block.
|
||||
- #address-cells: number of address cells for the USB channel subnodes, must
|
||||
be <1>.
|
||||
- #size-cells: number of size cells for the USB channel subnodes, must be <0>.
|
||||
- clocks: clock phandle and specifier pair.
|
||||
- clock-names: string, clock input name, must be "usbhs".
|
||||
|
||||
The USB PHY device tree node should have the subnodes corresponding to the USB
|
||||
channels. These subnodes must contain the following properties:
|
||||
- reg: the USB controller selector; see the table below for the values.
|
||||
- #phy-cells: see phy-bindings.txt in the same directory, must be <1>.
|
||||
|
||||
The phandle's argument in the PHY specifier is the USB controller selector for
|
||||
the USB channel other than r8a77470 SoC; see the selector meanings below:
|
||||
|
||||
+-----------+---------------+---------------+
|
||||
|\ Selector | | |
|
||||
+ --------- + 0 | 1 |
|
||||
| Channel \| | |
|
||||
+-----------+---------------+---------------+
|
||||
| 0 | PCI EHCI/OHCI | HS-USB |
|
||||
| 2 | PCI EHCI/OHCI | xHCI |
|
||||
+-----------+---------------+---------------+
|
||||
|
||||
For r8a77470 SoC;see the selector meaning below:
|
||||
|
||||
+-----------+---------------+---------------+
|
||||
|\ Selector | | |
|
||||
+ --------- + 0 | 1 |
|
||||
| Channel \| | |
|
||||
+-----------+---------------+---------------+
|
||||
| 0 | EHCI/OHCI | HS-USB |
|
||||
+-----------+---------------+---------------+
|
||||
|
||||
Example (Lager board):
|
||||
|
||||
usb-phy@e6590100 {
|
||||
compatible = "renesas,usb-phy-r8a7790", "renesas,rcar-gen2-usb-phy";
|
||||
reg = <0 0xe6590100 0 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&cpg CPG_MOD 704>;
|
||||
clock-names = "usbhs";
|
||||
power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 704>;
|
||||
|
||||
usb0: usb-channel@0 {
|
||||
reg = <0>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
usb2: usb-channel@2 {
|
||||
reg = <2>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
Example (iWave RZ/G1C sbc):
|
||||
|
||||
usbphy0: usb-phy0@e6590100 {
|
||||
compatible = "renesas,usb-phy-r8a77470",
|
||||
"renesas,rcar-gen2-usb-phy";
|
||||
reg = <0 0xe6590100 0 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&cpg CPG_MOD 704>;
|
||||
clock-names = "usbhs";
|
||||
power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 704>;
|
||||
|
||||
usb0: usb-channel@0 {
|
||||
reg = <0>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
usbphy1: usb-phy@e6598100 {
|
||||
compatible = "renesas,usb-phy-r8a77470",
|
||||
"renesas,rcar-gen2-usb-phy";
|
||||
reg = <0 0xe6598100 0 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&cpg CPG_MOD 706>;
|
||||
clock-names = "usbhs";
|
||||
power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 706>;
|
||||
|
||||
usb1: usb-channel@0 {
|
||||
reg = <0>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
};
|
@ -0,0 +1,123 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/renesas,rcar-gen2-usb-phy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas R-Car Gen2 USB PHY
|
||||
|
||||
maintainers:
|
||||
- Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,usb-phy-r8a7742 # RZ/G1H
|
||||
- renesas,usb-phy-r8a7743 # RZ/G1M
|
||||
- renesas,usb-phy-r8a7744 # RZ/G1N
|
||||
- renesas,usb-phy-r8a7745 # RZ/G1E
|
||||
- renesas,usb-phy-r8a77470 # RZ/G1C
|
||||
- renesas,usb-phy-r8a7790 # R-Car H2
|
||||
- renesas,usb-phy-r8a7791 # R-Car M2-W
|
||||
- renesas,usb-phy-r8a7794 # R-Car E2
|
||||
- const: renesas,rcar-gen2-usb-phy # R-Car Gen2 or RZ/G1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: usbhs
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^usb-phy@[02]$":
|
||||
type: object
|
||||
description: Subnode corresponding to a USB channel.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: FIXME RZ/G1C supports channel 0 only
|
||||
enum: [0, 2]
|
||||
|
||||
'#phy-cells':
|
||||
description: |
|
||||
The phandle's argument in the PHY specifier is the USB controller
|
||||
selector for the USB channel.
|
||||
For RZ/G1C:
|
||||
- 0 for EHCI/OHCI
|
||||
- 1 for HS-USB
|
||||
For all other SoCS:
|
||||
- 0 for PCI EHCI/OHCI
|
||||
- 1 for HS-USB (channel 0) or xHCI (channel 2)
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- reg
|
||||
- '#phy-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- power-domains
|
||||
- usb-phy@0
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,usb-phy-r8a77470
|
||||
then:
|
||||
properties:
|
||||
usb-phy@2: false
|
||||
else:
|
||||
required:
|
||||
- usb-phy@2
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r8a7790-cpg-mssr.h>
|
||||
#include <dt-bindings/power/r8a7790-sysc.h>
|
||||
usb-phy-controller@e6590100 {
|
||||
compatible = "renesas,usb-phy-r8a7790", "renesas,rcar-gen2-usb-phy";
|
||||
reg = <0xe6590100 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&cpg CPG_MOD 704>;
|
||||
clock-names = "usbhs";
|
||||
power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 704>;
|
||||
|
||||
usb0: usb-phy@0 {
|
||||
reg = <0>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
usb2: usb-phy@2 {
|
||||
reg = <2>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
};
|
@ -0,0 +1,80 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/rockchip,pcie3-phy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rockchip PCIe v3 phy
|
||||
|
||||
maintainers:
|
||||
- Heiko Stuebner <heiko@sntech.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- rockchip,rk3568-pcie3-phy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: refclk_m
|
||||
- const: refclk_n
|
||||
- const: pclk
|
||||
|
||||
data-lanes:
|
||||
description: which lanes (by position) should be mapped to which
|
||||
controller (value). 0 means lane disabled, higher value means used.
|
||||
(controller-number +1 )
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 2
|
||||
maxItems: 16
|
||||
items:
|
||||
minimum: 0
|
||||
maximum: 16
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
reset-names:
|
||||
const: phy
|
||||
|
||||
rockchip,phy-grf:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: phandle to the syscon managing the phy "general register files"
|
||||
|
||||
rockchip,pipe-grf:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: phandle to the syscon managing the pipe "general register files"
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- rockchip,phy-grf
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/rk3568-cru.h>
|
||||
pcie30phy: phy@fe8c0000 {
|
||||
compatible = "rockchip,rk3568-pcie3-phy";
|
||||
reg = <0xfe8c0000 0x20000>;
|
||||
#phy-cells = <0>;
|
||||
clocks = <&pmucru CLK_PCIE30PHY_REF_M>,
|
||||
<&pmucru CLK_PCIE30PHY_REF_N>,
|
||||
<&cru PCLK_PCIE30PHY>;
|
||||
clock-names = "refclk_m", "refclk_n", "pclk";
|
||||
resets = <&cru SRST_PCIE30PHY>;
|
||||
reset-names = "phy";
|
||||
rockchip,phy-grf = <&pcie30_phy_grf>;
|
||||
};
|
@ -18,6 +18,7 @@ properties:
|
||||
- rockchip,px30-dsi-dphy
|
||||
- rockchip,rk3128-dsi-dphy
|
||||
- rockchip,rk3368-dsi-dphy
|
||||
- rockchip,rk3568-dsi-dphy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -20,6 +20,7 @@ properties:
|
||||
- rockchip,rk1808-csi-dphy
|
||||
- rockchip,rk3326-csi-dphy
|
||||
- rockchip,rk3368-csi-dphy
|
||||
- rockchip,rk3568-csi-dphy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -27,18 +27,12 @@ properties:
|
||||
- const: phy-pma
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: PLL reference clock
|
||||
- description: symbol clock for input symbol ( rx0-ch0 symbol clock)
|
||||
- description: symbol clock for input symbol ( rx1-ch1 symbol clock)
|
||||
- description: symbol clock for output symbol ( tx0 symbol clock)
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref_clk
|
||||
- const: rx1_symbol_clk
|
||||
- const: rx0_symbol_clk
|
||||
- const: tx0_symbol_clk
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
samsung,pmu-syscon:
|
||||
$ref: '/schemas/types.yaml#/definitions/phandle-array'
|
||||
@ -62,6 +56,39 @@ required:
|
||||
- clock-names
|
||||
- samsung,pmu-syscon
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos7-ufs-phy
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: PLL reference clock
|
||||
- description: symbol clock for input symbol (rx0-ch0 symbol clock)
|
||||
- description: symbol clock for input symbol (rx1-ch1 symbol clock)
|
||||
- description: symbol clock for output symbol (tx0 symbol clock)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref_clk
|
||||
- const: rx1_symbol_clk
|
||||
- const: rx0_symbol_clk
|
||||
- const: tx0_symbol_clk
|
||||
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: PLL reference clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref_clk
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
@ -0,0 +1,73 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) Sunplus Co., Ltd. 2021
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/phy/sunplus,sp7021-usb2-phy.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Sunplus SP7021 USB 2.0 PHY Controller
|
||||
|
||||
maintainers:
|
||||
- Vincent Shih <vincent.sunplus@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sunplus,sp7021-usb2-phy
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: UPHY register region
|
||||
- description: MOON4 register region
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: moon4
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
nvmem-cell-names:
|
||||
description: names corresponding to the nvmem cells of disconnect voltage
|
||||
const: disc_vol
|
||||
|
||||
nvmem-cells:
|
||||
description: nvmem cell address of disconnect voltage
|
||||
maxItems: 1
|
||||
|
||||
sunplus,disc-vol-addr-off:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: the otp address offset of disconnect voltage
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
- resets
|
||||
- "#phy-cells"
|
||||
- nvmem-cell-names
|
||||
- nvmem-cells
|
||||
- sunplus,disc-vol-addr-off
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sp_uphy0: usb-phy@9c004a80 {
|
||||
compatible = "sunplus,sp7021-usb2-phy";
|
||||
reg = <0x9c004a80 0x80>, <0x9c000248 0x10>;
|
||||
reg-names = "phy", "moon4";
|
||||
clocks = <&clkc 0x3d>;
|
||||
resets = <&rstc 0x2d>;
|
||||
#phy-cells = <0>;
|
||||
nvmem-cell-names = "disc_vol";
|
||||
nvmem-cells = <&disc_vol>;
|
||||
sunplus,disc-vol-addr-off = <0>;
|
||||
};
|
@ -53,12 +53,25 @@ properties:
|
||||
- ti,am43xx-phy-gmii-sel
|
||||
- ti,dm814-phy-gmii-sel
|
||||
- ti,am654-phy-gmii-sel
|
||||
- ti,j7200-cpsw5g-phy-gmii-sel
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#phy-cells': true
|
||||
|
||||
ti,qsgmii-main-ports:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: |
|
||||
Required only for QSGMII mode. Array to select the port for
|
||||
QSGMII main mode. Rest of the ports are selected as QSGMII_SUB
|
||||
ports automatically. Any one of the 4 CPSW5G ports can act as the
|
||||
main port with the rest of them being the QSGMII_SUB ports.
|
||||
maxItems: 1
|
||||
items:
|
||||
minimum: 1
|
||||
maximum: 4
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
@ -73,6 +86,18 @@ allOf:
|
||||
'#phy-cells':
|
||||
const: 1
|
||||
description: CPSW port number (starting from 1)
|
||||
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- ti,j7200-cpsw5g-phy-gmii-sel
|
||||
then:
|
||||
properties:
|
||||
ti,qsgmii-main-ports: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
@ -97,7 +122,7 @@ additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
phy_gmii_sel: phy-gmii-sel@650 {
|
||||
phy_gmii_sel: phy@650 {
|
||||
compatible = "ti,am3352-phy-gmii-sel";
|
||||
reg = <0x650 0x4>;
|
||||
#phy-cells = <2>;
|
||||
|
@ -16,19 +16,23 @@ properties:
|
||||
- ti,j721e-wiz-16g
|
||||
- ti,j721e-wiz-10g
|
||||
- ti,am64-wiz-10g
|
||||
- ti,j7200-wiz-10g
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 3
|
||||
minItems: 3
|
||||
maxItems: 4
|
||||
description: clock-specifier to represent input to the WIZ
|
||||
|
||||
clock-names:
|
||||
minItems: 3
|
||||
items:
|
||||
- const: fck
|
||||
- const: core_ref_clk
|
||||
- const: ext_ref_clk
|
||||
- const: core_ref1_clk
|
||||
|
||||
num-lanes:
|
||||
minimum: 1
|
||||
@ -79,10 +83,12 @@ properties:
|
||||
|
||||
refclk-dig:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: |
|
||||
WIZ node should have subnode for refclk_dig to select the reference
|
||||
clock source for the reference clock used in the PHY and PMA digital
|
||||
logic.
|
||||
deprecated: true
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 2
|
||||
@ -105,12 +111,19 @@ properties:
|
||||
- assigned-clocks
|
||||
- assigned-clock-parents
|
||||
|
||||
ti,scm:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: |
|
||||
phandle to System Control Module for syscon regmap access.
|
||||
|
||||
patternProperties:
|
||||
"^pll[0|1]-refclk$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: |
|
||||
WIZ node should have subnodes for each of the PLLs present in
|
||||
the SERDES.
|
||||
deprecated: true
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 2
|
||||
@ -133,9 +146,11 @@ patternProperties:
|
||||
|
||||
"^cmn-refclk1?-dig-div$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description:
|
||||
WIZ node should have subnodes for each of the PMA common refclock
|
||||
provided by the SERDES.
|
||||
deprecated: true
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
@ -170,6 +185,16 @@ required:
|
||||
- "#reset-cells"
|
||||
- ranges
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: ti,j7200-wiz-10g
|
||||
then:
|
||||
required:
|
||||
- ti,scm
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
10
MAINTAINERS
10
MAINTAINERS
@ -13548,6 +13548,7 @@ M: UNGLinuxDriver@microchip.com
|
||||
L: linux-mips@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/mips/mscc.txt
|
||||
F: Documentation/devicetree/bindings/phy/mscc,vsc7514-serdes.yaml
|
||||
F: Documentation/devicetree/bindings/power/reset/ocelot-reset.txt
|
||||
F: arch/mips/boot/dts/mscc/
|
||||
F: arch/mips/configs/generic/board-ocelot.config
|
||||
@ -19617,6 +19618,15 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml
|
||||
F: drivers/nvmem/sunplus-ocotp.c
|
||||
|
||||
SUNPLUS USB2 PHY DRIVER
|
||||
M: Vincent Shih <vincent.sunplus@gmail.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/phy/sunplus,sp7021-usb2-phy.yaml
|
||||
F: drivers/phy/sunplus/Kconfig
|
||||
F: drivers/phy/sunplus/Makefile
|
||||
F: drivers/phy/sunplus/phy-sunplus-usb2.c
|
||||
|
||||
SUNPLUS PWM DRIVER
|
||||
M: Hammer Hsieh <hammerh0314@gmail.com>
|
||||
S: Maintained
|
||||
|
@ -91,6 +91,7 @@ source "drivers/phy/rockchip/Kconfig"
|
||||
source "drivers/phy/samsung/Kconfig"
|
||||
source "drivers/phy/socionext/Kconfig"
|
||||
source "drivers/phy/st/Kconfig"
|
||||
source "drivers/phy/sunplus/Kconfig"
|
||||
source "drivers/phy/tegra/Kconfig"
|
||||
source "drivers/phy/ti/Kconfig"
|
||||
source "drivers/phy/intel/Kconfig"
|
||||
|
@ -31,6 +31,7 @@ obj-y += allwinner/ \
|
||||
samsung/ \
|
||||
socionext/ \
|
||||
st/ \
|
||||
sunplus/ \
|
||||
tegra/ \
|
||||
ti/ \
|
||||
xilinx/
|
||||
|
@ -768,7 +768,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
|
||||
if (data->cfg->dedicated_clocks)
|
||||
snprintf(name, sizeof(name), "usb%d_phy", i);
|
||||
else
|
||||
strlcpy(name, "usb_phy", sizeof(name));
|
||||
strscpy(name, "usb_phy", sizeof(name));
|
||||
|
||||
phy->clk = devm_clk_get(dev, name);
|
||||
if (IS_ERR(phy->clk)) {
|
||||
|
@ -197,7 +197,7 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
|
||||
struct phy_provider *phy;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct phy_axg_mipi_pcie_analog_priv *priv;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *np = dev->of_node, *parent_np;
|
||||
struct regmap *map;
|
||||
int ret;
|
||||
|
||||
@ -206,7 +206,9 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Get the hhi system controller node */
|
||||
map = syscon_node_to_regmap(of_get_parent(dev->of_node));
|
||||
parent_np = of_get_parent(dev->of_node);
|
||||
map = syscon_node_to_regmap(parent_np);
|
||||
of_node_put(parent_np);
|
||||
if (IS_ERR(map)) {
|
||||
dev_err(dev,
|
||||
"failed to get HHI regmap\n");
|
||||
|
@ -388,7 +388,6 @@ static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev)
|
||||
struct phy_g12a_usb3_pcie_priv *priv;
|
||||
struct phy_provider *phy_provider;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
@ -408,43 +407,24 @@ static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(priv->regmap_cr))
|
||||
return PTR_ERR(priv->regmap_cr);
|
||||
|
||||
priv->clk_ref = devm_clk_get(dev, "ref_clk");
|
||||
priv->clk_ref = devm_clk_get_enabled(dev, "ref_clk");
|
||||
if (IS_ERR(priv->clk_ref))
|
||||
return PTR_ERR(priv->clk_ref);
|
||||
|
||||
ret = clk_prepare_enable(priv->clk_ref);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->reset = devm_reset_control_array_get_exclusive(dev);
|
||||
if (IS_ERR(priv->reset)) {
|
||||
ret = PTR_ERR(priv->reset);
|
||||
goto err_disable_clk_ref;
|
||||
}
|
||||
if (IS_ERR(priv->reset))
|
||||
return PTR_ERR(priv->reset);
|
||||
|
||||
priv->phy = devm_phy_create(dev, np, &phy_g12a_usb3_pcie_ops);
|
||||
if (IS_ERR(priv->phy)) {
|
||||
ret = PTR_ERR(priv->phy);
|
||||
dev_err_probe(dev, ret, "failed to create PHY\n");
|
||||
goto err_disable_clk_ref;
|
||||
}
|
||||
if (IS_ERR(priv->phy))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->phy), "failed to create PHY\n");
|
||||
|
||||
phy_set_drvdata(priv->phy, priv);
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev,
|
||||
phy_g12a_usb3_pcie_xlate);
|
||||
if (IS_ERR(phy_provider)) {
|
||||
ret = PTR_ERR(phy_provider);
|
||||
goto err_disable_clk_ref;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable_clk_ref:
|
||||
clk_disable_unprepare(priv->clk_ref);
|
||||
|
||||
return ret;
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
}
|
||||
|
||||
static const struct of_device_id phy_g12a_usb3_pcie_of_match[] = {
|
||||
|
@ -413,44 +413,29 @@ static int intel_cbphy_fwnode_parse(struct intel_combo_phy *cbphy)
|
||||
u32 val;
|
||||
|
||||
cbphy->core_clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(cbphy->core_clk)) {
|
||||
ret = PTR_ERR(cbphy->core_clk);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Get clk failed:%d!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(cbphy->core_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(cbphy->core_clk),
|
||||
"Get clk failed!\n");
|
||||
|
||||
cbphy->core_rst = devm_reset_control_get_optional(dev, "core");
|
||||
if (IS_ERR(cbphy->core_rst)) {
|
||||
ret = PTR_ERR(cbphy->core_rst);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Get core reset control err: %d!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(cbphy->core_rst))
|
||||
return dev_err_probe(dev, PTR_ERR(cbphy->core_rst),
|
||||
"Get core reset control err!\n");
|
||||
|
||||
cbphy->phy_rst = devm_reset_control_get_optional(dev, "phy");
|
||||
if (IS_ERR(cbphy->phy_rst)) {
|
||||
ret = PTR_ERR(cbphy->phy_rst);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Get PHY reset control err: %d!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(cbphy->phy_rst))
|
||||
return dev_err_probe(dev, PTR_ERR(cbphy->phy_rst),
|
||||
"Get PHY reset control err!\n");
|
||||
|
||||
cbphy->iphy[0].app_rst = devm_reset_control_get_optional(dev, "iphy0");
|
||||
if (IS_ERR(cbphy->iphy[0].app_rst)) {
|
||||
ret = PTR_ERR(cbphy->iphy[0].app_rst);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Get phy0 reset control err: %d!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(cbphy->iphy[0].app_rst))
|
||||
return dev_err_probe(dev, PTR_ERR(cbphy->iphy[0].app_rst),
|
||||
"Get phy0 reset control err!\n");
|
||||
|
||||
cbphy->iphy[1].app_rst = devm_reset_control_get_optional(dev, "iphy1");
|
||||
if (IS_ERR(cbphy->iphy[1].app_rst)) {
|
||||
ret = PTR_ERR(cbphy->iphy[1].app_rst);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Get phy1 reset control err: %d!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(cbphy->iphy[1].app_rst))
|
||||
return dev_err_probe(dev, PTR_ERR(cbphy->iphy[1].app_rst),
|
||||
"Get phy1 reset control err!\n");
|
||||
|
||||
cbphy->app_base = devm_platform_ioremap_resource_byname(pdev, "app");
|
||||
if (IS_ERR(cbphy->app_base))
|
||||
|
@ -85,7 +85,7 @@ struct mtk_dp_phy {
|
||||
static int mtk_dp_phy_init(struct phy *phy)
|
||||
{
|
||||
struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
|
||||
u32 driving_params[] = {
|
||||
static const u32 driving_params[] = {
|
||||
DRIVING_PARAM_3_DEFAULT,
|
||||
DRIVING_PARAM_4_DEFAULT,
|
||||
DRIVING_PARAM_5_DEFAULT,
|
||||
|
@ -5,83 +5,66 @@
|
||||
*/
|
||||
|
||||
#include "phy-mtk-hdmi.h"
|
||||
#include "phy-mtk-io.h"
|
||||
|
||||
#define HDMI_CON0 0x00
|
||||
#define RG_HDMITX_DRV_IBIAS 0
|
||||
#define RG_HDMITX_DRV_IBIAS_MASK (0x3f << 0)
|
||||
#define RG_HDMITX_EN_SER 12
|
||||
#define RG_HDMITX_EN_SER_MASK (0x0f << 12)
|
||||
#define RG_HDMITX_EN_SLDO 16
|
||||
#define RG_HDMITX_EN_SLDO_MASK (0x0f << 16)
|
||||
#define RG_HDMITX_EN_PRED 20
|
||||
#define RG_HDMITX_EN_PRED_MASK (0x0f << 20)
|
||||
#define RG_HDMITX_EN_IMP 24
|
||||
#define RG_HDMITX_EN_IMP_MASK (0x0f << 24)
|
||||
#define RG_HDMITX_EN_DRV 28
|
||||
#define RG_HDMITX_EN_DRV_MASK (0x0f << 28)
|
||||
#define RG_HDMITX_DRV_IBIAS_MASK GENMASK(5, 0)
|
||||
#define RG_HDMITX_EN_SER_MASK GENMASK(15, 12)
|
||||
#define RG_HDMITX_EN_SLDO_MASK GENMASK(19, 16)
|
||||
#define RG_HDMITX_EN_PRED_MASK GENMASK(23, 20)
|
||||
#define RG_HDMITX_EN_IMP_MASK GENMASK(27, 24)
|
||||
#define RG_HDMITX_EN_DRV_MASK GENMASK(31, 28)
|
||||
|
||||
#define HDMI_CON1 0x04
|
||||
#define RG_HDMITX_PRED_IBIAS 18
|
||||
#define RG_HDMITX_PRED_IBIAS_MASK (0x0f << 18)
|
||||
#define RG_HDMITX_PRED_IMP (0x01 << 22)
|
||||
#define RG_HDMITX_DRV_IMP 26
|
||||
#define RG_HDMITX_DRV_IMP_MASK (0x3f << 26)
|
||||
#define RG_HDMITX_PRED_IBIAS_MASK GENMASK(21, 18)
|
||||
#define RG_HDMITX_PRED_IMP BIT(22)
|
||||
#define RG_HDMITX_DRV_IMP_MASK GENMASK(31, 26)
|
||||
|
||||
#define HDMI_CON2 0x08
|
||||
#define RG_HDMITX_EN_TX_CKLDO (0x01 << 0)
|
||||
#define RG_HDMITX_EN_TX_POSDIV (0x01 << 1)
|
||||
#define RG_HDMITX_TX_POSDIV 3
|
||||
#define RG_HDMITX_TX_POSDIV_MASK (0x03 << 3)
|
||||
#define RG_HDMITX_EN_MBIAS (0x01 << 6)
|
||||
#define RG_HDMITX_MBIAS_LPF_EN (0x01 << 7)
|
||||
#define RG_HDMITX_EN_TX_CKLDO BIT(0)
|
||||
#define RG_HDMITX_EN_TX_POSDIV BIT(1)
|
||||
#define RG_HDMITX_TX_POSDIV_MASK GENMASK(4, 3)
|
||||
#define RG_HDMITX_EN_MBIAS BIT(6)
|
||||
#define RG_HDMITX_MBIAS_LPF_EN BIT(7)
|
||||
|
||||
#define HDMI_CON4 0x10
|
||||
#define RG_HDMITX_RESERVE_MASK (0xffffffff << 0)
|
||||
#define RG_HDMITX_RESERVE_MASK GENMASK(31, 0)
|
||||
|
||||
#define HDMI_CON6 0x18
|
||||
#define RG_HTPLL_BR 0
|
||||
#define RG_HTPLL_BR_MASK (0x03 << 0)
|
||||
#define RG_HTPLL_BC 2
|
||||
#define RG_HTPLL_BC_MASK (0x03 << 2)
|
||||
#define RG_HTPLL_BP 4
|
||||
#define RG_HTPLL_BP_MASK (0x0f << 4)
|
||||
#define RG_HTPLL_IR 8
|
||||
#define RG_HTPLL_IR_MASK (0x0f << 8)
|
||||
#define RG_HTPLL_IC 12
|
||||
#define RG_HTPLL_IC_MASK (0x0f << 12)
|
||||
#define RG_HTPLL_POSDIV 16
|
||||
#define RG_HTPLL_POSDIV_MASK (0x03 << 16)
|
||||
#define RG_HTPLL_PREDIV 18
|
||||
#define RG_HTPLL_PREDIV_MASK (0x03 << 18)
|
||||
#define RG_HTPLL_FBKSEL 20
|
||||
#define RG_HTPLL_FBKSEL_MASK (0x03 << 20)
|
||||
#define RG_HTPLL_RLH_EN (0x01 << 22)
|
||||
#define RG_HTPLL_FBKDIV 24
|
||||
#define RG_HTPLL_FBKDIV_MASK (0x7f << 24)
|
||||
#define RG_HTPLL_EN (0x01 << 31)
|
||||
#define RG_HTPLL_BR_MASK GENMASK(1, 0)
|
||||
#define RG_HTPLL_BC_MASK GENMASK(3, 2)
|
||||
#define RG_HTPLL_BP_MASK GENMASK(7, 4)
|
||||
#define RG_HTPLL_IR_MASK GENMASK(11, 8)
|
||||
#define RG_HTPLL_IC_MASK GENMASK(15, 12)
|
||||
#define RG_HTPLL_POSDIV_MASK GENMASK(17, 16)
|
||||
#define RG_HTPLL_PREDIV_MASK GENMASK(19, 18)
|
||||
#define RG_HTPLL_FBKSEL_MASK GENMASK(21, 20)
|
||||
#define RG_HTPLL_RLH_EN BIT(22)
|
||||
#define RG_HTPLL_FBKDIV_MASK GENMASK(30, 24)
|
||||
#define RG_HTPLL_EN BIT(31)
|
||||
|
||||
#define HDMI_CON7 0x1c
|
||||
#define RG_HTPLL_AUTOK_EN (0x01 << 23)
|
||||
#define RG_HTPLL_DIVEN 28
|
||||
#define RG_HTPLL_DIVEN_MASK (0x07 << 28)
|
||||
#define RG_HTPLL_AUTOK_EN BIT(23)
|
||||
#define RG_HTPLL_DIVEN_MASK GENMASK(30, 28)
|
||||
|
||||
static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
void __iomem *base = hdmi_phy->regs;
|
||||
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
|
||||
mtk_phy_set_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
|
||||
mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
usleep_range(80, 100);
|
||||
return 0;
|
||||
}
|
||||
@ -89,20 +72,21 @@ static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
|
||||
static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
void __iomem *base = hdmi_phy->regs;
|
||||
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
|
||||
mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_EN);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);
|
||||
mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);
|
||||
mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);
|
||||
usleep_range(80, 100);
|
||||
}
|
||||
|
||||
@ -116,6 +100,7 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
void __iomem *base = hdmi_phy->regs;
|
||||
u32 pos_div;
|
||||
|
||||
if (rate <= 64000000)
|
||||
@ -125,37 +110,25 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
else
|
||||
pos_div = 1;
|
||||
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_PREDIV_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IC),
|
||||
RG_HTPLL_IC_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IR),
|
||||
RG_HTPLL_IR_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON2, (pos_div << RG_HDMITX_TX_POSDIV),
|
||||
RG_HDMITX_TX_POSDIV_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (1 << RG_HTPLL_FBKSEL),
|
||||
RG_HTPLL_FBKSEL_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (19 << RG_HTPLL_FBKDIV),
|
||||
RG_HTPLL_FBKDIV_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON7, (0x2 << RG_HTPLL_DIVEN),
|
||||
RG_HTPLL_DIVEN_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0xc << RG_HTPLL_BP),
|
||||
RG_HTPLL_BP_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x2 << RG_HTPLL_BC),
|
||||
RG_HTPLL_BC_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_BR),
|
||||
RG_HTPLL_BR_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_PREDIV_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
|
||||
mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_IC_MASK, 0x1);
|
||||
mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_IR_MASK, 0x1);
|
||||
mtk_phy_update_field(base + HDMI_CON2, RG_HDMITX_TX_POSDIV_MASK, pos_div);
|
||||
mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_FBKSEL_MASK, 1);
|
||||
mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_FBKDIV_MASK, 19);
|
||||
mtk_phy_update_field(base + HDMI_CON7, RG_HTPLL_DIVEN_MASK, 0x2);
|
||||
mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_BP_MASK, 0xc);
|
||||
mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_BC_MASK, 0x2);
|
||||
mtk_phy_update_field(base + HDMI_CON6, RG_HTPLL_BR_MASK, 0x1);
|
||||
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PRED_IMP);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x3 << RG_HDMITX_PRED_IBIAS),
|
||||
RG_HDMITX_PRED_IBIAS_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_IMP_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x28 << RG_HDMITX_DRV_IMP),
|
||||
RG_HDMITX_DRV_IMP_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4, 0x28, RG_HDMITX_RESERVE_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0, (0xa << RG_HDMITX_DRV_IBIAS),
|
||||
RG_HDMITX_DRV_IBIAS_MASK);
|
||||
mtk_phy_clear_bits(base + HDMI_CON1, RG_HDMITX_PRED_IMP);
|
||||
mtk_phy_update_field(base + HDMI_CON1, RG_HDMITX_PRED_IBIAS_MASK, 0x3);
|
||||
mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_IMP_MASK);
|
||||
mtk_phy_update_field(base + HDMI_CON1, RG_HDMITX_DRV_IMP_MASK, 0x28);
|
||||
mtk_phy_update_field(base + HDMI_CON4, RG_HDMITX_RESERVE_MASK, 0x28);
|
||||
mtk_phy_update_field(base + HDMI_CON0, RG_HDMITX_DRV_IBIAS_MASK, 0xa);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -164,9 +137,10 @@ static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
unsigned long out_rate, val;
|
||||
u32 tmp;
|
||||
|
||||
val = (readl(hdmi_phy->regs + HDMI_CON6)
|
||||
& RG_HTPLL_PREDIV_MASK) >> RG_HTPLL_PREDIV;
|
||||
tmp = readl(hdmi_phy->regs + HDMI_CON6);
|
||||
val = FIELD_GET(RG_HTPLL_PREDIV_MASK, tmp);
|
||||
switch (val) {
|
||||
case 0x00:
|
||||
out_rate = parent_rate;
|
||||
@ -179,14 +153,14 @@ static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
|
||||
break;
|
||||
}
|
||||
|
||||
val = (readl(hdmi_phy->regs + HDMI_CON6)
|
||||
& RG_HTPLL_FBKDIV_MASK) >> RG_HTPLL_FBKDIV;
|
||||
val = FIELD_GET(RG_HTPLL_FBKDIV_MASK, tmp);
|
||||
out_rate *= (val + 1) * 2;
|
||||
val = (readl(hdmi_phy->regs + HDMI_CON2)
|
||||
& RG_HDMITX_TX_POSDIV_MASK);
|
||||
out_rate >>= (val >> RG_HDMITX_TX_POSDIV);
|
||||
|
||||
if (readl(hdmi_phy->regs + HDMI_CON2) & RG_HDMITX_EN_TX_POSDIV)
|
||||
tmp = readl(hdmi_phy->regs + HDMI_CON2);
|
||||
val = FIELD_GET(RG_HDMITX_TX_POSDIV_MASK, tmp);
|
||||
out_rate >>= val;
|
||||
|
||||
if (tmp & RG_HDMITX_EN_TX_POSDIV)
|
||||
out_rate /= 5;
|
||||
|
||||
return out_rate;
|
||||
@ -202,37 +176,41 @@ static const struct clk_ops mtk_hdmi_phy_pll_ops = {
|
||||
|
||||
static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
|
||||
{
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
|
||||
void __iomem *base = hdmi_phy->regs;
|
||||
|
||||
mtk_phy_set_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON6, RG_HTPLL_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
|
||||
mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
usleep_range(80, 100);
|
||||
}
|
||||
|
||||
static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
|
||||
{
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
void __iomem *base = hdmi_phy->regs;
|
||||
|
||||
mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
|
||||
mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_EN);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON2, RG_HDMITX_EN_MBIAS);
|
||||
mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_POSDIV_MASK);
|
||||
mtk_phy_clear_bits(base + HDMI_CON6, RG_HTPLL_RLH_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON7, RG_HTPLL_AUTOK_EN);
|
||||
usleep_range(80, 100);
|
||||
}
|
||||
|
||||
|
@ -5,121 +5,99 @@
|
||||
*/
|
||||
|
||||
#include "phy-mtk-hdmi.h"
|
||||
#include "phy-mtk-io.h"
|
||||
|
||||
#define HDMI_CON0 0x00
|
||||
#define RG_HDMITX_PLL_EN BIT(31)
|
||||
#define RG_HDMITX_PLL_FBKDIV (0x7f << 24)
|
||||
#define PLL_FBKDIV_SHIFT 24
|
||||
#define RG_HDMITX_PLL_FBKSEL (0x3 << 22)
|
||||
#define PLL_FBKSEL_SHIFT 22
|
||||
#define RG_HDMITX_PLL_PREDIV (0x3 << 20)
|
||||
#define PREDIV_SHIFT 20
|
||||
#define RG_HDMITX_PLL_POSDIV (0x3 << 18)
|
||||
#define POSDIV_SHIFT 18
|
||||
#define RG_HDMITX_PLL_RST_DLY (0x3 << 16)
|
||||
#define RG_HDMITX_PLL_IR (0xf << 12)
|
||||
#define PLL_IR_SHIFT 12
|
||||
#define RG_HDMITX_PLL_IC (0xf << 8)
|
||||
#define PLL_IC_SHIFT 8
|
||||
#define RG_HDMITX_PLL_BP (0xf << 4)
|
||||
#define PLL_BP_SHIFT 4
|
||||
#define RG_HDMITX_PLL_BR (0x3 << 2)
|
||||
#define PLL_BR_SHIFT 2
|
||||
#define RG_HDMITX_PLL_BC (0x3 << 0)
|
||||
#define PLL_BC_SHIFT 0
|
||||
#define RG_HDMITX_PLL_FBKDIV GENMASK(30, 24)
|
||||
#define RG_HDMITX_PLL_FBKSEL GENMASK(23, 22)
|
||||
#define RG_HDMITX_PLL_PREDIV GENMASK(21, 20)
|
||||
#define RG_HDMITX_PLL_POSDIV GENMASK(19, 18)
|
||||
#define RG_HDMITX_PLL_RST_DLY GENMASK(17, 16)
|
||||
#define RG_HDMITX_PLL_IR GENMASK(15, 12)
|
||||
#define RG_HDMITX_PLL_IC GENMASK(11, 8)
|
||||
#define RG_HDMITX_PLL_BP GENMASK(7, 4)
|
||||
#define RG_HDMITX_PLL_BR GENMASK(3, 2)
|
||||
#define RG_HDMITX_PLL_BC GENMASK(1, 0)
|
||||
#define HDMI_CON1 0x04
|
||||
#define RG_HDMITX_PLL_DIVEN (0x7 << 29)
|
||||
#define PLL_DIVEN_SHIFT 29
|
||||
#define RG_HDMITX_PLL_DIVEN GENMASK(31, 29)
|
||||
#define RG_HDMITX_PLL_AUTOK_EN BIT(28)
|
||||
#define RG_HDMITX_PLL_AUTOK_KF (0x3 << 26)
|
||||
#define RG_HDMITX_PLL_AUTOK_KS (0x3 << 24)
|
||||
#define RG_HDMITX_PLL_AUTOK_KF GENMASK(27, 26)
|
||||
#define RG_HDMITX_PLL_AUTOK_KS GENMASK(25, 24)
|
||||
#define RG_HDMITX_PLL_AUTOK_LOAD BIT(23)
|
||||
#define RG_HDMITX_PLL_BAND (0x3f << 16)
|
||||
#define RG_HDMITX_PLL_BAND GENMASK(21, 16)
|
||||
#define RG_HDMITX_PLL_REF_SEL BIT(15)
|
||||
#define RG_HDMITX_PLL_BIAS_EN BIT(14)
|
||||
#define RG_HDMITX_PLL_BIAS_LPF_EN BIT(13)
|
||||
#define RG_HDMITX_PLL_TXDIV_EN BIT(12)
|
||||
#define RG_HDMITX_PLL_TXDIV (0x3 << 10)
|
||||
#define PLL_TXDIV_SHIFT 10
|
||||
#define RG_HDMITX_PLL_TXDIV GENMASK(11, 10)
|
||||
#define RG_HDMITX_PLL_LVROD_EN BIT(9)
|
||||
#define RG_HDMITX_PLL_MONVC_EN BIT(8)
|
||||
#define RG_HDMITX_PLL_MONCK_EN BIT(7)
|
||||
#define RG_HDMITX_PLL_MONREF_EN BIT(6)
|
||||
#define RG_HDMITX_PLL_TST_EN BIT(5)
|
||||
#define RG_HDMITX_PLL_TST_CK_EN BIT(4)
|
||||
#define RG_HDMITX_PLL_TST_SEL (0xf << 0)
|
||||
#define RG_HDMITX_PLL_TST_SEL GENMASK(3, 0)
|
||||
#define HDMI_CON2 0x08
|
||||
#define RGS_HDMITX_PLL_AUTOK_BAND (0x7f << 8)
|
||||
#define RGS_HDMITX_PLL_AUTOK_BAND GENMASK(14, 8)
|
||||
#define RGS_HDMITX_PLL_AUTOK_FAIL BIT(1)
|
||||
#define RG_HDMITX_EN_TX_CKLDO BIT(0)
|
||||
#define HDMI_CON3 0x0c
|
||||
#define RG_HDMITX_SER_EN (0xf << 28)
|
||||
#define RG_HDMITX_PRD_EN (0xf << 24)
|
||||
#define RG_HDMITX_PRD_IMP_EN (0xf << 20)
|
||||
#define RG_HDMITX_DRV_EN (0xf << 16)
|
||||
#define RG_HDMITX_DRV_IMP_EN (0xf << 12)
|
||||
#define DRV_IMP_EN_SHIFT 12
|
||||
#define RG_HDMITX_SER_EN GENMASK(31, 28)
|
||||
#define RG_HDMITX_PRD_EN GENMASK(27, 24)
|
||||
#define RG_HDMITX_PRD_IMP_EN GENMASK(23, 20)
|
||||
#define RG_HDMITX_DRV_EN GENMASK(19, 16)
|
||||
#define RG_HDMITX_DRV_IMP_EN GENMASK(15, 12)
|
||||
#define RG_HDMITX_MHLCK_FORCE BIT(10)
|
||||
#define RG_HDMITX_MHLCK_PPIX_EN BIT(9)
|
||||
#define RG_HDMITX_MHLCK_EN BIT(8)
|
||||
#define RG_HDMITX_SER_DIN_SEL (0xf << 4)
|
||||
#define RG_HDMITX_SER_DIN_SEL GENMASK(7, 4)
|
||||
#define RG_HDMITX_SER_5T1_BIST_EN BIT(3)
|
||||
#define RG_HDMITX_SER_BIST_TOG BIT(2)
|
||||
#define RG_HDMITX_SER_DIN_TOG BIT(1)
|
||||
#define RG_HDMITX_SER_CLKDIG_INV BIT(0)
|
||||
#define HDMI_CON4 0x10
|
||||
#define RG_HDMITX_PRD_IBIAS_CLK (0xf << 24)
|
||||
#define RG_HDMITX_PRD_IBIAS_D2 (0xf << 16)
|
||||
#define RG_HDMITX_PRD_IBIAS_D1 (0xf << 8)
|
||||
#define RG_HDMITX_PRD_IBIAS_D0 (0xf << 0)
|
||||
#define PRD_IBIAS_CLK_SHIFT 24
|
||||
#define PRD_IBIAS_D2_SHIFT 16
|
||||
#define PRD_IBIAS_D1_SHIFT 8
|
||||
#define PRD_IBIAS_D0_SHIFT 0
|
||||
#define RG_HDMITX_PRD_IBIAS_CLK GENMASK(27, 24)
|
||||
#define RG_HDMITX_PRD_IBIAS_D2 GENMASK(19, 16)
|
||||
#define RG_HDMITX_PRD_IBIAS_D1 GENMASK(11, 8)
|
||||
#define RG_HDMITX_PRD_IBIAS_D0 GENMASK(3, 0)
|
||||
#define HDMI_CON5 0x14
|
||||
#define RG_HDMITX_DRV_IBIAS_CLK (0x3f << 24)
|
||||
#define RG_HDMITX_DRV_IBIAS_D2 (0x3f << 16)
|
||||
#define RG_HDMITX_DRV_IBIAS_D1 (0x3f << 8)
|
||||
#define RG_HDMITX_DRV_IBIAS_D0 (0x3f << 0)
|
||||
#define DRV_IBIAS_CLK_SHIFT 24
|
||||
#define DRV_IBIAS_D2_SHIFT 16
|
||||
#define DRV_IBIAS_D1_SHIFT 8
|
||||
#define DRV_IBIAS_D0_SHIFT 0
|
||||
#define RG_HDMITX_DRV_IBIAS_CLK GENMASK(29, 24)
|
||||
#define RG_HDMITX_DRV_IBIAS_D2 GENMASK(21, 16)
|
||||
#define RG_HDMITX_DRV_IBIAS_D1 GENMASK(13, 8)
|
||||
#define RG_HDMITX_DRV_IBIAS_D0 GENMASK(5, 0)
|
||||
#define HDMI_CON6 0x18
|
||||
#define RG_HDMITX_DRV_IMP_CLK (0x3f << 24)
|
||||
#define RG_HDMITX_DRV_IMP_D2 (0x3f << 16)
|
||||
#define RG_HDMITX_DRV_IMP_D1 (0x3f << 8)
|
||||
#define RG_HDMITX_DRV_IMP_D0 (0x3f << 0)
|
||||
#define DRV_IMP_CLK_SHIFT 24
|
||||
#define DRV_IMP_D2_SHIFT 16
|
||||
#define DRV_IMP_D1_SHIFT 8
|
||||
#define DRV_IMP_D0_SHIFT 0
|
||||
#define RG_HDMITX_DRV_IMP_CLK GENMASK(29, 24)
|
||||
#define RG_HDMITX_DRV_IMP_D2 GENMASK(21, 16)
|
||||
#define RG_HDMITX_DRV_IMP_D1 GENMASK(13, 8)
|
||||
#define RG_HDMITX_DRV_IMP_D0 GENMASK(5, 0)
|
||||
#define HDMI_CON7 0x1c
|
||||
#define RG_HDMITX_MHLCK_DRV_IBIAS (0x1f << 27)
|
||||
#define RG_HDMITX_SER_DIN (0x3ff << 16)
|
||||
#define RG_HDMITX_CHLDC_TST (0xf << 12)
|
||||
#define RG_HDMITX_CHLCK_TST (0xf << 8)
|
||||
#define RG_HDMITX_RESERVE (0xff << 0)
|
||||
#define RG_HDMITX_MHLCK_DRV_IBIAS GENMASK(31, 27)
|
||||
#define RG_HDMITX_SER_DIN GENMASK(25, 16)
|
||||
#define RG_HDMITX_CHLDC_TST GENMASK(15, 12)
|
||||
#define RG_HDMITX_CHLCK_TST GENMASK(11, 8)
|
||||
#define RG_HDMITX_RESERVE GENMASK(7, 0)
|
||||
#define HDMI_CON8 0x20
|
||||
#define RGS_HDMITX_2T1_LEV (0xf << 16)
|
||||
#define RGS_HDMITX_2T1_EDG (0xf << 12)
|
||||
#define RGS_HDMITX_5T1_LEV (0xf << 8)
|
||||
#define RGS_HDMITX_5T1_EDG (0xf << 4)
|
||||
#define RGS_HDMITX_2T1_LEV GENMASK(19, 16)
|
||||
#define RGS_HDMITX_2T1_EDG GENMASK(15, 12)
|
||||
#define RGS_HDMITX_5T1_LEV GENMASK(11, 8)
|
||||
#define RGS_HDMITX_5T1_EDG GENMASK(7, 4)
|
||||
#define RGS_HDMITX_PLUG_TST BIT(0)
|
||||
|
||||
static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
void __iomem *base = hdmi_phy->regs;
|
||||
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3, RG_HDMITX_MHLCK_EN);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_PLL_POSDIV);
|
||||
mtk_phy_clear_bits(base + HDMI_CON3, RG_HDMITX_MHLCK_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
|
||||
usleep_range(100, 150);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_PLL_EN);
|
||||
usleep_range(100, 150);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -127,15 +105,16 @@ static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
|
||||
static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
void __iomem *base = hdmi_phy->regs;
|
||||
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
|
||||
usleep_range(100, 150);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_PLL_EN);
|
||||
usleep_range(100, 150);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON0, RG_HDMITX_PLL_POSDIV);
|
||||
mtk_phy_clear_bits(base + HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
|
||||
usleep_range(100, 150);
|
||||
}
|
||||
|
||||
@ -157,6 +136,7 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
void __iomem *base = hdmi_phy->regs;
|
||||
unsigned int pre_div;
|
||||
unsigned int div;
|
||||
unsigned int pre_ibias;
|
||||
@ -177,65 +157,57 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
div = 1;
|
||||
}
|
||||
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
|
||||
(pre_div << PREDIV_SHIFT), RG_HDMITX_PLL_PREDIV);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
|
||||
(0x1 << PLL_IC_SHIFT) | (0x1 << PLL_IR_SHIFT),
|
||||
RG_HDMITX_PLL_IC | RG_HDMITX_PLL_IR);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
|
||||
(div << PLL_TXDIV_SHIFT), RG_HDMITX_PLL_TXDIV);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
|
||||
(0x1 << PLL_FBKSEL_SHIFT) | (19 << PLL_FBKDIV_SHIFT),
|
||||
RG_HDMITX_PLL_FBKSEL | RG_HDMITX_PLL_FBKDIV);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
|
||||
(0x2 << PLL_DIVEN_SHIFT), RG_HDMITX_PLL_DIVEN);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
|
||||
(0xc << PLL_BP_SHIFT) | (0x2 << PLL_BC_SHIFT) |
|
||||
(0x1 << PLL_BR_SHIFT),
|
||||
RG_HDMITX_PLL_BP | RG_HDMITX_PLL_BC |
|
||||
RG_HDMITX_PLL_BR);
|
||||
mtk_phy_update_field(base + HDMI_CON0, RG_HDMITX_PLL_PREDIV, pre_div);
|
||||
mtk_phy_set_bits(base + HDMI_CON0, RG_HDMITX_PLL_POSDIV);
|
||||
mtk_phy_update_bits(base + HDMI_CON0,
|
||||
RG_HDMITX_PLL_IC | RG_HDMITX_PLL_IR,
|
||||
FIELD_PREP(RG_HDMITX_PLL_IC, 0x1) |
|
||||
FIELD_PREP(RG_HDMITX_PLL_IR, 0x1));
|
||||
mtk_phy_update_field(base + HDMI_CON1, RG_HDMITX_PLL_TXDIV, div);
|
||||
mtk_phy_update_bits(base + HDMI_CON0,
|
||||
RG_HDMITX_PLL_FBKSEL | RG_HDMITX_PLL_FBKDIV,
|
||||
FIELD_PREP(RG_HDMITX_PLL_FBKSEL, 0x1) |
|
||||
FIELD_PREP(RG_HDMITX_PLL_FBKDIV, 19));
|
||||
mtk_phy_update_field(base + HDMI_CON1, RG_HDMITX_PLL_DIVEN, 0x2);
|
||||
mtk_phy_update_bits(base + HDMI_CON0,
|
||||
RG_HDMITX_PLL_BP | RG_HDMITX_PLL_BC |
|
||||
RG_HDMITX_PLL_BR,
|
||||
FIELD_PREP(RG_HDMITX_PLL_BP, 0xc) |
|
||||
FIELD_PREP(RG_HDMITX_PLL_BC, 0x2) |
|
||||
FIELD_PREP(RG_HDMITX_PLL_BR, 0x1));
|
||||
if (rate < 165000000) {
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
|
||||
RG_HDMITX_PRD_IMP_EN);
|
||||
mtk_phy_clear_bits(base + HDMI_CON3, RG_HDMITX_PRD_IMP_EN);
|
||||
pre_ibias = 0x3;
|
||||
imp_en = 0x0;
|
||||
hdmi_ibias = hdmi_phy->ibias;
|
||||
} else {
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
|
||||
RG_HDMITX_PRD_IMP_EN);
|
||||
mtk_phy_set_bits(base + HDMI_CON3, RG_HDMITX_PRD_IMP_EN);
|
||||
pre_ibias = 0x6;
|
||||
imp_en = 0xf;
|
||||
hdmi_ibias = hdmi_phy->ibias_up;
|
||||
}
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4,
|
||||
(pre_ibias << PRD_IBIAS_CLK_SHIFT) |
|
||||
(pre_ibias << PRD_IBIAS_D2_SHIFT) |
|
||||
(pre_ibias << PRD_IBIAS_D1_SHIFT) |
|
||||
(pre_ibias << PRD_IBIAS_D0_SHIFT),
|
||||
RG_HDMITX_PRD_IBIAS_CLK |
|
||||
RG_HDMITX_PRD_IBIAS_D2 |
|
||||
RG_HDMITX_PRD_IBIAS_D1 |
|
||||
RG_HDMITX_PRD_IBIAS_D0);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON3,
|
||||
(imp_en << DRV_IMP_EN_SHIFT),
|
||||
RG_HDMITX_DRV_IMP_EN);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6,
|
||||
(hdmi_phy->drv_imp_clk << DRV_IMP_CLK_SHIFT) |
|
||||
(hdmi_phy->drv_imp_d2 << DRV_IMP_D2_SHIFT) |
|
||||
(hdmi_phy->drv_imp_d1 << DRV_IMP_D1_SHIFT) |
|
||||
(hdmi_phy->drv_imp_d0 << DRV_IMP_D0_SHIFT),
|
||||
RG_HDMITX_DRV_IMP_CLK | RG_HDMITX_DRV_IMP_D2 |
|
||||
RG_HDMITX_DRV_IMP_D1 | RG_HDMITX_DRV_IMP_D0);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON5,
|
||||
(hdmi_ibias << DRV_IBIAS_CLK_SHIFT) |
|
||||
(hdmi_ibias << DRV_IBIAS_D2_SHIFT) |
|
||||
(hdmi_ibias << DRV_IBIAS_D1_SHIFT) |
|
||||
(hdmi_ibias << DRV_IBIAS_D0_SHIFT),
|
||||
RG_HDMITX_DRV_IBIAS_CLK |
|
||||
RG_HDMITX_DRV_IBIAS_D2 |
|
||||
RG_HDMITX_DRV_IBIAS_D1 |
|
||||
RG_HDMITX_DRV_IBIAS_D0);
|
||||
mtk_phy_update_bits(base + HDMI_CON4,
|
||||
RG_HDMITX_PRD_IBIAS_CLK | RG_HDMITX_PRD_IBIAS_D2 |
|
||||
RG_HDMITX_PRD_IBIAS_D1 | RG_HDMITX_PRD_IBIAS_D0,
|
||||
FIELD_PREP(RG_HDMITX_PRD_IBIAS_CLK, pre_ibias) |
|
||||
FIELD_PREP(RG_HDMITX_PRD_IBIAS_D2, pre_ibias) |
|
||||
FIELD_PREP(RG_HDMITX_PRD_IBIAS_D1, pre_ibias) |
|
||||
FIELD_PREP(RG_HDMITX_PRD_IBIAS_D0, pre_ibias));
|
||||
mtk_phy_update_field(base + HDMI_CON3, RG_HDMITX_DRV_IMP_EN, imp_en);
|
||||
mtk_phy_update_bits(base + HDMI_CON6,
|
||||
RG_HDMITX_DRV_IMP_CLK | RG_HDMITX_DRV_IMP_D2 |
|
||||
RG_HDMITX_DRV_IMP_D1 | RG_HDMITX_DRV_IMP_D0,
|
||||
FIELD_PREP(RG_HDMITX_DRV_IMP_CLK, hdmi_phy->drv_imp_clk) |
|
||||
FIELD_PREP(RG_HDMITX_DRV_IMP_D2, hdmi_phy->drv_imp_d2) |
|
||||
FIELD_PREP(RG_HDMITX_DRV_IMP_D1, hdmi_phy->drv_imp_d1) |
|
||||
FIELD_PREP(RG_HDMITX_DRV_IMP_D0, hdmi_phy->drv_imp_d0));
|
||||
mtk_phy_update_bits(base + HDMI_CON5,
|
||||
RG_HDMITX_DRV_IBIAS_CLK | RG_HDMITX_DRV_IBIAS_D2 |
|
||||
RG_HDMITX_DRV_IBIAS_D1 | RG_HDMITX_DRV_IBIAS_D0,
|
||||
FIELD_PREP(RG_HDMITX_DRV_IBIAS_CLK, hdmi_ibias) |
|
||||
FIELD_PREP(RG_HDMITX_DRV_IBIAS_D2, hdmi_ibias) |
|
||||
FIELD_PREP(RG_HDMITX_DRV_IBIAS_D1, hdmi_ibias) |
|
||||
FIELD_PREP(RG_HDMITX_DRV_IBIAS_D0, hdmi_ibias));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -257,17 +229,17 @@ static const struct clk_ops mtk_hdmi_phy_pll_ops = {
|
||||
|
||||
static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
|
||||
{
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
|
||||
RG_HDMITX_SER_EN | RG_HDMITX_PRD_EN |
|
||||
RG_HDMITX_DRV_EN);
|
||||
mtk_phy_set_bits(hdmi_phy->regs + HDMI_CON3,
|
||||
RG_HDMITX_SER_EN | RG_HDMITX_PRD_EN |
|
||||
RG_HDMITX_DRV_EN);
|
||||
usleep_range(100, 150);
|
||||
}
|
||||
|
||||
static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
|
||||
{
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
|
||||
RG_HDMITX_DRV_EN | RG_HDMITX_PRD_EN |
|
||||
RG_HDMITX_SER_EN);
|
||||
mtk_phy_clear_bits(hdmi_phy->regs + HDMI_CON3,
|
||||
RG_HDMITX_DRV_EN | RG_HDMITX_PRD_EN |
|
||||
RG_HDMITX_SER_EN);
|
||||
}
|
||||
|
||||
struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf = {
|
||||
|
@ -15,39 +15,6 @@ static const struct phy_ops mtk_hdmi_phy_dev_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
|
||||
u32 bits)
|
||||
{
|
||||
void __iomem *reg = hdmi_phy->regs + offset;
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl(reg);
|
||||
tmp &= ~bits;
|
||||
writel(tmp, reg);
|
||||
}
|
||||
|
||||
void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
|
||||
u32 bits)
|
||||
{
|
||||
void __iomem *reg = hdmi_phy->regs + offset;
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl(reg);
|
||||
tmp |= bits;
|
||||
writel(tmp, reg);
|
||||
}
|
||||
|
||||
void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
|
||||
u32 val, u32 mask)
|
||||
{
|
||||
void __iomem *reg = hdmi_phy->regs + offset;
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl(reg);
|
||||
tmp = (tmp & ~mask) | (val & mask);
|
||||
writel(tmp, reg);
|
||||
}
|
||||
|
||||
inline struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct mtk_hdmi_phy, pll_hw);
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
@ -42,12 +41,6 @@ struct mtk_hdmi_phy {
|
||||
unsigned int ibias_up;
|
||||
};
|
||||
|
||||
void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
|
||||
u32 bits);
|
||||
void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
|
||||
u32 bits);
|
||||
void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
|
||||
u32 val, u32 mask);
|
||||
struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw);
|
||||
|
||||
extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#ifndef __PHY_MTK_H__
|
||||
#define __PHY_MTK_H__
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
static inline void mtk_phy_clear_bits(void __iomem *reg, u32 bits)
|
||||
@ -35,4 +36,11 @@ static inline void mtk_phy_update_bits(void __iomem *reg, u32 mask, u32 val)
|
||||
writel(tmp, reg);
|
||||
}
|
||||
|
||||
/* field @mask shall be constant and continuous */
|
||||
#define mtk_phy_update_field(reg, mask, val) \
|
||||
({ \
|
||||
typeof(mask) mask_ = (mask); \
|
||||
mtk_phy_update_bits(reg, mask_, FIELD_PREP(mask_, val)); \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
@ -4,14 +4,15 @@
|
||||
* Author: jitao.shi <jitao.shi@mediatek.com>
|
||||
*/
|
||||
|
||||
#include "phy-mtk-io.h"
|
||||
#include "phy-mtk-mipi-dsi.h"
|
||||
|
||||
#define MIPITX_DSI_CON 0x00
|
||||
#define RG_DSI_LDOCORE_EN BIT(0)
|
||||
#define RG_DSI_CKG_LDOOUT_EN BIT(1)
|
||||
#define RG_DSI_BCLK_SEL (3 << 2)
|
||||
#define RG_DSI_LD_IDX_SEL (7 << 4)
|
||||
#define RG_DSI_PHYCLK_SEL (2 << 8)
|
||||
#define RG_DSI_BCLK_SEL GENMASK(3, 2)
|
||||
#define RG_DSI_LD_IDX_SEL GENMASK(6, 4)
|
||||
#define RG_DSI_PHYCLK_SEL GENMASK(9, 8)
|
||||
#define RG_DSI_DSICLK_FREQ_SEL BIT(10)
|
||||
#define RG_DSI_LPTX_CLMP_EN BIT(11)
|
||||
|
||||
@ -27,41 +28,46 @@
|
||||
#define RG_DSI_LNTx_LPTX_IMINUS BIT(4)
|
||||
#define RG_DSI_LNTx_LPCD_IPLUS BIT(5)
|
||||
#define RG_DSI_LNTx_LPCD_IMINUS BIT(6)
|
||||
#define RG_DSI_LNTx_RT_CODE (0xf << 8)
|
||||
#define RG_DSI_LNTx_RT_CODE GENMASK(11, 8)
|
||||
|
||||
#define MIPITX_DSI_TOP_CON 0x40
|
||||
#define RG_DSI_LNT_INTR_EN BIT(0)
|
||||
#define RG_DSI_LNT_HS_BIAS_EN BIT(1)
|
||||
#define RG_DSI_LNT_IMP_CAL_EN BIT(2)
|
||||
#define RG_DSI_LNT_TESTMODE_EN BIT(3)
|
||||
#define RG_DSI_LNT_IMP_CAL_CODE (0xf << 4)
|
||||
#define RG_DSI_LNT_AIO_SEL (7 << 8)
|
||||
#define RG_DSI_LNT_IMP_CAL_CODE GENMASK(7, 4)
|
||||
#define RG_DSI_LNT_AIO_SEL GENMASK(10, 8)
|
||||
#define RG_DSI_PAD_TIE_LOW_EN BIT(11)
|
||||
#define RG_DSI_DEBUG_INPUT_EN BIT(12)
|
||||
#define RG_DSI_PRESERVE (7 << 13)
|
||||
#define RG_DSI_PRESERVE GENMASK(15, 13)
|
||||
|
||||
#define MIPITX_DSI_BG_CON 0x44
|
||||
#define RG_DSI_BG_CORE_EN BIT(0)
|
||||
#define RG_DSI_BG_CKEN BIT(1)
|
||||
#define RG_DSI_BG_DIV (0x3 << 2)
|
||||
#define RG_DSI_BG_DIV GENMASK(3, 2)
|
||||
#define RG_DSI_BG_FAST_CHARGE BIT(4)
|
||||
#define RG_DSI_VOUT_MSK (0x3ffff << 5)
|
||||
#define RG_DSI_V12_SEL (7 << 5)
|
||||
#define RG_DSI_V10_SEL (7 << 8)
|
||||
#define RG_DSI_V072_SEL (7 << 11)
|
||||
#define RG_DSI_V04_SEL (7 << 14)
|
||||
#define RG_DSI_V032_SEL (7 << 17)
|
||||
#define RG_DSI_V02_SEL (7 << 20)
|
||||
#define RG_DSI_BG_R1_TRIM (0xf << 24)
|
||||
#define RG_DSI_BG_R2_TRIM (0xf << 28)
|
||||
|
||||
#define RG_DSI_V12_SEL GENMASK(7, 5)
|
||||
#define RG_DSI_V10_SEL GENMASK(10, 8)
|
||||
#define RG_DSI_V072_SEL GENMASK(13, 11)
|
||||
#define RG_DSI_V04_SEL GENMASK(16, 14)
|
||||
#define RG_DSI_V032_SEL GENMASK(19, 17)
|
||||
#define RG_DSI_V02_SEL GENMASK(22, 20)
|
||||
#define RG_DSI_VOUT_MSK \
|
||||
(RG_DSI_V12_SEL | RG_DSI_V10_SEL | RG_DSI_V072_SEL | \
|
||||
RG_DSI_V04_SEL | RG_DSI_V032_SEL | RG_DSI_V02_SEL)
|
||||
#define RG_DSI_BG_R1_TRIM GENMASK(27, 24)
|
||||
#define RG_DSI_BG_R2_TRIM GENMASK(31, 28)
|
||||
|
||||
#define MIPITX_DSI_PLL_CON0 0x50
|
||||
#define RG_DSI_MPPLL_PLL_EN BIT(0)
|
||||
#define RG_DSI_MPPLL_DIV_MSK (0x1ff << 1)
|
||||
#define RG_DSI_MPPLL_PREDIV (3 << 1)
|
||||
#define RG_DSI_MPPLL_TXDIV0 (3 << 3)
|
||||
#define RG_DSI_MPPLL_TXDIV1 (3 << 5)
|
||||
#define RG_DSI_MPPLL_POSDIV (7 << 7)
|
||||
#define RG_DSI_MPPLL_PREDIV GENMASK(2, 1)
|
||||
#define RG_DSI_MPPLL_TXDIV0 GENMASK(4, 3)
|
||||
#define RG_DSI_MPPLL_TXDIV1 GENMASK(6, 5)
|
||||
#define RG_DSI_MPPLL_POSDIV GENMASK(9, 7)
|
||||
#define RG_DSI_MPPLL_DIV_MSK \
|
||||
(RG_DSI_MPPLL_PREDIV | RG_DSI_MPPLL_TXDIV0 | \
|
||||
RG_DSI_MPPLL_TXDIV1 | RG_DSI_MPPLL_POSDIV)
|
||||
#define RG_DSI_MPPLL_MONVC_EN BIT(10)
|
||||
#define RG_DSI_MPPLL_MONREF_EN BIT(11)
|
||||
#define RG_DSI_MPPLL_VOD_EN BIT(12)
|
||||
@ -70,12 +76,12 @@
|
||||
#define RG_DSI_MPPLL_SDM_FRA_EN BIT(0)
|
||||
#define RG_DSI_MPPLL_SDM_SSC_PH_INIT BIT(1)
|
||||
#define RG_DSI_MPPLL_SDM_SSC_EN BIT(2)
|
||||
#define RG_DSI_MPPLL_SDM_SSC_PRD (0xffff << 16)
|
||||
#define RG_DSI_MPPLL_SDM_SSC_PRD GENMASK(31, 16)
|
||||
|
||||
#define MIPITX_DSI_PLL_CON2 0x58
|
||||
|
||||
#define MIPITX_DSI_PLL_TOP 0x64
|
||||
#define RG_DSI_MPPLL_PRESERVE (0xff << 8)
|
||||
#define RG_DSI_MPPLL_PRESERVE GENMASK(15, 8)
|
||||
|
||||
#define MIPITX_DSI_PLL_PWR 0x68
|
||||
#define RG_DSI_MPPLL_SDM_PWR_ON BIT(0)
|
||||
@ -116,6 +122,7 @@
|
||||
static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
void __iomem *base = mipi_tx->regs;
|
||||
u8 txdiv, txdiv0, txdiv1;
|
||||
u64 pcw;
|
||||
|
||||
@ -145,34 +152,38 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_BG_CON,
|
||||
RG_DSI_VOUT_MSK |
|
||||
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN,
|
||||
(4 << 20) | (4 << 17) | (4 << 14) |
|
||||
(4 << 11) | (4 << 8) | (4 << 5) |
|
||||
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN);
|
||||
mtk_phy_update_bits(base + MIPITX_DSI_BG_CON,
|
||||
RG_DSI_VOUT_MSK | RG_DSI_BG_CKEN |
|
||||
RG_DSI_BG_CORE_EN,
|
||||
FIELD_PREP(RG_DSI_V02_SEL, 4) |
|
||||
FIELD_PREP(RG_DSI_V032_SEL, 4) |
|
||||
FIELD_PREP(RG_DSI_V04_SEL, 4) |
|
||||
FIELD_PREP(RG_DSI_V072_SEL, 4) |
|
||||
FIELD_PREP(RG_DSI_V10_SEL, 4) |
|
||||
FIELD_PREP(RG_DSI_V12_SEL, 4) |
|
||||
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN);
|
||||
|
||||
usleep_range(30, 100);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_LNT_IMP_CAL_CODE | RG_DSI_LNT_HS_BIAS_EN,
|
||||
(8 << 4) | RG_DSI_LNT_HS_BIAS_EN);
|
||||
mtk_phy_update_bits(base + MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_LNT_IMP_CAL_CODE | RG_DSI_LNT_HS_BIAS_EN,
|
||||
FIELD_PREP(RG_DSI_LNT_IMP_CAL_CODE, 8) |
|
||||
RG_DSI_LNT_HS_BIAS_EN);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_CON,
|
||||
RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
|
||||
mtk_phy_set_bits(base + MIPITX_DSI_CON,
|
||||
RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR,
|
||||
RG_DSI_MPPLL_SDM_PWR_ON |
|
||||
RG_DSI_MPPLL_SDM_ISO_EN,
|
||||
RG_DSI_MPPLL_SDM_PWR_ON);
|
||||
mtk_phy_update_bits(base + MIPITX_DSI_PLL_PWR,
|
||||
RG_DSI_MPPLL_SDM_PWR_ON | RG_DSI_MPPLL_SDM_ISO_EN,
|
||||
RG_DSI_MPPLL_SDM_PWR_ON);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_PLL_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_TXDIV0 | RG_DSI_MPPLL_TXDIV1 |
|
||||
RG_DSI_MPPLL_PREDIV,
|
||||
(txdiv0 << 3) | (txdiv1 << 5));
|
||||
mtk_phy_update_bits(base + MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_TXDIV0 | RG_DSI_MPPLL_TXDIV1 |
|
||||
RG_DSI_MPPLL_PREDIV,
|
||||
FIELD_PREP(RG_DSI_MPPLL_TXDIV0, txdiv0) |
|
||||
FIELD_PREP(RG_DSI_MPPLL_TXDIV1, txdiv1));
|
||||
|
||||
/*
|
||||
* PLL PCW config
|
||||
@ -182,23 +193,20 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
|
||||
* Post DIV =4, so need data_Rate*4
|
||||
* Ref_clk is 26MHz
|
||||
*/
|
||||
pcw = div_u64(((u64)mipi_tx->data_rate * 2 * txdiv) << 24,
|
||||
26000000);
|
||||
writel(pcw, mipi_tx->regs + MIPITX_DSI_PLL_CON2);
|
||||
pcw = div_u64(((u64)mipi_tx->data_rate * 2 * txdiv) << 24, 26000000);
|
||||
writel(pcw, base + MIPITX_DSI_PLL_CON2);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
|
||||
RG_DSI_MPPLL_SDM_FRA_EN);
|
||||
mtk_phy_set_bits(base + MIPITX_DSI_PLL_CON1, RG_DSI_MPPLL_SDM_FRA_EN);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN);
|
||||
mtk_phy_set_bits(base + MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN);
|
||||
|
||||
usleep_range(20, 100);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
|
||||
RG_DSI_MPPLL_SDM_SSC_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_DSI_PLL_CON1, RG_DSI_MPPLL_SDM_SSC_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP,
|
||||
RG_DSI_MPPLL_PRESERVE,
|
||||
mipi_tx->driver_data->mppll_preserve);
|
||||
mtk_phy_update_field(base + MIPITX_DSI_PLL_TOP,
|
||||
RG_DSI_MPPLL_PRESERVE,
|
||||
mipi_tx->driver_data->mppll_preserve);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -206,31 +214,27 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
|
||||
static void mtk_mipi_tx_pll_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
void __iomem *base = mipi_tx->regs;
|
||||
|
||||
dev_dbg(mipi_tx->dev, "unprepare\n");
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_PLL_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP,
|
||||
RG_DSI_MPPLL_PRESERVE, 0);
|
||||
mtk_phy_clear_bits(base + MIPITX_DSI_PLL_TOP, RG_DSI_MPPLL_PRESERVE);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR,
|
||||
RG_DSI_MPPLL_SDM_ISO_EN |
|
||||
RG_DSI_MPPLL_SDM_PWR_ON,
|
||||
RG_DSI_MPPLL_SDM_ISO_EN);
|
||||
mtk_phy_update_bits(base + MIPITX_DSI_PLL_PWR,
|
||||
RG_DSI_MPPLL_SDM_ISO_EN | RG_DSI_MPPLL_SDM_PWR_ON,
|
||||
RG_DSI_MPPLL_SDM_ISO_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_LNT_HS_BIAS_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_DSI_TOP_CON, RG_DSI_LNT_HS_BIAS_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_CON,
|
||||
RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_DSI_CON,
|
||||
RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_BG_CON,
|
||||
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_DSI_BG_CON,
|
||||
RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
|
||||
RG_DSI_MPPLL_DIV_MSK);
|
||||
mtk_phy_clear_bits(base + MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_DIV_MSK);
|
||||
}
|
||||
|
||||
static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
@ -254,10 +258,10 @@ static void mtk_mipi_tx_power_on_signal(struct phy *phy)
|
||||
|
||||
for (reg = MIPITX_DSI_CLOCK_LANE;
|
||||
reg <= MIPITX_DSI_DATA_LANE3; reg += 4)
|
||||
mtk_mipi_tx_set_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN);
|
||||
mtk_phy_set_bits(mipi_tx->regs + reg, RG_DSI_LNTx_LDOOUT_EN);
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_PAD_TIE_LOW_EN);
|
||||
mtk_phy_clear_bits(mipi_tx->regs + MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_PAD_TIE_LOW_EN);
|
||||
}
|
||||
|
||||
static void mtk_mipi_tx_power_off_signal(struct phy *phy)
|
||||
@ -265,23 +269,23 @@ static void mtk_mipi_tx_power_off_signal(struct phy *phy)
|
||||
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
|
||||
u32 reg;
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_PAD_TIE_LOW_EN);
|
||||
mtk_phy_set_bits(mipi_tx->regs + MIPITX_DSI_TOP_CON,
|
||||
RG_DSI_PAD_TIE_LOW_EN);
|
||||
|
||||
for (reg = MIPITX_DSI_CLOCK_LANE;
|
||||
reg <= MIPITX_DSI_DATA_LANE3; reg += 4)
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN);
|
||||
mtk_phy_clear_bits(mipi_tx->regs + reg, RG_DSI_LNTx_LDOOUT_EN);
|
||||
}
|
||||
|
||||
const struct mtk_mipitx_data mt2701_mipitx_data = {
|
||||
.mppll_preserve = (3 << 8),
|
||||
.mppll_preserve = 3,
|
||||
.mipi_tx_clk_ops = &mtk_mipi_tx_pll_ops,
|
||||
.mipi_tx_enable_signal = mtk_mipi_tx_power_on_signal,
|
||||
.mipi_tx_disable_signal = mtk_mipi_tx_power_off_signal,
|
||||
};
|
||||
|
||||
const struct mtk_mipitx_data mt8173_mipitx_data = {
|
||||
.mppll_preserve = (0 << 8),
|
||||
.mppll_preserve = 0,
|
||||
.mipi_tx_clk_ops = &mtk_mipi_tx_pll_ops,
|
||||
.mipi_tx_enable_signal = mtk_mipi_tx_power_on_signal,
|
||||
.mipi_tx_disable_signal = mtk_mipi_tx_power_off_signal,
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Author: jitao.shi <jitao.shi@mediatek.com>
|
||||
*/
|
||||
|
||||
#include "phy-mtk-io.h"
|
||||
#include "phy-mtk-mipi-dsi.h"
|
||||
|
||||
#define MIPITX_LANE_CON 0x000c
|
||||
@ -18,7 +19,7 @@
|
||||
#define RG_DSI_PAD_TIEL_SEL BIT(8)
|
||||
|
||||
#define MIPITX_VOLTAGE_SEL 0x0010
|
||||
#define RG_DSI_HSTX_LDO_REF_SEL (0xf << 6)
|
||||
#define RG_DSI_HSTX_LDO_REF_SEL GENMASK(9, 6)
|
||||
|
||||
#define MIPITX_PLL_PWR 0x0028
|
||||
#define MIPITX_PLL_CON0 0x002c
|
||||
@ -26,7 +27,7 @@
|
||||
#define MIPITX_PLL_CON2 0x0034
|
||||
#define MIPITX_PLL_CON3 0x0038
|
||||
#define MIPITX_PLL_CON4 0x003c
|
||||
#define RG_DSI_PLL_IBIAS (3 << 10)
|
||||
#define RG_DSI_PLL_IBIAS GENMASK(11, 10)
|
||||
|
||||
#define MIPITX_D2P_RTCODE 0x0100
|
||||
#define MIPITX_D2_SW_CTL_EN 0x0144
|
||||
@ -41,11 +42,12 @@
|
||||
#define AD_DSI_PLL_SDM_ISO_EN BIT(1)
|
||||
|
||||
#define RG_DSI_PLL_EN BIT(4)
|
||||
#define RG_DSI_PLL_POSDIV (0x7 << 8)
|
||||
#define RG_DSI_PLL_POSDIV GENMASK(10, 8)
|
||||
|
||||
static int mtk_mipi_tx_pll_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
void __iomem *base = mipi_tx->regs;
|
||||
unsigned int txdiv, txdiv0;
|
||||
u64 pcw;
|
||||
|
||||
@ -70,17 +72,16 @@ static int mtk_mipi_tx_pll_enable(struct clk_hw *hw)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON4, RG_DSI_PLL_IBIAS);
|
||||
mtk_phy_clear_bits(base + MIPITX_PLL_CON4, RG_DSI_PLL_IBIAS);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN);
|
||||
mtk_phy_set_bits(base + MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
|
||||
mtk_phy_clear_bits(base + MIPITX_PLL_CON1, RG_DSI_PLL_EN);
|
||||
udelay(1);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN);
|
||||
pcw = div_u64(((u64)mipi_tx->data_rate * txdiv) << 24, 26000000);
|
||||
writel(pcw, mipi_tx->regs + MIPITX_PLL_CON0);
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_POSDIV,
|
||||
txdiv0 << 8);
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN);
|
||||
writel(pcw, base + MIPITX_PLL_CON0);
|
||||
mtk_phy_update_field(base + MIPITX_PLL_CON1, RG_DSI_PLL_POSDIV, txdiv0);
|
||||
mtk_phy_set_bits(base + MIPITX_PLL_CON1, RG_DSI_PLL_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -88,11 +89,12 @@ static int mtk_mipi_tx_pll_enable(struct clk_hw *hw)
|
||||
static void mtk_mipi_tx_pll_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
|
||||
void __iomem *base = mipi_tx->regs;
|
||||
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_CON1, RG_DSI_PLL_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_PLL_CON1, RG_DSI_PLL_EN);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
|
||||
mtk_phy_set_bits(base + MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
|
||||
}
|
||||
|
||||
static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
@ -121,7 +123,7 @@ static void mtk_mipi_tx_config_calibration_data(struct mtk_mipi_tx *mipi_tx)
|
||||
mipi_tx->rt_code[i] |= 0x10 << 5;
|
||||
|
||||
for (j = 0; j < 10; j++)
|
||||
mtk_mipi_tx_update_bits(mipi_tx,
|
||||
mtk_phy_update_bits(mipi_tx->regs +
|
||||
MIPITX_D2P_RTCODE * (i + 1) + j * 4,
|
||||
1, mipi_tx->rt_code[i] >> j & 1);
|
||||
}
|
||||
@ -130,44 +132,42 @@ static void mtk_mipi_tx_config_calibration_data(struct mtk_mipi_tx *mipi_tx)
|
||||
static void mtk_mipi_tx_power_on_signal(struct phy *phy)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
|
||||
void __iomem *base = mipi_tx->regs;
|
||||
|
||||
/* BG_LPF_EN / BG_CORE_EN */
|
||||
writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN,
|
||||
mipi_tx->regs + MIPITX_LANE_CON);
|
||||
writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN, base + MIPITX_LANE_CON);
|
||||
usleep_range(30, 100);
|
||||
writel(RG_DSI_BG_CORE_EN | RG_DSI_BG_LPF_EN,
|
||||
mipi_tx->regs + MIPITX_LANE_CON);
|
||||
writel(RG_DSI_BG_CORE_EN | RG_DSI_BG_LPF_EN, base + MIPITX_LANE_CON);
|
||||
|
||||
/* Switch OFF each Lane */
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_phy_clear_bits(base + MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
|
||||
mtk_mipi_tx_update_bits(mipi_tx, MIPITX_VOLTAGE_SEL,
|
||||
RG_DSI_HSTX_LDO_REF_SEL,
|
||||
(mipi_tx->mipitx_drive - 3000) / 200 << 6);
|
||||
mtk_phy_update_field(base + MIPITX_VOLTAGE_SEL, RG_DSI_HSTX_LDO_REF_SEL,
|
||||
(mipi_tx->mipitx_drive - 3000) / 200);
|
||||
|
||||
mtk_mipi_tx_config_calibration_data(mipi_tx);
|
||||
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_CKMODE_EN, DSI_CK_CKMODE_EN);
|
||||
mtk_phy_set_bits(base + MIPITX_CK_CKMODE_EN, DSI_CK_CKMODE_EN);
|
||||
}
|
||||
|
||||
static void mtk_mipi_tx_power_off_signal(struct phy *phy)
|
||||
{
|
||||
struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
|
||||
void __iomem *base = mipi_tx->regs;
|
||||
|
||||
/* Switch ON each Lane */
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_mipi_tx_set_bits(mipi_tx, MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_phy_set_bits(base + MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_phy_set_bits(base + MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_phy_set_bits(base + MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_phy_set_bits(base + MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
mtk_phy_set_bits(base + MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
|
||||
|
||||
writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN,
|
||||
mipi_tx->regs + MIPITX_LANE_CON);
|
||||
writel(RG_DSI_PAD_TIEL_SEL, mipi_tx->regs + MIPITX_LANE_CON);
|
||||
writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN, base + MIPITX_LANE_CON);
|
||||
writel(RG_DSI_PAD_TIEL_SEL, base + MIPITX_LANE_CON);
|
||||
}
|
||||
|
||||
const struct mtk_mipitx_data mt8183_mipitx_data = {
|
||||
|
@ -10,30 +10,6 @@ inline struct mtk_mipi_tx *mtk_mipi_tx_from_clk_hw(struct clk_hw *hw)
|
||||
return container_of(hw, struct mtk_mipi_tx, pll_hw);
|
||||
}
|
||||
|
||||
void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
|
||||
u32 bits)
|
||||
{
|
||||
u32 temp = readl(mipi_tx->regs + offset);
|
||||
|
||||
writel(temp & ~bits, mipi_tx->regs + offset);
|
||||
}
|
||||
|
||||
void mtk_mipi_tx_set_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
|
||||
u32 bits)
|
||||
{
|
||||
u32 temp = readl(mipi_tx->regs + offset);
|
||||
|
||||
writel(temp | bits, mipi_tx->regs + offset);
|
||||
}
|
||||
|
||||
void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
|
||||
u32 mask, u32 data)
|
||||
{
|
||||
u32 temp = readl(mipi_tx->regs + offset);
|
||||
|
||||
writel((temp & ~mask) | (data & mask), mipi_tx->regs + offset);
|
||||
}
|
||||
|
||||
int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/of_device.h>
|
||||
@ -37,10 +36,6 @@ struct mtk_mipi_tx {
|
||||
};
|
||||
|
||||
struct mtk_mipi_tx *mtk_mipi_tx_from_clk_hw(struct clk_hw *hw);
|
||||
void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, u32 bits);
|
||||
void mtk_mipi_tx_set_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, u32 bits);
|
||||
void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, u32 mask,
|
||||
u32 data);
|
||||
int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate);
|
||||
unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw,
|
||||
|
@ -89,14 +89,14 @@ static void mtk_pcie_efuse_set_lane(struct mtk_pcie_phy *pcie_phy,
|
||||
addr = pcie_phy->sif_base + PEXTP_ANA_LN0_TRX_REG +
|
||||
lane * PEXTP_ANA_LANE_OFFSET;
|
||||
|
||||
mtk_phy_update_bits(addr + PEXTP_ANA_TX_REG, EFUSE_LN_TX_PMOS_SEL,
|
||||
FIELD_PREP(EFUSE_LN_TX_PMOS_SEL, data->tx_pmos));
|
||||
mtk_phy_update_field(addr + PEXTP_ANA_TX_REG, EFUSE_LN_TX_PMOS_SEL,
|
||||
data->tx_pmos);
|
||||
|
||||
mtk_phy_update_bits(addr + PEXTP_ANA_TX_REG, EFUSE_LN_TX_NMOS_SEL,
|
||||
FIELD_PREP(EFUSE_LN_TX_NMOS_SEL, data->tx_nmos));
|
||||
mtk_phy_update_field(addr + PEXTP_ANA_TX_REG, EFUSE_LN_TX_NMOS_SEL,
|
||||
data->tx_nmos);
|
||||
|
||||
mtk_phy_update_bits(addr + PEXTP_ANA_RX_REG, EFUSE_LN_RX_SEL,
|
||||
FIELD_PREP(EFUSE_LN_RX_SEL, data->rx_data));
|
||||
mtk_phy_update_field(addr + PEXTP_ANA_RX_REG, EFUSE_LN_RX_SEL,
|
||||
data->rx_data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,9 +116,8 @@ static int mtk_pcie_phy_init(struct phy *phy)
|
||||
return 0;
|
||||
|
||||
/* Set global data */
|
||||
mtk_phy_update_bits(pcie_phy->sif_base + PEXTP_ANA_GLB_00_REG,
|
||||
EFUSE_GLB_INTR_SEL,
|
||||
FIELD_PREP(EFUSE_GLB_INTR_SEL, pcie_phy->efuse_glb_intr));
|
||||
mtk_phy_update_field(pcie_phy->sif_base + PEXTP_ANA_GLB_00_REG,
|
||||
EFUSE_GLB_INTR_SEL, pcie_phy->efuse_glb_intr);
|
||||
|
||||
for (i = 0; i < pcie_phy->data->num_lanes; i++)
|
||||
mtk_pcie_efuse_set_lane(pcie_phy, i);
|
||||
|
@ -49,35 +49,28 @@
|
||||
#define U3P_USBPHYACR0 0x000
|
||||
#define PA0_RG_U2PLL_FORCE_ON BIT(15)
|
||||
#define PA0_USB20_PLL_PREDIV GENMASK(7, 6)
|
||||
#define PA0_USB20_PLL_PREDIV_VAL(x) ((0x3 & (x)) << 6)
|
||||
#define PA0_RG_USB20_INTR_EN BIT(5)
|
||||
|
||||
#define U3P_USBPHYACR1 0x004
|
||||
#define PA1_RG_INTR_CAL GENMASK(23, 19)
|
||||
#define PA1_RG_INTR_CAL_VAL(x) ((0x1f & (x)) << 19)
|
||||
#define PA1_RG_VRT_SEL GENMASK(14, 12)
|
||||
#define PA1_RG_VRT_SEL_VAL(x) ((0x7 & (x)) << 12)
|
||||
#define PA1_RG_TERM_SEL GENMASK(10, 8)
|
||||
#define PA1_RG_TERM_SEL_VAL(x) ((0x7 & (x)) << 8)
|
||||
|
||||
#define U3P_USBPHYACR2 0x008
|
||||
#define PA2_RG_U2PLL_BW GENMASK(21, 19)
|
||||
#define PA2_RG_U2PLL_BW_VAL(x) ((0x7 & (x)) << 19)
|
||||
#define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18)
|
||||
|
||||
#define U3P_USBPHYACR5 0x014
|
||||
#define PA5_RG_U2_HSTX_SRCAL_EN BIT(15)
|
||||
#define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12)
|
||||
#define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12)
|
||||
#define PA5_RG_U2_HS_100U_U3_EN BIT(11)
|
||||
|
||||
#define U3P_USBPHYACR6 0x018
|
||||
#define PA6_RG_U2_PRE_EMP GENMASK(31, 30)
|
||||
#define PA6_RG_U2_BC11_SW_EN BIT(23)
|
||||
#define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20)
|
||||
#define PA6_RG_U2_DISCTH GENMASK(7, 4)
|
||||
#define PA6_RG_U2_DISCTH_VAL(x) ((0xf & (x)) << 4)
|
||||
#define PA6_RG_U2_SQTH GENMASK(3, 0)
|
||||
#define PA6_RG_U2_SQTH_VAL(x) (0xf & (x))
|
||||
|
||||
#define U3P_U2PHYACR4 0x020
|
||||
#define P2C_RG_USB20_GPIO_CTL BIT(9)
|
||||
@ -104,11 +97,9 @@
|
||||
#define P2C_FORCE_SUSPENDM BIT(18)
|
||||
#define P2C_FORCE_TERMSEL BIT(17)
|
||||
#define P2C_RG_DATAIN GENMASK(13, 10)
|
||||
#define P2C_RG_DATAIN_VAL(x) ((0xf & (x)) << 10)
|
||||
#define P2C_RG_DMPULLDOWN BIT(7)
|
||||
#define P2C_RG_DPPULLDOWN BIT(6)
|
||||
#define P2C_RG_XCVRSEL GENMASK(5, 4)
|
||||
#define P2C_RG_XCVRSEL_VAL(x) ((0x3 & (x)) << 4)
|
||||
#define P2C_RG_SUSPENDM BIT(3)
|
||||
#define P2C_RG_TERMSEL BIT(2)
|
||||
#define P2C_DTM0_PART_MASK \
|
||||
@ -139,87 +130,65 @@
|
||||
|
||||
#define U3P_U3_PHYA_REG0 0x000
|
||||
#define P3A_RG_IEXT_INTR GENMASK(15, 10)
|
||||
#define P3A_RG_IEXT_INTR_VAL(x) ((0x3f & (x)) << 10)
|
||||
#define P3A_RG_CLKDRV_OFF GENMASK(3, 2)
|
||||
#define P3A_RG_CLKDRV_OFF_VAL(x) ((0x3 & (x)) << 2)
|
||||
|
||||
#define U3P_U3_PHYA_REG1 0x004
|
||||
#define P3A_RG_CLKDRV_AMP GENMASK(31, 29)
|
||||
#define P3A_RG_CLKDRV_AMP_VAL(x) ((0x7 & (x)) << 29)
|
||||
|
||||
#define U3P_U3_PHYA_REG6 0x018
|
||||
#define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
|
||||
#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28)
|
||||
|
||||
#define U3P_U3_PHYA_REG9 0x024
|
||||
#define P3A_RG_RX_DAC_MUX GENMASK(5, 1)
|
||||
#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1)
|
||||
|
||||
#define U3P_U3_PHYA_DA_REG0 0x100
|
||||
#define P3A_RG_XTAL_EXT_PE2H GENMASK(17, 16)
|
||||
#define P3A_RG_XTAL_EXT_PE2H_VAL(x) ((0x3 & (x)) << 16)
|
||||
#define P3A_RG_XTAL_EXT_PE1H GENMASK(13, 12)
|
||||
#define P3A_RG_XTAL_EXT_PE1H_VAL(x) ((0x3 & (x)) << 12)
|
||||
#define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10)
|
||||
#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10)
|
||||
|
||||
#define U3P_U3_PHYA_DA_REG4 0x108
|
||||
#define P3A_RG_PLL_DIVEN_PE2H GENMASK(21, 19)
|
||||
#define P3A_RG_PLL_BC_PE2H GENMASK(7, 6)
|
||||
#define P3A_RG_PLL_BC_PE2H_VAL(x) ((0x3 & (x)) << 6)
|
||||
|
||||
#define U3P_U3_PHYA_DA_REG5 0x10c
|
||||
#define P3A_RG_PLL_BR_PE2H GENMASK(29, 28)
|
||||
#define P3A_RG_PLL_BR_PE2H_VAL(x) ((0x3 & (x)) << 28)
|
||||
#define P3A_RG_PLL_IC_PE2H GENMASK(15, 12)
|
||||
#define P3A_RG_PLL_IC_PE2H_VAL(x) ((0xf & (x)) << 12)
|
||||
|
||||
#define U3P_U3_PHYA_DA_REG6 0x110
|
||||
#define P3A_RG_PLL_IR_PE2H GENMASK(19, 16)
|
||||
#define P3A_RG_PLL_IR_PE2H_VAL(x) ((0xf & (x)) << 16)
|
||||
|
||||
#define U3P_U3_PHYA_DA_REG7 0x114
|
||||
#define P3A_RG_PLL_BP_PE2H GENMASK(19, 16)
|
||||
#define P3A_RG_PLL_BP_PE2H_VAL(x) ((0xf & (x)) << 16)
|
||||
|
||||
#define U3P_U3_PHYA_DA_REG20 0x13c
|
||||
#define P3A_RG_PLL_DELTA1_PE2H GENMASK(31, 16)
|
||||
#define P3A_RG_PLL_DELTA1_PE2H_VAL(x) ((0xffff & (x)) << 16)
|
||||
|
||||
#define U3P_U3_PHYA_DA_REG25 0x148
|
||||
#define P3A_RG_PLL_DELTA_PE2H GENMASK(15, 0)
|
||||
#define P3A_RG_PLL_DELTA_PE2H_VAL(x) (0xffff & (x))
|
||||
|
||||
#define U3P_U3_PHYD_LFPS1 0x00c
|
||||
#define P3D_RG_FWAKE_TH GENMASK(21, 16)
|
||||
#define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16)
|
||||
|
||||
#define U3P_U3_PHYD_IMPCAL0 0x010
|
||||
#define P3D_RG_FORCE_TX_IMPEL BIT(31)
|
||||
#define P3D_RG_TX_IMPEL GENMASK(28, 24)
|
||||
#define P3D_RG_TX_IMPEL_VAL(x) ((0x1f & (x)) << 24)
|
||||
|
||||
#define U3P_U3_PHYD_IMPCAL1 0x014
|
||||
#define P3D_RG_FORCE_RX_IMPEL BIT(31)
|
||||
#define P3D_RG_RX_IMPEL GENMASK(28, 24)
|
||||
#define P3D_RG_RX_IMPEL_VAL(x) ((0x1f & (x)) << 24)
|
||||
|
||||
#define U3P_U3_PHYD_RSV 0x054
|
||||
#define P3D_RG_EFUSE_AUTO_LOAD_DIS BIT(12)
|
||||
|
||||
#define U3P_U3_PHYD_CDR1 0x05c
|
||||
#define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24)
|
||||
#define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24)
|
||||
#define P3D_RG_CDR_BIR_LTD0 GENMASK(12, 8)
|
||||
#define P3D_RG_CDR_BIR_LTD0_VAL(x) ((0x1f & (x)) << 8)
|
||||
|
||||
#define U3P_U3_PHYD_RXDET1 0x128
|
||||
#define P3D_RG_RXDET_STB2_SET GENMASK(17, 9)
|
||||
#define P3D_RG_RXDET_STB2_SET_VAL(x) ((0x1ff & (x)) << 9)
|
||||
|
||||
#define U3P_U3_PHYD_RXDET2 0x12c
|
||||
#define P3D_RG_RXDET_STB2_SET_P3 GENMASK(8, 0)
|
||||
#define P3D_RG_RXDET_STB2_SET_P3_VAL(x) (0x1ff & (x))
|
||||
|
||||
#define U3P_SPLLC_XTALCTL3 0x018
|
||||
#define XC3_RG_U3_XTAL_RX_PWD BIT(9)
|
||||
@ -227,10 +196,8 @@
|
||||
|
||||
#define U3P_U2FREQ_FMCR0 0x00
|
||||
#define P2F_RG_MONCLK_SEL GENMASK(27, 26)
|
||||
#define P2F_RG_MONCLK_SEL_VAL(x) ((0x3 & (x)) << 26)
|
||||
#define P2F_RG_FREQDET_EN BIT(24)
|
||||
#define P2F_RG_CYCLECNT GENMASK(23, 0)
|
||||
#define P2F_RG_CYCLECNT_VAL(x) ((P2F_RG_CYCLECNT) & (x))
|
||||
|
||||
#define U3P_U2FREQ_VALUE 0x0c
|
||||
|
||||
@ -247,60 +214,45 @@
|
||||
#define PHYD_CTRL_SIGNAL_MODE4 0x1c
|
||||
/* CDR Charge Pump P-path current adjustment */
|
||||
#define RG_CDR_BICLTD1_GEN1_MSK GENMASK(23, 20)
|
||||
#define RG_CDR_BICLTD1_GEN1_VAL(x) ((0xf & (x)) << 20)
|
||||
#define RG_CDR_BICLTD0_GEN1_MSK GENMASK(11, 8)
|
||||
#define RG_CDR_BICLTD0_GEN1_VAL(x) ((0xf & (x)) << 8)
|
||||
|
||||
#define PHYD_DESIGN_OPTION2 0x24
|
||||
/* Symbol lock count selection */
|
||||
#define RG_LOCK_CNT_SEL_MSK GENMASK(5, 4)
|
||||
#define RG_LOCK_CNT_SEL_VAL(x) ((0x3 & (x)) << 4)
|
||||
|
||||
#define PHYD_DESIGN_OPTION9 0x40
|
||||
/* COMWAK GAP width window */
|
||||
#define RG_TG_MAX_MSK GENMASK(20, 16)
|
||||
#define RG_TG_MAX_VAL(x) ((0x1f & (x)) << 16)
|
||||
/* COMINIT GAP width window */
|
||||
#define RG_T2_MAX_MSK GENMASK(13, 8)
|
||||
#define RG_T2_MAX_VAL(x) ((0x3f & (x)) << 8)
|
||||
/* COMWAK GAP width window */
|
||||
#define RG_TG_MIN_MSK GENMASK(7, 5)
|
||||
#define RG_TG_MIN_VAL(x) ((0x7 & (x)) << 5)
|
||||
/* COMINIT GAP width window */
|
||||
#define RG_T2_MIN_MSK GENMASK(4, 0)
|
||||
#define RG_T2_MIN_VAL(x) (0x1f & (x))
|
||||
|
||||
#define ANA_RG_CTRL_SIGNAL1 0x4c
|
||||
/* TX driver tail current control for 0dB de-empahsis mdoe for Gen1 speed */
|
||||
#define RG_IDRV_0DB_GEN1_MSK GENMASK(13, 8)
|
||||
#define RG_IDRV_0DB_GEN1_VAL(x) ((0x3f & (x)) << 8)
|
||||
|
||||
#define ANA_RG_CTRL_SIGNAL4 0x58
|
||||
#define RG_CDR_BICLTR_GEN1_MSK GENMASK(23, 20)
|
||||
#define RG_CDR_BICLTR_GEN1_VAL(x) ((0xf & (x)) << 20)
|
||||
/* Loop filter R1 resistance adjustment for Gen1 speed */
|
||||
#define RG_CDR_BR_GEN2_MSK GENMASK(10, 8)
|
||||
#define RG_CDR_BR_GEN2_VAL(x) ((0x7 & (x)) << 8)
|
||||
|
||||
#define ANA_RG_CTRL_SIGNAL6 0x60
|
||||
/* I-path capacitance adjustment for Gen1 */
|
||||
#define RG_CDR_BC_GEN1_MSK GENMASK(28, 24)
|
||||
#define RG_CDR_BC_GEN1_VAL(x) ((0x1f & (x)) << 24)
|
||||
#define RG_CDR_BIRLTR_GEN1_MSK GENMASK(4, 0)
|
||||
#define RG_CDR_BIRLTR_GEN1_VAL(x) (0x1f & (x))
|
||||
|
||||
#define ANA_EQ_EYE_CTRL_SIGNAL1 0x6c
|
||||
/* RX Gen1 LEQ tuning step */
|
||||
#define RG_EQ_DLEQ_LFI_GEN1_MSK GENMASK(11, 8)
|
||||
#define RG_EQ_DLEQ_LFI_GEN1_VAL(x) ((0xf & (x)) << 8)
|
||||
|
||||
#define ANA_EQ_EYE_CTRL_SIGNAL4 0xd8
|
||||
#define RG_CDR_BIRLTD0_GEN1_MSK GENMASK(20, 16)
|
||||
#define RG_CDR_BIRLTD0_GEN1_VAL(x) ((0x1f & (x)) << 16)
|
||||
|
||||
#define ANA_EQ_EYE_CTRL_SIGNAL5 0xdc
|
||||
#define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0)
|
||||
#define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x))
|
||||
|
||||
/* PHY switch between pcie/usb3/sgmii/sata */
|
||||
#define USB_PHY_SWITCH_CTRL 0x0
|
||||
@ -370,6 +322,7 @@ struct mtk_phy_instance {
|
||||
int eye_term;
|
||||
int intr;
|
||||
int discth;
|
||||
int pre_emphasis;
|
||||
bool bc12_en;
|
||||
};
|
||||
|
||||
@ -411,9 +364,9 @@ static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
|
||||
/* set cycle count as 1024, and select u2 channel */
|
||||
tmp = readl(fmreg + U3P_U2FREQ_FMCR0);
|
||||
tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL);
|
||||
tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT);
|
||||
tmp |= FIELD_PREP(P2F_RG_CYCLECNT, U3P_FM_DET_CYCLE_CNT);
|
||||
if (tphy->pdata->version == MTK_PHY_V1)
|
||||
tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index >> 1);
|
||||
tmp |= FIELD_PREP(P2F_RG_MONCLK_SEL, instance->index >> 1);
|
||||
|
||||
writel(tmp, fmreg + U3P_U2FREQ_FMCR0);
|
||||
|
||||
@ -446,8 +399,8 @@ static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
|
||||
tphy->src_ref_clk, tphy->src_coef);
|
||||
|
||||
/* set HS slew rate */
|
||||
mtk_phy_update_bits(com + U3P_USBPHYACR5, PA5_RG_U2_HSTX_SRCTRL,
|
||||
PA5_RG_U2_HSTX_SRCTRL_VAL(calibration_val));
|
||||
mtk_phy_update_field(com + U3P_USBPHYACR5, PA5_RG_U2_HSTX_SRCTRL,
|
||||
calibration_val);
|
||||
|
||||
/* disable USB ring oscillator */
|
||||
mtk_phy_clear_bits(com + U3P_USBPHYACR5, PA5_RG_U2_HSTX_SRCAL_EN);
|
||||
@ -457,33 +410,30 @@ static void u3_phy_instance_init(struct mtk_tphy *tphy,
|
||||
struct mtk_phy_instance *instance)
|
||||
{
|
||||
struct u3phy_banks *u3_banks = &instance->u3_banks;
|
||||
void __iomem *phya = u3_banks->phya;
|
||||
void __iomem *phyd = u3_banks->phyd;
|
||||
|
||||
/* gating PCIe Analog XTAL clock */
|
||||
mtk_phy_set_bits(u3_banks->spllc + U3P_SPLLC_XTALCTL3,
|
||||
XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD);
|
||||
|
||||
/* gating XSQ */
|
||||
mtk_phy_update_bits(u3_banks->phya + U3P_U3_PHYA_DA_REG0,
|
||||
P3A_RG_XTAL_EXT_EN_U3, P3A_RG_XTAL_EXT_EN_U3_VAL(2));
|
||||
mtk_phy_update_field(phya + U3P_U3_PHYA_DA_REG0, P3A_RG_XTAL_EXT_EN_U3, 2);
|
||||
|
||||
mtk_phy_update_bits(u3_banks->phya + U3P_U3_PHYA_REG9,
|
||||
P3A_RG_RX_DAC_MUX, P3A_RG_RX_DAC_MUX_VAL(4));
|
||||
mtk_phy_update_field(phya + U3P_U3_PHYA_REG9, P3A_RG_RX_DAC_MUX, 4);
|
||||
|
||||
mtk_phy_update_bits(u3_banks->phya + U3P_U3_PHYA_REG6,
|
||||
P3A_RG_TX_EIDLE_CM, P3A_RG_TX_EIDLE_CM_VAL(0xe));
|
||||
mtk_phy_update_field(phya + U3P_U3_PHYA_REG6, P3A_RG_TX_EIDLE_CM, 0xe);
|
||||
|
||||
mtk_phy_update_bits(u3_banks->phyd + U3P_U3_PHYD_CDR1,
|
||||
P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1,
|
||||
P3D_RG_CDR_BIR_LTD0_VAL(0xc) | P3D_RG_CDR_BIR_LTD1_VAL(0x3));
|
||||
FIELD_PREP(P3D_RG_CDR_BIR_LTD0, 0xc) |
|
||||
FIELD_PREP(P3D_RG_CDR_BIR_LTD1, 0x3));
|
||||
|
||||
mtk_phy_update_bits(u3_banks->phyd + U3P_U3_PHYD_LFPS1,
|
||||
P3D_RG_FWAKE_TH, P3D_RG_FWAKE_TH_VAL(0x34));
|
||||
mtk_phy_update_field(phyd + U3P_U3_PHYD_LFPS1, P3D_RG_FWAKE_TH, 0x34);
|
||||
|
||||
mtk_phy_update_bits(u3_banks->phyd + U3P_U3_PHYD_RXDET1,
|
||||
P3D_RG_RXDET_STB2_SET, P3D_RG_RXDET_STB2_SET_VAL(0x10));
|
||||
mtk_phy_update_field(phyd + U3P_U3_PHYD_RXDET1, P3D_RG_RXDET_STB2_SET, 0x10);
|
||||
|
||||
mtk_phy_update_bits(u3_banks->phyd + U3P_U3_PHYD_RXDET2,
|
||||
P3D_RG_RXDET_STB2_SET_P3, P3D_RG_RXDET_STB2_SET_P3_VAL(0x10));
|
||||
mtk_phy_update_field(phyd + U3P_U3_PHYD_RXDET2, P3D_RG_RXDET_STB2_SET_P3, 0x10);
|
||||
|
||||
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
|
||||
}
|
||||
@ -497,11 +447,9 @@ static void u2_phy_pll_26m_set(struct mtk_tphy *tphy,
|
||||
if (!tphy->pdata->sw_pll_48m_to_26m)
|
||||
return;
|
||||
|
||||
mtk_phy_update_bits(com + U3P_USBPHYACR0, PA0_USB20_PLL_PREDIV,
|
||||
PA0_USB20_PLL_PREDIV_VAL(0));
|
||||
mtk_phy_update_field(com + U3P_USBPHYACR0, PA0_USB20_PLL_PREDIV, 0);
|
||||
|
||||
mtk_phy_update_bits(com + U3P_USBPHYACR2, PA2_RG_U2PLL_BW,
|
||||
PA2_RG_U2PLL_BW_VAL(3));
|
||||
mtk_phy_update_field(com + U3P_USBPHYACR2, PA2_RG_U2PLL_BW, 3);
|
||||
|
||||
writel(P2R_RG_U2PLL_FBDIV_26M, com + U3P_U2PHYA_RESV);
|
||||
|
||||
@ -519,8 +467,8 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy,
|
||||
/* switch to USB function, and enable usb pll */
|
||||
mtk_phy_clear_bits(com + U3P_U2PHYDTM0, P2C_FORCE_UART_EN | P2C_FORCE_SUSPENDM);
|
||||
|
||||
mtk_phy_update_bits(com + U3P_U2PHYDTM0, P2C_RG_XCVRSEL | P2C_RG_DATAIN,
|
||||
P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0));
|
||||
mtk_phy_clear_bits(com + U3P_U2PHYDTM0,
|
||||
P2C_RG_XCVRSEL | P2C_RG_DATAIN | P2C_DTM0_PART_MASK);
|
||||
|
||||
mtk_phy_clear_bits(com + U3P_U2PHYDTM1, P2C_RG_UART_EN);
|
||||
|
||||
@ -529,8 +477,7 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy,
|
||||
/* disable switch 100uA current to SSUSB */
|
||||
mtk_phy_clear_bits(com + U3P_USBPHYACR5, PA5_RG_U2_HS_100U_U3_EN);
|
||||
|
||||
if (!index)
|
||||
mtk_phy_clear_bits(com + U3P_U2PHYACR4, P2C_U2_GPIO_CTR_MSK);
|
||||
mtk_phy_clear_bits(com + U3P_U2PHYACR4, P2C_U2_GPIO_CTR_MSK);
|
||||
|
||||
if (tphy->pdata->avoid_rx_sen_degradation) {
|
||||
if (!index) {
|
||||
@ -548,7 +495,7 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy,
|
||||
/* DP/DM BC1.1 path Disable */
|
||||
mtk_phy_clear_bits(com + U3P_USBPHYACR6, PA6_RG_U2_BC11_SW_EN);
|
||||
|
||||
mtk_phy_update_bits(com + U3P_USBPHYACR6, PA6_RG_U2_SQTH, PA6_RG_U2_SQTH_VAL(2));
|
||||
mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_SQTH, 2);
|
||||
|
||||
/* Workaround only for mt8195, HW fix it for others (V3) */
|
||||
u2_phy_pll_26m_set(tphy, instance);
|
||||
@ -563,9 +510,6 @@ static void u2_phy_instance_power_on(struct mtk_tphy *tphy,
|
||||
void __iomem *com = u2_banks->com;
|
||||
u32 index = instance->index;
|
||||
|
||||
mtk_phy_clear_bits(com + U3P_U2PHYDTM0,
|
||||
P2C_RG_XCVRSEL | P2C_RG_DATAIN | P2C_DTM0_PART_MASK);
|
||||
|
||||
/* OTG Enable */
|
||||
mtk_phy_set_bits(com + U3P_USBPHYACR6, PA6_RG_U2_OTG_VBUSCMP_EN);
|
||||
|
||||
@ -588,8 +532,6 @@ static void u2_phy_instance_power_off(struct mtk_tphy *tphy,
|
||||
void __iomem *com = u2_banks->com;
|
||||
u32 index = instance->index;
|
||||
|
||||
mtk_phy_clear_bits(com + U3P_U2PHYDTM0, P2C_RG_XCVRSEL | P2C_RG_DATAIN);
|
||||
|
||||
/* OTG Disable */
|
||||
mtk_phy_clear_bits(com + U3P_USBPHYACR6, PA6_RG_U2_OTG_VBUSCMP_EN);
|
||||
|
||||
@ -656,43 +598,39 @@ static void pcie_phy_instance_init(struct mtk_tphy *tphy,
|
||||
|
||||
mtk_phy_update_bits(phya + U3P_U3_PHYA_DA_REG0,
|
||||
P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H,
|
||||
P3A_RG_XTAL_EXT_PE1H_VAL(0x2) | P3A_RG_XTAL_EXT_PE2H_VAL(0x2));
|
||||
FIELD_PREP(P3A_RG_XTAL_EXT_PE1H, 0x2) |
|
||||
FIELD_PREP(P3A_RG_XTAL_EXT_PE2H, 0x2));
|
||||
|
||||
/* ref clk drive */
|
||||
mtk_phy_update_bits(phya + U3P_U3_PHYA_REG1, P3A_RG_CLKDRV_AMP,
|
||||
P3A_RG_CLKDRV_AMP_VAL(0x4));
|
||||
mtk_phy_update_field(phya + U3P_U3_PHYA_REG1, P3A_RG_CLKDRV_AMP, 0x4);
|
||||
|
||||
mtk_phy_update_bits(phya + U3P_U3_PHYA_REG0, P3A_RG_CLKDRV_OFF,
|
||||
P3A_RG_CLKDRV_OFF_VAL(0x1));
|
||||
mtk_phy_update_field(phya + U3P_U3_PHYA_REG0, P3A_RG_CLKDRV_OFF, 0x1);
|
||||
|
||||
/* SSC delta -5000ppm */
|
||||
mtk_phy_update_bits(phya + U3P_U3_PHYA_DA_REG20, P3A_RG_PLL_DELTA1_PE2H,
|
||||
P3A_RG_PLL_DELTA1_PE2H_VAL(0x3c));
|
||||
mtk_phy_update_field(phya + U3P_U3_PHYA_DA_REG20, P3A_RG_PLL_DELTA1_PE2H, 0x3c);
|
||||
|
||||
mtk_phy_update_bits(phya + U3P_U3_PHYA_DA_REG25, P3A_RG_PLL_DELTA_PE2H,
|
||||
P3A_RG_PLL_DELTA_PE2H_VAL(0x36));
|
||||
mtk_phy_update_field(phya + U3P_U3_PHYA_DA_REG25, P3A_RG_PLL_DELTA_PE2H, 0x36);
|
||||
|
||||
/* change pll BW 0.6M */
|
||||
mtk_phy_update_bits(phya + U3P_U3_PHYA_DA_REG5,
|
||||
P3A_RG_PLL_BR_PE2H | P3A_RG_PLL_IC_PE2H,
|
||||
P3A_RG_PLL_BR_PE2H_VAL(0x1) | P3A_RG_PLL_IC_PE2H_VAL(0x1));
|
||||
FIELD_PREP(P3A_RG_PLL_BR_PE2H, 0x1) |
|
||||
FIELD_PREP(P3A_RG_PLL_IC_PE2H, 0x1));
|
||||
|
||||
mtk_phy_update_bits(phya + U3P_U3_PHYA_DA_REG4,
|
||||
P3A_RG_PLL_DIVEN_PE2H | P3A_RG_PLL_BC_PE2H,
|
||||
P3A_RG_PLL_BC_PE2H_VAL(0x3));
|
||||
FIELD_PREP(P3A_RG_PLL_BC_PE2H, 0x3));
|
||||
|
||||
mtk_phy_update_bits(phya + U3P_U3_PHYA_DA_REG6, P3A_RG_PLL_IR_PE2H,
|
||||
P3A_RG_PLL_IR_PE2H_VAL(0x2));
|
||||
mtk_phy_update_field(phya + U3P_U3_PHYA_DA_REG6, P3A_RG_PLL_IR_PE2H, 0x2);
|
||||
|
||||
mtk_phy_update_bits(phya + U3P_U3_PHYA_DA_REG7, P3A_RG_PLL_BP_PE2H,
|
||||
P3A_RG_PLL_BP_PE2H_VAL(0xa));
|
||||
mtk_phy_update_field(phya + U3P_U3_PHYA_DA_REG7, P3A_RG_PLL_BP_PE2H, 0xa);
|
||||
|
||||
/* Tx Detect Rx Timing: 10us -> 5us */
|
||||
mtk_phy_update_bits(u3_banks->phyd + U3P_U3_PHYD_RXDET1,
|
||||
P3D_RG_RXDET_STB2_SET, P3D_RG_RXDET_STB2_SET_VAL(0x10));
|
||||
mtk_phy_update_field(u3_banks->phyd + U3P_U3_PHYD_RXDET1,
|
||||
P3D_RG_RXDET_STB2_SET, 0x10);
|
||||
|
||||
mtk_phy_update_bits(u3_banks->phyd + U3P_U3_PHYD_RXDET2,
|
||||
P3D_RG_RXDET_STB2_SET_P3, P3D_RG_RXDET_STB2_SET_P3_VAL(0x10));
|
||||
mtk_phy_update_field(u3_banks->phyd + U3P_U3_PHYD_RXDET2,
|
||||
P3D_RG_RXDET_STB2_SET_P3, 0x10);
|
||||
|
||||
/* wait for PCIe subsys register to active */
|
||||
usleep_range(2500, 3000);
|
||||
@ -733,38 +671,38 @@ static void sata_phy_instance_init(struct mtk_tphy *tphy,
|
||||
/* charge current adjustment */
|
||||
mtk_phy_update_bits(phyd + ANA_RG_CTRL_SIGNAL6,
|
||||
RG_CDR_BIRLTR_GEN1_MSK | RG_CDR_BC_GEN1_MSK,
|
||||
RG_CDR_BIRLTR_GEN1_VAL(0x6) | RG_CDR_BC_GEN1_VAL(0x1a));
|
||||
FIELD_PREP(RG_CDR_BIRLTR_GEN1_MSK, 0x6) |
|
||||
FIELD_PREP(RG_CDR_BC_GEN1_MSK, 0x1a));
|
||||
|
||||
mtk_phy_update_bits(phyd + ANA_EQ_EYE_CTRL_SIGNAL4, RG_CDR_BIRLTD0_GEN1_MSK,
|
||||
RG_CDR_BIRLTD0_GEN1_VAL(0x18));
|
||||
mtk_phy_update_field(phyd + ANA_EQ_EYE_CTRL_SIGNAL4, RG_CDR_BIRLTD0_GEN1_MSK, 0x18);
|
||||
|
||||
mtk_phy_update_bits(phyd + ANA_EQ_EYE_CTRL_SIGNAL5, RG_CDR_BIRLTD0_GEN3_MSK,
|
||||
RG_CDR_BIRLTD0_GEN3_VAL(0x06));
|
||||
mtk_phy_update_field(phyd + ANA_EQ_EYE_CTRL_SIGNAL5, RG_CDR_BIRLTD0_GEN3_MSK, 0x06);
|
||||
|
||||
mtk_phy_update_bits(phyd + ANA_RG_CTRL_SIGNAL4,
|
||||
RG_CDR_BICLTR_GEN1_MSK | RG_CDR_BR_GEN2_MSK,
|
||||
RG_CDR_BICLTR_GEN1_VAL(0x0c) | RG_CDR_BR_GEN2_VAL(0x07));
|
||||
FIELD_PREP(RG_CDR_BICLTR_GEN1_MSK, 0x0c) |
|
||||
FIELD_PREP(RG_CDR_BR_GEN2_MSK, 0x07));
|
||||
|
||||
mtk_phy_update_bits(phyd + PHYD_CTRL_SIGNAL_MODE4,
|
||||
RG_CDR_BICLTD0_GEN1_MSK | RG_CDR_BICLTD1_GEN1_MSK,
|
||||
RG_CDR_BICLTD0_GEN1_VAL(0x08) | RG_CDR_BICLTD1_GEN1_VAL(0x02));
|
||||
FIELD_PREP(RG_CDR_BICLTD0_GEN1_MSK, 0x08) |
|
||||
FIELD_PREP(RG_CDR_BICLTD1_GEN1_MSK, 0x02));
|
||||
|
||||
mtk_phy_update_bits(phyd + PHYD_DESIGN_OPTION2, RG_LOCK_CNT_SEL_MSK,
|
||||
RG_LOCK_CNT_SEL_VAL(0x02));
|
||||
mtk_phy_update_field(phyd + PHYD_DESIGN_OPTION2, RG_LOCK_CNT_SEL_MSK, 0x02);
|
||||
|
||||
mtk_phy_update_bits(phyd + PHYD_DESIGN_OPTION9,
|
||||
RG_T2_MIN_MSK | RG_TG_MIN_MSK,
|
||||
RG_T2_MIN_VAL(0x12) | RG_TG_MIN_VAL(0x04));
|
||||
FIELD_PREP(RG_T2_MIN_MSK, 0x12) |
|
||||
FIELD_PREP(RG_TG_MIN_MSK, 0x04));
|
||||
|
||||
mtk_phy_update_bits(phyd + PHYD_DESIGN_OPTION9,
|
||||
RG_T2_MAX_MSK | RG_TG_MAX_MSK,
|
||||
RG_T2_MAX_VAL(0x31) | RG_TG_MAX_VAL(0x0e));
|
||||
FIELD_PREP(RG_T2_MAX_MSK, 0x31) |
|
||||
FIELD_PREP(RG_TG_MAX_MSK, 0x0e));
|
||||
|
||||
mtk_phy_update_bits(phyd + ANA_RG_CTRL_SIGNAL1, RG_IDRV_0DB_GEN1_MSK,
|
||||
RG_IDRV_0DB_GEN1_VAL(0x20));
|
||||
mtk_phy_update_field(phyd + ANA_RG_CTRL_SIGNAL1, RG_IDRV_0DB_GEN1_MSK, 0x20);
|
||||
|
||||
mtk_phy_update_bits(phyd + ANA_EQ_EYE_CTRL_SIGNAL1, RG_EQ_DLEQ_LFI_GEN1_MSK,
|
||||
RG_EQ_DLEQ_LFI_GEN1_VAL(0x03));
|
||||
mtk_phy_update_field(phyd + ANA_EQ_EYE_CTRL_SIGNAL1, RG_EQ_DLEQ_LFI_GEN1_MSK, 0x03);
|
||||
|
||||
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
|
||||
}
|
||||
@ -841,10 +779,13 @@ static void phy_parse_property(struct mtk_tphy *tphy,
|
||||
&instance->intr);
|
||||
device_property_read_u32(dev, "mediatek,discth",
|
||||
&instance->discth);
|
||||
device_property_read_u32(dev, "mediatek,pre-emphasis",
|
||||
&instance->pre_emphasis);
|
||||
dev_dbg(dev, "bc12:%d, src:%d, vrt:%d, term:%d, intr:%d, disc:%d\n",
|
||||
instance->bc12_en, instance->eye_src,
|
||||
instance->eye_vrt, instance->eye_term,
|
||||
instance->intr, instance->discth);
|
||||
dev_dbg(dev, "pre-emp:%d\n", instance->pre_emphasis);
|
||||
}
|
||||
|
||||
static void u2_phy_props_set(struct mtk_tphy *tphy,
|
||||
@ -857,24 +798,33 @@ static void u2_phy_props_set(struct mtk_tphy *tphy,
|
||||
mtk_phy_set_bits(com + U3P_U2PHYBC12C, P2C_RG_CHGDT_EN);
|
||||
|
||||
if (tphy->pdata->version < MTK_PHY_V3 && instance->eye_src)
|
||||
mtk_phy_update_bits(com + U3P_USBPHYACR5, PA5_RG_U2_HSTX_SRCTRL,
|
||||
PA5_RG_U2_HSTX_SRCTRL_VAL(instance->eye_src));
|
||||
mtk_phy_update_field(com + U3P_USBPHYACR5, PA5_RG_U2_HSTX_SRCTRL,
|
||||
instance->eye_src);
|
||||
|
||||
if (instance->eye_vrt)
|
||||
mtk_phy_update_bits(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL,
|
||||
PA1_RG_VRT_SEL_VAL(instance->eye_vrt));
|
||||
mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL,
|
||||
instance->eye_vrt);
|
||||
|
||||
if (instance->eye_term)
|
||||
mtk_phy_update_bits(com + U3P_USBPHYACR1, PA1_RG_TERM_SEL,
|
||||
PA1_RG_TERM_SEL_VAL(instance->eye_term));
|
||||
mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_TERM_SEL,
|
||||
instance->eye_term);
|
||||
|
||||
if (instance->intr)
|
||||
mtk_phy_update_bits(com + U3P_USBPHYACR1, PA1_RG_INTR_CAL,
|
||||
PA1_RG_INTR_CAL_VAL(instance->intr));
|
||||
if (instance->intr) {
|
||||
if (u2_banks->misc)
|
||||
mtk_phy_set_bits(u2_banks->misc + U3P_MISC_REG1,
|
||||
MR1_EFUSE_AUTO_LOAD_DIS);
|
||||
|
||||
mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_INTR_CAL,
|
||||
instance->intr);
|
||||
}
|
||||
|
||||
if (instance->discth)
|
||||
mtk_phy_update_bits(com + U3P_USBPHYACR6, PA6_RG_U2_DISCTH,
|
||||
PA6_RG_U2_DISCTH_VAL(instance->discth));
|
||||
mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_DISCTH,
|
||||
instance->discth);
|
||||
|
||||
if (instance->pre_emphasis)
|
||||
mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_PRE_EMP,
|
||||
instance->pre_emphasis);
|
||||
}
|
||||
|
||||
/* type switch for usb3/pcie/sgmii/sata */
|
||||
@ -906,7 +856,7 @@ static int phy_type_syscon_get(struct mtk_phy_instance *instance,
|
||||
static int phy_type_set(struct mtk_phy_instance *instance)
|
||||
{
|
||||
int type;
|
||||
u32 mask;
|
||||
u32 offset;
|
||||
|
||||
if (!instance->type_sw)
|
||||
return 0;
|
||||
@ -929,8 +879,9 @@ static int phy_type_set(struct mtk_phy_instance *instance)
|
||||
return 0;
|
||||
}
|
||||
|
||||
mask = RG_PHY_SW_TYPE << (instance->type_sw_index * BITS_PER_BYTE);
|
||||
regmap_update_bits(instance->type_sw, instance->type_sw_reg, mask, type);
|
||||
offset = instance->type_sw_index * BITS_PER_BYTE;
|
||||
regmap_update_bits(instance->type_sw, instance->type_sw_reg,
|
||||
RG_PHY_SW_TYPE << offset, type << offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1022,23 +973,23 @@ static void phy_efuse_set(struct mtk_phy_instance *instance)
|
||||
case PHY_TYPE_USB2:
|
||||
mtk_phy_set_bits(u2_banks->misc + U3P_MISC_REG1, MR1_EFUSE_AUTO_LOAD_DIS);
|
||||
|
||||
mtk_phy_update_bits(u2_banks->com + U3P_USBPHYACR1, PA1_RG_INTR_CAL,
|
||||
PA1_RG_INTR_CAL_VAL(instance->efuse_intr));
|
||||
mtk_phy_update_field(u2_banks->com + U3P_USBPHYACR1, PA1_RG_INTR_CAL,
|
||||
instance->efuse_intr);
|
||||
break;
|
||||
case PHY_TYPE_USB3:
|
||||
case PHY_TYPE_PCIE:
|
||||
mtk_phy_set_bits(u3_banks->phyd + U3P_U3_PHYD_RSV, P3D_RG_EFUSE_AUTO_LOAD_DIS);
|
||||
|
||||
mtk_phy_update_bits(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_TX_IMPEL,
|
||||
P3D_RG_TX_IMPEL_VAL(instance->efuse_tx_imp));
|
||||
mtk_phy_update_field(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_TX_IMPEL,
|
||||
instance->efuse_tx_imp);
|
||||
mtk_phy_set_bits(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_FORCE_TX_IMPEL);
|
||||
|
||||
mtk_phy_update_bits(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_RX_IMPEL,
|
||||
P3D_RG_RX_IMPEL_VAL(instance->efuse_rx_imp));
|
||||
mtk_phy_update_field(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_RX_IMPEL,
|
||||
instance->efuse_rx_imp);
|
||||
mtk_phy_set_bits(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_FORCE_RX_IMPEL);
|
||||
|
||||
mtk_phy_update_bits(u3_banks->phya + U3P_U3_PHYA_REG0, P3A_RG_IEXT_INTR,
|
||||
P3A_RG_IEXT_INTR_VAL(instance->efuse_intr));
|
||||
mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0, P3A_RG_IEXT_INTR,
|
||||
instance->efuse_intr);
|
||||
break;
|
||||
default:
|
||||
dev_warn(dev, "no sw efuse for type %d\n", instance->type);
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "phy-mtk-io.h"
|
||||
|
||||
/* mphy register and offsets */
|
||||
#define MP_GLB_DIG_8C 0x008C
|
||||
#define FRC_PLL_ISO_EN BIT(8)
|
||||
@ -39,34 +41,6 @@ struct ufs_mtk_phy {
|
||||
struct clk_bulk_data clks[UFSPHY_CLKS_CNT];
|
||||
};
|
||||
|
||||
static inline u32 mphy_readl(struct ufs_mtk_phy *phy, u32 reg)
|
||||
{
|
||||
return readl(phy->mmio + reg);
|
||||
}
|
||||
|
||||
static inline void mphy_writel(struct ufs_mtk_phy *phy, u32 val, u32 reg)
|
||||
{
|
||||
writel(val, phy->mmio + reg);
|
||||
}
|
||||
|
||||
static void mphy_set_bit(struct ufs_mtk_phy *phy, u32 reg, u32 bit)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = mphy_readl(phy, reg);
|
||||
val |= bit;
|
||||
mphy_writel(phy, val, reg);
|
||||
}
|
||||
|
||||
static void mphy_clr_bit(struct ufs_mtk_phy *phy, u32 reg, u32 bit)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = mphy_readl(phy, reg);
|
||||
val &= ~bit;
|
||||
mphy_writel(phy, val, reg);
|
||||
}
|
||||
|
||||
static struct ufs_mtk_phy *get_ufs_mtk_phy(struct phy *generic_phy)
|
||||
{
|
||||
return (struct ufs_mtk_phy *)phy_get_drvdata(generic_phy);
|
||||
@ -84,57 +58,61 @@ static int ufs_mtk_phy_clk_init(struct ufs_mtk_phy *phy)
|
||||
|
||||
static void ufs_mtk_phy_set_active(struct ufs_mtk_phy *phy)
|
||||
{
|
||||
void __iomem *mmio = phy->mmio;
|
||||
|
||||
/* release DA_MP_PLL_PWR_ON */
|
||||
mphy_set_bit(phy, MP_GLB_DIG_8C, PLL_PWR_ON);
|
||||
mphy_clr_bit(phy, MP_GLB_DIG_8C, FRC_FRC_PWR_ON);
|
||||
mtk_phy_set_bits(mmio + MP_GLB_DIG_8C, PLL_PWR_ON);
|
||||
mtk_phy_clear_bits(mmio + MP_GLB_DIG_8C, FRC_FRC_PWR_ON);
|
||||
|
||||
/* release DA_MP_PLL_ISO_EN */
|
||||
mphy_clr_bit(phy, MP_GLB_DIG_8C, PLL_ISO_EN);
|
||||
mphy_clr_bit(phy, MP_GLB_DIG_8C, FRC_PLL_ISO_EN);
|
||||
mtk_phy_clear_bits(mmio + MP_GLB_DIG_8C, PLL_ISO_EN);
|
||||
mtk_phy_clear_bits(mmio + MP_GLB_DIG_8C, FRC_PLL_ISO_EN);
|
||||
|
||||
/* release DA_MP_CDR_PWR_ON */
|
||||
mphy_set_bit(phy, MP_LN_RX_44, CDR_PWR_ON);
|
||||
mphy_clr_bit(phy, MP_LN_RX_44, FRC_CDR_PWR_ON);
|
||||
mtk_phy_set_bits(mmio + MP_LN_RX_44, CDR_PWR_ON);
|
||||
mtk_phy_clear_bits(mmio + MP_LN_RX_44, FRC_CDR_PWR_ON);
|
||||
|
||||
/* release DA_MP_CDR_ISO_EN */
|
||||
mphy_clr_bit(phy, MP_LN_RX_44, CDR_ISO_EN);
|
||||
mphy_clr_bit(phy, MP_LN_RX_44, FRC_CDR_ISO_EN);
|
||||
mtk_phy_clear_bits(mmio + MP_LN_RX_44, CDR_ISO_EN);
|
||||
mtk_phy_clear_bits(mmio + MP_LN_RX_44, FRC_CDR_ISO_EN);
|
||||
|
||||
/* release DA_MP_RX0_SQ_EN */
|
||||
mphy_set_bit(phy, MP_LN_DIG_RX_AC, RX_SQ_EN);
|
||||
mphy_clr_bit(phy, MP_LN_DIG_RX_AC, FRC_RX_SQ_EN);
|
||||
mtk_phy_set_bits(mmio + MP_LN_DIG_RX_AC, RX_SQ_EN);
|
||||
mtk_phy_clear_bits(mmio + MP_LN_DIG_RX_AC, FRC_RX_SQ_EN);
|
||||
|
||||
/* delay 1us to wait DIFZ stable */
|
||||
udelay(1);
|
||||
|
||||
/* release DIFZ */
|
||||
mphy_clr_bit(phy, MP_LN_DIG_RX_9C, FSM_DIFZ_FRC);
|
||||
mtk_phy_clear_bits(mmio + MP_LN_DIG_RX_9C, FSM_DIFZ_FRC);
|
||||
}
|
||||
|
||||
static void ufs_mtk_phy_set_deep_hibern(struct ufs_mtk_phy *phy)
|
||||
{
|
||||
void __iomem *mmio = phy->mmio;
|
||||
|
||||
/* force DIFZ */
|
||||
mphy_set_bit(phy, MP_LN_DIG_RX_9C, FSM_DIFZ_FRC);
|
||||
mtk_phy_set_bits(mmio + MP_LN_DIG_RX_9C, FSM_DIFZ_FRC);
|
||||
|
||||
/* force DA_MP_RX0_SQ_EN */
|
||||
mphy_set_bit(phy, MP_LN_DIG_RX_AC, FRC_RX_SQ_EN);
|
||||
mphy_clr_bit(phy, MP_LN_DIG_RX_AC, RX_SQ_EN);
|
||||
mtk_phy_set_bits(mmio + MP_LN_DIG_RX_AC, FRC_RX_SQ_EN);
|
||||
mtk_phy_clear_bits(mmio + MP_LN_DIG_RX_AC, RX_SQ_EN);
|
||||
|
||||
/* force DA_MP_CDR_ISO_EN */
|
||||
mphy_set_bit(phy, MP_LN_RX_44, FRC_CDR_ISO_EN);
|
||||
mphy_set_bit(phy, MP_LN_RX_44, CDR_ISO_EN);
|
||||
mtk_phy_set_bits(mmio + MP_LN_RX_44, FRC_CDR_ISO_EN);
|
||||
mtk_phy_set_bits(mmio + MP_LN_RX_44, CDR_ISO_EN);
|
||||
|
||||
/* force DA_MP_CDR_PWR_ON */
|
||||
mphy_set_bit(phy, MP_LN_RX_44, FRC_CDR_PWR_ON);
|
||||
mphy_clr_bit(phy, MP_LN_RX_44, CDR_PWR_ON);
|
||||
mtk_phy_set_bits(mmio + MP_LN_RX_44, FRC_CDR_PWR_ON);
|
||||
mtk_phy_clear_bits(mmio + MP_LN_RX_44, CDR_PWR_ON);
|
||||
|
||||
/* force DA_MP_PLL_ISO_EN */
|
||||
mphy_set_bit(phy, MP_GLB_DIG_8C, FRC_PLL_ISO_EN);
|
||||
mphy_set_bit(phy, MP_GLB_DIG_8C, PLL_ISO_EN);
|
||||
mtk_phy_set_bits(mmio + MP_GLB_DIG_8C, FRC_PLL_ISO_EN);
|
||||
mtk_phy_set_bits(mmio + MP_GLB_DIG_8C, PLL_ISO_EN);
|
||||
|
||||
/* force DA_MP_PLL_PWR_ON */
|
||||
mphy_set_bit(phy, MP_GLB_DIG_8C, FRC_FRC_PWR_ON);
|
||||
mphy_clr_bit(phy, MP_GLB_DIG_8C, PLL_PWR_ON);
|
||||
mtk_phy_set_bits(mmio + MP_GLB_DIG_8C, FRC_FRC_PWR_ON);
|
||||
mtk_phy_clear_bits(mmio + MP_GLB_DIG_8C, PLL_PWR_ON);
|
||||
}
|
||||
|
||||
static int ufs_mtk_phy_power_on(struct phy *generic_phy)
|
||||
|
@ -37,7 +37,6 @@
|
||||
#define XSP_U2FREQ_FMCR0 ((SSUSB_SIFSLV_U2FREQ) + 0x00)
|
||||
#define P2F_RG_FREQDET_EN BIT(24)
|
||||
#define P2F_RG_CYCLECNT GENMASK(23, 0)
|
||||
#define P2F_RG_CYCLECNT_VAL(x) ((P2F_RG_CYCLECNT) & (x))
|
||||
|
||||
#define XSP_U2FREQ_MMONR0 ((SSUSB_SIFSLV_U2FREQ) + 0x0c)
|
||||
|
||||
@ -50,16 +49,12 @@
|
||||
|
||||
#define XSP_USBPHYACR1 ((SSUSB_SIFSLV_U2PHY_COM) + 0x04)
|
||||
#define P2A1_RG_INTR_CAL GENMASK(23, 19)
|
||||
#define P2A1_RG_INTR_CAL_VAL(x) ((0x1f & (x)) << 19)
|
||||
#define P2A1_RG_VRT_SEL GENMASK(14, 12)
|
||||
#define P2A1_RG_VRT_SEL_VAL(x) ((0x7 & (x)) << 12)
|
||||
#define P2A1_RG_TERM_SEL GENMASK(10, 8)
|
||||
#define P2A1_RG_TERM_SEL_VAL(x) ((0x7 & (x)) << 8)
|
||||
|
||||
#define XSP_USBPHYACR5 ((SSUSB_SIFSLV_U2PHY_COM) + 0x014)
|
||||
#define P2A5_RG_HSTX_SRCAL_EN BIT(15)
|
||||
#define P2A5_RG_HSTX_SRCTRL GENMASK(14, 12)
|
||||
#define P2A5_RG_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12)
|
||||
|
||||
#define XSP_USBPHYACR6 ((SSUSB_SIFSLV_U2PHY_COM) + 0x018)
|
||||
#define P2A6_RG_BC11_SW_EN BIT(23)
|
||||
@ -74,15 +69,12 @@
|
||||
|
||||
#define SSPXTP_PHYA_GLB_00 ((SSPXTP_SIFSLV_PHYA_GLB) + 0x00)
|
||||
#define RG_XTP_GLB_BIAS_INTR_CTRL GENMASK(21, 16)
|
||||
#define RG_XTP_GLB_BIAS_INTR_CTRL_VAL(x) ((0x3f & (x)) << 16)
|
||||
|
||||
#define SSPXTP_PHYA_LN_04 ((SSPXTP_SIFSLV_PHYA_LN) + 0x04)
|
||||
#define RG_XTP_LN0_TX_IMPSEL GENMASK(4, 0)
|
||||
#define RG_XTP_LN0_TX_IMPSEL_VAL(x) (0x1f & (x))
|
||||
|
||||
#define SSPXTP_PHYA_LN_14 ((SSPXTP_SIFSLV_PHYA_LN) + 0x014)
|
||||
#define RG_XTP_LN0_RX_IMPSEL GENMASK(4, 0)
|
||||
#define RG_XTP_LN0_RX_IMPSEL_VAL(x) (0x1f & (x))
|
||||
|
||||
#define XSP_REF_CLK 26 /* MHZ */
|
||||
#define XSP_SLEW_RATE_COEF 17
|
||||
@ -134,8 +126,8 @@ static void u2_phy_slew_rate_calibrate(struct mtk_xsphy *xsphy,
|
||||
mtk_phy_set_bits(pbase + XSP_U2FREQ_FMMONR1, P2F_RG_FRCK_EN);
|
||||
|
||||
/* set cycle count as 1024 */
|
||||
mtk_phy_update_bits(pbase + XSP_U2FREQ_FMCR0, P2F_RG_CYCLECNT,
|
||||
P2F_RG_CYCLECNT_VAL(XSP_FM_DET_CYCLE_CNT));
|
||||
mtk_phy_update_field(pbase + XSP_U2FREQ_FMCR0, P2F_RG_CYCLECNT,
|
||||
XSP_FM_DET_CYCLE_CNT);
|
||||
|
||||
/* enable frequency meter */
|
||||
mtk_phy_set_bits(pbase + XSP_U2FREQ_FMCR0, P2F_RG_FREQDET_EN);
|
||||
@ -166,8 +158,7 @@ static void u2_phy_slew_rate_calibrate(struct mtk_xsphy *xsphy,
|
||||
xsphy->src_ref_clk, xsphy->src_coef);
|
||||
|
||||
/* set HS slew rate */
|
||||
mtk_phy_update_bits(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCTRL,
|
||||
P2A5_RG_HSTX_SRCTRL_VAL(calib_val));
|
||||
mtk_phy_update_field(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCTRL, calib_val);
|
||||
|
||||
/* disable USB ring oscillator */
|
||||
mtk_phy_clear_bits(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCAL_EN);
|
||||
@ -280,20 +271,20 @@ static void u2_phy_props_set(struct mtk_xsphy *xsphy,
|
||||
void __iomem *pbase = inst->port_base;
|
||||
|
||||
if (inst->efuse_intr)
|
||||
mtk_phy_update_bits(pbase + XSP_USBPHYACR1, P2A1_RG_INTR_CAL,
|
||||
P2A1_RG_INTR_CAL_VAL(inst->efuse_intr));
|
||||
mtk_phy_update_field(pbase + XSP_USBPHYACR1, P2A1_RG_INTR_CAL,
|
||||
inst->efuse_intr);
|
||||
|
||||
if (inst->eye_src)
|
||||
mtk_phy_update_bits(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCTRL,
|
||||
P2A5_RG_HSTX_SRCTRL_VAL(inst->eye_src));
|
||||
mtk_phy_update_field(pbase + XSP_USBPHYACR5, P2A5_RG_HSTX_SRCTRL,
|
||||
inst->eye_src);
|
||||
|
||||
if (inst->eye_vrt)
|
||||
mtk_phy_update_bits(pbase + XSP_USBPHYACR1, P2A1_RG_VRT_SEL,
|
||||
P2A1_RG_VRT_SEL_VAL(inst->eye_vrt));
|
||||
mtk_phy_update_field(pbase + XSP_USBPHYACR1, P2A1_RG_VRT_SEL,
|
||||
inst->eye_vrt);
|
||||
|
||||
if (inst->eye_term)
|
||||
mtk_phy_update_bits(pbase + XSP_USBPHYACR1, P2A1_RG_TERM_SEL,
|
||||
P2A1_RG_TERM_SEL_VAL(inst->eye_term));
|
||||
mtk_phy_update_field(pbase + XSP_USBPHYACR1, P2A1_RG_TERM_SEL,
|
||||
inst->eye_term);
|
||||
}
|
||||
|
||||
static void u3_phy_props_set(struct mtk_xsphy *xsphy,
|
||||
@ -302,19 +293,16 @@ static void u3_phy_props_set(struct mtk_xsphy *xsphy,
|
||||
void __iomem *pbase = inst->port_base;
|
||||
|
||||
if (inst->efuse_intr)
|
||||
mtk_phy_update_bits(xsphy->glb_base + SSPXTP_PHYA_GLB_00,
|
||||
RG_XTP_GLB_BIAS_INTR_CTRL,
|
||||
RG_XTP_GLB_BIAS_INTR_CTRL_VAL(inst->efuse_intr));
|
||||
mtk_phy_update_field(xsphy->glb_base + SSPXTP_PHYA_GLB_00,
|
||||
RG_XTP_GLB_BIAS_INTR_CTRL, inst->efuse_intr);
|
||||
|
||||
if (inst->efuse_tx_imp)
|
||||
mtk_phy_update_bits(pbase + SSPXTP_PHYA_LN_04,
|
||||
RG_XTP_LN0_TX_IMPSEL,
|
||||
RG_XTP_LN0_TX_IMPSEL_VAL(inst->efuse_tx_imp));
|
||||
mtk_phy_update_field(pbase + SSPXTP_PHYA_LN_04,
|
||||
RG_XTP_LN0_TX_IMPSEL, inst->efuse_tx_imp);
|
||||
|
||||
if (inst->efuse_rx_imp)
|
||||
mtk_phy_update_bits(pbase + SSPXTP_PHYA_LN_14,
|
||||
RG_XTP_LN0_RX_IMPSEL,
|
||||
RG_XTP_LN0_RX_IMPSEL_VAL(inst->efuse_rx_imp));
|
||||
mtk_phy_update_field(pbase + SSPXTP_PHYA_LN_14,
|
||||
RG_XTP_LN0_RX_IMPSEL, inst->efuse_rx_imp);
|
||||
}
|
||||
|
||||
static int mtk_phy_init(struct phy *phy)
|
||||
|
@ -42,7 +42,10 @@
|
||||
#define SERDES_MUX_QSGMII(i, p, m, c) \
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_QSGMII, m, c)
|
||||
#define SERDES_MUX_RGMII(i, p, m, c) \
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII, m, c)
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII, m, c), \
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_TXID, m, c), \
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_RXID, m, c), \
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_ID, m, c)
|
||||
|
||||
static void lan_rmw_(u32 val, u32 mask, void __iomem *mem, u32 offset)
|
||||
{
|
||||
@ -94,21 +97,29 @@ static const struct serdes_mux lan966x_serdes_muxes[] = {
|
||||
HSIO_HW_CFG_SD6G_1_CFG_SET(1)),
|
||||
|
||||
SERDES_MUX_RGMII(RGMII(0), 2, HSIO_HW_CFG_RGMII_0_CFG |
|
||||
HSIO_HW_CFG_RGMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_0_CFG_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(0))),
|
||||
HSIO_HW_CFG_RGMII_ENA |
|
||||
HSIO_HW_CFG_GMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_0_CFG_SET(0) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_GMII_ENA_SET(BIT(2))),
|
||||
SERDES_MUX_RGMII(RGMII(1), 3, HSIO_HW_CFG_RGMII_1_CFG |
|
||||
HSIO_HW_CFG_RGMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_1_CFG_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(1))),
|
||||
HSIO_HW_CFG_RGMII_ENA |
|
||||
HSIO_HW_CFG_GMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_1_CFG_SET(0) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(1)) |
|
||||
HSIO_HW_CFG_GMII_ENA_SET(BIT(3))),
|
||||
SERDES_MUX_RGMII(RGMII(0), 5, HSIO_HW_CFG_RGMII_0_CFG |
|
||||
HSIO_HW_CFG_RGMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_ENA |
|
||||
HSIO_HW_CFG_GMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_0_CFG_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(0))),
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_GMII_ENA_SET(BIT(5))),
|
||||
SERDES_MUX_RGMII(RGMII(1), 6, HSIO_HW_CFG_RGMII_1_CFG |
|
||||
HSIO_HW_CFG_RGMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_ENA |
|
||||
HSIO_HW_CFG_GMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_1_CFG_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(1))),
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(1)) |
|
||||
HSIO_HW_CFG_GMII_ENA_SET(BIT(6))),
|
||||
};
|
||||
|
||||
struct serdes_ctrl {
|
||||
@ -382,6 +393,67 @@ static int lan966x_sd6g40_setup(struct serdes_macro *macro, u32 idx, int mode)
|
||||
return lan966x_sd6g40_setup_lane(macro, conf, idx);
|
||||
}
|
||||
|
||||
static int lan966x_rgmii_setup(struct serdes_macro *macro, u32 idx, int mode)
|
||||
{
|
||||
bool tx_delay = false;
|
||||
bool rx_delay = false;
|
||||
|
||||
/* Configure RGMII */
|
||||
lan_rmw(HSIO_RGMII_CFG_RGMII_RX_RST_SET(0) |
|
||||
HSIO_RGMII_CFG_RGMII_TX_RST_SET(0) |
|
||||
HSIO_RGMII_CFG_TX_CLK_CFG_SET(macro->speed == SPEED_1000 ? 1 :
|
||||
macro->speed == SPEED_100 ? 2 :
|
||||
macro->speed == SPEED_10 ? 3 : 0),
|
||||
HSIO_RGMII_CFG_RGMII_RX_RST |
|
||||
HSIO_RGMII_CFG_RGMII_TX_RST |
|
||||
HSIO_RGMII_CFG_TX_CLK_CFG,
|
||||
macro->ctrl->regs, HSIO_RGMII_CFG(idx));
|
||||
|
||||
if (mode == PHY_INTERFACE_MODE_RGMII ||
|
||||
mode == PHY_INTERFACE_MODE_RGMII_TXID)
|
||||
rx_delay = true;
|
||||
|
||||
if (mode == PHY_INTERFACE_MODE_RGMII ||
|
||||
mode == PHY_INTERFACE_MODE_RGMII_RXID)
|
||||
tx_delay = true;
|
||||
|
||||
/* Setup DLL configuration */
|
||||
lan_rmw(HSIO_DLL_CFG_DLL_RST_SET(0) |
|
||||
HSIO_DLL_CFG_DLL_ENA_SET(rx_delay),
|
||||
HSIO_DLL_CFG_DLL_RST |
|
||||
HSIO_DLL_CFG_DLL_ENA,
|
||||
macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2));
|
||||
|
||||
lan_rmw(HSIO_DLL_CFG_DELAY_ENA_SET(rx_delay),
|
||||
HSIO_DLL_CFG_DELAY_ENA,
|
||||
macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2));
|
||||
|
||||
lan_rmw(HSIO_DLL_CFG_DLL_RST_SET(0) |
|
||||
HSIO_DLL_CFG_DLL_ENA_SET(tx_delay),
|
||||
HSIO_DLL_CFG_DLL_RST |
|
||||
HSIO_DLL_CFG_DLL_ENA,
|
||||
macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3));
|
||||
|
||||
lan_rmw(HSIO_DLL_CFG_DELAY_ENA_SET(tx_delay),
|
||||
HSIO_DLL_CFG_DELAY_ENA,
|
||||
macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serdes_set_speed(struct phy *phy, int speed)
|
||||
{
|
||||
struct serdes_macro *macro = phy_get_drvdata(phy);
|
||||
|
||||
if (!phy_interface_mode_is_rgmii(macro->mode))
|
||||
return 0;
|
||||
|
||||
macro->speed = speed;
|
||||
lan966x_rgmii_setup(macro, macro->idx - (SERDES6G_MAX + 1), macro->mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
{
|
||||
struct serdes_macro *macro = phy_get_drvdata(phy);
|
||||
@ -427,7 +499,9 @@ static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
macro->mode);
|
||||
|
||||
if (macro->idx < RGMII_MAX)
|
||||
return 0;
|
||||
return lan966x_rgmii_setup(macro,
|
||||
macro->idx - (SERDES6G_MAX + 1),
|
||||
macro->mode);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@ -437,6 +511,7 @@ static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
|
||||
static const struct phy_ops serdes_ops = {
|
||||
.set_mode = serdes_set_mode,
|
||||
.set_speed = serdes_set_speed,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -206,4 +206,46 @@ enum lan966x_target {
|
||||
#define HSIO_HW_CFG_QSGMII_ENA_GET(x)\
|
||||
FIELD_GET(HSIO_HW_CFG_QSGMII_ENA, x)
|
||||
|
||||
/* HSIO:HW_CFGSTAT:RGMII_CFG */
|
||||
#define HSIO_RGMII_CFG(r) __REG(TARGET_HSIO, 0, 1, 104, 0, 1, 52, 20, r, 2, 4)
|
||||
|
||||
#define HSIO_RGMII_CFG_TX_CLK_CFG GENMASK(4, 2)
|
||||
#define HSIO_RGMII_CFG_TX_CLK_CFG_SET(x)\
|
||||
FIELD_PREP(HSIO_RGMII_CFG_TX_CLK_CFG, x)
|
||||
#define HSIO_RGMII_CFG_TX_CLK_CFG_GET(x)\
|
||||
FIELD_GET(HSIO_RGMII_CFG_TX_CLK_CFG, x)
|
||||
|
||||
#define HSIO_RGMII_CFG_RGMII_TX_RST BIT(1)
|
||||
#define HSIO_RGMII_CFG_RGMII_TX_RST_SET(x)\
|
||||
FIELD_PREP(HSIO_RGMII_CFG_RGMII_TX_RST, x)
|
||||
#define HSIO_RGMII_CFG_RGMII_TX_RST_GET(x)\
|
||||
FIELD_GET(HSIO_RGMII_CFG_RGMII_TX_RST, x)
|
||||
|
||||
#define HSIO_RGMII_CFG_RGMII_RX_RST BIT(0)
|
||||
#define HSIO_RGMII_CFG_RGMII_RX_RST_SET(x)\
|
||||
FIELD_PREP(HSIO_RGMII_CFG_RGMII_RX_RST, x)
|
||||
#define HSIO_RGMII_CFG_RGMII_RX_RST_GET(x)\
|
||||
FIELD_GET(HSIO_RGMII_CFG_RGMII_RX_RST, x)
|
||||
|
||||
/* HSIO:HW_CFGSTAT:DLL_CFG */
|
||||
#define HSIO_DLL_CFG(r) __REG(TARGET_HSIO, 0, 1, 104, 0, 1, 52, 36, r, 4, 4)
|
||||
|
||||
#define HSIO_DLL_CFG_DELAY_ENA BIT(2)
|
||||
#define HSIO_DLL_CFG_DELAY_ENA_SET(x)\
|
||||
FIELD_PREP(HSIO_DLL_CFG_DELAY_ENA, x)
|
||||
#define HSIO_DLL_CFG_DELAY_ENA_GET(x)\
|
||||
FIELD_GET(HSIO_DLL_CFG_DELAY_ENA, x)
|
||||
|
||||
#define HSIO_DLL_CFG_DLL_ENA BIT(1)
|
||||
#define HSIO_DLL_CFG_DLL_ENA_SET(x)\
|
||||
FIELD_PREP(HSIO_DLL_CFG_DLL_ENA, x)
|
||||
#define HSIO_DLL_CFG_DLL_ENA_GET(x)\
|
||||
FIELD_GET(HSIO_DLL_CFG_DLL_ENA, x)
|
||||
|
||||
#define HSIO_DLL_CFG_DLL_RST BIT(0)
|
||||
#define HSIO_DLL_CFG_DLL_RST_SET(x)\
|
||||
FIELD_PREP(HSIO_DLL_CFG_DLL_RST, x)
|
||||
#define HSIO_DLL_CFG_DLL_RST_GET(x)\
|
||||
FIELD_GET(HSIO_DLL_CFG_DLL_RST, x)
|
||||
|
||||
#endif /* _LAN966X_HSIO_REGS_H_ */
|
||||
|
@ -70,8 +70,19 @@
|
||||
|
||||
#define TXn_TRAN_DRVR_EMP_EN 0x0078
|
||||
|
||||
struct qcom_edp_cfg {
|
||||
bool is_dp;
|
||||
|
||||
/* DP PHY swing and pre_emphasis tables */
|
||||
const u8 (*swing_hbr_rbr)[4][4];
|
||||
const u8 (*swing_hbr3_hbr2)[4][4];
|
||||
const u8 (*pre_emphasis_hbr_rbr)[4][4];
|
||||
const u8 (*pre_emphasis_hbr3_hbr2)[4][4];
|
||||
};
|
||||
|
||||
struct qcom_edp {
|
||||
struct device *dev;
|
||||
const struct qcom_edp_cfg *cfg;
|
||||
|
||||
struct phy *phy;
|
||||
|
||||
@ -89,10 +100,84 @@ struct qcom_edp {
|
||||
struct regulator_bulk_data supplies[2];
|
||||
};
|
||||
|
||||
static const u8 dp_swing_hbr_rbr[4][4] = {
|
||||
{ 0x08, 0x0f, 0x16, 0x1f },
|
||||
{ 0x11, 0x1e, 0x1f, 0xff },
|
||||
{ 0x16, 0x1f, 0xff, 0xff },
|
||||
{ 0x1f, 0xff, 0xff, 0xff }
|
||||
};
|
||||
|
||||
static const u8 dp_pre_emp_hbr_rbr[4][4] = {
|
||||
{ 0x00, 0x0d, 0x14, 0x1a },
|
||||
{ 0x00, 0x0e, 0x15, 0xff },
|
||||
{ 0x00, 0x0e, 0xff, 0xff },
|
||||
{ 0x03, 0xff, 0xff, 0xff }
|
||||
};
|
||||
|
||||
static const u8 dp_swing_hbr2_hbr3[4][4] = {
|
||||
{ 0x02, 0x12, 0x16, 0x1a },
|
||||
{ 0x09, 0x19, 0x1f, 0xff },
|
||||
{ 0x10, 0x1f, 0xff, 0xff },
|
||||
{ 0x1f, 0xff, 0xff, 0xff }
|
||||
};
|
||||
|
||||
static const u8 dp_pre_emp_hbr2_hbr3[4][4] = {
|
||||
{ 0x00, 0x0c, 0x15, 0x1b },
|
||||
{ 0x02, 0x0e, 0x16, 0xff },
|
||||
{ 0x02, 0x11, 0xff, 0xff },
|
||||
{ 0x04, 0xff, 0xff, 0xff }
|
||||
};
|
||||
|
||||
static const struct qcom_edp_cfg dp_phy_cfg = {
|
||||
.is_dp = true,
|
||||
.swing_hbr_rbr = &dp_swing_hbr_rbr,
|
||||
.swing_hbr3_hbr2 = &dp_swing_hbr2_hbr3,
|
||||
.pre_emphasis_hbr_rbr = &dp_pre_emp_hbr_rbr,
|
||||
.pre_emphasis_hbr3_hbr2 = &dp_pre_emp_hbr2_hbr3,
|
||||
};
|
||||
|
||||
static const u8 edp_swing_hbr_rbr[4][4] = {
|
||||
{ 0x07, 0x0f, 0x16, 0x1f },
|
||||
{ 0x0d, 0x16, 0x1e, 0xff },
|
||||
{ 0x11, 0x1b, 0xff, 0xff },
|
||||
{ 0x16, 0xff, 0xff, 0xff }
|
||||
};
|
||||
|
||||
static const u8 edp_pre_emp_hbr_rbr[4][4] = {
|
||||
{ 0x05, 0x12, 0x17, 0x1d },
|
||||
{ 0x05, 0x11, 0x18, 0xff },
|
||||
{ 0x06, 0x11, 0xff, 0xff },
|
||||
{ 0x00, 0xff, 0xff, 0xff }
|
||||
};
|
||||
|
||||
static const u8 edp_swing_hbr2_hbr3[4][4] = {
|
||||
{ 0x0b, 0x11, 0x17, 0x1c },
|
||||
{ 0x10, 0x19, 0x1f, 0xff },
|
||||
{ 0x19, 0x1f, 0xff, 0xff },
|
||||
{ 0x1f, 0xff, 0xff, 0xff }
|
||||
};
|
||||
|
||||
static const u8 edp_pre_emp_hbr2_hbr3[4][4] = {
|
||||
{ 0x08, 0x11, 0x17, 0x1b },
|
||||
{ 0x00, 0x0c, 0x13, 0xff },
|
||||
{ 0x05, 0x10, 0xff, 0xff },
|
||||
{ 0x00, 0xff, 0xff, 0xff }
|
||||
};
|
||||
|
||||
static const struct qcom_edp_cfg edp_phy_cfg = {
|
||||
.is_dp = false,
|
||||
.swing_hbr_rbr = &edp_swing_hbr_rbr,
|
||||
.swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3,
|
||||
.pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr,
|
||||
.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3,
|
||||
};
|
||||
|
||||
static int qcom_edp_phy_init(struct phy *phy)
|
||||
{
|
||||
struct qcom_edp *edp = phy_get_drvdata(phy);
|
||||
const struct qcom_edp_cfg *cfg = edp->cfg;
|
||||
int ret;
|
||||
u8 cfg8;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies);
|
||||
if (ret)
|
||||
@ -117,6 +202,13 @@ static int qcom_edp_phy_init(struct phy *phy)
|
||||
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
|
||||
edp->edp + DP_PHY_PD_CTL);
|
||||
|
||||
if (cfg && cfg->is_dp)
|
||||
cfg8 = 0xb7;
|
||||
else
|
||||
cfg8 = 0x37;
|
||||
|
||||
writel(0xfc, edp->edp + DP_PHY_MODE);
|
||||
|
||||
writel(0x00, edp->edp + DP_PHY_AUX_CFG0);
|
||||
writel(0x13, edp->edp + DP_PHY_AUX_CFG1);
|
||||
writel(0x24, edp->edp + DP_PHY_AUX_CFG2);
|
||||
@ -125,7 +217,7 @@ static int qcom_edp_phy_init(struct phy *phy)
|
||||
writel(0x26, edp->edp + DP_PHY_AUX_CFG5);
|
||||
writel(0x0a, edp->edp + DP_PHY_AUX_CFG6);
|
||||
writel(0x03, edp->edp + DP_PHY_AUX_CFG7);
|
||||
writel(0x37, edp->edp + DP_PHY_AUX_CFG8);
|
||||
writel(cfg8, edp->edp + DP_PHY_AUX_CFG8);
|
||||
writel(0x03, edp->edp + DP_PHY_AUX_CFG9);
|
||||
|
||||
writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
|
||||
@ -142,14 +234,60 @@ out_disable_supplies:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configure_opts_dp *dp_opts)
|
||||
{
|
||||
const struct qcom_edp_cfg *cfg = edp->cfg;
|
||||
unsigned int v_level = 0;
|
||||
unsigned int p_level = 0;
|
||||
u8 ldo_config;
|
||||
u8 swing;
|
||||
u8 emph;
|
||||
int i;
|
||||
|
||||
if (!cfg)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < dp_opts->lanes; i++) {
|
||||
v_level = max(v_level, dp_opts->voltage[i]);
|
||||
p_level = max(p_level, dp_opts->pre[i]);
|
||||
}
|
||||
|
||||
if (dp_opts->link_rate <= 2700) {
|
||||
swing = (*cfg->swing_hbr_rbr)[v_level][p_level];
|
||||
emph = (*cfg->pre_emphasis_hbr_rbr)[v_level][p_level];
|
||||
} else {
|
||||
swing = (*cfg->swing_hbr3_hbr2)[v_level][p_level];
|
||||
emph = (*cfg->pre_emphasis_hbr3_hbr2)[v_level][p_level];
|
||||
}
|
||||
|
||||
if (swing == 0xff || emph == 0xff)
|
||||
return -EINVAL;
|
||||
|
||||
ldo_config = (cfg && cfg->is_dp) ? 0x1 : 0x0;
|
||||
|
||||
writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
|
||||
writel(swing, edp->tx0 + TXn_TX_DRV_LVL);
|
||||
writel(emph, edp->tx0 + TXn_TX_EMP_POST1_LVL);
|
||||
|
||||
writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG);
|
||||
writel(swing, edp->tx1 + TXn_TX_DRV_LVL);
|
||||
writel(emph, edp->tx1 + TXn_TX_EMP_POST1_LVL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_edp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
|
||||
{
|
||||
const struct phy_configure_opts_dp *dp_opts = &opts->dp;
|
||||
struct qcom_edp *edp = phy_get_drvdata(phy);
|
||||
int ret = 0;
|
||||
|
||||
memcpy(&edp->dp_opts, dp_opts, sizeof(*dp_opts));
|
||||
|
||||
return 0;
|
||||
if (dp_opts->set_voltages)
|
||||
ret = qcom_edp_set_voltages(edp, dp_opts);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
|
||||
@ -272,31 +410,30 @@ static int qcom_edp_configure_pll(const struct qcom_edp *edp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_edp_set_vco_div(const struct qcom_edp *edp)
|
||||
static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel_freq)
|
||||
{
|
||||
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
|
||||
unsigned long pixel_freq;
|
||||
u32 vco_div;
|
||||
|
||||
switch (dp_opts->link_rate) {
|
||||
case 1620:
|
||||
vco_div = 0x1;
|
||||
pixel_freq = 1620000000UL / 2;
|
||||
*pixel_freq = 1620000000UL / 2;
|
||||
break;
|
||||
|
||||
case 2700:
|
||||
vco_div = 0x1;
|
||||
pixel_freq = 2700000000UL / 2;
|
||||
*pixel_freq = 2700000000UL / 2;
|
||||
break;
|
||||
|
||||
case 5400:
|
||||
vco_div = 0x2;
|
||||
pixel_freq = 5400000000UL / 4;
|
||||
*pixel_freq = 5400000000UL / 4;
|
||||
break;
|
||||
|
||||
case 8100:
|
||||
vco_div = 0x0;
|
||||
pixel_freq = 8100000000UL / 6;
|
||||
*pixel_freq = 8100000000UL / 6;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -306,18 +443,20 @@ static int qcom_edp_set_vco_div(const struct qcom_edp *edp)
|
||||
|
||||
writel(vco_div, edp->edp + DP_PHY_VCO_DIV);
|
||||
|
||||
clk_set_rate(edp->dp_link_hw.clk, dp_opts->link_rate * 100000);
|
||||
clk_set_rate(edp->dp_pixel_hw.clk, pixel_freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_edp_phy_power_on(struct phy *phy)
|
||||
{
|
||||
const struct qcom_edp *edp = phy_get_drvdata(phy);
|
||||
const struct qcom_edp_cfg *cfg = edp->cfg;
|
||||
u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
|
||||
unsigned long pixel_freq;
|
||||
u8 ldo_config;
|
||||
int timeout;
|
||||
int ret;
|
||||
u32 val;
|
||||
u8 cfg1;
|
||||
|
||||
writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
|
||||
DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
|
||||
@ -330,8 +469,11 @@ static int qcom_edp_phy_power_on(struct phy *phy)
|
||||
if (timeout)
|
||||
return timeout;
|
||||
|
||||
writel(0x01, edp->tx0 + TXn_LDO_CONFIG);
|
||||
writel(0x01, edp->tx1 + TXn_LDO_CONFIG);
|
||||
|
||||
ldo_config = (cfg && cfg->is_dp) ? 0x1 : 0x0;
|
||||
|
||||
writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
|
||||
writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG);
|
||||
writel(0x00, edp->tx0 + TXn_LANE_MODE_1);
|
||||
writel(0x00, edp->tx1 + TXn_LANE_MODE_1);
|
||||
|
||||
@ -363,7 +505,7 @@ static int qcom_edp_phy_power_on(struct phy *phy)
|
||||
writel(0x01, edp->tx1 + TXn_TRAN_DRVR_EMP_EN);
|
||||
writel(0x04, edp->tx1 + TXn_TX_BAND);
|
||||
|
||||
ret = qcom_edp_set_vco_div(edp);
|
||||
ret = qcom_edp_set_vco_div(edp, &pixel_freq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -398,19 +540,46 @@ static int qcom_edp_phy_power_on(struct phy *phy)
|
||||
writel(0x1f, edp->tx0 + TXn_TX_DRV_LVL);
|
||||
writel(0x1f, edp->tx1 + TXn_TX_DRV_LVL);
|
||||
|
||||
writel(0x4, edp->tx0 + TXn_HIGHZ_DRVR_EN);
|
||||
writel(0x3, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
|
||||
writel(0x4, edp->tx1 + TXn_HIGHZ_DRVR_EN);
|
||||
writel(0x0, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
|
||||
writel(0x3, edp->edp + DP_PHY_CFG_1);
|
||||
if (edp->dp_opts.lanes == 1) {
|
||||
bias0_en = 0x01;
|
||||
bias1_en = 0x00;
|
||||
drvr0_en = 0x06;
|
||||
drvr1_en = 0x07;
|
||||
cfg1 = 0x1;
|
||||
} else if (edp->dp_opts.lanes == 2) {
|
||||
bias0_en = 0x03;
|
||||
bias1_en = 0x00;
|
||||
drvr0_en = 0x04;
|
||||
drvr1_en = 0x07;
|
||||
cfg1 = 0x3;
|
||||
} else {
|
||||
bias0_en = 0x03;
|
||||
bias1_en = 0x03;
|
||||
drvr0_en = 0x04;
|
||||
drvr1_en = 0x04;
|
||||
cfg1 = 0xf;
|
||||
}
|
||||
|
||||
writel(drvr0_en, edp->tx0 + TXn_HIGHZ_DRVR_EN);
|
||||
writel(bias0_en, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
|
||||
writel(drvr1_en, edp->tx1 + TXn_HIGHZ_DRVR_EN);
|
||||
writel(bias1_en, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
|
||||
writel(cfg1, edp->edp + DP_PHY_CFG_1);
|
||||
|
||||
writel(0x18, edp->edp + DP_PHY_CFG);
|
||||
usleep_range(100, 1000);
|
||||
|
||||
writel(0x19, edp->edp + DP_PHY_CFG);
|
||||
|
||||
return readl_poll_timeout(edp->edp + DP_PHY_STATUS,
|
||||
val, val & BIT(1), 500, 10000);
|
||||
ret = readl_poll_timeout(edp->edp + DP_PHY_STATUS,
|
||||
val, val & BIT(1), 500, 10000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_set_rate(edp->dp_link_hw.clk, edp->dp_opts.link_rate * 100000);
|
||||
clk_set_rate(edp->dp_pixel_hw.clk, pixel_freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_edp_phy_power_off(struct phy *phy)
|
||||
@ -571,21 +740,24 @@ static int qcom_edp_clks_register(struct qcom_edp *edp, struct device_node *np)
|
||||
{
|
||||
struct clk_hw_onecell_data *data;
|
||||
struct clk_init_data init = { };
|
||||
char name[64];
|
||||
int ret;
|
||||
|
||||
data = devm_kzalloc(edp->dev, struct_size(data, hws, 2), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(name, sizeof(name), "%s::link_clk", dev_name(edp->dev));
|
||||
init.ops = &qcom_edp_dp_link_clk_ops;
|
||||
init.name = "edp_phy_pll_link_clk";
|
||||
init.name = name;
|
||||
edp->dp_link_hw.init = &init;
|
||||
ret = devm_clk_hw_register(edp->dev, &edp->dp_link_hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(edp->dev));
|
||||
init.ops = &qcom_edp_dp_pixel_clk_ops;
|
||||
init.name = "edp_phy_pll_vco_div_clk";
|
||||
init.name = name;
|
||||
edp->dp_pixel_hw.init = &init;
|
||||
ret = devm_clk_hw_register(edp->dev, &edp->dp_pixel_hw);
|
||||
if (ret)
|
||||
@ -610,6 +782,7 @@ static int qcom_edp_phy_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
edp->dev = dev;
|
||||
edp->cfg = of_device_get_match_data(&pdev->dev);
|
||||
|
||||
edp->edp = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(edp->edp))
|
||||
@ -670,6 +843,8 @@ static int qcom_edp_phy_probe(struct platform_device *pdev)
|
||||
static const struct of_device_id qcom_edp_phy_match_table[] = {
|
||||
{ .compatible = "qcom,sc7280-edp-phy" },
|
||||
{ .compatible = "qcom,sc8180x-edp-phy" },
|
||||
{ .compatible = "qcom,sc8280xp-dp-phy", .data = &dp_phy_cfg },
|
||||
{ .compatible = "qcom,sc8280xp-edp-phy", .data = &edp_phy_cfg },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_edp_phy_match_table);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -36,46 +36,13 @@
|
||||
/* QPHY_PCS_STATUS bit */
|
||||
#define PHYSTATUS BIT(6)
|
||||
#define PHYSTATUS_4_20 BIT(7)
|
||||
/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */
|
||||
/* QPHY_COM_PCS_READY_STATUS bit */
|
||||
#define PCS_READY BIT(0)
|
||||
|
||||
/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
|
||||
/* DP PHY soft reset */
|
||||
#define SW_DPPHY_RESET BIT(0)
|
||||
/* mux to select DP PHY reset control, 0:HW control, 1: software reset */
|
||||
#define SW_DPPHY_RESET_MUX BIT(1)
|
||||
/* USB3 PHY soft reset */
|
||||
#define SW_USB3PHY_RESET BIT(2)
|
||||
/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */
|
||||
#define SW_USB3PHY_RESET_MUX BIT(3)
|
||||
|
||||
/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */
|
||||
#define USB3_MODE BIT(0) /* enables USB3 mode */
|
||||
#define DP_MODE BIT(1) /* enables DP mode */
|
||||
|
||||
/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */
|
||||
#define ARCVR_DTCT_EN BIT(0)
|
||||
#define ALFPS_DTCT_EN BIT(1)
|
||||
#define ARCVR_DTCT_EVENT_SEL BIT(4)
|
||||
|
||||
/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */
|
||||
#define IRQ_CLEAR BIT(0)
|
||||
|
||||
/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */
|
||||
#define RCVR_DETECT BIT(0)
|
||||
|
||||
/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
|
||||
#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
|
||||
|
||||
#define PHY_INIT_COMPLETE_TIMEOUT 10000
|
||||
#define POWER_DOWN_DELAY_US_MIN 10
|
||||
#define POWER_DOWN_DELAY_US_MAX 11
|
||||
|
||||
#define MAX_PROP_NAME 32
|
||||
|
||||
/* Define the assumed distance between lanes for underspecified device trees. */
|
||||
#define QMP_PHY_LEGACY_LANE_STRIDE 0x400
|
||||
|
||||
struct qmp_phy_init_tbl {
|
||||
unsigned int offset;
|
||||
unsigned int val;
|
||||
@ -123,14 +90,8 @@ enum qphy_reg_layout {
|
||||
/* PCS registers */
|
||||
QPHY_SW_RESET,
|
||||
QPHY_START_CTRL,
|
||||
QPHY_PCS_READY_STATUS,
|
||||
QPHY_PCS_STATUS,
|
||||
QPHY_PCS_AUTONOMOUS_MODE_CTRL,
|
||||
QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR,
|
||||
QPHY_PCS_LFPS_RXTERM_IRQ_STATUS,
|
||||
QPHY_PCS_POWER_DOWN_CONTROL,
|
||||
/* PCS_MISC registers */
|
||||
QPHY_PCS_MISC_TYPEC_CTRL,
|
||||
/* Keep last to ensure regs_layout arrays are properly initialized */
|
||||
QPHY_LAYOUT_SIZE
|
||||
};
|
||||
@ -223,36 +184,20 @@ static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V2_PCS_TXDEEMPH_M3P5DB_V0, 0x0e),
|
||||
};
|
||||
|
||||
struct qmp_phy;
|
||||
|
||||
/* struct qmp_phy_cfg - per-PHY initialization config */
|
||||
struct qmp_phy_cfg {
|
||||
/* phy-type - PCIE/UFS/USB */
|
||||
unsigned int type;
|
||||
/* number of lanes provided by phy */
|
||||
int nlanes;
|
||||
/* number of PHYs provided by this block */
|
||||
int num_phys;
|
||||
|
||||
/* Init sequence for PHY blocks - serdes, tx, rx, pcs */
|
||||
const struct qmp_phy_init_tbl *serdes_tbl;
|
||||
int serdes_tbl_num;
|
||||
const struct qmp_phy_init_tbl *serdes_tbl_sec;
|
||||
int serdes_tbl_num_sec;
|
||||
const struct qmp_phy_init_tbl *tx_tbl;
|
||||
int tx_tbl_num;
|
||||
const struct qmp_phy_init_tbl *tx_tbl_sec;
|
||||
int tx_tbl_num_sec;
|
||||
const struct qmp_phy_init_tbl *rx_tbl;
|
||||
int rx_tbl_num;
|
||||
const struct qmp_phy_init_tbl *rx_tbl_sec;
|
||||
int rx_tbl_num_sec;
|
||||
const struct qmp_phy_init_tbl *pcs_tbl;
|
||||
int pcs_tbl_num;
|
||||
const struct qmp_phy_init_tbl *pcs_tbl_sec;
|
||||
int pcs_tbl_num_sec;
|
||||
const struct qmp_phy_init_tbl *pcs_misc_tbl;
|
||||
int pcs_misc_tbl_num;
|
||||
const struct qmp_phy_init_tbl *pcs_misc_tbl_sec;
|
||||
int pcs_misc_tbl_num_sec;
|
||||
|
||||
/* clock ids to be requested */
|
||||
const char * const *clk_list;
|
||||
@ -289,12 +234,10 @@ struct qmp_phy_cfg {
|
||||
* @tx: iomapped memory space for lane's tx
|
||||
* @rx: iomapped memory space for lane's rx
|
||||
* @pcs: iomapped memory space for lane's pcs
|
||||
* @pcs_misc: iomapped memory space for lane's pcs_misc
|
||||
* @pipe_clk: pipe clock
|
||||
* @index: lane index
|
||||
* @qmp: QMP phy to which this lane belongs
|
||||
* @lane_rst: lane's reset controller
|
||||
* @mode: current PHY mode
|
||||
*/
|
||||
struct qmp_phy {
|
||||
struct phy *phy;
|
||||
@ -303,12 +246,10 @@ struct qmp_phy {
|
||||
void __iomem *tx;
|
||||
void __iomem *rx;
|
||||
void __iomem *pcs;
|
||||
void __iomem *pcs_misc;
|
||||
struct clk *pipe_clk;
|
||||
unsigned int index;
|
||||
struct qcom_qmp *qmp;
|
||||
struct reset_control *lane_rst;
|
||||
enum phy_mode mode;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -377,8 +318,7 @@ static const char * const qmp_phy_vreg_l[] = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg msm8996_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 3,
|
||||
.num_phys = 3,
|
||||
|
||||
.serdes_tbl = msm8996_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(msm8996_pcie_serdes_tbl),
|
||||
@ -406,7 +346,7 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = {
|
||||
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
|
||||
};
|
||||
|
||||
static void qcom_qmp_phy_pcie_msm8996_configure_lane(void __iomem *base,
|
||||
static void qmp_pcie_msm8996_configure_lane(void __iomem *base,
|
||||
const unsigned int *regs,
|
||||
const struct qmp_phy_init_tbl tbl[],
|
||||
int num,
|
||||
@ -429,15 +369,15 @@ static void qcom_qmp_phy_pcie_msm8996_configure_lane(void __iomem *base,
|
||||
}
|
||||
}
|
||||
|
||||
static void qcom_qmp_phy_pcie_msm8996_configure(void __iomem *base,
|
||||
static void qmp_pcie_msm8996_configure(void __iomem *base,
|
||||
const unsigned int *regs,
|
||||
const struct qmp_phy_init_tbl tbl[],
|
||||
int num)
|
||||
{
|
||||
qcom_qmp_phy_pcie_msm8996_configure_lane(base, regs, tbl, num, 0xff);
|
||||
qmp_pcie_msm8996_configure_lane(base, regs, tbl, num, 0xff);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_serdes_init(struct qmp_phy *qphy)
|
||||
static int qmp_pcie_msm8996_serdes_init(struct qmp_phy *qphy)
|
||||
{
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
@ -448,11 +388,7 @@ static int qcom_qmp_phy_pcie_msm8996_serdes_init(struct qmp_phy *qphy)
|
||||
unsigned int mask, val;
|
||||
int ret;
|
||||
|
||||
qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num);
|
||||
if (cfg->serdes_tbl_sec)
|
||||
qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, cfg->serdes_tbl_sec,
|
||||
cfg->serdes_tbl_num_sec);
|
||||
|
||||
qmp_pcie_msm8996_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num);
|
||||
|
||||
qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET);
|
||||
qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL],
|
||||
@ -472,7 +408,7 @@ static int qcom_qmp_phy_pcie_msm8996_serdes_init(struct qmp_phy *qphy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_com_init(struct qmp_phy *qphy)
|
||||
static int qmp_pcie_msm8996_com_init(struct qmp_phy *qphy)
|
||||
{
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
@ -525,7 +461,7 @@ err_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_com_exit(struct qmp_phy *qphy)
|
||||
static int qmp_pcie_msm8996_com_exit(struct qmp_phy *qphy)
|
||||
{
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
@ -555,21 +491,21 @@ static int qcom_qmp_phy_pcie_msm8996_com_exit(struct qmp_phy *qphy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_init(struct phy *phy)
|
||||
static int qmp_pcie_msm8996_init(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
int ret;
|
||||
dev_vdbg(qmp->dev, "Initializing QMP phy\n");
|
||||
|
||||
ret = qcom_qmp_phy_pcie_msm8996_com_init(qphy);
|
||||
ret = qmp_pcie_msm8996_com_init(qphy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy)
|
||||
static int qmp_pcie_msm8996_power_on(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
@ -577,12 +513,11 @@ static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy)
|
||||
void __iomem *tx = qphy->tx;
|
||||
void __iomem *rx = qphy->rx;
|
||||
void __iomem *pcs = qphy->pcs;
|
||||
void __iomem *pcs_misc = qphy->pcs_misc;
|
||||
void __iomem *status;
|
||||
unsigned int mask, val, ready;
|
||||
int ret;
|
||||
|
||||
qcom_qmp_phy_pcie_msm8996_serdes_init(qphy);
|
||||
qmp_pcie_msm8996_serdes_init(qphy);
|
||||
|
||||
ret = reset_control_deassert(qphy->lane_rst);
|
||||
if (ret) {
|
||||
@ -598,28 +533,13 @@ static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy)
|
||||
}
|
||||
|
||||
/* Tx, Rx, and PCS configurations */
|
||||
qcom_qmp_phy_pcie_msm8996_configure_lane(tx, cfg->regs,
|
||||
cfg->tx_tbl, cfg->tx_tbl_num, 1);
|
||||
if (cfg->tx_tbl_sec)
|
||||
qcom_qmp_phy_pcie_msm8996_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec,
|
||||
cfg->tx_tbl_num_sec, 1);
|
||||
qmp_pcie_msm8996_configure_lane(tx, cfg->regs, cfg->tx_tbl,
|
||||
cfg->tx_tbl_num, 1);
|
||||
|
||||
qcom_qmp_phy_pcie_msm8996_configure_lane(rx, cfg->regs,
|
||||
cfg->rx_tbl, cfg->rx_tbl_num, 1);
|
||||
if (cfg->rx_tbl_sec)
|
||||
qcom_qmp_phy_pcie_msm8996_configure_lane(rx, cfg->regs,
|
||||
cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1);
|
||||
qmp_pcie_msm8996_configure_lane(rx, cfg->regs, cfg->rx_tbl,
|
||||
cfg->rx_tbl_num, 1);
|
||||
|
||||
qcom_qmp_phy_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
|
||||
if (cfg->pcs_tbl_sec)
|
||||
qcom_qmp_phy_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl_sec,
|
||||
cfg->pcs_tbl_num_sec);
|
||||
|
||||
qcom_qmp_phy_pcie_msm8996_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl,
|
||||
cfg->pcs_misc_tbl_num);
|
||||
if (cfg->pcs_misc_tbl_sec)
|
||||
qcom_qmp_phy_pcie_msm8996_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec,
|
||||
cfg->pcs_misc_tbl_num_sec);
|
||||
qmp_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
|
||||
|
||||
/*
|
||||
* Pull out PHY from POWER DOWN state.
|
||||
@ -657,7 +577,7 @@ err_reset_lane:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_power_off(struct phy *phy)
|
||||
static int qmp_pcie_msm8996_power_off(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
@ -682,53 +602,43 @@ static int qcom_qmp_phy_pcie_msm8996_power_off(struct phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_exit(struct phy *phy)
|
||||
static int qmp_pcie_msm8996_exit(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
|
||||
reset_control_assert(qphy->lane_rst);
|
||||
|
||||
qcom_qmp_phy_pcie_msm8996_com_exit(qphy);
|
||||
qmp_pcie_msm8996_com_exit(qphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_enable(struct phy *phy)
|
||||
static int qmp_pcie_msm8996_enable(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = qcom_qmp_phy_pcie_msm8996_init(phy);
|
||||
ret = qmp_pcie_msm8996_init(phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_qmp_phy_pcie_msm8996_power_on(phy);
|
||||
ret = qmp_pcie_msm8996_power_on(phy);
|
||||
if (ret)
|
||||
qcom_qmp_phy_pcie_msm8996_exit(phy);
|
||||
qmp_pcie_msm8996_exit(phy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_disable(struct phy *phy)
|
||||
static int qmp_pcie_msm8996_disable(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = qcom_qmp_phy_pcie_msm8996_power_off(phy);
|
||||
ret = qmp_pcie_msm8996_power_off(phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
return qcom_qmp_phy_pcie_msm8996_exit(phy);
|
||||
return qmp_pcie_msm8996_exit(phy);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_set_mode(struct phy *phy,
|
||||
enum phy_mode mode, int submode)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
|
||||
qphy->mode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
static int qmp_pcie_msm8996_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
int num = cfg->num_vregs;
|
||||
@ -744,7 +654,7 @@ static int qcom_qmp_phy_pcie_msm8996_vreg_init(struct device *dev, const struct
|
||||
return devm_regulator_bulk_get(dev, num, qmp->vregs);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
static int qmp_pcie_msm8996_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
int i;
|
||||
@ -765,7 +675,7 @@ static int qcom_qmp_phy_pcie_msm8996_reset_init(struct device *dev, const struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
static int qmp_pcie_msm8996_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
int num = cfg->num_clks;
|
||||
@ -841,10 +751,9 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np)
|
||||
return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np);
|
||||
}
|
||||
|
||||
static const struct phy_ops qcom_qmp_phy_pcie_msm8996_ops = {
|
||||
.power_on = qcom_qmp_phy_pcie_msm8996_enable,
|
||||
.power_off = qcom_qmp_phy_pcie_msm8996_disable,
|
||||
.set_mode = qcom_qmp_phy_pcie_msm8996_set_mode,
|
||||
static const struct phy_ops qmp_pcie_msm8996_ops = {
|
||||
.power_on = qmp_pcie_msm8996_enable,
|
||||
.power_off = qmp_pcie_msm8996_disable,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
@ -853,14 +762,12 @@ static void qcom_qmp_reset_control_put(void *data)
|
||||
reset_control_put(data);
|
||||
}
|
||||
|
||||
static
|
||||
int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np, int id,
|
||||
static int qmp_pcie_msm8996_create(struct device *dev, struct device_node *np, int id,
|
||||
void __iomem *serdes, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
struct phy *generic_phy;
|
||||
struct qmp_phy *qphy;
|
||||
char prop_name[MAX_PROP_NAME];
|
||||
int ret;
|
||||
|
||||
qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
|
||||
@ -872,36 +779,26 @@ int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np,
|
||||
/*
|
||||
* Get memory resources for each phy lane:
|
||||
* Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
|
||||
* For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5
|
||||
* For single lane PHYs: pcs_misc (optional) -> 3.
|
||||
*/
|
||||
qphy->tx = of_iomap(np, 0);
|
||||
if (!qphy->tx)
|
||||
return -ENOMEM;
|
||||
qphy->tx = devm_of_iomap(dev, np, 0, NULL);
|
||||
if (IS_ERR(qphy->tx))
|
||||
return PTR_ERR(qphy->tx);
|
||||
|
||||
qphy->rx = of_iomap(np, 1);
|
||||
if (!qphy->rx)
|
||||
return -ENOMEM;
|
||||
qphy->rx = devm_of_iomap(dev, np, 1, NULL);
|
||||
if (IS_ERR(qphy->rx))
|
||||
return PTR_ERR(qphy->rx);
|
||||
|
||||
qphy->pcs = of_iomap(np, 2);
|
||||
if (!qphy->pcs)
|
||||
return -ENOMEM;
|
||||
qphy->pcs = devm_of_iomap(dev, np, 2, NULL);
|
||||
if (IS_ERR(qphy->pcs))
|
||||
return PTR_ERR(qphy->pcs);
|
||||
|
||||
qphy->pcs_misc = of_iomap(np, 3);
|
||||
|
||||
if (!qphy->pcs_misc)
|
||||
dev_vdbg(dev, "PHY pcs_misc-reg not used\n");
|
||||
|
||||
snprintf(prop_name, sizeof(prop_name), "pipe%d", id);
|
||||
qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name);
|
||||
qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL);
|
||||
if (IS_ERR(qphy->pipe_clk)) {
|
||||
return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk),
|
||||
"failed to get lane%d pipe clock\n", id);
|
||||
}
|
||||
|
||||
/* Get lane reset, if any */
|
||||
snprintf(prop_name, sizeof(prop_name), "lane%d", id);
|
||||
qphy->lane_rst = of_reset_control_get_exclusive(np, prop_name);
|
||||
qphy->lane_rst = of_reset_control_get_exclusive_by_index(np, 0);
|
||||
if (IS_ERR(qphy->lane_rst)) {
|
||||
dev_err(dev, "failed to get lane%d reset\n", id);
|
||||
return PTR_ERR(qphy->lane_rst);
|
||||
@ -911,7 +808,7 @@ int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_pcie_msm8996_ops);
|
||||
generic_phy = devm_phy_create(dev, np, &qmp_pcie_msm8996_ops);
|
||||
if (IS_ERR(generic_phy)) {
|
||||
ret = PTR_ERR(generic_phy);
|
||||
dev_err(dev, "failed to create qphy %d\n", ret);
|
||||
@ -927,16 +824,16 @@ int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_qmp_phy_pcie_msm8996_of_match_table[] = {
|
||||
static const struct of_device_id qmp_pcie_msm8996_of_match_table[] = {
|
||||
{
|
||||
.compatible = "qcom,msm8996-qmp-pcie-phy",
|
||||
.data = &msm8996_pciephy_cfg,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_qmp_phy_pcie_msm8996_of_match_table);
|
||||
MODULE_DEVICE_TABLE(of, qmp_pcie_msm8996_of_match_table);
|
||||
|
||||
static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev)
|
||||
static int qmp_pcie_msm8996_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_qmp *qmp;
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -964,25 +861,22 @@ static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(serdes))
|
||||
return PTR_ERR(serdes);
|
||||
|
||||
expected_phys = cfg->nlanes;
|
||||
expected_phys = cfg->num_phys;
|
||||
|
||||
mutex_init(&qmp->phy_mutex);
|
||||
|
||||
ret = qcom_qmp_phy_pcie_msm8996_clk_init(dev, cfg);
|
||||
ret = qmp_pcie_msm8996_clk_init(dev, cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_qmp_phy_pcie_msm8996_reset_init(dev, cfg);
|
||||
ret = qmp_pcie_msm8996_reset_init(dev, cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_qmp_phy_pcie_msm8996_vreg_init(dev, cfg);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to get regulator supplies: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
ret = qmp_pcie_msm8996_vreg_init(dev, cfg);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to get regulator supplies\n");
|
||||
|
||||
num = of_get_available_child_count(dev->of_node);
|
||||
/* do we have a rogue child node ? */
|
||||
@ -993,18 +887,10 @@ static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev)
|
||||
if (!qmp->phys)
|
||||
return -ENOMEM;
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
/*
|
||||
* Prevent runtime pm from being ON by default. Users can enable
|
||||
* it using power/control in sysfs.
|
||||
*/
|
||||
pm_runtime_forbid(dev);
|
||||
|
||||
id = 0;
|
||||
for_each_available_child_of_node(dev->of_node, child) {
|
||||
/* Create per-lane phy */
|
||||
ret = qcom_qmp_phy_pcie_msm8996_create(dev, child, id, serdes, cfg);
|
||||
ret = qmp_pcie_msm8996_create(dev, child, id, serdes, cfg);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to create lane%d phy, %d\n",
|
||||
id, ret);
|
||||
@ -1026,28 +912,23 @@ static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
if (!IS_ERR(phy_provider))
|
||||
dev_info(dev, "Registered Qcom-QMP phy\n");
|
||||
else
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
|
||||
err_node_put:
|
||||
pm_runtime_disable(dev);
|
||||
of_node_put(child);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver qcom_qmp_phy_pcie_msm8996_driver = {
|
||||
.probe = qcom_qmp_phy_pcie_msm8996_probe,
|
||||
static struct platform_driver qmp_pcie_msm8996_driver = {
|
||||
.probe = qmp_pcie_msm8996_probe,
|
||||
.driver = {
|
||||
.name = "qcom-qmp-msm8996-pcie-phy",
|
||||
.of_match_table = qcom_qmp_phy_pcie_msm8996_of_match_table,
|
||||
.of_match_table = qmp_pcie_msm8996_of_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(qcom_qmp_phy_pcie_msm8996_driver);
|
||||
module_platform_driver(qmp_pcie_msm8996_driver);
|
||||
|
||||
MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>");
|
||||
MODULE_DESCRIPTION("Qualcomm QMP MSM8996 PCIe PHY driver");
|
||||
|
@ -32,49 +32,11 @@
|
||||
/* QPHY_START_CONTROL bits */
|
||||
#define SERDES_START BIT(0)
|
||||
#define PCS_START BIT(1)
|
||||
#define PLL_READY_GATE_EN BIT(3)
|
||||
/* QPHY_PCS_STATUS bit */
|
||||
#define PHYSTATUS BIT(6)
|
||||
#define PHYSTATUS_4_20 BIT(7)
|
||||
/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */
|
||||
#define PCS_READY BIT(0)
|
||||
|
||||
/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
|
||||
/* DP PHY soft reset */
|
||||
#define SW_DPPHY_RESET BIT(0)
|
||||
/* mux to select DP PHY reset control, 0:HW control, 1: software reset */
|
||||
#define SW_DPPHY_RESET_MUX BIT(1)
|
||||
/* USB3 PHY soft reset */
|
||||
#define SW_USB3PHY_RESET BIT(2)
|
||||
/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */
|
||||
#define SW_USB3PHY_RESET_MUX BIT(3)
|
||||
|
||||
/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */
|
||||
#define USB3_MODE BIT(0) /* enables USB3 mode */
|
||||
#define DP_MODE BIT(1) /* enables DP mode */
|
||||
|
||||
/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */
|
||||
#define ARCVR_DTCT_EN BIT(0)
|
||||
#define ALFPS_DTCT_EN BIT(1)
|
||||
#define ARCVR_DTCT_EVENT_SEL BIT(4)
|
||||
|
||||
/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */
|
||||
#define IRQ_CLEAR BIT(0)
|
||||
|
||||
/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */
|
||||
#define RCVR_DETECT BIT(0)
|
||||
|
||||
/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
|
||||
#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
|
||||
|
||||
#define PHY_INIT_COMPLETE_TIMEOUT 10000
|
||||
#define POWER_DOWN_DELAY_US_MIN 10
|
||||
#define POWER_DOWN_DELAY_US_MAX 11
|
||||
|
||||
#define MAX_PROP_NAME 32
|
||||
|
||||
/* Define the assumed distance between lanes for underspecified device trees. */
|
||||
#define QMP_PHY_LEGACY_LANE_STRIDE 0x400
|
||||
|
||||
struct qmp_phy_init_tbl {
|
||||
unsigned int offset;
|
||||
@ -123,14 +85,8 @@ enum qphy_reg_layout {
|
||||
/* PCS registers */
|
||||
QPHY_SW_RESET,
|
||||
QPHY_START_CTRL,
|
||||
QPHY_PCS_READY_STATUS,
|
||||
QPHY_PCS_STATUS,
|
||||
QPHY_PCS_AUTONOMOUS_MODE_CTRL,
|
||||
QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR,
|
||||
QPHY_PCS_LFPS_RXTERM_IRQ_STATUS,
|
||||
QPHY_PCS_POWER_DOWN_CONTROL,
|
||||
/* PCS_MISC registers */
|
||||
QPHY_PCS_MISC_TYPEC_CTRL,
|
||||
/* Keep last to ensure regs_layout arrays are properly initialized */
|
||||
QPHY_LAYOUT_SIZE
|
||||
};
|
||||
@ -1344,14 +1300,9 @@ static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_misc_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN, 0x2e),
|
||||
};
|
||||
|
||||
struct qmp_phy;
|
||||
|
||||
/* struct qmp_phy_cfg - per-PHY initialization config */
|
||||
struct qmp_phy_cfg {
|
||||
/* phy-type - PCIE/UFS/USB */
|
||||
unsigned int type;
|
||||
/* number of lanes provided by phy */
|
||||
int nlanes;
|
||||
int lanes;
|
||||
|
||||
/* Init sequence for PHY blocks - serdes, tx, rx, pcs */
|
||||
const struct qmp_phy_init_tbl *serdes_tbl;
|
||||
@ -1390,7 +1341,6 @@ struct qmp_phy_cfg {
|
||||
|
||||
unsigned int start_ctrl;
|
||||
unsigned int pwrdn_ctrl;
|
||||
unsigned int mask_com_pcs_ready;
|
||||
/* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */
|
||||
unsigned int phy_status;
|
||||
|
||||
@ -1400,9 +1350,6 @@ struct qmp_phy_cfg {
|
||||
int pwrdn_delay_min;
|
||||
int pwrdn_delay_max;
|
||||
|
||||
/* true, if PHY has secondary tx/rx lanes to be configured */
|
||||
bool is_dual_lane_phy;
|
||||
|
||||
/* QMP PHY pipe clock interface rate */
|
||||
unsigned long pipe_clock_rate;
|
||||
};
|
||||
@ -1420,9 +1367,7 @@ struct qmp_phy_cfg {
|
||||
* @rx2: iomapped memory space for second lane's rx (in dual lane PHYs)
|
||||
* @pcs_misc: iomapped memory space for lane's pcs_misc
|
||||
* @pipe_clk: pipe clock
|
||||
* @index: lane index
|
||||
* @qmp: QMP phy to which this lane belongs
|
||||
* @mode: current PHY mode
|
||||
*/
|
||||
struct qmp_phy {
|
||||
struct phy *phy;
|
||||
@ -1435,9 +1380,7 @@ struct qmp_phy {
|
||||
void __iomem *rx2;
|
||||
void __iomem *pcs_misc;
|
||||
struct clk *pipe_clk;
|
||||
unsigned int index;
|
||||
struct qcom_qmp *qmp;
|
||||
enum phy_mode mode;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1514,8 +1457,7 @@ static const char * const sdm845_pciephy_reset_l[] = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = ipq8074_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_serdes_tbl),
|
||||
@ -1543,8 +1485,7 @@ static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg ipq8074_pciephy_gen3_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = ipq8074_pcie_gen3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_gen3_serdes_tbl),
|
||||
@ -1573,8 +1514,7 @@ static const struct qmp_phy_cfg ipq8074_pciephy_gen3_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg ipq6018_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = ipq6018_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(ipq6018_pcie_serdes_tbl),
|
||||
@ -1603,8 +1543,7 @@ static const struct qmp_phy_cfg ipq6018_pciephy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sdm845_qmp_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_serdes_tbl),
|
||||
@ -1634,8 +1573,7 @@ static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sdm845_qhp_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_serdes_tbl),
|
||||
@ -1663,8 +1601,7 @@ static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sm8250_qmp_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl),
|
||||
@ -1702,8 +1639,7 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 2,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = sm8250_qmp_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl),
|
||||
@ -1735,15 +1671,13 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = {
|
||||
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
|
||||
.phy_status = PHYSTATUS,
|
||||
|
||||
.is_dual_lane_phy = true,
|
||||
.has_pwrdn_delay = true,
|
||||
.pwrdn_delay_min = 995, /* us */
|
||||
.pwrdn_delay_max = 1005, /* us */
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg msm8998_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = msm8998_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(msm8998_pcie_serdes_tbl),
|
||||
@ -1767,8 +1701,7 @@ static const struct qmp_phy_cfg msm8998_pciephy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sc8180x_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sc8180x_qmp_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_serdes_tbl),
|
||||
@ -1797,8 +1730,7 @@ static const struct qmp_phy_cfg sc8180x_pciephy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 2,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = sdx55_qmp_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl),
|
||||
@ -1822,15 +1754,13 @@ static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = {
|
||||
.pwrdn_ctrl = SW_PWRDN,
|
||||
.phy_status = PHYSTATUS_4_20,
|
||||
|
||||
.is_dual_lane_phy = true,
|
||||
.has_pwrdn_delay = true,
|
||||
.pwrdn_delay_min = 995, /* us */
|
||||
.pwrdn_delay_max = 1005, /* us */
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8450_qmp_gen3x1_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sm8450_qmp_gen3x1_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_serdes_tbl),
|
||||
@ -1860,8 +1790,7 @@ static const struct qmp_phy_cfg sm8450_qmp_gen3x1_pciephy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 2,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = sm8450_qmp_gen4x2_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_serdes_tbl),
|
||||
@ -1885,13 +1814,12 @@ static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = {
|
||||
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
|
||||
.phy_status = PHYSTATUS_4_20,
|
||||
|
||||
.is_dual_lane_phy = true,
|
||||
.has_pwrdn_delay = true,
|
||||
.pwrdn_delay_min = 995, /* us */
|
||||
.pwrdn_delay_max = 1005, /* us */
|
||||
};
|
||||
|
||||
static void qcom_qmp_phy_pcie_configure_lane(void __iomem *base,
|
||||
static void qmp_pcie_configure_lane(void __iomem *base,
|
||||
const unsigned int *regs,
|
||||
const struct qmp_phy_init_tbl tbl[],
|
||||
int num,
|
||||
@ -1914,31 +1842,30 @@ static void qcom_qmp_phy_pcie_configure_lane(void __iomem *base,
|
||||
}
|
||||
}
|
||||
|
||||
static void qcom_qmp_phy_pcie_configure(void __iomem *base,
|
||||
const unsigned int *regs,
|
||||
const struct qmp_phy_init_tbl tbl[],
|
||||
int num)
|
||||
static void qmp_pcie_configure(void __iomem *base,
|
||||
const unsigned int *regs,
|
||||
const struct qmp_phy_init_tbl tbl[],
|
||||
int num)
|
||||
{
|
||||
qcom_qmp_phy_pcie_configure_lane(base, regs, tbl, num, 0xff);
|
||||
qmp_pcie_configure_lane(base, regs, tbl, num, 0xff);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_serdes_init(struct qmp_phy *qphy)
|
||||
static int qmp_pcie_serdes_init(struct qmp_phy *qphy)
|
||||
{
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
void __iomem *serdes = qphy->serdes;
|
||||
const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl;
|
||||
int serdes_tbl_num = cfg->serdes_tbl_num;
|
||||
|
||||
qcom_qmp_phy_pcie_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num);
|
||||
if (cfg->serdes_tbl_sec)
|
||||
qcom_qmp_phy_pcie_configure(serdes, cfg->regs, cfg->serdes_tbl_sec,
|
||||
cfg->serdes_tbl_num_sec);
|
||||
qmp_pcie_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num);
|
||||
qmp_pcie_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, cfg->serdes_tbl_num_sec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_com_init(struct qmp_phy *qphy)
|
||||
static int qmp_pcie_init(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
void __iomem *pcs = qphy->pcs;
|
||||
@ -1985,8 +1912,9 @@ err_disable_regulators:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_com_exit(struct qmp_phy *qphy)
|
||||
static int qmp_pcie_exit(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
|
||||
@ -1999,21 +1927,7 @@ static int qcom_qmp_phy_pcie_com_exit(struct qmp_phy *qphy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_init(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
int ret;
|
||||
dev_vdbg(qmp->dev, "Initializing QMP phy\n");
|
||||
|
||||
ret = qcom_qmp_phy_pcie_com_init(qphy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_power_on(struct phy *phy)
|
||||
static int qmp_pcie_power_on(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
@ -2026,7 +1940,7 @@ static int qcom_qmp_phy_pcie_power_on(struct phy *phy)
|
||||
unsigned int mask, val, ready;
|
||||
int ret;
|
||||
|
||||
qcom_qmp_phy_pcie_serdes_init(qphy);
|
||||
qmp_pcie_serdes_init(qphy);
|
||||
|
||||
ret = clk_prepare_enable(qphy->pipe_clk);
|
||||
if (ret) {
|
||||
@ -2035,47 +1949,31 @@ static int qcom_qmp_phy_pcie_power_on(struct phy *phy)
|
||||
}
|
||||
|
||||
/* Tx, Rx, and PCS configurations */
|
||||
qcom_qmp_phy_pcie_configure_lane(tx, cfg->regs,
|
||||
cfg->tx_tbl, cfg->tx_tbl_num, 1);
|
||||
if (cfg->tx_tbl_sec)
|
||||
qcom_qmp_phy_pcie_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec,
|
||||
cfg->tx_tbl_num_sec, 1);
|
||||
qmp_pcie_configure_lane(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num, 1);
|
||||
qmp_pcie_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec, cfg->tx_tbl_num_sec, 1);
|
||||
|
||||
/* Configuration for other LANE for USB-DP combo PHY */
|
||||
if (cfg->is_dual_lane_phy) {
|
||||
qcom_qmp_phy_pcie_configure_lane(qphy->tx2, cfg->regs,
|
||||
cfg->tx_tbl, cfg->tx_tbl_num, 2);
|
||||
if (cfg->tx_tbl_sec)
|
||||
qcom_qmp_phy_pcie_configure_lane(qphy->tx2, cfg->regs,
|
||||
cfg->tx_tbl_sec,
|
||||
cfg->tx_tbl_num_sec, 2);
|
||||
if (cfg->lanes >= 2) {
|
||||
qmp_pcie_configure_lane(qphy->tx2, cfg->regs, cfg->tx_tbl,
|
||||
cfg->tx_tbl_num, 2);
|
||||
qmp_pcie_configure_lane(qphy->tx2, cfg->regs, cfg->tx_tbl_sec,
|
||||
cfg->tx_tbl_num_sec, 2);
|
||||
}
|
||||
|
||||
qcom_qmp_phy_pcie_configure_lane(rx, cfg->regs,
|
||||
cfg->rx_tbl, cfg->rx_tbl_num, 1);
|
||||
if (cfg->rx_tbl_sec)
|
||||
qcom_qmp_phy_pcie_configure_lane(rx, cfg->regs,
|
||||
cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1);
|
||||
qmp_pcie_configure_lane(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num, 1);
|
||||
qmp_pcie_configure_lane(rx, cfg->regs, cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1);
|
||||
|
||||
if (cfg->is_dual_lane_phy) {
|
||||
qcom_qmp_phy_pcie_configure_lane(qphy->rx2, cfg->regs,
|
||||
cfg->rx_tbl, cfg->rx_tbl_num, 2);
|
||||
if (cfg->rx_tbl_sec)
|
||||
qcom_qmp_phy_pcie_configure_lane(qphy->rx2, cfg->regs,
|
||||
cfg->rx_tbl_sec,
|
||||
cfg->rx_tbl_num_sec, 2);
|
||||
if (cfg->lanes >= 2) {
|
||||
qmp_pcie_configure_lane(qphy->rx2, cfg->regs, cfg->rx_tbl,
|
||||
cfg->rx_tbl_num, 2);
|
||||
qmp_pcie_configure_lane(qphy->rx2, cfg->regs, cfg->rx_tbl_sec,
|
||||
cfg->rx_tbl_num_sec, 2);
|
||||
}
|
||||
|
||||
qcom_qmp_phy_pcie_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
|
||||
if (cfg->pcs_tbl_sec)
|
||||
qcom_qmp_phy_pcie_configure(pcs, cfg->regs, cfg->pcs_tbl_sec,
|
||||
cfg->pcs_tbl_num_sec);
|
||||
qmp_pcie_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
|
||||
qmp_pcie_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, cfg->pcs_tbl_num_sec);
|
||||
|
||||
qcom_qmp_phy_pcie_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl,
|
||||
cfg->pcs_misc_tbl_num);
|
||||
if (cfg->pcs_misc_tbl_sec)
|
||||
qcom_qmp_phy_pcie_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec,
|
||||
cfg->pcs_misc_tbl_num_sec);
|
||||
qmp_pcie_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, cfg->pcs_misc_tbl_num);
|
||||
qmp_pcie_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, cfg->pcs_misc_tbl_num_sec);
|
||||
|
||||
/*
|
||||
* Pull out PHY from POWER DOWN state.
|
||||
@ -2111,7 +2009,7 @@ err_disable_pipe_clk:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_power_off(struct phy *phy)
|
||||
static int qmp_pcie_power_off(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
@ -2136,51 +2034,33 @@ static int qcom_qmp_phy_pcie_power_off(struct phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_exit(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
|
||||
qcom_qmp_phy_pcie_com_exit(qphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_enable(struct phy *phy)
|
||||
static int qmp_pcie_enable(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = qcom_qmp_phy_pcie_init(phy);
|
||||
ret = qmp_pcie_init(phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_qmp_phy_pcie_power_on(phy);
|
||||
ret = qmp_pcie_power_on(phy);
|
||||
if (ret)
|
||||
qcom_qmp_phy_pcie_exit(phy);
|
||||
qmp_pcie_exit(phy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_disable(struct phy *phy)
|
||||
static int qmp_pcie_disable(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = qcom_qmp_phy_pcie_power_off(phy);
|
||||
ret = qmp_pcie_power_off(phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
return qcom_qmp_phy_pcie_exit(phy);
|
||||
|
||||
return qmp_pcie_exit(phy);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_set_mode(struct phy *phy,
|
||||
enum phy_mode mode, int submode)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
|
||||
qphy->mode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
static int qmp_pcie_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
int num = cfg->num_vregs;
|
||||
@ -2196,7 +2076,7 @@ static int qcom_qmp_phy_pcie_vreg_init(struct device *dev, const struct qmp_phy_
|
||||
return devm_regulator_bulk_get(dev, num, qmp->vregs);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
static int qmp_pcie_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
int i;
|
||||
@ -2217,7 +2097,7 @@ static int qcom_qmp_phy_pcie_reset_init(struct device *dev, const struct qmp_phy
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_pcie_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
static int qmp_pcie_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
int num = cfg->num_clks;
|
||||
@ -2300,21 +2180,18 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np)
|
||||
return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np);
|
||||
}
|
||||
|
||||
static const struct phy_ops qcom_qmp_phy_pcie_ops = {
|
||||
.power_on = qcom_qmp_phy_pcie_enable,
|
||||
.power_off = qcom_qmp_phy_pcie_disable,
|
||||
.set_mode = qcom_qmp_phy_pcie_set_mode,
|
||||
static const struct phy_ops qmp_pcie_ops = {
|
||||
.power_on = qmp_pcie_enable,
|
||||
.power_off = qmp_pcie_disable,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static
|
||||
int qcom_qmp_phy_pcie_create(struct device *dev, struct device_node *np, int id,
|
||||
static int qmp_pcie_create(struct device *dev, struct device_node *np, int id,
|
||||
void __iomem *serdes, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
struct phy *generic_phy;
|
||||
struct qmp_phy *qphy;
|
||||
char prop_name[MAX_PROP_NAME];
|
||||
int ret;
|
||||
|
||||
qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
|
||||
@ -2329,59 +2206,51 @@ int qcom_qmp_phy_pcie_create(struct device *dev, struct device_node *np, int id,
|
||||
* For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5
|
||||
* For single lane PHYs: pcs_misc (optional) -> 3.
|
||||
*/
|
||||
qphy->tx = of_iomap(np, 0);
|
||||
if (!qphy->tx)
|
||||
return -ENOMEM;
|
||||
qphy->tx = devm_of_iomap(dev, np, 0, NULL);
|
||||
if (IS_ERR(qphy->tx))
|
||||
return PTR_ERR(qphy->tx);
|
||||
|
||||
qphy->rx = of_iomap(np, 1);
|
||||
if (!qphy->rx)
|
||||
return -ENOMEM;
|
||||
if (of_device_is_compatible(dev->of_node, "qcom,sdm845-qhp-pcie-phy"))
|
||||
qphy->rx = qphy->tx;
|
||||
else
|
||||
qphy->rx = devm_of_iomap(dev, np, 1, NULL);
|
||||
if (IS_ERR(qphy->rx))
|
||||
return PTR_ERR(qphy->rx);
|
||||
|
||||
qphy->pcs = of_iomap(np, 2);
|
||||
if (!qphy->pcs)
|
||||
return -ENOMEM;
|
||||
qphy->pcs = devm_of_iomap(dev, np, 2, NULL);
|
||||
if (IS_ERR(qphy->pcs))
|
||||
return PTR_ERR(qphy->pcs);
|
||||
|
||||
/*
|
||||
* If this is a dual-lane PHY, then there should be registers for the
|
||||
* second lane. Some old device trees did not specify this, so fall
|
||||
* back to old legacy behavior of assuming they can be reached at an
|
||||
* offset from the first lane.
|
||||
*/
|
||||
if (cfg->is_dual_lane_phy) {
|
||||
qphy->tx2 = of_iomap(np, 3);
|
||||
qphy->rx2 = of_iomap(np, 4);
|
||||
if (!qphy->tx2 || !qphy->rx2) {
|
||||
dev_warn(dev,
|
||||
"Underspecified device tree, falling back to legacy register regions\n");
|
||||
if (cfg->lanes >= 2) {
|
||||
qphy->tx2 = devm_of_iomap(dev, np, 3, NULL);
|
||||
if (IS_ERR(qphy->tx2))
|
||||
return PTR_ERR(qphy->tx2);
|
||||
|
||||
/* In the old version, pcs_misc is at index 3. */
|
||||
qphy->pcs_misc = qphy->tx2;
|
||||
qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE;
|
||||
qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE;
|
||||
|
||||
} else {
|
||||
qphy->pcs_misc = of_iomap(np, 5);
|
||||
}
|
||||
qphy->rx2 = devm_of_iomap(dev, np, 4, NULL);
|
||||
if (IS_ERR(qphy->rx2))
|
||||
return PTR_ERR(qphy->rx2);
|
||||
|
||||
qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL);
|
||||
} else {
|
||||
qphy->pcs_misc = of_iomap(np, 3);
|
||||
qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL);
|
||||
}
|
||||
|
||||
if (!qphy->pcs_misc &&
|
||||
if (IS_ERR(qphy->pcs_misc) &&
|
||||
of_device_is_compatible(dev->of_node, "qcom,ipq6018-qmp-pcie-phy"))
|
||||
qphy->pcs_misc = qphy->pcs + 0x400;
|
||||
|
||||
if (!qphy->pcs_misc)
|
||||
dev_vdbg(dev, "PHY pcs_misc-reg not used\n");
|
||||
if (IS_ERR(qphy->pcs_misc)) {
|
||||
if (cfg->pcs_misc_tbl || cfg->pcs_misc_tbl_sec)
|
||||
return PTR_ERR(qphy->pcs_misc);
|
||||
}
|
||||
|
||||
snprintf(prop_name, sizeof(prop_name), "pipe%d", id);
|
||||
qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name);
|
||||
qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL);
|
||||
if (IS_ERR(qphy->pipe_clk)) {
|
||||
return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk),
|
||||
"failed to get lane%d pipe clock\n", id);
|
||||
}
|
||||
|
||||
generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_pcie_ops);
|
||||
generic_phy = devm_phy_create(dev, np, &qmp_pcie_ops);
|
||||
if (IS_ERR(generic_phy)) {
|
||||
ret = PTR_ERR(generic_phy);
|
||||
dev_err(dev, "failed to create qphy %d\n", ret);
|
||||
@ -2389,7 +2258,6 @@ int qcom_qmp_phy_pcie_create(struct device *dev, struct device_node *np, int id,
|
||||
}
|
||||
|
||||
qphy->phy = generic_phy;
|
||||
qphy->index = id;
|
||||
qphy->qmp = qmp;
|
||||
qmp->phys[id] = qphy;
|
||||
phy_set_drvdata(generic_phy, qphy);
|
||||
@ -2397,7 +2265,7 @@ int qcom_qmp_phy_pcie_create(struct device *dev, struct device_node *np, int id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_qmp_phy_pcie_of_match_table[] = {
|
||||
static const struct of_device_id qmp_pcie_of_match_table[] = {
|
||||
{
|
||||
.compatible = "qcom,msm8998-qmp-pcie-phy",
|
||||
.data = &msm8998_pciephy_cfg,
|
||||
@ -2440,9 +2308,9 @@ static const struct of_device_id qcom_qmp_phy_pcie_of_match_table[] = {
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_qmp_phy_pcie_of_match_table);
|
||||
MODULE_DEVICE_TABLE(of, qmp_pcie_of_match_table);
|
||||
|
||||
static int qcom_qmp_phy_pcie_probe(struct platform_device *pdev)
|
||||
static int qmp_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_qmp *qmp;
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -2470,21 +2338,18 @@ static int qcom_qmp_phy_pcie_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(serdes))
|
||||
return PTR_ERR(serdes);
|
||||
|
||||
ret = qcom_qmp_phy_pcie_clk_init(dev, cfg);
|
||||
ret = qmp_pcie_clk_init(dev, cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_qmp_phy_pcie_reset_init(dev, cfg);
|
||||
ret = qmp_pcie_reset_init(dev, cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_qmp_phy_pcie_vreg_init(dev, cfg);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to get regulator supplies: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
ret = qmp_pcie_vreg_init(dev, cfg);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to get regulator supplies\n");
|
||||
|
||||
num = of_get_available_child_count(dev->of_node);
|
||||
/* do we have a rogue child node ? */
|
||||
@ -2495,18 +2360,10 @@ static int qcom_qmp_phy_pcie_probe(struct platform_device *pdev)
|
||||
if (!qmp->phys)
|
||||
return -ENOMEM;
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
/*
|
||||
* Prevent runtime pm from being ON by default. Users can enable
|
||||
* it using power/control in sysfs.
|
||||
*/
|
||||
pm_runtime_forbid(dev);
|
||||
|
||||
id = 0;
|
||||
for_each_available_child_of_node(dev->of_node, child) {
|
||||
/* Create per-lane phy */
|
||||
ret = qcom_qmp_phy_pcie_create(dev, child, id, serdes, cfg);
|
||||
ret = qmp_pcie_create(dev, child, id, serdes, cfg);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to create lane%d phy, %d\n",
|
||||
id, ret);
|
||||
@ -2528,28 +2385,23 @@ static int qcom_qmp_phy_pcie_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
if (!IS_ERR(phy_provider))
|
||||
dev_info(dev, "Registered Qcom-QMP phy\n");
|
||||
else
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
|
||||
err_node_put:
|
||||
pm_runtime_disable(dev);
|
||||
of_node_put(child);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver qcom_qmp_phy_pcie_driver = {
|
||||
.probe = qcom_qmp_phy_pcie_probe,
|
||||
static struct platform_driver qmp_pcie_driver = {
|
||||
.probe = qmp_pcie_probe,
|
||||
.driver = {
|
||||
.name = "qcom-qmp-pcie-phy",
|
||||
.of_match_table = qcom_qmp_phy_pcie_of_match_table,
|
||||
.of_match_table = qmp_pcie_of_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(qcom_qmp_phy_pcie_driver);
|
||||
module_platform_driver(qmp_pcie_driver);
|
||||
|
||||
MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>");
|
||||
MODULE_DESCRIPTION("Qualcomm QMP PCIe PHY driver");
|
||||
|
@ -7,11 +7,24 @@
|
||||
#define QCOM_PHY_QMP_PCS_V5_H_
|
||||
|
||||
/* Only for QMP V5 PHY - USB/PCIe PCS registers */
|
||||
#define QPHY_V5_PCS_LOCK_DETECT_CONFIG1 0x0c4
|
||||
#define QPHY_V5_PCS_LOCK_DETECT_CONFIG2 0x0c8
|
||||
#define QPHY_V5_PCS_LOCK_DETECT_CONFIG3 0x0cc
|
||||
#define QPHY_V5_PCS_LOCK_DETECT_CONFIG6 0x0d8
|
||||
#define QPHY_V5_PCS_REFGEN_REQ_CONFIG1 0x0dc
|
||||
#define QPHY_V5_PCS_G3S2_PRE_GAIN 0x170
|
||||
#define QPHY_V5_PCS_RX_SIGDET_LVL 0x188
|
||||
#define QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_L 0x190
|
||||
#define QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H 0x194
|
||||
#define QPHY_V5_PCS_RATE_SLEW_CNTRL1 0x198
|
||||
#define QPHY_V5_PCS_CDR_RESET_TIME 0x1b0
|
||||
#define QPHY_V5_PCS_RX_CONFIG 0x1b0
|
||||
#define QPHY_V5_PCS_ALIGN_DETECT_CONFIG1 0x1c0
|
||||
#define QPHY_V5_PCS_ALIGN_DETECT_CONFIG2 0x1c4
|
||||
#define QPHY_V5_PCS_PCS_TX_RX_CONFIG 0x1d0
|
||||
#define QPHY_V5_PCS_EQ_CONFIG1 0x1dc
|
||||
#define QPHY_V5_PCS_EQ_CONFIG2 0x1e0
|
||||
#define QPHY_V5_PCS_EQ_CONFIG3 0x1e4
|
||||
#define QPHY_V5_PCS_EQ_CONFIG5 0x1ec
|
||||
|
||||
#endif
|
||||
|
333
drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v5_5nm.h
Normal file
333
drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v5_5nm.h
Normal file
@ -0,0 +1,333 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef QCOM_PHY_QMP_QSERDES_TXRX_V5_5NM_H_
|
||||
#define QCOM_PHY_QMP_QSERDES_TXRX_V5_5NM_H_
|
||||
|
||||
/* Only for QMP V5 5NM PHY - TX registers */
|
||||
#define QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_TX 0x30
|
||||
#define QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_RX 0x34
|
||||
#define QSERDES_V5_5NM_TX_LANE_MODE_1 0x78
|
||||
#define QSERDES_V5_5NM_TX_LANE_MODE_2 0x7c
|
||||
#define QSERDES_V5_5NM_TX_LANE_MODE_3 0x80
|
||||
#define QSERDES_V5_5NM_TX_BIST_MODE_LANENO 0x00
|
||||
#define QSERDES_V5_5NM_TX_BIST_INVERT 0x04
|
||||
#define QSERDES_V5_5NM_TX_CLKBUF_ENABLE 0x08
|
||||
#define QSERDES_V5_5NM_TX_TX_EMP_POST1_LVL 0x0c
|
||||
#define QSERDES_V5_5NM_TX_TX_IDLE_LVL_LARGE_AMP 0x10
|
||||
#define QSERDES_V5_5NM_TX_TX_DRV_LVL 0x14
|
||||
#define QSERDES_V5_5NM_TX_TX_DRV_LVL_OFFSET 0x18
|
||||
#define QSERDES_V5_5NM_TX_RESET_TSYNC_EN 0x1c
|
||||
#define QSERDES_V5_5NM_TX_PRE_STALL_LDO_BOOST_EN 0x20
|
||||
#define QSERDES_V5_5NM_TX_LPB_EN 0x24
|
||||
#define QSERDES_V5_5NM_TX_RES_CODE_LANE_TX 0x28
|
||||
#define QSERDES_V5_5NM_TX_RES_CODE_LANE_RX 0x2c
|
||||
#define QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_TX 0x30
|
||||
#define QSERDES_V5_5NM_TX_RES_CODE_LANE_OFFSET_RX 0x34
|
||||
#define QSERDES_V5_5NM_TX_PERL_LENGTH1 0x38
|
||||
#define QSERDES_V5_5NM_TX_PERL_LENGTH2 0x3c
|
||||
#define QSERDES_V5_5NM_TX_SERDES_BYP_EN_OUT 0x40
|
||||
#define QSERDES_V5_5NM_TX_DEBUG_BUS_SEL 0x44
|
||||
#define QSERDES_V5_5NM_TX_TRANSCEIVER_BIAS_EN 0x48
|
||||
#define QSERDES_V5_5NM_TX_HIGHZ_DRVR_EN 0x4c
|
||||
#define QSERDES_V5_5NM_TX_TX_POL_INV 0x50
|
||||
#define QSERDES_V5_5NM_TX_PARRATE_REC_DETECT_IDLE_EN 0x54
|
||||
#define QSERDES_V5_5NM_TX_BIST_PATTERN1 0x58
|
||||
#define QSERDES_V5_5NM_TX_BIST_PATTERN2 0x5c
|
||||
#define QSERDES_V5_5NM_TX_BIST_PATTERN3 0x60
|
||||
#define QSERDES_V5_5NM_TX_BIST_PATTERN4 0x64
|
||||
#define QSERDES_V5_5NM_TX_BIST_PATTERN5 0x68
|
||||
#define QSERDES_V5_5NM_TX_BIST_PATTERN6 0x6c
|
||||
#define QSERDES_V5_5NM_TX_BIST_PATTERN7 0x70
|
||||
#define QSERDES_V5_5NM_TX_BIST_PATTERN8 0x74
|
||||
#define QSERDES_V5_5NM_TX_LANE_MODE_1 0x78
|
||||
#define QSERDES_V5_5NM_TX_LANE_MODE_2 0x7c
|
||||
#define QSERDES_V5_5NM_TX_LANE_MODE_3 0x80
|
||||
#define QSERDES_V5_5NM_TX_ATB_SEL1 0x84
|
||||
#define QSERDES_V5_5NM_TX_ATB_SEL2 0x88
|
||||
#define QSERDES_V5_5NM_TX_RCV_DETECT_LVL 0x8c
|
||||
#define QSERDES_V5_5NM_TX_RCV_DETECT_LVL_2 0x90
|
||||
#define QSERDES_V5_5NM_TX_PRBS_SEED1 0x94
|
||||
#define QSERDES_V5_5NM_TX_PRBS_SEED2 0x98
|
||||
#define QSERDES_V5_5NM_TX_PRBS_SEED3 0x9c
|
||||
#define QSERDES_V5_5NM_TX_PRBS_SEED4 0xa0
|
||||
#define QSERDES_V5_5NM_TX_RESET_GEN 0xa4
|
||||
#define QSERDES_V5_5NM_TX_RESET_GEN_MUXES 0xa8
|
||||
#define QSERDES_V5_5NM_TX_TRAN_DRVR_EMP_EN 0xac
|
||||
#define QSERDES_V5_5NM_TX_VMODE_CTRL1 0xb0
|
||||
#define QSERDES_V5_5NM_TX_ALOG_OBSV_BUS_CTRL_1 0xb4
|
||||
#define QSERDES_V5_5NM_TX_BIST_STATUS 0xb8
|
||||
#define QSERDES_V5_5NM_TX_BIST_ERROR_COUNT1 0xbc
|
||||
#define QSERDES_V5_5NM_TX_BIST_ERROR_COUNT2 0xc0
|
||||
#define QSERDES_V5_5NM_TX_ALOG_OBSV_BUS_STATUS_1 0xc4
|
||||
#define QSERDES_V5_5NM_TX_LANE_DIG_CONFIG 0xc8
|
||||
#define QSERDES_V5_5NM_TX_PI_QEC_CTRL 0xcc
|
||||
#define QSERDES_V5_5NM_TX_PRE_EMPH 0xd0
|
||||
#define QSERDES_V5_5NM_TX_SW_RESET 0xd4
|
||||
#define QSERDES_V5_5NM_TX_TX_BAND 0xd8
|
||||
#define QSERDES_V5_5NM_TX_SLEW_CNTL0 0xdc
|
||||
#define QSERDES_V5_5NM_TX_SLEW_CNTL1 0xe0
|
||||
#define QSERDES_V5_5NM_TX_INTERFACE_SELECT 0xe4
|
||||
#define QSERDES_V5_5NM_TX_DIG_BKUP_CTRL 0xe8
|
||||
#define QSERDES_V5_5NM_TX_DEBUG_BUS0 0xec
|
||||
#define QSERDES_V5_5NM_TX_DEBUG_BUS1 0xf0
|
||||
#define QSERDES_V5_5NM_TX_DEBUG_BUS2 0xf4
|
||||
#define QSERDES_V5_5NM_TX_DEBUG_BUS3 0xf8
|
||||
#define QSERDES_V5_5NM_TX_TX_BKUP_RO_BUS 0xfc
|
||||
|
||||
/* Only for QMP V5 5NM PHY - RX registers */
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_FO_GAIN_RATE0 0x000
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_FO_GAIN_RATE1 0x004
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_FO_GAIN_RATE2 0x008
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_FO_GAIN_RATE3 0x00c
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_SO_GAIN_RATE0 0x010
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_SO_GAIN_RATE1 0x014
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_SO_GAIN_RATE2 0x018
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_SO_GAIN_RATE3 0x01c
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SO_SATURATION 0x020
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FO_TO_SO_DELAY 0x024
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_LOW_RATE0 0x028
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE0 0x02c
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_LOW_RATE1 0x030
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE1 0x034
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_LOW_RATE2 0x038
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE2 0x03c
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_LOW_RATE3 0x040
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE3 0x044
|
||||
#define QSERDES_V5_5NM_RX_UCDR_PI_CTRL1 0x048
|
||||
#define QSERDES_V5_5NM_RX_UCDR_PI_CTRL2 0x04c
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH1_RATE0 0x050
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH1_RATE1 0x054
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH1_RATE2 0x058
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH1_RATE3 0x05c
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH2_RATE0 0x060
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH2_RATE1 0x064
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH2_RATE2 0x068
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_THRESH2_RATE3 0x06c
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN1_RATE0 0x070
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN1_RATE1 0x074
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN1_RATE2 0x078
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN1_RATE3 0x07c
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN2_RATE0 0x080
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN2_RATE1 0x084
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN2_RATE2 0x088
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SB2_GAIN2_RATE3 0x08c
|
||||
#define QSERDES_V5_5NM_RX_RXCLK_DIV2_CTRL 0x090
|
||||
#define QSERDES_V5_5NM_RX_RX_BAND 0x094
|
||||
#define QSERDES_V5_5NM_RX_RX_TERM_BW 0x098
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FO_GAIN_RATE0 0x09c
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FO_GAIN_RATE1 0x0a0
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FO_GAIN_RATE2 0x0a4
|
||||
#define QSERDES_V5_5NM_RX_UCDR_FO_GAIN_RATE3 0x0a8
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SO_GAIN_RATE0 0x0ac
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SO_GAIN_RATE1 0x0b0
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SO_GAIN_RATE2 0x0b4
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SO_GAIN_RATE3 0x0b8
|
||||
#define QSERDES_V5_5NM_RX_UCDR_PI_CONTROLS 0x0bc
|
||||
#define QSERDES_V5_5NM_RX_UCDR_PD_DATA_FILTER_ENABLES 0x0c0
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE0 0x0c4
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE1 0x0c8
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE2 0x0cc
|
||||
#define QSERDES_V5_5NM_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3 0x0d0
|
||||
#define QSERDES_V5_5NM_RX_AUX_CONTROL 0x0d4
|
||||
#define QSERDES_V5_5NM_RX_AUXDATA_TB 0x0d8
|
||||
#define QSERDES_V5_5NM_RX_RCLK_AUXDATA_SEL 0x0dc
|
||||
#define QSERDES_V5_5NM_RX_EOM_CTRL 0x0e0
|
||||
#define QSERDES_V5_5NM_RX_AC_JTAG_ENABLE 0x0e4
|
||||
#define QSERDES_V5_5NM_RX_AC_JTAG_INITP 0x0e8
|
||||
#define QSERDES_V5_5NM_RX_AC_JTAG_INITN 0x0ec
|
||||
#define QSERDES_V5_5NM_RX_AC_JTAG_LVL 0x0f0
|
||||
#define QSERDES_V5_5NM_RX_AC_JTAG_MODE 0x0f4
|
||||
#define QSERDES_V5_5NM_RX_AC_JTAG_RESET 0x0f8
|
||||
#define QSERDES_V5_5NM_RX_RX_RCVR_IQ_EN 0x0fc
|
||||
#define QSERDES_V5_5NM_RX_RX_Q_EN_RATES 0x100
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_I0_DC_OFFSETS 0x104
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_I0BAR_DC_OFFSETS 0x108
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_I1_DC_OFFSETS 0x10c
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_I1BAR_DC_OFFSETS 0x110
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_Q_DC_OFFSETS 0x114
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_QBAR_DC_OFFSETS 0x118
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_A_DC_OFFSETS 0x11c
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_ABAR_DC_OFFSETS 0x120
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_EN 0x124
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_ENABLES 0x128
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_SIGN 0x12c
|
||||
#define QSERDES_V5_5NM_RX_RX_IVCM_CAL_CODE_OVERRIDE 0x130
|
||||
#define QSERDES_V5_5NM_RX_RX_IVCM_CAL_CTRL1 0x134
|
||||
#define QSERDES_V5_5NM_RX_RX_IVCM_CAL_CTRL2 0x138
|
||||
#define QSERDES_V5_5NM_RX_RX_IVCM_POSTCAL_OFFSET 0x13c
|
||||
#define QSERDES_V5_5NM_RX_RX_SUMMER_CAL_SPD_MODE 0x140
|
||||
#define QSERDES_V5_5NM_RX_RX_HIGHZ_PARRATE 0x144
|
||||
#define QSERDES_V5_5NM_RX_RX_TERM_AC_BYPASS_DC_COUPLE_OFFSET 0x148
|
||||
#define QSERDES_V5_5NM_RX_DFE_1 0x14c
|
||||
#define QSERDES_V5_5NM_RX_DFE_2 0x150
|
||||
#define QSERDES_V5_5NM_RX_DFE_3 0x154
|
||||
#define QSERDES_V5_5NM_RX_DFE_4 0x158
|
||||
#define QSERDES_V5_5NM_RX_DFE_TAP3_CTRL 0x15c
|
||||
#define QSERDES_V5_5NM_RX_DFE_TAP3_MANVAL_KTAP 0x160
|
||||
#define QSERDES_V5_5NM_RX_DFE_TAP4_CTRL 0x164
|
||||
#define QSERDES_V5_5NM_RX_DFE_TAP4_MANVAL_KTAP 0x168
|
||||
#define QSERDES_V5_5NM_RX_DFE_TAP5_CTRL 0x16c
|
||||
#define QSERDES_V5_5NM_RX_DFE_TAP5_MANVAL_KTAP 0x170
|
||||
#define QSERDES_V5_5NM_RX_TX_ADPT_CTRL 0x174
|
||||
#define QSERDES_V5_5NM_RX_DFE_DAC_ENABLE1 0x178
|
||||
#define QSERDES_V5_5NM_RX_DFE_DAC_ENABLE2 0x17c
|
||||
#define QSERDES_V5_5NM_RX_TX_ADAPT_PRE_THRESH1 0x180
|
||||
#define QSERDES_V5_5NM_RX_TX_ADAPT_PRE_THRESH2 0x184
|
||||
#define QSERDES_V5_5NM_RX_TX_ADAPT_POST_THRESH1 0x188
|
||||
#define QSERDES_V5_5NM_RX_TX_ADAPT_POST_THRESH2 0x18c
|
||||
#define QSERDES_V5_5NM_RX_TX_ADAPT_MAIN_THRESH1 0x190
|
||||
#define QSERDES_V5_5NM_RX_TX_ADAPT_MAIN_THRESH2 0x194
|
||||
#define QSERDES_V5_5NM_RX_VGA_CAL_CNTRL1 0x198
|
||||
#define QSERDES_V5_5NM_RX_VGA_CAL_CNTRL2 0x19c
|
||||
#define QSERDES_V5_5NM_RX_VGA_CAL_MAN_VAL 0x1a0
|
||||
#define QSERDES_V5_5NM_RX_VTHRESH_CAL_CNTRL1 0x1a4
|
||||
#define QSERDES_V5_5NM_RX_VTHRESH_CAL_CNTRL2 0x1a8
|
||||
#define QSERDES_V5_5NM_RX_VTHRESH_CAL_MAN_VAL_RATE0 0x1ac
|
||||
#define QSERDES_V5_5NM_RX_VTHRESH_CAL_MAN_VAL_RATE1 0x1b0
|
||||
#define QSERDES_V5_5NM_RX_VTHRESH_CAL_MAN_VAL_RATE2 0x1b4
|
||||
#define QSERDES_V5_5NM_RX_VTHRESH_CAL_MAN_VAL_RATE3 0x1b8
|
||||
#define QSERDES_V5_5NM_RX_GM_CAL 0x1bc
|
||||
#define QSERDES_V5_5NM_RX_RX_VGA_GAIN2_BLK1 0x1c0
|
||||
#define QSERDES_V5_5NM_RX_RX_VGA_GAIN2_BLK2 0x1c4
|
||||
#define QSERDES_V5_5NM_RX_RX_EQU_ADAPTOR_CNTRL2 0x1c8
|
||||
#define QSERDES_V5_5NM_RX_RX_EQU_ADAPTOR_CNTRL3 0x1cc
|
||||
#define QSERDES_V5_5NM_RX_RX_EQU_ADAPTOR_CNTRL4 0x1d0
|
||||
#define QSERDES_V5_5NM_RX_RX_IDAC_TSETTLE_LOW 0x1d4
|
||||
#define QSERDES_V5_5NM_RX_RX_EQ_OFFSET_LSB 0x1d8
|
||||
#define QSERDES_V5_5NM_RX_RX_EQ_OFFSET_MSB 0x1dc
|
||||
#define QSERDES_V5_5NM_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x1e0
|
||||
#define QSERDES_V5_5NM_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x1e4
|
||||
#define QSERDES_V5_5NM_RX_SIGDET_ENABLES 0x1e8
|
||||
#define QSERDES_V5_5NM_RX_SIGDET_CNTRL 0x1ec
|
||||
#define QSERDES_V5_5NM_RX_SIGDET_LVL 0x1f0
|
||||
#define QSERDES_V5_5NM_RX_SIGDET_DEGLITCH_CNTRL 0x1f4
|
||||
#define QSERDES_V5_5NM_RX_CDR_FREEZE_UP_DN 0x1f8
|
||||
#define QSERDES_V5_5NM_RX_CDR_RESET_OVERRIDE 0x1fc
|
||||
#define QSERDES_V5_5NM_RX_RX_INTERFACE_MODE 0x200
|
||||
#define QSERDES_V5_5NM_RX_JITTER_GEN_MODE 0x204
|
||||
#define QSERDES_V5_5NM_RX_SJ_AMP1 0x208
|
||||
#define QSERDES_V5_5NM_RX_SJ_AMP2 0x20c
|
||||
#define QSERDES_V5_5NM_RX_SJ_PER1 0x210
|
||||
#define QSERDES_V5_5NM_RX_SJ_PER2 0x214
|
||||
#define QSERDES_V5_5NM_RX_PPM_OFFSET1 0x218
|
||||
#define QSERDES_V5_5NM_RX_PPM_OFFSET2 0x21c
|
||||
#define QSERDES_V5_5NM_RX_SIGN_PPM_PERIOD1 0x220
|
||||
#define QSERDES_V5_5NM_RX_SIGN_PPM_PERIOD2 0x224
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B0 0x228
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B1 0x22c
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B2 0x230
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B3 0x234
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B4 0x238
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B5 0x23c
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B6 0x240
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE_0_1_B7 0x244
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B0 0x248
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B1 0x24c
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B2 0x250
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B3 0x254
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B4 0x258
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B5 0x25c
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B6 0x260
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE2_B7 0x264
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B0 0x268
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B1 0x26c
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B2 0x270
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B3 0x274
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B4 0x278
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B5 0x27c
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B6 0x280
|
||||
#define QSERDES_V5_5NM_RX_RX_MODE_RATE3_B7 0x284
|
||||
#define QSERDES_V5_5NM_RX_PHPRE_CTRL 0x288
|
||||
#define QSERDES_V5_5NM_RX_PHPRE_INITVAL 0x28c
|
||||
#define QSERDES_V5_5NM_RX_DFE_EN_TIMER 0x290
|
||||
#define QSERDES_V5_5NM_RX_DFE_CTLE_POST_CAL_OFFSET 0x294
|
||||
#define QSERDES_V5_5NM_RX_DCC_CTRL1 0x298
|
||||
#define QSERDES_V5_5NM_RX_DCC_CTRL2 0x29c
|
||||
#define QSERDES_V5_5NM_RX_DCC_OFFSET 0x2a0
|
||||
#define QSERDES_V5_5NM_RX_DCC_CMUX_POSTCAL_OFFSET 0x2a4
|
||||
#define QSERDES_V5_5NM_RX_DCC_CMUX_CAL_CTRL1 0x2a8
|
||||
#define QSERDES_V5_5NM_RX_DCC_CMUX_CAL_CTRL2 0x2ac
|
||||
#define QSERDES_V5_5NM_RX_ALOG_OBSV_BUS_CTRL_1 0x2b0
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_CTRL1 0x2b4
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_CTRL2 0x2b8
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_CTRL3 0x2bc
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_CTRL_4 0x2c0
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_CFG_RATE_0_1 0x2c4
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_CFG_RATE_2_3 0x2c8
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_CTRL1 0x2cc
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_CTRL2 0x2d0
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH1_RATE210 0x2d4
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH1_RATE3 0x2d8
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH2_RATE210 0x2dc
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH2_RATE3 0x2e0
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH3_RATE210 0x2e4
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH3_RATE3 0x2e8
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH4_RATE210 0x2ec
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH4_RATE3 0x2f0
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH5_RATE210 0x2f4
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH5_RATE3 0x2f8
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH6_RATE210 0x2fc
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH6_RATE3 0x300
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH7_RATE210 0x304
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_THRESH7_RATE3 0x308
|
||||
#define QSERDES_V5_5NM_RX_Q_PI_INTRINSIC_BIAS_RATE10 0x30c
|
||||
#define QSERDES_V5_5NM_RX_Q_PI_INTRINSIC_BIAS_RATE32 0x310
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_VERTICAL_CTRL 0x314
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_VERTICAL_CODE 0x318
|
||||
#define QSERDES_V5_5NM_RX_RES_CODE_THRESH_HIGH_AND_BYP 0x31c
|
||||
#define QSERDES_V5_5NM_RX_RES_CODE_THRESH_LOW 0x320
|
||||
#define QSERDES_V5_5NM_RX_RX_BKUP_CTRL1 0x324
|
||||
#define QSERDES_V5_5NM_RX_RX_BKUP_CTRL2 0x328
|
||||
#define QSERDES_V5_5NM_RX_RX_BKUP_CTRL3 0x32c
|
||||
#define QSERDES_V5_5NM_RX_PI_CTRL1 0x330
|
||||
#define QSERDES_V5_5NM_RX_PI_CTRL2 0x334
|
||||
#define QSERDES_V5_5NM_RX_PI_QUAD 0x338
|
||||
#define QSERDES_V5_5NM_RX_QPI_CTRL1 0x33c
|
||||
#define QSERDES_V5_5NM_RX_QPI_CTRL2 0x340
|
||||
#define QSERDES_V5_5NM_RX_QPI_QUAD 0x344
|
||||
#define QSERDES_V5_5NM_RX_IDATA1 0x348
|
||||
#define QSERDES_V5_5NM_RX_IDATA2 0x34c
|
||||
#define QSERDES_V5_5NM_RX_IDATA3 0x350
|
||||
#define QSERDES_V5_5NM_RX_AC_JTAG_OUTP 0x354
|
||||
#define QSERDES_V5_5NM_RX_AC_JTAG_OUTN 0x358
|
||||
#define QSERDES_V5_5NM_RX_RX_SIGDET 0x35c
|
||||
#define QSERDES_V5_5NM_RX_ALOG_OBSV_BUS_STATUS_1 0x360
|
||||
#define QSERDES_V5_5NM_RX_READ_EQCODE 0x364
|
||||
#define QSERDES_V5_5NM_RX_READ_OFFSETCODE 0x368
|
||||
#define QSERDES_V5_5NM_RX_IA_ERROR_COUNTER_LOW 0x36c
|
||||
#define QSERDES_V5_5NM_RX_IA_ERROR_COUNTER_HIGH 0x370
|
||||
#define QSERDES_V5_5NM_RX_VGA_READ_CODE 0x374
|
||||
#define QSERDES_V5_5NM_RX_VTHRESH_READ_CODE 0x378
|
||||
#define QSERDES_V5_5NM_RX_DFE_TAP1_READ_CODE 0x37c
|
||||
#define QSERDES_V5_5NM_RX_DFE_TAP2_READ_CODE 0x380
|
||||
#define QSERDES_V5_5NM_RX_DFE_TAP3_READ_CODE 0x384
|
||||
#define QSERDES_V5_5NM_RX_DFE_TAP4_READ_CODE 0x388
|
||||
#define QSERDES_V5_5NM_RX_DFE_TAP5_READ_CODE 0x38c
|
||||
#define QSERDES_V5_5NM_RX_IDAC_STATUS_I0 0x390
|
||||
#define QSERDES_V5_5NM_RX_IDAC_STATUS_I0BAR 0x394
|
||||
#define QSERDES_V5_5NM_RX_IDAC_STATUS_I1 0x398
|
||||
#define QSERDES_V5_5NM_RX_IDAC_STATUS_I1BAR 0x39c
|
||||
#define QSERDES_V5_5NM_RX_IDAC_STATUS_Q 0x3a0
|
||||
#define QSERDES_V5_5NM_RX_IDAC_STATUS_QBAR 0x3a4
|
||||
#define QSERDES_V5_5NM_RX_IDAC_STATUS_A 0x3a8
|
||||
#define QSERDES_V5_5NM_RX_IDAC_STATUS_ABAR 0x3ac
|
||||
#define QSERDES_V5_5NM_RX_IDAC_STATUS_SM_ON 0x3b0
|
||||
#define QSERDES_V5_5NM_RX_IDAC_STATUS_SIGNERROR 0x3b4
|
||||
#define QSERDES_V5_5NM_RX_IVCM_CAL_STATUS 0x3b8
|
||||
#define QSERDES_V5_5NM_RX_IVCM_CAL_DEBUG_STATUS 0x3bc
|
||||
#define QSERDES_V5_5NM_RX_DCC_CAL_STATUS 0x3c0
|
||||
#define QSERDES_V5_5NM_RX_DCC_READ_CODE_STATUS 0x3c4
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_DEBUG1_STATUS 0x3c8
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_DEBUG2_STATUS 0x3cc
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_READ_CODE_STATUS 0x3d0
|
||||
#define QSERDES_V5_5NM_RX_EOM_ERR_CNT_LSB_STATUS 0x3d4
|
||||
#define QSERDES_V5_5NM_RX_EOM_ERR_CNT_MSB_STATUS 0x3d8
|
||||
#define QSERDES_V5_5NM_RX_RX_MARG_COARSE_TUNE_STATUS 0x3dc
|
||||
#define QSERDES_V5_5NM_RX_RX_BKUP_READ_BUS1_STATUS 0x3e0
|
||||
#define QSERDES_V5_5NM_RX_RX_BKUP_READ_BUS2_STATUS 0x3e4
|
||||
#define QSERDES_V5_5NM_RX_RX_BKUP_READ_BUS3_STATUS 0x3e8
|
||||
|
||||
#endif
|
@ -28,53 +28,15 @@
|
||||
#define SW_RESET BIT(0)
|
||||
/* QPHY_POWER_DOWN_CONTROL */
|
||||
#define SW_PWRDN BIT(0)
|
||||
#define REFCLK_DRV_DSBL BIT(1)
|
||||
/* QPHY_START_CONTROL bits */
|
||||
#define SERDES_START BIT(0)
|
||||
#define PCS_START BIT(1)
|
||||
#define PLL_READY_GATE_EN BIT(3)
|
||||
/* QPHY_PCS_STATUS bit */
|
||||
#define PHYSTATUS BIT(6)
|
||||
#define PHYSTATUS_4_20 BIT(7)
|
||||
/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */
|
||||
/* QPHY_PCS_READY_STATUS bit */
|
||||
#define PCS_READY BIT(0)
|
||||
|
||||
/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
|
||||
/* DP PHY soft reset */
|
||||
#define SW_DPPHY_RESET BIT(0)
|
||||
/* mux to select DP PHY reset control, 0:HW control, 1: software reset */
|
||||
#define SW_DPPHY_RESET_MUX BIT(1)
|
||||
/* USB3 PHY soft reset */
|
||||
#define SW_USB3PHY_RESET BIT(2)
|
||||
/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */
|
||||
#define SW_USB3PHY_RESET_MUX BIT(3)
|
||||
|
||||
/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */
|
||||
#define USB3_MODE BIT(0) /* enables USB3 mode */
|
||||
#define DP_MODE BIT(1) /* enables DP mode */
|
||||
|
||||
/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */
|
||||
#define ARCVR_DTCT_EN BIT(0)
|
||||
#define ALFPS_DTCT_EN BIT(1)
|
||||
#define ARCVR_DTCT_EVENT_SEL BIT(4)
|
||||
|
||||
/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */
|
||||
#define IRQ_CLEAR BIT(0)
|
||||
|
||||
/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */
|
||||
#define RCVR_DETECT BIT(0)
|
||||
|
||||
/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
|
||||
#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
|
||||
|
||||
#define PHY_INIT_COMPLETE_TIMEOUT 10000
|
||||
#define POWER_DOWN_DELAY_US_MIN 10
|
||||
#define POWER_DOWN_DELAY_US_MAX 11
|
||||
|
||||
#define MAX_PROP_NAME 32
|
||||
|
||||
/* Define the assumed distance between lanes for underspecified device trees. */
|
||||
#define QMP_PHY_LEGACY_LANE_STRIDE 0x400
|
||||
|
||||
struct qmp_phy_init_tbl {
|
||||
unsigned int offset;
|
||||
@ -115,22 +77,11 @@ struct qmp_phy_init_tbl {
|
||||
|
||||
/* set of registers with offsets different per-PHY */
|
||||
enum qphy_reg_layout {
|
||||
/* Common block control registers */
|
||||
QPHY_COM_SW_RESET,
|
||||
QPHY_COM_POWER_DOWN_CONTROL,
|
||||
QPHY_COM_START_CONTROL,
|
||||
QPHY_COM_PCS_READY_STATUS,
|
||||
/* PCS registers */
|
||||
QPHY_SW_RESET,
|
||||
QPHY_START_CTRL,
|
||||
QPHY_PCS_READY_STATUS,
|
||||
QPHY_PCS_STATUS,
|
||||
QPHY_PCS_AUTONOMOUS_MODE_CTRL,
|
||||
QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR,
|
||||
QPHY_PCS_LFPS_RXTERM_IRQ_STATUS,
|
||||
QPHY_PCS_POWER_DOWN_CONTROL,
|
||||
/* PCS_MISC registers */
|
||||
QPHY_PCS_MISC_TYPEC_CTRL,
|
||||
/* Keep last to ensure regs_layout arrays are properly initialized */
|
||||
QPHY_LAYOUT_SIZE
|
||||
};
|
||||
@ -580,14 +531,9 @@ static const struct qmp_phy_init_tbl sm8350_ufsphy_pcs_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
|
||||
};
|
||||
|
||||
struct qmp_phy;
|
||||
|
||||
/* struct qmp_phy_cfg - per-PHY initialization config */
|
||||
struct qmp_phy_cfg {
|
||||
/* phy-type - PCIE/UFS/USB */
|
||||
unsigned int type;
|
||||
/* number of lanes provided by phy */
|
||||
int nlanes;
|
||||
int lanes;
|
||||
|
||||
/* Init sequence for PHY blocks - serdes, tx, rx, pcs */
|
||||
const struct qmp_phy_init_tbl *serdes_tbl;
|
||||
@ -614,9 +560,6 @@ struct qmp_phy_cfg {
|
||||
/* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */
|
||||
unsigned int phy_status;
|
||||
|
||||
/* true, if PHY has secondary tx/rx lanes to be configured */
|
||||
bool is_dual_lane_phy;
|
||||
|
||||
/* true, if PCS block has no separate SW_RESET register */
|
||||
bool no_pcs_sw_reset;
|
||||
};
|
||||
@ -633,9 +576,7 @@ struct qmp_phy_cfg {
|
||||
* @tx2: iomapped memory space for second lane's tx (in dual lane PHYs)
|
||||
* @rx2: iomapped memory space for second lane's rx (in dual lane PHYs)
|
||||
* @pcs_misc: iomapped memory space for lane's pcs_misc
|
||||
* @index: lane index
|
||||
* @qmp: QMP phy to which this lane belongs
|
||||
* @mode: current PHY mode
|
||||
*/
|
||||
struct qmp_phy {
|
||||
struct phy *phy;
|
||||
@ -647,9 +588,7 @@ struct qmp_phy {
|
||||
void __iomem *tx2;
|
||||
void __iomem *rx2;
|
||||
void __iomem *pcs_misc;
|
||||
unsigned int index;
|
||||
struct qcom_qmp *qmp;
|
||||
enum phy_mode mode;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -719,8 +658,7 @@ static const char * const qmp_phy_vreg_l[] = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg msm8996_ufs_cfg = {
|
||||
.type = PHY_TYPE_UFS,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = msm8996_ufs_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(msm8996_ufs_serdes_tbl),
|
||||
@ -745,8 +683,7 @@ static const struct qmp_phy_cfg msm8996_ufs_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
|
||||
.type = PHY_TYPE_UFS,
|
||||
.nlanes = 2,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = sdm845_ufsphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sdm845_ufsphy_serdes_tbl),
|
||||
@ -766,13 +703,11 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
|
||||
.pwrdn_ctrl = SW_PWRDN,
|
||||
.phy_status = PHYSTATUS,
|
||||
|
||||
.is_dual_lane_phy = true,
|
||||
.no_pcs_sw_reset = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm6115_ufsphy_cfg = {
|
||||
.type = PHY_TYPE_UFS,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sm6115_ufsphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm6115_ufsphy_serdes_tbl),
|
||||
@ -795,8 +730,7 @@ static const struct qmp_phy_cfg sm6115_ufsphy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8150_ufsphy_cfg = {
|
||||
.type = PHY_TYPE_UFS,
|
||||
.nlanes = 2,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = sm8150_ufsphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8150_ufsphy_serdes_tbl),
|
||||
@ -815,13 +749,10 @@ static const struct qmp_phy_cfg sm8150_ufsphy_cfg = {
|
||||
.start_ctrl = SERDES_START,
|
||||
.pwrdn_ctrl = SW_PWRDN,
|
||||
.phy_status = PHYSTATUS,
|
||||
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8350_ufsphy_cfg = {
|
||||
.type = PHY_TYPE_UFS,
|
||||
.nlanes = 2,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = sm8350_ufsphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl),
|
||||
@ -840,13 +771,10 @@ static const struct qmp_phy_cfg sm8350_ufsphy_cfg = {
|
||||
.start_ctrl = SERDES_START,
|
||||
.pwrdn_ctrl = SW_PWRDN,
|
||||
.phy_status = PHYSTATUS,
|
||||
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8450_ufsphy_cfg = {
|
||||
.type = PHY_TYPE_UFS,
|
||||
.nlanes = 2,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = sm8350_ufsphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl),
|
||||
@ -865,11 +793,9 @@ static const struct qmp_phy_cfg sm8450_ufsphy_cfg = {
|
||||
.start_ctrl = SERDES_START,
|
||||
.pwrdn_ctrl = SW_PWRDN,
|
||||
.phy_status = PHYSTATUS,
|
||||
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static void qcom_qmp_phy_ufs_configure_lane(void __iomem *base,
|
||||
static void qmp_ufs_configure_lane(void __iomem *base,
|
||||
const unsigned int *regs,
|
||||
const struct qmp_phy_init_tbl tbl[],
|
||||
int num,
|
||||
@ -892,27 +818,27 @@ static void qcom_qmp_phy_ufs_configure_lane(void __iomem *base,
|
||||
}
|
||||
}
|
||||
|
||||
static void qcom_qmp_phy_ufs_configure(void __iomem *base,
|
||||
static void qmp_ufs_configure(void __iomem *base,
|
||||
const unsigned int *regs,
|
||||
const struct qmp_phy_init_tbl tbl[],
|
||||
int num)
|
||||
{
|
||||
qcom_qmp_phy_ufs_configure_lane(base, regs, tbl, num, 0xff);
|
||||
qmp_ufs_configure_lane(base, regs, tbl, num, 0xff);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_serdes_init(struct qmp_phy *qphy)
|
||||
static int qmp_ufs_serdes_init(struct qmp_phy *qphy)
|
||||
{
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
void __iomem *serdes = qphy->serdes;
|
||||
const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl;
|
||||
int serdes_tbl_num = cfg->serdes_tbl_num;
|
||||
|
||||
qcom_qmp_phy_ufs_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num);
|
||||
qmp_ufs_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_com_init(struct qmp_phy *qphy)
|
||||
static int qmp_ufs_com_init(struct qmp_phy *qphy)
|
||||
{
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
@ -946,7 +872,7 @@ err_disable_regulators:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_com_exit(struct qmp_phy *qphy)
|
||||
static int qmp_ufs_com_exit(struct qmp_phy *qphy)
|
||||
{
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
@ -960,7 +886,7 @@ static int qcom_qmp_phy_ufs_com_exit(struct qmp_phy *qphy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_init(struct phy *phy)
|
||||
static int qmp_ufs_init(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
@ -995,14 +921,14 @@ static int qcom_qmp_phy_ufs_init(struct phy *phy)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = qcom_qmp_phy_ufs_com_init(qphy);
|
||||
ret = qmp_ufs_com_init(qphy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_power_on(struct phy *phy)
|
||||
static int qmp_ufs_power_on(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
@ -1014,27 +940,24 @@ static int qcom_qmp_phy_ufs_power_on(struct phy *phy)
|
||||
unsigned int mask, val, ready;
|
||||
int ret;
|
||||
|
||||
qcom_qmp_phy_ufs_serdes_init(qphy);
|
||||
qmp_ufs_serdes_init(qphy);
|
||||
|
||||
/* Tx, Rx, and PCS configurations */
|
||||
qcom_qmp_phy_ufs_configure_lane(tx, cfg->regs,
|
||||
cfg->tx_tbl, cfg->tx_tbl_num, 1);
|
||||
qmp_ufs_configure_lane(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num, 1);
|
||||
|
||||
/* Configuration for other LANE for USB-DP combo PHY */
|
||||
if (cfg->is_dual_lane_phy) {
|
||||
qcom_qmp_phy_ufs_configure_lane(qphy->tx2, cfg->regs,
|
||||
cfg->tx_tbl, cfg->tx_tbl_num, 2);
|
||||
if (cfg->lanes >= 2) {
|
||||
qmp_ufs_configure_lane(qphy->tx2, cfg->regs,
|
||||
cfg->tx_tbl, cfg->tx_tbl_num, 2);
|
||||
}
|
||||
|
||||
qcom_qmp_phy_ufs_configure_lane(rx, cfg->regs,
|
||||
cfg->rx_tbl, cfg->rx_tbl_num, 1);
|
||||
qmp_ufs_configure_lane(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num, 1);
|
||||
|
||||
if (cfg->is_dual_lane_phy) {
|
||||
qcom_qmp_phy_ufs_configure_lane(qphy->rx2, cfg->regs,
|
||||
cfg->rx_tbl, cfg->rx_tbl_num, 2);
|
||||
if (cfg->lanes >= 2) {
|
||||
qmp_ufs_configure_lane(qphy->rx2, cfg->regs,
|
||||
cfg->rx_tbl, cfg->rx_tbl_num, 2);
|
||||
}
|
||||
|
||||
qcom_qmp_phy_ufs_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
|
||||
qmp_ufs_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
|
||||
|
||||
ret = reset_control_deassert(qmp->ufs_reset);
|
||||
if (ret)
|
||||
@ -1060,7 +983,7 @@ static int qcom_qmp_phy_ufs_power_on(struct phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_power_off(struct phy *phy)
|
||||
static int qmp_ufs_power_off(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
@ -1084,51 +1007,41 @@ static int qcom_qmp_phy_ufs_power_off(struct phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_exit(struct phy *phy)
|
||||
static int qmp_ufs_exit(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
|
||||
qcom_qmp_phy_ufs_com_exit(qphy);
|
||||
qmp_ufs_com_exit(qphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_enable(struct phy *phy)
|
||||
static int qmp_ufs_enable(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = qcom_qmp_phy_ufs_init(phy);
|
||||
ret = qmp_ufs_init(phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_qmp_phy_ufs_power_on(phy);
|
||||
ret = qmp_ufs_power_on(phy);
|
||||
if (ret)
|
||||
qcom_qmp_phy_ufs_exit(phy);
|
||||
qmp_ufs_exit(phy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_disable(struct phy *phy)
|
||||
static int qmp_ufs_disable(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = qcom_qmp_phy_ufs_power_off(phy);
|
||||
ret = qmp_ufs_power_off(phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
return qcom_qmp_phy_ufs_exit(phy);
|
||||
return qmp_ufs_exit(phy);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_set_mode(struct phy *phy,
|
||||
enum phy_mode mode, int submode)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
|
||||
qphy->mode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
static int qmp_ufs_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
int num = cfg->num_vregs;
|
||||
@ -1144,7 +1057,7 @@ static int qcom_qmp_phy_ufs_vreg_init(struct device *dev, const struct qmp_phy_c
|
||||
return devm_regulator_bulk_get(dev, num, qmp->vregs);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_ufs_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
static int qmp_ufs_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
int num = cfg->num_clks;
|
||||
@ -1161,14 +1074,12 @@ static int qcom_qmp_phy_ufs_clk_init(struct device *dev, const struct qmp_phy_cf
|
||||
}
|
||||
|
||||
static const struct phy_ops qcom_qmp_ufs_ops = {
|
||||
.power_on = qcom_qmp_phy_ufs_enable,
|
||||
.power_off = qcom_qmp_phy_ufs_disable,
|
||||
.set_mode = qcom_qmp_phy_ufs_set_mode,
|
||||
.power_on = qmp_ufs_enable,
|
||||
.power_off = qmp_ufs_disable,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static
|
||||
int qcom_qmp_phy_ufs_create(struct device *dev, struct device_node *np, int id,
|
||||
static int qmp_ufs_create(struct device *dev, struct device_node *np, int id,
|
||||
void __iomem *serdes, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
@ -1188,45 +1099,33 @@ int qcom_qmp_phy_ufs_create(struct device *dev, struct device_node *np, int id,
|
||||
* For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5
|
||||
* For single lane PHYs: pcs_misc (optional) -> 3.
|
||||
*/
|
||||
qphy->tx = of_iomap(np, 0);
|
||||
if (!qphy->tx)
|
||||
return -ENOMEM;
|
||||
qphy->tx = devm_of_iomap(dev, np, 0, NULL);
|
||||
if (IS_ERR(qphy->tx))
|
||||
return PTR_ERR(qphy->tx);
|
||||
|
||||
qphy->rx = of_iomap(np, 1);
|
||||
if (!qphy->rx)
|
||||
return -ENOMEM;
|
||||
qphy->rx = devm_of_iomap(dev, np, 1, NULL);
|
||||
if (IS_ERR(qphy->rx))
|
||||
return PTR_ERR(qphy->rx);
|
||||
|
||||
qphy->pcs = of_iomap(np, 2);
|
||||
if (!qphy->pcs)
|
||||
return -ENOMEM;
|
||||
qphy->pcs = devm_of_iomap(dev, np, 2, NULL);
|
||||
if (IS_ERR(qphy->pcs))
|
||||
return PTR_ERR(qphy->pcs);
|
||||
|
||||
/*
|
||||
* If this is a dual-lane PHY, then there should be registers for the
|
||||
* second lane. Some old device trees did not specify this, so fall
|
||||
* back to old legacy behavior of assuming they can be reached at an
|
||||
* offset from the first lane.
|
||||
*/
|
||||
if (cfg->is_dual_lane_phy) {
|
||||
qphy->tx2 = of_iomap(np, 3);
|
||||
qphy->rx2 = of_iomap(np, 4);
|
||||
if (!qphy->tx2 || !qphy->rx2) {
|
||||
dev_warn(dev,
|
||||
"Underspecified device tree, falling back to legacy register regions\n");
|
||||
if (cfg->lanes >= 2) {
|
||||
qphy->tx2 = devm_of_iomap(dev, np, 3, NULL);
|
||||
if (IS_ERR(qphy->tx2))
|
||||
return PTR_ERR(qphy->tx2);
|
||||
|
||||
/* In the old version, pcs_misc is at index 3. */
|
||||
qphy->pcs_misc = qphy->tx2;
|
||||
qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE;
|
||||
qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE;
|
||||
|
||||
} else {
|
||||
qphy->pcs_misc = of_iomap(np, 5);
|
||||
}
|
||||
qphy->rx2 = devm_of_iomap(dev, np, 4, NULL);
|
||||
if (IS_ERR(qphy->rx2))
|
||||
return PTR_ERR(qphy->rx2);
|
||||
|
||||
qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL);
|
||||
} else {
|
||||
qphy->pcs_misc = of_iomap(np, 3);
|
||||
qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL);
|
||||
}
|
||||
|
||||
if (!qphy->pcs_misc)
|
||||
if (IS_ERR(qphy->pcs_misc))
|
||||
dev_vdbg(dev, "PHY pcs_misc-reg not used\n");
|
||||
|
||||
generic_phy = devm_phy_create(dev, np, &qcom_qmp_ufs_ops);
|
||||
@ -1237,7 +1136,6 @@ int qcom_qmp_phy_ufs_create(struct device *dev, struct device_node *np, int id,
|
||||
}
|
||||
|
||||
qphy->phy = generic_phy;
|
||||
qphy->index = id;
|
||||
qphy->qmp = qmp;
|
||||
qmp->phys[id] = qphy;
|
||||
phy_set_drvdata(generic_phy, qphy);
|
||||
@ -1245,7 +1143,7 @@ int qcom_qmp_phy_ufs_create(struct device *dev, struct device_node *np, int id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_qmp_phy_ufs_of_match_table[] = {
|
||||
static const struct of_device_id qmp_ufs_of_match_table[] = {
|
||||
{
|
||||
.compatible = "qcom,msm8996-qmp-ufs-phy",
|
||||
.data = &msm8996_ufs_cfg,
|
||||
@ -1282,9 +1180,9 @@ static const struct of_device_id qcom_qmp_phy_ufs_of_match_table[] = {
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_qmp_phy_ufs_of_match_table);
|
||||
MODULE_DEVICE_TABLE(of, qmp_ufs_of_match_table);
|
||||
|
||||
static int qcom_qmp_phy_ufs_probe(struct platform_device *pdev)
|
||||
static int qmp_ufs_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_qmp *qmp;
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -1312,17 +1210,14 @@ static int qcom_qmp_phy_ufs_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(serdes))
|
||||
return PTR_ERR(serdes);
|
||||
|
||||
ret = qcom_qmp_phy_ufs_clk_init(dev, cfg);
|
||||
ret = qmp_ufs_clk_init(dev, cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_qmp_phy_ufs_vreg_init(dev, cfg);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to get regulator supplies: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
ret = qmp_ufs_vreg_init(dev, cfg);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to get regulator supplies\n");
|
||||
|
||||
num = of_get_available_child_count(dev->of_node);
|
||||
/* do we have a rogue child node ? */
|
||||
@ -1333,18 +1228,10 @@ static int qcom_qmp_phy_ufs_probe(struct platform_device *pdev)
|
||||
if (!qmp->phys)
|
||||
return -ENOMEM;
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
/*
|
||||
* Prevent runtime pm from being ON by default. Users can enable
|
||||
* it using power/control in sysfs.
|
||||
*/
|
||||
pm_runtime_forbid(dev);
|
||||
|
||||
id = 0;
|
||||
for_each_available_child_of_node(dev->of_node, child) {
|
||||
/* Create per-lane phy */
|
||||
ret = qcom_qmp_phy_ufs_create(dev, child, id, serdes, cfg);
|
||||
ret = qmp_ufs_create(dev, child, id, serdes, cfg);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to create lane%d phy, %d\n",
|
||||
id, ret);
|
||||
@ -1355,28 +1242,23 @@ static int qcom_qmp_phy_ufs_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
if (!IS_ERR(phy_provider))
|
||||
dev_info(dev, "Registered Qcom-QMP phy\n");
|
||||
else
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
|
||||
err_node_put:
|
||||
pm_runtime_disable(dev);
|
||||
of_node_put(child);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver qcom_qmp_phy_ufs_driver = {
|
||||
.probe = qcom_qmp_phy_ufs_probe,
|
||||
static struct platform_driver qmp_ufs_driver = {
|
||||
.probe = qmp_ufs_probe,
|
||||
.driver = {
|
||||
.name = "qcom-qmp-ufs-phy",
|
||||
.of_match_table = qcom_qmp_phy_ufs_of_match_table,
|
||||
.of_match_table = qmp_ufs_of_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(qcom_qmp_phy_ufs_driver);
|
||||
module_platform_driver(qmp_ufs_driver);
|
||||
|
||||
MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>");
|
||||
MODULE_DESCRIPTION("Qualcomm QMP UFS PHY driver");
|
||||
|
@ -28,16 +28,11 @@
|
||||
#define SW_RESET BIT(0)
|
||||
/* QPHY_POWER_DOWN_CONTROL */
|
||||
#define SW_PWRDN BIT(0)
|
||||
#define REFCLK_DRV_DSBL BIT(1)
|
||||
/* QPHY_START_CONTROL bits */
|
||||
#define SERDES_START BIT(0)
|
||||
#define PCS_START BIT(1)
|
||||
#define PLL_READY_GATE_EN BIT(3)
|
||||
/* QPHY_PCS_STATUS bit */
|
||||
#define PHYSTATUS BIT(6)
|
||||
#define PHYSTATUS_4_20 BIT(7)
|
||||
/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */
|
||||
#define PCS_READY BIT(0)
|
||||
|
||||
/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
|
||||
/* DP PHY soft reset */
|
||||
@ -71,11 +66,6 @@
|
||||
#define POWER_DOWN_DELAY_US_MIN 10
|
||||
#define POWER_DOWN_DELAY_US_MAX 11
|
||||
|
||||
#define MAX_PROP_NAME 32
|
||||
|
||||
/* Define the assumed distance between lanes for underspecified device trees. */
|
||||
#define QMP_PHY_LEGACY_LANE_STRIDE 0x400
|
||||
|
||||
struct qmp_phy_init_tbl {
|
||||
unsigned int offset;
|
||||
unsigned int val;
|
||||
@ -115,15 +105,9 @@ struct qmp_phy_init_tbl {
|
||||
|
||||
/* set of registers with offsets different per-PHY */
|
||||
enum qphy_reg_layout {
|
||||
/* Common block control registers */
|
||||
QPHY_COM_SW_RESET,
|
||||
QPHY_COM_POWER_DOWN_CONTROL,
|
||||
QPHY_COM_START_CONTROL,
|
||||
QPHY_COM_PCS_READY_STATUS,
|
||||
/* PCS registers */
|
||||
QPHY_SW_RESET,
|
||||
QPHY_START_CTRL,
|
||||
QPHY_PCS_READY_STATUS,
|
||||
QPHY_PCS_STATUS,
|
||||
QPHY_PCS_AUTONOMOUS_MODE_CTRL,
|
||||
QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR,
|
||||
@ -1338,14 +1322,114 @@ static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88),
|
||||
};
|
||||
|
||||
struct qmp_phy;
|
||||
static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_serdes_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0xab),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0xea),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE0, 0x24),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x34),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x14),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_BUF_ENABLE, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE2_MODE1, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE1, 0x24),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x08),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x82),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0xab),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0xea),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x82),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x34),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_EN_CENTER, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0xde),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x07),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_tx_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x10),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_rx_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdc),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_pcs_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG1, 0xd0),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG2, 0x07),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG3, 0x20),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG6, 0x13),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0xaa),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCS_TX_RX_CONFIG, 0x0c),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_CDR_RESET_TIME, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG1, 0x88),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG2, 0x13),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG1, 0x4b),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG5, 0x10),
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21),
|
||||
};
|
||||
|
||||
/* struct qmp_phy_cfg - per-PHY initialization config */
|
||||
struct qmp_phy_cfg {
|
||||
/* phy-type - PCIE/UFS/USB */
|
||||
unsigned int type;
|
||||
/* number of lanes provided by phy */
|
||||
int nlanes;
|
||||
int lanes;
|
||||
|
||||
/* Init sequence for PHY blocks - serdes, tx, rx, pcs */
|
||||
const struct qmp_phy_init_tbl *serdes_tbl;
|
||||
@ -1385,8 +1469,6 @@ struct qmp_phy_cfg {
|
||||
|
||||
/* true, if PHY has a separate DP_COM control block */
|
||||
bool has_phy_dp_com_ctrl;
|
||||
/* true, if PHY has secondary tx/rx lanes to be configured */
|
||||
bool is_dual_lane_phy;
|
||||
|
||||
/* Offset from PCS to PCS_USB region */
|
||||
unsigned int pcs_usb_offset;
|
||||
@ -1406,7 +1488,6 @@ struct qmp_phy_cfg {
|
||||
* @pcs_misc: iomapped memory space for lane's pcs_misc
|
||||
* @pcs_usb: iomapped memory space for lane's pcs_usb
|
||||
* @pipe_clk: pipe clock
|
||||
* @index: lane index
|
||||
* @qmp: QMP phy to which this lane belongs
|
||||
* @mode: current PHY mode
|
||||
*/
|
||||
@ -1422,7 +1503,6 @@ struct qmp_phy {
|
||||
void __iomem *pcs_misc;
|
||||
void __iomem *pcs_usb;
|
||||
struct clk *pipe_clk;
|
||||
unsigned int index;
|
||||
struct qcom_qmp *qmp;
|
||||
enum phy_mode mode;
|
||||
};
|
||||
@ -1520,8 +1600,7 @@ static const char * const qmp_phy_vreg_l[] = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = ipq8074_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(ipq8074_usb3_serdes_tbl),
|
||||
@ -1545,8 +1624,7 @@ static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = msm8996_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(msm8996_usb3_serdes_tbl),
|
||||
@ -1570,8 +1648,7 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = qmp_v3_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl),
|
||||
@ -1598,12 +1675,10 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
|
||||
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
|
||||
|
||||
.has_phy_dp_com_ctrl = true,
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sc7180_usb3phy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = qmp_v3_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl),
|
||||
@ -1630,12 +1705,38 @@ static const struct qmp_phy_cfg sc7180_usb3phy_cfg = {
|
||||
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
|
||||
|
||||
.has_phy_dp_com_ctrl = true,
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sc8280xp_usb3_uniphy_cfg = {
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sc8280xp_usb3_uniphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_serdes_tbl),
|
||||
.tx_tbl = sc8280xp_usb3_uniphy_tx_tbl,
|
||||
.tx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_tx_tbl),
|
||||
.rx_tbl = sc8280xp_usb3_uniphy_rx_tbl,
|
||||
.rx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_rx_tbl),
|
||||
.pcs_tbl = sc8280xp_usb3_uniphy_pcs_tbl,
|
||||
.pcs_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_pcs_tbl),
|
||||
.clk_list = qmp_v4_phy_clk_l,
|
||||
.num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l),
|
||||
.reset_list = msm8996_usb3phy_reset_l,
|
||||
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
|
||||
.vreg_list = qmp_phy_vreg_l,
|
||||
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
|
||||
.regs = qmp_v4_usb3phy_regs_layout,
|
||||
|
||||
.start_ctrl = SERDES_START | PCS_START,
|
||||
.pwrdn_ctrl = SW_PWRDN,
|
||||
.phy_status = PHYSTATUS,
|
||||
|
||||
.has_pwrdn_delay = true,
|
||||
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
|
||||
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = qmp_v3_usb3_uniphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_serdes_tbl),
|
||||
@ -1663,8 +1764,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg msm8998_usb3phy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = msm8998_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl),
|
||||
@ -1685,13 +1785,10 @@ static const struct qmp_phy_cfg msm8998_usb3phy_cfg = {
|
||||
.start_ctrl = SERDES_START | PCS_START,
|
||||
.pwrdn_ctrl = SW_PWRDN,
|
||||
.phy_status = PHYSTATUS,
|
||||
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8150_usb3phy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = sm8150_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl),
|
||||
@ -1722,12 +1819,10 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = {
|
||||
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
|
||||
|
||||
.has_phy_dp_com_ctrl = true,
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl),
|
||||
@ -1758,8 +1853,7 @@ static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8250_usb3phy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = sm8150_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl),
|
||||
@ -1789,12 +1883,10 @@ static const struct qmp_phy_cfg sm8250_usb3phy_cfg = {
|
||||
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
|
||||
|
||||
.has_phy_dp_com_ctrl = true,
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl),
|
||||
@ -1825,8 +1917,7 @@ static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl),
|
||||
@ -1857,8 +1948,7 @@ static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl),
|
||||
@ -1889,8 +1979,7 @@ static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8350_usb3phy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = sm8150_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl),
|
||||
@ -1920,12 +2009,10 @@ static const struct qmp_phy_cfg sm8350_usb3phy_cfg = {
|
||||
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
|
||||
|
||||
.has_phy_dp_com_ctrl = true,
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 1,
|
||||
|
||||
.serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl),
|
||||
@ -1956,8 +2043,7 @@ static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
.lanes = 2,
|
||||
|
||||
.serdes_tbl = qcm2290_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl),
|
||||
@ -1978,11 +2064,9 @@ static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = {
|
||||
.start_ctrl = SERDES_START | PCS_START,
|
||||
.pwrdn_ctrl = SW_PWRDN,
|
||||
.phy_status = PHYSTATUS,
|
||||
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static void qcom_qmp_phy_usb_configure_lane(void __iomem *base,
|
||||
static void qmp_usb_configure_lane(void __iomem *base,
|
||||
const unsigned int *regs,
|
||||
const struct qmp_phy_init_tbl tbl[],
|
||||
int num,
|
||||
@ -2005,28 +2089,29 @@ static void qcom_qmp_phy_usb_configure_lane(void __iomem *base,
|
||||
}
|
||||
}
|
||||
|
||||
static void qcom_qmp_phy_usb_configure(void __iomem *base,
|
||||
static void qmp_usb_configure(void __iomem *base,
|
||||
const unsigned int *regs,
|
||||
const struct qmp_phy_init_tbl tbl[],
|
||||
int num)
|
||||
{
|
||||
qcom_qmp_phy_usb_configure_lane(base, regs, tbl, num, 0xff);
|
||||
qmp_usb_configure_lane(base, regs, tbl, num, 0xff);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_serdes_init(struct qmp_phy *qphy)
|
||||
static int qmp_usb_serdes_init(struct qmp_phy *qphy)
|
||||
{
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
void __iomem *serdes = qphy->serdes;
|
||||
const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl;
|
||||
int serdes_tbl_num = cfg->serdes_tbl_num;
|
||||
|
||||
qcom_qmp_phy_usb_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num);
|
||||
qmp_usb_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_com_init(struct qmp_phy *qphy)
|
||||
static int qmp_usb_init(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
void __iomem *pcs = qphy->pcs;
|
||||
@ -2097,8 +2182,9 @@ err_disable_regulators:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_com_exit(struct qmp_phy *qphy)
|
||||
static int qmp_usb_exit(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
|
||||
@ -2111,21 +2197,7 @@ static int qcom_qmp_phy_usb_com_exit(struct qmp_phy *qphy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_init(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
int ret;
|
||||
dev_vdbg(qmp->dev, "Initializing QMP phy\n");
|
||||
|
||||
ret = qcom_qmp_phy_usb_com_init(qphy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_power_on(struct phy *phy)
|
||||
static int qmp_usb_power_on(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
struct qcom_qmp *qmp = qphy->qmp;
|
||||
@ -2137,7 +2209,7 @@ static int qcom_qmp_phy_usb_power_on(struct phy *phy)
|
||||
unsigned int mask, val, ready;
|
||||
int ret;
|
||||
|
||||
qcom_qmp_phy_usb_serdes_init(qphy);
|
||||
qmp_usb_serdes_init(qphy);
|
||||
|
||||
ret = clk_prepare_enable(qphy->pipe_clk);
|
||||
if (ret) {
|
||||
@ -2146,25 +2218,22 @@ static int qcom_qmp_phy_usb_power_on(struct phy *phy)
|
||||
}
|
||||
|
||||
/* Tx, Rx, and PCS configurations */
|
||||
qcom_qmp_phy_usb_configure_lane(tx, cfg->regs,
|
||||
cfg->tx_tbl, cfg->tx_tbl_num, 1);
|
||||
qmp_usb_configure_lane(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num, 1);
|
||||
|
||||
/* Configuration for other LANE for USB-DP combo PHY */
|
||||
if (cfg->is_dual_lane_phy) {
|
||||
qcom_qmp_phy_usb_configure_lane(qphy->tx2, cfg->regs,
|
||||
cfg->tx_tbl, cfg->tx_tbl_num, 2);
|
||||
if (cfg->lanes >= 2) {
|
||||
qmp_usb_configure_lane(qphy->tx2, cfg->regs,
|
||||
cfg->tx_tbl, cfg->tx_tbl_num, 2);
|
||||
}
|
||||
|
||||
qcom_qmp_phy_usb_configure_lane(rx, cfg->regs,
|
||||
cfg->rx_tbl, cfg->rx_tbl_num, 1);
|
||||
qmp_usb_configure_lane(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num, 1);
|
||||
|
||||
if (cfg->is_dual_lane_phy) {
|
||||
qcom_qmp_phy_usb_configure_lane(qphy->rx2, cfg->regs,
|
||||
cfg->rx_tbl, cfg->rx_tbl_num, 2);
|
||||
if (cfg->lanes >= 2) {
|
||||
qmp_usb_configure_lane(qphy->rx2, cfg->regs,
|
||||
cfg->rx_tbl, cfg->rx_tbl_num, 2);
|
||||
}
|
||||
|
||||
/* Configure link rate, swing, etc. */
|
||||
qcom_qmp_phy_usb_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
|
||||
qmp_usb_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
|
||||
|
||||
if (cfg->has_pwrdn_delay)
|
||||
usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max);
|
||||
@ -2194,7 +2263,7 @@ err_disable_pipe_clk:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_power_off(struct phy *phy)
|
||||
static int qmp_usb_power_off(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
@ -2219,42 +2288,32 @@ static int qcom_qmp_phy_usb_power_off(struct phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_exit(struct phy *phy)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
|
||||
qcom_qmp_phy_usb_com_exit(qphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_enable(struct phy *phy)
|
||||
static int qmp_usb_enable(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = qcom_qmp_phy_usb_init(phy);
|
||||
ret = qmp_usb_init(phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_qmp_phy_usb_power_on(phy);
|
||||
ret = qmp_usb_power_on(phy);
|
||||
if (ret)
|
||||
qcom_qmp_phy_usb_exit(phy);
|
||||
qmp_usb_exit(phy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_disable(struct phy *phy)
|
||||
static int qmp_usb_disable(struct phy *phy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = qcom_qmp_phy_usb_power_off(phy);
|
||||
ret = qmp_usb_power_off(phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
return qcom_qmp_phy_usb_exit(phy);
|
||||
return qmp_usb_exit(phy);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_set_mode(struct phy *phy,
|
||||
enum phy_mode mode, int submode)
|
||||
static int qmp_usb_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
{
|
||||
struct qmp_phy *qphy = phy_get_drvdata(phy);
|
||||
|
||||
@ -2263,7 +2322,7 @@ static int qcom_qmp_phy_usb_set_mode(struct phy *phy,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qcom_qmp_phy_usb_enable_autonomous_mode(struct qmp_phy *qphy)
|
||||
static void qmp_usb_enable_autonomous_mode(struct qmp_phy *qphy)
|
||||
{
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
void __iomem *pcs_usb = qphy->pcs_usb ?: qphy->pcs;
|
||||
@ -2292,7 +2351,7 @@ static void qcom_qmp_phy_usb_enable_autonomous_mode(struct qmp_phy *qphy)
|
||||
qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN);
|
||||
}
|
||||
|
||||
static void qcom_qmp_phy_usb_disable_autonomous_mode(struct qmp_phy *qphy)
|
||||
static void qmp_usb_disable_autonomous_mode(struct qmp_phy *qphy)
|
||||
{
|
||||
const struct qmp_phy_cfg *cfg = qphy->cfg;
|
||||
void __iomem *pcs_usb = qphy->pcs_usb ?: qphy->pcs;
|
||||
@ -2310,7 +2369,7 @@ static void qcom_qmp_phy_usb_disable_autonomous_mode(struct qmp_phy *qphy)
|
||||
qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
|
||||
}
|
||||
|
||||
static int __maybe_unused qcom_qmp_phy_usb_runtime_suspend(struct device *dev)
|
||||
static int __maybe_unused qmp_usb_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
struct qmp_phy *qphy = qmp->phys[0];
|
||||
@ -2318,16 +2377,12 @@ static int __maybe_unused qcom_qmp_phy_usb_runtime_suspend(struct device *dev)
|
||||
|
||||
dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode);
|
||||
|
||||
/* Supported only for USB3 PHY and luckily USB3 is the first phy */
|
||||
if (cfg->type != PHY_TYPE_USB3)
|
||||
return 0;
|
||||
|
||||
if (!qphy->phy->init_count) {
|
||||
dev_vdbg(dev, "PHY not initialized, bailing out\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
qcom_qmp_phy_usb_enable_autonomous_mode(qphy);
|
||||
qmp_usb_enable_autonomous_mode(qphy);
|
||||
|
||||
clk_disable_unprepare(qphy->pipe_clk);
|
||||
clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
|
||||
@ -2335,7 +2390,7 @@ static int __maybe_unused qcom_qmp_phy_usb_runtime_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused qcom_qmp_phy_usb_runtime_resume(struct device *dev)
|
||||
static int __maybe_unused qmp_usb_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
struct qmp_phy *qphy = qmp->phys[0];
|
||||
@ -2344,10 +2399,6 @@ static int __maybe_unused qcom_qmp_phy_usb_runtime_resume(struct device *dev)
|
||||
|
||||
dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode);
|
||||
|
||||
/* Supported only for USB3 PHY and luckily USB3 is the first phy */
|
||||
if (cfg->type != PHY_TYPE_USB3)
|
||||
return 0;
|
||||
|
||||
if (!qphy->phy->init_count) {
|
||||
dev_vdbg(dev, "PHY not initialized, bailing out\n");
|
||||
return 0;
|
||||
@ -2364,12 +2415,12 @@ static int __maybe_unused qcom_qmp_phy_usb_runtime_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
qcom_qmp_phy_usb_disable_autonomous_mode(qphy);
|
||||
qmp_usb_disable_autonomous_mode(qphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
static int qmp_usb_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
int num = cfg->num_vregs;
|
||||
@ -2385,7 +2436,7 @@ static int qcom_qmp_phy_usb_vreg_init(struct device *dev, const struct qmp_phy_c
|
||||
return devm_regulator_bulk_get(dev, num, qmp->vregs);
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
static int qmp_usb_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
int i;
|
||||
@ -2406,7 +2457,7 @@ static int qcom_qmp_phy_usb_reset_init(struct device *dev, const struct qmp_phy_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_qmp_phy_usb_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
static int qmp_usb_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
int num = cfg->num_clks;
|
||||
@ -2482,23 +2533,47 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np)
|
||||
return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np);
|
||||
}
|
||||
|
||||
static const struct phy_ops qcom_qmp_phy_usb_ops = {
|
||||
.init = qcom_qmp_phy_usb_enable,
|
||||
.exit = qcom_qmp_phy_usb_disable,
|
||||
.set_mode = qcom_qmp_phy_usb_set_mode,
|
||||
static const struct phy_ops qmp_usb_ops = {
|
||||
.init = qmp_usb_enable,
|
||||
.exit = qmp_usb_disable,
|
||||
.set_mode = qmp_usb_set_mode,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static void __iomem *qmp_usb_iomap(struct device *dev, struct device_node *np,
|
||||
int index, bool exclusive)
|
||||
{
|
||||
struct resource res;
|
||||
|
||||
if (!exclusive) {
|
||||
if (of_address_to_resource(np, index, &res))
|
||||
return IOMEM_ERR_PTR(-EINVAL);
|
||||
|
||||
return devm_ioremap(dev, res.start, resource_size(&res));
|
||||
}
|
||||
|
||||
return devm_of_iomap(dev, np, index, NULL);
|
||||
}
|
||||
|
||||
static
|
||||
int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id,
|
||||
int qmp_usb_create(struct device *dev, struct device_node *np, int id,
|
||||
void __iomem *serdes, const struct qmp_phy_cfg *cfg)
|
||||
{
|
||||
struct qcom_qmp *qmp = dev_get_drvdata(dev);
|
||||
struct phy *generic_phy;
|
||||
struct qmp_phy *qphy;
|
||||
char prop_name[MAX_PROP_NAME];
|
||||
bool exclusive = true;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* FIXME: These bindings should be fixed to not rely on overlapping
|
||||
* mappings for PCS.
|
||||
*/
|
||||
if (of_device_is_compatible(dev->of_node, "qcom,sdx65-qmp-usb3-uni-phy"))
|
||||
exclusive = false;
|
||||
if (of_device_is_compatible(dev->of_node, "qcom,sm8350-qmp-usb3-uni-phy"))
|
||||
exclusive = false;
|
||||
|
||||
qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
|
||||
if (!qphy)
|
||||
return -ENOMEM;
|
||||
@ -2511,58 +2586,47 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id,
|
||||
* For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5
|
||||
* For single lane PHYs: pcs_misc (optional) -> 3.
|
||||
*/
|
||||
qphy->tx = of_iomap(np, 0);
|
||||
if (!qphy->tx)
|
||||
return -ENOMEM;
|
||||
qphy->tx = devm_of_iomap(dev, np, 0, NULL);
|
||||
if (IS_ERR(qphy->tx))
|
||||
return PTR_ERR(qphy->tx);
|
||||
|
||||
qphy->rx = of_iomap(np, 1);
|
||||
if (!qphy->rx)
|
||||
return -ENOMEM;
|
||||
qphy->rx = devm_of_iomap(dev, np, 1, NULL);
|
||||
if (IS_ERR(qphy->rx))
|
||||
return PTR_ERR(qphy->rx);
|
||||
|
||||
qphy->pcs = of_iomap(np, 2);
|
||||
if (!qphy->pcs)
|
||||
return -ENOMEM;
|
||||
qphy->pcs = qmp_usb_iomap(dev, np, 2, exclusive);
|
||||
if (IS_ERR(qphy->pcs))
|
||||
return PTR_ERR(qphy->pcs);
|
||||
|
||||
if (cfg->pcs_usb_offset)
|
||||
qphy->pcs_usb = qphy->pcs + cfg->pcs_usb_offset;
|
||||
|
||||
/*
|
||||
* If this is a dual-lane PHY, then there should be registers for the
|
||||
* second lane. Some old device trees did not specify this, so fall
|
||||
* back to old legacy behavior of assuming they can be reached at an
|
||||
* offset from the first lane.
|
||||
*/
|
||||
if (cfg->is_dual_lane_phy) {
|
||||
qphy->tx2 = of_iomap(np, 3);
|
||||
qphy->rx2 = of_iomap(np, 4);
|
||||
if (!qphy->tx2 || !qphy->rx2) {
|
||||
dev_warn(dev,
|
||||
"Underspecified device tree, falling back to legacy register regions\n");
|
||||
if (cfg->lanes >= 2) {
|
||||
qphy->tx2 = devm_of_iomap(dev, np, 3, NULL);
|
||||
if (IS_ERR(qphy->tx2))
|
||||
return PTR_ERR(qphy->tx2);
|
||||
|
||||
/* In the old version, pcs_misc is at index 3. */
|
||||
qphy->pcs_misc = qphy->tx2;
|
||||
qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE;
|
||||
qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE;
|
||||
|
||||
} else {
|
||||
qphy->pcs_misc = of_iomap(np, 5);
|
||||
}
|
||||
qphy->rx2 = devm_of_iomap(dev, np, 4, NULL);
|
||||
if (IS_ERR(qphy->rx2))
|
||||
return PTR_ERR(qphy->rx2);
|
||||
|
||||
qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL);
|
||||
} else {
|
||||
qphy->pcs_misc = of_iomap(np, 3);
|
||||
qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL);
|
||||
}
|
||||
|
||||
if (!qphy->pcs_misc)
|
||||
if (IS_ERR(qphy->pcs_misc)) {
|
||||
dev_vdbg(dev, "PHY pcs_misc-reg not used\n");
|
||||
qphy->pcs_misc = NULL;
|
||||
}
|
||||
|
||||
snprintf(prop_name, sizeof(prop_name), "pipe%d", id);
|
||||
qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name);
|
||||
qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL);
|
||||
if (IS_ERR(qphy->pipe_clk)) {
|
||||
return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk),
|
||||
"failed to get lane%d pipe clock\n", id);
|
||||
}
|
||||
|
||||
generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_usb_ops);
|
||||
generic_phy = devm_phy_create(dev, np, &qmp_usb_ops);
|
||||
if (IS_ERR(generic_phy)) {
|
||||
ret = PTR_ERR(generic_phy);
|
||||
dev_err(dev, "failed to create qphy %d\n", ret);
|
||||
@ -2570,7 +2634,6 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id,
|
||||
}
|
||||
|
||||
qphy->phy = generic_phy;
|
||||
qphy->index = id;
|
||||
qphy->qmp = qmp;
|
||||
qmp->phys[id] = qphy;
|
||||
phy_set_drvdata(generic_phy, qphy);
|
||||
@ -2578,7 +2641,7 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_qmp_phy_usb_of_match_table[] = {
|
||||
static const struct of_device_id qmp_usb_of_match_table[] = {
|
||||
{
|
||||
.compatible = "qcom,ipq8074-qmp-usb3-phy",
|
||||
.data = &ipq8074_usb3phy_cfg,
|
||||
@ -2594,6 +2657,9 @@ static const struct of_device_id qcom_qmp_phy_usb_of_match_table[] = {
|
||||
}, {
|
||||
.compatible = "qcom,sc8180x-qmp-usb3-phy",
|
||||
.data = &sm8150_usb3phy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sc8280xp-qmp-usb3-uni-phy",
|
||||
.data = &sc8280xp_usb3_uniphy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sdm845-qmp-usb3-phy",
|
||||
.data = &qmp_v3_usb3phy_cfg,
|
||||
@ -2636,14 +2702,14 @@ static const struct of_device_id qcom_qmp_phy_usb_of_match_table[] = {
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_qmp_phy_usb_of_match_table);
|
||||
MODULE_DEVICE_TABLE(of, qmp_usb_of_match_table);
|
||||
|
||||
static const struct dev_pm_ops qcom_qmp_phy_usb_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(qcom_qmp_phy_usb_runtime_suspend,
|
||||
qcom_qmp_phy_usb_runtime_resume, NULL)
|
||||
static const struct dev_pm_ops qmp_usb_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(qmp_usb_runtime_suspend,
|
||||
qmp_usb_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static int qcom_qmp_phy_usb_probe(struct platform_device *pdev)
|
||||
static int qmp_usb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_qmp *qmp;
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -2678,21 +2744,18 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(qmp->dp_com);
|
||||
}
|
||||
|
||||
ret = qcom_qmp_phy_usb_clk_init(dev, cfg);
|
||||
ret = qmp_usb_clk_init(dev, cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_qmp_phy_usb_reset_init(dev, cfg);
|
||||
ret = qmp_usb_reset_init(dev, cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_qmp_phy_usb_vreg_init(dev, cfg);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to get regulator supplies: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
ret = qmp_usb_vreg_init(dev, cfg);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to get regulator supplies\n");
|
||||
|
||||
num = of_get_available_child_count(dev->of_node);
|
||||
/* do we have a rogue child node ? */
|
||||
@ -2704,7 +2767,9 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
ret = devm_pm_runtime_enable(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
/*
|
||||
* Prevent runtime pm from being ON by default. Users can enable
|
||||
* it using power/control in sysfs.
|
||||
@ -2714,7 +2779,7 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev)
|
||||
id = 0;
|
||||
for_each_available_child_of_node(dev->of_node, child) {
|
||||
/* Create per-lane phy */
|
||||
ret = qcom_qmp_phy_usb_create(dev, child, id, serdes, cfg);
|
||||
ret = qmp_usb_create(dev, child, id, serdes, cfg);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to create lane%d phy, %d\n",
|
||||
id, ret);
|
||||
@ -2736,29 +2801,24 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
if (!IS_ERR(phy_provider))
|
||||
dev_info(dev, "Registered Qcom-QMP phy\n");
|
||||
else
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
|
||||
err_node_put:
|
||||
pm_runtime_disable(dev);
|
||||
of_node_put(child);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver qcom_qmp_phy_usb_driver = {
|
||||
.probe = qcom_qmp_phy_usb_probe,
|
||||
static struct platform_driver qmp_usb_driver = {
|
||||
.probe = qmp_usb_probe,
|
||||
.driver = {
|
||||
.name = "qcom-qmp-usb-phy",
|
||||
.pm = &qcom_qmp_phy_usb_pm_ops,
|
||||
.of_match_table = qcom_qmp_phy_usb_of_match_table,
|
||||
.pm = &qmp_usb_pm_ops,
|
||||
.of_match_table = qmp_usb_of_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(qcom_qmp_phy_usb_driver);
|
||||
module_platform_driver(qmp_usb_driver);
|
||||
|
||||
MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>");
|
||||
MODULE_DESCRIPTION("Qualcomm QMP USB PHY driver");
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "phy-qcom-qmp-qserdes-com-v5.h"
|
||||
#include "phy-qcom-qmp-qserdes-txrx-v5.h"
|
||||
#include "phy-qcom-qmp-qserdes-txrx-v5_20.h"
|
||||
#include "phy-qcom-qmp-qserdes-txrx-v5_5nm.h"
|
||||
|
||||
#include "phy-qcom-qmp-qserdes-pll.h"
|
||||
|
||||
|
@ -973,20 +973,14 @@ static int qusb2_phy_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(qphy->base);
|
||||
|
||||
qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb");
|
||||
if (IS_ERR(qphy->cfg_ahb_clk)) {
|
||||
ret = PTR_ERR(qphy->cfg_ahb_clk);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to get cfg ahb clk, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(qphy->cfg_ahb_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(qphy->cfg_ahb_clk),
|
||||
"failed to get cfg ahb clk\n");
|
||||
|
||||
qphy->ref_clk = devm_clk_get(dev, "ref");
|
||||
if (IS_ERR(qphy->ref_clk)) {
|
||||
ret = PTR_ERR(qphy->ref_clk);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to get ref clk, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(qphy->ref_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(qphy->ref_clk),
|
||||
"failed to get ref clk\n");
|
||||
|
||||
qphy->iface_clk = devm_clk_get_optional(dev, "iface");
|
||||
if (IS_ERR(qphy->iface_clk))
|
||||
@ -1003,12 +997,9 @@ static int qusb2_phy_probe(struct platform_device *pdev)
|
||||
qphy->vregs[i].supply = qusb2_phy_vreg_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, num, qphy->vregs);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to get regulator supplies: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to get regulator supplies\n");
|
||||
|
||||
/* Get the specific init parameters of QMP phy */
|
||||
qphy->cfg = of_device_get_match_data(dev);
|
||||
|
@ -52,6 +52,12 @@
|
||||
#define USB2_SUSPEND_N BIT(2)
|
||||
#define USB2_SUSPEND_N_SEL BIT(3)
|
||||
|
||||
#define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0 (0x6c)
|
||||
#define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1 (0x70)
|
||||
#define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2 (0x74)
|
||||
#define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X3 (0x78)
|
||||
#define PARAM_OVRD_MASK 0xFF
|
||||
|
||||
#define USB2_PHY_USB_PHY_CFG0 (0x94)
|
||||
#define UTMI_PHY_DATAPATH_CTRL_OVERRIDE_EN BIT(0)
|
||||
#define UTMI_PHY_CMN_CTRL_OVERRIDE_EN BIT(1)
|
||||
@ -60,12 +66,47 @@
|
||||
#define REFCLK_SEL_MASK GENMASK(1, 0)
|
||||
#define REFCLK_SEL_DEFAULT (0x2 << 0)
|
||||
|
||||
#define HS_DISCONNECT_MASK GENMASK(2, 0)
|
||||
#define SQUELCH_DETECTOR_MASK GENMASK(7, 5)
|
||||
|
||||
#define HS_AMPLITUDE_MASK GENMASK(3, 0)
|
||||
#define PREEMPHASIS_DURATION_MASK BIT(5)
|
||||
#define PREEMPHASIS_AMPLITUDE_MASK GENMASK(7, 6)
|
||||
|
||||
#define HS_RISE_FALL_MASK GENMASK(1, 0)
|
||||
#define HS_CROSSOVER_VOLTAGE_MASK GENMASK(3, 2)
|
||||
#define HS_OUTPUT_IMPEDANCE_MASK GENMASK(5, 4)
|
||||
|
||||
#define LS_FS_OUTPUT_IMPEDANCE_MASK GENMASK(3, 0)
|
||||
|
||||
static const char * const qcom_snps_hsphy_vreg_names[] = {
|
||||
"vdda-pll", "vdda33", "vdda18",
|
||||
};
|
||||
|
||||
#define SNPS_HS_NUM_VREGS ARRAY_SIZE(qcom_snps_hsphy_vreg_names)
|
||||
|
||||
struct override_param {
|
||||
s32 value;
|
||||
u8 reg_val;
|
||||
};
|
||||
|
||||
struct override_param_map {
|
||||
const char *prop_name;
|
||||
const struct override_param *param_table;
|
||||
u8 table_size;
|
||||
u8 reg_offset;
|
||||
u8 param_mask;
|
||||
};
|
||||
|
||||
struct phy_override_seq {
|
||||
bool need_update;
|
||||
u8 offset;
|
||||
u8 value;
|
||||
u8 mask;
|
||||
};
|
||||
|
||||
#define NUM_HSPHY_TUNING_PARAMS (9)
|
||||
|
||||
/**
|
||||
* struct qcom_snps_hsphy - snps hs phy attributes
|
||||
*
|
||||
@ -91,6 +132,7 @@ struct qcom_snps_hsphy {
|
||||
|
||||
bool phy_initialized;
|
||||
enum phy_mode mode;
|
||||
struct phy_override_seq update_seq_cfg[NUM_HSPHY_TUNING_PARAMS];
|
||||
};
|
||||
|
||||
static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset,
|
||||
@ -173,10 +215,158 @@ static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct override_param hs_disconnect_sc7280[] = {
|
||||
{ -272, 0 },
|
||||
{ 0, 1 },
|
||||
{ 317, 2 },
|
||||
{ 630, 3 },
|
||||
{ 973, 4 },
|
||||
{ 1332, 5 },
|
||||
{ 1743, 6 },
|
||||
{ 2156, 7 },
|
||||
};
|
||||
|
||||
static const struct override_param squelch_det_threshold_sc7280[] = {
|
||||
{ -2090, 7 },
|
||||
{ -1560, 6 },
|
||||
{ -1030, 5 },
|
||||
{ -530, 4 },
|
||||
{ 0, 3 },
|
||||
{ 530, 2 },
|
||||
{ 1060, 1 },
|
||||
{ 1590, 0 },
|
||||
};
|
||||
|
||||
static const struct override_param hs_amplitude_sc7280[] = {
|
||||
{ -660, 0 },
|
||||
{ -440, 1 },
|
||||
{ -220, 2 },
|
||||
{ 0, 3 },
|
||||
{ 230, 4 },
|
||||
{ 440, 5 },
|
||||
{ 650, 6 },
|
||||
{ 890, 7 },
|
||||
{ 1110, 8 },
|
||||
{ 1330, 9 },
|
||||
{ 1560, 10 },
|
||||
{ 1780, 11 },
|
||||
{ 2000, 12 },
|
||||
{ 2220, 13 },
|
||||
{ 2430, 14 },
|
||||
{ 2670, 15 },
|
||||
};
|
||||
|
||||
static const struct override_param preemphasis_duration_sc7280[] = {
|
||||
{ 10000, 1 },
|
||||
{ 20000, 0 },
|
||||
};
|
||||
|
||||
static const struct override_param preemphasis_amplitude_sc7280[] = {
|
||||
{ 10000, 1 },
|
||||
{ 20000, 2 },
|
||||
{ 30000, 3 },
|
||||
{ 40000, 0 },
|
||||
};
|
||||
|
||||
static const struct override_param hs_rise_fall_time_sc7280[] = {
|
||||
{ -4100, 3 },
|
||||
{ 0, 2 },
|
||||
{ 2810, 1 },
|
||||
{ 5430, 0 },
|
||||
};
|
||||
|
||||
static const struct override_param hs_crossover_voltage_sc7280[] = {
|
||||
{ -31000, 1 },
|
||||
{ 0, 3 },
|
||||
{ 28000, 2 },
|
||||
};
|
||||
|
||||
static const struct override_param hs_output_impedance_sc7280[] = {
|
||||
{ -2300000, 3 },
|
||||
{ 0, 2 },
|
||||
{ 2600000, 1 },
|
||||
{ 6100000, 0 },
|
||||
};
|
||||
|
||||
static const struct override_param ls_fs_output_impedance_sc7280[] = {
|
||||
{ -1053, 15 },
|
||||
{ -557, 7 },
|
||||
{ 0, 3 },
|
||||
{ 612, 1 },
|
||||
{ 1310, 0 },
|
||||
};
|
||||
|
||||
static const struct override_param_map sc7280_snps_7nm_phy[] = {
|
||||
{
|
||||
"qcom,hs-disconnect-bp",
|
||||
hs_disconnect_sc7280,
|
||||
ARRAY_SIZE(hs_disconnect_sc7280),
|
||||
USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0,
|
||||
HS_DISCONNECT_MASK
|
||||
},
|
||||
{
|
||||
"qcom,squelch-detector-bp",
|
||||
squelch_det_threshold_sc7280,
|
||||
ARRAY_SIZE(squelch_det_threshold_sc7280),
|
||||
USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0,
|
||||
SQUELCH_DETECTOR_MASK
|
||||
},
|
||||
{
|
||||
"qcom,hs-amplitude-bp",
|
||||
hs_amplitude_sc7280,
|
||||
ARRAY_SIZE(hs_amplitude_sc7280),
|
||||
USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1,
|
||||
HS_AMPLITUDE_MASK
|
||||
},
|
||||
{
|
||||
"qcom,pre-emphasis-duration-bp",
|
||||
preemphasis_duration_sc7280,
|
||||
ARRAY_SIZE(preemphasis_duration_sc7280),
|
||||
USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1,
|
||||
PREEMPHASIS_DURATION_MASK,
|
||||
},
|
||||
{
|
||||
"qcom,pre-emphasis-amplitude-bp",
|
||||
preemphasis_amplitude_sc7280,
|
||||
ARRAY_SIZE(preemphasis_amplitude_sc7280),
|
||||
USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1,
|
||||
PREEMPHASIS_AMPLITUDE_MASK,
|
||||
},
|
||||
{
|
||||
"qcom,hs-rise-fall-time-bp",
|
||||
hs_rise_fall_time_sc7280,
|
||||
ARRAY_SIZE(hs_rise_fall_time_sc7280),
|
||||
USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2,
|
||||
HS_RISE_FALL_MASK
|
||||
},
|
||||
{
|
||||
"qcom,hs-crossover-voltage-microvolt",
|
||||
hs_crossover_voltage_sc7280,
|
||||
ARRAY_SIZE(hs_crossover_voltage_sc7280),
|
||||
USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2,
|
||||
HS_CROSSOVER_VOLTAGE_MASK
|
||||
},
|
||||
{
|
||||
"qcom,hs-output-impedance-micro-ohms",
|
||||
hs_output_impedance_sc7280,
|
||||
ARRAY_SIZE(hs_output_impedance_sc7280),
|
||||
USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2,
|
||||
HS_OUTPUT_IMPEDANCE_MASK,
|
||||
},
|
||||
{
|
||||
"qcom,ls-fs-output-impedance-bp",
|
||||
ls_fs_output_impedance_sc7280,
|
||||
ARRAY_SIZE(ls_fs_output_impedance_sc7280),
|
||||
USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X3,
|
||||
LS_FS_OUTPUT_IMPEDANCE_MASK,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static int qcom_snps_hsphy_init(struct phy *phy)
|
||||
{
|
||||
struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
dev_vdbg(&phy->dev, "%s(): Initializing SNPS HS phy\n", __func__);
|
||||
|
||||
@ -223,6 +413,14 @@ static int qcom_snps_hsphy_init(struct phy *phy)
|
||||
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL1,
|
||||
VBUSVLDEXT0, VBUSVLDEXT0);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hsphy->update_seq_cfg); i++) {
|
||||
if (hsphy->update_seq_cfg[i].need_update)
|
||||
qcom_snps_hsphy_write_mask(hsphy->base,
|
||||
hsphy->update_seq_cfg[i].offset,
|
||||
hsphy->update_seq_cfg[i].mask,
|
||||
hsphy->update_seq_cfg[i].value);
|
||||
}
|
||||
|
||||
qcom_snps_hsphy_write_mask(hsphy->base,
|
||||
USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2,
|
||||
VREGBYPASS, VREGBYPASS);
|
||||
@ -280,7 +478,10 @@ static const struct phy_ops qcom_snps_hsphy_gen_ops = {
|
||||
static const struct of_device_id qcom_snps_hsphy_of_match_table[] = {
|
||||
{ .compatible = "qcom,sm8150-usb-hs-phy", },
|
||||
{ .compatible = "qcom,usb-snps-hs-5nm-phy", },
|
||||
{ .compatible = "qcom,usb-snps-hs-7nm-phy", },
|
||||
{
|
||||
.compatible = "qcom,usb-snps-hs-7nm-phy",
|
||||
.data = &sc7280_snps_7nm_phy,
|
||||
},
|
||||
{ .compatible = "qcom,usb-snps-femto-v2-phy", },
|
||||
{ }
|
||||
};
|
||||
@ -291,6 +492,55 @@ static const struct dev_pm_ops qcom_snps_hsphy_pm_ops = {
|
||||
qcom_snps_hsphy_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static void qcom_snps_hsphy_override_param_update_val(
|
||||
const struct override_param_map map,
|
||||
s32 dt_val, struct phy_override_seq *seq_entry)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Param table for each param is in increasing order
|
||||
* of dt values. We need to iterate over the list to
|
||||
* select the entry that matches the dt value and pick
|
||||
* up the corresponding register value.
|
||||
*/
|
||||
for (i = 0; i < map.table_size - 1; i++) {
|
||||
if (map.param_table[i].value == dt_val)
|
||||
break;
|
||||
}
|
||||
|
||||
seq_entry->need_update = true;
|
||||
seq_entry->offset = map.reg_offset;
|
||||
seq_entry->mask = map.param_mask;
|
||||
seq_entry->value = map.param_table[i].reg_val << __ffs(map.param_mask);
|
||||
}
|
||||
|
||||
static void qcom_snps_hsphy_read_override_param_seq(struct device *dev)
|
||||
{
|
||||
struct device_node *node = dev->of_node;
|
||||
s32 val;
|
||||
int ret, i;
|
||||
struct qcom_snps_hsphy *hsphy;
|
||||
const struct override_param_map *cfg = of_device_get_match_data(dev);
|
||||
|
||||
if (!cfg)
|
||||
return;
|
||||
|
||||
hsphy = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; cfg[i].prop_name != NULL; i++) {
|
||||
ret = of_property_read_s32(node, cfg[i].prop_name, &val);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
qcom_snps_hsphy_override_param_update_val(cfg[i], val,
|
||||
&hsphy->update_seq_cfg[i]);
|
||||
dev_dbg(&hsphy->phy->dev, "Read param: %s dt_val: %d reg_val: 0x%x\n",
|
||||
cfg[i].prop_name, val, hsphy->update_seq_cfg[i].value);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int qcom_snps_hsphy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -309,12 +559,9 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(hsphy->base);
|
||||
|
||||
hsphy->ref_clk = devm_clk_get(dev, "ref");
|
||||
if (IS_ERR(hsphy->ref_clk)) {
|
||||
ret = PTR_ERR(hsphy->ref_clk);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to get ref clk, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(hsphy->ref_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(hsphy->ref_clk),
|
||||
"failed to get ref clk\n");
|
||||
|
||||
hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
if (IS_ERR(hsphy->phy_reset)) {
|
||||
@ -327,12 +574,9 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
|
||||
hsphy->vregs[i].supply = qcom_snps_hsphy_vreg_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, num, hsphy->vregs);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to get regulator supplies: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to get regulator supplies\n");
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
@ -352,6 +596,7 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
|
||||
|
||||
dev_set_drvdata(dev, hsphy);
|
||||
phy_set_drvdata(generic_phy, hsphy);
|
||||
qcom_snps_hsphy_read_override_param_seq(dev);
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
if (!IS_ERR(phy_provider))
|
||||
|
@ -54,8 +54,10 @@ static int qcom_usb_hsic_phy_power_on(struct phy *phy)
|
||||
|
||||
/* Configure pins for HSIC functionality */
|
||||
pins_default = pinctrl_lookup_state(uphy->pctl, PINCTRL_STATE_DEFAULT);
|
||||
if (IS_ERR(pins_default))
|
||||
return PTR_ERR(pins_default);
|
||||
if (IS_ERR(pins_default)) {
|
||||
ret = PTR_ERR(pins_default);
|
||||
goto err_ulpi;
|
||||
}
|
||||
|
||||
ret = pinctrl_select_state(uphy->pctl, pins_default);
|
||||
if (ret)
|
||||
|
@ -83,6 +83,15 @@ config PHY_ROCKCHIP_PCIE
|
||||
help
|
||||
Enable this to support the Rockchip PCIe PHY.
|
||||
|
||||
config PHY_ROCKCHIP_SNPS_PCIE3
|
||||
tristate "Rockchip Snps PCIe3 PHY Driver"
|
||||
depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
select GENERIC_PHY
|
||||
select MFD_SYSCON
|
||||
help
|
||||
Enable this to support the Rockchip snps PCIe3 PHY.
|
||||
|
||||
config PHY_ROCKCHIP_TYPEC
|
||||
tristate "Rockchip TYPEC PHY Driver"
|
||||
depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST)
|
||||
|
@ -8,5 +8,6 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o
|
||||
obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
|
||||
obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o
|
||||
obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
|
||||
obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o
|
||||
obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
|
||||
obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
|
||||
|
@ -27,6 +27,9 @@
|
||||
|
||||
#define RK3368_GRF_SOC_CON6_OFFSET 0x0418
|
||||
|
||||
#define RK3568_GRF_VI_CON0 0x0340
|
||||
#define RK3568_GRF_VI_CON1 0x0344
|
||||
|
||||
/* PHY */
|
||||
#define CSIDPHY_CTRL_LANE_ENABLE 0x00
|
||||
#define CSIDPHY_CTRL_LANE_ENABLE_CK BIT(6)
|
||||
@ -58,9 +61,11 @@
|
||||
#define RK1808_CSIDPHY_CLK_WR_THS_SETTLE 0x160
|
||||
#define RK3326_CSIDPHY_CLK_WR_THS_SETTLE 0x100
|
||||
#define RK3368_CSIDPHY_CLK_WR_THS_SETTLE 0x100
|
||||
#define RK3568_CSIDPHY_CLK_WR_THS_SETTLE 0x160
|
||||
|
||||
/* Calibration reception enable */
|
||||
#define RK1808_CSIDPHY_CLK_CALIB_EN 0x168
|
||||
#define RK3568_CSIDPHY_CLK_CALIB_EN 0x168
|
||||
|
||||
/*
|
||||
* The higher 16-bit of this register is used for write protection
|
||||
@ -103,6 +108,12 @@ static const struct dphy_reg rk3368_grf_dphy_regs[] = {
|
||||
[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3368_GRF_SOC_CON6_OFFSET, 4, 8),
|
||||
};
|
||||
|
||||
static const struct dphy_reg rk3568_grf_dphy_regs[] = {
|
||||
[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3568_GRF_VI_CON0, 4, 0),
|
||||
[GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK3568_GRF_VI_CON0, 4, 4),
|
||||
[GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK3568_GRF_VI_CON0, 1, 8),
|
||||
};
|
||||
|
||||
struct hsfreq_range {
|
||||
u32 range_h;
|
||||
u8 cfg_bit;
|
||||
@ -352,6 +363,15 @@ static const struct dphy_drv_data rk3368_mipidphy_drv_data = {
|
||||
.grf_regs = rk3368_grf_dphy_regs,
|
||||
};
|
||||
|
||||
static const struct dphy_drv_data rk3568_mipidphy_drv_data = {
|
||||
.pwrctl_offset = -1,
|
||||
.ths_settle_offset = RK3568_CSIDPHY_CLK_WR_THS_SETTLE,
|
||||
.calib_offset = RK3568_CSIDPHY_CLK_CALIB_EN,
|
||||
.hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges,
|
||||
.num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges),
|
||||
.grf_regs = rk3568_grf_dphy_regs,
|
||||
};
|
||||
|
||||
static const struct of_device_id rockchip_inno_csidphy_match_id[] = {
|
||||
{
|
||||
.compatible = "rockchip,px30-csi-dphy",
|
||||
@ -369,6 +389,10 @@ static const struct of_device_id rockchip_inno_csidphy_match_id[] = {
|
||||
.compatible = "rockchip,rk3368-csi-dphy",
|
||||
.data = &rk3368_mipidphy_drv_data,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rk3568-csi-dphy",
|
||||
.data = &rk3568_mipidphy_drv_data,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rockchip_inno_csidphy_match_id);
|
||||
|
@ -84,9 +84,25 @@
|
||||
#define DATA_LANE_0_SKEW_PHASE_MASK GENMASK(2, 0)
|
||||
#define DATA_LANE_0_SKEW_PHASE(x) UPDATE(x, 2, 0)
|
||||
/* Analog Register Part: reg08 */
|
||||
#define PLL_POST_DIV_ENABLE_MASK BIT(5)
|
||||
#define PLL_POST_DIV_ENABLE BIT(5)
|
||||
#define SAMPLE_CLOCK_DIRECTION_MASK BIT(4)
|
||||
#define SAMPLE_CLOCK_DIRECTION_REVERSE BIT(4)
|
||||
#define SAMPLE_CLOCK_DIRECTION_FORWARD 0
|
||||
#define LOWFRE_EN_MASK BIT(5)
|
||||
#define PLL_OUTPUT_FREQUENCY_DIV_BY_1 0
|
||||
#define PLL_OUTPUT_FREQUENCY_DIV_BY_2 1
|
||||
/* Analog Register Part: reg0b */
|
||||
#define CLOCK_LANE_VOD_RANGE_SET_MASK GENMASK(3, 0)
|
||||
#define CLOCK_LANE_VOD_RANGE_SET(x) UPDATE(x, 3, 0)
|
||||
#define VOD_MIN_RANGE 0x1
|
||||
#define VOD_MID_RANGE 0x3
|
||||
#define VOD_BIG_RANGE 0x7
|
||||
#define VOD_MAX_RANGE 0xf
|
||||
/* Analog Register Part: reg1E */
|
||||
#define PLL_MODE_SEL_MASK GENMASK(6, 5)
|
||||
#define PLL_MODE_SEL_LVDS_MODE 0
|
||||
#define PLL_MODE_SEL_MIPI_MODE BIT(5)
|
||||
/* Digital Register Part: reg00 */
|
||||
#define REG_DIG_RSTN_MASK BIT(0)
|
||||
#define REG_DIG_RSTN_NORMAL BIT(0)
|
||||
@ -102,20 +118,22 @@
|
||||
#define T_LPX_CNT_MASK GENMASK(5, 0)
|
||||
#define T_LPX_CNT(x) UPDATE(x, 5, 0)
|
||||
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg06 */
|
||||
#define T_HS_ZERO_CNT_HI_MASK BIT(7)
|
||||
#define T_HS_ZERO_CNT_HI(x) UPDATE(x, 7, 7)
|
||||
#define T_HS_PREPARE_CNT_MASK GENMASK(6, 0)
|
||||
#define T_HS_PREPARE_CNT(x) UPDATE(x, 6, 0)
|
||||
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg07 */
|
||||
#define T_HS_ZERO_CNT_MASK GENMASK(5, 0)
|
||||
#define T_HS_ZERO_CNT(x) UPDATE(x, 5, 0)
|
||||
#define T_HS_ZERO_CNT_LO_MASK GENMASK(5, 0)
|
||||
#define T_HS_ZERO_CNT_LO(x) UPDATE(x, 5, 0)
|
||||
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg08 */
|
||||
#define T_HS_TRAIL_CNT_MASK GENMASK(6, 0)
|
||||
#define T_HS_TRAIL_CNT(x) UPDATE(x, 6, 0)
|
||||
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg09 */
|
||||
#define T_HS_EXIT_CNT_MASK GENMASK(4, 0)
|
||||
#define T_HS_EXIT_CNT(x) UPDATE(x, 4, 0)
|
||||
#define T_HS_EXIT_CNT_LO_MASK GENMASK(4, 0)
|
||||
#define T_HS_EXIT_CNT_LO(x) UPDATE(x, 4, 0)
|
||||
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0a */
|
||||
#define T_CLK_POST_CNT_MASK GENMASK(3, 0)
|
||||
#define T_CLK_POST_CNT(x) UPDATE(x, 3, 0)
|
||||
#define T_CLK_POST_CNT_LO_MASK GENMASK(3, 0)
|
||||
#define T_CLK_POST_CNT_LO(x) UPDATE(x, 3, 0)
|
||||
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0c */
|
||||
#define LPDT_TX_PPI_SYNC_MASK BIT(2)
|
||||
#define LPDT_TX_PPI_SYNC_ENABLE BIT(2)
|
||||
@ -129,9 +147,13 @@
|
||||
#define T_CLK_PRE_CNT_MASK GENMASK(3, 0)
|
||||
#define T_CLK_PRE_CNT(x) UPDATE(x, 3, 0)
|
||||
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg10 */
|
||||
#define T_CLK_POST_CNT_HI_MASK GENMASK(7, 6)
|
||||
#define T_CLK_POST_CNT_HI(x) UPDATE(x, 7, 6)
|
||||
#define T_TA_GO_CNT_MASK GENMASK(5, 0)
|
||||
#define T_TA_GO_CNT(x) UPDATE(x, 5, 0)
|
||||
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg11 */
|
||||
#define T_HS_EXIT_CNT_HI_MASK BIT(6)
|
||||
#define T_HS_EXIT_CNT_HI(x) UPDATE(x, 6, 6)
|
||||
#define T_TA_SURE_CNT_MASK GENMASK(5, 0)
|
||||
#define T_TA_SURE_CNT(x) UPDATE(x, 5, 0)
|
||||
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg12 */
|
||||
@ -169,11 +191,23 @@
|
||||
#define DSI_PHY_STATUS 0xb0
|
||||
#define PHY_LOCK BIT(0)
|
||||
|
||||
enum phy_max_rate {
|
||||
MAX_1GHZ,
|
||||
MAX_2_5GHZ,
|
||||
};
|
||||
|
||||
struct inno_video_phy_plat_data {
|
||||
const struct inno_mipi_dphy_timing *inno_mipi_dphy_timing_table;
|
||||
const unsigned int num_timings;
|
||||
enum phy_max_rate max_rate;
|
||||
};
|
||||
|
||||
struct inno_dsidphy {
|
||||
struct device *dev;
|
||||
struct clk *ref_clk;
|
||||
struct clk *pclk_phy;
|
||||
struct clk *pclk_host;
|
||||
const struct inno_video_phy_plat_data *pdata;
|
||||
void __iomem *phy_base;
|
||||
void __iomem *host_base;
|
||||
struct reset_control *rst;
|
||||
@ -200,6 +234,53 @@ enum {
|
||||
REGISTER_PART_LVDS,
|
||||
};
|
||||
|
||||
struct inno_mipi_dphy_timing {
|
||||
unsigned long rate;
|
||||
u8 lpx;
|
||||
u8 hs_prepare;
|
||||
u8 clk_lane_hs_zero;
|
||||
u8 data_lane_hs_zero;
|
||||
u8 hs_trail;
|
||||
};
|
||||
|
||||
static const
|
||||
struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_1ghz[] = {
|
||||
{ 110000000, 0x0, 0x20, 0x16, 0x02, 0x22},
|
||||
{ 150000000, 0x0, 0x06, 0x16, 0x03, 0x45},
|
||||
{ 200000000, 0x0, 0x18, 0x17, 0x04, 0x0b},
|
||||
{ 250000000, 0x0, 0x05, 0x17, 0x05, 0x16},
|
||||
{ 300000000, 0x0, 0x51, 0x18, 0x06, 0x2c},
|
||||
{ 400000000, 0x0, 0x64, 0x19, 0x07, 0x33},
|
||||
{ 500000000, 0x0, 0x20, 0x1b, 0x07, 0x4e},
|
||||
{ 600000000, 0x0, 0x6a, 0x1d, 0x08, 0x3a},
|
||||
{ 700000000, 0x0, 0x3e, 0x1e, 0x08, 0x6a},
|
||||
{ 800000000, 0x0, 0x21, 0x1f, 0x09, 0x29},
|
||||
{1000000000, 0x0, 0x09, 0x20, 0x09, 0x27},
|
||||
};
|
||||
|
||||
static const
|
||||
struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_2_5ghz[] = {
|
||||
{ 110000000, 0x02, 0x7f, 0x16, 0x02, 0x02},
|
||||
{ 150000000, 0x02, 0x7f, 0x16, 0x03, 0x02},
|
||||
{ 200000000, 0x02, 0x7f, 0x17, 0x04, 0x02},
|
||||
{ 250000000, 0x02, 0x7f, 0x17, 0x05, 0x04},
|
||||
{ 300000000, 0x02, 0x7f, 0x18, 0x06, 0x04},
|
||||
{ 400000000, 0x03, 0x7e, 0x19, 0x07, 0x04},
|
||||
{ 500000000, 0x03, 0x7c, 0x1b, 0x07, 0x08},
|
||||
{ 600000000, 0x03, 0x70, 0x1d, 0x08, 0x10},
|
||||
{ 700000000, 0x05, 0x40, 0x1e, 0x08, 0x30},
|
||||
{ 800000000, 0x05, 0x02, 0x1f, 0x09, 0x30},
|
||||
{1000000000, 0x05, 0x08, 0x20, 0x09, 0x30},
|
||||
{1200000000, 0x06, 0x03, 0x32, 0x14, 0x0f},
|
||||
{1400000000, 0x09, 0x03, 0x32, 0x14, 0x0f},
|
||||
{1600000000, 0x0d, 0x42, 0x36, 0x0e, 0x0f},
|
||||
{1800000000, 0x0e, 0x47, 0x7a, 0x0e, 0x0f},
|
||||
{2000000000, 0x11, 0x64, 0x7a, 0x0e, 0x0b},
|
||||
{2200000000, 0x13, 0x64, 0x7e, 0x15, 0x0b},
|
||||
{2400000000, 0x13, 0x33, 0x7f, 0x15, 0x6a},
|
||||
{2500000000, 0x15, 0x54, 0x7f, 0x15, 0x6a},
|
||||
};
|
||||
|
||||
static inline struct inno_dsidphy *hw_to_inno(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct inno_dsidphy, pll.hw);
|
||||
@ -290,31 +371,15 @@ static unsigned long inno_dsidphy_pll_calc_rate(struct inno_dsidphy *inno,
|
||||
static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno)
|
||||
{
|
||||
struct phy_configure_opts_mipi_dphy *cfg = &inno->dphy_cfg;
|
||||
const struct {
|
||||
unsigned long rate;
|
||||
u8 hs_prepare;
|
||||
u8 clk_lane_hs_zero;
|
||||
u8 data_lane_hs_zero;
|
||||
u8 hs_trail;
|
||||
} timings[] = {
|
||||
{ 110000000, 0x20, 0x16, 0x02, 0x22},
|
||||
{ 150000000, 0x06, 0x16, 0x03, 0x45},
|
||||
{ 200000000, 0x18, 0x17, 0x04, 0x0b},
|
||||
{ 250000000, 0x05, 0x17, 0x05, 0x16},
|
||||
{ 300000000, 0x51, 0x18, 0x06, 0x2c},
|
||||
{ 400000000, 0x64, 0x19, 0x07, 0x33},
|
||||
{ 500000000, 0x20, 0x1b, 0x07, 0x4e},
|
||||
{ 600000000, 0x6a, 0x1d, 0x08, 0x3a},
|
||||
{ 700000000, 0x3e, 0x1e, 0x08, 0x6a},
|
||||
{ 800000000, 0x21, 0x1f, 0x09, 0x29},
|
||||
{1000000000, 0x09, 0x20, 0x09, 0x27},
|
||||
};
|
||||
const struct inno_mipi_dphy_timing *timings;
|
||||
u32 t_txbyteclkhs, t_txclkesc;
|
||||
u32 txbyteclkhs, txclkesc, esc_clk_div;
|
||||
u32 hs_exit, clk_post, clk_pre, wakeup, lpx, ta_go, ta_sure, ta_wait;
|
||||
u32 hs_prepare, hs_trail, hs_zero, clk_lane_hs_zero, data_lane_hs_zero;
|
||||
unsigned int i;
|
||||
|
||||
timings = inno->pdata->inno_mipi_dphy_timing_table;
|
||||
|
||||
inno_dsidphy_pll_calc_rate(inno, cfg->hs_clk_rate);
|
||||
|
||||
/* Select MIPI mode */
|
||||
@ -327,6 +392,13 @@ static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno)
|
||||
REG_FBDIV_HI_MASK, REG_FBDIV_HI(inno->pll.fbdiv));
|
||||
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x04,
|
||||
REG_FBDIV_LO_MASK, REG_FBDIV_LO(inno->pll.fbdiv));
|
||||
if (inno->pdata->max_rate == MAX_2_5GHZ) {
|
||||
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x08,
|
||||
PLL_POST_DIV_ENABLE_MASK, PLL_POST_DIV_ENABLE);
|
||||
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x0b,
|
||||
CLOCK_LANE_VOD_RANGE_SET_MASK,
|
||||
CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE));
|
||||
}
|
||||
/* Enable PLL and LDO */
|
||||
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
|
||||
REG_LDOPD_MASK | REG_PLLPD_MASK,
|
||||
@ -367,14 +439,6 @@ static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno)
|
||||
*/
|
||||
clk_pre = DIV_ROUND_UP(cfg->clk_pre, BITS_PER_BYTE);
|
||||
|
||||
/*
|
||||
* The value of counter for HS Tlpx Time
|
||||
* Tlpx = Tpin_txbyteclkhs * (2 + value)
|
||||
*/
|
||||
lpx = DIV_ROUND_UP(cfg->lpx, t_txbyteclkhs);
|
||||
if (lpx >= 2)
|
||||
lpx -= 2;
|
||||
|
||||
/*
|
||||
* The value of counter for HS Tta-go
|
||||
* Tta-go for turnaround
|
||||
@ -394,13 +458,24 @@ static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno)
|
||||
*/
|
||||
ta_wait = DIV_ROUND_UP(cfg->ta_get, t_txclkesc);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(timings); i++)
|
||||
for (i = 0; i < inno->pdata->num_timings; i++)
|
||||
if (inno->pll.rate <= timings[i].rate)
|
||||
break;
|
||||
|
||||
if (i == ARRAY_SIZE(timings))
|
||||
if (i == inno->pdata->num_timings)
|
||||
--i;
|
||||
|
||||
/*
|
||||
* The value of counter for HS Tlpx Time
|
||||
* Tlpx = Tpin_txbyteclkhs * (2 + value)
|
||||
*/
|
||||
if (inno->pdata->max_rate == MAX_1GHZ) {
|
||||
lpx = DIV_ROUND_UP(cfg->lpx, t_txbyteclkhs);
|
||||
if (lpx >= 2)
|
||||
lpx -= 2;
|
||||
} else
|
||||
lpx = timings[i].lpx;
|
||||
|
||||
hs_prepare = timings[i].hs_prepare;
|
||||
hs_trail = timings[i].hs_trail;
|
||||
clk_lane_hs_zero = timings[i].clk_lane_hs_zero;
|
||||
@ -417,14 +492,23 @@ static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno)
|
||||
T_LPX_CNT(lpx));
|
||||
phy_update_bits(inno, i, 0x06, T_HS_PREPARE_CNT_MASK,
|
||||
T_HS_PREPARE_CNT(hs_prepare));
|
||||
phy_update_bits(inno, i, 0x07, T_HS_ZERO_CNT_MASK,
|
||||
T_HS_ZERO_CNT(hs_zero));
|
||||
if (inno->pdata->max_rate == MAX_2_5GHZ)
|
||||
phy_update_bits(inno, i, 0x06, T_HS_ZERO_CNT_HI_MASK,
|
||||
T_HS_ZERO_CNT_HI(hs_zero >> 6));
|
||||
phy_update_bits(inno, i, 0x07, T_HS_ZERO_CNT_LO_MASK,
|
||||
T_HS_ZERO_CNT_LO(hs_zero));
|
||||
phy_update_bits(inno, i, 0x08, T_HS_TRAIL_CNT_MASK,
|
||||
T_HS_TRAIL_CNT(hs_trail));
|
||||
phy_update_bits(inno, i, 0x09, T_HS_EXIT_CNT_MASK,
|
||||
T_HS_EXIT_CNT(hs_exit));
|
||||
phy_update_bits(inno, i, 0x0a, T_CLK_POST_CNT_MASK,
|
||||
T_CLK_POST_CNT(clk_post));
|
||||
if (inno->pdata->max_rate == MAX_2_5GHZ)
|
||||
phy_update_bits(inno, i, 0x11, T_HS_EXIT_CNT_HI_MASK,
|
||||
T_HS_EXIT_CNT_HI(hs_exit >> 5));
|
||||
phy_update_bits(inno, i, 0x09, T_HS_EXIT_CNT_LO_MASK,
|
||||
T_HS_EXIT_CNT_LO(hs_exit));
|
||||
if (inno->pdata->max_rate == MAX_2_5GHZ)
|
||||
phy_update_bits(inno, i, 0x10, T_CLK_POST_CNT_HI_MASK,
|
||||
T_CLK_POST_CNT_HI(clk_post >> 4));
|
||||
phy_update_bits(inno, i, 0x0a, T_CLK_POST_CNT_LO_MASK,
|
||||
T_CLK_POST_CNT_LO(clk_post));
|
||||
phy_update_bits(inno, i, 0x0e, T_CLK_PRE_CNT_MASK,
|
||||
T_CLK_PRE_CNT(clk_pre));
|
||||
phy_update_bits(inno, i, 0x0c, T_WAKEUP_CNT_HI_MASK,
|
||||
@ -452,8 +536,9 @@ static void inno_dsidphy_lvds_mode_enable(struct inno_dsidphy *inno)
|
||||
|
||||
/* Sample clock reverse direction */
|
||||
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x08,
|
||||
SAMPLE_CLOCK_DIRECTION_MASK,
|
||||
SAMPLE_CLOCK_DIRECTION_REVERSE);
|
||||
SAMPLE_CLOCK_DIRECTION_MASK | LOWFRE_EN_MASK,
|
||||
SAMPLE_CLOCK_DIRECTION_REVERSE |
|
||||
PLL_OUTPUT_FREQUENCY_DIV_BY_1);
|
||||
|
||||
/* Select LVDS mode */
|
||||
phy_update_bits(inno, REGISTER_PART_LVDS, 0x03,
|
||||
@ -473,6 +558,10 @@ static void inno_dsidphy_lvds_mode_enable(struct inno_dsidphy *inno)
|
||||
|
||||
msleep(20);
|
||||
|
||||
/* Select PLL mode */
|
||||
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x1e,
|
||||
PLL_MODE_SEL_MASK, PLL_MODE_SEL_LVDS_MODE);
|
||||
|
||||
/* Reset LVDS digital logic */
|
||||
phy_update_bits(inno, REGISTER_PART_LVDS, 0x00,
|
||||
LVDS_DIGITAL_INTERNAL_RESET_MASK,
|
||||
@ -592,6 +681,18 @@ static const struct phy_ops inno_dsidphy_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct inno_video_phy_plat_data max_1ghz_video_phy_plat_data = {
|
||||
.inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_1ghz,
|
||||
.num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_1ghz),
|
||||
.max_rate = MAX_1GHZ,
|
||||
};
|
||||
|
||||
static const struct inno_video_phy_plat_data max_2_5ghz_video_phy_plat_data = {
|
||||
.inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_2_5ghz,
|
||||
.num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_2_5ghz),
|
||||
.max_rate = MAX_2_5GHZ,
|
||||
};
|
||||
|
||||
static int inno_dsidphy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -605,6 +706,7 @@ static int inno_dsidphy_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
inno->dev = dev;
|
||||
inno->pdata = of_device_get_match_data(inno->dev);
|
||||
platform_set_drvdata(pdev, inno);
|
||||
|
||||
inno->phy_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
@ -663,9 +765,19 @@ static int inno_dsidphy_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id inno_dsidphy_of_match[] = {
|
||||
{ .compatible = "rockchip,px30-dsi-dphy", },
|
||||
{ .compatible = "rockchip,rk3128-dsi-dphy", },
|
||||
{ .compatible = "rockchip,rk3368-dsi-dphy", },
|
||||
{
|
||||
.compatible = "rockchip,px30-dsi-dphy",
|
||||
.data = &max_1ghz_video_phy_plat_data,
|
||||
}, {
|
||||
.compatible = "rockchip,rk3128-dsi-dphy",
|
||||
.data = &max_1ghz_video_phy_plat_data,
|
||||
}, {
|
||||
.compatible = "rockchip,rk3368-dsi-dphy",
|
||||
.data = &max_1ghz_video_phy_plat_data,
|
||||
}, {
|
||||
.compatible = "rockchip,rk3568-dsi-dphy",
|
||||
.data = &max_2_5ghz_video_phy_plat_data,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, inno_dsidphy_of_match);
|
||||
|
@ -1124,7 +1124,7 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
|
||||
struct rockchip_usb2phy_port *rport,
|
||||
struct device_node *child_np)
|
||||
{
|
||||
int ret;
|
||||
int ret, id;
|
||||
|
||||
rport->port_id = USB2PHY_PORT_OTG;
|
||||
rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG];
|
||||
@ -1162,13 +1162,15 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
|
||||
|
||||
ret = devm_extcon_register_notifier(rphy->dev, rphy->edev,
|
||||
EXTCON_USB_HOST, &rport->event_nb);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_err(rphy->dev, "register USB HOST notifier failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!of_property_read_bool(rphy->dev->of_node, "extcon")) {
|
||||
/* do initial sync of usb state */
|
||||
ret = property_enabled(rphy->grf, &rport->port_cfg->utmi_id);
|
||||
extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !ret);
|
||||
id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id);
|
||||
extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id);
|
||||
}
|
||||
}
|
||||
|
||||
|
322
drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
Normal file
322
drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
Normal file
@ -0,0 +1,322 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Rockchip PCIE3.0 phy driver
|
||||
*
|
||||
* Copyright (C) 2022 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/phy/pcie.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
/* Register for RK3568 */
|
||||
#define GRF_PCIE30PHY_CON1 0x4
|
||||
#define GRF_PCIE30PHY_CON6 0x18
|
||||
#define GRF_PCIE30PHY_CON9 0x24
|
||||
#define GRF_PCIE30PHY_DA_OCM (BIT(15) | BIT(31))
|
||||
#define GRF_PCIE30PHY_STATUS0 0x80
|
||||
#define GRF_PCIE30PHY_WR_EN (0xf << 16)
|
||||
#define SRAM_INIT_DONE(reg) (reg & BIT(14))
|
||||
|
||||
#define RK3568_BIFURCATION_LANE_0_1 BIT(0)
|
||||
|
||||
/* Register for RK3588 */
|
||||
#define PHP_GRF_PCIESEL_CON 0x100
|
||||
#define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0
|
||||
#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904
|
||||
#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04
|
||||
#define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0))
|
||||
|
||||
#define RK3588_BIFURCATION_LANE_0_1 BIT(0)
|
||||
#define RK3588_BIFURCATION_LANE_2_3 BIT(1)
|
||||
#define RK3588_LANE_AGGREGATION BIT(2)
|
||||
|
||||
struct rockchip_p3phy_ops;
|
||||
|
||||
struct rockchip_p3phy_priv {
|
||||
const struct rockchip_p3phy_ops *ops;
|
||||
void __iomem *mmio;
|
||||
/* mode: RC, EP */
|
||||
int mode;
|
||||
/* pcie30_phymode: Aggregation, Bifurcation */
|
||||
int pcie30_phymode;
|
||||
struct regmap *phy_grf;
|
||||
struct regmap *pipe_grf;
|
||||
struct reset_control *p30phy;
|
||||
struct phy *phy;
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
int num_lanes;
|
||||
u32 lanes[4];
|
||||
};
|
||||
|
||||
struct rockchip_p3phy_ops {
|
||||
int (*phy_init)(struct rockchip_p3phy_priv *priv);
|
||||
};
|
||||
|
||||
static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
{
|
||||
struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
|
||||
|
||||
/* Actually We don't care EP/RC mode, but just record it */
|
||||
switch (submode) {
|
||||
case PHY_MODE_PCIE_RC:
|
||||
priv->mode = PHY_MODE_PCIE_RC;
|
||||
break;
|
||||
case PHY_MODE_PCIE_EP:
|
||||
priv->mode = PHY_MODE_PCIE_EP;
|
||||
break;
|
||||
default:
|
||||
dev_err(&phy->dev, "%s, invalid mode\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv)
|
||||
{
|
||||
struct phy *phy = priv->phy;
|
||||
bool bifurcation = false;
|
||||
int ret;
|
||||
u32 reg;
|
||||
|
||||
/* Deassert PCIe PMA output clamp mode */
|
||||
regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, GRF_PCIE30PHY_DA_OCM);
|
||||
|
||||
for (int i = 0; i < priv->num_lanes; i++) {
|
||||
dev_info(&phy->dev, "lane number %d, val %d\n", i, priv->lanes[i]);
|
||||
if (priv->lanes[i] > 1)
|
||||
bifurcation = true;
|
||||
}
|
||||
|
||||
/* Set bifurcation if needed, and it doesn't care RC/EP */
|
||||
if (bifurcation) {
|
||||
dev_info(&phy->dev, "bifurcation enabled\n");
|
||||
regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
|
||||
GRF_PCIE30PHY_WR_EN | RK3568_BIFURCATION_LANE_0_1);
|
||||
regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1,
|
||||
GRF_PCIE30PHY_DA_OCM);
|
||||
} else {
|
||||
dev_dbg(&phy->dev, "bifurcation disabled\n");
|
||||
regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
|
||||
GRF_PCIE30PHY_WR_EN & ~RK3568_BIFURCATION_LANE_0_1);
|
||||
}
|
||||
|
||||
reset_control_deassert(priv->p30phy);
|
||||
|
||||
ret = regmap_read_poll_timeout(priv->phy_grf,
|
||||
GRF_PCIE30PHY_STATUS0,
|
||||
reg, SRAM_INIT_DONE(reg),
|
||||
0, 500);
|
||||
if (ret)
|
||||
dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n",
|
||||
__func__, reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct rockchip_p3phy_ops rk3568_ops = {
|
||||
.phy_init = rockchip_p3phy_rk3568_init,
|
||||
};
|
||||
|
||||
static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
|
||||
{
|
||||
u32 reg = 0;
|
||||
u8 mode = 0;
|
||||
int ret;
|
||||
|
||||
/* Deassert PCIe PMA output clamp mode */
|
||||
regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, BIT(8) | BIT(24));
|
||||
|
||||
/* Set bifurcation if needed */
|
||||
for (int i = 0; i < priv->num_lanes; i++) {
|
||||
if (!priv->lanes[i])
|
||||
mode |= (BIT(i) << 3);
|
||||
|
||||
if (priv->lanes[i] > 1)
|
||||
mode |= (BIT(i) >> 1);
|
||||
}
|
||||
|
||||
if (!mode)
|
||||
reg = RK3588_LANE_AGGREGATION;
|
||||
else {
|
||||
if (mode & (BIT(0) | BIT(1)))
|
||||
reg |= RK3588_BIFURCATION_LANE_0_1;
|
||||
|
||||
if (mode & (BIT(2) | BIT(3)))
|
||||
reg |= RK3588_BIFURCATION_LANE_2_3;
|
||||
}
|
||||
|
||||
regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, (0x7<<16) | reg);
|
||||
|
||||
/* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */
|
||||
if (!IS_ERR(priv->pipe_grf)) {
|
||||
reg = (mode & (BIT(6) | BIT(7))) >> 6;
|
||||
if (reg)
|
||||
regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
|
||||
(reg << 16) | reg);
|
||||
}
|
||||
|
||||
reset_control_deassert(priv->p30phy);
|
||||
|
||||
ret = regmap_read_poll_timeout(priv->phy_grf,
|
||||
RK3588_PCIE3PHY_GRF_PHY0_STATUS1,
|
||||
reg, RK3588_SRAM_INIT_DONE(reg),
|
||||
0, 500);
|
||||
ret |= regmap_read_poll_timeout(priv->phy_grf,
|
||||
RK3588_PCIE3PHY_GRF_PHY1_STATUS1,
|
||||
reg, RK3588_SRAM_INIT_DONE(reg),
|
||||
0, 500);
|
||||
if (ret)
|
||||
dev_err(&priv->phy->dev, "lock failed 0x%x, check input refclk and power supply\n",
|
||||
reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct rockchip_p3phy_ops rk3588_ops = {
|
||||
.phy_init = rockchip_p3phy_rk3588_init,
|
||||
};
|
||||
|
||||
static int rochchip_p3phy_init(struct phy *phy)
|
||||
{
|
||||
struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
|
||||
int ret;
|
||||
|
||||
ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
|
||||
if (ret) {
|
||||
dev_err(&priv->phy->dev, "failed to enable PCIe bulk clks %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
reset_control_assert(priv->p30phy);
|
||||
udelay(1);
|
||||
|
||||
if (priv->ops->phy_init) {
|
||||
ret = priv->ops->phy_init(priv);
|
||||
if (ret)
|
||||
clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rochchip_p3phy_exit(struct phy *phy)
|
||||
{
|
||||
struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
|
||||
|
||||
clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
|
||||
reset_control_assert(priv->p30phy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ops rochchip_p3phy_ops = {
|
||||
.init = rochchip_p3phy_init,
|
||||
.exit = rochchip_p3phy_exit,
|
||||
.set_mode = rockchip_p3phy_set_mode,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int rockchip_p3phy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct phy_provider *phy_provider;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rockchip_p3phy_priv *priv;
|
||||
struct device_node *np = dev->of_node;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
|
||||
if (IS_ERR(priv->mmio)) {
|
||||
ret = PTR_ERR(priv->mmio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->ops = of_device_get_match_data(&pdev->dev);
|
||||
if (!priv->ops) {
|
||||
dev_err(dev, "no of match data provided\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->phy_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,phy-grf");
|
||||
if (IS_ERR(priv->phy_grf)) {
|
||||
dev_err(dev, "failed to find rockchip,phy_grf regmap\n");
|
||||
return PTR_ERR(priv->phy_grf);
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(np, "rockchip,rk3588-pcie3-phy")) {
|
||||
priv->pipe_grf =
|
||||
syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||
"rockchip,pipe-grf");
|
||||
if (IS_ERR(priv->pipe_grf))
|
||||
dev_info(dev, "failed to find rockchip,pipe_grf regmap\n");
|
||||
} else {
|
||||
priv->pipe_grf = NULL;
|
||||
}
|
||||
|
||||
priv->num_lanes = of_property_read_variable_u32_array(dev->of_node, "data-lanes",
|
||||
priv->lanes, 2,
|
||||
ARRAY_SIZE(priv->lanes));
|
||||
|
||||
/* if no data-lanes assume aggregation */
|
||||
if (priv->num_lanes == -EINVAL) {
|
||||
dev_dbg(dev, "no data-lanes property found\n");
|
||||
priv->num_lanes = 1;
|
||||
priv->lanes[0] = 1;
|
||||
} else if (priv->num_lanes < 0) {
|
||||
dev_err(dev, "failed to read data-lanes property %d\n", priv->num_lanes);
|
||||
return priv->num_lanes;
|
||||
}
|
||||
|
||||
priv->phy = devm_phy_create(dev, NULL, &rochchip_p3phy_ops);
|
||||
if (IS_ERR(priv->phy)) {
|
||||
dev_err(dev, "failed to create combphy\n");
|
||||
return PTR_ERR(priv->phy);
|
||||
}
|
||||
|
||||
priv->p30phy = devm_reset_control_get_optional_exclusive(dev, "phy");
|
||||
if (IS_ERR(priv->p30phy)) {
|
||||
return dev_err_probe(dev, PTR_ERR(priv->p30phy),
|
||||
"failed to get phy reset control\n");
|
||||
}
|
||||
if (!priv->p30phy)
|
||||
dev_info(dev, "no phy reset control specified\n");
|
||||
|
||||
priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
|
||||
if (priv->num_clks < 1)
|
||||
return -ENODEV;
|
||||
|
||||
dev_set_drvdata(dev, priv);
|
||||
phy_set_drvdata(priv->phy, priv);
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
}
|
||||
|
||||
static const struct of_device_id rockchip_p3phy_of_match[] = {
|
||||
{ .compatible = "rockchip,rk3568-pcie3-phy", .data = &rk3568_ops },
|
||||
{ .compatible = "rockchip,rk3588-pcie3-phy", .data = &rk3588_ops },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rockchip_p3phy_of_match);
|
||||
|
||||
static struct platform_driver rockchip_p3phy_driver = {
|
||||
.probe = rockchip_p3phy_probe,
|
||||
.driver = {
|
||||
.name = "rockchip-snps-pcie3-phy",
|
||||
.of_match_table = rockchip_p3phy_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(rockchip_p3phy_driver);
|
||||
MODULE_DESCRIPTION("Rockchip Synopsys PCIe 3.0 PHY driver");
|
||||
MODULE_LICENSE("GPL");
|
12
drivers/phy/sunplus/Kconfig
Normal file
12
drivers/phy/sunplus/Kconfig
Normal file
@ -0,0 +1,12 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
config PHY_SUNPLUS_USB
|
||||
tristate "Sunplus SP7021 USB 2.0 PHY driver"
|
||||
depends on OF && (SOC_SP7021 || COMPILE_TEST)
|
||||
select GENERIC_PHY
|
||||
help
|
||||
Enable this to support the USB 2.0 PHY on Sunplus SP7021
|
||||
SoC. The USB 2.0 PHY controller supports battery charger
|
||||
and synchronous signals, various power down modes including
|
||||
operating, partial and suspend modes, and high-speed,
|
||||
full-speed and low-speed data transfer.
|
2
drivers/phy/sunplus/Makefile
Normal file
2
drivers/phy/sunplus/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_PHY_SUNPLUS_USB) += phy-sunplus-usb2.o
|
296
drivers/phy/sunplus/phy-sunplus-usb2.c
Normal file
296
drivers/phy/sunplus/phy-sunplus-usb2.c
Normal file
@ -0,0 +1,296 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
/*
|
||||
* Sunplus SP7021 USB 2.0 phy driver
|
||||
*
|
||||
* Copyright (C) 2022 Sunplus Technology Inc., All rights reserved.
|
||||
*
|
||||
* Note 1 : non-posted write command for the registers accesses of
|
||||
* Sunplus SP7021.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#define HIGH_MASK_BITS GENMASK(31, 16)
|
||||
#define LOW_MASK_BITS GENMASK(15, 0)
|
||||
#define OTP_DISC_LEVEL_DEFAULT 0xd
|
||||
|
||||
/* GROUP UPHY */
|
||||
#define CONFIG1 0x4
|
||||
#define J_HS_TX_PWRSAV BIT(5)
|
||||
#define CONFIG3 0xc
|
||||
#define J_FORCE_DISC_ON BIT(5)
|
||||
#define J_DEBUG_CTRL_ADDR_MACRO BIT(0)
|
||||
#define CONFIG7 0x1c
|
||||
#define J_DISC 0X1f
|
||||
#define CONFIG9 0x24
|
||||
#define J_ECO_PATH BIT(6)
|
||||
#define CONFIG16 0x40
|
||||
#define J_TBCWAIT_MASK GENMASK(6, 5)
|
||||
#define J_TBCWAIT_1P1_MS FIELD_PREP(J_TBCWAIT_MASK, 0)
|
||||
#define J_TVDM_SRC_DIS_MASK GENMASK(4, 3)
|
||||
#define J_TVDM_SRC_DIS_8P2_MS FIELD_PREP(J_TVDM_SRC_DIS_MASK, 3)
|
||||
#define J_TVDM_SRC_EN_MASK GENMASK(2, 1)
|
||||
#define J_TVDM_SRC_EN_1P6_MS FIELD_PREP(J_TVDM_SRC_EN_MASK, 0)
|
||||
#define J_BC_EN BIT(0)
|
||||
#define CONFIG17 0x44
|
||||
#define IBG_TRIM0_MASK GENMASK(7, 5)
|
||||
#define IBG_TRIM0_SSLVHT FIELD_PREP(IBG_TRIM0_MASK, 4)
|
||||
#define J_VDATREE_TRIM_MASK GENMASK(4, 1)
|
||||
#define J_VDATREE_TRIM_DEFAULT FIELD_PREP(J_VDATREE_TRIM_MASK, 9)
|
||||
#define CONFIG23 0x5c
|
||||
#define PROB_MASK GENMASK(5, 3)
|
||||
#define PROB FIELD_PREP(PROB_MASK, 7)
|
||||
|
||||
/* GROUP MOON4 */
|
||||
#define UPHY_CONTROL0 0x0
|
||||
#define UPHY_CONTROL1 0x4
|
||||
#define UPHY_CONTROL2 0x8
|
||||
#define MO1_UPHY_RX_CLK_SEL BIT(6)
|
||||
#define MASK_MO1_UPHY_RX_CLK_SEL BIT(6 + 16)
|
||||
#define UPHY_CONTROL3 0xc
|
||||
#define MO1_UPHY_PLL_POWER_OFF_SEL BIT(7)
|
||||
#define MASK_MO1_UPHY_PLL_POWER_OFF_SEL BIT(7 + 16)
|
||||
#define MO1_UPHY_PLL_POWER_OFF BIT(3)
|
||||
#define MASK_UPHY_PLL_POWER_OFF BIT(3 + 16)
|
||||
|
||||
struct sp_usbphy {
|
||||
struct device *dev;
|
||||
struct resource *phy_res_mem;
|
||||
struct resource *moon4_res_mem;
|
||||
struct reset_control *rstc;
|
||||
struct clk *phy_clk;
|
||||
void __iomem *phy_regs;
|
||||
void __iomem *moon4_regs;
|
||||
u32 disc_vol_addr_off;
|
||||
};
|
||||
|
||||
static int update_disc_vol(struct sp_usbphy *usbphy)
|
||||
{
|
||||
struct nvmem_cell *cell;
|
||||
char *disc_name = "disc_vol";
|
||||
ssize_t otp_l = 0;
|
||||
char *otp_v;
|
||||
u32 val, set;
|
||||
|
||||
cell = nvmem_cell_get(usbphy->dev, disc_name);
|
||||
if (IS_ERR_OR_NULL(cell)) {
|
||||
if (PTR_ERR(cell) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
otp_v = nvmem_cell_read(cell, &otp_l);
|
||||
nvmem_cell_put(cell);
|
||||
|
||||
if (!IS_ERR(otp_v)) {
|
||||
set = *(otp_v + 1);
|
||||
set = (set << (sizeof(char) * 8)) | *otp_v;
|
||||
set = (set >> usbphy->disc_vol_addr_off) & J_DISC;
|
||||
}
|
||||
|
||||
if (IS_ERR(otp_v) || set == 0)
|
||||
set = OTP_DISC_LEVEL_DEFAULT;
|
||||
|
||||
val = readl(usbphy->phy_regs + CONFIG7);
|
||||
val = (val & ~J_DISC) | set;
|
||||
writel(val, usbphy->phy_regs + CONFIG7);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp_uphy_init(struct phy *phy)
|
||||
{
|
||||
struct sp_usbphy *usbphy = phy_get_drvdata(phy);
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(usbphy->phy_clk);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
|
||||
ret = reset_control_deassert(usbphy->rstc);
|
||||
if (ret)
|
||||
goto err_reset;
|
||||
|
||||
/* Default value modification */
|
||||
writel(HIGH_MASK_BITS | 0x4002, usbphy->moon4_regs + UPHY_CONTROL0);
|
||||
writel(HIGH_MASK_BITS | 0x8747, usbphy->moon4_regs + UPHY_CONTROL1);
|
||||
|
||||
/* disconnect voltage */
|
||||
ret = update_disc_vol(usbphy);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* board uphy 0 internal register modification for tid certification */
|
||||
val = readl(usbphy->phy_regs + CONFIG9);
|
||||
val &= ~(J_ECO_PATH);
|
||||
writel(val, usbphy->phy_regs + CONFIG9);
|
||||
|
||||
val = readl(usbphy->phy_regs + CONFIG1);
|
||||
val &= ~(J_HS_TX_PWRSAV);
|
||||
writel(val, usbphy->phy_regs + CONFIG1);
|
||||
|
||||
val = readl(usbphy->phy_regs + CONFIG23);
|
||||
val = (val & ~PROB) | PROB;
|
||||
writel(val, usbphy->phy_regs + CONFIG23);
|
||||
|
||||
/* port 0 uphy clk fix */
|
||||
writel(MASK_MO1_UPHY_RX_CLK_SEL | MO1_UPHY_RX_CLK_SEL,
|
||||
usbphy->moon4_regs + UPHY_CONTROL2);
|
||||
|
||||
/* battery charger */
|
||||
writel(J_TBCWAIT_1P1_MS | J_TVDM_SRC_DIS_8P2_MS | J_TVDM_SRC_EN_1P6_MS | J_BC_EN,
|
||||
usbphy->phy_regs + CONFIG16);
|
||||
writel(IBG_TRIM0_SSLVHT | J_VDATREE_TRIM_DEFAULT, usbphy->phy_regs + CONFIG17);
|
||||
|
||||
/* chirp mode */
|
||||
writel(J_FORCE_DISC_ON | J_DEBUG_CTRL_ADDR_MACRO, usbphy->phy_regs + CONFIG3);
|
||||
|
||||
return 0;
|
||||
|
||||
err_reset:
|
||||
reset_control_assert(usbphy->rstc);
|
||||
err_clk:
|
||||
clk_disable_unprepare(usbphy->phy_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sp_uphy_power_on(struct phy *phy)
|
||||
{
|
||||
struct sp_usbphy *usbphy = phy_get_drvdata(phy);
|
||||
u32 pll_pwr_on, pll_pwr_off;
|
||||
|
||||
/* PLL power off/on twice */
|
||||
pll_pwr_off = (readl(usbphy->moon4_regs + UPHY_CONTROL3) & ~LOW_MASK_BITS)
|
||||
| MO1_UPHY_PLL_POWER_OFF_SEL | MO1_UPHY_PLL_POWER_OFF;
|
||||
pll_pwr_on = (readl(usbphy->moon4_regs + UPHY_CONTROL3) & ~LOW_MASK_BITS)
|
||||
| MO1_UPHY_PLL_POWER_OFF_SEL;
|
||||
|
||||
writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | pll_pwr_off,
|
||||
usbphy->moon4_regs + UPHY_CONTROL3);
|
||||
mdelay(1);
|
||||
writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | pll_pwr_on,
|
||||
usbphy->moon4_regs + UPHY_CONTROL3);
|
||||
mdelay(1);
|
||||
writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | pll_pwr_off,
|
||||
usbphy->moon4_regs + UPHY_CONTROL3);
|
||||
mdelay(1);
|
||||
writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | pll_pwr_on,
|
||||
usbphy->moon4_regs + UPHY_CONTROL3);
|
||||
mdelay(1);
|
||||
writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | 0x0,
|
||||
usbphy->moon4_regs + UPHY_CONTROL3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp_uphy_power_off(struct phy *phy)
|
||||
{
|
||||
struct sp_usbphy *usbphy = phy_get_drvdata(phy);
|
||||
u32 pll_pwr_off;
|
||||
|
||||
pll_pwr_off = (readl(usbphy->moon4_regs + UPHY_CONTROL3) & ~LOW_MASK_BITS)
|
||||
| MO1_UPHY_PLL_POWER_OFF_SEL | MO1_UPHY_PLL_POWER_OFF;
|
||||
|
||||
writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | pll_pwr_off,
|
||||
usbphy->moon4_regs + UPHY_CONTROL3);
|
||||
mdelay(1);
|
||||
writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | 0x0,
|
||||
usbphy->moon4_regs + UPHY_CONTROL3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp_uphy_exit(struct phy *phy)
|
||||
{
|
||||
struct sp_usbphy *usbphy = phy_get_drvdata(phy);
|
||||
|
||||
reset_control_assert(usbphy->rstc);
|
||||
clk_disable_unprepare(usbphy->phy_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ops sp_uphy_ops = {
|
||||
.init = sp_uphy_init,
|
||||
.power_on = sp_uphy_power_on,
|
||||
.power_off = sp_uphy_power_off,
|
||||
.exit = sp_uphy_exit,
|
||||
};
|
||||
|
||||
static const struct of_device_id sp_uphy_dt_ids[] = {
|
||||
{.compatible = "sunplus,sp7021-usb2-phy", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sp_uphy_dt_ids);
|
||||
|
||||
static int sp_usb_phy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sp_usbphy *usbphy;
|
||||
struct phy_provider *phy_provider;
|
||||
struct phy *phy;
|
||||
int ret;
|
||||
|
||||
usbphy = devm_kzalloc(&pdev->dev, sizeof(*usbphy), GFP_KERNEL);
|
||||
if (!usbphy)
|
||||
return -ENOMEM;
|
||||
|
||||
usbphy->dev = &pdev->dev;
|
||||
|
||||
usbphy->phy_res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
|
||||
usbphy->phy_regs = devm_ioremap_resource(&pdev->dev, usbphy->phy_res_mem);
|
||||
if (IS_ERR(usbphy->phy_regs))
|
||||
return PTR_ERR(usbphy->phy_regs);
|
||||
|
||||
usbphy->moon4_res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "moon4");
|
||||
usbphy->moon4_regs = devm_ioremap(&pdev->dev, usbphy->moon4_res_mem->start,
|
||||
resource_size(usbphy->moon4_res_mem));
|
||||
if (IS_ERR(usbphy->moon4_regs))
|
||||
return PTR_ERR(usbphy->moon4_regs);
|
||||
|
||||
usbphy->phy_clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(usbphy->phy_clk))
|
||||
return PTR_ERR(usbphy->phy_clk);
|
||||
|
||||
usbphy->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
if (IS_ERR(usbphy->rstc))
|
||||
return PTR_ERR(usbphy->rstc);
|
||||
|
||||
of_property_read_u32(pdev->dev.of_node, "sunplus,disc-vol-addr-off",
|
||||
&usbphy->disc_vol_addr_off);
|
||||
|
||||
phy = devm_phy_create(&pdev->dev, NULL, &sp_uphy_ops);
|
||||
if (IS_ERR(phy)) {
|
||||
ret = -PTR_ERR(phy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
phy_set_drvdata(phy, usbphy);
|
||||
phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
|
||||
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
}
|
||||
|
||||
static struct platform_driver sunplus_usb_phy_driver = {
|
||||
.probe = sp_usb_phy_probe,
|
||||
.driver = {
|
||||
.name = "sunplus-usb2-phy",
|
||||
.of_match_table = sp_uphy_dt_ids,
|
||||
},
|
||||
};
|
||||
module_platform_driver(sunplus_usb_phy_driver);
|
||||
|
||||
MODULE_AUTHOR("Vincent Shih <vincent.shih@sunplus.com>");
|
||||
MODULE_DESCRIPTION("Sunplus USB 2.0 phy driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -1381,12 +1381,9 @@ tegra186_xusb_read_fuse_calibration(struct tegra186_xusb_padctl *padctl)
|
||||
return -ENOMEM;
|
||||
|
||||
err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value);
|
||||
if (err) {
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to read calibration fuse: %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
return dev_err_probe(dev, err,
|
||||
"failed to read calibration fuse\n");
|
||||
|
||||
dev_dbg(dev, "FUSE_USB_CALIB_0 %#x\n", value);
|
||||
|
||||
|
@ -656,6 +656,7 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
|
||||
struct usb_role_switch_desc role_sx_desc = {
|
||||
.fwnode = dev_fwnode(&port->dev),
|
||||
.set = tegra_xusb_role_sw_set,
|
||||
.allow_userspace_control = true,
|
||||
};
|
||||
int err = 0;
|
||||
|
||||
@ -1270,7 +1271,7 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev)
|
||||
|
||||
padctl->soc->ops->remove(padctl);
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused int tegra_xusb_padctl_suspend_noirq(struct device *dev)
|
||||
|
@ -22,6 +22,12 @@
|
||||
#define AM33XX_GMII_SEL_MODE_RMII 1
|
||||
#define AM33XX_GMII_SEL_MODE_RGMII 2
|
||||
|
||||
/* J72xx SoC specific definitions for the CONTROL port */
|
||||
#define J72XX_GMII_SEL_MODE_QSGMII 4
|
||||
#define J72XX_GMII_SEL_MODE_QSGMII_SUB 6
|
||||
|
||||
#define PHY_GMII_PORT(n) BIT((n) - 1)
|
||||
|
||||
enum {
|
||||
PHY_GMII_SEL_PORT_MODE = 0,
|
||||
PHY_GMII_SEL_RGMII_ID_MODE,
|
||||
@ -43,6 +49,7 @@ struct phy_gmii_sel_soc_data {
|
||||
u32 features;
|
||||
const struct reg_field (*regfields)[PHY_GMII_SEL_LAST];
|
||||
bool use_of_data;
|
||||
u64 extra_modes;
|
||||
};
|
||||
|
||||
struct phy_gmii_sel_priv {
|
||||
@ -53,6 +60,7 @@ struct phy_gmii_sel_priv {
|
||||
struct phy_gmii_sel_phy_priv *if_phys;
|
||||
u32 num_ports;
|
||||
u32 reg_offset;
|
||||
u32 qsgmii_main_ports;
|
||||
};
|
||||
|
||||
static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
@ -88,10 +96,17 @@ static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
gmii_sel_mode = AM33XX_GMII_SEL_MODE_MII;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_QSGMII:
|
||||
if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_QSGMII)))
|
||||
goto unsupported;
|
||||
if (if_phy->priv->qsgmii_main_ports & BIT(if_phy->id - 1))
|
||||
gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII;
|
||||
else
|
||||
gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII_SUB;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_warn(dev, "port%u: unsupported mode: \"%s\"\n",
|
||||
if_phy->id, phy_modes(submode));
|
||||
return -EINVAL;
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
if_phy->phy_if_mode = submode;
|
||||
@ -123,6 +138,11 @@ static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
unsupported:
|
||||
dev_warn(dev, "port%u: unsupported mode: \"%s\"\n",
|
||||
if_phy->id, phy_modes(submode));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const
|
||||
@ -188,6 +208,13 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am654 = {
|
||||
.regfields = phy_gmii_sel_fields_am654,
|
||||
};
|
||||
|
||||
static const
|
||||
struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = {
|
||||
.use_of_data = true,
|
||||
.regfields = phy_gmii_sel_fields_am654,
|
||||
.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII),
|
||||
};
|
||||
|
||||
static const struct of_device_id phy_gmii_sel_id_table[] = {
|
||||
{
|
||||
.compatible = "ti,am3352-phy-gmii-sel",
|
||||
@ -209,6 +236,10 @@ static const struct of_device_id phy_gmii_sel_id_table[] = {
|
||||
.compatible = "ti,am654-phy-gmii-sel",
|
||||
.data = &phy_gmii_sel_soc_am654,
|
||||
},
|
||||
{
|
||||
.compatible = "ti,j7200-cpsw5g-phy-gmii-sel",
|
||||
.data = &phy_gmii_sel_cpsw5g_soc_j7200,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, phy_gmii_sel_id_table);
|
||||
@ -350,6 +381,7 @@ static int phy_gmii_sel_probe(struct platform_device *pdev)
|
||||
struct device_node *node = dev->of_node;
|
||||
const struct of_device_id *of_id;
|
||||
struct phy_gmii_sel_priv *priv;
|
||||
u32 main_ports = 1;
|
||||
int ret;
|
||||
|
||||
of_id = of_match_node(phy_gmii_sel_id_table, pdev->dev.of_node);
|
||||
@ -363,6 +395,15 @@ static int phy_gmii_sel_probe(struct platform_device *pdev)
|
||||
priv->dev = &pdev->dev;
|
||||
priv->soc_data = of_id->data;
|
||||
priv->num_ports = priv->soc_data->num_ports;
|
||||
of_property_read_u32(node, "ti,qsgmii-main-ports", &main_ports);
|
||||
/*
|
||||
* Ensure that main_ports is within bounds. If the property
|
||||
* ti,qsgmii-main-ports is not mentioned, or the value mentioned
|
||||
* is out of bounds, default to 1.
|
||||
*/
|
||||
if (main_ports < 1 || main_ports > 4)
|
||||
main_ports = 1;
|
||||
priv->qsgmii_main_ports = PHY_GMII_PORT(main_ports);
|
||||
|
||||
priv->regmap = syscon_node_to_regmap(node->parent);
|
||||
if (IS_ERR(priv->regmap)) {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/mux/consumer.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
@ -23,6 +24,15 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
|
||||
#define REF_CLK_19_2MHZ 19200000
|
||||
#define REF_CLK_25MHZ 25000000
|
||||
#define REF_CLK_100MHZ 100000000
|
||||
#define REF_CLK_156_25MHZ 156250000
|
||||
|
||||
/* SCM offsets */
|
||||
#define SERDES_SUP_CTRL 0x4400
|
||||
|
||||
/* SERDES offsets */
|
||||
#define WIZ_SERDES_CTRL 0x404
|
||||
#define WIZ_SERDES_TOP_CTRL 0x408
|
||||
#define WIZ_SERDES_RST 0x40c
|
||||
@ -85,6 +95,18 @@ static const struct reg_field pma_cmn_refclk_dig_div =
|
||||
REG_FIELD(WIZ_SERDES_TOP_CTRL, 26, 27);
|
||||
static const struct reg_field pma_cmn_refclk1_dig_div =
|
||||
REG_FIELD(WIZ_SERDES_TOP_CTRL, 24, 25);
|
||||
|
||||
static const struct reg_field sup_pll0_refclk_mux_sel =
|
||||
REG_FIELD(SERDES_SUP_CTRL, 0, 1);
|
||||
static const struct reg_field sup_pll1_refclk_mux_sel =
|
||||
REG_FIELD(SERDES_SUP_CTRL, 2, 3);
|
||||
static const struct reg_field sup_pma_cmn_refclk1_int_mode =
|
||||
REG_FIELD(SERDES_SUP_CTRL, 4, 5);
|
||||
static const struct reg_field sup_refclk_dig_sel_10g =
|
||||
REG_FIELD(SERDES_SUP_CTRL, 6, 7);
|
||||
static const struct reg_field sup_legacy_clk_override =
|
||||
REG_FIELD(SERDES_SUP_CTRL, 8, 8);
|
||||
|
||||
static const char * const output_clk_names[] = {
|
||||
[TI_WIZ_PLL0_REFCLK] = "pll0-refclk",
|
||||
[TI_WIZ_PLL1_REFCLK] = "pll1-refclk",
|
||||
@ -129,6 +151,26 @@ static const struct reg_field p0_fullrt_div[WIZ_MAX_LANES] = {
|
||||
REG_FIELD(WIZ_LANECTL(3), 22, 23),
|
||||
};
|
||||
|
||||
static const struct reg_field p0_mac_src_sel[WIZ_MAX_LANES] = {
|
||||
REG_FIELD(WIZ_LANECTL(0), 20, 21),
|
||||
REG_FIELD(WIZ_LANECTL(1), 20, 21),
|
||||
REG_FIELD(WIZ_LANECTL(2), 20, 21),
|
||||
REG_FIELD(WIZ_LANECTL(3), 20, 21),
|
||||
};
|
||||
|
||||
static const struct reg_field p0_rxfclk_sel[WIZ_MAX_LANES] = {
|
||||
REG_FIELD(WIZ_LANECTL(0), 6, 7),
|
||||
REG_FIELD(WIZ_LANECTL(1), 6, 7),
|
||||
REG_FIELD(WIZ_LANECTL(2), 6, 7),
|
||||
REG_FIELD(WIZ_LANECTL(3), 6, 7),
|
||||
};
|
||||
|
||||
static const struct reg_field p0_refclk_sel[WIZ_MAX_LANES] = {
|
||||
REG_FIELD(WIZ_LANECTL(0), 18, 19),
|
||||
REG_FIELD(WIZ_LANECTL(1), 18, 19),
|
||||
REG_FIELD(WIZ_LANECTL(2), 18, 19),
|
||||
REG_FIELD(WIZ_LANECTL(3), 18, 19),
|
||||
};
|
||||
static const struct reg_field p_mac_div_sel0[WIZ_MAX_LANES] = {
|
||||
REG_FIELD(WIZ_LANEDIV(0), 16, 22),
|
||||
REG_FIELD(WIZ_LANEDIV(1), 16, 22),
|
||||
@ -228,6 +270,27 @@ static const struct wiz_clk_mux_sel clk_mux_sel_10g[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct wiz_clk_mux_sel clk_mux_sel_10g_2_refclk[] = {
|
||||
{
|
||||
.num_parents = 3,
|
||||
.parents = { WIZ_CORE_REFCLK, WIZ_CORE_REFCLK1, WIZ_EXT_REFCLK },
|
||||
.table = { 2, 3, 0 },
|
||||
.node_name = "pll0-refclk",
|
||||
},
|
||||
{
|
||||
.num_parents = 3,
|
||||
.parents = { WIZ_CORE_REFCLK, WIZ_CORE_REFCLK1, WIZ_EXT_REFCLK },
|
||||
.table = { 2, 3, 0 },
|
||||
.node_name = "pll1-refclk",
|
||||
},
|
||||
{
|
||||
.num_parents = 3,
|
||||
.parents = { WIZ_CORE_REFCLK, WIZ_CORE_REFCLK1, WIZ_EXT_REFCLK },
|
||||
.table = { 2, 3, 0 },
|
||||
.node_name = "refclk-dig",
|
||||
},
|
||||
};
|
||||
|
||||
static const struct clk_div_table clk_div_table[] = {
|
||||
{ .val = 0, .div = 1, },
|
||||
{ .val = 1, .div = 2, },
|
||||
@ -249,14 +312,18 @@ static const struct wiz_clk_div_sel clk_div_sel[] = {
|
||||
|
||||
enum wiz_type {
|
||||
J721E_WIZ_16G,
|
||||
J721E_WIZ_10G,
|
||||
J721E_WIZ_10G, /* Also for J7200 SR1.0 */
|
||||
AM64_WIZ_10G,
|
||||
J7200_WIZ_10G, /* J7200 SR2.0 */
|
||||
};
|
||||
|
||||
struct wiz_data {
|
||||
enum wiz_type type;
|
||||
const struct reg_field *pll0_refclk_mux_sel;
|
||||
const struct reg_field *pll1_refclk_mux_sel;
|
||||
const struct reg_field *refclk_dig_sel;
|
||||
const struct reg_field *pma_cmn_refclk1_dig_div;
|
||||
const struct reg_field *pma_cmn_refclk1_int_mode;
|
||||
const struct wiz_clk_mux_sel *clk_mux_sel;
|
||||
unsigned int clk_div_sel_num;
|
||||
};
|
||||
@ -266,6 +333,7 @@ struct wiz_data {
|
||||
|
||||
struct wiz {
|
||||
struct regmap *regmap;
|
||||
struct regmap *scm_regmap;
|
||||
enum wiz_type type;
|
||||
const struct wiz_clk_mux_sel *clk_mux_sel;
|
||||
const struct wiz_clk_div_sel *clk_div_sel;
|
||||
@ -280,13 +348,18 @@ struct wiz {
|
||||
struct regmap_field *p_mac_div_sel0[WIZ_MAX_LANES];
|
||||
struct regmap_field *p_mac_div_sel1[WIZ_MAX_LANES];
|
||||
struct regmap_field *p0_fullrt_div[WIZ_MAX_LANES];
|
||||
struct regmap_field *p0_mac_src_sel[WIZ_MAX_LANES];
|
||||
struct regmap_field *p0_rxfclk_sel[WIZ_MAX_LANES];
|
||||
struct regmap_field *p0_refclk_sel[WIZ_MAX_LANES];
|
||||
struct regmap_field *pma_cmn_refclk_int_mode;
|
||||
struct regmap_field *pma_cmn_refclk1_int_mode;
|
||||
struct regmap_field *pma_cmn_refclk_mode;
|
||||
struct regmap_field *pma_cmn_refclk_dig_div;
|
||||
struct regmap_field *pma_cmn_refclk1_dig_div;
|
||||
struct regmap_field *mux_sel_field[WIZ_MUX_NUM_CLOCKS];
|
||||
struct regmap_field *div_sel_field[WIZ_DIV_NUM_CLOCKS_16G];
|
||||
struct regmap_field *typec_ln10_swap;
|
||||
struct regmap_field *sup_legacy_clk_override;
|
||||
|
||||
struct device *dev;
|
||||
u32 num_lanes;
|
||||
@ -325,7 +398,9 @@ static int wiz_p_mac_div_sel(struct wiz *wiz)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_lanes; i++) {
|
||||
if (wiz->lane_phy_type[i] == PHY_TYPE_QSGMII) {
|
||||
if (wiz->lane_phy_type[i] == PHY_TYPE_SGMII ||
|
||||
wiz->lane_phy_type[i] == PHY_TYPE_QSGMII ||
|
||||
wiz->lane_phy_type[i] == PHY_TYPE_USXGMII) {
|
||||
ret = regmap_field_write(wiz->p_mac_div_sel0[i], 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -354,6 +429,13 @@ static int wiz_mode_select(struct wiz *wiz)
|
||||
else
|
||||
continue;
|
||||
|
||||
if (wiz->lane_phy_type[i] == PHY_TYPE_USXGMII) {
|
||||
ret = regmap_field_write(wiz->p0_mac_src_sel[i], 0x3);
|
||||
ret = regmap_field_write(wiz->p0_rxfclk_sel[i], 0x3);
|
||||
ret = regmap_field_write(wiz->p0_refclk_sel[i], 0x3);
|
||||
mode = LANE_MODE_GEN1;
|
||||
}
|
||||
|
||||
ret = regmap_field_write(wiz->p_standard_mode[i], mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -416,6 +498,7 @@ static int wiz_init(struct wiz *wiz)
|
||||
static int wiz_regfield_init(struct wiz *wiz)
|
||||
{
|
||||
struct regmap *regmap = wiz->regmap;
|
||||
struct regmap *scm_regmap = wiz->regmap; /* updated later to scm_regmap if applicable */
|
||||
int num_lanes = wiz->num_lanes;
|
||||
struct device *dev = wiz->dev;
|
||||
const struct wiz_data *data = wiz->data;
|
||||
@ -465,27 +548,46 @@ static int wiz_regfield_init(struct wiz *wiz)
|
||||
}
|
||||
}
|
||||
|
||||
if (wiz->scm_regmap) {
|
||||
scm_regmap = wiz->scm_regmap;
|
||||
wiz->sup_legacy_clk_override =
|
||||
devm_regmap_field_alloc(dev, scm_regmap, sup_legacy_clk_override);
|
||||
if (IS_ERR(wiz->sup_legacy_clk_override)) {
|
||||
dev_err(dev, "SUP_LEGACY_CLK_OVERRIDE reg field init failed\n");
|
||||
return PTR_ERR(wiz->sup_legacy_clk_override);
|
||||
}
|
||||
}
|
||||
|
||||
wiz->mux_sel_field[PLL0_REFCLK] =
|
||||
devm_regmap_field_alloc(dev, regmap, pll0_refclk_mux_sel);
|
||||
devm_regmap_field_alloc(dev, scm_regmap, *data->pll0_refclk_mux_sel);
|
||||
if (IS_ERR(wiz->mux_sel_field[PLL0_REFCLK])) {
|
||||
dev_err(dev, "PLL0_REFCLK_SEL reg field init failed\n");
|
||||
return PTR_ERR(wiz->mux_sel_field[PLL0_REFCLK]);
|
||||
}
|
||||
|
||||
wiz->mux_sel_field[PLL1_REFCLK] =
|
||||
devm_regmap_field_alloc(dev, regmap, pll1_refclk_mux_sel);
|
||||
devm_regmap_field_alloc(dev, scm_regmap, *data->pll1_refclk_mux_sel);
|
||||
if (IS_ERR(wiz->mux_sel_field[PLL1_REFCLK])) {
|
||||
dev_err(dev, "PLL1_REFCLK_SEL reg field init failed\n");
|
||||
return PTR_ERR(wiz->mux_sel_field[PLL1_REFCLK]);
|
||||
}
|
||||
|
||||
wiz->mux_sel_field[REFCLK_DIG] = devm_regmap_field_alloc(dev, regmap,
|
||||
wiz->mux_sel_field[REFCLK_DIG] = devm_regmap_field_alloc(dev, scm_regmap,
|
||||
*data->refclk_dig_sel);
|
||||
if (IS_ERR(wiz->mux_sel_field[REFCLK_DIG])) {
|
||||
dev_err(dev, "REFCLK_DIG_SEL reg field init failed\n");
|
||||
return PTR_ERR(wiz->mux_sel_field[REFCLK_DIG]);
|
||||
}
|
||||
|
||||
if (data->pma_cmn_refclk1_int_mode) {
|
||||
wiz->pma_cmn_refclk1_int_mode =
|
||||
devm_regmap_field_alloc(dev, scm_regmap, *data->pma_cmn_refclk1_int_mode);
|
||||
if (IS_ERR(wiz->pma_cmn_refclk1_int_mode)) {
|
||||
dev_err(dev, "PMA_CMN_REFCLK1_INT_MODE reg field init failed\n");
|
||||
return PTR_ERR(wiz->pma_cmn_refclk1_int_mode);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num_lanes; i++) {
|
||||
wiz->p_enable[i] = devm_regmap_field_alloc(dev, regmap,
|
||||
p_enable[i]);
|
||||
@ -523,6 +625,24 @@ static int wiz_regfield_init(struct wiz *wiz)
|
||||
return PTR_ERR(wiz->p0_fullrt_div[i]);
|
||||
}
|
||||
|
||||
wiz->p0_mac_src_sel[i] = devm_regmap_field_alloc(dev, regmap, p0_mac_src_sel[i]);
|
||||
if (IS_ERR(wiz->p0_mac_src_sel[i])) {
|
||||
dev_err(dev, "P%d_MAC_SRC_SEL reg field init failed\n", i);
|
||||
return PTR_ERR(wiz->p0_mac_src_sel[i]);
|
||||
}
|
||||
|
||||
wiz->p0_rxfclk_sel[i] = devm_regmap_field_alloc(dev, regmap, p0_rxfclk_sel[i]);
|
||||
if (IS_ERR(wiz->p0_rxfclk_sel[i])) {
|
||||
dev_err(dev, "P%d_RXFCLK_SEL reg field init failed\n", i);
|
||||
return PTR_ERR(wiz->p0_rxfclk_sel[i]);
|
||||
}
|
||||
|
||||
wiz->p0_refclk_sel[i] = devm_regmap_field_alloc(dev, regmap, p0_refclk_sel[i]);
|
||||
if (IS_ERR(wiz->p0_refclk_sel[i])) {
|
||||
dev_err(dev, "P%d_REFCLK_SEL reg field init failed\n", i);
|
||||
return PTR_ERR(wiz->p0_refclk_sel[i]);
|
||||
}
|
||||
|
||||
wiz->p_mac_div_sel0[i] =
|
||||
devm_regmap_field_alloc(dev, regmap, p_mac_div_sel0[i]);
|
||||
if (IS_ERR(wiz->p_mac_div_sel0[i])) {
|
||||
@ -597,6 +717,8 @@ static int wiz_phy_en_refclk_register(struct wiz *wiz)
|
||||
struct device *dev = wiz->dev;
|
||||
struct clk_init_data *init;
|
||||
struct clk *clk;
|
||||
char *clk_name;
|
||||
unsigned int sz;
|
||||
|
||||
wiz_phy_en_refclk = devm_kzalloc(dev, sizeof(*wiz_phy_en_refclk), GFP_KERNEL);
|
||||
if (!wiz_phy_en_refclk)
|
||||
@ -606,12 +728,23 @@ static int wiz_phy_en_refclk_register(struct wiz *wiz)
|
||||
|
||||
init->ops = &wiz_phy_en_refclk_ops;
|
||||
init->flags = 0;
|
||||
init->name = output_clk_names[TI_WIZ_PHY_EN_REFCLK];
|
||||
|
||||
sz = strlen(dev_name(dev)) + strlen(output_clk_names[TI_WIZ_PHY_EN_REFCLK]) + 2;
|
||||
|
||||
clk_name = kzalloc(sz, GFP_KERNEL);
|
||||
if (!clk_name)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(clk_name, sz, "%s_%s", dev_name(dev), output_clk_names[TI_WIZ_PHY_EN_REFCLK]);
|
||||
init->name = clk_name;
|
||||
|
||||
wiz_phy_en_refclk->phy_en_refclk = wiz->phy_en_refclk;
|
||||
wiz_phy_en_refclk->hw.init = init;
|
||||
|
||||
clk = devm_clk_register(dev, &wiz_phy_en_refclk->hw);
|
||||
|
||||
kfree(clk_name);
|
||||
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
@ -856,9 +989,13 @@ static void wiz_clock_cleanup(struct wiz *wiz, struct device_node *node)
|
||||
struct device_node *clk_node;
|
||||
int i;
|
||||
|
||||
if (wiz->type == AM64_WIZ_10G) {
|
||||
switch (wiz->type) {
|
||||
case AM64_WIZ_10G:
|
||||
case J7200_WIZ_10G:
|
||||
of_clk_del_provider(dev->of_node);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++) {
|
||||
@ -885,9 +1022,6 @@ static int wiz_clock_register(struct wiz *wiz)
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (wiz->type != AM64_WIZ_10G)
|
||||
return 0;
|
||||
|
||||
clk_index = TI_WIZ_PLL0_REFCLK;
|
||||
for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++, clk_index++) {
|
||||
ret = wiz_mux_clk_register(wiz, wiz->mux_sel_field[i], &clk_mux_sel[i], clk_index);
|
||||
@ -937,6 +1071,41 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
|
||||
else
|
||||
regmap_field_write(wiz->pma_cmn_refclk_int_mode, 0x3);
|
||||
|
||||
switch (wiz->type) {
|
||||
case AM64_WIZ_10G:
|
||||
case J7200_WIZ_10G:
|
||||
switch (rate) {
|
||||
case REF_CLK_100MHZ:
|
||||
regmap_field_write(wiz->div_sel_field[CMN_REFCLK_DIG_DIV], 0x2);
|
||||
break;
|
||||
case REF_CLK_156_25MHZ:
|
||||
regmap_field_write(wiz->div_sel_field[CMN_REFCLK_DIG_DIV], 0x3);
|
||||
break;
|
||||
default:
|
||||
regmap_field_write(wiz->div_sel_field[CMN_REFCLK_DIG_DIV], 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (wiz->data->pma_cmn_refclk1_int_mode) {
|
||||
clk = devm_clk_get(dev, "core_ref1_clk");
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(dev, "core_ref1_clk clock not found\n");
|
||||
ret = PTR_ERR(clk);
|
||||
return ret;
|
||||
}
|
||||
wiz->input_clks[WIZ_CORE_REFCLK1] = clk;
|
||||
|
||||
rate = clk_get_rate(clk);
|
||||
if (rate >= 100000000)
|
||||
regmap_field_write(wiz->pma_cmn_refclk1_int_mode, 0x1);
|
||||
else
|
||||
regmap_field_write(wiz->pma_cmn_refclk1_int_mode, 0x3);
|
||||
}
|
||||
|
||||
clk = devm_clk_get(dev, "ext_ref_clk");
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(dev, "ext_ref_clk clock not found\n");
|
||||
@ -951,11 +1120,15 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
|
||||
else
|
||||
regmap_field_write(wiz->pma_cmn_refclk_mode, 0x2);
|
||||
|
||||
if (wiz->type == AM64_WIZ_10G) {
|
||||
switch (wiz->type) {
|
||||
case AM64_WIZ_10G:
|
||||
case J7200_WIZ_10G:
|
||||
ret = wiz_clock_register(wiz);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to register wiz clocks\n");
|
||||
return ret;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++) {
|
||||
@ -1025,12 +1198,19 @@ static int wiz_phy_reset_assert(struct reset_controller_dev *rcdev,
|
||||
|
||||
static int wiz_phy_fullrt_div(struct wiz *wiz, int lane)
|
||||
{
|
||||
if (wiz->type != AM64_WIZ_10G)
|
||||
switch (wiz->type) {
|
||||
case AM64_WIZ_10G:
|
||||
if (wiz->lane_phy_type[lane] == PHY_TYPE_PCIE)
|
||||
return regmap_field_write(wiz->p0_fullrt_div[lane], 0x1);
|
||||
break;
|
||||
case J721E_WIZ_10G:
|
||||
case J7200_WIZ_10G:
|
||||
if (wiz->lane_phy_type[lane] == PHY_TYPE_SGMII)
|
||||
return regmap_field_write(wiz->p0_fullrt_div[lane], 0x2);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
||||
if (wiz->lane_phy_type[lane] == PHY_TYPE_PCIE)
|
||||
return regmap_field_write(wiz->p0_fullrt_div[lane], 0x1);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1083,6 +1263,8 @@ static const struct regmap_config wiz_regmap_config = {
|
||||
|
||||
static struct wiz_data j721e_16g_data = {
|
||||
.type = J721E_WIZ_16G,
|
||||
.pll0_refclk_mux_sel = &pll0_refclk_mux_sel,
|
||||
.pll1_refclk_mux_sel = &pll1_refclk_mux_sel,
|
||||
.refclk_dig_sel = &refclk_dig_sel_16g,
|
||||
.pma_cmn_refclk1_dig_div = &pma_cmn_refclk1_dig_div,
|
||||
.clk_mux_sel = clk_mux_sel_16g,
|
||||
@ -1091,6 +1273,8 @@ static struct wiz_data j721e_16g_data = {
|
||||
|
||||
static struct wiz_data j721e_10g_data = {
|
||||
.type = J721E_WIZ_10G,
|
||||
.pll0_refclk_mux_sel = &pll0_refclk_mux_sel,
|
||||
.pll1_refclk_mux_sel = &pll1_refclk_mux_sel,
|
||||
.refclk_dig_sel = &refclk_dig_sel_10g,
|
||||
.clk_mux_sel = clk_mux_sel_10g,
|
||||
.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
|
||||
@ -1098,11 +1282,23 @@ static struct wiz_data j721e_10g_data = {
|
||||
|
||||
static struct wiz_data am64_10g_data = {
|
||||
.type = AM64_WIZ_10G,
|
||||
.pll0_refclk_mux_sel = &pll0_refclk_mux_sel,
|
||||
.pll1_refclk_mux_sel = &pll1_refclk_mux_sel,
|
||||
.refclk_dig_sel = &refclk_dig_sel_10g,
|
||||
.clk_mux_sel = clk_mux_sel_10g,
|
||||
.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
|
||||
};
|
||||
|
||||
static struct wiz_data j7200_pg2_10g_data = {
|
||||
.type = J7200_WIZ_10G,
|
||||
.pll0_refclk_mux_sel = &sup_pll0_refclk_mux_sel,
|
||||
.pll1_refclk_mux_sel = &sup_pll1_refclk_mux_sel,
|
||||
.refclk_dig_sel = &sup_refclk_dig_sel_10g,
|
||||
.pma_cmn_refclk1_int_mode = &sup_pma_cmn_refclk1_int_mode,
|
||||
.clk_mux_sel = clk_mux_sel_10g_2_refclk,
|
||||
.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
|
||||
};
|
||||
|
||||
static const struct of_device_id wiz_id_table[] = {
|
||||
{
|
||||
.compatible = "ti,j721e-wiz-16g", .data = &j721e_16g_data,
|
||||
@ -1113,6 +1309,9 @@ static const struct of_device_id wiz_id_table[] = {
|
||||
{
|
||||
.compatible = "ti,am64-wiz-10g", .data = &am64_10g_data,
|
||||
},
|
||||
{
|
||||
.compatible = "ti,j7200-wiz-10g", .data = &j7200_pg2_10g_data,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, wiz_id_table);
|
||||
@ -1210,6 +1409,17 @@ static int wiz_probe(struct platform_device *pdev)
|
||||
goto err_addr_to_resource;
|
||||
}
|
||||
|
||||
wiz->scm_regmap = syscon_regmap_lookup_by_phandle(node, "ti,scm");
|
||||
if (IS_ERR(wiz->scm_regmap)) {
|
||||
if (wiz->type == J7200_WIZ_10G) {
|
||||
dev_err(dev, "Couldn't get ti,scm regmap\n");
|
||||
ret = -ENODEV;
|
||||
goto err_addr_to_resource;
|
||||
}
|
||||
|
||||
wiz->scm_regmap = NULL;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "num-lanes", &num_lanes);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read num-lanes property\n");
|
||||
@ -1254,7 +1464,7 @@ static int wiz_probe(struct platform_device *pdev)
|
||||
|
||||
ret = wiz_get_lane_phy_types(dev, wiz);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_addr_to_resource;
|
||||
|
||||
wiz->dev = dev;
|
||||
wiz->regmap = regmap;
|
||||
@ -1271,6 +1481,10 @@ static int wiz_probe(struct platform_device *pdev)
|
||||
goto err_addr_to_resource;
|
||||
}
|
||||
|
||||
/* Enable supplemental Control override if available */
|
||||
if (wiz->scm_regmap)
|
||||
regmap_field_write(wiz->sup_legacy_clk_override, 1);
|
||||
|
||||
phy_reset_dev = &wiz->wiz_phy_reset_dev;
|
||||
phy_reset_dev->dev = dev;
|
||||
phy_reset_dev->ops = &wiz_phy_reset_ops,
|
||||
|
@ -22,5 +22,6 @@
|
||||
#define PHY_TYPE_QSGMII 9
|
||||
#define PHY_TYPE_DPHY 10
|
||||
#define PHY_TYPE_CPHY 11
|
||||
#define PHY_TYPE_USXGMII 12
|
||||
|
||||
#endif /* _DT_BINDINGS_PHY */
|
||||
|
12
include/linux/phy/pcie.h
Normal file
12
include/linux/phy/pcie.h
Normal file
@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
#ifndef __PHY_PCIE_H
|
||||
#define __PHY_PCIE_H
|
||||
|
||||
#define PHY_MODE_PCIE_RC 20
|
||||
#define PHY_MODE_PCIE_EP 21
|
||||
#define PHY_MODE_PCIE_BIFURCATION 22
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user