Commit e7904111 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull phy updates from Vinod Koul:
 "This tme we have again a big pile of qcom-qmp-* changes, one new
  driver and bunch of new hardware support.

  New hardware support:

   - Allwinner H616 USB PHY and A100 DPHY support

   - TI J721s2, J784s4 and J721e support

   - Freescale i.MX8MP PCIe PHY support

   - New driver for Renesas Ethernet SERDES supporting R-Car S4-8

   - Qualcomm SM8450 PCIe1 PHY support in EP mode

   - Qualcomm SC8280XP PCIe PHY support (including x4 mode)

   - Fixed Qualcomm SC8280XP USB4-USB3-DP PHY DT bindings

  Updates:

   - A big pile of updates on qcom-qmp-* drivers following the driver
     split and reorganization merged earlier

   - Phy order of API calls documentation update"

* tag 'phy-for-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (174 commits)
  phy: ti: phy-j721e-wiz: add j721s2-wiz-10g module support
  dt-bindings: phy-j721e-wiz: add j721s2 compatible string
  phy: use devm_platform_get_and_ioremap_resource()
  phy: allwinner: phy-sun6i-mipi-dphy: Add the A100 DPHY variant
  phy: allwinner: phy-sun6i-mipi-dphy: Add a variant power-on hook
  phy: allwinner: phy-sun6i-mipi-dphy: Set the enable bit last
  phy: allwinner: phy-sun6i-mipi-dphy: Make RX support optional
  dt-bindings: sun6i-a31-mipi-dphy: Add the A100 DPHY variant
  dt-bindings: sun6i-a31-mipi-dphy: Add the interrupts property
  phy: qcom-qmp-pcie: drop redundant clock allocation
  phy: qcom-qmp-usb: drop redundant clock allocation
  phy: qcom-qmp: drop unused type header
  phy: qcom-qmp-usb: drop sc8280xp reference-clock source
  dt-bindings: phy: qcom,sc8280xp-qmp-usb3-uni: drop reference-clock source
  phy: qcom-qmp-combo: add support for updated sc8280xp binding
  phy: qcom-qmp-combo: rename DP_PHY register pointer
  phy: qcom-qmp-combo: rename common-register pointers
  phy: qcom-qmp-combo: clean up DP clock callbacks
  phy: qcom-qmp-combo: separate clock and provider registration
  phy: qcom-qmp-combo: add clock registration helper
  ...
