phy: for 5.7

*) Rename and Re-design phy-cadence-dp driver to phy-cadence-torrent driver
 *) Add new PHY driver for Qualcomm 28nm Hi-Speed USB PHY
 *) Add new PHY driver for Qualcomm Super Speed PHY in QCS404
 *) Add support for Qualcomm PCIe QMP/QHP PHY in SDM845 to phy-qcom-qmp driver
 *) Add support for Qualcomm UFS PHY in MSM8996 to phy-qcom-qmp driver
 *) Add support for an additional reference clock in Mediatek phy-mtk-tphy driver
 *) Add support for configuring tuning parameters in Mediatek phy-mtk-tphy driver
 *) Add support for GMII PHY in TI K3 AM654x/J721E SoCs to phy-gmii-sel driver
 *) Add support for USB2 PHY in Amlogic A1 SoC Family to phy-meson-g12a-usb2
    driver
 *) Add support for USB3/USB2/PCIe PHY in Socionext Pro5 SoC to
    phy-uniphier-usb3ss/phy-uniphier-usb3hs/phy-uniphier-pcie driver respectively
 *) Add support for QUSB2 PHY in Qualcomm SC7180 in driver
 *) Convert dt-bindings of Cadence DP, Qualcomm QUSB2 to YAML format
 
 Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCgAsFiEEUXMr/TfP2p4suIY5Dlx4XIBNgtkFAl51P+IOHGtpc2hvbkB0
 aS5jb20ACgkQDlx4XIBNgtmEUQ//cnSP2uYWIfi7UXEMBqSMjwOeGqG8mLNNaLFh
 L3+AXf60I78wHvnPOu3u5kGi5P82YnkDeBnxKhElrNxtcv3iWxHswU2DKwr3i+/S
 OsPgBKTvYYoqcpeM/nf2hYZWJ8DofA0wuQ2o7n67Ldrm+QWORZzwohir0JAiNCl9
 5+XAQo7gnQqUrsfQ1uuCkcYVM5hoE/7HebaxcXMYDdPfttz+QhZZ4XjHgh4KAiGO
 MHn0aiF6nNJz465Un6YF+rFAcQjkl8R7WK93hCW2YPU2l2nvR+Z7cc7GfVIWPoss
 Rv9dUDtdXEJxPxZNaaQWqx+fyr3JmRm3hM53oj/aocZkxzH9omt+HNA5F98EP9S7
 X9YbxG/xRkf0sTfHFJbrGKZMXJn6u+jmJP54R3YhHqt1oBtHyQ1nCaqWLg3Lj7gx
 vaAV50dtwA0jkZVxP2iyAfGUBxG2NlDLeDZt7XUxZWGOyrwbujqt4PcxMyxS1tRs
 LHaT4xDBqR2pLbElx3omnx2q5U2wAW37yUzDMQ+q9mFHJhSMZ+vwkk418cleMaQE
 itu3Lg0I3uy3WIYj7V/xkAhEHH+MclmaBLOdtAA0Je75Zw8p6yDubv93A5lEmlrY
 P5ePuhgi/jBUqfYrtbzAP3v+vkC10auDDmA3342AaILwZ6LkWz6sqa8w6urT+6za
 2twcuWI=
 =+CzV
 -----END PGP SIGNATURE-----

Merge tag 'phy-for-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-next

Kishon writes:

phy: for 5.7

*) Rename and Re-design phy-cadence-dp driver to phy-cadence-torrent driver
*) Add new PHY driver for Qualcomm 28nm Hi-Speed USB PHY
*) Add new PHY driver for Qualcomm Super Speed PHY in QCS404
*) Add support for Qualcomm PCIe QMP/QHP PHY in SDM845 to phy-qcom-qmp driver
*) Add support for Qualcomm UFS PHY in MSM8996 to phy-qcom-qmp driver
*) Add support for an additional reference clock in Mediatek phy-mtk-tphy driver
*) Add support for configuring tuning parameters in Mediatek phy-mtk-tphy driver
*) Add support for GMII PHY in TI K3 AM654x/J721E SoCs to phy-gmii-sel driver
*) Add support for USB2 PHY in Amlogic A1 SoC Family to phy-meson-g12a-usb2
   driver
*) Add support for USB3/USB2/PCIe PHY in Socionext Pro5 SoC to
   phy-uniphier-usb3ss/phy-uniphier-usb3hs/phy-uniphier-pcie driver respectively
*) Add support for QUSB2 PHY in Qualcomm SC7180 in driver
*) Convert dt-bindings of Cadence DP, Qualcomm QUSB2 to YAML format

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

* tag 'phy-for-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy: (52 commits)
  phy: qcom-qusb2: Add new overriding tuning parameters in QUSB2 V2 PHY
  phy: qcom-qusb2: Add support for overriding tuning parameters in QUSB2 V2 PHY
  dt-bindings: phy: qcom-qusb2: Add support for overriding Phy tuning parameters
  phy: qcom-qusb2: Add generic QUSB2 V2 PHY support
  dt-bindings: phy: qcom,qusb2: Add compatibles for QUSB2 V2 phy and SC7180
  dt-bindings: phy: qcom,qusb2: Convert QUSB2 phy bindings to yaml
  phy: rk-inno-usb2: Decrease verbosity of repeating log.
  phy: amlogic: Add Amlogic A1 USB2 PHY Driver
  dt-bindings: phy: Add Amlogic A1 USB2 PHY Bindings
  phy: ti: gmii-sel: add support for am654x/j721e soc
  dt-bindings: phy: ti: gmii-sel: add support for am654x/j721e soc
  phy: qualcomm: usb: Add SuperSpeed PHY driver
  dt-bindings: Add Qualcomm USB SuperSpeed PHY bindings
  phy: qualcomm: Add Synopsys 28nm Hi-Speed USB PHY driver
  dt-bindings: phy: Add Qualcomm Synopsys Hi-Speed USB PHY binding
  dt-bindings: phy: remove qcom-dwc3-usb-phy
  phy: phy-mtk-tphy: add a new reference clock
  phy: phy-mtk-tphy: remove unused u3phya_ref clock
  phy: phy-mtk-tphy: make the ref clock optional
  phy: phy-mtk-tphy: add a property for internal resistance
  ...
This commit is contained in:
Greg Kroah-Hartman 2020-03-21 12:02:20 +01:00
commit e79220db63
32 changed files with 4120 additions and 837 deletions

View file

