phy-for-7.0

- Core
   - Add suuport for "rx-polarity" and "tx-polarity" device tree properties
     and phy common properties to manage this
 
  - New Support
   - Qualcomm Glymur PCIe Gen4 2-lanes PCIe phy, DP and edp phy support, USB
     UNI PHY support and SMB2370 eUSB2 repeater support. SC8280xp QMP UFS PHY
     support, Kaanapali PCIe phy and QMP PHY support, QCS615 QMP USB3+DP PHY
     and driver support for that.
   - SpacemiT PCIe/combo PHY and K1 USB2 PHY driver.
   - HDMI 2.1 FRL configuration support and driver enabling for rockchip
     samsung-hdptx driver.
   - TI TCAN1046 phy support.
   - Renesas RZ/V2H(P) and RZ/V2N usb3 support
   - Mediatek MT8188 hdmi-phy support
   - Google Tensor SoC USB PHY driver
   - Apple Type-C PHY support
 
 - Updates
   - Subsystem conversion for clock round_rate() to determine_rate()
   - TI USB3 DT schema conversion
   - Samsung ExynosAutov920 usb3, combo hsphy and ssphy support
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmmUivwACgkQfBQHDyUj
 g0cbiQ/6A88WwlDoA/hh5NFN/5mkloHaVvcbYEraqvkzpdsWjCXOxQXfCBC5IVI+
 BOn8GjjVEQMKLs8V7LXF/ZdGGJ+DI0TOod1GLrgKX/q8YL6XTxZ5DThWqSZrVRBI
 SXY8/PFu6t12frVN7+f5l00m3/e/V1vdO1s1TBIzsrIt72RWI9vggjaLG9Gi0q3/
 XBvgJFHV7/S5QIpn4+mL8b/r0CUshUnRX4VkIn5nRT+QUlZejs4RcuB322NF5Cva
 ghFPLv5wrniZl6PGRsQyoEtPNS1mjJpnbKf0HqU/4BeaaVh+ylDu4ooXxH6w3E4v
 vpk93MT3ZZXJWb1I6LkHJJnm5E5J8QRqhJXaeAoYXNsQZBx1L3CkpZG9DR2nO7V5
 fv2eL/C2uDbPRovj4OT4BNAHXziqqjFTpS8se0U8MNG0qri0KmPJmP6MkSHM+pLg
 USOsln+geUBsMkbqrDmy4RLPvP61qqid8RsPXxZoQpJiIrAL8WoT1JQ2DOh6NwqJ
 IyPicLPihevXCvvLGm44HfYOHAcG+IGCD71vwOxnRkLFefc10Lg9FhnzHCKrnJvR
 ELbx8ucu5+XRsL4mJa8DU6bi8DF4unzVpfBPvmguZtGS1noaDnsYGO5xTMeHZGMX
 WASaH25iuEtXgLXfeeHvkxqPXP2oZHqVRT4rlIZ7O7ODU79Dshw=
 =6ibD
 -----END PGP SIGNATURE-----

Merge tag 'phy-for-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy

Pull phy updates from Vinod Koul:
 "Core:

   - Add suuport for "rx-polarity" and "tx-polarity" device tree
     properties and phy common properties to manage this

  New Support:

   - Qualcomm Glymur PCIe Gen4 2-lanes PCIe phy, DP and edp phy, USB UNI
     PHY and SMB2370 eUSB2 repeater. SC8280xp QMP UFS PHY, Kaanapali
     PCIe phy and QMP PHY, QCS615 QMP USB3+DP PHY and driver support for
     that.

   - SpacemiT PCIe/combo PHY and K1 USB2 PHY driver.

   - HDMI 2.1 FRL configuration support and driver enabling for rockchip
     samsung-hdptx driver

   - TI TCAN1046 phy

   - Renesas RZ/V2H(P) and RZ/V2N usb3

   - Mediatek MT8188 hdmi-phy

   - Google Tensor SoC USB PHY driver

   - Apple Type-C PHY

  Updates:

   - Subsystem conversion for clock round_rate() to determine_rate()

   - TI USB3 DT schema conversion

   - Samsung ExynosAutov920 usb3, combo hsphy and ssphy support"

* tag 'phy-for-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (143 commits)
  phy: ti: phy-j721e-wiz: convert from divider_round_rate() to divider_determine_rate()
  dt-bindings: phy: ti,control-phy-otghs: convert to DT schema
  dt-bindings: phy: ti,phy-usb3: convert to DT schema
  phy: tegra: xusb: Remove unused powered_on variable
  phy: renesas: rcar-gen3-usb2: add regulator dependency
  phy: GOOGLE_USB: add TYPEC dependency
  phy: enter drivers/phy/Makefile even without CONFIG_GENERIC_PHY
  phy: renesas: rcar-gen3-usb2: Use mux-state for phyrst management
  phy: renesas: rcar-gen3-usb2: Add regulator for OTG VBUS control
  phy: renesas: rcar-gen3-usb2: Use devm_pm_runtime_enable()
  phy: renesas: rcar-gen3-usb2: Factor out VBUS control logic
  dt-bindings: phy: renesas,usb2-phy: Document RZ/G3E SoC
  dt-bindings: phy: renesas,usb2-phy: Document mux-states property
  dt-bindings: phy: renesas,usb2-phy: Document USB VBUS regulator
  phy: rockchip: samsung-hdptx: Add HDMI 2.1 FRL support
  phy: rockchip: samsung-hdptx: Extend rk_hdptx_phy_verify_hdmi_config() helper
  phy: rockchip: samsung-hdptx: Switch to driver specific HDMI config
  phy: rockchip: samsung-hdptx: Drop hw_rate driver data
  phy: rockchip: samsung-hdptx: Compute clk rate from PLL config
  phy: rockchip: samsung-hdptx: Cleanup *_cmn_init_seq lists
  ...
This commit is contained in:
Linus Torvalds 2026-02-17 11:40:04 -08:00
commit 9b725d5959
93 changed files with 11325 additions and 876 deletions

View file

@ -0,0 +1,222 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/apple,atcphy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Apple Type-C PHY (ATCPHY)
maintainers:
- Sven Peter <sven@kernel.org>
description: >
The Apple Type-C PHY (ATCPHY) is a combined PHY for USB 2.0, USB 3.x,
USB4/Thunderbolt, and DisplayPort connectivity via Type-C ports found in
Apple Silicon SoCs.
The PHY handles muxing between these different protocols and also provides the
reset controller for the attached DWC3 USB controller.
It is designed for USB4 operation and does not handle individual differential
pairs as distinct DisplayPort lanes. Any reference to lane in this binding
hence refers to two differential pairs (RX and TX) as used in USB terminology.
In order to correctly setup these lanes for the various modes calibration
values copied from Apple's firmware and converted to the format described
below by our bootloader m1n1 are required. Without these only USB2 operation
is possible.
allOf:
- $ref: /schemas/usb/usb-switch.yaml#
$defs:
apple,tunable:
$ref: /schemas/types.yaml#/definitions/uint32-matrix
items:
items:
- description: Register offset
- description: Mask to be applied to the register value
- description: Bits to be set after applying the mask
description: >
List of (register offset, mask, value) tuples copied from Apple's Device
Tree by our bootloader m1n1 and used to configure the PHY. These values
even vary for a single product/device and likely contain calibration
values determined by Apple at manufacturing time.
Unless otherwise noted these tunables are always applied to the core
register region.
properties:
compatible:
oneOf:
- items:
- enum:
- apple,t6000-atcphy
- apple,t6020-atcphy
- apple,t8112-atcphy
- const: apple,t8103-atcphy
- const: apple,t8103-atcphy
reg:
items:
- description: Common controls for all PHYs (USB2/3/4, DisplayPort, TBT)
- description: DisplayPort Alternate Mode PHY specific controls
- description: Type-C PHY AXI to Apple Fabric interconnect controls
- description: USB2 PHY specific controls
- description: USB3 PIPE interface controls
reg-names:
items:
- const: core
- const: lpdptx
- const: axi2af
- const: usb2phy
- const: pipehandler
"#phy-cells":
const: 1
"#reset-cells":
const: 0
mode-switch: true
orientation-switch: true
power-domains:
maxItems: 1
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description: Outgoing connection to the SS port of the Type-C connector.
port@1:
$ref: /schemas/graph.yaml#/properties/port
description: Incoming endpoint from the USB3 controller.
port@2:
$ref: /schemas/graph.yaml#/properties/port
description: Incoming endpoint from the DisplayPort controller.
port@3:
$ref: /schemas/graph.yaml#/properties/port
description: Incoming endpoint from the USB4/Thunderbolt controller.
apple,tunable-common-a:
$ref: "#/$defs/apple,tunable"
description: >
Common tunables required for all modes, applied before tunable-axi2af.
apple,tunable-axi2af:
$ref: "#/$defs/apple,tunable"
description: >
AXI to Apple Fabric tunables, required for all modes. Unlike all other
tunables these are applied to the axi2af region.
apple,tunable-common-b:
$ref: "#/$defs/apple,tunable"
description: >
Common tunables required for all modes, applied after tunable-axi2af.
apple,tunable-lane0-usb:
$ref: "#/$defs/apple,tunable"
description: USB3 tunables for lane 0.
apple,tunable-lane1-usb:
$ref: "#/$defs/apple,tunable"
description: USB3 tunables for lane 1.
apple,tunable-lane0-cio:
$ref: "#/$defs/apple,tunable"
description: USB4/Thunderbolt ("Converged IO") tunables for lane 0.
apple,tunable-lane1-cio:
$ref: "#/$defs/apple,tunable"
description: USB4/Thunderbolt ("Converged IO") tunables for lane 1.
apple,tunable-lane0-dp:
$ref: "#/$defs/apple,tunable"
description: >
DisplayPort tunables for lane 0.
Note that lane here refers to a USB RX and TX pair re-used for DisplayPort
and not to an individual DisplayPort differential lane.
apple,tunable-lane1-dp:
$ref: "#/$defs/apple,tunable"
description: >
DisplayPort tunables for lane 1.
Note that lane here refers to a USB RX and TX pair re-used for DisplayPort
and not to an individual DisplayPort differential lane.
required:
- compatible
- reg
- reg-names
- "#phy-cells"
- "#reset-cells"
- orientation-switch
- mode-switch
- power-domains
- ports
additionalProperties: false
examples:
- |
phy@83000000 {
compatible = "apple,t8103-atcphy";
reg = <0x83000000 0x4c000>,
<0x83050000 0x8000>,
<0x80000000 0x4000>,
<0x82a90000 0x4000>,
<0x82a84000 0x4000>;
reg-names = "core", "lpdptx", "axi2af", "usb2phy",
"pipehandler";
#phy-cells = <1>;
#reset-cells = <0>;
orientation-switch;
mode-switch;
power-domains = <&ps_atc0_usb>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
endpoint {
remote-endpoint = <&typec_connector_ss>;
};
};
port@1 {
reg = <1>;
endpoint {
remote-endpoint = <&dwc3_ss_out>;
};
};
port@2 {
reg = <2>;
endpoint {
remote-endpoint = <&dcp_dp_out>;
};
};
port@3 {
reg = <3>;
endpoint {
remote-endpoint = <&acio_tbt_out>;
};
};
};
};

View file

@ -20,6 +20,32 @@ properties:
"#phy-cells":
const: 1
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"^phy@[0-7]$":
type: object
description: SerDes lane (single RX/TX differential pair)
properties:
reg:
minimum: 0
maximum: 7
description: Lane index as seen in register map
"#phy-cells":
const: 0
required:
- reg
- "#phy-cells"
additionalProperties: false
required:
- compatible
- reg
@ -32,9 +58,52 @@ examples:
soc {
#address-cells = <2>;
#size-cells = <2>;
serdes_1: phy@1ea0000 {
serdes@1ea0000 {
compatible = "fsl,lynx-28g";
reg = <0x0 0x1ea0000 0x0 0x1e30>;
#address-cells = <1>;
#size-cells = <0>;
#phy-cells = <1>;
phy@0 {
reg = <0>;
#phy-cells = <0>;
};
phy@1 {
reg = <1>;
#phy-cells = <0>;
};
phy@2 {
reg = <2>;
#phy-cells = <0>;
};
phy@3 {
reg = <3>;
#phy-cells = <0>;
};
phy@4 {
reg = <4>;
#phy-cells = <0>;
};
phy@5 {
reg = <5>;
#phy-cells = <0>;
};
phy@6 {
reg = <6>;
#phy-cells = <0>;
};
phy@7 {
reg = <7>;
#phy-cells = <0>;
};
};
};

View file

@ -0,0 +1,133 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2025, Google LLC
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/google,lga-usb-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Google Tensor Series G5 (Laguna) USB PHY
maintainers:
- Roy Luo <royluo@google.com>
description:
Describes the USB PHY interfaces integrated with the DWC3 USB controller on
Google Tensor SoCs, starting with the G5 generation (laguna).
Two specific PHY IPs from Synopsys are integrated, including eUSB 2.0 PHY IP
and USB3.2/DisplayPort combo PHY IP.
properties:
compatible:
const: google,lga-usb-phy
reg:
items:
- description: USB3.2/DisplayPort combo PHY core registers.
- description: USB3.2/DisplayPort combo PHY Type-C Assist registers.
- description: eUSB 2.0 PHY core registers.
- description: Top-level wrapper registers for the integrated PHYs.
reg-names:
items:
- const: usb3_core
- const: usb3_tca
- const: usb2_core
- const: usbdp_top
"#phy-cells":
description: |
The phandle's argument in the PHY specifier selects one of the three
following PHY interfaces.
- 0 for USB high-speed.
- 1 for USB super-speed.
- 2 for DisplayPort.
const: 1
clocks:
items:
- description: USB2 PHY clock.
- description: USB2 PHY APB clock.
- description: USB3.2/DisplayPort combo PHY clock.
- description: USB3.2/DisplayPort combo PHY firmware clock.
clock-names:
items:
- const: usb2
- const: usb2_apb
- const: usb3
- const: usb3_fw
resets:
items:
- description: USB2 PHY reset.
- description: USB2 PHY APB reset.
- description: USB3.2/DisplayPort combo PHY reset.
reset-names:
items:
- const: usb2
- const: usb2_apb
- const: usb3
power-domains:
maxItems: 1
orientation-switch:
type: boolean
description:
Indicates the PHY as a handler of USB Type-C orientation changes
google,usb-cfg-csr:
description:
A phandle to a syscon node used to access the USB configuration
registers. These registers are the top-level wrapper of the USB
subsystem and provide control and status for the integrated USB
controller and USB PHY.
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
- description: phandle to the syscon node.
- description: USB2 PHY configuration register offset.
required:
- compatible
- reg
- reg-names
- "#phy-cells"
- clocks
- clock-names
- resets
- reset-names
- power-domains
- orientation-switch
- google,usb-cfg-csr
additionalProperties: false
examples:
- |
soc {
#address-cells = <2>;
#size-cells = <2>;
usb-phy@c410000 {
compatible = "google,lga-usb-phy";
reg = <0 0x0c410000 0 0x20000>,
<0 0x0c430000 0 0x1000>,
<0 0x0c440000 0 0x10000>,
<0 0x0c637000 0 0xa0>;
reg-names = "usb3_core", "usb3_tca", "usb2_core", "usbdp_top";
#phy-cells = <1>;
clocks = <&hsion_usb2_phy_clk>, <&hsion_u2phy_apb_clk>,
<&hsion_usb3_phy_clk>, <&hsion_usb3_phy_fw_clk>;
clock-names = "usb2", "usb2_apb", "usb3", "usb3_fw";
resets = <&hsion_resets_usb2_phy>,
<&hsion_resets_u2phy_apb>,
<&hsion_resets_usb3_phy>;
reset-names = "usb2", "usb2_apb", "usb3";
power-domains = <&hsio_n_usb_pd>;
orientation-switch;
google,usb-cfg-csr = <&usb_cfg_csr 0x14>;
};
};
...

View file

@ -18,6 +18,7 @@ properties:
compatible:
oneOf:
- enum:
- qcom,glymur-dp-phy
- qcom,sa8775p-edp-phy
- qcom,sc7280-edp-phy
- qcom,sc8180x-edp-phy
@ -37,12 +38,15 @@ properties:
- description: PLL register block
clocks:
maxItems: 2
minItems: 2
maxItems: 3
clock-names:
minItems: 2
items:
- const: aux
- const: cfg_ahb
- const: ref
"#clock-cells":
const: 1
@ -64,6 +68,30 @@ required:
- "#clock-cells"
- "#phy-cells"
allOf:
- if:
properties:
compatible:
enum:
- qcom,glymur-dp-phy
- qcom,x1e80100-dp-phy
then:
properties:
clocks:
minItems: 3
maxItems: 3
clock-names:
minItems: 3
maxItems: 3
else:
properties:
clocks:
minItems: 2
maxItems: 2
clock-names:
minItems: 2
maxItems: 2
additionalProperties: false
examples:

View file

@ -15,9 +15,13 @@ description:
properties:
compatible:
items:
- enum:
- qcom,sm8750-m31-eusb2-phy
oneOf:
- items:
- enum:
- qcom,glymur-m31-eusb2-phy
- qcom,kaanapali-m31-eusb2-phy
- const: qcom,sm8750-m31-eusb2-phy
- const: qcom,sm8750-m31-eusb2-phy
reg:
maxItems: 1

View file

@ -0,0 +1,111 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/qcom,qcs615-qmp-usb3dp-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QMP USB3-DP PHY controller (DP, QCS615)
maintainers:
- Xiangxu Yin <xiangxu.yin@oss.qualcomm.com>
description:
The QMP PHY controller supports physical layer functionality for both USB3
and DisplayPort over USB-C. While it enables mode switching between USB3 and
DisplayPort, but does not support combo mode.
properties:
compatible:
enum:
- qcom,qcs615-qmp-usb3-dp-phy
reg:
maxItems: 1
clocks:
maxItems: 4
clock-names:
items:
- const: aux
- const: ref
- const: cfg_ahb
- const: pipe
resets:
maxItems: 2
reset-names:
items:
- const: phy_phy
- const: dp_phy
vdda-phy-supply: true
vdda-pll-supply: true
"#clock-cells":
const: 1
description:
See include/dt-bindings/phy/phy-qcom-qmp.h
"#phy-cells":
const: 1
description:
See include/dt-bindings/phy/phy-qcom-qmp.h
qcom,tcsr-reg:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
- description: phandle to TCSR hardware block
- description: offset of the VLS CLAMP register
- description: offset of the PHY mode register
description: Clamp and PHY mode register present in the TCSR
required:
- compatible
- reg
- clocks
- clock-names
- resets
- reset-names
- vdda-phy-supply
- vdda-pll-supply
- "#clock-cells"
- "#phy-cells"
- qcom,tcsr-reg
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,qcs615-gcc.h>
#include <dt-bindings/clock/qcom,rpmh.h>
phy@88e8000 {
compatible = "qcom,qcs615-qmp-usb3-dp-phy";
reg = <0x88e8000 0x2000>;
clocks = <&gcc GCC_USB2_SEC_PHY_AUX_CLK>,
<&gcc GCC_USB3_SEC_CLKREF_CLK>,
<&gcc GCC_AHB2PHY_WEST_CLK>,
<&gcc GCC_USB2_SEC_PHY_PIPE_CLK>;
clock-names = "aux",
"ref",
"cfg_ahb",
"pipe";
resets = <&gcc GCC_USB3PHY_PHY_SEC_BCR>,
<&gcc GCC_USB3_DP_PHY_SEC_BCR>;
reset-names = "phy_phy",
"dp_phy";
vdda-phy-supply = <&vreg_l5a>;
vdda-pll-supply = <&vreg_l12a>;
#clock-cells = <1>;
#phy-cells = <1>;
qcom,tcsr-reg = <&tcsr 0xbff0 0xb24c>;
};

View file

@ -16,7 +16,9 @@ description:
properties:
compatible:
enum:
- qcom,glymur-qmp-gen4x2-pcie-phy
- qcom,glymur-qmp-gen5x4-pcie-phy
- qcom,kaanapali-qmp-gen3x2-pcie-phy
- qcom,qcs615-qmp-gen3x1-pcie-phy
- qcom,qcs8300-qmp-gen4x2-pcie-phy
- qcom,sa8775p-qmp-gen4x2-pcie-phy
@ -146,6 +148,7 @@ allOf:
compatible:
contains:
enum:
- qcom,kaanapali-qmp-gen3x2-pcie-phy
- qcom,qcs615-qmp-gen3x1-pcie-phy
- qcom,sar2130p-qmp-gen3x2-pcie-phy
- qcom,sc8180x-qmp-pcie-phy
@ -178,6 +181,7 @@ allOf:
compatible:
contains:
enum:
- qcom,glymur-qmp-gen4x2-pcie-phy
- qcom,glymur-qmp-gen5x4-pcie-phy
- qcom,qcs8300-qmp-gen4x2-pcie-phy
- qcom,sa8775p-qmp-gen4x2-pcie-phy
@ -202,7 +206,9 @@ allOf:
compatible:
contains:
enum:
- qcom,glymur-qmp-gen4x2-pcie-phy
- qcom,glymur-qmp-gen5x4-pcie-phy
- qcom,kaanapali-qmp-gen3x2-pcie-phy
- qcom,sm8550-qmp-gen4x2-pcie-phy
- qcom,sm8650-qmp-gen4x2-pcie-phy
- qcom,x1e80100-qmp-gen3x2-pcie-phy

View file

@ -20,6 +20,10 @@ properties:
- enum:
- qcom,qcs615-qmp-ufs-phy
- const: qcom,sm6115-qmp-ufs-phy
- items:
- enum:
- qcom,x1e80100-qmp-ufs-phy
- const: qcom,sm8550-qmp-ufs-phy
- items:
- enum:
- qcom,qcs8300-qmp-ufs-phy
@ -29,6 +33,7 @@ properties:
- qcom,kaanapali-qmp-ufs-phy
- const: qcom,sm8750-qmp-ufs-phy
- enum:
- qcom,milos-qmp-ufs-phy
- qcom,msm8996-qmp-ufs-phy
- qcom,msm8998-qmp-ufs-phy
- qcom,sa8775p-qmp-ufs-phy
@ -98,6 +103,7 @@ allOf:
compatible:
contains:
enum:
- qcom,milos-qmp-ufs-phy
- qcom,msm8998-qmp-ufs-phy
- qcom,sa8775p-qmp-ufs-phy
- qcom,sc7180-qmp-ufs-phy

View file

@ -16,6 +16,7 @@ description:
properties:
compatible:
enum:
- qcom,glymur-qmp-usb3-uni-phy
- qcom,ipq5424-qmp-usb3-phy
- qcom,ipq6018-qmp-usb3-phy
- qcom,ipq8074-qmp-usb3-phy
@ -61,6 +62,8 @@ properties:
vdda-pll-supply: true
refgen-supply: true
"#clock-cells":
const: 0
@ -113,6 +116,7 @@ allOf:
compatible:
contains:
enum:
- qcom,glymur-qmp-usb3-uni-phy
- qcom,qcs8300-qmp-usb3-uni-phy
- qcom,qdu1000-qmp-usb3-uni-phy
- qcom,sa8775p-qmp-usb3-uni-phy
@ -156,6 +160,7 @@ allOf:
compatible:
contains:
enum:
- qcom,glymur-qmp-usb3-uni-phy
- qcom,sa8775p-qmp-usb3-uni-phy
- qcom,sc8180x-qmp-usb3-uni-phy
- qcom,sc8280xp-qmp-usb3-uni-phy
@ -164,6 +169,19 @@ allOf:
required:
- power-domains
- if:
properties:
compatible:
contains:
enum:
- qcom,glymur-qmp-usb3-uni-phy
then:
required:
- refgen-supply
else:
properties:
refgen-supply: false
additionalProperties: false
examples:

View file

@ -15,22 +15,28 @@ description:
properties:
compatible:
enum:
- qcom,sar2130p-qmp-usb3-dp-phy
- qcom,sc7180-qmp-usb3-dp-phy
- qcom,sc7280-qmp-usb3-dp-phy
- qcom,sc8180x-qmp-usb3-dp-phy
- qcom,sc8280xp-qmp-usb43dp-phy
- qcom,sdm845-qmp-usb3-dp-phy
- qcom,sm6350-qmp-usb3-dp-phy
- qcom,sm8150-qmp-usb3-dp-phy
- qcom,sm8250-qmp-usb3-dp-phy
- qcom,sm8350-qmp-usb3-dp-phy
- qcom,sm8450-qmp-usb3-dp-phy
- qcom,sm8550-qmp-usb3-dp-phy
- qcom,sm8650-qmp-usb3-dp-phy
- qcom,sm8750-qmp-usb3-dp-phy
- qcom,x1e80100-qmp-usb3-dp-phy
oneOf:
- items:
- enum:
- qcom,kaanapali-qmp-usb3-dp-phy
- const: qcom,sm8750-qmp-usb3-dp-phy
- enum:
- qcom,glymur-qmp-usb3-dp-phy
- qcom,sar2130p-qmp-usb3-dp-phy
- qcom,sc7180-qmp-usb3-dp-phy
- qcom,sc7280-qmp-usb3-dp-phy
- qcom,sc8180x-qmp-usb3-dp-phy
- qcom,sc8280xp-qmp-usb43dp-phy
- qcom,sdm845-qmp-usb3-dp-phy
- qcom,sm6350-qmp-usb3-dp-phy
- qcom,sm8150-qmp-usb3-dp-phy
- qcom,sm8250-qmp-usb3-dp-phy
- qcom,sm8350-qmp-usb3-dp-phy
- qcom,sm8450-qmp-usb3-dp-phy
- qcom,sm8550-qmp-usb3-dp-phy
- qcom,sm8650-qmp-usb3-dp-phy
- qcom,sm8750-qmp-usb3-dp-phy
- qcom,x1e80100-qmp-usb3-dp-phy
reg:
maxItems: 1
@ -63,6 +69,8 @@ properties:
vdda-pll-supply: true
refgen-supply: true
"#clock-cells":
const: 1
description:
@ -194,14 +202,16 @@ allOf:
- if:
properties:
compatible:
enum:
- qcom,sar2130p-qmp-usb3-dp-phy
- qcom,sc8280xp-qmp-usb43dp-phy
- qcom,sm6350-qmp-usb3-dp-phy
- qcom,sm8550-qmp-usb3-dp-phy
- qcom,sm8650-qmp-usb3-dp-phy
- qcom,sm8750-qmp-usb3-dp-phy
- qcom,x1e80100-qmp-usb3-dp-phy
contains:
enum:
- qcom,glymur-qmp-usb3-dp-phy
- qcom,sar2130p-qmp-usb3-dp-phy
- qcom,sc8280xp-qmp-usb43dp-phy
- qcom,sm6350-qmp-usb3-dp-phy
- qcom,sm8550-qmp-usb3-dp-phy
- qcom,sm8650-qmp-usb3-dp-phy
- qcom,sm8750-qmp-usb3-dp-phy
- qcom,x1e80100-qmp-usb3-dp-phy
then:
required:
- power-domains
@ -209,6 +219,18 @@ allOf:
properties:
power-domains: false
- if:
properties:
compatible:
enum:
- qcom,glymur-qmp-usb3-dp-phy
then:
required:
- refgen-supply
else:
properties:
refgen-supply: false
additionalProperties: false
examples:

View file

@ -24,6 +24,7 @@ properties:
- qcom,pm8550b-eusb2-repeater
- qcom,pmiv0104-eusb2-repeater
- qcom,smb2360-eusb2-repeater
- qcom,smb2370-eusb2-repeater
reg:
maxItems: 1
@ -59,6 +60,14 @@ properties:
minimum: 0
maximum: 7
qcom,squelch-detector-bp:
description:
This adjusts the voltage level for the threshold used to detect valid
high-speed data.
minimum: -6000
maximum: 1000
multipleOf: 1000
required:
- compatible
- reg

View file

@ -11,7 +11,14 @@ maintainers:
properties:
compatible:
const: renesas,r9a09g047-usb3-phy
oneOf:
- const: renesas,r9a09g047-usb3-phy # RZ/G3E
- items:
- enum:
- renesas,r9a09g056-usb3-phy # RZ/V2N
- renesas,r9a09g057-usb3-phy # RZ/V2H(P)
- const: renesas,r9a09g047-usb3-phy
reg:
maxItems: 1

View file

@ -41,7 +41,9 @@ properties:
- const: renesas,rzg2l-usb2-phy
- items:
- const: renesas,usb2-phy-r9a09g056 # RZ/V2N
- enum:
- renesas,usb2-phy-r9a09g047 # RZ/G3E
- renesas,usb2-phy-r9a09g056 # RZ/V2N
- const: renesas,usb2-phy-r9a09g057
- const: renesas,usb2-phy-r9a09g077 # RZ/T2H
@ -89,6 +91,12 @@ properties:
Phandle to a regulator that provides power to the VBUS. This regulator
will be managed during the PHY power on/off sequence.
vbus-regulator:
$ref: /schemas/regulator/regulator.yaml#
description: USB VBUS internal regulator
type: object
unevaluatedProperties: false
renesas,no-otg-pins:
$ref: /schemas/types.yaml#/definitions/flag
description: |
@ -96,6 +104,11 @@ properties:
dr_mode: true
mux-states:
description:
phandle to a mux controller node that select the source for USB VBUS.
maxItems: 1
if:
properties:
compatible:

View file

@ -36,6 +36,9 @@ properties:
minItems: 1
maxItems: 4
power-domains:
maxItems: 1
samsung,pmu-syscon:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1

View file

@ -34,6 +34,9 @@ properties:
- samsung,exynos7870-usbdrd-phy
- samsung,exynos850-usbdrd-phy
- samsung,exynos990-usbdrd-phy
- samsung,exynosautov920-usb31drd-combo-ssphy
- samsung,exynosautov920-usbdrd-combo-hsphy
- samsung,exynosautov920-usbdrd-phy
clocks:
minItems: 1
@ -51,6 +54,9 @@ properties:
settings register. For Exynos5420 this is given as 'sclk_usbphy30'
in the CMU. It's not needed for Exynos2200.
power-domains:
maxItems: 1
"#phy-cells":
const: 1
@ -110,6 +116,15 @@ properties:
vddh-usbdp-supply:
description: VDDh power supply for the USB DP phy.
dvdd-supply:
description: 0.75V power supply for the USB phy.
vdd18-supply:
description: 1.8V power supply for the USB phy.
vdd33-supply:
description: 3.3V power supply for the USB phy.
required:
- compatible
- clocks
@ -221,6 +236,9 @@ allOf:
- samsung,exynos7870-usbdrd-phy
- samsung,exynos850-usbdrd-phy
- samsung,exynos990-usbdrd-phy
- samsung,exynosautov920-usb31drd-combo-ssphy
- samsung,exynosautov920-usbdrd-combo-hsphy
- samsung,exynosautov920-usbdrd-phy
then:
properties:
clocks:
@ -238,6 +256,39 @@ allOf:
reg-names:
maxItems: 1
- if:
properties:
compatible:
contains:
enum:
- samsung,exynosautov920-usb31drd-combo-ssphy
- samsung,exynosautov920-usbdrd-combo-hsphy
- samsung,exynosautov920-usbdrd-phy
then:
required:
- dvdd-supply
- vdd18-supply
else:
properties:
dvdd-supply: false
vdd18-supply: false
- if:
properties:
compatible:
contains:
enum:
- samsung,exynosautov920-usbdrd-combo-hsphy
- samsung,exynosautov920-usbdrd-phy
then:
required:
- vdd33-supply
else:
properties:
vdd33-supply: false
unevaluatedProperties: false
examples:

View file

@ -0,0 +1,114 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/spacemit,k1-combo-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SpacemiT K1 PCIe/USB3 Combo PHY
maintainers:
- Alex Elder <elder@riscstar.com>
description: >
Of the three PHYs on the SpacemiT K1 SoC capable of being used for
PCIe, one is a combo PHY that can also be configured for use by a
USB 3 controller. Using PCIe or USB 3 is a board design decision.
The combo PHY is also the only PCIe PHY that is able to determine
PCIe calibration values to use, and this must be determined before
the other two PCIe PHYs can be used. This calibration must be
performed with the combo PHY in PCIe mode, and is this is done
when the combo PHY is probed.
The combo PHY uses an external oscillator as a reference clock.
During normal operation, the PCIe or USB port driver is responsible
for ensuring all other clocks needed by a PHY are enabled, and all
resets affecting the PHY are deasserted. However, for the combo
PHY to perform calibration independent of whether it's later used
for PCIe or USB, all PCIe mode clocks and resets must be defined.
properties:
compatible:
const: spacemit,k1-combo-phy
reg:
items:
- description: PHY control registers
clocks:
items:
- description: External oscillator used by the PHY PLL
- description: DWC PCIe Data Bus Interface (DBI) clock
- description: DWC PCIe application AXI-bus Master interface clock
- description: DWC PCIe application AXI-bus slave interface clock
clock-names:
items:
- const: refclk
- const: dbi
- const: mstr
- const: slv
resets:
items:
- description: PHY reset; remains deasserted after initialization
- description: DWC PCIe Data Bus Interface (DBI) reset
- description: DWC PCIe application AXI-bus Master interface reset
- description: DWC PCIe application AXI-bus slave interface reset
reset-names:
items:
- const: phy
- const: dbi
- const: mstr
- const: slv
spacemit,apmu:
description:
A phandle that refers to the APMU system controller, whose
regmap is used in setting the mode
$ref: /schemas/types.yaml#/definitions/phandle
"#phy-cells":
const: 1
description:
The argument value (PHY_TYPE_PCIE or PHY_TYPE_USB3) determines
whether the PHY operates in PCIe or USB3 mode.
required:
- compatible
- reg
- clocks
- clock-names
- resets
- reset-names
- spacemit,apmu
- "#phy-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/spacemit,k1-syscon.h>
phy@c0b10000 {
compatible = "spacemit,k1-combo-phy";
reg = <0xc0b10000 0x1000>;
clocks = <&vctcxo_24m>,
<&syscon_apmu CLK_PCIE0_DBI>,
<&syscon_apmu CLK_PCIE0_MASTER>,
<&syscon_apmu CLK_PCIE0_SLAVE>;
clock-names = "refclk",
"dbi",
"mstr",
"slv";
resets = <&syscon_apmu RESET_PCIE0_GLOBAL>,
<&syscon_apmu RESET_PCIE0_DBI>,
<&syscon_apmu RESET_PCIE0_MASTER>,
<&syscon_apmu RESET_PCIE0_SLAVE>;
reset-names = "phy",
"dbi",
"mstr",
"slv";
spacemit,apmu = <&syscon_apmu>;
#phy-cells = <1>;
};

View file

@ -0,0 +1,71 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/spacemit,k1-pcie-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SpacemiT K1 PCIe PHY
maintainers:
- Alex Elder <elder@riscstar.com>
description: >
Two PHYs on the SpacemiT K1 SoC used for only for PCIe. These
PHYs must be configured using calibration values that are
determined by a third "combo PHY". The combo PHY determines
these calibration values during probe so they can be used for
the two PCIe-only PHYs.
The PHY uses an external oscillator as a reference clock. During
normal operation, the PCIe host driver is responsible for ensuring
all other clocks needed by a PHY are enabled, and all resets
affecting the PHY are deasserted.
properties:
compatible:
const: spacemit,k1-pcie-phy
reg:
items:
- description: PHY control registers
clocks:
items:
- description: External oscillator used by the PHY PLL
clock-names:
const: refclk
resets:
items:
- description: PHY reset; remains deasserted after initialization
reset-names:
const: phy
"#phy-cells":
const: 0
required:
- compatible
- reg
- clocks
- clock-names
- resets
- reset-names
- "#phy-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/spacemit,k1-syscon.h>
phy@c0c10000 {
compatible = "spacemit,k1-pcie-phy";
reg = <0xc0c10000 0x1000>;
clocks = <&vctcxo_24m>;
clock-names = "refclk";
resets = <&syscon_apmu RESET_PCIE1_GLOBAL>;
reset-names = "phy";
#phy-cells = <0>;
};

View file

@ -0,0 +1,40 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/spacemit,usb2-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SpacemiT K1 SoC USB 2.0 PHY
maintainers:
- Ze Huang <huang.ze@linux.dev>
properties:
compatible:
const: spacemit,k1-usb2-phy
reg:
maxItems: 1
clocks:
maxItems: 1
"#phy-cells":
const: 0
required:
- compatible
- reg
- clocks
- "#phy-cells"
additionalProperties: false
examples:
- |
usb-phy@c09c0000 {
compatible = "spacemit,k1-usb2-phy";
reg = <0xc09c0000 0x200>;
clocks = <&syscon_apmu 15>;
#phy-cells = <0>;
};

View file

@ -0,0 +1,99 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/ti,control-phy-otghs.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI OMAP Control PHY Module
maintainers:
- Roger Quadros <rogerq@ti.com>
description:
The TI OMAP Control PHY module is a hardware block within the system
control module (SCM) of Texas Instruments OMAP SoCs. It provides
centralized control over power, configuration, and auxiliary features
for multiple on-chip PHYs. This module is essential for proper PHY
operation in power-constrained embedded systems.
properties:
$nodename:
pattern: "^phy@[0-9a-f]+$"
compatible:
enum:
- ti,control-phy-otghs
- ti,control-phy-pcie
- ti,control-phy-pipe3
- ti,control-phy-usb2
- ti,control-phy-usb2-am437
- ti,control-phy-usb2-dra7
reg:
minItems: 1
maxItems: 3
reg-names:
minItems: 1
maxItems: 3
items:
enum: [otghs_control, power, pcie_pcs, control_sma]
allOf:
- if:
properties:
compatible:
contains:
enum:
- ti,control-phy-otghs
then:
properties:
reg-names:
const: otghs_control
- if:
properties:
compatible:
contains:
enum:
- ti,control-phy-pcie
then:
properties:
reg:
minItems: 3
reg-names:
items:
- const: power
- const: pcie_pcs
- const: control_sma
- if:
properties:
compatible:
contains:
enum:
- ti,control-phy-usb2
- ti,control-phy-usb2-dra7
- ti,control-phy-usb2-am437
- ti,control-phy-pipe3
then:
properties:
reg-names:
const: power
required:
- reg
- compatible
- reg-names
unevaluatedProperties: false
examples:
- |
phy@4a00233c {
compatible = "ti,control-phy-otghs";
reg = <0x4a00233c 0x4>;
reg-names = "otghs_control";
};
...

View file

@ -0,0 +1,138 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/ti,phy-usb3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI PIPE3 PHY Module
maintainers:
- Roger Quadros <rogerq@ti.com>
description:
The TI PIPE3 PHY is a high-speed SerDes (Serializer/Deserializer)
transceiver integrated in OMAP5, DRA7xx/AM57xx, and similar SoCs.
It supports multiple protocols (USB3, SATA, PCIe) using the PIPE3
interface standard, which defines a common physical layer for
high-speed serial interfaces.
properties:
$nodename:
pattern: "^(pcie-phy|usb3-phy|phy)@[0-9a-f]+$"
compatible:
enum:
- ti,omap-usb3
- ti,phy-pipe3-pcie
- ti,phy-pipe3-sata
- ti,phy-usb3
reg:
minItems: 2
maxItems: 3
reg-names:
minItems: 2
items:
- const: phy_rx
- const: phy_tx
- const: pll_ctrl
"#phy-cells":
const: 0
clocks:
minItems: 2
maxItems: 7
clock-names:
minItems: 2
maxItems: 7
items:
enum: [wkupclk, sysclk, refclk, dpll_ref,
dpll_ref_m2, phy-div, div-clk]
syscon-phy-power:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
items:
items:
- description: Phandle to the system control module
- description: Register offset controlling PHY power
syscon-pllreset:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
items:
items:
- description: Phandle to the system control module
- description: Register offset of CTRL_CORE_SMA_SW_0
syscon-pcs:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
items:
items:
- description: Phandle to the system control module
- description: Register offset for PCS delay programming
ctrl-module:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Phandle of control module for PHY power on.
deprecated: true
allOf:
- if:
properties:
compatible:
contains:
const: ti,phy-pipe3-sata
then:
properties:
syscon-pllreset: true
else:
properties:
syscon-pllreset: false
required:
- reg
- compatible
- reg-names
- "#phy-cells"
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
/* TI PIPE3 USB3 PHY */
usb3-phy@4a084400 {
compatible = "ti,phy-usb3";
reg = <0x4a084400 0x80>,
<0x4a084800 0x64>,
<0x4a084c00 0x40>;
reg-names = "phy_rx", "phy_tx", "pll_ctrl";
#phy-cells = <0>;
clocks = <&usb_phy_cm_clk32k>,
<&sys_clkin>,
<&usb_otg_ss_refclk960m>;
clock-names = "wkupclk", "sysclk", "refclk";
ctrl-module = <&omap_control_usb>;
};
- |
/* TI PIPE3 SATA PHY */
phy@4a096000 {
compatible = "ti,phy-pipe3-sata";
reg = <0x4a096000 0x80>, /* phy_rx */
<0x4a096400 0x64>, /* phy_tx */
<0x4a096800 0x40>; /* pll_ctrl */
reg-names = "phy_rx", "phy_tx", "pll_ctrl";
clocks = <&sys_clkin1>, <&sata_ref_clk>;
clock-names = "sysclk", "refclk";
syscon-pllreset = <&scm_conf 0x3fc>;
#phy-cells = <0>;
};
...

View file

@ -20,6 +20,9 @@ properties:
- microchip,ata6561
- ti,tcan1051
- const: ti,tcan1042
- items:
- const: ti,tcan1046
- const: nxp,tja1048
- enum:
- ti,tcan1042
- ti,tcan1043

View file

@ -1,98 +0,0 @@
TI PHY: DT DOCUMENTATION FOR PHYs in TI PLATFORMs
OMAP CONTROL PHY
Required properties:
- compatible: Should be one of
"ti,control-phy-otghs" - if it has otghs_control mailbox register as on OMAP4.
"ti,control-phy-usb2" - if it has Power down bit in control_dev_conf register
e.g. USB2_PHY on OMAP5.
"ti,control-phy-pipe3" - if it has DPLL and individual Rx & Tx power control
e.g. USB3 PHY and SATA PHY on OMAP5.
"ti,control-phy-pcie" - for pcie to support external clock for pcie and to
set PCS delay value.
e.g. PCIE PHY in DRA7x
"ti,control-phy-usb2-dra7" - if it has power down register like USB2 PHY on
DRA7 platform.
"ti,control-phy-usb2-am437" - if it has power down register like USB2 PHY on
AM437 platform.
- reg : register ranges as listed in the reg-names property
- reg-names: "otghs_control" for control-phy-otghs
"power", "pcie_pcs" and "control_sma" for control-phy-pcie
"power" for all other types
omap_control_usb: omap-control-usb@4a002300 {
compatible = "ti,control-phy-otghs";
reg = <0x4a00233c 0x4>;
reg-names = "otghs_control";
};
TI PIPE3 PHY
Required properties:
- compatible: Should be "ti,phy-usb3", "ti,phy-pipe3-sata" or
"ti,phy-pipe3-pcie. "ti,omap-usb3" is deprecated.
- reg : Address and length of the register set for the device.
- reg-names: The names of the register addresses corresponding to the registers
filled in "reg".
- #phy-cells: determine the number of cells that should be given in the
phandle while referencing this phy.
- clocks: a list of phandles and clock-specifier pairs, one for each entry in
clock-names.
- clock-names: should include:
* "wkupclk" - wakeup clock.
* "sysclk" - system clock.
* "refclk" - reference clock.
* "dpll_ref" - external dpll ref clk
* "dpll_ref_m2" - external dpll ref clk
* "phy-div" - divider for apll
* "div-clk" - apll clock
Optional properties:
- id: If there are multiple instance of the same type, in order to
differentiate between each instance "id" can be used (e.g., multi-lane PCIe
PHY). If "id" is not provided, it is set to default value of '1'.
- syscon-pllreset: Handle to system control region that contains the
CTRL_CORE_SMA_SW_0 register and register offset to the CTRL_CORE_SMA_SW_0
register that contains the SATA_PLL_SOFT_RESET bit. Only valid for sata_phy.
- syscon-pcs : phandle/offset pair. Phandle to the system control module and the
register offset to write the PCS delay value.
Deprecated properties:
- ctrl-module : phandle of the control module used by PHY driver to power on
the PHY.
Recommended properties:
- syscon-phy-power : phandle/offset pair. Phandle to the system control
module and the register offset to power on/off the PHY.
This is usually a subnode of ocp2scp to which it is connected.
usb3phy@4a084400 {
compatible = "ti,phy-usb3";
reg = <0x4a084400 0x80>,
<0x4a084800 0x64>,
<0x4a084c00 0x40>;
reg-names = "phy_rx", "phy_tx", "pll_ctrl";
ctrl-module = <&omap_control_usb>;
#phy-cells = <0>;
clocks = <&usb_phy_cm_clk32k>,
<&sys_clkin>,
<&usb_otg_ss_refclk960m>;
clock-names = "wkupclk",
"sysclk",
"refclk";
};
sata_phy: phy@4a096000 {
compatible = "ti,phy-pipe3-sata";
reg = <0x4A096000 0x80>, /* phy_rx */
<0x4A096400 0x64>, /* phy_tx */
<0x4A096800 0x40>; /* pll_ctrl */
reg-names = "phy_rx", "phy_tx", "pll_ctrl";
ctrl-module = <&omap_control_sata>;
clocks = <&sys_clkin1>, <&sata_ref_clk>;
clock-names = "sysclk", "refclk";
syscon-pllreset = <&scm_conf 0x3fc>;
#phy-cells = <0>;
};

View file

@ -2520,6 +2520,7 @@ F: Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml
F: Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
F: Documentation/devicetree/bindings/nvmem/apple,spmi-nvmem.yaml
F: Documentation/devicetree/bindings/pci/apple,pcie.yaml
F: Documentation/devicetree/bindings/phy/apple,atcphy.yaml
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
F: Documentation/devicetree/bindings/power/apple*
F: Documentation/devicetree/bindings/power/reset/apple,smc-reboot.yaml
@ -2548,6 +2549,7 @@ F: drivers/mfd/macsmc.c
F: drivers/nvme/host/apple.c
F: drivers/nvmem/apple-efuses.c
F: drivers/nvmem/apple-spmi-nvmem.c
F: drivers/phy/apple/
F: drivers/pinctrl/pinctrl-apple-gpio.c
F: drivers/power/reset/macsmc-reboot.c
F: drivers/pwm/pwm-apple.c
@ -10858,10 +10860,12 @@ S: Maintained
P: Documentation/process/maintainer-soc-clean-dts.rst
C: irc://irc.oftc.net/pixel6-kernel-dev
F: Documentation/devicetree/bindings/clock/google,gs101-clock.yaml
F: Documentation/devicetree/bindings/phy/google,lga-usb-phy.yaml
F: Documentation/devicetree/bindings/soc/google/google,gs101-pmu-intr-gen.yaml
F: Documentation/devicetree/bindings/usb/google,lga-dwc3.yaml
F: arch/arm64/boot/dts/exynos/google/
F: drivers/clk/samsung/clk-gs101.c
F: drivers/phy/phy-google-usb.c
F: drivers/soc/samsung/gs101-pmu.c
F: drivers/phy/samsung/phy-gs101-ufs.c
F: drivers/usb/dwc3/dwc3-google.c

View file

@ -10,7 +10,7 @@ obj-y += cache/
obj-y += irqchip/
obj-y += bus/
obj-$(CONFIG_GENERIC_PHY) += phy/
obj-y += phy/
# GPIO must come after pinctrl as gpios may need to mux pins etc
obj-$(CONFIG_PINCTRL) += pinctrl/

View file

@ -47,6 +47,17 @@ config GENERIC_PHY_MIPI_DPHY
Provides a number of helpers a core functions for MIPI D-PHY
drivers to us.
config PHY_GOOGLE_USB
tristate "Google Tensor SoC USB PHY driver"
select GENERIC_PHY
depends on TYPEC
help
Enable support for the USB PHY on Google Tensor SoCs, starting with
the G5 generation (Laguna). This driver provides the PHY interfaces
to interact with the SNPS eUSB2 and USB 3.2/DisplayPort Combo PHY,
both of which are integrated with the DWC3 USB DRD controller.
This driver currently supports USB high-speed.
config PHY_LPC18XX_USB_OTG
tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
@ -123,8 +134,21 @@ config PHY_NXP_PTN3222
schemes. It supports all three USB 2.0 data rates: Low Speed, Full
Speed and High Speed.
config PHY_SPACEMIT_K1_PCIE
tristate "PCIe and combo PHY driver for the SpacemiT K1 SoC"
depends on ARCH_SPACEMIT || COMPILE_TEST
depends on COMMON_CLK
depends on HAS_IOMEM
depends on OF
select GENERIC_PHY
default ARCH_SPACEMIT
help
Enable support for the PCIe and USB 3 combo PHY and two
PCIe-only PHYs used in the SpacemiT K1 SoC.
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/apple/Kconfig"
source "drivers/phy/broadcom/Kconfig"
source "drivers/phy/cadence/Kconfig"
source "drivers/phy/freescale/Kconfig"
@ -145,6 +169,7 @@ source "drivers/phy/rockchip/Kconfig"
source "drivers/phy/samsung/Kconfig"
source "drivers/phy/socionext/Kconfig"
source "drivers/phy/sophgo/Kconfig"
source "drivers/phy/spacemit/Kconfig"
source "drivers/phy/st/Kconfig"
source "drivers/phy/starfive/Kconfig"
source "drivers/phy/sunplus/Kconfig"

View file

@ -8,6 +8,7 @@ obj-$(CONFIG_PHY_COMMON_PROPS_TEST) += phy-common-props-test.o
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o
obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o
obj-$(CONFIG_PHY_GOOGLE_USB) += phy-google-usb.o
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
@ -15,8 +16,10 @@ obj-$(CONFIG_PHY_SNPS_EUSB2) += phy-snps-eusb2.o
obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o
obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o
obj-y += allwinner/ \
obj-$(CONFIG_PHY_SPACEMIT_K1_PCIE) += phy-spacemit-k1-pcie.o
obj-$(CONFIG_GENERIC_PHY) += allwinner/ \
amlogic/ \
apple/ \
broadcom/ \
cadence/ \
freescale/ \
@ -38,6 +41,7 @@ obj-y += allwinner/ \
samsung/ \
socionext/ \
sophgo/ \
spacemit/ \
st/ \
starfive/ \
sunplus/ \

View file

@ -359,7 +359,7 @@ static int sun4i_usb_phy_init(struct phy *_phy)
/* Force ISCR and cable state updates */
data->id_det = -1;
data->vbus_det = -1;
queue_delayed_work(system_wq, &data->detect, 0);
queue_delayed_work(system_percpu_wq, &data->detect, 0);
}
return 0;
@ -482,7 +482,7 @@ static int sun4i_usb_phy_power_on(struct phy *_phy)
/* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */
if (phy->index == 0 && sun4i_usb_phy0_poll(data))
mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
mod_delayed_work(system_percpu_wq, &data->detect, DEBOUNCE_TIME);
return 0;
}
@ -503,7 +503,7 @@ static int sun4i_usb_phy_power_off(struct phy *_phy)
* Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan.
*/
if (phy->index == 0 && !sun4i_usb_phy0_poll(data))
mod_delayed_work(system_wq, &data->detect, POLL_TIME);
mod_delayed_work(system_percpu_wq, &data->detect, POLL_TIME);
return 0;
}
@ -542,7 +542,7 @@ static int sun4i_usb_phy_set_mode(struct phy *_phy,
data->id_det = -1; /* Force reprocessing of id */
data->force_session_end = true;
queue_delayed_work(system_wq, &data->detect, 0);
queue_delayed_work(system_percpu_wq, &data->detect, 0);
return 0;
}
@ -654,7 +654,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
extcon_set_state_sync(data->extcon, EXTCON_USB, vbus_det);
if (sun4i_usb_phy0_poll(data))
queue_delayed_work(system_wq, &data->detect, POLL_TIME);
queue_delayed_work(system_percpu_wq, &data->detect, POLL_TIME);
}
static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id)
@ -662,7 +662,7 @@ static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id)
struct sun4i_usb_phy_data *data = dev_id;
/* vbus or id changed, let the pins settle and then scan them */
mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
mod_delayed_work(system_percpu_wq, &data->detect, DEBOUNCE_TIME);
return IRQ_HANDLED;
}
@ -676,7 +676,7 @@ static int sun4i_usb_phy0_vbus_notify(struct notifier_block *nb,
/* Properties on the vbus_power_supply changed, scan vbus_det */
if (val == PSY_EVENT_PROP_CHANGED && psy == data->vbus_power_supply)
mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
mod_delayed_work(system_percpu_wq, &data->detect, DEBOUNCE_TIME);
return NOTIFY_OK;
}

13
drivers/phy/apple/Kconfig Normal file
View file

@ -0,0 +1,13 @@
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
config PHY_APPLE_ATC
tristate "Apple Type-C PHY"
depends on (ARM64 && ARCH_APPLE) || (COMPILE_TEST && !GENERIC_ATOMIC64)
depends on TYPEC
select GENERIC_PHY
select APPLE_TUNABLE
help
Enable this to add support for the Apple Type-C PHY found in
Apple Silicon M-series SoCs. This PHY supports USB2,
USB3, USB4, Thunderbolt, and DisplayPort.
If M is selected the module will be called 'phy-apple-atc'.

View file

@ -0,0 +1,4 @@
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
obj-$(CONFIG_PHY_APPLE_ATC) += phy-apple-atc.o
phy-apple-atc-y := atc.o

2295
drivers/phy/apple/atc.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -300,6 +300,7 @@ enum cdns_torrent_phy_type {
TYPE_USB,
TYPE_USXGMII,
TYPE_PCIE_ML,
TYPE_XAUI,
};
enum cdns_torrent_ref_clk {
@ -320,14 +321,14 @@ enum cdns_torrent_ssc_mode {
/* Unique key id for vals table entry
* REFCLK0_RATE | REFCLK1_RATE | LINK0_TYPE | LINK1_TYPE | SSC_TYPE
*/
#define REFCLK0_SHIFT 12
#define REFCLK0_MASK GENMASK(14, 12)
#define REFCLK1_SHIFT 9
#define REFCLK1_MASK GENMASK(11, 9)
#define LINK0_SHIFT 6
#define LINK0_MASK GENMASK(8, 6)
#define REFCLK0_SHIFT 15
#define REFCLK0_MASK GENMASK(18, 15)
#define REFCLK1_SHIFT 11
#define REFCLK1_MASK GENMASK(14, 11)
#define LINK0_SHIFT 7
#define LINK0_MASK GENMASK(10, 7)
#define LINK1_SHIFT 3
#define LINK1_MASK GENMASK(5, 3)
#define LINK1_MASK GENMASK(6, 3)
#define SSC_SHIFT 0
#define SSC_MASK GENMASK(2, 0)
@ -397,6 +398,7 @@ struct cdns_torrent_refclk_driver {
struct clk_hw hw;
struct regmap_field *cmn_fields[REFCLK_OUT_NUM_CMN_CONFIG];
struct clk_init_data clk_data;
u8 parent_index;
};
#define to_cdns_torrent_refclk_driver(_hw) \
@ -708,6 +710,8 @@ static const char *cdns_torrent_get_phy_type(enum cdns_torrent_phy_type phy_type
return "USB";
case TYPE_USXGMII:
return "USXGMII";
case TYPE_XAUI:
return "XAUI";
default:
return "None";
}
@ -3020,6 +3024,9 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
case PHY_TYPE_USXGMII:
cdns_phy->phys[node].phy_type = TYPE_USXGMII;
break;
case PHY_TYPE_XAUI:
cdns_phy->phys[node].phy_type = TYPE_XAUI;
break;
default:
dev_err(dev, "Unsupported protocol\n");
ret = -EINVAL;
@ -3326,11 +3333,29 @@ static const struct cdns_torrent_vals sgmii_qsgmii_xcvr_diag_ln_vals = {
.num_regs = ARRAY_SIZE(sgmii_qsgmii_xcvr_diag_ln_regs),
};
static void cdns_torrent_refclk_driver_suspend(struct cdns_torrent_phy *cdns_phy)
{
struct clk_hw *hw = cdns_phy->clk_hw_data->hws[CDNS_TORRENT_REFCLK_DRIVER];
struct cdns_torrent_refclk_driver *refclk_driver = to_cdns_torrent_refclk_driver(hw);
refclk_driver->parent_index = cdns_torrent_refclk_driver_get_parent(hw);
}
static int cdns_torrent_refclk_driver_resume(struct cdns_torrent_phy *cdns_phy)
{
struct clk_hw *hw = cdns_phy->clk_hw_data->hws[CDNS_TORRENT_REFCLK_DRIVER];
struct cdns_torrent_refclk_driver *refclk_driver = to_cdns_torrent_refclk_driver(hw);
return cdns_torrent_refclk_driver_set_parent(hw, refclk_driver->parent_index);
}
static int cdns_torrent_phy_suspend_noirq(struct device *dev)
{
struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(dev);
int i;
cdns_torrent_refclk_driver_suspend(cdns_phy);
reset_control_assert(cdns_phy->phy_rst);
reset_control_assert(cdns_phy->apb_rst);
for (i = 0; i < cdns_phy->nsubnodes; i++)
@ -3352,6 +3377,10 @@ static int cdns_torrent_phy_resume_noirq(struct device *dev)
int node = cdns_phy->nsubnodes;
int ret, i;
ret = cdns_torrent_refclk_driver_resume(cdns_phy);
if (ret)
return ret;
ret = cdns_torrent_clk(cdns_phy);
if (ret)
return ret;
@ -3382,6 +3411,95 @@ static DEFINE_NOIRQ_DEV_PM_OPS(cdns_torrent_phy_pm_ops,
cdns_torrent_phy_suspend_noirq,
cdns_torrent_phy_resume_noirq);
/* PCIe and XAUI link configuration */
static const struct cdns_reg_pairs pcie_xaui_link_cmn_regs[] = {
{0x0003, PHY_PLL_CFG},
{0x0600, CMN_PDIAG_PLL1_CLK_SEL_M0}
};
static const struct cdns_reg_pairs xaui_pcie_xcvr_diag_ln_regs[] = {
{0x0011, XCVR_DIAG_HSCLK_SEL},
{0x0089, XCVR_DIAG_PLLDRC_CTRL}
};
static const struct cdns_torrent_vals pcie_xaui_link_cmn_vals = {
.reg_pairs = pcie_xaui_link_cmn_regs,
.num_regs = ARRAY_SIZE(pcie_xaui_link_cmn_regs),
};
static const struct cdns_torrent_vals xaui_pcie_xcvr_diag_ln_vals = {
.reg_pairs = xaui_pcie_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(xaui_pcie_xcvr_diag_ln_regs),
};
/* XAUI 100 MHz Ref clk, no SSC */
static const struct cdns_reg_pairs xaui_100_no_ssc_cmn_regs[] = {
{0x0004, CMN_PLL1_DSM_DIAG_M0},
{0x0B17, CMN_PDIAG_PLL1_CP_PADJ_M0},
{0x0E01, CMN_PDIAG_PLL1_CP_IADJ_M0},
{0x0D05, CMN_PDIAG_PLL1_FILT_PADJ_M0},
{0x003E, CMN_PLL1_INTDIV_M0},
{0x8000, CMN_PLL1_FRACDIVL_M0},
{0x0002, CMN_PLL1_FRACDIVH_M0},
{0x002A, CMN_PLL1_HIGH_THR_M0},
{0x3102, CMN_PDIAG_PLL1_CTRL_M0},
{0x007F, CMN_TXPUCAL_TUNE},
{0x007F, CMN_TXPDCAL_TUNE}
};
static const struct cdns_reg_pairs xaui_100_no_ssc_tx_ln_regs[] = {
{0x00F3, TX_PSC_A0},
{0x04A2, TX_PSC_A2},
{0x04A2, TX_PSC_A3 },
{0x0000, TX_TXCC_CPOST_MULT_00}
};
static const struct cdns_reg_pairs ti_xaui_100_no_ssc_tx_ln_regs[] = {
{0x00F3, TX_PSC_A0},
{0x04A2, TX_PSC_A2},
{0x04A2, TX_PSC_A3 },
{0x0000, TX_TXCC_CPOST_MULT_00},
{0x4000, XCVR_DIAG_RXCLK_CTRL}
};
static const struct cdns_reg_pairs xaui_100_no_ssc_rx_ln_regs[] = {
{0x091D, RX_PSC_A0},
{0x0900, RX_PSC_A2},
{0x0100, RX_PSC_A3},
{0x03C7, RX_REE_GCSM1_EQENM_PH1},
{0x01C7, RX_REE_GCSM1_EQENM_PH2},
{0x0000, RX_DIAG_DFE_CTRL},
{0x0019, RX_REE_TAP1_CLIP},
{0x0019, RX_REE_TAP2TON_CLIP},
{0x0098, RX_DIAG_NQST_CTRL},
{0x0C01, RX_DIAG_DFE_AMP_TUNE_2},
{0x0000, RX_DIAG_DFE_AMP_TUNE_3},
{0x0000, RX_DIAG_PI_CAP},
{0x0031, RX_DIAG_PI_RATE},
{0x0001, RX_DIAG_ACYA},
{0x018C, RX_CDRLF_CNFG},
};
static const struct cdns_torrent_vals xaui_100_no_ssc_cmn_vals = {
.reg_pairs = xaui_100_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(xaui_100_no_ssc_cmn_regs),
};
static const struct cdns_torrent_vals xaui_100_no_ssc_tx_ln_vals = {
.reg_pairs = xaui_100_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(xaui_100_no_ssc_tx_ln_regs),
};
static const struct cdns_torrent_vals ti_xaui_100_no_ssc_tx_ln_vals = {
.reg_pairs = ti_xaui_100_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(ti_xaui_100_no_ssc_tx_ln_regs),
};
static const struct cdns_torrent_vals xaui_100_no_ssc_rx_ln_vals = {
.reg_pairs = xaui_100_no_ssc_rx_ln_regs,
.num_regs = ARRAY_SIZE(xaui_100_no_ssc_rx_ln_regs),
};
/* USB and DP link configuration */
static const struct cdns_reg_pairs usb_dp_link_cmn_regs[] = {
{0x0002, PHY_PLL_CFG},
@ -4853,6 +4971,7 @@ static const struct cdns_torrent_vals_entry link_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USB), &pcie_usb_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_DP), &pcie_dp_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USXGMII), &pcie_usxgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_XAUI), &pcie_xaui_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE_ML, TYPE_USB), &ml_pcie_usb_link_cmn_vals},
@ -4879,6 +4998,8 @@ static const struct cdns_torrent_vals_entry link_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_PCIE), &pcie_usxgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_SGMII), &usxgmii_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_QSGMII), &usxgmii_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_XAUI, TYPE_PCIE), &pcie_xaui_link_cmn_vals},
};
static const struct cdns_torrent_vals_entry xcvr_diag_vals_entries[] = {
@ -4893,6 +5014,7 @@ static const struct cdns_torrent_vals_entry xcvr_diag_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USB), &pcie_usb_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_DP), &pcie_dp_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USXGMII), &pcie_usxgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_XAUI), NULL},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE_ML, TYPE_USB), &ml_pcie_usb_xcvr_diag_ln_vals},
@ -4919,6 +5041,8 @@ static const struct cdns_torrent_vals_entry xcvr_diag_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_PCIE), &usxgmii_pcie_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_SGMII), &usxgmii_sgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_QSGMII), &usxgmii_sgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_XAUI, TYPE_PCIE), &xaui_pcie_xcvr_diag_ln_vals},
};
static const struct cdns_torrent_vals_entry pcs_cmn_vals_entries[] = {
@ -4960,6 +5084,8 @@ static const struct cdns_torrent_vals_entry cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_XAUI, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, NO_SSC), &ml_pcie_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, EXTERNAL_SSC), &ml_pcie_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, INTERNAL_SSC), &ml_pcie_100_int_ssc_cmn_vals},
@ -5010,6 +5136,8 @@ static const struct cdns_torrent_vals_entry cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_XAUI, TYPE_PCIE, NO_SSC), &xaui_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &sl_usxgmii_156_25_no_ssc_cmn_vals},
/* Dual refclk */
@ -5054,6 +5182,8 @@ static const struct cdns_torrent_vals_entry cdns_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_XAUI, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, EXTERNAL_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, INTERNAL_SSC), NULL},
@ -5104,6 +5234,8 @@ static const struct cdns_torrent_vals_entry cdns_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_XAUI, TYPE_PCIE, NO_SSC), &xaui_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
/* Dual refclk */
@ -5148,6 +5280,8 @@ static const struct cdns_torrent_vals_entry cdns_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_XAUI, NO_SSC), &ml_pcie_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, NO_SSC), &ml_pcie_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, EXTERNAL_SSC), &ml_pcie_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, INTERNAL_SSC), &ml_pcie_100_no_ssc_rx_ln_vals},
@ -5198,6 +5332,8 @@ static const struct cdns_torrent_vals_entry cdns_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_XAUI, TYPE_PCIE, NO_SSC), &xaui_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_rx_ln_vals},
/* Dual refclk */
@ -5278,6 +5414,8 @@ static const struct cdns_torrent_vals_entry ti_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_XAUI, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, EXTERNAL_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, INTERNAL_SSC), NULL},
@ -5328,6 +5466,8 @@ static const struct cdns_torrent_vals_entry ti_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_XAUI, TYPE_PCIE, NO_SSC), &ti_xaui_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
/* Dual refclk */
@ -5406,6 +5546,8 @@ static const struct cdns_torrent_vals_entry ti_j7200_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_XAUI, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, NO_SSC), &ml_pcie_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, EXTERNAL_SSC), &ml_pcie_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, INTERNAL_SSC), &ml_pcie_100_int_ssc_cmn_vals},
@ -5456,6 +5598,8 @@ static const struct cdns_torrent_vals_entry ti_j7200_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_XAUI, TYPE_PCIE, NO_SSC), &xaui_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &sl_usxgmii_156_25_no_ssc_cmn_vals},
/* Dual refclk */
@ -5500,6 +5644,8 @@ static const struct cdns_torrent_vals_entry ti_j7200_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_XAUI, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, NO_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, EXTERNAL_SSC), NULL},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, INTERNAL_SSC), NULL},
@ -5550,6 +5696,8 @@ static const struct cdns_torrent_vals_entry ti_j7200_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_XAUI, TYPE_PCIE, NO_SSC), &ti_xaui_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
/* Dual refclk */
@ -5594,6 +5742,8 @@ static const struct cdns_torrent_vals_entry ti_j7200_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_XAUI, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE_ML, TYPE_USB, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
@ -5644,6 +5794,8 @@ static const struct cdns_torrent_vals_entry ti_j7200_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_XAUI, TYPE_PCIE, NO_SSC), &xaui_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_rx_ln_vals},
/* Dual refclk */

View file

@ -17,6 +17,10 @@
#define PHY_CTRL0_FSEL_MASK GENMASK(10, 5)
#define PHY_CTRL0_FSEL_24M 0x2a
#define PHY_CTRL0_FSEL_100M 0x27
#define PHY_CTRL0_SSC_RANGE_MASK GENMASK(23, 21)
#define PHY_CTRL0_SSC_RANGE_4003PPM 0x2
#define PHY_CTRL0_SSC_RANGE_4492PPM 0x1
#define PHY_CTRL0_SSC_RANGE_4980PPM 0x0
#define PHY_CTRL1 0x4
#define PHY_CTRL1_RESET BIT(0)
@ -47,6 +51,7 @@
#define PHY_CTRL5_PCS_TX_SWING_FULL_MASK GENMASK(6, 0)
#define PHY_CTRL6 0x18
#define PHY_CTRL6_RXTERM_OVERRIDE_SEL BIT(29)
#define PHY_CTRL6_ALT_CLK_EN BIT(1)
#define PHY_CTRL6_ALT_CLK_SEL BIT(0)
@ -587,6 +592,9 @@ static int imx8mp_usb_phy_init(struct phy *phy)
value = readl(imx_phy->base + PHY_CTRL0);
value |= PHY_CTRL0_REF_SSP_EN;
value &= ~PHY_CTRL0_SSC_RANGE_MASK;
value |= FIELD_PREP(PHY_CTRL0_SSC_RANGE_MASK,
PHY_CTRL0_SSC_RANGE_4003PPM);
writel(value, imx_phy->base + PHY_CTRL0);
value = readl(imx_phy->base + PHY_CTRL2);
@ -610,6 +618,7 @@ static int imx8mp_usb_phy_init(struct phy *phy)
static int imx8mq_phy_power_on(struct phy *phy)
{
struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy);
u32 value;
int ret;
ret = regulator_enable(imx_phy->vbus);
@ -626,12 +635,23 @@ static int imx8mq_phy_power_on(struct phy *phy)
return ret;
}
return ret;
/* Disable rx term override */
value = readl(imx_phy->base + PHY_CTRL6);
value &= ~PHY_CTRL6_RXTERM_OVERRIDE_SEL;
writel(value, imx_phy->base + PHY_CTRL6);
return 0;
}
static int imx8mq_phy_power_off(struct phy *phy)
{
struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy);
u32 value;
/* Override rx term to be 0 */
value = readl(imx_phy->base + PHY_CTRL6);
value |= PHY_CTRL6_RXTERM_OVERRIDE_SEL;
writel(value, imx_phy->base + PHY_CTRL6);
clk_disable_unprepare(imx_phy->alt_clk);
clk_disable_unprepare(imx_phy->clk);
@ -676,6 +696,8 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
if (!imx_phy)
return -ENOMEM;
platform_set_drvdata(pdev, imx_phy);
imx_phy->clk = devm_clk_get(dev, "phy");
if (IS_ERR(imx_phy->clk)) {
dev_err(dev, "failed to get imx8mq usb phy clock\n");
@ -730,6 +752,7 @@ static struct platform_driver imx8mq_usb_phy_driver = {
.driver = {
.name = "imx8mq-usb-phy",
.of_match_table = imx8mq_usb_phy_of_match,
.suppress_bind_attrs = true,
}
};
module_platform_driver(imx8mq_usb_phy_driver);

View file

@ -251,7 +251,7 @@ static void imx_hsio_configure_clk_pad(struct phy *phy)
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
if (strncmp(priv->refclk_pad, "output", 6) == 0) {
if (priv->refclk_pad && strncmp(priv->refclk_pad, "output", 6) == 0) {
pll = true;
regmap_update_bits(priv->misc, HSIO_CTRL0,
HSIO_IOB_A_0_TXOE | HSIO_IOB_A_0_M1M0_MASK,

View file

@ -286,11 +286,9 @@ static int mixel_lvds_phy_reset(struct device *dev)
regmap_write(priv->regmap, PHY_CTRL, CTRL_RESET_VAL);
ret = pm_runtime_put(dev);
if (ret < 0)
dev_err(dev, "failed to put PM runtime: %d\n", ret);
pm_runtime_put(dev);
return ret;
return 0;
}
static struct phy *mixel_lvds_phy_xlate(struct device *dev,

File diff suppressed because it is too large Load diff

View file

@ -570,17 +570,20 @@ const struct phy_config *fsl_samsung_hdmi_phy_find_settings(struct fsl_samsung_h
return fract_div_phy;
}
static long fsl_samsung_hdmi_phy_clk_round_rate(struct clk_hw *hw,
unsigned long rate, unsigned long *parent_rate)
static int fsl_samsung_hdmi_phy_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw);
const struct phy_config *target_settings = fsl_samsung_hdmi_phy_find_settings(phy, rate);
const struct phy_config *target_settings = fsl_samsung_hdmi_phy_find_settings(phy,
req->rate);
if (target_settings == NULL)
return -EINVAL;
dev_dbg(phy->dev, "round_rate, closest rate = %u\n", target_settings->pixclk);
return target_settings->pixclk;
req->rate = target_settings->pixclk;
return 0;
}
static int fsl_samsung_hdmi_phy_clk_set_rate(struct clk_hw *hw,
@ -599,7 +602,7 @@ static int fsl_samsung_hdmi_phy_clk_set_rate(struct clk_hw *hw,
static const struct clk_ops phy_clk_ops = {
.recalc_rate = phy_clk_recalc_rate,
.round_rate = fsl_samsung_hdmi_phy_clk_round_rate,
.determine_rate = fsl_samsung_hdmi_phy_clk_determine_rate,
.set_rate = fsl_samsung_hdmi_phy_clk_set_rate,
};

View file

@ -338,7 +338,7 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
return -ENOMEM;
}
port->dr_mode = of_usb_get_dr_mode_by_phy(child, -1);
port->dr_mode = of_usb_get_dr_mode_by_phy(child, 0);
if ((port->dr_mode != USB_DR_MODE_HOST) &&
(port->dr_mode != USB_DR_MODE_PERIPHERAL)) {
dev_err(&pdev->dev,

View file

@ -90,10 +90,10 @@ static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
usleep_range(80, 100);
}
static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int mtk_hdmi_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return rate;
return 0;
}
static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -170,7 +170,7 @@ static const struct clk_ops mtk_hdmi_phy_pll_ops = {
.prepare = mtk_hdmi_pll_prepare,
.unprepare = mtk_hdmi_pll_unprepare,
.set_rate = mtk_hdmi_pll_set_rate,
.round_rate = mtk_hdmi_pll_round_rate,
.determine_rate = mtk_hdmi_pll_determine_rate,
.recalc_rate = mtk_hdmi_pll_recalc_rate,
};

View file

@ -118,18 +118,18 @@ static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
usleep_range(100, 150);
}
static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int mtk_hdmi_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
hdmi_phy->pll_rate = rate;
if (rate <= 74250000)
*parent_rate = rate;
hdmi_phy->pll_rate = req->rate;
if (req->rate <= 74250000)
req->best_parent_rate = req->rate;
else
*parent_rate = rate / 2;
req->best_parent_rate = req->rate / 2;
return rate;
return 0;
}
static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -223,7 +223,7 @@ static const struct clk_ops mtk_hdmi_phy_pll_ops = {
.prepare = mtk_hdmi_pll_prepare,
.unprepare = mtk_hdmi_pll_unprepare,
.set_rate = mtk_hdmi_pll_set_rate,
.round_rate = mtk_hdmi_pll_round_rate,
.determine_rate = mtk_hdmi_pll_determine_rate,
.recalc_rate = mtk_hdmi_pll_recalc_rate,
};

View file

@ -418,13 +418,13 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
return mtk_hdmi_pll_calc(hdmi_phy, hw, rate, parent_rate);
}
static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int mtk_hdmi_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
hdmi_phy->pll_rate = rate;
return rate;
hdmi_phy->pll_rate = req->rate;
return 0;
}
static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
@ -439,7 +439,7 @@ static const struct clk_ops mtk_hdmi_pll_ops = {
.prepare = mtk_hdmi_pll_prepare,
.unprepare = mtk_hdmi_pll_unprepare,
.set_rate = mtk_hdmi_pll_set_rate,
.round_rate = mtk_hdmi_pll_round_rate,
.determine_rate = mtk_hdmi_pll_determine_rate,
.recalc_rate = mtk_hdmi_pll_recalc_rate,
};

View file

@ -237,16 +237,18 @@ static void mtk_mipi_tx_pll_unprepare(struct clk_hw *hw)
mtk_phy_clear_bits(base + MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_DIV_MSK);
}
static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int mtk_mipi_tx_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return clamp_val(rate, 50000000, 1250000000);
req->rate = clamp_val(req->rate, 50000000, 1250000000);
return 0;
}
static const struct clk_ops mtk_mipi_tx_pll_ops = {
.prepare = mtk_mipi_tx_pll_prepare,
.unprepare = mtk_mipi_tx_pll_unprepare,
.round_rate = mtk_mipi_tx_pll_round_rate,
.determine_rate = mtk_mipi_tx_pll_determine_rate,
.set_rate = mtk_mipi_tx_pll_set_rate,
.recalc_rate = mtk_mipi_tx_pll_recalc_rate,
};

View file

@ -97,16 +97,18 @@ static void mtk_mipi_tx_pll_disable(struct clk_hw *hw)
mtk_phy_clear_bits(base + MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
}
static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int mtk_mipi_tx_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return clamp_val(rate, 125000000, 1600000000);
req->rate = clamp_val(req->rate, 125000000, 1600000000);
return 0;
}
static const struct clk_ops mtk_mipi_tx_pll_ops = {
.enable = mtk_mipi_tx_pll_enable,
.disable = mtk_mipi_tx_pll_disable,
.round_rate = mtk_mipi_tx_pll_round_rate,
.determine_rate = mtk_mipi_tx_pll_determine_rate,
.set_rate = mtk_mipi_tx_pll_set_rate,
.recalc_rate = mtk_mipi_tx_pll_recalc_rate,
};

View file

@ -353,7 +353,7 @@ static int mtk_xfi_tphy_power_on(struct phy *phy)
* Disable and unprepare all clocks previously enabled.
*
* Return:
* See clk_bulk_prepare_disable().
* See clk_bulk_disable_unprepare().
*/
static int mtk_xfi_tphy_power_off(struct phy *phy)
{

View file

@ -138,17 +138,14 @@ static struct phy *phy_find(struct device *dev, const char *con_id)
static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
{
struct phy_provider *phy_provider;
struct device_node *child;
list_for_each_entry(phy_provider, &phy_provider_list, list) {
if (phy_provider->dev->of_node == node)
return phy_provider;
for_each_child_of_node(phy_provider->children, child)
if (child == node) {
of_node_put(child);
for_each_child_of_node_scoped(phy_provider->children, child)
if (child == node)
return phy_provider;
}
}
return ERR_PTR(-EPROBE_DEFER);
@ -190,15 +187,15 @@ int phy_pm_runtime_get_sync(struct phy *phy)
}
EXPORT_SYMBOL_GPL(phy_pm_runtime_get_sync);
int phy_pm_runtime_put(struct phy *phy)
void phy_pm_runtime_put(struct phy *phy)
{
if (!phy)
return 0;
return;
if (!pm_runtime_enabled(&phy->dev))
return -ENOTSUPP;
return;
return pm_runtime_put(&phy->dev);
pm_runtime_put(&phy->dev);
}
EXPORT_SYMBOL_GPL(phy_pm_runtime_put);

View file

@ -0,0 +1,296 @@
// SPDX-License-Identifier: GPL-2.0
/*
* phy-google-usb.c - Google USB PHY driver
*
* Copyright (C) 2025, Google LLC
*/
#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/usb/typec_mux.h>
#define USBCS_USB2PHY_CFG19_OFFSET 0x0
#define USBCS_USB2PHY_CFG19_PHY_CFG_PLL_FB_DIV GENMASK(19, 8)
#define USBCS_USB2PHY_CFG21_OFFSET 0x8
#define USBCS_USB2PHY_CFG21_PHY_ENABLE BIT(12)
#define USBCS_USB2PHY_CFG21_REF_FREQ_SEL GENMASK(15, 13)
#define USBCS_USB2PHY_CFG21_PHY_TX_DIG_BYPASS_SEL BIT(19)
#define USBCS_PHY_CFG1_OFFSET 0x28
#define USBCS_PHY_CFG1_SYS_VBUSVALID BIT(17)
enum google_usb_phy_id {
GOOGLE_USB2_PHY,
GOOGLE_USB_PHY_NUM,
};
struct google_usb_phy_instance {
struct google_usb_phy *parent;
unsigned int index;
struct phy *phy;
unsigned int num_clks;
struct clk_bulk_data *clks;
unsigned int num_rsts;
struct reset_control_bulk_data *rsts;
};
struct google_usb_phy {
struct device *dev;
struct regmap *usb_cfg_regmap;
unsigned int usb2_cfg_offset;
void __iomem *usbdp_top_base;
struct google_usb_phy_instance *insts;
/*
* Protect phy registers from concurrent access, specifically via
* google_usb_set_orientation callback.
*/
struct mutex phy_mutex;
struct typec_switch_dev *sw;
enum typec_orientation orientation;
};
static void set_vbus_valid(struct google_usb_phy *gphy)
{
u32 reg;
if (gphy->orientation == TYPEC_ORIENTATION_NONE) {
reg = readl(gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
reg &= ~USBCS_PHY_CFG1_SYS_VBUSVALID;
writel(reg, gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
} else {
reg = readl(gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
reg |= USBCS_PHY_CFG1_SYS_VBUSVALID;
writel(reg, gphy->usbdp_top_base + USBCS_PHY_CFG1_OFFSET);
}
}
static int google_usb_set_orientation(struct typec_switch_dev *sw,
enum typec_orientation orientation)
{
struct google_usb_phy *gphy = typec_switch_get_drvdata(sw);
dev_dbg(gphy->dev, "set orientation %d\n", orientation);
gphy->orientation = orientation;
if (pm_runtime_suspended(gphy->dev))
return 0;
guard(mutex)(&gphy->phy_mutex);
set_vbus_valid(gphy);
return 0;
}
static int google_usb2_phy_init(struct phy *_phy)
{
struct google_usb_phy_instance *inst = phy_get_drvdata(_phy);
struct google_usb_phy *gphy = inst->parent;
u32 reg;
int ret;
dev_dbg(gphy->dev, "initializing usb2 phy\n");
guard(mutex)(&gphy->phy_mutex);
regmap_read(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG21_OFFSET, &reg);
reg &= ~USBCS_USB2PHY_CFG21_PHY_TX_DIG_BYPASS_SEL;
reg &= ~USBCS_USB2PHY_CFG21_REF_FREQ_SEL;
reg |= FIELD_PREP(USBCS_USB2PHY_CFG21_REF_FREQ_SEL, 0);
regmap_write(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG21_OFFSET, reg);
regmap_read(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG19_OFFSET, &reg);
reg &= ~USBCS_USB2PHY_CFG19_PHY_CFG_PLL_FB_DIV;
reg |= FIELD_PREP(USBCS_USB2PHY_CFG19_PHY_CFG_PLL_FB_DIV, 368);
regmap_write(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG19_OFFSET, reg);
set_vbus_valid(gphy);
ret = clk_bulk_prepare_enable(inst->num_clks, inst->clks);
if (ret)
return ret;
ret = reset_control_bulk_deassert(inst->num_rsts, inst->rsts);
if (ret) {
clk_bulk_disable_unprepare(inst->num_clks, inst->clks);
return ret;
}
regmap_read(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG21_OFFSET, &reg);
reg |= USBCS_USB2PHY_CFG21_PHY_ENABLE;
regmap_write(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG21_OFFSET, reg);
return 0;
}
static int google_usb2_phy_exit(struct phy *_phy)
{
struct google_usb_phy_instance *inst = phy_get_drvdata(_phy);
struct google_usb_phy *gphy = inst->parent;
u32 reg;
dev_dbg(gphy->dev, "exiting usb2 phy\n");
guard(mutex)(&gphy->phy_mutex);
regmap_read(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG21_OFFSET, &reg);
reg &= ~USBCS_USB2PHY_CFG21_PHY_ENABLE;
regmap_write(gphy->usb_cfg_regmap, gphy->usb2_cfg_offset + USBCS_USB2PHY_CFG21_OFFSET, reg);
reset_control_bulk_assert(inst->num_rsts, inst->rsts);
clk_bulk_disable_unprepare(inst->num_clks, inst->clks);
return 0;
}
static const struct phy_ops google_usb2_phy_ops = {
.init = google_usb2_phy_init,
.exit = google_usb2_phy_exit,
};
static struct phy *google_usb_phy_xlate(struct device *dev,
const struct of_phandle_args *args)
{
struct google_usb_phy *gphy = dev_get_drvdata(dev);
if (args->args[0] >= GOOGLE_USB_PHY_NUM) {
dev_err(dev, "invalid PHY index requested from DT\n");
return ERR_PTR(-ENODEV);
}
return gphy->insts[args->args[0]].phy;
}
static int google_usb_phy_probe(struct platform_device *pdev)
{
struct typec_switch_desc sw_desc = { };
struct google_usb_phy_instance *inst;
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
struct google_usb_phy *gphy;
struct phy *phy;
u32 args[1];
int ret;
gphy = devm_kzalloc(dev, sizeof(*gphy), GFP_KERNEL);
if (!gphy)
return -ENOMEM;
dev_set_drvdata(dev, gphy);
gphy->dev = dev;
ret = devm_mutex_init(dev, &gphy->phy_mutex);
if (ret)
return ret;
gphy->usb_cfg_regmap =
syscon_regmap_lookup_by_phandle_args(dev->of_node,
"google,usb-cfg-csr",
ARRAY_SIZE(args), args);
if (IS_ERR(gphy->usb_cfg_regmap)) {
return dev_err_probe(dev, PTR_ERR(gphy->usb_cfg_regmap),
"invalid usb cfg csr\n");
}
gphy->usb2_cfg_offset = args[0];
gphy->usbdp_top_base = devm_platform_ioremap_resource_byname(pdev,
"usbdp_top");
if (IS_ERR(gphy->usbdp_top_base))
return dev_err_probe(dev, PTR_ERR(gphy->usbdp_top_base),
"invalid usbdp top\n");
gphy->insts = devm_kcalloc(dev, GOOGLE_USB_PHY_NUM, sizeof(*gphy->insts), GFP_KERNEL);
if (!gphy->insts)
return -ENOMEM;
inst = &gphy->insts[GOOGLE_USB2_PHY];
inst->parent = gphy;
inst->index = GOOGLE_USB2_PHY;
phy = devm_phy_create(dev, NULL, &google_usb2_phy_ops);
if (IS_ERR(phy))
return dev_err_probe(dev, PTR_ERR(phy),
"failed to create usb2 phy instance\n");
inst->phy = phy;
phy_set_drvdata(phy, inst);
inst->num_clks = 2;
inst->clks = devm_kcalloc(dev, inst->num_clks, sizeof(*inst->clks), GFP_KERNEL);
if (!inst->clks)
return -ENOMEM;
inst->clks[0].id = "usb2";
inst->clks[1].id = "usb2_apb";
ret = devm_clk_bulk_get(dev, inst->num_clks, inst->clks);
if (ret)
return dev_err_probe(dev, ret, "failed to get u2 phy clks\n");
inst->num_rsts = 2;
inst->rsts = devm_kcalloc(dev, inst->num_rsts, sizeof(*inst->rsts), GFP_KERNEL);
if (!inst->rsts)
return -ENOMEM;
inst->rsts[0].id = "usb2";
inst->rsts[1].id = "usb2_apb";
ret = devm_reset_control_bulk_get_exclusive(dev, inst->num_rsts, inst->rsts);
if (ret)
return dev_err_probe(dev, ret, "failed to get u2 phy resets\n");
phy_provider = devm_of_phy_provider_register(dev, google_usb_phy_xlate);
if (IS_ERR(phy_provider))
return dev_err_probe(dev, PTR_ERR(phy_provider),
"failed to register phy provider\n");
pm_runtime_enable(dev);
sw_desc.fwnode = dev_fwnode(dev);
sw_desc.drvdata = gphy;
sw_desc.name = fwnode_get_name(dev_fwnode(dev));
sw_desc.set = google_usb_set_orientation;
gphy->sw = typec_switch_register(dev, &sw_desc);
if (IS_ERR(gphy->sw))
return dev_err_probe(dev, PTR_ERR(gphy->sw),
"failed to register typec switch\n");
return 0;
}
static void google_usb_phy_remove(struct platform_device *pdev)
{
struct google_usb_phy *gphy = dev_get_drvdata(&pdev->dev);
typec_switch_unregister(gphy->sw);
pm_runtime_disable(&pdev->dev);
}
static const struct of_device_id google_usb_phy_of_match[] = {
{
.compatible = "google,lga-usb-phy",
},
{ }
};
MODULE_DEVICE_TABLE(of, google_usb_phy_of_match);
static struct platform_driver google_usb_phy = {
.probe = google_usb_phy_probe,
.remove = google_usb_phy_remove,
.driver = {
.name = "google-usb-phy",
.of_match_table = google_usb_phy_of_match,
}
};
module_platform_driver(google_usb_phy);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Google USB phy driver");

View file

@ -0,0 +1,670 @@
// SPDX-License-Identifier: GPL-2.0
/*
* SpacemiT K1 PCIe and PCIe/USB 3 combo PHY driver
*
* Copyright (C) 2025 by RISCstar Solutions Corporation. All rights reserved.
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <dt-bindings/phy/phy.h>
/*
* Three PCIe ports are supported in the SpacemiT K1 SoC, and this driver
* supports their PHYs.
*
* The PHY for PCIe port A is different from the PHYs for ports B and C:
* - It has one lane, while ports B and C have two
* - It is a combo PHY can be used for PCIe or USB 3
* - It can automatically calibrate PCIe TX and RX termination settings
*
* The PHY functionality for PCIe ports B and C is identical:
* - They have two PCIe lanes (but can be restricted to 1 via device tree)
* - They are used for PCIe only
* - They are configured using TX and RX values computed for port A
*
* A given board is designed to use the combo PHY for either PCIe or USB 3.
* Whether the combo PHY is configured for PCIe or USB 3 is specified in
* device tree using a phandle plus an argument. The argument indicates
* the type (either PHY_TYPE_PCIE or PHY_TYPE_USB3).
*
* Each PHY has a reset that it gets and deasserts during initialization.
* Each depends also on other clocks and resets provided by the controller
* hardware (PCIe or USB) it is associated with. The controller drivers
* are required to enable any clocks and de-assert any resets that affect
* PHY operation. In addition each PHY implements an internal PLL, driven
* by an external (24 MHz) oscillator.
*
* PCIe PHYs must be programmed with RX and TX calibration values. The
* combo PHY is the only one that can determine these values. They are
* determined by temporarily enabling the combo PHY in PCIe mode at probe
* time (if necessary). This calibration only needs to be done once, and
* when it has completed the TX and RX values are saved.
*
* To allow the combo PHY to be enabled for calibration, the resets and
* clocks it uses in PCIe mode must be supplied.
*/
struct k1_pcie_phy {
struct device *dev; /* PHY provider device */
struct phy *phy;
void __iomem *regs;
u32 pcie_lanes; /* Max (1 or 2) unless limited by DT */
struct clk *pll;
struct clk_hw pll_hw; /* Private PLL clock */
/* The remaining fields are only used for the combo PHY */
u32 type; /* PHY_TYPE_PCIE or PHY_TYPE_USB3 */
struct regmap *pmu; /* MMIO regmap (no errors) */
};
#define CALIBRATION_TIMEOUT 500000 /* For combo PHY (usec) */
#define PLL_TIMEOUT 500000 /* For PHY PLL lock (usec) */
#define POLL_DELAY 500 /* Time between polls (usec) */
/* Selecting the combo PHY operating mode requires APMU regmap access */
#define SYSCON_APMU "spacemit,apmu"
/* PMU space, for selecting between PCIe and USB 3 mode (combo PHY only) */
#define PMUA_USB_PHY_CTRL0 0x0110
#define COMBO_PHY_SEL BIT(3) /* 0: PCIe; 1: USB 3 */
#define PCIE_CLK_RES_CTRL 0x03cc
#define PCIE_APP_HOLD_PHY_RST BIT(30)
/* PHY register space */
/* Offset between lane 0 and lane 1 registers when there are two */
#define PHY_LANE_OFFSET 0x0400
/* PHY PLL configuration */
#define PCIE_PU_ADDR_CLK_CFG 0x0008
#define PLL_READY BIT(0) /* read-only */
#define CFG_INTERNAL_TIMER_ADJ GENMASK(10, 7)
#define TIMER_ADJ_USB 0x2
#define TIMER_ADJ_PCIE 0x6
#define CFG_SW_PHY_INIT_DONE BIT(11) /* We set after PLL config */
#define PCIE_RC_DONE_STATUS 0x0018
#define CFG_FORCE_RCV_RETRY BIT(10) /* Used for PCIe */
/* PCIe PHY lane calibration; assumes 24MHz input clock */
#define PCIE_RC_CAL_REG2 0x0020
#define RC_CAL_TOGGLE BIT(22)
#define CLKSEL GENMASK(31, 29)
#define CLKSEL_24M 0x3
/* Additional PHY PLL configuration (USB 3 and PCIe) */
#define PCIE_PU_PLL_1 0x0048
#define REF_100_WSSC BIT(12) /* 1: input is 100MHz, SSC */
#define FREF_SEL GENMASK(15, 13)
#define FREF_24M 0x1
#define SSC_DEP_SEL GENMASK(19, 16)
#define SSC_DEP_NONE 0x0
#define SSC_DEP_5000PPM 0xa
/* PCIe PHY configuration */
#define PCIE_PU_PLL_2 0x004c
#define GEN_REF100 BIT(4) /* 1: generate 100MHz clk */
#define PCIE_RX_REG1 0x0050
#define EN_RTERM BIT(3)
#define AFE_RTERM_REG GENMASK(11, 8)
#define PCIE_RX_REG2 0x0054
#define RX_RTERM_SEL BIT(5) /* 0: use AFE_RTERM_REG value */
#define PCIE_LTSSM_DIS_ENTRY 0x005c
#define CFG_REFCLK_MODE GENMASK(9, 8)
#define RFCLK_MODE_DRIVER 0x1
#define OVRD_REFCLK_MODE BIT(10) /* 1: use CFG_RFCLK_MODE */
#define PCIE_TX_REG1 0x0064
#define TX_RTERM_REG GENMASK(15, 12)
#define TX_RTERM_SEL BIT(25) /* 1: use TX_RTERM_REG */
/* Zeroed for the combo PHY operating in USB mode */
#define USB3_TEST_CTRL 0x0068
/* PHY calibration values, determined by the combo PHY at probe time */
#define PCIE_RCAL_RESULT 0x0084 /* Port A PHY only */
#define RTERM_VALUE_RX GENMASK(3, 0)
#define RTERM_VALUE_TX GENMASK(7, 4)
#define R_TUNE_DONE BIT(10)
static u32 k1_phy_rterm = ~0; /* Invalid initial value */
/* Save the RX and TX receiver termination values */
static void k1_phy_rterm_set(u32 val)
{
k1_phy_rterm = val & (RTERM_VALUE_RX | RTERM_VALUE_TX);
}
static bool k1_phy_rterm_valid(void)
{
/* Valid if no bits outside those we care about are set */
return !(k1_phy_rterm & ~(RTERM_VALUE_RX | RTERM_VALUE_TX));
}
static u32 k1_phy_rterm_rx(void)
{
return FIELD_GET(RTERM_VALUE_RX, k1_phy_rterm);
}
static u32 k1_phy_rterm_tx(void)
{
return FIELD_GET(RTERM_VALUE_TX, k1_phy_rterm);
}
/* Only the combo PHY has a PMU pointer defined */
static bool k1_phy_port_a(struct k1_pcie_phy *k1_phy)
{
return !!k1_phy->pmu;
}
/* The PLL clocks are driven by the external oscillator */
static const struct clk_parent_data k1_pcie_phy_data[] = {
{ .fw_name = "refclk", },
};
static struct k1_pcie_phy *clk_hw_to_k1_phy(struct clk_hw *clk_hw)
{
return container_of(clk_hw, struct k1_pcie_phy, pll_hw);
}
/* USB mode only works on the combo PHY, which has only one lane */
static void k1_pcie_phy_pll_prepare_usb(struct k1_pcie_phy *k1_phy)
{
void __iomem *regs = k1_phy->regs;
u32 val;
val = readl(regs + PCIE_PU_ADDR_CLK_CFG);
val &= ~CFG_INTERNAL_TIMER_ADJ;
val |= FIELD_PREP(CFG_INTERNAL_TIMER_ADJ, TIMER_ADJ_USB);
writel(val, regs + PCIE_PU_ADDR_CLK_CFG);
val = readl(regs + PCIE_PU_PLL_1);
val &= ~SSC_DEP_SEL;
val |= FIELD_PREP(SSC_DEP_SEL, SSC_DEP_5000PPM);
writel(val, regs + PCIE_PU_PLL_1);
}
/* Perform PCIe-specific register updates before starting the PLL clock */
static void k1_pcie_phy_pll_prepare_pcie(struct k1_pcie_phy *k1_phy)
{
void __iomem *regs = k1_phy->regs;
u32 val;
u32 i;
for (i = 0; i < k1_phy->pcie_lanes; i++) {
val = readl(regs + PCIE_PU_ADDR_CLK_CFG);
val &= ~CFG_INTERNAL_TIMER_ADJ;
val |= FIELD_PREP(CFG_INTERNAL_TIMER_ADJ, TIMER_ADJ_PCIE);
writel(val, regs + PCIE_PU_ADDR_CLK_CFG);
regs += PHY_LANE_OFFSET; /* Next lane */
}
regs = k1_phy->regs;
val = readl(regs + PCIE_RC_DONE_STATUS);
val |= CFG_FORCE_RCV_RETRY;
writel(val, regs + PCIE_RC_DONE_STATUS);
val = readl(regs + PCIE_PU_PLL_1);
val &= ~SSC_DEP_SEL;
val |= FIELD_PREP(SSC_DEP_SEL, SSC_DEP_NONE);
writel(val, regs + PCIE_PU_PLL_1);
val = readl(regs + PCIE_PU_PLL_2);
val |= GEN_REF100; /* Enable 100 MHz PLL output clock */
writel(val, regs + PCIE_PU_PLL_2);
}
static int k1_pcie_phy_pll_prepare(struct clk_hw *clk_hw)
{
struct k1_pcie_phy *k1_phy = clk_hw_to_k1_phy(clk_hw);
void __iomem *regs = k1_phy->regs;
u32 val;
u32 i;
if (k1_phy_port_a(k1_phy) && k1_phy->type == PHY_TYPE_USB3)
k1_pcie_phy_pll_prepare_usb(k1_phy);
else
k1_pcie_phy_pll_prepare_pcie(k1_phy);
/*
* Disable 100 MHz input reference with spread-spectrum
* clocking and select the 24 MHz clock input frequency
*/
val = readl(regs + PCIE_PU_PLL_1);
val &= ~REF_100_WSSC;
val &= ~FREF_SEL;
val |= FIELD_PREP(FREF_SEL, FREF_24M);
writel(val, regs + PCIE_PU_PLL_1);
/* Mark PLL configuration done on all lanes */
for (i = 0; i < k1_phy->pcie_lanes; i++) {
val = readl(regs + PCIE_PU_ADDR_CLK_CFG);
val |= CFG_SW_PHY_INIT_DONE;
writel(val, regs + PCIE_PU_ADDR_CLK_CFG);
regs += PHY_LANE_OFFSET; /* Next lane */
}
/*
* Wait for indication the PHY PLL is locked. Lanes for ports
* B and C share a PLL, so it's enough to sample just lane 0.
*/
return readl_poll_timeout(k1_phy->regs + PCIE_PU_ADDR_CLK_CFG,
val, val & PLL_READY,
POLL_DELAY, PLL_TIMEOUT);
}
/* Prepare implies enable, and once enabled, it's always on */
static const struct clk_ops k1_pcie_phy_pll_ops = {
.prepare = k1_pcie_phy_pll_prepare,
};
/* We represent the PHY PLL as a private clock */
static int k1_pcie_phy_pll_setup(struct k1_pcie_phy *k1_phy)
{
struct clk_hw *hw = &k1_phy->pll_hw;
struct device *dev = k1_phy->dev;
struct clk_init_data init = { };
char *name;
int ret;
name = kasprintf(GFP_KERNEL, "pcie%u_phy_pll", k1_phy->phy->id);
if (!name)
return -ENOMEM;
init.name = name;
init.ops = &k1_pcie_phy_pll_ops;
init.parent_data = k1_pcie_phy_data;
init.num_parents = ARRAY_SIZE(k1_pcie_phy_data);
hw->init = &init;
ret = devm_clk_hw_register(dev, hw);
kfree(name); /* __clk_register() duplicates the name we provide */
if (ret)
return ret;
k1_phy->pll = devm_clk_hw_get_clk(dev, hw, "pll");
if (IS_ERR(k1_phy->pll))
return PTR_ERR(k1_phy->pll);
return 0;
}
/* Select PCIe or USB 3 mode for the combo PHY. */
static void k1_combo_phy_sel(struct k1_pcie_phy *k1_phy, bool usb)
{
struct regmap *pmu = k1_phy->pmu;
/* Only change it if it's not already in the desired state */
if (!regmap_test_bits(pmu, PMUA_USB_PHY_CTRL0, COMBO_PHY_SEL) == usb)
regmap_assign_bits(pmu, PMUA_USB_PHY_CTRL0, COMBO_PHY_SEL, usb);
}
static void k1_pcie_phy_init_pcie(struct k1_pcie_phy *k1_phy)
{
u32 rx_rterm = k1_phy_rterm_rx();
u32 tx_rterm = k1_phy_rterm_tx();
void __iomem *regs;
u32 val;
int i;
/* For the combo PHY, set PHY to PCIe mode */
if (k1_phy_port_a(k1_phy))
k1_combo_phy_sel(k1_phy, false);
regs = k1_phy->regs;
for (i = 0; i < k1_phy->pcie_lanes; i++) {
val = readl(regs + PCIE_RX_REG1);
/* Set RX analog front-end receiver termination value */
val &= ~AFE_RTERM_REG;
val |= FIELD_PREP(AFE_RTERM_REG, rx_rterm);
/* And enable refclock receiver termination */
val |= EN_RTERM;
writel(val, regs + PCIE_RX_REG1);
val = readl(regs + PCIE_RX_REG2);
/* Use PCIE_RX_REG1 AFE_RTERM_REG value */
val &= ~RX_RTERM_SEL;
writel(val, regs + PCIE_RX_REG2);
val = readl(regs + PCIE_TX_REG1);
/* Set TX driver termination value */
val &= ~TX_RTERM_REG;
val |= FIELD_PREP(TX_RTERM_REG, tx_rterm);
/* Use PCIE_TX_REG1 TX_RTERM_REG value */
val |= TX_RTERM_SEL;
writel(val, regs + PCIE_TX_REG1);
/* Set the input clock to 24 MHz, and clear RC_CAL_TOGGLE */
val = readl(regs + PCIE_RC_CAL_REG2);
val &= CLKSEL;
val |= FIELD_PREP(CLKSEL, CLKSEL_24M);
val &= ~RC_CAL_TOGGLE;
writel(val, regs + PCIE_RC_CAL_REG2);
/* Now trigger recalibration by setting RC_CAL_TOGGLE again */
val |= RC_CAL_TOGGLE;
writel(val, regs + PCIE_RC_CAL_REG2);
val = readl(regs + PCIE_LTSSM_DIS_ENTRY);
/* Override the reference clock; set to refclk driver mode */
val |= OVRD_REFCLK_MODE;
val &= ~CFG_REFCLK_MODE;
val |= FIELD_PREP(CFG_REFCLK_MODE, RFCLK_MODE_DRIVER);
writel(val, regs + PCIE_LTSSM_DIS_ENTRY);
regs += PHY_LANE_OFFSET; /* Next lane */
}
}
/* Only called for combo PHY */
static void k1_pcie_phy_init_usb(struct k1_pcie_phy *k1_phy)
{
k1_combo_phy_sel(k1_phy, true);
/* We're not doing any testing */
writel(0, k1_phy->regs + USB3_TEST_CTRL);
}
static int k1_pcie_phy_init(struct phy *phy)
{
struct k1_pcie_phy *k1_phy = phy_get_drvdata(phy);
/* Note: port type is only valid for port A (both checks needed) */
if (k1_phy_port_a(k1_phy) && k1_phy->type == PHY_TYPE_USB3)
k1_pcie_phy_init_usb(k1_phy);
else
k1_pcie_phy_init_pcie(k1_phy);
return clk_prepare_enable(k1_phy->pll);
}
static int k1_pcie_phy_exit(struct phy *phy)
{
struct k1_pcie_phy *k1_phy = phy_get_drvdata(phy);
clk_disable_unprepare(k1_phy->pll);
return 0;
}
static const struct phy_ops k1_pcie_phy_ops = {
.init = k1_pcie_phy_init,
.exit = k1_pcie_phy_exit,
.owner = THIS_MODULE,
};
/*
* Get values needed for calibrating PHYs operating in PCIe mode. Only
* the combo PHY is able to do this, and its calibration values are used
* for configuring all PCIe PHYs.
*
* We always need to de-assert the "global" reset on the combo PHY,
* because the USB driver depends on it. If used for PCIe, that driver
* will (also) de-assert this, but by leaving it de-asserted for the
* combo PHY, the USB driver doesn't have to do this. Note: although
* SpacemiT refers to this as the global reset, we name the "phy" reset.
*
* In addition, we guarantee the APP_HOLD_PHY_RESET bit is clear for the
* combo PHY, so the USB driver doesn't have to manage that either. The
* PCIe driver is free to change this bit for normal operation.
*
* Calibration only needs to be done once. It's possible calibration has
* already completed (e.g., it might have happened in the boot loader, or
* -EPROBE_DEFER might result in this function being called again). So we
* check that early too, to avoid doing it more than once.
*
* Otherwise we temporarily power up the PHY using the PCIe app clocks
* and resets, wait for the hardware to indicate calibration is done,
* grab the value, then shut the PHY down again.
*/
static int k1_pcie_combo_phy_calibrate(struct k1_pcie_phy *k1_phy)
{
struct reset_control_bulk_data resets[] = {
{ .id = "dbi", },
{ .id = "mstr", },
{ .id = "slv", },
};
struct clk_bulk_data clocks[] = {
{ .id = "dbi", },
{ .id = "mstr", },
{ .id = "slv", },
};
struct device *dev = k1_phy->dev;
int ret = 0;
int val;
/* Nothing to do if we already set the receiver termination value */
if (k1_phy_rterm_valid())
return 0;
/*
* We also guarantee the APP_HOLD_PHY_RESET bit is clear. We can
* leave this bit clear even if an error happens below.
*/
regmap_assign_bits(k1_phy->pmu, PCIE_CLK_RES_CTRL,
PCIE_APP_HOLD_PHY_RST, false);
/* If the calibration already completed (e.g. by U-Boot), we're done */
val = readl(k1_phy->regs + PCIE_RCAL_RESULT);
if (val & R_TUNE_DONE)
goto out_tune_done;
/* Put the PHY into PCIe mode */
k1_combo_phy_sel(k1_phy, false);
/* Get and enable the PCIe app clocks */
ret = clk_bulk_get(dev, ARRAY_SIZE(clocks), clocks);
if (ret < 0)
goto out_tune_done;
ret = clk_bulk_prepare_enable(ARRAY_SIZE(clocks), clocks);
if (ret)
goto out_put_clocks;
/* Get the PCIe application resets (not the PHY reset) */
ret = reset_control_bulk_get_shared(dev, ARRAY_SIZE(resets), resets);
if (ret)
goto out_disable_clocks;
/* De-assert the PCIe application resets */
ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
if (ret)
goto out_put_resets;
/*
* This is the core activity here. Wait for the hardware to
* signal that it has completed calibration/tuning. Once it
* has, the register value will contain the values we'll
* use to configure PCIe PHYs.
*/
ret = readl_poll_timeout(k1_phy->regs + PCIE_RCAL_RESULT,
val, val & R_TUNE_DONE,
POLL_DELAY, CALIBRATION_TIMEOUT);
/* Clean up. We're done with the resets and clocks */
reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
out_put_resets:
reset_control_bulk_put(ARRAY_SIZE(resets), resets);
out_disable_clocks:
clk_bulk_disable_unprepare(ARRAY_SIZE(clocks), clocks);
out_put_clocks:
clk_bulk_put(ARRAY_SIZE(clocks), clocks);
out_tune_done:
/* If we got the value without timing out, set k1_phy_rterm */
if (!ret)
k1_phy_rterm_set(val);
return ret;
}
static struct phy *
k1_pcie_combo_phy_xlate(struct device *dev, const struct of_phandle_args *args)
{
struct k1_pcie_phy *k1_phy = dev_get_drvdata(dev);
u32 type;
/* The argument specifying the PHY mode is required */
if (args->args_count != 1)
return ERR_PTR(-EINVAL);
/* We only support PCIe and USB 3 mode */
type = args->args[0];
if (type != PHY_TYPE_PCIE && type != PHY_TYPE_USB3)
return ERR_PTR(-EINVAL);
/* This PHY can only be used once */
if (k1_phy->type != PHY_NONE)
return ERR_PTR(-EBUSY);
k1_phy->type = type;
return k1_phy->phy;
}
/* Use the maximum number of PCIe lanes unless limited by device tree */
static u32 k1_pcie_num_lanes(struct k1_pcie_phy *k1_phy, bool port_a)
{
struct device *dev = k1_phy->dev;
u32 count = 0;
u32 max;
int ret;
ret = of_property_read_u32(dev_of_node(dev), "num-lanes", &count);
if (count == 1)
return 1;
if (count == 2 && !port_a)
return 2;
max = port_a ? 1 : 2;
if (ret != -EINVAL)
dev_warn(dev, "bad lane count %u for port; using %u\n",
count, max);
return max;
}
static int k1_pcie_combo_phy_probe(struct k1_pcie_phy *k1_phy)
{
struct device *dev = k1_phy->dev;
struct regmap *regmap;
int ret;
/* Setting the PHY mode requires access to the PMU regmap */
regmap = syscon_regmap_lookup_by_phandle(dev_of_node(dev), SYSCON_APMU);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap), "failed to get PMU\n");
k1_phy->pmu = regmap;
ret = k1_pcie_combo_phy_calibrate(k1_phy);
if (ret)
return dev_err_probe(dev, ret, "calibration failed\n");
/* Needed by k1_pcie_combo_phy_xlate(), which also sets k1_phy->type */
dev_set_drvdata(dev, k1_phy);
return 0;
}
static int k1_pcie_phy_probe(struct platform_device *pdev)
{
struct phy *(*xlate)(struct device *dev,
const struct of_phandle_args *args);
struct device *dev = &pdev->dev;
struct reset_control *phy_reset;
struct phy_provider *provider;
struct k1_pcie_phy *k1_phy;
bool probing_port_a;
int ret;
xlate = of_device_get_match_data(dev);
probing_port_a = xlate == k1_pcie_combo_phy_xlate;
/* Only the combo PHY can calibrate, so it must probe first */
if (!k1_phy_rterm_valid() && !probing_port_a)
return -EPROBE_DEFER;
k1_phy = devm_kzalloc(dev, sizeof(*k1_phy), GFP_KERNEL);
if (!k1_phy)
return -ENOMEM;
k1_phy->dev = dev;
k1_phy->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(k1_phy->regs))
return dev_err_probe(dev, PTR_ERR(k1_phy->regs),
"error mapping registers\n");
/* De-assert the PHY (global) reset and leave it that way */
phy_reset = devm_reset_control_get_exclusive_deasserted(dev, "phy");
if (IS_ERR(phy_reset))
return PTR_ERR(phy_reset);
if (probing_port_a) {
ret = k1_pcie_combo_phy_probe(k1_phy);
if (ret)
return dev_err_probe(dev, ret,
"error probing combo phy\n");
}
k1_phy->pcie_lanes = k1_pcie_num_lanes(k1_phy, probing_port_a);
k1_phy->phy = devm_phy_create(dev, NULL, &k1_pcie_phy_ops);
if (IS_ERR(k1_phy->phy))
return dev_err_probe(dev, PTR_ERR(k1_phy->phy),
"error creating phy\n");
phy_set_drvdata(k1_phy->phy, k1_phy);
ret = k1_pcie_phy_pll_setup(k1_phy);
if (ret)
return dev_err_probe(dev, ret, "error initializing clock\n");
provider = devm_of_phy_provider_register(dev, xlate);
if (IS_ERR(provider))
return dev_err_probe(dev, PTR_ERR(provider),
"error registering provider\n");
return 0;
}
static const struct of_device_id k1_pcie_phy_of_match[] = {
{ .compatible = "spacemit,k1-combo-phy", k1_pcie_combo_phy_xlate, },
{ .compatible = "spacemit,k1-pcie-phy", of_phy_simple_xlate, },
{ },
};
MODULE_DEVICE_TABLE(of, k1_pcie_phy_of_match);
static struct platform_driver k1_pcie_phy_driver = {
.probe = k1_pcie_phy_probe,
.driver = {
.of_match_table = k1_pcie_phy_of_match,
.name = "spacemit-k1-pcie-phy",
}
};
module_platform_driver(k1_pcie_phy_driver);
MODULE_DESCRIPTION("SpacemiT K1 PCIe and USB 3 PHY driver");
MODULE_LICENSE("GPL");

View file

@ -26,13 +26,15 @@
#include "phy-qcom-qmp-qserdes-com-v4.h"
#include "phy-qcom-qmp-qserdes-com-v6.h"
#include "phy-qcom-qmp-qserdes-dp-com-v8.h"
/* EDP_PHY registers */
#define DP_PHY_CFG 0x0010
#define DP_PHY_CFG_1 0x0014
#define DP_PHY_PD_CTL 0x001c
#define DP_PHY_MODE 0x0020
#define DP_AUX_CFG_SIZE 10
#define DP_AUX_CFG_SIZE 13
#define DP_PHY_AUX_CFG(n) (0x24 + (0x04 * (n)))
#define DP_PHY_AUX_INTERRUPT_MASK 0x0058
@ -76,6 +78,7 @@ struct phy_ver_ops {
int (*com_power_on)(const struct qcom_edp *edp);
int (*com_resetsm_cntrl)(const struct qcom_edp *edp);
int (*com_bias_en_clkbuflr)(const struct qcom_edp *edp);
int (*com_clk_fwd_cfg)(const struct qcom_edp *edp);
int (*com_configure_pll)(const struct qcom_edp *edp);
int (*com_configure_ssc)(const struct qcom_edp *edp);
};
@ -83,6 +86,7 @@ struct phy_ver_ops {
struct qcom_edp_phy_cfg {
bool is_edp;
const u8 *aux_cfg;
const u8 *vco_div_cfg;
const struct qcom_edp_swing_pre_emph_cfg *swing_pre_emph_cfg;
const struct phy_ver_ops *ver_ops;
};
@ -103,7 +107,9 @@ struct qcom_edp {
struct phy_configure_opts_dp dp_opts;
struct clk_bulk_data clks[2];
struct clk_bulk_data *clks;
int num_clks;
struct regulator_bulk_data supplies[2];
bool is_edp;
@ -179,8 +185,12 @@ static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg = {
.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3,
};
static const u8 edp_phy_aux_cfg_v4[10] = {
0x00, 0x13, 0x24, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
static const u8 edp_phy_aux_cfg_v4[DP_AUX_CFG_SIZE] = {
0x00, 0x13, 0x24, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03, 0x02, 0x02, 0x00,
};
static const u8 edp_phy_vco_div_cfg_v4[4] = {
0x01, 0x01, 0x02, 0x00,
};
static const u8 edp_pre_emp_hbr_rbr_v5[4][4] = {
@ -204,8 +214,16 @@ static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v5 =
.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3_v5,
};
static const u8 edp_phy_aux_cfg_v5[10] = {
0x00, 0x13, 0xa4, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
static const u8 edp_phy_aux_cfg_v5[DP_AUX_CFG_SIZE] = {
0x00, 0x13, 0xa4, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03, 0x02, 0x02, 0x00,
};
static const u8 edp_phy_aux_cfg_v8[DP_AUX_CFG_SIZE] = {
0x00, 0x00, 0xa0, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03, 0x02, 0x02, 0x04,
};
static const u8 edp_phy_vco_div_cfg_v8[4] = {
0x00, 0x00, 0x02, 0x01,
};
static int qcom_edp_phy_init(struct phy *phy)
@ -218,12 +236,16 @@ static int qcom_edp_phy_init(struct phy *phy)
if (ret)
return ret;
ret = clk_bulk_prepare_enable(ARRAY_SIZE(edp->clks), edp->clks);
ret = clk_bulk_prepare_enable(edp->num_clks, edp->clks);
if (ret)
goto out_disable_supplies;
memcpy(aux_cfg, edp->cfg->aux_cfg, sizeof(aux_cfg));
ret = edp->cfg->ver_ops->com_clk_fwd_cfg(edp);
if (ret)
return ret;
writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
edp->edp + DP_PHY_PD_CTL);
@ -343,22 +365,22 @@ static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel
switch (dp_opts->link_rate) {
case 1620:
vco_div = 0x1;
vco_div = edp->cfg->vco_div_cfg[0];
*pixel_freq = 1620000000UL / 2;
break;
case 2700:
vco_div = 0x1;
vco_div = edp->cfg->vco_div_cfg[1];
*pixel_freq = 2700000000UL / 2;
break;
case 5400:
vco_div = 0x2;
vco_div = edp->cfg->vco_div_cfg[2];
*pixel_freq = 5400000000UL / 4;
break;
case 8100:
vco_div = 0x0;
vco_div = edp->cfg->vco_div_cfg[3];
*pixel_freq = 8100000000UL / 6;
break;
@ -396,6 +418,11 @@ static int qcom_edp_phy_com_resetsm_cntrl_v4(const struct qcom_edp *edp)
val, val & BIT(0), 500, 10000);
}
static int qcom_edp_com_clk_fwd_cfg_v4(const struct qcom_edp *edp)
{
return 0;
}
static int qcom_edp_com_bias_en_clkbuflr_v4(const struct qcom_edp *edp)
{
/* Turn on BIAS current for PHY/PLL */
@ -528,6 +555,7 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v4 = {
.com_power_on = qcom_edp_phy_power_on_v4,
.com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v4,
.com_bias_en_clkbuflr = qcom_edp_com_bias_en_clkbuflr_v4,
.com_clk_fwd_cfg = qcom_edp_com_clk_fwd_cfg_v4,
.com_configure_pll = qcom_edp_com_configure_pll_v4,
.com_configure_ssc = qcom_edp_com_configure_ssc_v4,
};
@ -535,17 +563,20 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v4 = {
static const struct qcom_edp_phy_cfg sa8775p_dp_phy_cfg = {
.is_edp = false,
.aux_cfg = edp_phy_aux_cfg_v5,
.vco_div_cfg = edp_phy_vco_div_cfg_v4,
.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
.ver_ops = &qcom_edp_phy_ops_v4,
};
static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = {
.aux_cfg = edp_phy_aux_cfg_v4,
.vco_div_cfg = edp_phy_vco_div_cfg_v4,
.ver_ops = &qcom_edp_phy_ops_v4,
};
static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
.aux_cfg = edp_phy_aux_cfg_v4,
.vco_div_cfg = edp_phy_vco_div_cfg_v4,
.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
.ver_ops = &qcom_edp_phy_ops_v4,
};
@ -553,6 +584,7 @@ static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = {
.is_edp = true,
.aux_cfg = edp_phy_aux_cfg_v4,
.vco_div_cfg = edp_phy_vco_div_cfg_v4,
.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
.ver_ops = &qcom_edp_phy_ops_v4,
};
@ -726,16 +758,197 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v6 = {
.com_power_on = qcom_edp_phy_power_on_v6,
.com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v6,
.com_bias_en_clkbuflr = qcom_edp_com_bias_en_clkbuflr_v6,
.com_clk_fwd_cfg = qcom_edp_com_clk_fwd_cfg_v4,
.com_configure_pll = qcom_edp_com_configure_pll_v6,
.com_configure_ssc = qcom_edp_com_configure_ssc_v6,
};
static struct qcom_edp_phy_cfg x1e80100_phy_cfg = {
.aux_cfg = edp_phy_aux_cfg_v4,
.vco_div_cfg = edp_phy_vco_div_cfg_v4,
.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
.ver_ops = &qcom_edp_phy_ops_v6,
};
static int qcom_edp_com_configure_ssc_v8(const struct qcom_edp *edp)
{
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
u32 step1;
u32 step2;
switch (dp_opts->link_rate) {
case 1620:
case 2700:
case 8100:
step1 = 0x5b;
step2 = 0x02;
break;
case 5400:
step1 = 0x5b;
step2 = 0x02;
break;
default:
/* Other link rates aren't supported */
return -EINVAL;
}
writel(0x01, edp->pll + DP_QSERDES_V8_COM_SSC_EN_CENTER);
writel(0x00, edp->pll + DP_QSERDES_V8_COM_SSC_ADJ_PER1);
writel(0x6b, edp->pll + DP_QSERDES_V8_COM_SSC_PER1);
writel(0x02, edp->pll + DP_QSERDES_V8_COM_SSC_PER2);
writel(step1, edp->pll + DP_QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0);
writel(step2, edp->pll + DP_QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0);
return 0;
}
static int qcom_edp_com_configure_pll_v8(const struct qcom_edp *edp)
{
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
u32 div_frac_start2_mode0;
u32 div_frac_start3_mode0;
u32 dec_start_mode0;
u32 lock_cmp1_mode0;
u32 lock_cmp2_mode0;
u32 code1_mode0;
u32 code2_mode0;
u32 hsclk_sel;
switch (dp_opts->link_rate) {
case 1620:
hsclk_sel = 0x5;
dec_start_mode0 = 0x34;
div_frac_start2_mode0 = 0xc0;
div_frac_start3_mode0 = 0x0b;
lock_cmp1_mode0 = 0x37;
lock_cmp2_mode0 = 0x04;
code1_mode0 = 0x71;
code2_mode0 = 0x0c;
break;
case 2700:
hsclk_sel = 0x3;
dec_start_mode0 = 0x34;
div_frac_start2_mode0 = 0xc0;
div_frac_start3_mode0 = 0x0b;
lock_cmp1_mode0 = 0x07;
lock_cmp2_mode0 = 0x07;
code1_mode0 = 0x71;
code2_mode0 = 0x0c;
break;
case 5400:
case 8100:
hsclk_sel = 0x2;
dec_start_mode0 = 0x4f;
div_frac_start2_mode0 = 0xa0;
div_frac_start3_mode0 = 0x01;
lock_cmp1_mode0 = 0x18;
lock_cmp2_mode0 = 0x15;
code1_mode0 = 0x14;
code2_mode0 = 0x25;
break;
default:
/* Other link rates aren't supported */
return -EINVAL;
}
writel(0x01, edp->pll + DP_QSERDES_V8_COM_SVS_MODE_CLK_SEL);
writel(0x3b, edp->pll + DP_QSERDES_V8_COM_SYSCLK_EN_SEL);
writel(0x02, edp->pll + DP_QSERDES_V8_COM_SYS_CLK_CTRL);
writel(0x0c, edp->pll + DP_QSERDES_V8_COM_CLK_ENABLE1);
writel(0x06, edp->pll + DP_QSERDES_V8_COM_SYSCLK_BUF_ENABLE);
writel(0x30, edp->pll + DP_QSERDES_V8_COM_CLK_SELECT);
writel(hsclk_sel, edp->pll + DP_QSERDES_V8_COM_HSCLK_SEL_1);
writel(0x07, edp->pll + DP_QSERDES_V8_COM_PLL_IVCO);
writel(0x00, edp->pll + DP_QSERDES_V8_COM_LOCK_CMP_EN);
writel(0x36, edp->pll + DP_QSERDES_V8_COM_PLL_CCTRL_MODE0);
writel(0x16, edp->pll + DP_QSERDES_V8_COM_PLL_RCTRL_MODE0);
writel(0x06, edp->pll + DP_QSERDES_V8_COM_CP_CTRL_MODE0);
writel(dec_start_mode0, edp->pll + DP_QSERDES_V8_COM_DEC_START_MODE0);
writel(0x00, edp->pll + DP_QSERDES_V8_COM_DIV_FRAC_START1_MODE0);
writel(div_frac_start2_mode0, edp->pll + DP_QSERDES_V8_COM_DIV_FRAC_START2_MODE0);
writel(div_frac_start3_mode0, edp->pll + DP_QSERDES_V8_COM_DIV_FRAC_START3_MODE0);
writel(0x96, edp->pll + DP_QSERDES_V8_COM_CMN_CONFIG_1);
writel(0x3f, edp->pll + DP_QSERDES_V8_COM_INTEGLOOP_GAIN0_MODE0);
writel(0x00, edp->pll + DP_QSERDES_V8_COM_INTEGLOOP_GAIN1_MODE0);
writel(0x00, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE_MAP);
writel(lock_cmp1_mode0, edp->pll + DP_QSERDES_V8_COM_LOCK_CMP1_MODE0);
writel(lock_cmp2_mode0, edp->pll + DP_QSERDES_V8_COM_LOCK_CMP2_MODE0);
writel(0x0a, edp->pll + DP_QSERDES_V8_COM_BG_TIMER);
writel(0x0a, edp->pll + DP_QSERDES_V8_COM_CORECLK_DIV_MODE0);
writel(0x00, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE_CTRL);
writel(0x1f, edp->pll + DP_QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN);
writel(0x00, edp->pll + DP_QSERDES_V8_COM_CORE_CLK_EN);
writel(0xa0, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE1_MODE0);
writel(0x01, edp->pll + DP_QSERDES_V8_COM_VCO_TUNE2_MODE0);
writel(code1_mode0, edp->pll + DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0);
writel(code2_mode0, edp->pll + DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0);
return 0;
}
static int qcom_edp_phy_com_resetsm_cntrl_v8(const struct qcom_edp *edp)
{
u32 val;
writel(0x20, edp->pll + DP_QSERDES_V8_COM_RESETSM_CNTRL);
return readl_poll_timeout(edp->pll + DP_QSERDES_V8_COM_C_READY_STATUS,
val, val & BIT(0), 500, 10000);
}
static int qcom_edp_com_clk_fwd_cfg_v8(const struct qcom_edp *edp)
{
writel(0x3f, edp->pll + DP_QSERDES_V8_COM_CLK_FWD_CONFIG_1);
return 0;
}
static int qcom_edp_com_bias_en_clkbuflr_v8(const struct qcom_edp *edp)
{
/* Turn on BIAS current for PHY/PLL */
writel(0x1f, edp->pll + DP_QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN);
return 0;
}
static int qcom_edp_phy_power_on_v8(const struct qcom_edp *edp)
{
u32 val;
writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
edp->edp + DP_PHY_PD_CTL);
writel(0xfc, edp->edp + DP_PHY_MODE);
return readl_poll_timeout(edp->pll + DP_QSERDES_V8_COM_CMN_STATUS,
val, val & BIT(7), 5, 200);
}
static const struct phy_ver_ops qcom_edp_phy_ops_v8 = {
.com_power_on = qcom_edp_phy_power_on_v8,
.com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v8,
.com_bias_en_clkbuflr = qcom_edp_com_bias_en_clkbuflr_v8,
.com_clk_fwd_cfg = qcom_edp_com_clk_fwd_cfg_v8,
.com_configure_pll = qcom_edp_com_configure_pll_v8,
.com_configure_ssc = qcom_edp_com_configure_ssc_v8,
};
static struct qcom_edp_phy_cfg glymur_phy_cfg = {
.aux_cfg = edp_phy_aux_cfg_v8,
.vco_div_cfg = edp_phy_vco_div_cfg_v8,
.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
.ver_ops = &qcom_edp_phy_ops_v8,
};
static int qcom_edp_phy_power_on(struct phy *phy)
{
const struct qcom_edp *edp = phy_get_drvdata(phy);
@ -885,7 +1098,7 @@ static int qcom_edp_phy_exit(struct phy *phy)
{
struct qcom_edp *edp = phy_get_drvdata(phy);
clk_bulk_disable_unprepare(ARRAY_SIZE(edp->clks), edp->clks);
clk_bulk_disable_unprepare(edp->num_clks, edp->clks);
regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
return 0;
@ -1092,11 +1305,9 @@ static int qcom_edp_phy_probe(struct platform_device *pdev)
if (IS_ERR(edp->pll))
return PTR_ERR(edp->pll);
edp->clks[0].id = "aux";
edp->clks[1].id = "cfg_ahb";
ret = devm_clk_bulk_get(dev, ARRAY_SIZE(edp->clks), edp->clks);
if (ret)
return ret;
edp->num_clks = devm_clk_bulk_get_all(dev, &edp->clks);
if (edp->num_clks < 0)
return dev_err_probe(dev, edp->num_clks, "failed to get clocks\n");
edp->supplies[0].supply = "vdda-phy";
edp->supplies[1].supply = "vdda-pll";
@ -1133,6 +1344,7 @@ static int qcom_edp_phy_probe(struct platform_device *pdev)
}
static const struct of_device_id qcom_edp_phy_match_table[] = {
{ .compatible = "qcom,glymur-dp-phy", .data = &glymur_phy_cfg, },
{ .compatible = "qcom,sa8775p-edp-phy", .data = &sa8775p_dp_phy_cfg, },
{ .compatible = "qcom,sc7280-edp-phy", .data = &sc7280_dp_phy_cfg, },
{ .compatible = "qcom,sc8180x-edp-phy", .data = &sc7280_dp_phy_cfg, },

View file

@ -37,6 +37,17 @@
#define EUSB2_TUNE_EUSB_EQU 0x5A
#define EUSB2_TUNE_EUSB_HS_COMP_CUR 0x5B
static const int squelch_detector[] = {
[0] = -6000,
[1] = -5000,
[2] = -4000,
[3] = -3000,
[4] = -2000,
[5] = -1000,
[6] = 0,
[7] = 1000,
};
struct eusb2_repeater_init_tbl_reg {
unsigned int reg;
unsigned int value;
@ -75,6 +86,13 @@ static const struct eusb2_repeater_init_tbl_reg smb2360_init_tbl[] = {
{ EUSB2_TUNE_USB2_PREEM, 0x2 },
};
static const struct eusb2_repeater_init_tbl_reg smb2370_init_tbl[] = {
{ EUSB2_TUNE_IUSB2, 0x4 },
{ EUSB2_TUNE_SQUELCH_U, 0x3 },
{ EUSB2_TUNE_USB2_SLEW, 0x7 },
{ EUSB2_TUNE_USB2_PREEM, 0x0 },
};
static const struct eusb2_repeater_cfg pm8550b_eusb2_cfg = {
.init_tbl = pm8550b_init_tbl,
.init_tbl_num = ARRAY_SIZE(pm8550b_init_tbl),
@ -97,6 +115,13 @@ static const struct eusb2_repeater_cfg smb2360_eusb2_cfg = {
.num_vregs = ARRAY_SIZE(pm8550b_vreg_l),
};
static const struct eusb2_repeater_cfg smb2370_eusb2_cfg = {
.init_tbl = smb2370_init_tbl,
.init_tbl_num = ARRAY_SIZE(smb2370_init_tbl),
.vreg_list = pm8550b_vreg_l,
.num_vregs = ARRAY_SIZE(pm8550b_vreg_l),
};
static int eusb2_repeater_init_vregs(struct eusb2_repeater *rptr)
{
int num = rptr->cfg->num_vregs;
@ -120,7 +145,9 @@ static int eusb2_repeater_init(struct phy *phy)
struct regmap *regmap = rptr->regmap;
u32 base = rptr->base;
u32 poll_val;
s32 dt_val;
int ret;
int i;
u8 val;
ret = regulator_bulk_enable(rptr->cfg->num_vregs, rptr->vregs);
@ -147,6 +174,15 @@ static int eusb2_repeater_init(struct phy *phy)
if (!of_property_read_u8(np, "qcom,tune-res-fsdif", &val))
regmap_write(regmap, base + EUSB2_TUNE_RES_FSDIF, val);
if (!of_property_read_s32(np, "qcom,squelch-detector-bp", &dt_val)) {
for (i = 0; i < ARRAY_SIZE(squelch_detector); i++) {
if (squelch_detector[i] == dt_val) {
regmap_write(regmap, base + EUSB2_TUNE_SQUELCH_U, i);
break;
}
}
}
/* Wait for status OK */
ret = regmap_read_poll_timeout(regmap, base + EUSB2_RPTR_STATUS, poll_val,
poll_val & RPTR_OK, 10, 5);
@ -278,6 +314,10 @@ static const struct of_device_id eusb2_repeater_of_match_table[] = {
.compatible = "qcom,smb2360-eusb2-repeater",
.data = &smb2360_eusb2_cfg,
},
{
.compatible = "qcom,smb2370-eusb2-repeater",
.data = &smb2370_eusb2_cfg,
},
{ },
};
MODULE_DEVICE_TABLE(of, eusb2_repeater_of_match_table);

View file

@ -30,7 +30,12 @@
#include "phy-qcom-qmp-common.h"
#include "phy-qcom-qmp.h"
#include "phy-qcom-qmp-pcs-aon-v6.h"
#include "phy-qcom-qmp-pcs-aon-v8.h"
#include "phy-qcom-qmp-pcs-misc-v3.h"
#include "phy-qcom-qmp-pcs-misc-v4.h"
#include "phy-qcom-qmp-pcs-misc-v5.h"
#include "phy-qcom-qmp-pcs-misc-v8.h"
#include "phy-qcom-qmp-pcs-usb-v4.h"
#include "phy-qcom-qmp-pcs-usb-v5.h"
#include "phy-qcom-qmp-pcs-usb-v6.h"
@ -43,6 +48,9 @@
#include "phy-qcom-qmp-dp-phy-v4.h"
#include "phy-qcom-qmp-dp-phy-v5.h"
#include "phy-qcom-qmp-dp-phy-v6.h"
#include "phy-qcom-qmp-dp-phy-v8.h"
#include "phy-qcom-qmp-usb43-pcs-v8.h"
/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
/* DP PHY soft reset */
@ -61,6 +69,7 @@
/* QPHY_V3_DP_COM_TYPEC_CTRL register bits */
#define SW_PORTSELECT_VAL BIT(0)
#define SW_PORTSELECT_MUX BIT(1)
#define INVERT_CC_POLARITY BIT(2)
#define PHY_INIT_COMPLETE_TIMEOUT 10000
@ -79,6 +88,7 @@ enum qphy_reg_layout {
QPHY_PCS_AUTONOMOUS_MODE_CTRL,
QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR,
QPHY_PCS_POWER_DOWN_CONTROL,
QPHY_PCS_CLAMP_ENABLE,
QPHY_COM_RESETSM_CNTRL,
QPHY_COM_C_READY_STATUS,
@ -94,6 +104,8 @@ enum qphy_reg_layout {
QPHY_TX_HIGHZ_DRVR_EN,
QPHY_TX_TRANSCEIVER_BIAS_EN,
QPHY_AON_TOGGLE_ENABLE,
QPHY_DP_AON_TOGGLE_ENABLE,
/* Keep last to ensure regs_layout arrays are properly initialized */
QPHY_LAYOUT_SIZE
};
@ -106,6 +118,8 @@ static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V3_PCS_AUTONOMOUS_MODE_CTRL,
[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V3_PCS_LFPS_RXTERM_IRQ_CLEAR,
[QPHY_PCS_CLAMP_ENABLE] = QPHY_V3_PCS_MISC_CLAMP_ENABLE,
[QPHY_COM_RESETSM_CNTRL] = QSERDES_V3_COM_RESETSM_CNTRL,
[QPHY_COM_C_READY_STATUS] = QSERDES_V3_COM_C_READY_STATUS,
[QPHY_COM_CMN_STATUS] = QSERDES_V3_COM_CMN_STATUS,
@ -131,6 +145,8 @@ static const unsigned int qmp_v45_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL,
[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR,
[QPHY_PCS_CLAMP_ENABLE] = QPHY_V4_PCS_MISC_CLAMP_ENABLE,
[QPHY_COM_RESETSM_CNTRL] = QSERDES_V4_COM_RESETSM_CNTRL,
[QPHY_COM_C_READY_STATUS] = QSERDES_V4_COM_C_READY_STATUS,
[QPHY_COM_CMN_STATUS] = QSERDES_V4_COM_CMN_STATUS,
@ -156,6 +172,8 @@ static const unsigned int qmp_v5_5nm_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V5_PCS_USB3_AUTONOMOUS_MODE_CTRL,
[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V5_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR,
[QPHY_PCS_CLAMP_ENABLE] = QPHY_V5_PCS_MISC_CLAMP_ENABLE,
[QPHY_COM_RESETSM_CNTRL] = QSERDES_V5_COM_RESETSM_CNTRL,
[QPHY_COM_C_READY_STATUS] = QSERDES_V5_COM_C_READY_STATUS,
[QPHY_COM_CMN_STATUS] = QSERDES_V5_COM_CMN_STATUS,
@ -181,6 +199,8 @@ static const unsigned int qmp_v6_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V6_PCS_USB3_AUTONOMOUS_MODE_CTRL,
[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V6_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR,
[QPHY_PCS_CLAMP_ENABLE] = QPHY_V6_PCS_AON_CLAMP_ENABLE,
[QPHY_COM_RESETSM_CNTRL] = QSERDES_V6_COM_RESETSM_CNTRL,
[QPHY_COM_C_READY_STATUS] = QSERDES_V6_COM_C_READY_STATUS,
[QPHY_COM_CMN_STATUS] = QSERDES_V6_COM_CMN_STATUS,
@ -206,6 +226,8 @@ static const unsigned int qmp_v6_n4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V6_PCS_USB3_AUTONOMOUS_MODE_CTRL,
[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V6_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR,
[QPHY_PCS_CLAMP_ENABLE] = QPHY_V6_PCS_AON_CLAMP_ENABLE,
[QPHY_COM_RESETSM_CNTRL] = QSERDES_V6_COM_RESETSM_CNTRL,
[QPHY_COM_C_READY_STATUS] = QSERDES_V6_COM_C_READY_STATUS,
[QPHY_COM_CMN_STATUS] = QSERDES_V6_COM_CMN_STATUS,
@ -246,6 +268,237 @@ static const unsigned int qmp_v8_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_TX_TRANSCEIVER_BIAS_EN] = QSERDES_V8_TX_TRANSCEIVER_BIAS_EN,
};
static const unsigned int qmp_v8_n3_usb43dpphy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_SW_RESET] = QPHY_V8_USB43_PCS_SW_RESET,
[QPHY_START_CTRL] = QPHY_V8_USB43_PCS_START_CONTROL,
[QPHY_PCS_STATUS] = QPHY_V8_USB43_PCS_PCS_STATUS1,
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V8_USB43_PCS_POWER_DOWN_CONTROL,
/* In PCS_USB */
[QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V8_PCS_USB_AUTONOMOUS_MODE_CTRL,
[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V8_PCS_USB_LFPS_RXTERM_IRQ_CLEAR,
[QPHY_PCS_CLAMP_ENABLE] = QPHY_V8_PCS_AON_USB3_AON_CLAMP_ENABLE,
[QPHY_AON_TOGGLE_ENABLE] = QPHY_V8_PCS_AON_USB3_AON_TOGGLE_ENABLE,
[QPHY_DP_AON_TOGGLE_ENABLE] = QPHY_V8_PCS_AON_DP_AON_TOGGLE_ENABLE,
[QPHY_COM_RESETSM_CNTRL] = QSERDES_V8_COM_RESETSM_CNTRL,
[QPHY_COM_C_READY_STATUS] = QSERDES_V8_COM_C_READY_STATUS,
[QPHY_COM_CMN_STATUS] = QSERDES_V8_COM_CMN_STATUS,
[QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN,
[QPHY_DP_PHY_STATUS] = QSERDES_V8_DP_PHY_STATUS,
[QPHY_DP_PHY_VCO_DIV] = QSERDES_V8_DP_PHY_VCO_DIV,
[QPHY_TX_TX_DRV_LVL] = QSERDES_V8_LALB_TX0_DRV_LVL,
[QPHY_TX_TX_EMP_POST1_LVL] = QSERDES_V8_LALB_TX0_EMP_POST1_LVL,
[QPHY_TX_HIGHZ_DRVR_EN] = QSERDES_V8_LALB_HIGHZ_DRVR_EN,
[QPHY_TX_TRANSCEIVER_BIAS_EN] = QSERDES_V8_LALB_TRANSMITTER_EN_CTRL,
};
static const struct qmp_phy_init_tbl glymur_usb43dp_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE1, 0xe1),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CP_CTRL_MODE1, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE1, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORECLK_DIV_MODE1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE1, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE1, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE1, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MSB_MODE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE1, 0xab),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE1, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x13),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE1, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE1_MODE1, 0x4d),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE1, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x95),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x4b),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0xe1),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORECLK_DIV_MODE0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MSB_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE0, 0xab),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE1_MODE0, 0x4d),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BG_TIMER, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_EN_CENTER, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_PER1, 0x62),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_PER2, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_BUF_ENABLE, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_IVCO, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_IVCO_MODE1, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP_EN, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP_CFG, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_CTRL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_MAP, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORE_CLK_EN, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x76),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SVS_MODE_CLK_SEL, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_SPARE_FOR_ECO, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DCC_CAL_1, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DCC_CAL_2, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DCC_CAL_3, 0x60),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PSM_CAL_EN, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x33),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xaf),
};
static const struct qmp_phy_init_tbl glymur_usb43dp_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V8_PCS_MISC_PCS_MISC_CONFIG1, 0x01),
};
static const struct qmp_phy_init_tbl glymur_usb43dp_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_LOCK_DETECT_CONFIG1, 0xc4),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_LOCK_DETECT_CONFIG2, 0x89),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_LOCK_DETECT_CONFIG3, 0x20),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_LOCK_DETECT_CONFIG6, 0x13),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_REFGEN_REQ_CONFIG1, 0x21),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_RX_SIGDET_LVL, 0x55),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_TSYNC_RSYNC_TIME, 0xa4),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_RX_CONFIG, 0x0a),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_TSYNC_DLY_TIME, 0x04),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_ALIGN_DETECT_CONFIG1, 0xd4),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_ALIGN_DETECT_CONFIG2, 0x30),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_PCS_TX_RX_CONFIG, 0x0c),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_EQ_CONFIG1, 0x4b),
QMP_PHY_INIT_CFG(QPHY_V8_USB43_PCS_EQ_CONFIG5, 0x10),
};
static const struct qmp_phy_init_tbl glymur_usb43dp_pcs_usb_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_RXEQTRAINING_DFE_TIME_S2, 0x07),
};
static const struct qmp_phy_init_tbl glymur_usb43dp_lalb_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CLKBUF_ENABLE, 0x81),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_LVL_UPDATE_CTRL, 0x0d),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL3, 0x80),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL4, 0x8D),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRANSMITTER_EN_CTRL, 0x13),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_1, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_3, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_4, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_CAL_CTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_RESTRIM_CAL_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_POST_CAL_OFFSET, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_VREF_SEL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_RESTRIM_VREF_SEL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_ANA_INTERFACE_SELECT2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCS_INTERFACE_SELECT1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE_0_1_B0, 0xa4),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE_0_1_B1, 0xa2),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE_0_1_B2, 0x6e),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE_0_1_B3, 0x51),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE_0_1_B4, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE_0_1_B5, 0x26),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE_0_1_B6, 0x12),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE_0_1_B7, 0x2a),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B0, 0x4c),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B1, 0xc4),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B2, 0x38),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B3, 0x64),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B4, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B5, 0x4b),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B6, 0x12),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_MODE_RATE2_B7, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_DCC_ANA_CTRL2, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT1_RATE1, 0x26),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT2_RATE1, 0x26),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT1_RATE2, 0x26),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT2_RATE2, 0x26),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_INIT_RATE_0_1, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_INIT_RATE_2_3, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_CODE_OVRD_RATE1, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_CODE_OVRD_RATE2, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF1_RATE1, 0x15),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF2_RATE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF1_RATE2, 0x22),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF2_RATE2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CODE_OVRD_RATE_2_3, 0x22),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND1_RATE1, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND2_RATE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND1_RATE2, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND2_RATE2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_LOWER_FREQ_DIFF_BND_RATE1, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_KP_CAL_LOWER_FREQ_DIFF_BND_RATE2, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_SUMMER_CAL_SPD_MODE_RATE_0123, 0x2f),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_IVCM_CAL_CODE_OVERRIDE_RATE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_IVCM_CAL_CODE_OVERRIDE_RATE2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_IVCM_CAL_CTRL2, 0x85),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_IVCM_CAL_CTRL3, 0x45),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_IVCM_POSTCAL_OFFSET_RATE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_IVCM_POSTCAL_OFFSET_RATE2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_SIGDET_ENABLES, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_SIGDET_CNTRL, 0xa3),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_SIGDET_LVL, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_SIGDET_DEGLITCH_CNTRL, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_SIGDET_CAL_CTRL1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_SIGDET_CAL_CTRL2_AND_CDR_LOCK_EDGE, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_SIGDET_CAL_TRIM, 0x66),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_FREQ_LOCK_DET_DLY_RATE1, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_FREQ_LOCK_DET_DLY_RATE2, 0x32),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_CP_CUR_FLL_RATE1, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_CP_CUR_FLL_RATE2, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_CP_CUR_PLL_RATE1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_CP_CUR_PLL_RATE2, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_CCODE_RATE_01, 0x76),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_CCODE_RATE_23, 0x67),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_FAST_RATE_0_1, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_FAST_RATE_2_3, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_FLL_RATE_0_1, 0x33),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_FLL_RATE_2_3, 0x43),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_PLL_RATE_0_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_RCODE_PLL_RATE_2_3, 0x51),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_FLL_DIV_RATIO_RATE_0123, 0xe5),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_CAP_CODE_RATE_0123, 0xf5),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_TYPE_CONFIG, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_EN_LOWFREQ, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_LOOP_FUNC_CTRL, 0xd0),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_GM_CAL_EN, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_GM_CAL_RES_RATE0_1, 0x88),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_GM_CAL_RES_RATE2_3, 0x88),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_AUX_CLK_CTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_EOM_CTRL1, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_EQU_ADAPTOR_CNTRL2, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_EQU_ADAPTOR_CNTRL3, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RX_EQU_ADAPTOR_CNTRL4, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CTLE_POST_CAL_OFFSET_RATE_0_1_2, 0x77),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_VGA_CAL_CNTRL1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_VGA_CAL_MAN_VAL_RATE0_1, 0xdd),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_VGA_CAL_MAN_VAL_RATE2_3, 0xd8),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_DFE_TAP1_DAC_ENABLE, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_DFE_TAP2_DAC_ENABLE, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_DFE_TAP345_DAC_ENABLE, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_DFE_TAP67_DAC_ENABLE, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_IQTUNE_CTRL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_IQTUNE_MAN_INDEX, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_IQTUNE_DIV2_CTRL_RATE0123, 0x1C),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CDR_VCO_CAP_CODE_OVRD_MUXES, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_DIG_BKUP_CTRL16, 0x37),
};
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),
@ -1132,6 +1385,38 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0x0f),
};
static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE1, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORECLK_DIV_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BG_TIMER, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_EN_CENTER, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_ADJ_PER1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_PER1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_PER2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_ENABLE1, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYS_CLK_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_BUF_ENABLE, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_IVCO, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x3b),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP_EN, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_CTRL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_MAP, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_SELECT, 0x30),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORE_CLK_EN, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x56),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SVS_MODE_CLK_SEL, 0x15),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD1, 0x24),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DCC_CAL_1, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DCC_CAL_3, 0x60),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PSM_CAL_EN, 0x01),
};
static const struct qmp_phy_init_tbl qmp_v6_dp_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_TX_VMODE_CTRL1, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V6_TX_PRE_STALL_LDO_BOOST_EN, 0x30),
@ -1159,6 +1444,33 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_N4_TX_TX_BAND, 0x1),
};
static const struct qmp_phy_init_tbl qmp_v8_n3p_dp_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRANSMITTER_EN_CTRL, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_VMODE_CTRL1, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_ANA_INTERFACE_SELECT1, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_ANA_INTERFACE_SELECT2, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_PCS_INTERFACE_SELECT1, 0x50),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_1, 0x0d),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_CLKBUF_ENABLE, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_LVL_UPDATE_CTRL, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TRAN_DRVR_EMP_EN, 0x5f),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_EMP_POST1_LVL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_EMP_POST1_LVL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_PRE1_EMPH, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_PRE1_EMPH, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_DRV_LVL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_DRV_LVL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_HIGHZ_DRVR_EN, 0x30),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_2, 0x50),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_LANE_MODE_3, 0x51),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX_DCC_ANA_CTRL2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_CAL_CTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_RESTRIM_CAL_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX0_RESTRIM_POST_CAL_OFFSET, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V8_LALB_TX1_RESTRIM_POST_CAL_OFFSET, 0x10),
};
static const struct qmp_phy_init_tbl qmp_v6_dp_serdes_tbl_rbr[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x34),
@ -1275,6 +1587,109 @@ static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl_hbr3[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01),
};
static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_rbr[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x7a),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x83),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x37),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x54),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE1_MODE0, 0xfe),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x30),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xa4),
};
static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x21),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x46),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE1_MODE0, 0xae),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xa3),
};
static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr2[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xf6),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x0),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x46),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE1_MODE0, 0xae),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0xbf),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_RESETSM_CNTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x3f),
};
static const struct qmp_phy_init_tbl qmp_v8_dp_serdes_tbl_hbr3[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_HSCLK_SEL_1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x63),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0, 0x5b),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORECLK_DIV_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0, 0x17),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0, 0x15),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DEC_START_MODE0, 0x4f),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE1_MODE0, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_ADJ_PER1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_PER1, 0x6b),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SSC_PER2, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_ENABLE1, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYS_CLK_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_BUF_ENABLE, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_PLL_IVCO, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SYSCLK_EN_SEL, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_CTRL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_VCO_TUNE_MAP, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_SELECT, 0x30),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CORE_CLK_EN, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_SVS_MODE_CLK_SEL, 0x15),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1, 0x30),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD3, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_CMN_MODE_CONTD1, 0x24),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL, 0x84),
};
static const struct qmp_phy_init_tbl sc8280xp_usb43dp_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31),
@ -1649,6 +2064,12 @@ static struct regulator_bulk_data qmp_phy_vreg_l[] = {
{ .supply = "vdda-pll", .init_load_uA = 36000, },
};
static struct regulator_bulk_data qmp_phy_vreg_refgen[] = {
{ .supply = "vdda-phy", .init_load_uA = 21800 },
{ .supply = "vdda-pll", .init_load_uA = 36000 },
{ .supply = "refgen", .init_load_uA = 3270 },
};
static const u8 qmp_dp_v3_pre_emphasis_hbr3_hbr2[4][4] = {
{ 0x00, 0x0c, 0x15, 0x1a },
{ 0x02, 0x0e, 0x16, 0xff },
@ -1771,6 +2192,7 @@ struct qmp_combo_offsets {
u16 usb3_serdes;
u16 usb3_pcs_misc;
u16 usb3_pcs;
u16 usb3_pcs_aon;
u16 usb3_pcs_usb;
u16 dp_serdes;
u16 dp_txa;
@ -1792,6 +2214,8 @@ struct qmp_phy_cfg {
int pcs_tbl_num;
const struct qmp_phy_init_tbl *pcs_usb_tbl;
int pcs_usb_tbl_num;
const struct qmp_phy_init_tbl *pcs_misc_tbl;
int pcs_misc_tbl_num;
const struct qmp_phy_init_tbl *dp_serdes_tbl;
int dp_serdes_tbl_num;
@ -1815,6 +2239,7 @@ struct qmp_phy_cfg {
const u8 (*pre_emphasis_hbr3_hbr2)[4][4];
/* DP PHY callbacks */
int (*configure_dp_clocks)(struct qmp_combo *qmp);
int (*configure_dp_phy)(struct qmp_combo *qmp);
void (*configure_dp_tx)(struct qmp_combo *qmp);
int (*calibrate_dp_phy)(struct qmp_combo *qmp);
@ -1836,6 +2261,7 @@ struct qmp_phy_cfg {
/* Offset from PCS to PCS_USB region */
unsigned int pcs_usb_offset;
bool invert_cc_polarity;
};
struct qmp_combo {
@ -1852,6 +2278,7 @@ struct qmp_combo {
void __iomem *tx2;
void __iomem *rx2;
void __iomem *pcs_misc;
void __iomem *pcs_aon;
void __iomem *pcs_usb;
void __iomem *dp_serdes;
@ -1891,6 +2318,7 @@ struct qmp_combo {
static void qmp_v3_dp_aux_init(struct qmp_combo *qmp);
static void qmp_v3_configure_dp_tx(struct qmp_combo *qmp);
static int qmp_v3_configure_dp_clocks(struct qmp_combo *qmp);
static int qmp_v3_configure_dp_phy(struct qmp_combo *qmp);
static int qmp_v3_calibrate_dp_phy(struct qmp_combo *qmp);
@ -1899,6 +2327,10 @@ static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp);
static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp);
static int qmp_v4_calibrate_dp_phy(struct qmp_combo *qmp);
static void qmp_v8_dp_aux_init(struct qmp_combo *qmp);
static int qmp_v8_configure_dp_clocks(struct qmp_combo *qmp);
static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp);
static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
{
u32 reg;
@ -1976,6 +2408,7 @@ static const struct qmp_combo_offsets qmp_combo_offsets_v8 = {
.usb3_serdes = 0x1000,
.usb3_pcs_misc = 0x1c00,
.usb3_pcs = 0x1e00,
.usb3_pcs_aon = 0x2000,
.usb3_pcs_usb = 0x2100,
.dp_serdes = 0x3000,
.dp_txa = 0x3400,
@ -1983,6 +2416,19 @@ static const struct qmp_combo_offsets qmp_combo_offsets_v8 = {
.dp_dp_phy = 0x3c00,
};
static const struct qmp_combo_offsets qmp_combo_usb43dp_offsets_v8 = {
.com = 0x0000,
.usb3_pcs_aon = 0x0100,
.usb3_serdes = 0x1000,
.usb3_pcs_misc = 0x1400,
.usb3_pcs = 0x1600,
.usb3_pcs_usb = 0x1900,
.dp_serdes = 0x2000,
.dp_dp_phy = 0x2400,
.txa = 0x4000,
.txb = 0x5000,
};
static const struct qmp_phy_cfg sar2130p_usb3dpphy_cfg = {
.offsets = &qmp_combo_offsets_v3,
@ -2018,6 +2464,7 @@ static const struct qmp_phy_cfg sar2130p_usb3dpphy_cfg = {
.dp_aux_init = qmp_v4_dp_aux_init,
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
@ -2026,6 +2473,7 @@ static const struct qmp_phy_cfg sar2130p_usb3dpphy_cfg = {
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.invert_cc_polarity = true,
};
static const struct qmp_phy_cfg sc7180_usb3dpphy_cfg = {
@ -2153,6 +2601,7 @@ static const struct qmp_phy_cfg sc8180x_usb3dpphy_cfg = {
.dp_aux_init = qmp_v4_dp_aux_init,
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
@ -2199,6 +2648,7 @@ static const struct qmp_phy_cfg sc8280xp_usb43dpphy_cfg = {
.dp_aux_init = qmp_v4_dp_aux_init,
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
@ -2244,6 +2694,7 @@ static const struct qmp_phy_cfg x1e80100_usb3dpphy_cfg = {
.dp_aux_init = qmp_v4_dp_aux_init,
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
@ -2332,6 +2783,7 @@ static const struct qmp_phy_cfg sm8250_usb3dpphy_cfg = {
.dp_aux_init = qmp_v4_dp_aux_init,
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
@ -2380,6 +2832,7 @@ static const struct qmp_phy_cfg sm8350_usb3dpphy_cfg = {
.dp_aux_init = qmp_v4_dp_aux_init,
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
@ -2427,6 +2880,7 @@ static const struct qmp_phy_cfg sm8550_usb3dpphy_cfg = {
.dp_aux_init = qmp_v4_dp_aux_init,
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
@ -2472,6 +2926,7 @@ static const struct qmp_phy_cfg sm8650_usb3dpphy_cfg = {
.dp_aux_init = qmp_v4_dp_aux_init,
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
@ -2517,6 +2972,7 @@ static const struct qmp_phy_cfg sm8750_usb3dpphy_cfg = {
.dp_aux_init = qmp_v4_dp_aux_init,
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v3_configure_dp_clocks,
.configure_dp_phy = qmp_v4_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
@ -2527,6 +2983,52 @@ static const struct qmp_phy_cfg sm8750_usb3dpphy_cfg = {
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
};
static const struct qmp_phy_cfg glymur_usb3dpphy_cfg = {
.offsets = &qmp_combo_usb43dp_offsets_v8,
.serdes_tbl = glymur_usb43dp_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(glymur_usb43dp_serdes_tbl),
.tx_tbl = glymur_usb43dp_lalb_tbl,
.tx_tbl_num = ARRAY_SIZE(glymur_usb43dp_lalb_tbl),
.pcs_tbl = glymur_usb43dp_pcs_tbl,
.pcs_tbl_num = ARRAY_SIZE(glymur_usb43dp_pcs_tbl),
.pcs_usb_tbl = glymur_usb43dp_pcs_usb_tbl,
.pcs_usb_tbl_num = ARRAY_SIZE(glymur_usb43dp_pcs_usb_tbl),
.pcs_misc_tbl = glymur_usb43dp_pcs_misc_tbl,
.pcs_misc_tbl_num = ARRAY_SIZE(glymur_usb43dp_pcs_misc_tbl),
.dp_serdes_tbl = qmp_v8_dp_serdes_tbl,
.dp_serdes_tbl_num = ARRAY_SIZE(qmp_v8_dp_serdes_tbl),
.dp_tx_tbl = qmp_v8_n3p_dp_tx_tbl,
.dp_tx_tbl_num = ARRAY_SIZE(qmp_v8_n3p_dp_tx_tbl),
.serdes_tbl_rbr = qmp_v8_dp_serdes_tbl_rbr,
.serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v8_dp_serdes_tbl_rbr),
.serdes_tbl_hbr = qmp_v8_dp_serdes_tbl_hbr,
.serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v8_dp_serdes_tbl_hbr),
.serdes_tbl_hbr2 = qmp_v8_dp_serdes_tbl_hbr2,
.serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v8_dp_serdes_tbl_hbr2),
.serdes_tbl_hbr3 = qmp_v8_dp_serdes_tbl_hbr3,
.serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v8_dp_serdes_tbl_hbr3),
.swing_hbr_rbr = &qmp_dp_v6_voltage_swing_hbr_rbr,
.pre_emphasis_hbr_rbr = &qmp_dp_v6_pre_emphasis_hbr_rbr,
.swing_hbr3_hbr2 = &qmp_dp_v5_voltage_swing_hbr3_hbr2,
.pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2,
.dp_aux_init = qmp_v8_dp_aux_init,
.configure_dp_tx = qmp_v4_configure_dp_tx,
.configure_dp_clocks = qmp_v8_configure_dp_clocks,
.configure_dp_phy = qmp_v8_configure_dp_phy,
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
.regs = qmp_v8_n3_usb43dpphy_regs_layout,
.reset_list = msm8996_usb3phy_reset_l,
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
.vreg_list = qmp_phy_vreg_refgen,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_refgen),
};
static int qmp_combo_dp_serdes_init(struct qmp_combo *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@ -2689,7 +3191,7 @@ static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp)
return reverse;
}
static int qmp_combo_configure_dp_clocks(struct qmp_combo *qmp)
static int qmp_v3_configure_dp_clocks(struct qmp_combo *qmp)
{
const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
u32 phy_vco_div;
@ -2736,7 +3238,7 @@ static int qmp_v3_configure_dp_phy(struct qmp_combo *qmp)
writel(0x05, qmp->dp_dp_phy + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL);
writel(0x05, qmp->dp_dp_phy + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL);
ret = qmp_combo_configure_dp_clocks(qmp);
ret = qmp_v3_configure_dp_clocks(qmp);
if (ret)
return ret;
@ -2822,6 +3324,35 @@ static void qmp_v4_dp_aux_init(struct qmp_combo *qmp)
qmp->dp_dp_phy + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK);
}
static void qmp_v8_dp_aux_init(struct qmp_combo *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
/* Turn on BIAS current for PHY/PLL */
writel(0x1c, qmp->dp_serdes + cfg->regs[QPHY_COM_BIAS_EN_CLKBUFLR_EN]);
writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG0);
writel(0x13, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG1);
writel(0x06, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG2);
writel(0x00, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG3);
writel(0x0a, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG4);
writel(0x26, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG5);
writel(0x0a, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG6);
writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG7);
writel(0xb7, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG8);
writel(0x03, qmp->dp_dp_phy + QSERDES_DP_PHY_AUX_CFG9);
qmp->dp_aux_cfg = 0;
writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
PHY_AUX_REQ_ERR_MASK,
qmp->dp_dp_phy + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK);
}
static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@ -2836,6 +3367,58 @@ static void qmp_v4_configure_dp_tx(struct qmp_combo *qmp)
qmp_combo_configure_dp_swing(qmp);
}
static int qmp_v8_configure_dp_clocks(struct qmp_combo *qmp)
{
const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
u32 phy_vco_div;
unsigned long pixel_freq;
const struct qmp_phy_cfg *cfg = qmp->cfg;
switch (dp_opts->link_rate) {
case 1620:
phy_vco_div = 0x4;
pixel_freq = 1620000000UL / 2;
break;
case 2700:
phy_vco_div = 0x2;
pixel_freq = 2700000000UL / 2;
break;
case 5400:
phy_vco_div = 0x4;
pixel_freq = 5400000000UL / 4;
break;
case 8100:
phy_vco_div = 0x3;
pixel_freq = 8100000000UL / 6;
break;
default:
/* Other link rates aren't supported */
return -EINVAL;
}
writel(phy_vco_div, qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_VCO_DIV]);
/* disable core reset tsync */
writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG);
writel(0x04, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SETUP_CYC);
writel(0x08, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_SILENCE_CYC);
writel(0x08, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_CYC);
writel(0x11, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD);
writel(0x3e, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TSYNC_OVRD);
writel(0x05, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TX2_TX3_LANE_CTL);
writel(0x05, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_TX0_TX1_LANE_CTL);
writel(0x01, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_AUXLESS_CFG1);
writel(0x11, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LFPS_PERIOD);
writel(0x1f, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LN0_DRV_LVL);
writel(0x1f, qmp->dp_dp_phy + QSERDES_V8_DP_PHY_LN1_DRV_LVL);
clk_set_rate(qmp->dp_link_hw.clk, dp_opts->link_rate * 100000);
clk_set_rate(qmp->dp_pixel_hw.clk, pixel_freq);
return 0;
}
static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@ -2852,7 +3435,7 @@ static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp)
writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL);
writel(0x05, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL);
ret = qmp_combo_configure_dp_clocks(qmp);
ret = qmp->cfg->configure_dp_clocks(qmp);
if (ret)
return ret;
@ -2966,6 +3549,62 @@ static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp)
return 0;
}
static int qmp_v8_configure_dp_phy(struct qmp_combo *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE);
const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
u32 status;
int ret;
ret = qmp_v456_configure_dp_phy(qmp);
if (ret < 0)
return ret;
if (dp_opts->lanes == 1) {
bias0_en = reverse ? 0x3e : 0x15;
bias1_en = reverse ? 0x15 : 0x3e;
drvr0_en = reverse ? 0x13 : 0x10;
drvr1_en = reverse ? 0x10 : 0x13;
} else if (dp_opts->lanes == 2) {
bias0_en = reverse ? 0x3f : 0x15;
bias1_en = reverse ? 0x15 : 0x3f;
drvr0_en = 0x10;
drvr1_en = 0x10;
} else {
bias0_en = 0x3f;
bias1_en = 0x3f;
drvr0_en = 0x34;
drvr1_en = 0x34;
}
writel(drvr0_en, qmp->dp_tx + cfg->regs[QPHY_TX_HIGHZ_DRVR_EN]);
writel(bias0_en, qmp->dp_tx + cfg->regs[QPHY_TX_TRANSCEIVER_BIAS_EN]);
writel(drvr1_en, qmp->dp_tx2 + cfg->regs[QPHY_TX_HIGHZ_DRVR_EN]);
writel(bias1_en, qmp->dp_tx2 + cfg->regs[QPHY_TX_TRANSCEIVER_BIAS_EN]);
writel(0x08, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG);
udelay(100);
writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG);
udelay(500);
if (readl_poll_timeout(qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_STATUS],
status,
((status & BIT(1)) > 0),
500,
10000))
return -ETIMEDOUT;
writel(0x00, qmp->dp_tx + cfg->regs[QPHY_TX_TX_DRV_LVL]);
writel(0x00, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_DRV_LVL]);
writel(0x2b, qmp->dp_tx + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]);
writel(0x2b, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]);
return 0;
}
/*
* We need to calibrate the aux setting here as many times
* as the caller tries
@ -3023,6 +3662,7 @@ static int qmp_combo_com_init(struct qmp_combo *qmp, bool force)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
void __iomem *com = qmp->com;
void __iomem *pcs_aon = qmp->pcs_aon;
int ret;
u32 val;
@ -3058,10 +3698,20 @@ static int qmp_combo_com_init(struct qmp_combo *qmp, bool force)
SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
/* override hardware control for reset of qmp phy */
if (pcs_aon && cfg->regs[QPHY_AON_TOGGLE_ENABLE]) {
qphy_clrbits(pcs_aon, cfg->regs[QPHY_AON_TOGGLE_ENABLE], 0x1);
qphy_clrbits(pcs_aon, cfg->regs[QPHY_DP_AON_TOGGLE_ENABLE], 0x1);
}
/* Use software based port select and switch on typec orientation */
val = SW_PORTSELECT_MUX;
if (qmp->orientation == TYPEC_ORIENTATION_REVERSE)
val |= SW_PORTSELECT_VAL;
if (cfg->invert_cc_polarity)
val |= INVERT_CC_POLARITY;
writel(val, com + QPHY_V3_DP_COM_TYPEC_CTRL);
switch (qmp->qmpphy_mode) {
@ -3235,6 +3885,8 @@ static int qmp_combo_usb_power_on(struct phy *phy)
qmp_configure_lane(qmp->dev, rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2);
qmp_configure(qmp->dev, pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
qmp_configure(qmp->dev, qmp->pcs_misc, cfg->pcs_misc_tbl, cfg->pcs_misc_tbl_num);
if (pcs_usb)
qmp_configure(qmp->dev, pcs_usb, cfg->pcs_usb_tbl,
@ -3361,6 +4013,7 @@ static void qmp_combo_enable_autonomous_mode(struct qmp_combo *qmp)
const struct qmp_phy_cfg *cfg = qmp->cfg;
void __iomem *pcs_usb = qmp->pcs_usb ?: qmp->pcs;
void __iomem *pcs_misc = qmp->pcs_misc;
void __iomem *pcs_aon = qmp->pcs_aon;
u32 intr_mask;
if (qmp->phy_mode == PHY_MODE_USB_HOST_SS ||
@ -3380,9 +4033,14 @@ static void qmp_combo_enable_autonomous_mode(struct qmp_combo *qmp)
/* Enable required PHY autonomous mode interrupts */
qphy_setbits(pcs_usb, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask);
/* Enable i/o clamp_n for autonomous mode */
if (pcs_misc)
qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN);
/*
* Enable i/o clamp_n for autonomous mode
* V6 and later versions use pcs aon clamp register
*/
if (pcs_aon)
qphy_clrbits(pcs_aon, cfg->regs[QPHY_PCS_CLAMP_ENABLE], CLAMP_EN);
else if (pcs_misc)
qphy_clrbits(pcs_misc, cfg->regs[QPHY_PCS_CLAMP_ENABLE], CLAMP_EN);
}
static void qmp_combo_disable_autonomous_mode(struct qmp_combo *qmp)
@ -3390,10 +4048,13 @@ static void qmp_combo_disable_autonomous_mode(struct qmp_combo *qmp)
const struct qmp_phy_cfg *cfg = qmp->cfg;
void __iomem *pcs_usb = qmp->pcs_usb ?: qmp->pcs;
void __iomem *pcs_misc = qmp->pcs_misc;
void __iomem *pcs_aon = qmp->pcs_aon;
/* Disable i/o clamp_n on resume for normal mode */
if (pcs_misc)
qphy_setbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN);
if (pcs_aon)
qphy_setbits(pcs_aon, cfg->regs[QPHY_PCS_CLAMP_ENABLE], CLAMP_EN);
else if (pcs_misc)
qphy_setbits(pcs_misc, cfg->regs[QPHY_PCS_CLAMP_ENABLE], CLAMP_EN);
qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN);
@ -4058,6 +4719,8 @@ static int qmp_combo_parse_dt(struct qmp_combo *qmp)
qmp->serdes = base + offs->usb3_serdes;
qmp->pcs_misc = base + offs->usb3_pcs_misc;
qmp->pcs = base + offs->usb3_pcs;
if (offs->usb3_pcs_aon)
qmp->pcs_aon = base + offs->usb3_pcs_aon;
qmp->pcs_usb = base + offs->usb3_pcs_usb;
qmp->dp_serdes = base + offs->dp_serdes;
@ -4319,6 +4982,10 @@ err_node_put:
}
static const struct of_device_id qmp_combo_of_match_table[] = {
{
.compatible = "qcom,glymur-qmp-usb3-dp-phy",
.data = &glymur_usb3dpphy_cfg,
},
{
.compatible = "qcom,sar2130p-qmp-usb3-dp-phy",
.data = &sar2130p_usb3dpphy_cfg,

View file

@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_DP_PHY_V2_H_
#define QCOM_PHY_QMP_DP_PHY_V2_H_
// /* Only for QMP V2 PHY - DP PHY registers */
#define QSERDES_V2_DP_PHY_AUX_INTERRUPT_MASK 0x048
#define QSERDES_V2_DP_PHY_AUX_INTERRUPT_CLEAR 0x04c
#define QSERDES_V2_DP_PHY_AUX_BIST_CFG 0x050
#define QSERDES_V2_DP_PHY_VCO_DIV 0x068
#define QSERDES_V2_DP_PHY_TX0_TX1_LANE_CTL 0x06c
#define QSERDES_V2_DP_PHY_TX2_TX3_LANE_CTL 0x088
#define QSERDES_V2_DP_PHY_SPARE0 0x0ac
#define QSERDES_V2_DP_PHY_STATUS 0x0c0
#endif

View file

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_DP_PHY_V8_H_
#define QCOM_PHY_QMP_DP_PHY_V8_H_
/* Only for QMP V8 PHY - DP PHY registers */
#define QSERDES_V8_DP_PHY_VCO_DIV 0x070
#define QSERDES_V8_DP_PHY_AUX_INTERRUPT_STATUS 0x0e0
#define QSERDES_V8_DP_PHY_TSYNC_OVRD 0x074
#define QSERDES_V8_DP_PHY_TX0_TX1_LANE_CTL 0x078
#define QSERDES_V8_DP_PHY_TX2_TX3_LANE_CTL 0x0bc
#define QSERDES_V8_DP_PHY_AUXLESS_CFG1 0x0c8
#define QSERDES_V8_DP_PHY_LFPS_PERIOD 0x0d0
#define QSERDES_V8_DP_PHY_LFPS_CYC 0x0d4
#define QSERDES_V8_DP_PHY_AUXLESS_SETUP_CYC 0x0d8
#define QSERDES_V8_DP_PHY_AUXLESS_SILENCE_CYC 0x0d8
#define QSERDES_V8_DP_PHY_LN0_DRV_LVL 0x0e0
#define QSERDES_V8_DP_PHY_LN1_DRV_LVL 0x0e4
#define QSERDES_V8_DP_PHY_STATUS 0x114
#endif

View file

@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2025 Linaro Ltd.
*/
#ifndef QCOM_PHY_QMP_DP_QSERDES_COM_V8_H_
#define QCOM_PHY_QMP_DP_QSERDES_COM_V8_H_
/* Only for DP QMP V8 PHY - QSERDES COM registers */
#define DP_QSERDES_V8_COM_HSCLK_SEL_1 0x03c
#define DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x058
#define DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x05c
#define DP_QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0 0x060
#define DP_QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0 0x064
#define DP_QSERDES_V8_COM_CP_CTRL_MODE0 0x070
#define DP_QSERDES_V8_COM_PLL_RCTRL_MODE0 0x074
#define DP_QSERDES_V8_COM_PLL_CCTRL_MODE0 0x078
#define DP_QSERDES_V8_COM_CORECLK_DIV_MODE0 0x07c
#define DP_QSERDES_V8_COM_LOCK_CMP1_MODE0 0x080
#define DP_QSERDES_V8_COM_LOCK_CMP2_MODE0 0x084
#define DP_QSERDES_V8_COM_DEC_START_MODE0 0x088
#define DP_QSERDES_V8_COM_DIV_FRAC_START1_MODE0 0x090
#define DP_QSERDES_V8_COM_DIV_FRAC_START2_MODE0 0x094
#define DP_QSERDES_V8_COM_DIV_FRAC_START3_MODE0 0x098
#define DP_QSERDES_V8_COM_INTEGLOOP_GAIN0_MODE0 0x0a0
#define DP_QSERDES_V8_COM_VCO_TUNE1_MODE0 0x0a8
#define DP_QSERDES_V8_COM_INTEGLOOP_GAIN1_MODE0 0x0a4
#define DP_QSERDES_V8_COM_VCO_TUNE2_MODE0 0x0ac
#define DP_QSERDES_V8_COM_BG_TIMER 0x0bc
#define DP_QSERDES_V8_COM_SSC_EN_CENTER 0x0c0
#define DP_QSERDES_V8_COM_SSC_ADJ_PER1 0x0c4
#define DP_QSERDES_V8_COM_SSC_PER1 0x0cc
#define DP_QSERDES_V8_COM_SSC_PER2 0x0d0
#define DP_QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN 0x0dc
#define DP_QSERDES_V8_COM_CLK_ENABLE1 0x0e0
#define DP_QSERDES_V8_COM_SYS_CLK_CTRL 0x0e4
#define DP_QSERDES_V8_COM_SYSCLK_BUF_ENABLE 0x0e8
#define DP_QSERDES_V8_COM_PLL_IVCO 0x0f4
#define DP_QSERDES_V8_COM_SYSCLK_EN_SEL 0x110
#define DP_QSERDES_V8_COM_RESETSM_CNTRL 0x118
#define DP_QSERDES_V8_COM_LOCK_CMP_EN 0x120
#define DP_QSERDES_V8_COM_VCO_TUNE_CTRL 0x13c
#define DP_QSERDES_V8_COM_VCO_TUNE_MAP 0x140
#define DP_QSERDES_V8_COM_CLK_SELECT 0x164
#define DP_QSERDES_V8_COM_CORE_CLK_EN 0x170
#define DP_QSERDES_V8_COM_CMN_CONFIG_1 0x174
#define DP_QSERDES_V8_COM_SVS_MODE_CLK_SEL 0x180
#define DP_QSERDES_V8_COM_CLK_FWD_CONFIG_1 0x2f4
#define DP_QSERDES_V8_COM_CMN_STATUS 0x314
#define DP_QSERDES_V8_COM_C_READY_STATUS 0x33c
#endif

View file

@ -37,6 +37,9 @@
#include "phy-qcom-qmp-pcs-pcie-v6_30.h"
#include "phy-qcom-qmp-pcs-v6_30.h"
#include "phy-qcom-qmp-pcie-qhp.h"
#include "phy-qcom-qmp-qserdes-com-v8.h"
#include "phy-qcom-qmp-pcs-pcie-v8.h"
#include "phy-qcom-qmp-qserdes-txrx-pcie-v8.h"
#define PHY_INIT_COMPLETE_TIMEOUT 10000
@ -100,6 +103,13 @@ static const unsigned int pciephy_v7_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V7_PCS_POWER_DOWN_CONTROL,
};
static const unsigned int pciephy_v8_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_SW_RESET] = QPHY_V8_PCS_SW_RESET,
[QPHY_START_CTRL] = QPHY_V8_PCS_START_CONTROL,
[QPHY_PCS_STATUS] = QPHY_V8_PCS_PCS_STATUS1,
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V8_PCS_POWER_DOWN_CONTROL,
};
static const unsigned int pciephy_v8_50_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_START_CTRL] = QPHY_V8_50_PCS_START_CONTROL,
[QPHY_PCS_STATUS] = QPHY_V8_50_PCS_STATUS1,
@ -3067,6 +3077,149 @@ static const struct qmp_phy_init_tbl sar2130p_qmp_gen3x2_pcie_ep_pcs_misc_tbl[]
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
};
static const struct qmp_phy_init_tbl kaanapali_qmp_gen3x2_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE1_MODE1, 0x93),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE2_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_MODE1, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_MODE1, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CORECLK_DIV_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP1_MODE1, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP2_MODE1, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MODE1, 0x34),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START1_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START2_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START3_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_HSCLK_SEL_1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0, 0xf8),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CORECLK_DIV_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP1_MODE0, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP2_MODE0, 0x0d),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MODE0, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START1_MODE0, 0xab),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START2_MODE0, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START3_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_BG_TIMER, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_PER1, 0x62),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_PER2, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CLK_ENABLE1, 0x90),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SYS_CLK_CTRL, 0x82),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_IVCO, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP_EN, 0x46),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP_CFG, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE_MAP, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CLK_SELECT, 0x34),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CORE_CLK_EN, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CMN_MISC_1, 0x88),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CMN_MODE, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_DC_LEVEL_CTRL, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_SPARE_FOR_ECO, 0x02),
};
static const struct qmp_phy_init_tbl kaanapali_qmp_gen3x2_pcie_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_RES_CODE_LANE_OFFSET_TX, 0x1b),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_RES_CODE_LANE_OFFSET_RX, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_LANE_MODE_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_LANE_MODE_2, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_LANE_MODE_3, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_TRAN_DRVR_EMP_EN, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_TX_BAND0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_TX_BAND1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_SEL_10B_8B, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_SEL_20B_10B, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_PARRATE_REC_DETECT_IDLE_EN, 0x90),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_TX_ADAPT_POST_THRESH1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_TX_ADAPT_POST_THRESH2, 0x0d),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_EQ_RCF_CTRL_RATE3, 0x53),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_EQ_RCF_CTRL_RATE4, 0x54),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_TX_PHPRE_CTRL, 0x20),
};
static const struct qmp_phy_init_tbl kaanapali_qmp_gen3x2_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_UCDR_FO_GAIN_RATE4, 0x0b),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_UCDR_SO_GAIN_RATE3, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_UCDR_SO_GAIN_RATE4, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_UCDR_PI_CONTROLS, 0x15),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_VGA_CAL_CNTRL1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_VGA_CAL_MAN_VAL, 0x89),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_EQU_ADAPTOR_CNTRL4, 0x2d),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_SIGDET_ENABLES, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_SIGDET_LVL, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RXCLK_DIV2_CTRL, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_BAND_CTRL0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_TERM_BW_CTRL0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_TERM_BW_CTRL1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_SVS_MODE_CTRL, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_UCDR_PI_CTRL1, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_UCDR_PI_CTRL2, 0x42),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_UCDR_SB2_THRESH2_RATE3, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_UCDR_SB2_GAIN1_RATE3, 0x12),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_UCDR_SB2_GAIN2_RATE3, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE_0_1_B0, 0xc2),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE_0_1_B1, 0xc2),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE_0_1_B2, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE_0_1_B4, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE_0_1_B7, 0x62),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE3_B0, 0xe4),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE3_B1, 0x63),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE3_B2, 0xd8),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE3_B3, 0x99),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE3_B4, 0x67),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B0, 0xa4),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B1, 0xa4),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B2, 0x28),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B3, 0x9f),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B4, 0x48),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B5, 0x24),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_Q_PI_INTRINSIC_BIAS_RATE32, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_Q_PI_INTRINSIC_BIAS_RATE4, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_EOM_MAX_ERR_LIMIT_LSB, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_EOM_MAX_ERR_LIMIT_MSB, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_AUXDATA_BIN_RATE23, 0x30),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_AUXDATA_BIN_RATE4, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_VTHRESH_CAL_MAN_VAL_RATE3, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_VTHRESH_CAL_MAN_VAL_RATE4, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V8_PCIE_RX_GM_CAL, 0x0d),
};
static const struct qmp_phy_init_tbl kaanapali_qmp_gen3x2_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_G12S1_TXDEEMPH_M6DB, 0x17),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_G3S2_PRE_GAIN, 0x2e),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_RX_SIGDET_LVL, 0xcc),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_ELECIDLE_DLY_SEL, 0x40),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_PCS_TX_RX_CONFIG1, 0x04),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_PCS_TX_RX_CONFIG2, 0x02),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_EQ_CONFIG4, 0x00),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_EQ_CONFIG5, 0x22),
};
static const struct qmp_phy_init_tbl kaanapali_qmp_gen3x2_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_TX_RX_CONFIG, 0xc0),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_POWER_STATE_CONFIG2, 0x1d),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_ENDPOINT_REFCLK_DRIVE, 0xc1),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_OSC_DTCT_ACTIONS, 0x00),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_EQ_CONFIG1, 0x16),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_G3_RXEQEVAL_TIME, 0x27),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_G4_RXEQEVAL_TIME, 0x27),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_G4_EQ_CONFIG5, 0x02),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_G4_PRE_GAIN, 0x2e),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_RX_MARGINING_CONFIG1, 0x03),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_RX_MARGINING_CONFIG3, 0x28),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_RX_MARGINING_CONFIG5, 0x0f),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_G3_FOM_EQ_CONFIG5, 0xf2),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_G4_FOM_EQ_CONFIG5, 0xf2),
QMP_PHY_INIT_CFG(QPHY_PCIE_V8_PCS_POWER_STATE_CONFIG6, 0x1f),
};
struct qmp_pcie_offsets {
u16 serdes;
u16 pcs;
@ -3363,6 +3516,16 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v6_30 = {
.ln_shrd = 0x8000,
};
static const struct qmp_pcie_offsets qmp_pcie_offsets_v8_0 = {
.serdes = 0x1000,
.pcs = 0x1400,
.pcs_misc = 0x1800,
.tx = 0x0000,
.rx = 0x0200,
.tx2 = 0x0800,
.rx2 = 0x0a00,
};
static const struct qmp_pcie_offsets qmp_pcie_offsets_v8_50 = {
.serdes = 0x8000,
.pcs = 0x9000,
@ -4425,6 +4588,34 @@ static const struct qmp_phy_cfg qmp_v6_gen4x4_pciephy_cfg = {
.phy_status = PHYSTATUS_4_20,
};
static const struct qmp_phy_cfg qmp_v8_gen3x2_pciephy_cfg = {
.lanes = 2,
.offsets = &qmp_pcie_offsets_v8_0,
.tbls = {
.serdes = kaanapali_qmp_gen3x2_pcie_serdes_tbl,
.serdes_num = ARRAY_SIZE(kaanapali_qmp_gen3x2_pcie_serdes_tbl),
.tx = kaanapali_qmp_gen3x2_pcie_tx_tbl,
.tx_num = ARRAY_SIZE(kaanapali_qmp_gen3x2_pcie_tx_tbl),
.rx = kaanapali_qmp_gen3x2_pcie_rx_tbl,
.rx_num = ARRAY_SIZE(kaanapali_qmp_gen3x2_pcie_rx_tbl),
.pcs = kaanapali_qmp_gen3x2_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(kaanapali_qmp_gen3x2_pcie_pcs_tbl),
.pcs_misc = kaanapali_qmp_gen3x2_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(kaanapali_qmp_gen3x2_pcie_pcs_misc_tbl),
},
.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 = pciephy_v8_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS_4_20,
};
static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_cfg = {
.lanes = 4,
@ -4441,6 +4632,22 @@ static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_cfg = {
.phy_status = PHYSTATUS_4_20,
};
static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = {
.lanes = 2,
.offsets = &qmp_pcie_offsets_v8_0,
.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 = pciephy_v8_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS_4_20,
};
static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@ -5192,6 +5399,9 @@ err_node_put:
static const struct of_device_id qmp_pcie_of_match_table[] = {
{
.compatible = "qcom,glymur-qmp-gen4x2-pcie-phy",
.data = &glymur_qmp_gen4x2_pciephy_cfg,
}, {
.compatible = "qcom,glymur-qmp-gen5x4-pcie-phy",
.data = &glymur_qmp_gen5x4_pciephy_cfg,
}, {
@ -5209,6 +5419,9 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, {
.compatible = "qcom,ipq9574-qmp-gen3x2-pcie-phy",
.data = &ipq9574_gen3x2_pciephy_cfg,
}, {
.compatible = "qcom,kaanapali-qmp-gen3x2-pcie-phy",
.data = &qmp_v8_gen3x2_pciephy_cfg,
}, {
.compatible = "qcom,msm8998-qmp-pcie-phy",
.data = &msm8998_pciephy_cfg,

View file

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_PCS_AON_V6_H_
#define QCOM_PHY_QMP_PCS_AON_V6_H_
/* Only for QMP V6 PHY - PCS_AON registers */
#define QPHY_V6_PCS_AON_CLAMP_ENABLE 0x00
#endif

View file

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_PCS_AON_V8_H_
#define QCOM_PHY_QMP_PCS_AON_V8_H_
/* Only for QMP V8 PHY - PCS_AON registers */
#define QPHY_V8_PCS_AON_USB3_AON_CLAMP_ENABLE 0x00
#define QPHY_V8_PCS_AON_USB4_AON_CLAMP_ENABLE 0x04
#define QPHY_V8_PCS_AON_USB3_AON_TOGGLE_ENABLE 0x08
#define QPHY_V8_PCS_AON_USB4_AON_TOGGLE_ENABLE 0x0c
#define QPHY_V8_PCS_AON_DP_AON_TOGGLE_ENABLE 0x10
#define QPHY_V8_PCS_AON_DUMMY_STATUS 0x14
#endif

View file

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_PCS_MISC_V5_H_
#define QCOM_PHY_QMP_PCS_MISC_V5_H_
/* Only for QMP V5 PHY - PCS_MISC registers */
#define QPHY_V5_PCS_MISC_CLAMP_ENABLE 0x0c
#endif

View file

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_PCS_MISC_V8_H_
#define QCOM_PHY_QMP_PCS_MISC_V8_H_
/* Only for QMP V8 PHY - PCS_MISC registers */
#define QPHY_V8_PCS_MISC_PCS_MISC_CONFIG1 0x08
#endif

View file

@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_PCS_PCIE_V8_H_
#define QCOM_PHY_QMP_PCS_PCIE_V8_H_
/* Only for QMP V8 PHY - PCIE PCS registers */
#define QPHY_PCIE_V8_PCS_POWER_STATE_CONFIG2 0x00c
#define QPHY_PCIE_V8_PCS_TX_RX_CONFIG 0x018
#define QPHY_PCIE_V8_PCS_ENDPOINT_REFCLK_DRIVE 0x01c
#define QPHY_PCIE_V8_PCS_OSC_DTCT_ACTIONS 0x090
#define QPHY_PCIE_V8_PCS_EQ_CONFIG1 0x0a0
#define QPHY_PCIE_V8_PCS_G3_RXEQEVAL_TIME 0x0f0
#define QPHY_PCIE_V8_PCS_G4_RXEQEVAL_TIME 0x0f4
#define QPHY_PCIE_V8_PCS_G4_EQ_CONFIG5 0x108
#define QPHY_PCIE_V8_PCS_G4_PRE_GAIN 0x15c
#define QPHY_PCIE_V8_PCS_G12S1_TXDEEMPH_M6DB 0x170
#define QPHY_PCIE_V8_PCS_G3S2_PRE_GAIN 0x178
#define QPHY_PCIE_V8_PCS_RX_MARGINING_CONFIG1 0x17c
#define QPHY_PCIE_V8_PCS_RX_MARGINING_CONFIG3 0x184
#define QPHY_PCIE_V8_PCS_RX_MARGINING_CONFIG5 0x18c
#define QPHY_PCIE_V8_PCS_RX_SIGDET_LVL 0x190
#define QPHY_PCIE_V8_PCS_G3_FOM_EQ_CONFIG5 0x1ac
#define QPHY_PCIE_V8_PCS_ELECIDLE_DLY_SEL 0x1b8
#define QPHY_PCIE_V8_PCS_G4_FOM_EQ_CONFIG5 0x1c0
#define QPHY_PCIE_V8_PCS_POWER_STATE_CONFIG6 0x1d0
#define QPHY_PCIE_V8_PCS_PCS_TX_RX_CONFIG1 0x1dc
#define QPHY_PCIE_V8_PCS_PCS_TX_RX_CONFIG2 0x1e0
#define QPHY_PCIE_V8_PCS_EQ_CONFIG4 0x1f8
#define QPHY_PCIE_V8_PCS_EQ_CONFIG5 0x1fc
#endif

View file

@ -0,0 +1,106 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_QSERDES_COM_V2_H_
#define QCOM_PHY_QMP_QSERDES_COM_V2_H_
/* Only for QMP V2 PHY - QSERDES COM registers */
#define QSERDES_V2_COM_ATB_SEL1 0x000
#define QSERDES_V2_COM_ATB_SEL2 0x004
#define QSERDES_V2_COM_FREQ_UPDATE 0x008
#define QSERDES_V2_COM_BG_TIMER 0x00c
#define QSERDES_V2_COM_SSC_EN_CENTER 0x010
#define QSERDES_V2_COM_SSC_ADJ_PER1 0x014
#define QSERDES_V2_COM_SSC_ADJ_PER2 0x018
#define QSERDES_V2_COM_SSC_PER1 0x01c
#define QSERDES_V2_COM_SSC_PER2 0x020
#define QSERDES_V2_COM_SSC_STEP_SIZE1 0x024
#define QSERDES_V2_COM_SSC_STEP_SIZE2 0x028
#define QSERDES_V2_COM_POST_DIV 0x02c
#define QSERDES_V2_COM_POST_DIV_MUX 0x030
#define QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN 0x034
#define QSERDES_V2_COM_CLK_ENABLE1 0x038
#define QSERDES_V2_COM_SYS_CLK_CTRL 0x03c
#define QSERDES_V2_COM_SYSCLK_BUF_ENABLE 0x040
#define QSERDES_V2_COM_PLL_EN 0x044
#define QSERDES_V2_COM_PLL_IVCO 0x048
#define QSERDES_V2_COM_LOCK_CMP1_MODE0 0x04c
#define QSERDES_V2_COM_LOCK_CMP2_MODE0 0x050
#define QSERDES_V2_COM_LOCK_CMP3_MODE0 0x054
#define QSERDES_V2_COM_LOCK_CMP1_MODE1 0x058
#define QSERDES_V2_COM_LOCK_CMP2_MODE1 0x05c
#define QSERDES_V2_COM_LOCK_CMP3_MODE1 0x060
#define QSERDES_V2_COM_EP_CLOCK_DETECT_CTR 0x068
#define QSERDES_V2_COM_SYSCLK_DET_COMP_STATUS 0x06c
#define QSERDES_V2_COM_CLK_EP_DIV 0x074
#define QSERDES_V2_COM_CP_CTRL_MODE0 0x078
#define QSERDES_V2_COM_CP_CTRL_MODE1 0x07c
#define QSERDES_V2_COM_PLL_RCTRL_MODE0 0x084
#define QSERDES_V2_COM_PLL_RCTRL_MODE1 0x088
#define QSERDES_V2_COM_PLL_CCTRL_MODE0 0x090
#define QSERDES_V2_COM_PLL_CCTRL_MODE1 0x094
#define QSERDES_V2_COM_PLL_CNTRL 0x09c
#define QSERDES_V2_COM_BIAS_EN_CTRL_BY_PSM 0x0a8
#define QSERDES_V2_COM_SYSCLK_EN_SEL 0x0ac
#define QSERDES_V2_COM_CML_SYSCLK_SEL 0x0b0
#define QSERDES_V2_COM_RESETSM_CNTRL 0x0b4
#define QSERDES_V2_COM_RESETSM_CNTRL2 0x0b8
#define QSERDES_V2_COM_LOCK_CMP_EN 0x0c8
#define QSERDES_V2_COM_LOCK_CMP_CFG 0x0cc
#define QSERDES_V2_COM_DEC_START_MODE0 0x0d0
#define QSERDES_V2_COM_DEC_START_MODE1 0x0d4
#define QSERDES_V2_COM_VCOCAL_DEADMAN_CTRL 0x0d8
#define QSERDES_V2_COM_DIV_FRAC_START1_MODE0 0x0dc
#define QSERDES_V2_COM_DIV_FRAC_START2_MODE0 0x0e0
#define QSERDES_V2_COM_DIV_FRAC_START3_MODE0 0x0e4
#define QSERDES_V2_COM_DIV_FRAC_START1_MODE1 0x0e8
#define QSERDES_V2_COM_DIV_FRAC_START2_MODE1 0x0ec
#define QSERDES_V2_COM_DIV_FRAC_START3_MODE1 0x0f0
#define QSERDES_V2_COM_VCO_TUNE_MINVAL1 0x0f4
#define QSERDES_V2_COM_VCO_TUNE_MINVAL2 0x0f8
#define QSERDES_V2_COM_INTEGLOOP_INITVAL 0x100
#define QSERDES_V2_COM_INTEGLOOP_EN 0x104
#define QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0 0x108
#define QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE0 0x10c
#define QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE1 0x110
#define QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE1 0x114
#define QSERDES_V2_COM_VCO_TUNE_MAXVAL1 0x118
#define QSERDES_V2_COM_VCO_TUNE_MAXVAL2 0x11c
#define QSERDES_V2_COM_VCO_TUNE_CTRL 0x124
#define QSERDES_V2_COM_VCO_TUNE_MAP 0x128
#define QSERDES_V2_COM_VCO_TUNE1_MODE0 0x12c
#define QSERDES_V2_COM_VCO_TUNE2_MODE0 0x130
#define QSERDES_V2_COM_VCO_TUNE1_MODE1 0x134
#define QSERDES_V2_COM_VCO_TUNE2_MODE1 0x138
#define QSERDES_V2_COM_VCO_TUNE_INITVAL1 0x13c
#define QSERDES_V2_COM_VCO_TUNE_INITVAL2 0x140
#define QSERDES_V2_COM_VCO_TUNE_TIMER1 0x144
#define QSERDES_V2_COM_VCO_TUNE_TIMER2 0x148
#define QSERDES_V2_COM_CMN_STATUS 0x15c
#define QSERDES_V2_COM_RESET_SM_STATUS 0x160
#define QSERDES_V2_COM_RESTRIM_CODE_STATUS 0x164
#define QSERDES_V2_COM_PLLCAL_CODE1_STATUS 0x168
#define QSERDES_V2_COM_PLLCAL_CODE2_STATUS 0x16c
#define QSERDES_V2_COM_CLK_SELECT 0x174
#define QSERDES_V2_COM_HSCLK_SEL 0x178
#define QSERDES_V2_COM_INTEGLOOP_BINCODE_STATUS 0x17c
#define QSERDES_V2_COM_PLL_ANALOG 0x180
#define QSERDES_V2_COM_CORECLK_DIV 0x184
#define QSERDES_V2_COM_SW_RESET 0x188
#define QSERDES_V2_COM_CORE_CLK_EN 0x18c
#define QSERDES_V2_COM_C_READY_STATUS 0x190
#define QSERDES_V2_COM_CMN_CONFIG 0x194
#define QSERDES_V2_COM_CMN_RATE_OVERRIDE 0x198
#define QSERDES_V2_COM_SVS_MODE_CLK_SEL 0x19c
#define QSERDES_V2_COM_DEBUG_BUS0 0x1a0
#define QSERDES_V2_COM_DEBUG_BUS1 0x1a4
#define QSERDES_V2_COM_DEBUG_BUS2 0x1a8
#define QSERDES_V2_COM_DEBUG_BUS3 0x1ac
#define QSERDES_V2_COM_DEBUG_BUS_SEL 0x1b0
#define QSERDES_V2_COM_CMN_MISC1 0x1b4
#define QSERDES_V2_COM_CMN_MISC2 0x1b8
#define QSERDES_V2_COM_CORECLK_DIV_MODE1 0x1bc
#endif

View file

@ -33,6 +33,7 @@
#define QSERDES_V8_COM_CP_CTRL_MODE0 0x070
#define QSERDES_V8_COM_PLL_RCTRL_MODE0 0x074
#define QSERDES_V8_COM_PLL_CCTRL_MODE0 0x078
#define QSERDES_V8_COM_CORECLK_DIV_MODE0 0x07c
#define QSERDES_V8_COM_LOCK_CMP1_MODE0 0x080
#define QSERDES_V8_COM_LOCK_CMP2_MODE0 0x084
#define QSERDES_V8_COM_DEC_START_MODE0 0x088
@ -40,6 +41,7 @@
#define QSERDES_V8_COM_DIV_FRAC_START1_MODE0 0x090
#define QSERDES_V8_COM_DIV_FRAC_START2_MODE0 0x094
#define QSERDES_V8_COM_DIV_FRAC_START3_MODE0 0x098
#define QSERDES_V8_COM_HSCLK_HS_SWITCH_SEL_1 0x09c
#define QSERDES_V8_COM_VCO_TUNE1_MODE0 0x0a8
#define QSERDES_V8_COM_VCO_TUNE2_MODE0 0x0ac
#define QSERDES_V8_COM_BG_TIMER 0x0bc
@ -47,13 +49,22 @@
#define QSERDES_V8_COM_SSC_PER1 0x0cc
#define QSERDES_V8_COM_SSC_PER2 0x0d0
#define QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN 0x0dc
#define QSERDES_V8_COM_CLK_ENABLE1 0x0e0
#define QSERDES_V8_COM_SYS_CLK_CTRL 0x0e4
#define QSERDES_V8_COM_PLL_IVCO 0x0f4
#define QSERDES_V8_COM_SYSCLK_BUF_ENABLE 0x0e8
#define QSERDES_V8_COM_SYSCLK_EN_SEL 0x110
#define QSERDES_V8_COM_RESETSM_CNTRL 0x118
#define QSERDES_V8_COM_LOCK_CMP_EN 0x120
#define QSERDES_V8_COM_LOCK_CMP_CFG 0x124
#define QSERDES_V8_COM_VCO_TUNE_MAP 0x140
#define QSERDES_V8_COM_CLK_SELECT 0x164
#define QSERDES_V8_COM_CORE_CLK_EN 0x170
#define QSERDES_V8_COM_CMN_CONFIG_1 0x174
#define QSERDES_V8_COM_CMN_MISC_1 0x184
#define QSERDES_V8_COM_CMN_MODE 0x188
#define QSERDES_V8_COM_VCO_DC_LEVEL_CTRL 0x198
#define QSERDES_V8_COM_PLL_SPARE_FOR_ECO 0x2b4
#define QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_1 0x1a4
#define QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_2 0x1a8
#define QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_3 0x1ac

View file

@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2025 Linaro Ltd.
*/
#ifndef QCOM_PHY_QMP_QSERDES_DP_COM_V8_H_
#define QCOM_PHY_QMP_QSERDES_DP_COM_V8_H_
/* Only for DP QMP V8 PHY - QSERDES COM registers */
#define DP_QSERDES_V8_COM_HSCLK_SEL_1 0x03c
#define DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x058
#define DP_QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x05c
#define DP_QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0 0x060
#define DP_QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0 0x064
#define DP_QSERDES_V8_COM_CP_CTRL_MODE0 0x070
#define DP_QSERDES_V8_COM_PLL_RCTRL_MODE0 0x074
#define DP_QSERDES_V8_COM_PLL_CCTRL_MODE0 0x078
#define DP_QSERDES_V8_COM_CORECLK_DIV_MODE0 0x07c
#define DP_QSERDES_V8_COM_LOCK_CMP1_MODE0 0x080
#define DP_QSERDES_V8_COM_LOCK_CMP2_MODE0 0x084
#define DP_QSERDES_V8_COM_DEC_START_MODE0 0x088
#define DP_QSERDES_V8_COM_DIV_FRAC_START1_MODE0 0x090
#define DP_QSERDES_V8_COM_DIV_FRAC_START2_MODE0 0x094
#define DP_QSERDES_V8_COM_DIV_FRAC_START3_MODE0 0x098
#define DP_QSERDES_V8_COM_INTEGLOOP_GAIN0_MODE0 0x0a0
#define DP_QSERDES_V8_COM_VCO_TUNE1_MODE0 0x0a8
#define DP_QSERDES_V8_COM_INTEGLOOP_GAIN1_MODE0 0x0a4
#define DP_QSERDES_V8_COM_VCO_TUNE2_MODE0 0x0ac
#define DP_QSERDES_V8_COM_BG_TIMER 0x0bc
#define DP_QSERDES_V8_COM_SSC_EN_CENTER 0x0c0
#define DP_QSERDES_V8_COM_SSC_ADJ_PER1 0x0c4
#define DP_QSERDES_V8_COM_SSC_PER1 0x0cc
#define DP_QSERDES_V8_COM_SSC_PER2 0x0d0
#define DP_QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN 0x0dc
#define DP_QSERDES_V8_COM_CLK_ENABLE1 0x0e0
#define DP_QSERDES_V8_COM_SYS_CLK_CTRL 0x0e4
#define DP_QSERDES_V8_COM_SYSCLK_BUF_ENABLE 0x0e8
#define DP_QSERDES_V8_COM_PLL_IVCO 0x0f4
#define DP_QSERDES_V8_COM_SYSCLK_EN_SEL 0x110
#define DP_QSERDES_V8_COM_RESETSM_CNTRL 0x118
#define DP_QSERDES_V8_COM_LOCK_CMP_EN 0x120
#define DP_QSERDES_V8_COM_VCO_TUNE_CTRL 0x13c
#define DP_QSERDES_V8_COM_VCO_TUNE_MAP 0x140
#define DP_QSERDES_V8_COM_CLK_SELECT 0x164
#define DP_QSERDES_V8_COM_CORE_CLK_EN 0x170
#define DP_QSERDES_V8_COM_CMN_CONFIG_1 0x174
#define DP_QSERDES_V8_COM_SVS_MODE_CLK_SEL 0x180
#define DP_QSERDES_V8_COM_CLK_FWD_CONFIG_1 0x2f4
#define DP_QSERDES_V8_COM_CMN_STATUS 0x314
#define DP_QSERDES_V8_COM_C_READY_STATUS 0x33c
#endif

View file

@ -0,0 +1,639 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_QSERDES_V8_LALBH_
#define QCOM_PHY_QMP_QSERDES_V8_LALBH_
#define QSERDES_V8_LALB_BIST_MODE_LANENO 0x0
#define QSERDES_V8_LALB_BIST_INVERT 0x4
#define QSERDES_V8_LALB_PERL_LENGTH1 0x8
#define QSERDES_V8_LALB_PERL_LENGTH2 0xc
#define QSERDES_V8_LALB_BIST_PATTERN1 0x10
#define QSERDES_V8_LALB_BIST_PATTERN2 0x14
#define QSERDES_V8_LALB_BIST_PATTERN3 0x18
#define QSERDES_V8_LALB_BIST_PATTERN4 0x1c
#define QSERDES_V8_LALB_BIST_PATTERN5 0x20
#define QSERDES_V8_LALB_BIST_PATTERN6 0x24
#define QSERDES_V8_LALB_BIST_PATTERN7 0x28
#define QSERDES_V8_LALB_BIST_PATTERN8 0x2c
#define QSERDES_V8_LALB_PRBS_SEED1 0x30
#define QSERDES_V8_LALB_PRBS_SEED2 0x34
#define QSERDES_V8_LALB_PRBS_SEED3 0x38
#define QSERDES_V8_LALB_PRBS_SEED4 0x3c
#define QSERDES_V8_LALB_PRBS_SEED5 0x40
#define QSERDES_V8_LALB_PRBS_SEED6 0x44
#define QSERDES_V8_LALB_PRBS_SEED7 0x48
#define QSERDES_V8_LALB_SW_RESET_PWRDNB 0x4c
#define QSERDES_V8_LALB_RESET_GEN 0x50
#define QSERDES_V8_LALB_RESET_TSYNC_EN_CTRL 0x54
#define QSERDES_V8_LALB_CDR_EN_RXEQ_RESET 0x58
#define QSERDES_V8_LALB_CLKBUF_ENABLE 0x5c
#define QSERDES_V8_LALB_TX0_EMP_POST1_LVL 0x60
#define QSERDES_V8_LALB_TX1_EMP_POST1_LVL 0x64
#define QSERDES_V8_LALB_TX0_IDLE_CTRL 0x68
#define QSERDES_V8_LALB_TX1_IDLE_CTRL 0x6c
#define QSERDES_V8_LALB_TX0_DRV_LVL 0x70
#define QSERDES_V8_LALB_TX0_DRV_LVL_OFFSET 0x74
#define QSERDES_V8_LALB_TX1_DRV_LVL 0x78
#define QSERDES_V8_LALB_TX1_DRV_LVL_OFFSET 0x7c
#define QSERDES_V8_LALB_TRAN_DRVR_EMP_EN 0x80
#define QSERDES_V8_LALB_TX_LVL_UPDATE_CTRL 0x84
#define QSERDES_V8_LALB_TX0_PRE1_EMPH 0x88
#define QSERDES_V8_LALB_TX1_PRE1_EMPH 0x8c
#define QSERDES_V8_LALB_TX0_PRE2_EMPH 0x90
#define QSERDES_V8_LALB_TX1_PRE2_EMPH 0x94
#define QSERDES_V8_LALB_STALL_LDO_BOOST_EN 0x98
#define QSERDES_V8_LALB_PRE_EMPH_EN_CTRL 0x9c
#define QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL1 0xa0
#define QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL2 0xa4
#define QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL3 0xa8
#define QSERDES_V8_LALB_PCIE5_TOP_LDO_CODE_CTRL4 0xac
#define QSERDES_V8_LALB_TRANSMITTER_EN_CTRL 0xb0
#define QSERDES_V8_LALB_HIGHZ_DRVR_EN 0xb4
#define QSERDES_V8_LALB_TX_MISC_CTRL1 0xb8
#define QSERDES_V8_LALB_LPB_EN_CTRL1 0xbc
#define QSERDES_V8_LALB_LBP_EN_CTRL2 0xc0
#define QSERDES_V8_LALB_TX0_SERDES_BYP_CTRL 0xc4
#define QSERDES_V8_LALB_TX1_SERDES_BYP_CTRL 0xc8
#define QSERDES_V8_LALB_LANE_MODE_1 0xcc
#define QSERDES_V8_LALB_LANE_MODE_2 0xd0
#define QSERDES_V8_LALB_LANE_MODE_3 0xd4
#define QSERDES_V8_LALB_LANE_MODE_4 0xd8
#define QSERDES_V8_LALB_ATB_SEL1 0xdc
#define QSERDES_V8_LALB_ATB_SEL2 0xe0
#define QSERDES_V8_LALB_TX0_RES_CODE_LANE 0xe4
#define QSERDES_V8_LALB_TX0_RESTRIM_ICAL_OVRD 0xe8
#define QSERDES_V8_LALB_TX0_RESTRIM_CAL_CTRL 0xec
#define QSERDES_V8_LALB_TX0_RESTRIM_INIT_CODE 0xf0
#define QSERDES_V8_LALB_TX0_RESTRIM_POST_CAL_OFFSET 0xf4
#define QSERDES_V8_LALB_TX1_RES_CODE_LANE 0xf8
#define QSERDES_V8_LALB_TX1_RESTRIM_ICAL_OVRD 0xfc
#define QSERDES_V8_LALB_TX1_RESTRIM_CAL_CTRL 0x100
#define QSERDES_V8_LALB_TX1_RESTRIM_INIT_CODE 0x104
#define QSERDES_V8_LALB_TX1_RESTRIM_POST_CAL_OFFSET 0x108
#define QSERDES_V8_LALB_TX0_RESTRIM_VREF_SEL 0x10c
#define QSERDES_V8_LALB_TX1_RESTRIM_VREF_SEL 0x110
#define QSERDES_V8_LALB_VMODE_CTRL1 0x114
#define QSERDES_V8_LALB_SLEW_CNTL_RATE01 0x118
#define QSERDES_V8_LALB_SLEW_CNTL_RATE23 0x11c
#define QSERDES_V8_LALB_SLEW_CNTL_RATE4 0x120
#define QSERDES_V8_LALB_ANA_INTERFACE_SELECT1 0x124
#define QSERDES_V8_LALB_ANA_INTERFACE_SELECT2 0x128
#define QSERDES_V8_LALB_ANA_INTERFACE_SELECT3 0x12c
#define QSERDES_V8_LALB_PCS_INTERFACE_SELECT1 0x130
#define QSERDES_V8_LALB_PCS_INTERFACE_SELECT2 0x134
#define QSERDES_V8_LALB_LDO_TIMER_CTRL 0x138
#define QSERDES_V8_LALB_AC_JTAG_ENABLE 0x13c
#define QSERDES_V8_LALB_AC_JTAG_INITP 0x140
#define QSERDES_V8_LALB_AC_JTAG_INITN 0x144
#define QSERDES_V8_LALB_AC_JTAG_LVL 0x148
#define QSERDES_V8_LALB_AC_JTAG_MODE 0x14c
#define QSERDES_V8_LALB_AC_JTAG_RESET 0x150
#define QSERDES_V8_LALB_RX_MODE_RATE_0_1_B0 0x154
#define QSERDES_V8_LALB_RX_MODE_RATE_0_1_B1 0x158
#define QSERDES_V8_LALB_RX_MODE_RATE_0_1_B2 0x15c
#define QSERDES_V8_LALB_RX_MODE_RATE_0_1_B3 0x160
#define QSERDES_V8_LALB_RX_MODE_RATE_0_1_B4 0x164
#define QSERDES_V8_LALB_RX_MODE_RATE_0_1_B5 0x168
#define QSERDES_V8_LALB_RX_MODE_RATE_0_1_B6 0x16c
#define QSERDES_V8_LALB_RX_MODE_RATE_0_1_B7 0x170
#define QSERDES_V8_LALB_RX_MODE_RATE2_B0 0x174
#define QSERDES_V8_LALB_RX_MODE_RATE2_B1 0x178
#define QSERDES_V8_LALB_RX_MODE_RATE2_B2 0x17c
#define QSERDES_V8_LALB_RX_MODE_RATE2_B3 0x180
#define QSERDES_V8_LALB_RX_MODE_RATE2_B4 0x184
#define QSERDES_V8_LALB_RX_MODE_RATE2_B5 0x188
#define QSERDES_V8_LALB_RX_MODE_RATE2_B6 0x18c
#define QSERDES_V8_LALB_RX_MODE_RATE2_B7 0x190
#define QSERDES_V8_LALB_RX_MODE_RATE3_B0 0x194
#define QSERDES_V8_LALB_RX_MODE_RATE3_B1 0x198
#define QSERDES_V8_LALB_RX_MODE_RATE3_B2 0x19c
#define QSERDES_V8_LALB_RX_MODE_RATE3_B3 0x1a0
#define QSERDES_V8_LALB_RX_MODE_RATE3_B4 0x1a4
#define QSERDES_V8_LALB_RX_MODE_RATE3_B5 0x1a8
#define QSERDES_V8_LALB_RX_MODE_RATE3_B6 0x1ac
#define QSERDES_V8_LALB_RX_MODE_RATE3_B7 0x1b0
#define QSERDES_V8_LALB_RX_MODE_RATE4_B0 0x1b4
#define QSERDES_V8_LALB_RX_MODE_RATE4_B1 0x1b8
#define QSERDES_V8_LALB_RX_MODE_RATE4_B2 0x1bc
#define QSERDES_V8_LALB_RX_MODE_RATE4_B3 0x1c0
#define QSERDES_V8_LALB_RX_MODE_RATE4_B4 0x1c4
#define QSERDES_V8_LALB_RX_MODE_RATE4_B5 0x1c8
#define QSERDES_V8_LALB_RX_MODE_RATE4_B6 0x1cc
#define QSERDES_V8_LALB_RX_MODE_RATE4_B7 0x1d0
#define QSERDES_V8_LALB_TX_DCC_ANA_CTRL1 0x1d4
#define QSERDES_V8_LALB_TX_DCC_ANA_CTRL2 0x1d8
#define QSERDES_V8_LALB_CMUX_DCC_CTRL1 0x1dc
#define QSERDES_V8_LALB_CMUX_DCC_POSTCAL_OFFSET 0x1e0
#define QSERDES_V8_LALB_CMUX_DCC_OVRD 0x1e4
#define QSERDES_V8_LALB_TX_DCC_CTRL 0x1e8
#define QSERDES_V8_LALB_TX0_CTUNE_DCC_CONFIG 0x1ec
#define QSERDES_V8_LALB_TX0_CTUNE_DCC_POSTCAL_OFFSET 0x1f0
#define QSERDES_V8_LALB_TX0_CTUNE_DCC_OVRD 0x1f4
#define QSERDES_V8_LALB_TX0_FTUNE_MSB_DCC_CONFIG 0x1f8
#define QSERDES_V8_LALB_TX0_FTUNE_MSB_DCC_OFFSET_AND_OVRD 0x1fc
#define QSERDES_V8_LALB_TX0_FTUNE_LSB_DCC_CONFIG 0x200
#define QSERDES_V8_LALB_TX0_FTUNE_LSB_DCC_OFFSET_AND_OVRD 0x204
#define QSERDES_V8_LALB_TX1_CTUNE_DCC_CONFIG 0x208
#define QSERDES_V8_LALB_TX1_CTUNE_DCC_POSTCAL_OFFSET 0x20c
#define QSERDES_V8_LALB_TX1_CTUNE_DCC_OVRD 0x210
#define QSERDES_V8_LALB_TX1_FTUNE_MSB_DCC_CONFIG 0x214
#define QSERDES_V8_LALB_TX1_FTUNE_MSB_DCC_OFFSET_AND_OVRD 0x218
#define QSERDES_V8_LALB_TX1_FTUNE_LSB_DCC_CONFIG 0x21c
#define QSERDES_V8_LALB_TX1_FTUNE_LSB_DCC_OFFSET_AND_OVRD 0x220
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_CTRL 0x224
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_CODE_OVRD_RATE0 0x228
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_CODE_OVRD_RATE1 0x22c
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_CODE_OVRD_RATE2 0x230
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_CODE_OVRD_RATE3 0x234
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_CODE_OVRD_RATE4 0x238
#define QSERDES_V8_LALB_CDR_VCO_CAL_CTRL 0x23c
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT1_RATE0 0x240
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT2_RATE0 0x244
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT1_RATE1 0x248
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT2_RATE1 0x24c
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT1_RATE2 0x250
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT2_RATE2 0x254
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT1_RATE3 0x258
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT2_RATE3 0x25c
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT1_RATE4 0x260
#define QSERDES_V8_LALB_CDR_VCO_CTUNE_MEAS_CNT2_RATE4 0x264
#define QSERDES_V8_LALB_CDR_VCTRL_RATE_0_1 0x268
#define QSERDES_V8_LALB_CDR_VCTRL_RATE_2_3 0x26c
#define QSERDES_V8_LALB_CDR_VCTRL_RATE_4 0x270
#define QSERDES_V8_LALB_KVCO_INIT_RATE_0_1 0x274
#define QSERDES_V8_LALB_KVCO_INIT_RATE_2_3 0x278
#define QSERDES_V8_LALB_KVCO_INIT_RATE_4 0x27c
#define QSERDES_V8_LALB_KVCO_CODE_OVRD_RATE0 0x280
#define QSERDES_V8_LALB_KVCO_CODE_OVRD_RATE1 0x284
#define QSERDES_V8_LALB_KVCO_CODE_OVRD_RATE2 0x288
#define QSERDES_V8_LALB_KVCO_CODE_OVRD_RATE3 0x28c
#define QSERDES_V8_LALB_KVCO_CODE_OVRD_RATE4 0x290
#define QSERDES_V8_LALB_KVCO_CAL_VCTRL_HIGH_RATE_0_1 0x294
#define QSERDES_V8_LALB_KVCO_CAL_VCTRL_HIGH_RATE_2_3 0x298
#define QSERDES_V8_LALB_KVCO_CAL_VCTRL_HIGH_RATE_4 0x29c
#define QSERDES_V8_LALB_KVCO_CAL_VCTRL_LOW_RATE_0_1 0x2a0
#define QSERDES_V8_LALB_KVCO_CAL_VCTRL_LOW_RATE_2_3 0x2a4
#define QSERDES_V8_LALB_KVCO_CAL_VCTRL_LOW_RATE_4 0x2a8
#define QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF1_RATE0 0x2ac
#define QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF2_RATE0 0x2b0
#define QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF1_RATE1 0x2b4
#define QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF2_RATE1 0x2b8
#define QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF1_RATE2 0x2bc
#define QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF2_RATE2 0x2c0
#define QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF1_RATE3 0x2c4
#define QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF2_RATE3 0x2c8
#define QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF1_RATE4 0x2cc
#define QSERDES_V8_LALB_KVCO_IDEAL_FREQ_DIFF2_RATE4 0x2d0
#define QSERDES_V8_LALB_KP_CDR_UP_DN 0x2d4
#define QSERDES_V8_LALB_KP_CODE_OVRD_RATE_0_1 0x2d8
#define QSERDES_V8_LALB_KP_CODE_OVRD_RATE_2_3 0x2dc
#define QSERDES_V8_LALB_KP_CODE_OVRD_RATE4 0x2e0
#define QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND1_RATE0 0x2e4
#define QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND2_RATE0 0x2e8
#define QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND1_RATE1 0x2ec
#define QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND2_RATE1 0x2f0
#define QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND1_RATE2 0x2f4
#define QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND2_RATE2 0x2f8
#define QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND1_RATE3 0x2fc
#define QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND2_RATE3 0x300
#define QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND1_RATE4 0x304
#define QSERDES_V8_LALB_KP_CAL_UPPER_FREQ_DIFF_BND2_RATE4 0x308
#define QSERDES_V8_LALB_KP_CAL_LOWER_FREQ_DIFF_BND_RATE0 0x30c
#define QSERDES_V8_LALB_KP_CAL_LOWER_FREQ_DIFF_BND_RATE1 0x310
#define QSERDES_V8_LALB_KP_CAL_LOWER_FREQ_DIFF_BND_RATE2 0x314
#define QSERDES_V8_LALB_KP_CAL_LOWER_FREQ_DIFF_BND_RATE3 0x318
#define QSERDES_V8_LALB_KP_CAL_LOWER_FREQ_DIFF_BND_RATE4 0x31c
#define QSERDES_V8_LALB_CDR_KVCO_KP_CAL_FREQ_MEAS_CTRL 0x320
#define QSERDES_V8_LALB_PLLLOCK_CMP_DEBUG_CTRL 0x324
#define QSERDES_V8_LALB_PLLLOCK_CMP_DEBUG_CNT1 0x328
#define QSERDES_V8_LALB_PLLLOCK_CMP_DEBUG_CNT2 0x32c
#define QSERDES_V8_LALB_PLLLOCK_CMP_DEBUG_CNT3 0x330
#define QSERDES_V8_LALB_RX_SUMMER_CAL_SPD_MODE_RATE_0123 0x334
#define QSERDES_V8_LALB_RX_SUMMER_CAL_SPD_MODE_RATE_4 0x338
#define QSERDES_V8_LALB_RX_IVCM_CAL_CODE_OVERRIDE_RATE0 0x33c
#define QSERDES_V8_LALB_RX_IVCM_CAL_CODE_OVERRIDE_RATE1 0x340
#define QSERDES_V8_LALB_RX_IVCM_CAL_CODE_OVERRIDE_RATE2 0x344
#define QSERDES_V8_LALB_RX_IVCM_CAL_CODE_OVERRIDE_RATE3 0x348
#define QSERDES_V8_LALB_RX_IVCM_CAL_CODE_OVERRIDE_RATE4 0x34c
#define QSERDES_V8_LALB_RX_IVCM_CAL_CTRL1 0x350
#define QSERDES_V8_LALB_RX_IVCM_CAL_CTRL2 0x354
#define QSERDES_V8_LALB_RX_IVCM_CAL_CTRL3 0x358
#define QSERDES_V8_LALB_RX_IVCM_CAL_CTRL4 0x35c
#define QSERDES_V8_LALB_RX_IVCM_POSTCAL_OFFSET_RATE0 0x360
#define QSERDES_V8_LALB_RX_IVCM_POSTCAL_OFFSET_RATE1 0x364
#define QSERDES_V8_LALB_RX_IVCM_POSTCAL_OFFSET_RATE2 0x368
#define QSERDES_V8_LALB_RX_IVCM_POSTCAL_OFFSET_RATE3 0x36c
#define QSERDES_V8_LALB_RX_IVCM_POSTCAL_OFFSET_RATE4 0x370
#define QSERDES_V8_LALB_RX_IDAC_I0_DC_OFFSETS 0x374
#define QSERDES_V8_LALB_RX_IDAC_I0BAR_DC_OFFSETS 0x378
#define QSERDES_V8_LALB_RX_IDAC_I1_DC_OFFSETS 0x37c
#define QSERDES_V8_LALB_RX_IDAC_I1BAR_DC_OFFSETS 0x380
#define QSERDES_V8_LALB_RX_IDAC_Q_DC_OFFSETS 0x384
#define QSERDES_V8_LALB_RX_IDAC_QBAR_DC_OFFSETS 0x388
#define QSERDES_V8_LALB_RX_IDAC_A_DC_OFFSETS 0x38c
#define QSERDES_V8_LALB_RX_IDAC_ABAR_DC_OFFSETS 0x390
#define QSERDES_V8_LALB_RX_IDAC_EN 0x394
#define QSERDES_V8_LALB_DATA_SLICER_INIT_TIMER_CTRL 0x398
#define QSERDES_V8_LALB_RX_IDAC_ENABLES 0x39c
#define QSERDES_V8_LALB_RX_IDAC_SIGN 0x3a0
#define QSERDES_V8_LALB_RX_IDAC_TSETTLE 0x3a4
#define QSERDES_V8_LALB_SIGDET_ENABLES 0x3a8
#define QSERDES_V8_LALB_SIGDET_CNTRL 0x3ac
#define QSERDES_V8_LALB_SIGDET_LVL 0x3b0
#define QSERDES_V8_LALB_SIGDET_DEGLITCH_CNTRL 0x3b4
#define QSERDES_V8_LALB_SIGDET_CAL_CTRL1 0x3b8
#define QSERDES_V8_LALB_SIGDET_CAL_CTRL2_AND_CDR_LOCK_EDGE 0x3bc
#define QSERDES_V8_LALB_SIGDET_CAL_TRIM 0x3c0
#define QSERDES_V8_LALB_IA_OFFSET_CENTER_CAL_CTRL 0x3c4
#define QSERDES_V8_LALB_FREQ_LOCK_DET_DLY_RATE0 0x3c8
#define QSERDES_V8_LALB_FREQ_LOCK_DET_DLY_RATE1 0x3cc
#define QSERDES_V8_LALB_FREQ_LOCK_DET_DLY_RATE2 0x3d0
#define QSERDES_V8_LALB_FREQ_LOCK_DET_DLY_RATE3 0x3d4
#define QSERDES_V8_LALB_FREQ_LOCK_DET_DLY_RATE4 0x3d8
#define QSERDES_V8_LALB_CDR_PHASE_LOCK_CNT_RATE0 0x3dc
#define QSERDES_V8_LALB_CDR_PHASE_LOCK_CNT_RATE1 0x3e0
#define QSERDES_V8_LALB_CDR_PHASE_LOCK_CNT_RATE2 0x3e4
#define QSERDES_V8_LALB_CDR_PHASE_LOCK_CNT_RATE3 0x3e8
#define QSERDES_V8_LALB_CDR_PHASE_LOCK_CNT_RATE4 0x3ec
#define QSERDES_V8_LALB_CDR_LOCK_CTRL 0x3f0
#define QSERDES_V8_LALB_CDR_CP_CUR_FLL_RATE0 0x3f4
#define QSERDES_V8_LALB_CDR_CP_CUR_FLL_RATE1 0x3f8
#define QSERDES_V8_LALB_CDR_CP_CUR_FLL_RATE2 0x3fc
#define QSERDES_V8_LALB_CDR_CP_CUR_FLL_RATE3 0x400
#define QSERDES_V8_LALB_CDR_CP_CUR_FLL_RATE4 0x404
#define QSERDES_V8_LALB_CDR_CP_CUR_PLL_RATE0 0x408
#define QSERDES_V8_LALB_CDR_CP_CUR_PLL_RATE1 0x40c
#define QSERDES_V8_LALB_CDR_CP_CUR_PLL_RATE2 0x410
#define QSERDES_V8_LALB_CDR_CP_CUR_PLL_RATE3 0x414
#define QSERDES_V8_LALB_CDR_CP_CUR_PLL_RATE4 0x418
#define QSERDES_V8_LALB_CDR_FLL_DIV_RATIO_RATE_0123 0x41c
#define QSERDES_V8_LALB_CDR_FLL_DIV_RATIO_RATE4 0x420
#define QSERDES_V8_LALB_CDR_LOOP_CCODE_RATE_01 0x424
#define QSERDES_V8_LALB_CDR_LOOP_CCODE_RATE_23 0x428
#define QSERDES_V8_LALB_CDR_LOOP_CCODE_RATE4 0x42c
#define QSERDES_V8_LALB_CDR_LOOP_RCODE_FAST_RATE_0_1 0x430
#define QSERDES_V8_LALB_CDR_LOOP_RCODE_FAST_RATE_2_3 0x434
#define QSERDES_V8_LALB_CDR_LOOP_RCODE_FAST_RATE4 0x438
#define QSERDES_V8_LALB_CDR_LOOP_RCODE_FLL_RATE_0_1 0x43c
#define QSERDES_V8_LALB_CDR_LOOP_RCODE_FLL_RATE_2_3 0x440
#define QSERDES_V8_LALB_CDR_LOOP_RCODE_FLL_RATE4 0x444
#define QSERDES_V8_LALB_CDR_LOOP_RCODE_PLL_RATE_0_1 0x448
#define QSERDES_V8_LALB_CDR_LOOP_RCODE_PLL_RATE_2_3 0x44c
#define QSERDES_V8_LALB_CDR_LOOP_RCODE_PLL_RATE4 0x450
#define QSERDES_V8_LALB_CDR_VCO_CAP_CODE_RATE_0123 0x454
#define QSERDES_V8_LALB_CDR_VCO_CAP_CODE_RATE4 0x458
#define QSERDES_V8_LALB_CDR_VCO_TYPE_CONFIG 0x45c
#define QSERDES_V8_LALB_CDR_VCO_EN_LOWFREQ 0x460
#define QSERDES_V8_LALB_CDR_FAST_SLOW_VCO_OVRD 0x464
#define QSERDES_V8_LALB_CDR_LOOP_FUNC_CTRL 0x468
#define QSERDES_V8_LALB_CDR_FAST_LOCK_EN_CTRL 0x46c
#define QSERDES_V8_LALB_RX_RCVR_EN 0x470
#define QSERDES_V8_LALB_LANE_RATE_CTRL 0x474
#define QSERDES_V8_LALB_RX_TERM_RCVR_CTRL 0x478
#define QSERDES_V8_LALB_REC_DETECT_CTRL 0x47c
#define QSERDES_V8_LALB_RCV_DETECT_LVL 0x480
#define QSERDES_V8_LALB_GM_CAL_EN 0x484
#define QSERDES_V8_LALB_GM_CAL_RES_RATE0_1 0x488
#define QSERDES_V8_LALB_GM_CAL_RES_RATE2_3 0x48c
#define QSERDES_V8_LALB_GM_CAL_RES_RATE4 0x490
#define QSERDES_V8_LALB_RX_TERM_BW_RATE_0123 0x494
#define QSERDES_V8_LALB_RX_TERM_BW_RATE4 0x498
#define QSERDES_V8_LALB_AUX_CLK_CTRL 0x49c
#define QSERDES_V8_LALB_AUX_OFFSET_CONTROL 0x4a0
#define QSERDES_V8_LALB_AUXDATA_TB 0x4a4
#define QSERDES_V8_LALB_EOM_CTRL1 0x4a8
#define QSERDES_V8_LALB_EOM_CTRL2 0x4ac
#define QSERDES_V8_LALB_EOM_CTRL3 0x4b0
#define QSERDES_V8_LALB_EOM_CTRL4 0x4b4
#define QSERDES_V8_LALB_DFE_EN_TIMER 0x4b8
#define QSERDES_V8_LALB_RX_EQ_OFFSET_LSB 0x4bc
#define QSERDES_V8_LALB_RX_EQ_OFFSET_MSB 0x4c0
#define QSERDES_V8_LALB_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x4c4
#define QSERDES_V8_LALB_RX_OFFSET_ADAPTOR_CNTRL2 0x4c8
#define QSERDES_V8_LALB_RX_OFFSET_ADAPTOR_CNTRL3 0x4cc
#define QSERDES_V8_LALB_RX_EQU_ADAPTOR_CNTRL1 0x4d0
#define QSERDES_V8_LALB_RX_EQU_ADAPTOR_CNTRL2 0x4d4
#define QSERDES_V8_LALB_RX_EQU_ADAPTOR_CNTRL3 0x4d8
#define QSERDES_V8_LALB_RX_EQU_ADAPTOR_CNTRL4 0x4dc
#define QSERDES_V8_LALB_RX_EQU_ADAPTOR_CNTRL5 0x4e0
#define QSERDES_V8_LALB_RX_EQU_KEQ_UP_LSB 0x4e4
#define QSERDES_V8_LALB_RX_EQU_KEQ_UP_MSB 0x4e8
#define QSERDES_V8_LALB_RX_EQU_KEQ_DN_LSB 0x4ec
#define QSERDES_V8_LALB_RX_EQU_KEQ_DN_MSB 0x4f0
#define QSERDES_V8_LALB_CTLE_ADP_RESET_INIT_CODE_RATE_0_1_2 0x4f4
#define QSERDES_V8_LALB_CTLE_ADP_RESET_INIT_CODE_RATE_3_4 0x4f8
#define QSERDES_V8_LALB_CTLE_POST_CAL_OFFSET_RATE_0_1_2 0x4fc
#define QSERDES_V8_LALB_CTLE_POST_CAL_OFFSET_RATE_3_4 0x500
#define QSERDES_V8_LALB_RX_VGA_GAIN2_BLK1 0x504
#define QSERDES_V8_LALB_RX_VGA_GAIN2_BLK2 0x508
#define QSERDES_V8_LALB_VGA_CAL_CNTRL1 0x50c
#define QSERDES_V8_LALB_VGA_CAL_CNTRL2 0x510
#define QSERDES_V8_LALB_VGA_CAL_MAN_VAL_RATE0_1 0x514
#define QSERDES_V8_LALB_VGA_CAL_MAN_VAL_RATE2_3 0x518
#define QSERDES_V8_LALB_VGA_CAL_MAN_VAL_RATE4 0x51c
#define QSERDES_V8_LALB_KVGA_CTRL1 0x520
#define QSERDES_V8_LALB_KVGA_CTRL2 0x524
#define QSERDES_V8_LALB_VTHRESH_CAL_CNTRL1 0x528
#define QSERDES_V8_LALB_VTHRESH_CAL_CNTRL2 0x52c
#define QSERDES_V8_LALB_VTHRESH_CAL_MAN_VAL_RATE0 0x530
#define QSERDES_V8_LALB_VTHRESH_CAL_MAN_VAL_RATE1 0x534
#define QSERDES_V8_LALB_VTHRESH_CAL_MAN_VAL_RATE2 0x538
#define QSERDES_V8_LALB_VTHRESH_CAL_MAN_VAL_RATE3 0x53c
#define QSERDES_V8_LALB_VTHRESH_CAL_MAN_VAL_RATE4 0x540
#define QSERDES_V8_LALB_VTHRESH_CAL_MAN_CAL_PAM3 0x544
#define QSERDES_V8_LALB_VTH_POST_CAL_OFFSET_RATE_0_1 0x548
#define QSERDES_V8_LALB_VTH_POST_CAL_OFFSET_RATE_2_3 0x54c
#define QSERDES_V8_LALB_VTH_POST_CAL_OFFSET_RATE4 0x550
#define QSERDES_V8_LALB_DFE_TAP1_CTRL 0x554
#define QSERDES_V8_LALB_DFE_TAP1_MANVAL_KTAP 0x558
#define QSERDES_V8_LALB_DFE_TAP1_POST_CAL_OFFSET_RATE_0_1_2 0x55c
#define QSERDES_V8_LALB_DFE_TAP1_POST_CAL_OFFSET_RATE_3_4 0x560
#define QSERDES_V8_LALB_DFE_TAP2_CTRL 0x564
#define QSERDES_V8_LALB_DFE_TAP2_MANVAL_KTAP 0x568
#define QSERDES_V8_LALB_DFE_TAP3_CTRL 0x56c
#define QSERDES_V8_LALB_DFE_TAP3_MANVAL_KTAP 0x570
#define QSERDES_V8_LALB_DFE_TAP4_CTRL 0x574
#define QSERDES_V8_LALB_DFE_TAP4_MANVAL_KTAP 0x578
#define QSERDES_V8_LALB_DFE_TAP5_CTRL 0x57c
#define QSERDES_V8_LALB_DFE_TAP5_MANVAL_KTAP 0x580
#define QSERDES_V8_LALB_DFE_TAP6_CTRL 0x584
#define QSERDES_V8_LALB_DFE_TAP6_MANVAL_KTAP 0x588
#define QSERDES_V8_LALB_DFE_TAP7_CTRL 0x58c
#define QSERDES_V8_LALB_DFE_TAP7_MANVAL_KTAP 0x590
#define QSERDES_V8_LALB_DFE_TAP1_DAC_ENABLE 0x594
#define QSERDES_V8_LALB_DFE_TAP2_DAC_ENABLE 0x598
#define QSERDES_V8_LALB_DFE_TAP345_DAC_ENABLE 0x59c
#define QSERDES_V8_LALB_DFE_TAP67_DAC_ENABLE 0x5a0
#define QSERDES_V8_LALB_CDR_IQTUNE_CTRL 0x5a4
#define QSERDES_V8_LALB_CDR_IQTUNE_GAIN 0x5a8
#define QSERDES_V8_LALB_CDR_IQTUNE_MAN_INDEX 0x5ac
#define QSERDES_V8_LALB_CDR_IQTUNE_FILTER_CAL_CTRL1 0x5b0
#define QSERDES_V8_LALB_CDR_IQTUNE_FILTER_CAL_CTRL2 0x5b4
#define QSERDES_V8_LALB_CDR_IQTUNE_CLK0_CAL_CODE_RATE0 0x5b8
#define QSERDES_V8_LALB_CDR_IQTUNE_CLK0_CAL_CODE_RATE1 0x5bc
#define QSERDES_V8_LALB_CDR_IQTUNE_CLK0_CAL_CODE_RATE2 0x5c0
#define QSERDES_V8_LALB_CDR_IQTUNE_CLK0_CAL_CODE_RATE3 0x5c4
#define QSERDES_V8_LALB_CDR_IQTUNE_CLK0_CAL_CODE_RATE4 0x5c8
#define QSERDES_V8_LALB_CDR_IQTUNE_CLK90_CAL_CODE_RATE0 0x5cc
#define QSERDES_V8_LALB_CDR_IQTUNE_CLK90_CAL_CODE_RATE1 0x5d0
#define QSERDES_V8_LALB_CDR_IQTUNE_CLK90_CAL_CODE_RATE2 0x5d4
#define QSERDES_V8_LALB_CDR_IQTUNE_CLK90_CAL_CODE_RATE3 0x5d8
#define QSERDES_V8_LALB_CDR_IQTUNE_CLK90_CAL_CODE_RATE4 0x5dc
#define QSERDES_V8_LALB_CDR_IQTUNE_ANA_CTRL 0x5e0
#define QSERDES_V8_LALB_CDR_IQTUNE_VDCC_CTRL 0x5e4
#define QSERDES_V8_LALB_CDR_IQTUNE_DIV2_CTRL_RATE0123 0x5e8
#define QSERDES_V8_LALB_CDR_IQTUNE_DIV2_CTRL_RATE4 0x5ec
#define QSERDES_V8_LALB_BLW_CTRL 0x5f0
#define QSERDES_V8_LALB_BLW_ANA_VER_CTRL 0x5f4
#define QSERDES_V8_LALB_BLW_GAIN_CAL_CTRL 0x5f8
#define QSERDES_V8_LALB_BLW_GAIN_FORCE_CODE 0x5fc
#define QSERDES_V8_LALB_BLW_MAN_VAL_RATE3 0x600
#define QSERDES_V8_LALB_BLW_MAN_VAL_RATE4 0x604
#define QSERDES_V8_LALB_IVTH_CAL_CTRL1 0x608
#define QSERDES_V8_LALB_IVTH_CAL_CTRL2 0x60c
#define QSERDES_V8_LALB_IVTH_CAL_CTRL3 0x610
#define QSERDES_V8_LALB_VTH_I_UP_CNTRL_VAL 0x614
#define QSERDES_V8_LALB_VTH_I_DN_CNTRL_VAL 0x618
#define QSERDES_V8_LALB_NRZ_EYE_HEIGHT_SEL_VAL 0x61c
#define QSERDES_V8_LALB_IVTH_CAL_VAL_OVRD_MUX 0x620
#define QSERDES_V8_LALB_CDR_VCO_CAP_CODE_OVRD_MUXES 0x624
#define QSERDES_V8_LALB_VCO_CTUNE_LOWER_BND_RATE0 0x628
#define QSERDES_V8_LALB_VCO_CTUNE_LOWER_BND_RATE1 0x62c
#define QSERDES_V8_LALB_VCO_CTUNE_LOWER_BND_RATE2 0x630
#define QSERDES_V8_LALB_VCO_CTUNE_LOWER_BND_RATE3 0x634
#define QSERDES_V8_LALB_VCO_CTUNE_LOWER_BND_RATE4 0x638
#define QSERDES_V8_LALB_VCO_CTUNE_UPPER_BND_RATE0 0x63c
#define QSERDES_V8_LALB_VCO_CTUNE_UPPER_BND_RATE1 0x640
#define QSERDES_V8_LALB_VCO_CTUNE_UPPER_BND_RATE2 0x644
#define QSERDES_V8_LALB_VCO_CTUNE_UPPER_BND_RATE3 0x648
#define QSERDES_V8_LALB_VCO_CTUNE_UPPER_BND_RATE4 0x64c
#define QSERDES_V8_LALB_CDR_LOCK_KVCO_OFFSET_RATE0 0x650
#define QSERDES_V8_LALB_CDR_LOCK_KVCO_OFFSET_RATE1 0x654
#define QSERDES_V8_LALB_CDR_LOCK_KVCO_OFFSET_RATE2 0x658
#define QSERDES_V8_LALB_CDR_LOCK_KVCO_OFFSET_RATE3 0x65c
#define QSERDES_V8_LALB_CDR_LOCK_KVCO_OFFSET_RATE4 0x660
#define QSERDES_V8_LALB_CDR_LOCK_KP_OFFSET_RATE0 0x664
#define QSERDES_V8_LALB_CDR_LOCK_KP_OFFSET_RATE1 0x668
#define QSERDES_V8_LALB_CDR_LOCK_KP_OFFSET_RATE2 0x66c
#define QSERDES_V8_LALB_CDR_LOCK_KP_OFFSET_RATE3 0x670
#define QSERDES_V8_LALB_CDR_LOCK_KP_OFFSET_RATE4 0x674
#define QSERDES_V8_LALB_CDR_FASTLOCK_CP_CUR_PLL_RATE0 0x678
#define QSERDES_V8_LALB_CDR_FASTLOCK_CP_CUR_PLL_RATE1 0x67c
#define QSERDES_V8_LALB_CDR_FASTLOCK_CP_CUR_PLL_RATE2 0x680
#define QSERDES_V8_LALB_CDR_FASTLOCK_CP_CUR_PLL_RATE3 0x684
#define QSERDES_V8_LALB_CDR_FASTLOCK_CP_CUR_PLL_RATE4 0x688
#define QSERDES_V8_LALB_DEBUG_BUS_SEL 0x68c
#define QSERDES_V8_LALB_BIST_STATUS 0x690
#define QSERDES_V8_LALB_BIST_ERROR_COUNT1 0x694
#define QSERDES_V8_LALB_BIST_ERROR_COUNT2 0x698
#define QSERDES_V8_LALB_AC_JTAG_OUTP 0x69c
#define QSERDES_V8_LALB_AC_JTAG_OUTN 0x6a0
#define QSERDES_V8_LALB_DATA_SLICER_DEBUG_STATUS 0x6a4
#define QSERDES_V8_LALB_DATA_SLICER_TIMER1_STATUS 0x6a8
#define QSERDES_V8_LALB_DATA_SLICER_TIMER2_STATUS 0x6ac
#define QSERDES_V8_LALB_TX0_RESTRIM_CODE_STATUS 0x6b0
#define QSERDES_V8_LALB_TX0_RESTRIM_ICAL_CODE_STATUS 0x6b4
#define QSERDES_V8_LALB_TX0_RESTRIM_CAL_STATUS 0x6b8
#define QSERDES_V8_LALB_TX1_RESTRIM_CODE_STATUS 0x6bc
#define QSERDES_V8_LALB_TX1_RESTRIM_ICAL_CODE_STATUS 0x6c0
#define QSERDES_V8_LALB_TX1_RESTRIM_CAL_STATUS 0x6c4
#define QSERDES_V8_LALB_CMUX_DCC_CAL_FSM_STATUS 0x6c8
#define QSERDES_V8_LALB_CMUX_DCC_READCODE_STATUS 0x6cc
#define QSERDES_V8_LALB_TX_DCC_CAL_ANA_STATUS 0x6d0
#define QSERDES_V8_LALB_TX0_CTUNE_DCC_FSM_DEBUG_STATUS 0x6d4
#define QSERDES_V8_LALB_TX0_COARSE_DCC_READCODE_STATUS 0x6d8
#define QSERDES_V8_LALB_TX0_FTUNE_MSB_DCC_FSM_DEBUG_STATUS 0x6dc
#define QSERDES_V8_LALB_TX0_FTUNE_LSB_DCC_FSM_DEBUG_STATUS 0x6e0
#define QSERDES_V8_LALB_TX0_FINE_DCC_READCODE_STATUS 0x6e4
#define QSERDES_V8_LALB_TX1_CTUNE_DCC_FSM_DEBUG_STATUS 0x6e8
#define QSERDES_V8_LALB_TX1_COARSE_DCC_READCODE_STATUS 0x6ec
#define QSERDES_V8_LALB_TX1_FTUNE_MSB_DCC_FSM_DEBUG_STATUS 0x6f0
#define QSERDES_V8_LALB_TX1_FTUNE_LSB_DCC_FSM_DEBUG_STATUS 0x6f4
#define QSERDES_V8_LALB_TX1_FINE_DCC_READCODE_STATUS 0x6f8
#define QSERDES_V8_LALB_CDR_VCO_CAL_STATUS 0x6fc
#define QSERDES_V8_LALB_CDR_VCTRL_STATUS 0x700
#define QSERDES_V8_LALB_CDR_VCO_CAP_CODE_STATUS 0x704
#define QSERDES_V8_LALB_KVCO_CAL_DEBUG1_STATUS 0x708
#define QSERDES_V8_LALB_KVCO_CAL_DEBUG2_STATUS 0x70c
#define QSERDES_V8_LALB_KP_CAL_DEBUG1_STATUS 0x710
#define QSERDES_V8_LALB_KP_CAL_DEBUG2_STATUS 0x714
#define QSERDES_V8_LALB_CDR_VCO_FREQ_DEBUG1_STATUS 0x718
#define QSERDES_V8_LALB_CDR_VCO_FREQ_DEBUG2_STATUS 0x71c
#define QSERDES_V8_LALB_CDR_VCO_FREQ_DEBUG3_STATUS 0x720
#define QSERDES_V8_LALB_CDR_VCO_FREQ_DEBUG4_STATUS 0x724
#define QSERDES_V8_LALB_IVCM_CAL_STATUS 0x728
#define QSERDES_V8_LALB_IVCM_CAL_DEBUG_STATUS 0x72c
#define QSERDES_V8_LALB_IDAC_STATUS_I0 0x730
#define QSERDES_V8_LALB_IDAC_STATUS_I0BAR 0x734
#define QSERDES_V8_LALB_IDAC_STATUS_I1 0x738
#define QSERDES_V8_LALB_IDAC_STATUS_I1BAR 0x73c
#define QSERDES_V8_LALB_IDAC_STATUS_Q 0x740
#define QSERDES_V8_LALB_IDAC_STATUS_QBAR 0x744
#define QSERDES_V8_LALB_IDAC_STATUS_A 0x748
#define QSERDES_V8_LALB_IDAC_STATUS_ABAR 0x74c
#define QSERDES_V8_LALB_IDAC_STATUS_SM_ON 0x750
#define QSERDES_V8_LALB_IDAC_STATUS_SIGNERROR 0x754
#define QSERDES_V8_LALB_RX_SIGDET_STATUS 0x758
#define QSERDES_V8_LALB_SIGDET_CAL_CODE_STATUS 0x75c
#define QSERDES_V8_LALB_SIGDET_CAL_FSM_DEBUG_STATUS 0x760
#define QSERDES_V8_LALB_CDR_FREQ_LOCK_CNT_STATUS 0x764
#define QSERDES_V8_LALB_CDR_PHASE_LOCK_CNT_STATUS 0x768
#define QSERDES_V8_LALB_CDR_LOCK_DEBUG_STATUS 0x76c
#define QSERDES_V8_LALB_IDATA_HIGH_STATUS1 0x770
#define QSERDES_V8_LALB_IDATA_HIGH_STATUS2 0x774
#define QSERDES_V8_LALB_IDATA_HIGH_STATUS3 0x778
#define QSERDES_V8_LALB_IDATA_HIGH_STATUS4 0x77c
#define QSERDES_V8_LALB_IDATA_LOW_STATUS1 0x780
#define QSERDES_V8_LALB_IDATA_LOW_STATUS2 0x784
#define QSERDES_V8_LALB_IDATA_LOW_STATUS3 0x788
#define QSERDES_V8_LALB_IDATA_LOW_STATUS4 0x78c
#define QSERDES_V8_LALB_QDATA_STATUS1 0x790
#define QSERDES_V8_LALB_QDATA_STATUS2 0x794
#define QSERDES_V8_LALB_QDATA_STATUS3 0x798
#define QSERDES_V8_LALB_QDATA_STATUS4 0x79c
#define QSERDES_V8_LALB_IA_ERROR_COUNTER_LOW 0x7a0
#define QSERDES_V8_LALB_IA_ERROR_COUNTER_HIGH 0x7a4
#define QSERDES_V8_LALB_EOM_ERR_CNT_LSB_STATUS 0x7a8
#define QSERDES_V8_LALB_EOM_ERR_CNT_MSB_STATUS 0x7ac
#define QSERDES_V8_LALB_EOM_OP_STATUS 0x7b0
#define QSERDES_V8_LALB_AUX_MIXER_INDEX_STATUS 0x7b4
#define QSERDES_V8_LALB_AUX_OFFSET_STATUS 0x7b8
#define QSERDES_V8_LALB_AUXDATA_TB_STATUS 0x7bc
#define QSERDES_V8_LALB_AUX_MIXER_CTRL_0_STATUS 0x7c0
#define QSERDES_V8_LALB_AUX_MIXER_CTRL_90_STATUS 0x7c4
#define QSERDES_V8_LALB_AUX_MIXER_CTRL_180_STATUS 0x7c8
#define QSERDES_V8_LALB_IQ_MIXER_INDEX_STATUS 0x7cc
#define QSERDES_V8_LALB_IQTUNE_FLTR_INDEX_STATUS 0x7d0
#define QSERDES_V8_LALB_IQ_MIXER_CTRL_0_STATUS 0x7d4
#define QSERDES_V8_LALB_IQ_MIXER_CTRL_90_STATUS 0x7d8
#define QSERDES_V8_LALB_IQ_MIXER_CTRL_180_STATUS 0x7dc
#define QSERDES_V8_LALB_READ_EQCODE 0x7e0
#define QSERDES_V8_LALB_READ_OFFSETCODE 0x7e4
#define QSERDES_V8_LALB_VGA_READ_CODE 0x7e8
#define QSERDES_V8_LALB_VTHRESH_READ_CODE 0x7ec
#define QSERDES_V8_LALB_DFE_TAP1_READ_CODE 0x7f0
#define QSERDES_V8_LALB_DFE_TAP2_READ_CODE 0x7f4
#define QSERDES_V8_LALB_DFE_TAP3_READ_CODE 0x7f8
#define QSERDES_V8_LALB_DFE_TAP4_READ_CODE 0x7fc
#define QSERDES_V8_LALB_DFE_TAP5_READ_CODE 0x800
#define QSERDES_V8_LALB_DFE_TAP6_READ_CODE 0x804
#define QSERDES_V8_LALB_DFE_TAP7_READ_CODE 0x808
#define QSERDES_V8_LALB_CDR_IQTUNE_FILTER_BIN_CODE 0x80c
#define QSERDES_V8_LALB_CDR_IQTUNE_FILTER_CLK0_CODE 0x810
#define QSERDES_V8_LALB_CDR_IQTUNE_FILTER_CLK90_CODE 0x814
#define QSERDES_V8_LALB_BLW_READ_CODE 0x818
#define QSERDES_V8_LALB_IA_OFFSET_CAL_DEBUG_STATUS 0x81c
#define QSERDES_V8_LALB_IA_OFFSET_CAL_STATUS 0x820
#define QSERDES_V8_LALB_IVTH_CAL_STATUS 0x824
#define QSERDES_V8_LALB_IVTH_NRZ_EYE_HEIGHT_STATUS 0x828
#define QSERDES_V8_LALB_IVTH_UPPER_EYE_MAX_STATUS 0x82c
#define QSERDES_V8_LALB_IVTH_UPPER_EYE_MIN_STATUS 0x830
#define QSERDES_V8_LALB_IVTH_LOWER_EYE_MAX_STATUS 0x834
#define QSERDES_V8_LALB_IVTH_LOWER_EYE_MIN_STATUS 0x838
#define QSERDES_V8_LALB_IVTH_UP_INIT_CTR_STATUS 0x83c
#define QSERDES_V8_LALB_VTH_I_UP_CNTRL_STATUS 0x840
#define QSERDES_V8_LALB_VTH_I_DN_CNTRL_STATUS 0x844
#define QSERDES_V8_LALB_NRZ_EYE_HEIGHT_SEL_STATUS 0x848
#define QSERDES_V8_LALB_DEBUG_BUS0 0x84c
#define QSERDES_V8_LALB_DEBUG_BUS1 0x850
#define QSERDES_V8_LALB_DEBUG_BUS2 0x854
#define QSERDES_V8_LALB_DEBUG_BUS3 0x858
#define QSERDES_V8_LALB_DIG_BKUP_CTRL1 0x85c
#define QSERDES_V8_LALB_DIG_BKUP_CTRL2 0x860
#define QSERDES_V8_LALB_DIG_BKUP_CTRL3 0x864
#define QSERDES_V8_LALB_DIG_BKUP_CTRL4 0x868
#define QSERDES_V8_LALB_DIG_BKUP_CTRL5 0x86c
#define QSERDES_V8_LALB_DIG_BKUP_CTRL6 0x870
#define QSERDES_V8_LALB_DIG_BKUP_CTRL7 0x874
#define QSERDES_V8_LALB_DIG_BKUP_CTRL8 0x878
#define QSERDES_V8_LALB_DIG_BKUP_CTRL9 0x87c
#define QSERDES_V8_LALB_DIG_BKUP_CTRL10 0x880
#define QSERDES_V8_LALB_DIG_BKUP_CTRL11 0x884
#define QSERDES_V8_LALB_DIG_BKUP_CTRL12 0x888
#define QSERDES_V8_LALB_DIG_BKUP_CTRL13 0x88c
#define QSERDES_V8_LALB_DIG_BKUP_CTRL14 0x890
#define QSERDES_V8_LALB_DIG_BKUP_CTRL15 0x894
#define QSERDES_V8_LALB_DIG_BKUP_CTRL16 0x898
#define QSERDES_V8_LALB_DIG_BKUP_CTRL17 0x89c
#define QSERDES_V8_LALB_DIG_BKUP_CTRL18 0x8a0
#define QSERDES_V8_LALB_DIG_BKUP_CTRL19 0x8a4
#define QSERDES_V8_LALB_DIG_BKUP_CTRL20 0x8a8
#define QSERDES_V8_LALB_DIG_BKUP_CTRL21 0x8ac
#define QSERDES_V8_LALB_DIG_BKUP_CTRL22 0x8b0
#define QSERDES_V8_LALB_DIG_BKUP_CTRL23 0x8b4
#define QSERDES_V8_LALB_DIG_BKUP_CTRL24 0x8b8
#define QSERDES_V8_LALB_DIG_BKUP_CTRL25 0x8bc
#define QSERDES_V8_LALB_DIG_BKUP_CTRL26 0x8c0
#define QSERDES_V8_LALB_DIG_BKUP_CTRL27 0x8c4
#define QSERDES_V8_LALB_DIG_BKUP_CTRL28 0x8c8
#define QSERDES_V8_LALB_DIG_BKUP_CTRL29 0x8cc
#define QSERDES_V8_LALB_DIG_BKUP_CTRL30 0x8d0
#define QSERDES_V8_LALB_DIG_BKUP_CTRL31 0x8d4
#define QSERDES_V8_LALB_DIG_BKUP_CTRL32 0x8d8
#define QSERDES_V8_LALB_DIG_BKUP_CTRL_V2_1 0x8dc
#define QSERDES_V8_LALB_DIG_BKUP_CTRL_V2_2 0x8e0
#define QSERDES_V8_LALB_DIG_BKUP_CTRL_V2_3 0x8e4
#define QSERDES_V8_LALB_DIG_BKUP_CTRL_V2_4 0x8e8
#define QSERDES_V8_LALB_DIG_BKUP_CTRL_V2_5 0x8ec
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS1 0x8f0
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS2 0x8f4
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS3 0x8f8
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS4 0x8fc
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS5 0x900
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS6 0x904
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS7 0x908
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS8 0x90c
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS9 0x910
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS10 0x914
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS11 0x918
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS12 0x91c
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS13 0x920
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS14 0x924
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS15 0x928
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS16 0x92c
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS17 0x930
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS18 0x934
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS19 0x938
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS20 0x93c
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS21 0x940
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS22 0x944
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS23 0x948
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS24 0x94c
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS25 0x950
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS26 0x954
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS27 0x958
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS28 0x95c
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS29 0x960
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS30 0x964
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS31 0x968
#define QSERDES_V8_LALB_DIG_BKUP_RO_BUS32 0x96c
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS1 0x970
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS2 0x974
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS3 0x978
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS4 0x97c
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS5 0x980
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS6 0x984
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS7 0x988
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS8 0x98c
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS9 0x990
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS10 0x994
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS11 0x998
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS12 0x99c
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS13 0x9a0
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS14 0x9a4
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS15 0x9a8
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS16 0x9ac
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS17 0x9b0
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS18 0x9b4
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS19 0x9b8
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS20 0x9bc
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS21 0x9c0
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS22 0x9c4
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS23 0x9c8
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS24 0x9cc
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS25 0x9d0
#define QSERDES_V8_LALB_DIG_BKUP_RO_V2_BUS26 0x9d4
#endif /* QCOM_PHY_QMP_QSERDES_V8_LALBH_ */

View file

@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_QSERDES_TXRX_PCIE_V8_H_
#define QCOM_PHY_QMP_QSERDES_TXRX_PCIE_V8_H_
#define QSERDES_V8_PCIE_TX_RES_CODE_LANE_OFFSET_TX 0x030
#define QSERDES_V8_PCIE_TX_RES_CODE_LANE_OFFSET_RX 0x034
#define QSERDES_V8_PCIE_TX_LANE_MODE_1 0x07c
#define QSERDES_V8_PCIE_TX_LANE_MODE_2 0x080
#define QSERDES_V8_PCIE_TX_LANE_MODE_3 0x084
#define QSERDES_V8_PCIE_TX_TRAN_DRVR_EMP_EN 0x0b4
#define QSERDES_V8_PCIE_TX_TX_BAND0 0x0e0
#define QSERDES_V8_PCIE_TX_TX_BAND1 0x0e4
#define QSERDES_V8_PCIE_TX_SEL_10B_8B 0x0f4
#define QSERDES_V8_PCIE_TX_SEL_20B_10B 0x0f8
#define QSERDES_V8_PCIE_TX_PARRATE_REC_DETECT_IDLE_EN 0x058
#define QSERDES_V8_PCIE_TX_TX_ADAPT_POST_THRESH1 0x118
#define QSERDES_V8_PCIE_TX_TX_ADAPT_POST_THRESH2 0x11c
#define QSERDES_V8_PCIE_TX_PHPRE_CTRL 0x128
#define QSERDES_V8_PCIE_TX_EQ_RCF_CTRL_RATE3 0x148
#define QSERDES_V8_PCIE_TX_EQ_RCF_CTRL_RATE4 0x14c
#define QSERDES_V8_PCIE_RX_UCDR_FO_GAIN_RATE4 0x0dc
#define QSERDES_V8_PCIE_RX_UCDR_SO_GAIN_RATE3 0x0ec
#define QSERDES_V8_PCIE_RX_UCDR_SO_GAIN_RATE4 0x0f0
#define QSERDES_V8_PCIE_RX_UCDR_PI_CONTROLS 0x0f4
#define QSERDES_V8_PCIE_RX_VGA_CAL_CNTRL1 0x170
#define QSERDES_V8_PCIE_RX_VGA_CAL_MAN_VAL 0x178
#define QSERDES_V8_PCIE_RX_RX_EQU_ADAPTOR_CNTRL4 0x1b4
#define QSERDES_V8_PCIE_RX_SIGDET_ENABLES 0x1d8
#define QSERDES_V8_PCIE_RX_SIGDET_LVL 0x1e0
#define QSERDES_V8_PCIE_RX_RXCLK_DIV2_CTRL 0x0b8
#define QSERDES_V8_PCIE_RX_RX_BAND_CTRL0 0x0bc
#define QSERDES_V8_PCIE_RX_RX_TERM_BW_CTRL0 0x0c4
#define QSERDES_V8_PCIE_RX_RX_TERM_BW_CTRL1 0x0c8
#define QSERDES_V8_PCIE_RX_SVS_MODE_CTRL 0x0b4
#define QSERDES_V8_PCIE_RX_UCDR_PI_CTRL1 0x058
#define QSERDES_V8_PCIE_RX_UCDR_PI_CTRL2 0x05c
#define QSERDES_V8_PCIE_RX_UCDR_SB2_THRESH2_RATE3 0x084
#define QSERDES_V8_PCIE_RX_UCDR_SB2_GAIN1_RATE3 0x098
#define QSERDES_V8_PCIE_RX_UCDR_SB2_GAIN2_RATE3 0x0ac
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE_0_1_B0 0x218
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE_0_1_B1 0x21c
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE_0_1_B2 0x220
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE_0_1_B4 0x228
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE_0_1_B7 0x234
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE3_B0 0x260
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE3_B1 0x264
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE3_B2 0x268
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE3_B3 0x26c
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE3_B4 0x270
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B0 0x284
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B1 0x288
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B2 0x28c
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B3 0x290
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B4 0x294
#define QSERDES_V8_PCIE_RX_RX_MODE_RATE4_SA_B5 0x298
#define QSERDES_V8_PCIE_RX_Q_PI_INTRINSIC_BIAS_RATE32 0x31c
#define QSERDES_V8_PCIE_RX_Q_PI_INTRINSIC_BIAS_RATE4 0x320
#define QSERDES_V8_PCIE_RX_EOM_MAX_ERR_LIMIT_LSB 0x11c
#define QSERDES_V8_PCIE_RX_EOM_MAX_ERR_LIMIT_MSB 0x120
#define QSERDES_V8_PCIE_RX_AUXDATA_BIN_RATE23 0x108
#define QSERDES_V8_PCIE_RX_AUXDATA_BIN_RATE4 0x10c
#define QSERDES_V8_PCIE_RX_VTHRESH_CAL_MAN_VAL_RATE3 0x198
#define QSERDES_V8_PCIE_RX_VTHRESH_CAL_MAN_VAL_RATE4 0x19c
#define QSERDES_V8_PCIE_RX_GM_CAL 0x1a0
#endif

View file

@ -0,0 +1,68 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_QSERDES_TXRX_V2_H_
#define QCOM_PHY_QMP_QSERDES_TXRX_V2_H_
/* Only for QMP V2 PHY - TX registers */
#define QSERDES_V2_TX_BIST_MODE_LANENO 0x000
#define QSERDES_V2_TX_CLKBUF_ENABLE 0x008
#define QSERDES_V2_TX_TX_EMP_POST1_LVL 0x00c
#define QSERDES_V2_TX_TX_DRV_LVL 0x01c
#define QSERDES_V2_TX_RESET_TSYNC_EN 0x024
#define QSERDES_V2_TX_PRE_STALL_LDO_BOOST_EN 0x028
#define QSERDES_V2_TX_TX_BAND 0x02c
#define QSERDES_V2_TX_SLEW_CNTL 0x030
#define QSERDES_V2_TX_INTERFACE_SELECT 0x034
#define QSERDES_V2_TX_RES_CODE_LANE_TX 0x03c
#define QSERDES_V2_TX_RES_CODE_LANE_RX 0x040
#define QSERDES_V2_TX_RES_CODE_LANE_OFFSET_TX 0x044
#define QSERDES_V2_TX_RES_CODE_LANE_OFFSET_RX 0x048
#define QSERDES_V2_TX_DEBUG_BUS_SEL 0x058
#define QSERDES_V2_TX_TRANSCEIVER_BIAS_EN 0x05c
#define QSERDES_V2_TX_HIGHZ_DRVR_EN 0x060
#define QSERDES_V2_TX_TX_POL_INV 0x064
#define QSERDES_V2_TX_PARRATE_REC_DETECT_IDLE_EN 0x068
#define QSERDES_V2_TX_LANE_MODE_1 0x08c
#define QSERDES_V2_TX_LANE_MODE_2 0x090
#define QSERDES_V2_TX_LANE_MODE_3 0x094
#define QSERDES_V2_TX_RCV_DETECT_LVL_2 0x0a4
#define QSERDES_V2_TX_TRAN_DRVR_EMP_EN 0x0c0
#define QSERDES_V2_TX_TX_INTERFACE_MODE 0x0c4
#define QSERDES_V2_TX_VMODE_CTRL1 0x0f0
/* Only for QMP V2 PHY - RX registers */
#define QSERDES_V2_RX_UCDR_FO_GAIN 0x008
#define QSERDES_V2_RX_UCDR_SO_GAIN_HALF 0x00c
#define QSERDES_V2_RX_UCDR_SO_GAIN 0x014
#define QSERDES_V2_RX_UCDR_SVS_SO_GAIN_HALF 0x024
#define QSERDES_V2_RX_UCDR_SVS_SO_GAIN_QUARTER 0x028
#define QSERDES_V2_RX_UCDR_SVS_SO_GAIN 0x02c
#define QSERDES_V2_RX_UCDR_FASTLOCK_FO_GAIN 0x030
#define QSERDES_V2_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034
#define QSERDES_V2_RX_UCDR_FASTLOCK_COUNT_LOW 0x03c
#define QSERDES_V2_RX_UCDR_FASTLOCK_COUNT_HIGH 0x040
#define QSERDES_V2_RX_UCDR_PI_CONTROLS 0x044
#define QSERDES_V2_RX_RX_TERM_BW 0x07c
#define QSERDES_V2_RX_VGA_CAL_CNTRL1 0x0bc
#define QSERDES_V2_RX_VGA_CAL_CNTRL2 0x0c0
#define QSERDES_V2_RX_RX_EQ_GAIN2_LSB 0x0c8
#define QSERDES_V2_RX_RX_EQ_GAIN2_MSB 0x0cc
#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL1 0x0d0
#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d4
#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL3 0x0d8
#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL4 0x0dc
#define QSERDES_V2_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x0f8
#define QSERDES_V2_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x0fc
#define QSERDES_V2_RX_SIGDET_ENABLES 0x100
#define QSERDES_V2_RX_SIGDET_CNTRL 0x104
#define QSERDES_V2_RX_SIGDET_LVL 0x108
#define QSERDES_V2_RX_SIGDET_DEGLITCH_CNTRL 0x10c
#define QSERDES_V2_RX_RX_BAND 0x110
#define QSERDES_V2_RX_RX_INTERFACE_MODE 0x11c
#define QSERDES_V2_RX_RX_MODE_00 0x164
#define QSERDES_V2_RX_RX_MODE_01 0x168
#endif

View file

@ -84,6 +84,68 @@ static const unsigned int ufsphy_v6_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V6_PCS_UFS_POWER_DOWN_CONTROL,
};
static const struct qmp_phy_init_tbl milos_ufsphy_serdes[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IETRIM, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IPTRIM, 0x17),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_INITVAL2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x82),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x98),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x32),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x0f),
};
static const struct qmp_phy_init_tbl milos_ufsphy_tx[] = {
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_LANE_MODE_1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x07),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_RX, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_FR_DCC_CTRL, 0xcc),
};
static const struct qmp_phy_init_tbl milos_ufsphy_rx[] = {
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE2, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x3e),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0, 0xce),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1, 0xce),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B2, 0x18),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B3, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B4, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B6, 0x60),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B3, 0x9e),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B6, 0x60),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B3, 0x9e),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B4, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B5, 0x36),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B8, 0x02),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_PI_CTRL1, 0x94),
};
static const struct qmp_phy_init_tbl milos_ufsphy_pcs[] = {
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x0b),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x68),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04),
};
static const struct qmp_phy_init_tbl msm8996_ufsphy_serdes[] = {
QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xd7),
@ -1165,6 +1227,11 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
}
/* Regulator bulk data with load values for specific configurations */
static const struct regulator_bulk_data milos_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 140120 },
{ .supply = "vdda-pll", .init_load_uA = 18340 },
};
static const struct regulator_bulk_data msm8996_ufsphy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 51400 },
{ .supply = "vdda-pll", .init_load_uA = 14600 },
@ -1258,6 +1325,32 @@ static const struct qmp_ufs_offsets qmp_ufs_offsets_v6 = {
.rx2 = 0x1a00,
};
static const struct qmp_phy_cfg milos_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets_v6,
.max_supported_gear = UFS_HS_G4,
.tbls = {
.serdes = milos_ufsphy_serdes,
.serdes_num = ARRAY_SIZE(milos_ufsphy_serdes),
.tx = milos_ufsphy_tx,
.tx_num = ARRAY_SIZE(milos_ufsphy_tx),
.rx = milos_ufsphy_rx,
.rx_num = ARRAY_SIZE(milos_ufsphy_rx),
.pcs = milos_ufsphy_pcs,
.pcs_num = ARRAY_SIZE(milos_ufsphy_pcs),
},
.tbls_hs_b = {
.serdes = sm8550_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sm8550_ufsphy_hs_b_serdes),
},
.vreg_list = milos_ufsphy_vreg_l,
.num_vregs = ARRAY_SIZE(milos_ufsphy_vreg_l),
.regs = ufsphy_v6_regs_layout,
};
static const struct qmp_phy_cfg msm8996_ufsphy_cfg = {
.lanes = 1,
@ -2166,6 +2259,9 @@ err_node_put:
static const struct of_device_id qmp_ufs_of_match_table[] = {
{
.compatible = "qcom,milos-qmp-ufs-phy",
.data = &milos_ufsphy_cfg,
}, {
.compatible = "qcom,msm8996-qmp-ufs-phy",
.data = &msm8996_ufsphy_cfg,
}, {

View file

@ -28,6 +28,7 @@
#include "phy-qcom-qmp-pcs-usb-v5.h"
#include "phy-qcom-qmp-pcs-usb-v6.h"
#include "phy-qcom-qmp-pcs-usb-v7.h"
#include "phy-qcom-qmp-pcs-usb-v8.h"
#define PHY_INIT_COMPLETE_TIMEOUT 10000
@ -109,6 +110,139 @@ static const unsigned int qmp_v7_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V7_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR,
};
static const struct qmp_phy_init_tbl glymur_usb3_uniphy_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE1_MODE1, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE2_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_MODE1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_MODE1, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CORECLK_DIV_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP1_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP2_MODE1, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MODE1, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MSB_MODE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START1_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START2_MODE1, 0x75),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START3_MODE1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_HSCLK_SEL_1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE1_MODE1, 0x25),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE2_MODE1, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x5c),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x5c),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE1_MODE0, 0xc0),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_STEP_SIZE2_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CP_CTRL_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP1_MODE0, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP2_MODE0, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MODE0, 0x41),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DEC_START_MSB_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START1_MODE0, 0x55),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START2_MODE0, 0x75),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_DIV_FRAC_START3_MODE0, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE1_MODE0, 0x25),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_BG_TIMER, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_PER1, 0x62),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SSC_PER2, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SYSCLK_BUF_ENABLE, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_SYSCLK_EN_SEL, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_LOCK_CMP_CFG, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_VCO_TUNE_MAP, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CORE_CLK_EN, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_1, 0xb6),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_2, 0x4a),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_AUTO_GAIN_ADJ_CTRL_3, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V8_COM_ADDITIONAL_MISC, 0x0c),
};
static const struct qmp_phy_init_tbl glymur_usb3_uniphy_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG1, 0xc4),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG2, 0x89),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG3, 0x20),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_LOCK_DETECT_CONFIG6, 0x13),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_REFGEN_REQ_CONFIG1, 0x21),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_RX_SIGDET_LVL, 0x55),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_CDR_RESET_TIME, 0x0a),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_ALIGN_DETECT_CONFIG1, 0xd4),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_ALIGN_DETECT_CONFIG2, 0x30),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_PCS_TX_RX_CONFIG, 0x0c),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_EQ_CONFIG1, 0x4b),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_EQ_CONFIG5, 0x10),
};
static const struct qmp_phy_init_tbl glymur_usb3_uniphy_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_TX, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_RX, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_OFFSET_TX, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V8_TX_RES_CODE_LANE_OFFSET_RX, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_1, 0xf5),
QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_3, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_4, 0x30),
QMP_PHY_INIT_CFG(QSERDES_V8_TX_LANE_MODE_5, 0x5f),
QMP_PHY_INIT_CFG(QSERDES_V8_TX_RCV_DETECT_LVL_2, 0x12),
QMP_PHY_INIT_CFG(QSERDES_V8_TX_PI_QEC_CTRL, 0x21),
};
static const struct qmp_phy_init_tbl glymur_usb3_uniphy_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FO_GAIN, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SO_GAIN, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_PI_CONTROLS, 0x99),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_THRESH1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_THRESH2, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_GAIN1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_UCDR_SB2_GAIN2, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_AUX_DATA_TCOARSE_TFINE, 0x20),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_VGA_CAL_CNTRL1, 0x54),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_VGA_CAL_CNTRL2, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_GM_CAL, 0x1b),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_IDAC_TSETTLE_LOW, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_ENABLES, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_CNTRL, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_DEGLITCH_CNTRL, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_LOW, 0xbf),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH, 0xbf),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH2, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH3, 0xdf),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_00_HIGH4, 0xed),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_LOW, 0x19),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH2, 0x91),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH3, 0xb7),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_RX_MODE_01_HIGH4, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_DFE_EN_TIMER, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_DCC_CTRL1, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_VTH_CODE, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_CAL_CTRL1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V8_RX_SIGDET_CAL_TRIM, 0x08),
};
static const struct qmp_phy_init_tbl glymur_usb3_uniphy_pcs_usb_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_RXEQTRAINING_DFE_TIME_S2, 0x07),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_RXEQTRAINING_WAIT_TIME, 0x75),
QMP_PHY_INIT_CFG(QPHY_V8_PCS_USB_RCVR_DTCT_DLY_U3_L, 0x40),
};
static const struct qmp_phy_init_tbl ipq9574_usb3_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
@ -1266,7 +1400,7 @@ struct qmp_phy_cfg {
int pcs_usb_tbl_num;
/* regulators to be requested */
const char * const *vreg_list;
const struct regulator_bulk_data *vreg_list;
int num_vregs;
/* array of registers with different offsets */
@ -1344,8 +1478,9 @@ static const char * const usb3phy_reset_l[] = {
};
/* list of regulators */
static const char * const qmp_phy_vreg_l[] = {
"vdda-phy", "vdda-pll",
static const struct regulator_bulk_data qmp_phy_vreg_l[] = {
{ .supply = "vdda-phy", .init_load_uA = 21800, },
{ .supply = "vdda-pll", .init_load_uA = 36000, },
};
static const struct qmp_usb_offsets qmp_usb_offsets_v3 = {
@ -1403,6 +1538,14 @@ static const struct qmp_usb_offsets qmp_usb_offsets_v7 = {
.rx = 0x1000,
};
static const struct qmp_usb_offsets qmp_usb_offsets_v8 = {
.serdes = 0,
.pcs = 0x0400,
.pcs_usb = 0x1200,
.tx = 0x0e00,
.rx = 0x1000,
};
static const struct qmp_phy_cfg ipq6018_usb3phy_cfg = {
.offsets = &qmp_usb_offsets_v3,
@ -1704,6 +1847,24 @@ static const struct qmp_phy_cfg x1e80100_usb3_uniphy_cfg = {
.regs = qmp_v7_usb3phy_regs_layout,
};
static const struct qmp_phy_cfg glymur_usb3_uniphy_cfg = {
.offsets = &qmp_usb_offsets_v8,
.serdes_tbl = glymur_usb3_uniphy_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(glymur_usb3_uniphy_serdes_tbl),
.tx_tbl = glymur_usb3_uniphy_tx_tbl,
.tx_tbl_num = ARRAY_SIZE(glymur_usb3_uniphy_tx_tbl),
.rx_tbl = glymur_usb3_uniphy_rx_tbl,
.rx_tbl_num = ARRAY_SIZE(glymur_usb3_uniphy_rx_tbl),
.pcs_tbl = glymur_usb3_uniphy_pcs_tbl,
.pcs_tbl_num = ARRAY_SIZE(glymur_usb3_uniphy_pcs_tbl),
.pcs_usb_tbl = glymur_usb3_uniphy_pcs_usb_tbl,
.pcs_usb_tbl_num = ARRAY_SIZE(glymur_usb3_uniphy_pcs_usb_tbl),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = qmp_v7_usb3phy_regs_layout,
};
static int qmp_usb_serdes_init(struct qmp_usb *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@ -1986,23 +2147,6 @@ static const struct dev_pm_ops qmp_usb_pm_ops = {
qmp_usb_runtime_resume, NULL)
};
static int qmp_usb_vreg_init(struct qmp_usb *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
int num = cfg->num_vregs;
int i;
qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
if (!qmp->vregs)
return -ENOMEM;
for (i = 0; i < num; i++)
qmp->vregs[i].supply = cfg->vreg_list[i];
return devm_regulator_bulk_get(dev, num, qmp->vregs);
}
static int qmp_usb_reset_init(struct qmp_usb *qmp,
const char *const *reset_list,
int num_resets)
@ -2251,7 +2395,8 @@ static int qmp_usb_probe(struct platform_device *pdev)
if (!qmp->cfg)
return -EINVAL;
ret = qmp_usb_vreg_init(qmp);
ret = devm_regulator_bulk_get_const(dev, qmp->cfg->num_vregs,
qmp->cfg->vreg_list, &qmp->vregs);
if (ret)
return ret;
@ -2302,6 +2447,9 @@ err_node_put:
static const struct of_device_id qmp_usb_of_match_table[] = {
{
.compatible = "qcom,glymur-qmp-usb3-uni-phy",
.data = &glymur_usb3_uniphy_cfg,
}, {
.compatible = "qcom,ipq5424-qmp-usb3-phy",
.data = &ipq9574_usb3phy_cfg,
}, {

View file

@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_USB43_PCS_V8_H_
#define QCOM_PHY_QMP_USB43_PCS_V8_H_
#define QPHY_V8_USB43_PCS_SW_RESET 0x000
#define QPHY_V8_USB43_PCS_PCS_STATUS1 0x014
#define QPHY_V8_USB43_PCS_POWER_DOWN_CONTROL 0x040
#define QPHY_V8_USB43_PCS_START_CONTROL 0x044
#define QPHY_V8_USB43_PCS_POWER_STATE_CONFIG1 0x090
#define QPHY_V8_USB43_PCS_LOCK_DETECT_CONFIG1 0x0c4
#define QPHY_V8_USB43_PCS_LOCK_DETECT_CONFIG2 0x0c8
#define QPHY_V8_USB43_PCS_LOCK_DETECT_CONFIG3 0x0cc
#define QPHY_V8_USB43_PCS_LOCK_DETECT_CONFIG6 0x0d8
#define QPHY_V8_USB43_PCS_REFGEN_REQ_CONFIG1 0x0dc
#define QPHY_V8_USB43_PCS_RX_SIGDET_LVL 0x188
#define QPHY_V8_USB43_PCS_RCVR_DTCT_DLY_P1U2_L 0x190
#define QPHY_V8_USB43_PCS_RCVR_DTCT_DLY_P1U2_H 0x194
#define QPHY_V8_USB43_PCS_RATE_SLEW_CNTRL1 0x198
#define QPHY_V8_USB43_PCS_TSYNC_RSYNC_TIME 0x1ac
#define QPHY_V8_USB43_PCS_RX_CONFIG 0x1b0
#define QPHY_V8_USB43_PCS_TSYNC_DLY_TIME 0x1b4
#define QPHY_V8_USB43_PCS_ALIGN_DETECT_CONFIG1 0x1c0
#define QPHY_V8_USB43_PCS_ALIGN_DETECT_CONFIG2 0x1c4
#define QPHY_V8_USB43_PCS_PCS_TX_RX_CONFIG 0x1d0
#define QPHY_V8_USB43_PCS_EQ_CONFIG1 0x1dc
#define QPHY_V8_USB43_PCS_EQ_CONFIG2 0x1e0
#define QPHY_V8_USB43_PCS_EQ_CONFIG5 0x1ec
#endif

View file

@ -0,0 +1,224 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef QCOM_PHY_QMP_USB43_QSERDES_COM_V8_H_
#define QCOM_PHY_QMP_USB43_QSERDES_COM_V8_H_
#define QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE1 0x000
#define QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE1 0x004
#define QSERDES_V8_USB43_COM_SSC_STEP_SIZE3_MODE1 0x008
#define QSERDES_V8_USB43_COM_CLK_EP_DIV_MODE1 0x00c
#define QSERDES_V8_USB43_COM_CP_CTRL_MODE1 0x010
#define QSERDES_V8_USB43_COM_PLL_RCTRL_MODE1 0x014
#define QSERDES_V8_USB43_COM_PLL_CCTRL_MODE1 0x018
#define QSERDES_V8_USB43_COM_CORECLK_DIV_MODE1 0x01c
#define QSERDES_V8_USB43_COM_LOCK_CMP1_MODE1 0x020
#define QSERDES_V8_USB43_COM_LOCK_CMP2_MODE1 0x024
#define QSERDES_V8_USB43_COM_DEC_START_MODE1 0x028
#define QSERDES_V8_USB43_COM_DEC_START_MSB_MODE1 0x02c
#define QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE1 0x030
#define QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE1 0x034
#define QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE1 0x038
#define QSERDES_V8_USB43_COM_HSCLK_SEL_1 0x03c
#define QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE1 0x040
#define QSERDES_V8_USB43_COM_INTEGLOOP_GAIN1_MODE1 0x044
#define QSERDES_V8_USB43_COM_VCO_TUNE1_MODE1 0x048
#define QSERDES_V8_USB43_COM_VCO_TUNE2_MODE1 0x04c
#define QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE1 0x050
#define QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x054
#define QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x058
#define QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x05c
#define QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE0 0x060
#define QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE0 0x064
#define QSERDES_V8_USB43_COM_SSC_STEP_SIZE3_MODE0 0x068
#define QSERDES_V8_USB43_COM_CLK_EP_DIV_MODE0 0x06c
#define QSERDES_V8_USB43_COM_CP_CTRL_MODE0 0x070
#define QSERDES_V8_USB43_COM_PLL_RCTRL_MODE0 0x074
#define QSERDES_V8_USB43_COM_PLL_CCTRL_MODE0 0x078
#define QSERDES_V8_USB43_COM_CORECLK_DIV_MODE0 0x07c
#define QSERDES_V8_USB43_COM_LOCK_CMP1_MODE0 0x080
#define QSERDES_V8_USB43_COM_LOCK_CMP2_MODE0 0x084
#define QSERDES_V8_USB43_COM_DEC_START_MODE0 0x088
#define QSERDES_V8_USB43_COM_DEC_START_MSB_MODE0 0x08c
#define QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE0 0x090
#define QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE0 0x094
#define QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE0 0x098
#define QSERDES_V8_USB43_COM_HSCLK_HS_SWITCH_SEL_1 0x09c
#define QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE0 0x0a0
#define QSERDES_V8_USB43_COM_INTEGLOOP_GAIN1_MODE0 0x0a4
#define QSERDES_V8_USB43_COM_VCO_TUNE1_MODE0 0x0a8
#define QSERDES_V8_USB43_COM_VCO_TUNE2_MODE0 0x0ac
#define QSERDES_V8_USB43_COM_ATB_SEL1 0x0b0
#define QSERDES_V8_USB43_COM_ATB_SEL2 0x0b4
#define QSERDES_V8_USB43_COM_FREQ_UPDATE 0x0b8
#define QSERDES_V8_USB43_COM_BG_TIMER 0x0bc
#define QSERDES_V8_USB43_COM_SSC_EN_CENTER 0x0c0
#define QSERDES_V8_USB43_COM_SSC_ADJ_PER1 0x0c4
#define QSERDES_V8_USB43_COM_SSC_ADJ_PER2 0x0c8
#define QSERDES_V8_USB43_COM_SSC_PER1 0x0cc
#define QSERDES_V8_USB43_COM_SSC_PER2 0x0d0
#define QSERDES_V8_USB43_COM_POST_DIV 0x0d4
#define QSERDES_V8_USB43_COM_POST_DIV_MUX 0x0d8
#define QSERDES_V8_USB43_COM_BIAS_EN_CLKBUFLR_EN 0x0dc
#define QSERDES_V8_USB43_COM_CLK_ENABLE1 0x0e0
#define QSERDES_V8_USB43_COM_SYS_CLK_CTRL 0x0e4
#define QSERDES_V8_USB43_COM_SYSCLK_BUF_ENABLE 0x0e8
#define QSERDES_V8_USB43_COM_PLL_EN 0x0ec
#define QSERDES_V8_USB43_COM_DEBUG_BUS_OVRD 0x0f0
#define QSERDES_V8_USB43_COM_PLL_IVCO 0x0f4
#define QSERDES_V8_USB43_COM_PLL_IVCO_MODE1 0x0f8
#define QSERDES_V8_USB43_COM_CMN_IETRIM 0x0fc
#define QSERDES_V8_USB43_COM_CMN_IPTRIM 0x100
#define QSERDES_V8_USB43_COM_EP_CLOCK_DETECT_CTRL 0x104
#define QSERDES_V8_USB43_COM_PLL_CNTRL 0x108
#define QSERDES_V8_USB43_COM_BIAS_EN_CTRL_BY_PSM 0x10c
#define QSERDES_V8_USB43_COM_SYSCLK_EN_SEL 0x110
#define QSERDES_V8_USB43_COM_CML_SYSCLK_SEL 0x114
#define QSERDES_V8_USB43_COM_RESETSM_CNTRL 0x118
#define QSERDES_V8_USB43_COM_RESETSM_CNTRL2 0x11c
#define QSERDES_V8_USB43_COM_LOCK_CMP_EN 0x120
#define QSERDES_V8_USB43_COM_LOCK_CMP_CFG 0x124
#define QSERDES_V8_USB43_COM_INTEGLOOP_INITVAL 0x128
#define QSERDES_V8_USB43_COM_INTEGLOOP_EN 0x12c
#define QSERDES_V8_USB43_COM_INTEGLOOP_P_PATH_GAIN0 0x130
#define QSERDES_V8_USB43_COM_INTEGLOOP_P_PATH_GAIN1 0x134
#define QSERDES_V8_USB43_COM_VCOCAL_DEADMAN_CTRL 0x138
#define QSERDES_V8_USB43_COM_VCO_TUNE_CTRL 0x13c
#define QSERDES_V8_USB43_COM_VCO_TUNE_MAP 0x140
#define QSERDES_V8_USB43_COM_VCO_TUNE_INITVAL1 0x144
#define QSERDES_V8_USB43_COM_VCO_TUNE_INITVAL2 0x148
#define QSERDES_V8_USB43_COM_VCO_TUNE_MINVAL1 0x14c
#define QSERDES_V8_USB43_COM_VCO_TUNE_MINVAL2 0x150
#define QSERDES_V8_USB43_COM_VCO_TUNE_MAXVAL1 0x154
#define QSERDES_V8_USB43_COM_VCO_TUNE_MAXVAL2 0x158
#define QSERDES_V8_USB43_COM_VCO_TUNE_TIMER1 0x15c
#define QSERDES_V8_USB43_COM_VCO_TUNE_TIMER2 0x160
#define QSERDES_V8_USB43_COM_CLK_SELECT 0x164
#define QSERDES_V8_USB43_COM_PLL_ANALOG 0x168
#define QSERDES_V8_USB43_COM_SW_RESET 0x16c
#define QSERDES_V8_USB43_COM_CORE_CLK_EN 0x170
#define QSERDES_V8_USB43_COM_CMN_CONFIG_1 0x174
#define QSERDES_V8_USB43_COM_CMN_CONFIG_3 0x178
#define QSERDES_V8_USB43_COM_CMN_RATE_OVERRIDE 0x17c
#define QSERDES_V8_USB43_COM_SVS_MODE_CLK_SEL 0x180
#define QSERDES_V8_USB43_COM_DEBUG_BUS_SEL 0x184
#define QSERDES_V8_USB43_COM_CMN_MISC1 0x188
#define QSERDES_V8_USB43_COM_CMN_MODE 0x18c
#define QSERDES_V8_USB43_COM_CMN_MODE_CONTD 0x190
#define QSERDES_V8_USB43_COM_CMN_MODE_CONTD1 0x194
#define QSERDES_V8_USB43_COM_CMN_MODE_CONTD2 0x198
#define QSERDES_V8_USB43_COM_VCO_DC_LEVEL_CTRL 0x19c
#define QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_1 0x1a0
#define QSERDES_V8_USB43_COM_ADDITIONAL_CTRL_1 0x1a4
#define QSERDES_V8_USB43_COM_AUTO_GAIN_ADJ_CTRL_1 0x1a8
#define QSERDES_V8_USB43_COM_AUTO_GAIN_ADJ_CTRL_2 0x1ac
#define QSERDES_V8_USB43_COM_AUTO_GAIN_ADJ_CTRL_3 0x1b0
#define QSERDES_V8_USB43_COM_AUTO_GAIN_ADJ_CTRL_4 0x1b4
#define QSERDES_V8_USB43_COM_ADDITIONAL_MISC 0x1b8
#define QSERDES_V8_USB43_COM_ADDITIONAL_MISC_2 0x1bc
#define QSERDES_V8_USB43_COM_ADDITIONAL_MISC_3 0x1c0
#define QSERDES_V8_USB43_COM_ADDITIONAL_MISC_4 0x1c4
#define QSERDES_V8_USB43_COM_ADDITIONAL_MISC_5 0x1c8
#define QSERDES_V8_USB43_COM_SSC_STEP_SIZE1_MODE2 0x1cc
#define QSERDES_V8_USB43_COM_SSC_STEP_SIZE2_MODE2 0x1d0
#define QSERDES_V8_USB43_COM_SSC_STEP_SIZE3_MODE2 0x1d4
#define QSERDES_V8_USB43_COM_CLK_EP_DIV_MODE2 0x1d8
#define QSERDES_V8_USB43_COM_CP_CTRL_MODE2 0x1dc
#define QSERDES_V8_USB43_COM_PLL_RCTRL_MODE2 0x1e0
#define QSERDES_V8_USB43_COM_PLL_CCTRL_MODE2 0x1e4
#define QSERDES_V8_USB43_COM_CORECLK_DIV_MODE2 0x1e8
#define QSERDES_V8_USB43_COM_LOCK_CMP1_MODE2 0x1ec
#define QSERDES_V8_USB43_COM_LOCK_CMP2_MODE2 0x1f0
#define QSERDES_V8_USB43_COM_DEC_START_MODE2 0x1f4
#define QSERDES_V8_USB43_COM_DEC_START_MSB_MODE2 0x1f8
#define QSERDES_V8_USB43_COM_DIV_FRAC_START1_MODE2 0x1fc
#define QSERDES_V8_USB43_COM_DIV_FRAC_START2_MODE2 0x200
#define QSERDES_V8_USB43_COM_DIV_FRAC_START3_MODE2 0x204
#define QSERDES_V8_USB43_COM_INTEGLOOP_GAIN0_MODE2 0x208
#define QSERDES_V8_USB43_COM_INTEGLOOP_GAIN1_MODE2 0x20c
#define QSERDES_V8_USB43_COM_VCO_TUNE1_MODE2 0x210
#define QSERDES_V8_USB43_COM_VCO_TUNE2_MODE2 0x214
#define QSERDES_V8_USB43_COM_PLL_IVCO_MODE2 0x218
#define QSERDES_V8_USB43_COM_HSCLK_SEL_2 0x21c
#define QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE1_MODE2 0x220
#define QSERDES_V8_USB43_COM_BIN_VCOCAL_CMP_CODE2_MODE2 0x224
#define QSERDES_V8_USB43_COM_HSCLK_HS_SWITCH_SEL_2 0x228
#define QSERDES_V8_USB43_COM_CMN_CONFIG_2 0x22c
#define QSERDES_V8_USB43_COM_BIN_VCOCAL_HSCLK_SEL_2 0x230
#define QSERDES_V8_USB43_COM_IVCOCAL_CONFIG_0 0x234
#define QSERDES_V8_USB43_COM_IVCOCAL_CONFIG_1 0x238
#define QSERDES_V8_USB43_COM_IVCOCAL_CONFIG_2 0x23c
#define QSERDES_V8_USB43_COM_IVCOCAL_CONFIG_3 0x240
#define QSERDES_V8_USB43_COM_IVCOCAL_CONFIG_4 0x244
#define QSERDES_V8_USB43_COM_IVCOCAL_CONFIG_5 0x248
#define QSERDES_V8_USB43_COM_LOCK_CMP1_EARLY_MODE0 0x24c
#define QSERDES_V8_USB43_COM_LOCK_CMP2_EARLY_MODE0 0x250
#define QSERDES_V8_USB43_COM_LOCK_CMP1_EARLY_MODE1 0x254
#define QSERDES_V8_USB43_COM_LOCK_CMP2_EARLY_MODE1 0x258
#define QSERDES_V8_USB43_COM_LOCK_CMP1_EARLY_MODE2 0x25c
#define QSERDES_V8_USB43_COM_LOCK_CMP2_EARLY_MODE2 0x260
#define QSERDES_V8_USB43_COM_EARLY_LOCK_CONFIG_0 0x264
#define QSERDES_V8_USB43_COM_EARLY_LOCK_CONFIG_1 0x268
#define QSERDES_V8_USB43_COM_ADAPTIVE_ANALOG_CONFIG 0x26c
#define QSERDES_V8_USB43_COM_CP_CTRL_ADAPTIVE_MODE0 0x270
#define QSERDES_V8_USB43_COM_PLL_RCCTRL_ADAPTIVE_MODE0 0x274
#define QSERDES_V8_USB43_COM_PLL_CCTRL_ADAPTIVE_MODE0 0x278
#define QSERDES_V8_USB43_COM_CP_CTRL_ADAPTIVE_MODE1 0x27c
#define QSERDES_V8_USB43_COM_PLL_RCCTRL_ADAPTIVE_MODE1 0x280
#define QSERDES_V8_USB43_COM_PLL_CCTRL_ADAPTIVE_MODE1 0x284
#define QSERDES_V8_USB43_COM_CP_CTRL_ADAPTIVE_MODE2 0x288
#define QSERDES_V8_USB43_COM_PLL_RCCTRL_ADAPTIVE_MODE2 0x28c
#define QSERDES_V8_USB43_COM_PLL_CCTRL_ADAPTIVE_MODE2 0x290
#define QSERDES_V8_USB43_COM_CMN_MODE_CONTD3 0x294
#define QSERDES_V8_USB43_COM_CMN_MODE_CONTD4 0x298
#define QSERDES_V8_USB43_COM_CMN_MODE_CONTD5 0x29c
#define QSERDES_V8_USB43_COM_CMN_MODE_CONTD6 0x2a0
#define QSERDES_V8_USB43_COM_ADDITIONAL_MISC_6 0x2a4
#define QSERDES_V8_USB43_COM_ADDITIONAL_MISC_7 0x2a8
#define QSERDES_V8_USB43_COM_VCO_WAIT_CYCLES 0x2ac
#define QSERDES_V8_USB43_COM_BIAS_WAIT_CYCLES 0x2b0
#define QSERDES_V8_USB43_COM_AUX_CLK_PSM_ENABLE 0x2b4
#define QSERDES_V8_USB43_COM_PLL_SPARE_FOR_ECO 0x2b8
#define QSERDES_V8_USB43_COM_PLL_SPARE_FOR_ECO_1 0x2bc
#define QSERDES_V8_USB43_COM_PLL_SPARE_FOR_ECO_2 0x2c0
#define QSERDES_V8_USB43_COM_LDO_CAL_1 0x2c4
#define QSERDES_V8_USB43_COM_LDO_CAL_2 0x2c8
#define QSERDES_V8_USB43_COM_LDO_CAL_3 0x2cc
#define QSERDES_V8_USB43_COM_LDO_CAL_4 0x2d0
#define QSERDES_V8_USB43_COM_LDO_CAL_5 0x2d4
#define QSERDES_V8_USB43_COM_DCC_CAL_1 0x2d8
#define QSERDES_V8_USB43_COM_DCC_CAL_2 0x2dc
#define QSERDES_V8_USB43_COM_DCC_CAL_3 0x2e0
#define QSERDES_V8_USB43_COM_DCC_CAL_4 0x2e4
#define QSERDES_V8_USB43_COM_DCC_CAL_5 0x2e8
#define QSERDES_V8_USB43_COM_DCC_CAL_6 0x2ec
#define QSERDES_V8_USB43_COM_PSM_CAL_EN 0x2f0
#define QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_1 0x2f4
#define QSERDES_V8_USB43_COM_CLK_FWD_CONFIG_2 0x2f8
#define QSERDES_V8_USB43_COM_IP_CTRL_AND_DP_SEL 0x2fc
#define QSERDES_V8_USB43_COM_DCC_CAL_7 0x300
#define QSERDES_V8_USB43_COM_DCC_CAL_8 0x304
#define QSERDES_V8_USB43_COM_DCC_CAL_9 0x308
#define QSERDES_V8_USB43_COM_MODE_OPERATION_STATUS 0x30c
#define QSERDES_V8_USB43_COM_SYSCLK_DET_COMP_STATUS 0x310
#define QSERDES_V8_USB43_COM_CMN_STATUS 0x314
#define QSERDES_V8_USB43_COM_RESET_SM_STATUS 0x318
#define QSERDES_V8_USB43_COM_RESTRIM_CODE_STATUS 0x31c
#define QSERDES_V8_USB43_COM_PLLCAL_CODE1_STATUS 0x320
#define QSERDES_V8_USB43_COM_PLLCAL_CODE2_STATUS 0x324
#define QSERDES_V8_USB43_COM_INTEGLOOP_BINCODE_STATUS 0x328
#define QSERDES_V8_USB43_COM_DEBUG_BUS0 0x32c
#define QSERDES_V8_USB43_COM_DEBUG_BUS1 0x330
#define QSERDES_V8_USB43_COM_DEBUG_BUS2 0x334
#define QSERDES_V8_USB43_COM_DEBUG_BUS3 0x338
#define QSERDES_V8_USB43_COM_C_READY_STATUS 0x33c
#define QSERDES_V8_USB43_COM_READ_DUMMY_1 0x340
#define QSERDES_V8_USB43_COM_READ_DUMMY_2 0x344
#define QSERDES_V8_USB43_COM_READ_DUMMY_3 0x348
#define QSERDES_V8_USB43_COM_IVCO_CAL_CODE_STATUS 0x34c
#define QSERDES_V8_USB43_COM_PLL_LDO_CAL_STATUS_2 0x350
#define QSERDES_V8_USB43_COM_PLL_LDO_CAL_STATUS_3 0x354
#endif

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,9 @@
#include "phy-qcom-qmp-qserdes-com.h"
#include "phy-qcom-qmp-qserdes-txrx.h"
#include "phy-qcom-qmp-qserdes-com-v2.h"
#include "phy-qcom-qmp-qserdes-txrx-v2.h"
#include "phy-qcom-qmp-qserdes-com-v3.h"
#include "phy-qcom-qmp-qserdes-txrx-v3.h"
@ -32,7 +35,9 @@
#include "phy-qcom-qmp-qserdes-txrx-v7.h"
#include "phy-qcom-qmp-qserdes-com-v8.h"
#include "phy-qcom-qmp-usb43-qserdes-com-v8.h"
#include "phy-qcom-qmp-qserdes-txrx-v8.h"
#include "phy-qcom-qmp-qserdes-lalb-v8.h"
#include "phy-qcom-qmp-qserdes-pll.h"

View file

@ -29,7 +29,9 @@ config PHY_RCAR_GEN3_USB2
depends on ARCH_RENESAS
depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
depends on USB_SUPPORT
depends on REGULATOR
select GENERIC_PHY
select MULTIPLEXER
select USB_COMMON
help
Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs.

View file

@ -85,7 +85,7 @@ static int rcar_gen2_phy_init(struct phy *p)
* Try to acquire exclusive access to PHY. The first driver calling
* phy_init() on a given channel wins, and all attempts to use another
* PHY on this channel will fail until phy_exit() is called by the first
* driver. Achieving this with cmpxcgh() should be SMP-safe.
* driver. Achieving this with cmpxchg() should be SMP-safe.
*/
if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1)
return -EBUSY;
@ -337,7 +337,6 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct rcar_gen2_phy_driver *drv;
struct phy_provider *provider;
struct device_node *np;
void __iomem *base;
struct clk *clk;
const struct rcar_gen2_phy_data *data;
@ -379,7 +378,7 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev)
if (!drv->channels)
return -ENOMEM;
for_each_child_of_node(dev->of_node, np) {
for_each_child_of_node_scoped(dev->of_node, np) {
struct rcar_gen2_channel *channel = drv->channels + i;
u32 channel_num;
int error, n;
@ -391,7 +390,6 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev)
error = of_property_read_u32(np, "reg", &channel_num);
if (error || channel_num >= data->num_channels) {
dev_err(dev, "Invalid \"reg\" property\n");
of_node_put(np);
return error;
}
channel->select_mask = select_mask[channel_num];

View file

@ -17,11 +17,13 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/mux/consumer.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/driver.h>
#include <linux/reset.h>
#include <linux/string.h>
#include <linux/usb/of.h>
@ -141,6 +143,7 @@ struct rcar_gen3_chan {
bool extcon_host;
bool is_otg_channel;
bool uses_otg_pins;
bool otg_internal_reg;
};
struct rcar_gen3_phy_drv_data {
@ -204,28 +207,43 @@ static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
writel(val, usb2_base + USB2_LINECTRL1);
}
static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
static void rcar_gen3_phy_usb2_set_vbus(struct rcar_gen3_chan *ch,
u32 vbus_ctrl_reg,
u32 vbus_ctrl_val,
bool enable)
{
void __iomem *usb2_base = ch->base;
u32 vbus_ctrl_reg = USB2_ADPCTRL;
u32 vbus_ctrl_val = USB2_ADPCTRL_DRVVBUS;
u32 val;
val = readl(usb2_base + vbus_ctrl_reg);
if (enable)
val |= vbus_ctrl_val;
else
val &= ~vbus_ctrl_val;
writel(val, usb2_base + vbus_ctrl_reg);
dev_vdbg(ch->dev, "%s: reg=0x%08x, val=%08x, enable=%d\n",
__func__, vbus_ctrl_reg, val, enable);
}
static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
{
if (ch->otg_internal_reg) {
regulator_hardware_enable(ch->vbus, vbus);
return;
}
if (ch->phy_data->no_adp_ctrl || ch->phy_data->vblvl_ctrl) {
if (ch->vbus)
regulator_hardware_enable(ch->vbus, vbus);
vbus_ctrl_reg = USB2_VBCTRL;
vbus_ctrl_val = USB2_VBCTRL_VBOUT;
rcar_gen3_phy_usb2_set_vbus(ch, USB2_VBCTRL,
USB2_VBCTRL_VBOUT, vbus);
return;
}
val = readl(usb2_base + vbus_ctrl_reg);
if (vbus)
val |= vbus_ctrl_val;
else
val &= ~vbus_ctrl_val;
dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus);
writel(val, usb2_base + vbus_ctrl_reg);
rcar_gen3_phy_usb2_set_vbus(ch, USB2_ADPCTRL,
USB2_ADPCTRL_DRVVBUS, vbus);
}
static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable)
@ -583,7 +601,7 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p)
u32 val;
int ret = 0;
if (channel->vbus) {
if (channel->vbus && !channel->otg_internal_reg) {
ret = regulator_enable(channel->vbus);
if (ret)
return ret;
@ -624,7 +642,7 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p)
}
}
if (channel->vbus)
if (channel->vbus && !channel->otg_internal_reg)
ret = regulator_disable(channel->vbus);
return ret;
@ -799,11 +817,149 @@ static int rcar_gen3_phy_usb2_init_bus(struct rcar_gen3_chan *channel)
return 0;
}
static int rcar_gen3_phy_usb2_regulator_endisable(struct regulator_dev *rdev,
bool enable)
{
struct rcar_gen3_chan *channel = rdev_get_drvdata(rdev);
struct device *dev = channel->dev;
int ret;
ret = pm_runtime_resume_and_get(dev);
if (ret < 0) {
dev_warn(dev, "pm_runtime_get failed: %i\n", ret);
return ret;
}
rcar_gen3_phy_usb2_set_vbus(channel, USB2_VBCTRL,
USB2_VBCTRL_VBOUT, enable);
pm_runtime_put_noidle(dev);
return ret;
}
static int rcar_gen3_phy_usb2_regulator_enable(struct regulator_dev *rdev)
{
return rcar_gen3_phy_usb2_regulator_endisable(rdev, true);
}
static int rcar_gen3_phy_usb2_regulator_disable(struct regulator_dev *rdev)
{
return rcar_gen3_phy_usb2_regulator_endisable(rdev, false);
}
static int rcar_gen3_phy_usb2_regulator_is_enabled(struct regulator_dev *rdev)
{
struct rcar_gen3_chan *channel = rdev_get_drvdata(rdev);
void __iomem *usb2_base = channel->base;
struct device *dev = channel->dev;
u32 vbus_ctrl_reg = USB2_VBCTRL;
u32 val;
int ret;
ret = pm_runtime_resume_and_get(dev);
if (ret < 0) {
dev_warn(dev, "pm_runtime_get failed: %i\n", ret);
return ret;
}
val = readl(usb2_base + vbus_ctrl_reg);
pm_runtime_put_noidle(dev);
dev_dbg(channel->dev, "%s: %08x\n", __func__, val);
return (val & USB2_VBCTRL_VBOUT) ? 1 : 0;
}
static const struct regulator_ops rcar_gen3_phy_usb2_regulator_ops = {
.enable = rcar_gen3_phy_usb2_regulator_enable,
.disable = rcar_gen3_phy_usb2_regulator_disable,
.is_enabled = rcar_gen3_phy_usb2_regulator_is_enabled,
};
static const struct regulator_desc rcar_gen3_phy_usb2_regulator = {
.name = "otg-vbus-regulator",
.of_match = of_match_ptr("vbus-regulator"),
.ops = &rcar_gen3_phy_usb2_regulator_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.fixed_uV = 5000000,
.n_voltages = 1,
};
static void rcar_gen3_phy_usb2_vbus_disable_action(void *data)
{
struct regulator *vbus = data;
regulator_disable(vbus);
}
static int rcar_gen3_phy_usb2_vbus_regulator_get_exclusive_enable(struct rcar_gen3_chan *channel,
bool enable)
{
struct device *dev = channel->dev;
int ret;
channel->vbus = devm_regulator_get_exclusive(dev, "vbus");
if (IS_ERR(channel->vbus))
return PTR_ERR(channel->vbus);
if (!enable)
return 0;
ret = regulator_enable(channel->vbus);
if (ret)
return ret;
return devm_add_action_or_reset(dev, rcar_gen3_phy_usb2_vbus_disable_action,
channel->vbus);
}
static int rcar_gen3_phy_usb2_vbus_regulator_register(struct rcar_gen3_chan *channel)
{
struct device *dev = channel->dev;
struct regulator_config rcfg = { .dev = dev, };
struct regulator_dev *rdev;
bool enable = false;
rcfg.of_node = of_get_available_child_by_name(dev->of_node,
"vbus-regulator");
if (rcfg.of_node) {
rcfg.driver_data = channel;
rdev = devm_regulator_register(dev, &rcar_gen3_phy_usb2_regulator,
&rcfg);
of_node_put(rcfg.of_node);
if (IS_ERR(rdev))
return dev_err_probe(dev, PTR_ERR(rdev),
"Failed to create vbus-regulator\n");
channel->otg_internal_reg = true;
enable = true;
}
return rcar_gen3_phy_usb2_vbus_regulator_get_exclusive_enable(channel, enable);
}
/* Temporary wrapper until the multiplexer subsystem supports optional muxes */
static inline struct mux_state *
devm_mux_state_get_optional(struct device *dev, const char *mux_name)
{
if (!of_property_present(dev->of_node, "mux-states"))
return NULL;
return devm_mux_state_get(dev, mux_name);
}
static void rcar_gen3_phy_mux_state_deselect(void *data)
{
mux_state_deselect(data);
}
static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rcar_gen3_chan *channel;
struct phy_provider *provider;
struct mux_state *mux_state;
int ret = 0, i, irq;
if (!dev->of_node) {
@ -852,78 +1008,87 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
* devm_phy_create() will call pm_runtime_enable(&phy->dev);
* And then, phy-core will manage runtime pm for this device.
*/
pm_runtime_enable(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
return dev_err_probe(dev, ret, "Failed to enable pm_runtime\n");
channel->phy_data = of_device_get_match_data(dev);
if (!channel->phy_data) {
ret = -EINVAL;
goto error;
}
if (!channel->phy_data)
return -EINVAL;
platform_set_drvdata(pdev, channel);
channel->dev = dev;
ret = rcar_gen3_phy_usb2_init_bus(channel);
if (ret)
goto error;
return ret;
spin_lock_init(&channel->lock);
for (i = 0; i < NUM_OF_PHYS; i++) {
channel->rphys[i].phy = devm_phy_create(dev, NULL,
channel->phy_data->phy_usb2_ops);
if (IS_ERR(channel->rphys[i].phy)) {
dev_err(dev, "Failed to create USB2 PHY\n");
ret = PTR_ERR(channel->rphys[i].phy);
goto error;
}
if (IS_ERR(channel->rphys[i].phy))
return dev_err_probe(dev, PTR_ERR(channel->rphys[i].phy),
"Failed to create USB2 PHY\n");
channel->rphys[i].ch = channel;
channel->rphys[i].int_enable_bits = rcar_gen3_int_enable[i];
phy_set_drvdata(channel->rphys[i].phy, &channel->rphys[i]);
}
if (channel->phy_data->no_adp_ctrl && channel->is_otg_channel)
channel->vbus = devm_regulator_get_exclusive(dev, "vbus");
else
mux_state = devm_mux_state_get_optional(dev, NULL);
if (IS_ERR(mux_state))
return PTR_ERR(mux_state);
if (mux_state) {
ret = mux_state_select(mux_state);
if (ret)
return dev_err_probe(dev, ret, "Failed to select USB mux\n");
ret = devm_add_action_or_reset(dev, rcar_gen3_phy_mux_state_deselect,
mux_state);
if (ret)
return dev_err_probe(dev, ret,
"Failed to register USB mux state deselect\n");
}
if (channel->phy_data->no_adp_ctrl && channel->is_otg_channel) {
ret = rcar_gen3_phy_usb2_vbus_regulator_register(channel);
if (ret)
return ret;
} else {
channel->vbus = devm_regulator_get_optional(dev, "vbus");
}
if (IS_ERR(channel->vbus)) {
if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) {
ret = PTR_ERR(channel->vbus);
goto error;
}
if (PTR_ERR(channel->vbus) == -EPROBE_DEFER)
return PTR_ERR(channel->vbus);
channel->vbus = NULL;
}
irq = platform_get_irq_optional(pdev, 0);
if (irq < 0 && irq != -ENXIO) {
ret = irq;
goto error;
return irq;
} else if (irq > 0) {
INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
ret = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
IRQF_SHARED, dev_name(dev), channel);
if (ret < 0) {
dev_err(dev, "Failed to request irq (%d)\n", irq);
goto error;
}
if (ret < 0)
return dev_err_probe(dev, ret,
"Failed to request irq (%d)\n",
irq);
}
provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate);
if (IS_ERR(provider)) {
dev_err(dev, "Failed to register PHY provider\n");
ret = PTR_ERR(provider);
goto error;
return dev_err_probe(dev, PTR_ERR(provider),
"Failed to register PHY provider\n");
} else if (channel->is_otg_channel) {
ret = device_create_file(dev, &dev_attr_role);
if (ret < 0)
goto error;
return ret;
}
return 0;
error:
pm_runtime_disable(dev);
return ret;
}
static void rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
@ -932,8 +1097,6 @@ static void rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
if (channel->is_otg_channel)
device_remove_file(&pdev->dev, &dev_attr_role);
pm_runtime_disable(&pdev->dev);
}
static int rcar_gen3_phy_usb2_suspend(struct device *dev)

View file

@ -749,22 +749,23 @@ unsigned long inno_hdmi_phy_rk3228_clk_recalc_rate(struct clk_hw *hw,
return vco;
}
static long inno_hdmi_phy_rk3228_clk_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *parent_rate)
static int inno_hdmi_phy_rk3228_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
const struct pre_pll_config *cfg = pre_pll_cfg_table;
rate = (rate / 1000) * 1000;
req->rate = (req->rate / 1000) * 1000;
for (; cfg->pixclock != 0; cfg++)
if (cfg->pixclock == rate && !cfg->fracdiv)
if (cfg->pixclock == req->rate && !cfg->fracdiv)
break;
if (cfg->pixclock == 0)
return -EINVAL;
return cfg->pixclock;
req->rate = cfg->pixclock;
return 0;
}
static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw,
@ -835,7 +836,7 @@ static const struct clk_ops inno_hdmi_phy_rk3228_clk_ops = {
.unprepare = inno_hdmi_phy_rk3228_clk_unprepare,
.is_prepared = inno_hdmi_phy_rk3228_clk_is_prepared,
.recalc_rate = inno_hdmi_phy_rk3228_clk_recalc_rate,
.round_rate = inno_hdmi_phy_rk3228_clk_round_rate,
.determine_rate = inno_hdmi_phy_rk3228_clk_determine_rate,
.set_rate = inno_hdmi_phy_rk3228_clk_set_rate,
};
@ -906,22 +907,23 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw,
return inno->pixclock;
}
static long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *parent_rate)
static int inno_hdmi_phy_rk3328_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
const struct pre_pll_config *cfg = pre_pll_cfg_table;
rate = (rate / 1000) * 1000;
req->rate = (req->rate / 1000) * 1000;
for (; cfg->pixclock != 0; cfg++)
if (cfg->pixclock == rate)
if (cfg->pixclock == req->rate)
break;
if (cfg->pixclock == 0)
return -EINVAL;
return cfg->pixclock;
req->rate = cfg->pixclock;
return 0;
}
static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
@ -989,7 +991,7 @@ static const struct clk_ops inno_hdmi_phy_rk3328_clk_ops = {
.unprepare = inno_hdmi_phy_rk3328_clk_unprepare,
.is_prepared = inno_hdmi_phy_rk3328_clk_is_prepared,
.recalc_rate = inno_hdmi_phy_rk3328_clk_recalc_rate,
.round_rate = inno_hdmi_phy_rk3328_clk_round_rate,
.determine_rate = inno_hdmi_phy_rk3328_clk_determine_rate,
.set_rate = inno_hdmi_phy_rk3328_clk_set_rate,
};

View file

@ -529,7 +529,7 @@ static int rk3528_combphy_cfg(struct rockchip_combphy_priv *priv)
return -EINVAL;
}
if (device_property_read_bool(priv->dev, "rockchip,ext-refclk")) {
if (priv->ext_refclk) {
rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);
if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {
@ -554,11 +554,9 @@ static int rk3528_combphy_cfg(struct rockchip_combphy_priv *priv)
}
}
if (priv->type == PHY_TYPE_PCIE) {
if (device_property_read_bool(priv->dev, "rockchip,enable-ssc"))
rockchip_combphy_updatel(priv, RK3528_PHYREG40_SSC_EN,
RK3528_PHYREG40_SSC_EN, RK3528_PHYREG40);
}
if (priv->type == PHY_TYPE_PCIE && priv->enable_ssc)
rockchip_combphy_updatel(priv, RK3528_PHYREG40_SSC_EN,
RK3528_PHYREG40_SSC_EN, RK3528_PHYREG40);
return 0;
}
@ -582,7 +580,7 @@ static const struct rockchip_combphy_grfcfg rk3528_combphy_grfcfgs = {
.con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x101 },
.con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 },
/* pipe-grf */
.u3otg0_port_en = { 0x0044, 15, 0, 0x0181, 0x1100 },
.u3otg0_port_en = { 0x0044, 15, 0, 0x0181, 0x1100 },
};
static const struct rockchip_combphy_cfg rk3528_combphy_cfgs = {

View file

@ -1508,7 +1508,9 @@ static int samsung_mipi_dcphy_exit(struct phy *phy)
{
struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
return pm_runtime_put(samsung->dev);
pm_runtime_put(samsung->dev);
return 0;
}
static const struct phy_ops samsung_mipi_dcphy_ops = {

File diff suppressed because it is too large Load diff

View file

@ -446,7 +446,6 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct rockchip_usb_phy_base *phy_base;
struct phy_provider *phy_provider;
struct device_node *child;
int err;
phy_base = devm_kzalloc(dev, sizeof(*phy_base), GFP_KERNEL);
@ -472,12 +471,10 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
return PTR_ERR(phy_base->reg_base);
}
for_each_available_child_of_node(dev->of_node, child) {
for_each_available_child_of_node_scoped(dev->of_node, child) {
err = rockchip_usb_phy_init(phy_base, child);
if (err) {
of_node_put(child);
if (err)
return err;
}
}
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);

View file

@ -41,6 +41,13 @@
#define EXYNOS2200_CLKRST_LINK_PCLK_SEL BIT(1)
#define EXYNOS2200_DRD_UTMI 0x10
/* ExynosAutov920 bits */
#define UTMICTL_FORCE_UTMI_SUSPEND BIT(13)
#define UTMICTL_FORCE_UTMI_SLEEP BIT(12)
#define UTMICTL_FORCE_DPPULLDOWN BIT(9)
#define UTMICTL_FORCE_DMPULLDOWN BIT(8)
#define EXYNOS2200_UTMI_FORCE_VBUSVALID BIT(1)
#define EXYNOS2200_UTMI_FORCE_BVALID BIT(0)
@ -250,6 +257,52 @@
#define EXYNOS850_DRD_HSP_TEST 0x5c
#define HSP_TEST_SIDDQ BIT(24)
#define EXYNOSAUTOV920_DRD_HSP_CLKRST 0x100
#define HSPCLKRST_PHY20_SW_PORTRESET BIT(3)
#define HSPCLKRST_PHY20_SW_POR BIT(1)
#define HSPCLKRST_PHY20_SW_POR_SEL BIT(0)
#define EXYNOSAUTOV920_DRD_HSPCTL 0x104
#define HSPCTRL_VBUSVLDEXTSEL BIT(13)
#define HSPCTRL_VBUSVLDEXT BIT(12)
#define HSPCTRL_EN_UTMISUSPEND BIT(9)
#define HSPCTRL_COMMONONN BIT(8)
#define EXYNOSAUTOV920_DRD_HSP_TEST 0x10c
#define EXYNOSAUTOV920_DRD_HSPPLLTUNE 0x110
#define HSPPLLTUNE_FSEL GENMASK(18, 16)
/* ExynosAutov920 phy usb31drd port reg */
#define EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL 0x000
#define PHY_RST_CTRL_PIPE_LANE0_RESET_N_OVRD_EN BIT(5)
#define PHY_RST_CTRL_PIPE_LANE0_RESET_N BIT(4)
#define PHY_RST_CTRL_PHY_RESET_OVRD_EN BIT(1)
#define PHY_RST_CTRL_PHY_RESET BIT(0)
#define EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0 0x0004
#define PHY_CR_PARA_CON0_PHY0_CR_PARA_ADDR GENMASK(31, 16)
#define PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK BIT(8)
#define PHY_CR_PARA_CON0_PHY0_CR_PARA_ACK BIT(4)
#define PHY_CR_PARA_CON0_PHY0_CR_PARA_SEL BIT(0)
#define EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON1 0x0008
#define EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON2 0x000c
#define PHY_CR_PARA_CON2_PHY0_CR_PARA_WR_EN BIT(0)
#define PHY_CR_PARA_CON2_PHY0_CR_PARA_WR_DATA GENMASK(31, 16)
#define EXYNOSAUTOV920_USB31DRD_PHY_CONFIG0 0x100
#define PHY_CONFIG0_PHY0_PMA_PWR_STABLE BIT(14)
#define PHY_CONFIG0_PHY0_PCS_PWR_STABLE BIT(13)
#define PHY_CONFIG0_PHY0_ANA_PWR_EN BIT(1)
#define EXYNOSAUTOV920_USB31DRD_PHY_CONFIG7 0x11c
#define PHY_CONFIG7_PHY_TEST_POWERDOWN BIT(24)
#define EXYNOSAUTOV920_USB31DRD_PHY_CONFIG4 0x110
#define PHY_CONFIG4_PIPE_RX0_SRIS_MODE_EN BIT(2)
/* Exynos9 - GS101 */
#define EXYNOS850_DRD_SECPMACTL 0x48
#define SECPMACTL_PMA_ROPLL_REF_CLK_SEL GENMASK(13, 12)
@ -2054,6 +2107,595 @@ static const struct exynos5_usbdrd_phy_drvdata exynos990_usbdrd_phy = {
.n_regulators = ARRAY_SIZE(exynos5_regulator_names),
};
static void
exynosautov920_usb31drd_cr_clk(struct exynos5_usbdrd_phy *phy_drd, bool high)
{
void __iomem *reg_phy = phy_drd->reg_phy;
u32 reg;
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0);
if (high)
reg |= PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK;
else
reg &= ~PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0);
fsleep(1);
}
static void
exynosautov920_usb31drd_port_phy_ready(struct exynos5_usbdrd_phy *phy_drd)
{
struct device *dev = phy_drd->dev;
void __iomem *reg_phy = phy_drd->reg_phy;
static const unsigned int timeout_us = 20000;
static const unsigned int sleep_us = 40;
u32 reg;
int err;
/* Clear cr_para_con */
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0);
reg &= ~(PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK |
PHY_CR_PARA_CON0_PHY0_CR_PARA_ADDR);
reg |= PHY_CR_PARA_CON0_PHY0_CR_PARA_SEL;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0);
writel(0x0, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON1);
writel(0x0, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON2);
exynosautov920_usb31drd_cr_clk(phy_drd, true);
exynosautov920_usb31drd_cr_clk(phy_drd, false);
/*
* The maximum time from phy reset de-assertion to de-assertion of
* tx/rx_ack can be as high as 5ms in fast simulation mode.
* Time to phy ready is < 20ms
*/
err = readl_poll_timeout(reg_phy +
EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0,
reg, !(reg & PHY_CR_PARA_CON0_PHY0_CR_PARA_ACK),
sleep_us, timeout_us);
if (err)
dev_err(dev, "timed out waiting for rx/tx_ack: %#.8x\n", reg);
reg &= ~PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0);
}
static void
exynosautov920_usb31drd_cr_write(struct exynos5_usbdrd_phy *phy_drd,
u16 addr, u16 data)
{
void __iomem *reg_phy = phy_drd->reg_phy;
u32 cnt = 0;
u32 reg;
/* Pre Clocking */
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0);
reg |= PHY_CR_PARA_CON0_PHY0_CR_PARA_SEL;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0);
/*
* tx clks must be available prior to assertion of tx req.
* tx pstate p2 to p0 transition directly is not permitted.
* tx clk ready must be asserted synchronously on tx clk prior
* to internal transmit clk alignment sequence in the phy
* when entering from p2 to p1 to p0.
*/
do {
exynosautov920_usb31drd_cr_clk(phy_drd, true);
exynosautov920_usb31drd_cr_clk(phy_drd, false);
cnt++;
} while (cnt < 15);
reg &= ~PHY_CR_PARA_CON0_PHY0_CR_PARA_SEL;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0);
/*
* tx data path is active when tx lane is in p0 state
* and tx data en asserted. enable cr_para_wr_en.
*/
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON2);
reg &= ~PHY_CR_PARA_CON2_PHY0_CR_PARA_WR_DATA;
reg |= FIELD_PREP(PHY_CR_PARA_CON2_PHY0_CR_PARA_WR_DATA, data) |
PHY_CR_PARA_CON2_PHY0_CR_PARA_WR_EN;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON2);
/* write addr */
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0);
reg &= ~PHY_CR_PARA_CON0_PHY0_CR_PARA_ADDR;
reg |= FIELD_PREP(PHY_CR_PARA_CON0_PHY0_CR_PARA_ADDR, addr) |
PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK |
PHY_CR_PARA_CON0_PHY0_CR_PARA_SEL;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0);
/* check cr_para_ack*/
cnt = 0;
do {
/*
* data symbols are captured by phy on rising edge of the
* tx_clk when tx data enabled.
* completion of the write cycle is acknowledged by assertion
* of the cr_para_ack.
*/
exynosautov920_usb31drd_cr_clk(phy_drd, true);
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0);
if ((reg & PHY_CR_PARA_CON0_PHY0_CR_PARA_ACK))
break;
exynosautov920_usb31drd_cr_clk(phy_drd, false);
/*
* wait for minimum of 10 cr_para_clk cycles after phy reset
* is negated, before accessing control regs to allow for
* internal resets.
*/
cnt++;
} while (cnt < 10);
if (cnt < 10)
exynosautov920_usb31drd_cr_clk(phy_drd, false);
}
static void
exynosautov920_usb31drd_phy_reset(struct exynos5_usbdrd_phy *phy_drd, int val)
{
void __iomem *reg_phy = phy_drd->reg_phy;
u32 reg;
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL);
reg &= ~PHY_RST_CTRL_PHY_RESET_OVRD_EN;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL);
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL);
if (val)
reg |= PHY_RST_CTRL_PHY_RESET;
else
reg &= ~PHY_RST_CTRL_PHY_RESET;
reg |= PHY_RST_CTRL_PHY_RESET_OVRD_EN;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL);
}
static void
exynosautov920_usb31drd_lane0_reset(struct exynos5_usbdrd_phy *phy_drd, int val)
{
void __iomem *reg_phy = phy_drd->reg_phy;
u32 reg;
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL);
reg |= PHY_RST_CTRL_PIPE_LANE0_RESET_N_OVRD_EN;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL);
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL);
if (val)
reg &= ~PHY_RST_CTRL_PIPE_LANE0_RESET_N;
else
reg |= PHY_RST_CTRL_PIPE_LANE0_RESET_N;
reg &= ~PHY_RST_CTRL_PIPE_LANE0_RESET_N_OVRD_EN;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL);
}
static void
exynosautov920_usb31drd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
{
void __iomem *reg_phy = phy_drd->reg_phy;
u32 reg;
/*
* Phy and Pipe Lane reset assert.
* assert reset (phy_reset = 1).
* The lane-ack outputs are asserted during reset (tx_ack = rx_ack = 1)
*/
exynosautov920_usb31drd_phy_reset(phy_drd, 1);
exynosautov920_usb31drd_lane0_reset(phy_drd, 1);
/*
* ANA Power En, PCS & PMA PWR Stable Set
* ramp-up power suppiles
*/
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG0);
reg |= PHY_CONFIG0_PHY0_ANA_PWR_EN | PHY_CONFIG0_PHY0_PCS_PWR_STABLE |
PHY_CONFIG0_PHY0_PMA_PWR_STABLE;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG0);
fsleep(10);
/*
* phy is not functional in test_powerdown mode, test_powerdown to be
* de-asserted for normal operation
*/
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG7);
reg &= ~PHY_CONFIG7_PHY_TEST_POWERDOWN;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG7);
/*
* phy reset signal be asserted for minimum 10us after power
* supplies are ramped-up
*/
fsleep(10);
/*
* Phy and Pipe Lane reset assert de-assert
*/
exynosautov920_usb31drd_phy_reset(phy_drd, 0);
exynosautov920_usb31drd_lane0_reset(phy_drd, 0);
/* Pipe_rx0_sris_mode_en = 1 */
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG4);
reg |= PHY_CONFIG4_PIPE_RX0_SRIS_MODE_EN;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG4);
/*
* wait for lane ack outputs to de-assert (tx_ack = rx_ack = 0)
* Exit from the reset state is indicated by de-assertion of *_ack
*/
exynosautov920_usb31drd_port_phy_ready(phy_drd);
/* override values for level settings */
exynosautov920_usb31drd_cr_write(phy_drd, 0x22, 0x00F5);
}
static void
exynosautov920_usb31drd_ssphy_disable(struct exynos5_usbdrd_phy *phy_drd)
{
void __iomem *reg_phy = phy_drd->reg_phy;
u32 reg;
/* 1. Assert reset (phy_reset = 1) */
exynosautov920_usb31drd_lane0_reset(phy_drd, 1);
exynosautov920_usb31drd_phy_reset(phy_drd, 1);
/* phy test power down */
reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG7);
reg |= PHY_CONFIG7_PHY_TEST_POWERDOWN;
writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG7);
}
static void
exynosautov920_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
{
void __iomem *reg_phy = phy_drd->reg_phy;
u32 reg;
/*
* Disable HWACG (hardware auto clock gating control). This
* forces QACTIVE signal in Q-Channel interface to HIGH level,
* to make sure the PHY clock is not gated by the hardware.
*/
reg = readl(reg_phy + EXYNOS850_DRD_LINKCTRL);
reg |= LINKCTRL_FORCE_QACT;
writel(reg, reg_phy + EXYNOS850_DRD_LINKCTRL);
/* De-assert link reset */
reg = readl(reg_phy + EXYNOS2200_DRD_CLKRST);
reg &= ~CLKRST_LINK_SW_RST;
writel(reg, reg_phy + EXYNOS2200_DRD_CLKRST);
/* Set PHY POR High */
reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSP_CLKRST);
reg |= HSPCLKRST_PHY20_SW_POR | HSPCLKRST_PHY20_SW_POR_SEL;
writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSP_CLKRST);
/* Enable UTMI+ */
reg = readl(reg_phy + EXYNOS2200_DRD_UTMI);
reg &= ~(UTMICTL_FORCE_UTMI_SUSPEND | UTMICTL_FORCE_UTMI_SLEEP |
UTMICTL_FORCE_DPPULLDOWN | UTMICTL_FORCE_DMPULLDOWN);
writel(reg, reg_phy + EXYNOS2200_DRD_UTMI);
/* set phy clock & control HS phy */
reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSPCTL);
reg |= HSPCTRL_EN_UTMISUSPEND | HSPCTRL_COMMONONN;
writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSPCTL);
fsleep(100);
/* Set VBUS Valid and DP-Pull up control by VBUS pad usage */
reg = readl(reg_phy + EXYNOS850_DRD_LINKCTRL);
reg |= FIELD_PREP_CONST(LINKCTRL_BUS_FILTER_BYPASS, 0xf);
writel(reg, reg_phy + EXYNOS850_DRD_LINKCTRL);
reg = readl(reg_phy + EXYNOS2200_DRD_UTMI);
reg |= EXYNOS2200_UTMI_FORCE_VBUSVALID | EXYNOS2200_UTMI_FORCE_BVALID;
writel(reg, reg_phy + EXYNOS2200_DRD_UTMI);
reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSPCTL);
reg |= HSPCTRL_VBUSVLDEXTSEL | HSPCTRL_VBUSVLDEXT;
writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSPCTL);
/* Setting FSEL for refference clock */
reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSPPLLTUNE);
reg &= ~HSPPLLTUNE_FSEL;
switch (phy_drd->extrefclk) {
case EXYNOS5_FSEL_50MHZ:
reg |= FIELD_PREP(HSPPLLTUNE_FSEL, 7);
break;
case EXYNOS5_FSEL_26MHZ:
reg |= FIELD_PREP(HSPPLLTUNE_FSEL, 6);
break;
case EXYNOS5_FSEL_24MHZ:
reg |= FIELD_PREP(HSPPLLTUNE_FSEL, 2);
break;
case EXYNOS5_FSEL_20MHZ:
reg |= FIELD_PREP(HSPPLLTUNE_FSEL, 1);
break;
case EXYNOS5_FSEL_19MHZ2:
reg |= FIELD_PREP(HSPPLLTUNE_FSEL, 0);
break;
default:
dev_warn(phy_drd->dev, "unsupported ref clk: %#.2x\n",
phy_drd->extrefclk);
break;
}
writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSPPLLTUNE);
/* Enable PHY Power Mode */
reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSP_TEST);
reg &= ~HSP_TEST_SIDDQ;
writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSP_TEST);
/* before POR low, 10us delay is needed to Finish PHY reset */
fsleep(10);
/* Set PHY POR Low */
reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSP_CLKRST);
reg |= HSPCLKRST_PHY20_SW_POR_SEL;
reg &= ~(HSPCLKRST_PHY20_SW_POR | HSPCLKRST_PHY20_SW_PORTRESET);
writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSP_CLKRST);
/* after POR low and delay 75us, PHYCLOCK is guaranteed. */
fsleep(75);
/* Disable forcing pipe interface */
reg = readl(reg_phy + EXYNOS850_DRD_LINKCTRL);
reg &= ~LINKCTRL_FORCE_PIPE_EN;
writel(reg, reg_phy + EXYNOS850_DRD_LINKCTRL);
/* Pclk to pipe_clk */
reg = readl(reg_phy + EXYNOS2200_DRD_CLKRST);
reg |= EXYNOS2200_CLKRST_LINK_PCLK_SEL;
writel(reg, reg_phy + EXYNOS2200_DRD_CLKRST);
}
static void
exynosautov920_usbdrd_hsphy_disable(struct exynos5_usbdrd_phy *phy_drd)
{
u32 reg;
void __iomem *reg_phy = phy_drd->reg_phy;
/* set phy clock & control HS phy */
reg = readl(reg_phy + EXYNOS2200_DRD_UTMI);
reg |= UTMICTL_FORCE_UTMI_SUSPEND | UTMICTL_FORCE_UTMI_SLEEP;
reg &= ~(UTMICTL_FORCE_DPPULLDOWN | UTMICTL_FORCE_DMPULLDOWN);
writel(reg, reg_phy + EXYNOS2200_DRD_UTMI);
/* Disable PHY Power Mode */
reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSP_TEST);
reg |= HSP_TEST_SIDDQ;
writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSP_TEST);
/* clear force q-channel */
reg = readl(reg_phy + EXYNOS850_DRD_LINKCTRL);
reg &= ~LINKCTRL_FORCE_QACT;
writel(reg, reg_phy + EXYNOS850_DRD_LINKCTRL);
/* link sw reset is need for USB_DP/DM high-z in host mode */
reg = readl(reg_phy + EXYNOS2200_DRD_CLKRST);
reg |= CLKRST_LINK_SW_RST;
writel(reg, reg_phy + EXYNOS2200_DRD_CLKRST);
fsleep(10);
reg &= ~CLKRST_LINK_SW_RST;
writel(reg, reg_phy + EXYNOS2200_DRD_CLKRST);
}
static int exynosautov920_usbdrd_phy_init(struct phy *phy)
{
struct phy_usb_instance *inst = phy_get_drvdata(phy);
struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
int ret;
ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);
if (ret)
return ret;
/* Bypass PHY isol */
inst->phy_cfg->phy_isol(inst, false);
/* UTMI or PIPE3 specific init */
inst->phy_cfg->phy_init(phy_drd);
clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);
return 0;
}
static int exynosautov920_usbdrd_phy_exit(struct phy *phy)
{
struct phy_usb_instance *inst = phy_get_drvdata(phy);
struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
int ret;
ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);
if (ret)
return ret;
exynos850_usbdrd_phy_exit(phy);
/* enable PHY isol */
inst->phy_cfg->phy_isol(inst, true);
clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);
return 0;
}
static int exynosautov920_usbdrd_combo_phy_exit(struct phy *phy)
{
struct phy_usb_instance *inst = phy_get_drvdata(phy);
struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
int ret = 0;
ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);
if (ret)
return ret;
if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI)
exynosautov920_usbdrd_hsphy_disable(phy_drd);
else if (inst->phy_cfg->id == EXYNOS5_DRDPHY_PIPE3)
exynosautov920_usb31drd_ssphy_disable(phy_drd);
/* enable PHY isol */
inst->phy_cfg->phy_isol(inst, true);
clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);
return 0;
}
static int exynosautov920_usbdrd_phy_power_on(struct phy *phy)
{
struct phy_usb_instance *inst = phy_get_drvdata(phy);
struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
int ret;
dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_core_clks,
phy_drd->core_clks);
if (ret)
return ret;
/* Enable supply */
ret = regulator_bulk_enable(phy_drd->drv_data->n_regulators,
phy_drd->regulators);
if (ret) {
dev_err(phy_drd->dev, "Failed to enable PHY regulator(s)\n");
goto fail_supply;
}
return 0;
fail_supply:
clk_bulk_disable_unprepare(phy_drd->drv_data->n_core_clks,
phy_drd->core_clks);
return ret;
}
static int exynosautov920_usbdrd_phy_power_off(struct phy *phy)
{
struct phy_usb_instance *inst = phy_get_drvdata(phy);
struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");
/* Disable supply */
regulator_bulk_disable(phy_drd->drv_data->n_regulators,
phy_drd->regulators);
clk_bulk_disable_unprepare(phy_drd->drv_data->n_core_clks,
phy_drd->core_clks);
return 0;
}
static const char * const exynosautov920_usb30_regulators[] = {
"dvdd", "vdd18",
};
static const char * const exynosautov920_usb20_regulators[] = {
"dvdd", "vdd18", "vdd33",
};
static const struct
exynos5_usbdrd_phy_config usb31drd_phy_cfg_exynosautov920[] = {
{
.id = EXYNOS5_DRDPHY_PIPE3,
.phy_isol = exynos5_usbdrd_phy_isol,
.phy_init = exynosautov920_usb31drd_pipe3_init,
},
};
static const struct phy_ops exynosautov920_usb31drd_combo_ssphy_ops = {
.init = exynosautov920_usbdrd_phy_init,
.exit = exynosautov920_usbdrd_combo_phy_exit,
.power_on = exynosautov920_usbdrd_phy_power_on,
.power_off = exynosautov920_usbdrd_phy_power_off,
.owner = THIS_MODULE,
};
static const
struct exynos5_usbdrd_phy_drvdata exynosautov920_usb31drd_combo_ssphy = {
.phy_cfg = usb31drd_phy_cfg_exynosautov920,
.phy_ops = &exynosautov920_usb31drd_combo_ssphy_ops,
.pmu_offset_usbdrd0_phy = EXYNOSAUTOV920_PHY_CTRL_USB31,
.clk_names = exynos5_clk_names,
.n_clks = ARRAY_SIZE(exynos5_clk_names),
.core_clk_names = exynos5_core_clk_names,
.n_core_clks = ARRAY_SIZE(exynos5_core_clk_names),
.regulator_names = exynosautov920_usb30_regulators,
.n_regulators = ARRAY_SIZE(exynosautov920_usb30_regulators),
};
static const struct phy_ops exynosautov920_usbdrd_combo_hsphy_ops = {
.init = exynosautov920_usbdrd_phy_init,
.exit = exynosautov920_usbdrd_combo_phy_exit,
.power_on = exynosautov920_usbdrd_phy_power_on,
.power_off = exynosautov920_usbdrd_phy_power_off,
.owner = THIS_MODULE,
};
static const struct
exynos5_usbdrd_phy_config usbdrd_hsphy_cfg_exynosautov920[] = {
{
.id = EXYNOS5_DRDPHY_UTMI,
.phy_isol = exynos5_usbdrd_phy_isol,
.phy_init = exynosautov920_usbdrd_utmi_init,
},
};
static const
struct exynos5_usbdrd_phy_drvdata exynosautov920_usbdrd_combo_hsphy = {
.phy_cfg = usbdrd_hsphy_cfg_exynosautov920,
.phy_ops = &exynosautov920_usbdrd_combo_hsphy_ops,
.pmu_offset_usbdrd0_phy = EXYNOSAUTOV920_PHY_CTRL_USB20,
.clk_names = exynos5_clk_names,
.n_clks = ARRAY_SIZE(exynos5_clk_names),
.core_clk_names = exynos5_core_clk_names,
.n_core_clks = ARRAY_SIZE(exynos5_core_clk_names),
.regulator_names = exynosautov920_usb20_regulators,
.n_regulators = ARRAY_SIZE(exynosautov920_usb20_regulators),
};
static const struct phy_ops exynosautov920_usbdrd_phy_ops = {
.init = exynosautov920_usbdrd_phy_init,
.exit = exynosautov920_usbdrd_phy_exit,
.power_on = exynosautov920_usbdrd_phy_power_on,
.power_off = exynosautov920_usbdrd_phy_power_off,
.owner = THIS_MODULE,
};
static const struct exynos5_usbdrd_phy_config phy_cfg_exynosautov920[] = {
{
.id = EXYNOS5_DRDPHY_UTMI,
.phy_isol = exynos5_usbdrd_phy_isol,
.phy_init = exynos850_usbdrd_utmi_init,
},
};
static const struct exynos5_usbdrd_phy_drvdata exynosautov920_usbdrd_phy = {
.phy_cfg = phy_cfg_exynosautov920,
.phy_ops = &exynosautov920_usbdrd_phy_ops,
.pmu_offset_usbdrd0_phy = EXYNOSAUTOV920_PHY_CTRL_USB20,
.clk_names = exynos5_clk_names,
.n_clks = ARRAY_SIZE(exynos5_clk_names),
.core_clk_names = exynos5_core_clk_names,
.n_core_clks = ARRAY_SIZE(exynos5_core_clk_names),
.regulator_names = exynosautov920_usb20_regulators,
.n_regulators = ARRAY_SIZE(exynosautov920_usb20_regulators),
};
static const struct exynos5_usbdrd_phy_config phy_cfg_gs101[] = {
{
.id = EXYNOS5_DRDPHY_UTMI,
@ -2260,6 +2902,15 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
}, {
.compatible = "samsung,exynos990-usbdrd-phy",
.data = &exynos990_usbdrd_phy
}, {
.compatible = "samsung,exynosautov920-usb31drd-combo-ssphy",
.data = &exynosautov920_usb31drd_combo_ssphy
}, {
.compatible = "samsung,exynosautov920-usbdrd-combo-hsphy",
.data = &exynosautov920_usbdrd_combo_hsphy
}, {
.compatible = "samsung,exynosautov920-usbdrd-phy",
.data = &exynosautov920_usbdrd_phy
},
{ },
};

View file

@ -106,7 +106,7 @@ static const struct phy_ops uniphier_u2phy_ops = {
static int uniphier_u2phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *parent, *child;
struct device_node *parent;
struct uniphier_u2phy_priv *priv = NULL, *next = NULL;
struct phy_provider *phy_provider;
struct regmap *regmap;
@ -129,34 +129,31 @@ static int uniphier_u2phy_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
}
for_each_child_of_node(dev->of_node, child) {
for_each_child_of_node_scoped(dev->of_node, child) {
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
goto out_put_child;
}
if (!priv)
return -ENOMEM;
priv->regmap = regmap;
priv->vbus = devm_regulator_get_optional(dev, "vbus");
if (IS_ERR(priv->vbus)) {
if (PTR_ERR(priv->vbus) == -EPROBE_DEFER) {
ret = PTR_ERR(priv->vbus);
goto out_put_child;
}
if (PTR_ERR(priv->vbus) == -EPROBE_DEFER)
return PTR_ERR(priv->vbus);
priv->vbus = NULL;
}
priv->phy = devm_phy_create(dev, child, &uniphier_u2phy_ops);
if (IS_ERR(priv->phy)) {
dev_err(dev, "Failed to create phy\n");
ret = PTR_ERR(priv->phy);
goto out_put_child;
return PTR_ERR(priv->phy);
}
ret = of_property_read_u32(child, "reg", &data_idx);
if (ret) {
dev_err(dev, "Failed to get reg property\n");
goto out_put_child;
return ret;
}
if (data_idx < ndatas)
@ -174,11 +171,6 @@ static int uniphier_u2phy_probe(struct platform_device *pdev)
phy_provider = devm_of_phy_provider_register(dev,
uniphier_u2phy_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
out_put_child:
of_node_put(child);
return ret;
}
static const struct uniphier_u2phy_soc_data uniphier_pro4_data[] = {

View file

@ -0,0 +1,13 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Phy drivers for SpacemiT platforms
#
config PHY_SPACEMIT_K1_USB2
tristate "SpacemiT K1 USB 2.0 PHY support"
depends on (ARCH_SPACEMIT || COMPILE_TEST) && OF
depends on COMMON_CLK
depends on USB_COMMON
select GENERIC_PHY
help
Enable this to support K1 USB 2.0 PHY driver. This driver takes care of
enabling and clock setup and will be used by K1 udc/ehci/otg/xhci driver.

View file

@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_PHY_SPACEMIT_K1_USB2) += phy-k1-usb2.o

View file

@ -0,0 +1,200 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* SpacemiT K1 USB 2.0 PHY driver
*
* Copyright (C) 2025 SpacemiT (Hangzhou) Technology Co. Ltd
* Copyright (C) 2025 Ze Huang <huang.ze@linux.dev>
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/iopoll.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/usb/of.h>
#define PHY_RST_MODE_CTRL 0x04
#define PHY_PLL_RDY BIT(0)
#define PHY_CLK_CDR_EN BIT(1)
#define PHY_CLK_PLL_EN BIT(2)
#define PHY_CLK_MAC_EN BIT(3)
#define PHY_MAC_RSTN BIT(5)
#define PHY_CDR_RSTN BIT(6)
#define PHY_PLL_RSTN BIT(7)
/*
* hs line state sel (Bit 13):
* - 1 (Default): Internal HS line state is set to 01 when usb_hs_tx_en is valid.
* - 0: Internal HS line state is always driven by usb_hs_lstate.
*
* fs line state sel (Bit 14):
* - 1 (Default): FS line state is determined by the output data
* (usb_fs_datain/b).
* - 0: FS line state is always determined by the input data (dmo/dpo).
*/
#define PHY_HS_LINE_TX_MODE BIT(13)
#define PHY_FS_LINE_TX_MODE BIT(14)
#define PHY_INIT_MODE_BITS (PHY_FS_LINE_TX_MODE | PHY_HS_LINE_TX_MODE)
#define PHY_CLK_ENABLE_BITS (PHY_CLK_PLL_EN | PHY_CLK_CDR_EN | \
PHY_CLK_MAC_EN)
#define PHY_DEASSERT_RST_BITS (PHY_PLL_RSTN | PHY_CDR_RSTN | \
PHY_MAC_RSTN)
#define PHY_TX_HOST_CTRL 0x10
#define PHY_HST_DISC_AUTO_CLR BIT(2) /* autoclear hs host disc when re-connect */
#define PHY_HSTXP_HW_CTRL 0x34
#define PHY_HSTXP_RSTN BIT(2) /* generate reset for clock hstxp */
#define PHY_CLK_HSTXP_EN BIT(3) /* clock hstxp enable */
#define PHY_HSTXP_MODE BIT(4) /* 0: force en_txp to be 1; 1: no force */
#define PHY_PLL_DIV_CFG 0x98
#define PHY_FDIV_FRACT_8_15 GENMASK(7, 0)
#define PHY_FDIV_FRACT_16_19 GENMASK(11, 8)
#define PHY_FDIV_FRACT_20_21 BIT(12) /* fdiv_reg<21>, <20>, bit21 == bit20 */
/*
* freq_sel<1:0>
* if ref clk freq=24.0MHz-->freq_sel<2:0> == 3b'001, then internal divider value == 80
*/
#define PHY_FDIV_FRACT_0_1 GENMASK(14, 13)
/*
* pll divider value selection
* 1: divider value will choose internal default value ,dependent on freq_sel<1:0>
* 0: divider value will be over ride by fdiv_reg<21:0>
*/
#define PHY_DIV_LOCAL_EN BIT(15)
#define PHY_SEL_FREQ_24MHZ 0x01
#define FDIV_REG_MASK (PHY_FDIV_FRACT_20_21 | PHY_FDIV_FRACT_16_19 | \
PHY_FDIV_FRACT_8_15)
#define FDIV_REG_VAL 0x1ec4 /* 0x100 selects 24MHz, rest are default */
#define K1_USB2PHY_RESET_TIME_MS 50
struct spacemit_usb2phy {
struct phy *phy;
struct clk *clk;
struct regmap *regmap_base;
};
static const struct regmap_config phy_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = 0x200,
};
static int spacemit_usb2phy_init(struct phy *phy)
{
struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
struct regmap *map = sphy->regmap_base;
u32 val;
int ret;
ret = clk_enable(sphy->clk);
if (ret) {
dev_err(&phy->dev, "failed to enable clock\n");
clk_disable(sphy->clk);
return ret;
}
/*
* make sure the usb controller is not under reset process before
* any configuration
*/
usleep_range(150, 200);
/* 24M ref clk */
val = FIELD_PREP(FDIV_REG_MASK, FDIV_REG_VAL) |
FIELD_PREP(PHY_FDIV_FRACT_0_1, PHY_SEL_FREQ_24MHZ) |
PHY_DIV_LOCAL_EN;
regmap_write(map, PHY_PLL_DIV_CFG, val);
ret = regmap_read_poll_timeout(map, PHY_RST_MODE_CTRL, val,
(val & PHY_PLL_RDY),
500, K1_USB2PHY_RESET_TIME_MS * 1000);
if (ret) {
dev_err(&phy->dev, "wait PLLREADY timeout\n");
clk_disable(sphy->clk);
return ret;
}
/* release usb2 phy internal reset and enable clock gating */
val = (PHY_INIT_MODE_BITS | PHY_CLK_ENABLE_BITS | PHY_DEASSERT_RST_BITS);
regmap_write(map, PHY_RST_MODE_CTRL, val);
val = (PHY_HSTXP_RSTN | PHY_CLK_HSTXP_EN | PHY_HSTXP_MODE);
regmap_write(map, PHY_HSTXP_HW_CTRL, val);
/* auto clear host disc */
regmap_update_bits(map, PHY_TX_HOST_CTRL, PHY_HST_DISC_AUTO_CLR,
PHY_HST_DISC_AUTO_CLR);
return 0;
}
static int spacemit_usb2phy_exit(struct phy *phy)
{
struct spacemit_usb2phy *sphy = phy_get_drvdata(phy);
clk_disable(sphy->clk);
return 0;
}
static const struct phy_ops spacemit_usb2phy_ops = {
.init = spacemit_usb2phy_init,
.exit = spacemit_usb2phy_exit,
.owner = THIS_MODULE,
};
static int spacemit_usb2phy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
struct spacemit_usb2phy *sphy;
void __iomem *base;
sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
if (!sphy)
return -ENOMEM;
sphy->clk = devm_clk_get_prepared(&pdev->dev, NULL);
if (IS_ERR(sphy->clk))
return dev_err_probe(dev, PTR_ERR(sphy->clk), "Failed to get clock\n");
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
sphy->regmap_base = devm_regmap_init_mmio(dev, base, &phy_regmap_config);
if (IS_ERR(sphy->regmap_base))
return dev_err_probe(dev, PTR_ERR(sphy->regmap_base), "Failed to init regmap\n");
sphy->phy = devm_phy_create(dev, NULL, &spacemit_usb2phy_ops);
if (IS_ERR(sphy->phy))
return dev_err_probe(dev, PTR_ERR(sphy->phy), "Failed to create phy\n");
phy_set_drvdata(sphy->phy, sphy);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id spacemit_usb2phy_dt_match[] = {
{ .compatible = "spacemit,k1-usb2-phy", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, spacemit_usb2phy_dt_match);
static struct platform_driver spacemit_usb2_phy_driver = {
.probe = spacemit_usb2phy_probe,
.driver = {
.name = "spacemit-usb2-phy",
.of_match_table = spacemit_usb2phy_dt_match,
},
};
module_platform_driver(spacemit_usb2_phy_driver);
MODULE_DESCRIPTION("Spacemit USB 2.0 PHY driver");
MODULE_LICENSE("GPL");

View file

@ -69,7 +69,6 @@ struct tegra_xusb_usb2_lane {
struct tegra_xusb_lane base;
u32 hs_curr_level_offset;
bool powered_on;
};
static inline struct tegra_xusb_usb2_lane *

View file

@ -393,6 +393,7 @@ struct wiz {
struct clk *output_clks[WIZ_MAX_OUTPUT_CLOCKS];
struct clk_onecell_data clk_data;
const struct wiz_data *data;
int mux_sel_status[WIZ_MUX_NUM_CLOCKS];
};
static int wiz_reset(struct wiz *wiz)
@ -934,12 +935,12 @@ static unsigned long wiz_clk_div_recalc_rate(struct clk_hw *hw,
return divider_recalc_rate(hw, parent_rate, val, div->table, 0x0, 2);
}
static long wiz_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int wiz_clk_div_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct wiz_clk_divider *div = to_wiz_clk_div(hw);
return divider_round_rate(hw, rate, prate, div->table, 2, 0x0);
return divider_determine_rate(hw, req, div->table, 2, 0x0);
}
static int wiz_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
@ -958,7 +959,7 @@ static int wiz_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops wiz_clk_div_ops = {
.recalc_rate = wiz_clk_div_recalc_rate,
.round_rate = wiz_clk_div_round_rate,
.determine_rate = wiz_clk_div_determine_rate,
.set_rate = wiz_clk_div_set_rate,
};
@ -1654,11 +1655,25 @@ static void wiz_remove(struct platform_device *pdev)
pm_runtime_disable(dev);
}
static int wiz_suspend_noirq(struct device *dev)
{
struct wiz *wiz = dev_get_drvdata(dev);
int i;
for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++)
regmap_field_read(wiz->mux_sel_field[i], &wiz->mux_sel_status[i]);
return 0;
}
static int wiz_resume_noirq(struct device *dev)
{
struct device_node *node = dev->of_node;
struct wiz *wiz = dev_get_drvdata(dev);
int ret;
int ret, i;
for (i = 0; i < WIZ_MUX_NUM_CLOCKS; i++)
regmap_field_write(wiz->mux_sel_field[i], wiz->mux_sel_status[i]);
/* Enable supplemental Control override if available */
if (wiz->sup_legacy_clk_override)
@ -1680,7 +1695,7 @@ err_wiz_init:
return ret;
}
static DEFINE_NOIRQ_DEV_PM_OPS(wiz_pm_ops, NULL, wiz_resume_noirq);
static DEFINE_NOIRQ_DEV_PM_OPS(wiz_pm_ops, wiz_suspend_noirq, wiz_resume_noirq);
static struct platform_driver wiz_driver = {
.probe = wiz_probe,

View file

@ -38,6 +38,10 @@ config APPLE_SART
Say 'y' here if you have an Apple SoC.
config APPLE_TUNABLE
tristate
depends on ARCH_APPLE || COMPILE_TEST
endmenu
endif

View file

@ -8,3 +8,6 @@ apple-rtkit-y = rtkit.o rtkit-crashlog.o
obj-$(CONFIG_APPLE_SART) += apple-sart.o
apple-sart-y = sart.o
obj-$(CONFIG_APPLE_TUNABLE) += apple-tunable.o
apple-tunable-y = tunable.o

View file

@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
* Apple Silicon hardware tunable support
*
* Each tunable is a list with each entry containing a offset into the MMIO
* region, a mask of bits to be cleared and a set of bits to be set. These
* tunables are passed along by the previous boot stages and vary from device
* to device such that they cannot be hardcoded in the individual drivers.
*
* Copyright (C) The Asahi Linux Contributors
*/
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/overflow.h>
#include <linux/soc/apple/tunable.h>
struct apple_tunable *devm_apple_tunable_parse(struct device *dev,
struct device_node *np,
const char *name,
struct resource *res)
{
struct apple_tunable *tunable;
struct property *prop;
const __be32 *p;
size_t sz;
int i;
if (resource_size(res) < 4)
return ERR_PTR(-EINVAL);
prop = of_find_property(np, name, NULL);
if (!prop)
return ERR_PTR(-ENOENT);
if (prop->length % (3 * sizeof(u32)))
return ERR_PTR(-EINVAL);
sz = prop->length / (3 * sizeof(u32));
tunable = devm_kzalloc(dev, struct_size(tunable, values, sz), GFP_KERNEL);
if (!tunable)
return ERR_PTR(-ENOMEM);
tunable->sz = sz;
for (i = 0, p = NULL; i < tunable->sz; ++i) {
p = of_prop_next_u32(prop, p, &tunable->values[i].offset);
p = of_prop_next_u32(prop, p, &tunable->values[i].mask);
p = of_prop_next_u32(prop, p, &tunable->values[i].value);
/* Sanity checks to catch bugs in our bootloader */
if (tunable->values[i].offset % 4)
return ERR_PTR(-EINVAL);
if (tunable->values[i].offset > (resource_size(res) - 4))
return ERR_PTR(-EINVAL);
}
return tunable;
}
EXPORT_SYMBOL(devm_apple_tunable_parse);
void apple_tunable_apply(void __iomem *regs, struct apple_tunable *tunable)
{
size_t i;
for (i = 0; i < tunable->sz; ++i) {
u32 val, old_val;
old_val = readl(regs + tunable->values[i].offset);
val = old_val & ~tunable->values[i].mask;
val |= tunable->values[i].value;
if (val != old_val)
writel(val, regs + tunable->values[i].offset);
}
}
EXPORT_SYMBOL(apple_tunable_apply);
MODULE_LICENSE("Dual MIT/GPL");
MODULE_AUTHOR("Sven Peter <sven@kernel.org>");
MODULE_DESCRIPTION("Apple Silicon hardware tunable support");

View file

@ -23,6 +23,7 @@
#define PHY_TYPE_DPHY 10
#define PHY_TYPE_CPHY 11
#define PHY_TYPE_USXGMII 12
#define PHY_TYPE_XAUI 13
#define PHY_POL_NORMAL 0
#define PHY_POL_INVERT 1

View file

@ -6,16 +6,31 @@
#ifndef __PHY_HDMI_H_
#define __PHY_HDMI_H_
#include <linux/types.h>
enum phy_hdmi_mode {
PHY_HDMI_MODE_TMDS,
PHY_HDMI_MODE_FRL,
};
/**
* struct phy_configure_opts_hdmi - HDMI configuration set
* @tmds_char_rate: HDMI TMDS Character Rate in Hertz.
* @bpc: Bits per color channel.
* @tmds_char_rate: HDMI TMDS Character Rate in Hertz.
* @frl.rate_per_lane: HDMI FRL Rate per Lane in Gbps.
* @frl.lanes: HDMI FRL lanes count.
*
* This structure is used to represent the configuration state of a HDMI phy.
*/
struct phy_configure_opts_hdmi {
unsigned long long tmds_char_rate;
unsigned int bpc;
union {
unsigned long long tmds_char_rate;
struct {
u8 rate_per_lane;
u8 lanes;
} frl;
};
};
#endif /* __PHY_HDMI_H_ */

View file

@ -243,7 +243,7 @@ static inline void *phy_get_drvdata(struct phy *phy)
#if IS_ENABLED(CONFIG_GENERIC_PHY)
int phy_pm_runtime_get(struct phy *phy);
int phy_pm_runtime_get_sync(struct phy *phy);
int phy_pm_runtime_put(struct phy *phy);
void phy_pm_runtime_put(struct phy *phy);
int phy_pm_runtime_put_sync(struct phy *phy);
int phy_init(struct phy *phy);
int phy_exit(struct phy *phy);
@ -324,11 +324,8 @@ static inline int phy_pm_runtime_get_sync(struct phy *phy)
return -ENOSYS;
}
static inline int phy_pm_runtime_put(struct phy *phy)
static inline void phy_pm_runtime_put(struct phy *phy)
{
if (!phy)
return 0;
return -ENOSYS;
}
static inline int phy_pm_runtime_put_sync(struct phy *phy)

View file

@ -0,0 +1,62 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
/*
* Apple Silicon hardware tunable support
*
* Each tunable is a list with each entry containing a offset into the MMIO
* region, a mask of bits to be cleared and a set of bits to be set. These
* tunables are passed along by the previous boot stages and vary from device
* to device such that they cannot be hardcoded in the individual drivers.
*
* Copyright (C) The Asahi Linux Contributors
*/
#ifndef _LINUX_SOC_APPLE_TUNABLE_H_
#define _LINUX_SOC_APPLE_TUNABLE_H_
#include <linux/device.h>
#include <linux/types.h>
/**
* Struct to store an Apple Silicon hardware tunable.
*
* Each tunable is a list with each entry containing a offset into the MMIO
* region, a mask of bits to be cleared and a set of bits to be set. These
* tunables are passed along by the previous boot stages and vary from device
* to device such that they cannot be hardcoded in the individual drivers.
*
* @param sz Number of [offset, mask, value] tuples stored in values.
* @param values [offset, mask, value] array.
*/
struct apple_tunable {
size_t sz;
struct {
u32 offset;
u32 mask;
u32 value;
} values[] __counted_by(sz);
};
/**
* Parse an array of hardware tunables from the device tree.
*
* @dev: Device node used for devm_kzalloc internally.
* @np: Device node which contains the tunable array.
* @name: Name of the device tree property which contains the tunables.
* @res: Resource to which the tunables will be applied, used for bound checking
*
* @return: devres allocated struct on success or PTR_ERR on failure.
*/
struct apple_tunable *devm_apple_tunable_parse(struct device *dev,
struct device_node *np,
const char *name,
struct resource *res);
/**
* Apply a previously loaded hardware tunable.
*
* @param regs: MMIO to which the tunable will be applied.
* @param tunable: Pointer to the tunable.
*/
void apple_tunable_apply(void __iomem *regs, struct apple_tunable *tunable);
#endif

View file

@ -1015,4 +1015,7 @@
#define GS101_GRP2_INTR_BID_UPEND (0x0208)
#define GS101_GRP2_INTR_BID_CLEAR (0x020c)
/* exynosautov920 */
#define EXYNOSAUTOV920_PHY_CTRL_USB20 (0x0710)
#define EXYNOSAUTOV920_PHY_CTRL_USB31 (0x0714)
#endif /* __LINUX_SOC_EXYNOS_REGS_PMU_H */