mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-13 00:29:50 +00:00
phy: for 5.8
*) Add new PHY driver to support Cadence SALVO PHY which supports USB3 & USB2 *) Add new PHY driver to support Intel ComboPhy which supports PCIe, SATA and EMAC *) Add new PHY driver for Qualcomm IPQ40xx USB PHY *) Add new PHY driver for Synopsys FemtoPHY V2 driver used in Qualcomm SOCs *) Add support for Qualcomm SM8250 UFS PHY and SM8150 QMP USB3 PHY in qcom-qmp-phy driver *) Add support for Amlogic USB2 PHY on Meson8m2 in phy-meson8b-usb2 driver *) Add DisplayPort mode support in Wiz (TI Cadence PHY wrapper), to enable eDP in TI's J721E SoC *) Add support for super speed USB PHY in TI's AM654 SoC *) Add fix in Broadcom Stingray USB PHY to get USB PHY PLL lock reliably *) Add fix in Samsung phy-s5pv210-usb2 to get USB working on s5pv210 *) Add fix in Amlogic phy-meson8b-usb2 to get host only mode working on Meson8 *) Add fix in Cadence phy-cadence-sierra to get USB3 device disconnect issue *) Convert meson8b-usb2-phy, qcom-qmp-phy, rcar-gen3-phy-usb2 and rcar-gen3-phy-usb3 device tree binding to YAML schema *) Minor fixes and cleanups in phy-cpcap-usb, j721e-wiz, omap-usb2, phy-bcm-sr-usb, phy-brcm-usb PHY driver Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> -----BEGIN PGP SIGNATURE----- iQJCBAABCgAsFiEEUXMr/TfP2p4suIY5Dlx4XIBNgtkFAl7GlXwOHGtpc2hvbkB0 aS5jb20ACgkQDlx4XIBNgtkapw/+IpzMaMb//L1Z4HXLCUljz37OpWER6u6GivRK +OE89+NzsoYdNrCPVM7b9VvFdTmlDRm4N3c8PoZS5Xw5lBMuzYqobafS2duLt401 ysuipcSihM5qKHboOXqDGHhzbTbYlLBPa7m7RHnlasC6hhK51a31Kmh6wb+buZKG iTogZAnObr7/EKm7HAud96vRv3Mh6V8UQgA4q1lnYnXiCWNY6w/U61JFVoWuaDxg 5ED0nS5F6sgS+EIqYVo7du9sJO8dgbD4xmBV4ODXTTaszgXnRps+bBjMWIYBiXNt Iuwx67ZyEI1kYnFx/EjO3ktRQWtkyoo7ljm494Ds685rY/Ibpea02KPqOu1Adn69 vph3R3YpH/B7C9CC9MTt00RRr3DCHS/GtBeNZAdkp8r+AQibwp4KRyLSFZgb3MjN 0DkGGaZM+LDrlGdi4Bq0PJyy2p5I7zG2F2tw8hcJw25FO1KEJVyjtOPCYyDQSIzn vlI4q0bTl3kjQYhnxYulEiYB+6WfjOOG0oGCNAi1fhWbAakJbOVHX0icq0idFp/a PQRfsVjDCPGxF8gLAM//t4ITc6ZyAPmSq/yOu/bSCHkUIxfjd10aFs/6OIXaRaB+ WbvsT6A6OwEdQOyod2iiP66RvQskujWK/BA1frXTF7hzPlL7qgVNhtHNlLAcwOXD A1Bl+pw= =H+Lw -----END PGP SIGNATURE----- Merge tag 'phy-for-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy into usb-next Kishon writes: phy: for 5.8 *) Add new PHY driver to support Cadence SALVO PHY which supports USB3 & USB2 *) Add new PHY driver to support Intel ComboPhy which supports PCIe, SATA and EMAC *) Add new PHY driver for Qualcomm IPQ40xx USB PHY *) Add new PHY driver for Synopsys FemtoPHY V2 driver used in Qualcomm SOCs *) Add support for Qualcomm SM8250 UFS PHY and SM8150 QMP USB3 PHY in qcom-qmp-phy driver *) Add support for Amlogic USB2 PHY on Meson8m2 in phy-meson8b-usb2 driver *) Add DisplayPort mode support in Wiz (TI Cadence PHY wrapper), to enable eDP in TI's J721E SoC *) Add support for super speed USB PHY in TI's AM654 SoC *) Add fix in Broadcom Stingray USB PHY to get USB PHY PLL lock reliably *) Add fix in Samsung phy-s5pv210-usb2 to get USB working on s5pv210 *) Add fix in Amlogic phy-meson8b-usb2 to get host only mode working on Meson8 *) Add fix in Cadence phy-cadence-sierra to get USB3 device disconnect issue *) Convert meson8b-usb2-phy, qcom-qmp-phy, rcar-gen3-phy-usb2 and rcar-gen3-phy-usb3 device tree binding to YAML schema *) Minor fixes and cleanups in phy-cpcap-usb, j721e-wiz, omap-usb2, phy-bcm-sr-usb, phy-brcm-usb PHY driver Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> * tag 'phy-for-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (43 commits) phy: intel: Add driver support for ComboPhy dt-bindings: phy: Add YAML schemas for Intel ComboPhy dt-bindings: phy: Add PHY_TYPE_XPCS definition phy: qcom-qmp: Add QMP V3 USB3 PHY support for SC7180 dt-bindings: phy: qcom,qmp-usb3-dp: Add support for SC7180 dt-bindings: phy: qcom,qmp-usb3-dp: Add dt bindings for USB3 DP PHY dt-bindings: phy: qcom,qmp: Convert QMP PHY bindings to yaml phy: cadence: sierra: Fix for USB3 U1/U2 state phy: ti: am654: add support for USB super-speed phy: ti: am654: show up in regmap debugfs drivers: phy: sr-usb: do not use internal fsm for USB2 phy init dt-bindings: phy: renesas: usb3-phy: add r8a77961 support dt-bindings: phy: renesas: usb3-phy: convert bindings to json-schema dt-bindings: phy: renesas: usb2-phy: add r8a77961 support dt-bindings: phy: renesas: usb2-phy: convert bindings to json-schema phy: qcom-qmp: Ensure register indirection arrays initialized phy: omap-usb2: Clean up exported header phy: phy-bcm-ns2-usbdrd: Constify phy_ops phy: phy-brcm-usb: Constify static structs phy: sr-usb: Constify phy_ops ...
This commit is contained in:
commit
14f3a5ccac
@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/phy/amlogic,meson8b-usb2-phy.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Amlogic Meson8, Meson8b, Meson8m2 and GXBB USB2 PHY
|
||||
|
||||
maintainers:
|
||||
- Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- amlogic,meson8-usb2-phy
|
||||
- amlogic,meson8b-usb2-phy
|
||||
- amlogic,meson8m2-usb2-phy
|
||||
- const: amlogic,meson-mx-usb2-phy
|
||||
- const: amlogic,meson-gxbb-usb2-phy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: usb_general
|
||||
- const: usb
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
phy-supply:
|
||||
description:
|
||||
Phandle to a regulator that provides power to the PHY. This
|
||||
regulator will be managed during the PHY power on/off sequence.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
usb-phy@c0000000 {
|
||||
compatible = "amlogic,meson-gxbb-usb2-phy";
|
||||
reg = <0xc0000000 0x20>;
|
||||
resets = <&reset_usb_phy>;
|
||||
clocks = <&clk_usb_general>, <&reset_usb>;
|
||||
clock-names = "usb_general", "usb";
|
||||
phy-supply = <&usb_vbus>;
|
||||
#phy-cells = <0>;
|
||||
};
|
52
Documentation/devicetree/bindings/phy/cdns,salvo-phy.yaml
Normal file
52
Documentation/devicetree/bindings/phy/cdns,salvo-phy.yaml
Normal file
@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
# Copyright (c) 2020 NXP
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/phy/cdns,salvo-phy.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Cadence SALVO PHY
|
||||
|
||||
maintainers:
|
||||
- Peter Chen <peter.chen@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- nxp,salvo-phy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: salvo_phy_clk
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/firmware/imx/rsrc.h>
|
||||
|
||||
usb3phy: usb3-phy@5b160000 {
|
||||
compatible = "nxp,salvo-phy";
|
||||
reg = <0x5b160000 0x40000>;
|
||||
clocks = <&usb3_lpcg 4>;
|
||||
clock-names = "salvo_phy_clk";
|
||||
power-domains = <&pd IMX_SC_R_USB_2_PHY>;
|
||||
#phy-cells = <0>;
|
||||
};
|
101
Documentation/devicetree/bindings/phy/intel,combo-phy.yaml
Normal file
101
Documentation/devicetree/bindings/phy/intel,combo-phy.yaml
Normal file
@ -0,0 +1,101 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/intel,combo-phy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Intel ComboPhy Subsystem
|
||||
|
||||
maintainers:
|
||||
- Dilip Kota <eswara.kota@linux.intel.com>
|
||||
|
||||
description: |
|
||||
Intel Combophy subsystem supports PHYs for PCIe, EMAC and SATA
|
||||
controllers. A single Combophy provides two PHY instances.
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "combophy(@.*|-[0-9a-f])*$"
|
||||
|
||||
compatible:
|
||||
items:
|
||||
- const: intel,combophy-lgm
|
||||
- const: intel,combo-phy
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: ComboPhy core registers
|
||||
- description: PCIe app core control registers
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: app
|
||||
|
||||
resets:
|
||||
maxItems: 4
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: core
|
||||
- const: iphy0
|
||||
- const: iphy1
|
||||
|
||||
intel,syscfg:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description: Chip configuration registers handle and ComboPhy instance id
|
||||
|
||||
intel,hsio:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description: HSIO registers handle and ComboPhy instance id on NOC
|
||||
|
||||
intel,aggregation:
|
||||
type: boolean
|
||||
description: |
|
||||
Specify the flag to configure ComboPHY in dual lane mode.
|
||||
|
||||
intel,phy-mode:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
Mode of the two phys in ComboPhy.
|
||||
See dt-bindings/phy/phy.h for values.
|
||||
|
||||
"#phy-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
- reg
|
||||
- reg-names
|
||||
- intel,syscfg
|
||||
- intel,hsio
|
||||
- intel,phy-mode
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/phy/phy.h>
|
||||
combophy@d0a00000 {
|
||||
compatible = "intel,combophy-lgm", "intel,combo-phy";
|
||||
clocks = <&cgu0 1>;
|
||||
#phy-cells = <1>;
|
||||
reg = <0xd0a00000 0x40000>,
|
||||
<0xd0a40000 0x1000>;
|
||||
reg-names = "core", "app";
|
||||
resets = <&rcu0 0x50 6>,
|
||||
<&rcu0 0x50 17>,
|
||||
<&rcu0 0x50 23>,
|
||||
<&rcu0 0x50 24>;
|
||||
reset-names = "phy", "core", "iphy0", "iphy1";
|
||||
intel,syscfg = <&sysconf 0>;
|
||||
intel,hsio = <&hsiol 0>;
|
||||
intel,phy-mode = <PHY_TYPE_PCIE>;
|
||||
intel,aggregation;
|
||||
};
|
@ -1,28 +0,0 @@
|
||||
* Amlogic Meson8, Meson8b and GXBB USB2 PHY
|
||||
|
||||
Required properties:
|
||||
- compatible: Depending on the platform this should be one of:
|
||||
"amlogic,meson8-usb2-phy"
|
||||
"amlogic,meson8b-usb2-phy"
|
||||
"amlogic,meson-gxbb-usb2-phy"
|
||||
- reg: The base address and length of the registers
|
||||
- #phys-cells: should be 0 (see phy-bindings.txt in this directory)
|
||||
- clocks: phandle and clock identifier for the phy clocks
|
||||
- clock-names: "usb_general" and "usb"
|
||||
|
||||
Optional properties:
|
||||
- resets: reference to the reset controller
|
||||
- phy-supply: see phy-bindings.txt in this directory
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
usb0_phy: usb-phy@c0000000 {
|
||||
compatible = "amlogic,meson-gxbb-usb2-phy";
|
||||
#phy-cells = <0>;
|
||||
reg = <0x0 0xc0000000 0x0 0x20>;
|
||||
resets = <&reset RESET_USB_OTG>;
|
||||
clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>;
|
||||
clock-names = "usb_general", "usb";
|
||||
phy-supply = <&usb_vbus>;
|
||||
};
|
313
Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
Normal file
313
Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
Normal file
@ -0,0 +1,313 @@
|
||||
# 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:
|
||||
- Manu Gautam <mgautam@codeaurora.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,ipq8074-qmp-pcie-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,sdm845-qhp-pcie-phy
|
||||
- qcom,sdm845-qmp-pcie-phy
|
||||
- qcom,sdm845-qmp-ufs-phy
|
||||
- qcom,sdm845-qmp-usb3-uni-phy
|
||||
- qcom,sm8150-qmp-ufs-phy
|
||||
- qcom,sm8250-qmp-ufs-phy
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: Address and length of PHY's common serdes block.
|
||||
|
||||
"#clock-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
"#address-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
"#size-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
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"
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
|
||||
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
|
||||
- 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
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- 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
|
||||
- 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
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8998-qmp-ufs-phy
|
||||
- qcom,sdm845-qmp-ufs-phy
|
||||
- qcom,sm8150-qmp-ufs-phy
|
||||
- qcom,sm8250-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
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq8074-qmp-pcie-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: pipe clk.
|
||||
clock-names:
|
||||
items:
|
||||
- const: pipe_clk
|
||||
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,sdm845-qhp-pcie-phy
|
||||
- qcom,sdm845-qmp-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
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-sdm845.h>
|
||||
usb_2_qmpphy: phy-wrapper@88eb000 {
|
||||
compatible = "qcom,sdm845-qmp-usb3-uni-phy";
|
||||
reg = <0 0x088eb000 0 0x18c>;
|
||||
#clock-cells = <1>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
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@88eb200 {
|
||||
reg = <0 0x088eb200 0 0x128>,
|
||||
<0 0x088eb400 0 0x1fc>,
|
||||
<0 0x088eb800 0 0x218>,
|
||||
<0 0x088eb600 0 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";
|
||||
};
|
||||
};
|
136
Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
Normal file
136
Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
Normal file
@ -0,0 +1,136 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/phy/qcom,qmp-usb3-dp-phy.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcomm QMP USB3 DP PHY controller
|
||||
|
||||
maintainers:
|
||||
- Manu Gautam <mgautam@codeaurora.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sc7180-qmp-usb3-phy
|
||||
- qcom,sdm845-qmp-usb3-phy
|
||||
reg:
|
||||
items:
|
||||
- description: Address and length of PHY's common serdes block.
|
||||
- description: Address and length of the DP_COM control block.
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: reg-base
|
||||
- const: dp_com
|
||||
|
||||
"#clock-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
"#address-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
"#size-cells":
|
||||
enum: [ 1, 2 ]
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
- reg-names
|
||||
- "#clock-cells"
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
- vdda-phy-supply
|
||||
- vdda-pll-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-sdm845.h>
|
||||
usb_1_qmpphy: phy-wrapper@88e9000 {
|
||||
compatible = "qcom,sdm845-qmp-usb3-phy";
|
||||
reg = <0 0x088e9000 0 0x18c>,
|
||||
<0 0x088e8000 0 0x10>;
|
||||
reg-names = "reg-base", "dp_com";
|
||||
#clock-cells = <1>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
|
||||
<&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
|
||||
<&gcc GCC_USB3_PRIM_CLKREF_CLK>,
|
||||
<&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
|
||||
clock-names = "aux", "cfg_ahb", "ref", "com_aux";
|
||||
|
||||
resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
|
||||
<&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
|
||||
reset-names = "phy", "common";
|
||||
|
||||
vdda-phy-supply = <&vdda_usb2_ss_1p2>;
|
||||
vdda-pll-supply = <&vdda_usb2_ss_core>;
|
||||
|
||||
usb_1_ssphy: phy@88e9200 {
|
||||
reg = <0 0x088e9200 0 0x128>,
|
||||
<0 0x088e9400 0 0x200>,
|
||||
<0 0x088e9c00 0 0x218>,
|
||||
<0 0x088e9600 0 0x128>,
|
||||
<0 0x088e9800 0 0x200>,
|
||||
<0 0x088e9a00 0 0x100>;
|
||||
#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";
|
||||
};
|
||||
};
|
@ -0,0 +1,80 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/phy/qcom,usb-snps-femto-v2.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcomm Synopsys Femto High-Speed USB PHY V2
|
||||
|
||||
maintainers:
|
||||
- Wesley Cheng <wcheng@codeaurora.org>
|
||||
|
||||
description: |
|
||||
Qualcomm High-Speed USB PHY
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,usb-snps-hs-7nm-phy
|
||||
- qcom,sm8150-usb-hs-phy
|
||||
- qcom,usb-snps-femto-v2-phy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: rpmhcc ref clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ref
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: PHY core reset
|
||||
|
||||
vdda-pll-supply:
|
||||
description: phandle to the regulator VDD supply node.
|
||||
|
||||
vdda18-supply:
|
||||
description: phandle to the regulator 1.8V supply node.
|
||||
|
||||
vdda33-supply:
|
||||
description: phandle to the regulator 3.3V supply node.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#phy-cells"
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- vdda-pll-supply
|
||||
- vdda18-supply
|
||||
- vdda33-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-sm8150.h>
|
||||
phy@88e2000 {
|
||||
compatible = "qcom,sm8150-usb-hs-phy";
|
||||
reg = <0 0x088e2000 0 0x400>;
|
||||
#phy-cells = <0>;
|
||||
|
||||
clocks = <&rpmhcc RPMH_CXO_CLK>;
|
||||
clock-names = "ref";
|
||||
|
||||
resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
|
||||
|
||||
vdda-pll-supply = <&vdd_usb_hs_core>;
|
||||
vdda33-supply = <&vdda_usb_hs_3p1>;
|
||||
vdda18-supply = <&vdda_usb_hs_1p8>;
|
||||
};
|
||||
...
|
@ -1,242 +0,0 @@
|
||||
Qualcomm QMP PHY controller
|
||||
===========================
|
||||
|
||||
QMP phy controller supports physical layer functionality for a number of
|
||||
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
|
||||
|
||||
Required properties:
|
||||
- compatible: compatible list, contains:
|
||||
"qcom,ipq8074-qmp-pcie-phy" for PCIe phy on IPQ8074
|
||||
"qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996,
|
||||
"qcom,msm8996-qmp-ufs-phy" for 14nm UFS phy on msm8996,
|
||||
"qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996,
|
||||
"qcom,msm8998-qmp-usb3-phy" for USB3 QMP V3 phy on msm8998,
|
||||
"qcom,msm8998-qmp-ufs-phy" for UFS QMP phy on msm8998,
|
||||
"qcom,msm8998-qmp-pcie-phy" for PCIe QMP phy on msm8998,
|
||||
"qcom,sdm845-qhp-pcie-phy" for QHP PCIe phy on sdm845,
|
||||
"qcom,sdm845-qmp-pcie-phy" for QMP PCIe phy on sdm845,
|
||||
"qcom,sdm845-qmp-usb3-phy" for USB3 QMP V3 phy on sdm845,
|
||||
"qcom,sdm845-qmp-usb3-uni-phy" for USB3 QMP V3 UNI phy on sdm845,
|
||||
"qcom,sdm845-qmp-ufs-phy" for UFS QMP phy on sdm845,
|
||||
"qcom,sm8150-qmp-ufs-phy" for UFS QMP phy on sm8150.
|
||||
|
||||
- reg:
|
||||
- index 0: address and length of register set for PHY's common
|
||||
serdes block.
|
||||
- index 1: address and length of the DP_COM control block (for
|
||||
"qcom,sdm845-qmp-usb3-phy" only).
|
||||
|
||||
- reg-names:
|
||||
- For "qcom,sdm845-qmp-usb3-phy":
|
||||
- Should be: "reg-base", "dp_com"
|
||||
- For all others:
|
||||
- The reg-names property shouldn't be defined.
|
||||
|
||||
- #address-cells: must be 1
|
||||
- #size-cells: must be 1
|
||||
- ranges: must be present
|
||||
|
||||
- clocks: a list of phandles and clock-specifier pairs,
|
||||
one for each entry in clock-names.
|
||||
- clock-names: "cfg_ahb" for phy config clock,
|
||||
"aux" for phy aux clock,
|
||||
"ref" for 19.2 MHz ref clk,
|
||||
"com_aux" for phy common block aux clock,
|
||||
"ref_aux" for phy reference aux clock,
|
||||
|
||||
For "qcom,ipq8074-qmp-pcie-phy": no clocks are listed.
|
||||
For "qcom,msm8996-qmp-pcie-phy" must contain:
|
||||
"aux", "cfg_ahb", "ref".
|
||||
For "qcom,msm8996-qmp-ufs-phy" must contain:
|
||||
"ref".
|
||||
For "qcom,msm8996-qmp-usb3-phy" must contain:
|
||||
"aux", "cfg_ahb", "ref".
|
||||
For "qcom,msm8998-qmp-usb3-phy" must contain:
|
||||
"aux", "cfg_ahb", "ref".
|
||||
For "qcom,msm8998-qmp-ufs-phy" must contain:
|
||||
"ref", "ref_aux".
|
||||
For "qcom,msm8998-qmp-pcie-phy" must contain:
|
||||
"aux", "cfg_ahb", "ref".
|
||||
For "qcom,sdm845-qhp-pcie-phy" must contain:
|
||||
"aux", "cfg_ahb", "ref", "refgen".
|
||||
For "qcom,sdm845-qmp-pcie-phy" must contain:
|
||||
"aux", "cfg_ahb", "ref", "refgen".
|
||||
For "qcom,sdm845-qmp-usb3-phy" must contain:
|
||||
"aux", "cfg_ahb", "ref", "com_aux".
|
||||
For "qcom,sdm845-qmp-usb3-uni-phy" must contain:
|
||||
"aux", "cfg_ahb", "ref", "com_aux".
|
||||
For "qcom,sdm845-qmp-ufs-phy" must contain:
|
||||
"ref", "ref_aux".
|
||||
For "qcom,sm8150-qmp-ufs-phy" must contain:
|
||||
"ref", "ref_aux".
|
||||
|
||||
- resets: a list of phandles and reset controller specifier pairs,
|
||||
one for each entry in reset-names.
|
||||
- reset-names: "phy" for reset of phy block,
|
||||
"common" for phy common block reset,
|
||||
"cfg" for phy's ahb cfg block reset,
|
||||
"ufsphy" for the PHY reset in the UFS controller.
|
||||
|
||||
For "qcom,ipq8074-qmp-pcie-phy" must contain:
|
||||
"phy", "common".
|
||||
For "qcom,msm8996-qmp-pcie-phy" must contain:
|
||||
"phy", "common", "cfg".
|
||||
For "qcom,msm8996-qmp-ufs-phy": must contain:
|
||||
"ufsphy".
|
||||
For "qcom,msm8996-qmp-usb3-phy" must contain
|
||||
"phy", "common".
|
||||
For "qcom,msm8998-qmp-usb3-phy" must contain
|
||||
"phy", "common".
|
||||
For "qcom,msm8998-qmp-ufs-phy": must contain:
|
||||
"ufsphy".
|
||||
For "qcom,msm8998-qmp-pcie-phy" must contain:
|
||||
"phy", "common".
|
||||
For "qcom,sdm845-qhp-pcie-phy" must contain:
|
||||
"phy".
|
||||
For "qcom,sdm845-qmp-pcie-phy" must contain:
|
||||
"phy".
|
||||
For "qcom,sdm845-qmp-usb3-phy" must contain:
|
||||
"phy", "common".
|
||||
For "qcom,sdm845-qmp-usb3-uni-phy" must contain:
|
||||
"phy", "common".
|
||||
For "qcom,sdm845-qmp-ufs-phy": must contain:
|
||||
"ufsphy".
|
||||
For "qcom,sm8150-qmp-ufs-phy": must contain:
|
||||
"ufsphy".
|
||||
|
||||
- vdda-phy-supply: Phandle to a regulator supply to PHY core block.
|
||||
- vdda-pll-supply: Phandle to 1.8V regulator supply to PHY refclk pll block.
|
||||
|
||||
Optional properties:
|
||||
- vddp-ref-clk-supply: Phandle to a regulator supply to any specific refclk
|
||||
pll block.
|
||||
|
||||
Required nodes:
|
||||
- Each device node of QMP phy is required to have as many child nodes as
|
||||
the number of lanes the PHY has.
|
||||
|
||||
Required properties for child nodes of PCIe PHYs (one child per lane):
|
||||
- reg: list of offset and length pairs of register sets for PHY blocks -
|
||||
tx, rx, pcs, and pcs_misc (optional).
|
||||
- #phy-cells: must be 0
|
||||
|
||||
Required properties for a single "lanes" child node of non-PCIe PHYs:
|
||||
- reg: list of offset and length pairs of register sets for PHY blocks
|
||||
For 1-lane devices:
|
||||
tx, rx, pcs, and (optionally) pcs_misc
|
||||
For 2-lane devices:
|
||||
tx0, rx0, pcs, tx1, rx1, and (optionally) pcs_misc
|
||||
- #phy-cells: must be 0
|
||||
|
||||
Required properties for child node of PCIe and USB3 qmp phys:
|
||||
- clocks: a list of phandles and clock-specifier pairs,
|
||||
one for each entry in clock-names.
|
||||
- clock-names: Must contain following:
|
||||
"pipe<lane-number>" for pipe clock specific to each lane.
|
||||
- clock-output-names: Name of the PHY clock that will be the parent for
|
||||
the above pipe clock.
|
||||
For "qcom,ipq8074-qmp-pcie-phy":
|
||||
- "pcie20_phy0_pipe_clk" Pipe Clock parent
|
||||
(or)
|
||||
"pcie20_phy1_pipe_clk"
|
||||
- #clock-cells: must be 0
|
||||
- Phy pll outputs pipe clocks for pipe based PHYs. These clocks are then
|
||||
gate-controlled by the gcc.
|
||||
|
||||
Required properties for child node of PHYs with lane reset, AKA:
|
||||
"qcom,msm8996-qmp-pcie-phy"
|
||||
- resets: a list of phandles and reset controller specifier pairs,
|
||||
one for each entry in reset-names.
|
||||
- reset-names: Must contain following:
|
||||
"lane<lane-number>" for reset specific to each lane.
|
||||
|
||||
Example:
|
||||
phy@34000 {
|
||||
compatible = "qcom,msm8996-qmp-pcie-phy";
|
||||
reg = <0x34000 0x488>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
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";
|
||||
|
||||
vdda-phy-supply = <&pm8994_l28>;
|
||||
vdda-pll-supply = <&pm8994_l12>;
|
||||
|
||||
resets = <&gcc GCC_PCIE_PHY_BCR>,
|
||||
<&gcc GCC_PCIE_PHY_COM_BCR>,
|
||||
<&gcc GCC_PCIE_PHY_COM_NOCSR_BCR>;
|
||||
reset-names = "phy", "common", "cfg";
|
||||
|
||||
pciephy_0: lane@35000 {
|
||||
reg = <0x35000 0x130>,
|
||||
<0x35200 0x200>,
|
||||
<0x35400 0x1dc>;
|
||||
#clock-cells = <0>;
|
||||
#phy-cells = <0>;
|
||||
|
||||
clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
|
||||
clock-names = "pipe0";
|
||||
clock-output-names = "pcie_0_pipe_clk_src";
|
||||
resets = <&gcc GCC_PCIE_0_PHY_BCR>;
|
||||
reset-names = "lane0";
|
||||
};
|
||||
|
||||
pciephy_1: lane@36000 {
|
||||
...
|
||||
...
|
||||
};
|
||||
|
||||
phy@88eb000 {
|
||||
compatible = "qcom,sdm845-qmp-usb3-uni-phy";
|
||||
reg = <0x88eb000 0x18c>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
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";
|
||||
|
||||
lane@88eb200 {
|
||||
reg = <0x88eb200 0x128>,
|
||||
<0x88eb400 0x1fc>,
|
||||
<0x88eb800 0x218>,
|
||||
<0x88eb600 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";
|
||||
};
|
||||
};
|
||||
|
||||
phy@1d87000 {
|
||||
compatible = "qcom,sdm845-qmp-ufs-phy";
|
||||
reg = <0x1d87000 0x18c>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
clock-names = "ref",
|
||||
"ref_aux";
|
||||
clocks = <&gcc GCC_UFS_MEM_CLKREF_CLK>,
|
||||
<&gcc GCC_UFS_PHY_PHY_AUX_CLK>;
|
||||
|
||||
lanes@1d87400 {
|
||||
reg = <0x1d87400 0x108>,
|
||||
<0x1d87600 0x1e0>,
|
||||
<0x1d87c00 0x1dc>,
|
||||
<0x1d87800 0x108>,
|
||||
<0x1d87a00 0x1e0>;
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/phy/qcom-usb-ipq4019-phy.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Qualcom IPQ40xx Dakota HS/SS USB PHY
|
||||
|
||||
maintainers:
|
||||
- Robert Marko <robert.marko@sartura.hr>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,usb-ss-ipq4019-phy
|
||||
- qcom,usb-hs-ipq4019-phy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 2
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: por_rst
|
||||
- const: srif_rst
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- resets
|
||||
- reset-names
|
||||
- "#phy-cells"
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-ipq4019.h>
|
||||
|
||||
hsphy@a8000 {
|
||||
#phy-cells = <0>;
|
||||
compatible = "qcom,usb-hs-ipq4019-phy";
|
||||
reg = <0xa8000 0x40>;
|
||||
resets = <&gcc USB2_HSPHY_POR_ARES>,
|
||||
<&gcc USB2_HSPHY_S_ARES>;
|
||||
reset-names = "por_rst", "srif_rst";
|
||||
};
|
@ -1,70 +0,0 @@
|
||||
* Renesas R-Car generation 3 USB 2.0 PHY
|
||||
|
||||
This file provides information on what the device node for the R-Car generation
|
||||
3, RZ/G1C, RZ/G2 and RZ/A2 USB 2.0 PHY contain.
|
||||
|
||||
Required properties:
|
||||
- compatible: "renesas,usb2-phy-r7s9210" if the device is a part of an R7S9210
|
||||
SoC.
|
||||
"renesas,usb2-phy-r8a77470" if the device is a part of an R8A77470
|
||||
SoC.
|
||||
"renesas,usb2-phy-r8a774a1" if the device is a part of an R8A774A1
|
||||
SoC.
|
||||
"renesas,usb2-phy-r8a774b1" if the device is a part of an R8A774B1
|
||||
SoC.
|
||||
"renesas,usb2-phy-r8a774c0" if the device is a part of an R8A774C0
|
||||
SoC.
|
||||
"renesas,usb2-phy-r8a7795" if the device is a part of an R8A7795
|
||||
SoC.
|
||||
"renesas,usb2-phy-r8a7796" if the device is a part of an R8A7796
|
||||
SoC.
|
||||
"renesas,usb2-phy-r8a77965" if the device is a part of an
|
||||
R8A77965 SoC.
|
||||
"renesas,usb2-phy-r8a77990" if the device is a part of an
|
||||
R8A77990 SoC.
|
||||
"renesas,usb2-phy-r8a77995" if the device is a part of an
|
||||
R8A77995 SoC.
|
||||
"renesas,rcar-gen3-usb2-phy" for a generic R-Car Gen3, RZ/G2 or
|
||||
RZ/A2 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 partial USB 2.0 Host register block.
|
||||
- clocks: clock phandle and specifier pair(s).
|
||||
- #phy-cells: see phy-bindings.txt in the same directory, must be <1> (and
|
||||
using <0> is deprecated).
|
||||
|
||||
The phandle's argument in the PHY specifier is the INT_STATUS bit of controller:
|
||||
- 1 = USBH_INTA (OHCI)
|
||||
- 2 = USBH_INTB (EHCI)
|
||||
- 3 = UCOM_INT (OTG and BC)
|
||||
|
||||
Optional properties:
|
||||
To use a USB channel where USB 2.0 Host and HSUSB (USB 2.0 Peripheral) are
|
||||
combined, the device tree node should set interrupt properties to use the
|
||||
channel as USB OTG:
|
||||
- interrupts: interrupt specifier for the PHY.
|
||||
- vbus-supply: Phandle to a regulator that provides power to the VBUS. This
|
||||
regulator will be managed during the PHY power on/off sequence.
|
||||
- renesas,no-otg-pins: boolean, specify when a board does not provide proper
|
||||
otg pins.
|
||||
- dr_mode: string, indicates the working mode for the PHY. Can be "host",
|
||||
"peripheral", or "otg". Should be set if otg controller is not used.
|
||||
|
||||
|
||||
Example (R-Car H3):
|
||||
|
||||
usb-phy@ee080200 {
|
||||
compatible = "renesas,usb2-phy-r8a7795", "renesas,rcar-gen3-usb2-phy";
|
||||
reg = <0 0xee080200 0 0x700>;
|
||||
interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cpg CPG_MOD 703>;
|
||||
};
|
||||
|
||||
usb-phy@ee0a0200 {
|
||||
compatible = "renesas,usb2-phy-r8a7795", "renesas,rcar-gen3-usb2-phy";
|
||||
reg = <0 0xee0a0200 0 0x700>;
|
||||
clocks = <&cpg CPG_MOD 702>;
|
||||
};
|
@ -1,52 +0,0 @@
|
||||
* Renesas R-Car generation 3 USB 3.0 PHY
|
||||
|
||||
This file provides information on what the device node for the R-Car generation
|
||||
3 and RZ/G2 USB 3.0 PHY contain.
|
||||
If you want to enable spread spectrum clock (ssc), you should use USB_EXTAL
|
||||
instead of USB3_CLK. However, if you don't want to these features, you don't
|
||||
need this driver.
|
||||
|
||||
Required properties:
|
||||
- compatible: "renesas,r8a774a1-usb3-phy" if the device is a part of an R8A774A1
|
||||
SoC.
|
||||
"renesas,r8a774b1-usb3-phy" if the device is a part of an R8A774B1
|
||||
SoC.
|
||||
"renesas,r8a7795-usb3-phy" if the device is a part of an R8A7795
|
||||
SoC.
|
||||
"renesas,r8a7796-usb3-phy" if the device is a part of an R8A7796
|
||||
SoC.
|
||||
"renesas,r8a77965-usb3-phy" if the device is a part of an
|
||||
R8A77965 SoC.
|
||||
"renesas,rcar-gen3-usb3-phy" for a generic R-Car Gen3 or RZ/G2
|
||||
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 USB 3.0 PHY register block.
|
||||
- clocks: A list of phandles and clock-specifier pairs.
|
||||
- clock-names: Name of the clocks.
|
||||
- The funcional clock must be "usb3-if".
|
||||
- The usb3's external clock must be "usb3s_clk".
|
||||
- The usb2's external clock must be "usb_extal". If you want to use the ssc,
|
||||
the clock-frequency must not be 0.
|
||||
- #phy-cells: see phy-bindings.txt in the same directory, must be <0>.
|
||||
|
||||
Optional properties:
|
||||
- renesas,ssc-range: Enable/disable spread spectrum clock (ssc) by using
|
||||
the following values as u32:
|
||||
- 0 (or the property doesn't exist): disable the ssc
|
||||
- 4980: enable the ssc as -4980 ppm
|
||||
- 4492: enable the ssc as -4492 ppm
|
||||
- 4003: enable the ssc as -4003 ppm
|
||||
|
||||
Example (R-Car H3):
|
||||
|
||||
usb-phy@e65ee000 {
|
||||
compatible = "renesas,r8a7795-usb3-phy",
|
||||
"renesas,rcar-gen3-usb3-phy";
|
||||
reg = <0 0xe65ee000 0 0x90>;
|
||||
clocks = <&cpg CPG_MOD 328>, <&usb3s0_clk>, <&usb_extal>;
|
||||
clock-names = "usb3-if", "usb3s_clk", "usb_extal";
|
||||
};
|
117
Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml
Normal file
117
Documentation/devicetree/bindings/phy/renesas,usb2-phy.yaml
Normal file
@ -0,0 +1,117 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/renesas,usb2-phy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas R-Car generation 3 USB 2.0 PHY
|
||||
|
||||
maintainers:
|
||||
- Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: renesas,usb2-phy-r8a77470 # RZ/G1C
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,usb2-phy-r7s9210 # RZ/A2
|
||||
- renesas,usb2-phy-r8a774a1 # RZ/G2M
|
||||
- renesas,usb2-phy-r8a774b1 # RZ/G2N
|
||||
- renesas,usb2-phy-r8a774c0 # RZ/G2E
|
||||
- renesas,usb2-phy-r8a7795 # R-Car H3
|
||||
- renesas,usb2-phy-r8a7796 # R-Car M3-W
|
||||
- renesas,usb2-phy-r8a77961 # R-Car M3-W+
|
||||
- renesas,usb2-phy-r8a77965 # R-Car M3-N
|
||||
- renesas,usb2-phy-r8a77990 # R-Car E3
|
||||
- renesas,usb2-phy-r8a77995 # R-Car D3
|
||||
- const: renesas,rcar-gen3-usb2-phy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
items:
|
||||
- const: fck
|
||||
- const: usb_x1
|
||||
|
||||
'#phy-cells':
|
||||
enum: [0, 1] # and 0 is deprecated.
|
||||
description: |
|
||||
The phandle's argument in the PHY specifier is the INT_STATUS bit of
|
||||
controller.
|
||||
- 1 = USBH_INTA (OHCI)
|
||||
- 2 = USBH_INTB (EHCI)
|
||||
- 3 = UCOM_INT (OTG and BC)
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
items:
|
||||
- description: reset of USB 2.0 host side
|
||||
- description: reset of USB 2.0 peripheral side
|
||||
|
||||
vbus-supply:
|
||||
description: |
|
||||
Phandle to a regulator that provides power to the VBUS. This regulator
|
||||
will be managed during the PHY power on/off sequence.
|
||||
|
||||
renesas,no-otg-pins:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description: |
|
||||
specify when a board does not provide proper otg pins.
|
||||
|
||||
dr_mode: true
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
enum:
|
||||
- renesas,usb2-phy-r7s9210
|
||||
then:
|
||||
required:
|
||||
- clock-names
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- '#phy-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/r8a7795-sysc.h>
|
||||
|
||||
usb-phy@ee080200 {
|
||||
compatible = "renesas,usb2-phy-r8a7795", "renesas,rcar-gen3-usb2-phy";
|
||||
reg = <0xee080200 0x700>;
|
||||
interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cpg CPG_MOD 703>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
|
||||
usb-phy@ee0a0200 {
|
||||
compatible = "renesas,usb2-phy-r8a7795", "renesas,rcar-gen3-usb2-phy";
|
||||
reg = <0xee0a0200 0x700>;
|
||||
clocks = <&cpg CPG_MOD 702>;
|
||||
#phy-cells = <1>;
|
||||
};
|
79
Documentation/devicetree/bindings/phy/renesas,usb3-phy.yaml
Normal file
79
Documentation/devicetree/bindings/phy/renesas,usb3-phy.yaml
Normal file
@ -0,0 +1,79 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/renesas,usb3-phy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas R-Car generation 3 USB 3.0 PHY
|
||||
|
||||
maintainers:
|
||||
- Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r8a774a1-usb3-phy # RZ/G2M
|
||||
- renesas,r8a774b1-usb3-phy # RZ/G2N
|
||||
- renesas,r8a7795-usb3-phy # R-Car H3
|
||||
- renesas,r8a7796-usb3-phy # R-Car M3-W
|
||||
- renesas,r8a77961-usb3-phy # R-Car M3-W+
|
||||
- renesas,r8a77965-usb3-phy # R-Car M3-N
|
||||
- const: renesas,rcar-gen3-usb3-phy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
# If you want to use the ssc, the clock-frequency of usb_extal
|
||||
# must not be 0.
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
items:
|
||||
- const: usb3-if # The funcional clock
|
||||
- const: usb3s_clk # The usb3's external clock
|
||||
- const: usb_extal # The usb2's external clock
|
||||
|
||||
'#phy-cells':
|
||||
# see phy-bindings.txt in the same directory
|
||||
const: 0
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
renesas,ssc-range:
|
||||
description: |
|
||||
Enable/disable spread spectrum clock (ssc). 0 or the property doesn't
|
||||
exist means disabling the ssc. The actual value will be -<value> ppm.
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- enum: [ 0, 4003, 4492, 4980 ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#phy-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
|
||||
#include <dt-bindings/power/r8a7795-sysc.h>
|
||||
|
||||
usb-phy@e65ee000 {
|
||||
compatible = "renesas,r8a7795-usb3-phy", "renesas,rcar-gen3-usb3-phy";
|
||||
reg = <0xe65ee000 0x90>;
|
||||
clocks = <&cpg CPG_MOD 328>, <&usb3s0_clk>, <&usb_extal>;
|
||||
clock-names = "usb3-if", "usb3s_clk", "usb_extal";
|
||||
#phy-cells = <0>;
|
||||
};
|
@ -3,12 +3,13 @@
|
||||
# Phy drivers for Amlogic platforms
|
||||
#
|
||||
config PHY_MESON8B_USB2
|
||||
tristate "Meson8, Meson8b and GXBB USB2 PHY driver"
|
||||
tristate "Meson8, Meson8b, Meson8m2 and GXBB USB2 PHY driver"
|
||||
default ARCH_MESON
|
||||
depends on OF && (ARCH_MESON || COMPILE_TEST)
|
||||
depends on USB_SUPPORT
|
||||
select USB_COMMON
|
||||
select GENERIC_PHY
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
Enable this to support the Meson USB2 PHYs found in Meson8,
|
||||
Meson8b and GXBB SoCs.
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -76,6 +78,17 @@
|
||||
#define REG_ADP_BC_ACA_PIN_FLOAT BIT(26)
|
||||
|
||||
#define REG_DBG_UART 0x10
|
||||
#define REG_DBG_UART_BYPASS_SEL BIT(0)
|
||||
#define REG_DBG_UART_BYPASS_DM_EN BIT(1)
|
||||
#define REG_DBG_UART_BYPASS_DP_EN BIT(2)
|
||||
#define REG_DBG_UART_BYPASS_DM_DATA BIT(3)
|
||||
#define REG_DBG_UART_BYPASS_DP_DATA BIT(4)
|
||||
#define REG_DBG_UART_FSV_MINUS BIT(5)
|
||||
#define REG_DBG_UART_FSV_PLUS BIT(6)
|
||||
#define REG_DBG_UART_FSV_BURN_IN_TEST BIT(7)
|
||||
#define REG_DBG_UART_LOOPBACK_EN_B BIT(8)
|
||||
#define REG_DBG_UART_SET_IDDQ BIT(9)
|
||||
#define REG_DBG_UART_ATE_RESET BIT(10)
|
||||
|
||||
#define REG_TEST 0x14
|
||||
#define REG_TEST_DATA_IN_MASK GENMASK(3, 0)
|
||||
@ -104,35 +117,30 @@
|
||||
#define RESET_COMPLETE_TIME 500
|
||||
#define ACA_ENABLE_COMPLETE_TIME 50
|
||||
|
||||
struct phy_meson8b_usb2_priv {
|
||||
void __iomem *regs;
|
||||
enum usb_dr_mode dr_mode;
|
||||
struct clk *clk_usb_general;
|
||||
struct clk *clk_usb;
|
||||
struct reset_control *reset;
|
||||
struct phy_meson8b_usb2_match_data {
|
||||
bool host_enable_aca;
|
||||
};
|
||||
|
||||
static u32 phy_meson8b_usb2_read(struct phy_meson8b_usb2_priv *phy_priv,
|
||||
u32 reg)
|
||||
{
|
||||
return readl(phy_priv->regs + reg);
|
||||
}
|
||||
struct phy_meson8b_usb2_priv {
|
||||
struct regmap *regmap;
|
||||
enum usb_dr_mode dr_mode;
|
||||
struct clk *clk_usb_general;
|
||||
struct clk *clk_usb;
|
||||
struct reset_control *reset;
|
||||
const struct phy_meson8b_usb2_match_data *match;
|
||||
};
|
||||
|
||||
static void phy_meson8b_usb2_mask_bits(struct phy_meson8b_usb2_priv *phy_priv,
|
||||
u32 reg, u32 mask, u32 value)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
data = phy_meson8b_usb2_read(phy_priv, reg);
|
||||
data &= ~mask;
|
||||
data |= (value & mask);
|
||||
|
||||
writel(data, phy_priv->regs + reg);
|
||||
}
|
||||
static const struct regmap_config phy_meson8b_usb2_regmap_conf = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.max_register = REG_TUNE,
|
||||
};
|
||||
|
||||
static int phy_meson8b_usb2_power_on(struct phy *phy)
|
||||
{
|
||||
struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
||||
if (!IS_ERR_OR_NULL(priv->reset)) {
|
||||
@ -156,38 +164,43 @@ static int phy_meson8b_usb2_power_on(struct phy *phy)
|
||||
return ret;
|
||||
}
|
||||
|
||||
phy_meson8b_usb2_mask_bits(priv, REG_CONFIG, REG_CONFIG_CLK_32k_ALTSEL,
|
||||
REG_CONFIG_CLK_32k_ALTSEL);
|
||||
regmap_update_bits(priv->regmap, REG_CONFIG, REG_CONFIG_CLK_32k_ALTSEL,
|
||||
REG_CONFIG_CLK_32k_ALTSEL);
|
||||
|
||||
phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_REF_CLK_SEL_MASK,
|
||||
0x2 << REG_CTRL_REF_CLK_SEL_SHIFT);
|
||||
regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_REF_CLK_SEL_MASK,
|
||||
0x2 << REG_CTRL_REF_CLK_SEL_SHIFT);
|
||||
|
||||
phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_FSEL_MASK,
|
||||
0x5 << REG_CTRL_FSEL_SHIFT);
|
||||
regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_FSEL_MASK,
|
||||
0x5 << REG_CTRL_FSEL_SHIFT);
|
||||
|
||||
/* reset the PHY */
|
||||
phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET,
|
||||
REG_CTRL_POWER_ON_RESET);
|
||||
regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET,
|
||||
REG_CTRL_POWER_ON_RESET);
|
||||
udelay(RESET_COMPLETE_TIME);
|
||||
phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET, 0);
|
||||
regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET, 0);
|
||||
udelay(RESET_COMPLETE_TIME);
|
||||
|
||||
phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_SOF_TOGGLE_OUT,
|
||||
REG_CTRL_SOF_TOGGLE_OUT);
|
||||
regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_SOF_TOGGLE_OUT,
|
||||
REG_CTRL_SOF_TOGGLE_OUT);
|
||||
|
||||
if (priv->dr_mode == USB_DR_MODE_HOST) {
|
||||
phy_meson8b_usb2_mask_bits(priv, REG_ADP_BC,
|
||||
regmap_update_bits(priv->regmap, REG_DBG_UART,
|
||||
REG_DBG_UART_SET_IDDQ, 0);
|
||||
|
||||
if (priv->match->host_enable_aca) {
|
||||
regmap_update_bits(priv->regmap, REG_ADP_BC,
|
||||
REG_ADP_BC_ACA_ENABLE,
|
||||
REG_ADP_BC_ACA_ENABLE);
|
||||
|
||||
udelay(ACA_ENABLE_COMPLETE_TIME);
|
||||
udelay(ACA_ENABLE_COMPLETE_TIME);
|
||||
|
||||
if (phy_meson8b_usb2_read(priv, REG_ADP_BC) &
|
||||
REG_ADP_BC_ACA_PIN_FLOAT) {
|
||||
dev_warn(&phy->dev, "USB ID detect failed!\n");
|
||||
clk_disable_unprepare(priv->clk_usb);
|
||||
clk_disable_unprepare(priv->clk_usb_general);
|
||||
return -EINVAL;
|
||||
regmap_read(priv->regmap, REG_ADP_BC, ®);
|
||||
if (reg & REG_ADP_BC_ACA_PIN_FLOAT) {
|
||||
dev_warn(&phy->dev, "USB ID detect failed!\n");
|
||||
clk_disable_unprepare(priv->clk_usb);
|
||||
clk_disable_unprepare(priv->clk_usb_general);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,6 +211,11 @@ static int phy_meson8b_usb2_power_off(struct phy *phy)
|
||||
{
|
||||
struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
|
||||
|
||||
if (priv->dr_mode == USB_DR_MODE_HOST)
|
||||
regmap_update_bits(priv->regmap, REG_DBG_UART,
|
||||
REG_DBG_UART_SET_IDDQ,
|
||||
REG_DBG_UART_SET_IDDQ);
|
||||
|
||||
clk_disable_unprepare(priv->clk_usb);
|
||||
clk_disable_unprepare(priv->clk_usb_general);
|
||||
|
||||
@ -213,18 +231,26 @@ static const struct phy_ops phy_meson8b_usb2_ops = {
|
||||
static int phy_meson8b_usb2_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct phy_meson8b_usb2_priv *priv;
|
||||
struct resource *res;
|
||||
struct phy *phy;
|
||||
struct phy_provider *phy_provider;
|
||||
void __iomem *base;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(priv->regs))
|
||||
return PTR_ERR(priv->regs);
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
priv->match = device_get_match_data(&pdev->dev);
|
||||
if (!priv->match)
|
||||
return -ENODEV;
|
||||
|
||||
priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
|
||||
&phy_meson8b_usb2_regmap_conf);
|
||||
if (IS_ERR(priv->regmap))
|
||||
return PTR_ERR(priv->regmap);
|
||||
|
||||
priv->clk_usb_general = devm_clk_get(&pdev->dev, "usb_general");
|
||||
if (IS_ERR(priv->clk_usb_general))
|
||||
@ -259,11 +285,32 @@ static int phy_meson8b_usb2_probe(struct platform_device *pdev)
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
}
|
||||
|
||||
static const struct phy_meson8b_usb2_match_data phy_meson8_usb2_match_data = {
|
||||
.host_enable_aca = false,
|
||||
};
|
||||
|
||||
static const struct phy_meson8b_usb2_match_data phy_meson8b_usb2_match_data = {
|
||||
.host_enable_aca = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id phy_meson8b_usb2_of_match[] = {
|
||||
{ .compatible = "amlogic,meson8-usb2-phy", },
|
||||
{ .compatible = "amlogic,meson8b-usb2-phy", },
|
||||
{ .compatible = "amlogic,meson-gxbb-usb2-phy", },
|
||||
{ },
|
||||
{
|
||||
.compatible = "amlogic,meson8-usb2-phy",
|
||||
.data = &phy_meson8_usb2_match_data
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson8b-usb2-phy",
|
||||
.data = &phy_meson8b_usb2_match_data
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson8m2-usb2-phy",
|
||||
.data = &phy_meson8b_usb2_match_data
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson-gxbb-usb2-phy",
|
||||
.data = &phy_meson8b_usb2_match_data
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, phy_meson8b_usb2_of_match);
|
||||
|
||||
@ -277,5 +324,5 @@ static struct platform_driver phy_meson8b_usb2_driver = {
|
||||
module_platform_driver(phy_meson8b_usb2_driver);
|
||||
|
||||
MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
|
||||
MODULE_DESCRIPTION("Meson8, Meson8b and GXBB USB2 PHY driver");
|
||||
MODULE_DESCRIPTION("Meson8, Meson8b, Meson8m2 and GXBB USB2 PHY driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -279,7 +279,7 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct phy_ops ops = {
|
||||
static const struct phy_ops ops = {
|
||||
.init = ns2_drd_phy_init,
|
||||
.power_on = ns2_drd_phy_poweron,
|
||||
.power_off = ns2_drd_phy_poweroff,
|
||||
|
@ -16,8 +16,6 @@ enum bcm_usb_phy_version {
|
||||
};
|
||||
|
||||
enum bcm_usb_phy_reg {
|
||||
PLL_NDIV_FRAC,
|
||||
PLL_NDIV_INT,
|
||||
PLL_CTRL,
|
||||
PHY_CTRL,
|
||||
PHY_PLL_CTRL,
|
||||
@ -31,18 +29,11 @@ static const u8 bcm_usb_combo_phy_ss[] = {
|
||||
};
|
||||
|
||||
static const u8 bcm_usb_combo_phy_hs[] = {
|
||||
[PLL_NDIV_FRAC] = 0x04,
|
||||
[PLL_NDIV_INT] = 0x08,
|
||||
[PLL_CTRL] = 0x0c,
|
||||
[PHY_CTRL] = 0x10,
|
||||
};
|
||||
|
||||
#define HSPLL_NDIV_INT_VAL 0x13
|
||||
#define HSPLL_NDIV_FRAC_VAL 0x1005
|
||||
|
||||
static const u8 bcm_usb_hs_phy[] = {
|
||||
[PLL_NDIV_FRAC] = 0x0,
|
||||
[PLL_NDIV_INT] = 0x4,
|
||||
[PLL_CTRL] = 0x8,
|
||||
[PHY_CTRL] = 0xc,
|
||||
};
|
||||
@ -52,7 +43,6 @@ enum pll_ctrl_bits {
|
||||
SSPLL_SUSPEND_EN,
|
||||
PLL_SEQ_START,
|
||||
PLL_LOCK,
|
||||
PLL_PDIV,
|
||||
};
|
||||
|
||||
static const u8 u3pll_ctrl[] = {
|
||||
@ -66,29 +56,17 @@ static const u8 u3pll_ctrl[] = {
|
||||
#define HSPLL_PDIV_VAL 0x1
|
||||
|
||||
static const u8 u2pll_ctrl[] = {
|
||||
[PLL_PDIV] = 1,
|
||||
[PLL_RESETB] = 5,
|
||||
[PLL_LOCK] = 6,
|
||||
};
|
||||
|
||||
enum bcm_usb_phy_ctrl_bits {
|
||||
CORERDY,
|
||||
AFE_LDO_PWRDWNB,
|
||||
AFE_PLL_PWRDWNB,
|
||||
AFE_BG_PWRDWNB,
|
||||
PHY_ISO,
|
||||
PHY_RESETB,
|
||||
PHY_PCTL,
|
||||
};
|
||||
|
||||
#define PHY_PCTL_MASK 0xffff
|
||||
/*
|
||||
* 0x0806 of PCTL_VAL has below bits set
|
||||
* BIT-8 : refclk divider 1
|
||||
* BIT-3:2: device mode; mode is not effect
|
||||
* BIT-1: soft reset active low
|
||||
*/
|
||||
#define HSPHY_PCTL_VAL 0x0806
|
||||
#define SSPHY_PCTL_VAL 0x0006
|
||||
|
||||
static const u8 u3phy_ctrl[] = {
|
||||
@ -98,10 +76,6 @@ static const u8 u3phy_ctrl[] = {
|
||||
|
||||
static const u8 u2phy_ctrl[] = {
|
||||
[CORERDY] = 0,
|
||||
[AFE_LDO_PWRDWNB] = 1,
|
||||
[AFE_PLL_PWRDWNB] = 2,
|
||||
[AFE_BG_PWRDWNB] = 3,
|
||||
[PHY_ISO] = 4,
|
||||
[PHY_RESETB] = 5,
|
||||
[PHY_PCTL] = 6,
|
||||
};
|
||||
@ -186,38 +160,13 @@ static int bcm_usb_hs_phy_init(struct bcm_usb_phy_cfg *phy_cfg)
|
||||
int ret = 0;
|
||||
void __iomem *regs = phy_cfg->regs;
|
||||
const u8 *offset;
|
||||
u32 rd_data;
|
||||
|
||||
offset = phy_cfg->offset;
|
||||
|
||||
writel(HSPLL_NDIV_INT_VAL, regs + offset[PLL_NDIV_INT]);
|
||||
writel(HSPLL_NDIV_FRAC_VAL, regs + offset[PLL_NDIV_FRAC]);
|
||||
|
||||
rd_data = readl(regs + offset[PLL_CTRL]);
|
||||
rd_data &= ~(HSPLL_PDIV_MASK << u2pll_ctrl[PLL_PDIV]);
|
||||
rd_data |= (HSPLL_PDIV_VAL << u2pll_ctrl[PLL_PDIV]);
|
||||
writel(rd_data, regs + offset[PLL_CTRL]);
|
||||
|
||||
/* Set Core Ready high */
|
||||
bcm_usb_reg32_setbits(regs + offset[PHY_CTRL],
|
||||
BIT(u2phy_ctrl[CORERDY]));
|
||||
|
||||
/* Maximum timeout for Core Ready done */
|
||||
msleep(30);
|
||||
|
||||
bcm_usb_reg32_clrbits(regs + offset[PLL_CTRL],
|
||||
BIT(u2pll_ctrl[PLL_RESETB]));
|
||||
bcm_usb_reg32_setbits(regs + offset[PLL_CTRL],
|
||||
BIT(u2pll_ctrl[PLL_RESETB]));
|
||||
bcm_usb_reg32_setbits(regs + offset[PHY_CTRL],
|
||||
BIT(u2phy_ctrl[PHY_RESETB]));
|
||||
|
||||
|
||||
rd_data = readl(regs + offset[PHY_CTRL]);
|
||||
rd_data &= ~(PHY_PCTL_MASK << u2phy_ctrl[PHY_PCTL]);
|
||||
rd_data |= (HSPHY_PCTL_VAL << u2phy_ctrl[PHY_PCTL]);
|
||||
writel(rd_data, regs + offset[PHY_CTRL]);
|
||||
|
||||
/* Maximum timeout for PLL reset done */
|
||||
msleep(30);
|
||||
|
||||
ret = bcm_usb_pll_lock_check(regs + offset[PLL_CTRL],
|
||||
BIT(u2pll_ctrl[PLL_LOCK]));
|
||||
@ -256,7 +205,7 @@ static int bcm_usb_phy_init(struct phy *phy)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct phy_ops sr_phy_ops = {
|
||||
static const struct phy_ops sr_phy_ops = {
|
||||
.init = bcm_usb_phy_init,
|
||||
.reset = bcm_usb_phy_reset,
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -39,14 +39,14 @@ struct match_chip_info {
|
||||
u8 optional_reg;
|
||||
};
|
||||
|
||||
static struct value_to_name_map brcm_dr_mode_to_name[] = {
|
||||
static const struct value_to_name_map brcm_dr_mode_to_name[] = {
|
||||
{ USB_CTLR_MODE_HOST, "host" },
|
||||
{ USB_CTLR_MODE_DEVICE, "peripheral" },
|
||||
{ USB_CTLR_MODE_DRD, "drd" },
|
||||
{ USB_CTLR_MODE_TYPEC_PD, "typec-pd" }
|
||||
};
|
||||
|
||||
static struct value_to_name_map brcm_dual_mode_to_name[] = {
|
||||
static const struct value_to_name_map brcm_dual_mode_to_name[] = {
|
||||
{ 0, "host" },
|
||||
{ 1, "device" },
|
||||
{ 2, "auto" },
|
||||
@ -138,7 +138,7 @@ static int brcm_usb_phy_exit(struct phy *gphy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy_ops brcm_usb_phy_ops = {
|
||||
static const struct phy_ops brcm_usb_phy_ops = {
|
||||
.init = brcm_usb_phy_init,
|
||||
.exit = brcm_usb_phy_exit,
|
||||
.owner = THIS_MODULE,
|
||||
@ -170,7 +170,7 @@ static struct phy *brcm_usb_phy_xlate(struct device *dev,
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static int name_to_value(struct value_to_name_map *table, int count,
|
||||
static int name_to_value(const struct value_to_name_map *table, int count,
|
||||
const char *name, int *value)
|
||||
{
|
||||
int x;
|
||||
@ -185,7 +185,7 @@ static int name_to_value(struct value_to_name_map *table, int count,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const char *value_to_name(struct value_to_name_map *table, int count,
|
||||
static const char *value_to_name(const struct value_to_name_map *table, int count,
|
||||
int value)
|
||||
{
|
||||
if (value >= count)
|
||||
@ -252,7 +252,7 @@ static const struct attribute_group brcm_usb_phy_group = {
|
||||
.attrs = brcm_usb_phy_attrs,
|
||||
};
|
||||
|
||||
static struct match_chip_info chip_info_7216 = {
|
||||
static const struct match_chip_info chip_info_7216 = {
|
||||
.init_func = &brcm_usb_dvr_init_7216,
|
||||
.required_regs = {
|
||||
BRCM_REGS_CTRL,
|
||||
@ -262,7 +262,7 @@ static struct match_chip_info chip_info_7216 = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct match_chip_info chip_info_7211b0 = {
|
||||
static const struct match_chip_info chip_info_7211b0 = {
|
||||
.init_func = &brcm_usb_dvr_init_7211b0,
|
||||
.required_regs = {
|
||||
BRCM_REGS_CTRL,
|
||||
@ -275,7 +275,7 @@ static struct match_chip_info chip_info_7211b0 = {
|
||||
.optional_reg = BRCM_REGS_BDC_EC,
|
||||
};
|
||||
|
||||
static struct match_chip_info chip_info_7445 = {
|
||||
static const struct match_chip_info chip_info_7445 = {
|
||||
.init_func = &brcm_usb_dvr_init_7445,
|
||||
.required_regs = {
|
||||
BRCM_REGS_CTRL,
|
||||
|
@ -27,3 +27,12 @@ config PHY_CADENCE_SIERRA
|
||||
select GENERIC_PHY
|
||||
help
|
||||
Enable this to support the Cadence Sierra PHY driver
|
||||
|
||||
config PHY_CADENCE_SALVO
|
||||
tristate "Cadence Salvo PHY Driver"
|
||||
depends on OF && HAS_IOMEM
|
||||
select GENERIC_PHY
|
||||
help
|
||||
Enable this to support the Cadence SALVO PHY driver,
|
||||
this PHY is a legacy PHY, and only are used for USB3
|
||||
and USB2.
|
||||
|
@ -2,3 +2,4 @@
|
||||
obj-$(CONFIG_PHY_CADENCE_TORRENT) += phy-cadence-torrent.o
|
||||
obj-$(CONFIG_PHY_CADENCE_DPHY) += cdns-dphy.o
|
||||
obj-$(CONFIG_PHY_CADENCE_SIERRA) += phy-cadence-sierra.o
|
||||
obj-$(CONFIG_PHY_CADENCE_SALVO) += phy-cadence-salvo.o
|
||||
|
325
drivers/phy/cadence/phy-cadence-salvo.c
Normal file
325
drivers/phy/cadence/phy-cadence-salvo.c
Normal file
@ -0,0 +1,325 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Salvo PHY is a 28nm PHY, it is a legacy PHY, and only
|
||||
* for USB3 and USB2.
|
||||
*
|
||||
* Copyright (c) 2019-2020 NXP
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
/* PHY register definition */
|
||||
#define PHY_PMA_CMN_CTRL1 0xC800
|
||||
#define TB_ADDR_CMN_DIAG_HSCLK_SEL 0x01e0
|
||||
#define TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR 0x0084
|
||||
#define TB_ADDR_CMN_PLL0_VCOCAL_ITER_TMR 0x0085
|
||||
#define TB_ADDR_CMN_PLL0_INTDIV 0x0094
|
||||
#define TB_ADDR_CMN_PLL0_FRACDIV 0x0095
|
||||
#define TB_ADDR_CMN_PLL0_HIGH_THR 0x0096
|
||||
#define TB_ADDR_CMN_PLL0_SS_CTRL1 0x0098
|
||||
#define TB_ADDR_CMN_PLL0_SS_CTRL2 0x0099
|
||||
#define TB_ADDR_CMN_PLL0_DSM_DIAG 0x0097
|
||||
#define TB_ADDR_CMN_DIAG_PLL0_OVRD 0x01c2
|
||||
#define TB_ADDR_CMN_DIAG_PLL0_FBH_OVRD 0x01c0
|
||||
#define TB_ADDR_CMN_DIAG_PLL0_FBL_OVRD 0x01c1
|
||||
#define TB_ADDR_CMN_DIAG_PLL0_V2I_TUNE 0x01C5
|
||||
#define TB_ADDR_CMN_DIAG_PLL0_CP_TUNE 0x01C6
|
||||
#define TB_ADDR_CMN_DIAG_PLL0_LF_PROG 0x01C7
|
||||
#define TB_ADDR_CMN_DIAG_PLL0_TEST_MODE 0x01c4
|
||||
#define TB_ADDR_CMN_PSM_CLK_CTRL 0x0061
|
||||
#define TB_ADDR_XCVR_DIAG_RX_LANE_CAL_RST_TMR 0x40ea
|
||||
#define TB_ADDR_XCVR_PSM_RCTRL 0x4001
|
||||
#define TB_ADDR_TX_PSC_A0 0x4100
|
||||
#define TB_ADDR_TX_PSC_A1 0x4101
|
||||
#define TB_ADDR_TX_PSC_A2 0x4102
|
||||
#define TB_ADDR_TX_PSC_A3 0x4103
|
||||
#define TB_ADDR_TX_DIAG_ECTRL_OVRD 0x41f5
|
||||
#define TB_ADDR_TX_PSC_CAL 0x4106
|
||||
#define TB_ADDR_TX_PSC_RDY 0x4107
|
||||
#define TB_ADDR_RX_PSC_A0 0x8000
|
||||
#define TB_ADDR_RX_PSC_A1 0x8001
|
||||
#define TB_ADDR_RX_PSC_A2 0x8002
|
||||
#define TB_ADDR_RX_PSC_A3 0x8003
|
||||
#define TB_ADDR_RX_PSC_CAL 0x8006
|
||||
#define TB_ADDR_RX_PSC_RDY 0x8007
|
||||
#define TB_ADDR_TX_TXCC_MGNLS_MULT_000 0x4058
|
||||
#define TB_ADDR_TX_DIAG_BGREF_PREDRV_DELAY 0x41e7
|
||||
#define TB_ADDR_RX_SLC_CU_ITER_TMR 0x80e3
|
||||
#define TB_ADDR_RX_SIGDET_HL_FILT_TMR 0x8090
|
||||
#define TB_ADDR_RX_SAMP_DAC_CTRL 0x8058
|
||||
#define TB_ADDR_RX_DIAG_SIGDET_TUNE 0x81dc
|
||||
#define TB_ADDR_RX_DIAG_LFPSDET_TUNE2 0x81df
|
||||
#define TB_ADDR_RX_DIAG_BS_TM 0x81f5
|
||||
#define TB_ADDR_RX_DIAG_DFE_CTRL1 0x81d3
|
||||
#define TB_ADDR_RX_DIAG_ILL_IQE_TRIM4 0x81c7
|
||||
#define TB_ADDR_RX_DIAG_ILL_E_TRIM0 0x81c2
|
||||
#define TB_ADDR_RX_DIAG_ILL_IQ_TRIM0 0x81c1
|
||||
#define TB_ADDR_RX_DIAG_ILL_IQE_TRIM6 0x81c9
|
||||
#define TB_ADDR_RX_DIAG_RXFE_TM3 0x81f8
|
||||
#define TB_ADDR_RX_DIAG_RXFE_TM4 0x81f9
|
||||
#define TB_ADDR_RX_DIAG_LFPSDET_TUNE 0x81dd
|
||||
#define TB_ADDR_RX_DIAG_DFE_CTRL3 0x81d5
|
||||
#define TB_ADDR_RX_DIAG_SC2C_DELAY 0x81e1
|
||||
#define TB_ADDR_RX_REE_VGA_GAIN_NODFE 0x81bf
|
||||
#define TB_ADDR_XCVR_PSM_CAL_TMR 0x4002
|
||||
#define TB_ADDR_XCVR_PSM_A0BYP_TMR 0x4004
|
||||
#define TB_ADDR_XCVR_PSM_A0IN_TMR 0x4003
|
||||
#define TB_ADDR_XCVR_PSM_A1IN_TMR 0x4005
|
||||
#define TB_ADDR_XCVR_PSM_A2IN_TMR 0x4006
|
||||
#define TB_ADDR_XCVR_PSM_A3IN_TMR 0x4007
|
||||
#define TB_ADDR_XCVR_PSM_A4IN_TMR 0x4008
|
||||
#define TB_ADDR_XCVR_PSM_A5IN_TMR 0x4009
|
||||
#define TB_ADDR_XCVR_PSM_A0OUT_TMR 0x400a
|
||||
#define TB_ADDR_XCVR_PSM_A1OUT_TMR 0x400b
|
||||
#define TB_ADDR_XCVR_PSM_A2OUT_TMR 0x400c
|
||||
#define TB_ADDR_XCVR_PSM_A3OUT_TMR 0x400d
|
||||
#define TB_ADDR_XCVR_PSM_A4OUT_TMR 0x400e
|
||||
#define TB_ADDR_XCVR_PSM_A5OUT_TMR 0x400f
|
||||
#define TB_ADDR_TX_RCVDET_EN_TMR 0x4122
|
||||
#define TB_ADDR_TX_RCVDET_ST_TMR 0x4123
|
||||
#define TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR 0x40f2
|
||||
#define TB_ADDR_TX_RCVDETSC_CTRL 0x4124
|
||||
|
||||
/* TB_ADDR_TX_RCVDETSC_CTRL */
|
||||
#define RXDET_IN_P3_32KHZ BIT(1)
|
||||
|
||||
struct cdns_reg_pairs {
|
||||
u16 val;
|
||||
u32 off;
|
||||
};
|
||||
|
||||
struct cdns_salvo_data {
|
||||
u8 reg_offset_shift;
|
||||
struct cdns_reg_pairs *init_sequence_val;
|
||||
u8 init_sequence_length;
|
||||
};
|
||||
|
||||
struct cdns_salvo_phy {
|
||||
struct phy *phy;
|
||||
struct clk *clk;
|
||||
void __iomem *base;
|
||||
struct cdns_salvo_data *data;
|
||||
};
|
||||
|
||||
static const struct of_device_id cdns_salvo_phy_of_match[];
|
||||
static u16 cdns_salvo_read(struct cdns_salvo_phy *salvo_phy, u32 reg)
|
||||
{
|
||||
return (u16)readl(salvo_phy->base +
|
||||
reg * (1 << salvo_phy->data->reg_offset_shift));
|
||||
}
|
||||
|
||||
static void cdns_salvo_write(struct cdns_salvo_phy *salvo_phy,
|
||||
u32 reg, u16 val)
|
||||
{
|
||||
writel(val, salvo_phy->base +
|
||||
reg * (1 << salvo_phy->data->reg_offset_shift));
|
||||
}
|
||||
|
||||
/*
|
||||
* Below bringup sequence pair are from Cadence PHY's User Guide
|
||||
* and NXP platform tuning results.
|
||||
*/
|
||||
static struct cdns_reg_pairs cdns_nxp_sequence_pair[] = {
|
||||
{0x0830, PHY_PMA_CMN_CTRL1},
|
||||
{0x0010, TB_ADDR_CMN_DIAG_HSCLK_SEL},
|
||||
{0x00f0, TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR},
|
||||
{0x0018, TB_ADDR_CMN_PLL0_VCOCAL_ITER_TMR},
|
||||
{0x00d0, TB_ADDR_CMN_PLL0_INTDIV},
|
||||
{0x4aaa, TB_ADDR_CMN_PLL0_FRACDIV},
|
||||
{0x0034, TB_ADDR_CMN_PLL0_HIGH_THR},
|
||||
{0x01ee, TB_ADDR_CMN_PLL0_SS_CTRL1},
|
||||
{0x7f03, TB_ADDR_CMN_PLL0_SS_CTRL2},
|
||||
{0x0020, TB_ADDR_CMN_PLL0_DSM_DIAG},
|
||||
{0x0000, TB_ADDR_CMN_DIAG_PLL0_OVRD},
|
||||
{0x0000, TB_ADDR_CMN_DIAG_PLL0_FBH_OVRD},
|
||||
{0x0000, TB_ADDR_CMN_DIAG_PLL0_FBL_OVRD},
|
||||
{0x0007, TB_ADDR_CMN_DIAG_PLL0_V2I_TUNE},
|
||||
{0x0027, TB_ADDR_CMN_DIAG_PLL0_CP_TUNE},
|
||||
{0x0008, TB_ADDR_CMN_DIAG_PLL0_LF_PROG},
|
||||
{0x0022, TB_ADDR_CMN_DIAG_PLL0_TEST_MODE},
|
||||
{0x000a, TB_ADDR_CMN_PSM_CLK_CTRL},
|
||||
{0x0139, TB_ADDR_XCVR_DIAG_RX_LANE_CAL_RST_TMR},
|
||||
{0xbefc, TB_ADDR_XCVR_PSM_RCTRL},
|
||||
|
||||
{0x7799, TB_ADDR_TX_PSC_A0},
|
||||
{0x7798, TB_ADDR_TX_PSC_A1},
|
||||
{0x509b, TB_ADDR_TX_PSC_A2},
|
||||
{0x0003, TB_ADDR_TX_DIAG_ECTRL_OVRD},
|
||||
{0x509b, TB_ADDR_TX_PSC_A3},
|
||||
{0x2090, TB_ADDR_TX_PSC_CAL},
|
||||
{0x2090, TB_ADDR_TX_PSC_RDY},
|
||||
|
||||
{0xA6FD, TB_ADDR_RX_PSC_A0},
|
||||
{0xA6FD, TB_ADDR_RX_PSC_A1},
|
||||
{0xA410, TB_ADDR_RX_PSC_A2},
|
||||
{0x2410, TB_ADDR_RX_PSC_A3},
|
||||
|
||||
{0x23FF, TB_ADDR_RX_PSC_CAL},
|
||||
{0x2010, TB_ADDR_RX_PSC_RDY},
|
||||
|
||||
{0x0020, TB_ADDR_TX_TXCC_MGNLS_MULT_000},
|
||||
{0x00ff, TB_ADDR_TX_DIAG_BGREF_PREDRV_DELAY},
|
||||
{0x0002, TB_ADDR_RX_SLC_CU_ITER_TMR},
|
||||
{0x0013, TB_ADDR_RX_SIGDET_HL_FILT_TMR},
|
||||
{0x0000, TB_ADDR_RX_SAMP_DAC_CTRL},
|
||||
{0x1004, TB_ADDR_RX_DIAG_SIGDET_TUNE},
|
||||
{0x4041, TB_ADDR_RX_DIAG_LFPSDET_TUNE2},
|
||||
{0x0480, TB_ADDR_RX_DIAG_BS_TM},
|
||||
{0x8006, TB_ADDR_RX_DIAG_DFE_CTRL1},
|
||||
{0x003f, TB_ADDR_RX_DIAG_ILL_IQE_TRIM4},
|
||||
{0x543f, TB_ADDR_RX_DIAG_ILL_E_TRIM0},
|
||||
{0x543f, TB_ADDR_RX_DIAG_ILL_IQ_TRIM0},
|
||||
{0x0000, TB_ADDR_RX_DIAG_ILL_IQE_TRIM6},
|
||||
{0x8000, TB_ADDR_RX_DIAG_RXFE_TM3},
|
||||
{0x0003, TB_ADDR_RX_DIAG_RXFE_TM4},
|
||||
{0x2408, TB_ADDR_RX_DIAG_LFPSDET_TUNE},
|
||||
{0x05ca, TB_ADDR_RX_DIAG_DFE_CTRL3},
|
||||
{0x0258, TB_ADDR_RX_DIAG_SC2C_DELAY},
|
||||
{0x1fff, TB_ADDR_RX_REE_VGA_GAIN_NODFE},
|
||||
|
||||
{0x02c6, TB_ADDR_XCVR_PSM_CAL_TMR},
|
||||
{0x0002, TB_ADDR_XCVR_PSM_A0BYP_TMR},
|
||||
{0x02c6, TB_ADDR_XCVR_PSM_A0IN_TMR},
|
||||
{0x0010, TB_ADDR_XCVR_PSM_A1IN_TMR},
|
||||
{0x0010, TB_ADDR_XCVR_PSM_A2IN_TMR},
|
||||
{0x0010, TB_ADDR_XCVR_PSM_A3IN_TMR},
|
||||
{0x0010, TB_ADDR_XCVR_PSM_A4IN_TMR},
|
||||
{0x0010, TB_ADDR_XCVR_PSM_A5IN_TMR},
|
||||
|
||||
{0x0002, TB_ADDR_XCVR_PSM_A0OUT_TMR},
|
||||
{0x0002, TB_ADDR_XCVR_PSM_A1OUT_TMR},
|
||||
{0x0002, TB_ADDR_XCVR_PSM_A2OUT_TMR},
|
||||
{0x0002, TB_ADDR_XCVR_PSM_A3OUT_TMR},
|
||||
{0x0002, TB_ADDR_XCVR_PSM_A4OUT_TMR},
|
||||
{0x0002, TB_ADDR_XCVR_PSM_A5OUT_TMR},
|
||||
/* Change rx detect parameter */
|
||||
{0x0960, TB_ADDR_TX_RCVDET_EN_TMR},
|
||||
{0x01e0, TB_ADDR_TX_RCVDET_ST_TMR},
|
||||
{0x0090, TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR},
|
||||
};
|
||||
|
||||
static int cdns_salvo_phy_init(struct phy *phy)
|
||||
{
|
||||
struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy);
|
||||
struct cdns_salvo_data *data = salvo_phy->data;
|
||||
int ret, i;
|
||||
u16 value;
|
||||
|
||||
ret = clk_prepare_enable(salvo_phy->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < data->init_sequence_length; i++) {
|
||||
struct cdns_reg_pairs *reg_pair = data->init_sequence_val + i;
|
||||
|
||||
cdns_salvo_write(salvo_phy, reg_pair->off, reg_pair->val);
|
||||
}
|
||||
|
||||
/* RXDET_IN_P3_32KHZ, Receiver detect slow clock enable */
|
||||
value = cdns_salvo_read(salvo_phy, TB_ADDR_TX_RCVDETSC_CTRL);
|
||||
value |= RXDET_IN_P3_32KHZ;
|
||||
cdns_salvo_write(salvo_phy, TB_ADDR_TX_RCVDETSC_CTRL,
|
||||
RXDET_IN_P3_32KHZ);
|
||||
|
||||
udelay(10);
|
||||
|
||||
clk_disable_unprepare(salvo_phy->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cdns_salvo_phy_power_on(struct phy *phy)
|
||||
{
|
||||
struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy);
|
||||
|
||||
return clk_prepare_enable(salvo_phy->clk);
|
||||
}
|
||||
|
||||
static int cdns_salvo_phy_power_off(struct phy *phy)
|
||||
{
|
||||
struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy);
|
||||
|
||||
clk_disable_unprepare(salvo_phy->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy_ops cdns_salvo_phy_ops = {
|
||||
.init = cdns_salvo_phy_init,
|
||||
.power_on = cdns_salvo_phy_power_on,
|
||||
.power_off = cdns_salvo_phy_power_off,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int cdns_salvo_phy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct phy_provider *phy_provider;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct cdns_salvo_phy *salvo_phy;
|
||||
struct resource *res;
|
||||
const struct of_device_id *match;
|
||||
struct cdns_salvo_data *data;
|
||||
|
||||
match = of_match_device(cdns_salvo_phy_of_match, dev);
|
||||
if (!match)
|
||||
return -EINVAL;
|
||||
|
||||
data = (struct cdns_salvo_data *)match->data;
|
||||
salvo_phy = devm_kzalloc(dev, sizeof(*salvo_phy), GFP_KERNEL);
|
||||
if (!salvo_phy)
|
||||
return -ENOMEM;
|
||||
|
||||
salvo_phy->data = data;
|
||||
salvo_phy->clk = devm_clk_get_optional(dev, "salvo_phy_clk");
|
||||
if (IS_ERR(salvo_phy->clk))
|
||||
return PTR_ERR(salvo_phy->clk);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
salvo_phy->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(salvo_phy->base))
|
||||
return PTR_ERR(salvo_phy->base);
|
||||
|
||||
salvo_phy->phy = devm_phy_create(dev, NULL, &cdns_salvo_phy_ops);
|
||||
if (IS_ERR(salvo_phy->phy))
|
||||
return PTR_ERR(salvo_phy->phy);
|
||||
|
||||
phy_set_drvdata(salvo_phy->phy, salvo_phy);
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
}
|
||||
|
||||
static const struct cdns_salvo_data cdns_nxp_salvo_data = {
|
||||
2,
|
||||
cdns_nxp_sequence_pair,
|
||||
ARRAY_SIZE(cdns_nxp_sequence_pair),
|
||||
};
|
||||
|
||||
static const struct of_device_id cdns_salvo_phy_of_match[] = {
|
||||
{
|
||||
.compatible = "nxp,salvo-phy",
|
||||
.data = &cdns_nxp_salvo_data,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cdns_salvo_phy_of_match);
|
||||
|
||||
static struct platform_driver cdns_salvo_phy_driver = {
|
||||
.probe = cdns_salvo_phy_probe,
|
||||
.driver = {
|
||||
.name = "cdns-salvo-phy",
|
||||
.of_match_table = cdns_salvo_phy_of_match,
|
||||
}
|
||||
};
|
||||
module_platform_driver(cdns_salvo_phy_driver);
|
||||
|
||||
MODULE_AUTHOR("Peter Chen <peter.chen@nxp.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Cadence SALVO PHY Driver");
|
@ -685,10 +685,10 @@ static struct cdns_reg_pairs cdns_usb_cmn_regs_ext_ssc[] = {
|
||||
static struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = {
|
||||
{0xFE0A, SIERRA_DET_STANDEC_A_PREG},
|
||||
{0x000F, SIERRA_DET_STANDEC_B_PREG},
|
||||
{0x00A5, SIERRA_DET_STANDEC_C_PREG},
|
||||
{0x55A5, SIERRA_DET_STANDEC_C_PREG},
|
||||
{0x69ad, SIERRA_DET_STANDEC_D_PREG},
|
||||
{0x0241, SIERRA_DET_STANDEC_E_PREG},
|
||||
{0x0010, SIERRA_PSM_LANECAL_DLY_A1_RESETS_PREG},
|
||||
{0x0110, SIERRA_PSM_LANECAL_DLY_A1_RESETS_PREG},
|
||||
{0x0014, SIERRA_PSM_A0IN_TMR_PREG},
|
||||
{0xCF00, SIERRA_PSM_DIAG_PREG},
|
||||
{0x001F, SIERRA_PSC_TX_A0_PREG},
|
||||
@ -696,7 +696,7 @@ static struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = {
|
||||
{0x0003, SIERRA_PSC_TX_A2_PREG},
|
||||
{0x0003, SIERRA_PSC_TX_A3_PREG},
|
||||
{0x0FFF, SIERRA_PSC_RX_A0_PREG},
|
||||
{0x0619, SIERRA_PSC_RX_A1_PREG},
|
||||
{0x0003, SIERRA_PSC_RX_A1_PREG},
|
||||
{0x0003, SIERRA_PSC_RX_A2_PREG},
|
||||
{0x0001, SIERRA_PSC_RX_A3_PREG},
|
||||
{0x0001, SIERRA_PLLCTRL_SUBRATE_PREG},
|
||||
@ -705,19 +705,19 @@ static struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = {
|
||||
{0x00CA, SIERRA_CLKPATH_BIASTRIM_PREG},
|
||||
{0x2512, SIERRA_DFE_BIASTRIM_PREG},
|
||||
{0x0000, SIERRA_DRVCTRL_ATTEN_PREG},
|
||||
{0x873E, SIERRA_CLKPATHCTRL_TMR_PREG},
|
||||
{0x03CF, SIERRA_RX_CREQ_FLTR_A_MODE1_PREG},
|
||||
{0x01CE, SIERRA_RX_CREQ_FLTR_A_MODE0_PREG},
|
||||
{0x823E, SIERRA_CLKPATHCTRL_TMR_PREG},
|
||||
{0x078F, SIERRA_RX_CREQ_FLTR_A_MODE1_PREG},
|
||||
{0x078F, SIERRA_RX_CREQ_FLTR_A_MODE0_PREG},
|
||||
{0x7B3C, SIERRA_CREQ_CCLKDET_MODE01_PREG},
|
||||
{0x033F, SIERRA_RX_CTLE_MAINTENANCE_PREG},
|
||||
{0x023C, SIERRA_RX_CTLE_MAINTENANCE_PREG},
|
||||
{0x3232, SIERRA_CREQ_FSMCLK_SEL_PREG},
|
||||
{0x0000, SIERRA_CREQ_EQ_CTRL_PREG},
|
||||
{0x8000, SIERRA_CREQ_SPARE_PREG},
|
||||
{0x0000, SIERRA_CREQ_SPARE_PREG},
|
||||
{0xCC44, SIERRA_CREQ_EQ_OPEN_EYE_THRESH_PREG},
|
||||
{0x8453, SIERRA_CTLELUT_CTRL_PREG},
|
||||
{0x4110, SIERRA_DFE_ECMP_RATESEL_PREG},
|
||||
{0x4110, SIERRA_DFE_SMP_RATESEL_PREG},
|
||||
{0x0002, SIERRA_DEQ_PHALIGN_CTRL},
|
||||
{0x8452, SIERRA_CTLELUT_CTRL_PREG},
|
||||
{0x4121, SIERRA_DFE_ECMP_RATESEL_PREG},
|
||||
{0x4121, SIERRA_DFE_SMP_RATESEL_PREG},
|
||||
{0x0003, SIERRA_DEQ_PHALIGN_CTRL},
|
||||
{0x3200, SIERRA_DEQ_CONCUR_CTRL1_PREG},
|
||||
{0x5064, SIERRA_DEQ_CONCUR_CTRL2_PREG},
|
||||
{0x0030, SIERRA_DEQ_EPIPWR_CTRL2_PREG},
|
||||
@ -725,7 +725,7 @@ static struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = {
|
||||
{0x5A5A, SIERRA_DEQ_ERRCMP_CTRL_PREG},
|
||||
{0x02F5, SIERRA_DEQ_OFFSET_CTRL_PREG},
|
||||
{0x02F5, SIERRA_DEQ_GAIN_CTRL_PREG},
|
||||
{0x9A8A, SIERRA_DEQ_VGATUNE_CTRL_PREG},
|
||||
{0x9999, SIERRA_DEQ_VGATUNE_CTRL_PREG},
|
||||
{0x0014, SIERRA_DEQ_GLUT0},
|
||||
{0x0014, SIERRA_DEQ_GLUT1},
|
||||
{0x0014, SIERRA_DEQ_GLUT2},
|
||||
@ -772,6 +772,7 @@ static struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = {
|
||||
{0x000F, SIERRA_LFPSFILT_NS_PREG},
|
||||
{0x0009, SIERRA_LFPSFILT_RD_PREG},
|
||||
{0x0001, SIERRA_LFPSFILT_MP_PREG},
|
||||
{0x6013, SIERRA_SIGDET_SUPPORT_PREG},
|
||||
{0x8013, SIERRA_SDFILT_H2L_A_PREG},
|
||||
{0x8009, SIERRA_SDFILT_L2H_PREG},
|
||||
{0x0024, SIERRA_RXBUFFER_CTLECTRL_PREG},
|
||||
|
@ -2,8 +2,23 @@
|
||||
#
|
||||
# Phy drivers for Intel Lightning Mountain(LGM) platform
|
||||
#
|
||||
config PHY_INTEL_COMBO
|
||||
bool "Intel ComboPHY driver"
|
||||
depends on X86 || COMPILE_TEST
|
||||
depends on OF && HAS_IOMEM
|
||||
select MFD_SYSCON
|
||||
select GENERIC_PHY
|
||||
select REGMAP
|
||||
help
|
||||
Enable this to support Intel ComboPhy.
|
||||
|
||||
This driver configures ComboPhy subsystem on Intel gateway
|
||||
chipsets which provides PHYs for various controllers, EMAC,
|
||||
SATA and PCIe.
|
||||
|
||||
config PHY_INTEL_EMMC
|
||||
tristate "Intel EMMC PHY driver"
|
||||
depends on X86 || COMPILE_TEST
|
||||
select GENERIC_PHY
|
||||
help
|
||||
Enable this to support the Intel EMMC PHY
|
||||
|
@ -1,2 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_PHY_INTEL_COMBO) += phy-intel-combo.o
|
||||
obj-$(CONFIG_PHY_INTEL_EMMC) += phy-intel-emmc.o
|
||||
|
632
drivers/phy/intel/phy-intel-combo.c
Normal file
632
drivers/phy/intel/phy-intel-combo.c
Normal file
@ -0,0 +1,632 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Intel Combo-PHY driver
|
||||
*
|
||||
* Copyright (C) 2019-2020 Intel Corporation.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include <dt-bindings/phy/phy.h>
|
||||
|
||||
#define PCIE_PHY_GEN_CTRL 0x00
|
||||
#define PCIE_PHY_CLK_PAD BIT(17)
|
||||
|
||||
#define PAD_DIS_CFG 0x174
|
||||
|
||||
#define PCS_XF_ATE_OVRD_IN_2 0x3008
|
||||
#define ADAPT_REQ_MSK GENMASK(5, 4)
|
||||
|
||||
#define PCS_XF_RX_ADAPT_ACK 0x3010
|
||||
#define RX_ADAPT_ACK_BIT BIT(0)
|
||||
|
||||
#define CR_ADDR(addr, lane) (((addr) + (lane) * 0x100) << 2)
|
||||
#define REG_COMBO_MODE(x) ((x) * 0x200)
|
||||
#define REG_CLK_DISABLE(x) ((x) * 0x200 + 0x124)
|
||||
|
||||
#define COMBO_PHY_ID(x) ((x)->parent->id)
|
||||
#define PHY_ID(x) ((x)->id)
|
||||
|
||||
#define CLK_100MHZ 100000000
|
||||
#define CLK_156_25MHZ 156250000
|
||||
|
||||
static const unsigned long intel_iphy_clk_rates[] = {
|
||||
CLK_100MHZ, CLK_156_25MHZ, CLK_100MHZ,
|
||||
};
|
||||
|
||||
enum {
|
||||
PHY_0,
|
||||
PHY_1,
|
||||
PHY_MAX_NUM
|
||||
};
|
||||
|
||||
/*
|
||||
* Clock Register bit fields to enable clocks
|
||||
* for ComboPhy according to the mode.
|
||||
*/
|
||||
enum intel_phy_mode {
|
||||
PHY_PCIE_MODE = 0,
|
||||
PHY_XPCS_MODE,
|
||||
PHY_SATA_MODE,
|
||||
};
|
||||
|
||||
/* ComboPhy mode Register values */
|
||||
enum intel_combo_mode {
|
||||
PCIE0_PCIE1_MODE = 0,
|
||||
PCIE_DL_MODE,
|
||||
RXAUI_MODE,
|
||||
XPCS0_XPCS1_MODE,
|
||||
SATA0_SATA1_MODE,
|
||||
};
|
||||
|
||||
enum aggregated_mode {
|
||||
PHY_SL_MODE,
|
||||
PHY_DL_MODE,
|
||||
};
|
||||
|
||||
struct intel_combo_phy;
|
||||
|
||||
struct intel_cbphy_iphy {
|
||||
struct phy *phy;
|
||||
struct intel_combo_phy *parent;
|
||||
struct reset_control *app_rst;
|
||||
u32 id;
|
||||
};
|
||||
|
||||
struct intel_combo_phy {
|
||||
struct device *dev;
|
||||
struct clk *core_clk;
|
||||
unsigned long clk_rate;
|
||||
void __iomem *app_base;
|
||||
void __iomem *cr_base;
|
||||
struct regmap *syscfg;
|
||||
struct regmap *hsiocfg;
|
||||
u32 id;
|
||||
u32 bid;
|
||||
struct reset_control *phy_rst;
|
||||
struct reset_control *core_rst;
|
||||
struct intel_cbphy_iphy iphy[PHY_MAX_NUM];
|
||||
enum intel_phy_mode phy_mode;
|
||||
enum aggregated_mode aggr_mode;
|
||||
u32 init_cnt;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
static int intel_cbphy_iphy_enable(struct intel_cbphy_iphy *iphy, bool set)
|
||||
{
|
||||
struct intel_combo_phy *cbphy = iphy->parent;
|
||||
u32 mask = BIT(cbphy->phy_mode * 2 + iphy->id);
|
||||
u32 val;
|
||||
|
||||
/* Register: 0 is enable, 1 is disable */
|
||||
val = set ? 0 : mask;
|
||||
|
||||
return regmap_update_bits(cbphy->hsiocfg, REG_CLK_DISABLE(cbphy->bid),
|
||||
mask, val);
|
||||
}
|
||||
|
||||
static int intel_cbphy_pcie_refclk_cfg(struct intel_cbphy_iphy *iphy, bool set)
|
||||
{
|
||||
struct intel_combo_phy *cbphy = iphy->parent;
|
||||
u32 mask = BIT(cbphy->id * 2 + iphy->id);
|
||||
u32 val;
|
||||
|
||||
/* Register: 0 is enable, 1 is disable */
|
||||
val = set ? 0 : mask;
|
||||
|
||||
return regmap_update_bits(cbphy->syscfg, PAD_DIS_CFG, mask, val);
|
||||
}
|
||||
|
||||
static inline void combo_phy_w32_off_mask(void __iomem *base, unsigned int reg,
|
||||
u32 mask, u32 val)
|
||||
{
|
||||
u32 reg_val;
|
||||
|
||||
reg_val = readl(base + reg);
|
||||
reg_val &= ~mask;
|
||||
reg_val |= FIELD_PREP(mask, val);
|
||||
writel(reg_val, base + reg);
|
||||
}
|
||||
|
||||
static int intel_cbphy_iphy_cfg(struct intel_cbphy_iphy *iphy,
|
||||
int (*phy_cfg)(struct intel_cbphy_iphy *))
|
||||
{
|
||||
struct intel_combo_phy *cbphy = iphy->parent;
|
||||
int ret;
|
||||
|
||||
ret = phy_cfg(iphy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cbphy->aggr_mode != PHY_DL_MODE)
|
||||
return 0;
|
||||
|
||||
return phy_cfg(&cbphy->iphy[PHY_1]);
|
||||
}
|
||||
|
||||
static int intel_cbphy_pcie_en_pad_refclk(struct intel_cbphy_iphy *iphy)
|
||||
{
|
||||
struct intel_combo_phy *cbphy = iphy->parent;
|
||||
int ret;
|
||||
|
||||
ret = intel_cbphy_pcie_refclk_cfg(iphy, true);
|
||||
if (ret) {
|
||||
dev_err(cbphy->dev, "Failed to enable PCIe pad refclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (cbphy->init_cnt)
|
||||
return 0;
|
||||
|
||||
combo_phy_w32_off_mask(cbphy->app_base, PCIE_PHY_GEN_CTRL,
|
||||
PCIE_PHY_CLK_PAD, 0);
|
||||
|
||||
/* Delay for stable clock PLL */
|
||||
usleep_range(50, 100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_cbphy_pcie_dis_pad_refclk(struct intel_cbphy_iphy *iphy)
|
||||
{
|
||||
struct intel_combo_phy *cbphy = iphy->parent;
|
||||
int ret;
|
||||
|
||||
ret = intel_cbphy_pcie_refclk_cfg(iphy, false);
|
||||
if (ret) {
|
||||
dev_err(cbphy->dev, "Failed to disable PCIe pad refclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (cbphy->init_cnt)
|
||||
return 0;
|
||||
|
||||
combo_phy_w32_off_mask(cbphy->app_base, PCIE_PHY_GEN_CTRL,
|
||||
PCIE_PHY_CLK_PAD, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_cbphy_set_mode(struct intel_combo_phy *cbphy)
|
||||
{
|
||||
enum intel_combo_mode cb_mode = PHY_PCIE_MODE;
|
||||
enum aggregated_mode aggr = cbphy->aggr_mode;
|
||||
struct device *dev = cbphy->dev;
|
||||
enum intel_phy_mode mode;
|
||||
int ret;
|
||||
|
||||
mode = cbphy->phy_mode;
|
||||
|
||||
switch (mode) {
|
||||
case PHY_PCIE_MODE:
|
||||
cb_mode = (aggr == PHY_DL_MODE) ? PCIE_DL_MODE : PCIE0_PCIE1_MODE;
|
||||
break;
|
||||
|
||||
case PHY_XPCS_MODE:
|
||||
cb_mode = (aggr == PHY_DL_MODE) ? RXAUI_MODE : XPCS0_XPCS1_MODE;
|
||||
break;
|
||||
|
||||
case PHY_SATA_MODE:
|
||||
if (aggr == PHY_DL_MODE) {
|
||||
dev_err(dev, "Mode:%u not support dual lane!\n", mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cb_mode = SATA0_SATA1_MODE;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = regmap_write(cbphy->hsiocfg, REG_COMBO_MODE(cbphy->bid), cb_mode);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to set ComboPhy mode: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void intel_cbphy_rst_assert(struct intel_combo_phy *cbphy)
|
||||
{
|
||||
reset_control_assert(cbphy->core_rst);
|
||||
reset_control_assert(cbphy->phy_rst);
|
||||
}
|
||||
|
||||
static void intel_cbphy_rst_deassert(struct intel_combo_phy *cbphy)
|
||||
{
|
||||
reset_control_deassert(cbphy->core_rst);
|
||||
reset_control_deassert(cbphy->phy_rst);
|
||||
/* Delay to ensure reset process is done */
|
||||
usleep_range(10, 20);
|
||||
}
|
||||
|
||||
static int intel_cbphy_iphy_power_on(struct intel_cbphy_iphy *iphy)
|
||||
{
|
||||
struct intel_combo_phy *cbphy = iphy->parent;
|
||||
int ret;
|
||||
|
||||
if (!cbphy->init_cnt) {
|
||||
ret = clk_prepare_enable(cbphy->core_clk);
|
||||
if (ret) {
|
||||
dev_err(cbphy->dev, "Clock enable failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(cbphy->core_clk, cbphy->clk_rate);
|
||||
if (ret) {
|
||||
dev_err(cbphy->dev, "Clock freq set to %lu failed!\n",
|
||||
cbphy->clk_rate);
|
||||
goto clk_err;
|
||||
}
|
||||
|
||||
intel_cbphy_rst_assert(cbphy);
|
||||
intel_cbphy_rst_deassert(cbphy);
|
||||
ret = intel_cbphy_set_mode(cbphy);
|
||||
if (ret)
|
||||
goto clk_err;
|
||||
}
|
||||
|
||||
ret = intel_cbphy_iphy_enable(iphy, true);
|
||||
if (ret) {
|
||||
dev_err(cbphy->dev, "Failed enabling PHY core\n");
|
||||
goto clk_err;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(iphy->app_rst);
|
||||
if (ret) {
|
||||
dev_err(cbphy->dev, "PHY(%u:%u) reset deassert failed!\n",
|
||||
COMBO_PHY_ID(iphy), PHY_ID(iphy));
|
||||
goto clk_err;
|
||||
}
|
||||
|
||||
/* Delay to ensure reset process is done */
|
||||
udelay(1);
|
||||
|
||||
return 0;
|
||||
|
||||
clk_err:
|
||||
clk_disable_unprepare(cbphy->core_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int intel_cbphy_iphy_power_off(struct intel_cbphy_iphy *iphy)
|
||||
{
|
||||
struct intel_combo_phy *cbphy = iphy->parent;
|
||||
int ret;
|
||||
|
||||
ret = reset_control_assert(iphy->app_rst);
|
||||
if (ret) {
|
||||
dev_err(cbphy->dev, "PHY(%u:%u) reset assert failed!\n",
|
||||
COMBO_PHY_ID(iphy), PHY_ID(iphy));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = intel_cbphy_iphy_enable(iphy, false);
|
||||
if (ret) {
|
||||
dev_err(cbphy->dev, "Failed disabling PHY core\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (cbphy->init_cnt)
|
||||
return 0;
|
||||
|
||||
clk_disable_unprepare(cbphy->core_clk);
|
||||
intel_cbphy_rst_assert(cbphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_cbphy_init(struct phy *phy)
|
||||
{
|
||||
struct intel_cbphy_iphy *iphy = phy_get_drvdata(phy);
|
||||
struct intel_combo_phy *cbphy = iphy->parent;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&cbphy->lock);
|
||||
ret = intel_cbphy_iphy_cfg(iphy, intel_cbphy_iphy_power_on);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (cbphy->phy_mode == PHY_PCIE_MODE) {
|
||||
ret = intel_cbphy_iphy_cfg(iphy, intel_cbphy_pcie_en_pad_refclk);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
cbphy->init_cnt++;
|
||||
|
||||
err:
|
||||
mutex_unlock(&cbphy->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int intel_cbphy_exit(struct phy *phy)
|
||||
{
|
||||
struct intel_cbphy_iphy *iphy = phy_get_drvdata(phy);
|
||||
struct intel_combo_phy *cbphy = iphy->parent;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&cbphy->lock);
|
||||
cbphy->init_cnt--;
|
||||
if (cbphy->phy_mode == PHY_PCIE_MODE) {
|
||||
ret = intel_cbphy_iphy_cfg(iphy, intel_cbphy_pcie_dis_pad_refclk);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = intel_cbphy_iphy_cfg(iphy, intel_cbphy_iphy_power_off);
|
||||
|
||||
err:
|
||||
mutex_unlock(&cbphy->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int intel_cbphy_calibrate(struct phy *phy)
|
||||
{
|
||||
struct intel_cbphy_iphy *iphy = phy_get_drvdata(phy);
|
||||
struct intel_combo_phy *cbphy = iphy->parent;
|
||||
void __iomem *cr_base = cbphy->cr_base;
|
||||
int val, ret, id;
|
||||
|
||||
if (cbphy->phy_mode != PHY_XPCS_MODE)
|
||||
return 0;
|
||||
|
||||
id = PHY_ID(iphy);
|
||||
|
||||
/* trigger auto RX adaptation */
|
||||
combo_phy_w32_off_mask(cr_base, CR_ADDR(PCS_XF_ATE_OVRD_IN_2, id),
|
||||
ADAPT_REQ_MSK, 3);
|
||||
/* Wait RX adaptation to finish */
|
||||
ret = readl_poll_timeout(cr_base + CR_ADDR(PCS_XF_RX_ADAPT_ACK, id),
|
||||
val, val & RX_ADAPT_ACK_BIT, 10, 5000);
|
||||
if (ret)
|
||||
dev_err(cbphy->dev, "RX Adaptation failed!\n");
|
||||
else
|
||||
dev_dbg(cbphy->dev, "RX Adaptation success!\n");
|
||||
|
||||
/* Stop RX adaptation */
|
||||
combo_phy_w32_off_mask(cr_base, CR_ADDR(PCS_XF_ATE_OVRD_IN_2, id),
|
||||
ADAPT_REQ_MSK, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int intel_cbphy_fwnode_parse(struct intel_combo_phy *cbphy)
|
||||
{
|
||||
struct device *dev = cbphy->dev;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct fwnode_handle *fwnode = dev_fwnode(dev);
|
||||
struct fwnode_reference_args ref;
|
||||
int ret;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
cbphy->app_base = devm_platform_ioremap_resource_byname(pdev, "app");
|
||||
if (IS_ERR(cbphy->app_base))
|
||||
return PTR_ERR(cbphy->app_base);
|
||||
|
||||
cbphy->cr_base = devm_platform_ioremap_resource_byname(pdev, "core");
|
||||
if (IS_ERR(cbphy->cr_base))
|
||||
return PTR_ERR(cbphy->cr_base);
|
||||
|
||||
/*
|
||||
* syscfg and hsiocfg variables stores the handle of the registers set
|
||||
* in which ComboPhy subsytem specific registers are subset. Using
|
||||
* Register map framework to access the registers set.
|
||||
*/
|
||||
ret = fwnode_property_get_reference_args(fwnode, "intel,syscfg", NULL,
|
||||
1, 0, &ref);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
cbphy->id = ref.args[0];
|
||||
cbphy->syscfg = device_node_to_regmap(to_of_node(ref.fwnode));
|
||||
fwnode_handle_put(ref.fwnode);
|
||||
|
||||
ret = fwnode_property_get_reference_args(fwnode, "intel,hsio", NULL, 1,
|
||||
0, &ref);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
cbphy->bid = ref.args[0];
|
||||
cbphy->hsiocfg = device_node_to_regmap(to_of_node(ref.fwnode));
|
||||
fwnode_handle_put(ref.fwnode);
|
||||
|
||||
ret = fwnode_property_read_u32_array(fwnode, "intel,phy-mode", &val, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (val) {
|
||||
case PHY_TYPE_PCIE:
|
||||
cbphy->phy_mode = PHY_PCIE_MODE;
|
||||
break;
|
||||
|
||||
case PHY_TYPE_SATA:
|
||||
cbphy->phy_mode = PHY_SATA_MODE;
|
||||
break;
|
||||
|
||||
case PHY_TYPE_XPCS:
|
||||
cbphy->phy_mode = PHY_XPCS_MODE;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(dev, "Invalid PHY mode: %u\n", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cbphy->clk_rate = intel_iphy_clk_rates[cbphy->phy_mode];
|
||||
|
||||
if (fwnode_property_present(fwnode, "intel,aggregation"))
|
||||
cbphy->aggr_mode = PHY_DL_MODE;
|
||||
else
|
||||
cbphy->aggr_mode = PHY_SL_MODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ops intel_cbphy_ops = {
|
||||
.init = intel_cbphy_init,
|
||||
.exit = intel_cbphy_exit,
|
||||
.calibrate = intel_cbphy_calibrate,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct phy *intel_cbphy_xlate(struct device *dev,
|
||||
struct of_phandle_args *args)
|
||||
{
|
||||
struct intel_combo_phy *cbphy = dev_get_drvdata(dev);
|
||||
u32 iphy_id;
|
||||
|
||||
if (args->args_count < 1) {
|
||||
dev_err(dev, "Invalid number of arguments\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
iphy_id = args->args[0];
|
||||
if (iphy_id >= PHY_MAX_NUM) {
|
||||
dev_err(dev, "Invalid phy instance %d\n", iphy_id);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (cbphy->aggr_mode == PHY_DL_MODE && iphy_id == PHY_1) {
|
||||
dev_err(dev, "Invalid. ComboPhy is in Dual lane mode %d\n", iphy_id);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return cbphy->iphy[iphy_id].phy;
|
||||
}
|
||||
|
||||
static int intel_cbphy_create(struct intel_combo_phy *cbphy)
|
||||
{
|
||||
struct phy_provider *phy_provider;
|
||||
struct device *dev = cbphy->dev;
|
||||
struct intel_cbphy_iphy *iphy;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PHY_MAX_NUM; i++) {
|
||||
iphy = &cbphy->iphy[i];
|
||||
iphy->parent = cbphy;
|
||||
iphy->id = i;
|
||||
|
||||
/* In dual lane mode skip phy creation for the second phy */
|
||||
if (cbphy->aggr_mode == PHY_DL_MODE && iphy->id == PHY_1)
|
||||
continue;
|
||||
|
||||
iphy->phy = devm_phy_create(dev, NULL, &intel_cbphy_ops);
|
||||
if (IS_ERR(iphy->phy)) {
|
||||
dev_err(dev, "PHY[%u:%u]: create PHY instance failed!\n",
|
||||
COMBO_PHY_ID(iphy), PHY_ID(iphy));
|
||||
|
||||
return PTR_ERR(iphy->phy);
|
||||
}
|
||||
|
||||
phy_set_drvdata(iphy->phy, iphy);
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, cbphy);
|
||||
phy_provider = devm_of_phy_provider_register(dev, intel_cbphy_xlate);
|
||||
if (IS_ERR(phy_provider))
|
||||
dev_err(dev, "Register PHY provider failed!\n");
|
||||
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
}
|
||||
|
||||
static int intel_cbphy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct intel_combo_phy *cbphy;
|
||||
int ret;
|
||||
|
||||
cbphy = devm_kzalloc(dev, sizeof(*cbphy), GFP_KERNEL);
|
||||
if (!cbphy)
|
||||
return -ENOMEM;
|
||||
|
||||
cbphy->dev = dev;
|
||||
cbphy->init_cnt = 0;
|
||||
mutex_init(&cbphy->lock);
|
||||
ret = intel_cbphy_fwnode_parse(cbphy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, cbphy);
|
||||
|
||||
return intel_cbphy_create(cbphy);
|
||||
}
|
||||
|
||||
static int intel_cbphy_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct intel_combo_phy *cbphy = platform_get_drvdata(pdev);
|
||||
|
||||
intel_cbphy_rst_assert(cbphy);
|
||||
clk_disable_unprepare(cbphy->core_clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_intel_cbphy_match[] = {
|
||||
{ .compatible = "intel,combo-phy" },
|
||||
{ .compatible = "intel,combophy-lgm" },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver intel_cbphy_driver = {
|
||||
.probe = intel_cbphy_probe,
|
||||
.remove = intel_cbphy_remove,
|
||||
.driver = {
|
||||
.name = "intel-combo-phy",
|
||||
.of_match_table = of_intel_cbphy_match,
|
||||
}
|
||||
};
|
||||
|
||||
module_platform_driver(intel_cbphy_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Intel Combo-phy driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -122,7 +122,6 @@ enum cpcap_gpio_mode {
|
||||
struct cpcap_phy_ddata {
|
||||
struct regmap *reg;
|
||||
struct device *dev;
|
||||
struct clk *refclk;
|
||||
struct usb_phy phy;
|
||||
struct delayed_work detect_work;
|
||||
struct pinctrl *pins;
|
||||
@ -707,7 +706,6 @@ static int cpcap_usb_phy_remove(struct platform_device *pdev)
|
||||
|
||||
usb_remove_phy(&ddata->phy);
|
||||
cancel_delayed_work_sync(&ddata->detect_work);
|
||||
clk_unprepare(ddata->refclk);
|
||||
regulator_disable(ddata->vusb);
|
||||
|
||||
return 0;
|
||||
|
@ -18,6 +18,13 @@ config PHY_QCOM_APQ8064_SATA
|
||||
depends on OF
|
||||
select GENERIC_PHY
|
||||
|
||||
config PHY_QCOM_IPQ4019_USB
|
||||
tristate "Qualcomm IPQ4019 USB PHY driver"
|
||||
depends on OF && (ARCH_QCOM || COMPILE_TEST)
|
||||
select GENERIC_PHY
|
||||
help
|
||||
Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s.
|
||||
|
||||
config PHY_QCOM_IPQ806X_SATA
|
||||
tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
|
||||
depends on ARCH_QCOM
|
||||
@ -85,6 +92,16 @@ config PHY_QCOM_USB_HS
|
||||
Support for the USB high-speed ULPI compliant phy on Qualcomm
|
||||
chipsets.
|
||||
|
||||
config PHY_QCOM_USB_SNPS_FEMTO_V2
|
||||
tristate "Qualcomm SNPS FEMTO USB HS PHY V2 module"
|
||||
depends on OF && (ARCH_QCOM || COMPILE_TEST)
|
||||
select GENERIC_PHY
|
||||
help
|
||||
Enable support for the USB high-speed SNPS Femto phy on Qualcomm
|
||||
chipsets. This PHY has differences in the register map compared
|
||||
to the V1 variants. The PHY is paired with a Synopsys DWC3 USB
|
||||
controller on Qualcomm SOCs.
|
||||
|
||||
config PHY_QCOM_USB_HSIC
|
||||
tristate "Qualcomm USB HSIC ULPI PHY module"
|
||||
depends on USB_ULPI_BUS
|
||||
|
@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_PHY_ATH79_USB) += phy-ath79-usb.o
|
||||
obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
|
||||
obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o
|
||||
obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
|
||||
obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o
|
||||
obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o
|
||||
@ -12,3 +13,4 @@ obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o
|
||||
obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
|
||||
obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o
|
||||
obj-$(CONFIG_PHY_QCOM_USB_SS) += phy-qcom-usb-ss.o
|
||||
obj-$(CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2)+= phy-qcom-snps-femto-v2.o
|
||||
|
148
drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c
Normal file
148
drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c
Normal file
@ -0,0 +1,148 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2018 John Crispin <john@phrozen.org>
|
||||
*
|
||||
* Based on code from
|
||||
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
struct ipq4019_usb_phy {
|
||||
struct device *dev;
|
||||
struct phy *phy;
|
||||
void __iomem *base;
|
||||
struct reset_control *por_rst;
|
||||
struct reset_control *srif_rst;
|
||||
};
|
||||
|
||||
static int ipq4019_ss_phy_power_off(struct phy *_phy)
|
||||
{
|
||||
struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||
|
||||
reset_control_assert(phy->por_rst);
|
||||
msleep(10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipq4019_ss_phy_power_on(struct phy *_phy)
|
||||
{
|
||||
struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||
|
||||
ipq4019_ss_phy_power_off(_phy);
|
||||
|
||||
reset_control_deassert(phy->por_rst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy_ops ipq4019_usb_ss_phy_ops = {
|
||||
.power_on = ipq4019_ss_phy_power_on,
|
||||
.power_off = ipq4019_ss_phy_power_off,
|
||||
};
|
||||
|
||||
static int ipq4019_hs_phy_power_off(struct phy *_phy)
|
||||
{
|
||||
struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||
|
||||
reset_control_assert(phy->por_rst);
|
||||
msleep(10);
|
||||
|
||||
reset_control_assert(phy->srif_rst);
|
||||
msleep(10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipq4019_hs_phy_power_on(struct phy *_phy)
|
||||
{
|
||||
struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||
|
||||
ipq4019_hs_phy_power_off(_phy);
|
||||
|
||||
reset_control_deassert(phy->srif_rst);
|
||||
msleep(10);
|
||||
|
||||
reset_control_deassert(phy->por_rst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy_ops ipq4019_usb_hs_phy_ops = {
|
||||
.power_on = ipq4019_hs_phy_power_on,
|
||||
.power_off = ipq4019_hs_phy_power_off,
|
||||
};
|
||||
|
||||
static const struct of_device_id ipq4019_usb_phy_of_match[] = {
|
||||
{ .compatible = "qcom,usb-hs-ipq4019-phy", .data = &ipq4019_usb_hs_phy_ops},
|
||||
{ .compatible = "qcom,usb-ss-ipq4019-phy", .data = &ipq4019_usb_ss_phy_ops},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ipq4019_usb_phy_of_match);
|
||||
|
||||
static int ipq4019_usb_phy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
struct phy_provider *phy_provider;
|
||||
struct ipq4019_usb_phy *phy;
|
||||
|
||||
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
|
||||
if (!phy)
|
||||
return -ENOMEM;
|
||||
|
||||
phy->dev = &pdev->dev;
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
phy->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(phy->base)) {
|
||||
dev_err(dev, "failed to remap register memory\n");
|
||||
return PTR_ERR(phy->base);
|
||||
}
|
||||
|
||||
phy->por_rst = devm_reset_control_get(phy->dev, "por_rst");
|
||||
if (IS_ERR(phy->por_rst)) {
|
||||
if (PTR_ERR(phy->por_rst) != -EPROBE_DEFER)
|
||||
dev_err(dev, "POR reset is missing\n");
|
||||
return PTR_ERR(phy->por_rst);
|
||||
}
|
||||
|
||||
phy->srif_rst = devm_reset_control_get_optional(phy->dev, "srif_rst");
|
||||
if (IS_ERR(phy->srif_rst))
|
||||
return PTR_ERR(phy->srif_rst);
|
||||
|
||||
phy->phy = devm_phy_create(dev, NULL, of_device_get_match_data(dev));
|
||||
if (IS_ERR(phy->phy)) {
|
||||
dev_err(dev, "failed to create PHY\n");
|
||||
return PTR_ERR(phy->phy);
|
||||
}
|
||||
phy_set_drvdata(phy->phy, phy);
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
}
|
||||
|
||||
static struct platform_driver ipq4019_usb_phy_driver = {
|
||||
.probe = ipq4019_usb_phy_probe,
|
||||
.driver = {
|
||||
.of_match_table = ipq4019_usb_phy_of_match,
|
||||
.name = "ipq4019-usb-phy",
|
||||
}
|
||||
};
|
||||
module_platform_driver(ipq4019_usb_phy_driver);
|
||||
|
||||
MODULE_DESCRIPTION("QCOM/IPQ4019 USB phy driver");
|
||||
MODULE_AUTHOR("John Crispin <john@phrozen.org>");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -119,14 +119,17 @@ enum qphy_reg_layout {
|
||||
QPHY_PCS_AUTONOMOUS_MODE_CTRL,
|
||||
QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR,
|
||||
QPHY_PCS_LFPS_RXTERM_IRQ_STATUS,
|
||||
QPHY_PCS_POWER_DOWN_CONTROL,
|
||||
/* Keep last to ensure regs_layout arrays are properly initialized */
|
||||
QPHY_LAYOUT_SIZE
|
||||
};
|
||||
|
||||
static const unsigned int msm8996_ufsphy_regs_layout[] = {
|
||||
static const unsigned int msm8996_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = {
|
||||
[QPHY_START_CTRL] = 0x00,
|
||||
[QPHY_PCS_READY_STATUS] = 0x168,
|
||||
};
|
||||
|
||||
static const unsigned int pciephy_regs_layout[] = {
|
||||
static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = {
|
||||
[QPHY_COM_SW_RESET] = 0x400,
|
||||
[QPHY_COM_POWER_DOWN_CONTROL] = 0x404,
|
||||
[QPHY_COM_START_CONTROL] = 0x408,
|
||||
@ -142,7 +145,7 @@ static const unsigned int pciephy_regs_layout[] = {
|
||||
[QPHY_PCS_STATUS] = 0x174,
|
||||
};
|
||||
|
||||
static const unsigned int usb3phy_regs_layout[] = {
|
||||
static const unsigned int usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
|
||||
[QPHY_FLL_CNTRL1] = 0xc0,
|
||||
[QPHY_FLL_CNTRL2] = 0xc4,
|
||||
[QPHY_FLL_CNT_VAL_L] = 0xc8,
|
||||
@ -156,7 +159,7 @@ static const unsigned int usb3phy_regs_layout[] = {
|
||||
[QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178,
|
||||
};
|
||||
|
||||
static const unsigned int qmp_v3_usb3phy_regs_layout[] = {
|
||||
static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
|
||||
[QPHY_SW_RESET] = 0x00,
|
||||
[QPHY_START_CTRL] = 0x08,
|
||||
[QPHY_PCS_STATUS] = 0x174,
|
||||
@ -165,27 +168,34 @@ static const unsigned int qmp_v3_usb3phy_regs_layout[] = {
|
||||
[QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170,
|
||||
};
|
||||
|
||||
static const unsigned int sdm845_qmp_pciephy_regs_layout[] = {
|
||||
static const unsigned int sdm845_qmp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = {
|
||||
[QPHY_SW_RESET] = 0x00,
|
||||
[QPHY_START_CTRL] = 0x08,
|
||||
[QPHY_PCS_STATUS] = 0x174,
|
||||
};
|
||||
|
||||
static const unsigned int sdm845_qhp_pciephy_regs_layout[] = {
|
||||
static const unsigned int sdm845_qhp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = {
|
||||
[QPHY_SW_RESET] = 0x00,
|
||||
[QPHY_START_CTRL] = 0x08,
|
||||
[QPHY_PCS_STATUS] = 0x2ac,
|
||||
};
|
||||
|
||||
static const unsigned int sdm845_ufsphy_regs_layout[] = {
|
||||
static const unsigned int qmp_v4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
|
||||
[QPHY_SW_RESET] = 0x00,
|
||||
[QPHY_START_CTRL] = 0x44,
|
||||
[QPHY_PCS_STATUS] = 0x14,
|
||||
[QPHY_PCS_POWER_DOWN_CONTROL] = 0x40,
|
||||
};
|
||||
|
||||
static const unsigned int sdm845_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = {
|
||||
[QPHY_START_CTRL] = 0x00,
|
||||
[QPHY_PCS_READY_STATUS] = 0x160,
|
||||
};
|
||||
|
||||
static const unsigned int sm8150_ufsphy_regs_layout[] = {
|
||||
[QPHY_START_CTRL] = QPHY_V4_PHY_START,
|
||||
[QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_READY_STATUS,
|
||||
[QPHY_SW_RESET] = QPHY_V4_SW_RESET,
|
||||
static const unsigned int sm8150_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = {
|
||||
[QPHY_START_CTRL] = QPHY_V4_PCS_UFS_PHY_START,
|
||||
[QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_UFS_READY_STATUS,
|
||||
[QPHY_SW_RESET] = QPHY_V4_PCS_UFS_SW_RESET,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = {
|
||||
@ -1272,13 +1282,121 @@ static const struct qmp_phy_init_tbl sm8150_ufsphy_rx_tbl[] = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8150_ufsphy_pcs_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_RX_SIGDET_CTRL2, 0x6d),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_TX_LARGE_AMP_DRV_LVL, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_TX_SMALL_AMP_DRV_LVL, 0x02),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_TX_MID_TERM_CTRL1, 0x43),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_DEBUG_BUS_CLKSEL, 0x1f),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_RX_MIN_HIBERN8_TIME, 0xff),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_MULTI_LANE_CTRL1, 0x02),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_SIGDET_CTRL2, 0x6d),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8150_usb3_serdes_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8150_usb3_tx_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8150_usb3_rx_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xbf),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x3f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x94),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8150_usb3_pcs_tbl[] = {
|
||||
/* Lock Det settings */
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13),
|
||||
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
|
||||
};
|
||||
|
||||
/* struct qmp_phy_cfg - per-PHY initialization config */
|
||||
@ -1445,6 +1563,10 @@ static const char * const sdm845_pciephy_clk_l[] = {
|
||||
"aux", "cfg_ahb", "ref", "refgen",
|
||||
};
|
||||
|
||||
static const char * const qmp_v4_phy_clk_l[] = {
|
||||
"aux", "ref_clk_src", "ref", "com_aux",
|
||||
};
|
||||
|
||||
static const char * const sdm845_ufs_phy_clk_l[] = {
|
||||
"ref", "ref_aux",
|
||||
};
|
||||
@ -1458,6 +1580,10 @@ static const char * const msm8996_usb3phy_reset_l[] = {
|
||||
"phy", "common",
|
||||
};
|
||||
|
||||
static const char * const sc7180_usb3phy_reset_l[] = {
|
||||
"phy",
|
||||
};
|
||||
|
||||
static const char * const sdm845_pciephy_reset_l[] = {
|
||||
"phy",
|
||||
};
|
||||
@ -1671,6 +1797,37 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sc7180_usb3phy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
|
||||
.serdes_tbl = qmp_v3_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl),
|
||||
.tx_tbl = qmp_v3_usb3_tx_tbl,
|
||||
.tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl),
|
||||
.rx_tbl = qmp_v3_usb3_rx_tbl,
|
||||
.rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl),
|
||||
.pcs_tbl = qmp_v3_usb3_pcs_tbl,
|
||||
.pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl),
|
||||
.clk_list = qmp_v3_phy_clk_l,
|
||||
.num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l),
|
||||
.reset_list = sc7180_usb3phy_reset_l,
|
||||
.num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l),
|
||||
.vreg_list = qmp_phy_vreg_l,
|
||||
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
|
||||
.regs = qmp_v3_usb3phy_regs_layout,
|
||||
|
||||
.start_ctrl = SERDES_START | PCS_START,
|
||||
.pwrdn_ctrl = SW_PWRDN,
|
||||
|
||||
.has_pwrdn_delay = true,
|
||||
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
|
||||
.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 qmp_v3_usb3_uniphy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
@ -1798,6 +1955,37 @@ static const struct qmp_phy_cfg sm8150_ufsphy_cfg = {
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8150_usb3phy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
|
||||
.serdes_tbl = sm8150_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl),
|
||||
.tx_tbl = sm8150_usb3_tx_tbl,
|
||||
.tx_tbl_num = ARRAY_SIZE(sm8150_usb3_tx_tbl),
|
||||
.rx_tbl = sm8150_usb3_rx_tbl,
|
||||
.rx_tbl_num = ARRAY_SIZE(sm8150_usb3_rx_tbl),
|
||||
.pcs_tbl = sm8150_usb3_pcs_tbl,
|
||||
.pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_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,
|
||||
|
||||
.has_pwrdn_delay = true,
|
||||
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
|
||||
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
|
||||
|
||||
.has_phy_dp_com_ctrl = true,
|
||||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static void qcom_qmp_phy_configure(void __iomem *base,
|
||||
const unsigned int *regs,
|
||||
const struct qmp_phy_init_tbl tbl[],
|
||||
@ -1880,11 +2068,18 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy)
|
||||
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
|
||||
}
|
||||
|
||||
if (cfg->has_phy_com_ctrl)
|
||||
if (cfg->has_phy_com_ctrl) {
|
||||
qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
|
||||
SW_PWRDN);
|
||||
else
|
||||
qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
|
||||
} else {
|
||||
if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL])
|
||||
qphy_setbits(pcs,
|
||||
cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
|
||||
cfg->pwrdn_ctrl);
|
||||
else
|
||||
qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL,
|
||||
cfg->pwrdn_ctrl);
|
||||
}
|
||||
|
||||
/* Serdes configuration */
|
||||
qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl,
|
||||
@ -2110,7 +2305,13 @@ static int qcom_qmp_phy_disable(struct phy *phy)
|
||||
qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
|
||||
|
||||
/* Put PHY into POWER DOWN state: active low */
|
||||
qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
|
||||
if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) {
|
||||
qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
|
||||
cfg->pwrdn_ctrl);
|
||||
} else {
|
||||
qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL,
|
||||
cfg->pwrdn_ctrl);
|
||||
}
|
||||
|
||||
if (cfg->has_lane_rst)
|
||||
reset_control_assert(qphy->lane_rst);
|
||||
@ -2515,6 +2716,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
|
||||
}, {
|
||||
.compatible = "qcom,ipq8074-qmp-pcie-phy",
|
||||
.data = &ipq8074_pciephy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sc7180-qmp-usb3-phy",
|
||||
.data = &sc7180_usb3phy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sdm845-qhp-pcie-phy",
|
||||
.data = &sdm845_qhp_pciephy_cfg,
|
||||
@ -2536,6 +2740,12 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
|
||||
}, {
|
||||
.compatible = "qcom,sm8150-qmp-ufs-phy",
|
||||
.data = &sm8150_ufsphy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sm8250-qmp-ufs-phy",
|
||||
.data = &sm8150_ufsphy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sm8150-qmp-usb3-phy",
|
||||
.data = &sm8150_usb3phy_cfg,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
@ -125,7 +125,7 @@
|
||||
#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1DC
|
||||
#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1E0
|
||||
|
||||
/* Only for QMP V3 PHY - DP COM registers */
|
||||
/* Only for QMP V3 & V4 PHY - DP COM registers */
|
||||
#define QPHY_V3_DP_COM_PHY_MODE_CTRL 0x00
|
||||
#define QPHY_V3_DP_COM_SW_RESET 0x04
|
||||
#define QPHY_V3_DP_COM_POWER_DOWN_CTRL 0x08
|
||||
@ -314,6 +314,14 @@
|
||||
#define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5 0x60
|
||||
|
||||
/* Only for QMP V4 PHY - QSERDES COM registers */
|
||||
#define QSERDES_V4_COM_SSC_EN_CENTER 0x010
|
||||
#define QSERDES_V4_COM_SSC_PER1 0x01c
|
||||
#define QSERDES_V4_COM_SSC_PER2 0x020
|
||||
#define QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0 0x024
|
||||
#define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0 0x028
|
||||
#define QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1 0x030
|
||||
#define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1 0x034
|
||||
#define QSERDES_V4_COM_SYSCLK_BUF_ENABLE 0x050
|
||||
#define QSERDES_V4_COM_PLL_IVCO 0x058
|
||||
#define QSERDES_V4_COM_CMN_IPTRIM 0x060
|
||||
#define QSERDES_V4_COM_CP_CTRL_MODE0 0x074
|
||||
@ -330,10 +338,22 @@
|
||||
#define QSERDES_V4_COM_DEC_START_MODE0 0x0bc
|
||||
#define QSERDES_V4_COM_LOCK_CMP2_MODE1 0x0b8
|
||||
#define QSERDES_V4_COM_DEC_START_MODE1 0x0c4
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START1_MODE0 0x0cc
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START2_MODE0 0x0d0
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START3_MODE0 0x0d4
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START1_MODE1 0x0d8
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START2_MODE1 0x0dc
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START3_MODE1 0x0e0
|
||||
#define QSERDES_V4_COM_VCO_TUNE_MAP 0x10c
|
||||
#define QSERDES_V4_COM_VCO_TUNE1_MODE0 0x110
|
||||
#define QSERDES_V4_COM_VCO_TUNE2_MODE0 0x114
|
||||
#define QSERDES_V4_COM_VCO_TUNE1_MODE1 0x118
|
||||
#define QSERDES_V4_COM_VCO_TUNE2_MODE1 0x11c
|
||||
#define QSERDES_V4_COM_VCO_TUNE_INITVAL2 0x124
|
||||
#define QSERDES_V4_COM_HSCLK_SEL 0x158
|
||||
#define QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL 0x15c
|
||||
#define QSERDES_V4_COM_CORECLK_DIV_MODE1 0x16c
|
||||
#define QSERDES_V4_COM_SVS_MODE_CLK_SEL 0x184
|
||||
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x1ac
|
||||
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x1b0
|
||||
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1 0x1b4
|
||||
@ -341,12 +361,16 @@
|
||||
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x1b8
|
||||
|
||||
/* Only for QMP V4 PHY - TX registers */
|
||||
#define QSERDES_V4_TX_RES_CODE_LANE_TX 0x34
|
||||
#define QSERDES_V4_TX_RES_CODE_LANE_RX 0x38
|
||||
#define QSERDES_V4_TX_LANE_MODE_1 0x84
|
||||
#define QSERDES_V4_TX_RCV_DETECT_LVL_2 0x9c
|
||||
#define QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1 0xd8
|
||||
#define QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1 0xdC
|
||||
#define QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1 0xe0
|
||||
#define QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1 0xe4
|
||||
#define QSERDES_V4_TX_TRAN_DRVR_EMP_EN 0xb8
|
||||
#define QSERDES_V4_TX_PI_QEC_CTRL 0x104
|
||||
|
||||
/* Only for QMP V4 PHY - RX registers */
|
||||
#define QSERDES_V4_RX_UCDR_FO_GAIN 0x008
|
||||
@ -354,17 +378,27 @@
|
||||
#define QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN 0x030
|
||||
#define QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034
|
||||
#define QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW 0x03c
|
||||
#define QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH 0x040
|
||||
#define QSERDES_V4_RX_UCDR_PI_CONTROLS 0x044
|
||||
#define QSERDES_V4_RX_UCDR_PI_CTRL2 0x048
|
||||
#define QSERDES_V4_RX_UCDR_SB2_THRESH1 0x04c
|
||||
#define QSERDES_V4_RX_UCDR_SB2_THRESH2 0x050
|
||||
#define QSERDES_V4_RX_UCDR_SB2_GAIN1 0x054
|
||||
#define QSERDES_V4_RX_UCDR_SB2_GAIN2 0x058
|
||||
#define QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE 0x060
|
||||
#define QSERDES_V4_RX_AC_JTAG_ENABLE 0x068
|
||||
#define QSERDES_V4_RX_AC_JTAG_MODE 0x078
|
||||
#define QSERDES_V4_RX_RX_TERM_BW 0x080
|
||||
#define QSERDES_V4_RX_VGA_CAL_CNTRL1 0x0d4
|
||||
#define QSERDES_V4_RX_VGA_CAL_CNTRL2 0x0d8
|
||||
#define QSERDES_V4_RX_GM_CAL 0x0dc
|
||||
#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2 0x0ec
|
||||
#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3 0x0f0
|
||||
#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4 0x0f4
|
||||
#define QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW 0x0f8
|
||||
#define QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH 0x0fc
|
||||
#define QSERDES_V4_RX_RX_IDAC_MEASURE_TIME 0x100
|
||||
#define QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110
|
||||
#define QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x114
|
||||
#define QSERDES_V4_RX_SIGDET_CNTRL 0x11c
|
||||
#define QSERDES_V4_RX_SIGDET_LVL 0x120
|
||||
@ -385,29 +419,32 @@
|
||||
#define QSERDES_V4_RX_RX_MODE_10_HIGH2 0x1a0
|
||||
#define QSERDES_V4_RX_RX_MODE_10_HIGH3 0x1a4
|
||||
#define QSERDES_V4_RX_RX_MODE_10_HIGH4 0x1a8
|
||||
#define QSERDES_V4_RX_DFE_EN_TIMER 0x1b4
|
||||
#define QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET 0x1b8
|
||||
#define QSERDES_V4_RX_DCC_CTRL1 0x1bc
|
||||
#define QSERDES_V4_RX_VTH_CODE 0x1c4
|
||||
|
||||
/* Only for QMP V4 PHY - PCS registers */
|
||||
#define QPHY_V4_PHY_START 0x000
|
||||
#define QPHY_V4_POWER_DOWN_CONTROL 0x004
|
||||
#define QPHY_V4_SW_RESET 0x008
|
||||
#define QPHY_V4_TIMER_20US_CORECLK_STEPS_MSB 0x00c
|
||||
#define QPHY_V4_TIMER_20US_CORECLK_STEPS_LSB 0x010
|
||||
#define QPHY_V4_PLL_CNTL 0x02c
|
||||
#define QPHY_V4_TX_LARGE_AMP_DRV_LVL 0x030
|
||||
#define QPHY_V4_TX_SMALL_AMP_DRV_LVL 0x038
|
||||
#define QPHY_V4_BIST_FIXED_PAT_CTRL 0x060
|
||||
#define QPHY_V4_TX_HSGEAR_CAPABILITY 0x074
|
||||
#define QPHY_V4_RX_HSGEAR_CAPABILITY 0x0b4
|
||||
#define QPHY_V4_DEBUG_BUS_CLKSEL 0x124
|
||||
#define QPHY_V4_LINECFG_DISABLE 0x148
|
||||
#define QPHY_V4_RX_MIN_HIBERN8_TIME 0x150
|
||||
#define QPHY_V4_RX_SIGDET_CTRL2 0x158
|
||||
#define QPHY_V4_TX_PWM_GEAR_BAND 0x160
|
||||
#define QPHY_V4_TX_HS_GEAR_BAND 0x168
|
||||
#define QPHY_V4_PCS_READY_STATUS 0x180
|
||||
#define QPHY_V4_TX_MID_TERM_CTRL1 0x1d8
|
||||
#define QPHY_V4_MULTI_LANE_CTRL1 0x1e0
|
||||
/* Only for QMP V4 PHY - UFS PCS registers */
|
||||
#define QPHY_V4_PCS_UFS_PHY_START 0x000
|
||||
#define QPHY_V4_PCS_UFS_POWER_DOWN_CONTROL 0x004
|
||||
#define QPHY_V4_PCS_UFS_SW_RESET 0x008
|
||||
#define QPHY_V4_PCS_UFS_TIMER_20US_CORECLK_STEPS_MSB 0x00c
|
||||
#define QPHY_V4_PCS_UFS_TIMER_20US_CORECLK_STEPS_LSB 0x010
|
||||
#define QPHY_V4_PCS_UFS_PLL_CNTL 0x02c
|
||||
#define QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL 0x030
|
||||
#define QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL 0x038
|
||||
#define QPHY_V4_PCS_UFS_BIST_FIXED_PAT_CTRL 0x060
|
||||
#define QPHY_V4_PCS_UFS_TX_HSGEAR_CAPABILITY 0x074
|
||||
#define QPHY_V4_PCS_UFS_RX_HSGEAR_CAPABILITY 0x0b4
|
||||
#define QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL 0x124
|
||||
#define QPHY_V4_PCS_UFS_LINECFG_DISABLE 0x148
|
||||
#define QPHY_V4_PCS_UFS_RX_MIN_HIBERN8_TIME 0x150
|
||||
#define QPHY_V4_PCS_UFS_RX_SIGDET_CTRL2 0x158
|
||||
#define QPHY_V4_PCS_UFS_TX_PWM_GEAR_BAND 0x160
|
||||
#define QPHY_V4_PCS_UFS_TX_HS_GEAR_BAND 0x168
|
||||
#define QPHY_V4_PCS_UFS_READY_STATUS 0x180
|
||||
#define QPHY_V4_PCS_UFS_TX_MID_TERM_CTRL1 0x1d8
|
||||
#define QPHY_V4_PCS_UFS_MULTI_LANE_CTRL1 0x1e0
|
||||
|
||||
/* PCIE GEN3 COM registers */
|
||||
#define PCIE_GEN3_QHP_COM_SSC_EN_CENTER 0x14
|
||||
@ -523,4 +560,161 @@
|
||||
#define PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG5 0x16c
|
||||
#define PCIE_GEN3_QHP_PHY_PCS_TX_RX_CONFIG 0x174
|
||||
|
||||
/* Only for QMP V4 PHY - USB/PCIe PCS registers */
|
||||
#define QPHY_V4_PCS_SW_RESET 0x000
|
||||
#define QPHY_V4_PCS_REVISION_ID0 0x004
|
||||
#define QPHY_V4_PCS_REVISION_ID1 0x008
|
||||
#define QPHY_V4_PCS_REVISION_ID2 0x00c
|
||||
#define QPHY_V4_PCS_REVISION_ID3 0x010
|
||||
#define QPHY_V4_PCS_PCS_STATUS1 0x014
|
||||
#define QPHY_V4_PCS_PCS_STATUS2 0x018
|
||||
#define QPHY_V4_PCS_PCS_STATUS3 0x01c
|
||||
#define QPHY_V4_PCS_PCS_STATUS4 0x020
|
||||
#define QPHY_V4_PCS_PCS_STATUS5 0x024
|
||||
#define QPHY_V4_PCS_PCS_STATUS6 0x028
|
||||
#define QPHY_V4_PCS_PCS_STATUS7 0x02c
|
||||
#define QPHY_V4_PCS_DEBUG_BUS_0_STATUS 0x030
|
||||
#define QPHY_V4_PCS_DEBUG_BUS_1_STATUS 0x034
|
||||
#define QPHY_V4_PCS_DEBUG_BUS_2_STATUS 0x038
|
||||
#define QPHY_V4_PCS_DEBUG_BUS_3_STATUS 0x03c
|
||||
#define QPHY_V4_PCS_POWER_DOWN_CONTROL 0x040
|
||||
#define QPHY_V4_PCS_START_CONTROL 0x044
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL1 0x048
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL2 0x04c
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL3 0x050
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL4 0x054
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL5 0x058
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL6 0x05c
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL7 0x060
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL8 0x064
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL1 0x068
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL2 0x06c
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL3 0x070
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL4 0x074
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL5 0x078
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL7 0x07c
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL8 0x080
|
||||
#define QPHY_V4_PCS_OUTSIG_SW_CTRL1 0x084
|
||||
#define QPHY_V4_PCS_OUTSIG_MX_CTRL1 0x088
|
||||
#define QPHY_V4_PCS_CLAMP_ENABLE 0x08c
|
||||
#define QPHY_V4_PCS_POWER_STATE_CONFIG1 0x090
|
||||
#define QPHY_V4_PCS_POWER_STATE_CONFIG2 0x094
|
||||
#define QPHY_V4_PCS_FLL_CNTRL1 0x098
|
||||
#define QPHY_V4_PCS_FLL_CNTRL2 0x09c
|
||||
#define QPHY_V4_PCS_FLL_CNT_VAL_L 0x0a0
|
||||
#define QPHY_V4_PCS_FLL_CNT_VAL_H_TOL 0x0a4
|
||||
#define QPHY_V4_PCS_FLL_MAN_CODE 0x0a8
|
||||
#define QPHY_V4_PCS_TEST_CONTROL1 0x0ac
|
||||
#define QPHY_V4_PCS_TEST_CONTROL2 0x0b0
|
||||
#define QPHY_V4_PCS_TEST_CONTROL3 0x0b4
|
||||
#define QPHY_V4_PCS_TEST_CONTROL4 0x0b8
|
||||
#define QPHY_V4_PCS_TEST_CONTROL5 0x0bc
|
||||
#define QPHY_V4_PCS_TEST_CONTROL6 0x0c0
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG1 0x0c4
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG2 0x0c8
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG3 0x0cc
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG4 0x0d0
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG5 0x0d4
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG6 0x0d8
|
||||
#define QPHY_V4_PCS_REFGEN_REQ_CONFIG1 0x0dc
|
||||
#define QPHY_V4_PCS_REFGEN_REQ_CONFIG2 0x0e0
|
||||
#define QPHY_V4_PCS_REFGEN_REQ_CONFIG3 0x0e4
|
||||
#define QPHY_V4_PCS_BIST_CTRL 0x0e8
|
||||
#define QPHY_V4_PCS_PRBS_POLY0 0x0ec
|
||||
#define QPHY_V4_PCS_PRBS_POLY1 0x0f0
|
||||
#define QPHY_V4_PCS_FIXED_PAT0 0x0f4
|
||||
#define QPHY_V4_PCS_FIXED_PAT1 0x0f8
|
||||
#define QPHY_V4_PCS_FIXED_PAT2 0x0fc
|
||||
#define QPHY_V4_PCS_FIXED_PAT3 0x100
|
||||
#define QPHY_V4_PCS_FIXED_PAT4 0x104
|
||||
#define QPHY_V4_PCS_FIXED_PAT5 0x108
|
||||
#define QPHY_V4_PCS_FIXED_PAT6 0x10c
|
||||
#define QPHY_V4_PCS_FIXED_PAT7 0x110
|
||||
#define QPHY_V4_PCS_FIXED_PAT8 0x114
|
||||
#define QPHY_V4_PCS_FIXED_PAT9 0x118
|
||||
#define QPHY_V4_PCS_FIXED_PAT10 0x11c
|
||||
#define QPHY_V4_PCS_FIXED_PAT11 0x120
|
||||
#define QPHY_V4_PCS_FIXED_PAT12 0x124
|
||||
#define QPHY_V4_PCS_FIXED_PAT13 0x128
|
||||
#define QPHY_V4_PCS_FIXED_PAT14 0x12c
|
||||
#define QPHY_V4_PCS_FIXED_PAT15 0x130
|
||||
#define QPHY_V4_PCS_TXMGN_CONFIG 0x134
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V0 0x138
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V1 0x13c
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V2 0x140
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V3 0x144
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V4 0x148
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V0_RS 0x14c
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V1_RS 0x150
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V2_RS 0x154
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V3_RS 0x158
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V4_RS 0x15c
|
||||
#define QPHY_V4_PCS_G3S2_TXMGN_MAIN 0x160
|
||||
#define QPHY_V4_PCS_G3S2_TXMGN_MAIN_RS 0x164
|
||||
#define QPHY_V4_PCS_G12S1_TXDEEMPH_M6DB 0x168
|
||||
#define QPHY_V4_PCS_G12S1_TXDEEMPH_M3P5DB 0x16c
|
||||
#define QPHY_V4_PCS_G3S2_PRE_GAIN 0x170
|
||||
#define QPHY_V4_PCS_G3S2_POST_GAIN 0x174
|
||||
#define QPHY_V4_PCS_G3S2_PRE_POST_OFFSET 0x178
|
||||
#define QPHY_V4_PCS_G3S2_PRE_GAIN_RS 0x17c
|
||||
#define QPHY_V4_PCS_G3S2_POST_GAIN_RS 0x180
|
||||
#define QPHY_V4_PCS_G3S2_PRE_POST_OFFSET_RS 0x184
|
||||
#define QPHY_V4_PCS_RX_SIGDET_LVL 0x188
|
||||
#define QPHY_V4_PCS_RX_SIGDET_DTCT_CNTRL 0x18c
|
||||
#define QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L 0x190
|
||||
#define QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H 0x194
|
||||
#define QPHY_V4_PCS_RATE_SLEW_CNTRL1 0x198
|
||||
#define QPHY_V4_PCS_RATE_SLEW_CNTRL2 0x19c
|
||||
#define QPHY_V4_PCS_PWRUP_RESET_DLY_TIME_AUXCLK 0x1a0
|
||||
#define QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L 0x1a4
|
||||
#define QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_H 0x1a8
|
||||
#define QPHY_V4_PCS_TSYNC_RSYNC_TIME 0x1ac
|
||||
#define QPHY_V4_PCS_CDR_RESET_TIME 0x1b0
|
||||
#define QPHY_V4_PCS_TSYNC_DLY_TIME 0x1b4
|
||||
#define QPHY_V4_PCS_ELECIDLE_DLY_SEL 0x1b8
|
||||
#define QPHY_V4_PCS_CMN_ACK_OUT_SEL 0x1bc
|
||||
#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG1 0x1c0
|
||||
#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG2 0x1c4
|
||||
#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG3 0x1c8
|
||||
#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG4 0x1cc
|
||||
#define QPHY_V4_PCS_PCS_TX_RX_CONFIG 0x1d0
|
||||
#define QPHY_V4_PCS_RX_IDLE_DTCT_CNTRL 0x1d4
|
||||
#define QPHY_V4_PCS_RX_DCC_CAL_CONFIG 0x1d8
|
||||
#define QPHY_V4_PCS_EQ_CONFIG1 0x1dc
|
||||
#define QPHY_V4_PCS_EQ_CONFIG2 0x1e0
|
||||
#define QPHY_V4_PCS_EQ_CONFIG3 0x1e4
|
||||
#define QPHY_V4_PCS_EQ_CONFIG4 0x1e8
|
||||
#define QPHY_V4_PCS_EQ_CONFIG5 0x1ec
|
||||
#define QPHY_V4_PCS_USB3_POWER_STATE_CONFIG1 0x300
|
||||
#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_STATUS 0x304
|
||||
#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL 0x308
|
||||
#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL2 0x30c
|
||||
#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_SOURCE_STATUS 0x310
|
||||
#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR 0x314
|
||||
#define QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL 0x318
|
||||
#define QPHY_V4_PCS_USB3_LFPS_TX_ECSTART 0x31c
|
||||
#define QPHY_V4_PCS_USB3_LFPS_PER_TIMER_VAL 0x320
|
||||
#define QPHY_V4_PCS_USB3_LFPS_TX_END_CNT_U3_START 0x324
|
||||
#define QPHY_V4_PCS_USB3_RXEQTRAINING_LOCK_TIME 0x328
|
||||
#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME 0x32c
|
||||
#define QPHY_V4_PCS_USB3_RXEQTRAINING_CTLE_TIME 0x330
|
||||
#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME_S2 0x334
|
||||
#define QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2 0x338
|
||||
#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_L 0x33c
|
||||
#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_H 0x340
|
||||
#define QPHY_V4_PCS_USB3_ARCVR_DTCT_EN_PERIOD 0x344
|
||||
#define QPHY_V4_PCS_USB3_ARCVR_DTCT_CM_DLY 0x348
|
||||
#define QPHY_V4_PCS_USB3_TXONESZEROS_RUN_LENGTH 0x34c
|
||||
#define QPHY_V4_PCS_USB3_ALFPS_DEGLITCH_VAL 0x350
|
||||
#define QPHY_V4_PCS_USB3_SIGDET_STARTUP_TIMER_VAL 0x354
|
||||
#define QPHY_V4_PCS_USB3_TEST_CONTROL 0x358
|
||||
|
||||
/* Only for QMP V4 PHY - PCS_MISC registers */
|
||||
#define QPHY_V4_PCS_MISC_TYPEC_CTRL 0x00
|
||||
#define QPHY_V4_PCS_MISC_TYPEC_PWRDN_CTRL 0x04
|
||||
#define QPHY_V4_PCS_MISC_PCS_MISC_CONFIG1 0x08
|
||||
#define QPHY_V4_PCS_MISC_CLAMP_ENABLE 0x0c
|
||||
#define QPHY_V4_PCS_MISC_TYPEC_STATUS 0x10
|
||||
#define QPHY_V4_PCS_MISC_PLACEHOLDER_STATUS 0x14
|
||||
|
||||
#endif
|
||||
|
287
drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
Normal file
287
drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
Normal file
@ -0,0 +1,287 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define USB2_PHY_USB_PHY_UTMI_CTRL0 (0x3c)
|
||||
#define SLEEPM BIT(0)
|
||||
#define OPMODE_MASK GENMASK(4, 3)
|
||||
#define OPMODE_NORMAL (0x00)
|
||||
#define OPMODE_NONDRIVING BIT(3)
|
||||
#define TERMSEL BIT(5)
|
||||
|
||||
#define USB2_PHY_USB_PHY_UTMI_CTRL1 (0x40)
|
||||
#define XCVRSEL BIT(0)
|
||||
|
||||
#define USB2_PHY_USB_PHY_UTMI_CTRL5 (0x50)
|
||||
#define POR BIT(1)
|
||||
|
||||
#define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0 (0x54)
|
||||
#define RETENABLEN BIT(3)
|
||||
#define FSEL_MASK GENMASK(7, 5)
|
||||
#define FSEL_DEFAULT (0x3 << 4)
|
||||
|
||||
#define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1 (0x58)
|
||||
#define VBUSVLDEXTSEL0 BIT(4)
|
||||
#define PLLBTUNE BIT(5)
|
||||
|
||||
#define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2 (0x5c)
|
||||
#define VREGBYPASS BIT(0)
|
||||
|
||||
#define USB2_PHY_USB_PHY_HS_PHY_CTRL1 (0x60)
|
||||
#define VBUSVLDEXT0 BIT(0)
|
||||
|
||||
#define USB2_PHY_USB_PHY_HS_PHY_CTRL2 (0x64)
|
||||
#define USB2_AUTO_RESUME BIT(0)
|
||||
#define USB2_SUSPEND_N BIT(2)
|
||||
#define USB2_SUSPEND_N_SEL BIT(3)
|
||||
|
||||
#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)
|
||||
|
||||
#define USB2_PHY_USB_PHY_REFCLK_CTRL (0xa0)
|
||||
#define REFCLK_SEL_MASK GENMASK(1, 0)
|
||||
#define REFCLK_SEL_DEFAULT (0x2 << 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 qcom_snps_hsphy - snps hs phy attributes
|
||||
*
|
||||
* @phy: generic phy
|
||||
* @base: iomapped memory space for snps hs phy
|
||||
*
|
||||
* @cfg_ahb_clk: AHB2PHY interface clock
|
||||
* @ref_clk: phy reference clock
|
||||
* @iface_clk: phy interface clock
|
||||
* @phy_reset: phy reset control
|
||||
* @vregs: regulator supplies bulk data
|
||||
* @phy_initialized: if PHY has been initialized correctly
|
||||
*/
|
||||
struct qcom_snps_hsphy {
|
||||
struct phy *phy;
|
||||
void __iomem *base;
|
||||
|
||||
struct clk *cfg_ahb_clk;
|
||||
struct clk *ref_clk;
|
||||
struct reset_control *phy_reset;
|
||||
struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS];
|
||||
|
||||
bool phy_initialized;
|
||||
};
|
||||
|
||||
static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset,
|
||||
u32 mask, u32 val)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = readl_relaxed(base + offset);
|
||||
reg &= ~mask;
|
||||
reg |= val & mask;
|
||||
writel_relaxed(reg, base + offset);
|
||||
|
||||
/* Ensure above write is completed */
|
||||
readl_relaxed(base + offset);
|
||||
}
|
||||
|
||||
static int qcom_snps_hsphy_init(struct phy *phy)
|
||||
{
|
||||
struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
|
||||
int ret;
|
||||
|
||||
dev_vdbg(&phy->dev, "%s(): Initializing SNPS HS phy\n", __func__);
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(hsphy->cfg_ahb_clk);
|
||||
if (ret) {
|
||||
dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret);
|
||||
goto poweroff_phy;
|
||||
}
|
||||
|
||||
ret = reset_control_assert(hsphy->phy_reset);
|
||||
if (ret) {
|
||||
dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
|
||||
goto disable_ahb_clk;
|
||||
}
|
||||
|
||||
usleep_range(100, 150);
|
||||
|
||||
ret = reset_control_deassert(hsphy->phy_reset);
|
||||
if (ret) {
|
||||
dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
|
||||
goto disable_ahb_clk;
|
||||
}
|
||||
|
||||
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
|
||||
UTMI_PHY_CMN_CTRL_OVERRIDE_EN,
|
||||
UTMI_PHY_CMN_CTRL_OVERRIDE_EN);
|
||||
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5,
|
||||
POR, POR);
|
||||
qcom_snps_hsphy_write_mask(hsphy->base,
|
||||
USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0,
|
||||
FSEL_MASK, 0);
|
||||
qcom_snps_hsphy_write_mask(hsphy->base,
|
||||
USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1,
|
||||
PLLBTUNE, PLLBTUNE);
|
||||
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_REFCLK_CTRL,
|
||||
REFCLK_SEL_DEFAULT, REFCLK_SEL_MASK);
|
||||
qcom_snps_hsphy_write_mask(hsphy->base,
|
||||
USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1,
|
||||
VBUSVLDEXTSEL0, VBUSVLDEXTSEL0);
|
||||
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL1,
|
||||
VBUSVLDEXT0, VBUSVLDEXT0);
|
||||
|
||||
qcom_snps_hsphy_write_mask(hsphy->base,
|
||||
USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2,
|
||||
VREGBYPASS, VREGBYPASS);
|
||||
|
||||
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2,
|
||||
USB2_SUSPEND_N_SEL | USB2_SUSPEND_N,
|
||||
USB2_SUSPEND_N_SEL | USB2_SUSPEND_N);
|
||||
|
||||
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL0,
|
||||
SLEEPM, SLEEPM);
|
||||
|
||||
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5,
|
||||
POR, 0);
|
||||
|
||||
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2,
|
||||
USB2_SUSPEND_N_SEL, 0);
|
||||
|
||||
qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
|
||||
UTMI_PHY_CMN_CTRL_OVERRIDE_EN, 0);
|
||||
|
||||
hsphy->phy_initialized = true;
|
||||
|
||||
return 0;
|
||||
|
||||
disable_ahb_clk:
|
||||
clk_disable_unprepare(hsphy->cfg_ahb_clk);
|
||||
poweroff_phy:
|
||||
regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_snps_hsphy_exit(struct phy *phy)
|
||||
{
|
||||
struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
|
||||
|
||||
reset_control_assert(hsphy->phy_reset);
|
||||
clk_disable_unprepare(hsphy->cfg_ahb_clk);
|
||||
regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
|
||||
hsphy->phy_initialized = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ops qcom_snps_hsphy_gen_ops = {
|
||||
.init = qcom_snps_hsphy_init,
|
||||
.exit = qcom_snps_hsphy_exit,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct of_device_id qcom_snps_hsphy_of_match_table[] = {
|
||||
{ .compatible = "qcom,sm8150-usb-hs-phy", },
|
||||
{ .compatible = "qcom,usb-snps-hs-7nm-phy", },
|
||||
{ .compatible = "qcom,usb-snps-femto-v2-phy", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_snps_hsphy_of_match_table);
|
||||
|
||||
static int qcom_snps_hsphy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct qcom_snps_hsphy *hsphy;
|
||||
struct phy_provider *phy_provider;
|
||||
struct phy *generic_phy;
|
||||
int ret, i;
|
||||
int num;
|
||||
|
||||
hsphy = devm_kzalloc(dev, sizeof(*hsphy), GFP_KERNEL);
|
||||
if (!hsphy)
|
||||
return -ENOMEM;
|
||||
|
||||
hsphy->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(hsphy->base))
|
||||
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;
|
||||
}
|
||||
|
||||
hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
if (IS_ERR(hsphy->phy_reset)) {
|
||||
dev_err(dev, "failed to get phy core reset\n");
|
||||
return PTR_ERR(hsphy->phy_reset);
|
||||
}
|
||||
|
||||
num = ARRAY_SIZE(hsphy->vregs);
|
||||
for (i = 0; i < num; i++)
|
||||
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;
|
||||
}
|
||||
|
||||
generic_phy = devm_phy_create(dev, NULL, &qcom_snps_hsphy_gen_ops);
|
||||
if (IS_ERR(generic_phy)) {
|
||||
ret = PTR_ERR(generic_phy);
|
||||
dev_err(dev, "failed to create phy, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
hsphy->phy = generic_phy;
|
||||
|
||||
dev_set_drvdata(dev, hsphy);
|
||||
phy_set_drvdata(generic_phy, hsphy);
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
if (!IS_ERR(phy_provider))
|
||||
dev_dbg(dev, "Registered Qcom-SNPS HS phy\n");
|
||||
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
}
|
||||
|
||||
static struct platform_driver qcom_snps_hsphy_driver = {
|
||||
.probe = qcom_snps_hsphy_probe,
|
||||
.driver = {
|
||||
.name = "qcom-snps-hs-femto-v2-phy",
|
||||
.of_match_table = qcom_snps_hsphy_of_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(qcom_snps_hsphy_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Qualcomm SNPS FEMTO USB HS PHY V2 driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -139,6 +139,10 @@ static void s5pv210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
|
||||
udelay(10);
|
||||
rst &= ~rstbits;
|
||||
writel(rst, drv->reg_phy + S5PV210_UPHYRST);
|
||||
/* The following delay is necessary for the reset sequence to be
|
||||
* completed
|
||||
*/
|
||||
udelay(80);
|
||||
} else {
|
||||
pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
|
||||
pwr |= phypwr;
|
||||
|
@ -77,6 +77,7 @@ static struct regmap_config serdes_am654_regmap_config = {
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.fast_io = true,
|
||||
.max_register = 0x1ffc,
|
||||
};
|
||||
|
||||
static const struct reg_field cmu_master_cdn_o = REG_FIELD(CMU_R07C, 24, 24);
|
||||
@ -200,9 +201,91 @@ static int serdes_am654_power_off(struct phy *x)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serdes_am654_init(struct phy *x)
|
||||
#define SERDES_AM654_CFG(offset, a, b, val) \
|
||||
regmap_update_bits(phy->regmap, (offset),\
|
||||
GENMASK((a), (b)), (val) << (b))
|
||||
|
||||
static int serdes_am654_usb3_init(struct serdes_am654 *phy)
|
||||
{
|
||||
SERDES_AM654_CFG(0x0000, 31, 24, 0x17);
|
||||
SERDES_AM654_CFG(0x0004, 15, 8, 0x02);
|
||||
SERDES_AM654_CFG(0x0004, 7, 0, 0x0e);
|
||||
SERDES_AM654_CFG(0x0008, 23, 16, 0x2e);
|
||||
SERDES_AM654_CFG(0x0008, 31, 24, 0x2e);
|
||||
SERDES_AM654_CFG(0x0060, 7, 0, 0x4b);
|
||||
SERDES_AM654_CFG(0x0060, 15, 8, 0x98);
|
||||
SERDES_AM654_CFG(0x0060, 23, 16, 0x60);
|
||||
SERDES_AM654_CFG(0x00d0, 31, 24, 0x45);
|
||||
SERDES_AM654_CFG(0x00e8, 15, 8, 0x0e);
|
||||
SERDES_AM654_CFG(0x0220, 7, 0, 0x34);
|
||||
SERDES_AM654_CFG(0x0220, 15, 8, 0x34);
|
||||
SERDES_AM654_CFG(0x0220, 31, 24, 0x37);
|
||||
SERDES_AM654_CFG(0x0224, 7, 0, 0x37);
|
||||
SERDES_AM654_CFG(0x0224, 15, 8, 0x37);
|
||||
SERDES_AM654_CFG(0x0228, 23, 16, 0x37);
|
||||
SERDES_AM654_CFG(0x0228, 31, 24, 0x37);
|
||||
SERDES_AM654_CFG(0x022c, 7, 0, 0x37);
|
||||
SERDES_AM654_CFG(0x022c, 15, 8, 0x37);
|
||||
SERDES_AM654_CFG(0x0230, 15, 8, 0x2a);
|
||||
SERDES_AM654_CFG(0x0230, 23, 16, 0x2a);
|
||||
SERDES_AM654_CFG(0x0240, 23, 16, 0x10);
|
||||
SERDES_AM654_CFG(0x0240, 31, 24, 0x34);
|
||||
SERDES_AM654_CFG(0x0244, 7, 0, 0x40);
|
||||
SERDES_AM654_CFG(0x0244, 23, 16, 0x34);
|
||||
SERDES_AM654_CFG(0x0248, 15, 8, 0x0d);
|
||||
SERDES_AM654_CFG(0x0258, 15, 8, 0x16);
|
||||
SERDES_AM654_CFG(0x0258, 23, 16, 0x84);
|
||||
SERDES_AM654_CFG(0x0258, 31, 24, 0xf2);
|
||||
SERDES_AM654_CFG(0x025c, 7, 0, 0x21);
|
||||
SERDES_AM654_CFG(0x0260, 7, 0, 0x27);
|
||||
SERDES_AM654_CFG(0x0260, 15, 8, 0x04);
|
||||
SERDES_AM654_CFG(0x0268, 15, 8, 0x04);
|
||||
SERDES_AM654_CFG(0x0288, 15, 8, 0x2c);
|
||||
SERDES_AM654_CFG(0x0330, 31, 24, 0xa0);
|
||||
SERDES_AM654_CFG(0x0338, 23, 16, 0x03);
|
||||
SERDES_AM654_CFG(0x0338, 31, 24, 0x00);
|
||||
SERDES_AM654_CFG(0x033c, 7, 0, 0x00);
|
||||
SERDES_AM654_CFG(0x0344, 31, 24, 0x18);
|
||||
SERDES_AM654_CFG(0x034c, 7, 0, 0x18);
|
||||
SERDES_AM654_CFG(0x039c, 23, 16, 0x3b);
|
||||
SERDES_AM654_CFG(0x0a04, 7, 0, 0x03);
|
||||
SERDES_AM654_CFG(0x0a14, 31, 24, 0x3c);
|
||||
SERDES_AM654_CFG(0x0a18, 15, 8, 0x3c);
|
||||
SERDES_AM654_CFG(0x0a38, 7, 0, 0x3e);
|
||||
SERDES_AM654_CFG(0x0a38, 15, 8, 0x3e);
|
||||
SERDES_AM654_CFG(0x0ae0, 7, 0, 0x07);
|
||||
SERDES_AM654_CFG(0x0b6c, 23, 16, 0xcd);
|
||||
SERDES_AM654_CFG(0x0b6c, 31, 24, 0x04);
|
||||
SERDES_AM654_CFG(0x0b98, 23, 16, 0x03);
|
||||
SERDES_AM654_CFG(0x1400, 7, 0, 0x3f);
|
||||
SERDES_AM654_CFG(0x1404, 23, 16, 0x6f);
|
||||
SERDES_AM654_CFG(0x1404, 31, 24, 0x6f);
|
||||
SERDES_AM654_CFG(0x140c, 7, 0, 0x6f);
|
||||
SERDES_AM654_CFG(0x140c, 15, 8, 0x6f);
|
||||
SERDES_AM654_CFG(0x1410, 15, 8, 0x27);
|
||||
SERDES_AM654_CFG(0x1414, 7, 0, 0x0c);
|
||||
SERDES_AM654_CFG(0x1414, 23, 16, 0x07);
|
||||
SERDES_AM654_CFG(0x1418, 23, 16, 0x40);
|
||||
SERDES_AM654_CFG(0x141c, 7, 0, 0x00);
|
||||
SERDES_AM654_CFG(0x141c, 15, 8, 0x1f);
|
||||
SERDES_AM654_CFG(0x1428, 31, 24, 0x08);
|
||||
SERDES_AM654_CFG(0x1434, 31, 24, 0x00);
|
||||
SERDES_AM654_CFG(0x1444, 7, 0, 0x94);
|
||||
SERDES_AM654_CFG(0x1460, 31, 24, 0x7f);
|
||||
SERDES_AM654_CFG(0x1464, 7, 0, 0x43);
|
||||
SERDES_AM654_CFG(0x1464, 23, 16, 0x6f);
|
||||
SERDES_AM654_CFG(0x1464, 31, 24, 0x43);
|
||||
SERDES_AM654_CFG(0x1484, 23, 16, 0x8f);
|
||||
SERDES_AM654_CFG(0x1498, 7, 0, 0x4f);
|
||||
SERDES_AM654_CFG(0x1498, 23, 16, 0x4f);
|
||||
SERDES_AM654_CFG(0x007c, 31, 24, 0x0d);
|
||||
SERDES_AM654_CFG(0x0b90, 15, 8, 0x0f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serdes_am654_pcie_init(struct serdes_am654 *phy)
|
||||
{
|
||||
struct serdes_am654 *phy = phy_get_drvdata(x);
|
||||
int ret;
|
||||
|
||||
ret = regmap_field_write(phy->config_version, VERSION);
|
||||
@ -220,11 +303,28 @@ static int serdes_am654_init(struct phy *x)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serdes_am654_init(struct phy *x)
|
||||
{
|
||||
struct serdes_am654 *phy = phy_get_drvdata(x);
|
||||
|
||||
switch (phy->type) {
|
||||
case PHY_TYPE_PCIE:
|
||||
return serdes_am654_pcie_init(phy);
|
||||
case PHY_TYPE_USB3:
|
||||
return serdes_am654_usb3_init(phy);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int serdes_am654_reset(struct phy *x)
|
||||
{
|
||||
struct serdes_am654 *phy = phy_get_drvdata(x);
|
||||
int ret;
|
||||
|
||||
serdes_am654_disable_pll(phy);
|
||||
serdes_am654_disable_txrx(phy);
|
||||
|
||||
ret = regmap_field_write(phy->por_en, 0x1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <dt-bindings/phy/phy.h>
|
||||
|
||||
#define WIZ_SERDES_CTRL 0x404
|
||||
#define WIZ_SERDES_TOP_CTRL 0x408
|
||||
@ -78,6 +79,8 @@ static const struct reg_field p_enable[WIZ_MAX_LANES] = {
|
||||
REG_FIELD(WIZ_LANECTL(3), 30, 31),
|
||||
};
|
||||
|
||||
enum p_enable { P_ENABLE = 2, P_ENABLE_FORCE = 1, P_ENABLE_DISABLE = 0 };
|
||||
|
||||
static const struct reg_field p_align[WIZ_MAX_LANES] = {
|
||||
REG_FIELD(WIZ_LANECTL(0), 29, 29),
|
||||
REG_FIELD(WIZ_LANECTL(1), 29, 29),
|
||||
@ -220,6 +223,7 @@ struct wiz {
|
||||
struct reset_controller_dev wiz_phy_reset_dev;
|
||||
struct gpio_desc *gpio_typec_dir;
|
||||
int typec_dir_delay;
|
||||
u32 lane_phy_type[WIZ_MAX_LANES];
|
||||
};
|
||||
|
||||
static int wiz_reset(struct wiz *wiz)
|
||||
@ -242,12 +246,17 @@ static int wiz_reset(struct wiz *wiz)
|
||||
static int wiz_mode_select(struct wiz *wiz)
|
||||
{
|
||||
u32 num_lanes = wiz->num_lanes;
|
||||
enum wiz_lane_standard_mode mode;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_lanes; i++) {
|
||||
ret = regmap_field_write(wiz->p_standard_mode[i],
|
||||
LANE_MODE_GEN4);
|
||||
if (wiz->lane_phy_type[i] == PHY_TYPE_DP)
|
||||
mode = LANE_MODE_GEN1;
|
||||
else
|
||||
mode = LANE_MODE_GEN4;
|
||||
|
||||
ret = regmap_field_write(wiz->p_standard_mode[i], mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -707,7 +716,7 @@ static int wiz_phy_reset_assert(struct reset_controller_dev *rcdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_field_write(wiz->p_enable[id - 1], false);
|
||||
ret = regmap_field_write(wiz->p_enable[id - 1], P_ENABLE_DISABLE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -734,7 +743,11 @@ static int wiz_phy_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_field_write(wiz->p_enable[id - 1], true);
|
||||
if (wiz->lane_phy_type[id - 1] == PHY_TYPE_DP)
|
||||
ret = regmap_field_write(wiz->p_enable[id - 1], P_ENABLE);
|
||||
else
|
||||
ret = regmap_field_write(wiz->p_enable[id - 1], P_ENABLE_FORCE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -761,6 +774,40 @@ static const struct of_device_id wiz_id_table[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, wiz_id_table);
|
||||
|
||||
static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz)
|
||||
{
|
||||
struct device_node *serdes, *subnode;
|
||||
|
||||
serdes = of_get_child_by_name(dev->of_node, "serdes");
|
||||
if (!serdes) {
|
||||
dev_err(dev, "%s: Getting \"serdes\"-node failed\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for_each_child_of_node(serdes, subnode) {
|
||||
u32 reg, num_lanes = 1, phy_type = PHY_NONE;
|
||||
int ret, i;
|
||||
|
||||
ret = of_property_read_u32(subnode, "reg", ®);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"%s: Reading \"reg\" from \"%s\" failed: %d\n",
|
||||
__func__, subnode->name, ret);
|
||||
return ret;
|
||||
}
|
||||
of_property_read_u32(subnode, "cdns,num-lanes", &num_lanes);
|
||||
of_property_read_u32(subnode, "cdns,phy-type", &phy_type);
|
||||
|
||||
dev_dbg(dev, "%s: Lanes %u-%u have phy-type %u\n", __func__,
|
||||
reg, reg + num_lanes - 1, phy_type);
|
||||
|
||||
for (i = reg; i < reg + num_lanes; i++)
|
||||
wiz->lane_phy_type[i] = phy_type;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wiz_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct reset_controller_dev *phy_reset_dev;
|
||||
@ -794,8 +841,10 @@ static int wiz_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
base = devm_ioremap(dev, res.start, resource_size(&res));
|
||||
if (!base)
|
||||
if (!base) {
|
||||
ret = -ENOMEM;
|
||||
goto err_addr_to_resource;
|
||||
}
|
||||
|
||||
regmap = devm_regmap_init_mmio(dev, base, &wiz_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
@ -812,6 +861,7 @@ static int wiz_probe(struct platform_device *pdev)
|
||||
|
||||
if (num_lanes > WIZ_MAX_LANES) {
|
||||
dev_err(dev, "Cannot support %d lanes\n", num_lanes);
|
||||
ret = -ENODEV;
|
||||
goto err_addr_to_resource;
|
||||
}
|
||||
|
||||
@ -844,6 +894,10 @@ static int wiz_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
ret = wiz_get_lane_phy_types(dev, wiz);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
wiz->dev = dev;
|
||||
wiz->regmap = regmap;
|
||||
wiz->num_lanes = num_lanes;
|
||||
@ -897,6 +951,7 @@ static int wiz_probe(struct platform_device *pdev)
|
||||
serdes_pdev = of_platform_device_create(child_node, NULL, dev);
|
||||
if (!serdes_pdev) {
|
||||
dev_WARN(dev, "Unable to create SERDES platform device\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_pdev_create;
|
||||
}
|
||||
wiz->serdes_pdev = serdes_pdev;
|
||||
|
@ -1,8 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* omap-usb2.c - USB PHY, talking to musb controller in OMAP.
|
||||
* omap-usb2.c - USB PHY, talking to USB controller on TI SoCs.
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
|
||||
* Copyright (C) 2012-2020 Texas Instruments Incorporated - http://www.ti.com
|
||||
* Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||||
*/
|
||||
|
||||
@ -23,13 +23,65 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#define USB2PHY_DISCON_BYP_LATCH (1 << 31)
|
||||
#define USB2PHY_ANA_CONFIG1 0x4c
|
||||
#define USB2PHY_ANA_CONFIG1 0x4c
|
||||
#define USB2PHY_DISCON_BYP_LATCH BIT(31)
|
||||
|
||||
/* SoC Specific USB2_OTG register definitions */
|
||||
#define AM654_USB2_OTG_PD BIT(8)
|
||||
#define AM654_USB2_VBUS_DET_EN BIT(5)
|
||||
#define AM654_USB2_VBUSVALID_DET_EN BIT(4)
|
||||
|
||||
#define OMAP_DEV_PHY_PD BIT(0)
|
||||
#define OMAP_USB2_PHY_PD BIT(28)
|
||||
|
||||
#define AM437X_USB2_PHY_PD BIT(0)
|
||||
#define AM437X_USB2_OTG_PD BIT(1)
|
||||
#define AM437X_USB2_OTGVDET_EN BIT(19)
|
||||
#define AM437X_USB2_OTGSESSEND_EN BIT(20)
|
||||
|
||||
/* Driver Flags */
|
||||
#define OMAP_USB2_HAS_START_SRP BIT(0)
|
||||
#define OMAP_USB2_HAS_SET_VBUS BIT(1)
|
||||
#define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT BIT(2)
|
||||
|
||||
struct omap_usb {
|
||||
struct usb_phy phy;
|
||||
struct phy_companion *comparator;
|
||||
void __iomem *pll_ctrl_base;
|
||||
void __iomem *phy_base;
|
||||
struct device *dev;
|
||||
struct device *control_dev;
|
||||
struct clk *wkupclk;
|
||||
struct clk *optclk;
|
||||
u8 flags;
|
||||
struct regmap *syscon_phy_power; /* ctrl. reg. acces */
|
||||
unsigned int power_reg; /* power reg. index within syscon */
|
||||
u32 mask;
|
||||
u32 power_on;
|
||||
u32 power_off;
|
||||
};
|
||||
|
||||
#define phy_to_omapusb(x) container_of((x), struct omap_usb, phy)
|
||||
|
||||
struct usb_phy_data {
|
||||
const char *label;
|
||||
u8 flags;
|
||||
u32 mask;
|
||||
u32 power_on;
|
||||
u32 power_off;
|
||||
};
|
||||
|
||||
static inline u32 omap_usb_readl(void __iomem *addr, unsigned int offset)
|
||||
{
|
||||
return __raw_readl(addr + offset);
|
||||
}
|
||||
|
||||
static inline void omap_usb_writel(void __iomem *addr, unsigned int offset,
|
||||
u32 data)
|
||||
{
|
||||
__raw_writel(data, addr + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* omap_usb2_set_comparator - links the comparator present in the sytem with
|
||||
* this phy
|
||||
|
@ -17,5 +17,6 @@
|
||||
#define PHY_TYPE_USB3 4
|
||||
#define PHY_TYPE_UFS 5
|
||||
#define PHY_TYPE_DP 6
|
||||
#define PHY_TYPE_XPCS 7
|
||||
|
||||
#endif /* _DT_BINDINGS_PHY */
|
||||
|
@ -2,68 +2,14 @@
|
||||
/*
|
||||
* omap_usb.h -- omap usb2 phy header file
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
|
||||
* Copyright (C) 2012-2020 Texas Instruments Incorporated - http://www.ti.com
|
||||
* Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_OMAP_USB2_H
|
||||
#define __DRIVERS_OMAP_USB2_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/usb/otg.h>
|
||||
|
||||
struct usb_dpll_params {
|
||||
u16 m;
|
||||
u8 n;
|
||||
u8 freq:3;
|
||||
u8 sd;
|
||||
u32 mf;
|
||||
};
|
||||
|
||||
enum omap_usb_phy_type {
|
||||
TYPE_USB2, /* USB2_PHY, power down in CONTROL_DEV_CONF */
|
||||
TYPE_DRA7USB2, /* USB2 PHY, power and power_aux e.g. DRA7 */
|
||||
TYPE_AM437USB2, /* USB2 PHY, power e.g. AM437x */
|
||||
};
|
||||
|
||||
struct omap_usb {
|
||||
struct usb_phy phy;
|
||||
struct phy_companion *comparator;
|
||||
void __iomem *pll_ctrl_base;
|
||||
void __iomem *phy_base;
|
||||
struct device *dev;
|
||||
struct device *control_dev;
|
||||
struct clk *wkupclk;
|
||||
struct clk *optclk;
|
||||
u8 flags;
|
||||
enum omap_usb_phy_type type;
|
||||
struct regmap *syscon_phy_power; /* ctrl. reg. acces */
|
||||
unsigned int power_reg; /* power reg. index within syscon */
|
||||
u32 mask;
|
||||
u32 power_on;
|
||||
u32 power_off;
|
||||
};
|
||||
|
||||
struct usb_phy_data {
|
||||
const char *label;
|
||||
u8 flags;
|
||||
u32 mask;
|
||||
u32 power_on;
|
||||
u32 power_off;
|
||||
};
|
||||
|
||||
/* Driver Flags */
|
||||
#define OMAP_USB2_HAS_START_SRP (1 << 0)
|
||||
#define OMAP_USB2_HAS_SET_VBUS (1 << 1)
|
||||
#define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT (1 << 2)
|
||||
|
||||
#define OMAP_DEV_PHY_PD BIT(0)
|
||||
#define OMAP_USB2_PHY_PD BIT(28)
|
||||
|
||||
#define AM437X_USB2_PHY_PD BIT(0)
|
||||
#define AM437X_USB2_OTG_PD BIT(1)
|
||||
#define AM437X_USB2_OTGVDET_EN BIT(19)
|
||||
#define AM437X_USB2_OTGSESSEND_EN BIT(20)
|
||||
#include <linux/usb/phy_companion.h>
|
||||
|
||||
#define phy_to_omapusb(x) container_of((x), struct omap_usb, phy)
|
||||
|
||||
@ -76,15 +22,4 @@ static inline int omap_usb2_set_comparator(struct phy_companion *comparator)
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline u32 omap_usb_readl(void __iomem *addr, unsigned offset)
|
||||
{
|
||||
return __raw_readl(addr + offset);
|
||||
}
|
||||
|
||||
static inline void omap_usb_writel(void __iomem *addr, unsigned offset,
|
||||
u32 data)
|
||||
{
|
||||
__raw_writel(data, addr + offset);
|
||||
}
|
||||
|
||||
#endif /* __DRIVERS_OMAP_USB_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user