phy-for-5.15
- Updates: - Yaml conversion for Freescale imx8mq usb phy, TI AM654 SERDES phy, Cadence torrent phy - Updates for Amlogic Meson8b-usb2 phy, Samsung ufs phy - New support: - UFS phy for Qualcomm SM6115 - PCIe & USB/DP phy for Qualcomm sc8180x - USB3 PHY support for Qualcomm IPQ6018 - Renesas USB2.0 PHY for RZ/G2L -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmEkfloACgkQfBQHDyUj g0dwzA/9G658xS6jZSLTQX3PzWSpxk+mmmC2IR7fkeB5ShVcrju83PGRD0OQnpkG aRZRZy20iGbuKkrA/+oIliVgNEg44D32zqD5pojHAfmwMUNMUP6R4YmAFNreJ3Do sHXLlS3p9hhRZONKbl6VMg6rS4yTre79ozTovNH6HGyTlSObezAaKVjUTCofuSaa /AXL2/WCINJuCtZmm67/AHxgzptK/h7FSqJdg4JET7Dt6Y/HN/WrNCwcyOlloteQ Dyc+C0cdBncRK6A1og83A3jw7oiOhl2/72paCyQFljvS4v0BW8B3Sth1hukE2rsE RmtP4EYSLN8uWXdLsBjerS09WFfjZBlE8UeU46AhzffCWOwCwgRwdJFpqUjN/OCO ain9X16yQY8SBHShjxQAQMt5OtTNJCb0qhfcDa+47D5b+NNVJxfMoUTjPzqg7dpB JJZZzUgNyd2PxvLApzgkYj5yqv/PN1cXB6UYqOQN/YojmyZKtIB1U+9JvY01Qb8c 9Dj92M7rUGzgfmUqLl4WPWhUZu56e0W/VRlYftFNOgAbQ+SehyG9CREaEqJCNzzl m9HAL4ZzpK8hGQbS5FHiWrplcX8IQWd+XF8vXhkVV+wiE+ryGiPB5LrkjKfvEmoa AgfpzHBOSATpR2nuRL/bruMZeHFhj2kzFQpg0MXhyfZAr06Zq5U= =3U1A -----END PGP SIGNATURE----- Merge tag 'phy-for-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy into char-misc-next Vinod writes: phy-for-5.15 - Updates: - Yaml conversion for Freescale imx8mq usb phy, TI AM654 SERDES phy, Cadence torrent phy - Updates for Amlogic Meson8b-usb2 phy, Samsung ufs phy - New support: - UFS phy for Qualcomm SM6115 - PCIe & USB/DP phy for Qualcomm sc8180x - USB3 PHY support for Qualcomm IPQ6018 - Renesas USB2.0 PHY for RZ/G2L * tag 'phy-for-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (45 commits) phy: qcom-qmp: Add support for SM6115 UFS phy dt-bindings: phy: qcom,qmp: Add SM6115 UFS PHY bindings phy: qmp: Provide unique clock names for DP clocks phy: xilinx: zynqmp: skip PHY initialization and PLL lock for USB phy: amlogic: meson8b-usb2: don't log an error on -EPROBE_DEFER phy: amlogic: meson8b-usb2: Power off the PHY by putting it into reset mode phy: phy-mtk-mipi-dsi: convert to devm_platform_ioremap_resource phy: phy-mtk-mipi-dsi: remove dummy assignment of error number phy: phy-mtk-hdmi: convert to devm_platform_ioremap_resource phy: phy-mtk-ufs: use clock bulk to get clocks phy: phy-mtk-tphy: remove error log of ioremap failure phy: phy-mtk-tphy: print error log using child device phy: phy-mtk-tphy: support type switch by pericfg phy: phy-mtk-tphy: use clock bulk to get clocks dt-bindings: phy: mediatek: tphy: support type switch by pericfg phy: cadence-torrent: Check PIPE mode PHY status to be ready for operation phy: cadence-torrent: Add debug information for PHY configuration phy: cadence-torrent: Add separate functions for reusable code phy: cadence-torrent: Add PHY configuration for DP with 100MHz ref clock phy: cadence-torrent: Add PHY registers for DP in array format ...
This commit is contained in:
commit
96e9df335a
|
@ -1,20 +0,0 @@
|
|||
* Freescale i.MX8MQ USB3 PHY binding
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "fsl,imx8mq-usb-phy" or "fsl,imx8mp-usb-phy"
|
||||
- #phys-cells: must be 0 (see phy-bindings.txt in this directory)
|
||||
- reg: The base address and length of the registers
|
||||
- clocks: phandles to the clocks for each clock listed in clock-names
|
||||
- clock-names: must contain "phy"
|
||||
|
||||
Optional properties:
|
||||
- vbus-supply: A phandle to the regulator for USB VBUS.
|
||||
|
||||
Example:
|
||||
usb3_phy0: phy@381f0040 {
|
||||
compatible = "fsl,imx8mq-usb-phy";
|
||||
reg = <0x381f0040 0x40>;
|
||||
clocks = <&clk IMX8MQ_CLK_USB1_PHY_ROOT>;
|
||||
clock-names = "phy";
|
||||
#phy-cells = <0>;
|
||||
};
|
|
@ -0,0 +1,53 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/fsl,imx8mq-usb-phy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX8MQ USB3 PHY binding
|
||||
|
||||
maintainers:
|
||||
- Li Jun <jun.li@nxp.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx8mq-usb-phy
|
||||
- fsl,imx8mp-usb-phy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: phy
|
||||
|
||||
vbus-supply:
|
||||
description:
|
||||
A phandle to the regulator for USB VBUS.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#phy-cells"
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8mq-clock.h>
|
||||
usb3_phy0: phy@381f0040 {
|
||||
compatible = "fsl,imx8mq-usb-phy";
|
||||
reg = <0x381f0040 0x40>;
|
||||
clocks = <&clk IMX8MQ_CLK_USB1_PHY_ROOT>;
|
||||
clock-names = "phy";
|
||||
#phy-cells = <0>;
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/intel,phy-keembay-usb.yaml#
|
||||
$id: http://devicetree.org/schemas/phy/intel,keembay-phy-usb.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Intel Keem Bay USB PHY bindings
|
|
@ -15,7 +15,7 @@ description: |
|
|||
controllers on MediaTek SoCs, includes USB2.0, USB3.0, PCIe and SATA.
|
||||
|
||||
Layout differences of banks between T-PHY V1 (mt8173/mt2701) and
|
||||
T-PHY V2 (mt2712) when works on USB mode:
|
||||
T-PHY V2 (mt2712) / V3 (mt8195) when works on USB mode:
|
||||
-----------------------------------
|
||||
Version 1:
|
||||
port offset bank
|
||||
|
@ -34,7 +34,7 @@ description: |
|
|||
u2 port2 0x1800 U2PHY_COM
|
||||
...
|
||||
|
||||
Version 2:
|
||||
Version 2/3:
|
||||
port offset bank
|
||||
u2 port0 0x0000 MISC
|
||||
0x0100 FMREG
|
||||
|
@ -59,7 +59,8 @@ description: |
|
|||
|
||||
SPLLC shared by u3 ports and FMREG shared by u2 ports on V1 are put back
|
||||
into each port; a new bank MISC for u2 ports and CHIP for u3 ports are
|
||||
added on V2.
|
||||
added on V2; the FMREG bank for slew rate calibration is not used anymore
|
||||
and reserved on V3;
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
|
@ -79,8 +80,11 @@ properties:
|
|||
- mediatek,mt2712-tphy
|
||||
- mediatek,mt7629-tphy
|
||||
- mediatek,mt8183-tphy
|
||||
- mediatek,mt8195-tphy
|
||||
- const: mediatek,generic-tphy-v2
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt8195-tphy
|
||||
- const: mediatek,generic-tphy-v3
|
||||
- const: mediatek,mt2701-u3phy
|
||||
deprecated: true
|
||||
- const: mediatek,mt2712-u3phy
|
||||
|
@ -91,7 +95,7 @@ properties:
|
|||
description:
|
||||
Register shared by multiple ports, exclude port's private register.
|
||||
It is needed for T-PHY V1, such as mt2701 and mt8173, but not for
|
||||
T-PHY V2, such as mt2712.
|
||||
T-PHY V2/V3, such as mt2712.
|
||||
maxItems: 1
|
||||
|
||||
"#address-cells":
|
||||
|
@ -197,6 +201,22 @@ patternProperties:
|
|||
Specify the flag to enable BC1.2 if support it
|
||||
type: boolean
|
||||
|
||||
mediatek,syscon-type:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
maxItems: 1
|
||||
description:
|
||||
A phandle to syscon used to access the register of type switch,
|
||||
the field should always be 3 cells long.
|
||||
items:
|
||||
items:
|
||||
- description:
|
||||
The first cell represents a phandle to syscon
|
||||
- description:
|
||||
The second cell represents the register offset
|
||||
- description:
|
||||
The third cell represents the index of config segment
|
||||
enum: [0, 1, 2, 3]
|
||||
|
||||
required:
|
||||
- reg
|
||||
- "#phy-cells"
|
||||
|
|
|
@ -18,6 +18,7 @@ properties:
|
|||
compatible:
|
||||
enum:
|
||||
- qcom,ipq6018-qmp-pcie-phy
|
||||
- qcom,ipq6018-qmp-usb3-phy
|
||||
- qcom,ipq8074-qmp-pcie-phy
|
||||
- qcom,ipq8074-qmp-usb3-phy
|
||||
- qcom,msm8996-qmp-pcie-phy
|
||||
|
@ -27,6 +28,7 @@ properties:
|
|||
- qcom,msm8998-qmp-ufs-phy
|
||||
- qcom,msm8998-qmp-usb3-phy
|
||||
- qcom,sc7180-qmp-usb3-phy
|
||||
- qcom,sc8180x-qmp-pcie-phy
|
||||
- qcom,sc8180x-qmp-ufs-phy
|
||||
- qcom,sc8180x-qmp-usb3-phy
|
||||
- qcom,sdm845-qhp-pcie-phy
|
||||
|
@ -34,6 +36,7 @@ properties:
|
|||
- qcom,sdm845-qmp-ufs-phy
|
||||
- qcom,sdm845-qmp-usb3-phy
|
||||
- qcom,sdm845-qmp-usb3-uni-phy
|
||||
- qcom,sm6115-qmp-ufs-phy
|
||||
- qcom,sm8150-qmp-ufs-phy
|
||||
- qcom,sm8150-qmp-usb3-phy
|
||||
- qcom,sm8150-qmp-usb3-uni-phy
|
||||
|
@ -326,6 +329,7 @@ allOf:
|
|||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sc8180x-qmp-pcie-phy
|
||||
- qcom,sdm845-qhp-pcie-phy
|
||||
- qcom,sdm845-qmp-pcie-phy
|
||||
- qcom,sdx55-qmp-pcie-phy
|
||||
|
|
|
@ -14,6 +14,7 @@ properties:
|
|||
compatible:
|
||||
enum:
|
||||
- qcom,sc7180-qmp-usb3-dp-phy
|
||||
- qcom,sc8180x-qmp-usb3-dp-phy
|
||||
- qcom,sdm845-qmp-usb3-dp-phy
|
||||
- qcom,sm8250-qmp-usb3-dp-phy
|
||||
reg:
|
||||
|
|
|
@ -30,6 +30,11 @@ properties:
|
|||
- renesas,usb2-phy-r8a77995 # R-Car D3
|
||||
- const: renesas,rcar-gen3-usb2-phy
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,usb2-phy-r9a07g044 # RZ/G2{L,LC}
|
||||
- const: renesas,rzg2l-usb2-phy # RZ/G2L family
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
|
@ -91,6 +96,16 @@ required:
|
|||
- clocks
|
||||
- '#phy-cells'
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,rzg2l-usb2-phy
|
||||
then:
|
||||
required:
|
||||
- resets
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
|
|
@ -16,6 +16,7 @@ properties:
|
|||
compatible:
|
||||
enum:
|
||||
- samsung,exynos7-ufs-phy
|
||||
- samsung,exynosautov9-ufs-phy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
TI AM654 SERDES
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "ti,phy-am654-serdes"
|
||||
- reg : Address and length of the register set for the device.
|
||||
- #phy-cells: determine the number of cells that should be given in the
|
||||
phandle while referencing this phy. Should be "2". The 1st cell
|
||||
corresponds to the phy type (should be one of the types specified in
|
||||
include/dt-bindings/phy/phy.h) and the 2nd cell should be the serdes
|
||||
lane function.
|
||||
If SERDES0 is referenced 2nd cell should be:
|
||||
0 - USB3
|
||||
1 - PCIe0 Lane0
|
||||
2 - ICSS2 SGMII Lane0
|
||||
If SERDES1 is referenced 2nd cell should be:
|
||||
0 - PCIe1 Lane0
|
||||
1 - PCIe0 Lane1
|
||||
2 - ICSS2 SGMII Lane1
|
||||
- power-domains: As documented by the generic PM domain bindings in
|
||||
Documentation/devicetree/bindings/power/power_domain.txt.
|
||||
- clocks: List of clock-specifiers representing the input to the SERDES.
|
||||
Should have 3 items representing the left input clock, external
|
||||
reference clock and right input clock in that order.
|
||||
- clock-output-names: List of clock names for each of the clock outputs of
|
||||
SERDES. Should have 3 items for CMU reference clock,
|
||||
left output clock and right output clock in that order.
|
||||
- assigned-clocks: As defined in
|
||||
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
- assigned-clock-parents: As defined in
|
||||
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
- #clock-cells: Should be <1> to choose between the 3 output clocks.
|
||||
Defined in Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
||||
The following macros are defined in dt-bindings/phy/phy-am654-serdes.h
|
||||
for selecting the correct reference clock. This can be used while
|
||||
specifying the clocks created by SERDES.
|
||||
=> AM654_SERDES_CMU_REFCLK
|
||||
=> AM654_SERDES_LO_REFCLK
|
||||
=> AM654_SERDES_RO_REFCLK
|
||||
|
||||
- mux-controls: Phandle to the multiplexer that is used to select the lane
|
||||
function. See #phy-cells above to see the multiplex values.
|
||||
|
||||
Example:
|
||||
|
||||
Example for SERDES0 is given below. It has 3 clock inputs;
|
||||
left input reference clock as indicated by <&k3_clks 153 4>, external
|
||||
reference clock as indicated by <&k3_clks 153 1> and right input
|
||||
reference clock as indicated by <&serdes1 AM654_SERDES_LO_REFCLK>. (The
|
||||
right input of SERDES0 is connected to the left output of SERDES1).
|
||||
|
||||
SERDES0 registers 3 clock outputs as indicated in clock-output-names. The
|
||||
first refers to the CMU reference clock, second refers to the left output
|
||||
reference clock and the third refers to the right output reference clock.
|
||||
|
||||
The assigned-clocks and assigned-clock-parents is used here to set the
|
||||
parent of left input reference clock to MAINHSDIV_CLKOUT4 and parent of
|
||||
CMU reference clock to left input reference clock.
|
||||
|
||||
serdes0: serdes@900000 {
|
||||
compatible = "ti,phy-am654-serdes";
|
||||
reg = <0x0 0x900000 0x0 0x2000>;
|
||||
reg-names = "serdes";
|
||||
#phy-cells = <2>;
|
||||
power-domains = <&k3_pds 153>;
|
||||
clocks = <&k3_clks 153 4>, <&k3_clks 153 1>,
|
||||
<&serdes1 AM654_SERDES_LO_REFCLK>;
|
||||
clock-output-names = "serdes0_cmu_refclk", "serdes0_lo_refclk",
|
||||
"serdes0_ro_refclk";
|
||||
assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>;
|
||||
assigned-clock-parents = <&k3_clks 153 8>, <&k3_clks 153 4>;
|
||||
ti,serdes-clk = <&serdes0_clk>;
|
||||
mux-controls = <&serdes_mux 0>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
Example for PCIe consumer node using the SERDES PHY specifier is given below.
|
||||
&pcie0_rc {
|
||||
num-lanes = <2>;
|
||||
phys = <&serdes0 PHY_TYPE_PCIE 1>, <&serdes1 PHY_TYPE_PCIE 1>;
|
||||
phy-names = "pcie-phy0", "pcie-phy1";
|
||||
};
|
|
@ -0,0 +1,103 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/phy/ti,phy-am654-serdes.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TI AM654 SERDES binding
|
||||
|
||||
description:
|
||||
This binding describes the TI AM654 SERDES. AM654 SERDES can be configured
|
||||
to be used with either PCIe or USB or SGMII.
|
||||
|
||||
maintainers:
|
||||
- Kishon Vijay Abraham I <kishon@ti.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,phy-am654-serdes
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: serdes
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 3
|
||||
description:
|
||||
Three input clocks referring to left input reference clock, refclk and right input reference
|
||||
clock.
|
||||
|
||||
assigned-clocks:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle-array"
|
||||
assigned-clock-parents:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle-array"
|
||||
|
||||
'#phy-cells':
|
||||
const: 2
|
||||
description:
|
||||
The 1st cell corresponds to the phy type (should be one of the types specified in
|
||||
include/dt-bindings/phy/phy.h) and the 2nd cell should be the serdes lane function.
|
||||
|
||||
ti,serdes-clk:
|
||||
description: Phandle to the SYSCON entry required for configuring SERDES clock selection.
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
mux-controls:
|
||||
maxItems: 1
|
||||
description: Phandle to the SYSCON entry required for configuring SERDES lane function.
|
||||
|
||||
clock-output-names:
|
||||
oneOf:
|
||||
- description: Clock output names for SERDES 0
|
||||
items:
|
||||
- const: serdes0_cmu_refclk
|
||||
- const: serdes0_lo_refclk
|
||||
- const: serdes0_ro_refclk
|
||||
- description: Clock output names for SERDES 1
|
||||
items:
|
||||
- const: serdes1_cmu_refclk
|
||||
- const: serdes1_lo_refclk
|
||||
- const: serdes1_ro_refclk
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- power-domains
|
||||
- clocks
|
||||
- assigned-clocks
|
||||
- assigned-clock-parents
|
||||
- ti,serdes-clk
|
||||
- mux-controls
|
||||
- clock-output-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/phy/phy-am654-serdes.h>
|
||||
|
||||
serdes0: serdes@900000 {
|
||||
compatible = "ti,phy-am654-serdes";
|
||||
reg = <0x900000 0x2000>;
|
||||
reg-names = "serdes";
|
||||
#phy-cells = <2>;
|
||||
power-domains = <&k3_pds 153>;
|
||||
clocks = <&k3_clks 153 4>, <&k3_clks 153 1>,
|
||||
<&serdes1 AM654_SERDES_LO_REFCLK>;
|
||||
clock-output-names = "serdes0_cmu_refclk", "serdes0_lo_refclk", "serdes0_ro_refclk";
|
||||
assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>;
|
||||
assigned-clock-parents = <&k3_clks 153 8>, <&k3_clks 153 4>;
|
||||
ti,serdes-clk = <&serdes0_clk>;
|
||||
mux-controls = <&serdes_mux 0>;
|
||||
#clock-cells = <1>;
|
||||
};
|
|
@ -219,6 +219,10 @@ static int phy_meson8b_usb2_power_off(struct phy *phy)
|
|||
clk_disable_unprepare(priv->clk_usb);
|
||||
clk_disable_unprepare(priv->clk_usb_general);
|
||||
|
||||
/* power off the PHY by putting it into reset mode */
|
||||
regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET,
|
||||
REG_CTRL_POWER_ON_RESET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -273,8 +277,8 @@ static int phy_meson8b_usb2_probe(struct platform_device *pdev)
|
|||
|
||||
phy = devm_phy_create(&pdev->dev, NULL, &phy_meson8b_usb2_ops);
|
||||
if (IS_ERR(phy)) {
|
||||
dev_err(&pdev->dev, "failed to create PHY\n");
|
||||
return PTR_ERR(phy);
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(phy),
|
||||
"failed to create PHY\n");
|
||||
}
|
||||
|
||||
phy_set_drvdata(phy, priv);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -100,7 +100,6 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mtk_hdmi_phy *hdmi_phy;
|
||||
struct resource *mem;
|
||||
struct clk *ref_clk;
|
||||
const char *ref_clk_name;
|
||||
struct clk_init_data clk_init = {
|
||||
|
@ -116,11 +115,9 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
|
|||
if (!hdmi_phy)
|
||||
return -ENOMEM;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
hdmi_phy->regs = devm_ioremap_resource(dev, mem);
|
||||
if (IS_ERR(hdmi_phy->regs)) {
|
||||
hdmi_phy->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(hdmi_phy->regs))
|
||||
return PTR_ERR(hdmi_phy->regs);
|
||||
}
|
||||
|
||||
ref_clk = devm_clk_get(dev, "pll_ref");
|
||||
if (IS_ERR(ref_clk)) {
|
||||
|
|
|
@ -130,7 +130,6 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mtk_mipi_tx *mipi_tx;
|
||||
struct resource *mem;
|
||||
const char *ref_clk_name;
|
||||
struct clk *ref_clk;
|
||||
struct clk_init_data clk_init = {
|
||||
|
@ -148,11 +147,9 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
|
|||
|
||||
mipi_tx->driver_data = of_device_get_match_data(dev);
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
mipi_tx->regs = devm_ioremap_resource(dev, mem);
|
||||
if (IS_ERR(mipi_tx->regs)) {
|
||||
mipi_tx->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(mipi_tx->regs))
|
||||
return PTR_ERR(mipi_tx->regs);
|
||||
}
|
||||
|
||||
ref_clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(ref_clk)) {
|
||||
|
@ -203,10 +200,8 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
|
|||
phy_set_drvdata(phy, mipi_tx);
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
if (IS_ERR(phy_provider)) {
|
||||
ret = PTR_ERR(phy_provider);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(phy_provider))
|
||||
return PTR_ERR(phy_provider);
|
||||
|
||||
mipi_tx->dev = dev;
|
||||
|
||||
|
|
|
@ -10,11 +10,13 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* version V1 sub-banks offset base address */
|
||||
/* banks shared by multiple phys */
|
||||
|
@ -27,7 +29,8 @@
|
|||
#define SSUSB_SIFSLV_V1_U3PHYD 0x000
|
||||
#define SSUSB_SIFSLV_V1_U3PHYA 0x200
|
||||
|
||||
/* version V2 sub-banks offset base address */
|
||||
/* version V2/V3 sub-banks offset base address */
|
||||
/* V3: U2FREQ is not used anymore, but reserved */
|
||||
/* u2 phy banks */
|
||||
#define SSUSB_SIFSLV_V2_MISC 0x000
|
||||
#define SSUSB_SIFSLV_V2_U2FREQ 0x100
|
||||
|
@ -40,6 +43,8 @@
|
|||
|
||||
#define U3P_USBPHYACR0 0x000
|
||||
#define PA0_RG_U2PLL_FORCE_ON BIT(15)
|
||||
#define PA0_USB20_PLL_PREDIV GENMASK(7, 6)
|
||||
#define PA0_USB20_PLL_PREDIV_VAL(x) ((0x3 & (x)) << 6)
|
||||
#define PA0_RG_USB20_INTR_EN BIT(5)
|
||||
|
||||
#define U3P_USBPHYACR1 0x004
|
||||
|
@ -51,6 +56,8 @@
|
|||
#define PA1_RG_TERM_SEL_VAL(x) ((0x7 & (x)) << 8)
|
||||
|
||||
#define U3P_USBPHYACR2 0x008
|
||||
#define PA2_RG_U2PLL_BW GENMASK(21, 19)
|
||||
#define PA2_RG_U2PLL_BW_VAL(x) ((0x7 & (x)) << 19)
|
||||
#define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18)
|
||||
|
||||
#define U3P_USBPHYACR5 0x014
|
||||
|
@ -72,6 +79,14 @@
|
|||
#define P2C_USB20_GPIO_MODE BIT(8)
|
||||
#define P2C_U2_GPIO_CTR_MSK (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE)
|
||||
|
||||
#define U3P_U2PHYA_RESV 0x030
|
||||
#define P2R_RG_U2PLL_FBDIV_26M 0x1bb13b
|
||||
#define P2R_RG_U2PLL_FBDIV_48M 0x3c0000
|
||||
|
||||
#define U3P_U2PHYA_RESV1 0x044
|
||||
#define P2R_RG_U2PLL_REFCLK_SEL BIT(5)
|
||||
#define P2R_RG_U2PLL_FRA_EN BIT(3)
|
||||
|
||||
#define U3D_U2PHYDCR0 0x060
|
||||
#define P2C_RG_SIF_U2PLL_FORCE_ON BIT(24)
|
||||
|
||||
|
@ -267,14 +282,31 @@
|
|||
#define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0)
|
||||
#define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x))
|
||||
|
||||
/* PHY switch between pcie/usb3/sgmii/sata */
|
||||
#define USB_PHY_SWITCH_CTRL 0x0
|
||||
#define RG_PHY_SW_TYPE GENMASK(3, 0)
|
||||
#define RG_PHY_SW_PCIE 0x0
|
||||
#define RG_PHY_SW_USB3 0x1
|
||||
#define RG_PHY_SW_SGMII 0x2
|
||||
#define RG_PHY_SW_SATA 0x3
|
||||
|
||||
#define TPHY_CLKS_CNT 2
|
||||
|
||||
enum mtk_phy_version {
|
||||
MTK_PHY_V1 = 1,
|
||||
MTK_PHY_V2,
|
||||
MTK_PHY_V3,
|
||||
};
|
||||
|
||||
struct mtk_phy_pdata {
|
||||
/* avoid RX sensitivity level degradation only for mt8173 */
|
||||
bool avoid_rx_sen_degradation;
|
||||
/*
|
||||
* workaround only for mt8195, HW fix it for others of V3,
|
||||
* u2phy should use integer mode instead of fractional mode of
|
||||
* 48M PLL, fix it by switching PLL to 26M from default 48M
|
||||
*/
|
||||
bool sw_pll_48m_to_26m;
|
||||
enum mtk_phy_version version;
|
||||
};
|
||||
|
||||
|
@ -298,10 +330,12 @@ struct mtk_phy_instance {
|
|||
struct u2phy_banks u2_banks;
|
||||
struct u3phy_banks u3_banks;
|
||||
};
|
||||
struct clk *ref_clk; /* reference clock of (digital) phy */
|
||||
struct clk *da_ref_clk; /* reference clock of analog phy */
|
||||
struct clk_bulk_data clks[TPHY_CLKS_CNT];
|
||||
u32 index;
|
||||
u8 type;
|
||||
u32 type;
|
||||
struct regmap *type_sw;
|
||||
u32 type_sw_reg;
|
||||
u32 type_sw_index;
|
||||
int eye_src;
|
||||
int eye_vrt;
|
||||
int eye_term;
|
||||
|
@ -330,6 +364,10 @@ static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
|
|||
int fm_out;
|
||||
u32 tmp;
|
||||
|
||||
/* HW V3 doesn't support slew rate cal anymore */
|
||||
if (tphy->pdata->version == MTK_PHY_V3)
|
||||
return;
|
||||
|
||||
/* use force value */
|
||||
if (instance->eye_src)
|
||||
return;
|
||||
|
@ -450,6 +488,33 @@ static void u3_phy_instance_init(struct mtk_tphy *tphy,
|
|||
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
|
||||
}
|
||||
|
||||
static void u2_phy_pll_26m_set(struct mtk_tphy *tphy,
|
||||
struct mtk_phy_instance *instance)
|
||||
{
|
||||
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
||||
void __iomem *com = u2_banks->com;
|
||||
u32 tmp;
|
||||
|
||||
if (!tphy->pdata->sw_pll_48m_to_26m)
|
||||
return;
|
||||
|
||||
tmp = readl(com + U3P_USBPHYACR0);
|
||||
tmp &= ~PA0_USB20_PLL_PREDIV;
|
||||
tmp |= PA0_USB20_PLL_PREDIV_VAL(0);
|
||||
writel(tmp, com + U3P_USBPHYACR0);
|
||||
|
||||
tmp = readl(com + U3P_USBPHYACR2);
|
||||
tmp &= ~PA2_RG_U2PLL_BW;
|
||||
tmp |= PA2_RG_U2PLL_BW_VAL(3);
|
||||
writel(tmp, com + U3P_USBPHYACR2);
|
||||
|
||||
writel(P2R_RG_U2PLL_FBDIV_26M, com + U3P_U2PHYA_RESV);
|
||||
|
||||
tmp = readl(com + U3P_U2PHYA_RESV1);
|
||||
tmp |= P2R_RG_U2PLL_FRA_EN | P2R_RG_U2PLL_REFCLK_SEL;
|
||||
writel(tmp, com + U3P_U2PHYA_RESV1);
|
||||
}
|
||||
|
||||
static void u2_phy_instance_init(struct mtk_tphy *tphy,
|
||||
struct mtk_phy_instance *instance)
|
||||
{
|
||||
|
@ -509,6 +574,9 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy,
|
|||
tmp |= PA6_RG_U2_SQTH_VAL(2);
|
||||
writel(tmp, com + U3P_USBPHYACR6);
|
||||
|
||||
/* Workaround only for mt8195, HW fix it for others (V3) */
|
||||
u2_phy_pll_26m_set(tphy, instance);
|
||||
|
||||
dev_dbg(tphy->dev, "%s(%d)\n", __func__, index);
|
||||
}
|
||||
|
||||
|
@ -878,7 +946,7 @@ static void u2_phy_props_set(struct mtk_tphy *tphy,
|
|||
writel(tmp, com + U3P_U2PHYBC12C);
|
||||
}
|
||||
|
||||
if (instance->eye_src) {
|
||||
if (tphy->pdata->version < MTK_PHY_V3 && instance->eye_src) {
|
||||
tmp = readl(com + U3P_USBPHYACR5);
|
||||
tmp &= ~PA5_RG_U2_HSTX_SRCTRL;
|
||||
tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(instance->eye_src);
|
||||
|
@ -914,24 +982,73 @@ static void u2_phy_props_set(struct mtk_tphy *tphy,
|
|||
}
|
||||
}
|
||||
|
||||
/* type switch for usb3/pcie/sgmii/sata */
|
||||
static int phy_type_syscon_get(struct mtk_phy_instance *instance,
|
||||
struct device_node *dn)
|
||||
{
|
||||
struct of_phandle_args args;
|
||||
int ret;
|
||||
|
||||
/* type switch function is optional */
|
||||
if (!of_property_read_bool(dn, "mediatek,syscon-type"))
|
||||
return 0;
|
||||
|
||||
ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type",
|
||||
2, 0, &args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
instance->type_sw_reg = args.args[0];
|
||||
instance->type_sw_index = args.args[1] & 0x3; /* <=3 */
|
||||
instance->type_sw = syscon_node_to_regmap(args.np);
|
||||
of_node_put(args.np);
|
||||
dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n",
|
||||
instance->type_sw_reg, instance->type_sw_index);
|
||||
|
||||
return PTR_ERR_OR_ZERO(instance->type_sw);
|
||||
}
|
||||
|
||||
static int phy_type_set(struct mtk_phy_instance *instance)
|
||||
{
|
||||
int type;
|
||||
u32 mask;
|
||||
|
||||
if (!instance->type_sw)
|
||||
return 0;
|
||||
|
||||
switch (instance->type) {
|
||||
case PHY_TYPE_USB3:
|
||||
type = RG_PHY_SW_USB3;
|
||||
break;
|
||||
case PHY_TYPE_PCIE:
|
||||
type = RG_PHY_SW_PCIE;
|
||||
break;
|
||||
case PHY_TYPE_SGMII:
|
||||
type = RG_PHY_SW_SGMII;
|
||||
break;
|
||||
case PHY_TYPE_SATA:
|
||||
type = RG_PHY_SW_SATA;
|
||||
break;
|
||||
case PHY_TYPE_USB2:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
mask = RG_PHY_SW_TYPE << (instance->type_sw_index * BITS_PER_BYTE);
|
||||
regmap_update_bits(instance->type_sw, instance->type_sw_reg, mask, type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_phy_init(struct phy *phy)
|
||||
{
|
||||
struct mtk_phy_instance *instance = phy_get_drvdata(phy);
|
||||
struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(instance->ref_clk);
|
||||
if (ret) {
|
||||
dev_err(tphy->dev, "failed to enable ref_clk\n");
|
||||
ret = clk_bulk_prepare_enable(TPHY_CLKS_CNT, instance->clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(instance->da_ref_clk);
|
||||
if (ret) {
|
||||
dev_err(tphy->dev, "failed to enable da_ref\n");
|
||||
clk_disable_unprepare(instance->ref_clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (instance->type) {
|
||||
case PHY_TYPE_USB2:
|
||||
|
@ -947,10 +1064,12 @@ static int mtk_phy_init(struct phy *phy)
|
|||
case PHY_TYPE_SATA:
|
||||
sata_phy_instance_init(tphy, instance);
|
||||
break;
|
||||
case PHY_TYPE_SGMII:
|
||||
/* nothing to do, only used to set type */
|
||||
break;
|
||||
default:
|
||||
dev_err(tphy->dev, "incompatible PHY type\n");
|
||||
clk_disable_unprepare(instance->ref_clk);
|
||||
clk_disable_unprepare(instance->da_ref_clk);
|
||||
clk_bulk_disable_unprepare(TPHY_CLKS_CNT, instance->clks);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -993,8 +1112,7 @@ static int mtk_phy_exit(struct phy *phy)
|
|||
if (instance->type == PHY_TYPE_USB2)
|
||||
u2_phy_instance_exit(tphy, instance);
|
||||
|
||||
clk_disable_unprepare(instance->ref_clk);
|
||||
clk_disable_unprepare(instance->da_ref_clk);
|
||||
clk_bulk_disable_unprepare(TPHY_CLKS_CNT, instance->clks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1037,21 +1155,27 @@ static struct phy *mtk_phy_xlate(struct device *dev,
|
|||
if (!(instance->type == PHY_TYPE_USB2 ||
|
||||
instance->type == PHY_TYPE_USB3 ||
|
||||
instance->type == PHY_TYPE_PCIE ||
|
||||
instance->type == PHY_TYPE_SATA)) {
|
||||
instance->type == PHY_TYPE_SATA ||
|
||||
instance->type == PHY_TYPE_SGMII)) {
|
||||
dev_err(dev, "unsupported device type: %d\n", instance->type);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (tphy->pdata->version == MTK_PHY_V1) {
|
||||
switch (tphy->pdata->version) {
|
||||
case MTK_PHY_V1:
|
||||
phy_v1_banks_init(tphy, instance);
|
||||
} else if (tphy->pdata->version == MTK_PHY_V2) {
|
||||
break;
|
||||
case MTK_PHY_V2:
|
||||
case MTK_PHY_V3:
|
||||
phy_v2_banks_init(tphy, instance);
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "phy version is not supported\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
phy_parse_property(tphy, instance);
|
||||
phy_type_set(instance);
|
||||
|
||||
return instance->phy;
|
||||
}
|
||||
|
@ -1075,17 +1199,28 @@ static const struct mtk_phy_pdata tphy_v2_pdata = {
|
|||
.version = MTK_PHY_V2,
|
||||
};
|
||||
|
||||
static const struct mtk_phy_pdata tphy_v3_pdata = {
|
||||
.version = MTK_PHY_V3,
|
||||
};
|
||||
|
||||
static const struct mtk_phy_pdata mt8173_pdata = {
|
||||
.avoid_rx_sen_degradation = true,
|
||||
.version = MTK_PHY_V1,
|
||||
};
|
||||
|
||||
static const struct mtk_phy_pdata mt8195_pdata = {
|
||||
.sw_pll_48m_to_26m = true,
|
||||
.version = MTK_PHY_V3,
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_tphy_id_table[] = {
|
||||
{ .compatible = "mediatek,mt2701-u3phy", .data = &tphy_v1_pdata },
|
||||
{ .compatible = "mediatek,mt2712-u3phy", .data = &tphy_v2_pdata },
|
||||
{ .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata },
|
||||
{ .compatible = "mediatek,mt8195-tphy", .data = &mt8195_pdata },
|
||||
{ .compatible = "mediatek,generic-tphy-v1", .data = &tphy_v1_pdata },
|
||||
{ .compatible = "mediatek,generic-tphy-v2", .data = &tphy_v2_pdata },
|
||||
{ .compatible = "mediatek,generic-tphy-v3", .data = &tphy_v3_pdata },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_tphy_id_table);
|
||||
|
@ -1129,16 +1264,21 @@ static int mtk_tphy_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
tphy->src_ref_clk = U3P_REF_CLK;
|
||||
tphy->src_coef = U3P_SLEW_RATE_COEF;
|
||||
/* update parameters of slew rate calibrate if exist */
|
||||
device_property_read_u32(dev, "mediatek,src-ref-clk-mhz",
|
||||
&tphy->src_ref_clk);
|
||||
device_property_read_u32(dev, "mediatek,src-coef", &tphy->src_coef);
|
||||
if (tphy->pdata->version < MTK_PHY_V3) {
|
||||
tphy->src_ref_clk = U3P_REF_CLK;
|
||||
tphy->src_coef = U3P_SLEW_RATE_COEF;
|
||||
/* update parameters of slew rate calibrate if exist */
|
||||
device_property_read_u32(dev, "mediatek,src-ref-clk-mhz",
|
||||
&tphy->src_ref_clk);
|
||||
device_property_read_u32(dev, "mediatek,src-coef",
|
||||
&tphy->src_coef);
|
||||
}
|
||||
|
||||
port = 0;
|
||||
for_each_child_of_node(np, child_np) {
|
||||
struct mtk_phy_instance *instance;
|
||||
struct clk_bulk_data *clks;
|
||||
struct device *subdev;
|
||||
struct phy *phy;
|
||||
|
||||
instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
|
||||
|
@ -1156,16 +1296,16 @@ static int mtk_tphy_probe(struct platform_device *pdev)
|
|||
goto put_child;
|
||||
}
|
||||
|
||||
subdev = &phy->dev;
|
||||
retval = of_address_to_resource(child_np, 0, &res);
|
||||
if (retval) {
|
||||
dev_err(dev, "failed to get address resource(id-%d)\n",
|
||||
dev_err(subdev, "failed to get address resource(id-%d)\n",
|
||||
port);
|
||||
goto put_child;
|
||||
}
|
||||
|
||||
instance->port_base = devm_ioremap_resource(&phy->dev, &res);
|
||||
instance->port_base = devm_ioremap_resource(subdev, &res);
|
||||
if (IS_ERR(instance->port_base)) {
|
||||
dev_err(dev, "failed to remap phy regs\n");
|
||||
retval = PTR_ERR(instance->port_base);
|
||||
goto put_child;
|
||||
}
|
||||
|
@ -1175,20 +1315,16 @@ static int mtk_tphy_probe(struct platform_device *pdev)
|
|||
phy_set_drvdata(phy, instance);
|
||||
port++;
|
||||
|
||||
instance->ref_clk = devm_clk_get_optional(&phy->dev, "ref");
|
||||
if (IS_ERR(instance->ref_clk)) {
|
||||
dev_err(dev, "failed to get ref_clk(id-%d)\n", port);
|
||||
retval = PTR_ERR(instance->ref_clk);
|
||||
clks = instance->clks;
|
||||
clks[0].id = "ref"; /* digital (& analog) clock */
|
||||
clks[1].id = "da_ref"; /* analog clock */
|
||||
retval = devm_clk_bulk_get_optional(subdev, TPHY_CLKS_CNT, clks);
|
||||
if (retval)
|
||||
goto put_child;
|
||||
}
|
||||
|
||||
instance->da_ref_clk =
|
||||
devm_clk_get_optional(&phy->dev, "da_ref");
|
||||
if (IS_ERR(instance->da_ref_clk)) {
|
||||
dev_err(dev, "failed to get da_ref_clk(id-%d)\n", port);
|
||||
retval = PTR_ERR(instance->da_ref_clk);
|
||||
retval = phy_type_syscon_get(instance, child_np);
|
||||
if (retval)
|
||||
goto put_child;
|
||||
}
|
||||
}
|
||||
|
||||
provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
|
||||
|
|
|
@ -31,11 +31,12 @@
|
|||
#define FRC_CDR_ISO_EN BIT(19)
|
||||
#define CDR_ISO_EN BIT(20)
|
||||
|
||||
#define UFSPHY_CLKS_CNT 2
|
||||
|
||||
struct ufs_mtk_phy {
|
||||
struct device *dev;
|
||||
void __iomem *mmio;
|
||||
struct clk *mp_clk;
|
||||
struct clk *unipro_clk;
|
||||
struct clk_bulk_data clks[UFSPHY_CLKS_CNT];
|
||||
};
|
||||
|
||||
static inline u32 mphy_readl(struct ufs_mtk_phy *phy, u32 reg)
|
||||
|
@ -74,20 +75,11 @@ static struct ufs_mtk_phy *get_ufs_mtk_phy(struct phy *generic_phy)
|
|||
static int ufs_mtk_phy_clk_init(struct ufs_mtk_phy *phy)
|
||||
{
|
||||
struct device *dev = phy->dev;
|
||||
struct clk_bulk_data *clks = phy->clks;
|
||||
|
||||
phy->unipro_clk = devm_clk_get(dev, "unipro");
|
||||
if (IS_ERR(phy->unipro_clk)) {
|
||||
dev_err(dev, "failed to get clock: unipro");
|
||||
return PTR_ERR(phy->unipro_clk);
|
||||
}
|
||||
|
||||
phy->mp_clk = devm_clk_get(dev, "mp");
|
||||
if (IS_ERR(phy->mp_clk)) {
|
||||
dev_err(dev, "failed to get clock: mp");
|
||||
return PTR_ERR(phy->mp_clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
clks[0].id = "unipro";
|
||||
clks[1].id = "mp";
|
||||
return devm_clk_bulk_get(dev, UFSPHY_CLKS_CNT, clks);
|
||||
}
|
||||
|
||||
static void ufs_mtk_phy_set_active(struct ufs_mtk_phy *phy)
|
||||
|
@ -150,26 +142,13 @@ static int ufs_mtk_phy_power_on(struct phy *generic_phy)
|
|||
struct ufs_mtk_phy *phy = get_ufs_mtk_phy(generic_phy);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(phy->unipro_clk);
|
||||
if (ret) {
|
||||
dev_err(phy->dev, "unipro_clk enable failed %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(phy->mp_clk);
|
||||
if (ret) {
|
||||
dev_err(phy->dev, "mp_clk enable failed %d\n", ret);
|
||||
goto out_unprepare_unipro_clk;
|
||||
}
|
||||
ret = clk_bulk_prepare_enable(UFSPHY_CLKS_CNT, phy->clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ufs_mtk_phy_set_active(phy);
|
||||
|
||||
return 0;
|
||||
|
||||
out_unprepare_unipro_clk:
|
||||
clk_disable_unprepare(phy->unipro_clk);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ufs_mtk_phy_power_off(struct phy *generic_phy)
|
||||
|
@ -178,8 +157,7 @@ static int ufs_mtk_phy_power_off(struct phy *generic_phy)
|
|||
|
||||
ufs_mtk_phy_set_deep_hibern(phy);
|
||||
|
||||
clk_disable_unprepare(phy->unipro_clk);
|
||||
clk_disable_unprepare(phy->mp_clk);
|
||||
clk_bulk_disable_unprepare(UFSPHY_CLKS_CNT, phy->clks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -234,6 +234,11 @@ static const unsigned int sdm845_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = {
|
|||
[QPHY_PCS_READY_STATUS] = 0x160,
|
||||
};
|
||||
|
||||
static const unsigned int sm6115_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = {
|
||||
[QPHY_START_CTRL] = 0x00,
|
||||
[QPHY_PCS_READY_STATUS] = 0x168,
|
||||
};
|
||||
|
||||
static const unsigned int sm8250_pcie_regs_layout[QPHY_LAYOUT_SIZE] = {
|
||||
[QPHY_SW_RESET] = 0x00,
|
||||
[QPHY_START_CTRL] = 0x44,
|
||||
|
@ -1329,6 +1334,97 @@ static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = {
|
|||
QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm6115_ufsphy_serdes_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL1, 0xff),
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00),
|
||||
|
||||
/* Rate B */
|
||||
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x44),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm6115_ufsphy_tx_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
|
||||
QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm6115_ufsphy_rx_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x0F),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x40),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5B),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5B),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm6115_ufsphy_pcs_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_RX_PWM_GEAR_BAND, 0x15),
|
||||
QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_CTRL2, 0x6d),
|
||||
QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_DRV_LVL, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_DRV_LVL, 0x02),
|
||||
QMP_PHY_INIT_CFG(QPHY_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28),
|
||||
QMP_PHY_INIT_CFG(QPHY_RX_SYM_RESYNC_CTRL, 0x03),
|
||||
QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_POST_EMP_LVL, 0x12),
|
||||
QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_POST_EMP_LVL, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QPHY_RX_MIN_HIBERN8_TIME, 0x9a), /* 8 us */
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
|
||||
|
@ -2035,6 +2131,113 @@ static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = {
|
|||
QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_serdes_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_tx_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x5),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_rx_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x14),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x07),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x6e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x4a),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x37),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x39),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x39),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xdb),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x75),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0xc0),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x05),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x01),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_misc_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58),
|
||||
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
|
||||
};
|
||||
|
||||
static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34),
|
||||
|
@ -3289,6 +3492,31 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
|
|||
.no_pcs_sw_reset = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm6115_ufsphy_cfg = {
|
||||
.type = PHY_TYPE_UFS,
|
||||
.nlanes = 1,
|
||||
|
||||
.serdes_tbl = sm6115_ufsphy_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm6115_ufsphy_serdes_tbl),
|
||||
.tx_tbl = sm6115_ufsphy_tx_tbl,
|
||||
.tx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_tx_tbl),
|
||||
.rx_tbl = sm6115_ufsphy_rx_tbl,
|
||||
.rx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_rx_tbl),
|
||||
.pcs_tbl = sm6115_ufsphy_pcs_tbl,
|
||||
.pcs_tbl_num = ARRAY_SIZE(sm6115_ufsphy_pcs_tbl),
|
||||
.clk_list = sdm845_ufs_phy_clk_l,
|
||||
.num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
|
||||
.vreg_list = qmp_phy_vreg_l,
|
||||
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
|
||||
.regs = sm6115_ufsphy_regs_layout,
|
||||
|
||||
.start_ctrl = SERDES_START,
|
||||
.pwrdn_ctrl = SW_PWRDN,
|
||||
|
||||
.is_dual_lane_phy = false,
|
||||
.no_pcs_sw_reset = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg msm8998_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 1,
|
||||
|
@ -3399,6 +3627,76 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = {
|
|||
.is_dual_lane_phy = true,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sc8180x_pciephy_cfg = {
|
||||
.type = PHY_TYPE_PCIE,
|
||||
.nlanes = 1,
|
||||
|
||||
.serdes_tbl = sc8180x_qmp_pcie_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl),
|
||||
.tx_tbl = sc8180x_qmp_pcie_tx_tbl,
|
||||
.tx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_tx_tbl),
|
||||
.rx_tbl = sc8180x_qmp_pcie_rx_tbl,
|
||||
.rx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_rx_tbl),
|
||||
.pcs_tbl = sc8180x_qmp_pcie_pcs_tbl,
|
||||
.pcs_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_tbl),
|
||||
.pcs_misc_tbl = sc8180x_qmp_pcie_pcs_misc_tbl,
|
||||
.pcs_misc_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_misc_tbl),
|
||||
.clk_list = sdm845_pciephy_clk_l,
|
||||
.num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l),
|
||||
.reset_list = sdm845_pciephy_reset_l,
|
||||
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
|
||||
.vreg_list = qmp_phy_vreg_l,
|
||||
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
|
||||
.regs = sm8250_pcie_regs_layout,
|
||||
|
||||
.start_ctrl = PCS_START | SERDES_START,
|
||||
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
|
||||
|
||||
.has_pwrdn_delay = true,
|
||||
.pwrdn_delay_min = 995, /* us */
|
||||
.pwrdn_delay_max = 1005, /* us */
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sc8180x_dpphy_cfg = {
|
||||
.type = PHY_TYPE_DP,
|
||||
.nlanes = 1,
|
||||
|
||||
.serdes_tbl = qmp_v4_dp_serdes_tbl,
|
||||
.serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl),
|
||||
.tx_tbl = qmp_v4_dp_tx_tbl,
|
||||
.tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl),
|
||||
|
||||
.serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr,
|
||||
.serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr),
|
||||
.serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr,
|
||||
.serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr),
|
||||
.serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2,
|
||||
.serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2),
|
||||
.serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3,
|
||||
.serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3),
|
||||
|
||||
.clk_list = qmp_v3_phy_clk_l,
|
||||
.num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l),
|
||||
.reset_list = sc7180_usb3phy_reset_l,
|
||||
.num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l),
|
||||
.vreg_list = qmp_phy_vreg_l,
|
||||
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
|
||||
.regs = qmp_v3_usb3phy_regs_layout,
|
||||
|
||||
.has_phy_dp_com_ctrl = true,
|
||||
.is_dual_lane_phy = true,
|
||||
|
||||
.dp_aux_init = qcom_qmp_v4_phy_dp_aux_init,
|
||||
.configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx,
|
||||
.configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy,
|
||||
.calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_combo_cfg sc8180x_usb3dpphy_cfg = {
|
||||
.usb_cfg = &sm8150_usb3phy_cfg,
|
||||
.dp_cfg = &sc8180x_dpphy_cfg,
|
||||
};
|
||||
|
||||
static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = {
|
||||
.type = PHY_TYPE_USB3,
|
||||
.nlanes = 1,
|
||||
|
@ -5018,6 +5316,7 @@ static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy,
|
|||
{
|
||||
struct clk_init_data init = { };
|
||||
struct qmp_phy_dp_clks *dp_clks;
|
||||
char name[64];
|
||||
int ret;
|
||||
|
||||
dp_clks = devm_kzalloc(qmp->dev, sizeof(*dp_clks), GFP_KERNEL);
|
||||
|
@ -5027,15 +5326,17 @@ static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy,
|
|||
dp_clks->qphy = qphy;
|
||||
qphy->dp_clks = dp_clks;
|
||||
|
||||
snprintf(name, sizeof(name), "%s::link_clk", dev_name(qmp->dev));
|
||||
init.ops = &qcom_qmp_dp_link_clk_ops;
|
||||
init.name = "qmp_dp_phy_pll_link_clk";
|
||||
init.name = name;
|
||||
dp_clks->dp_link_hw.init = &init;
|
||||
ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_link_hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(qmp->dev));
|
||||
init.ops = &qcom_qmp_dp_pixel_clk_ops;
|
||||
init.name = "qmp_dp_phy_pll_vco_div_clk";
|
||||
init.name = name;
|
||||
dp_clks->dp_pixel_hw.init = &init;
|
||||
ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_pixel_hw);
|
||||
if (ret)
|
||||
|
@ -5225,18 +5526,27 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
|
|||
}, {
|
||||
.compatible = "qcom,ipq6018-qmp-pcie-phy",
|
||||
.data = &ipq6018_pciephy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,ipq6018-qmp-usb3-phy",
|
||||
.data = &ipq8074_usb3phy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sc7180-qmp-usb3-phy",
|
||||
.data = &sc7180_usb3phy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sc7180-qmp-usb3-dp-phy",
|
||||
/* It's a combo phy */
|
||||
}, {
|
||||
.compatible = "qcom,sc8180x-qmp-pcie-phy",
|
||||
.data = &sc8180x_pciephy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sc8180x-qmp-ufs-phy",
|
||||
.data = &sm8150_ufsphy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sc8180x-qmp-usb3-phy",
|
||||
.data = &sm8150_usb3phy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sc8180x-qmp-usb3-dp-phy",
|
||||
/* It's a combo phy */
|
||||
}, {
|
||||
.compatible = "qcom,sdm845-qhp-pcie-phy",
|
||||
.data = &sdm845_qhp_pciephy_cfg,
|
||||
|
@ -5255,6 +5565,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
|
|||
}, {
|
||||
.compatible = "qcom,msm8998-qmp-usb3-phy",
|
||||
.data = &msm8998_usb3phy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sm6115-qmp-ufs-phy",
|
||||
.data = &sm6115_ufsphy_cfg,
|
||||
}, {
|
||||
.compatible = "qcom,sm8150-qmp-ufs-phy",
|
||||
.data = &sm8150_ufsphy_cfg,
|
||||
|
@ -5314,6 +5627,10 @@ static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = {
|
|||
.compatible = "qcom,sm8250-qmp-usb3-dp-phy",
|
||||
.data = &sm8250_usb3dpphy_cfg,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,sc8180x-qmp-usb3-dp-phy",
|
||||
.data = &sc8180x_usb3dpphy_cfg,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -191,6 +191,8 @@
|
|||
#define QSERDES_COM_VCO_TUNE2_MODE0 0x130
|
||||
#define QSERDES_COM_VCO_TUNE1_MODE1 0x134
|
||||
#define QSERDES_COM_VCO_TUNE2_MODE1 0x138
|
||||
#define QSERDES_COM_VCO_TUNE_INITVAL1 0x13c
|
||||
#define QSERDES_COM_VCO_TUNE_INITVAL2 0x140
|
||||
#define QSERDES_COM_VCO_TUNE_TIMER1 0x144
|
||||
#define QSERDES_COM_VCO_TUNE_TIMER2 0x148
|
||||
#define QSERDES_COM_BG_CTRL 0x170
|
||||
|
@ -220,6 +222,10 @@
|
|||
/* Only for QMP V2 PHY - RX registers */
|
||||
#define QSERDES_RX_UCDR_SO_GAIN_HALF 0x010
|
||||
#define QSERDES_RX_UCDR_SO_GAIN 0x01c
|
||||
#define QSERDES_RX_UCDR_SVS_SO_GAIN_HALF 0x030
|
||||
#define QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER 0x034
|
||||
#define QSERDES_RX_UCDR_SVS_SO_GAIN_EIGHTH 0x038
|
||||
#define QSERDES_RX_UCDR_SVS_SO_GAIN 0x03c
|
||||
#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN 0x040
|
||||
#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x048
|
||||
#define QSERDES_RX_RX_TERM_BW 0x090
|
||||
|
@ -243,6 +249,10 @@
|
|||
#define QPHY_POWER_DOWN_CONTROL 0x04
|
||||
#define QPHY_TXDEEMPH_M6DB_V0 0x24
|
||||
#define QPHY_TXDEEMPH_M3P5DB_V0 0x28
|
||||
#define QPHY_TX_LARGE_AMP_DRV_LVL 0x34
|
||||
#define QPHY_TX_LARGE_AMP_POST_EMP_LVL 0x38
|
||||
#define QPHY_TX_SMALL_AMP_DRV_LVL 0x3c
|
||||
#define QPHY_TX_SMALL_AMP_POST_EMP_LVL 0x40
|
||||
#define QPHY_ENDPOINT_REFCLK_DRIVE 0x54
|
||||
#define QPHY_RX_IDLE_DTCT_CNTRL 0x58
|
||||
#define QPHY_POWER_STATE_CONFIG1 0x60
|
||||
|
@ -253,6 +263,11 @@
|
|||
#define QPHY_LOCK_DETECT_CONFIG3 0x88
|
||||
#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0
|
||||
#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4
|
||||
#define QPHY_RX_MIN_STALL_NOCONFIG_TIME_CAP 0xcc
|
||||
#define QPHY_RX_SYM_RESYNC_CTRL 0x13c
|
||||
#define QPHY_RX_MIN_HIBERN8_TIME 0x140
|
||||
#define QPHY_RX_SIGDET_CTRL2 0x148
|
||||
#define QPHY_RX_PWM_GEAR_BAND 0x154
|
||||
#define QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB 0x1A8
|
||||
#define QPHY_OSC_DTCT_ACTIONS 0x1AC
|
||||
#define QPHY_RX_SIGDET_LVL 0x1D8
|
||||
|
@ -280,6 +295,8 @@
|
|||
#define QSERDES_V3_COM_SSC_PER2 0x020
|
||||
#define QSERDES_V3_COM_SSC_STEP_SIZE1 0x024
|
||||
#define QSERDES_V3_COM_SSC_STEP_SIZE2 0x028
|
||||
#define QSERDES_V3_COM_POST_DIV 0x02c
|
||||
#define QSERDES_V3_COM_POST_DIV_MUX 0x030
|
||||
#define QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN 0x034
|
||||
# define QSERDES_V3_COM_BIAS_EN 0x0001
|
||||
# define QSERDES_V3_COM_BIAS_EN_MUX 0x0002
|
||||
|
@ -291,6 +308,7 @@
|
|||
#define QSERDES_V3_COM_CLK_ENABLE1 0x038
|
||||
#define QSERDES_V3_COM_SYS_CLK_CTRL 0x03c
|
||||
#define QSERDES_V3_COM_SYSCLK_BUF_ENABLE 0x040
|
||||
#define QSERDES_V3_COM_PLL_EN 0x044
|
||||
#define QSERDES_V3_COM_PLL_IVCO 0x048
|
||||
#define QSERDES_V3_COM_LOCK_CMP1_MODE0 0x098
|
||||
#define QSERDES_V3_COM_LOCK_CMP2_MODE0 0x09c
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2016 Linaro Ltd
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
/* VBCTRL */
|
||||
#define USB2_VBCTRL_OCCLREN BIT(16)
|
||||
#define USB2_VBCTRL_DRVVBUSSEL BIT(8)
|
||||
#define USB2_VBCTRL_VBOUT BIT(0)
|
||||
|
||||
/* LINECTRL1 */
|
||||
#define USB2_LINECTRL1_DPRPD_EN BIT(19)
|
||||
|
@ -78,6 +79,10 @@
|
|||
#define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */
|
||||
#define USB2_ADPCTRL_DRVVBUS BIT(4)
|
||||
|
||||
/* RZ/G2L specific */
|
||||
#define USB2_OBINT_IDCHG_EN BIT(0)
|
||||
#define USB2_LINECTRL1_USB2_IDMON BIT(0)
|
||||
|
||||
#define NUM_OF_PHYS 4
|
||||
enum rcar_gen3_phy_index {
|
||||
PHY_INDEX_BOTH_HC,
|
||||
|
@ -112,9 +117,16 @@ struct rcar_gen3_chan {
|
|||
struct mutex lock; /* protects rphys[...].powered */
|
||||
enum usb_dr_mode dr_mode;
|
||||
int irq;
|
||||
u32 obint_enable_bits;
|
||||
bool extcon_host;
|
||||
bool is_otg_channel;
|
||||
bool uses_otg_pins;
|
||||
bool soc_no_adp_ctrl;
|
||||
};
|
||||
|
||||
struct rcar_gen3_phy_drv_data {
|
||||
const struct phy_ops *phy_usb2_ops;
|
||||
bool no_adp_ctrl;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -172,14 +184,22 @@ static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
|
|||
static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
|
||||
{
|
||||
void __iomem *usb2_base = ch->base;
|
||||
u32 val = readl(usb2_base + USB2_ADPCTRL);
|
||||
u32 vbus_ctrl_reg = USB2_ADPCTRL;
|
||||
u32 vbus_ctrl_val = USB2_ADPCTRL_DRVVBUS;
|
||||
u32 val;
|
||||
|
||||
dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus);
|
||||
if (ch->soc_no_adp_ctrl) {
|
||||
vbus_ctrl_reg = USB2_VBCTRL;
|
||||
vbus_ctrl_val = USB2_VBCTRL_VBOUT;
|
||||
}
|
||||
|
||||
val = readl(usb2_base + vbus_ctrl_reg);
|
||||
if (vbus)
|
||||
val |= USB2_ADPCTRL_DRVVBUS;
|
||||
val |= vbus_ctrl_val;
|
||||
else
|
||||
val &= ~USB2_ADPCTRL_DRVVBUS;
|
||||
writel(val, usb2_base + USB2_ADPCTRL);
|
||||
val &= ~vbus_ctrl_val;
|
||||
writel(val, usb2_base + vbus_ctrl_reg);
|
||||
}
|
||||
|
||||
static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable)
|
||||
|
@ -188,9 +208,9 @@ static void rcar_gen3_control_otg_irq(struct rcar_gen3_chan *ch, int enable)
|
|||
u32 val = readl(usb2_base + USB2_OBINTEN);
|
||||
|
||||
if (ch->uses_otg_pins && enable)
|
||||
val |= USB2_OBINT_BITS;
|
||||
val |= ch->obint_enable_bits;
|
||||
else
|
||||
val &= ~USB2_OBINT_BITS;
|
||||
val &= ~ch->obint_enable_bits;
|
||||
writel(val, usb2_base + USB2_OBINTEN);
|
||||
}
|
||||
|
||||
|
@ -252,6 +272,9 @@ static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
|
|||
if (!ch->uses_otg_pins)
|
||||
return (ch->dr_mode == USB_DR_MODE_HOST) ? false : true;
|
||||
|
||||
if (ch->soc_no_adp_ctrl)
|
||||
return !!(readl(ch->base + USB2_LINECTRL1) & USB2_LINECTRL1_USB2_IDMON);
|
||||
|
||||
return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
|
||||
}
|
||||
|
||||
|
@ -376,16 +399,17 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
|
|||
USB2_LINECTRL1_DMRPD_EN | USB2_LINECTRL1_DM_RPD;
|
||||
writel(val, usb2_base + USB2_LINECTRL1);
|
||||
|
||||
val = readl(usb2_base + USB2_VBCTRL);
|
||||
val &= ~USB2_VBCTRL_OCCLREN;
|
||||
writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
|
||||
val = readl(usb2_base + USB2_ADPCTRL);
|
||||
writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
|
||||
|
||||
if (!ch->soc_no_adp_ctrl) {
|
||||
val = readl(usb2_base + USB2_VBCTRL);
|
||||
val &= ~USB2_VBCTRL_OCCLREN;
|
||||
writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
|
||||
val = readl(usb2_base + USB2_ADPCTRL);
|
||||
writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
writel(0xffffffff, usb2_base + USB2_OBINTSTA);
|
||||
writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
|
||||
writel(ch->obint_enable_bits, usb2_base + USB2_OBINTEN);
|
||||
|
||||
rcar_gen3_device_recognition(ch);
|
||||
}
|
||||
|
@ -397,9 +421,9 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
|
|||
u32 status = readl(usb2_base + USB2_OBINTSTA);
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
if (status & USB2_OBINT_BITS) {
|
||||
if (status & ch->obint_enable_bits) {
|
||||
dev_vdbg(ch->dev, "%s: %08x\n", __func__, status);
|
||||
writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
|
||||
writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA);
|
||||
rcar_gen3_device_recognition(ch);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
@ -535,26 +559,45 @@ static const struct phy_ops rz_g1c_phy_usb2_ops = {
|
|||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct rcar_gen3_phy_drv_data rcar_gen3_phy_usb2_data = {
|
||||
.phy_usb2_ops = &rcar_gen3_phy_usb2_ops,
|
||||
.no_adp_ctrl = false,
|
||||
};
|
||||
|
||||
static const struct rcar_gen3_phy_drv_data rz_g1c_phy_usb2_data = {
|
||||
.phy_usb2_ops = &rz_g1c_phy_usb2_ops,
|
||||
.no_adp_ctrl = false,
|
||||
};
|
||||
|
||||
static const struct rcar_gen3_phy_drv_data rz_g2l_phy_usb2_data = {
|
||||
.phy_usb2_ops = &rcar_gen3_phy_usb2_ops,
|
||||
.no_adp_ctrl = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
|
||||
{
|
||||
.compatible = "renesas,usb2-phy-r8a77470",
|
||||
.data = &rz_g1c_phy_usb2_ops,
|
||||
.data = &rz_g1c_phy_usb2_data,
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,usb2-phy-r8a7795",
|
||||
.data = &rcar_gen3_phy_usb2_ops,
|
||||
.data = &rcar_gen3_phy_usb2_data,
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,usb2-phy-r8a7796",
|
||||
.data = &rcar_gen3_phy_usb2_ops,
|
||||
.data = &rcar_gen3_phy_usb2_data,
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,usb2-phy-r8a77965",
|
||||
.data = &rcar_gen3_phy_usb2_ops,
|
||||
.data = &rcar_gen3_phy_usb2_data,
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,rzg2l-usb2-phy",
|
||||
.data = &rz_g2l_phy_usb2_data,
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,rcar-gen3-usb2-phy",
|
||||
.data = &rcar_gen3_phy_usb2_ops,
|
||||
.data = &rcar_gen3_phy_usb2_data,
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
@ -608,10 +651,10 @@ static enum usb_dr_mode rcar_gen3_get_dr_mode(struct device_node *np)
|
|||
|
||||
static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct rcar_gen3_phy_drv_data *phy_data;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rcar_gen3_chan *channel;
|
||||
struct phy_provider *provider;
|
||||
const struct phy_ops *phy_usb2_ops;
|
||||
int ret = 0, i;
|
||||
|
||||
if (!dev->of_node) {
|
||||
|
@ -627,6 +670,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(channel->base))
|
||||
return PTR_ERR(channel->base);
|
||||
|
||||
channel->obint_enable_bits = USB2_OBINT_BITS;
|
||||
/* get irq number here and request_irq for OTG in phy_init */
|
||||
channel->irq = platform_get_irq_optional(pdev, 0);
|
||||
channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node);
|
||||
|
@ -653,16 +697,21 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
|
|||
* And then, phy-core will manage runtime pm for this device.
|
||||
*/
|
||||
pm_runtime_enable(dev);
|
||||
phy_usb2_ops = of_device_get_match_data(dev);
|
||||
if (!phy_usb2_ops) {
|
||||
|
||||
phy_data = of_device_get_match_data(dev);
|
||||
if (!phy_data) {
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl;
|
||||
if (phy_data->no_adp_ctrl)
|
||||
channel->obint_enable_bits = USB2_OBINT_IDCHG_EN;
|
||||
|
||||
mutex_init(&channel->lock);
|
||||
for (i = 0; i < NUM_OF_PHYS; i++) {
|
||||
channel->rphys[i].phy = devm_phy_create(dev, NULL,
|
||||
phy_usb2_ops);
|
||||
phy_data->phy_usb2_ops);
|
||||
if (IS_ERR(channel->rphys[i].phy)) {
|
||||
dev_err(dev, "Failed to create USB2 PHY\n");
|
||||
ret = PTR_ERR(channel->rphys[i].phy);
|
||||
|
|
|
@ -1180,8 +1180,10 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
|
|||
|
||||
next_child:
|
||||
/* to prevent out of boundary */
|
||||
if (++index >= rphy->phy_cfg->num_ports)
|
||||
if (++index >= rphy->phy_cfg->num_ports) {
|
||||
of_node_put(child_np);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
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-samsung-ufs.o
|
||||
obj-$(CONFIG_PHY_SAMSUNG_UFS) += phy-exynos-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
|
||||
obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
|
||||
phy-exynos-usb2-y += phy-samsung-usb2.o
|
||||
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* UFS PHY driver data for Samsung EXYNOS7 SoC
|
||||
*
|
||||
* Copyright (C) 2020 Samsung Electronics Co., Ltd.
|
||||
*/
|
||||
#ifndef _PHY_EXYNOS7_UFS_H_
|
||||
#define _PHY_EXYNOS7_UFS_H_
|
||||
|
||||
#include "phy-samsung-ufs.h"
|
||||
|
||||
|
@ -68,7 +66,7 @@ static const struct samsung_ufs_phy_cfg *exynos7_ufs_phy_cfgs[CFG_TAG_MAX] = {
|
|||
[CFG_POST_PWR_HS] = exynos7_post_pwr_hs_cfg,
|
||||
};
|
||||
|
||||
static struct samsung_ufs_phy_drvdata exynos7_ufs_phy = {
|
||||
const struct samsung_ufs_phy_drvdata exynos7_ufs_phy = {
|
||||
.cfg = exynos7_ufs_phy_cfgs,
|
||||
.isol = {
|
||||
.offset = EXYNOS7_EMBEDDED_COMBO_PHY_CTRL,
|
||||
|
@ -77,5 +75,3 @@ static struct samsung_ufs_phy_drvdata exynos7_ufs_phy = {
|
|||
},
|
||||
.has_symbol_clk = 1,
|
||||
};
|
||||
|
||||
#endif /* _PHY_EXYNOS7_UFS_H_ */
|
|
@ -0,0 +1,67 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* UFS PHY driver data for Samsung EXYNOSAUTO v9 SoC
|
||||
*
|
||||
* Copyright (C) 2021 Samsung Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "phy-samsung-ufs.h"
|
||||
|
||||
#define EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL 0x728
|
||||
#define EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_MASK 0x1
|
||||
#define EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_EN BIT(0)
|
||||
|
||||
#define PHY_TRSV_REG_CFG_AUTOV9(o, v, d) \
|
||||
PHY_TRSV_REG_CFG_OFFSET(o, v, d, 0x50)
|
||||
|
||||
/* Calibration for phy initialization */
|
||||
static const struct samsung_ufs_phy_cfg exynosautov9_pre_init_cfg[] = {
|
||||
PHY_COMN_REG_CFG(0x023, 0x80, PWR_MODE_ANY),
|
||||
PHY_COMN_REG_CFG(0x01d, 0x10, PWR_MODE_ANY),
|
||||
|
||||
PHY_TRSV_REG_CFG_AUTOV9(0x044, 0xb5, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_AUTOV9(0x04d, 0x43, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_AUTOV9(0x05b, 0x20, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_AUTOV9(0x05e, 0xc0, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_AUTOV9(0x038, 0x12, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_AUTOV9(0x059, 0x58, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_AUTOV9(0x06c, 0x18, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG_AUTOV9(0x06d, 0x02, PWR_MODE_ANY),
|
||||
|
||||
PHY_COMN_REG_CFG(0x023, 0xc0, PWR_MODE_ANY),
|
||||
PHY_COMN_REG_CFG(0x023, 0x00, PWR_MODE_ANY),
|
||||
|
||||
PHY_TRSV_REG_CFG(0x042, 0x5d, PWR_MODE_ANY),
|
||||
PHY_TRSV_REG_CFG(0x043, 0x80, PWR_MODE_ANY),
|
||||
|
||||
END_UFS_PHY_CFG,
|
||||
};
|
||||
|
||||
/* Calibration for HS mode series A/B */
|
||||
static const struct samsung_ufs_phy_cfg exynosautov9_pre_pwr_hs_cfg[] = {
|
||||
PHY_TRSV_REG_CFG(0x032, 0xbc, PWR_MODE_HS_ANY),
|
||||
PHY_TRSV_REG_CFG(0x03c, 0x7f, PWR_MODE_HS_ANY),
|
||||
PHY_TRSV_REG_CFG(0x048, 0xc0, PWR_MODE_HS_ANY),
|
||||
|
||||
PHY_TRSV_REG_CFG(0x04a, 0x00, PWR_MODE_HS_G3_SER_B),
|
||||
PHY_TRSV_REG_CFG(0x04b, 0x10, PWR_MODE_HS_G1_SER_B |
|
||||
PWR_MODE_HS_G3_SER_B),
|
||||
PHY_TRSV_REG_CFG(0x04d, 0x63, PWR_MODE_HS_G3_SER_B),
|
||||
|
||||
END_UFS_PHY_CFG,
|
||||
};
|
||||
|
||||
static const struct samsung_ufs_phy_cfg *exynosautov9_ufs_phy_cfgs[CFG_TAG_MAX] = {
|
||||
[CFG_PRE_INIT] = exynosautov9_pre_init_cfg,
|
||||
[CFG_PRE_PWR_HS] = exynosautov9_pre_pwr_hs_cfg,
|
||||
};
|
||||
|
||||
const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy = {
|
||||
.cfg = exynosautov9_ufs_phy_cfgs,
|
||||
.isol = {
|
||||
.offset = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL,
|
||||
.mask = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_MASK,
|
||||
.en = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_EN,
|
||||
},
|
||||
.has_symbol_clk = 0,
|
||||
};
|
|
@ -347,6 +347,9 @@ static const struct of_device_id samsung_ufs_phy_match[] = {
|
|||
{
|
||||
.compatible = "samsung,exynos7-ufs-phy",
|
||||
.data = &exynos7_ufs_phy,
|
||||
}, {
|
||||
.compatible = "samsung,exynosautov9-ufs-phy",
|
||||
.data = &exynosautov9_ufs_phy,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#ifndef _PHY_SAMSUNG_UFS_
|
||||
#define _PHY_SAMSUNG_UFS_
|
||||
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define PHY_COMN_BLK 1
|
||||
#define PHY_TRSV_BLK 2
|
||||
#define END_UFS_PHY_CFG { 0 }
|
||||
|
@ -24,14 +27,17 @@
|
|||
.id = PHY_COMN_BLK, \
|
||||
}
|
||||
|
||||
#define PHY_TRSV_REG_CFG(o, v, d) { \
|
||||
#define PHY_TRSV_REG_CFG_OFFSET(o, v, d, c) { \
|
||||
.off_0 = PHY_APB_ADDR((o)), \
|
||||
.off_1 = PHY_APB_ADDR((o) + PHY_TRSV_CH_OFFSET), \
|
||||
.off_1 = PHY_APB_ADDR((o) + (c)), \
|
||||
.val = (v), \
|
||||
.desc = (d), \
|
||||
.id = PHY_TRSV_BLK, \
|
||||
}
|
||||
|
||||
#define PHY_TRSV_REG_CFG(o, v, d) \
|
||||
PHY_TRSV_REG_CFG_OFFSET(o, v, d, PHY_TRSV_CH_OFFSET)
|
||||
|
||||
/* UFS PHY registers */
|
||||
#define PHY_PLL_LOCK_STATUS 0x1e
|
||||
#define PHY_CDR_LOCK_STATUS 0x5e
|
||||
|
@ -134,6 +140,7 @@ static inline void samsung_ufs_phy_ctrl_isol(
|
|||
phy->isol->mask, isol ? 0 : phy->isol->en);
|
||||
}
|
||||
|
||||
#include "phy-exynos7-ufs.h"
|
||||
extern const struct samsung_ufs_phy_drvdata exynos7_ufs_phy;
|
||||
extern const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy;
|
||||
|
||||
#endif /* _PHY_SAMSUNG_UFS_ */
|
||||
|
|
|
@ -1273,7 +1273,7 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int tegra_xusb_padctl_suspend_noirq(struct device *dev)
|
||||
static __maybe_unused int tegra_xusb_padctl_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -1283,7 +1283,7 @@ static int tegra_xusb_padctl_suspend_noirq(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_xusb_padctl_resume_noirq(struct device *dev)
|
||||
static __maybe_unused int tegra_xusb_padctl_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
|
||||
|
||||
|
|
|
@ -162,6 +162,8 @@ struct twl4030_usb {
|
|||
atomic_t connected;
|
||||
bool vbus_supplied;
|
||||
bool musb_mailbox_pending;
|
||||
unsigned long runtime_suspended:1;
|
||||
unsigned long needs_resume:1;
|
||||
|
||||
struct delayed_work id_workaround_work;
|
||||
};
|
||||
|
@ -384,6 +386,9 @@ static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
|
|||
WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
|
||||
}
|
||||
|
||||
static int twl4030_usb_runtime_suspend(struct device *dev);
|
||||
static int twl4030_usb_runtime_resume(struct device *dev);
|
||||
|
||||
static int __maybe_unused twl4030_usb_suspend(struct device *dev)
|
||||
{
|
||||
struct twl4030_usb *twl = dev_get_drvdata(dev);
|
||||
|
@ -395,6 +400,10 @@ static int __maybe_unused twl4030_usb_suspend(struct device *dev)
|
|||
*/
|
||||
dev_dbg(twl->dev, "%s\n", __func__);
|
||||
disable_irq(twl->irq);
|
||||
if (!twl->runtime_suspended && !atomic_read(&twl->connected)) {
|
||||
twl4030_usb_runtime_suspend(dev);
|
||||
twl->needs_resume = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -405,9 +414,13 @@ static int __maybe_unused twl4030_usb_resume(struct device *dev)
|
|||
|
||||
dev_dbg(twl->dev, "%s\n", __func__);
|
||||
enable_irq(twl->irq);
|
||||
if (twl->needs_resume)
|
||||
twl4030_usb_runtime_resume(dev);
|
||||
/* check whether cable status changed */
|
||||
twl4030_usb_irq(0, twl);
|
||||
|
||||
twl->runtime_suspended = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -422,6 +435,8 @@ static int __maybe_unused twl4030_usb_runtime_suspend(struct device *dev)
|
|||
regulator_disable(twl->usb1v8);
|
||||
regulator_disable(twl->usb3v1);
|
||||
|
||||
twl->runtime_suspended = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -626,6 +626,9 @@ static int xpsgtr_phy_power_on(struct phy *phy)
|
|||
struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
|
||||
int ret = 0;
|
||||
|
||||
/* Skip initialization if not required. */
|
||||
if (!xpsgtr_phy_init_required(gtr_phy))
|
||||
return ret;
|
||||
/*
|
||||
* Wait for the PLL to lock. For DP, only wait on DP0 to avoid
|
||||
* cumulating waits for both lanes. The user is expected to initialize
|
||||
|
|
Loading…
Reference in New Issue