mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
phy-for-6.10
- New Support - Support for Embedded DisplayPort and DisplayPort submodes and driver support on Qualcomm X1E80100 edp driver - Qualcomm QMP UFS PHY for SM8475, QMP USB phy for QDU1000/QRU1000 and eusb2-repeater for SMB2360 - Samsung HDMI PHY for i.MX8MP, gs101 UFS phy - Mediatek XFI T-PHY support for mt7988 - Rockchip usbdp combo phy driver - Updates - Qualcomm x4 lane EP support for sa8775p, v4 ad v6 support for X1E80100, SM8650 tables for UFS Gear 4 & 5 and correct voltage swing tables - Freescale imx8m-pci pcie link-up updates - Rockchip rx-common-refclk-mode support - More platform remove callback returning void conversions -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmZMSswACgkQfBQHDyUj g0cFBQ//ZJIbYXFfCqiC0jfpqAtO6f3yxScNvn7xOXTHqe2ErzAiG08Sj/fdKwFT UCMY8jSm+AQq7VQYUqGqJypRIBgdKrWXtBTemT5Xa5VeB5cgVoFpNv5U+1rL7MS7 IK3U5jKIYXUBh7z2gmZr4ftrIEXJXgNhJn4Ntelh5mQYL/QZBcCoIfteJIe6pDCv /mbLT4jAaju2/b4P7/Q96JsMeOXW0ewBuveM/mmFZgqDNDB0nBvHvh+Cn2RHRzR0 /xXEZ1L4TXAQ5txtv0dIPdQp8vnM7OQj6xY256Os19bhxr+zcRgl7aRDvJdgJgrA np6H14hh5H/XiAFJqg8ZTTaGFhnyUDI9bndMUxj5Zku+lmwLGleu8tfiR0kS7v1l exgHsTMYNkgwDQ8KmU0z+hDTDCM0nVnpI/GcKruc79e0ZuEh28N1S9d8CGAYx1Of vmfF9A6hhzSDY6RvyQT4vvm+JLhesuox1CxE9IDMIeIiydyR4ZLlGBvv6Opk1E9U v0FtMnF9HGv6SiGTBsA5VB94o9Z91Ad3G2sMwkTZTjR8KgM9pcO9hlHF+Cec8ua0 y4mcxDrcuzUNvZ9qzwCUTyxuv0600tAlsaebAeAI7LQAMFeompOzhqdr7Jc2MGiQ 10nnB86pOdxh16migt65aL7zglqHo0T8zpvMBOJqNeW/D32fJG8= =og1j -----END PGP SIGNATURE----- Merge tag 'phy-for-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy Pull generic phy updates from Vinod Koul: "New HW Support: - Support for Embedded DisplayPort and DisplayPort submodes and driver support on Qualcomm X1E80100 edp driver - Qualcomm QMP UFS PHY for SM8475, QMP USB phy for QDU1000/QRU1000 and eusb2-repeater for SMB2360 - Samsung HDMI PHY for i.MX8MP, gs101 UFS phy - Mediatek XFI T-PHY support for mt7988 - Rockchip usbdp combo phy driver Updates: - Qualcomm x4 lane EP support for sa8775p, v4 ad v6 support for X1E80100, SM8650 tables for UFS Gear 4 & 5 and correct voltage swing tables - Freescale imx8m-pci pcie link-up updates - Rockchip rx-common-refclk-mode support - More platform remove callback returning void conversions" * tag 'phy-for-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (43 commits) dt-bindings: phy: qcom,usb-snps-femto-v2: use correct fallback for sc8180x dt-bindings: phy: qcom,sc8280xp-qmp-ufs-phy: fix msm899[68] power-domains dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: fix x1e80100-gen3x2 schema phy: qcpm-qmp-usb: Add support for QDU1000/QRU1000 dt-bindings: phy: qcom,qmp-usb: Add QDU1000 USB3 PHY dt-bindings: phy: qcom,usb-snps-femto-v2: Add bindings for QDU1000 phy: qcom-qmp-pcie: add x4 lane EP support for sa8775p phy: samsung-ufs: ufs: exit on first reported error phy: samsung-ufs: ufs: remove superfluous mfd/syscon.h header phy: rockchip: fix CONFIG_TYPEC dependency phy: rockchip: usbdp: fix uninitialized variable phy: rockchip-snps-pcie3: add support for rockchip,rx-common-refclk-mode dt-bindings: phy: rockchip,pcie3-phy: add rockchip,rx-common-refclk-mode phy: rockchip: add usbdp combo phy driver dt-bindings: phy: add rockchip usbdp combo phy document phy: add driver for MediaTek XFI T-PHY dt-bindings: phy: mediatek,mt7988-xfi-tphy: add new bindings phy: freescale: fsl-samsung-hdmi: Convert to platform remove callback returning void phy: qcom: qmp-ufs: update SM8650 tables for Gear 4 & 5 MAINTAINERS: Add phy-gs101-ufs file to Tensor GS101. ...
This commit is contained in:
commit
8053d2ffc4
@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/fsl,imx8mp-hdmi-phy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8MP HDMI PHY
|
||||
|
||||
maintainers:
|
||||
- Lucas Stach <l.stach@pengutronix.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx8mp-hdmi-phy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: apb
|
||||
- const: ref
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#clock-cells"
|
||||
- clocks
|
||||
- clock-names
|
||||
- "#phy-cells"
|
||||
- power-domains
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8mp-clock.h>
|
||||
#include <dt-bindings/power/imx8mp-power.h>
|
||||
|
||||
phy@32fdff00 {
|
||||
compatible = "fsl,imx8mp-hdmi-phy";
|
||||
reg = <0x32fdff00 0x100>;
|
||||
clocks = <&clk IMX8MP_CLK_HDMI_APB>,
|
||||
<&clk IMX8MP_CLK_HDMI_24M>;
|
||||
clock-names = "apb", "ref";
|
||||
power-domains = <&hdmi_blk_ctrl IMX8MP_HDMIBLK_PD_HDMI_TX_PHY>;
|
||||
#clock-cells = <0>;
|
||||
#phy-cells = <0>;
|
||||
};
|
@ -0,0 +1,80 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/mediatek,mt7988-xfi-tphy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT7988 XFI T-PHY
|
||||
|
||||
maintainers:
|
||||
- Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
description:
|
||||
The MediaTek XFI SerDes T-PHY provides the physical SerDes lanes
|
||||
used by the (10G/5G) USXGMII PCS and (1G/2.5G) LynxI PCS found in
|
||||
MediaTek's 10G-capabale MT7988 SoC.
|
||||
In MediaTek's SDK sources, this unit is referred to as "pextp".
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt7988-xfi-tphy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: XFI PHY clock
|
||||
- description: XFI register clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: xfipll
|
||||
- const: topxtal
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: Reset controller corresponding to the phy instance.
|
||||
|
||||
mediatek,usxgmii-performance-errata:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
One instance of the T-PHY on MT7988 suffers from a performance
|
||||
problem in 10GBase-R mode which needs a work-around in the driver.
|
||||
This flag enables a work-around ajusting an analog phy setting and
|
||||
is required for XFI Port0 of the MT7988 SoC to be in compliance with
|
||||
the SFP specification.
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/mediatek,mt7988-clk.h>
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
phy@11f20000 {
|
||||
compatible = "mediatek,mt7988-xfi-tphy";
|
||||
reg = <0 0x11f20000 0 0x10000>;
|
||||
clocks = <&xfi_pll CLK_XFIPLL_PLL_EN>,
|
||||
<&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>;
|
||||
clock-names = "xfipll", "topxtal";
|
||||
resets = <&watchdog 14>;
|
||||
mediatek,usxgmii-performance-errata;
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
148
Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
Normal file
148
Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
Normal file
@ -0,0 +1,148 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/phy-rockchip-usbdp.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rockchip USBDP Combo PHY with Samsung IP block
|
||||
|
||||
maintainers:
|
||||
- Frank Wang <frank.wang@rock-chips.com>
|
||||
- Zhang Yubing <yubing.zhang@rock-chips.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- rockchip,rk3588-usbdp-phy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#phy-cells":
|
||||
description: |
|
||||
Cell allows setting the type of the PHY. Possible values are:
|
||||
- PHY_TYPE_USB3
|
||||
- PHY_TYPE_DP
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: refclk
|
||||
- const: immortal
|
||||
- const: pclk
|
||||
- const: utmi
|
||||
|
||||
resets:
|
||||
maxItems: 5
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: init
|
||||
- const: cmn
|
||||
- const: lane
|
||||
- const: pcs_apb
|
||||
- const: pma_apb
|
||||
|
||||
rockchip,dp-lane-mux:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
items:
|
||||
maximum: 3
|
||||
description:
|
||||
An array of physical Type-C lanes indexes. Position of an entry
|
||||
determines the DisplayPort (DP) lane index, while the value of an entry
|
||||
indicates physical Type-C lane. The supported DP lanes number are 2 or 4.
|
||||
e.g. for 2 lanes DP lanes map, we could have "rockchip,dp-lane-mux = <2,
|
||||
3>;", assuming DP lane0 on Type-C phy lane2, DP lane1 on Type-C phy
|
||||
lane3. For 4 lanes DP lanes map, we could have "rockchip,dp-lane-mux =
|
||||
<0, 1, 2, 3>;", assuming DP lane0 on Type-C phy lane0, DP lane1 on Type-C
|
||||
phy lane1, DP lane2 on Type-C phy lane2, DP lane3 on Type-C phy lane3. If
|
||||
DP lanes are mapped by DisplayPort Alt mode, this property is not needed.
|
||||
|
||||
rockchip,u2phy-grf:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to the syscon managing the 'usb2 phy general register files'.
|
||||
|
||||
rockchip,usb-grf:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to the syscon managing the 'usb general register files'.
|
||||
|
||||
rockchip,usbdpphy-grf:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to the syscon managing the 'usbdp phy general register files'.
|
||||
|
||||
rockchip,vo-grf:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to the syscon managing the 'video output general register files'.
|
||||
When select the DP lane mapping will request its phandle.
|
||||
|
||||
sbu1-dc-gpios:
|
||||
description:
|
||||
GPIO connected to the SBU1 line of the USB-C connector via a big resistor
|
||||
(~100K) to apply a DC offset for signalling the connector orientation.
|
||||
maxItems: 1
|
||||
|
||||
sbu2-dc-gpios:
|
||||
description:
|
||||
GPIO connected to the SBU2 line of the USB-C connector via a big resistor
|
||||
(~100K) to apply a DC offset for signalling the connector orientation.
|
||||
maxItems: 1
|
||||
|
||||
orientation-switch:
|
||||
description: Flag the port as possible handler of orientation switching
|
||||
type: boolean
|
||||
|
||||
mode-switch:
|
||||
description: Flag the port as possible handler of altmode switching
|
||||
type: boolean
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
A port node to link the PHY to a TypeC controller for the purpose of
|
||||
handling orientation switching.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
- "#phy-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/rockchip,rk3588-cru.h>
|
||||
#include <dt-bindings/reset/rockchip,rk3588-cru.h>
|
||||
|
||||
usbdp_phy0: phy@fed80000 {
|
||||
compatible = "rockchip,rk3588-usbdp-phy";
|
||||
reg = <0xfed80000 0x10000>;
|
||||
#phy-cells = <1>;
|
||||
clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>,
|
||||
<&cru CLK_USBDP_PHY0_IMMORTAL>,
|
||||
<&cru PCLK_USBDPPHY0>,
|
||||
<&u2phy0>;
|
||||
clock-names = "refclk", "immortal", "pclk", "utmi";
|
||||
resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>,
|
||||
<&cru SRST_USBDP_COMBO_PHY0_CMN>,
|
||||
<&cru SRST_USBDP_COMBO_PHY0_LANE>,
|
||||
<&cru SRST_USBDP_COMBO_PHY0_PCS>,
|
||||
<&cru SRST_P_USBDPPHY0>;
|
||||
reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb";
|
||||
rockchip,u2phy-grf = <&usb2phy0_grf>;
|
||||
rockchip,usb-grf = <&usb_grf>;
|
||||
rockchip,usbdpphy-grf = <&usbdpphy0_grf>;
|
||||
rockchip,vo-grf = <&vo0_grf>;
|
||||
};
|
@ -21,6 +21,7 @@ properties:
|
||||
- qcom,sc8180x-edp-phy
|
||||
- qcom,sc8280xp-dp-phy
|
||||
- qcom,sc8280xp-edp-phy
|
||||
- qcom,x1e80100-dp-phy
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
@ -88,11 +88,11 @@ properties:
|
||||
- description: offset of PCIe 4-lane configuration register
|
||||
- description: offset of configuration bit for this PHY
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
"#clock-cells": true
|
||||
|
||||
clock-output-names:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
@ -198,7 +198,6 @@ allOf:
|
||||
enum:
|
||||
- qcom,sm8550-qmp-gen4x2-pcie-phy
|
||||
- qcom,sm8650-qmp-gen4x2-pcie-phy
|
||||
- qcom,x1e80100-qmp-gen3x2-pcie-phy
|
||||
- qcom,x1e80100-qmp-gen4x2-pcie-phy
|
||||
then:
|
||||
properties:
|
||||
@ -213,6 +212,27 @@ allOf:
|
||||
reset-names:
|
||||
maxItems: 1
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm8450-qmp-gen4x2-pcie-phy
|
||||
- qcom,sm8550-qmp-gen4x2-pcie-phy
|
||||
- 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
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
|
||||
|
@ -32,6 +32,7 @@ properties:
|
||||
- qcom,sm8250-qmp-ufs-phy
|
||||
- qcom,sm8350-qmp-ufs-phy
|
||||
- qcom,sm8450-qmp-ufs-phy
|
||||
- qcom,sm8475-qmp-ufs-phy
|
||||
- qcom,sm8550-qmp-ufs-phy
|
||||
- qcom,sm8650-qmp-ufs-phy
|
||||
|
||||
@ -71,7 +72,6 @@ required:
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
- resets
|
||||
- reset-names
|
||||
- vdda-phy-supply
|
||||
@ -86,6 +86,7 @@ allOf:
|
||||
enum:
|
||||
- qcom,msm8998-qmp-ufs-phy
|
||||
- qcom,sa8775p-qmp-ufs-phy
|
||||
- qcom,sc7180-qmp-ufs-phy
|
||||
- qcom,sc7280-qmp-ufs-phy
|
||||
- qcom,sc8180x-qmp-ufs-phy
|
||||
- qcom,sc8280xp-qmp-ufs-phy
|
||||
@ -98,6 +99,7 @@ allOf:
|
||||
- qcom,sm8250-qmp-ufs-phy
|
||||
- qcom,sm8350-qmp-ufs-phy
|
||||
- qcom,sm8450-qmp-ufs-phy
|
||||
- qcom,sm8475-qmp-ufs-phy
|
||||
- qcom,sm8550-qmp-ufs-phy
|
||||
- qcom,sm8650-qmp-ufs-phy
|
||||
then:
|
||||
@ -127,6 +129,21 @@ allOf:
|
||||
- const: ref
|
||||
- const: qref
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8996-qmp-ufs-phy
|
||||
- qcom,msm8998-qmp-ufs-phy
|
||||
then:
|
||||
properties:
|
||||
power-domains:
|
||||
false
|
||||
else:
|
||||
required:
|
||||
- power-domains
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
@ -20,6 +20,7 @@ properties:
|
||||
- qcom,ipq8074-qmp-usb3-phy
|
||||
- qcom,ipq9574-qmp-usb3-phy
|
||||
- qcom,msm8996-qmp-usb3-phy
|
||||
- com,qdu1000-qmp-usb3-uni-phy
|
||||
- qcom,sa8775p-qmp-usb3-uni-phy
|
||||
- qcom,sc8280xp-qmp-usb3-uni-phy
|
||||
- qcom,sdm845-qmp-usb3-uni-phy
|
||||
@ -109,6 +110,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,qdu1000-qmp-usb3-uni-phy
|
||||
- qcom,sa8775p-qmp-usb3-uni-phy
|
||||
- qcom,sc8280xp-qmp-usb3-uni-phy
|
||||
- qcom,sm8150-qmp-usb3-uni-phy
|
||||
|
@ -20,7 +20,9 @@ properties:
|
||||
- enum:
|
||||
- qcom,pm7550ba-eusb2-repeater
|
||||
- const: qcom,pm8550b-eusb2-repeater
|
||||
- const: qcom,pm8550b-eusb2-repeater
|
||||
- enum:
|
||||
- qcom,pm8550b-eusb2-repeater
|
||||
- qcom,smb2360-eusb2-repeater
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -15,9 +15,6 @@ description: |
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- qcom,sc8180x-usb-hs-phy
|
||||
- qcom,usb-snps-femto-v2-phy
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sa8775p-usb-hs-phy
|
||||
@ -25,7 +22,9 @@ properties:
|
||||
- const: qcom,usb-snps-hs-5nm-phy
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,qdu1000-usb-hs-phy
|
||||
- qcom,sc7280-usb-hs-phy
|
||||
- qcom,sc8180x-usb-hs-phy
|
||||
- qcom,sdx55-usb-hs-phy
|
||||
- qcom,sdx65-usb-hs-phy
|
||||
- qcom,sm6375-usb-hs-phy
|
||||
|
@ -54,6 +54,16 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: phandle to the syscon managing the pipe "general register files"
|
||||
|
||||
rockchip,rx-common-refclk-mode:
|
||||
description: which lanes (by position) should be configured to run in
|
||||
RX common reference clock mode. 0 means disabled, 1 means enabled.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 1
|
||||
maxItems: 16
|
||||
items:
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -15,6 +15,7 @@ properties:
|
||||
|
||||
compatible:
|
||||
enum:
|
||||
- google,gs101-ufs-phy
|
||||
- samsung,exynos7-ufs-phy
|
||||
- samsung,exynosautov9-ufs-phy
|
||||
- tesla,fsd-ufs-phy
|
||||
|
@ -9312,6 +9312,7 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/clock/google,gs101-clock.yaml
|
||||
F: arch/arm64/boot/dts/exynos/google/
|
||||
F: drivers/clk/samsung/clk-gs101.c
|
||||
F: drivers/phy/samsung/phy-gs101-ufs.c
|
||||
F: include/dt-bindings/clock/google,gs101.h
|
||||
K: [gG]oogle.?[tT]ensor
|
||||
|
||||
@ -13987,6 +13988,7 @@ L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/phy/mediatek-ge-soc.c
|
||||
F: drivers/net/phy/mediatek-ge.c
|
||||
F: drivers/phy/mediatek/phy-mtk-xfi-tphy.c
|
||||
|
||||
MEDIATEK I2C CONTROLLER DRIVER
|
||||
M: Qii Wang <qii.wang@mediatek.com>
|
||||
|
@ -35,6 +35,12 @@ 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_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
|
||||
|
@ -4,3 +4,4 @@ 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_LYNX_28G) += phy-fsl-lynx-28g.o
|
||||
obj-$(CONFIG_PHY_FSL_SAMSUNG_HDMI_PHY) += phy-fsl-samsung-hdmi.o
|
||||
|
718
drivers/phy/freescale/phy-fsl-samsung-hdmi.c
Normal file
718
drivers/phy/freescale/phy-fsl-samsung-hdmi.c
Normal file
@ -0,0 +1,718 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2020 NXP
|
||||
* Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de>
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#define PHY_REG_00 0x00
|
||||
#define PHY_REG_01 0x04
|
||||
#define PHY_REG_02 0x08
|
||||
#define PHY_REG_08 0x20
|
||||
#define PHY_REG_09 0x24
|
||||
#define PHY_REG_10 0x28
|
||||
#define PHY_REG_11 0x2c
|
||||
|
||||
#define PHY_REG_12 0x30
|
||||
#define REG12_CK_DIV_MASK GENMASK(5, 4)
|
||||
|
||||
#define PHY_REG_13 0x34
|
||||
#define REG13_TG_CODE_LOW_MASK GENMASK(7, 0)
|
||||
|
||||
#define PHY_REG_14 0x38
|
||||
#define REG14_TOL_MASK GENMASK(7, 4)
|
||||
#define REG14_RP_CODE_MASK GENMASK(3, 1)
|
||||
#define REG14_TG_CODE_HIGH_MASK GENMASK(0, 0)
|
||||
|
||||
#define PHY_REG_15 0x3c
|
||||
#define PHY_REG_16 0x40
|
||||
#define PHY_REG_17 0x44
|
||||
#define PHY_REG_18 0x48
|
||||
#define PHY_REG_19 0x4c
|
||||
#define PHY_REG_20 0x50
|
||||
|
||||
#define PHY_REG_21 0x54
|
||||
#define REG21_SEL_TX_CK_INV BIT(7)
|
||||
#define REG21_PMS_S_MASK GENMASK(3, 0)
|
||||
|
||||
#define PHY_REG_22 0x58
|
||||
#define PHY_REG_23 0x5c
|
||||
#define PHY_REG_24 0x60
|
||||
#define PHY_REG_25 0x64
|
||||
#define PHY_REG_26 0x68
|
||||
#define PHY_REG_27 0x6c
|
||||
#define PHY_REG_28 0x70
|
||||
#define PHY_REG_29 0x74
|
||||
#define PHY_REG_30 0x78
|
||||
#define PHY_REG_31 0x7c
|
||||
#define PHY_REG_32 0x80
|
||||
|
||||
/*
|
||||
* REG33 does not match the ref manual. According to Sandor Yu from NXP,
|
||||
* "There is a doc issue on the i.MX8MP latest RM"
|
||||
* REG33 is being used per guidance from Sandor
|
||||
*/
|
||||
|
||||
#define PHY_REG_33 0x84
|
||||
#define REG33_MODE_SET_DONE BIT(7)
|
||||
#define REG33_FIX_DA BIT(1)
|
||||
|
||||
#define PHY_REG_34 0x88
|
||||
#define REG34_PHY_READY BIT(7)
|
||||
#define REG34_PLL_LOCK BIT(6)
|
||||
#define REG34_PHY_CLK_READY BIT(5)
|
||||
|
||||
#define PHY_REG_35 0x8c
|
||||
#define PHY_REG_36 0x90
|
||||
#define PHY_REG_37 0x94
|
||||
#define PHY_REG_38 0x98
|
||||
#define PHY_REG_39 0x9c
|
||||
#define PHY_REG_40 0xa0
|
||||
#define PHY_REG_41 0xa4
|
||||
#define PHY_REG_42 0xa8
|
||||
#define PHY_REG_43 0xac
|
||||
#define PHY_REG_44 0xb0
|
||||
#define PHY_REG_45 0xb4
|
||||
#define PHY_REG_46 0xb8
|
||||
#define PHY_REG_47 0xbc
|
||||
|
||||
#define PHY_PLL_DIV_REGS_NUM 6
|
||||
|
||||
struct phy_config {
|
||||
u32 pixclk;
|
||||
u8 pll_div_regs[PHY_PLL_DIV_REGS_NUM];
|
||||
};
|
||||
|
||||
static const struct phy_config phy_pll_cfg[] = {
|
||||
{
|
||||
.pixclk = 22250000,
|
||||
.pll_div_regs = { 0x4b, 0xf1, 0x89, 0x88, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 23750000,
|
||||
.pll_div_regs = { 0x50, 0xf1, 0x86, 0x85, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 24000000,
|
||||
.pll_div_regs = { 0x50, 0xf0, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 24024000,
|
||||
.pll_div_regs = { 0x50, 0xf1, 0x99, 0x02, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 25175000,
|
||||
.pll_div_regs = { 0x54, 0xfc, 0xcc, 0x91, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 25200000,
|
||||
.pll_div_regs = { 0x54, 0xf0, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 26750000,
|
||||
.pll_div_regs = { 0x5a, 0xf2, 0x89, 0x88, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 27000000,
|
||||
.pll_div_regs = { 0x5a, 0xf0, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 27027000,
|
||||
.pll_div_regs = { 0x5a, 0xf2, 0xfd, 0x0c, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 29500000,
|
||||
.pll_div_regs = { 0x62, 0xf4, 0x95, 0x08, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 30750000,
|
||||
.pll_div_regs = { 0x66, 0xf4, 0x82, 0x01, 0x88, 0x45 },
|
||||
}, {
|
||||
.pixclk = 30888000,
|
||||
.pll_div_regs = { 0x66, 0xf4, 0x99, 0x18, 0x88, 0x45 },
|
||||
}, {
|
||||
.pixclk = 33750000,
|
||||
.pll_div_regs = { 0x70, 0xf4, 0x82, 0x01, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 35000000,
|
||||
.pll_div_regs = { 0x58, 0xb8, 0x8b, 0x88, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 36000000,
|
||||
.pll_div_regs = { 0x5a, 0xb0, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 36036000,
|
||||
.pll_div_regs = { 0x5a, 0xb2, 0xfd, 0x0c, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 40000000,
|
||||
.pll_div_regs = { 0x64, 0xb0, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 43200000,
|
||||
.pll_div_regs = { 0x5a, 0x90, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 43243200,
|
||||
.pll_div_regs = { 0x5a, 0x92, 0xfd, 0x0c, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 44500000,
|
||||
.pll_div_regs = { 0x5c, 0x92, 0x98, 0x11, 0x84, 0x41 },
|
||||
}, {
|
||||
.pixclk = 47000000,
|
||||
.pll_div_regs = { 0x62, 0x94, 0x95, 0x82, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 47500000,
|
||||
.pll_div_regs = { 0x63, 0x96, 0xa1, 0x82, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 50349650,
|
||||
.pll_div_regs = { 0x54, 0x7c, 0xc3, 0x8f, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 50400000,
|
||||
.pll_div_regs = { 0x54, 0x70, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 53250000,
|
||||
.pll_div_regs = { 0x58, 0x72, 0x84, 0x03, 0x82, 0x41 },
|
||||
}, {
|
||||
.pixclk = 53500000,
|
||||
.pll_div_regs = { 0x5a, 0x72, 0x89, 0x88, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 54000000,
|
||||
.pll_div_regs = { 0x5a, 0x70, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 54054000,
|
||||
.pll_div_regs = { 0x5a, 0x72, 0xfd, 0x0c, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 59000000,
|
||||
.pll_div_regs = { 0x62, 0x74, 0x95, 0x08, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 59340659,
|
||||
.pll_div_regs = { 0x62, 0x74, 0xdb, 0x52, 0x88, 0x47 },
|
||||
}, {
|
||||
.pixclk = 59400000,
|
||||
.pll_div_regs = { 0x63, 0x70, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 61500000,
|
||||
.pll_div_regs = { 0x66, 0x74, 0x82, 0x01, 0x88, 0x45 },
|
||||
}, {
|
||||
.pixclk = 63500000,
|
||||
.pll_div_regs = { 0x69, 0x74, 0x89, 0x08, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 67500000,
|
||||
.pll_div_regs = { 0x54, 0x52, 0x87, 0x03, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 70000000,
|
||||
.pll_div_regs = { 0x58, 0x58, 0x8b, 0x88, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 72000000,
|
||||
.pll_div_regs = { 0x5a, 0x50, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 72072000,
|
||||
.pll_div_regs = { 0x5a, 0x52, 0xfd, 0x0c, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 74176000,
|
||||
.pll_div_regs = { 0x5d, 0x58, 0xdb, 0xA2, 0x88, 0x41 },
|
||||
}, {
|
||||
.pixclk = 74250000,
|
||||
.pll_div_regs = { 0x5c, 0x52, 0x90, 0x0d, 0x84, 0x41 },
|
||||
}, {
|
||||
.pixclk = 78500000,
|
||||
.pll_div_regs = { 0x62, 0x54, 0x87, 0x01, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 80000000,
|
||||
.pll_div_regs = { 0x64, 0x50, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 82000000,
|
||||
.pll_div_regs = { 0x66, 0x54, 0x82, 0x01, 0x88, 0x45 },
|
||||
}, {
|
||||
.pixclk = 82500000,
|
||||
.pll_div_regs = { 0x67, 0x54, 0x88, 0x01, 0x90, 0x49 },
|
||||
}, {
|
||||
.pixclk = 89000000,
|
||||
.pll_div_regs = { 0x70, 0x54, 0x84, 0x83, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 90000000,
|
||||
.pll_div_regs = { 0x70, 0x54, 0x82, 0x01, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 94000000,
|
||||
.pll_div_regs = { 0x4e, 0x32, 0xa7, 0x10, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 95000000,
|
||||
.pll_div_regs = { 0x50, 0x31, 0x86, 0x85, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 98901099,
|
||||
.pll_div_regs = { 0x52, 0x3a, 0xdb, 0x4c, 0x88, 0x47 },
|
||||
}, {
|
||||
.pixclk = 99000000,
|
||||
.pll_div_regs = { 0x52, 0x32, 0x82, 0x01, 0x88, 0x47 },
|
||||
}, {
|
||||
.pixclk = 100699300,
|
||||
.pll_div_regs = { 0x54, 0x3c, 0xc3, 0x8f, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 100800000,
|
||||
.pll_div_regs = { 0x54, 0x30, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 102500000,
|
||||
.pll_div_regs = { 0x55, 0x32, 0x8c, 0x05, 0x90, 0x4b },
|
||||
}, {
|
||||
.pixclk = 104750000,
|
||||
.pll_div_regs = { 0x57, 0x32, 0x98, 0x07, 0x90, 0x49 },
|
||||
}, {
|
||||
.pixclk = 106500000,
|
||||
.pll_div_regs = { 0x58, 0x32, 0x84, 0x03, 0x82, 0x41 },
|
||||
}, {
|
||||
.pixclk = 107000000,
|
||||
.pll_div_regs = { 0x5a, 0x32, 0x89, 0x88, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 108000000,
|
||||
.pll_div_regs = { 0x5a, 0x30, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 108108000,
|
||||
.pll_div_regs = { 0x5a, 0x32, 0xfd, 0x0c, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 118000000,
|
||||
.pll_div_regs = { 0x62, 0x34, 0x95, 0x08, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 118800000,
|
||||
.pll_div_regs = { 0x63, 0x30, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 123000000,
|
||||
.pll_div_regs = { 0x66, 0x34, 0x82, 0x01, 0x88, 0x45 },
|
||||
}, {
|
||||
.pixclk = 127000000,
|
||||
.pll_div_regs = { 0x69, 0x34, 0x89, 0x08, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 135000000,
|
||||
.pll_div_regs = { 0x70, 0x34, 0x82, 0x01, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 135580000,
|
||||
.pll_div_regs = { 0x71, 0x39, 0xe9, 0x82, 0x9c, 0x5b },
|
||||
}, {
|
||||
.pixclk = 137520000,
|
||||
.pll_div_regs = { 0x72, 0x38, 0x99, 0x10, 0x85, 0x41 },
|
||||
}, {
|
||||
.pixclk = 138750000,
|
||||
.pll_div_regs = { 0x73, 0x35, 0x88, 0x05, 0x90, 0x4d },
|
||||
}, {
|
||||
.pixclk = 140000000,
|
||||
.pll_div_regs = { 0x75, 0x36, 0xa7, 0x90, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 144000000,
|
||||
.pll_div_regs = { 0x78, 0x30, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 148352000,
|
||||
.pll_div_regs = { 0x7b, 0x35, 0xdb, 0x39, 0x90, 0x45 },
|
||||
}, {
|
||||
.pixclk = 148500000,
|
||||
.pll_div_regs = { 0x7b, 0x35, 0x84, 0x03, 0x90, 0x45 },
|
||||
}, {
|
||||
.pixclk = 154000000,
|
||||
.pll_div_regs = { 0x40, 0x18, 0x83, 0x01, 0x00, 0x40 },
|
||||
}, {
|
||||
.pixclk = 157000000,
|
||||
.pll_div_regs = { 0x41, 0x11, 0xa7, 0x14, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 160000000,
|
||||
.pll_div_regs = { 0x42, 0x12, 0xa1, 0x20, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 162000000,
|
||||
.pll_div_regs = { 0x43, 0x18, 0x8b, 0x08, 0x96, 0x55 },
|
||||
}, {
|
||||
.pixclk = 164000000,
|
||||
.pll_div_regs = { 0x45, 0x11, 0x83, 0x82, 0x90, 0x4b },
|
||||
}, {
|
||||
.pixclk = 165000000,
|
||||
.pll_div_regs = { 0x45, 0x11, 0x84, 0x81, 0x90, 0x4b },
|
||||
}, {
|
||||
.pixclk = 180000000,
|
||||
.pll_div_regs = { 0x4b, 0x10, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 185625000,
|
||||
.pll_div_regs = { 0x4e, 0x12, 0x9a, 0x95, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 188000000,
|
||||
.pll_div_regs = { 0x4e, 0x12, 0xa7, 0x10, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 198000000,
|
||||
.pll_div_regs = { 0x52, 0x12, 0x82, 0x01, 0x88, 0x47 },
|
||||
}, {
|
||||
.pixclk = 205000000,
|
||||
.pll_div_regs = { 0x55, 0x12, 0x8c, 0x05, 0x90, 0x4b },
|
||||
}, {
|
||||
.pixclk = 209500000,
|
||||
.pll_div_regs = { 0x57, 0x12, 0x98, 0x07, 0x90, 0x49 },
|
||||
}, {
|
||||
.pixclk = 213000000,
|
||||
.pll_div_regs = { 0x58, 0x12, 0x84, 0x03, 0x82, 0x41 },
|
||||
}, {
|
||||
.pixclk = 216000000,
|
||||
.pll_div_regs = { 0x5a, 0x10, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 216216000,
|
||||
.pll_div_regs = { 0x5a, 0x12, 0xfd, 0x0c, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 237600000,
|
||||
.pll_div_regs = { 0x63, 0x10, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 254000000,
|
||||
.pll_div_regs = { 0x69, 0x14, 0x89, 0x08, 0x80, 0x40 },
|
||||
}, {
|
||||
.pixclk = 277500000,
|
||||
.pll_div_regs = { 0x73, 0x15, 0x88, 0x05, 0x90, 0x4d },
|
||||
}, {
|
||||
.pixclk = 288000000,
|
||||
.pll_div_regs = { 0x78, 0x10, 0x00, 0x00, 0x80, 0x00 },
|
||||
}, {
|
||||
.pixclk = 297000000,
|
||||
.pll_div_regs = { 0x7b, 0x15, 0x84, 0x03, 0x90, 0x45 },
|
||||
},
|
||||
};
|
||||
|
||||
struct reg_settings {
|
||||
u8 reg;
|
||||
u8 val;
|
||||
};
|
||||
|
||||
static const struct reg_settings common_phy_cfg[] = {
|
||||
{ PHY_REG_00, 0x00 }, { PHY_REG_01, 0xd1 },
|
||||
{ PHY_REG_08, 0x4f }, { PHY_REG_09, 0x30 },
|
||||
{ PHY_REG_10, 0x33 }, { PHY_REG_11, 0x65 },
|
||||
/* REG12 pixclk specific */
|
||||
/* REG13 pixclk specific */
|
||||
/* REG14 pixclk specific */
|
||||
{ PHY_REG_15, 0x80 }, { PHY_REG_16, 0x6c },
|
||||
{ PHY_REG_17, 0xf2 }, { PHY_REG_18, 0x67 },
|
||||
{ PHY_REG_19, 0x00 }, { PHY_REG_20, 0x10 },
|
||||
/* REG21 pixclk specific */
|
||||
{ PHY_REG_22, 0x30 }, { PHY_REG_23, 0x32 },
|
||||
{ PHY_REG_24, 0x60 }, { PHY_REG_25, 0x8f },
|
||||
{ PHY_REG_26, 0x00 }, { PHY_REG_27, 0x00 },
|
||||
{ PHY_REG_28, 0x08 }, { PHY_REG_29, 0x00 },
|
||||
{ PHY_REG_30, 0x00 }, { PHY_REG_31, 0x00 },
|
||||
{ PHY_REG_32, 0x00 }, { PHY_REG_33, 0x80 },
|
||||
{ PHY_REG_34, 0x00 }, { PHY_REG_35, 0x00 },
|
||||
{ PHY_REG_36, 0x00 }, { PHY_REG_37, 0x00 },
|
||||
{ PHY_REG_38, 0x00 }, { PHY_REG_39, 0x00 },
|
||||
{ PHY_REG_40, 0x00 }, { PHY_REG_41, 0xe0 },
|
||||
{ PHY_REG_42, 0x83 }, { PHY_REG_43, 0x0f },
|
||||
{ PHY_REG_44, 0x3E }, { PHY_REG_45, 0xf8 },
|
||||
{ PHY_REG_46, 0x00 }, { PHY_REG_47, 0x00 }
|
||||
};
|
||||
|
||||
struct fsl_samsung_hdmi_phy {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
struct clk *apbclk;
|
||||
struct clk *refclk;
|
||||
|
||||
/* clk provider */
|
||||
struct clk_hw hw;
|
||||
const struct phy_config *cur_cfg;
|
||||
};
|
||||
|
||||
static inline struct fsl_samsung_hdmi_phy *
|
||||
to_fsl_samsung_hdmi_phy(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct fsl_samsung_hdmi_phy, hw);
|
||||
}
|
||||
|
||||
static void
|
||||
fsl_samsung_hdmi_phy_configure_pixclk(struct fsl_samsung_hdmi_phy *phy,
|
||||
const struct phy_config *cfg)
|
||||
{
|
||||
u8 div = 0x1;
|
||||
|
||||
switch (cfg->pixclk) {
|
||||
case 22250000 ... 33750000:
|
||||
div = 0xf;
|
||||
break;
|
||||
case 35000000 ... 40000000:
|
||||
div = 0xb;
|
||||
break;
|
||||
case 43200000 ... 47500000:
|
||||
div = 0x9;
|
||||
break;
|
||||
case 50349650 ... 63500000:
|
||||
div = 0x7;
|
||||
break;
|
||||
case 67500000 ... 90000000:
|
||||
div = 0x5;
|
||||
break;
|
||||
case 94000000 ... 148500000:
|
||||
div = 0x3;
|
||||
break;
|
||||
case 154000000 ... 297000000:
|
||||
div = 0x1;
|
||||
break;
|
||||
}
|
||||
|
||||
writeb(REG21_SEL_TX_CK_INV | FIELD_PREP(REG21_PMS_S_MASK, div),
|
||||
phy->regs + PHY_REG_21);
|
||||
}
|
||||
|
||||
static void
|
||||
fsl_samsung_hdmi_phy_configure_pll_lock_det(struct fsl_samsung_hdmi_phy *phy,
|
||||
const struct phy_config *cfg)
|
||||
{
|
||||
u32 pclk = cfg->pixclk;
|
||||
u32 fld_tg_code;
|
||||
u32 pclk_khz;
|
||||
u8 div = 1;
|
||||
|
||||
switch (cfg->pixclk) {
|
||||
case 22250000 ... 47500000:
|
||||
div = 1;
|
||||
break;
|
||||
case 50349650 ... 99000000:
|
||||
div = 2;
|
||||
break;
|
||||
case 100699300 ... 198000000:
|
||||
div = 4;
|
||||
break;
|
||||
case 205000000 ... 297000000:
|
||||
div = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
writeb(FIELD_PREP(REG12_CK_DIV_MASK, ilog2(div)), phy->regs + PHY_REG_12);
|
||||
|
||||
/*
|
||||
* Calculation for the frequency lock detector target code (fld_tg_code)
|
||||
* is based on reference manual register description of PHY_REG13
|
||||
* (13.10.3.1.14.2):
|
||||
* 1st) Calculate int_pllclk which is determinded by FLD_CK_DIV
|
||||
* 2nd) Increase resolution to avoid rounding issues
|
||||
* 3th) Do the div (256 / Freq. of int_pllclk) * 24
|
||||
* 4th) Reduce the resolution and always round up since the NXP
|
||||
* settings rounding up always too. TODO: Check if that is
|
||||
* correct.
|
||||
*/
|
||||
pclk /= div;
|
||||
pclk_khz = pclk / 1000;
|
||||
fld_tg_code = 256 * 1000 * 1000 / pclk_khz * 24;
|
||||
fld_tg_code = DIV_ROUND_UP(fld_tg_code, 1000);
|
||||
|
||||
/* FLD_TOL and FLD_RP_CODE taken from downstream driver */
|
||||
writeb(FIELD_PREP(REG13_TG_CODE_LOW_MASK, fld_tg_code),
|
||||
phy->regs + PHY_REG_13);
|
||||
writeb(FIELD_PREP(REG14_TOL_MASK, 2) |
|
||||
FIELD_PREP(REG14_RP_CODE_MASK, 2) |
|
||||
FIELD_PREP(REG14_TG_CODE_HIGH_MASK, fld_tg_code >> 8),
|
||||
phy->regs + PHY_REG_14);
|
||||
}
|
||||
|
||||
static int fsl_samsung_hdmi_phy_configure(struct fsl_samsung_hdmi_phy *phy,
|
||||
const struct phy_config *cfg)
|
||||
{
|
||||
int i, ret;
|
||||
u8 val;
|
||||
|
||||
/* HDMI PHY init */
|
||||
writeb(REG33_FIX_DA, phy->regs + PHY_REG_33);
|
||||
|
||||
/* common PHY registers */
|
||||
for (i = 0; i < ARRAY_SIZE(common_phy_cfg); i++)
|
||||
writeb(common_phy_cfg[i].val, phy->regs + common_phy_cfg[i].reg);
|
||||
|
||||
/* set individual PLL registers PHY_REG2 ... PHY_REG7 */
|
||||
for (i = 0; i < PHY_PLL_DIV_REGS_NUM; i++)
|
||||
writeb(cfg->pll_div_regs[i], phy->regs + PHY_REG_02 + i * 4);
|
||||
|
||||
fsl_samsung_hdmi_phy_configure_pixclk(phy, cfg);
|
||||
fsl_samsung_hdmi_phy_configure_pll_lock_det(phy, cfg);
|
||||
|
||||
writeb(REG33_FIX_DA | REG33_MODE_SET_DONE, phy->regs + PHY_REG_33);
|
||||
|
||||
ret = readb_poll_timeout(phy->regs + PHY_REG_34, val,
|
||||
val & REG34_PLL_LOCK, 50, 20000);
|
||||
if (ret)
|
||||
dev_err(phy->dev, "PLL failed to lock\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned long phy_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw);
|
||||
|
||||
if (!phy->cur_cfg)
|
||||
return 74250000;
|
||||
|
||||
return phy->cur_cfg->pixclk;
|
||||
}
|
||||
|
||||
static long phy_clk_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long *parent_rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = ARRAY_SIZE(phy_pll_cfg) - 1; i >= 0; i--)
|
||||
if (phy_pll_cfg[i].pixclk <= rate)
|
||||
return phy_pll_cfg[i].pixclk;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int phy_clk_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long parent_rate)
|
||||
{
|
||||
struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw);
|
||||
int i;
|
||||
|
||||
for (i = ARRAY_SIZE(phy_pll_cfg) - 1; i >= 0; i--)
|
||||
if (phy_pll_cfg[i].pixclk <= rate)
|
||||
break;
|
||||
|
||||
if (i < 0)
|
||||
return -EINVAL;
|
||||
|
||||
phy->cur_cfg = &phy_pll_cfg[i];
|
||||
|
||||
return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
|
||||
}
|
||||
|
||||
static const struct clk_ops phy_clk_ops = {
|
||||
.recalc_rate = phy_clk_recalc_rate,
|
||||
.round_rate = phy_clk_round_rate,
|
||||
.set_rate = phy_clk_set_rate,
|
||||
};
|
||||
|
||||
static int phy_clk_register(struct fsl_samsung_hdmi_phy *phy)
|
||||
{
|
||||
struct device *dev = phy->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct clk_init_data init;
|
||||
const char *parent_name;
|
||||
struct clk *phyclk;
|
||||
int ret;
|
||||
|
||||
parent_name = __clk_get_name(phy->refclk);
|
||||
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
init.flags = 0;
|
||||
init.name = "hdmi_pclk";
|
||||
init.ops = &phy_clk_ops;
|
||||
|
||||
phy->hw.init = &init;
|
||||
|
||||
phyclk = devm_clk_register(dev, &phy->hw);
|
||||
if (IS_ERR(phyclk))
|
||||
return dev_err_probe(dev, PTR_ERR(phyclk),
|
||||
"failed to register clock\n");
|
||||
|
||||
ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, phyclk);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to register clock provider\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsl_samsung_hdmi_phy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct fsl_samsung_hdmi_phy *phy;
|
||||
int ret;
|
||||
|
||||
phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
|
||||
if (!phy)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, phy);
|
||||
phy->dev = &pdev->dev;
|
||||
|
||||
phy->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(phy->regs))
|
||||
return PTR_ERR(phy->regs);
|
||||
|
||||
phy->apbclk = devm_clk_get(phy->dev, "apb");
|
||||
if (IS_ERR(phy->apbclk))
|
||||
return dev_err_probe(phy->dev, PTR_ERR(phy->apbclk),
|
||||
"failed to get apb clk\n");
|
||||
|
||||
phy->refclk = devm_clk_get(phy->dev, "ref");
|
||||
if (IS_ERR(phy->refclk))
|
||||
return dev_err_probe(phy->dev, PTR_ERR(phy->refclk),
|
||||
"failed to get ref clk\n");
|
||||
|
||||
ret = clk_prepare_enable(phy->apbclk);
|
||||
if (ret) {
|
||||
dev_err(phy->dev, "failed to enable apbclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_get_noresume(phy->dev);
|
||||
pm_runtime_set_active(phy->dev);
|
||||
pm_runtime_enable(phy->dev);
|
||||
|
||||
ret = phy_clk_register(phy);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "register clk failed\n");
|
||||
goto register_clk_failed;
|
||||
}
|
||||
|
||||
pm_runtime_put(phy->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
register_clk_failed:
|
||||
clk_disable_unprepare(phy->apbclk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fsl_samsung_hdmi_phy_remove(struct platform_device *pdev)
|
||||
{
|
||||
of_clk_del_provider(pdev->dev.of_node);
|
||||
}
|
||||
|
||||
static int __maybe_unused fsl_samsung_hdmi_phy_suspend(struct device *dev)
|
||||
{
|
||||
struct fsl_samsung_hdmi_phy *phy = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(phy->apbclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused fsl_samsung_hdmi_phy_resume(struct device *dev)
|
||||
{
|
||||
struct fsl_samsung_hdmi_phy *phy = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
ret = clk_prepare_enable(phy->apbclk);
|
||||
if (ret) {
|
||||
dev_err(phy->dev, "failed to enable apbclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (phy->cur_cfg)
|
||||
ret = fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static DEFINE_RUNTIME_DEV_PM_OPS(fsl_samsung_hdmi_phy_pm_ops,
|
||||
fsl_samsung_hdmi_phy_suspend,
|
||||
fsl_samsung_hdmi_phy_resume, NULL);
|
||||
|
||||
static const struct of_device_id fsl_samsung_hdmi_phy_of_match[] = {
|
||||
{
|
||||
.compatible = "fsl,imx8mp-hdmi-phy",
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fsl_samsung_hdmi_phy_of_match);
|
||||
|
||||
static struct platform_driver fsl_samsung_hdmi_phy_driver = {
|
||||
.probe = fsl_samsung_hdmi_phy_probe,
|
||||
.remove_new = fsl_samsung_hdmi_phy_remove,
|
||||
.driver = {
|
||||
.name = "fsl-samsung-hdmi-phy",
|
||||
.of_match_table = fsl_samsung_hdmi_phy_of_match,
|
||||
.pm = pm_ptr(&fsl_samsung_hdmi_phy_pm_ops),
|
||||
},
|
||||
};
|
||||
module_platform_driver(fsl_samsung_hdmi_phy_driver);
|
||||
|
||||
MODULE_AUTHOR("Sandor Yu <Sandor.yu@nxp.com>");
|
||||
MODULE_DESCRIPTION("SAMSUNG HDMI 2.0 Transmitter PHY Driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -13,6 +13,17 @@ config PHY_MTK_PCIE
|
||||
callback for PCIe GEN3 port, it supports software efuse
|
||||
initialization.
|
||||
|
||||
config PHY_MTK_XFI_TPHY
|
||||
tristate "MediaTek 10GE SerDes XFI T-PHY driver"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
depends on OF
|
||||
select GENERIC_PHY
|
||||
help
|
||||
Say 'Y' here to add support for MediaTek XFI T-PHY driver.
|
||||
The driver provides access to the Ethernet SerDes T-PHY supporting
|
||||
1GE and 2.5GE modes via the LynxI PCS, and 5GE and 10GE modes
|
||||
via the USXGMII PCS found in MediaTek SoCs with 10G Ethernet.
|
||||
|
||||
config PHY_MTK_TPHY
|
||||
tristate "MediaTek T-PHY Driver"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
|
@ -8,6 +8,7 @@ obj-$(CONFIG_PHY_MTK_PCIE) += phy-mtk-pcie.o
|
||||
obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o
|
||||
obj-$(CONFIG_PHY_MTK_UFS) += phy-mtk-ufs.o
|
||||
obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o
|
||||
obj-$(CONFIG_PHY_MTK_XFI_TPHY) += phy-mtk-xfi-tphy.o
|
||||
|
||||
phy-mtk-hdmi-drv-y := phy-mtk-hdmi.o
|
||||
phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt2701.o
|
||||
|
451
drivers/phy/mediatek/phy-mtk-xfi-tphy.c
Normal file
451
drivers/phy/mediatek/phy-mtk-xfi-tphy.c
Normal file
@ -0,0 +1,451 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* MediaTek 10GE SerDes XFI T-PHY driver
|
||||
*
|
||||
* Copyright (c) 2024 Daniel Golle <daniel@makrotopia.org>
|
||||
* Bc-bocun Chen <bc-bocun.chen@mediatek.com>
|
||||
* based on mtk_usxgmii.c and mtk_sgmii.c found in MediaTek's SDK (GPL-2.0)
|
||||
* Copyright (c) 2022 MediaTek Inc.
|
||||
* Author: Henry Yen <henry.yen@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/phy/phy.h>
|
||||
|
||||
#include "phy-mtk-io.h"
|
||||
|
||||
#define MTK_XFI_TPHY_NUM_CLOCKS 2
|
||||
|
||||
#define REG_DIG_GLB_70 0x0070
|
||||
#define XTP_PCS_RX_EQ_IN_PROGRESS(x) FIELD_PREP(GENMASK(25, 24), (x))
|
||||
#define XTP_PCS_MODE_MASK GENMASK(17, 16)
|
||||
#define XTP_PCS_MODE(x) FIELD_PREP(GENMASK(17, 16), (x))
|
||||
#define XTP_PCS_RST_B BIT(15)
|
||||
#define XTP_FRC_PCS_RST_B BIT(14)
|
||||
#define XTP_PCS_PWD_SYNC_MASK GENMASK(13, 12)
|
||||
#define XTP_PCS_PWD_SYNC(x) FIELD_PREP(XTP_PCS_PWD_SYNC_MASK, (x))
|
||||
#define XTP_PCS_PWD_ASYNC_MASK GENMASK(11, 10)
|
||||
#define XTP_PCS_PWD_ASYNC(x) FIELD_PREP(XTP_PCS_PWD_ASYNC_MASK, (x))
|
||||
#define XTP_FRC_PCS_PWD_ASYNC BIT(8)
|
||||
#define XTP_PCS_UPDT BIT(4)
|
||||
#define XTP_PCS_IN_FR_RG BIT(0)
|
||||
|
||||
#define REG_DIG_GLB_F4 0x00f4
|
||||
#define XFI_DPHY_PCS_SEL BIT(0)
|
||||
#define XFI_DPHY_PCS_SEL_SGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 1)
|
||||
#define XFI_DPHY_PCS_SEL_USXGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 0)
|
||||
#define XFI_DPHY_AD_SGDT_FRC_EN BIT(5)
|
||||
|
||||
#define REG_DIG_LN_TRX_40 0x3040
|
||||
#define XTP_LN_FRC_TX_DATA_EN BIT(29)
|
||||
#define XTP_LN_TX_DATA_EN BIT(28)
|
||||
|
||||
#define REG_DIG_LN_TRX_B0 0x30b0
|
||||
#define XTP_LN_FRC_TX_MACCK_EN BIT(5)
|
||||
#define XTP_LN_TX_MACCK_EN BIT(4)
|
||||
|
||||
#define REG_ANA_GLB_D0 0x90d0
|
||||
#define XTP_GLB_USXGMII_SEL_MASK GENMASK(3, 1)
|
||||
#define XTP_GLB_USXGMII_SEL(x) FIELD_PREP(GENMASK(3, 1), (x))
|
||||
#define XTP_GLB_USXGMII_EN BIT(0)
|
||||
|
||||
/**
|
||||
* struct mtk_xfi_tphy - run-time data of the XFI phy instance
|
||||
* @base: IO memory area to access phy registers.
|
||||
* @dev: Kernel device used to output prefixed debug info.
|
||||
* @reset: Reset control corresponding to the phy instance.
|
||||
* @clocks: All clocks required for the phy to operate.
|
||||
* @da_war: Enables work-around for 10GBase-R mode.
|
||||
*/
|
||||
struct mtk_xfi_tphy {
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
struct reset_control *reset;
|
||||
struct clk_bulk_data clocks[MTK_XFI_TPHY_NUM_CLOCKS];
|
||||
bool da_war;
|
||||
};
|
||||
|
||||
/**
|
||||
* mtk_xfi_tphy_setup() - Setup phy for specified interface mode.
|
||||
* @xfi_tphy: XFI phy instance.
|
||||
* @interface: Ethernet interface mode
|
||||
*
|
||||
* The setup function is the condensed result of combining the 5 functions which
|
||||
* setup the phy in MediaTek's GPL licensed public SDK sources. They can be found
|
||||
* in mtk_sgmii.c[1] as well as mtk_usxgmii.c[2].
|
||||
*
|
||||
* Many magic values have been replaced by register and bit definitions, however,
|
||||
* that has not been possible in all cases. While the vendor driver uses a
|
||||
* sequence of 32-bit writes, here we try to only modify the actually required
|
||||
* bits.
|
||||
*
|
||||
* [1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/b72d6cba92bf9e29fb035c03052fa1e86664a25b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
|
||||
*
|
||||
* [2]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/dec96a1d9b82cdcda4a56453fd0b453d4cab4b85/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||
*/
|
||||
static void mtk_xfi_tphy_setup(struct mtk_xfi_tphy *xfi_tphy,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
bool is_1g, is_2p5g, is_5g, is_10g, da_war, use_lynxi_pcs;
|
||||
|
||||
/* shorthands for specific clock speeds depending on interface mode */
|
||||
is_1g = interface == PHY_INTERFACE_MODE_1000BASEX ||
|
||||
interface == PHY_INTERFACE_MODE_SGMII;
|
||||
is_2p5g = interface == PHY_INTERFACE_MODE_2500BASEX;
|
||||
is_5g = interface == PHY_INTERFACE_MODE_5GBASER;
|
||||
is_10g = interface == PHY_INTERFACE_MODE_10GBASER ||
|
||||
interface == PHY_INTERFACE_MODE_USXGMII;
|
||||
|
||||
/* Is overriding 10GBase-R tuning value required? */
|
||||
da_war = xfi_tphy->da_war && (interface == PHY_INTERFACE_MODE_10GBASER);
|
||||
|
||||
/* configure input mux to either
|
||||
* - USXGMII PCS (64b/66b coding) for 5G/10G
|
||||
* - LynxI PCS (8b/10b coding) for 1G/2.5G
|
||||
*/
|
||||
use_lynxi_pcs = is_1g || is_2p5g;
|
||||
|
||||
dev_dbg(xfi_tphy->dev, "setting up for mode %s\n", phy_modes(interface));
|
||||
|
||||
/* Setup PLL setting */
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x9024, 0x100000, is_10g ? 0x0 : 0x100000);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x2020, 0x202000, is_5g ? 0x202000 : 0x0);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x2030, 0x500, is_1g ? 0x0 : 0x500);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x2034, 0xa00, is_1g ? 0x0 : 0xa00);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x2040, 0x340000, is_1g ? 0x200000 : 0x140000);
|
||||
|
||||
/* Setup RXFE BW setting */
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x50f0, 0xc10, is_1g ? 0x410 : is_5g ? 0x800 : 0x400);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x50e0, 0x4000, is_5g ? 0x0 : 0x4000);
|
||||
|
||||
/* Setup RX CDR setting */
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x506c, 0x30000, is_5g ? 0x0 : 0x30000);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x5070, 0x670000, is_5g ? 0x620000 : 0x50000);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x5074, 0x180000, is_5g ? 0x180000 : 0x0);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x5078, 0xf000400, is_5g ? 0x8000000 :
|
||||
0x7000400);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x507c, 0x5000500, is_5g ? 0x4000400 :
|
||||
0x1000100);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x5080, 0x1410, is_1g ? 0x400 : is_5g ? 0x1010 : 0x0);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x5084, 0x30300, is_1g ? 0x30300 :
|
||||
is_5g ? 0x30100 :
|
||||
0x100);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x5088, 0x60200, is_1g ? 0x20200 :
|
||||
is_5g ? 0x40000 :
|
||||
0x20000);
|
||||
|
||||
/* Setting RXFE adaptation range setting */
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x50e4, 0xc0000, is_5g ? 0x0 : 0xc0000);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x50e8, 0x40000, is_5g ? 0x0 : 0x40000);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x50ec, 0xa00, is_1g ? 0x200 : 0x800);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x50a8, 0xee0000, is_5g ? 0x800000 :
|
||||
0x6e0000);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x6004, 0x190000, is_5g ? 0x0 : 0x190000);
|
||||
|
||||
if (is_10g)
|
||||
writel(0x01423342, xfi_tphy->base + 0x00f8);
|
||||
else if (is_5g)
|
||||
writel(0x00a132a1, xfi_tphy->base + 0x00f8);
|
||||
else if (is_2p5g)
|
||||
writel(0x009c329c, xfi_tphy->base + 0x00f8);
|
||||
else
|
||||
writel(0x00fa32fa, xfi_tphy->base + 0x00f8);
|
||||
|
||||
/* Force SGDT_OUT off and select PCS */
|
||||
mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_F4,
|
||||
XFI_DPHY_AD_SGDT_FRC_EN | XFI_DPHY_PCS_SEL,
|
||||
XFI_DPHY_AD_SGDT_FRC_EN |
|
||||
(use_lynxi_pcs ? XFI_DPHY_PCS_SEL_SGMII :
|
||||
XFI_DPHY_PCS_SEL_USXGMII));
|
||||
|
||||
/* Force GLB_CKDET_OUT */
|
||||
mtk_phy_set_bits(xfi_tphy->base + 0x0030, 0xc00);
|
||||
|
||||
/* Force AEQ on */
|
||||
writel(XTP_PCS_RX_EQ_IN_PROGRESS(2) | XTP_PCS_PWD_SYNC(2) | XTP_PCS_PWD_ASYNC(2),
|
||||
xfi_tphy->base + REG_DIG_GLB_70);
|
||||
|
||||
usleep_range(1, 5);
|
||||
writel(XTP_LN_FRC_TX_DATA_EN, xfi_tphy->base + REG_DIG_LN_TRX_40);
|
||||
|
||||
/* Setup TX DA default value */
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x30b0, 0x30, 0x20);
|
||||
writel(0x00008a01, xfi_tphy->base + 0x3028);
|
||||
writel(0x0000a884, xfi_tphy->base + 0x302c);
|
||||
writel(0x00083002, xfi_tphy->base + 0x3024);
|
||||
|
||||
/* Setup RG default value */
|
||||
if (use_lynxi_pcs) {
|
||||
writel(0x00011110, xfi_tphy->base + 0x3010);
|
||||
writel(0x40704000, xfi_tphy->base + 0x3048);
|
||||
} else {
|
||||
writel(0x00022220, xfi_tphy->base + 0x3010);
|
||||
writel(0x0f020a01, xfi_tphy->base + 0x5064);
|
||||
writel(0x06100600, xfi_tphy->base + 0x50b4);
|
||||
if (interface == PHY_INTERFACE_MODE_USXGMII)
|
||||
writel(0x40704000, xfi_tphy->base + 0x3048);
|
||||
else
|
||||
writel(0x47684100, xfi_tphy->base + 0x3048);
|
||||
}
|
||||
|
||||
if (is_1g)
|
||||
writel(0x0000c000, xfi_tphy->base + 0x3064);
|
||||
|
||||
/* Setup RX EQ initial value */
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x3050, 0xa8000000,
|
||||
(interface != PHY_INTERFACE_MODE_10GBASER) ? 0xa8000000 : 0x0);
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0x3054, 0xaa,
|
||||
(interface != PHY_INTERFACE_MODE_10GBASER) ? 0xaa : 0x0);
|
||||
|
||||
if (!use_lynxi_pcs)
|
||||
writel(0x00000f00, xfi_tphy->base + 0x306c);
|
||||
else if (is_2p5g)
|
||||
writel(0x22000f00, xfi_tphy->base + 0x306c);
|
||||
else
|
||||
writel(0x20200f00, xfi_tphy->base + 0x306c);
|
||||
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0xa008, 0x10000, da_war ? 0x10000 : 0x0);
|
||||
|
||||
mtk_phy_update_bits(xfi_tphy->base + 0xa060, 0x50000, use_lynxi_pcs ? 0x50000 : 0x40000);
|
||||
|
||||
/* Setup PHYA speed */
|
||||
mtk_phy_update_bits(xfi_tphy->base + REG_ANA_GLB_D0,
|
||||
XTP_GLB_USXGMII_SEL_MASK | XTP_GLB_USXGMII_EN,
|
||||
is_10g ? XTP_GLB_USXGMII_SEL(0) :
|
||||
is_5g ? XTP_GLB_USXGMII_SEL(1) :
|
||||
is_2p5g ? XTP_GLB_USXGMII_SEL(2) :
|
||||
XTP_GLB_USXGMII_SEL(3));
|
||||
mtk_phy_set_bits(xfi_tphy->base + REG_ANA_GLB_D0, XTP_GLB_USXGMII_EN);
|
||||
|
||||
/* Release reset */
|
||||
mtk_phy_set_bits(xfi_tphy->base + REG_DIG_GLB_70,
|
||||
XTP_PCS_RST_B | XTP_FRC_PCS_RST_B);
|
||||
usleep_range(150, 500);
|
||||
|
||||
/* Switch to P0 */
|
||||
mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_70,
|
||||
XTP_PCS_IN_FR_RG |
|
||||
XTP_FRC_PCS_PWD_ASYNC |
|
||||
XTP_PCS_PWD_ASYNC_MASK |
|
||||
XTP_PCS_PWD_SYNC_MASK |
|
||||
XTP_PCS_UPDT,
|
||||
XTP_PCS_IN_FR_RG |
|
||||
XTP_FRC_PCS_PWD_ASYNC |
|
||||
XTP_PCS_UPDT);
|
||||
usleep_range(1, 5);
|
||||
|
||||
mtk_phy_clear_bits(xfi_tphy->base + REG_DIG_GLB_70, XTP_PCS_UPDT);
|
||||
usleep_range(15, 50);
|
||||
|
||||
if (use_lynxi_pcs) {
|
||||
/* Switch to Gen2 */
|
||||
mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_70,
|
||||
XTP_PCS_MODE_MASK | XTP_PCS_UPDT,
|
||||
XTP_PCS_MODE(1) | XTP_PCS_UPDT);
|
||||
} else {
|
||||
/* Switch to Gen3 */
|
||||
mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_70,
|
||||
XTP_PCS_MODE_MASK | XTP_PCS_UPDT,
|
||||
XTP_PCS_MODE(2) | XTP_PCS_UPDT);
|
||||
}
|
||||
usleep_range(1, 5);
|
||||
|
||||
mtk_phy_clear_bits(xfi_tphy->base + REG_DIG_GLB_70, XTP_PCS_UPDT);
|
||||
|
||||
usleep_range(100, 500);
|
||||
|
||||
/* Enable MAC CK */
|
||||
mtk_phy_set_bits(xfi_tphy->base + REG_DIG_LN_TRX_B0, XTP_LN_TX_MACCK_EN);
|
||||
mtk_phy_clear_bits(xfi_tphy->base + REG_DIG_GLB_F4, XFI_DPHY_AD_SGDT_FRC_EN);
|
||||
|
||||
/* Enable TX data */
|
||||
mtk_phy_set_bits(xfi_tphy->base + REG_DIG_LN_TRX_40,
|
||||
XTP_LN_FRC_TX_DATA_EN | XTP_LN_TX_DATA_EN);
|
||||
usleep_range(400, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* mtk_xfi_tphy_set_mode() - Setup phy for specified interface mode.
|
||||
*
|
||||
* @phy: Phy instance.
|
||||
* @mode: Only PHY_MODE_ETHERNET is supported.
|
||||
* @submode: An Ethernet interface mode.
|
||||
*
|
||||
* Validate selected mode and call function mtk_xfi_tphy_setup().
|
||||
*
|
||||
* Return:
|
||||
* * %0 - OK
|
||||
* * %-EINVAL - invalid mode
|
||||
*/
|
||||
static int mtk_xfi_tphy_set_mode(struct phy *phy, enum phy_mode mode, int
|
||||
submode)
|
||||
{
|
||||
struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
|
||||
|
||||
if (mode != PHY_MODE_ETHERNET)
|
||||
return -EINVAL;
|
||||
|
||||
switch (submode) {
|
||||
case PHY_INTERFACE_MODE_1000BASEX:
|
||||
case PHY_INTERFACE_MODE_2500BASEX:
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
case PHY_INTERFACE_MODE_5GBASER:
|
||||
case PHY_INTERFACE_MODE_10GBASER:
|
||||
case PHY_INTERFACE_MODE_USXGMII:
|
||||
mtk_xfi_tphy_setup(xfi_tphy, submode);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mtk_xfi_tphy_reset() - Reset the phy.
|
||||
*
|
||||
* @phy: Phy instance.
|
||||
*
|
||||
* Reset the phy using the external reset controller.
|
||||
*
|
||||
* Return:
|
||||
* %0 - OK
|
||||
*/
|
||||
static int mtk_xfi_tphy_reset(struct phy *phy)
|
||||
{
|
||||
struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
|
||||
|
||||
reset_control_assert(xfi_tphy->reset);
|
||||
usleep_range(100, 500);
|
||||
reset_control_deassert(xfi_tphy->reset);
|
||||
usleep_range(1, 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mtk_xfi_tphy_power_on() - Power-on the phy.
|
||||
*
|
||||
* @phy: Phy instance.
|
||||
*
|
||||
* Prepare and enable all clocks required for the phy to operate.
|
||||
*
|
||||
* Return:
|
||||
* See clk_bulk_prepare_enable().
|
||||
*/
|
||||
static int mtk_xfi_tphy_power_on(struct phy *phy)
|
||||
{
|
||||
struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
|
||||
|
||||
return clk_bulk_prepare_enable(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* mtk_xfi_tphy_power_off() - Power-off the phy.
|
||||
*
|
||||
* @phy: Phy instance.
|
||||
*
|
||||
* Disable and unprepare all clocks previously enabled.
|
||||
*
|
||||
* Return:
|
||||
* See clk_bulk_prepare_disable().
|
||||
*/
|
||||
static int mtk_xfi_tphy_power_off(struct phy *phy)
|
||||
{
|
||||
struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
|
||||
|
||||
clk_bulk_disable_unprepare(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ops mtk_xfi_tphy_ops = {
|
||||
.power_on = mtk_xfi_tphy_power_on,
|
||||
.power_off = mtk_xfi_tphy_power_off,
|
||||
.set_mode = mtk_xfi_tphy_set_mode,
|
||||
.reset = mtk_xfi_tphy_reset,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
/**
|
||||
* mtk_xfi_tphy_probe() - Probe phy instance from Device Tree.
|
||||
* @pdev: Matching platform device.
|
||||
*
|
||||
* The probe function gets IO resource, clocks, reset controller and
|
||||
* whether the DA work-around for 10GBase-R is required from Device Tree and
|
||||
* allocates memory for holding that information in a struct mtk_xfi_tphy.
|
||||
*
|
||||
* Return:
|
||||
* * %0 - OK
|
||||
* * %-ENODEV - Missing associated Device Tree node (should never happen).
|
||||
* * %-ENOMEM - Out of memory.
|
||||
* * Any error value which devm_platform_ioremap_resource(),
|
||||
* devm_clk_bulk_get(), devm_reset_control_get_exclusive(),
|
||||
* devm_phy_create() or devm_of_phy_provider_register() may return.
|
||||
*/
|
||||
static int mtk_xfi_tphy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct phy_provider *phy_provider;
|
||||
struct mtk_xfi_tphy *xfi_tphy;
|
||||
struct phy *phy;
|
||||
int ret;
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
xfi_tphy = devm_kzalloc(&pdev->dev, sizeof(*xfi_tphy), GFP_KERNEL);
|
||||
if (!xfi_tphy)
|
||||
return -ENOMEM;
|
||||
|
||||
xfi_tphy->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(xfi_tphy->base))
|
||||
return PTR_ERR(xfi_tphy->base);
|
||||
|
||||
xfi_tphy->dev = &pdev->dev;
|
||||
xfi_tphy->clocks[0].id = "topxtal";
|
||||
xfi_tphy->clocks[1].id = "xfipll";
|
||||
ret = devm_clk_bulk_get(&pdev->dev, MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
xfi_tphy->reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
if (IS_ERR(xfi_tphy->reset))
|
||||
return PTR_ERR(xfi_tphy->reset);
|
||||
|
||||
xfi_tphy->da_war = of_property_read_bool(np, "mediatek,usxgmii-performance-errata");
|
||||
|
||||
phy = devm_phy_create(&pdev->dev, NULL, &mtk_xfi_tphy_ops);
|
||||
if (IS_ERR(phy))
|
||||
return PTR_ERR(phy);
|
||||
|
||||
phy_set_drvdata(phy, xfi_tphy);
|
||||
phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
|
||||
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
}
|
||||
|
||||
static const struct of_device_id mtk_xfi_tphy_match[] = {
|
||||
{ .compatible = "mediatek,mt7988-xfi-tphy", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_xfi_tphy_match);
|
||||
|
||||
static struct platform_driver mtk_xfi_tphy_driver = {
|
||||
.probe = mtk_xfi_tphy_probe,
|
||||
.driver = {
|
||||
.name = "mtk-xfi-tphy",
|
||||
.of_match_table = mtk_xfi_tphy_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(mtk_xfi_tphy_driver);
|
||||
|
||||
MODULE_DESCRIPTION("MediaTek 10GE SerDes XFI T-PHY driver");
|
||||
MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
|
||||
MODULE_AUTHOR("Bc-bocun Chen <bc-bocun.chen@mediatek.com>");
|
||||
MODULE_LICENSE("GPL");
|
@ -20,7 +20,12 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
static struct class *phy_class;
|
||||
static void phy_release(struct device *dev);
|
||||
static const struct class phy_class = {
|
||||
.name = "phy",
|
||||
.dev_release = phy_release,
|
||||
};
|
||||
|
||||
static struct dentry *phy_debugfs_root;
|
||||
static DEFINE_MUTEX(phy_provider_mutex);
|
||||
static LIST_HEAD(phy_provider_list);
|
||||
@ -753,7 +758,7 @@ struct phy *of_phy_simple_xlate(struct device *dev,
|
||||
struct phy *phy;
|
||||
struct class_dev_iter iter;
|
||||
|
||||
class_dev_iter_init(&iter, phy_class, NULL, NULL);
|
||||
class_dev_iter_init(&iter, &phy_class, NULL, NULL);
|
||||
while ((dev = class_dev_iter_next(&iter))) {
|
||||
phy = to_phy(dev);
|
||||
if (args->np != phy->dev.of_node)
|
||||
@ -1016,7 +1021,7 @@ struct phy *phy_create(struct device *dev, struct device_node *node,
|
||||
device_initialize(&phy->dev);
|
||||
mutex_init(&phy->mutex);
|
||||
|
||||
phy->dev.class = phy_class;
|
||||
phy->dev.class = &phy_class;
|
||||
phy->dev.parent = dev;
|
||||
phy->dev.of_node = node ?: dev->of_node;
|
||||
phy->id = id;
|
||||
@ -1285,14 +1290,13 @@ static void phy_release(struct device *dev)
|
||||
|
||||
static int __init phy_core_init(void)
|
||||
{
|
||||
phy_class = class_create("phy");
|
||||
if (IS_ERR(phy_class)) {
|
||||
pr_err("failed to create phy class --> %ld\n",
|
||||
PTR_ERR(phy_class));
|
||||
return PTR_ERR(phy_class);
|
||||
}
|
||||
int err;
|
||||
|
||||
phy_class->dev_release = phy_release;
|
||||
err = class_register(&phy_class);
|
||||
if (err) {
|
||||
pr_err("failed to register phy class");
|
||||
return err;
|
||||
}
|
||||
|
||||
phy_debugfs_root = debugfs_create_dir("phy", NULL);
|
||||
|
||||
@ -1303,6 +1307,6 @@ device_initcall(phy_core_init);
|
||||
static void __exit phy_core_exit(void)
|
||||
{
|
||||
debugfs_remove_recursive(phy_debugfs_root);
|
||||
class_destroy(phy_class);
|
||||
class_unregister(&phy_class);
|
||||
}
|
||||
module_exit(phy_core_exit);
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "phy-qcom-qmp-dp-phy.h"
|
||||
#include "phy-qcom-qmp-qserdes-com-v4.h"
|
||||
#include "phy-qcom-qmp-qserdes-com-v6.h"
|
||||
|
||||
/* EDP_PHY registers */
|
||||
#define DP_PHY_CFG 0x0010
|
||||
@ -77,9 +78,20 @@ struct qcom_edp_swing_pre_emph_cfg {
|
||||
const u8 (*pre_emphasis_hbr3_hbr2)[4][4];
|
||||
};
|
||||
|
||||
struct qcom_edp;
|
||||
|
||||
struct phy_ver_ops {
|
||||
int (*com_power_on)(const struct qcom_edp *edp);
|
||||
int (*com_resetsm_cntrl)(const struct qcom_edp *edp);
|
||||
int (*com_bias_en_clkbuflr)(const struct qcom_edp *edp);
|
||||
int (*com_configure_pll)(const struct qcom_edp *edp);
|
||||
int (*com_configure_ssc)(const struct qcom_edp *edp);
|
||||
};
|
||||
|
||||
struct qcom_edp_phy_cfg {
|
||||
bool is_edp;
|
||||
const struct qcom_edp_swing_pre_emph_cfg *swing_pre_emph_cfg;
|
||||
const struct phy_ver_ops *ver_ops;
|
||||
};
|
||||
|
||||
struct qcom_edp {
|
||||
@ -174,18 +186,6 @@ static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg = {
|
||||
.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3,
|
||||
};
|
||||
|
||||
static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = {
|
||||
};
|
||||
|
||||
static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
|
||||
.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
|
||||
};
|
||||
|
||||
static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = {
|
||||
.is_edp = true,
|
||||
.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
|
||||
};
|
||||
|
||||
static int qcom_edp_phy_init(struct phy *phy)
|
||||
{
|
||||
struct qcom_edp *edp = phy_get_drvdata(phy);
|
||||
@ -204,8 +204,9 @@ static int qcom_edp_phy_init(struct phy *phy)
|
||||
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
|
||||
edp->edp + DP_PHY_PD_CTL);
|
||||
|
||||
/* Turn on BIAS current for PHY/PLL */
|
||||
writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
|
||||
ret = edp->cfg->ver_ops->com_bias_en_clkbuflr(edp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
|
||||
msleep(20);
|
||||
@ -312,6 +313,84 @@ static int qcom_edp_phy_configure(struct phy *phy, union phy_configure_opts *opt
|
||||
}
|
||||
|
||||
static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
|
||||
{
|
||||
return edp->cfg->ver_ops->com_configure_ssc(edp);
|
||||
}
|
||||
|
||||
static int qcom_edp_configure_pll(const struct qcom_edp *edp)
|
||||
{
|
||||
return edp->cfg->ver_ops->com_configure_pll(edp);
|
||||
}
|
||||
|
||||
static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel_freq)
|
||||
{
|
||||
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
|
||||
u32 vco_div;
|
||||
|
||||
switch (dp_opts->link_rate) {
|
||||
case 1620:
|
||||
vco_div = 0x1;
|
||||
*pixel_freq = 1620000000UL / 2;
|
||||
break;
|
||||
|
||||
case 2700:
|
||||
vco_div = 0x1;
|
||||
*pixel_freq = 2700000000UL / 2;
|
||||
break;
|
||||
|
||||
case 5400:
|
||||
vco_div = 0x2;
|
||||
*pixel_freq = 5400000000UL / 4;
|
||||
break;
|
||||
|
||||
case 8100:
|
||||
vco_div = 0x0;
|
||||
*pixel_freq = 8100000000UL / 6;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Other link rates aren't supported */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel(vco_div, edp->edp + DP_PHY_VCO_DIV);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_edp_phy_power_on_v4(const struct qcom_edp *edp)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
|
||||
DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
|
||||
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
|
||||
edp->edp + DP_PHY_PD_CTL);
|
||||
writel(0xfc, edp->edp + DP_PHY_MODE);
|
||||
|
||||
return readl_poll_timeout(edp->pll + QSERDES_V4_COM_CMN_STATUS,
|
||||
val, val & BIT(7), 5, 200);
|
||||
}
|
||||
|
||||
static int qcom_edp_phy_com_resetsm_cntrl_v4(const struct qcom_edp *edp)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
writel(0x20, edp->pll + QSERDES_V4_COM_RESETSM_CNTRL);
|
||||
|
||||
return readl_poll_timeout(edp->pll + QSERDES_V4_COM_C_READY_STATUS,
|
||||
val, val & BIT(0), 500, 10000);
|
||||
}
|
||||
|
||||
static int qcom_edp_com_bias_en_clkbuflr_v4(const struct qcom_edp *edp)
|
||||
{
|
||||
/* Turn on BIAS current for PHY/PLL */
|
||||
writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_edp_com_configure_ssc_v4(const struct qcom_edp *edp)
|
||||
{
|
||||
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
|
||||
u32 step1;
|
||||
@ -345,7 +424,7 @@ static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_edp_configure_pll(const struct qcom_edp *edp)
|
||||
static int qcom_edp_com_configure_pll_v4(const struct qcom_edp *edp)
|
||||
{
|
||||
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
|
||||
u32 div_frac_start2_mode0;
|
||||
@ -431,52 +510,32 @@ static int qcom_edp_configure_pll(const struct qcom_edp *edp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel_freq)
|
||||
static const struct phy_ver_ops qcom_edp_phy_ops_v4 = {
|
||||
.com_power_on = qcom_edp_phy_power_on_v4,
|
||||
.com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v4,
|
||||
.com_bias_en_clkbuflr = qcom_edp_com_bias_en_clkbuflr_v4,
|
||||
.com_configure_pll = qcom_edp_com_configure_pll_v4,
|
||||
.com_configure_ssc = qcom_edp_com_configure_ssc_v4,
|
||||
};
|
||||
|
||||
static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = {
|
||||
.ver_ops = &qcom_edp_phy_ops_v4,
|
||||
};
|
||||
|
||||
static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
|
||||
.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
|
||||
.ver_ops = &qcom_edp_phy_ops_v4,
|
||||
};
|
||||
|
||||
static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = {
|
||||
.is_edp = true,
|
||||
.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
|
||||
.ver_ops = &qcom_edp_phy_ops_v4,
|
||||
};
|
||||
|
||||
static int qcom_edp_phy_power_on_v6(const struct qcom_edp *edp)
|
||||
{
|
||||
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
|
||||
u32 vco_div;
|
||||
|
||||
switch (dp_opts->link_rate) {
|
||||
case 1620:
|
||||
vco_div = 0x1;
|
||||
*pixel_freq = 1620000000UL / 2;
|
||||
break;
|
||||
|
||||
case 2700:
|
||||
vco_div = 0x1;
|
||||
*pixel_freq = 2700000000UL / 2;
|
||||
break;
|
||||
|
||||
case 5400:
|
||||
vco_div = 0x2;
|
||||
*pixel_freq = 5400000000UL / 4;
|
||||
break;
|
||||
|
||||
case 8100:
|
||||
vco_div = 0x0;
|
||||
*pixel_freq = 8100000000UL / 6;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Other link rates aren't supported */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel(vco_div, edp->edp + DP_PHY_VCO_DIV);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_edp_phy_power_on(struct phy *phy)
|
||||
{
|
||||
const struct qcom_edp *edp = phy_get_drvdata(phy);
|
||||
u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
|
||||
unsigned long pixel_freq;
|
||||
u8 ldo_config = 0x0;
|
||||
int timeout;
|
||||
int ret;
|
||||
u32 val;
|
||||
u8 cfg1;
|
||||
|
||||
writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
|
||||
DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
|
||||
@ -484,11 +543,187 @@ static int qcom_edp_phy_power_on(struct phy *phy)
|
||||
edp->edp + DP_PHY_PD_CTL);
|
||||
writel(0xfc, edp->edp + DP_PHY_MODE);
|
||||
|
||||
timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_CMN_STATUS,
|
||||
return readl_poll_timeout(edp->pll + QSERDES_V6_COM_CMN_STATUS,
|
||||
val, val & BIT(7), 5, 200);
|
||||
if (timeout)
|
||||
return timeout;
|
||||
}
|
||||
|
||||
static int qcom_edp_phy_com_resetsm_cntrl_v6(const struct qcom_edp *edp)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
writel(0x20, edp->pll + QSERDES_V6_COM_RESETSM_CNTRL);
|
||||
|
||||
return readl_poll_timeout(edp->pll + QSERDES_V6_COM_C_READY_STATUS,
|
||||
val, val & BIT(0), 500, 10000);
|
||||
}
|
||||
|
||||
static int qcom_edp_com_bias_en_clkbuflr_v6(const struct qcom_edp *edp)
|
||||
{
|
||||
/* Turn on BIAS current for PHY/PLL */
|
||||
writel(0x1f, edp->pll + QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_edp_com_configure_ssc_v6(const struct qcom_edp *edp)
|
||||
{
|
||||
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
|
||||
u32 step1;
|
||||
u32 step2;
|
||||
|
||||
switch (dp_opts->link_rate) {
|
||||
case 1620:
|
||||
case 2700:
|
||||
case 8100:
|
||||
step1 = 0x92;
|
||||
step2 = 0x01;
|
||||
break;
|
||||
|
||||
case 5400:
|
||||
step1 = 0x18;
|
||||
step2 = 0x02;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Other link rates aren't supported */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel(0x01, edp->pll + QSERDES_V6_COM_SSC_EN_CENTER);
|
||||
writel(0x00, edp->pll + QSERDES_V6_COM_SSC_ADJ_PER1);
|
||||
writel(0x36, edp->pll + QSERDES_V6_COM_SSC_PER1);
|
||||
writel(0x01, edp->pll + QSERDES_V6_COM_SSC_PER2);
|
||||
writel(step1, edp->pll + QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0);
|
||||
writel(step2, edp->pll + QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_edp_com_configure_pll_v6(const struct qcom_edp *edp)
|
||||
{
|
||||
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
|
||||
u32 div_frac_start2_mode0;
|
||||
u32 div_frac_start3_mode0;
|
||||
u32 dec_start_mode0;
|
||||
u32 lock_cmp1_mode0;
|
||||
u32 lock_cmp2_mode0;
|
||||
u32 code1_mode0;
|
||||
u32 code2_mode0;
|
||||
u32 hsclk_sel;
|
||||
|
||||
switch (dp_opts->link_rate) {
|
||||
case 1620:
|
||||
hsclk_sel = 0x5;
|
||||
dec_start_mode0 = 0x34;
|
||||
div_frac_start2_mode0 = 0xc0;
|
||||
div_frac_start3_mode0 = 0x0b;
|
||||
lock_cmp1_mode0 = 0x37;
|
||||
lock_cmp2_mode0 = 0x04;
|
||||
code1_mode0 = 0x71;
|
||||
code2_mode0 = 0x0c;
|
||||
break;
|
||||
|
||||
case 2700:
|
||||
hsclk_sel = 0x3;
|
||||
dec_start_mode0 = 0x34;
|
||||
div_frac_start2_mode0 = 0xc0;
|
||||
div_frac_start3_mode0 = 0x0b;
|
||||
lock_cmp1_mode0 = 0x07;
|
||||
lock_cmp2_mode0 = 0x07;
|
||||
code1_mode0 = 0x71;
|
||||
code2_mode0 = 0x0c;
|
||||
break;
|
||||
|
||||
case 5400:
|
||||
hsclk_sel = 0x1;
|
||||
dec_start_mode0 = 0x46;
|
||||
div_frac_start2_mode0 = 0x00;
|
||||
div_frac_start3_mode0 = 0x05;
|
||||
lock_cmp1_mode0 = 0x0f;
|
||||
lock_cmp2_mode0 = 0x0e;
|
||||
code1_mode0 = 0x97;
|
||||
code2_mode0 = 0x10;
|
||||
break;
|
||||
|
||||
case 8100:
|
||||
hsclk_sel = 0x0;
|
||||
dec_start_mode0 = 0x34;
|
||||
div_frac_start2_mode0 = 0xc0;
|
||||
div_frac_start3_mode0 = 0x0b;
|
||||
lock_cmp1_mode0 = 0x17;
|
||||
lock_cmp2_mode0 = 0x15;
|
||||
code1_mode0 = 0x71;
|
||||
code2_mode0 = 0x0c;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Other link rates aren't supported */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel(0x01, edp->pll + QSERDES_V6_COM_SVS_MODE_CLK_SEL);
|
||||
writel(0x0b, edp->pll + QSERDES_V6_COM_SYSCLK_EN_SEL);
|
||||
writel(0x02, edp->pll + QSERDES_V6_COM_SYS_CLK_CTRL);
|
||||
writel(0x0c, edp->pll + QSERDES_V6_COM_CLK_ENABLE1);
|
||||
writel(0x06, edp->pll + QSERDES_V6_COM_SYSCLK_BUF_ENABLE);
|
||||
writel(0x30, edp->pll + QSERDES_V6_COM_CLK_SELECT);
|
||||
writel(hsclk_sel, edp->pll + QSERDES_V6_COM_HSCLK_SEL_1);
|
||||
writel(0x07, edp->pll + QSERDES_V6_COM_PLL_IVCO);
|
||||
writel(0x08, edp->pll + QSERDES_V6_COM_LOCK_CMP_EN);
|
||||
writel(0x36, edp->pll + QSERDES_V6_COM_PLL_CCTRL_MODE0);
|
||||
writel(0x16, edp->pll + QSERDES_V6_COM_PLL_RCTRL_MODE0);
|
||||
writel(0x06, edp->pll + QSERDES_V6_COM_CP_CTRL_MODE0);
|
||||
writel(dec_start_mode0, edp->pll + QSERDES_V6_COM_DEC_START_MODE0);
|
||||
writel(0x00, edp->pll + QSERDES_V6_COM_DIV_FRAC_START1_MODE0);
|
||||
writel(div_frac_start2_mode0, edp->pll + QSERDES_V6_COM_DIV_FRAC_START2_MODE0);
|
||||
writel(div_frac_start3_mode0, edp->pll + QSERDES_V6_COM_DIV_FRAC_START3_MODE0);
|
||||
writel(0x12, edp->pll + QSERDES_V6_COM_CMN_CONFIG_1);
|
||||
writel(0x3f, edp->pll + QSERDES_V6_COM_INTEGLOOP_GAIN0_MODE0);
|
||||
writel(0x00, edp->pll + QSERDES_V6_COM_INTEGLOOP_GAIN1_MODE0);
|
||||
writel(0x00, edp->pll + QSERDES_V6_COM_VCO_TUNE_MAP);
|
||||
writel(lock_cmp1_mode0, edp->pll + QSERDES_V6_COM_LOCK_CMP1_MODE0);
|
||||
writel(lock_cmp2_mode0, edp->pll + QSERDES_V6_COM_LOCK_CMP2_MODE0);
|
||||
|
||||
writel(0x0a, edp->pll + QSERDES_V6_COM_BG_TIMER);
|
||||
writel(0x14, edp->pll + QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0);
|
||||
writel(0x00, edp->pll + QSERDES_V6_COM_VCO_TUNE_CTRL);
|
||||
writel(0x1f, edp->pll + QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN);
|
||||
writel(0x0f, edp->pll + QSERDES_V6_COM_CORE_CLK_EN);
|
||||
writel(0xa0, edp->pll + QSERDES_V6_COM_VCO_TUNE1_MODE0);
|
||||
writel(0x03, edp->pll + QSERDES_V6_COM_VCO_TUNE2_MODE0);
|
||||
|
||||
writel(code1_mode0, edp->pll + QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0);
|
||||
writel(code2_mode0, edp->pll + QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ver_ops qcom_edp_phy_ops_v6 = {
|
||||
.com_power_on = qcom_edp_phy_power_on_v6,
|
||||
.com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v6,
|
||||
.com_bias_en_clkbuflr = qcom_edp_com_bias_en_clkbuflr_v6,
|
||||
.com_configure_pll = qcom_edp_com_configure_pll_v6,
|
||||
.com_configure_ssc = qcom_edp_com_configure_ssc_v6,
|
||||
};
|
||||
|
||||
static struct qcom_edp_phy_cfg x1e80100_phy_cfg = {
|
||||
.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
|
||||
.ver_ops = &qcom_edp_phy_ops_v6,
|
||||
};
|
||||
|
||||
static int qcom_edp_phy_power_on(struct phy *phy)
|
||||
{
|
||||
const struct qcom_edp *edp = phy_get_drvdata(phy);
|
||||
u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
|
||||
unsigned long pixel_freq;
|
||||
u8 ldo_config = 0x0;
|
||||
int ret;
|
||||
u32 val;
|
||||
u8 cfg1;
|
||||
|
||||
ret = edp->cfg->ver_ops->com_power_on(edp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
|
||||
ldo_config = 0x1;
|
||||
@ -535,12 +770,9 @@ static int qcom_edp_phy_power_on(struct phy *phy)
|
||||
writel(0x01, edp->edp + DP_PHY_CFG);
|
||||
writel(0x09, edp->edp + DP_PHY_CFG);
|
||||
|
||||
writel(0x20, edp->pll + QSERDES_V4_COM_RESETSM_CNTRL);
|
||||
|
||||
timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_C_READY_STATUS,
|
||||
val, val & BIT(0), 500, 10000);
|
||||
if (timeout)
|
||||
return timeout;
|
||||
ret = edp->cfg->ver_ops->com_resetsm_cntrl(edp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
writel(0x19, edp->edp + DP_PHY_CFG);
|
||||
writel(0x1f, edp->tx0 + TXn_HIGHZ_DRVR_EN);
|
||||
@ -880,6 +1112,7 @@ static const struct of_device_id qcom_edp_phy_match_table[] = {
|
||||
{ .compatible = "qcom,sc8180x-edp-phy", .data = &sc7280_dp_phy_cfg, },
|
||||
{ .compatible = "qcom,sc8280xp-dp-phy", .data = &sc8280xp_dp_phy_cfg, },
|
||||
{ .compatible = "qcom,sc8280xp-edp-phy", .data = &sc8280xp_edp_phy_cfg, },
|
||||
{ .compatible = "qcom,x1e80100-dp-phy", .data = &x1e80100_phy_cfg, },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_edp_phy_match_table);
|
||||
|
@ -88,6 +88,12 @@ static const u32 pm8550b_init_tbl[NUM_TUNE_FIELDS] = {
|
||||
[TUNE_USB2_PREEM] = 0x5,
|
||||
};
|
||||
|
||||
static const u32 smb2360_init_tbl[NUM_TUNE_FIELDS] = {
|
||||
[TUNE_IUSB2] = 0x5,
|
||||
[TUNE_SQUELCH_U] = 0x3,
|
||||
[TUNE_USB2_PREEM] = 0x2,
|
||||
};
|
||||
|
||||
static const struct eusb2_repeater_cfg pm8550b_eusb2_cfg = {
|
||||
.init_tbl = pm8550b_init_tbl,
|
||||
.init_tbl_num = ARRAY_SIZE(pm8550b_init_tbl),
|
||||
@ -95,6 +101,13 @@ static const struct eusb2_repeater_cfg pm8550b_eusb2_cfg = {
|
||||
.num_vregs = ARRAY_SIZE(pm8550b_vreg_l),
|
||||
};
|
||||
|
||||
static const struct eusb2_repeater_cfg smb2360_eusb2_cfg = {
|
||||
.init_tbl = smb2360_init_tbl,
|
||||
.init_tbl_num = ARRAY_SIZE(smb2360_init_tbl),
|
||||
.vreg_list = pm8550b_vreg_l,
|
||||
.num_vregs = ARRAY_SIZE(pm8550b_vreg_l),
|
||||
};
|
||||
|
||||
static int eusb2_repeater_init_vregs(struct eusb2_repeater *rptr)
|
||||
{
|
||||
int num = rptr->cfg->num_vregs;
|
||||
@ -271,6 +284,10 @@ static const struct of_device_id eusb2_repeater_of_match_table[] = {
|
||||
.compatible = "qcom,pm8550b-eusb2-repeater",
|
||||
.data = &pm8550b_eusb2_cfg,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,smb2360-eusb2-repeater",
|
||||
.data = &smb2360_eusb2_cfg,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, eusb2_repeater_of_match_table);
|
||||
|
@ -1382,6 +1382,13 @@ static const u8 qmp_dp_v5_voltage_swing_hbr_rbr[4][4] = {
|
||||
{ 0x3f, 0xff, 0xff, 0xff }
|
||||
};
|
||||
|
||||
static const u8 qmp_dp_v6_voltage_swing_hbr_rbr[4][4] = {
|
||||
{ 0x27, 0x2f, 0x36, 0x3f },
|
||||
{ 0x31, 0x3e, 0x3f, 0xff },
|
||||
{ 0x36, 0x3f, 0xff, 0xff },
|
||||
{ 0x3f, 0xff, 0xff, 0xff }
|
||||
};
|
||||
|
||||
static const u8 qmp_dp_v6_pre_emphasis_hbr_rbr[4][4] = {
|
||||
{ 0x20, 0x2d, 0x34, 0x3a },
|
||||
{ 0x20, 0x2e, 0x35, 0xff },
|
||||
@ -2001,6 +2008,51 @@ static const struct qmp_phy_cfg sm8550_usb3dpphy_cfg = {
|
||||
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8650_usb3dpphy_cfg = {
|
||||
.offsets = &qmp_combo_offsets_v3,
|
||||
|
||||
.serdes_tbl = sm8550_usb3_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8550_usb3_serdes_tbl),
|
||||
.tx_tbl = sm8550_usb3_tx_tbl,
|
||||
.tx_tbl_num = ARRAY_SIZE(sm8550_usb3_tx_tbl),
|
||||
.rx_tbl = sm8550_usb3_rx_tbl,
|
||||
.rx_tbl_num = ARRAY_SIZE(sm8550_usb3_rx_tbl),
|
||||
.pcs_tbl = sm8550_usb3_pcs_tbl,
|
||||
.pcs_tbl_num = ARRAY_SIZE(sm8550_usb3_pcs_tbl),
|
||||
.pcs_usb_tbl = sm8550_usb3_pcs_usb_tbl,
|
||||
.pcs_usb_tbl_num = ARRAY_SIZE(sm8550_usb3_pcs_usb_tbl),
|
||||
|
||||
.dp_serdes_tbl = qmp_v6_dp_serdes_tbl,
|
||||
.dp_serdes_tbl_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl),
|
||||
.dp_tx_tbl = qmp_v6_dp_tx_tbl,
|
||||
.dp_tx_tbl_num = ARRAY_SIZE(qmp_v6_dp_tx_tbl),
|
||||
|
||||
.serdes_tbl_rbr = qmp_v6_dp_serdes_tbl_rbr,
|
||||
.serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_rbr),
|
||||
.serdes_tbl_hbr = qmp_v6_dp_serdes_tbl_hbr,
|
||||
.serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr),
|
||||
.serdes_tbl_hbr2 = qmp_v6_dp_serdes_tbl_hbr2,
|
||||
.serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr2),
|
||||
.serdes_tbl_hbr3 = qmp_v6_dp_serdes_tbl_hbr3,
|
||||
.serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr3),
|
||||
|
||||
.swing_hbr_rbr = &qmp_dp_v6_voltage_swing_hbr_rbr,
|
||||
.pre_emphasis_hbr_rbr = &qmp_dp_v6_pre_emphasis_hbr_rbr,
|
||||
.swing_hbr3_hbr2 = &qmp_dp_v5_voltage_swing_hbr3_hbr2,
|
||||
.pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2,
|
||||
|
||||
.dp_aux_init = qmp_v4_dp_aux_init,
|
||||
.configure_dp_tx = qmp_v4_configure_dp_tx,
|
||||
.configure_dp_phy = qmp_v4_configure_dp_phy,
|
||||
.calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
|
||||
|
||||
.regs = qmp_v6_usb3phy_regs_layout,
|
||||
.reset_list = msm8996_usb3phy_reset_l,
|
||||
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
|
||||
.vreg_list = qmp_phy_vreg_l,
|
||||
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
|
||||
};
|
||||
|
||||
static int qmp_combo_dp_serdes_init(struct qmp_combo *qmp)
|
||||
{
|
||||
const struct qmp_phy_cfg *cfg = qmp->cfg;
|
||||
@ -2437,8 +2489,6 @@ static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp)
|
||||
writel(0x20, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]);
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3631,7 +3681,7 @@ static const struct of_device_id qmp_combo_of_match_table[] = {
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,sm8650-qmp-usb3-dp-phy",
|
||||
.data = &sm8550_usb3dpphy_cfg,
|
||||
.data = &sm8650_usb3dpphy_cfg,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,x1e80100-qmp-usb3-dp-phy",
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <linux/reset.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/phy/phy-qcom-qmp.h>
|
||||
|
||||
#include "phy-qcom-qmp-common.h"
|
||||
|
||||
#include "phy-qcom-qmp.h"
|
||||
@ -2246,6 +2248,7 @@ static const struct qmp_phy_init_tbl sa8775p_qmp_gen4x4_pcie_pcs_alt_tbl[] = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sa8775p_qmp_gen4x4_pcie_serdes_alt_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36),
|
||||
@ -2272,7 +2275,6 @@ static const struct qmp_phy_init_tbl sa8775p_qmp_gen4x4_pcie_rc_serdes_alt_tbl[]
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x97),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x0c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06),
|
||||
@ -2389,6 +2391,9 @@ struct qmp_phy_cfg {
|
||||
|
||||
/* QMP PHY pipe clock interface rate */
|
||||
unsigned long pipe_clock_rate;
|
||||
|
||||
/* QMP PHY AUX clock interface rate */
|
||||
unsigned long aux_clock_rate;
|
||||
};
|
||||
|
||||
struct qmp_pcie {
|
||||
@ -2420,6 +2425,7 @@ struct qmp_pcie {
|
||||
int mode;
|
||||
|
||||
struct clk_fixed_rate pipe_clk_fixed;
|
||||
struct clk_fixed_rate aux_clk_fixed;
|
||||
};
|
||||
|
||||
static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
|
||||
@ -3135,6 +3141,9 @@ static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = {
|
||||
|
||||
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
|
||||
.phy_status = PHYSTATUS_4_20,
|
||||
|
||||
/* 20MHz PHY AUX Clock */
|
||||
.aux_clock_rate = 20000000,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8550_qmp_gen3x2_pciephy_cfg = {
|
||||
@ -3192,6 +3201,9 @@ static const struct qmp_phy_cfg sm8550_qmp_gen4x2_pciephy_cfg = {
|
||||
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
|
||||
.phy_status = PHYSTATUS_4_20,
|
||||
.has_nocsr_reset = true,
|
||||
|
||||
/* 20MHz PHY AUX Clock */
|
||||
.aux_clock_rate = 20000000,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8650_qmp_gen4x2_pciephy_cfg = {
|
||||
@ -3222,6 +3234,9 @@ static const struct qmp_phy_cfg sm8650_qmp_gen4x2_pciephy_cfg = {
|
||||
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
|
||||
.phy_status = PHYSTATUS_4_20,
|
||||
.has_nocsr_reset = true,
|
||||
|
||||
/* 20MHz PHY AUX Clock */
|
||||
.aux_clock_rate = 20000000,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sa8775p_qmp_gen4x2_pciephy_cfg = {
|
||||
@ -3291,6 +3306,13 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = {
|
||||
.pcs_misc_num = ARRAY_SIZE(sa8775p_qmp_gen4_pcie_rc_pcs_misc_tbl),
|
||||
},
|
||||
|
||||
.tbls_ep = &(const struct qmp_phy_cfg_tbls) {
|
||||
.serdes = sa8775p_qmp_gen4x2_pcie_ep_serdes_alt_tbl,
|
||||
.serdes_num = ARRAY_SIZE(sa8775p_qmp_gen4x2_pcie_ep_serdes_alt_tbl),
|
||||
.pcs_misc = sm8450_qmp_gen4x2_pcie_ep_pcs_misc_tbl,
|
||||
.pcs_misc_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_ep_pcs_misc_tbl),
|
||||
},
|
||||
|
||||
.reset_list = sdm845_pciephy_reset_l,
|
||||
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
|
||||
.vreg_list = qmp_phy_vreg_l,
|
||||
@ -3664,7 +3686,7 @@ static int phy_pipe_clk_register(struct qmp_pcie *qmp, struct device_node *np)
|
||||
struct clk_init_data init = { };
|
||||
int ret;
|
||||
|
||||
ret = of_property_read_string(np, "clock-output-names", &init.name);
|
||||
ret = of_property_read_string_index(np, "clock-output-names", 0, &init.name);
|
||||
if (ret) {
|
||||
dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np);
|
||||
return ret;
|
||||
@ -3683,13 +3705,86 @@ static int phy_pipe_clk_register(struct qmp_pcie *qmp, struct device_node *np)
|
||||
|
||||
fixed->hw.init = &init;
|
||||
|
||||
ret = devm_clk_hw_register(qmp->dev, &fixed->hw);
|
||||
return devm_clk_hw_register(qmp->dev, &fixed->hw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a fixed rate PHY aux clock.
|
||||
*
|
||||
* The <s>_phy_aux_clksrc generated by PHY goes to the GCC that gate
|
||||
* controls it. The <s>_phy_aux_clk coming out of the GCC is requested
|
||||
* by the PHY driver for its operations.
|
||||
* We register the <s>_phy_aux_clksrc here. The gcc driver takes care
|
||||
* of assigning this <s>_phy_aux_clksrc as parent to <s>_phy_aux_clk.
|
||||
* Below picture shows this relationship.
|
||||
*
|
||||
* +---------------+
|
||||
* | PHY block |<<---------------------------------------------+
|
||||
* | | |
|
||||
* | +-------+ | +-----+ |
|
||||
* I/P---^-->| PLL |---^--->phy_aux_clksrc--->| GCC |--->phy_aux_clk---+
|
||||
* clk | +-------+ | +-----+
|
||||
* +---------------+
|
||||
*/
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
init.ops = &clk_fixed_rate_ops;
|
||||
|
||||
fixed->fixed_rate = qmp->cfg->aux_clock_rate;
|
||||
fixed->hw.init = &init;
|
||||
|
||||
return devm_clk_hw_register(qmp->dev, &fixed->hw);
|
||||
}
|
||||
|
||||
static struct clk_hw *qmp_pcie_clk_hw_get(struct of_phandle_args *clkspec, void *data)
|
||||
{
|
||||
struct qmp_pcie *qmp = data;
|
||||
|
||||
/* Support legacy bindings */
|
||||
if (!clkspec->args_count)
|
||||
return &qmp->pipe_clk_fixed.hw;
|
||||
|
||||
switch (clkspec->args[0]) {
|
||||
case QMP_PCIE_PIPE_CLK:
|
||||
return &qmp->pipe_clk_fixed.hw;
|
||||
case QMP_PCIE_PHY_AUX_CLK:
|
||||
return &qmp->aux_clk_fixed.hw;
|
||||
}
|
||||
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static int qmp_pcie_register_clocks(struct qmp_pcie *qmp, struct device_node *np)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = phy_pipe_clk_register(qmp, np);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (qmp->cfg->aux_clock_rate) {
|
||||
ret = phy_aux_clk_register(qmp, np);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_clk_add_hw_provider(np, qmp_pcie_clk_hw_get, qmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &qmp->pipe_clk_fixed.hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Roll a devm action because the clock provider is the child node, but
|
||||
@ -3899,7 +3994,7 @@ static int qmp_pcie_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto err_node_put;
|
||||
|
||||
ret = phy_pipe_clk_register(qmp, np);
|
||||
ret = qmp_pcie_register_clocks(qmp, np);
|
||||
if (ret)
|
||||
goto err_node_put;
|
||||
|
||||
|
@ -30,5 +30,9 @@
|
||||
#define QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1 0x1f4
|
||||
#define QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1 0x1fc
|
||||
#define QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME 0x220
|
||||
#define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S4 0x240
|
||||
#define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S5 0x244
|
||||
#define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S6 0x248
|
||||
#define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S7 0x24c
|
||||
|
||||
#endif
|
||||
|
@ -25,12 +25,15 @@
|
||||
#define QSERDES_UFS_V6_RX_UCDR_SO_GAIN_RATE4 0xf0
|
||||
#define QSERDES_UFS_V6_RX_UCDR_PI_CONTROLS 0xf4
|
||||
#define QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL 0x178
|
||||
#define QSERDES_UFS_V6_RX_RX_EQU_ADAPTOR_CNTRL4 0x1ac
|
||||
#define QSERDES_UFS_V6_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x1bc
|
||||
#define QSERDES_UFS_V6_RX_INTERFACE_MODE 0x1e0
|
||||
#define QSERDES_UFS_V6_RX_OFFSET_ADAPTOR_CNTRL3 0x1c4
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0 0x208
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1 0x20c
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B2 0x210
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B3 0x214
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B4 0x218
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B6 0x220
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE2_B3 0x238
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE2_B6 0x244
|
||||
@ -38,6 +41,9 @@
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE3_B4 0x260
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE3_B5 0x264
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE3_B8 0x270
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE4_B0 0x274
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE4_B1 0x278
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE4_B2 0x27c
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE4_B3 0x280
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE4_B4 0x284
|
||||
#define QSERDES_UFS_V6_RX_MODE_RATE4_B6 0x28c
|
||||
|
@ -722,6 +722,38 @@ static const struct qmp_phy_init_tbl sm8350_ufsphy_g4_pcs[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_BIST_FIXED_PAT_CTRL, 0x0a),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8475_ufsphy_serdes[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_INITVAL2, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x82),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x18),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0xff),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0c),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8475_ufsphy_g4_serdes[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x14),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x98),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x14),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x18),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x32),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x0f),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8475_ufsphy_g4_pcs[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x0b),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8550_ufsphy_serdes[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
|
||||
@ -830,17 +862,20 @@ static const struct qmp_phy_init_tbl sm8650_ufsphy_serdes[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x44),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x1f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO_MODE1, 0x1f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IETRIM, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IPTRIM, 0x17),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_INITVAL2, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x14),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x7f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x4c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x14),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x99),
|
||||
@ -848,17 +883,28 @@ static const struct qmp_phy_init_tbl sm8650_ufsphy_serdes[] = {
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8650_ufsphy_tx[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_LANE_MODE_1, 0x05),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_LANE_MODE_1, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x07),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_RX, 0x0e),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8650_ufsphy_rx[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE2, 0x0c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE4, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x0e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0, 0xc2),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1, 0xc2),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE4, 0x0c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_SO_GAIN_RATE4, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x14),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_PI_CONTROLS, 0x07),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_OFFSET_ADAPTOR_CNTRL3, 0x0e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_FO_GAIN_RATE4, 0x1c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_SO_GAIN_RATE4, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x3e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0, 0xce),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1, 0xce),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B2, 0x18),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B3, 0x1a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B4, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B6, 0x60),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B3, 0x9e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B6, 0x60),
|
||||
@ -866,23 +912,41 @@ static const struct qmp_phy_init_tbl sm8650_ufsphy_rx[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B4, 0x0e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B5, 0x36),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B8, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B0, 0x24),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B1, 0x24),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B2, 0x20),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B3, 0xb9),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B6, 0xff),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B4, 0x4f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_SO_SATURATION, 0x1f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_PI_CTRL1, 0x94),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_RX_TERM_BW_CTRL0, 0xfa),
|
||||
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_DLL0_FTUNE_CTRL, 0x30),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8650_ufsphy_pcs[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x00),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PCS_CTRL1, 0xc1),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x68),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S4, 0x0e),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S5, 0x12),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S6, 0x15),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S7, 0x19),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8650_ufsphy_g4_pcs[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x13),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x69),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8650_ufsphy_g5_pcs[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x05),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x05),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HS_G5_SYNC_LENGTH_CAPABILITY, 0x4d),
|
||||
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME, 0x9e),
|
||||
};
|
||||
|
||||
struct qmp_ufs_offsets {
|
||||
@ -1346,6 +1410,42 @@ static const struct qmp_phy_cfg sm8450_ufsphy_cfg = {
|
||||
.regs = ufsphy_v5_regs_layout,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8475_ufsphy_cfg = {
|
||||
.lanes = 2,
|
||||
|
||||
.offsets = &qmp_ufs_offsets_v6,
|
||||
.max_supported_gear = UFS_HS_G4,
|
||||
|
||||
.tbls = {
|
||||
.serdes = sm8475_ufsphy_serdes,
|
||||
.serdes_num = ARRAY_SIZE(sm8475_ufsphy_serdes),
|
||||
.tx = sm8550_ufsphy_tx,
|
||||
.tx_num = ARRAY_SIZE(sm8550_ufsphy_tx),
|
||||
.rx = sm8550_ufsphy_rx,
|
||||
.rx_num = ARRAY_SIZE(sm8550_ufsphy_rx),
|
||||
.pcs = sm8550_ufsphy_pcs,
|
||||
.pcs_num = ARRAY_SIZE(sm8550_ufsphy_pcs),
|
||||
},
|
||||
.tbls_hs_b = {
|
||||
.serdes = sm8550_ufsphy_hs_b_serdes,
|
||||
.serdes_num = ARRAY_SIZE(sm8550_ufsphy_hs_b_serdes),
|
||||
},
|
||||
.tbls_hs_overlay[0] = {
|
||||
.serdes = sm8475_ufsphy_g4_serdes,
|
||||
.serdes_num = ARRAY_SIZE(sm8475_ufsphy_g4_serdes),
|
||||
.tx = sm8550_ufsphy_g4_tx,
|
||||
.tx_num = ARRAY_SIZE(sm8550_ufsphy_g4_tx),
|
||||
.rx = sm8550_ufsphy_g4_rx,
|
||||
.rx_num = ARRAY_SIZE(sm8550_ufsphy_g4_rx),
|
||||
.pcs = sm8475_ufsphy_g4_pcs,
|
||||
.pcs_num = ARRAY_SIZE(sm8475_ufsphy_g4_pcs),
|
||||
.max_gear = UFS_HS_G4,
|
||||
},
|
||||
.vreg_list = qmp_phy_vreg_l,
|
||||
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
|
||||
.regs = ufsphy_v6_regs_layout,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8550_ufsphy_cfg = {
|
||||
.lanes = 2,
|
||||
|
||||
@ -1407,6 +1507,17 @@ static const struct qmp_phy_cfg sm8650_ufsphy_cfg = {
|
||||
.pcs = sm8650_ufsphy_pcs,
|
||||
.pcs_num = ARRAY_SIZE(sm8650_ufsphy_pcs),
|
||||
},
|
||||
.tbls_hs_overlay[0] = {
|
||||
.pcs = sm8650_ufsphy_g4_pcs,
|
||||
.pcs_num = ARRAY_SIZE(sm8650_ufsphy_g4_pcs),
|
||||
.max_gear = UFS_HS_G4,
|
||||
},
|
||||
.tbls_hs_overlay[1] = {
|
||||
.pcs = sm8650_ufsphy_g5_pcs,
|
||||
.pcs_num = ARRAY_SIZE(sm8650_ufsphy_g5_pcs),
|
||||
.max_gear = UFS_HS_G5,
|
||||
},
|
||||
|
||||
.vreg_list = qmp_phy_vreg_l,
|
||||
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
|
||||
.regs = ufsphy_v6_regs_layout,
|
||||
@ -1941,6 +2052,9 @@ static const struct of_device_id qmp_ufs_of_match_table[] = {
|
||||
}, {
|
||||
.compatible = "qcom,sm8450-qmp-ufs-phy",
|
||||
.data = &sm8450_ufsphy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sm8475-qmp-ufs-phy",
|
||||
.data = &sm8475_ufsphy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sm8550-qmp-ufs-phy",
|
||||
.data = &sm8550_ufsphy_cfg,
|
||||
|
@ -337,6 +337,29 @@ static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V2_PCS_POWER_STATE_CONFIG2, 0x08),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl qdu1000_usb3_uniphy_pcs_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xc4),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x89),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl qdu1000_usb3_uniphy_pcs_usb_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_POWER_STATE_CONFIG1, 0x6f),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_serdes_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
|
||||
@ -1400,6 +1423,27 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
|
||||
.regs = qmp_v2_usb3phy_regs_layout,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg qdu1000_usb3_uniphy_cfg = {
|
||||
.offsets = &qmp_usb_offsets_v5,
|
||||
|
||||
.serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl),
|
||||
.tx_tbl = sm8350_usb3_uniphy_tx_tbl,
|
||||
.tx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_tx_tbl),
|
||||
.rx_tbl = sm8350_usb3_uniphy_rx_tbl,
|
||||
.rx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_rx_tbl),
|
||||
.pcs_tbl = qdu1000_usb3_uniphy_pcs_tbl,
|
||||
.pcs_tbl_num = ARRAY_SIZE(qdu1000_usb3_uniphy_pcs_tbl),
|
||||
.pcs_usb_tbl = qdu1000_usb3_uniphy_pcs_usb_tbl,
|
||||
.pcs_usb_tbl_num = ARRAY_SIZE(qdu1000_usb3_uniphy_pcs_usb_tbl),
|
||||
.vreg_list = qmp_phy_vreg_l,
|
||||
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
|
||||
.regs = qmp_v4_usb3phy_regs_layout,
|
||||
.pcs_usb_offset = 0x1000,
|
||||
|
||||
.has_pwrdn_delay = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = {
|
||||
.offsets = &qmp_usb_offsets_v5,
|
||||
|
||||
@ -2202,6 +2246,9 @@ static const struct of_device_id qmp_usb_of_match_table[] = {
|
||||
}, {
|
||||
.compatible = "qcom,msm8996-qmp-usb3-phy",
|
||||
.data = &msm8996_usb3phy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,qdu1000-qmp-usb3-uni-phy",
|
||||
.data = &qdu1000_usb3_uniphy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sa8775p-qmp-usb3-uni-phy",
|
||||
.data = &sa8775p_usb3_uniphy_cfg,
|
||||
|
@ -116,3 +116,15 @@ config PHY_ROCKCHIP_USB
|
||||
select GENERIC_PHY
|
||||
help
|
||||
Enable this to support the Rockchip USB 2.0 PHY.
|
||||
|
||||
config PHY_ROCKCHIP_USBDP
|
||||
tristate "Rockchip USBDP COMBO PHY Driver"
|
||||
depends on ARCH_ROCKCHIP && OF
|
||||
depends on TYPEC
|
||||
select GENERIC_PHY
|
||||
help
|
||||
Enable this to support the Rockchip USB3.0/DP combo PHY with
|
||||
Samsung IP block. This is required for USB3 support on RK3588.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called phy-rockchip-usbdp
|
||||
|
@ -12,3 +12,4 @@ obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX) += phy-rockchip-samsung-hdptx.o
|
||||
obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o
|
||||
obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
|
||||
obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
|
||||
obj-$(CONFIG_PHY_ROCKCHIP_USBDP) += phy-rockchip-usbdp.o
|
||||
|
@ -248,7 +248,7 @@ static int rockchip_combphy_exit(struct phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ops rochchip_combphy_ops = {
|
||||
static const struct phy_ops rockchip_combphy_ops = {
|
||||
.init = rockchip_combphy_init,
|
||||
.exit = rockchip_combphy_exit,
|
||||
.owner = THIS_MODULE,
|
||||
@ -364,7 +364,7 @@ static int rockchip_combphy_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->phy = devm_phy_create(dev, NULL, &rochchip_combphy_ops);
|
||||
priv->phy = devm_phy_create(dev, NULL, &rockchip_combphy_ops);
|
||||
if (IS_ERR(priv->phy)) {
|
||||
dev_err(dev, "failed to create combphy\n");
|
||||
return PTR_ERR(priv->phy);
|
||||
|
@ -35,11 +35,17 @@
|
||||
#define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0
|
||||
#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904
|
||||
#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04
|
||||
#define RK3588_PCIE3PHY_GRF_PHY0_LN0_CON1 0x1004
|
||||
#define RK3588_PCIE3PHY_GRF_PHY0_LN1_CON1 0x1104
|
||||
#define RK3588_PCIE3PHY_GRF_PHY1_LN0_CON1 0x2004
|
||||
#define RK3588_PCIE3PHY_GRF_PHY1_LN1_CON1 0x2104
|
||||
#define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0))
|
||||
|
||||
#define RK3588_BIFURCATION_LANE_0_1 BIT(0)
|
||||
#define RK3588_BIFURCATION_LANE_2_3 BIT(1)
|
||||
#define RK3588_LANE_AGGREGATION BIT(2)
|
||||
#define RK3588_RX_CMN_REFCLK_MODE_EN ((BIT(7) << 16) | BIT(7))
|
||||
#define RK3588_RX_CMN_REFCLK_MODE_DIS (BIT(7) << 16)
|
||||
#define RK3588_PCIE1LN_SEL_EN (GENMASK(1, 0) << 16)
|
||||
#define RK3588_PCIE30_PHY_MODE_EN (GENMASK(2, 0) << 16)
|
||||
|
||||
@ -60,6 +66,7 @@ struct rockchip_p3phy_priv {
|
||||
int num_clks;
|
||||
int num_lanes;
|
||||
u32 lanes[4];
|
||||
u32 rx_cmn_refclk_mode[4];
|
||||
};
|
||||
|
||||
struct rockchip_p3phy_ops {
|
||||
@ -137,6 +144,19 @@ static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
|
||||
u8 mode = RK3588_LANE_AGGREGATION; /* default */
|
||||
int ret;
|
||||
|
||||
regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY0_LN0_CON1,
|
||||
priv->rx_cmn_refclk_mode[0] ? RK3588_RX_CMN_REFCLK_MODE_EN :
|
||||
RK3588_RX_CMN_REFCLK_MODE_DIS);
|
||||
regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY0_LN1_CON1,
|
||||
priv->rx_cmn_refclk_mode[1] ? RK3588_RX_CMN_REFCLK_MODE_EN :
|
||||
RK3588_RX_CMN_REFCLK_MODE_DIS);
|
||||
regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY1_LN0_CON1,
|
||||
priv->rx_cmn_refclk_mode[2] ? RK3588_RX_CMN_REFCLK_MODE_EN :
|
||||
RK3588_RX_CMN_REFCLK_MODE_DIS);
|
||||
regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY1_LN1_CON1,
|
||||
priv->rx_cmn_refclk_mode[3] ? RK3588_RX_CMN_REFCLK_MODE_EN :
|
||||
RK3588_RX_CMN_REFCLK_MODE_DIS);
|
||||
|
||||
/* Deassert PCIe PMA output clamp mode */
|
||||
regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, BIT(8) | BIT(24));
|
||||
|
||||
@ -182,7 +202,7 @@ static const struct rockchip_p3phy_ops rk3588_ops = {
|
||||
.phy_init = rockchip_p3phy_rk3588_init,
|
||||
};
|
||||
|
||||
static int rochchip_p3phy_init(struct phy *phy)
|
||||
static int rockchip_p3phy_init(struct phy *phy)
|
||||
{
|
||||
struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
|
||||
int ret;
|
||||
@ -205,7 +225,7 @@ static int rochchip_p3phy_init(struct phy *phy)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rochchip_p3phy_exit(struct phy *phy)
|
||||
static int rockchip_p3phy_exit(struct phy *phy)
|
||||
{
|
||||
struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
|
||||
|
||||
@ -214,9 +234,9 @@ static int rochchip_p3phy_exit(struct phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ops rochchip_p3phy_ops = {
|
||||
.init = rochchip_p3phy_init,
|
||||
.exit = rochchip_p3phy_exit,
|
||||
static const struct phy_ops rockchip_p3phy_ops = {
|
||||
.init = rockchip_p3phy_init,
|
||||
.exit = rockchip_p3phy_exit,
|
||||
.set_mode = rockchip_p3phy_set_mode,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
@ -275,7 +295,24 @@ static int rockchip_p3phy_probe(struct platform_device *pdev)
|
||||
return priv->num_lanes;
|
||||
}
|
||||
|
||||
priv->phy = devm_phy_create(dev, NULL, &rochchip_p3phy_ops);
|
||||
ret = of_property_read_variable_u32_array(dev->of_node,
|
||||
"rockchip,rx-common-refclk-mode",
|
||||
priv->rx_cmn_refclk_mode, 1,
|
||||
ARRAY_SIZE(priv->rx_cmn_refclk_mode));
|
||||
/*
|
||||
* if no rockchip,rx-common-refclk-mode, assume enabled for all lanes in
|
||||
* order to be DT backwards compatible. (Since HW reset val is enabled.)
|
||||
*/
|
||||
if (ret == -EINVAL) {
|
||||
for (int i = 0; i < ARRAY_SIZE(priv->rx_cmn_refclk_mode); i++)
|
||||
priv->rx_cmn_refclk_mode[i] = 1;
|
||||
} else if (ret < 0) {
|
||||
dev_err(dev, "failed to read rockchip,rx-common-refclk-mode property %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->phy = devm_phy_create(dev, NULL, &rockchip_p3phy_ops);
|
||||
if (IS_ERR(priv->phy)) {
|
||||
dev_err(dev, "failed to create combphy\n");
|
||||
return PTR_ERR(priv->phy);
|
||||
|
1608
drivers/phy/rockchip/phy-rockchip-usbdp.c
Normal file
1608
drivers/phy/rockchip/phy-rockchip-usbdp.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@ obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
|
||||
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
|
||||
obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o
|
||||
obj-$(CONFIG_PHY_SAMSUNG_UFS) += phy-exynos-ufs.o
|
||||
phy-exynos-ufs-y += phy-gs101-ufs.o
|
||||
phy-exynos-ufs-y += phy-samsung-ufs.o
|
||||
phy-exynos-ufs-y += phy-exynos7-ufs.o
|
||||
phy-exynos-ufs-y += phy-exynosautov9-ufs.o
|
||||
|
@ -82,4 +82,5 @@ const struct samsung_ufs_phy_drvdata exynos7_ufs_phy = {
|
||||
.clk_list = exynos7_ufs_phy_clks,
|
||||
.num_clks = ARRAY_SIZE(exynos7_ufs_phy_clks),
|
||||
.cdr_lock_status_offset = EXYNOS7_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS,
|
||||
.wait_for_cdr = samsung_ufs_phy_wait_for_lock_acq,
|
||||
};
|
||||
|
@ -71,4 +71,5 @@ const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy = {
|
||||
.clk_list = exynosautov9_ufs_phy_clks,
|
||||
.num_clks = ARRAY_SIZE(exynosautov9_ufs_phy_clks),
|
||||
.cdr_lock_status_offset = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS,
|
||||
.wait_for_cdr = samsung_ufs_phy_wait_for_lock_acq,
|
||||
};
|
||||
|
@ -60,4 +60,5 @@ const struct samsung_ufs_phy_drvdata fsd_ufs_phy = {
|
||||
.clk_list = fsd_ufs_phy_clks,
|
||||
.num_clks = ARRAY_SIZE(fsd_ufs_phy_clks),
|
||||
.cdr_lock_status_offset = FSD_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS,
|
||||
.wait_for_cdr = samsung_ufs_phy_wait_for_lock_acq,
|
||||
};
|
||||
|
182
drivers/phy/samsung/phy-gs101-ufs.c
Normal file
182
drivers/phy/samsung/phy-gs101-ufs.c
Normal file
@ -0,0 +1,182 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* UFS PHY driver data for Google Tensor gs101 SoC
|
||||
*
|
||||
* Copyright (C) 2024 Linaro Ltd
|
||||
* Author: Peter Griffin <peter.griffin@linaro.org>
|
||||
*/
|
||||
|
||||
#include "phy-samsung-ufs.h"
|
||||
|
||||
#define TENSOR_GS101_PHY_CTRL 0x3ec8
|
||||
#define TENSOR_GS101_PHY_CTRL_MASK 0x1
|
||||
#define TENSOR_GS101_PHY_CTRL_EN BIT(0)
|
||||
#define PHY_GS101_LANE_OFFSET 0x200
|
||||
#define TRSV_REG338 0x338
|
||||
#define LN0_MON_RX_CAL_DONE BIT(3)
|
||||
#define TRSV_REG339 0x339
|
||||
#define LN0_MON_RX_CDR_FLD_CK_MODE_DONE BIT(3)
|
||||
#define TRSV_REG222 0x222
|
||||
#define LN0_OVRD_RX_CDR_EN BIT(4)
|
||||
#define LN0_RX_CDR_EN BIT(3)
|
||||
|
||||
#define PHY_PMA_TRSV_ADDR(reg, lane) (PHY_APB_ADDR((reg) + \
|
||||
((lane) * PHY_GS101_LANE_OFFSET)))
|
||||
|
||||
#define PHY_TRSV_REG_CFG_GS101(o, v, d) \
|
||||
PHY_TRSV_REG_CFG_OFFSET(o, v, d, PHY_GS101_LANE_OFFSET)
|
||||
|
||||
/* Calibration for phy initialization */
|
||||
static const struct samsung_ufs_phy_cfg tensor_gs101_pre_init_cfg[] = {
|
||||
PHY_COMN_REG_CFG(0x43, 0x10, PWR_MODE_ANY),
|
||||
PHY_COMN_REG_CFG(0x3C, 0x14, PWR_MODE_ANY),
|
||||
PHY_COMN_REG_CFG(0x46, 0x48, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x200, 0x00, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x201, 0x06, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x202, 0x06, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x203, 0x0a, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x204, 0x00, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x205, 0x11, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x207, 0x0c, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2E1, 0xc0, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x22D, 0xb8, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x234, 0x60, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x238, 0x13, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x239, 0x48, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x23A, 0x01, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x23B, 0x25, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x23C, 0x2a, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x23D, 0x01, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x23E, 0x13, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x23F, 0x13, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x240, 0x4a, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x243, 0x40, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x244, 0x02, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x25D, 0x00, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x25E, 0x3f, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x25F, 0xff, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x273, 0x33, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x274, 0x50, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x284, 0x02, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x285, 0x02, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2A2, 0x04, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x25D, 0x01, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2FA, 0x01, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x286, 0x03, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x287, 0x03, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x288, 0x03, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x289, 0x03, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2B3, 0x04, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2B6, 0x0b, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2B7, 0x0b, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2B8, 0x0b, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2B9, 0x0b, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2BA, 0x0b, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2BB, 0x06, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2BC, 0x06, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2BD, 0x06, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x29E, 0x06, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2E4, 0x1a, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2ED, 0x25, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x269, 0x1a, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x2F4, 0x2f, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x34B, 0x01, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x34C, 0x23, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x34D, 0x23, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x34E, 0x45, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x34F, 0x00, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x350, 0x31, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x351, 0x00, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x352, 0x02, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x353, 0x00, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x354, 0x01, PWR_MODE_ANY),
|
||||
PHY_COMN_REG_CFG(0x43, 0x18, PWR_MODE_ANY),
|
||||
PHY_COMN_REG_CFG(0x43, 0x00, PWR_MODE_ANY),
|
||||
END_UFS_PHY_CFG,
|
||||
};
|
||||
|
||||
static const struct samsung_ufs_phy_cfg tensor_gs101_pre_pwr_hs_config[] = {
|
||||
PHY_TRSV_REG_CFG_GS101(0x369, 0x11, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x246, 0x03, PWR_MODE_ANY),
|
||||
};
|
||||
|
||||
/* Calibration for HS mode series A/B */
|
||||
static const struct samsung_ufs_phy_cfg tensor_gs101_post_pwr_hs_config[] = {
|
||||
PHY_COMN_REG_CFG(0x8, 0x60, PWR_MODE_PWM_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x222, 0x08, PWR_MODE_PWM_ANY),
|
||||
PHY_TRSV_REG_CFG_GS101(0x246, 0x01, PWR_MODE_ANY),
|
||||
END_UFS_PHY_CFG,
|
||||
};
|
||||
|
||||
static const struct samsung_ufs_phy_cfg *tensor_gs101_ufs_phy_cfgs[CFG_TAG_MAX] = {
|
||||
[CFG_PRE_INIT] = tensor_gs101_pre_init_cfg,
|
||||
[CFG_PRE_PWR_HS] = tensor_gs101_pre_pwr_hs_config,
|
||||
[CFG_POST_PWR_HS] = tensor_gs101_post_pwr_hs_config,
|
||||
};
|
||||
|
||||
static const char * const tensor_gs101_ufs_phy_clks[] = {
|
||||
"ref_clk",
|
||||
};
|
||||
|
||||
static int gs101_phy_wait_for_calibration(struct phy *phy, u8 lane)
|
||||
{
|
||||
struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy);
|
||||
const unsigned int timeout_us = 40000;
|
||||
const unsigned int sleep_us = 40;
|
||||
u32 val;
|
||||
u32 off;
|
||||
int err;
|
||||
|
||||
off = PHY_PMA_TRSV_ADDR(TRSV_REG338, lane);
|
||||
|
||||
err = readl_poll_timeout(ufs_phy->reg_pma + off,
|
||||
val, (val & LN0_MON_RX_CAL_DONE),
|
||||
sleep_us, timeout_us);
|
||||
|
||||
if (err) {
|
||||
dev_err(ufs_phy->dev,
|
||||
"failed to get phy cal done %d\n", err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#define DELAY_IN_US 40
|
||||
#define RETRY_CNT 100
|
||||
static int gs101_phy_wait_for_cdr_lock(struct phy *phy, u8 lane)
|
||||
{
|
||||
struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy);
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RETRY_CNT; i++) {
|
||||
udelay(DELAY_IN_US);
|
||||
val = readl(ufs_phy->reg_pma +
|
||||
PHY_PMA_TRSV_ADDR(TRSV_REG339, lane));
|
||||
|
||||
if (val & LN0_MON_RX_CDR_FLD_CK_MODE_DONE)
|
||||
return 0;
|
||||
|
||||
udelay(DELAY_IN_US);
|
||||
/* Override and enable clock data recovery */
|
||||
writel(LN0_OVRD_RX_CDR_EN, ufs_phy->reg_pma +
|
||||
PHY_PMA_TRSV_ADDR(TRSV_REG222, lane));
|
||||
writel(LN0_OVRD_RX_CDR_EN | LN0_RX_CDR_EN,
|
||||
ufs_phy->reg_pma + PHY_PMA_TRSV_ADDR(TRSV_REG222, lane));
|
||||
}
|
||||
dev_err(ufs_phy->dev, "failed to get cdr lock\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
const struct samsung_ufs_phy_drvdata tensor_gs101_ufs_phy = {
|
||||
.cfgs = tensor_gs101_ufs_phy_cfgs,
|
||||
.isol = {
|
||||
.offset = TENSOR_GS101_PHY_CTRL,
|
||||
.mask = TENSOR_GS101_PHY_CTRL_MASK,
|
||||
.en = TENSOR_GS101_PHY_CTRL_EN,
|
||||
},
|
||||
.clk_list = tensor_gs101_ufs_phy_clks,
|
||||
.num_clks = ARRAY_SIZE(tensor_gs101_ufs_phy_clks),
|
||||
.wait_for_cal = gs101_phy_wait_for_calibration,
|
||||
.wait_for_cdr = gs101_phy_wait_for_cdr_lock,
|
||||
};
|
@ -13,11 +13,11 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/soc/samsung/exynos-pmu.h>
|
||||
|
||||
#include "phy-samsung-ufs.h"
|
||||
|
||||
@ -45,7 +45,7 @@ static void samsung_ufs_phy_config(struct samsung_ufs_phy *phy,
|
||||
}
|
||||
}
|
||||
|
||||
static int samsung_ufs_phy_wait_for_lock_acq(struct phy *phy)
|
||||
int samsung_ufs_phy_wait_for_lock_acq(struct phy *phy, u8 lane)
|
||||
{
|
||||
struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy);
|
||||
const unsigned int timeout_us = 100000;
|
||||
@ -97,8 +97,21 @@ static int samsung_ufs_phy_calibrate(struct phy *phy)
|
||||
}
|
||||
}
|
||||
|
||||
if (ufs_phy->ufs_phy_state == CFG_POST_PWR_HS)
|
||||
err = samsung_ufs_phy_wait_for_lock_acq(phy);
|
||||
for_each_phy_lane(ufs_phy, i) {
|
||||
if (ufs_phy->ufs_phy_state == CFG_PRE_INIT &&
|
||||
ufs_phy->drvdata->wait_for_cal) {
|
||||
err = ufs_phy->drvdata->wait_for_cal(phy, i);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ufs_phy->ufs_phy_state == CFG_POST_PWR_HS &&
|
||||
ufs_phy->drvdata->wait_for_cdr) {
|
||||
err = ufs_phy->drvdata->wait_for_cdr(phy, i);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In Samsung ufshci, PHY need to be calibrated at different
|
||||
@ -255,8 +268,8 @@ static int samsung_ufs_phy_probe(struct platform_device *pdev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
phy->reg_pmu = syscon_regmap_lookup_by_phandle(
|
||||
dev->of_node, "samsung,pmu-syscon");
|
||||
phy->reg_pmu = exynos_get_pmu_regmap_by_phandle(dev->of_node,
|
||||
"samsung,pmu-syscon");
|
||||
if (IS_ERR(phy->reg_pmu)) {
|
||||
err = PTR_ERR(phy->reg_pmu);
|
||||
dev_err(dev, "failed syscon remap for pmu\n");
|
||||
@ -302,6 +315,9 @@ out:
|
||||
|
||||
static const struct of_device_id samsung_ufs_phy_match[] = {
|
||||
{
|
||||
.compatible = "google,gs101-ufs-phy",
|
||||
.data = &tensor_gs101_ufs_phy,
|
||||
}, {
|
||||
.compatible = "samsung,exynos7-ufs-phy",
|
||||
.data = &exynos7_ufs_phy,
|
||||
}, {
|
||||
|
@ -112,6 +112,9 @@ struct samsung_ufs_phy_drvdata {
|
||||
const char * const *clk_list;
|
||||
int num_clks;
|
||||
u32 cdr_lock_status_offset;
|
||||
/* SoC's specific operations */
|
||||
int (*wait_for_cal)(struct phy *phy, u8 lane);
|
||||
int (*wait_for_cdr)(struct phy *phy, u8 lane);
|
||||
};
|
||||
|
||||
struct samsung_ufs_phy {
|
||||
@ -139,8 +142,11 @@ static inline void samsung_ufs_phy_ctrl_isol(
|
||||
phy->isol.mask, isol ? 0 : phy->isol.en);
|
||||
}
|
||||
|
||||
int samsung_ufs_phy_wait_for_lock_acq(struct phy *phy, u8 lane);
|
||||
|
||||
extern const struct samsung_ufs_phy_drvdata exynos7_ufs_phy;
|
||||
extern const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy;
|
||||
extern const struct samsung_ufs_phy_drvdata fsd_ufs_phy;
|
||||
extern const struct samsung_ufs_phy_drvdata tensor_gs101_ufs_phy;
|
||||
|
||||
#endif /* _PHY_SAMSUNG_UFS_ */
|
||||
|
@ -995,15 +995,13 @@ static int xpsgtr_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xpsgtr_remove(struct platform_device *pdev)
|
||||
static void xpsgtr_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct xpsgtr_dev *gtr_dev = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_disable(gtr_dev->dev);
|
||||
pm_runtime_put_noidle(gtr_dev->dev);
|
||||
pm_runtime_set_suspended(gtr_dev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id xpsgtr_of_match[] = {
|
||||
@ -1015,7 +1013,7 @@ MODULE_DEVICE_TABLE(of, xpsgtr_of_match);
|
||||
|
||||
static struct platform_driver xpsgtr_driver = {
|
||||
.probe = xpsgtr_probe,
|
||||
.remove = xpsgtr_remove,
|
||||
.remove_new = xpsgtr_remove,
|
||||
.driver = {
|
||||
.name = "xilinx-psgtr",
|
||||
.of_match_table = xpsgtr_of_match,
|
||||
|
@ -17,4 +17,8 @@
|
||||
#define QMP_USB43DP_USB3_PHY 0
|
||||
#define QMP_USB43DP_DP_PHY 1
|
||||
|
||||
/* QMP PCIE PHYs */
|
||||
#define QMP_PCIE_PIPE_CLK 0
|
||||
#define QMP_PCIE_PHY_AUX_CLK 1
|
||||
|
||||
#endif /* _DT_BINDINGS_PHY_QMP */
|
||||
|
Loading…
Reference in New Issue
Block a user