@ -14,6 +14,7 @@ properties:
compatible:
enum:
- amlogic,meson-g12a-usb2-phy
- amlogic,meson-a1-usb2-phy
reg:
maxItems: 1
@ -49,6 +50,19 @@ required:
- reset-names
- "#phy-cells"
if:
properties:
compatible:
enum:
- amlogic,meson-a1-usb-ctrl
then:
properties:
power-domains:
maxItems: 1
required:
- power-domains
examples:
- |
phy@36000 {

View file

@ -1,30 +0,0 @@
Cadence MHDP DisplayPort SD0801 PHY binding
===========================================
This binding describes the Cadence SD0801 PHY hardware included with
the Cadence MHDP DisplayPort controller.
-------------------------------------------------------------------------------
Required properties (controller (parent) node):
- compatible : Should be "cdns,dp-phy"
- reg : Defines the following sets of registers in the parent
mhdp device:
- Offset of the DPTX PHY configuration registers
- Offset of the SD0801 PHY configuration registers
- #phy-cells : from the generic PHY bindings, must be 0.
Optional properties:
- num_lanes : Number of DisplayPort lanes to use (1, 2 or 4)
- max_bit_rate : Maximum DisplayPort link bit rate to use, in Mbps (2160,
2430, 2700, 3240, 4320, 5400 or 8100)
-------------------------------------------------------------------------------
Example:
dp_phy: phy@f0fb030a00 {
compatible = "cdns,dp-phy";
reg = <0xf0 0xfb030a00 0x0 0x00000040>,
<0xf0 0xfb500000 0x0 0x00100000>;
num_lanes = <4>;
max_bit_rate = <8100>;
#phy-cells = <0>;
};

View file

@ -0,0 +1,143 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/phy/phy-cadence-torrent.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Cadence Torrent SD0801 PHY binding for DisplayPort
description:
This binding describes the Cadence SD0801 PHY (also known as Torrent PHY)
hardware included with the Cadence MHDP DisplayPort controller.
maintainers:
- Swapnil Jakhade <sjakhade@cadence.com>
- Yuti Amonkar <yamonkar@cadence.com>
properties:
compatible:
enum:
- cdns,torrent-phy
- ti,j721e-serdes-10g
'#address-cells':
const: 1
'#size-cells':
const: 0
clocks:
maxItems: 1
description:
PHY reference clock. Must contain an entry in clock-names.
clock-names:
const: refclk
reg:
minItems: 1
maxItems: 2
items:
- description: Offset of the Torrent PHY configuration registers.
- description: Offset of the DPTX PHY configuration registers.
reg-names:
minItems: 1
maxItems: 2
items:
- const: torrent_phy
- const: dptx_phy
resets:
maxItems: 1
description:
Torrent PHY reset.
See Documentation/devicetree/bindings/reset/reset.txt
patternProperties:
'^phy@[0-7]+$':
type: object
description:
Each group of PHY lanes with a single master lane should be represented as a sub-node.
properties:
reg:
description:
The master lane number. This is the lowest numbered lane in the lane group.
resets:
minItems: 1
maxItems: 4
description:
Contains list of resets, one per lane, to get all the link lanes out of reset.
"#phy-cells":
const: 0
cdns,phy-type:
description:
Specifies the type of PHY for which the group of PHY lanes is used.
Refer include/dt-bindings/phy/phy.h. Constants from the header should be used.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [1, 2, 3, 4, 5, 6]
cdns,num-lanes:
description:
Number of DisplayPort lanes.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [1, 2, 4]
default: 4
cdns,max-bit-rate:
description:
Maximum DisplayPort link bit rate to use, in Mbps
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [2160, 2430, 2700, 3240, 4320, 5400, 8100]
default: 8100
required:
- reg
- resets
- "#phy-cells"
- cdns,phy-type
additionalProperties: false
required:
- compatible
- "#address-cells"
- "#size-cells"
- clocks
- clock-names
- reg
- reg-names
- resets
additionalProperties: false
examples:
- |
#include <dt-bindings/phy/phy.h>
torrent_phy: torrent-phy@f0fb500000 {
compatible = "cdns,torrent-phy";
reg = <0xf0 0xfb500000 0x0 0x00100000>,
<0xf0 0xfb030a00 0x0 0x00000040>;
reg-names = "torrent_phy", "dptx_phy";
resets = <&phyrst 0>;
clocks = <&ref_clk>;
clock-names = "refclk";
#address-cells = <1>;
#size-cells = <0>;
torrent_phy_dp: phy@0 {
reg = <0>;
resets = <&phyrst 1>, <&phyrst 2>,
<&phyrst 3>, <&phyrst 4>;
#phy-cells = <0>;
cdns,phy-type = <PHY_TYPE_DP>;
cdns,num-lanes = <4>;
cdns,max-bit-rate = <8100>;
};
};
...

View file

@ -13,10 +13,16 @@ Required properties (controller (parent) node):
"mediatek,mt8173-u3phy";
make use of "mediatek,generic-tphy-v1" on mt2701 instead and
"mediatek,generic-tphy-v2" on mt2712 instead.
- clocks : (deprecated, use port's clocks instead) a list of phandle +
clock-specifier pairs, one for each entry in clock-names
- clock-names : (deprecated, use port's one instead) must contain
"u3phya_ref": for reference clock of usb3.0 analog phy.
- #address-cells: the number of cells used to represent physical
base addresses.
- #size-cells: the number of cells used to represent the size of an address.
- ranges: the address mapping relationship to the parent, defined with
- empty value: if optional 'reg' is used.
- non-empty value: if optional 'reg' is not used. should set
the child's base address to 0, the physical address
within parent's address space, and the length of
the address map.
Required nodes : a sub-node is required for each port the controller
provides. Address range information including the usual
@ -34,12 +40,6 @@ Optional properties (controller (parent) node):
Required properties (port (child) node):
- reg : address and length of the register set for the port.
- clocks : a list of phandle + clock-specifier pairs, one for each
entry in clock-names
- clock-names : must contain
"ref": 48M reference clock for HighSpeed analog phy; and 26M
reference clock for SuperSpeed analog phy, sometimes is
24M, 25M or 27M, depended on platform.
- #phy-cells : should be 1 (See second example)
cell after port phandle is phy type from:
- PHY_TYPE_USB2
@ -48,10 +48,22 @@ Required properties (port (child) node):
- PHY_TYPE_SATA
Optional properties (PHY_TYPE_USB2 port (child) node):
- clocks : a list of phandle + clock-specifier pairs, one for each
entry in clock-names
- clock-names : may contain
"ref": 48M reference clock for HighSpeed (digital) phy; and 26M
reference clock for SuperSpeed (digital) phy, sometimes is
24M, 25M or 27M, depended on platform.
"da_ref": the reference clock of analog phy, used if the clocks
of analog and digital phys are separated, otherwise uses
"ref" clock only if needed.
- mediatek,eye-src : u32, the value of slew rate calibrate
- mediatek,eye-vrt : u32, the selection of VRT reference voltage
- mediatek,eye-term : u32, the selection of HS_TX TERM reference voltage
- mediatek,bc12 : bool, enable BC12 of u2phy if support it
- mediatek,discth : u32, the selection of disconnect threshold
- mediatek,intr : u32, the selection of internal R (resistance)
Example:

View file

@ -0,0 +1,185 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/phy/qcom,qusb2-phy.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Qualcomm QUSB2 phy controller
maintainers:
- Manu Gautam <mgautam@codeaurora.org>
description:
QUSB2 controller supports LS/FS/HS usb connectivity on Qualcomm chipsets.
properties:
compatible:
oneOf:
- items:
- enum:
- qcom,msm8996-qusb2-phy
- qcom,msm8998-qusb2-phy
- items:
- enum:
- qcom,sc7180-qusb2-phy
- qcom,sdm845-qusb2-phy
- const: qcom,qusb2-v2-phy
reg:
maxItems: 1
"#phy-cells":
const: 0
clocks:
minItems: 2
maxItems: 3
items:
- description: phy config clock
- description: 19.2 MHz ref clk
- description: phy interface clock (Optional)
clock-names:
minItems: 2
maxItems: 3
items:
- const: cfg_ahb
- const: ref
- const: iface
vdda-pll-supply:
description:
Phandle to 1.8V regulator supply to PHY refclk pll block.
vdda-phy-dpdm-supply:
description:
Phandle to 3.1V regulator supply to Dp/Dm port signals.
resets:
maxItems: 1
description:
Phandle to reset to phy block.
nvmem-cells:
maxItems: 1
description:
Phandle to nvmem cell that contains 'HS Tx trim'
tuning parameter value for qusb2 phy.
qcom,tcsr-syscon:
description:
Phandle to TCSR syscon register region.
$ref: /schemas/types.yaml#/definitions/phandle
if:
properties:
compatible:
contains:
const: qcom,qusb2-v2-phy
then:
properties:
qcom,imp-res-offset-value:
description:
It is a 6 bit value that specifies offset to be
added to PHY refgen RESCODE via IMP_CTRL1 register. It is a PHY
tuning parameter that may vary for different boards of same SOC.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0
maximum: 63
default: 0
qcom,bias-ctrl-value:
description:
It is a 6 bit value that specifies bias-ctrl-value. It is a PHY
tuning parameter that may vary for different boards of same SOC.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0
maximum: 63
default: 0
qcom,charge-ctrl-value:
description:
It is a 2 bit value that specifies charge-ctrl-value. It is a PHY
tuning parameter that may vary for different boards of same SOC.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0
maximum: 3
default: 0
qcom,hstx-trim-value:
description:
It is a 4 bit value that specifies tuning for HSTX
output current.
Possible range is - 15mA to 24mA (stepsize of 600 uA).
See dt-bindings/phy/phy-qcom-qusb2.h for applicable values.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0
maximum: 15
default: 3
qcom,preemphasis-level:
description:
It is a 2 bit value that specifies pre-emphasis level.
Possible range is 0 to 15% (stepsize of 5%).
See dt-bindings/phy/phy-qcom-qusb2.h for applicable values.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0
maximum: 3
default: 2
qcom,preemphasis-width:
description:
It is a 1 bit value that specifies how long the HSTX
pre-emphasis (specified using qcom,preemphasis-level) must be in
effect. Duration could be half-bit of full-bit.
See dt-bindings/phy/phy-qcom-qusb2.h for applicable values.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0
maximum: 1
default: 0
qcom,hsdisc-trim-value:
description:
It is a 2 bit value tuning parameter that control disconnect
threshold and may vary for different boards of same SOC.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0
maximum: 3
default: 0
required:
- compatible
- reg
- "#phy-cells"
- clocks
- clock-names
- vdda-pll-supply
- vdda-phy-dpdm-supply
- resets
examples:
- |
#include <dt-bindings/clock/qcom,gcc-msm8996.h>
hsusb_phy: phy@7411000 {
compatible = "qcom,msm8996-qusb2-phy";
reg = <0x7411000 0x180>;
#phy-cells = <0>;
clocks = <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
<&gcc GCC_RX1_USB2_CLKREF_CLK>;
clock-names = "cfg_ahb", "ref";
vdda-pll-supply = <&pm8994_l12>;
vdda-phy-dpdm-supply = <&pm8994_l24>;
resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
nvmem-cells = <&qusb2p_hstx_trim>;
};

View file

@ -0,0 +1,90 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/phy/qcom,usb-hs-28nm.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Qualcomm Synopsys DesignWare Core 28nm High-Speed PHY
maintainers:
- Bryan O'Donoghue <bryan.odonoghue@linaro.org>
description: |
Qualcomm Low-Speed, Full-Speed, Hi-Speed 28nm USB PHY
properties:
compatible:
enum:
- qcom,usb-hs-28nm-femtophy
reg:
maxItems: 1
"#phy-cells":
const: 0
clocks:
items:
- description: rpmcc ref clock
- description: PHY AHB clock
- description: Rentention clock
clock-names:
items:
- const: ref
- const: ahb
- const: sleep
resets:
items:
- description: PHY core reset
- description: POR reset
reset-names:
items:
- const: phy
- const: por
vdd-supply:
description: phandle to the regulator VDD supply node.
vdda1p8-supply:
description: phandle to the regulator 1.8V supply node.
vdda3p3-supply:
description: phandle to the regulator 3.3V supply node.
required:
- compatible
- reg
- "#phy-cells"
- clocks
- clock-names
- resets
- reset-names
- vdd-supply
- vdda1p8-supply
- vdda3p3-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-qcs404.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
usb2_phy_prim: phy@7a000 {
compatible = "qcom,usb-hs-28nm-femtophy";
reg = <0x0007a000 0x200>;
#phy-cells = <0>;
clocks = <&rpmcc RPM_SMD_LN_BB_CLK>,
<&gcc GCC_USB_HS_PHY_CFG_AHB_CLK>,
<&gcc GCC_USB2A_PHY_SLEEP_CLK>;
clock-names = "ref", "ahb", "sleep";
resets = <&gcc GCC_USB_HS_PHY_CFG_AHB_BCR>,
<&gcc GCC_USB2A_PHY_BCR>;
reset-names = "phy", "por";
vdd-supply = <&vreg_l4_1p2>;
vdda1p8-supply = <&vreg_l5_1p8>;
vdda3p3-supply = <&vreg_l12_3p3>;
};
...

View file

@ -0,0 +1,83 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/phy/qcom,usb-ss.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Qualcomm Synopsys 1.0.0 SuperSpeed USB PHY
maintainers:
- Bryan O'Donoghue <bryan.odonoghue@linaro.org>
description: |
Qualcomm Synopsys 1.0.0 SuperSpeed USB PHY
properties:
compatible:
enum:
- qcom,usb-ss-28nm-phy
reg:
maxItems: 1
"#phy-cells":
const: 0
clocks:
items:
- description: rpmcc clock
- description: PHY AHB clock
- description: SuperSpeed pipe clock
clock-names:
items:
- const: ref
- const: ahb
- const: pipe
vdd-supply:
description: phandle to the regulator VDD supply node.
vdda1p8-supply:
description: phandle to the regulator 1.8V supply node.
resets:
items:
- description: COM reset
- description: PHY reset line
reset-names:
items:
- const: com
- const: phy
required:
- compatible
- reg
- "#phy-cells"
- clocks
- clock-names
- vdd-supply
- vdda1p8-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-qcs404.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
usb3_phy: usb3-phy@78000 {
compatible = "qcom,usb-ss-28nm-phy";
reg = <0x78000 0x400>;
#phy-cells = <0>;
clocks = <&rpmcc RPM_SMD_LN_BB_CLK>,
<&gcc GCC_USB_HS_PHY_CFG_AHB_CLK>,
<&gcc GCC_USB3_PHY_PIPE_CLK>;
clock-names = "ref", "ahb", "pipe";
resets = <&gcc GCC_USB3_PHY_BCR>,
<&gcc GCC_USB3PHY_PHY_BCR>;
reset-names = "com", "phy";
vdd-supply = <&vreg_l3_1p05>;
vdda1p8-supply = <&vreg_l5_1p8>;
};
...

View file

@ -1,37 +0,0 @@
Qualcomm DWC3 HS AND SS PHY CONTROLLER
--------------------------------------
DWC3 PHY nodes are defined to describe on-chip Synopsis Physical layer
controllers. Each DWC3 PHY controller should have its own node.
Required properties:
- compatible: should contain one of the following:
- "qcom,dwc3-hs-usb-phy" for High Speed Synopsis PHY controller
- "qcom,dwc3-ss-usb-phy" for Super Speed Synopsis PHY controller
- reg: offset and length of the DWC3 PHY controller register set
- #phy-cells: must be zero
- clocks: a list of phandles and clock-specifier pairs, one for each entry in
clock-names.
- clock-names: Should contain "ref" for the PHY reference clock
Optional clocks:
"xo" External reference clock
Example:
phy@100f8800 {
compatible = "qcom,dwc3-hs-usb-phy";
reg = <0x100f8800 0x30>;
clocks = <&gcc USB30_0_UTMI_CLK>;
clock-names = "ref";
#phy-cells = <0>;
};
phy@100f8830 {
compatible = "qcom,dwc3-ss-usb-phy";
reg = <0x100f8830 0x30>;
clocks = <&gcc USB30_0_MASTER_CLK>;
clock-names = "ref";
#phy-cells = <0>;
};

View file

@ -8,10 +8,13 @@ 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,
@ -44,6 +47,8 @@ Required properties:
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:
@ -52,6 +57,10 @@ Required properties:
"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:
@ -72,6 +81,8 @@ Required properties:
"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
@ -80,6 +91,10 @@ Required properties:
"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:

View file

@ -1,68 +0,0 @@
Qualcomm QUSB2 phy controller
=============================
QUSB2 controller supports LS/FS/HS usb connectivity on Qualcomm chipsets.
Required properties:
- compatible: compatible list, contains
"qcom,msm8996-qusb2-phy" for 14nm PHY on msm8996,
"qcom,msm8998-qusb2-phy" for 10nm PHY on msm8998,
"qcom,sdm845-qusb2-phy" for 10nm PHY on sdm845.
- reg: offset and length of the PHY register set.
- #phy-cells: must be 0.
- clocks: a list of phandles and clock-specifier pairs,
one for each entry in clock-names.
- clock-names: must be "cfg_ahb" for phy config clock,
"ref" for 19.2 MHz ref clk,
"iface" for phy interface clock (Optional).
- vdda-pll-supply: Phandle to 1.8V regulator supply to PHY refclk pll block.
- vdda-phy-dpdm-supply: Phandle to 3.1V regulator supply to Dp/Dm port signals.
- resets: Phandle to reset to phy block.
Optional properties:
- nvmem-cells: Phandle to nvmem cell that contains 'HS Tx trim'
tuning parameter value for qusb2 phy.
- qcom,tcsr-syscon: Phandle to TCSR syscon register region.
- qcom,imp-res-offset-value: It is a 6 bit value that specifies offset to be
added to PHY refgen RESCODE via IMP_CTRL1 register. It is a PHY
tuning parameter that may vary for different boards of same SOC.
This property is applicable to only QUSB2 v2 PHY (sdm845).
- qcom,hstx-trim-value: It is a 4 bit value that specifies tuning for HSTX
output current.
Possible range is - 15mA to 24mA (stepsize of 600 uA).
See dt-bindings/phy/phy-qcom-qusb2.h for applicable values.
This property is applicable to only QUSB2 v2 PHY (sdm845).
Default value is 22.2mA for sdm845.
- qcom,preemphasis-level: It is a 2 bit value that specifies pre-emphasis level.
Possible range is 0 to 15% (stepsize of 5%).
See dt-bindings/phy/phy-qcom-qusb2.h for applicable values.
This property is applicable to only QUSB2 v2 PHY (sdm845).
Default value is 10% for sdm845.
- qcom,preemphasis-width: It is a 1 bit value that specifies how long the HSTX
pre-emphasis (specified using qcom,preemphasis-level) must be in
effect. Duration could be half-bit of full-bit.
See dt-bindings/phy/phy-qcom-qusb2.h for applicable values.
This property is applicable to only QUSB2 v2 PHY (sdm845).
Default value is full-bit width for sdm845.
Example:
hsusb_phy: phy@7411000 {
compatible = "qcom,msm8996-qusb2-phy";
reg = <0x7411000 0x180>;
#phy-cells = <0>;
clocks = <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
<&gcc GCC_RX1_USB2_CLKREF_CLK>,
clock-names = "cfg_ahb", "ref";
vdda-pll-supply = <&pm8994_l12>;
vdda-phy-dpdm-supply = <&pm8994_l24>;
resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
nvmem-cells = <&qusb2p_hstx_trim>;
};

View file

@ -40,6 +40,7 @@ Required properties:
"ti,dra7xx-phy-gmii-sel" for dra7xx/am57xx platform
"ti,am43xx-phy-gmii-sel" for am43xx platform
"ti,dm814-phy-gmii-sel" for dm814x platform
"ti,am654-phy-gmii-sel" for AM654x/J721E platform
- reg : Address and length of the register set for the device
- #phy-cells : must be 2.
cell 1 - CPSW port number (starting from 1)

View file

@ -5,14 +5,19 @@ PCIe controller implemented on Socionext UniPhier SoCs.
Required properties:
- compatible: Should contain one of the following:
"socionext,uniphier-pro5-pcie-phy" - for Pro5 PHY
"socionext,uniphier-ld20-pcie-phy" - for LD20 PHY
"socionext,uniphier-pxs3-pcie-phy" - for PXs3 PHY
- reg: Specifies offset and length of the register set for the device.
- #phy-cells: Must be zero.
- clocks: A phandle to the clock gate for PCIe glue layer including
this phy.
- resets: A phandle to the reset line for PCIe glue layer including
this phy.
- clocks: A list of phandles to the clock gate for PCIe glue layer
including this phy.
- clock-names: For Pro5 only, should contain the following:
"gio", "link" - for Pro5 SoC
- resets: A list of phandles to the reset line for PCIe glue layer
including this phy.
- reset-names: For Pro5 only, should contain the following:
"gio", "link" - for Pro5 SoC
Optional properties:
- socionext,syscon: A phandle to system control to set configurations

View file

@ -7,7 +7,7 @@ this describes about High-Speed PHY.
Required properties:
- compatible: Should contain one of the following:
"socionext,uniphier-pro4-usb3-hsphy" - for Pro4 SoC
"socionext,uniphier-pro5-usb3-hsphy" - for Pro5 SoC
"socionext,uniphier-pxs2-usb3-hsphy" - for PXs2 SoC
"socionext,uniphier-ld20-usb3-hsphy" - for LD20 SoC
"socionext,uniphier-pxs3-usb3-hsphy" - for PXs3 SoC
@ -16,13 +16,13 @@ Required properties:
- clocks: A list of phandles to the clock gate for USB3 glue layer.
According to the clock-names, appropriate clocks are required.
- clock-names: Should contain the following:
"gio", "link" - for Pro4 SoC
"gio", "link" - for Pro5 SoC
"phy", "phy-ext", "link" - for PXs3 SoC, "phy-ext" is optional.
"phy", "link" - for others
- resets: A list of phandles to the reset control for USB3 glue layer.
According to the reset-names, appropriate resets are required.
- reset-names: Should contain the following:
"gio", "link" - for Pro4 SoC
"gio", "link" - for Pro5 SoC
"phy", "link" - for others
Optional properties:

View file

@ -8,6 +8,7 @@ this describes about Super-Speed PHY.
Required properties:
- compatible: Should contain one of the following:
"socionext,uniphier-pro4-usb3-ssphy" - for Pro4 SoC
"socionext,uniphier-pro5-usb3-ssphy" - for Pro5 SoC
"socionext,uniphier-pxs2-usb3-ssphy" - for PXs2 SoC
"socionext,uniphier-ld20-usb3-ssphy" - for LD20 SoC
"socionext,uniphier-pxs3-usb3-ssphy" - for PXs3 SoC
@ -16,13 +17,13 @@ Required properties:
- clocks: A list of phandles to the clock gate for USB3 glue layer.
According to the clock-names, appropriate clocks are required.
- clock-names:
"gio", "link" - for Pro4 SoC
"gio", "link" - for Pro4 and Pro5 SoC
"phy", "phy-ext", "link" - for PXs3 SoC, "phy-ext" is optional.
"phy", "link" - for others
- resets: A list of phandles to the reset control for USB3 glue layer.
According to the reset-names, appropriate resets are required.
- reset-names:
"gio", "link" - for Pro4 SoC
"gio", "link" - for Pro4 and Pro5 SoC
"phy", "link" - for others
Optional properties:

View file

@ -66,7 +66,7 @@
#define PHY_CTRL_R14 0x38
#define PHY_CTRL_R14_I_RDP_EN BIT(0)
#define PHY_CTRL_R14_I_RPU_SW1_EN BIT(1)
#define PHY_CTRL_R14_I_RPU_SW2_EN GENMASK(2, 3)
#define PHY_CTRL_R14_I_RPU_SW2_EN GENMASK(3, 2)
#define PHY_CTRL_R14_PG_RSTN BIT(4)
#define PHY_CTRL_R14_I_C2L_DATA_16_8 BIT(5)
#define PHY_CTRL_R14_I_C2L_ASSERT_SINGLE_EN_ZERO BIT(6)
@ -146,11 +146,17 @@
#define RESET_COMPLETE_TIME 1000
#define PLL_RESET_COMPLETE_TIME 100
enum meson_soc_id {
MESON_SOC_G12A = 0,
MESON_SOC_A1,
};
struct phy_meson_g12a_usb2_priv {
struct device *dev;
struct regmap *regmap;
struct clk *clk;
struct reset_control *reset;
int soc_id;
};
static const struct regmap_config phy_meson_g12a_usb2_regmap_conf = {
@ -164,6 +170,7 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
{
struct phy_meson_g12a_usb2_priv *priv = phy_get_drvdata(phy);
int ret;
unsigned int value;
ret = reset_control_reset(priv->reset);
if (ret)
@ -192,18 +199,22 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT2, 2) |
FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT1, 9));
regmap_write(priv->regmap, PHY_CTRL_R18,
FIELD_PREP(PHY_CTRL_R18_MPLL_LKW_SEL, 1) |
FIELD_PREP(PHY_CTRL_R18_MPLL_LK_W, 9) |
FIELD_PREP(PHY_CTRL_R18_MPLL_LK_S, 0x27) |
FIELD_PREP(PHY_CTRL_R18_MPLL_PFD_GAIN, 1) |
FIELD_PREP(PHY_CTRL_R18_MPLL_ROU, 7) |
FIELD_PREP(PHY_CTRL_R18_MPLL_DATA_SEL, 3) |
FIELD_PREP(PHY_CTRL_R18_MPLL_BIAS_ADJ, 1) |
FIELD_PREP(PHY_CTRL_R18_MPLL_BB_MODE, 0) |
FIELD_PREP(PHY_CTRL_R18_MPLL_ALPHA, 3) |
FIELD_PREP(PHY_CTRL_R18_MPLL_ADJ_LDO, 1) |
PHY_CTRL_R18_MPLL_ACG_RANGE);
value = FIELD_PREP(PHY_CTRL_R18_MPLL_LKW_SEL, 1) |
FIELD_PREP(PHY_CTRL_R18_MPLL_LK_W, 9) |
FIELD_PREP(PHY_CTRL_R18_MPLL_LK_S, 0x27) |
FIELD_PREP(PHY_CTRL_R18_MPLL_PFD_GAIN, 1) |
FIELD_PREP(PHY_CTRL_R18_MPLL_ROU, 7) |
FIELD_PREP(PHY_CTRL_R18_MPLL_DATA_SEL, 3) |
FIELD_PREP(PHY_CTRL_R18_MPLL_BIAS_ADJ, 1) |
FIELD_PREP(PHY_CTRL_R18_MPLL_BB_MODE, 0) |
FIELD_PREP(PHY_CTRL_R18_MPLL_ALPHA, 3) |
FIELD_PREP(PHY_CTRL_R18_MPLL_ADJ_LDO, 1) |
PHY_CTRL_R18_MPLL_ACG_RANGE;
if (priv->soc_id == MESON_SOC_A1)
value |= PHY_CTRL_R18_MPLL_DCO_CLK_SEL;
regmap_write(priv->regmap, PHY_CTRL_R18, value);
udelay(PLL_RESET_COMPLETE_TIME);
@ -227,13 +238,24 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R20_USB2_BGR_VREF_4_0, 0) |
FIELD_PREP(PHY_CTRL_R20_USB2_BGR_DBG_1_0, 0));
regmap_write(priv->regmap, PHY_CTRL_R4,
FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_7_0, 0xf) |
FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_15_8, 0xf) |
FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_23_16, 0xf) |
PHY_CTRL_R4_TEST_BYPASS_MODE_EN |
FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0, 0) |
FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2, 0));
if (priv->soc_id == MESON_SOC_G12A)
regmap_write(priv->regmap, PHY_CTRL_R4,
FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_7_0, 0xf) |
FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_15_8, 0xf) |
FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_23_16, 0xf) |
PHY_CTRL_R4_TEST_BYPASS_MODE_EN |
FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0, 0) |
FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2, 0));
else if (priv->soc_id == MESON_SOC_A1) {
regmap_write(priv->regmap, PHY_CTRL_R21,
PHY_CTRL_R21_USB2_CAL_ACK_EN |
PHY_CTRL_R21_USB2_TX_STRG_PD |
FIELD_PREP(PHY_CTRL_R21_USB2_OTG_ACA_TRIM_1_0, 2));
/* Analog Settings */
regmap_write(priv->regmap, PHY_CTRL_R13,
FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));
}
/* Tuning Disconnect Threshold */
regmap_write(priv->regmap, PHY_CTRL_R3,
@ -241,11 +263,13 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R3_HSDIC_REF, 1) |
FIELD_PREP(PHY_CTRL_R3_DISC_THRESH, 3));
/* Analog Settings */
regmap_write(priv->regmap, PHY_CTRL_R14, 0);
regmap_write(priv->regmap, PHY_CTRL_R13,
PHY_CTRL_R13_UPDATE_PMA_SIGNALS |
FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));
if (priv->soc_id == MESON_SOC_G12A) {
/* Analog Settings */
regmap_write(priv->regmap, PHY_CTRL_R14, 0);
regmap_write(priv->regmap, PHY_CTRL_R13,
PHY_CTRL_R13_UPDATE_PMA_SIGNALS |
FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));
}
return 0;
}
@ -286,6 +310,8 @@ static int phy_meson_g12a_usb2_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
priv->soc_id = (enum meson_soc_id)of_device_get_match_data(&pdev->dev);
priv->regmap = devm_regmap_init_mmio(dev, base,
&phy_meson_g12a_usb2_regmap_conf);
if (IS_ERR(priv->regmap))
@ -321,8 +347,15 @@ static int phy_meson_g12a_usb2_probe(struct platform_device *pdev)
}
static const struct of_device_id phy_meson_g12a_usb2_of_match[] = {
{ .compatible = "amlogic,g12a-usb2-phy", },
{ },
{
.compatible = "amlogic,g12a-usb2-phy",
.data = (void *)MESON_SOC_G12A,
},
{
.compatible = "amlogic,a1-usb2-phy",
.data = (void *)MESON_SOC_A1,
},
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, phy_meson_g12a_usb2_of_match);

View file

@ -3,13 +3,13 @@
# Phy drivers for Cadence PHYs
#
config PHY_CADENCE_DP
tristate "Cadence MHDP DisplayPort PHY driver"
config PHY_CADENCE_TORRENT
tristate "Cadence Torrent PHY driver"
depends on OF
depends on HAS_IOMEM
select GENERIC_PHY
help
Support for Cadence MHDP DisplayPort PHY.
Support for Cadence Torrent PHY.
config PHY_CADENCE_DPHY
tristate "Cadence D-PHY Support"

View file

@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_PHY_CADENCE_DP) += phy-cadence-dp.o
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

View file

@ -1,541 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Cadence MHDP DisplayPort SD0801 PHY driver.
*
* Copyright 2018 Cadence Design Systems, Inc.
*
*/
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#define DEFAULT_NUM_LANES 2
#define MAX_NUM_LANES 4
#define DEFAULT_MAX_BIT_RATE 8100 /* in Mbps */
#define POLL_TIMEOUT_US 2000
#define LANE_MASK 0x7
/*
* register offsets from DPTX PHY register block base (i.e MHDP
* register base + 0x30a00)
*/
#define PHY_AUX_CONFIG 0x00
#define PHY_AUX_CTRL 0x04
#define PHY_RESET 0x20
#define PHY_PMA_XCVR_PLLCLK_EN 0x24
#define PHY_PMA_XCVR_PLLCLK_EN_ACK 0x28
#define PHY_PMA_XCVR_POWER_STATE_REQ 0x2c
#define PHY_POWER_STATE_LN_0 0x0000
#define PHY_POWER_STATE_LN_1 0x0008
#define PHY_POWER_STATE_LN_2 0x0010
#define PHY_POWER_STATE_LN_3 0x0018
#define PHY_PMA_XCVR_POWER_STATE_ACK 0x30
#define PHY_PMA_CMN_READY 0x34
#define PHY_PMA_XCVR_TX_VMARGIN 0x38
#define PHY_PMA_XCVR_TX_DEEMPH 0x3c
/*
* register offsets from SD0801 PHY register block base (i.e MHDP
* register base + 0x500000)
*/
#define CMN_SSM_BANDGAP_TMR 0x00084
#define CMN_SSM_BIAS_TMR 0x00088
#define CMN_PLLSM0_PLLPRE_TMR 0x000a8
#define CMN_PLLSM0_PLLLOCK_TMR 0x000b0
#define CMN_PLLSM1_PLLPRE_TMR 0x000c8
#define CMN_PLLSM1_PLLLOCK_TMR 0x000d0
#define CMN_BGCAL_INIT_TMR 0x00190
#define CMN_BGCAL_ITER_TMR 0x00194
#define CMN_IBCAL_INIT_TMR 0x001d0
#define CMN_PLL0_VCOCAL_INIT_TMR 0x00210
#define CMN_PLL0_VCOCAL_ITER_TMR 0x00214
#define CMN_PLL0_VCOCAL_REFTIM_START 0x00218
#define CMN_PLL0_VCOCAL_PLLCNT_START 0x00220
#define CMN_PLL0_INTDIV_M0 0x00240
#define CMN_PLL0_FRACDIVL_M0 0x00244
#define CMN_PLL0_FRACDIVH_M0 0x00248
#define CMN_PLL0_HIGH_THR_M0 0x0024c
#define CMN_PLL0_DSM_DIAG_M0 0x00250
#define CMN_PLL0_LOCK_PLLCNT_START 0x00278
#define CMN_PLL1_VCOCAL_INIT_TMR 0x00310
#define CMN_PLL1_VCOCAL_ITER_TMR 0x00314
#define CMN_PLL1_DSM_DIAG_M0 0x00350
#define CMN_TXPUCAL_INIT_TMR 0x00410
#define CMN_TXPUCAL_ITER_TMR 0x00414
#define CMN_TXPDCAL_INIT_TMR 0x00430
#define CMN_TXPDCAL_ITER_TMR 0x00434
#define CMN_RXCAL_INIT_TMR 0x00450
#define CMN_RXCAL_ITER_TMR 0x00454
#define CMN_SD_CAL_INIT_TMR 0x00490
#define CMN_SD_CAL_ITER_TMR 0x00494
#define CMN_SD_CAL_REFTIM_START 0x00498
#define CMN_SD_CAL_PLLCNT_START 0x004a0
#define CMN_PDIAG_PLL0_CTRL_M0 0x00680
#define CMN_PDIAG_PLL0_CLK_SEL_M0 0x00684
#define CMN_PDIAG_PLL0_CP_PADJ_M0 0x00690
#define CMN_PDIAG_PLL0_CP_IADJ_M0 0x00694
#define CMN_PDIAG_PLL0_FILT_PADJ_M0 0x00698
#define CMN_PDIAG_PLL0_CP_PADJ_M1 0x006d0
#define CMN_PDIAG_PLL0_CP_IADJ_M1 0x006d4
#define CMN_PDIAG_PLL1_CLK_SEL_M0 0x00704
#define XCVR_DIAG_PLLDRC_CTRL 0x10394
#define XCVR_DIAG_HSCLK_SEL 0x10398
#define XCVR_DIAG_HSCLK_DIV 0x1039c
#define TX_PSC_A0 0x10400
#define TX_PSC_A1 0x10404
#define TX_PSC_A2 0x10408
#define TX_PSC_A3 0x1040c
#define RX_PSC_A0 0x20000
#define RX_PSC_A1 0x20004
#define RX_PSC_A2 0x20008
#define RX_PSC_A3 0x2000c
#define PHY_PLL_CFG 0x30038
struct cdns_dp_phy {
void __iomem *base; /* DPTX registers base */
void __iomem *sd_base; /* SD0801 registers base */
u32 num_lanes; /* Number of lanes to use */
u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */
struct device *dev;
};
static int cdns_dp_phy_init(struct phy *phy);
static void cdns_dp_phy_run(struct cdns_dp_phy *cdns_phy);
static void cdns_dp_phy_wait_pma_cmn_ready(struct cdns_dp_phy *cdns_phy);
static void cdns_dp_phy_pma_cfg(struct cdns_dp_phy *cdns_phy);
static void cdns_dp_phy_pma_cmn_cfg_25mhz(struct cdns_dp_phy *cdns_phy);
static void cdns_dp_phy_pma_lane_cfg(struct cdns_dp_phy *cdns_phy,
unsigned int lane);
static void cdns_dp_phy_pma_cmn_vco_cfg_25mhz(struct cdns_dp_phy *cdns_phy);
static void cdns_dp_phy_pma_cmn_rate(struct cdns_dp_phy *cdns_phy);
static void cdns_dp_phy_write_field(struct cdns_dp_phy *cdns_phy,
unsigned int offset,
unsigned char start_bit,
unsigned char num_bits,
unsigned int val);
static const struct phy_ops cdns_dp_phy_ops = {
.init = cdns_dp_phy_init,
.owner = THIS_MODULE,
};
static int cdns_dp_phy_init(struct phy *phy)
{
unsigned char lane_bits;
struct cdns_dp_phy *cdns_phy = phy_get_drvdata(phy);
writel(0x0003, cdns_phy->base + PHY_AUX_CTRL); /* enable AUX */
/* PHY PMA registers configuration function */
cdns_dp_phy_pma_cfg(cdns_phy);
/*
* Set lines power state to A0
* Set lines pll clk enable to 0
*/
cdns_dp_phy_write_field(cdns_phy, PHY_PMA_XCVR_POWER_STATE_REQ,
PHY_POWER_STATE_LN_0, 6, 0x0000);
if (cdns_phy->num_lanes >= 2) {
cdns_dp_phy_write_field(cdns_phy,
PHY_PMA_XCVR_POWER_STATE_REQ,
PHY_POWER_STATE_LN_1, 6, 0x0000);
if (cdns_phy->num_lanes == 4) {
cdns_dp_phy_write_field(cdns_phy,
PHY_PMA_XCVR_POWER_STATE_REQ,
PHY_POWER_STATE_LN_2, 6, 0);
cdns_dp_phy_write_field(cdns_phy,
PHY_PMA_XCVR_POWER_STATE_REQ,
PHY_POWER_STATE_LN_3, 6, 0);
}
}
cdns_dp_phy_write_field(cdns_phy, PHY_PMA_XCVR_PLLCLK_EN,
0, 1, 0x0000);
if (cdns_phy->num_lanes >= 2) {
cdns_dp_phy_write_field(cdns_phy, PHY_PMA_XCVR_PLLCLK_EN,
1, 1, 0x0000);
if (cdns_phy->num_lanes == 4) {
cdns_dp_phy_write_field(cdns_phy,
PHY_PMA_XCVR_PLLCLK_EN,
2, 1, 0x0000);
cdns_dp_phy_write_field(cdns_phy,
PHY_PMA_XCVR_PLLCLK_EN,
3, 1, 0x0000);
}
}
/*
* release phy_l0*_reset_n and pma_tx_elec_idle_ln_* based on
* used lanes
*/
lane_bits = (1 << cdns_phy->num_lanes) - 1;
writel(((0xF & ~lane_bits) << 4) | (0xF & lane_bits),
cdns_phy->base + PHY_RESET);
/* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
writel(0x0001, cdns_phy->base + PHY_PMA_XCVR_PLLCLK_EN);
/* PHY PMA registers configuration functions */
cdns_dp_phy_pma_cmn_vco_cfg_25mhz(cdns_phy);
cdns_dp_phy_pma_cmn_rate(cdns_phy);
/* take out of reset */
cdns_dp_phy_write_field(cdns_phy, PHY_RESET, 8, 1, 1);
cdns_dp_phy_wait_pma_cmn_ready(cdns_phy);
cdns_dp_phy_run(cdns_phy);
return 0;
}
static void cdns_dp_phy_wait_pma_cmn_ready(struct cdns_dp_phy *cdns_phy)
{
unsigned int reg;
int ret;
ret = readl_poll_timeout(cdns_phy->base + PHY_PMA_CMN_READY, reg,
reg & 1, 0, 500);
if (ret == -ETIMEDOUT)
dev_err(cdns_phy->dev,
"timeout waiting for PMA common ready\n");
}
static void cdns_dp_phy_pma_cfg(struct cdns_dp_phy *cdns_phy)
{
unsigned int i;
/* PMA common configuration */
cdns_dp_phy_pma_cmn_cfg_25mhz(cdns_phy);
/* PMA lane configuration to deal with multi-link operation */
for (i = 0; i < cdns_phy->num_lanes; i++)
cdns_dp_phy_pma_lane_cfg(cdns_phy, i);
}
static void cdns_dp_phy_pma_cmn_cfg_25mhz(struct cdns_dp_phy *cdns_phy)
{
/* refclock registers - assumes 25 MHz refclock */
writel(0x0019, cdns_phy->sd_base + CMN_SSM_BIAS_TMR);
writel(0x0032, cdns_phy->sd_base + CMN_PLLSM0_PLLPRE_TMR);
writel(0x00D1, cdns_phy->sd_base + CMN_PLLSM0_PLLLOCK_TMR);
writel(0x0032, cdns_phy->sd_base + CMN_PLLSM1_PLLPRE_TMR);
writel(0x00D1, cdns_phy->sd_base + CMN_PLLSM1_PLLLOCK_TMR);
writel(0x007D, cdns_phy->sd_base + CMN_BGCAL_INIT_TMR);
writel(0x007D, cdns_phy->sd_base + CMN_BGCAL_ITER_TMR);
writel(0x0019, cdns_phy->sd_base + CMN_IBCAL_INIT_TMR);
writel(0x001E, cdns_phy->sd_base + CMN_TXPUCAL_INIT_TMR);
writel(0x0006, cdns_phy->sd_base + CMN_TXPUCAL_ITER_TMR);
writel(0x001E, cdns_phy->sd_base + CMN_TXPDCAL_INIT_TMR);
writel(0x0006, cdns_phy->sd_base + CMN_TXPDCAL_ITER_TMR);
writel(0x02EE, cdns_phy->sd_base + CMN_RXCAL_INIT_TMR);
writel(0x0006, cdns_phy->sd_base + CMN_RXCAL_ITER_TMR);
writel(0x0002, cdns_phy->sd_base + CMN_SD_CAL_INIT_TMR);
writel(0x0002, cdns_phy->sd_base + CMN_SD_CAL_ITER_TMR);
writel(0x000E, cdns_phy->sd_base + CMN_SD_CAL_REFTIM_START);
writel(0x012B, cdns_phy->sd_base + CMN_SD_CAL_PLLCNT_START);
/* PLL registers */
writel(0x0409, cdns_phy->sd_base + CMN_PDIAG_PLL0_CP_PADJ_M0);
writel(0x1001, cdns_phy->sd_base + CMN_PDIAG_PLL0_CP_IADJ_M0);
writel(0x0F08, cdns_phy->sd_base + CMN_PDIAG_PLL0_FILT_PADJ_M0);
writel(0x0004, cdns_phy->sd_base + CMN_PLL0_DSM_DIAG_M0);
writel(0x00FA, cdns_phy->sd_base + CMN_PLL0_VCOCAL_INIT_TMR);
writel(0x0004, cdns_phy->sd_base + CMN_PLL0_VCOCAL_ITER_TMR);
writel(0x00FA, cdns_phy->sd_base + CMN_PLL1_VCOCAL_INIT_TMR);
writel(0x0004, cdns_phy->sd_base + CMN_PLL1_VCOCAL_ITER_TMR);
writel(0x0318, cdns_phy->sd_base + CMN_PLL0_VCOCAL_REFTIM_START);
}
static void cdns_dp_phy_pma_cmn_vco_cfg_25mhz(struct cdns_dp_phy *cdns_phy)
{
/* Assumes 25 MHz refclock */
switch (cdns_phy->max_bit_rate) {
/* Setting VCO for 10.8GHz */
case 2700:
case 5400:
writel(0x01B0, cdns_phy->sd_base + CMN_PLL0_INTDIV_M0);
writel(0x0000, cdns_phy->sd_base + CMN_PLL0_FRACDIVL_M0);
writel(0x0002, cdns_phy->sd_base + CMN_PLL0_FRACDIVH_M0);
writel(0x0120, cdns_phy->sd_base + CMN_PLL0_HIGH_THR_M0);
break;
/* Setting VCO for 9.72GHz */
case 2430:
case 3240:
writel(0x0184, cdns_phy->sd_base + CMN_PLL0_INTDIV_M0);
writel(0xCCCD, cdns_phy->sd_base + CMN_PLL0_FRACDIVL_M0);
writel(0x0002, cdns_phy->sd_base + CMN_PLL0_FRACDIVH_M0);
writel(0x0104, cdns_phy->sd_base + CMN_PLL0_HIGH_THR_M0);
break;
/* Setting VCO for 8.64GHz */
case 2160:
case 4320:
writel(0x0159, cdns_phy->sd_base + CMN_PLL0_INTDIV_M0);
writel(0x999A, cdns_phy->sd_base + CMN_PLL0_FRACDIVL_M0);
writel(0x0002, cdns_phy->sd_base + CMN_PLL0_FRACDIVH_M0);
writel(0x00E7, cdns_phy->sd_base + CMN_PLL0_HIGH_THR_M0);
break;
/* Setting VCO for 8.1GHz */
case 8100:
writel(0x0144, cdns_phy->sd_base + CMN_PLL0_INTDIV_M0);
writel(0x0000, cdns_phy->sd_base + CMN_PLL0_FRACDIVL_M0);
writel(0x0002, cdns_phy->sd_base + CMN_PLL0_FRACDIVH_M0);
writel(0x00D8, cdns_phy->sd_base + CMN_PLL0_HIGH_THR_M0);
break;
}
writel(0x0002, cdns_phy->sd_base + CMN_PDIAG_PLL0_CTRL_M0);
writel(0x0318, cdns_phy->sd_base + CMN_PLL0_VCOCAL_PLLCNT_START);
}
static void cdns_dp_phy_pma_cmn_rate(struct cdns_dp_phy *cdns_phy)
{
unsigned int clk_sel_val = 0;
unsigned int hsclk_div_val = 0;
unsigned int i;
/* 16'h0000 for single DP link configuration */
writel(0x0000, cdns_phy->sd_base + PHY_PLL_CFG);
switch (cdns_phy->max_bit_rate) {
case 1620:
clk_sel_val = 0x0f01;
hsclk_div_val = 2;
break;
case 2160:
case 2430:
case 2700:
clk_sel_val = 0x0701;
hsclk_div_val = 1;
break;
case 3240:
clk_sel_val = 0x0b00;
hsclk_div_val = 2;
break;
case 4320:
case 5400:
clk_sel_val = 0x0301;
hsclk_div_val = 0;
break;
case 8100:
clk_sel_val = 0x0200;
hsclk_div_val = 0;
break;
}
writel(clk_sel_val, cdns_phy->sd_base + CMN_PDIAG_PLL0_CLK_SEL_M0);
/* PMA lane configuration to deal with multi-link operation */
for (i = 0; i < cdns_phy->num_lanes; i++) {
writel(hsclk_div_val,
cdns_phy->sd_base + (XCVR_DIAG_HSCLK_DIV | (i<<11)));
}
}
static void cdns_dp_phy_pma_lane_cfg(struct cdns_dp_phy *cdns_phy,
unsigned int lane)
{
unsigned int lane_bits = (lane & LANE_MASK) << 11;
/* Writing Tx/Rx Power State Controllers registers */
writel(0x00FB, cdns_phy->sd_base + (TX_PSC_A0 | lane_bits));
writel(0x04AA, cdns_phy->sd_base + (TX_PSC_A2 | lane_bits));
writel(0x04AA, cdns_phy->sd_base + (TX_PSC_A3 | lane_bits));
writel(0x0000, cdns_phy->sd_base + (RX_PSC_A0 | lane_bits));
writel(0x0000, cdns_phy->sd_base + (RX_PSC_A2 | lane_bits));
writel(0x0000, cdns_phy->sd_base + (RX_PSC_A3 | lane_bits));
writel(0x0001, cdns_phy->sd_base + (XCVR_DIAG_PLLDRC_CTRL | lane_bits));
writel(0x0000, cdns_phy->sd_base + (XCVR_DIAG_HSCLK_SEL | lane_bits));
}
static void cdns_dp_phy_run(struct cdns_dp_phy *cdns_phy)
{
unsigned int read_val;
u32 write_val1 = 0;
u32 write_val2 = 0;
u32 mask = 0;
int ret;
/*
* waiting for ACK of pma_xcvr_pllclk_en_ln_*, only for the
* master lane
*/
ret = readl_poll_timeout(cdns_phy->base + PHY_PMA_XCVR_PLLCLK_EN_ACK,
read_val, read_val & 1, 0, POLL_TIMEOUT_US);
if (ret == -ETIMEDOUT)
dev_err(cdns_phy->dev,
"timeout waiting for link PLL clock enable ack\n");
ndelay(100);
switch (cdns_phy->num_lanes) {
case 1: /* lane 0 */
write_val1 = 0x00000004;
write_val2 = 0x00000001;
mask = 0x0000003f;
break;
case 2: /* lane 0-1 */
write_val1 = 0x00000404;
write_val2 = 0x00000101;
mask = 0x00003f3f;
break;
case 4: /* lane 0-3 */
write_val1 = 0x04040404;
write_val2 = 0x01010101;
mask = 0x3f3f3f3f;
break;
}
writel(write_val1, cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_REQ);
ret = readl_poll_timeout(cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_ACK,
read_val, (read_val & mask) == write_val1, 0,
POLL_TIMEOUT_US);
if (ret == -ETIMEDOUT)
dev_err(cdns_phy->dev,
"timeout waiting for link power state ack\n");
writel(0, cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_REQ);
ndelay(100);
writel(write_val2, cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_REQ);
ret = readl_poll_timeout(cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_ACK,
read_val, (read_val & mask) == write_val2, 0,
POLL_TIMEOUT_US);
if (ret == -ETIMEDOUT)
dev_err(cdns_phy->dev,
"timeout waiting for link power state ack\n");
writel(0, cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_REQ);
ndelay(100);
}
static void cdns_dp_phy_write_field(struct cdns_dp_phy *cdns_phy,
unsigned int offset,
unsigned char start_bit,
unsigned char num_bits,
unsigned int val)
{
unsigned int read_val;
read_val = readl(cdns_phy->base + offset);
writel(((val << start_bit) | (read_val & ~(((1 << num_bits) - 1) <<
start_bit))), cdns_phy->base + offset);
}
static int cdns_dp_phy_probe(struct platform_device *pdev)
{
struct resource *regs;
struct cdns_dp_phy *cdns_phy;
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
struct phy *phy;
int err;
cdns_phy = devm_kzalloc(dev, sizeof(*cdns_phy), GFP_KERNEL);
if (!cdns_phy)
return -ENOMEM;
cdns_phy->dev = &pdev->dev;
phy = devm_phy_create(dev, NULL, &cdns_dp_phy_ops);
if (IS_ERR(phy)) {
dev_err(dev, "failed to create DisplayPort PHY\n");
return PTR_ERR(phy);
}
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
cdns_phy->base = devm_ioremap_resource(&pdev->dev, regs);
if (IS_ERR(cdns_phy->base))
return PTR_ERR(cdns_phy->base);
regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
cdns_phy->sd_base = devm_ioremap_resource(&pdev->dev, regs);
if (IS_ERR(cdns_phy->sd_base))
return PTR_ERR(cdns_phy->sd_base);
err = device_property_read_u32(dev, "num_lanes",
&(cdns_phy->num_lanes));
if (err)
cdns_phy->num_lanes = DEFAULT_NUM_LANES;
switch (cdns_phy->num_lanes) {
case 1:
case 2:
case 4:
/* valid number of lanes */
break;
default:
dev_err(dev, "unsupported number of lanes: %d\n",
cdns_phy->num_lanes);
return -EINVAL;
}
err = device_property_read_u32(dev, "max_bit_rate",
&(cdns_phy->max_bit_rate));
if (err)
cdns_phy->max_bit_rate = DEFAULT_MAX_BIT_RATE;
switch (cdns_phy->max_bit_rate) {
case 2160:
case 2430:
case 2700:
case 3240:
case 4320:
case 5400:
case 8100:
/* valid bit rate */
break;
default:
dev_err(dev, "unsupported max bit rate: %dMbps\n",
cdns_phy->max_bit_rate);
return -EINVAL;
}
phy_set_drvdata(phy, cdns_phy);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
dev_info(dev, "%d lanes, max bit rate %d.%03d Gbps\n",
cdns_phy->num_lanes,
cdns_phy->max_bit_rate / 1000,
cdns_phy->max_bit_rate % 1000);
return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id cdns_dp_phy_of_match[] = {
{
.compatible = "cdns,dp-phy"
},
{}
};
MODULE_DEVICE_TABLE(of, cdns_dp_phy_of_match);
static struct platform_driver cdns_dp_phy_driver = {
.probe = cdns_dp_phy_probe,
.driver = {
.name = "cdns-dp-phy",
.of_match_table = cdns_dp_phy_of_match,
}
};
module_platform_driver(cdns_dp_phy_driver);
MODULE_AUTHOR("Cadence Design Systems, Inc.");
MODULE_DESCRIPTION("Cadence MHDP PHY driver");
MODULE_LICENSE("GPL v2");

File diff suppressed because it is too large Load diff

View file

@ -43,6 +43,8 @@
#define PA0_RG_USB20_INTR_EN BIT(5)
#define U3P_USBPHYACR1 0x004
#define PA1_RG_INTR_CAL GENMASK(23, 19)
#define PA1_RG_INTR_CAL_VAL(x) ((0x1f & (x)) << 19)
#define PA1_RG_VRT_SEL GENMASK(14, 12)
#define PA1_RG_VRT_SEL_VAL(x) ((0x7 & (x)) << 12)
#define PA1_RG_TERM_SEL GENMASK(10, 8)
@ -60,6 +62,8 @@
#define U3P_USBPHYACR6 0x018
#define PA6_RG_U2_BC11_SW_EN BIT(23)
#define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20)
#define PA6_RG_U2_DISCTH GENMASK(7, 4)
#define PA6_RG_U2_DISCTH_VAL(x) ((0xf & (x)) << 4)
#define PA6_RG_U2_SQTH GENMASK(3, 0)
#define PA6_RG_U2_SQTH_VAL(x) (0xf & (x))
@ -294,20 +298,21 @@ struct mtk_phy_instance {
struct u2phy_banks u2_banks;
struct u3phy_banks u3_banks;
};
struct clk *ref_clk; /* reference clock of anolog phy */
struct clk *ref_clk; /* reference clock of (digital) phy */
struct clk *da_ref_clk; /* reference clock of analog phy */
u32 index;
u8 type;
int eye_src;
int eye_vrt;
int eye_term;
int intr;
int discth;
bool bc12_en;
};
struct mtk_tphy {
struct device *dev;
void __iomem *sif_base; /* only shared sif */
/* deprecated, use @ref_clk instead in phy instance */
struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
const struct mtk_phy_pdata *pdata;
struct mtk_phy_instance **phys;
int nphys;
@ -850,9 +855,14 @@ static void phy_parse_property(struct mtk_tphy *tphy,
&instance->eye_vrt);
device_property_read_u32(dev, "mediatek,eye-term",
&instance->eye_term);
dev_dbg(dev, "bc12:%d, src:%d, vrt:%d, term:%d\n",
device_property_read_u32(dev, "mediatek,intr",
&instance->intr);
device_property_read_u32(dev, "mediatek,discth",
&instance->discth);
dev_dbg(dev, "bc12:%d, src:%d, vrt:%d, term:%d, intr:%d, disc:%d\n",
instance->bc12_en, instance->eye_src,
instance->eye_vrt, instance->eye_term);
instance->eye_vrt, instance->eye_term,
instance->intr, instance->discth);
}
static void u2_phy_props_set(struct mtk_tphy *tphy,
@ -888,6 +898,20 @@ static void u2_phy_props_set(struct mtk_tphy *tphy,
tmp |= PA1_RG_TERM_SEL_VAL(instance->eye_term);
writel(tmp, com + U3P_USBPHYACR1);
}
if (instance->intr) {
tmp = readl(com + U3P_USBPHYACR1);
tmp &= ~PA1_RG_INTR_CAL;
tmp |= PA1_RG_INTR_CAL_VAL(instance->intr);
writel(tmp, com + U3P_USBPHYACR1);
}
if (instance->discth) {
tmp = readl(com + U3P_USBPHYACR6);
tmp &= ~PA6_RG_U2_DISCTH;
tmp |= PA6_RG_U2_DISCTH_VAL(instance->discth);
writel(tmp, com + U3P_USBPHYACR6);
}
}
static int mtk_phy_init(struct phy *phy)
@ -896,18 +920,19 @@ static int mtk_phy_init(struct phy *phy)
struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
int ret;
ret = clk_prepare_enable(tphy->u3phya_ref);
if (ret) {
dev_err(tphy->dev, "failed to enable u3phya_ref\n");
return ret;
}
ret = clk_prepare_enable(instance->ref_clk);
if (ret) {
dev_err(tphy->dev, "failed to enable ref_clk\n");
return ret;
}
ret = clk_prepare_enable(instance->da_ref_clk);
if (ret) {
dev_err(tphy->dev, "failed to enable da_ref\n");
clk_disable_unprepare(instance->ref_clk);
return ret;
}
switch (instance->type) {
case PHY_TYPE_USB2:
u2_phy_instance_init(tphy, instance);
@ -967,7 +992,7 @@ static int mtk_phy_exit(struct phy *phy)
u2_phy_instance_exit(tphy, instance);
clk_disable_unprepare(instance->ref_clk);
clk_disable_unprepare(tphy->u3phya_ref);
clk_disable_unprepare(instance->da_ref_clk);
return 0;
}
@ -1102,11 +1127,6 @@ static int mtk_tphy_probe(struct platform_device *pdev)
}
}
/* it's deprecated, make it optional for backward compatibility */
tphy->u3phya_ref = devm_clk_get_optional(dev, "u3phya_ref");
if (IS_ERR(tphy->u3phya_ref))
return PTR_ERR(tphy->u3phya_ref);
tphy->src_ref_clk = U3P_REF_CLK;
tphy->src_coef = U3P_SLEW_RATE_COEF;
/* update parameters of slew rate calibrate if exist */
@ -1153,16 +1173,20 @@ static int mtk_tphy_probe(struct platform_device *pdev)
phy_set_drvdata(phy, instance);
port++;
/* if deprecated clock is provided, ignore instance's one */
if (tphy->u3phya_ref)
continue;
instance->ref_clk = devm_clk_get(&phy->dev, "ref");
instance->ref_clk = devm_clk_get_optional(&phy->dev, "ref");
if (IS_ERR(instance->ref_clk)) {
dev_err(dev, "failed to get ref_clk(id-%d)\n", port);
retval = PTR_ERR(instance->ref_clk);
goto put_child;
}
instance->da_ref_clk =
devm_clk_get_optional(&phy->dev, "da_ref");
if (IS_ERR(instance->da_ref_clk)) {
dev_err(dev, "failed to get da_ref_clk(id-%d)\n", port);
retval = PTR_ERR(instance->da_ref_clk);
goto put_child;
}
}
provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);