parents b8fd76f4 bea3ce75
......@@ -17,13 +17,20 @@ properties:
compatible:
oneOf:
- const: allwinner,sun6i-a31-mipi-dphy
- const: allwinner,sun50i-a100-mipi-dphy
- items:
- const: allwinner,sun50i-a64-mipi-dphy
- const: allwinner,sun6i-a31-mipi-dphy
- items:
- const: allwinner,sun20i-d1-mipi-dphy
- const: allwinner,sun50i-a100-mipi-dphy
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: Bus Clock
......@@ -53,6 +60,7 @@ required:
- "#phy-cells"
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
......@@ -61,9 +69,12 @@ additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
dphy0: d-phy@1ca1000 {
compatible = "allwinner,sun6i-a31-mipi-dphy";
reg = <0x01ca1000 0x1000>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu 23>, <&ccu 97>;
clock-names = "bus", "mod";
resets = <&ccu 4>;
......
......@@ -36,18 +36,22 @@ properties:
- const: pmu3
clocks:
minItems: 4
items:
- description: USB OTG PHY bus clock
- description: USB Host 0 PHY bus clock
- description: USB Host 1 PHY bus clock
- description: USB Host 2 PHY bus clock
- description: PMU clock for host port 2
clock-names:
minItems: 4
items:
- const: usb0_phy
- const: usb1_phy
- const: usb2_phy
- const: usb3_phy
- const: pmu2_clk
resets:
items:
......@@ -96,6 +100,28 @@ required:
- resets
- reset-names
allOf:
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun50i-h616-usb-phy
then:
properties:
clocks:
minItems: 5
clock-names:
minItems: 5
else:
properties:
clocks:
maxItems: 4
clock-names:
maxItems: 4
additionalProperties: false
examples:
......
......@@ -16,6 +16,7 @@ properties:
compatible:
enum:
- fsl,imx8mm-pcie-phy
- fsl,imx8mp-pcie-phy
reg:
maxItems: 1
......@@ -28,11 +29,16 @@ properties:
- const: ref
resets:
maxItems: 1
minItems: 1
maxItems: 2
reset-names:
items:
oneOf:
- items: # for iMX8MM
- const: pciephy
- items: # for IMX8MP
- const: pciephy
- const: perst
fsl,refclk-pad-mode:
description: |
......@@ -60,6 +66,10 @@ properties:
description: A boolean property indicating the CLKREQ# signal is
not supported in the board design (optional)
power-domains:
description: PCIe PHY power domain (optional).
maxItems: 1
required:
- "#phy-cells"
- compatible
......
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/qcom,qmp-pcie-phy.yaml#
$id: http://devicetree.org/schemas/phy/qcom,ipq8074-qmp-pcie-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QMP PHY controller (PCIe)
title: Qualcomm QMP PHY controller (PCIe, IPQ8074)
maintainers:
- Vinod Koul <vkoul@kernel.org>
......@@ -13,6 +13,9 @@ description:
QMP PHY controller supports physical layer functionality for a number of
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
Note that these bindings are for SoCs up to SC8180X. For newer SoCs, see
qcom,sc8280xp-qmp-pcie-phy.yaml.
properties:
compatible:
enum:
......
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/qcom,qmp-ufs-phy.yaml#
$id: http://devicetree.org/schemas/phy/qcom,msm8996-qmp-ufs-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QMP PHY controller (UFS)
title: Qualcomm QMP PHY controller (UFS, MSM8996)
maintainers:
- Vinod Koul <vkoul@kernel.org>
......@@ -13,13 +13,15 @@ description:
QMP PHY controller supports physical layer functionality for a number of
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
Note that these bindings are for SoCs up to SC8180X. For newer SoCs, see
qcom,sc8280xp-qmp-ufs-phy.yaml.
properties:
compatible:
enum:
- qcom,msm8996-qmp-ufs-phy
- qcom,msm8998-qmp-ufs-phy
- qcom,sc8180x-qmp-ufs-phy
- qcom,sc8280xp-qmp-ufs-phy
- qcom,sdm845-qmp-ufs-phy
- qcom,sm6115-qmp-ufs-phy
- qcom,sm6350-qmp-ufs-phy
......@@ -119,7 +121,6 @@ allOf:
enum:
- qcom,msm8998-qmp-ufs-phy
- qcom,sc8180x-qmp-ufs-phy
- qcom,sc8280xp-qmp-ufs-phy
- qcom,sdm845-qmp-ufs-phy
- qcom,sm6115-qmp-ufs-phy
- qcom,sm6350-qmp-ufs-phy
......@@ -156,7 +157,6 @@ allOf:
contains:
enum:
- qcom,msm8998-qmp-ufs-phy
- qcom,sc8280xp-qmp-ufs-phy
- qcom,sdm845-qmp-ufs-phy
- qcom,sm6350-qmp-ufs-phy
- qcom,sm8150-qmp-ufs-phy
......@@ -211,11 +211,12 @@ allOf:
examples:
- |
#include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
#include <dt-bindings/clock/qcom,gcc-sm8250.h>
#include <dt-bindings/clock/qcom,rpmh.h>
phy-wrapper@1d87000 {
compatible = "qcom,sc8280xp-qmp-ufs-phy";
reg = <0x01d87000 0xe10>;
compatible = "qcom,sm8250-qmp-ufs-phy";
reg = <0x01d87000 0x1c0>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x01d87000 0x1000>;
......
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/qcom,qmp-usb-phy.yaml#
$id: http://devicetree.org/schemas/phy/qcom,msm8996-qmp-usb3-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QMP PHY controller (USB)
title: Qualcomm QMP PHY controller (USB, MSM8996)
maintainers:
- Vinod Koul <vkoul@kernel.org>
......@@ -13,6 +13,9 @@ description:
QMP PHY controller supports physical layer functionality for a number of
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
Note that these bindings are for SoCs up to SC8180X. For newer SoCs, see
qcom,sc8280xp-qmp-usb3-uni-phy.yaml.
properties:
compatible:
enum:
......@@ -23,7 +26,6 @@ properties:
- qcom,qcm2290-qmp-usb3-phy
- qcom,sc7180-qmp-usb3-phy
- qcom,sc8180x-qmp-usb3-phy
- qcom,sc8280xp-qmp-usb3-uni-phy
- qcom,sdm845-qmp-usb3-phy
- qcom,sdm845-qmp-usb3-uni-phy
- qcom,sdx55-qmp-usb3-uni-phy
......@@ -201,7 +203,6 @@ allOf:
compatible:
contains:
enum:
- qcom,sc8280xp-qmp-usb3-uni-phy
- qcom,sm8150-qmp-usb3-phy
- qcom,sm8150-qmp-usb3-uni-phy
- qcom,sm8250-qmp-usb3-uni-phy
......@@ -268,16 +269,6 @@ allOf:
- const: phy_phy
- const: phy
- if:
properties:
compatible:
contains:
enum:
- qcom,sc8280xp-qmp-usb3-uni-phy
then:
required:
- power-domains
- if:
properties:
compatible:
......@@ -349,7 +340,6 @@ allOf:
contains:
enum:
- qcom,msm8996-qmp-usb3-phy
- qcom,sc8280xp-qmp-usb3-uni-phy
- qcom,sm8250-qmp-usb3-uni-phy
- qcom,sm8350-qmp-usb3-uni-phy
then:
......
......@@ -2,10 +2,17 @@
%YAML 1.2
---
$id: "http://devicetree.org/schemas/phy/qcom,qmp-usb3-dp-phy.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
$id: http://devicetree.org/schemas/phy/qcom,sc7180-qmp-usb3-dp-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QMP USB3 DP PHY controller
title: Qualcomm QMP USB3 DP PHY controller (SC7180)
description:
The QMP PHY controller supports physical layer functionality for a number of
controllers on Qualcomm chipsets, such as, PCIe, UFS and USB.
Note that these bindings are for SoCs up to SC8180X. For newer SoCs, see
qcom,sc8280xp-qmp-usb43dp-phy.yaml.
maintainers:
- Wesley Cheng <quic_wcheng@quicinc.com>
......@@ -16,7 +23,6 @@ properties:
- qcom,sc7180-qmp-usb3-dp-phy
- qcom,sc7280-qmp-usb3-dp-phy
- qcom,sc8180x-qmp-usb3-dp-phy
- qcom,sc8280xp-qmp-usb43dp-phy
- qcom,sdm845-qmp-usb3-dp-phy
- qcom,sm8250-qmp-usb3-dp-phy
reg:
......@@ -162,17 +168,6 @@ required:
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,sc8280xp-qmp-usb43dp-phy
then:
required:
- power-domains
examples:
- |
#include <dt-bindings/clock/qcom,gcc-sdm845.h>
......
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/qcom,sc8280xp-qmp-pcie-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QMP PHY controller (PCIe, SC8280XP)
maintainers:
- Vinod Koul <vkoul@kernel.org>
description:
The QMP PHY controller supports physical layer functionality for a number of
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
properties:
compatible:
enum:
- qcom,sc8280xp-qmp-gen3x1-pcie-phy
- qcom,sc8280xp-qmp-gen3x2-pcie-phy
- qcom,sc8280xp-qmp-gen3x4-pcie-phy
reg:
minItems: 1
maxItems: 2
clocks:
maxItems: 6
clock-names:
items:
- const: aux
- const: cfg_ahb
- const: ref
- const: rchng
- const: pipe
- const: pipediv2
power-domains:
maxItems: 1
resets:
maxItems: 1
reset-names:
items:
- const: phy
vdda-phy-supply: true
vdda-pll-supply: true
qcom,4ln-config-sel:
description: PCIe 4-lane configuration
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
- description: phandle of TCSR syscon
- description: offset of PCIe 4-lane configuration register
- description: offset of configuration bit for this PHY
"#clock-cells":
const: 0
clock-output-names:
maxItems: 1
"#phy-cells":
const: 0
required:
- compatible
- reg
- clocks
- clock-names
- power-domains
- resets
- reset-names
- vdda-phy-supply
- vdda-pll-supply
- "#clock-cells"
- clock-output-names
- "#phy-cells"
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,sc8280xp-qmp-gen3x4-pcie-phy
then:
properties:
reg:
items:
- description: port a
- description: port b
required:
- qcom,4ln-config-sel
else:
properties:
reg:
maxItems: 1
examples:
- |
#include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
pcie2b_phy: phy@1c18000 {
compatible = "qcom,sc8280xp-qmp-gen3x2-pcie-phy";
reg = <0x01c18000 0x2000>;
clocks = <&gcc GCC_PCIE_2B_AUX_CLK>,
<&gcc GCC_PCIE_2B_CFG_AHB_CLK>,
<&gcc GCC_PCIE_2A2B_CLKREF_CLK>,
<&gcc GCC_PCIE2B_PHY_RCHNG_CLK>,
<&gcc GCC_PCIE_2B_PIPE_CLK>,
<&gcc GCC_PCIE_2B_PIPEDIV2_CLK>;
clock-names = "aux", "cfg_ahb", "ref", "rchng",
"pipe", "pipediv2";
power-domains = <&gcc PCIE_2B_GDSC>;
resets = <&gcc GCC_PCIE_2B_PHY_BCR>;
reset-names = "phy";
vdda-phy-supply = <&vreg_l6d>;
vdda-pll-supply = <&vreg_l4d>;
#clock-cells = <0>;
clock-output-names = "pcie_2b_pipe_clk";
#phy-cells = <0>;
};
pcie2a_phy: phy@1c24000 {
compatible = "qcom,sc8280xp-qmp-gen3x4-pcie-phy";
reg = <0x01c24000 0x2000>, <0x01c26000 0x2000>;
clocks = <&gcc GCC_PCIE_2A_AUX_CLK>,
<&gcc GCC_PCIE_2A_CFG_AHB_CLK>,
<&gcc GCC_PCIE_2A2B_CLKREF_CLK>,
<&gcc GCC_PCIE2A_PHY_RCHNG_CLK>,
<&gcc GCC_PCIE_2A_PIPE_CLK>,
<&gcc GCC_PCIE_2A_PIPEDIV2_CLK>;
clock-names = "aux", "cfg_ahb", "ref", "rchng",
"pipe", "pipediv2";
power-domains = <&gcc PCIE_2A_GDSC>;
resets = <&gcc GCC_PCIE_2A_PHY_BCR>;
reset-names = "phy";
vdda-phy-supply = <&vreg_l6d>;
vdda-pll-supply = <&vreg_l4d>;
qcom,4ln-config-sel = <&tcsr 0xa044 0>;
#clock-cells = <0>;
clock-output-names = "pcie_2a_pipe_clk";
#phy-cells = <0>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/qcom,sc8280xp-qmp-ufs-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QMP PHY controller (UFS, SC8280XP)
maintainers:
- Vinod Koul <vkoul@kernel.org>
description:
The QMP PHY controller supports physical layer functionality for a number of
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
properties:
compatible:
enum:
- qcom,sc8280xp-qmp-ufs-phy
reg:
maxItems: 1
clocks:
maxItems: 2
clock-names:
items:
- const: ref
- const: ref_aux
power-domains:
maxItems: 1
resets:
maxItems: 1
reset-names:
items:
- const: ufsphy
vdda-phy-supply: true
vdda-pll-supply: true
"#phy-cells":
const: 0
required:
- compatible
- reg
- clocks
- clock-names
- power-domains
- resets
- reset-names
- vdda-phy-supply
- vdda-pll-supply
- "#phy-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
ufs_mem_phy: phy@1d87000 {
compatible = "qcom,sc8280xp-qmp-ufs-phy";
reg = <0x01d87000 0x1000>;
clocks = <&gcc GCC_UFS_REF_CLKREF_CLK>, <&gcc GCC_UFS_PHY_PHY_AUX_CLK>;
clock-names = "ref", "ref_aux";
power-domains = <&gcc UFS_PHY_GDSC>;
resets = <&ufs_mem_hc 0>;
reset-names = "ufsphy";
vdda-phy-supply = <&vreg_l6b>;
vdda-pll-supply = <&vreg_l3b>;
#phy-cells = <0>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/qcom,sc8280xp-qmp-usb3-uni-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QMP PHY controller (USB, SC8280XP)
maintainers:
- Vinod Koul <vkoul@kernel.org>
description:
The QMP PHY controller supports physical layer functionality for a number of
controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
properties:
compatible:
enum:
- qcom,sc8280xp-qmp-usb3-uni-phy
reg:
maxItems: 1
clocks:
maxItems: 4
clock-names:
items:
- const: aux
- const: ref
- const: com_aux
- const: pipe
power-domains:
maxItems: 1
resets:
maxItems: 2
reset-names:
items:
- const: phy
- const: phy_phy
vdda-phy-supply: true
vdda-pll-supply: true
"#clock-cells":
const: 0
clock-output-names:
maxItems: 1
"#phy-cells":
const: 0
required:
- compatible
- reg
- clocks
- clock-names
- power-domains
- resets
- reset-names
- vdda-phy-supply
- vdda-pll-supply
- "#clock-cells"
- clock-output-names
- "#phy-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
#include <dt-bindings/clock/qcom,rpmh.h>
phy@88ef000 {
compatible = "qcom,sc8280xp-qmp-usb3-uni-phy";
reg = <0x088ef000 0x2000>;
clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>,
<&gcc GCC_USB3_MP0_CLKREF_CLK>,
<&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>,
<&gcc GCC_USB3_MP_PHY_PIPE_0_CLK>;
clock-names = "aux", "ref", "com_aux", "pipe";
power-domains = <&gcc USB30_MP_GDSC>;
resets = <&gcc GCC_USB3_UNIPHY_MP0_BCR>,
<&gcc GCC_USB3UNIPHY_PHY_MP0_BCR>;
reset-names = "phy", "phy_phy";
vdda-phy-supply = <&vreg_l3a>;
vdda-pll-supply = <&vreg_l5a>;
#clock-cells = <0>;
clock-output-names = "usb2_phy0_pipe_clk";
#phy-cells = <0>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/qcom,sc8280xp-qmp-usb43dp-phy.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm QMP USB4-USB3-DP PHY controller (SC8280XP)
maintainers:
- Vinod Koul <vkoul@kernel.org>
description:
The QMP PHY controller supports physical layer functionality for a number of
controllers on Qualcomm chipsets, such as, PCIe, UFS and USB.
properties:
compatible:
enum:
- qcom,sc8280xp-qmp-usb43dp-phy
reg:
maxItems: 1
clocks:
maxItems: 4
clock-names:
items:
- const: aux
- const: ref
- const: com_aux
- const: usb3_pipe
power-domains:
maxItems: 1
resets:
maxItems: 2
reset-names:
items:
- const: phy
- const: common
vdda-phy-supply: true
vdda-pll-supply: true
"#clock-cells":
const: 1
description:
See include/dt-bindings/dt-bindings/phy/phy-qcom-qmp.h
"#phy-cells":
const: 1
description:
See include/dt-bindings/dt-bindings/phy/phy-qcom-qmp.h
required:
- compatible
- reg
- clocks
- clock-names
- power-domains
- resets
- reset-names
- vdda-phy-supply
- vdda-pll-supply
- "#clock-cells"
- "#phy-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
phy@88eb000 {
compatible = "qcom,sc8280xp-qmp-usb43dp-phy";
reg = <0x088eb000 0x4000>;
clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
<&gcc GCC_USB4_EUD_CLKREF_CLK>,
<&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
<&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
clock-names = "aux", "ref", "com_aux", "usb3_pipe";
power-domains = <&gcc USB30_PRIM_GDSC>;
resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
<&gcc GCC_USB4_DP_PHY_PRIM_BCR>;
reset-names = "phy", "common";
vdda-phy-supply = <&vreg_l9d>;
vdda-pll-supply = <&vreg_l4d>;
#clock-cells = <1>;
#phy-cells = <1>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/phy/renesas,r8a779f0-ether-serdes.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas Ethernet SERDES
maintainers:
- Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
properties:
compatible:
const: renesas,r8a779f0-ether-serdes
reg:
maxItems: 1
clocks:
maxItems: 1
resets:
maxItems: 1
power-domains:
maxItems: 1
'#phy-cells':
description: Port number of SERDES.
const: 1
required:
- compatible
- reg
- clocks
- resets
- power-domains
- '#phy-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/r8a779f0-cpg-mssr.h>
#include <dt-bindings/power/r8a779f0-sysc.h>
phy@e6444000 {
compatible = "renesas,r8a779f0-ether-serdes";
reg = <0xe6444000 0xc00>;
clocks = <&cpg CPG_MOD 1506>;
power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
resets = <&cpg 1506>;
#phy-cells = <1>;
};
......@@ -54,6 +54,7 @@ properties:
- ti,dm814-phy-gmii-sel
- ti,am654-phy-gmii-sel
- ti,j7200-cpsw5g-phy-gmii-sel
- ti,j721e-cpsw9g-phy-gmii-sel
reg:
maxItems: 1
......@@ -63,14 +64,17 @@ properties:
ti,qsgmii-main-ports:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: |
Required only for QSGMII mode. Array to select the port for
QSGMII main mode. Rest of the ports are selected as QSGMII_SUB
ports automatically. Any one of the 4 CPSW5G ports can act as the
main port with the rest of them being the QSGMII_SUB ports.
maxItems: 1
Required only for QSGMII mode. Array to select the port/s for QSGMII
main mode. The size of the array corresponds to the number of QSGMII
interfaces and thus, the number of distinct QSGMII main ports,
supported by the device. If the device supports two QSGMII interfaces
but only one QSGMII interface is desired, repeat the QSGMII main port
value corresponding to the QSGMII interface in the array.
minItems: 1
maxItems: 2
items:
minimum: 1
maximum: 4
maximum: 8
allOf:
- if:
......@@ -81,12 +85,43 @@ allOf:
- ti,dra7xx-phy-gmii-sel
- ti,dm814-phy-gmii-sel
- ti,am654-phy-gmii-sel
- ti,j7200-cpsw5g-phy-gmii-sel
- ti,j721e-cpsw9g-phy-gmii-sel
then:
properties:
'#phy-cells':
const: 1
description: CPSW port number (starting from 1)
- if:
properties:
compatible:
contains:
enum:
- ti,j7200-cpsw5g-phy-gmii-sel
then:
properties:
ti,qsgmii-main-ports:
maxItems: 1
items:
minimum: 1
maximum: 4
- if:
properties:
compatible:
contains:
enum:
- ti,j721e-cpsw9g-phy-gmii-sel
then:
properties:
ti,qsgmii-main-ports:
minItems: 2
maxItems: 2
items:
minimum: 1
maximum: 8
- if:
not:
properties:
......@@ -94,6 +129,7 @@ allOf:
contains:
enum:
- ti,j7200-cpsw5g-phy-gmii-sel
- ti,j721e-cpsw9g-phy-gmii-sel
then:
properties:
ti,qsgmii-main-ports: false
......
......@@ -15,8 +15,10 @@ properties:
enum:
- ti,j721e-wiz-16g
- ti,j721e-wiz-10g
- ti,j721s2-wiz-10g
- ti,am64-wiz-10g
- ti,j7200-wiz-10g
- ti,j784s4-wiz-10g
power-domains:
maxItems: 1
......
......@@ -94,7 +94,8 @@ Inorder to dereference the private data (in phy_ops), the phy provider driver
can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in
phy_ops to get back the private data.
4. Getting a reference to the PHY
Getting a reference to the PHY
==============================
Before the controller can make use of the PHY, it has to get a reference to
it. This framework provides the following APIs to get a reference to the PHY.
......@@ -130,6 +131,28 @@ the phy_init() and phy_exit() calls, and phy_power_on() and
phy_power_off() calls are all NOP when applied to a NULL phy. The NULL
phy is useful in devices for handling optional phy devices.
Order of API calls
==================
The general order of calls should be::
[devm_][of_]phy_get()
phy_init()
phy_power_on()
[phy_set_mode[_ext]()]
...
phy_power_off()
phy_exit()
[[of_]phy_put()]
Some PHY drivers may not implement :c:func:`phy_init` or :c:func:`phy_power_on`,
but controllers should always call these functions to be compatible with other
PHYs. Some PHYs may require :c:func:`phy_set_mode <phy_set_mode_ext>`, while
others may use a default mode (typically configured via devicetree or other
firmware). For compatibility, you should always call this function if you know
what mode you will be using. Generally, this function should be called after
:c:func:`phy_power_on`, although some PHY drivers may allow it at any time.
Releasing a reference to the PHY
================================
......
......@@ -14,6 +14,7 @@
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/mfd/syscon.h>
#include <linux/phy/pcie.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
......@@ -268,6 +269,10 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
if (ret)
goto err_disable_clk;
ret = phy_set_mode_ext(pcie_ep->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_EP);
if (ret)
goto err_phy_exit;
ret = phy_power_on(pcie_ep->phy);
if (ret)
goto err_phy_exit;
......
......@@ -23,6 +23,7 @@
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
#include <linux/phy/pcie.h>
#include <linux/phy/phy.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
......@@ -1499,6 +1500,10 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp)
if (ret)
return ret;
ret = phy_set_mode_ext(pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_RC);
if (ret)
goto err_deinit;
ret = phy_power_on(pcie->phy);
if (ret)
goto err_deinit;
......
......@@ -120,6 +120,7 @@ struct sun4i_usb_phy_cfg {
u8 phyctl_offset;
bool dedicated_clocks;
bool phy0_dual_route;
bool needs_phy2_siddq;
int missing_phys;
};
......@@ -289,6 +290,50 @@ static int sun4i_usb_phy_init(struct phy *_phy)
return ret;
}
/* Some PHYs on some SoCs need the help of PHY2 to work. */
if (data->cfg->needs_phy2_siddq && phy->index != 2) {
struct sun4i_usb_phy *phy2 = &data->phys[2];
ret = clk_prepare_enable(phy2->clk);
if (ret) {
reset_control_assert(phy->reset);
clk_disable_unprepare(phy->clk2);
clk_disable_unprepare(phy->clk);
return ret;
}
ret = reset_control_deassert(phy2->reset);
if (ret) {
clk_disable_unprepare(phy2->clk);
reset_control_assert(phy->reset);
clk_disable_unprepare(phy->clk2);
clk_disable_unprepare(phy->clk);
return ret;
}
/*
* This extra clock is just needed to access the
* REG_HCI_PHY_CTL PMU register for PHY2.
*/
ret = clk_prepare_enable(phy2->clk2);
if (ret) {
reset_control_assert(phy2->reset);
clk_disable_unprepare(phy2->clk);
reset_control_assert(phy->reset);
clk_disable_unprepare(phy->clk2);
clk_disable_unprepare(phy->clk);
return ret;
}
if (phy2->pmu && data->cfg->hci_phy_ctl_clear) {
val = readl(phy2->pmu + REG_HCI_PHY_CTL);
val &= ~data->cfg->hci_phy_ctl_clear;
writel(val, phy2->pmu + REG_HCI_PHY_CTL);
}
clk_disable_unprepare(phy->clk2);
}
if (phy->pmu && data->cfg->hci_phy_ctl_clear) {
val = readl(phy->pmu + REG_HCI_PHY_CTL);
val &= ~data->cfg->hci_phy_ctl_clear;
......@@ -354,6 +399,13 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
data->phy0_init = false;
}
if (data->cfg->needs_phy2_siddq && phy->index != 2) {
struct sun4i_usb_phy *phy2 = &data->phys[2];
clk_disable_unprepare(phy2->clk);
reset_control_assert(phy2->reset);
}
sun4i_usb_phy_passby(phy, 0);
reset_control_assert(phy->reset);
clk_disable_unprepare(phy->clk2);
......@@ -785,6 +837,13 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
dev_err(dev, "failed to get clock %s\n", name);
return PTR_ERR(phy->clk2);
}
} else {
snprintf(name, sizeof(name), "pmu%d_clk", i);
phy->clk2 = devm_clk_get_optional(dev, name);
if (IS_ERR(phy->clk2)) {
dev_err(dev, "failed to get clock %s\n", name);
return PTR_ERR(phy->clk2);
}
}
snprintf(name, sizeof(name), "usb%d_reset", i);
......@@ -973,6 +1032,17 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
.missing_phys = BIT(1) | BIT(2),
};
static const struct sun4i_usb_phy_cfg sun50i_h616_cfg = {
.num_phys = 4,
.type = sun50i_h6_phy,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
.phy0_dual_route = true,
.hci_phy_ctl_clear = PHY_CTL_SIDDQ,
.needs_phy2_siddq = true,
};
static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg },
{ .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg },
......@@ -988,6 +1058,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun50i-a64-usb-phy",
.data = &sun50i_a64_cfg},
{ .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg },
{ .compatible = "allwinner,sun50i-h616-usb-phy", .data = &sun50i_h616_cfg },
{ },
};
MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
......
This diff is collapsed.
......@@ -18,14 +18,14 @@
#define PIARBCTL_CAM 0x00
#define PIARBCTL_SPLITTER 0x04
#define PIARBCTL_MISC 0x08
#define PIARBCTL_MISC_SECURE_MASK 0x80000000
#define PIARBCTL_MISC_USB_SELECT_MASK 0x40000000
#define PIARBCTL_MISC_USB_4G_SDRAM_MASK 0x20000000
#define PIARBCTL_MISC_USB_PRIORITY_MASK 0x000f0000
#define PIARBCTL_MISC_USB_MEM_PAGE_MASK 0x0000f000
#define PIARBCTL_MISC_CAM1_MEM_PAGE_MASK 0x00000f00
#define PIARBCTL_MISC_CAM0_MEM_PAGE_MASK 0x000000f0
#define PIARBCTL_MISC_SATA_PRIORITY_MASK 0x0000000f
#define PIARBCTL_MISC_SATA_PRIORITY_MASK GENMASK(3, 0)
#define PIARBCTL_MISC_CAM0_MEM_PAGE_MASK GENMASK(7, 4)
#define PIARBCTL_MISC_CAM1_MEM_PAGE_MASK GENMASK(11, 8)
#define PIARBCTL_MISC_USB_MEM_PAGE_MASK GENMASK(15, 12)
#define PIARBCTL_MISC_USB_PRIORITY_MASK GENMASK(19, 16)
#define PIARBCTL_MISC_USB_4G_SDRAM_MASK BIT(29)
#define PIARBCTL_MISC_USB_SELECT_MASK BIT(30)
#define PIARBCTL_MISC_SECURE_MASK BIT(31)
#define PIARBCTL_MISC_USB_ONLY_MASK \
(PIARBCTL_MISC_USB_SELECT_MASK | \
......@@ -35,46 +35,47 @@
/* Register definitions for the USB CTRL block */
#define USB_CTRL_SETUP 0x00
#define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK 0x02000000
#define USB_CTRL_SETUP_SCB2_EN_MASK 0x00008000
#define USB_CTRL_SETUP_tca_drv_sel_MASK 0x01000000
#define USB_CTRL_SETUP_SCB1_EN_MASK 0x00004000
#define USB_CTRL_SETUP_SOFT_SHUTDOWN_MASK 0x00000200
#define USB_CTRL_SETUP_IPP_MASK 0x00000020
#define USB_CTRL_SETUP_IOC_MASK 0x00000010
#define USB_CTRL_SETUP_IOC_MASK BIT(4)
#define USB_CTRL_SETUP_IPP_MASK BIT(5)
#define USB_CTRL_SETUP_SOFT_SHUTDOWN_MASK BIT(9)
#define USB_CTRL_SETUP_SCB1_EN_MASK BIT(14)
#define USB_CTRL_SETUP_SCB2_EN_MASK BIT(15)
#define USB_CTRL_SETUP_tca_drv_sel_MASK BIT(24)
#define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK BIT(25)
#define USB_CTRL_USB_PM 0x04
#define USB_CTRL_USB_PM_USB_PWRDN_MASK 0x80000000
#define USB_CTRL_USB_PM_SOFT_RESET_MASK 0x40000000
#define USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK 0x00800000
#define USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK 0x00400000
#define USB_CTRL_USB_PM_XHC_PME_EN_MASK 0x00000010
#define USB_CTRL_USB_PM_XHC_S2_CLK_SWITCH_EN_MASK 0x00000008
#define USB_CTRL_USB_PM_XHC_S2_CLK_SWITCH_EN_MASK BIT(3)
#define USB_CTRL_USB_PM_XHC_PME_EN_MASK BIT(4)
#define USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK BIT(22)
#define USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK BIT(23)
#define USB_CTRL_USB_PM_SOFT_RESET_MASK BIT(30)
#define USB_CTRL_USB_PM_USB_PWRDN_MASK BIT(31)
#define USB_CTRL_USB_PM_STATUS 0x08
#define USB_CTRL_USB_DEVICE_CTL1 0x10
#define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK 0x00000003
#define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK GENMASK(1, 0)
#define USB_CTRL_TEST_PORT_CTL 0x30
#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_MASK 0x000000ff
#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_MASK GENMASK(7, 0)
#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_PME_GEN_MASK 0x0000002e
#define USB_CTRL_TP_DIAG1 0x34
#define USB_CTLR_TP_DIAG1_wake_MASK 0x00000002
#define USB_CTLR_TP_DIAG1_wake_MASK BIT(1)
#define USB_CTRL_CTLR_CSHCR 0x50
#define USB_CTRL_CTLR_CSHCR_ctl_pme_en_MASK 0x00040000
#define USB_CTRL_CTLR_CSHCR_ctl_pme_en_MASK BIT(18)
/* Register definitions for the USB_PHY block in 7211b0 */
#define USB_PHY_PLL_CTL 0x00
#define USB_PHY_PLL_CTL_PLL_RESETB_MASK 0x40000000
#define USB_PHY_PLL_CTL_PLL_SUSPEND_MASK BIT(27)
#define USB_PHY_PLL_CTL_PLL_RESETB_MASK BIT(30)
#define USB_PHY_PLL_LDO_CTL 0x08
#define USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK 0x00000004
#define USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK 0x00000002
#define USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK 0x00000001
#define USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK BIT(0)
#define USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK BIT(1)
#define USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK BIT(2)
#define USB_PHY_UTMI_CTL_1 0x04
#define USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK 0x00000800
#define USB_PHY_UTMI_CTL_1_PHY_MODE_MASK 0x0000000c
#define USB_PHY_UTMI_CTL_1_PHY_MODE_MASK GENMASK(3, 2)
#define USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT 2
#define USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK BIT(11)
#define USB_PHY_IDDQ 0x1c
#define USB_PHY_IDDQ_phy_iddq_MASK 0x00000001
#define USB_PHY_IDDQ_phy_iddq_MASK BIT(0)
#define USB_PHY_STATUS 0x20
#define USB_PHY_STATUS_pll_lock_MASK 0x00000001
#define USB_PHY_STATUS_pll_lock_MASK BIT(0)
/* Register definitions for the MDIO registers in the DWC2 block of
* the 7211b0.
......@@ -86,7 +87,7 @@
/* Register definitions for the BDC EC block in 7211b0 */
#define BDC_EC_AXIRDA 0x0c
#define BDC_EC_AXIRDA_RTS_MASK 0xf0000000
#define BDC_EC_AXIRDA_RTS_MASK GENMASK(31, 28)
#define BDC_EC_AXIRDA_RTS_SHIFT 28
......@@ -195,10 +196,10 @@ static void usb_init_common(struct brcm_usb_init_params *params)
if (USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE)) {
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
reg |= params->mode;
reg |= params->port_mode;
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
}
switch (params->mode) {
switch (params->supported_port_modes) {
case USB_CTLR_MODE_HOST:
USB_CTRL_UNSET(ctrl, USB_PM, BDC_SOFT_RESETB);
break;
......@@ -259,6 +260,11 @@ static void usb_init_common_7211b0(struct brcm_usb_init_params *params)
brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);
}
/* Disable PLL auto suspend */
reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);
reg |= USB_PHY_PLL_CTL_PLL_SUSPEND_MASK;
brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);
/* Init the PHY */
reg = USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK |
USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK |
......@@ -276,7 +282,7 @@ static void usb_init_common_7211b0(struct brcm_usb_init_params *params)
/* Set the PHY_MODE */
reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1);
reg &= ~USB_PHY_UTMI_CTL_1_PHY_MODE_MASK;
reg |= params->mode << USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT;
reg |= params->supported_port_modes << USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT;
brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);
usb_init_common(params);
......@@ -286,7 +292,7 @@ static void usb_init_common_7211b0(struct brcm_usb_init_params *params)
* the default "Read Transaction Size" of 6 (1024 bytes).
* Set it to 4 (256 bytes).
*/
if ((params->mode != USB_CTLR_MODE_HOST) && bdc_ec) {
if ((params->supported_port_modes != USB_CTLR_MODE_HOST) && bdc_ec) {
reg = brcm_usb_readl(bdc_ec + BDC_EC_AXIRDA);
reg &= ~BDC_EC_AXIRDA_RTS_MASK;
reg |= (0x4 << BDC_EC_AXIRDA_RTS_SHIFT);
......@@ -331,13 +337,12 @@ static void usb_uninit_common_7216(struct brcm_usb_init_params *params)
pr_debug("%s\n", __func__);
if (!params->wake_enabled) {
USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
if (params->wake_enabled) {
/* Switch to using slower clock during suspend to save power */
USB_CTRL_SET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN);
} else {
usb_wake_enable_7216(params, true);
} else {
USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
}
}
......@@ -385,7 +390,7 @@ static int usb_get_dual_select(struct brcm_usb_init_params *params)
return reg;
}
static void usb_set_dual_select(struct brcm_usb_init_params *params, int mode)
static void usb_set_dual_select(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
u32 reg;
......@@ -394,7 +399,7 @@ static void usb_set_dual_select(struct brcm_usb_init_params *params, int mode)
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
reg |= mode;
reg |= params->port_mode;
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
}
......@@ -425,7 +430,6 @@ void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params)
params->family_name = "7216";
params->ops = &bcm7216_ops;
params->suspend_with_clocks = true;
}
void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params)
......@@ -435,5 +439,4 @@ void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params)
params->family_name = "7211";
params->ops = &bcm7211b0_ops;
params->suspend_with_clocks = true;
}
......@@ -21,57 +21,57 @@
/* Register definitions for the USB CTRL block */
#define USB_CTRL_SETUP 0x00
#define USB_CTRL_SETUP_IOC_MASK 0x00000010
#define USB_CTRL_SETUP_IPP_MASK 0x00000020
#define USB_CTRL_SETUP_BABO_MASK 0x00000001
#define USB_CTRL_SETUP_FNHW_MASK 0x00000002
#define USB_CTRL_SETUP_FNBO_MASK 0x00000004
#define USB_CTRL_SETUP_WABO_MASK 0x00000008
#define USB_CTRL_SETUP_SCB_CLIENT_SWAP_MASK 0x00002000 /* option */
#define USB_CTRL_SETUP_SCB1_EN_MASK 0x00004000 /* option */
#define USB_CTRL_SETUP_SCB2_EN_MASK 0x00008000 /* option */
#define USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK 0X00020000 /* option */
#define USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK 0x00010000 /* option */
#define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK 0x02000000 /* option */
#define USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK 0x04000000 /* option */
#define USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK 0x08000000 /* opt */
#define USB_CTRL_SETUP_OC3_DISABLE_MASK 0xc0000000 /* option */
#define USB_CTRL_SETUP_BABO_MASK BIT(0)
#define USB_CTRL_SETUP_FNHW_MASK BIT(1)
#define USB_CTRL_SETUP_FNBO_MASK BIT(2)
#define USB_CTRL_SETUP_WABO_MASK BIT(3)
#define USB_CTRL_SETUP_IOC_MASK BIT(4)
#define USB_CTRL_SETUP_IPP_MASK BIT(5)
#define USB_CTRL_SETUP_SCB_CLIENT_SWAP_MASK BIT(13) /* option */
#define USB_CTRL_SETUP_SCB1_EN_MASK BIT(14) /* option */
#define USB_CTRL_SETUP_SCB2_EN_MASK BIT(15) /* option */
#define USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK BIT(17) /* option */
#define USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK BIT(16) /* option */
#define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK BIT(25) /* option */
#define USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK BIT(26) /* option */
#define USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK BIT(27) /* opt */
#define USB_CTRL_SETUP_OC3_DISABLE_MASK GENMASK(31, 30) /* option */
#define USB_CTRL_PLL_CTL 0x04
#define USB_CTRL_PLL_CTL_PLL_SUSPEND_EN_MASK 0x08000000
#define USB_CTRL_PLL_CTL_PLL_RESETB_MASK 0x40000000
#define USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK 0x80000000 /* option */
#define USB_CTRL_PLL_CTL_PLL_SUSPEND_EN_MASK BIT(27)
#define USB_CTRL_PLL_CTL_PLL_RESETB_MASK BIT(30)
#define USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK BIT(31) /* option */
#define USB_CTRL_EBRIDGE 0x0c
#define USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK 0x00020000 /* option */
#define USB_CTRL_EBRIDGE_EBR_SCB_SIZE_MASK 0x00000f80 /* option */
#define USB_CTRL_EBRIDGE_EBR_SCB_SIZE_MASK GENMASK(11, 7) /* option */
#define USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK BIT(17) /* option */
#define USB_CTRL_OBRIDGE 0x10
#define USB_CTRL_OBRIDGE_LS_KEEP_ALIVE_MASK 0x08000000
#define USB_CTRL_OBRIDGE_LS_KEEP_ALIVE_MASK BIT(27)
#define USB_CTRL_MDIO 0x14
#define USB_CTRL_MDIO2 0x18
#define USB_CTRL_UTMI_CTL_1 0x2c
#define USB_CTRL_UTMI_CTL_1_POWER_UP_FSM_EN_MASK 0x00000800
#define USB_CTRL_UTMI_CTL_1_POWER_UP_FSM_EN_P1_MASK 0x08000000
#define USB_CTRL_UTMI_CTL_1_POWER_UP_FSM_EN_MASK BIT(11)
#define USB_CTRL_UTMI_CTL_1_POWER_UP_FSM_EN_P1_MASK BIT(27)
#define USB_CTRL_USB_PM 0x34
#define USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK 0x00800000 /* option */
#define USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK 0x00400000 /* option */
#define USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK 0x40000000 /* option */
#define USB_CTRL_USB_PM_USB_PWRDN_MASK 0x80000000 /* option */
#define USB_CTRL_USB_PM_SOFT_RESET_MASK 0x40000000 /* option */
#define USB_CTRL_USB_PM_USB20_HC_RESETB_MASK 0x30000000 /* option */
#define USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK 0x00300000 /* option */
#define USB_CTRL_USB_PM_RMTWKUP_EN_MASK 0x00000001
#define USB_CTRL_USB_PM_RMTWKUP_EN_MASK BIT(0)
#define USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK GENMASK(21, 20) /* option */
#define USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK BIT(22) /* option */
#define USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK BIT(23) /* option */
#define USB_CTRL_USB_PM_USB20_HC_RESETB_MASK GENMASK(29, 28) /* option */
#define USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK BIT(30) /* option */
#define USB_CTRL_USB_PM_SOFT_RESET_MASK BIT(30) /* option */
#define USB_CTRL_USB_PM_USB_PWRDN_MASK BIT(31) /* option */
#define USB_CTRL_USB_PM_STATUS 0x38
#define USB_CTRL_USB30_CTL1 0x60
#define USB_CTRL_USB30_CTL1_PHY3_PLL_SEQ_START_MASK 0x00000010
#define USB_CTRL_USB30_CTL1_PHY3_RESETB_MASK 0x00010000
#define USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK 0x00020000 /* option */
#define USB_CTRL_USB30_CTL1_USB3_IOC_MASK 0x10000000 /* option */
#define USB_CTRL_USB30_CTL1_USB3_IPP_MASK 0x20000000 /* option */
#define USB_CTRL_USB30_CTL1_PHY3_PLL_SEQ_START_MASK BIT(4)
#define USB_CTRL_USB30_CTL1_PHY3_RESETB_MASK BIT(16)
#define USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK BIT(17) /* option */
#define USB_CTRL_USB30_CTL1_USB3_IOC_MASK BIT(28) /* option */
#define USB_CTRL_USB30_CTL1_USB3_IPP_MASK BIT(29) /* option */
#define USB_CTRL_USB30_PCTL 0x70
#define USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_MASK 0x00000002
#define USB_CTRL_USB30_PCTL_PHY3_IDDQ_OVERRIDE_MASK 0x00008000
#define USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_P1_MASK 0x00020000
#define USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_MASK BIT(1)
#define USB_CTRL_USB30_PCTL_PHY3_IDDQ_OVERRIDE_MASK BIT(15)
#define USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_P1_MASK BIT(17)
#define USB_CTRL_USB_DEVICE_CTL1 0x90
#define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK 0x00000003 /* option */
#define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK GENMASK(1, 0) /* option */
/* Register definitions for the XHCI EC block */
#define USB_XHCI_EC_IRAADR 0x658
......@@ -876,11 +876,11 @@ static void usb_init_common(struct brcm_usb_init_params *params)
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
reg &= ~USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1,
PORT_MODE);
reg |= params->mode;
reg |= params->port_mode;
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
}
if (USB_CTRL_MASK_FAMILY(params, USB_PM, BDC_SOFT_RESETB)) {
switch (params->mode) {
switch (params->supported_port_modes) {
case USB_CTLR_MODE_HOST:
USB_CTRL_UNSET_FAMILY(params, USB_PM, BDC_SOFT_RESETB);
break;
......@@ -891,7 +891,7 @@ static void usb_init_common(struct brcm_usb_init_params *params)
}
}
if (USB_CTRL_MASK_FAMILY(params, SETUP, CC_DRD_MODE_ENABLE)) {
if (params->mode == USB_CTLR_MODE_TYPEC_PD)
if (params->supported_port_modes == USB_CTLR_MODE_TYPEC_PD)
USB_CTRL_SET_FAMILY(params, SETUP, CC_DRD_MODE_ENABLE);
else
USB_CTRL_UNSET_FAMILY(params, SETUP,
......@@ -1000,7 +1000,7 @@ static int usb_get_dual_select(struct brcm_usb_init_params *params)
return reg;
}
static void usb_set_dual_select(struct brcm_usb_init_params *params, int mode)
static void usb_set_dual_select(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
u32 reg;
......@@ -1011,7 +1011,7 @@ static void usb_set_dual_select(struct brcm_usb_init_params *params, int mode)
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
reg &= ~USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1,
PORT_MODE);
reg |= mode;
reg |= params->port_mode;
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
}
}
......
......@@ -45,14 +45,15 @@ struct brcm_usb_init_ops {
void (*uninit_eohci)(struct brcm_usb_init_params *params);
void (*uninit_xhci)(struct brcm_usb_init_params *params);
int (*get_dual_select)(struct brcm_usb_init_params *params);
void (*set_dual_select)(struct brcm_usb_init_params *params, int mode);
void (*set_dual_select)(struct brcm_usb_init_params *params);
};
struct brcm_usb_init_params {
void __iomem *regs[BRCM_REGS_MAX];
int ioc;
int ipp;
int mode;
int supported_port_modes;
int port_mode;
u32 family_id;
u32 product_id;
int selected_family;
......@@ -61,7 +62,6 @@ struct brcm_usb_init_params {
const struct brcm_usb_init_ops *ops;
struct regmap *syscon_piarbctl;
bool wake_enabled;
bool suspend_with_clocks;
};
void brcm_usb_dvr_init_4908(struct brcm_usb_init_params *params);
......@@ -153,11 +153,10 @@ static inline int brcm_usb_get_dual_select(struct brcm_usb_init_params *ini)
return 0;
}
static inline void brcm_usb_set_dual_select(struct brcm_usb_init_params *ini,
int mode)
static inline void brcm_usb_set_dual_select(struct brcm_usb_init_params *ini)
{
if (ini->ops->set_dual_select)
ini->ops->set_dual_select(ini, mode);
ini->ops->set_dual_select(ini);
}
#endif /* _USB_BRCM_COMMON_INIT_H */
......@@ -102,9 +102,9 @@ static int brcm_pm_notifier(struct notifier_block *notifier,
static irqreturn_t brcm_usb_phy_wake_isr(int irq, void *dev_id)
{
struct phy *gphy = dev_id;
struct device *dev = dev_id;
pm_wakeup_event(&gphy->dev, 0);
pm_wakeup_event(dev, 0);
return IRQ_HANDLED;
}
......@@ -233,7 +233,7 @@ static ssize_t dr_mode_show(struct device *dev,
return sprintf(buf, "%s\n",
value_to_name(&brcm_dr_mode_to_name[0],
ARRAY_SIZE(brcm_dr_mode_to_name),
priv->ini.mode));
priv->ini.supported_port_modes));
}
static DEVICE_ATTR_RO(dr_mode);
......@@ -249,7 +249,8 @@ static ssize_t dual_select_store(struct device *dev,
res = name_to_value(&brcm_dual_mode_to_name[0],
ARRAY_SIZE(brcm_dual_mode_to_name), buf, &value);
if (!res) {
brcm_usb_set_dual_select(&priv->ini, value);
priv->ini.port_mode = value;
brcm_usb_set_dual_select(&priv->ini);
res = len;
}
mutex_unlock(&sysfs_lock);
......@@ -445,13 +446,13 @@ static int brcm_usb_phy_dvr_init(struct platform_device *pdev,
priv->suspend_clk = NULL;
}
priv->wake_irq = platform_get_irq_byname(pdev, "wake");
priv->wake_irq = platform_get_irq_byname_optional(pdev, "wake");
if (priv->wake_irq < 0)
priv->wake_irq = platform_get_irq_byname(pdev, "wakeup");
priv->wake_irq = platform_get_irq_byname_optional(pdev, "wakeup");
if (priv->wake_irq >= 0) {
err = devm_request_irq(dev, priv->wake_irq,
brcm_usb_phy_wake_isr, 0,
dev_name(dev), gphy);
dev_name(dev), dev);
if (err < 0)
return err;
device_set_wakeup_capable(dev, 1);
......@@ -495,13 +496,16 @@ static int brcm_usb_phy_probe(struct platform_device *pdev)
of_property_read_u32(dn, "brcm,ipp", &priv->ini.ipp);
of_property_read_u32(dn, "brcm,ioc", &priv->ini.ioc);
priv->ini.mode = USB_CTLR_MODE_HOST;
priv->ini.supported_port_modes = USB_CTLR_MODE_HOST;
err = of_property_read_string(dn, "dr_mode", &mode);
if (err == 0) {
name_to_value(&brcm_dr_mode_to_name[0],
ARRAY_SIZE(brcm_dr_mode_to_name),
mode, &priv->ini.mode);
mode, &priv->ini.supported_port_modes);
}
/* Default port_mode to supported port_modes */
priv->ini.port_mode = priv->ini.supported_port_modes;
if (of_property_read_bool(dn, "brcm,has-xhci"))
priv->has_xhci = true;
if (of_property_read_bool(dn, "brcm,has-eohci"))
......@@ -539,7 +543,7 @@ static int brcm_usb_phy_probe(struct platform_device *pdev)
* Create sysfs entries for mode.
* Remove "dual_select" attribute if not in dual mode
*/
if (priv->ini.mode != USB_CTLR_MODE_DRD)
if (priv->ini.supported_port_modes != USB_CTLR_MODE_DRD)
brcm_usb_phy_attrs[1] = NULL;
err = sysfs_create_group(&dev->kobj, &brcm_usb_phy_group);
if (err)
......@@ -598,7 +602,7 @@ static int brcm_usb_phy_suspend(struct device *dev)
* and newer XHCI->2.0-clks/3.0-clks.
*/
if (!priv->ini.suspend_with_clocks) {
if (!priv->ini.wake_enabled) {
if (priv->phys[BRCM_USB_PHY_3_0].inited)
clk_disable_unprepare(priv->usb_30_clk);
if (priv->phys[BRCM_USB_PHY_2_0].inited ||
......@@ -615,8 +619,10 @@ static int brcm_usb_phy_resume(struct device *dev)
{
struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
if (!priv->ini.wake_enabled) {
clk_prepare_enable(priv->usb_20_clk);
clk_prepare_enable(priv->usb_30_clk);
}
brcm_usb_init_ipp(&priv->ini);
/*
......
......@@ -11,6 +11,7 @@
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
......@@ -31,12 +32,10 @@
#define IMX8MM_PCIE_PHY_CMN_REG065 0x194
#define ANA_AUX_RX_TERM (BIT(7) | BIT(4))
#define ANA_AUX_TX_LVL GENMASK(3, 0)
#define IMX8MM_PCIE_PHY_CMN_REG75 0x1D4
#define PCIE_PHY_CMN_REG75_PLL_DONE 0x3
#define IMX8MM_PCIE_PHY_CMN_REG075 0x1D4
#define ANA_PLL_DONE 0x3
#define PCIE_PHY_TRSV_REG5 0x414
#define PCIE_PHY_TRSV_REG5_GEN1_DEEMP 0x2D
#define PCIE_PHY_TRSV_REG6 0x418
#define PCIE_PHY_TRSV_REG6_GEN2_DEEMP 0xF
#define IMX8MM_GPR_PCIE_REF_CLK_SEL GENMASK(25, 24)
#define IMX8MM_GPR_PCIE_REF_CLK_PLL FIELD_PREP(IMX8MM_GPR_PCIE_REF_CLK_SEL, 0x3)
......@@ -47,16 +46,28 @@
#define IMX8MM_GPR_PCIE_SSC_EN BIT(16)
#define IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE BIT(9)
enum imx8_pcie_phy_type {
IMX8MM,
IMX8MP,
};
struct imx8_pcie_phy_drvdata {
const char *gpr;
enum imx8_pcie_phy_type variant;
};
struct imx8_pcie_phy {
void __iomem *base;
struct clk *clk;
struct phy *phy;
struct regmap *iomuxc_gpr;
struct reset_control *perst;
struct reset_control *reset;
u32 refclk_pad_mode;
u32 tx_deemph_gen1;
u32 tx_deemph_gen2;
bool clkreq_unused;
const struct imx8_pcie_phy_drvdata *drvdata;
};
static int imx8_pcie_phy_power_on(struct phy *phy)
......@@ -65,34 +76,22 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
u32 val, pad_mode;
struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
reset_control_assert(imx8_phy->reset);
pad_mode = imx8_phy->refclk_pad_mode;
/* Set AUX_EN_OVERRIDE 1'b0, when the CLKREQ# isn't hooked */
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE,
imx8_phy->clkreq_unused ?
0 : IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE);
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_AUX_EN,
IMX8MM_GPR_PCIE_AUX_EN);
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_POWER_OFF, 0);
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_SSC_EN, 0);
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_REF_CLK_SEL,
pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT ?
IMX8MM_GPR_PCIE_REF_CLK_EXT :
IMX8MM_GPR_PCIE_REF_CLK_PLL);
usleep_range(100, 200);
switch (imx8_phy->drvdata->variant) {
case IMX8MM:
reset_control_assert(imx8_phy->reset);
/* Do the PHY common block reset */
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_CMN_RST,
IMX8MM_GPR_PCIE_CMN_RST);
usleep_range(200, 500);
/* Tune PHY de-emphasis setting to pass PCIe compliance. */
if (imx8_phy->tx_deemph_gen1)
writel(imx8_phy->tx_deemph_gen1,
imx8_phy->base + PCIE_PHY_TRSV_REG5);
if (imx8_phy->tx_deemph_gen2)
writel(imx8_phy->tx_deemph_gen2,
imx8_phy->base + PCIE_PHY_TRSV_REG6);
break;
case IMX8MP: /* Do nothing. */
break;
}
if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT ||
pad_mode == IMX8_PCIE_REFCLK_PAD_UNUSED) {
......@@ -120,20 +119,44 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065);
}
/* Tune PHY de-emphasis setting to pass PCIe compliance. */
if (imx8_phy->tx_deemph_gen1)
writel(imx8_phy->tx_deemph_gen1,
imx8_phy->base + PCIE_PHY_TRSV_REG5);
if (imx8_phy->tx_deemph_gen2)
writel(imx8_phy->tx_deemph_gen2,
imx8_phy->base + PCIE_PHY_TRSV_REG6);
/* Set AUX_EN_OVERRIDE 1'b0, when the CLKREQ# isn't hooked */
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE,
imx8_phy->clkreq_unused ?
0 : IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE);
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_AUX_EN,
IMX8MM_GPR_PCIE_AUX_EN);
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_POWER_OFF, 0);
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_SSC_EN, 0);
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_REF_CLK_SEL,
pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT ?
IMX8MM_GPR_PCIE_REF_CLK_EXT :
IMX8MM_GPR_PCIE_REF_CLK_PLL);
usleep_range(100, 200);
/* Do the PHY common block reset */
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
IMX8MM_GPR_PCIE_CMN_RST,
IMX8MM_GPR_PCIE_CMN_RST);
switch (imx8_phy->drvdata->variant) {
case IMX8MP:
reset_control_deassert(imx8_phy->perst);
fallthrough;
case IMX8MM:
reset_control_deassert(imx8_phy->reset);
usleep_range(200, 500);
break;
}
/* Polling to check the phy is ready or not. */
ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG75,
val, val == PCIE_PHY_CMN_REG75_PLL_DONE,
10, 20000);
ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG075,
val, val == ANA_PLL_DONE, 10, 20000);
return ret;
}
......@@ -160,6 +183,23 @@ static const struct phy_ops imx8_pcie_phy_ops = {
.owner = THIS_MODULE,
};
static const struct imx8_pcie_phy_drvdata imx8mm_drvdata = {
.gpr = "fsl,imx8mm-iomuxc-gpr",
.variant = IMX8MM,
};
static const struct imx8_pcie_phy_drvdata imx8mp_drvdata = {
.gpr = "fsl,imx8mp-iomuxc-gpr",
.variant = IMX8MP,
};
static const struct of_device_id imx8_pcie_phy_of_match[] = {
{.compatible = "fsl,imx8mm-pcie-phy", .data = &imx8mm_drvdata, },
{.compatible = "fsl,imx8mp-pcie-phy", .data = &imx8mp_drvdata, },
{ },
};
MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
static int imx8_pcie_phy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
......@@ -172,6 +212,8 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
if (!imx8_phy)
return -ENOMEM;
imx8_phy->drvdata = of_device_get_match_data(dev);
/* get PHY refclk pad mode */
of_property_read_u32(np, "fsl,refclk-pad-mode",
&imx8_phy->refclk_pad_mode);
......@@ -197,7 +239,7 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
/* Grab GPR config register range */
imx8_phy->iomuxc_gpr =
syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
syscon_regmap_lookup_by_compatible(imx8_phy->drvdata->gpr);
if (IS_ERR(imx8_phy->iomuxc_gpr)) {
dev_err(dev, "unable to find iomuxc registers\n");
return PTR_ERR(imx8_phy->iomuxc_gpr);
......@@ -209,6 +251,14 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
return PTR_ERR(imx8_phy->reset);
}
if (imx8_phy->drvdata->variant == IMX8MP) {
imx8_phy->perst =
devm_reset_control_get_exclusive(dev, "perst");
if (IS_ERR(imx8_phy->perst))
dev_err_probe(dev, PTR_ERR(imx8_phy->perst),
"Failed to get PCIE PHY PERST control\n");
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
imx8_phy->base = devm_ioremap_resource(dev, res);
if (IS_ERR(imx8_phy->base))
......@@ -225,12 +275,6 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id imx8_pcie_phy_of_match[] = {
{.compatible = "fsl,imx8mm-pcie-phy",},
{ },
};
MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
static struct platform_driver imx8_pcie_phy_driver = {
.probe = imx8_pcie_phy_probe,
.driver = {
......
......@@ -41,12 +41,10 @@ static int mmp3_hsic_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct phy_provider *provider;
struct resource *resource;
void __iomem *base;
struct phy *phy;
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, resource);
base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(base))
return PTR_ERR(base);
......
......@@ -826,6 +826,9 @@ mvebu_a3700_comphy_usb3_power_on(struct mvebu_a3700_comphy_lane *lane)
if (ret)
return ret;
/* COMPHY register reset (cleared automatically) */
comphy_lane_reg_set(lane, COMPHY_SFT_RESET, SFT_RST, SFT_RST);
/*
* 0. Set PHY OTG Control(0x5d034), bit 4, Power up OTG module The
* register belong to UTMI module, so it is set in UTMI phy driver.
......
......@@ -54,6 +54,7 @@ config PHY_QCOM_QMP
tristate "Qualcomm QMP PHY Driver"
depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST)
select GENERIC_PHY
select MFD_SYSCON
help
Enable this to support the QMP PHY transceiver that is used
with controllers such as PCIe, UFS, and USB on Qualcomm chips.
......
This diff is collapsed.
......@@ -20,8 +20,6 @@
#include <linux/reset.h>
#include <linux/slab.h>
#include <dt-bindings/phy/phy.h>
#include "phy-qcom-qmp.h"
/* QPHY_SW_RESET bit */
......@@ -35,22 +33,16 @@
#define PLL_READY_GATE_EN BIT(3)
/* QPHY_PCS_STATUS bit */
#define PHYSTATUS BIT(6)
#define PHYSTATUS_4_20 BIT(7)
/* QPHY_COM_PCS_READY_STATUS bit */
#define PCS_READY BIT(0)
#define PHY_INIT_COMPLETE_TIMEOUT 10000
#define POWER_DOWN_DELAY_US_MIN 10
#define POWER_DOWN_DELAY_US_MAX 11
#define POWER_DOWN_DELAY_US_MAX 20
struct qmp_phy_init_tbl {
unsigned int offset;
unsigned int val;
/*
* register part of layout ?
* if yes, then offset gives index in the reg-layout
*/
bool in_layout;
/*
* mask of lanes for which this register is written
* for cases when second lane needs different values
......@@ -65,14 +57,6 @@ struct qmp_phy_init_tbl {
.lane_mask = 0xff, \
}
#define QMP_PHY_INIT_CFG_L(o, v) \
{ \
.offset = o, \
.val = v, \
.in_layout = true, \
.lane_mask = 0xff, \
}
#define QMP_PHY_INIT_CFG_LANE(o, v, l) \
{ \
.offset = o, \
......@@ -91,7 +75,6 @@ enum qphy_reg_layout {
QPHY_SW_RESET,
QPHY_START_CTRL,
QPHY_PCS_STATUS,
QPHY_PCS_POWER_DOWN_CONTROL,
/* Keep last to ensure regs_layout arrays are properly initialized */
QPHY_LAYOUT_SIZE
};
......@@ -211,18 +194,6 @@ struct qmp_phy_cfg {
/* array of registers with different offsets */
const unsigned int *regs;
unsigned int start_ctrl;
unsigned int pwrdn_ctrl;
unsigned int mask_com_pcs_ready;
/* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */
unsigned int phy_status;
/* true, if PHY needs delay after POWER_DOWN */
bool has_pwrdn_delay;
/* power_down delay in usec */
int pwrdn_delay_min;
int pwrdn_delay_max;
};
/**
......@@ -335,19 +306,9 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = {
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = pciephy_regs_layout,
.start_ctrl = PCS_START | PLL_READY_GATE_EN,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.mask_com_pcs_ready = PCS_READY,
.phy_status = PHYSTATUS,
.has_pwrdn_delay = true,
.pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
};
static void qmp_pcie_msm8996_configure_lane(void __iomem *base,
const unsigned int *regs,
const struct qmp_phy_init_tbl tbl[],
int num,
u8 lane_mask)
......@@ -362,19 +323,15 @@ static void qmp_pcie_msm8996_configure_lane(void __iomem *base,
if (!(t->lane_mask & lane_mask))
continue;
if (t->in_layout)
writel(t->val, base + regs[t->offset]);
else
writel(t->val, base + t->offset);
}
}
static void qmp_pcie_msm8996_configure(void __iomem *base,
const unsigned int *regs,
const struct qmp_phy_init_tbl tbl[],
int num)
{
qmp_pcie_msm8996_configure_lane(base, regs, tbl, num, 0xff);
qmp_pcie_msm8996_configure_lane(base, tbl, num, 0xff);
}
static int qmp_pcie_msm8996_serdes_init(struct qmp_phy *qphy)
......@@ -385,19 +342,17 @@ static int qmp_pcie_msm8996_serdes_init(struct qmp_phy *qphy)
const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl;
int serdes_tbl_num = cfg->serdes_tbl_num;
void __iomem *status;
unsigned int mask, val;
unsigned int val;
int ret;
qmp_pcie_msm8996_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num);
qmp_pcie_msm8996_configure(serdes, serdes_tbl, serdes_tbl_num);
qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET);
qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL],
SERDES_START | PCS_START);
status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS];
mask = cfg->mask_com_pcs_ready;
ret = readl_poll_timeout(status, val, (val & mask), 10,
ret = readl_poll_timeout(status, val, (val & PCS_READY), 200,
PHY_INIT_COMPLETE_TIMEOUT);
if (ret) {
dev_err(qmp->dev,
......@@ -421,7 +376,6 @@ static int qmp_pcie_msm8996_com_init(struct qmp_phy *qphy)
return 0;
}
/* turn on regulator supplies */
ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
if (ret) {
dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
......@@ -514,7 +468,7 @@ static int qmp_pcie_msm8996_power_on(struct phy *phy)
void __iomem *rx = qphy->rx;
void __iomem *pcs = qphy->pcs;
void __iomem *status;
unsigned int mask, val, ready;
unsigned int val;
int ret;
qmp_pcie_msm8996_serdes_init(qphy);
......@@ -533,34 +487,28 @@ static int qmp_pcie_msm8996_power_on(struct phy *phy)
}
/* Tx, Rx, and PCS configurations */
qmp_pcie_msm8996_configure_lane(tx, cfg->regs, cfg->tx_tbl,
cfg->tx_tbl_num, 1);
qmp_pcie_msm8996_configure_lane(rx, cfg->regs, cfg->rx_tbl,
cfg->rx_tbl_num, 1);
qmp_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
qmp_pcie_msm8996_configure_lane(tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
qmp_pcie_msm8996_configure_lane(rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
qmp_pcie_msm8996_configure(pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
/*
* Pull out PHY from POWER DOWN state.
* This is active low enable signal to power-down PHY.
*/
qphy_setbits(pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
qphy_setbits(pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL,
SW_PWRDN | REFCLK_DRV_DSBL);
if (cfg->has_pwrdn_delay)
usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max);
usleep_range(POWER_DOWN_DELAY_US_MIN, POWER_DOWN_DELAY_US_MAX);
/* Pull PHY out of reset state */
qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
/* start SerDes and Phy-Coding-Sublayer */
qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL],
PCS_START | PLL_READY_GATE_EN);
status = pcs + cfg->regs[QPHY_PCS_STATUS];
mask = cfg->phy_status;
ready = 0;
ret = readl_poll_timeout(status, val, (val & mask) == ready, 10,
ret = readl_poll_timeout(status, val, !(val & PHYSTATUS), 200,
PHY_INIT_COMPLETE_TIMEOUT);
if (ret) {
dev_err(qmp->dev, "phy initialization timed-out\n");
......@@ -588,16 +536,12 @@ static int qmp_pcie_msm8996_power_off(struct phy *phy)
qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
/* stop SerDes and Phy-Coding-Sublayer */
qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL],
SERDES_START | PCS_START);
/* Put PHY into POWER DOWN state: active low */
if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) {
qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
cfg->pwrdn_ctrl);
} else {
qphy_clrbits(qphy->pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL,
cfg->pwrdn_ctrl);
}
SW_PWRDN | REFCLK_DRV_DSBL);
return 0;
}
......@@ -777,7 +721,7 @@ static int qmp_pcie_msm8996_create(struct device *dev, struct device_node *np, i
qphy->cfg = cfg;
qphy->serdes = serdes;
/*
* Get memory resources for each phy lane:
* Get memory resources for each PHY:
* Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
*/
qphy->tx = devm_of_iomap(dev, np, 0, NULL);
......@@ -851,12 +795,10 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev)
qmp->dev = dev;
dev_set_drvdata(dev, qmp);
/* Get the specific init parameters of QMP phy */
cfg = of_device_get_match_data(dev);
if (!cfg)
return -EINVAL;
/* per PHY serdes; usually located at base address */
serdes = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(serdes))
return PTR_ERR(serdes);
......@@ -875,8 +817,7 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev)
ret = qmp_pcie_msm8996_vreg_init(dev, cfg);
if (ret)
return dev_err_probe(dev, ret,
"failed to get regulator supplies\n");
return ret;
num = of_get_available_child_count(dev->of_node);
/* do we have a rogue child node ? */
......
This diff is collapsed.
......@@ -8,6 +8,8 @@
#define QCOM_PHY_QMP_PCS_PCIE_V5_H_
/* Only for QMP V5 PHY - PCS_PCIE registers */
#define QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG2 0x0c
#define QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG4 0x14
#define QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x20
#define QPHY_V5_PCS_PCIE_INT_AUX_CLK_CONFIG1 0x54
#define QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS 0x94
......
......@@ -8,8 +8,10 @@
/* Only for QMP V5_20 PHY - PCIe PCS registers */
#define QPHY_V5_20_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x01c
#define QPHY_V5_20_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x084
#define QPHY_V5_20_PCS_PCIE_OSC_DTCT_ACTIONS 0x090
#define QPHY_V5_20_PCS_PCIE_EQ_CONFIG1 0x0a0
#define QPHY_V5_20_PCS_PCIE_PRESET_P10_POST 0x0e0
#define QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG5 0x108
#define QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN 0x15c
#define QPHY_V5_20_PCS_PCIE_RX_MARGINING_CONFIG3 0x184
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2022, Linaro Ltd.
*/
#ifndef QCOM_PHY_QMP_PCS_V5_20_H_
#define QCOM_PHY_QMP_PCS_V5_20_H_
#define QPHY_V5_20_PCS_G3S2_PRE_GAIN 0x170
#define QPHY_V5_20_PCS_RX_SIGDET_LVL 0x188
#define QPHY_V5_20_PCS_EQ_CONFIG4 0x1e0
#define QPHY_V5_20_PCS_EQ_CONFIG5 0x1e4
#endif
This diff is collapsed.
This diff is collapsed.
......@@ -38,6 +38,7 @@
#include "phy-qcom-qmp-pcs-pcie-v4_20.h"
#include "phy-qcom-qmp-pcs-v5.h"
#include "phy-qcom-qmp-pcs-v5_20.h"
#include "phy-qcom-qmp-pcs-pcie-v5.h"
#include "phy-qcom-qmp-pcs-usb-v5.h"
#include "phy-qcom-qmp-pcs-ufs-v5.h"
......
......@@ -2,6 +2,14 @@
#
# Phy drivers for Renesas platforms
#
# NOTE: Please sorted config names alphabetically.
config PHY_R8A779F0_ETHERNET_SERDES
tristate "Renesas R-Car S4-8 Ethernet SERDES driver"
depends on ARCH_RENESAS || COMPILE_TEST
select GENERIC_PHY
help
Support for Ethernet SERDES found on Renesas R-Car S4-8 SoCs.
config PHY_RCAR_GEN2
tristate "Renesas R-Car generation 2 USB PHY driver"
depends on ARCH_RENESAS
......
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_R8A779F0_ETHERNET_SERDES) += r8a779f0-ether-serdes.o
obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
obj-$(CONFIG_PHY_RCAR_GEN3_PCIE) += phy-rcar-gen3-pcie.o
obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o
......
This diff is collapsed.
......@@ -15,6 +15,7 @@
#include <linux/phy/phy.h>
#define P2U_CONTROL_CMN 0x74
#define P2U_CONTROL_CMN_ENABLE_L2_EXIT_RATE_CHANGE BIT(13)
#define P2U_CONTROL_CMN_SKP_SIZE_PROTECTION_EN BIT(20)
#define P2U_PERIODIC_EQ_CTRL_GEN3 0xc0
......@@ -85,8 +86,21 @@ static int tegra_p2u_power_on(struct phy *x)
return 0;
}
static int tegra_p2u_calibrate(struct phy *x)
{
struct tegra_p2u *phy = phy_get_drvdata(x);
u32 val;
val = p2u_readl(phy, P2U_CONTROL_CMN);
val |= P2U_CONTROL_CMN_ENABLE_L2_EXIT_RATE_CHANGE;
p2u_writel(phy, val, P2U_CONTROL_CMN);
return 0;
}
static const struct phy_ops ops = {
.power_on = tegra_p2u_power_on,
.calibrate = tegra_p2u_calibrate,
.owner = THIS_MODULE,
};
......
......@@ -1652,7 +1652,6 @@ tegra124_usb3_port_map(struct tegra_xusb_port *port)
static const struct tegra_xusb_port_ops tegra124_usb3_port_ops = {
.release = tegra_xusb_usb3_port_release,
.remove = tegra_xusb_usb3_port_remove,
.enable = tegra124_usb3_port_enable,
.disable = tegra124_usb3_port_disable,
.map = tegra124_usb3_port_map,
......
......@@ -1185,7 +1185,6 @@ tegra186_usb3_port_map(struct tegra_xusb_port *port)
static const struct tegra_xusb_port_ops tegra186_usb3_port_ops = {
.release = tegra_xusb_usb3_port_release,
.remove = tegra_xusb_usb3_port_remove,
.enable = tegra186_usb3_port_enable,
.disable = tegra186_usb3_port_disable,
.map = tegra186_usb3_port_map,
......
......@@ -3078,7 +3078,6 @@ tegra210_usb3_port_map(struct tegra_xusb_port *port)
static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = {
.release = tegra_xusb_usb3_port_release,
.remove = tegra_xusb_usb3_port_remove,
.enable = tegra210_usb3_port_enable,
.disable = tegra210_usb3_port_disable,
.map = tegra210_usb3_port_map,
......
......@@ -954,8 +954,7 @@ static int tegra_xusb_usb3_port_parse_dt(struct tegra_xusb_usb3_port *usb3)
return -EINVAL;
}
usb3->supply = regulator_get(&port->dev, "vbus");
return PTR_ERR_OR_ZERO(usb3->supply);
return 0;
}
static int tegra_xusb_add_usb3_port(struct tegra_xusb_padctl *padctl,
......@@ -1012,13 +1011,6 @@ void tegra_xusb_usb3_port_release(struct tegra_xusb_port *port)
kfree(usb3);
}
void tegra_xusb_usb3_port_remove(struct tegra_xusb_port *port)
{
struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port);
regulator_put(usb3->supply);
}
static void __tegra_xusb_remove_ports(struct tegra_xusb_padctl *padctl)
{
struct tegra_xusb_port *port, *tmp;
......
......@@ -359,7 +359,6 @@ void tegra_xusb_hsic_port_release(struct tegra_xusb_port *port);
struct tegra_xusb_usb3_port {
struct tegra_xusb_port base;
struct regulator *supply;
bool context_saved;
unsigned int port;
bool internal;
......@@ -381,7 +380,6 @@ struct tegra_xusb_usb3_port *
tegra_xusb_find_usb3_port(struct tegra_xusb_padctl *padctl,
unsigned int index);
void tegra_xusb_usb3_port_release(struct tegra_xusb_port *port);
void tegra_xusb_usb3_port_remove(struct tegra_xusb_port *port);
struct tegra_xusb_port_ops {
void (*release)(struct tegra_xusb_port *port);
......
This diff is collapsed.
This diff is collapsed.
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* Qualcomm QMP PHY constants
*
* Copyright (C) 2022 Linaro Limited
*/
#ifndef _DT_BINDINGS_PHY_QMP
#define _DT_BINDINGS_PHY_QMP
/* QMP USB4-USB3-DP clocks */
#define QMP_USB43DP_USB3_PIPE_CLK 0
#define QMP_USB43DP_DP_LINK_CLK 1
#define QMP_USB43DP_DP_VCO_DIV_CLK 2
/* QMP USB4-USB3-DP PHYs */
#define QMP_USB43DP_USB3_PHY 0
#define QMP_USB43DP_DP_PHY 1
#endif /* _DT_BINDINGS_PHY_QMP */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment