phy-for-6.11

- New Support
   - Samsung Exynos gs101 drd combo phy
   - Qualcomm SC8180x USB uniphy, IPQ9574 QMP PCIe phy
   - Airoha EN7581 PCIe phy
   - Freescale i.MX8Q HSIO SerDes phy
   - Starfive jh7110 dphy tx
 
 - Updates
   - Resume support for j721e-wiz driver
   - Updates to Exynos usbdrd driver
   - Support for optional power domains in g12a usb2-phy driver
   - Debugfs support and updates to zynqmp driver
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmagrXcACgkQfBQHDyUj
 g0d70Q//WxsWO59+bXIbqRk1YyXOZBlV9vAF+4hrHohwH8CBkJsSLhmWPvM8oUID
 5OI9zFYqNUH9PnBtL4CkGkyvsdJAks98qIAIDxL5W500WWEbhjj874rb+BJR6/pm
 6LsojpgKnYL/Aq9wOtONZbztdHBK9xkoFTh3+g/EcA505O7j1ZdhW2JDkvFA6xdw
 9xQvf18IfOysz/ZnOzvdVzxsS1X19fm/v+4aWOzqQSNQeOppU3ZqInXsSAy2moUY
 UJ1b9b1WIslrsM0ZFVXhPOVEJp86ZuFC3PW5bJHWcTvbDrnUWz3PPWH3XwFca8fi
 EdP+8dAzvEvJsKtqZu034z5l9tAOiqOwMCs2loxEauHKihzklMko/dUkUs0IANA+
 UULLLEtLH9mGjNWKADJvIbzFFd+Tsv9H6GjoXTKWx7P+BrkBTuIKzDmDqM/kkjgU
 pYyj65eJJr7R5eLfoDKdIDDiWO7HfZfF8ujsvych5Pft/Kbxd/rTBSADbDz/6ljZ
 lgvC0XE4T6tMWkwwX+SHUHzJlcQFYBZ09txLgpGdHBmgywPZsJoK4/52BNADEes/
 LSe1jgegkc7LMVpfqhqIlHXLmaR+qXY+j5Y5jvYv5bVHx5syHrk7emrQT7YCtkpi
 0eJ9IUyFrteeheL1SuNw+BqUuDMBTaOomfzJWyGX4r36Nspg23c=
 =KWse
 -----END PGP SIGNATURE-----

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

Pull phy updates from Vinod Koul:
 "New Support
   - Samsung Exynos gs101 drd combo phy
   - Qualcomm SC8180x USB uniphy, IPQ9574 QMP PCIe phy
   - Airoha EN7581 PCIe phy
   - Freescale i.MX8Q HSIO SerDes phy
   - Starfive jh7110 dphy tx

  Updates:
   - Resume support for j721e-wiz driver
   - Updates to Exynos usbdrd driver
   - Support for optional power domains in g12a usb2-phy driver
   - Debugfs support and updates to zynqmp driver"

* tag 'phy-for-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (56 commits)
  phy: airoha: Add dtime and Rx AEQ IO registers
  dt-bindings: phy: airoha: Add dtime and Rx AEQ IO registers
  dt-bindings: phy: rockchip-emmc-phy: Convert to dtschema
  dt-bindings: phy: qcom,qmp-usb: fix spelling error
  phy: exynos5-usbdrd: support Exynos USBDRD 3.1 combo phy (HS & SS)
  phy: exynos5-usbdrd: convert Vbus supplies to regulator_bulk
  phy: exynos5-usbdrd: convert (phy) register access clock to clk_bulk
  phy: exynos5-usbdrd: convert core clocks to clk_bulk
  phy: exynos5-usbdrd: support isolating HS and SS ports independently
  dt-bindings: phy: samsung,usb3-drd-phy: add gs101 compatible
  phy: core: Fix documentation of of_phy_get
  phy: starfive: Correct the dphy configure process
  phy: zynqmp: Add debugfs support
  phy: zynqmp: Take the phy mutex in xlate
  phy: zynqmp: Only wait for PLL lock "primary" instances
  phy: zynqmp: Store instance instead of type
  phy: zynqmp: Enable reference clock correctly
  phy: cadence-torrent: Check return value on register read
  phy: Fix the cacography in phy-exynos5250-usb2.c
  phy: phy-rockchip-samsung-hdptx: Select CONFIG_MFD_SYSCON
  ...
This commit is contained in:
Linus Torvalds 2024-07-24 13:11:28 -07:00
commit c33ffdb70c
41 changed files with 4923 additions and 452 deletions

View File

@ -0,0 +1,69 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/airoha,en7581-pcie-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Airoha EN7581 PCI-Express PHY
maintainers:
- Lorenzo Bianconi <lorenzo@kernel.org>
description:
The PCIe PHY supports physical layer functionality for PCIe Gen2/Gen3 port.
properties:
compatible:
const: airoha,en7581-pcie-phy
reg:
items:
- description: PCIE analog base address
- description: PCIE lane0 base address
- description: PCIE lane1 base address
- description: PCIE lane0 detection time base address
- description: PCIE lane1 detection time base address
- description: PCIE Rx AEQ base address
reg-names:
items:
- const: csr-2l
- const: pma0
- const: pma1
- const: p0-xr-dtime
- const: p1-xr-dtime
- const: rx-aeq
"#phy-cells":
const: 0
required:
- compatible
- reg
- reg-names
- "#phy-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/phy/phy.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
phy@11e80000 {
compatible = "airoha,en7581-pcie-phy";
#phy-cells = <0>;
reg = <0x0 0x1fa5a000 0x0 0xfff>,
<0x0 0x1fa5b000 0x0 0xfff>,
<0x0 0x1fa5c000 0x0 0xfff>,
<0x0 0x1fc10044 0x0 0x4>,
<0x0 0x1fc30044 0x0 0x4>,
<0x0 0x1fc15030 0x0 0x104>;
reg-names = "csr-2l", "pma0", "pma1",
"p0-xr-dtime", "p1-xr-dtime",
"rx-aeq";
};
};

View File

@ -41,6 +41,9 @@ properties:
Phandle to a regulator that provides power to the PHY. This
regulator will be managed during the PHY power on/off sequence.
power-domains:
maxItems: 1
required:
- compatible
- reg

View File

@ -0,0 +1,164 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/fsl,imx8qm-hsio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale i.MX8QM SoC series High Speed IO(HSIO) SERDES PHY
maintainers:
- Richard Zhu <hongxing.zhu@nxp.com>
properties:
compatible:
enum:
- fsl,imx8qm-hsio
- fsl,imx8qxp-hsio
reg:
items:
- description: Base address and length of the PHY block
- description: HSIO control and status registers(CSR) of the PHY
- description: HSIO CSR of the controller bound to the PHY
- description: HSIO CSR for MISC
reg-names:
items:
- const: reg
- const: phy
- const: ctrl
- const: misc
"#phy-cells":
const: 3
description:
The first defines lane index.
The second defines the type of the PHY refer to the include phy.h.
The third defines the controller index, indicated which controller
is bound to the lane.
clocks:
minItems: 5
maxItems: 14
clock-names:
minItems: 5
maxItems: 14
fsl,hsio-cfg:
description: |
Specifies the use case of the HSIO module in the hardware design.
Regarding the design of i.MX8QM HSIO subsystem, HSIO module can be
confiured as following three use cases.
+---------------------------------------+
| | i.MX8QM |
|------------------|--------------------|
| | Lane0| Lane1| Lane2|
|------------------|------|------|------|
| pciea-x2-sata | PCIEA| PCIEA| SATA |
|------------------|------|------|------|
| pciea-x2-pcieb | PCIEA| PCIEA| PCIEB|
|------------------|------|------|------|
| pciea-pcieb-sata | PCIEA| PCIEB| SATA |
+---------------------------------------+
$ref: /schemas/types.yaml#/definitions/string
enum: [ pciea-x2-sata, pciea-x2-pcieb, pciea-pcieb-sata]
default: pciea-pcieb-sata
fsl,refclk-pad-mode:
description:
Specifies the mode of the refclk pad used. INPUT(PHY refclock is
provided externally via the refclk pad) or OUTPUT(PHY refclock is
derived from SoC internal source and provided on the refclk pad).
This property not exists means unused(PHY refclock is derived from
SoC internal source).
$ref: /schemas/types.yaml#/definitions/string
enum: [ input, output, unused ]
default: unused
power-domains:
minItems: 1
maxItems: 2
required:
- compatible
- reg
- reg-names
- "#phy-cells"
- clocks
- clock-names
- fsl,hsio-cfg
allOf:
- if:
properties:
compatible:
contains:
enum:
- fsl,imx8qxp-hsio
then:
properties:
clock-names:
items:
- const: pclk0
- const: apb_pclk0
- const: phy0_crr
- const: ctl0_crr
- const: misc_crr
power-domains:
maxItems: 1
- if:
properties:
compatible:
contains:
enum:
- fsl,imx8qm-hsio
then:
properties:
clock-names:
items:
- const: pclk0
- const: pclk1
- const: apb_pclk0
- const: apb_pclk1
- const: pclk2
- const: epcs_tx
- const: epcs_rx
- const: apb_pclk2
- const: phy0_crr
- const: phy1_crr
- const: ctl0_crr
- const: ctl1_crr
- const: ctl2_crr
- const: misc_crr
power-domains:
minItems: 2
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/imx8-clock.h>
#include <dt-bindings/clock/imx8-lpcg.h>
#include <dt-bindings/firmware/imx/rsrc.h>
#include <dt-bindings/phy/phy-imx8-pcie.h>
phy@5f1a0000 {
compatible = "fsl,imx8qxp-hsio";
reg = <0x5f1a0000 0x10000>,
<0x5f120000 0x10000>,
<0x5f140000 0x10000>,
<0x5f160000 0x10000>;
reg-names = "reg", "phy", "ctrl", "misc";
clocks = <&phyx1_lpcg IMX_LPCG_CLK_0>,
<&phyx1_lpcg IMX_LPCG_CLK_4>,
<&phyx1_crr1_lpcg IMX_LPCG_CLK_4>,
<&pcieb_crr3_lpcg IMX_LPCG_CLK_4>,
<&misc_crr5_lpcg IMX_LPCG_CLK_4>;
clock-names = "pclk0", "apb_pclk0", "phy0_crr", "ctl0_crr", "misc_crr";
power-domains = <&pd IMX_SC_R_SERDES_1>;
#phy-cells = <3>;
fsl,hsio-cfg = "pciea-pcieb-sata";
fsl,refclk-pad-mode = "input";
};
...

View File

@ -41,6 +41,12 @@ properties:
Phandle to the system controller node
$ref: /schemas/types.yaml#/definitions/phandle
swap-dx-lanes:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: |
Specifies the ports which will swap the differential-pair (D+/D-),
default is not-swapped.
# Required child nodes:
patternProperties:

View File

@ -19,6 +19,8 @@ properties:
- qcom,ipq6018-qmp-pcie-phy
- qcom,ipq8074-qmp-gen3-pcie-phy
- qcom,ipq8074-qmp-pcie-phy
- qcom,ipq9574-qmp-gen3x1-pcie-phy
- qcom,ipq9574-qmp-gen3x2-pcie-phy
reg:
items:

View File

@ -91,8 +91,7 @@ properties:
"#clock-cells": true
clock-output-names:
minItems: 1
maxItems: 2
maxItems: 1
"#phy-cells":
const: 0
@ -222,14 +221,10 @@ allOf:
- qcom,sm8650-qmp-gen4x2-pcie-phy
then:
properties:
clock-output-names:
minItems: 2
"#clock-cells":
const: 1
else:
properties:
clock-output-names:
maxItems: 1
"#clock-cells":
const: 0

View File

@ -20,8 +20,9 @@ properties:
- qcom,ipq8074-qmp-usb3-phy
- qcom,ipq9574-qmp-usb3-phy
- qcom,msm8996-qmp-usb3-phy
- com,qdu1000-qmp-usb3-uni-phy
- qcom,qdu1000-qmp-usb3-uni-phy
- qcom,sa8775p-qmp-usb3-uni-phy
- qcom,sc8180x-qmp-usb3-uni-phy
- qcom,sc8280xp-qmp-usb3-uni-phy
- qcom,sdm845-qmp-usb3-uni-phy
- qcom,sdx55-qmp-usb3-uni-phy
@ -112,6 +113,7 @@ allOf:
enum:
- qcom,qdu1000-qmp-usb3-uni-phy
- qcom,sa8775p-qmp-usb3-uni-phy
- qcom,sc8180x-qmp-usb3-uni-phy
- qcom,sc8280xp-qmp-usb3-uni-phy
- qcom,sm8150-qmp-usb3-uni-phy
- qcom,sm8250-qmp-usb3-uni-phy
@ -152,6 +154,7 @@ allOf:
contains:
enum:
- qcom,sa8775p-qmp-usb3-uni-phy
- qcom,sc8180x-qmp-usb3-uni-phy
- qcom,sc8280xp-qmp-usb3-uni-phy
- qcom,x1e80100-qmp-usb3-uni-phy
then:

View File

@ -15,6 +15,7 @@ if:
contains:
enum:
- qcom,usb-hs-phy-apq8064
- qcom,usb-hs-phy-msm8660
- qcom,usb-hs-phy-msm8960
then:
properties:
@ -41,6 +42,7 @@ properties:
- enum:
- qcom,usb-hs-phy-apq8064
- qcom,usb-hs-phy-msm8226
- qcom,usb-hs-phy-msm8660
- qcom,usb-hs-phy-msm8916
- qcom,usb-hs-phy-msm8960
- qcom,usb-hs-phy-msm8974

View File

@ -0,0 +1,64 @@
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/rockchip,rk3399-emmc-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip EMMC PHY
maintainers:
- Heiko Stuebner <heiko@sntech.de>
properties:
compatible:
const: rockchip,rk3399-emmc-phy
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: emmcclk
drive-impedance-ohm:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Specifies the drive impedance in Ohm.
enum: [33, 40, 50, 66, 100]
default: 50
rockchip,enable-strobe-pulldown:
type: boolean
description: |
Enable internal pull-down for the strobe
line. If not set, pull-down is not used.
rockchip,output-tapdelay-select:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Specifies the phyctrl_otapdlysec register.
default: 0x4
maximum: 0xf
"#phy-cells":
const: 0
required:
- compatible
- reg
- "#phy-cells"
additionalProperties: false
examples:
- |
phy@f780 {
compatible = "rockchip,rk3399-emmc-phy";
reg = <0xf780 0x20>;
clocks = <&sdhci>;
clock-names = "emmcclk";
drive-impedance-ohm = <50>;
#phy-cells = <0>;
};

View File

@ -1,43 +0,0 @@
Rockchip EMMC PHY
-----------------------
Required properties:
- compatible: rockchip,rk3399-emmc-phy
- #phy-cells: must be 0
- reg: PHY register address offset and length in "general
register files"
Optional properties:
- clock-names: Should contain "emmcclk". Although this is listed as optional
(because most boards can get basic functionality without having
access to it), it is strongly suggested.
See ../clock/clock-bindings.txt for details.
- clocks: Should have a phandle to the card clock exported by the SDHCI driver.
- drive-impedance-ohm: Specifies the drive impedance in Ohm.
Possible values are 33, 40, 50, 66 and 100.
If not set, the default value of 50 will be applied.
- rockchip,enable-strobe-pulldown: Enable internal pull-down for the strobe
line. If not set, pull-down is not used.
- rockchip,output-tapdelay-select: Specifies the phyctrl_otapdlysec register.
If not set, the register defaults to 0x4.
Maximum value 0xf.
Example:
grf: syscon@ff770000 {
compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
#address-cells = <1>;
#size-cells = <1>;
...
emmcphy: phy@f780 {
compatible = "rockchip,rk3399-emmc-phy";
reg = <0xf780 0x20>;
clocks = <&sdhci>;
clock-names = "emmcclk";
drive-impedance-ohm = <50>;
#phy-cells = <0>;
};
};

View File

@ -25,6 +25,7 @@ description: |
properties:
compatible:
enum:
- google,gs101-usb31drd-phy
- samsung,exynos5250-usbdrd-phy
- samsung,exynos5420-usbdrd-phy
- samsung,exynos5433-usbdrd-phy
@ -57,7 +58,15 @@ properties:
the OF graph bindings specified.
reg:
maxItems: 1
minItems: 1
maxItems: 3
reg-names:
minItems: 1
items:
- const: phy
- const: pcs
- const: pma
samsung,pmu-syscon:
$ref: /schemas/types.yaml#/definitions/phandle
@ -72,6 +81,19 @@ properties:
description:
VBUS Boost 5V power source.
pll-supply:
description: Power supply for the USB PLL.
dvdd-usb20-supply:
description: DVDD power supply for the USB 2.0 phy.
vddh-usb20-supply:
description: VDDh power supply for the USB 2.0 phy.
vdd33-usb20-supply:
description: 3.3V power supply for the USB 2.0 phy.
vdda-usbdp-supply:
description: VDDa power supply for the USB DP phy.
vddh-usbdp-supply:
description: VDDh power supply for the USB DP phy.
required:
- compatible
- clocks
@ -81,6 +103,40 @@ required:
- samsung,pmu-syscon
allOf:
- if:
properties:
compatible:
contains:
const: google,gs101-usb31drd-phy
then:
properties:
clocks:
items:
- description: Gate of main PHY clock
- description: Gate of PHY reference clock
- description: Gate of control interface AXI clock
- description: Gate of control interface APB clock
- description: Gate of SCL APB clock
clock-names:
items:
- const: phy
- const: ref
- const: ctrl_aclk
- const: ctrl_pclk
- const: scl_pclk
reg:
minItems: 3
reg-names:
minItems: 3
required:
- reg-names
- pll-supply
- dvdd-usb20-supply
- vddh-usb20-supply
- vdd33-usb20-supply
- vdda-usbdp-supply
- vddh-usbdp-supply
- if:
properties:
compatible:
@ -100,7 +156,20 @@ allOf:
- const: phy_utmi
- const: phy_pipe
- const: itp
else:
reg:
maxItems: 1
reg-names:
maxItems: 1
- if:
properties:
compatible:
contains:
enum:
- samsung,exynos5250-usbdrd-phy
- samsung,exynos5420-usbdrd-phy
- samsung,exynos850-usbdrd-phy
then:
properties:
clocks:
minItems: 2
@ -109,6 +178,10 @@ allOf:
items:
- const: phy
- const: ref
reg:
maxItems: 1
reg-names:
maxItems: 1
additionalProperties: false

View File

@ -0,0 +1,68 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/starfive,jh7110-dphy-tx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Starfive SoC MIPI D-PHY Tx Controller
maintainers:
- Keith Zhao <keith.zhao@starfivetech.com>
- Shengyang Chen <shengyang.chen@starfivetech.com>
description:
The Starfive SoC uses the MIPI DSI D-PHY based on M31 IP to transfer
DSI data.
properties:
compatible:
const: starfive,jh7110-dphy-tx
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: txesc
resets:
items:
- description: MIPITX_DPHY_SYS reset
reset-names:
items:
- const: sys
power-domains:
maxItems: 1
"#phy-cells":
const: 0
required:
- compatible
- reg
- clocks
- clock-names
- resets
- reset-names
- power-domains
- "#phy-cells"
additionalProperties: false
examples:
- |
phy@295e0000 {
compatible = "starfive,jh7110-dphy-tx";
reg = <0x295e0000 0x10000>;
clocks = <&voutcrg 14>;
clock-names = "txesc";
resets = <&syscrg 10>;
reset-names = "sys";
power-domains = <&aon_syscon 0>;
#phy-cells = <0>;
};

View File

@ -176,9 +176,10 @@ allOf:
Documentation/devicetree/bindings/phy/rockchip-pcie-phy.txt
patternProperties:
"phy@[0-9a-f]+$":
description:
Documentation/devicetree/bindings/phy/rockchip-emmc-phy.txt
"^phy@[0-9a-f]+$":
type: object
$ref: /schemas/phy/rockchip,rk3399-emmc-phy.yaml#
unevaluatedProperties: false
- if:
properties:
@ -292,6 +293,15 @@ examples:
#phy-cells = <0>;
};
phy@f780 {
compatible = "rockchip,rk3399-emmc-phy";
reg = <0xf780 0x20>;
clocks = <&sdhci>;
clock-names = "emmcclk";
drive-impedance-ohm = <50>;
#phy-cells = <0>;
};
u2phy0: usb2phy@e450 {
compatible = "rockchip,rk3399-usb2phy";
reg = <0xe450 0x10>;

View File

@ -702,6 +702,14 @@ S: Maintained
F: Documentation/devicetree/bindings/net/airoha,en7581-eth.yaml
F: drivers/net/ethernet/mediatek/airoha_eth.c
AIROHA PCIE PHY DRIVER
M: Lorenzo Bianconi <lorenzo@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.yaml
F: drivers/phy/phy-airoha-pcie-regs.h
F: drivers/phy/phy-airoha-pcie.c
AIROHA SPI SNFI DRIVER
M: Lorenzo Bianconi <lorenzo@kernel.org>
M: Ray Liu <ray.liu@airoha.com>
@ -21682,6 +21690,13 @@ S: Supported
F: Documentation/devicetree/bindings/phy/starfive,jh7110-dphy-rx.yaml
F: drivers/phy/starfive/phy-jh7110-dphy-rx.c
STARFIVE JH7110 DPHY TX DRIVER
M: Keith Zhao <keith.zhao@starfivetech.com>
M: Shengyang Chen <shengyang.chen@starfivetech.com>
S: Supported
F: Documentation/devicetree/bindings/phy/starfive,jh7110-dphy-tx.yaml
F: drivers/phy/starfive/phy-jh7110-dphy-tx.c
STARFIVE JH7110 MMC/SD/SDIO DRIVER
M: William Qiu <william.qiu@starfivetech.com>
S: Supported

View File

@ -72,6 +72,16 @@ config PHY_CAN_TRANSCEIVER
functional modes using gpios and sets the attribute max link
rate, for CAN drivers.
config PHY_AIROHA_PCIE
tristate "Airoha PCIe-PHY Driver"
depends on ARCH_AIROHA || COMPILE_TEST
depends on OF
select GENERIC_PHY
help
Say Y here to add support for Airoha PCIe PHY driver.
This driver create the basic PHY instance and provides initialize
callback for PCIe GEN3 port.
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/broadcom/Kconfig"

View File

@ -10,6 +10,7 @@ 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
obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o
obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
obj-y += allwinner/ \
amlogic/ \
broadcom/ \

View File

@ -162,4 +162,5 @@ static struct platform_driver bcm_ns_usb2_driver = {
};
module_platform_driver(bcm_ns_usb2_driver);
MODULE_DESCRIPTION("Broadcom Northstar USB 2.0 PHY Driver");
MODULE_LICENSE("GPL v2");

View File

@ -240,5 +240,6 @@ static struct mdio_driver bcm_ns_usb3_mdio_driver = {
mdio_module_driver(bcm_ns_usb3_mdio_driver);
MODULE_DESCRIPTION("Broadcom Northstar USB 3.0 PHY Driver");
MODULE_LICENSE("GPL v2");
MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table);

View File

@ -360,6 +360,7 @@ struct cdns_torrent_phy {
enum cdns_torrent_ref_clk ref_clk1_rate;
struct cdns_torrent_inst phys[MAX_NUM_LANES];
int nsubnodes;
int already_configured;
const struct cdns_torrent_data *init_data;
struct regmap *regmap_common_cdb;
struct regmap *regmap_phy_pcs_common_cdb;
@ -1156,6 +1157,9 @@ static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_POWER_STATE_ACK,
read_val, (read_val & mask) == value, 0,
POLL_TIMEOUT_US);
if (ret)
return ret;
cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000);
ndelay(100);
@ -1594,6 +1598,9 @@ static int cdns_torrent_dp_configure(struct phy *phy,
struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
int ret;
if (cdns_phy->already_configured)
return 0;
ret = cdns_torrent_dp_verify_config(inst, &opts->dp);
if (ret) {
dev_err(&phy->dev, "invalid params for phy configure\n");
@ -1629,6 +1636,12 @@ static int cdns_torrent_phy_on(struct phy *phy)
u32 read_val;
int ret;
if (cdns_phy->already_configured) {
/* Give 5ms to 10ms delay for the PIPE clock to be stable */
usleep_range(5000, 10000);
return 0;
}
if (cdns_phy->nsubnodes == 1) {
/* Take the PHY lane group out of reset */
reset_control_deassert(inst->lnk_rst);
@ -2307,6 +2320,9 @@ static int cdns_torrent_phy_init(struct phy *phy)
u32 num_regs;
int i, j;
if (cdns_phy->already_configured)
return 0;
if (cdns_phy->nsubnodes > 1) {
if (phy_type == TYPE_DP)
return cdns_torrent_dp_multilink_init(cdns_phy, inst, phy);
@ -2444,19 +2460,6 @@ static const struct phy_ops cdns_torrent_phy_ops = {
.owner = THIS_MODULE,
};
static int cdns_torrent_noop_phy_on(struct phy *phy)
{
/* Give 5ms to 10ms delay for the PIPE clock to be stable */
usleep_range(5000, 10000);
return 0;
}
static const struct phy_ops noop_ops = {
.power_on = cdns_torrent_noop_phy_on,
.owner = THIS_MODULE,
};
static
int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy)
{
@ -2678,7 +2681,7 @@ static int cdns_torrent_clk_register(struct cdns_torrent_phy *cdns_phy)
return 0;
}
static int cdns_torrent_reset(struct cdns_torrent_phy *cdns_phy)
static int cdns_torrent_of_get_reset(struct cdns_torrent_phy *cdns_phy)
{
struct device *dev = cdns_phy->dev;
@ -2699,20 +2702,29 @@ static int cdns_torrent_reset(struct cdns_torrent_phy *cdns_phy)
return 0;
}
static int cdns_torrent_of_get_clk(struct cdns_torrent_phy *cdns_phy)
{
/* refclk: Input reference clock for PLL0 */
cdns_phy->clk = devm_clk_get(cdns_phy->dev, "refclk");
if (IS_ERR(cdns_phy->clk))
return dev_err_probe(cdns_phy->dev, PTR_ERR(cdns_phy->clk),
"phy ref clock not found\n");
/* refclk1: Input reference clock for PLL1 */
cdns_phy->clk1 = devm_clk_get_optional(cdns_phy->dev, "pll1_refclk");
if (IS_ERR(cdns_phy->clk1))
return dev_err_probe(cdns_phy->dev, PTR_ERR(cdns_phy->clk1),
"phy PLL1 ref clock not found\n");
return 0;
}
static int cdns_torrent_clk(struct cdns_torrent_phy *cdns_phy)
{
struct device *dev = cdns_phy->dev;
unsigned long ref_clk1_rate;
unsigned long ref_clk_rate;
int ret;
/* refclk: Input reference clock for PLL0 */
cdns_phy->clk = devm_clk_get(dev, "refclk");
if (IS_ERR(cdns_phy->clk)) {
dev_err(dev, "phy ref clock not found\n");
return PTR_ERR(cdns_phy->clk);
}
ret = clk_prepare_enable(cdns_phy->clk);
if (ret) {
dev_err(cdns_phy->dev, "Failed to prepare ref clock: %d\n", ret);
@ -2745,14 +2757,6 @@ static int cdns_torrent_clk(struct cdns_torrent_phy *cdns_phy)
goto disable_clk;
}
/* refclk1: Input reference clock for PLL1 */
cdns_phy->clk1 = devm_clk_get_optional(dev, "pll1_refclk");
if (IS_ERR(cdns_phy->clk1)) {
dev_err(dev, "phy PLL1 ref clock not found\n");
ret = PTR_ERR(cdns_phy->clk1);
goto disable_clk;
}
if (cdns_phy->clk1) {
ret = clk_prepare_enable(cdns_phy->clk1);
if (ret) {
@ -2807,7 +2811,6 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
struct device_node *child;
int ret, subnodes, node = 0, i;
u32 total_num_lanes = 0;
int already_configured;
u8 init_dp_regmap = 0;
u32 phy_type;
@ -2846,13 +2849,17 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
if (ret)
return ret;
regmap_field_read(cdns_phy->phy_pma_cmn_ctrl_1, &already_configured);
ret = cdns_torrent_of_get_reset(cdns_phy);
if (ret)
goto clk_cleanup;
if (!already_configured) {
ret = cdns_torrent_reset(cdns_phy);
if (ret)
goto clk_cleanup;
ret = cdns_torrent_of_get_clk(cdns_phy);
if (ret)
goto clk_cleanup;
regmap_field_read(cdns_phy->phy_pma_cmn_ctrl_1, &cdns_phy->already_configured);
if (!cdns_phy->already_configured) {
ret = cdns_torrent_clk(cdns_phy);
if (ret)
goto clk_cleanup;
@ -2932,10 +2939,7 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
of_property_read_u32(child, "cdns,ssc-mode",
&cdns_phy->phys[node].ssc_mode);
if (!already_configured)
gphy = devm_phy_create(dev, child, &cdns_torrent_phy_ops);
else
gphy = devm_phy_create(dev, child, &noop_ops);
gphy = devm_phy_create(dev, child, &cdns_torrent_phy_ops);
if (IS_ERR(gphy)) {
ret = PTR_ERR(gphy);
goto put_child;
@ -3018,7 +3022,7 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
goto put_lnk_rst;
}
if (cdns_phy->nsubnodes > 1 && !already_configured) {
if (cdns_phy->nsubnodes > 1 && !cdns_phy->already_configured) {
ret = cdns_torrent_phy_configure_multilink(cdns_phy);
if (ret)
goto put_lnk_rst;
@ -3074,6 +3078,82 @@ static void cdns_torrent_phy_remove(struct platform_device *pdev)
cdns_torrent_clk_cleanup(cdns_phy);
}
/* SGMII and QSGMII link configuration */
static struct cdns_reg_pairs sgmii_qsgmii_link_cmn_regs[] = {
{0x0002, PHY_PLL_CFG}
};
static struct cdns_reg_pairs sgmii_qsgmii_xcvr_diag_ln_regs[] = {
{0x0003, XCVR_DIAG_HSCLK_DIV},
{0x0113, XCVR_DIAG_PLLDRC_CTRL}
};
static struct cdns_torrent_vals sgmii_qsgmii_link_cmn_vals = {
.reg_pairs = sgmii_qsgmii_link_cmn_regs,
.num_regs = ARRAY_SIZE(sgmii_qsgmii_link_cmn_regs),
};
static struct cdns_torrent_vals sgmii_qsgmii_xcvr_diag_ln_vals = {
.reg_pairs = sgmii_qsgmii_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(sgmii_qsgmii_xcvr_diag_ln_regs),
};
static int cdns_torrent_phy_suspend_noirq(struct device *dev)
{
struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(dev);
int i;
reset_control_assert(cdns_phy->phy_rst);
reset_control_assert(cdns_phy->apb_rst);
for (i = 0; i < cdns_phy->nsubnodes; i++)
reset_control_assert(cdns_phy->phys[i].lnk_rst);
if (cdns_phy->already_configured)
cdns_phy->already_configured = 0;
else {
clk_disable_unprepare(cdns_phy->clk1);
clk_disable_unprepare(cdns_phy->clk);
}
return 0;
}
static int cdns_torrent_phy_resume_noirq(struct device *dev)
{
struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(dev);
int node = cdns_phy->nsubnodes;
int ret, i;
ret = cdns_torrent_clk(cdns_phy);
if (ret)
return ret;
/* Enable APB */
reset_control_deassert(cdns_phy->apb_rst);
if (cdns_phy->nsubnodes > 1) {
ret = cdns_torrent_phy_configure_multilink(cdns_phy);
if (ret)
goto put_lnk_rst;
}
return 0;
put_lnk_rst:
for (i = 0; i < node; i++)
reset_control_assert(cdns_phy->phys[i].lnk_rst);
reset_control_assert(cdns_phy->apb_rst);
clk_disable_unprepare(cdns_phy->clk1);
clk_disable_unprepare(cdns_phy->clk);
return ret;
}
static DEFINE_NOIRQ_DEV_PM_OPS(cdns_torrent_phy_pm_ops,
cdns_torrent_phy_suspend_noirq,
cdns_torrent_phy_resume_noirq);
/* USB and DP link configuration */
static struct cdns_reg_pairs usb_dp_link_cmn_regs[] = {
{0x0002, PHY_PLL_CFG},
@ -4043,7 +4123,8 @@ static struct cdns_reg_pairs sgmii_100_no_ssc_tx_ln_regs[] = {
{0x04A2, TX_PSC_A2},
{0x04A2, TX_PSC_A3},
{0x0000, TX_TXCC_CPOST_MULT_00},
{0x00B3, DRV_DIAG_TX_DRV}
{0x00B3, DRV_DIAG_TX_DRV},
{0x0002, XCVR_DIAG_PSC_OVRD}
};
static struct cdns_reg_pairs ti_sgmii_100_no_ssc_tx_ln_regs[] = {
@ -4052,7 +4133,8 @@ static struct cdns_reg_pairs ti_sgmii_100_no_ssc_tx_ln_regs[] = {
{0x04A2, TX_PSC_A3},
{0x0000, TX_TXCC_CPOST_MULT_00},
{0x00B3, DRV_DIAG_TX_DRV},
{0x4000, XCVR_DIAG_RXCLK_CTRL},
{0x0002, XCVR_DIAG_PSC_OVRD},
{0x4000, XCVR_DIAG_RXCLK_CTRL}
};
static struct cdns_reg_pairs sgmii_100_no_ssc_rx_ln_regs[] = {
@ -4219,7 +4301,8 @@ static struct cdns_reg_pairs qsgmii_100_no_ssc_tx_ln_regs[] = {
{0x04A2, TX_PSC_A3},
{0x0000, TX_TXCC_CPOST_MULT_00},
{0x0011, TX_TXCC_MGNFS_MULT_100},
{0x0003, DRV_DIAG_TX_DRV}
{0x0003, DRV_DIAG_TX_DRV},
{0x0002, XCVR_DIAG_PSC_OVRD}
};
static struct cdns_reg_pairs ti_qsgmii_100_no_ssc_tx_ln_regs[] = {
@ -4229,7 +4312,8 @@ static struct cdns_reg_pairs ti_qsgmii_100_no_ssc_tx_ln_regs[] = {
{0x0000, TX_TXCC_CPOST_MULT_00},
{0x0011, TX_TXCC_MGNFS_MULT_100},
{0x0003, DRV_DIAG_TX_DRV},
{0x4000, XCVR_DIAG_RXCLK_CTRL},
{0x0002, XCVR_DIAG_PSC_OVRD},
{0x4000, XCVR_DIAG_RXCLK_CTRL}
};
static struct cdns_reg_pairs qsgmii_100_no_ssc_rx_ln_regs[] = {
@ -4541,11 +4625,13 @@ static struct cdns_torrent_vals_entry link_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_NONE), &sl_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_PCIE), &pcie_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_QSGMII), &sgmii_qsgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USB), &usb_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USXGMII), &usxgmii_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_NONE), &sl_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_PCIE), &pcie_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_SGMII), &sgmii_qsgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USB), &usb_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USXGMII), &usxgmii_sgmii_link_cmn_vals},
@ -4575,11 +4661,13 @@ static struct cdns_torrent_vals_entry xcvr_diag_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_NONE), &sl_sgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_PCIE), &sgmii_pcie_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_QSGMII), &sgmii_qsgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USB), &sgmii_usb_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USXGMII), &sgmii_usxgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_NONE), &sl_sgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_PCIE), &sgmii_pcie_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_SGMII), &sgmii_qsgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USB), &sgmii_usb_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USXGMII), &sgmii_usxgmii_xcvr_diag_ln_vals},
@ -4635,6 +4723,8 @@ static struct cdns_torrent_vals_entry cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_int_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &sl_sgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
@ -4645,6 +4735,8 @@ static struct cdns_torrent_vals_entry cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_int_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &sl_qsgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
@ -4713,6 +4805,8 @@ static struct cdns_torrent_vals_entry cdns_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
@ -4723,6 +4817,8 @@ static struct cdns_torrent_vals_entry cdns_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
@ -4791,6 +4887,8 @@ static struct cdns_torrent_vals_entry cdns_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
@ -4801,6 +4899,8 @@ static struct cdns_torrent_vals_entry cdns_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
@ -4905,6 +5005,8 @@ static struct cdns_torrent_vals_entry ti_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
@ -4915,6 +5017,8 @@ static struct cdns_torrent_vals_entry ti_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
@ -5017,6 +5121,8 @@ static struct cdns_torrent_vals_entry ti_j7200_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_int_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &sl_sgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
@ -5027,6 +5133,8 @@ static struct cdns_torrent_vals_entry ti_j7200_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_int_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &sl_qsgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
@ -5095,6 +5203,8 @@ static struct cdns_torrent_vals_entry ti_j7200_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
@ -5105,6 +5215,8 @@ static struct cdns_torrent_vals_entry ti_j7200_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
@ -5173,6 +5285,8 @@ static struct cdns_torrent_vals_entry ti_j7200_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
@ -5183,6 +5297,8 @@ static struct cdns_torrent_vals_entry ti_j7200_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
@ -5275,6 +5391,7 @@ static struct platform_driver cdns_torrent_phy_driver = {
.driver = {
.name = "cdns-torrent-phy",
.of_match_table = cdns_torrent_phy_of_match,
.pm = pm_sleep_ptr(&cdns_torrent_phy_pm_ops),
}
};
module_platform_driver(cdns_torrent_phy_driver);

View File

@ -35,12 +35,19 @@ config PHY_FSL_IMX8M_PCIE
Enable this to add support for the PCIE PHY as found on
i.MX8M family of SOCs.
config PHY_FSL_IMX8QM_HSIO
tristate "Freescale i.MX8QM HSIO PHY"
depends on OF && HAS_IOMEM
select GENERIC_PHY
help
Enable this to add support for the HSIO PHY as found on
i.MX8QM family of SOCs.
config PHY_FSL_SAMSUNG_HDMI_PHY
tristate "Samsung HDMI PHY support"
depends on OF && HAS_IOMEM && COMMON_CLK
help
Enable this to add support for the Samsung HDMI PHY in i.MX8MP.
endif
config PHY_FSL_LYNX_28G

View File

@ -3,5 +3,6 @@ obj-$(CONFIG_PHY_FSL_IMX8MQ_USB) += phy-fsl-imx8mq-usb.o
obj-$(CONFIG_PHY_MIXEL_LVDS_PHY) += phy-fsl-imx8qm-lvds-phy.o
obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o
obj-$(CONFIG_PHY_FSL_IMX8M_PCIE) += phy-fsl-imx8m-pcie.o
obj-$(CONFIG_PHY_FSL_IMX8QM_HSIO) += phy-fsl-imx8qm-hsio.o
obj-$(CONFIG_PHY_FSL_LYNX_28G) += phy-fsl-lynx-28g.o
obj-$(CONFIG_PHY_FSL_SAMSUNG_HDMI_PHY) += phy-fsl-samsung-hdmi.o

View File