View file

@ -91,3 +91,23 @@ config PHY_QCOM_USB_HSIC
select GENERIC_PHY
help
Support for the USB HSIC ULPI compliant PHY on QCOM chipsets.
config PHY_QCOM_USB_HS_28NM
tristate "Qualcomm 28nm High-Speed PHY"
depends on ARCH_QCOM || COMPILE_TEST
depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
select GENERIC_PHY
help
Enable this to support the Qualcomm Synopsys DesignWare Core 28nm
High-Speed PHY driver. This driver supports the Hi-Speed PHY which
is usually paired with either the ChipIdea or Synopsys DWC3 USB
IPs on MSM SOCs.
config PHY_QCOM_USB_SS
tristate "Qualcomm USB Super-Speed PHY driver"
depends on ARCH_QCOM || COMPILE_TEST
depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
select GENERIC_PHY
help
Enable this to support the Super-Speed USB transceiver on various
Qualcomm chipsets.

View file

@ -10,3 +10,5 @@ obj-$(CONFIG_PHY_QCOM_UFS_14NM) += phy-qcom-ufs-qmp-14nm.o
obj-$(CONFIG_PHY_QCOM_UFS_20NM) += phy-qcom-ufs-qmp-20nm.o
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

View file

@ -121,6 +121,11 @@ enum qphy_reg_layout {
QPHY_PCS_LFPS_RXTERM_IRQ_STATUS,
};
static const unsigned int msm8996_ufsphy_regs_layout[] = {
[QPHY_START_CTRL] = 0x00,
[QPHY_PCS_READY_STATUS] = 0x168,
};
static const unsigned int pciephy_regs_layout[] = {
[QPHY_COM_SW_RESET] = 0x400,
[QPHY_COM_POWER_DOWN_CONTROL] = 0x404,
@ -160,6 +165,18 @@ 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[] = {
[QPHY_SW_RESET] = 0x00,
[QPHY_START_CTRL] = 0x08,
[QPHY_PCS_STATUS] = 0x174,
};
static const unsigned int sdm845_qhp_pciephy_regs_layout[] = {
[QPHY_SW_RESET] = 0x00,
[QPHY_START_CTRL] = 0x08,
[QPHY_PCS_STATUS] = 0x2ac,
};
static const unsigned int sdm845_ufsphy_regs_layout[] = {
[QPHY_START_CTRL] = 0x00,
[QPHY_PCS_READY_STATUS] = 0x160,
@ -331,6 +348,75 @@ static const struct qmp_phy_init_tbl msm8998_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03),
};
static const struct qmp_phy_init_tbl msm8996_ufs_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x01),
QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xd7),
QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06),
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x05),
QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x10),
QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x54),
QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05),
QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98),
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b),
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28),
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80),
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6),
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00),
};
static const struct qmp_phy_init_tbl msm8996_ufs_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x02),
};
static const struct qmp_phy_init_tbl msm8996_ufs_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24),
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x00),
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x18),
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B),
QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5b),
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xff),
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xff),
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E),
};
static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14),
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
@ -481,6 +567,229 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3),
};
static const struct qmp_phy_init_tbl sdm845_qmp_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x007),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15),
};
static const struct qmp_phy_init_tbl sdm845_qmp_pcie_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06),
};
static const struct qmp_phy_init_tbl sdm845_qmp_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x71),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_01, 0x59),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40),
};
static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xbb),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x0d),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG4, 0x00),
};
static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_CONFIG2, 0x52),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG2, 0x10),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG4, 0x1a),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5, 0x06),
QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_PCIE_INT_AUX_CLK_CONFIG1, 0x00),
};
static const struct qmp_phy_init_tbl sdm845_qhp_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SYSCLK_EN_SEL, 0x27),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER1, 0x31),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER2, 0x01),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1, 0xde),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2, 0x07),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1_MODE1, 0x4c),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2_MODE1, 0x06),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BIAS_EN_CKBUFLR_EN, 0x18),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_ENABLE1, 0xb0),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE0, 0x8c),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE0, 0x20),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE1, 0x14),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE1, 0x34),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE1, 0x06),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE1, 0x36),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_RESTRIM_CTRL2, 0x05),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP_EN, 0x42),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE0, 0x82),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE1, 0x68),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE0, 0x55),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE0, 0x55),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE0, 0x03),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE1, 0xab),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE1, 0xaa),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE1, 0x02),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE1, 0x3f),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VCO_TUNE_MAP, 0x10),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_SELECT, 0x04),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_HSCLK_SEL1, 0x30),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV, 0x04),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORE_CLK_EN, 0x73),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_CONFIG, 0x0c),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SVS_MODE_CLK_SEL, 0x15),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV_MODE1, 0x04),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_MODE, 0x01),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV1, 0x22),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV2, 0x00),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BGV_TRIM, 0x20),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BG_CTRL, 0x07),
};
static const struct qmp_phy_init_tbl sdm845_qhp_pcie_tx_tbl[] = {
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL0, 0x00),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_TAP_EN, 0x0d),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TX_BAND_MODE, 0x01),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_LANE_MODE, 0x1a),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PARALLEL_RATE, 0x2f),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE0, 0x09),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE1, 0x09),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE2, 0x1b),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE1, 0x01),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE2, 0x07),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE0, 0x31),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE1, 0x31),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE2, 0x03),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_THRESH_DFE, 0x02),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CGA_THRESH_DFE, 0x00),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXENGINE_EN0, 0x12),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_TRAIN_TIME, 0x25),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_DFE_OVRLP_TIME, 0x00),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_REFRESH_TIME, 0x05),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_ENABLE_TIME, 0x01),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_GAIN, 0x26),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_GAIN, 0x12),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_GAIN, 0x04),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_OFFSET_GAIN, 0x04),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PRE_GAIN, 0x09),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_INTVAL, 0x15),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EDAC_INITVAL, 0x28),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB0, 0x7f),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB1, 0x07),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RCVRDONE_THRESH1, 0x04),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_CTRL, 0x70),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE0, 0x8b),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE1, 0x08),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE2, 0x0a),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE0, 0x03),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE1, 0x04),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE2, 0x04),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_CONFIG, 0x0c),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_BAND, 0x02),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE0, 0x5c),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE1, 0x3e),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE2, 0x3f),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_ENABLES, 0x01),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_CNTRL, 0xa0),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_DEGLITCH_CNTRL, 0x08),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DCC_GAIN, 0x01),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_EN_SIGNAL, 0xc3),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PSM_RX_EN_CAL, 0x00),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_MISC_CNTRL0, 0xbc),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TS0_TIMER, 0x7f),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DLL_HIGHDATARATE, 0x15),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL1, 0x0c),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL2, 0x0f),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RESETCODE_OFFSET, 0x04),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_INITVAL, 0x20),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RSM_START, 0x01),
};
static const struct qmp_phy_init_tbl sdm845_qhp_pcie_rx_tbl[] = {
};
static const struct qmp_phy_init_tbl sdm845_qhp_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG, 0x3f),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_PCS_TX_RX_CONFIG, 0x50),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M3P5DB, 0x19),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M3P5DB, 0x07),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M6DB, 0x17),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M6DB, 0x09),
QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG5, 0x9f),
};
static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
@ -988,6 +1297,8 @@ struct qmp_phy_cfg {
int rx_tbl_num;
const struct qmp_phy_init_tbl *pcs_tbl;
int pcs_tbl_num;
const struct qmp_phy_init_tbl *pcs_misc_tbl;
int pcs_misc_tbl_num;
/* clock ids to be requested */
const char * const *clk_list;
@ -1122,10 +1433,18 @@ static const char * const msm8996_phy_clk_l[] = {
"aux", "cfg_ahb", "ref",
};
static const char * const msm8996_ufs_phy_clk_l[] = {
"ref",
};
static const char * const qmp_v3_phy_clk_l[] = {
"aux", "cfg_ahb", "ref", "com_aux",
};
static const char * const sdm845_pciephy_clk_l[] = {
"aux", "cfg_ahb", "ref", "refgen",
};
static const char * const sdm845_ufs_phy_clk_l[] = {
"ref", "ref_aux",
};
@ -1139,6 +1458,10 @@ static const char * const msm8996_usb3phy_reset_l[] = {
"phy", "common",
};
static const char * const sdm845_pciephy_reset_l[] = {
"phy",
};
/* list of regulators */
static const char * const qmp_phy_vreg_l[] = {
"vdda-phy", "vdda-pll",
@ -1175,6 +1498,31 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = {
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
};
static const struct qmp_phy_cfg msm8996_ufs_cfg = {
.type = PHY_TYPE_UFS,
.nlanes = 1,
.serdes_tbl = msm8996_ufs_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(msm8996_ufs_serdes_tbl),
.tx_tbl = msm8996_ufs_tx_tbl,
.tx_tbl_num = ARRAY_SIZE(msm8996_ufs_tx_tbl),
.rx_tbl = msm8996_ufs_rx_tbl,
.rx_tbl_num = ARRAY_SIZE(msm8996_ufs_rx_tbl),
.clk_list = msm8996_ufs_phy_clk_l,
.num_clks = ARRAY_SIZE(msm8996_ufs_phy_clk_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = msm8996_ufsphy_regs_layout,
.start_ctrl = SERDES_START,
.pwrdn_ctrl = SW_PWRDN,
.no_pcs_sw_reset = true,
};
static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
.type = PHY_TYPE_USB3,
.nlanes = 1,
@ -1234,6 +1582,64 @@ static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
.pwrdn_delay_max = 1005, /* us */
};
static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = {
.type = PHY_TYPE_PCIE,
.nlanes = 1,
.serdes_tbl = sdm845_qmp_pcie_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_serdes_tbl),
.tx_tbl = sdm845_qmp_pcie_tx_tbl,
.tx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_tx_tbl),
.rx_tbl = sdm845_qmp_pcie_rx_tbl,
.rx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_rx_tbl),
.pcs_tbl = sdm845_qmp_pcie_pcs_tbl,
.pcs_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_tbl),
.pcs_misc_tbl = sdm845_qmp_pcie_pcs_misc_tbl,
.pcs_misc_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_misc_tbl),
.clk_list = sdm845_pciephy_clk_l,
.num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l),
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = sdm845_qmp_pciephy_regs_layout,
.start_ctrl = PCS_START | SERDES_START,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.has_pwrdn_delay = true,
.pwrdn_delay_min = 995, /* us */
.pwrdn_delay_max = 1005, /* us */
};
static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = {
.type = PHY_TYPE_PCIE,
.nlanes = 1,
.serdes_tbl = sdm845_qhp_pcie_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_serdes_tbl),
.tx_tbl = sdm845_qhp_pcie_tx_tbl,
.tx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_tx_tbl),
.rx_tbl = sdm845_qhp_pcie_rx_tbl,
.rx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_rx_tbl),
.pcs_tbl = sdm845_qhp_pcie_pcs_tbl,
.pcs_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_pcs_tbl),
.clk_list = sdm845_pciephy_clk_l,
.num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l),
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = sdm845_qhp_pciephy_regs_layout,
.start_ctrl = PCS_START | SERDES_START,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.has_pwrdn_delay = true,
.pwrdn_delay_min = 995, /* us */
.pwrdn_delay_max = 1005, /* us */
};
static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
.type = PHY_TYPE_USB3,
.nlanes = 1,
@ -1563,6 +1969,7 @@ static int qcom_qmp_phy_enable(struct phy *phy)
void __iomem *tx = qphy->tx;
void __iomem *rx = qphy->rx;
void __iomem *pcs = qphy->pcs;
void __iomem *pcs_misc = qphy->pcs_misc;
void __iomem *dp_com = qmp->dp_com;
void __iomem *status;
unsigned int mask, val, ready;
@ -1633,6 +2040,9 @@ static int qcom_qmp_phy_enable(struct phy *phy)
if (ret)
goto err_lane_rst;
qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl,
cfg->pcs_misc_tbl_num);
/*
* Pull out PHY from POWER DOWN state.
* This is active low enable signal to power-down PHY.
@ -1967,7 +2377,7 @@ static const struct phy_ops qcom_qmp_phy_gen_ops = {
.owner = THIS_MODULE,
};
static const struct phy_ops qcom_qmp_ufs_ops = {
static const struct phy_ops qcom_qmp_pcie_ufs_ops = {
.power_on = qcom_qmp_phy_enable,
.power_off = qcom_qmp_phy_disable,
.set_mode = qcom_qmp_phy_set_mode,
@ -2067,8 +2477,8 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
}
}
if (qmp->cfg->type == PHY_TYPE_UFS)
ops = &qcom_qmp_ufs_ops;
if (qmp->cfg->type == PHY_TYPE_UFS || qmp->cfg->type == PHY_TYPE_PCIE)
ops = &qcom_qmp_pcie_ufs_ops;
generic_phy = devm_phy_create(dev, np, ops);
if (IS_ERR(generic_phy)) {
@ -2090,6 +2500,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
{
.compatible = "qcom,msm8996-qmp-pcie-phy",
.data = &msm8996_pciephy_cfg,
}, {
.compatible = "qcom,msm8996-qmp-ufs-phy",
.data = &msm8996_ufs_cfg,
}, {
.compatible = "qcom,msm8996-qmp-usb3-phy",
.data = &msm8996_usb3phy_cfg,
@ -2102,6 +2515,12 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
}, {
.compatible = "qcom,ipq8074-qmp-pcie-phy",
.data = &ipq8074_pciephy_cfg,
}, {
.compatible = "qcom,sdm845-qhp-pcie-phy",
.data = &sdm845_qhp_pciephy_cfg,
}, {
.compatible = "qcom,sdm845-qmp-pcie-phy",
.data = &sdm845_qmp_pciephy_cfg,
}, {
.compatible = "qcom,sdm845-qmp-usb3-phy",
.data = &qmp_v3_usb3phy_cfg,

View file

@ -409,4 +409,118 @@
#define QPHY_V4_TX_MID_TERM_CTRL1 0x1d8
#define QPHY_V4_MULTI_LANE_CTRL1 0x1e0
/* PCIE GEN3 COM registers */
#define PCIE_GEN3_QHP_COM_SSC_EN_CENTER 0x14
#define PCIE_GEN3_QHP_COM_SSC_PER1 0x20
#define PCIE_GEN3_QHP_COM_SSC_PER2 0x24
#define PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1 0x28
#define PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2 0x2c
#define PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1_MODE1 0x34
#define PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2_MODE1 0x38
#define PCIE_GEN3_QHP_COM_BIAS_EN_CKBUFLR_EN 0x54
#define PCIE_GEN3_QHP_COM_CLK_ENABLE1 0x58
#define PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE0 0x6c
#define PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE0 0x70
#define PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE1 0x78
#define PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE1 0x7c
#define PCIE_GEN3_QHP_COM_BGV_TRIM 0x98
#define PCIE_GEN3_QHP_COM_CP_CTRL_MODE0 0xb4
#define PCIE_GEN3_QHP_COM_CP_CTRL_MODE1 0xb8
#define PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE0 0xc0
#define PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE1 0xc4
#define PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE0 0xcc
#define PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE1 0xd0
#define PCIE_GEN3_QHP_COM_SYSCLK_EN_SEL 0xdc
#define PCIE_GEN3_QHP_COM_RESTRIM_CTRL2 0xf0
#define PCIE_GEN3_QHP_COM_LOCK_CMP_EN 0xf8
#define PCIE_GEN3_QHP_COM_DEC_START_MODE0 0x100
#define PCIE_GEN3_QHP_COM_DEC_START_MODE1 0x108
#define PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE0 0x11c
#define PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE0 0x120
#define PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE0 0x124
#define PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE1 0x128
#define PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE1 0x12c
#define PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE1 0x130
#define PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE0 0x150
#define PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE1 0x158
#define PCIE_GEN3_QHP_COM_VCO_TUNE_MAP 0x178
#define PCIE_GEN3_QHP_COM_BG_CTRL 0x1c8
#define PCIE_GEN3_QHP_COM_CLK_SELECT 0x1cc
#define PCIE_GEN3_QHP_COM_HSCLK_SEL1 0x1d0
#define PCIE_GEN3_QHP_COM_CORECLK_DIV 0x1e0
#define PCIE_GEN3_QHP_COM_CORE_CLK_EN 0x1e8
#define PCIE_GEN3_QHP_COM_CMN_CONFIG 0x1f0
#define PCIE_GEN3_QHP_COM_SVS_MODE_CLK_SEL 0x1fc
#define PCIE_GEN3_QHP_COM_CORECLK_DIV_MODE1 0x21c
#define PCIE_GEN3_QHP_COM_CMN_MODE 0x224
#define PCIE_GEN3_QHP_COM_VREGCLK_DIV1 0x228
#define PCIE_GEN3_QHP_COM_VREGCLK_DIV2 0x22c
/* PCIE GEN3 QHP Lane registers */
#define PCIE_GEN3_QHP_L0_DRVR_CTRL0 0xc
#define PCIE_GEN3_QHP_L0_DRVR_CTRL1 0x10
#define PCIE_GEN3_QHP_L0_DRVR_CTRL2 0x14
#define PCIE_GEN3_QHP_L0_DRVR_TAP_EN 0x18
#define PCIE_GEN3_QHP_L0_TX_BAND_MODE 0x60
#define PCIE_GEN3_QHP_L0_LANE_MODE 0x64
#define PCIE_GEN3_QHP_L0_PARALLEL_RATE 0x7c
#define PCIE_GEN3_QHP_L0_CML_CTRL_MODE0 0xc0
#define PCIE_GEN3_QHP_L0_CML_CTRL_MODE1 0xc4
#define PCIE_GEN3_QHP_L0_CML_CTRL_MODE2 0xc8
#define PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE1 0xd0
#define PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE2 0xd4
#define PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE0 0xd8
#define PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE1 0xdc
#define PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE2 0xe0
#define PCIE_GEN3_QHP_L0_CTLE_THRESH_DFE 0xfc
#define PCIE_GEN3_QHP_L0_CGA_THRESH_DFE 0x100
#define PCIE_GEN3_QHP_L0_RXENGINE_EN0 0x108
#define PCIE_GEN3_QHP_L0_CTLE_TRAIN_TIME 0x114
#define PCIE_GEN3_QHP_L0_CTLE_DFE_OVRLP_TIME 0x118
#define PCIE_GEN3_QHP_L0_DFE_REFRESH_TIME 0x11c
#define PCIE_GEN3_QHP_L0_DFE_ENABLE_TIME 0x120
#define PCIE_GEN3_QHP_L0_VGA_GAIN 0x124
#define PCIE_GEN3_QHP_L0_DFE_GAIN 0x128
#define PCIE_GEN3_QHP_L0_EQ_GAIN 0x130
#define PCIE_GEN3_QHP_L0_OFFSET_GAIN 0x134
#define PCIE_GEN3_QHP_L0_PRE_GAIN 0x138
#define PCIE_GEN3_QHP_L0_VGA_INITVAL 0x13c
#define PCIE_GEN3_QHP_L0_EQ_INTVAL 0x154
#define PCIE_GEN3_QHP_L0_EDAC_INITVAL 0x160
#define PCIE_GEN3_QHP_L0_RXEQ_INITB0 0x168
#define PCIE_GEN3_QHP_L0_RXEQ_INITB1 0x16c
#define PCIE_GEN3_QHP_L0_RCVRDONE_THRESH1 0x178
#define PCIE_GEN3_QHP_L0_RXEQ_CTRL 0x180
#define PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE0 0x184
#define PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE1 0x188
#define PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE2 0x18c
#define PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE0 0x190
#define PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE1 0x194
#define PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE2 0x198
#define PCIE_GEN3_QHP_L0_UCDR_SO_CONFIG 0x19c
#define PCIE_GEN3_QHP_L0_RX_BAND 0x1a4
#define PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE0 0x1c0
#define PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE1 0x1c4
#define PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE2 0x1c8
#define PCIE_GEN3_QHP_L0_SIGDET_ENABLES 0x230
#define PCIE_GEN3_QHP_L0_SIGDET_CNTRL 0x234
#define PCIE_GEN3_QHP_L0_SIGDET_DEGLITCH_CNTRL 0x238
#define PCIE_GEN3_QHP_L0_DCC_GAIN 0x2a4
#define PCIE_GEN3_QHP_L0_RSM_START 0x2a8
#define PCIE_GEN3_QHP_L0_RX_EN_SIGNAL 0x2ac
#define PCIE_GEN3_QHP_L0_PSM_RX_EN_CAL 0x2b0
#define PCIE_GEN3_QHP_L0_RX_MISC_CNTRL0 0x2b8
#define PCIE_GEN3_QHP_L0_TS0_TIMER 0x2c0
#define PCIE_GEN3_QHP_L0_DLL_HIGHDATARATE 0x2c4
#define PCIE_GEN3_QHP_L0_RX_RESETCODE_OFFSET 0x2cc
/* PCIE GEN3 PCS registers */
#define PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M3P5DB 0x2c
#define PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M3P5DB 0x40
#define PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M6DB 0x54
#define PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M6DB 0x68
#define PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG 0x15c
#define PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG5 0x16c
#define PCIE_GEN3_QHP_PHY_PCS_TX_RX_CONFIG 0x174
#endif

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
* Copyright (c) 2017, 2019, The Linux Foundation. All rights reserved.
*/
#include <linux/clk.h>
@ -66,6 +66,14 @@
#define IMP_RES_OFFSET_MASK GENMASK(5, 0)
#define IMP_RES_OFFSET_SHIFT 0x0
/* QUSB2PHY_PLL_BIAS_CONTROL_2 register bits */
#define BIAS_CTRL2_RES_OFFSET_MASK GENMASK(5, 0)
#define BIAS_CTRL2_RES_OFFSET_SHIFT 0x0
/* QUSB2PHY_CHG_CONTROL_2 register bits */
#define CHG_CTRL2_OFFSET_MASK GENMASK(5, 4)
#define CHG_CTRL2_OFFSET_SHIFT 0x4
/* QUSB2PHY_PORT_TUNE1 register bits */
#define HSTX_TRIM_MASK GENMASK(7, 4)
#define HSTX_TRIM_SHIFT 0x4
@ -73,6 +81,10 @@
#define PREEMPHASIS_EN_MASK GENMASK(1, 0)
#define PREEMPHASIS_EN_SHIFT 0x0
/* QUSB2PHY_PORT_TUNE2 register bits */
#define HSDISC_TRIM_MASK GENMASK(1, 0)
#define HSDISC_TRIM_SHIFT 0x0
#define QUSB2PHY_PLL_ANALOG_CONTROLS_TWO 0x04
#define QUSB2PHY_PLL_CLOCK_INVERTERS 0x18c
#define QUSB2PHY_PLL_CMODE 0x2c
@ -177,7 +189,7 @@ static const struct qusb2_phy_init_tbl msm8998_init_tbl[] = {
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_DIGITAL_TIMERS_TWO, 0x19),
};
static const unsigned int sdm845_regs_layout[] = {
static const unsigned int qusb2_v2_regs_layout[] = {
[QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8,
[QUSB2PHY_PLL_STATUS] = 0x1a0,
[QUSB2PHY_PORT_TUNE1] = 0x240,
@ -191,7 +203,7 @@ static const unsigned int sdm845_regs_layout[] = {
[QUSB2PHY_INTR_CTRL] = 0x230,
};
static const struct qusb2_phy_init_tbl sdm845_init_tbl[] = {
static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = {
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CMODE, 0x80),
@ -258,10 +270,10 @@ static const struct qusb2_phy_cfg msm8998_phy_cfg = {
.update_tune1_with_efuse = true,
};
static const struct qusb2_phy_cfg sdm845_phy_cfg = {
.tbl = sdm845_init_tbl,
.tbl_num = ARRAY_SIZE(sdm845_init_tbl),
.regs = sdm845_regs_layout,
static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = {
.tbl = qusb2_v2_init_tbl,
.tbl_num = ARRAY_SIZE(qusb2_v2_init_tbl),
.regs = qusb2_v2_regs_layout,
.disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN |
POWER_DOWN),
@ -277,6 +289,34 @@ static const char * const qusb2_phy_vreg_names[] = {
#define QUSB2_NUM_VREGS ARRAY_SIZE(qusb2_phy_vreg_names)
/* struct override_param - structure holding qusb2 v2 phy overriding param
* set override true if the device tree property exists and read and assign
* to value
*/
struct override_param {
bool override;
u8 value;
};
/*struct override_params - structure holding qusb2 v2 phy overriding params
* @imp_res_offset: rescode offset to be updated in IMP_CTRL1 register
* @hstx_trim: HSTX_TRIM to be updated in TUNE1 register
* @preemphasis: Amplitude Pre-Emphasis to be updated in TUNE1 register
* @preemphasis_width: half/full-width Pre-Emphasis updated via TUNE1
* @bias_ctrl: bias ctrl to be updated in BIAS_CONTROL_2 register
* @charge_ctrl: charge ctrl to be updated in CHG_CTRL2 register
* @hsdisc_trim: disconnect threshold to be updated in TUNE2 register
*/
struct override_params {
struct override_param imp_res_offset;
struct override_param hstx_trim;
struct override_param preemphasis;
struct override_param preemphasis_width;
struct override_param bias_ctrl;
struct override_param charge_ctrl;
struct override_param hsdisc_trim;
};
/**
* struct qusb2_phy - structure holding qusb2 phy attributes
*
@ -292,14 +332,7 @@ static const char * const qusb2_phy_vreg_names[] = {
* @tcsr: TCSR syscon register map
* @cell: nvmem cell containing phy tuning value
*
* @override_imp_res_offset: PHY should use different rescode offset
* @imp_res_offset_value: rescode offset to be updated in IMP_CTRL1 register
* @override_hstx_trim: PHY should use different HSTX o/p current value
* @hstx_trim_value: HSTX_TRIM value to be updated in TUNE1 register
* @override_preemphasis: PHY should use different pre-amphasis amplitude
* @preemphasis_level: Amplitude Pre-Emphasis to be updated in TUNE1 register
* @override_preemphasis_width: PHY should use different pre-emphasis duration
* @preemphasis_width: half/full-width Pre-Emphasis updated via TUNE1
* @overrides: pointer to structure for all overriding tuning params
*
* @cfg: phy config data
* @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme
@ -319,14 +352,7 @@ struct qusb2_phy {
struct regmap *tcsr;
struct nvmem_cell *cell;
bool override_imp_res_offset;
u8 imp_res_offset_value;
bool override_hstx_trim;
u8 hstx_trim_value;
bool override_preemphasis;
u8 preemphasis_level;
bool override_preemphasis_width;
u8 preemphasis_width;
struct override_params overrides;
const struct qusb2_phy_cfg *cfg;
bool has_se_clk_scheme;
@ -394,24 +420,35 @@ void qcom_qusb2_phy_configure(void __iomem *base,
static void qusb2_phy_override_phy_params(struct qusb2_phy *qphy)
{
const struct qusb2_phy_cfg *cfg = qphy->cfg;
struct override_params *or = &qphy->overrides;
if (qphy->override_imp_res_offset)
if (or->imp_res_offset.override)
qusb2_write_mask(qphy->base, QUSB2PHY_IMP_CTRL1,
qphy->imp_res_offset_value << IMP_RES_OFFSET_SHIFT,
or->imp_res_offset.value << IMP_RES_OFFSET_SHIFT,
IMP_RES_OFFSET_MASK);
if (qphy->override_hstx_trim)
if (or->bias_ctrl.override)
qusb2_write_mask(qphy->base, QUSB2PHY_PLL_BIAS_CONTROL_2,
or->bias_ctrl.value << BIAS_CTRL2_RES_OFFSET_SHIFT,
BIAS_CTRL2_RES_OFFSET_MASK);
if (or->charge_ctrl.override)
qusb2_write_mask(qphy->base, QUSB2PHY_CHG_CTRL2,
or->charge_ctrl.value << CHG_CTRL2_OFFSET_SHIFT,
CHG_CTRL2_OFFSET_MASK);
if (or->hstx_trim.override)
qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1],
qphy->hstx_trim_value << HSTX_TRIM_SHIFT,
or->hstx_trim.value << HSTX_TRIM_SHIFT,
HSTX_TRIM_MASK);
if (qphy->override_preemphasis)
if (or->preemphasis.override)
qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1],
qphy->preemphasis_level << PREEMPHASIS_EN_SHIFT,
or->preemphasis.value << PREEMPHASIS_EN_SHIFT,
PREEMPHASIS_EN_MASK);
if (qphy->override_preemphasis_width) {
if (qphy->preemphasis_width ==
if (or->preemphasis_width.override) {
if (or->preemphasis_width.value ==
QUSB2_V2_PREEMPHASIS_WIDTH_HALF_BIT)
qusb2_setbits(qphy->base,
cfg->regs[QUSB2PHY_PORT_TUNE1],
@ -421,6 +458,11 @@ static void qusb2_phy_override_phy_params(struct qusb2_phy *qphy)
cfg->regs[QUSB2PHY_PORT_TUNE1],
PREEMPH_WIDTH_HALF_BIT);
}
if (or->hsdisc_trim.override)
qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2],
or->hsdisc_trim.value << HSDISC_TRIM_SHIFT,
HSDISC_TRIM_MASK);
}
/*
@ -774,8 +816,8 @@ static const struct of_device_id qusb2_phy_of_match_table[] = {
.compatible = "qcom,msm8998-qusb2-phy",
.data = &msm8998_phy_cfg,
}, {
.compatible = "qcom,sdm845-qusb2-phy",
.data = &sdm845_phy_cfg,
.compatible = "qcom,qusb2-v2-phy",
.data = &qusb2_v2_phy_cfg,
},
{ },
};
@ -796,10 +838,12 @@ static int qusb2_phy_probe(struct platform_device *pdev)
int ret, i;
int num;
u32 value;
struct override_params *or;
qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
if (!qphy)
return -ENOMEM;
or = &qphy->overrides;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
qphy->base = devm_ioremap_resource(dev, res);
@ -864,26 +908,44 @@ static int qusb2_phy_probe(struct platform_device *pdev)
if (!of_property_read_u32(dev->of_node, "qcom,imp-res-offset-value",
&value)) {
qphy->imp_res_offset_value = (u8)value;
qphy->override_imp_res_offset = true;
or->imp_res_offset.value = (u8)value;
or->imp_res_offset.override = true;
}
if (!of_property_read_u32(dev->of_node, "qcom,bias-ctrl-value",
&value)) {
or->bias_ctrl.value = (u8)value;
or->bias_ctrl.override = true;
}
if (!of_property_read_u32(dev->of_node, "qcom,charge-ctrl-value",
&value)) {
or->charge_ctrl.value = (u8)value;
or->charge_ctrl.override = true;
}
if (!of_property_read_u32(dev->of_node, "qcom,hstx-trim-value",
&value)) {
qphy->hstx_trim_value = (u8)value;
qphy->override_hstx_trim = true;
or->hstx_trim.value = (u8)value;
or->hstx_trim.override = true;
}
if (!of_property_read_u32(dev->of_node, "qcom,preemphasis-level",
&value)) {
qphy->preemphasis_level = (u8)value;
qphy->override_preemphasis = true;
or->preemphasis.value = (u8)value;
or->preemphasis.override = true;
}
if (!of_property_read_u32(dev->of_node, "qcom,preemphasis-width",
&value)) {
qphy->preemphasis_width = (u8)value;
qphy->override_preemphasis_width = true;
or->preemphasis_width.value = (u8)value;
or->preemphasis_width.override = true;
}
if (!of_property_read_u32(dev->of_node, "qcom,hsdisc-trim-value",
&value)) {
or->hsdisc_trim.value = (u8)value;
or->hsdisc_trim.override = true;
}
pm_runtime_set_active(dev);

View file

@ -0,0 +1,415 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2009-2018, Linux Foundation. All rights reserved.
* Copyright (c) 2018-2020, Linaro Limited
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/slab.h>
/* PHY register and bit definitions */
#define PHY_CTRL_COMMON0 0x078
#define SIDDQ BIT(2)
#define PHY_IRQ_CMD 0x0d0
#define PHY_INTR_MASK0 0x0d4
#define PHY_INTR_CLEAR0 0x0dc
#define DPDM_MASK 0x1e
#define DP_1_0 BIT(4)
#define DP_0_1 BIT(3)
#define DM_1_0 BIT(2)
#define DM_0_1 BIT(1)
enum hsphy_voltage {
VOL_NONE,
VOL_MIN,
VOL_MAX,
VOL_NUM,
};
enum hsphy_vreg {
VDD,
VDDA_1P8,
VDDA_3P3,
VREG_NUM,
};
struct hsphy_init_seq {
int offset;
int val;
int delay;
};
struct hsphy_data {
const struct hsphy_init_seq *init_seq;
unsigned int init_seq_num;
};
struct hsphy_priv {
void __iomem *base;
struct clk_bulk_data *clks;
int num_clks;
struct reset_control *phy_reset;
struct reset_control *por_reset;
struct regulator_bulk_data vregs[VREG_NUM];
const struct hsphy_data *data;
enum phy_mode mode;
};
static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode,
int submode)
{
struct hsphy_priv *priv = phy_get_drvdata(phy);
priv->mode = PHY_MODE_INVALID;
if (mode > 0)
priv->mode = mode;
return 0;
}
static void qcom_snps_hsphy_enable_hv_interrupts(struct hsphy_priv *priv)
{
u32 val;
/* Clear any existing interrupts before enabling the interrupts */
val = readb(priv->base + PHY_INTR_CLEAR0);
val |= DPDM_MASK;
writeb(val, priv->base + PHY_INTR_CLEAR0);
writeb(0x0, priv->base + PHY_IRQ_CMD);
usleep_range(200, 220);
writeb(0x1, priv->base + PHY_IRQ_CMD);
/* Make sure the interrupts are cleared */
usleep_range(200, 220);
val = readb(priv->base + PHY_INTR_MASK0);
switch (priv->mode) {
case PHY_MODE_USB_HOST_HS:
case PHY_MODE_USB_HOST_FS:
case PHY_MODE_USB_DEVICE_HS:
case PHY_MODE_USB_DEVICE_FS:
val |= DP_1_0 | DM_0_1;
break;
case PHY_MODE_USB_HOST_LS:
case PHY_MODE_USB_DEVICE_LS:
val |= DP_0_1 | DM_1_0;
break;
default:
/* No device connected */
val |= DP_0_1 | DM_0_1;
break;
}
writeb(val, priv->base + PHY_INTR_MASK0);
}
static void qcom_snps_hsphy_disable_hv_interrupts(struct hsphy_priv *priv)
{
u32 val;
val = readb(priv->base + PHY_INTR_MASK0);
val &= ~DPDM_MASK;
writeb(val, priv->base + PHY_INTR_MASK0);
/* Clear any pending interrupts */
val = readb(priv->base + PHY_INTR_CLEAR0);
val |= DPDM_MASK;
writeb(val, priv->base + PHY_INTR_CLEAR0);
writeb(0x0, priv->base + PHY_IRQ_CMD);
usleep_range(200, 220);
writeb(0x1, priv->base + PHY_IRQ_CMD);
usleep_range(200, 220);
}
static void qcom_snps_hsphy_enter_retention(struct hsphy_priv *priv)
{
u32 val;
val = readb(priv->base + PHY_CTRL_COMMON0);
val |= SIDDQ;
writeb(val, priv->base + PHY_CTRL_COMMON0);
}
static void qcom_snps_hsphy_exit_retention(struct hsphy_priv *priv)
{
u32 val;
val = readb(priv->base + PHY_CTRL_COMMON0);
val &= ~SIDDQ;
writeb(val, priv->base + PHY_CTRL_COMMON0);
}
static int qcom_snps_hsphy_power_on(struct phy *phy)
{
struct hsphy_priv *priv = phy_get_drvdata(phy);
int ret;
ret = regulator_bulk_enable(VREG_NUM, priv->vregs);
if (ret)
return ret;
ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
if (ret)
goto err_disable_regulator;
qcom_snps_hsphy_disable_hv_interrupts(priv);
qcom_snps_hsphy_exit_retention(priv);
return 0;
err_disable_regulator:
regulator_bulk_disable(VREG_NUM, priv->vregs);
return ret;
}
static int qcom_snps_hsphy_power_off(struct phy *phy)
{
struct hsphy_priv *priv = phy_get_drvdata(phy);
qcom_snps_hsphy_enter_retention(priv);
qcom_snps_hsphy_enable_hv_interrupts(priv);
clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
regulator_bulk_disable(VREG_NUM, priv->vregs);
return 0;
}
static int qcom_snps_hsphy_reset(struct hsphy_priv *priv)
{
int ret;
ret = reset_control_assert(priv->phy_reset);
if (ret)
return ret;
usleep_range(10, 15);
ret = reset_control_deassert(priv->phy_reset);
if (ret)
return ret;
usleep_range(80, 100);
return 0;
}
static void qcom_snps_hsphy_init_sequence(struct hsphy_priv *priv)
{
const struct hsphy_data *data = priv->data;
const struct hsphy_init_seq *seq;
int i;
/* Device match data is optional. */
if (!data)
return;
seq = data->init_seq;
for (i = 0; i < data->init_seq_num; i++, seq++) {
writeb(seq->val, priv->base + seq->offset);
if (seq->delay)
usleep_range(seq->delay, seq->delay + 10);
}
}
static int qcom_snps_hsphy_por_reset(struct hsphy_priv *priv)
{
int ret;
ret = reset_control_assert(priv->por_reset);
if (ret)
return ret;
/*
* The Femto PHY is POR reset in the following scenarios.
*
* 1. After overriding the parameter registers.
* 2. Low power mode exit from PHY retention.
*
* Ensure that SIDDQ is cleared before bringing the PHY
* out of reset.
*/
qcom_snps_hsphy_exit_retention(priv);
/*
* As per databook, 10 usec delay is required between
* PHY POR assert and de-assert.
*/
usleep_range(10, 20);
ret = reset_control_deassert(priv->por_reset);
if (ret)
return ret;
/*
* As per databook, it takes 75 usec for PHY to stabilize
* after the reset.
*/
usleep_range(80, 100);
return 0;
}
static int qcom_snps_hsphy_init(struct phy *phy)
{
struct hsphy_priv *priv = phy_get_drvdata(phy);
int ret;
ret = qcom_snps_hsphy_reset(priv);
if (ret)
return ret;
qcom_snps_hsphy_init_sequence(priv);
ret = qcom_snps_hsphy_por_reset(priv);
if (ret)
return ret;
return 0;
}
static const struct phy_ops qcom_snps_hsphy_ops = {
.init = qcom_snps_hsphy_init,
.power_on = qcom_snps_hsphy_power_on,
.power_off = qcom_snps_hsphy_power_off,
.set_mode = qcom_snps_hsphy_set_mode,
.owner = THIS_MODULE,
};
static const char * const qcom_snps_hsphy_clks[] = {
"ref",
"ahb",
"sleep",
};
static int qcom_snps_hsphy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct phy_provider *provider;
struct hsphy_priv *priv;
struct phy *phy;
int ret;
int i;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
priv->num_clks = ARRAY_SIZE(qcom_snps_hsphy_clks);
priv->clks = devm_kcalloc(dev, priv->num_clks, sizeof(*priv->clks),
GFP_KERNEL);
if (!priv->clks)
return -ENOMEM;
for (i = 0; i < priv->num_clks; i++)
priv->clks[i].id = qcom_snps_hsphy_clks[i];
ret = devm_clk_bulk_get(dev, priv->num_clks, priv->clks);
if (ret)
return ret;
priv->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
if (IS_ERR(priv->phy_reset))
return PTR_ERR(priv->phy_reset);
priv->por_reset = devm_reset_control_get_exclusive(dev, "por");
if (IS_ERR(priv->por_reset))
return PTR_ERR(priv->por_reset);
priv->vregs[VDD].supply = "vdd";
priv->vregs[VDDA_1P8].supply = "vdda1p8";
priv->vregs[VDDA_3P3].supply = "vdda3p3";
ret = devm_regulator_bulk_get(dev, VREG_NUM, priv->vregs);
if (ret)
return ret;
/* Get device match data */
priv->data = device_get_match_data(dev);
phy = devm_phy_create(dev, dev->of_node, &qcom_snps_hsphy_ops);
if (IS_ERR(phy))
return PTR_ERR(phy);
phy_set_drvdata(phy, priv);
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(provider))
return PTR_ERR(provider);
ret = regulator_set_load(priv->vregs[VDDA_1P8].consumer, 19000);
if (ret < 0)
return ret;
ret = regulator_set_load(priv->vregs[VDDA_3P3].consumer, 16000);
if (ret < 0)
goto unset_1p8_load;
return 0;
unset_1p8_load:
regulator_set_load(priv->vregs[VDDA_1P8].consumer, 0);
return ret;
}
/*
* The macro is used to define an initialization sequence. Each tuple
* is meant to program 'value' into phy register at 'offset' with 'delay'
* in us followed.
*/
#define HSPHY_INIT_CFG(o, v, d) { .offset = o, .val = v, .delay = d, }
static const struct hsphy_init_seq init_seq_femtophy[] = {
HSPHY_INIT_CFG(0xc0, 0x01, 0),
HSPHY_INIT_CFG(0xe8, 0x0d, 0),
HSPHY_INIT_CFG(0x74, 0x12, 0),
HSPHY_INIT_CFG(0x98, 0x63, 0),
HSPHY_INIT_CFG(0x9c, 0x03, 0),
HSPHY_INIT_CFG(0xa0, 0x1d, 0),
HSPHY_INIT_CFG(0xa4, 0x03, 0),
HSPHY_INIT_CFG(0x8c, 0x23, 0),
HSPHY_INIT_CFG(0x78, 0x08, 0),
HSPHY_INIT_CFG(0x7c, 0xdc, 0),
HSPHY_INIT_CFG(0x90, 0xe0, 20),
HSPHY_INIT_CFG(0x74, 0x10, 0),
HSPHY_INIT_CFG(0x90, 0x60, 0),
};
static const struct hsphy_data hsphy_data_femtophy = {
.init_seq = init_seq_femtophy,
.init_seq_num = ARRAY_SIZE(init_seq_femtophy),
};
static const struct of_device_id qcom_snps_hsphy_match[] = {
{ .compatible = "qcom,usb-hs-28nm-femtophy", .data = &hsphy_data_femtophy, },
{ },
};
MODULE_DEVICE_TABLE(of, qcom_snps_hsphy_match);
static struct platform_driver qcom_snps_hsphy_driver = {
.probe = qcom_snps_hsphy_probe,
.driver = {
.name = "qcom,usb-hs-28nm-phy",
.of_match_table = qcom_snps_hsphy_match,
},
};
module_platform_driver(qcom_snps_hsphy_driver);
MODULE_DESCRIPTION("Qualcomm 28nm Hi-Speed USB PHY driver");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,246 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2012-2014,2017 The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2020, Linaro Limited
*/
#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/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/slab.h>
#define PHY_CTRL0 0x6C
#define PHY_CTRL1 0x70
#define PHY_CTRL2 0x74
#define PHY_CTRL4 0x7C
/* PHY_CTRL bits */
#define REF_PHY_EN BIT(0)
#define LANE0_PWR_ON BIT(2)
#define SWI_PCS_CLK_SEL BIT(4)
#define TST_PWR_DOWN BIT(4)
#define PHY_RESET BIT(7)
#define NUM_BULK_CLKS 3
#define NUM_BULK_REGS 2
struct ssphy_priv {
void __iomem *base;
struct device *dev;
struct reset_control *reset_com;
struct reset_control *reset_phy;
struct regulator_bulk_data regs[NUM_BULK_REGS];
struct clk_bulk_data clks[NUM_BULK_CLKS];
enum phy_mode mode;
};
static inline void qcom_ssphy_updatel(void __iomem *addr, u32 mask, u32 val)
{
writel((readl(addr) & ~mask) | val, addr);
}
static int qcom_ssphy_do_reset(struct ssphy_priv *priv)
{
int ret;
if (!priv->reset_com) {
qcom_ssphy_updatel(priv->base + PHY_CTRL1, PHY_RESET,
PHY_RESET);
usleep_range(10, 20);
qcom_ssphy_updatel(priv->base + PHY_CTRL1, PHY_RESET, 0);
} else {
ret = reset_control_assert(priv->reset_com);
if (ret) {
dev_err(priv->dev, "Failed to assert reset com\n");
return ret;
}
ret = reset_control_assert(priv->reset_phy);
if (ret) {
dev_err(priv->dev, "Failed to assert reset phy\n");
return ret;
}
usleep_range(10, 20);
ret = reset_control_deassert(priv->reset_com);
if (ret) {
dev_err(priv->dev, "Failed to deassert reset com\n");
return ret;
}
ret = reset_control_deassert(priv->reset_phy);
if (ret) {
dev_err(priv->dev, "Failed to deassert reset phy\n");
return ret;
}
}
return 0;
}
static int qcom_ssphy_power_on(struct phy *phy)
{
struct ssphy_priv *priv = phy_get_drvdata(phy);
int ret;
ret = regulator_bulk_enable(NUM_BULK_REGS, priv->regs);
if (ret)
return ret;
ret = clk_bulk_prepare_enable(NUM_BULK_CLKS, priv->clks);
if (ret)
goto err_disable_regulator;
ret = qcom_ssphy_do_reset(priv);
if (ret)
goto err_disable_clock;
writeb(SWI_PCS_CLK_SEL, priv->base + PHY_CTRL0);
qcom_ssphy_updatel(priv->base + PHY_CTRL4, LANE0_PWR_ON, LANE0_PWR_ON);
qcom_ssphy_updatel(priv->base + PHY_CTRL2, REF_PHY_EN, REF_PHY_EN);
qcom_ssphy_updatel(priv->base + PHY_CTRL4, TST_PWR_DOWN, 0);
return 0;
err_disable_clock:
clk_bulk_disable_unprepare(NUM_BULK_CLKS, priv->clks);
err_disable_regulator:
regulator_bulk_disable(NUM_BULK_REGS, priv->regs);
return ret;
}
static int qcom_ssphy_power_off(struct phy *phy)
{
struct ssphy_priv *priv = phy_get_drvdata(phy);
qcom_ssphy_updatel(priv->base + PHY_CTRL4, LANE0_PWR_ON, 0);
qcom_ssphy_updatel(priv->base + PHY_CTRL2, REF_PHY_EN, 0);
qcom_ssphy_updatel(priv->base + PHY_CTRL4, TST_PWR_DOWN, TST_PWR_DOWN);
clk_bulk_disable_unprepare(NUM_BULK_CLKS, priv->clks);
regulator_bulk_disable(NUM_BULK_REGS, priv->regs);
return 0;
}
static int qcom_ssphy_init_clock(struct ssphy_priv *priv)
{
priv->clks[0].id = "ref";
priv->clks[1].id = "ahb";
priv->clks[2].id = "pipe";
return devm_clk_bulk_get(priv->dev, NUM_BULK_CLKS, priv->clks);
}
static int qcom_ssphy_init_regulator(struct ssphy_priv *priv)
{
int ret;
priv->regs[0].supply = "vdd";
priv->regs[1].supply = "vdda1p8";
ret = devm_regulator_bulk_get(priv->dev, NUM_BULK_REGS, priv->regs);
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(priv->dev, "Failed to get regulators\n");
return ret;
}
return ret;
}
static int qcom_ssphy_init_reset(struct ssphy_priv *priv)
{
priv->reset_com = devm_reset_control_get_optional_exclusive(priv->dev, "com");
if (IS_ERR(priv->reset_com)) {
dev_err(priv->dev, "Failed to get reset control com\n");
return PTR_ERR(priv->reset_com);
}
if (priv->reset_com) {
/* if reset_com is present, reset_phy is no longer optional */
priv->reset_phy = devm_reset_control_get_exclusive(priv->dev, "phy");
if (IS_ERR(priv->reset_phy)) {
dev_err(priv->dev, "Failed to get reset control phy\n");
return PTR_ERR(priv->reset_phy);
}
}
return 0;
}
static const struct phy_ops qcom_ssphy_ops = {
.power_off = qcom_ssphy_power_off,
.power_on = qcom_ssphy_power_on,
.owner = THIS_MODULE,
};
static int qcom_ssphy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct phy_provider *provider;
struct ssphy_priv *priv;
struct phy *phy;
int ret;
priv = devm_kzalloc(dev, sizeof(struct ssphy_priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->dev = dev;
priv->mode = PHY_MODE_INVALID;
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
ret = qcom_ssphy_init_clock(priv);
if (ret)
return ret;
ret = qcom_ssphy_init_reset(priv);
if (ret)
return ret;
ret = qcom_ssphy_init_regulator(priv);
if (ret)
return ret;
phy = devm_phy_create(dev, dev->of_node, &qcom_ssphy_ops);
if (IS_ERR(phy)) {
dev_err(dev, "Failed to create the SS phy\n");
return PTR_ERR(phy);
}
phy_set_drvdata(phy, priv);
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(provider);
}
static const struct of_device_id qcom_ssphy_match[] = {
{ .compatible = "qcom,usb-ss-28nm-phy", },
{ },
};
MODULE_DEVICE_TABLE(of, qcom_ssphy_match);
static struct platform_driver qcom_ssphy_driver = {
.probe = qcom_ssphy_probe,
.driver = {
.name = "qcom-usb-ssphy",
.of_match_table = qcom_ssphy_match,
},
};
module_platform_driver(qcom_ssphy_driver);
MODULE_DESCRIPTION("Qualcomm SuperSpeed USB PHY driver");
MODULE_LICENSE("GPL v2");

View file

@ -763,7 +763,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
/* put the controller in normal mode */
property_enable(base, &rphy->phy_cfg->chg_det.opmode, true);
rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
dev_info(&rport->phy->dev, "charger = %s\n",
dev_dbg(&rport->phy->dev, "charger = %s\n",
chg_to_string(rphy->chg_type));
return;
default:

View file

@ -19,6 +19,10 @@
#include <linux/resource.h>
/* PHY */
#define PCL_PHY_CLKCTRL 0x0000
#define PORT_SEL_MASK GENMASK(11, 9)
#define PORT_SEL_1 FIELD_PREP(PORT_SEL_MASK, 1)
#define PCL_PHY_TEST_I 0x2000
#define PCL_PHY_TEST_O 0x2004
#define TESTI_DAT_MASK GENMASK(13, 6)
@ -45,13 +49,14 @@
struct uniphier_pciephy_priv {
void __iomem *base;
struct device *dev;
struct clk *clk;
struct reset_control *rst;
struct clk *clk, *clk_gio;
struct reset_control *rst, *rst_gio;
const struct uniphier_pciephy_soc_data *data;
};
struct uniphier_pciephy_soc_data {
bool has_syscon;
bool is_legacy;
void (*set_phymode)(struct regmap *regmap);
};
static void uniphier_pciephy_testio_write(struct uniphier_pciephy_priv *priv,
@ -111,16 +116,35 @@ static void uniphier_pciephy_deassert(struct uniphier_pciephy_priv *priv)
static int uniphier_pciephy_init(struct phy *phy)
{
struct uniphier_pciephy_priv *priv = phy_get_drvdata(phy);
u32 val;
int ret;
ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
ret = reset_control_deassert(priv->rst);
ret = clk_prepare_enable(priv->clk_gio);
if (ret)
goto out_clk_disable;
ret = reset_control_deassert(priv->rst);
if (ret)
goto out_clk_gio_disable;
ret = reset_control_deassert(priv->rst_gio);
if (ret)
goto out_rst_assert;
/* support only 1 port */
val = readl(priv->base + PCL_PHY_CLKCTRL);
val &= ~PORT_SEL_MASK;
val |= PORT_SEL_1;
writel(val, priv->base + PCL_PHY_CLKCTRL);
/* legacy controller doesn't have phy_reset and parameters */
if (priv->data->is_legacy)
return 0;
uniphier_pciephy_set_param(priv, PCL_PHY_R00,
RX_EQ_ADJ_EN, RX_EQ_ADJ_EN);
uniphier_pciephy_set_param(priv, PCL_PHY_R06, RX_EQ_ADJ,
@ -134,6 +158,10 @@ static int uniphier_pciephy_init(struct phy *phy)
return 0;
out_rst_assert:
reset_control_assert(priv->rst);
out_clk_gio_disable:
clk_disable_unprepare(priv->clk_gio);
out_clk_disable:
clk_disable_unprepare(priv->clk);
@ -144,8 +172,11 @@ static int uniphier_pciephy_exit(struct phy *phy)
{
struct uniphier_pciephy_priv *priv = phy_get_drvdata(phy);
uniphier_pciephy_assert(priv);
if (!priv->data->is_legacy)
uniphier_pciephy_assert(priv);
reset_control_assert(priv->rst_gio);
reset_control_assert(priv->rst);
clk_disable_unprepare(priv->clk_gio);
clk_disable_unprepare(priv->clk);
return 0;
@ -163,7 +194,6 @@ static int uniphier_pciephy_probe(struct platform_device *pdev)
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
struct regmap *regmap;
struct resource *res;
struct phy *phy;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@ -176,18 +206,36 @@ static int uniphier_pciephy_probe(struct platform_device *pdev)
priv->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(dev, res);
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
if (priv->data->is_legacy) {
priv->clk_gio = devm_clk_get(dev, "gio");
if (IS_ERR(priv->clk_gio))
return PTR_ERR(priv->clk_gio);
priv->rst = devm_reset_control_get_shared(dev, NULL);
if (IS_ERR(priv->rst))
return PTR_ERR(priv->rst);
priv->rst_gio =
devm_reset_control_get_shared(dev, "gio");
if (IS_ERR(priv->rst_gio))
return PTR_ERR(priv->rst_gio);
priv->clk = devm_clk_get(dev, "link");
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
priv->rst = devm_reset_control_get_shared(dev, "link");
if (IS_ERR(priv->rst))
return PTR_ERR(priv->rst);
} else {
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
priv->rst = devm_reset_control_get_shared(dev, NULL);
if (IS_ERR(priv->rst))
return PTR_ERR(priv->rst);
}
phy = devm_phy_create(dev, dev->of_node, &uniphier_pciephy_ops);
if (IS_ERR(phy))
@ -195,9 +243,8 @@ static int uniphier_pciephy_probe(struct platform_device *pdev)
regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
"socionext,syscon");
if (!IS_ERR(regmap) && priv->data->has_syscon)
regmap_update_bits(regmap, SG_USBPCIESEL,
SG_USBPCIESEL_PCIE, SG_USBPCIESEL_PCIE);
if (!IS_ERR(regmap) && priv->data->set_phymode)
priv->data->set_phymode(regmap);
phy_set_drvdata(phy, priv);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
@ -205,15 +252,30 @@ static int uniphier_pciephy_probe(struct platform_device *pdev)
return PTR_ERR_OR_ZERO(phy_provider);
}
static void uniphier_pciephy_ld20_setmode(struct regmap *regmap)
{
regmap_update_bits(regmap, SG_USBPCIESEL,
SG_USBPCIESEL_PCIE, SG_USBPCIESEL_PCIE);
}
static const struct uniphier_pciephy_soc_data uniphier_pro5_data = {
.is_legacy = true,
};
static const struct uniphier_pciephy_soc_data uniphier_ld20_data = {
.has_syscon = true,
.is_legacy = false,
.set_phymode = uniphier_pciephy_ld20_setmode,
};
static const struct uniphier_pciephy_soc_data uniphier_pxs3_data = {
.has_syscon = false,
.is_legacy = false,
};
static const struct of_device_id uniphier_pciephy_match[] = {
{
.compatible = "socionext,uniphier-pro5-pcie-phy",
.data = &uniphier_pro5_data,
},
{
.compatible = "socionext,uniphier-ld20-pcie-phy",
.data = &uniphier_ld20_data,

View file

@ -41,10 +41,12 @@
#define PHY_F(regno, msb, lsb) { (regno), (msb), (lsb) }
#define RX_CHK_SYNC PHY_F(0, 5, 5) /* RX sync mode */
#define RX_SYNC_SEL PHY_F(1, 1, 0) /* RX sync length */
#define LS_SLEW PHY_F(10, 6, 6) /* LS mode slew rate */
#define FS_LS_DRV PHY_F(10, 5, 5) /* FS/LS slew rate */
#define MAX_PHY_PARAMS 2
#define MAX_PHY_PARAMS 4
struct uniphier_u3hsphy_param {
struct {
@ -66,13 +68,14 @@ struct uniphier_u3hsphy_trim_param {
struct uniphier_u3hsphy_priv {
struct device *dev;
void __iomem *base;
struct clk *clk, *clk_parent, *clk_ext;
struct reset_control *rst, *rst_parent;
struct clk *clk, *clk_parent, *clk_ext, *clk_parent_gio;
struct reset_control *rst, *rst_parent, *rst_parent_gio;
struct regulator *vbus;
const struct uniphier_u3hsphy_soc_data *data;
};
struct uniphier_u3hsphy_soc_data {
bool is_legacy;
int nparams;
const struct uniphier_u3hsphy_param param[MAX_PHY_PARAMS];
u32 config0;
@ -256,11 +259,20 @@ static int uniphier_u3hsphy_init(struct phy *phy)
if (ret)
return ret;
ret = reset_control_deassert(priv->rst_parent);
ret = clk_prepare_enable(priv->clk_parent_gio);
if (ret)
goto out_clk_disable;
if (!priv->data->config0 && !priv->data->config1)
ret = reset_control_deassert(priv->rst_parent);
if (ret)
goto out_clk_gio_disable;
ret = reset_control_deassert(priv->rst_parent_gio);
if (ret)
goto out_rst_assert;
if ((priv->data->is_legacy)
|| (!priv->data->config0 && !priv->data->config1))
return 0;
config0 = priv->data->config0;
@ -280,6 +292,8 @@ static int uniphier_u3hsphy_init(struct phy *phy)
out_rst_assert:
reset_control_assert(priv->rst_parent);
out_clk_gio_disable:
clk_disable_unprepare(priv->clk_parent_gio);
out_clk_disable:
clk_disable_unprepare(priv->clk_parent);
@ -290,7 +304,9 @@ static int uniphier_u3hsphy_exit(struct phy *phy)
{
struct uniphier_u3hsphy_priv *priv = phy_get_drvdata(phy);
reset_control_assert(priv->rst_parent_gio);
reset_control_assert(priv->rst_parent);
clk_disable_unprepare(priv->clk_parent_gio);
clk_disable_unprepare(priv->clk_parent);
return 0;
@ -309,7 +325,6 @@ static int uniphier_u3hsphy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct uniphier_u3hsphy_priv *priv;
struct phy_provider *phy_provider;
struct resource *res;
struct phy *phy;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@ -322,27 +337,38 @@ static int uniphier_u3hsphy_probe(struct platform_device *pdev)
priv->data->nparams > MAX_PHY_PARAMS))
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(dev, res);
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
priv->clk = devm_clk_get(dev, "phy");
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
if (!priv->data->is_legacy) {
priv->clk = devm_clk_get(dev, "phy");
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
priv->clk_ext = devm_clk_get_optional(dev, "phy-ext");
if (IS_ERR(priv->clk_ext))
return PTR_ERR(priv->clk_ext);
priv->rst = devm_reset_control_get_shared(dev, "phy");
if (IS_ERR(priv->rst))
return PTR_ERR(priv->rst);
} else {
priv->clk_parent_gio = devm_clk_get(dev, "gio");
if (IS_ERR(priv->clk_parent_gio))
return PTR_ERR(priv->clk_parent_gio);
priv->rst_parent_gio =
devm_reset_control_get_shared(dev, "gio");
if (IS_ERR(priv->rst_parent_gio))
return PTR_ERR(priv->rst_parent_gio);
}
priv->clk_parent = devm_clk_get(dev, "link");
if (IS_ERR(priv->clk_parent))
return PTR_ERR(priv->clk_parent);
priv->clk_ext = devm_clk_get_optional(dev, "phy-ext");
if (IS_ERR(priv->clk_ext))
return PTR_ERR(priv->clk_ext);
priv->rst = devm_reset_control_get_shared(dev, "phy");
if (IS_ERR(priv->rst))
return PTR_ERR(priv->rst);
priv->rst_parent = devm_reset_control_get_shared(dev, "link");
if (IS_ERR(priv->rst_parent))
return PTR_ERR(priv->rst_parent);
@ -364,13 +390,26 @@ static int uniphier_u3hsphy_probe(struct platform_device *pdev)
return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct uniphier_u3hsphy_soc_data uniphier_pxs2_data = {
static const struct uniphier_u3hsphy_soc_data uniphier_pro5_data = {
.is_legacy = true,
.nparams = 0,
};
static const struct uniphier_u3hsphy_soc_data uniphier_ld20_data = {
static const struct uniphier_u3hsphy_soc_data uniphier_pxs2_data = {
.is_legacy = false,
.nparams = 2,
.param = {
{ RX_CHK_SYNC, 1 },
{ RX_SYNC_SEL, 1 },
},
};
static const struct uniphier_u3hsphy_soc_data uniphier_ld20_data = {
.is_legacy = false,
.nparams = 4,
.param = {
{ RX_CHK_SYNC, 1 },
{ RX_SYNC_SEL, 1 },
{ LS_SLEW, 1 },
{ FS_LS_DRV, 1 },
},
@ -380,13 +419,22 @@ static const struct uniphier_u3hsphy_soc_data uniphier_ld20_data = {
};
static const struct uniphier_u3hsphy_soc_data uniphier_pxs3_data = {
.nparams = 0,
.is_legacy = false,
.nparams = 2,
.param = {
{ RX_CHK_SYNC, 1 },
{ RX_SYNC_SEL, 1 },
},
.trim_func = uniphier_u3hsphy_trim_ld20,
.config0 = 0x92316680,
.config1 = 0x00000106,
};
static const struct of_device_id uniphier_u3hsphy_match[] = {
{
.compatible = "socionext,uniphier-pro5-usb3-hsphy",
.data = &uniphier_pro5_data,
},
{
.compatible = "socionext,uniphier-pxs2-usb3-hsphy",
.data = &uniphier_pxs2_data,

View file

@ -215,7 +215,6 @@ static int uniphier_u3ssphy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct uniphier_u3ssphy_priv *priv;
struct phy_provider *phy_provider;
struct resource *res;
struct phy *phy;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@ -228,8 +227,7 @@ static int uniphier_u3ssphy_probe(struct platform_device *pdev)
priv->data->nparams > MAX_PHY_PARAMS))
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(dev, res);
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
@ -314,6 +312,10 @@ static const struct of_device_id uniphier_u3ssphy_match[] = {
.compatible = "socionext,uniphier-pro4-usb3-ssphy",
.data = &uniphier_pro4_data,
},
{
.compatible = "socionext,uniphier-pro5-usb3-ssphy",
.data = &uniphier_pro4_data,
},
{
.compatible = "socionext,uniphier-pxs2-usb3-ssphy",
.data = &uniphier_pxs2_data,

View file

@ -170,6 +170,21 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_soc_dm814 = {
.regfields = phy_gmii_sel_fields_am33xx,
};
static const
struct reg_field phy_gmii_sel_fields_am654[][PHY_GMII_SEL_LAST] = {
{
[PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x4040, 0, 1),
[PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD((~0), 0, 0),
[PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD((~0), 0, 0),
},
};
static const
struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am654 = {
.num_ports = 1,
.regfields = phy_gmii_sel_fields_am654,
};
static const struct of_device_id phy_gmii_sel_id_table[] = {
{
.compatible = "ti,am3352-phy-gmii-sel",
@ -187,6 +202,10 @@ static const struct of_device_id phy_gmii_sel_id_table[] = {
.compatible = "ti,dm814-phy-gmii-sel",
.data = &phy_gmii_sel_soc_dm814,
},
{
.compatible = "ti,am654-phy-gmii-sel",
.data = &phy_gmii_sel_soc_am654,
},
{}
};
MODULE_DEVICE_TABLE(of, phy_gmii_sel_id_table);