@ -0,0 +1,611 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2024 NXP
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pci_regs.h>
#include <linux/phy/phy.h>
#include <linux/phy/pcie.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/phy/phy-imx8-pcie.h>
#define MAX_NUM_LANE 3
#define LANE_NUM_CLKS 5
/* Parameters for the waiting for PCIe PHY PLL to lock */
#define PHY_INIT_WAIT_USLEEP_MAX 10
#define PHY_INIT_WAIT_TIMEOUT (1000 * PHY_INIT_WAIT_USLEEP_MAX)
/* i.MX8Q HSIO registers */
#define HSIO_CTRL0 0x0
#define HSIO_APB_RSTN_0 BIT(0)
#define HSIO_APB_RSTN_1 BIT(1)
#define HSIO_PIPE_RSTN_0_MASK GENMASK(25, 24)
#define HSIO_PIPE_RSTN_1_MASK GENMASK(27, 26)
#define HSIO_MODE_MASK GENMASK(20, 17)
#define HSIO_MODE_PCIE 0x0
#define HSIO_MODE_SATA 0x4
#define HSIO_DEVICE_TYPE_MASK GENMASK(27, 24)
#define HSIO_EPCS_TXDEEMP BIT(5)
#define HSIO_EPCS_TXDEEMP_SEL BIT(6)
#define HSIO_EPCS_PHYRESET_N BIT(7)
#define HSIO_RESET_N BIT(12)
#define HSIO_IOB_RXENA BIT(0)
#define HSIO_IOB_TXENA BIT(1)
#define HSIO_IOB_A_0_TXOE BIT(2)
#define HSIO_IOB_A_0_M1M0_2 BIT(4)
#define HSIO_IOB_A_0_M1M0_MASK GENMASK(4, 3)
#define HSIO_PHYX1_EPCS_SEL BIT(12)
#define HSIO_PCIE_AB_SELECT BIT(13)
#define HSIO_PHY_STS0 0x4
#define HSIO_LANE0_TX_PLL_LOCK BIT(4)
#define HSIO_LANE1_TX_PLL_LOCK BIT(12)
#define HSIO_CTRL2 0x8
#define HSIO_LTSSM_ENABLE BIT(4)
#define HSIO_BUTTON_RST_N BIT(21)
#define HSIO_PERST_N BIT(22)
#define HSIO_POWER_UP_RST_N BIT(23)
#define HSIO_PCIE_STS0 0xc
#define HSIO_PM_REQ_CORE_RST BIT(19)
#define HSIO_REG48_PMA_STATUS 0x30
#define HSIO_REG48_PMA_RDY BIT(7)
struct imx_hsio_drvdata {
int lane_num;
};
struct imx_hsio_lane {
u32 ctrl_index;
u32 ctrl_off;
u32 idx;
u32 phy_off;
u32 phy_type;
const char * const *clk_names;
struct clk_bulk_data clks[LANE_NUM_CLKS];
struct imx_hsio_priv *priv;
struct phy *phy;
enum phy_mode phy_mode;
};
struct imx_hsio_priv {
void __iomem *base;
struct device *dev;
struct mutex lock;
const char *hsio_cfg;
const char *refclk_pad;
u32 open_cnt;
struct regmap *phy;
struct regmap *ctrl;
struct regmap *misc;
const struct imx_hsio_drvdata *drvdata;
struct imx_hsio_lane lane[MAX_NUM_LANE];
};
static const char * const lan0_pcie_clks[] = {"apb_pclk0", "pclk0", "ctl0_crr",
"phy0_crr", "misc_crr"};
static const char * const lan1_pciea_clks[] = {"apb_pclk1", "pclk1", "ctl0_crr",
"phy0_crr", "misc_crr"};
static const char * const lan1_pcieb_clks[] = {"apb_pclk1", "pclk1", "ctl1_crr",
"phy0_crr", "misc_crr"};
static const char * const lan2_pcieb_clks[] = {"apb_pclk2", "pclk2", "ctl1_crr",
"phy1_crr", "misc_crr"};
static const char * const lan2_sata_clks[] = {"pclk2", "epcs_tx", "epcs_rx",
"phy1_crr", "misc_crr"};
static const struct regmap_config regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
};
static int imx_hsio_init(struct phy *phy)
{
int ret, i;
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
struct device *dev = priv->dev;
/* Assign clocks refer to different modes */
switch (lane->phy_type) {
case PHY_TYPE_PCIE:
lane->phy_mode = PHY_MODE_PCIE;
if (lane->ctrl_index == 0) { /* PCIEA */
lane->ctrl_off = 0;
lane->phy_off = 0;
for (i = 0; i < LANE_NUM_CLKS; i++) {
if (lane->idx == 0)
lane->clks[i].id = lan0_pcie_clks[i];
else
lane->clks[i].id = lan1_pciea_clks[i];
}
} else { /* PCIEB */
if (lane->idx == 0) { /* i.MX8QXP */
lane->ctrl_off = 0;
lane->phy_off = 0;
} else {
/*
* On i.MX8QM, only second or third lane can be
* bound to PCIEB.
*/
lane->ctrl_off = SZ_64K;
if (lane->idx == 1)
lane->phy_off = 0;
else /* the third lane is bound to PCIEB */
lane->phy_off = SZ_64K;
}
for (i = 0; i < LANE_NUM_CLKS; i++) {
if (lane->idx == 1)
lane->clks[i].id = lan1_pcieb_clks[i];
else if (lane->idx == 2)
lane->clks[i].id = lan2_pcieb_clks[i];
else /* i.MX8QXP only has PCIEB, idx is 0 */
lane->clks[i].id = lan0_pcie_clks[i];
}
}
break;
case PHY_TYPE_SATA:
/* On i.MX8QM, only the third lane can be bound to SATA */
lane->phy_mode = PHY_MODE_SATA;
lane->ctrl_off = SZ_128K;
lane->phy_off = SZ_64K;
for (i = 0; i < LANE_NUM_CLKS; i++)
lane->clks[i].id = lan2_sata_clks[i];
break;
default:
return -EINVAL;
}
/* Fetch clocks and enable them */
ret = devm_clk_bulk_get(dev, LANE_NUM_CLKS, lane->clks);
if (ret)
return ret;
ret = clk_bulk_prepare_enable(LANE_NUM_CLKS, lane->clks);
if (ret)
return ret;
/* allow the clocks to stabilize */
usleep_range(200, 500);
return 0;
}
static int imx_hsio_exit(struct phy *phy)
{
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
clk_bulk_disable_unprepare(LANE_NUM_CLKS, lane->clks);
return 0;
}
static void imx_hsio_pcie_phy_resets(struct phy *phy)
{
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
regmap_clear_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
HSIO_BUTTON_RST_N);
regmap_clear_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
HSIO_PERST_N);
regmap_clear_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
HSIO_POWER_UP_RST_N);
regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
HSIO_BUTTON_RST_N);
regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
HSIO_PERST_N);
regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
HSIO_POWER_UP_RST_N);
if (lane->idx == 1) {
regmap_set_bits(priv->phy, lane->phy_off + HSIO_CTRL0,
HSIO_APB_RSTN_1);
regmap_set_bits(priv->phy, lane->phy_off + HSIO_CTRL0,
HSIO_PIPE_RSTN_1_MASK);
} else {
regmap_set_bits(priv->phy, lane->phy_off + HSIO_CTRL0,
HSIO_APB_RSTN_0);
regmap_set_bits(priv->phy, lane->phy_off + HSIO_CTRL0,
HSIO_PIPE_RSTN_0_MASK);
}
}
static void imx_hsio_sata_phy_resets(struct phy *phy)
{
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
/* clear PHY RST, then set it */
regmap_clear_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
HSIO_EPCS_PHYRESET_N);
regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
HSIO_EPCS_PHYRESET_N);
/* CTRL RST: SET -> delay 1 us -> CLEAR -> SET */
regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0, HSIO_RESET_N);
udelay(1);
regmap_clear_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
HSIO_RESET_N);
regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0, HSIO_RESET_N);
}
static void imx_hsio_configure_clk_pad(struct phy *phy)
{
bool pll = false;
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
if (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,
HSIO_IOB_A_0_TXOE | HSIO_IOB_A_0_M1M0_2);
} else {
regmap_update_bits(priv->misc, HSIO_CTRL0,
HSIO_IOB_A_0_TXOE | HSIO_IOB_A_0_M1M0_MASK,
0);
}
regmap_update_bits(priv->misc, HSIO_CTRL0, HSIO_IOB_RXENA,
pll ? 0 : HSIO_IOB_RXENA);
regmap_update_bits(priv->misc, HSIO_CTRL0, HSIO_IOB_TXENA,
pll ? HSIO_IOB_TXENA : 0);
}
static void imx_hsio_pre_set(struct phy *phy)
{
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
if (strncmp(priv->hsio_cfg, "pciea-x2-pcieb", 14) == 0) {
regmap_set_bits(priv->misc, HSIO_CTRL0, HSIO_PCIE_AB_SELECT);
} else if (strncmp(priv->hsio_cfg, "pciea-x2-sata", 13) == 0) {
regmap_set_bits(priv->misc, HSIO_CTRL0, HSIO_PHYX1_EPCS_SEL);
} else if (strncmp(priv->hsio_cfg, "pciea-pcieb-sata", 16) == 0) {
regmap_set_bits(priv->misc, HSIO_CTRL0, HSIO_PCIE_AB_SELECT);
regmap_set_bits(priv->misc, HSIO_CTRL0, HSIO_PHYX1_EPCS_SEL);
}
imx_hsio_configure_clk_pad(phy);
}
static int imx_hsio_pcie_power_on(struct phy *phy)
{
int ret;
u32 val, addr, cond;
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
imx_hsio_pcie_phy_resets(phy);
/* Toggle apb_pclk to make sure PM_REQ_CORE_RST is cleared. */
clk_disable_unprepare(lane->clks[0].clk);
mdelay(1);
ret = clk_prepare_enable(lane->clks[0].clk);
if (ret) {
dev_err(priv->dev, "unable to enable phy apb_pclk\n");
return ret;
}
addr = lane->ctrl_off + HSIO_PCIE_STS0;
cond = HSIO_PM_REQ_CORE_RST;
ret = regmap_read_poll_timeout(priv->ctrl, addr, val,
(val & cond) == 0,
PHY_INIT_WAIT_USLEEP_MAX,
PHY_INIT_WAIT_TIMEOUT);
if (ret)
dev_err(priv->dev, "HSIO_PM_REQ_CORE_RST is set\n");
return ret;
}
static int imx_hsio_sata_power_on(struct phy *phy)
{
int ret;
u32 val, cond;
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
regmap_set_bits(priv->phy, lane->phy_off + HSIO_CTRL0, HSIO_APB_RSTN_0);
regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
HSIO_EPCS_TXDEEMP);
regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
HSIO_EPCS_TXDEEMP_SEL);
imx_hsio_sata_phy_resets(phy);
cond = HSIO_REG48_PMA_RDY;
ret = read_poll_timeout(readb, val, ((val & cond) == cond),
PHY_INIT_WAIT_USLEEP_MAX,
PHY_INIT_WAIT_TIMEOUT, false,
priv->base + HSIO_REG48_PMA_STATUS);
if (ret)
dev_err(priv->dev, "PHY calibration is timeout\n");
else
dev_dbg(priv->dev, "PHY calibration is done\n");
return ret;
}
static int imx_hsio_power_on(struct phy *phy)
{
int ret;
u32 val, cond;
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
scoped_guard(mutex, &priv->lock) {
if (!priv->open_cnt)
imx_hsio_pre_set(phy);
priv->open_cnt++;
}
if (lane->phy_mode == PHY_MODE_PCIE)
ret = imx_hsio_pcie_power_on(phy);
else /* SATA */
ret = imx_hsio_sata_power_on(phy);
if (ret)
return ret;
/* Polling to check the PHY is ready or not. */
if (lane->idx == 1)
cond = HSIO_LANE1_TX_PLL_LOCK;
else
/*
* Except the phy_off, the bit-offset of lane2 is same to lane0.
* Merge the lane0 and lane2 bit-operations together.
*/
cond = HSIO_LANE0_TX_PLL_LOCK;
ret = regmap_read_poll_timeout(priv->phy, lane->phy_off + HSIO_PHY_STS0,
val, ((val & cond) == cond),
PHY_INIT_WAIT_USLEEP_MAX,
PHY_INIT_WAIT_TIMEOUT);
if (ret) {
dev_err(priv->dev, "IMX8Q PHY%d PLL lock timeout\n", lane->idx);
return ret;
}
dev_dbg(priv->dev, "IMX8Q PHY%d PLL is locked\n", lane->idx);
return ret;
}
static int imx_hsio_power_off(struct phy *phy)
{
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
scoped_guard(mutex, &priv->lock) {
priv->open_cnt--;
if (priv->open_cnt == 0) {
regmap_clear_bits(priv->misc, HSIO_CTRL0,
HSIO_PCIE_AB_SELECT);
regmap_clear_bits(priv->misc, HSIO_CTRL0,
HSIO_PHYX1_EPCS_SEL);
if (lane->phy_mode == PHY_MODE_PCIE) {
regmap_clear_bits(priv->ctrl,
lane->ctrl_off + HSIO_CTRL2,
HSIO_BUTTON_RST_N);
regmap_clear_bits(priv->ctrl,
lane->ctrl_off + HSIO_CTRL2,
HSIO_PERST_N);
regmap_clear_bits(priv->ctrl,
lane->ctrl_off + HSIO_CTRL2,
HSIO_POWER_UP_RST_N);
} else {
regmap_clear_bits(priv->ctrl,
lane->ctrl_off + HSIO_CTRL0,
HSIO_EPCS_TXDEEMP);
regmap_clear_bits(priv->ctrl,
lane->ctrl_off + HSIO_CTRL0,
HSIO_EPCS_TXDEEMP_SEL);
regmap_clear_bits(priv->ctrl,
lane->ctrl_off + HSIO_CTRL0,
HSIO_RESET_N);
}
if (lane->idx == 1) {
regmap_clear_bits(priv->phy,
lane->phy_off + HSIO_CTRL0,
HSIO_APB_RSTN_1);
regmap_clear_bits(priv->phy,
lane->phy_off + HSIO_CTRL0,
HSIO_PIPE_RSTN_1_MASK);
} else {
/*
* Except the phy_off, the bit-offset of lane2 is same
* to lane0. Merge the lane0 and lane2 bit-operations
* together.
*/
regmap_clear_bits(priv->phy,
lane->phy_off + HSIO_CTRL0,
HSIO_APB_RSTN_0);
regmap_clear_bits(priv->phy,
lane->phy_off + HSIO_CTRL0,
HSIO_PIPE_RSTN_0_MASK);
}
}
}
return 0;
}
static int imx_hsio_set_mode(struct phy *phy, enum phy_mode mode,
int submode)
{
u32 val;
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
if (lane->phy_mode != mode)
return -EINVAL;
val = (mode == PHY_MODE_PCIE) ? HSIO_MODE_PCIE : HSIO_MODE_SATA;
val = FIELD_PREP(HSIO_MODE_MASK, val);
regmap_update_bits(priv->phy, lane->phy_off + HSIO_CTRL0,
HSIO_MODE_MASK, val);
switch (submode) {
case PHY_MODE_PCIE_RC:
val = FIELD_PREP(HSIO_DEVICE_TYPE_MASK, PCI_EXP_TYPE_ROOT_PORT);
break;
case PHY_MODE_PCIE_EP:
val = FIELD_PREP(HSIO_DEVICE_TYPE_MASK, PCI_EXP_TYPE_ENDPOINT);
break;
default: /* Support only PCIe EP and RC now. */
return 0;
}
if (submode)
regmap_update_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
HSIO_DEVICE_TYPE_MASK, val);
return 0;
}
static int imx_hsio_set_speed(struct phy *phy, int speed)
{
struct imx_hsio_lane *lane = phy_get_drvdata(phy);
struct imx_hsio_priv *priv = lane->priv;
regmap_update_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
HSIO_LTSSM_ENABLE,
speed ? HSIO_LTSSM_ENABLE : 0);
return 0;
}
static const struct phy_ops imx_hsio_ops = {
.init = imx_hsio_init,
.exit = imx_hsio_exit,
.power_on = imx_hsio_power_on,
.power_off = imx_hsio_power_off,
.set_mode = imx_hsio_set_mode,
.set_speed = imx_hsio_set_speed,
.owner = THIS_MODULE,
};
static const struct imx_hsio_drvdata imx8qxp_hsio_drvdata = {
.lane_num = 0x1,
};
static const struct imx_hsio_drvdata imx8qm_hsio_drvdata = {
.lane_num = 0x3,
};
static const struct of_device_id imx_hsio_of_match[] = {
{.compatible = "fsl,imx8qm-hsio", .data = &imx8qm_hsio_drvdata},
{.compatible = "fsl,imx8qxp-hsio", .data = &imx8qxp_hsio_drvdata},
{ },
};
MODULE_DEVICE_TABLE(of, imx_hsio_of_match);
static struct phy *imx_hsio_xlate(struct device *dev,
const struct of_phandle_args *args)
{
struct imx_hsio_priv *priv = dev_get_drvdata(dev);
int idx = args->args[0];
int phy_type = args->args[1];
int ctrl_index = args->args[2];
if (idx < 0 || idx >= priv->drvdata->lane_num)
return ERR_PTR(-EINVAL);
priv->lane[idx].idx = idx;
priv->lane[idx].phy_type = phy_type;
priv->lane[idx].ctrl_index = ctrl_index;
return priv->lane[idx].phy;
}
static int imx_hsio_probe(struct platform_device *pdev)
{
int i;
void __iomem *off;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct imx_hsio_priv *priv;
struct phy_provider *provider;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->dev = &pdev->dev;
priv->drvdata = of_device_get_match_data(dev);
/* Get HSIO configuration mode */
if (of_property_read_string(np, "fsl,hsio-cfg", &priv->hsio_cfg))
priv->hsio_cfg = "pciea-pcieb-sata";
/* Get PHY refclk pad mode */
if (of_property_read_string(np, "fsl,refclk-pad-mode",
&priv->refclk_pad))
priv->refclk_pad = NULL;
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
off = devm_platform_ioremap_resource_byname(pdev, "phy");
priv->phy = devm_regmap_init_mmio(dev, off, &regmap_config);
if (IS_ERR(priv->phy))
return dev_err_probe(dev, PTR_ERR(priv->phy),
"unable to find phy csr registers\n");
off = devm_platform_ioremap_resource_byname(pdev, "ctrl");
priv->ctrl = devm_regmap_init_mmio(dev, off, &regmap_config);
if (IS_ERR(priv->ctrl))
return dev_err_probe(dev, PTR_ERR(priv->ctrl),
"unable to find ctrl csr registers\n");
off = devm_platform_ioremap_resource_byname(pdev, "misc");
priv->misc = devm_regmap_init_mmio(dev, off, &regmap_config);
if (IS_ERR(priv->misc))
return dev_err_probe(dev, PTR_ERR(priv->misc),
"unable to find misc csr registers\n");
for (i = 0; i < priv->drvdata->lane_num; i++) {
struct imx_hsio_lane *lane = &priv->lane[i];
struct phy *phy;
phy = devm_phy_create(&pdev->dev, NULL, &imx_hsio_ops);
if (IS_ERR(phy))
return PTR_ERR(phy);
lane->priv = priv;
lane->phy = phy;
lane->idx = i;
phy_set_drvdata(phy, lane);
}
dev_set_drvdata(dev, priv);
dev_set_drvdata(&pdev->dev, priv);
provider = devm_of_phy_provider_register(&pdev->dev, imx_hsio_xlate);
return PTR_ERR_OR_ZERO(provider);
}
static struct platform_driver imx_hsio_driver = {
.probe = imx_hsio_probe,
.driver = {
.name = "imx8qm-hsio-phy",
.of_match_table = imx_hsio_of_match,
}
};
module_platform_driver(imx_hsio_driver);
MODULE_DESCRIPTION("FSL IMX8QM HSIO SERDES PHY driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,494 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2024 AIROHA Inc
* Author: Lorenzo Bianconi <lorenzo@kernel.org>
*/
#ifndef _PHY_AIROHA_PCIE_H
#define _PHY_AIROHA_PCIE_H
/* CSR_2L */
#define REG_CSR_2L_CMN 0x0000
#define CSR_2L_PXP_CMN_LANE_EN BIT(0)
#define CSR_2L_PXP_CMN_TRIM_MASK GENMASK(28, 24)
#define REG_CSR_2L_JCPLL_IB_EXT 0x0004
#define REG_CSR_2L_JCPLL_LPF_SHCK_EN BIT(8)
#define CSR_2L_PXP_JCPLL_CHP_IBIAS GENMASK(21, 16)
#define CSR_2L_PXP_JCPLL_CHP_IOFST GENMASK(29, 24)
#define REG_CSR_2L_JCPLL_LPF_BR 0x0008
#define CSR_2L_PXP_JCPLL_LPF_BR GENMASK(4, 0)
#define CSR_2L_PXP_JCPLL_LPF_BC GENMASK(12, 8)
#define CSR_2L_PXP_JCPLL_LPF_BP GENMASK(20, 16)
#define CSR_2L_PXP_JCPLL_LPF_BWR GENMASK(28, 24)
#define REG_CSR_2L_JCPLL_LPF_BWC 0x000c
#define CSR_2L_PXP_JCPLL_LPF_BWC GENMASK(4, 0)
#define CSR_2L_PXP_JCPLL_KBAND_CODE GENMASK(23, 16)
#define CSR_2L_PXP_JCPLL_KBAND_DIV GENMASK(26, 24)
#define REG_CSR_2L_JCPLL_KBAND_KFC 0x0010
#define CSR_2L_PXP_JCPLL_KBAND_KFC GENMASK(1, 0)
#define CSR_2L_PXP_JCPLL_KBAND_KF GENMASK(9, 8)
#define CSR_2L_PXP_JCPLL_KBAND_KS GENMASK(17, 16)
#define CSR_2L_PXP_JCPLL_POSTDIV_EN BIT(24)
#define REG_CSR_2L_JCPLL_MMD_PREDIV_MODE 0x0014
#define CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE GENMASK(1, 0)
#define CSR_2L_PXP_JCPLL_POSTDIV_D2 BIT(16)
#define CSR_2L_PXP_JCPLL_POSTDIV_D5 BIT(24)
#define CSR_2L_PXP_JCPLL_MONCK 0x0018
#define CSR_2L_PXP_JCPLL_REFIN_DIV GENMASK(25, 24)
#define REG_CSR_2L_JCPLL_RST_DLY 0x001c
#define CSR_2L_PXP_JCPLL_RST_DLY GENMASK(2, 0)
#define CSR_2L_PXP_JCPLL_RST BIT(8)
#define CSR_2L_PXP_JCPLL_SDM_DI_EN BIT(16)
#define CSR_2L_PXP_JCPLL_SDM_DI_LS GENMASK(25, 24)
#define REG_CSR_2L_JCPLL_SDM_IFM 0x0020
#define CSR_2L_PXP_JCPLL_SDM_IFM BIT(0)
#define REG_CSR_2L_JCPLL_SDM_HREN 0x0024
#define CSR_2L_PXP_JCPLL_SDM_HREN BIT(0)
#define CSR_2L_PXP_JCPLL_TCL_AMP_EN BIT(8)
#define CSR_2L_PXP_JCPLL_TCL_AMP_GAIN GENMASK(18, 16)
#define CSR_2L_PXP_JCPLL_TCL_AMP_VREF GENMASK(28, 24)
#define REG_CSR_2L_JCPLL_TCL_CMP 0x0028
#define CSR_2L_PXP_JCPLL_TCL_LPF_EN BIT(16)
#define CSR_2L_PXP_JCPLL_TCL_LPF_BW GENMASK(26, 24)
#define REG_CSR_2L_JCPLL_VCODIV 0x002c
#define CSR_2L_PXP_JCPLL_VCO_CFIX GENMASK(9, 8)
#define CSR_2L_PXP_JCPLL_VCO_HALFLSB_EN BIT(16)
#define CSR_2L_PXP_JCPLL_VCO_SCAPWR GENMASK(26, 24)
#define REG_CSR_2L_JCPLL_VCO_TCLVAR 0x0030
#define CSR_2L_PXP_JCPLL_VCO_TCLVAR GENMASK(2, 0)
#define REG_CSR_2L_JCPLL_SSC 0x0038
#define CSR_2L_PXP_JCPLL_SSC_EN BIT(0)
#define CSR_2L_PXP_JCPLL_SSC_PHASE_INI BIT(8)
#define CSR_2L_PXP_JCPLL_SSC_TRI_EN BIT(16)
#define REG_CSR_2L_JCPLL_SSC_DELTA1 0x003c
#define CSR_2L_PXP_JCPLL_SSC_DELTA1 GENMASK(15, 0)
#define CSR_2L_PXP_JCPLL_SSC_DELTA GENMASK(31, 16)
#define REG_CSR_2L_JCPLL_SSC_PERIOD 0x0040
#define CSR_2L_PXP_JCPLL_SSC_PERIOD GENMASK(15, 0)
#define REG_CSR_2L_JCPLL_TCL_VTP_EN 0x004c
#define CSR_2L_PXP_JCPLL_SPARE_LOW GENMASK(31, 24)
#define REG_CSR_2L_JCPLL_TCL_KBAND_VREF 0x0050
#define CSR_2L_PXP_JCPLL_TCL_KBAND_VREF GENMASK(4, 0)
#define CSR_2L_PXP_JCPLL_VCO_KBAND_MEAS_EN BIT(24)
#define REG_CSR_2L_750M_SYS_CK 0x0054
#define CSR_2L_PXP_TXPLL_LPF_SHCK_EN BIT(16)
#define CSR_2L_PXP_TXPLL_CHP_IBIAS GENMASK(29, 24)
#define REG_CSR_2L_TXPLL_CHP_IOFST 0x0058
#define CSR_2L_PXP_TXPLL_CHP_IOFST GENMASK(5, 0)
#define CSR_2L_PXP_TXPLL_LPF_BR GENMASK(12, 8)
#define CSR_2L_PXP_TXPLL_LPF_BC GENMASK(20, 16)
#define CSR_2L_PXP_TXPLL_LPF_BP GENMASK(28, 24)
#define REG_CSR_2L_TXPLL_LPF_BWR 0x005c
#define CSR_2L_PXP_TXPLL_LPF_BWR GENMASK(4, 0)
#define CSR_2L_PXP_TXPLL_LPF_BWC GENMASK(12, 8)
#define CSR_2L_PXP_TXPLL_KBAND_CODE GENMASK(31, 24)
#define REG_CSR_2L_TXPLL_KBAND_DIV 0x0060
#define CSR_2L_PXP_TXPLL_KBAND_DIV GENMASK(2, 0)
#define CSR_2L_PXP_TXPLL_KBAND_KFC GENMASK(9, 8)
#define CSR_2L_PXP_TXPLL_KBAND_KF GENMASK(17, 16)
#define CSR_2L_PXP_txpll_KBAND_KS GENMASK(25, 24)
#define REG_CSR_2L_TXPLL_POSTDIV 0x0064
#define CSR_2L_PXP_TXPLL_POSTDIV_EN BIT(0)
#define CSR_2L_PXP_TXPLL_MMD_PREDIV_MODE GENMASK(9, 8)
#define CSR_2L_PXP_TXPLL_PHY_CK1_EN BIT(24)
#define REG_CSR_2L_TXPLL_PHY_CK2 0x0068
#define CSR_2L_PXP_TXPLL_REFIN_INTERNAL BIT(24)
#define REG_CSR_2L_TXPLL_REFIN_DIV 0x006c
#define CSR_2L_PXP_TXPLL_REFIN_DIV GENMASK(1, 0)
#define CSR_2L_PXP_TXPLL_RST_DLY GENMASK(10, 8)
#define CSR_2L_PXP_TXPLL_PLL_RSTB BIT(16)
#define REG_CSR_2L_TXPLL_SDM_DI_LS 0x0070
#define CSR_2L_PXP_TXPLL_SDM_DI_LS GENMASK(1, 0)
#define CSR_2L_PXP_TXPLL_SDM_IFM BIT(8)
#define CSR_2L_PXP_TXPLL_SDM_ORD GENMASK(25, 24)
#define REG_CSR_2L_TXPLL_SDM_OUT 0x0074
#define CSR_2L_PXP_TXPLL_TCL_AMP_EN BIT(16)
#define CSR_2L_PXP_TXPLL_TCL_AMP_GAIN GENMASK(26, 24)
#define REG_CSR_2L_TXPLL_TCL_AMP_VREF 0x0078
#define CSR_2L_PXP_TXPLL_TCL_AMP_VREF GENMASK(4, 0)
#define CSR_2L_PXP_TXPLL_TCL_LPF_EN BIT(24)
#define REG_CSR_2L_TXPLL_TCL_LPF_BW 0x007c
#define CSR_2L_PXP_TXPLL_TCL_LPF_BW GENMASK(2, 0)
#define CSR_2L_PXP_TXPLL_VCO_CFIX GENMASK(17, 16)
#define CSR_2L_PXP_TXPLL_VCO_HALFLSB_EN BIT(24)
#define REG_CSR_2L_TXPLL_VCO_SCAPWR 0x0080
#define CSR_2L_PXP_TXPLL_VCO_SCAPWR GENMASK(2, 0)
#define REG_CSR_2L_TXPLL_SSC 0x0084
#define CSR_2L_PXP_TXPLL_SSC_EN BIT(0)
#define CSR_2L_PXP_TXPLL_SSC_PHASE_INI BIT(8)
#define REG_CSR_2L_TXPLL_SSC_DELTA1 0x0088
#define CSR_2L_PXP_TXPLL_SSC_DELTA1 GENMASK(15, 0)
#define CSR_2L_PXP_TXPLL_SSC_DELTA GENMASK(31, 16)
#define REG_CSR_2L_TXPLL_SSC_PERIOD 0x008c
#define CSR_2L_PXP_txpll_SSC_PERIOD GENMASK(15, 0)
#define REG_CSR_2L_TXPLL_VTP 0x0090
#define CSR_2L_PXP_TXPLL_VTP_EN BIT(0)
#define REG_CSR_2L_TXPLL_TCL_VTP 0x0098
#define CSR_2L_PXP_TXPLL_SPARE_L GENMASK(31, 24)
#define REG_CSR_2L_TXPLL_TCL_KBAND_VREF 0x009c
#define CSR_2L_PXP_TXPLL_TCL_KBAND_VREF GENMASK(4, 0)
#define CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN BIT(24)
#define REG_CSR_2L_TXPLL_POSTDIV_D256 0x00a0
#define CSR_2L_PXP_CLKTX0_AMP GENMASK(10, 8)
#define CSR_2L_PXP_CLKTX0_OFFSET GENMASK(17, 16)
#define CSR_2L_PXP_CLKTX0_SR GENMASK(25, 24)
#define REG_CSR_2L_CLKTX0_FORCE_OUT1 0x00a4
#define CSR_2L_PXP_CLKTX0_HZ BIT(8)
#define CSR_2L_PXP_CLKTX0_IMP_SEL GENMASK(20, 16)
#define CSR_2L_PXP_CLKTX1_AMP GENMASK(26, 24)
#define REG_CSR_2L_CLKTX1_OFFSET 0x00a8
#define CSR_2L_PXP_CLKTX1_OFFSET GENMASK(1, 0)
#define CSR_2L_PXP_CLKTX1_SR GENMASK(9, 8)
#define CSR_2L_PXP_CLKTX1_HZ BIT(24)
#define REG_CSR_2L_CLKTX1_IMP_SEL 0x00ac
#define CSR_2L_PXP_CLKTX1_IMP_SEL GENMASK(4, 0)
#define REG_CSR_2L_PLL_CMN_RESERVE0 0x00b0
#define CSR_2L_PXP_PLL_RESERVE_MASK GENMASK(15, 0)
#define REG_CSR_2L_TX0_CKLDO 0x00cc
#define CSR_2L_PXP_TX0_CKLDO_EN BIT(0)
#define CSR_2L_PXP_TX0_DMEDGEGEN_EN BIT(24)
#define REG_CSR_2L_TX1_CKLDO 0x00e8
#define CSR_2L_PXP_TX1_CKLDO_EN BIT(0)
#define CSR_2L_PXP_TX1_DMEDGEGEN_EN BIT(24)
#define REG_CSR_2L_TX1_MULTLANE 0x00ec
#define CSR_2L_PXP_TX1_MULTLANE_EN BIT(0)
#define REG_CSR_2L_RX0_REV0 0x00fc
#define CSR_2L_PXP_VOS_PNINV GENMASK(3, 2)
#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(6, 4)
#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(10, 8)
#define REG_CSR_2L_RX0_PHYCK_DIV 0x0100
#define CSR_2L_PXP_RX0_PHYCK_SEL GENMASK(9, 8)
#define CSR_2L_PXP_RX0_PHYCK_RSTB BIT(16)
#define CSR_2L_PXP_RX0_TDC_CK_SEL BIT(24)
#define REG_CSR_2L_CDR0_PD_PICAL_CKD8_INV 0x0104
#define CSR_2L_PXP_CDR0_PD_EDGE_DISABLE BIT(8)
#define REG_CSR_2L_CDR0_LPF_RATIO 0x0110
#define CSR_2L_PXP_CDR0_LPF_TOP_LIM GENMASK(26, 8)
#define REG_CSR_2L_CDR0_PR_INJ_MODE 0x011c
#define CSR_2L_PXP_CDR0_INJ_FORCE_OFF BIT(24)
#define REG_CSR_2L_CDR0_PR_BETA_DAC 0x0120
#define CSR_2L_PXP_CDR0_PR_BETA_SEL GENMASK(19, 16)
#define CSR_2L_PXP_CDR0_PR_KBAND_DIV GENMASK(26, 24)
#define REG_CSR_2L_CDR0_PR_VREG_IBAND 0x0124
#define CSR_2L_PXP_CDR0_PR_VREG_IBAND GENMASK(2, 0)
#define CSR_2L_PXP_CDR0_PR_VREG_CKBUF GENMASK(10, 8)
#define REG_CSR_2L_CDR0_PR_CKREF_DIV 0x0128
#define CSR_2L_PXP_CDR0_PR_CKREF_DIV GENMASK(1, 0)
#define REG_CSR_2L_CDR0_PR_MONCK 0x012c
#define CSR_2L_PXP_CDR0_PR_MONCK_ENABLE BIT(0)
#define CSR_2L_PXP_CDR0_PR_RESERVE0 GENMASK(19, 16)
#define REG_CSR_2L_CDR0_PR_COR_HBW 0x0130
#define CSR_2L_PXP_CDR0_PR_LDO_FORCE_ON BIT(8)
#define CSR_2L_PXP_CDR0_PR_CKREF_DIV1 GENMASK(17, 16)
#define REG_CSR_2L_CDR0_PR_MONPI 0x0134
#define CSR_2L_PXP_CDR0_PR_XFICK_EN BIT(8)
#define REG_CSR_2L_RX0_SIGDET_DCTEST 0x0140
#define CSR_2L_PXP_RX0_SIGDET_LPF_CTRL GENMASK(9, 8)
#define CSR_2L_PXP_RX0_SIGDET_PEAK GENMASK(25, 24)
#define REG_CSR_2L_RX0_SIGDET_VTH_SEL 0x0144
#define CSR_2L_PXP_RX0_SIGDET_VTH_SEL GENMASK(4, 0)
#define CSR_2L_PXP_RX0_FE_VB_EQ1_EN BIT(24)
#define REG_CSR_2L_PXP_RX0_FE_VB_EQ2 0x0148
#define CSR_2L_PXP_RX0_FE_VB_EQ2_EN BIT(0)
#define CSR_2L_PXP_RX0_FE_VB_EQ3_EN BIT(8)
#define CSR_2L_PXP_RX0_FE_VCM_GEN_PWDB BIT(16)
#define REG_CSR_2L_PXP_RX0_OSCAL_CTLE1IOS 0x0158
#define CSR_2L_PXP_RX0_PR_OSCAL_VGA1IOS GENMASK(29, 24)
#define REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS 0x015c
#define CSR_2L_PXP_RX0_PR_OSCAL_VGA1VOS GENMASK(5, 0)
#define CSR_2L_PXP_RX0_PR_OSCAL_VGA2IOS GENMASK(13, 8)
#define REG_CSR_2L_RX1_REV0 0x01b4
#define REG_CSR_2L_RX1_PHYCK_DIV 0x01b8
#define CSR_2L_PXP_RX1_PHYCK_SEL GENMASK(9, 8)
#define CSR_2L_PXP_RX1_PHYCK_RSTB BIT(16)
#define CSR_2L_PXP_RX1_TDC_CK_SEL BIT(24)
#define REG_CSR_2L_CDR1_PD_PICAL_CKD8_INV 0x01bc
#define CSR_2L_PXP_CDR1_PD_EDGE_DISABLE BIT(8)
#define REG_CSR_2L_CDR1_PR_BETA_DAC 0x01d8
#define CSR_2L_PXP_CDR1_PR_BETA_SEL GENMASK(19, 16)
#define CSR_2L_PXP_CDR1_PR_KBAND_DIV GENMASK(26, 24)
#define REG_CSR_2L_CDR1_PR_MONCK 0x01e4
#define CSR_2L_PXP_CDR1_PR_MONCK_ENABLE BIT(0)
#define CSR_2L_PXP_CDR1_PR_RESERVE0 GENMASK(19, 16)
#define REG_CSR_2L_CDR1_LPF_RATIO 0x01c8
#define CSR_2L_PXP_CDR1_LPF_TOP_LIM GENMASK(26, 8)
#define REG_CSR_2L_CDR1_PR_INJ_MODE 0x01d4
#define CSR_2L_PXP_CDR1_INJ_FORCE_OFF BIT(24)
#define REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL 0x01dc
#define CSR_2L_PXP_CDR1_PR_VREG_IBAND GENMASK(2, 0)
#define CSR_2L_PXP_CDR1_PR_VREG_CKBUF GENMASK(10, 8)
#define REG_CSR_2L_CDR1_PR_CKREF_DIV 0x01e0
#define CSR_2L_PXP_CDR1_PR_CKREF_DIV GENMASK(1, 0)
#define REG_CSR_2L_CDR1_PR_COR_HBW 0x01e8
#define CSR_2L_PXP_CDR1_PR_LDO_FORCE_ON BIT(8)
#define CSR_2L_PXP_CDR1_PR_CKREF_DIV1 GENMASK(17, 16)
#define REG_CSR_2L_CDR1_PR_MONPI 0x01ec
#define CSR_2L_PXP_CDR1_PR_XFICK_EN BIT(8)
#define REG_CSR_2L_RX1_DAC_RANGE_EYE 0x01f4
#define CSR_2L_PXP_RX1_SIGDET_LPF_CTRL GENMASK(25, 24)
#define REG_CSR_2L_RX1_SIGDET_NOVTH 0x01f8
#define CSR_2L_PXP_RX1_SIGDET_PEAK GENMASK(9, 8)
#define CSR_2L_PXP_RX1_SIGDET_VTH_SEL GENMASK(20, 16)
#define REG_CSR_2L_RX1_FE_VB_EQ1 0x0200
#define CSR_2L_PXP_RX1_FE_VB_EQ1_EN BIT(0)
#define CSR_2L_PXP_RX1_FE_VB_EQ2_EN BIT(8)
#define CSR_2L_PXP_RX1_FE_VB_EQ3_EN BIT(16)
#define CSR_2L_PXP_RX1_FE_VCM_GEN_PWDB BIT(24)
#define REG_CSR_2L_RX1_OSCAL_VGA1IOS 0x0214
#define CSR_2L_PXP_RX1_PR_OSCAL_VGA1IOS GENMASK(5, 0)
#define CSR_2L_PXP_RX1_PR_OSCAL_VGA1VOS GENMASK(13, 8)
#define CSR_2L_PXP_RX1_PR_OSCAL_VGA2IOS GENMASK(21, 16)
/* PMA */
#define REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1 0x0004
#define PCIE_LCPLL_MAN_PWDB BIT(0)
#define REG_PCIE_PMA_SEQUENCE_DISB_CTRL1 0x010c
#define PCIE_DISB_RX_SDCAL_EN BIT(0)
#define REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1 0x0114
#define PCIE_FORCE_RX_SDCAL_EN BIT(0)
#define REG_PCIE_PMA_SS_RX_FREQ_DET1 0x014c
#define PCIE_PLL_FT_LOCK_CYCLECNT GENMASK(15, 0)
#define PCIE_PLL_FT_UNLOCK_CYCLECNT GENMASK(31, 16)
#define REG_PCIE_PMA_SS_RX_FREQ_DET2 0x0150
#define PCIE_LOCK_TARGET_BEG GENMASK(15, 0)
#define PCIE_LOCK_TARGET_END GENMASK(31, 16)
#define REG_PCIE_PMA_SS_RX_FREQ_DET3 0x0154
#define PCIE_UNLOCK_TARGET_BEG GENMASK(15, 0)
#define PCIE_UNLOCK_TARGET_END GENMASK(31, 16)
#define REG_PCIE_PMA_SS_RX_FREQ_DET4 0x0158
#define PCIE_FREQLOCK_DET_EN GENMASK(2, 0)
#define PCIE_LOCK_LOCKTH GENMASK(11, 8)
#define PCIE_UNLOCK_LOCKTH GENMASK(15, 12)
#define REG_PCIE_PMA_SS_RX_CAL1 0x0160
#define REG_PCIE_PMA_SS_RX_CAL2 0x0164
#define PCIE_CAL_OUT_OS GENMASK(11, 8)
#define REG_PCIE_PMA_SS_RX_SIGDET0 0x0168
#define PCIE_SIGDET_WIN_NONVLD_TIMES GENMASK(28, 24)
#define REG_PCIE_PMA_TX_RESET 0x0260
#define PCIE_TX_TOP_RST BIT(0)
#define PCIE_TX_CAL_RST BIT(8)
#define REG_PCIE_PMA_RX_FORCE_MODE0 0x0294
#define PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL GENMASK(1, 0)
#define REG_PCIE_PMA_SS_DA_XPON_PWDB0 0x034c
#define PCIE_DA_XPON_CDR_PR_PWDB BIT(8)
#define REG_PCIE_PMA_SW_RESET 0x0460
#define PCIE_SW_RX_FIFO_RST BIT(0)
#define PCIE_SW_RX_RST BIT(1)
#define PCIE_SW_TX_RST BIT(2)
#define PCIE_SW_PMA_RST BIT(3)
#define PCIE_SW_ALLPCS_RST BIT(4)
#define PCIE_SW_REF_RST BIT(5)
#define PCIE_SW_TX_FIFO_RST BIT(6)
#define PCIE_SW_XFI_TXPCS_RST BIT(7)
#define PCIE_SW_XFI_RXPCS_RST BIT(8)
#define PCIE_SW_XFI_RXPCS_BIST_RST BIT(9)
#define PCIE_SW_HSG_TXPCS_RST BIT(10)
#define PCIE_SW_HSG_RXPCS_RST BIT(11)
#define PCIE_PMA_SW_RST (PCIE_SW_RX_FIFO_RST | \
PCIE_SW_RX_RST | \
PCIE_SW_TX_RST | \
PCIE_SW_PMA_RST | \
PCIE_SW_ALLPCS_RST | \
PCIE_SW_REF_RST | \
PCIE_SW_TX_FIFO_RST | \
PCIE_SW_XFI_TXPCS_RST | \
PCIE_SW_XFI_RXPCS_RST | \
PCIE_SW_XFI_RXPCS_BIST_RST | \
PCIE_SW_HSG_TXPCS_RST | \
PCIE_SW_HSG_RXPCS_RST)
#define REG_PCIE_PMA_RO_RX_FREQDET 0x0530
#define PCIE_RO_FBCK_LOCK BIT(0)
#define PCIE_RO_FL_OUT GENMASK(31, 16)
#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC 0x0794
#define PCIE_FORCE_DA_PXP_CDR_PR_IDAC GENMASK(10, 0)
#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC BIT(16)
#define PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW BIT(24)
#define REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW 0x0798
#define PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW GENMASK(30, 0)
#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS 0x079c
#define PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW BIT(16)
#define REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW 0x0800
#define PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW GENMASK(30, 0)
#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB 0x081c
#define PCIE_FORCE_DA_PXP_CDR_PD_PWDB BIT(0)
#define PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB BIT(8)
#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C 0x0820
#define PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN BIT(0)
#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN BIT(8)
#define PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN BIT(16)
#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN BIT(24)
#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB 0x0824
#define PCIE_FORCE_DA_PXP_CDR_PR_PWDB BIT(16)
#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB BIT(24)
#define REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT 0x0828
#define PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN BIT(0)
#define PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN BIT(8)
#define PCIE_FORCE_DA_PXP_JCPLL_EN BIT(16)
#define PCIE_FORCE_SEL_DA_PXP_JCPLL_EN BIT(24)
#define REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST 0x0084c
#define PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB BIT(16)
#define PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB BIT(24)
#define REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT 0x0854
#define PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN BIT(0)
#define PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN BIT(8)
#define PCIE_FORCE_DA_PXP_TXPLL_EN BIT(16)
#define PCIE_FORCE_SEL_DA_PXP_TXPLL_EN BIT(24)
#define REG_PCIE_PMA_SCAN_MODE 0x0884
#define PCIE_FORCE_DA_PXP_JCPLL_KBAND_LOAD_EN BIT(0)
#define PCIE_FORCE_SEL_DA_PXP_JCPLL_KBAND_LOAD_EN BIT(8)
#define REG_PCIE_PMA_DIG_RESERVE_13 0x08bc
#define PCIE_FLL_IDAC_PCIEG1 GENMASK(10, 0)
#define PCIE_FLL_IDAC_PCIEG2 GENMASK(26, 16)
#define REG_PCIE_PMA_DIG_RESERVE_14 0x08c0
#define PCIE_FLL_IDAC_PCIEG3 GENMASK(10, 0)
#define PCIE_FLL_LOAD_EN BIT(16)
#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL 0x088c
#define PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL GENMASK(1, 0)
#define PCIE_FORCE_SEL_DA_PXP_RX_FE_GAIN_CTRL BIT(8)
#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB 0x0894
#define PCIE_FORCE_DA_PXP_RX_FE_PWDB BIT(0)
#define PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB BIT(8)
#define REG_PCIE_PMA_DIG_RESERVE_12 0x08b8
#define PCIE_FORCE_PMA_RX_SPEED GENMASK(7, 4)
#define PCIE_FORCE_SEL_PMA_RX_SPEED BIT(7)
#define REG_PCIE_PMA_DIG_RESERVE_17 0x08e0
#define REG_PCIE_PMA_DIG_RESERVE_18 0x08e4
#define PCIE_PXP_RX_VTH_SEL_PCIE_G1 GENMASK(4, 0)
#define PCIE_PXP_RX_VTH_SEL_PCIE_G2 GENMASK(12, 8)
#define PCIE_PXP_RX_VTH_SEL_PCIE_G3 GENMASK(20, 16)
#define REG_PCIE_PMA_DIG_RESERVE_19 0x08e8
#define PCIE_PCP_RX_REV0_PCIE_GEN1 GENMASK(31, 16)
#define REG_PCIE_PMA_DIG_RESERVE_20 0x08ec
#define PCIE_PCP_RX_REV0_PCIE_GEN2 GENMASK(15, 0)
#define PCIE_PCP_RX_REV0_PCIE_GEN3 GENMASK(31, 16)
#define REG_PCIE_PMA_DIG_RESERVE_21 0x08f0
#define REG_PCIE_PMA_DIG_RESERVE_22 0x08f4
#define REG_PCIE_PMA_DIG_RESERVE_27 0x0908
#define REG_PCIE_PMA_DIG_RESERVE_30 0x0914
/* DTIME */
#define REG_PCIE_PEXTP_DIG_GLB44 0x00
#define PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL GENMASK(7, 0)
#define PCIE_XTP_RXDET_EN_STB_T_SEL GENMASK(15, 8)
#define PCIE_XTP_RXDET_FINISH_STB_T_SEL GENMASK(23, 16)
#define PCIE_XTP_TXPD_TX_DATA_EN_DLY GENMASK(27, 24)
#define PCIE_XTP_TXPD_RXDET_DONE_CDT BIT(28)
#define PCIE_XTP_RXDET_LATCH_STB_T_SEL GENMASK(31, 29)
/* RX AEQ */
#define REG_PCIE_PEXTP_DIG_LN_RX30_P0 0x0000
#define PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT GENMASK(7, 0)
#define PCIE_XTP_LN_RX_PDOWN_T2RLB_DIG_EN BIT(8)
#define PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT GENMASK(31, 16)
#define REG_PCIE_PEXTP_DIG_LN_RX30_P1 0x0100
#endif /* _PHY_AIROHA_PCIE_H */

File diff suppressed because it is too large Load Diff

View File

@ -664,7 +664,7 @@ out_unlock:
*
* Returns the phy driver, after getting a refcount to it; or
* -ENODEV if there is no such phy. The caller is responsible for
* calling phy_put() to release that count.
* calling of_phy_put() to release that count.
*/
struct phy *of_phy_get(struct device_node *np, const char *con_id)
{

View File

@ -489,6 +489,243 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_gen3_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
};
static const struct qmp_phy_init_tbl ipq9574_gen3x1_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18),
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x31),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42),
QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_MAP, 0x04),
QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_TIMER1, 0xff),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_TIMER2, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x30),
QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x21),
QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x68),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xd4),
QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24),
QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x20),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TIMER, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4),
QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_ADJ_PER1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_ADJ_PER2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_EP_DIV_MODE0, 0x19),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_EP_DIV_MODE1, 0x28),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90),
QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x89),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x10),
};
static const struct qmp_phy_init_tbl ipq9574_gen3x2_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18),
QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x31),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42),
QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20),
QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_MAP, 0x04),
QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_TIMER1, 0xff),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_TIMER2, 0x3f),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x30),
QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x21),
QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x68),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xd4),
QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE0, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24),
QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07),
QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TIMER, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29),
QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa),
QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03),
QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4),
QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_ADJ_PER1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_ADJ_PER2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08),
QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_EP_DIV_MODE0, 0x19),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_EP_DIV_MODE1, 0x28),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90),
QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x89),
QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x10),
};
static const struct qmp_phy_init_tbl ipq9574_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x61),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1e),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x73),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x80),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xc8),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0xb1),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xc8),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb1),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xf0),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x02),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x2f),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xd3),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
};
static const struct qmp_phy_init_tbl ipq9574_gen3x1_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_H, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_DCC_CAL_CONFIG, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_G12S1_TXDEEMPH_M3P5DB, 0x10),
};
static const struct qmp_phy_init_tbl ipq9574_gen3x1_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2, 0x0d),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG1, 0x14),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG1, 0x10),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG2, 0x0b),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG2, 0x52),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG2, 0x50),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG4, 0x1a),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5, 0x06),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG6, 0x03),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
};
static const struct qmp_phy_init_tbl ipq9574_gen3x2_pcie_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_G12S1_TXDEEMPH_M3P5DB, 0x10),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_H, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_DCC_CAL_CONFIG, 0x01),
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa),
};
static const struct qmp_phy_init_tbl ipq9574_gen3x2_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG2, 0x1d),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H, 0x00),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H, 0x00),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_EQ_CONFIG1, 0x14),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_EQ_CONFIG1, 0x10),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_EQ_CONFIG2, 0x0b),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_PRESET_P10_PRE, 0x00),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_PRESET_P10_POST, 0x58),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG1, 0x00),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG2, 0x52),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG4, 0x19),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG2, 0x49),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG4, 0x2a),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5, 0x02),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG6, 0x03),
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
};
static const struct qmp_phy_init_tbl sdm845_qmp_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
@ -2535,6 +2772,16 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v5 = {
.rx2 = 0x1800,
};
static const struct qmp_pcie_offsets qmp_pcie_offsets_ipq9574 = {
.serdes = 0,
.pcs = 0x1000,
.pcs_misc = 0x1400,
.tx = 0x0200,
.rx = 0x0400,
.tx2 = 0x0600,
.rx2 = 0x0800,
};
static const struct qmp_pcie_offsets qmp_pcie_offsets_v5_20 = {
.serdes = 0x1000,
.pcs = 0x1200,
@ -2647,6 +2894,62 @@ static const struct qmp_phy_cfg ipq6018_pciephy_cfg = {
.phy_status = PHYSTATUS,
};
static const struct qmp_phy_cfg ipq9574_gen3x1_pciephy_cfg = {
.lanes = 1,
.offsets = &qmp_pcie_offsets_v4x1,
.tbls = {
.serdes = ipq9574_gen3x1_pcie_serdes_tbl,
.serdes_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_serdes_tbl),
.tx = ipq8074_pcie_gen3_tx_tbl,
.tx_num = ARRAY_SIZE(ipq8074_pcie_gen3_tx_tbl),
.rx = ipq9574_pcie_rx_tbl,
.rx_num = ARRAY_SIZE(ipq9574_pcie_rx_tbl),
.pcs = ipq9574_gen3x1_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_pcs_tbl),
.pcs_misc = ipq9574_gen3x1_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_pcs_misc_tbl),
},
.reset_list = ipq8074_pciephy_reset_l,
.num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l),
.vreg_list = NULL,
.num_vregs = 0,
.regs = pciephy_v4_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
.pipe_clock_rate = 250000000,
};
static const struct qmp_phy_cfg ipq9574_gen3x2_pciephy_cfg = {
.lanes = 2,
.offsets = &qmp_pcie_offsets_ipq9574,
.tbls = {
.serdes = ipq9574_gen3x2_pcie_serdes_tbl,
.serdes_num = ARRAY_SIZE(ipq9574_gen3x2_pcie_serdes_tbl),
.tx = ipq8074_pcie_gen3_tx_tbl,
.tx_num = ARRAY_SIZE(ipq8074_pcie_gen3_tx_tbl),
.rx = ipq9574_pcie_rx_tbl,
.rx_num = ARRAY_SIZE(ipq9574_pcie_rx_tbl),
.pcs = ipq9574_gen3x2_pcie_pcs_tbl,
.pcs_num = ARRAY_SIZE(ipq9574_gen3x2_pcie_pcs_tbl),
.pcs_misc = ipq9574_gen3x2_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(ipq9574_gen3x2_pcie_pcs_misc_tbl),
},
.reset_list = ipq8074_pciephy_reset_l,
.num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l),
.vreg_list = NULL,
.num_vregs = 0,
.regs = pciephy_v5_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS,
.pipe_clock_rate = 250000000,
};
static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = {
.lanes = 1,
@ -3730,14 +4033,11 @@ static int phy_aux_clk_register(struct qmp_pcie *qmp, struct device_node *np)
{
struct clk_fixed_rate *fixed = &qmp->aux_clk_fixed;
struct clk_init_data init = { };
int ret;
char name[64];
ret = of_property_read_string_index(np, "clock-output-names", 1, &init.name);
if (ret) {
dev_err(qmp->dev, "%pOFn: No clock-output-names index 1\n", np);
return ret;
}
snprintf(name, sizeof(name), "%s::phy_aux_clk", dev_name(qmp->dev));
init.name = name;
init.ops = &clk_fixed_rate_ops;
fixed->fixed_rate = qmp->cfg->aux_clock_rate;
@ -4030,6 +4330,12 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, {
.compatible = "qcom,ipq8074-qmp-pcie-phy",
.data = &ipq8074_pciephy_cfg,
}, {
.compatible = "qcom,ipq9574-qmp-gen3x1-pcie-phy",
.data = &ipq9574_gen3x1_pciephy_cfg,
}, {
.compatible = "qcom,ipq9574-qmp-gen3x2-pcie-phy",
.data = &ipq9574_gen3x2_pciephy_cfg,
}, {
.compatible = "qcom,msm8998-qmp-pcie-phy",
.data = &msm8998_pciephy_cfg,

View File

@ -11,8 +11,22 @@
#define QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG2 0x0c
#define QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG4 0x14
#define QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x20
#define QPHY_V5_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L 0x44
#define QPHY_V5_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H 0x48
#define QPHY_V5_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L 0x4c
#define QPHY_V5_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H 0x50
#define QPHY_V5_PCS_PCIE_INT_AUX_CLK_CONFIG1 0x54
#define QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG1 0x5c
#define QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG2 0x60
#define QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG4 0x68
#define QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG2 0x7c
#define QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG4 0x84
#define QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x88
#define QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG6 0x8c
#define QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS 0x94
#define QPHY_V5_PCS_PCIE_EQ_CONFIG1 0xa4
#define QPHY_V5_PCS_PCIE_EQ_CONFIG2 0xa8
#define QPHY_V5_PCS_PCIE_PRESET_P10_PRE 0xc0
#define QPHY_V5_PCS_PCIE_PRESET_P10_POST 0xe4
#endif

View File

@ -8,6 +8,9 @@
/* QMP V2 PHY for PCIE gen3 ports - QSERDES PLL registers */
#define QSERDES_PLL_BG_TIMER 0x00c
#define QSERDES_PLL_SSC_EN_CENTER 0x010
#define QSERDES_PLL_SSC_ADJ_PER1 0x014
#define QSERDES_PLL_SSC_ADJ_PER2 0x018
#define QSERDES_PLL_SSC_PER1 0x01c
#define QSERDES_PLL_SSC_PER2 0x020
#define QSERDES_PLL_SSC_STEP_SIZE1_MODE0 0x024

View File

@ -2252,6 +2252,9 @@ static const struct of_device_id qmp_usb_of_match_table[] = {
}, {
.compatible = "qcom,sa8775p-qmp-usb3-uni-phy",
.data = &sa8775p_usb3_uniphy_cfg,
}, {
.compatible = "qcom,sc8180x-qmp-usb3-uni-phy",
.data = &sm8150_usb3_uniphy_cfg,
}, {
.compatible = "qcom,sc8280xp-qmp-usb3-uni-phy",
.data = &sc8280xp_usb3_uniphy_cfg,

View File

@ -86,7 +86,9 @@ config PHY_ROCKCHIP_PCIE
config PHY_ROCKCHIP_SAMSUNG_HDPTX
tristate "Rockchip Samsung HDMI/eDP Combo PHY driver"
depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
depends on HAS_IOMEM
select GENERIC_PHY
select MFD_SYSCON
select RATIONAL
help
Enable this to support the Rockchip HDMI/eDP Combo PHY

File diff suppressed because it is too large Load Diff

View File

@ -121,7 +121,7 @@
#define EXYNOS_5420_USB_ISOL_HOST_OFFSET 0x70C
#define EXYNOS_5250_USB_ISOL_ENABLE BIT(0)
/* Mode swtich register */
/* Mode switch register */
#define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230
#define EXYNOS_5250_MODE_SWITCH_MASK 1
#define EXYNOS_5250_MODE_SWITCH_DEVICE 0

View File

@ -228,11 +228,6 @@ struct miphy28lp_dev {
int nphys;
};
struct miphy_initval {
u16 reg;
u16 val;
};
enum miphy_sata_gen { SATA_GEN1, SATA_GEN2, SATA_GEN3 };
static char *PHY_TYPE_name[] = { "sata-up", "pcie-up", "", "usb3-up" };

View File

@ -15,6 +15,16 @@ config PHY_STARFIVE_JH7110_DPHY_RX
system. If M is selected, the module will be called
phy-jh7110-dphy-rx.ko.
config PHY_STARFIVE_JH7110_DPHY_TX
tristate "StarFive JH7110 D-PHY TX Support"
depends on HAS_IOMEM
select GENERIC_PHY
select GENERIC_PHY_MIPI_DPHY
help
Choose this option if you have a StarFive D-PHY TX in your
system. If M is selected, the module will be called
phy-jh7110-dphy-tx.ko.
config PHY_STARFIVE_JH7110_PCIE
tristate "Starfive JH7110 PCIE 2.0/USB 3.0 PHY support"
depends on HAS_IOMEM

View File

@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_RX) += phy-jh7110-dphy-rx.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_TX) += phy-jh7110-dphy-tx.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_PCIE) += phy-jh7110-pcie.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_USB) += phy-jh7110-usb.o

View File

@ -46,11 +46,6 @@
#define STF_MAP_LANES_NUM 6
struct regval {
u32 addr;
u32 val;
};
struct stf_dphy_info {
/**
* @maps:

View File

@ -0,0 +1,461 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* DPHY TX driver for the StarFive JH7110 SoC
*
* Copyright (C) 2023 StarFive Technology Co., Ltd.
* Author: Keith Zhao <keith.zhao@starfivetech.com>
* Author: Shengyang Chen <shengyang.chen@starfivetech.com>
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/phy/phy-mipi-dphy.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#define STF_DPHY_APBIFSAIF_SYSCFG(x) (x)
#define STF_DPHY_AON_POWER_READY_N_ACTIVE 0
#define STF_DPHY_AON_POWER_READY_N BIT(0)
#define STF_DPHY_CFG_L0_SWAP_SEL GENMASK(14, 12)
#define STF_DPHY_CFG_L1_SWAP_SEL GENMASK(17, 15)
#define STF_DPHY_CFG_L2_SWAP_SEL GENMASK(20, 18)
#define STF_DPHY_CFG_L3_SWAP_SEL GENMASK(23, 21)
#define STF_DPHY_CFG_L4_SWAP_SEL GENMASK(26, 24)
#define STF_DPHY_RGS_CDTX_PLL_UNLOCK BIT(18)
#define STF_DPHY_RG_CDTX_L0N_HSTX_RES GENMASK(23, 19)
#define STF_DPHY_RG_CDTX_L0P_HSTX_RES GENMASK(28, 24)
#define STF_DPHY_RG_CDTX_L1P_HSTX_RES GENMASK(9, 5)
#define STF_DPHY_RG_CDTX_L2N_HSTX_RES GENMASK(14, 10)
#define STF_DPHY_RG_CDTX_L2P_HSTX_RES GENMASK(19, 15)
#define STF_DPHY_RG_CDTX_L3N_HSTX_RES GENMASK(24, 20)
#define STF_DPHY_RG_CDTX_L3P_HSTX_RES GENMASK(29, 25)
#define STF_DPHY_RG_CDTX_L4N_HSTX_RES GENMASK(4, 0)
#define STF_DPHY_RG_CDTX_L4P_HSTX_RES GENMASK(9, 5)
#define STF_DPHY_RG_CDTX_PLL_FBK_FRA GENMASK(23, 0)
#define STF_DPHY_RG_CDTX_PLL_FBK_INT GENMASK(8, 0)
#define STF_DPHY_RG_CDTX_PLL_FM_EN BIT(9)
#define STF_DPHY_RG_CDTX_PLL_LDO_STB_X2_EN BIT(10)
#define STF_DPHY_RG_CDTX_PLL_PRE_DIV GENMASK(12, 11)
#define STF_DPHY_RG_CDTX_PLL_SSC_EN BIT(18)
#define STF_DPHY_RG_CLANE_HS_CLK_POST_TIME GENMASK(7, 0)
#define STF_DPHY_RG_CLANE_HS_CLK_PRE_TIME GENMASK(15, 8)
#define STF_DPHY_RG_CLANE_HS_PRE_TIME GENMASK(23, 16)
#define STF_DPHY_RG_CLANE_HS_TRAIL_TIME GENMASK(31, 24)
#define STF_DPHY_RG_CLANE_HS_ZERO_TIME GENMASK(7, 0)
#define STF_DPHY_RG_DLANE_HS_PRE_TIME GENMASK(15, 8)
#define STF_DPHY_RG_DLANE_HS_TRAIL_TIME GENMASK(23, 16)
#define STF_DPHY_RG_DLANE_HS_ZERO_TIME GENMASK(31, 24)
#define STF_DPHY_RG_EXTD_CYCLE_SEL GENMASK(2, 0)
#define STF_DPHY_SCFG_C_HS_PRE_ZERO_TIME GENMASK(31, 0)
#define STF_DPHY_SCFG_DSI_TXREADY_ESC_SEL GENMASK(2, 1)
#define STF_DPHY_SCFG_PPI_C_READY_SEL GENMASK(4, 3)
#define STF_DPHY_REFCLK_IN_SEL GENMASK(28, 26)
#define STF_DPHY_RESETB BIT(29)
#define STF_DPHY_REFCLK_12M 1
#define STF_DPHY_BITRATE_ALIGN 10000000
#define STF_MAP_LANES_NUM 5
#define STF_DPHY_LSHIFT_16(x) (FIELD_PREP(GENMASK(23, 16), (x)))
#define STF_DPHY_LSHIFT_8(x) (FIELD_PREP(GENMASK(15, 8), (x)))
#define STF_DPHY_HW_DELAY_US 200
#define STF_DPHY_HW_TIMEOUT_US 5000
struct stf_dphy_config {
unsigned long bitrate;
u32 pll_fbk_int;
u32 pll_fbk_fra_val;
u32 extd_cycle_sel;
u32 dlane_hs_pre_time;
u32 dlane_hs_zero_time;
u32 dlane_hs_trail_time;
u32 clane_hs_pre_time;
u32 clane_hs_zero_time;
u32 clane_hs_trail_time;
u32 clane_hs_clk_pre_time;
u32 clane_hs_clk_post_time;
};
static const struct stf_dphy_config reg_configs[] = {
{160000000, 0x6a, 0xaa, 0x3, 0xa, 0x17, 0x11, 0x5, 0x2b, 0xd, 0x7, 0x3d},
{170000000, 0x71, 0x55, 0x3, 0xb, 0x18, 0x11, 0x5, 0x2e, 0xd, 0x7, 0x3d},
{180000000, 0x78, 0x0, 0x3, 0xb, 0x19, 0x12, 0x6, 0x30, 0xe, 0x7, 0x3e},
{190000000, 0x7e, 0xaa, 0x3, 0xc, 0x1a, 0x12, 0x6, 0x33, 0xe, 0x7, 0x3e},
{200000000, 0x85, 0x55, 0x3, 0xc, 0x1b, 0x13, 0x7, 0x35, 0xf, 0x7, 0x3f},
{320000000, 0x6a, 0xaa, 0x2, 0x8, 0x14, 0xf, 0x5, 0x2b, 0xd, 0x3, 0x23},
{330000000, 0x6e, 0x0, 0x2, 0x8, 0x15, 0xf, 0x5, 0x2d, 0xd, 0x3, 0x23},
{340000000, 0x71, 0x55, 0x2, 0x9, 0x15, 0xf, 0x5, 0x2e, 0xd, 0x3, 0x23},
{350000000, 0x74, 0xaa, 0x2, 0x9, 0x15, 0x10, 0x6, 0x2f, 0xe, 0x3, 0x24},
{360000000, 0x78, 0x0, 0x2, 0x9, 0x16, 0x10, 0x6, 0x30, 0xe, 0x3, 0x24},
{370000000, 0x7b, 0x55, 0x2, 0x9, 0x17, 0x10, 0x6, 0x32, 0xe, 0x3, 0x24},
{380000000, 0x7e, 0xaa, 0x2, 0xa, 0x17, 0x10, 0x6, 0x33, 0xe, 0x3, 0x24},
{390000000, 0x82, 0x0, 0x2, 0xa, 0x17, 0x11, 0x6, 0x35, 0xf, 0x3, 0x25},
{400000000, 0x85, 0x55, 0x2, 0xa, 0x18, 0x11, 0x7, 0x35, 0xf, 0x3, 0x25},
{410000000, 0x88, 0xaa, 0x2, 0xa, 0x19, 0x11, 0x7, 0x37, 0xf, 0x3, 0x25},
{420000000, 0x8c, 0x0, 0x2, 0xa, 0x19, 0x12, 0x7, 0x38, 0x10, 0x3, 0x26},
{430000000, 0x8f, 0x55, 0x2, 0xb, 0x19, 0x12, 0x7, 0x39, 0x10, 0x3, 0x26},
{440000000, 0x92, 0xaa, 0x2, 0xb, 0x1a, 0x12, 0x7, 0x3b, 0x10, 0x3, 0x26},
{450000000, 0x96, 0x0, 0x2, 0xb, 0x1b, 0x12, 0x8, 0x3c, 0x10, 0x3, 0x26},
{460000000, 0x99, 0x55, 0x2, 0xb, 0x1b, 0x13, 0x8, 0x3d, 0x11, 0x3, 0x27},
{470000000, 0x9c, 0xaa, 0x2, 0xc, 0x1b, 0x13, 0x8, 0x3e, 0x11, 0x3, 0x27},
{480000000, 0xa0, 0x27, 0x2, 0xc, 0x1c, 0x13, 0x8, 0x40, 0x11, 0x3, 0x27},
{490000000, 0xa3, 0x55, 0x2, 0xc, 0x1d, 0x14, 0x8, 0x42, 0x12, 0x3, 0x28},
{500000000, 0xa6, 0xaa, 0x2, 0xc, 0x1d, 0x14, 0x9, 0x42, 0x12, 0x3, 0x28},
{510000000, 0xaa, 0x0, 0x2, 0xc, 0x1e, 0x14, 0x9, 0x44, 0x12, 0x3, 0x28},
{520000000, 0xad, 0x55, 0x2, 0xd, 0x1e, 0x15, 0x9, 0x45, 0x13, 0x3, 0x29},
{530000000, 0xb0, 0xaa, 0x2, 0xd, 0x1e, 0x15, 0x9, 0x47, 0x13, 0x3, 0x29},
{540000000, 0xb4, 0x0, 0x2, 0xd, 0x1f, 0x15, 0x9, 0x48, 0x13, 0x3, 0x29},
{550000000, 0xb7, 0x55, 0x2, 0xd, 0x20, 0x16, 0x9, 0x4a, 0x14, 0x3, 0x2a},
{560000000, 0xba, 0xaa, 0x2, 0xe, 0x20, 0x16, 0xa, 0x4a, 0x14, 0x3, 0x2a},
{570000000, 0xbe, 0x0, 0x2, 0xe, 0x20, 0x16, 0xa, 0x4c, 0x14, 0x3, 0x2a},
{580000000, 0xc1, 0x55, 0x2, 0xe, 0x21, 0x16, 0xa, 0x4d, 0x14, 0x3, 0x2a},
{590000000, 0xc4, 0xaa, 0x2, 0xe, 0x22, 0x17, 0xa, 0x4f, 0x15, 0x3, 0x2b},
{600000000, 0xc8, 0x0, 0x2, 0xe, 0x23, 0x17, 0xa, 0x50, 0x15, 0x3, 0x2b},
{610000000, 0xcb, 0x55, 0x2, 0xf, 0x22, 0x17, 0xb, 0x50, 0x15, 0x3, 0x2b},
{620000000, 0xce, 0xaa, 0x2, 0xf, 0x23, 0x18, 0xb, 0x52, 0x16, 0x3, 0x2c},
{630000000, 0x69, 0x0, 0x1, 0x7, 0x12, 0xd, 0x5, 0x2a, 0xc, 0x1, 0x15},
{640000000, 0x6a, 0xaa, 0x1, 0x7, 0x13, 0xe, 0x5, 0x2b, 0xd, 0x1, 0x16},
{650000000, 0x6c, 0x55, 0x1, 0x7, 0x13, 0xe, 0x5, 0x2c, 0xd, 0x1, 0x16},
{660000000, 0x6e, 0x0, 0x1, 0x7, 0x13, 0xe, 0x5, 0x2d, 0xd, 0x1, 0x16},
{670000000, 0x6f, 0xaa, 0x1, 0x8, 0x13, 0xe, 0x5, 0x2d, 0xd, 0x1, 0x16},
{680000000, 0x71, 0x55, 0x1, 0x8, 0x13, 0xe, 0x5, 0x2e, 0xd, 0x1, 0x16},
{690000000, 0x73, 0x0, 0x1, 0x8, 0x14, 0xe, 0x6, 0x2e, 0xd, 0x1, 0x16},
{700000000, 0x74, 0xaa, 0x1, 0x8, 0x14, 0xf, 0x6, 0x2f, 0xe, 0x1, 0x16},
{710000000, 0x76, 0x55, 0x1, 0x8, 0x14, 0xf, 0x6, 0x2f, 0xe, 0x1, 0x17},
{720000000, 0x78, 0x0, 0x1, 0x8, 0x15, 0xf, 0x6, 0x30, 0xe, 0x1, 0x17},
{730000000, 0x79, 0xaa, 0x1, 0x8, 0x15, 0xf, 0x6, 0x31, 0xe, 0x1, 0x17},
{740000000, 0x7b, 0x55, 0x1, 0x8, 0x15, 0xf, 0x6, 0x32, 0xe, 0x1, 0x17},
{750000000, 0x7d, 0x0, 0x1, 0x8, 0x16, 0xf, 0x6, 0x32, 0xe, 0x1, 0x17},
{760000000, 0x7e, 0xaa, 0x1, 0x9, 0x15, 0xf, 0x6, 0x33, 0xe, 0x1, 0x17},
{770000000, 0x80, 0x55, 0x1, 0x9, 0x15, 0x10, 0x6, 0x34, 0xf, 0x1, 0x18},
{780000000, 0x82, 0x0, 0x1, 0x9, 0x16, 0x10, 0x6, 0x35, 0xf, 0x1, 0x18,},
{790000000, 0x83, 0xaa, 0x1, 0x9, 0x16, 0x10, 0x7, 0x34, 0xf, 0x1, 0x18},
{800000000, 0x85, 0x55, 0x1, 0x9, 0x17, 0x10, 0x7, 0x35, 0xf, 0x1, 0x18},
{810000000, 0x87, 0x0, 0x1, 0x9, 0x17, 0x10, 0x7, 0x36, 0xf, 0x1, 0x18},
{820000000, 0x88, 0xaa, 0x1, 0x9, 0x17, 0x10, 0x7, 0x37, 0xf, 0x1, 0x18},
{830000000, 0x8a, 0x55, 0x1, 0x9, 0x18, 0x10, 0x7, 0x37, 0xf, 0x1, 0x18},
{840000000, 0x8c, 0x0, 0x1, 0x9, 0x18, 0x11, 0x7, 0x38, 0x10, 0x1, 0x19},
{850000000, 0x8d, 0xaa, 0x1, 0xa, 0x17, 0x11, 0x7, 0x39, 0x10, 0x1, 0x19},
{860000000, 0x8f, 0x55, 0x1, 0xa, 0x18, 0x11, 0x7, 0x39, 0x10, 0x1, 0x19},
{870000000, 0x91, 0x0, 0x1, 0xa, 0x18, 0x11, 0x7, 0x3a, 0x10, 0x1, 0x19},
{880000000, 0x92, 0xaa, 0x1, 0xa, 0x18, 0x11, 0x7, 0x3b, 0x10, 0x1, 0x19},
{890000000, 0x94, 0x55, 0x1, 0xa, 0x19, 0x11, 0x7, 0x3c, 0x10, 0x1, 0x19},
{900000000, 0x96, 0x0, 0x1, 0xa, 0x19, 0x12, 0x8, 0x3c, 0x10, 0x1, 0x19},
{910000000, 0x97, 0xaa, 0x1, 0xa, 0x19, 0x12, 0x8, 0x3c, 0x11, 0x1, 0x1a},
{920000000, 0x99, 0x55, 0x1, 0xa, 0x1a, 0x12, 0x8, 0x3d, 0x11, 0x1, 0x1a},
{930000000, 0x9b, 0x0, 0x1, 0xa, 0x1a, 0x12, 0x8, 0x3e, 0x11, 0x1, 0x1a},
{940000000, 0x9c, 0xaa, 0x1, 0xb, 0x1a, 0x12, 0x8, 0x3e, 0x11, 0x1, 0x1a},
{950000000, 0x9e, 0x55, 0x1, 0xb, 0x1a, 0x12, 0x8, 0x3f, 0x11, 0x1, 0x1a},
{960000000, 0xa0, 0x0, 0x1, 0xb, 0x1a, 0x12, 0x8, 0x40, 0x11, 0x1, 0x1a},
{970000000, 0xa1, 0xaa, 0x1, 0xb, 0x1b, 0x13, 0x8, 0x41, 0x12, 0x1, 0x1b},
{980000000, 0xa3, 0x55, 0x1, 0xb, 0x1b, 0x13, 0x8, 0x42, 0x12, 0x1, 0x1b},
{990000000, 0xa5, 0x0, 0x1, 0xb, 0x1b, 0x13, 0x8, 0x42, 0x12, 0x1, 0x1b},
{1000000000, 0xa6, 0xaa, 0x1, 0xb, 0x1c, 0x13, 0x9, 0x42, 0x12, 0x1, 0x1b},
};
struct stf_dphy_info {
/**
* @maps:
*
* Physical lanes and logic lanes mapping table.
*
* The default order is:
* [data lane 0, data lane 1, data lane 2, date lane 3, clk lane]
*/
u8 maps[STF_MAP_LANES_NUM];
};
struct stf_dphy {
struct device *dev;
void __iomem *topsys;
struct clk *txesc_clk;
struct reset_control *sys_rst;
struct phy_configure_opts_mipi_dphy config;
struct phy *phy;
const struct stf_dphy_info *info;
};
static u32 stf_dphy_get_config_index(u32 bitrate)
{
u32 i;
for (i = 0; i < ARRAY_SIZE(reg_configs); i++) {
if (reg_configs[i].bitrate == bitrate)
return i;
}
return 0;
}
static void stf_dphy_hw_reset(struct stf_dphy *dphy, int assert)
{
int rc;
u32 status = 0;
writel(FIELD_PREP(STF_DPHY_RESETB, assert),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(100));
if (assert) {
rc = readl_poll_timeout_atomic(dphy->topsys +
STF_DPHY_APBIFSAIF_SYSCFG(8),
status,
!(FIELD_GET(STF_DPHY_RGS_CDTX_PLL_UNLOCK, status)),
STF_DPHY_HW_DELAY_US, STF_DPHY_HW_TIMEOUT_US);
if (rc)
dev_err(dphy->dev, "MIPI dphy-tx # PLL Locked\n");
}
}
static int stf_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
{
struct stf_dphy *dphy = phy_get_drvdata(phy);
const struct stf_dphy_info *info = dphy->info;
const struct stf_dphy_config *p = reg_configs;
unsigned long alignment = STF_DPHY_BITRATE_ALIGN;
u32 bitrate = opts->mipi_dphy.hs_clk_rate;
u32 tmp;
u32 i;
if (bitrate % alignment)
bitrate += alignment - (bitrate % alignment);
i = stf_dphy_get_config_index(bitrate);
tmp = readl(dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(100));
tmp &= ~STF_DPHY_REFCLK_IN_SEL;
tmp |= FIELD_PREP(STF_DPHY_REFCLK_IN_SEL, STF_DPHY_REFCLK_12M);
writel(tmp, dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(100));
writel(FIELD_PREP(STF_DPHY_RG_CDTX_L0N_HSTX_RES, 0x10) |
FIELD_PREP(STF_DPHY_RG_CDTX_L0P_HSTX_RES, 0x10),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(8));
writel(FIELD_PREP(STF_DPHY_RG_CDTX_L0N_HSTX_RES, 0x10) |
FIELD_PREP(STF_DPHY_RG_CDTX_L2N_HSTX_RES, 0x10) |
FIELD_PREP(STF_DPHY_RG_CDTX_L3N_HSTX_RES, 0x10) |
FIELD_PREP(STF_DPHY_RG_CDTX_L1P_HSTX_RES, 0x10) |
FIELD_PREP(STF_DPHY_RG_CDTX_L2P_HSTX_RES, 0x10) |
FIELD_PREP(STF_DPHY_RG_CDTX_L3P_HSTX_RES, 0x10),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(12));
writel(FIELD_PREP(STF_DPHY_RG_CDTX_L4N_HSTX_RES, 0x10) |
FIELD_PREP(STF_DPHY_RG_CDTX_L4P_HSTX_RES, 0x10),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(16));
/* Lane setting */
writel(FIELD_PREP(STF_DPHY_AON_POWER_READY_N,
STF_DPHY_AON_POWER_READY_N_ACTIVE) |
FIELD_PREP(STF_DPHY_CFG_L0_SWAP_SEL, info->maps[0]) |
FIELD_PREP(STF_DPHY_CFG_L1_SWAP_SEL, info->maps[1]) |
FIELD_PREP(STF_DPHY_CFG_L2_SWAP_SEL, info->maps[2]) |
FIELD_PREP(STF_DPHY_CFG_L3_SWAP_SEL, info->maps[3]) |
FIELD_PREP(STF_DPHY_CFG_L4_SWAP_SEL, info->maps[4]),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(0));
/* PLL setting */
writel(FIELD_PREP(STF_DPHY_RG_CDTX_PLL_SSC_EN, 0x0),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(28));
writel(FIELD_PREP(STF_DPHY_RG_CDTX_PLL_LDO_STB_X2_EN, 0x1) |
FIELD_PREP(STF_DPHY_RG_CDTX_PLL_FM_EN, 0x1) |
FIELD_PREP(STF_DPHY_RG_CDTX_PLL_PRE_DIV, 0x0) |
FIELD_PREP(STF_DPHY_RG_CDTX_PLL_FBK_INT, p[i].pll_fbk_int),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(24));
writel(FIELD_PREP(STF_DPHY_RG_CDTX_PLL_FBK_FRA,
STF_DPHY_LSHIFT_16(p[i].pll_fbk_fra_val) |
STF_DPHY_LSHIFT_8(p[i].pll_fbk_fra_val) |
p[i].pll_fbk_fra_val),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(20));
writel(FIELD_PREP(STF_DPHY_RG_EXTD_CYCLE_SEL, p[i].extd_cycle_sel),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(40));
writel(FIELD_PREP(STF_DPHY_RG_DLANE_HS_PRE_TIME, p[i].dlane_hs_pre_time) |
FIELD_PREP(STF_DPHY_RG_DLANE_HS_ZERO_TIME, p[i].dlane_hs_zero_time) |
FIELD_PREP(STF_DPHY_RG_DLANE_HS_TRAIL_TIME, p[i].dlane_hs_trail_time) |
FIELD_PREP(STF_DPHY_RG_CLANE_HS_ZERO_TIME, p[i].clane_hs_zero_time),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(36));
writel(FIELD_PREP(STF_DPHY_RG_CLANE_HS_PRE_TIME, p[i].clane_hs_pre_time) |
FIELD_PREP(STF_DPHY_RG_CLANE_HS_TRAIL_TIME, p[i].clane_hs_trail_time) |
FIELD_PREP(STF_DPHY_RG_CLANE_HS_CLK_PRE_TIME, p[i].clane_hs_clk_pre_time) |
FIELD_PREP(STF_DPHY_RG_CLANE_HS_CLK_POST_TIME, p[i].clane_hs_clk_post_time),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(32));
return 0;
}
static int stf_dphy_init(struct phy *phy)
{
struct stf_dphy *dphy = phy_get_drvdata(phy);
int ret;
stf_dphy_hw_reset(dphy, 1);
writel(FIELD_PREP(STF_DPHY_SCFG_PPI_C_READY_SEL, 0) |
FIELD_PREP(STF_DPHY_SCFG_DSI_TXREADY_ESC_SEL, 0),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(48));
writel(FIELD_PREP(STF_DPHY_SCFG_C_HS_PRE_ZERO_TIME, 0x30),
dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(44));
ret = clk_prepare_enable(dphy->txesc_clk);
if (ret) {
dev_err(dphy->dev, "Failed to prepare/enable txesc_clk\n");
return ret;
}
ret = reset_control_deassert(dphy->sys_rst);
if (ret) {
dev_err(dphy->dev, "Failed to deassert sys_rst\n");
return ret;
}
return 0;
}
static int stf_dphy_exit(struct phy *phy)
{
struct stf_dphy *dphy = phy_get_drvdata(phy);
int ret;
ret = reset_control_assert(dphy->sys_rst);
if (ret) {
dev_err(dphy->dev, "Failed to assert sys_rst\n");
return ret;
}
clk_disable_unprepare(dphy->txesc_clk);
stf_dphy_hw_reset(dphy, 0);
return 0;
}
static int stf_dphy_power_on(struct phy *phy)
{
struct stf_dphy *dphy = phy_get_drvdata(phy);
return pm_runtime_resume_and_get(dphy->dev);
}
static int stf_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
union phy_configure_opts *opts)
{
if (mode != PHY_MODE_MIPI_DPHY)
return -EINVAL;
return 0;
}
static int stf_dphy_power_off(struct phy *phy)
{
struct stf_dphy *dphy = phy_get_drvdata(phy);
return pm_runtime_put_sync(dphy->dev);
}
static const struct phy_ops stf_dphy_ops = {
.power_on = stf_dphy_power_on,
.power_off = stf_dphy_power_off,
.init = stf_dphy_init,
.exit = stf_dphy_exit,
.configure = stf_dphy_configure,
.validate = stf_dphy_validate,
.owner = THIS_MODULE,
};
static int stf_dphy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct stf_dphy *dphy;
dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
if (!dphy)
return -ENOMEM;
dphy->info = of_device_get_match_data(&pdev->dev);
dphy->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, dphy);
dphy->topsys = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dphy->topsys))
return PTR_ERR(dphy->topsys);
pm_runtime_enable(&pdev->dev);
dphy->txesc_clk = devm_clk_get(&pdev->dev, "txesc");
if (IS_ERR(dphy->txesc_clk))
return dev_err_probe(&pdev->dev, PTR_ERR(dphy->txesc_clk),
"Failed to get txesc clock\n");
dphy->sys_rst = devm_reset_control_get_exclusive(&pdev->dev, "sys");
if (IS_ERR(dphy->sys_rst))
return dev_err_probe(&pdev->dev, PTR_ERR(dphy->sys_rst),
"Failed to get sys reset\n");
dphy->phy = devm_phy_create(&pdev->dev, NULL, &stf_dphy_ops);
if (IS_ERR(dphy->phy))
return dev_err_probe(&pdev->dev, PTR_ERR(dphy->phy),
"Failed to create phy\n");
phy_set_drvdata(dphy->phy, dphy);
phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return dev_err_probe(&pdev->dev, PTR_ERR(phy_provider),
"Failed to register phy\n");
return 0;
}
static const struct stf_dphy_info starfive_dphy_info = {
.maps = {0, 1, 2, 3, 4},
};
static const struct of_device_id stf_dphy_dt_ids[] = {
{
.compatible = "starfive,jh7110-dphy-tx",
.data = &starfive_dphy_info,
},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, stf_dphy_dt_ids);
static struct platform_driver stf_dphy_driver = {
.driver = {
.name = "starfive-dphy-tx",
.of_match_table = stf_dphy_dt_ids,
},
.probe = stf_dphy_probe,
};
module_platform_driver(stf_dphy_driver);
MODULE_AUTHOR("Keith Zhao <keith.zhao@starfivetech.com>");
MODULE_AUTHOR("Shengyang Chen <shengyang.chen@starfivetech.com>");
MODULE_DESCRIPTION("StarFive JH7110 DPHY TX driver");
MODULE_LICENSE("GPL");

View File

@ -30,7 +30,6 @@
#define LANE_R058 0x258
#define LANE_R06c 0x26c
#define LANE_R070 0x270
#define LANE_R070 0x270
#define LANE_R19C 0x39c
#define COMLANE_R004 0xa04

View File

@ -1076,27 +1076,12 @@ static int wiz_clock_register(struct wiz *wiz)
return ret;
}
static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
static void wiz_clock_init(struct wiz *wiz)
{
const struct wiz_clk_mux_sel *clk_mux_sel = wiz->clk_mux_sel;
struct device *dev = wiz->dev;
struct device_node *clk_node;
const char *node_name;
unsigned long rate;
struct clk *clk;
int ret;
int i;
clk = devm_clk_get(dev, "core_ref_clk");
if (IS_ERR(clk)) {
dev_err(dev, "core_ref_clk clock not found\n");
ret = PTR_ERR(clk);
return ret;
}
wiz->input_clks[WIZ_CORE_REFCLK] = clk;
rate = clk_get_rate(clk);
if (rate >= 100000000)
rate = clk_get_rate(wiz->input_clks[WIZ_CORE_REFCLK]);
if (rate >= REF_CLK_100MHZ)
regmap_field_write(wiz->pma_cmn_refclk_int_mode, 0x1);
else
regmap_field_write(wiz->pma_cmn_refclk_int_mode, 0x3);
@ -1120,35 +1105,55 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
break;
}
if (wiz->data->pma_cmn_refclk1_int_mode) {
clk = devm_clk_get(dev, "core_ref1_clk");
if (IS_ERR(clk)) {
dev_err(dev, "core_ref1_clk clock not found\n");
ret = PTR_ERR(clk);
return ret;
}
wiz->input_clks[WIZ_CORE_REFCLK1] = clk;
rate = clk_get_rate(clk);
if (rate >= 100000000)
if (wiz->input_clks[WIZ_CORE_REFCLK1]) {
rate = clk_get_rate(wiz->input_clks[WIZ_CORE_REFCLK1]);
if (rate >= REF_CLK_100MHZ)
regmap_field_write(wiz->pma_cmn_refclk1_int_mode, 0x1);
else
regmap_field_write(wiz->pma_cmn_refclk1_int_mode, 0x3);
}
clk = devm_clk_get(dev, "ext_ref_clk");
if (IS_ERR(clk)) {
dev_err(dev, "ext_ref_clk clock not found\n");
ret = PTR_ERR(clk);
return ret;
}
wiz->input_clks[WIZ_EXT_REFCLK] = clk;
rate = clk_get_rate(clk);
if (rate >= 100000000)
rate = clk_get_rate(wiz->input_clks[WIZ_EXT_REFCLK]);
if (rate >= REF_CLK_100MHZ)
regmap_field_write(wiz->pma_cmn_refclk_mode, 0x0);
else
regmap_field_write(wiz->pma_cmn_refclk_mode, 0x2);
}
static int wiz_clock_probe(struct wiz *wiz, struct device_node *node)
{
const struct wiz_clk_mux_sel *clk_mux_sel = wiz->clk_mux_sel;
struct device *dev = wiz->dev;
struct device_node *clk_node;
const char *node_name;
struct clk *clk;
int ret;
int i;
clk = devm_clk_get(dev, "core_ref_clk");
if (IS_ERR(clk))
return dev_err_probe(dev, PTR_ERR(clk),
"core_ref_clk clock not found\n");
wiz->input_clks[WIZ_CORE_REFCLK] = clk;
if (wiz->data->pma_cmn_refclk1_int_mode) {
clk = devm_clk_get(dev, "core_ref1_clk");
if (IS_ERR(clk))
return dev_err_probe(dev, PTR_ERR(clk),
"core_ref1_clk clock not found\n");
wiz->input_clks[WIZ_CORE_REFCLK1] = clk;
}
clk = devm_clk_get(dev, "ext_ref_clk");
if (IS_ERR(clk))
return dev_err_probe(dev, PTR_ERR(clk),
"ext_ref_clk clock not found\n");
wiz->input_clks[WIZ_EXT_REFCLK] = clk;
wiz_clock_init(wiz);
switch (wiz->type) {
case AM64_WIZ_10G:
@ -1157,8 +1162,9 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
case J721S2_WIZ_10G:
ret = wiz_clock_register(wiz);
if (ret)
dev_err(dev, "Failed to register wiz clocks\n");
return ret;
return dev_err_probe(dev, ret, "Failed to register wiz clocks\n");
return 0;
default:
break;
}
@ -1167,16 +1173,15 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
node_name = clk_mux_sel[i].node_name;
clk_node = of_get_child_by_name(node, node_name);
if (!clk_node) {
dev_err(dev, "Unable to get %s node\n", node_name);
ret = -EINVAL;
ret = dev_err_probe(dev, -EINVAL, "Unable to get %s node\n", node_name);
goto err;
}
ret = wiz_mux_of_clk_register(wiz, clk_node, wiz->mux_sel_field[i],
clk_mux_sel[i].table);
if (ret) {
dev_err(dev, "Failed to register %s clock\n",
node_name);
dev_err_probe(dev, ret, "Failed to register %s clock\n",
node_name);
of_node_put(clk_node);
goto err;
}
@ -1188,16 +1193,15 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
node_name = clk_div_sel[i].node_name;
clk_node = of_get_child_by_name(node, node_name);
if (!clk_node) {
dev_err(dev, "Unable to get %s node\n", node_name);
ret = -EINVAL;
ret = dev_err_probe(dev, -EINVAL, "Unable to get %s node\n", node_name);
goto err;
}
ret = wiz_div_clk_register(wiz, clk_node, wiz->div_sel_field[i],
clk_div_sel[i].table);
if (ret) {
dev_err(dev, "Failed to register %s clock\n",
node_name);
dev_err_probe(dev, ret, "Failed to register %s clock\n",
node_name);
of_node_put(clk_node);
goto err;
}
@ -1593,7 +1597,7 @@ static int wiz_probe(struct platform_device *pdev)
goto err_get_sync;
}
ret = wiz_clock_init(wiz, node);
ret = wiz_clock_probe(wiz, node);
if (ret < 0) {
dev_warn(dev, "Failed to initialize clocks\n");
goto err_get_sync;
@ -1655,12 +1659,41 @@ static void wiz_remove(struct platform_device *pdev)
pm_runtime_disable(dev);
}
static int wiz_resume_noirq(struct device *dev)
{
struct device_node *node = dev->of_node;
struct wiz *wiz = dev_get_drvdata(dev);
int ret;
/* Enable supplemental Control override if available */
if (wiz->sup_legacy_clk_override)
regmap_field_write(wiz->sup_legacy_clk_override, 1);
wiz_clock_init(wiz);
ret = wiz_init(wiz);
if (ret) {
dev_err(dev, "WIZ initialization failed\n");
goto err_wiz_init;
}
return 0;
err_wiz_init:
wiz_clock_cleanup(wiz, node);
return ret;
}
static DEFINE_NOIRQ_DEV_PM_OPS(wiz_pm_ops, NULL, wiz_resume_noirq);
static struct platform_driver wiz_driver = {
.probe = wiz_probe,
.remove_new = wiz_remove,
.driver = {
.name = "wiz",
.of_match_table = wiz_id_table,
.pm = pm_sleep_ptr(&wiz_pm_ops),
},
};
module_platform_driver(wiz_driver);

View File

@ -13,6 +13,7 @@
*/
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
@ -80,7 +81,8 @@
/* Reference clock selection parameters */
#define L0_Ln_REF_CLK_SEL(n) (0x2860 + (n) * 4)
#define L0_REF_CLK_SEL_MASK 0x8f
#define L0_REF_CLK_LCL_SEL BIT(7)
#define L0_REF_CLK_SEL_MASK 0x9f
/* Calibration digital logic parameters */
#define L3_TM_CALIB_DIG19 0xec4c
@ -122,6 +124,15 @@
#define ICM_PROTOCOL_DP 0x4
#define ICM_PROTOCOL_SGMII 0x5
static const char *const xpsgtr_icm_str[] = {
[ICM_PROTOCOL_PD] = "none",
[ICM_PROTOCOL_PCIE] = "PCIe",
[ICM_PROTOCOL_SATA] = "SATA",
[ICM_PROTOCOL_USB] = "USB",
[ICM_PROTOCOL_DP] = "DisplayPort",
[ICM_PROTOCOL_SGMII] = "SGMII",
};
/* Test Mode common reset control parameters */
#define TM_CMN_RST 0x10018
#define TM_CMN_RST_EN 0x1
@ -146,22 +157,6 @@
/* Total number of controllers */
#define CONTROLLERS_PER_LANE 5
/* Protocol Type parameters */
#define XPSGTR_TYPE_USB0 0 /* USB controller 0 */
#define XPSGTR_TYPE_USB1 1 /* USB controller 1 */
#define XPSGTR_TYPE_SATA_0 2 /* SATA controller lane 0 */
#define XPSGTR_TYPE_SATA_1 3 /* SATA controller lane 1 */
#define XPSGTR_TYPE_PCIE_0 4 /* PCIe controller lane 0 */
#define XPSGTR_TYPE_PCIE_1 5 /* PCIe controller lane 1 */
#define XPSGTR_TYPE_PCIE_2 6 /* PCIe controller lane 2 */
#define XPSGTR_TYPE_PCIE_3 7 /* PCIe controller lane 3 */
#define XPSGTR_TYPE_DP_0 8 /* Display Port controller lane 0 */
#define XPSGTR_TYPE_DP_1 9 /* Display Port controller lane 1 */
#define XPSGTR_TYPE_SGMII0 10 /* Ethernet SGMII controller 0 */
#define XPSGTR_TYPE_SGMII1 11 /* Ethernet SGMII controller 1 */
#define XPSGTR_TYPE_SGMII2 12 /* Ethernet SGMII controller 2 */
#define XPSGTR_TYPE_SGMII3 13 /* Ethernet SGMII controller 3 */
/* Timeout values */
#define TIMEOUT_US 1000
@ -184,7 +179,8 @@ struct xpsgtr_ssc {
/**
* struct xpsgtr_phy - representation of a lane
* @phy: pointer to the kernel PHY device
* @type: controller which uses this lane
* @instance: instance of the protocol type (such as the lane within a
* protocol, or the USB/Ethernet controller)
* @lane: lane number
* @protocol: protocol in which the lane operates
* @skip_phy_init: skip phy_init() if true
@ -193,7 +189,7 @@ struct xpsgtr_ssc {
*/
struct xpsgtr_phy {
struct phy *phy;
u8 type;
u8 instance;
u8 lane;
u8 protocol;
bool skip_phy_init;
@ -308,10 +304,30 @@ static int xpsgtr_wait_pll_lock(struct phy *phy)
struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
unsigned int timeout = TIMEOUT_US;
u8 protocol = gtr_phy->protocol;
int ret;
dev_dbg(gtr_dev->dev, "Waiting for PLL lock\n");
/*
* For DP and PCIe, only the instance 0 PLL is used. Switch to that phy
* so we wait on the right PLL.
*/
if ((protocol == ICM_PROTOCOL_DP || protocol == ICM_PROTOCOL_PCIE) &&
gtr_phy->instance) {
int i;
for (i = 0; i < NUM_LANES; i++) {
gtr_phy = &gtr_dev->phys[i];
if (gtr_phy->protocol == protocol && !gtr_phy->instance)
goto got_phy;
}
return -EBUSY;
}
got_phy:
while (1) {
u32 reg = xpsgtr_read_phy(gtr_phy, L0_PLL_STATUS_READ_1);
@ -330,8 +346,8 @@ static int xpsgtr_wait_pll_lock(struct phy *phy)
if (ret == -ETIMEDOUT)
dev_err(gtr_dev->dev,
"lane %u (type %u, protocol %u): PLL lock timeout\n",
gtr_phy->lane, gtr_phy->type, gtr_phy->protocol);
"lane %u (protocol %u, instance %u): PLL lock timeout\n",
gtr_phy->lane, gtr_phy->protocol, gtr_phy->instance);
return ret;
}
@ -349,11 +365,12 @@ static void xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)
PLL_FREQ_MASK, ssc->pll_ref_clk);
/* Enable lane clock sharing, if required */
if (gtr_phy->refclk != gtr_phy->lane) {
/* Lane3 Ref Clock Selection Register */
if (gtr_phy->refclk == gtr_phy->lane)
xpsgtr_clr_set(gtr_phy->dev, L0_Ln_REF_CLK_SEL(gtr_phy->lane),
L0_REF_CLK_SEL_MASK, L0_REF_CLK_LCL_SEL);
else
xpsgtr_clr_set(gtr_phy->dev, L0_Ln_REF_CLK_SEL(gtr_phy->lane),
L0_REF_CLK_SEL_MASK, 1 << gtr_phy->refclk);
}
/* SSC step size [7:0] */
xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEP_SIZE_0_LSB,
@ -573,7 +590,7 @@ static int xpsgtr_phy_init(struct phy *phy)
mutex_lock(&gtr_dev->gtr_mutex);
/* Configure and enable the clock when peripheral phy_init call */
if (clk_prepare_enable(gtr_dev->clk[gtr_phy->lane]))
if (clk_prepare_enable(gtr_dev->clk[gtr_phy->refclk]))
goto out;
/* Skip initialization if not required. */
@ -625,7 +642,7 @@ static int xpsgtr_phy_exit(struct phy *phy)
gtr_phy->skip_phy_init = false;
/* Ensure that disable clock only, which configure for lane */
clk_disable_unprepare(gtr_dev->clk[gtr_phy->lane]);
clk_disable_unprepare(gtr_dev->clk[gtr_phy->refclk]);
return 0;
}
@ -638,16 +655,7 @@ static int xpsgtr_phy_power_on(struct phy *phy)
/* Skip initialization if not required. */
if (!xpsgtr_phy_init_required(gtr_phy))
return ret;
/*
* Wait for the PLL to lock. For DP, only wait on DP0 to avoid
* cumulating waits for both lanes. The user is expected to initialize
* lane 0 last.
*/
if (gtr_phy->protocol != ICM_PROTOCOL_DP ||
gtr_phy->type == XPSGTR_TYPE_DP_0)
ret = xpsgtr_wait_pll_lock(phy);
return ret;
return xpsgtr_wait_pll_lock(phy);
}
static int xpsgtr_phy_configure(struct phy *phy, union phy_configure_opts *opts)
@ -674,73 +682,33 @@ static const struct phy_ops xpsgtr_phyops = {
* OF Xlate Support
*/
/* Set the lane type and protocol based on the PHY type and instance number. */
/* Set the lane protocol and instance based on the PHY type and instance number. */
static int xpsgtr_set_lane_type(struct xpsgtr_phy *gtr_phy, u8 phy_type,
unsigned int phy_instance)
{
unsigned int num_phy_types;
const int *phy_types;
switch (phy_type) {
case PHY_TYPE_SATA: {
static const int types[] = {
XPSGTR_TYPE_SATA_0,
XPSGTR_TYPE_SATA_1,
};
phy_types = types;
num_phy_types = ARRAY_SIZE(types);
case PHY_TYPE_SATA:
num_phy_types = 2;
gtr_phy->protocol = ICM_PROTOCOL_SATA;
break;
}
case PHY_TYPE_USB3: {
static const int types[] = {
XPSGTR_TYPE_USB0,
XPSGTR_TYPE_USB1,
};
phy_types = types;
num_phy_types = ARRAY_SIZE(types);
case PHY_TYPE_USB3:
num_phy_types = 2;
gtr_phy->protocol = ICM_PROTOCOL_USB;
break;
}
case PHY_TYPE_DP: {
static const int types[] = {
XPSGTR_TYPE_DP_0,
XPSGTR_TYPE_DP_1,
};
phy_types = types;
num_phy_types = ARRAY_SIZE(types);
case PHY_TYPE_DP:
num_phy_types = 2;
gtr_phy->protocol = ICM_PROTOCOL_DP;
break;
}
case PHY_TYPE_PCIE: {
static const int types[] = {
XPSGTR_TYPE_PCIE_0,
XPSGTR_TYPE_PCIE_1,
XPSGTR_TYPE_PCIE_2,
XPSGTR_TYPE_PCIE_3,
};
phy_types = types;
num_phy_types = ARRAY_SIZE(types);
case PHY_TYPE_PCIE:
num_phy_types = 4;
gtr_phy->protocol = ICM_PROTOCOL_PCIE;
break;
}
case PHY_TYPE_SGMII: {
static const int types[] = {
XPSGTR_TYPE_SGMII0,
XPSGTR_TYPE_SGMII1,
XPSGTR_TYPE_SGMII2,
XPSGTR_TYPE_SGMII3,
};
phy_types = types;
num_phy_types = ARRAY_SIZE(types);
case PHY_TYPE_SGMII:
num_phy_types = 4;
gtr_phy->protocol = ICM_PROTOCOL_SGMII;
break;
}
default:
return -EINVAL;
}
@ -748,22 +716,25 @@ static int xpsgtr_set_lane_type(struct xpsgtr_phy *gtr_phy, u8 phy_type,
if (phy_instance >= num_phy_types)
return -EINVAL;
gtr_phy->type = phy_types[phy_instance];
gtr_phy->instance = phy_instance;
return 0;
}
/*
* Valid combinations of controllers and lanes (Interconnect Matrix).
* Valid combinations of controllers and lanes (Interconnect Matrix). Each
* "instance" represents one controller for a lane. For PCIe and DP, the
* "instance" is the logical lane in the link. For SATA, USB, and SGMII,
* the instance is the index of the controller.
*
* This information is only used to validate the devicetree reference, and is
* not used when programming the hardware.
*/
static const unsigned int icm_matrix[NUM_LANES][CONTROLLERS_PER_LANE] = {
{ XPSGTR_TYPE_PCIE_0, XPSGTR_TYPE_SATA_0, XPSGTR_TYPE_USB0,
XPSGTR_TYPE_DP_1, XPSGTR_TYPE_SGMII0 },
{ XPSGTR_TYPE_PCIE_1, XPSGTR_TYPE_SATA_1, XPSGTR_TYPE_USB0,
XPSGTR_TYPE_DP_0, XPSGTR_TYPE_SGMII1 },
{ XPSGTR_TYPE_PCIE_2, XPSGTR_TYPE_SATA_0, XPSGTR_TYPE_USB0,
XPSGTR_TYPE_DP_1, XPSGTR_TYPE_SGMII2 },
{ XPSGTR_TYPE_PCIE_3, XPSGTR_TYPE_SATA_1, XPSGTR_TYPE_USB1,
XPSGTR_TYPE_DP_0, XPSGTR_TYPE_SGMII3 }
/* PCIe, SATA, USB, DP, SGMII */
{ 0, 0, 0, 1, 0 }, /* Lane 0 */
{ 1, 1, 0, 0, 1 }, /* Lane 1 */
{ 2, 0, 0, 1, 2 }, /* Lane 2 */
{ 3, 1, 1, 0, 3 }, /* Lane 3 */
};
/* Translate OF phandle and args to PHY instance. */
@ -798,6 +769,7 @@ static struct phy *xpsgtr_xlate(struct device *dev,
phy_type = args->args[1];
phy_instance = args->args[2];
guard(mutex)(&gtr_phy->phy->mutex);
ret = xpsgtr_set_lane_type(gtr_phy, phy_type, phy_instance);
if (ret < 0) {
dev_err(gtr_dev->dev, "Invalid PHY type and/or instance\n");
@ -818,13 +790,41 @@ static struct phy *xpsgtr_xlate(struct device *dev,
* is allowed to operate on the lane.
*/
for (i = 0; i < CONTROLLERS_PER_LANE; i++) {
if (icm_matrix[phy_lane][i] == gtr_phy->type)
if (icm_matrix[phy_lane][i] == gtr_phy->instance)
return gtr_phy->phy;
}
return ERR_PTR(-EINVAL);
}
/*
* DebugFS
*/
static int xpsgtr_status_read(struct seq_file *seq, void *data)
{
struct device *dev = seq->private;
struct xpsgtr_phy *gtr_phy = dev_get_drvdata(dev);
struct clk *clk;
u32 pll_status;
mutex_lock(&gtr_phy->phy->mutex);
pll_status = xpsgtr_read_phy(gtr_phy, L0_PLL_STATUS_READ_1);
clk = gtr_phy->dev->clk[gtr_phy->refclk];
seq_printf(seq, "Lane: %u\n", gtr_phy->lane);
seq_printf(seq, "Protocol: %s\n",
xpsgtr_icm_str[gtr_phy->protocol]);
seq_printf(seq, "Instance: %u\n", gtr_phy->instance);
seq_printf(seq, "Reference clock: %u (%pC)\n", gtr_phy->refclk, clk);
seq_printf(seq, "Reference rate: %lu\n", clk_get_rate(clk));
seq_printf(seq, "PLL locked: %s\n",
pll_status & PLL_STATUS_LOCKED ? "yes" : "no");
mutex_unlock(&gtr_phy->phy->mutex);
return 0;
}
/*
* Power Management
*/
@ -974,6 +974,8 @@ static int xpsgtr_probe(struct platform_device *pdev)
gtr_phy->phy = phy;
phy_set_drvdata(phy, gtr_phy);
debugfs_create_devm_seqfile(&phy->dev, "status", phy->debugfs,
xpsgtr_status_read);
}
/* Register the PHY provider. */

View File

@ -660,5 +660,7 @@
/* For Tensor GS101 */
#define GS101_SYSIP_DAT0 (0x810)
#define GS101_SYSTEM_CONFIGURATION (0x3A00)
#define GS101_PHY_CTRL_USB20 (0x3EB0)
#define GS101_PHY_CTRL_USBDP (0x3EB4)
#endif /* __LINUX_SOC_EXYNOS_REGS_PMU_H */