Merge tag 'phy-for-5.14_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/phy...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 23 Jun 2021 08:33:34 +0000 (10:33 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 23 Jun 2021 08:33:34 +0000 (10:33 +0200)
Vinod writes:

phy-for-5.14 version 2

  - Updates:
        - Yaml conversion for renesas,rcar-gen3 pcie phy and
          rockchip-usb-phy bindings
        - Support for devm_phy_get() taking NULL phy name

  - New support:
        - PCIe phy for Qualcomm IPQ60xx
        - PCIe phy for Qualcomm SDX55
        - USB phy for RK3308
        - CAN transceivers phy for TI TCAN104x
        - Innosilicon-based CSI dphy for rockchip

* tag 'phy-for-5.14_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (36 commits)
  phy: Revert "phy: ralink: Kconfig: convert mt7621-pci-phy into 'bool'"
  phy: ti: dm816x: Fix the error handling path in 'dm816x_usb_phy_probe()
  phy: uniphier-pcie: Fix updating phy parameters
  phy/rockchip: add Innosilicon-based CSI dphy
  dt-bindings: phy: add yaml binding for rockchip-inno-csi-dphy
  phy: rockchip: remove redundant initialization of pointer cfg
  phy: phy-can-transceiver: Add support for generic CAN transceiver driver
  dt-bindings: phy: Add binding for TI TCAN104x CAN transceivers
  phy: core: Reword the comment specifying the units of max_link_rate to be Mbps
  phy: phy-mtk-hdmi: Remove redundant dev_err call in mtk_hdmi_phy_probe()
  phy: phy-mtk-mipi-dsi: Remove redundant dev_err call in mtk_mipi_tx_probe()
  phy: phy-mmp3-hsic: Remove redundant dev_err call in mmp3_hsic_phy_probe()
  phy: bcm-ns-usb3: Remove redundant dev_err call in bcm_ns_usb3_mdio_probe()
  MAINTAINERS: update marvell,armada-3700-utmi-phy.yaml reference
  phy: phy-twl4030-usb: use DEVICE_ATTR_RO macro
  dt-bindings: phy: convert rockchip-usb-phy.txt to YAML
  phy: phy-rockchip-inno-usb2: add support for RK3308 USB phy
  dt-bindings: phy: rockchip-inno-usb2: add compatible for rk3308 USB phy
  phy: stm32: manage optional vbus regulator on phy_power_on/off
  dt-bindings: phy: add vbus-supply optional property to phy-stm32-usbphyc
  ...

36 files changed:
Documentation/devicetree/bindings/pci/qcom,pcie.txt
Documentation/devicetree/bindings/phy/mediatek,mt7621-pci-phy.yaml
Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml
Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml
Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt [deleted file]
Documentation/devicetree/bindings/phy/renesas,rcar-gen3-pcie-phy.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/phy/rockchip-inno-csi-dphy.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt [deleted file]
Documentation/devicetree/bindings/phy/rockchip-usb-phy.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml [new file with mode: 0644]
MAINTAINERS
drivers/phy/Kconfig
drivers/phy/Makefile
drivers/phy/broadcom/phy-bcm-ns-usb3.c
drivers/phy/marvell/phy-mmp3-hsic.c
drivers/phy/mediatek/phy-mtk-hdmi.c
drivers/phy/mediatek/phy-mtk-mipi-dsi.c
drivers/phy/phy-can-transceiver.c [new file with mode: 0644]
drivers/phy/phy-core-mipi-dphy.c
drivers/phy/phy-core.c
drivers/phy/phy-xgene.c
drivers/phy/qualcomm/phy-qcom-qmp.c
drivers/phy/qualcomm/phy-qcom-qmp.h
drivers/phy/ralink/Kconfig
drivers/phy/ralink/phy-mt7621-pci.c
drivers/phy/rockchip/Kconfig
drivers/phy/rockchip/Makefile
drivers/phy/rockchip/phy-rockchip-inno-csidphy.c [new file with mode: 0644]
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
drivers/phy/rockchip/phy-rockchip-inno-usb2.c
drivers/phy/socionext/phy-uniphier-pcie.c
drivers/phy/st/phy-stm32-usbphyc.c
drivers/phy/ti/phy-dm816x-usb.c
drivers/phy/ti/phy-twl4030-usb.c
include/linux/phy/phy.h

index 0da458a..25f4def 100644 (file)
@@ -14,6 +14,7 @@
                        - "qcom,pcie-qcs404" for qcs404
                        - "qcom,pcie-sdm845" for sdm845
                        - "qcom,pcie-sm8250" for sm8250
+                       - "qcom,pcie-ipq6018" for ipq6018
 
 - reg:
        Usage: required
                        - "aux"         Auxiliary clock
 
 - clock-names:
+       Usage: required for ipq6018
+       Value type: <stringlist>
+       Definition: Should contain the following entries
+                       - "iface"       PCIe to SysNOC BIU clock
+                       - "axi_m"       AXI Master clock
+                       - "axi_s"       AXI Slave clock
+                       - "axi_bridge"  AXI bridge clock
+                       - "rchng"
+
+- clock-names:
        Usage: required for qcs404
        Value type: <stringlist>
        Definition: Should contain the following entries
                        - "axi_m_sticky"        AXI Master Sticky reset
 
 - reset-names:
+       Usage: required for ipq6018
+       Value type: <stringlist>
+       Definition: Should contain the following entries
+                       - "pipe"                PIPE reset
+                       - "sleep"               Sleep reset
+                       - "sticky"              Core Sticky reset
+                       - "axi_m"               AXI Master reset
+                       - "axi_s"               AXI Slave reset
+                       - "ahb"                 AHB Reset
+                       - "axi_m_sticky"        AXI Master Sticky reset
+                       - "axi_s_sticky"        AXI Slave Sticky reset
+
+- reset-names:
        Usage: required for qcs404
        Value type: <stringlist>
        Definition: Should contain the following entries
index 0ccaded..29d4123 100644 (file)
@@ -16,6 +16,9 @@ properties:
   reg:
     maxItems: 1
 
+  clocks:
+    maxItems: 1
+
   "#phy-cells":
     const: 1
     description: selects if the phy is dual-ported
@@ -23,6 +26,7 @@ properties:
 required:
   - compatible
   - reg
+  - clocks
   - "#phy-cells"
 
 additionalProperties: false
@@ -32,5 +36,6 @@ examples:
     pcie0_phy: pcie-phy@1e149000 {
       compatible = "mediatek,mt7621-pci-phy";
       reg = <0x1e149000 0x0700>;
+      clocks = <&sysc 0>;
       #phy-cells = <1>;
     };
index fb29ad8..a5b027a 100644 (file)
@@ -14,6 +14,7 @@ properties:
     enum:
       - rockchip,px30-usb2phy
       - rockchip,rk3228-usb2phy
+      - rockchip,rk3308-usb2phy
       - rockchip,rk3328-usb2phy
       - rockchip,rk3366-usb2phy
       - rockchip,rk3399-usb2phy
index 018cc12..3329f1d 100644 (file)
@@ -74,6 +74,13 @@ patternProperties:
       "#phy-cells":
         enum: [ 0x0, 0x1 ]
 
+      connector:
+        type: object
+        allOf:
+          - $ref: ../connector/usb-connector.yaml
+        properties:
+          vbus-supply: true
+
     allOf:
       - if:
           properties:
@@ -130,6 +137,10 @@ examples:
             reg = <0>;
             phy-supply = <&vdd_usb>;
             #phy-cells = <0>;
+            connector {
+                compatible = "usb-a-connector";
+                vbus-supply = <&vbus_sw>;
+            };
         };
 
         usbphyc_port1: usb-phy@1 {
index 7808ec8..0f14de0 100644 (file)
@@ -17,6 +17,7 @@ description:
 properties:
   compatible:
     enum:
+      - qcom,ipq6018-qmp-pcie-phy
       - qcom,ipq8074-qmp-pcie-phy
       - qcom,ipq8074-qmp-usb3-phy
       - qcom,msm8996-qmp-pcie-phy
@@ -45,6 +46,7 @@ properties:
       - qcom,sm8350-qmp-ufs-phy
       - qcom,sm8350-qmp-usb3-phy
       - qcom,sm8350-qmp-usb3-uni-phy
+      - qcom,sdx55-qmp-pcie-phy
       - qcom,sdx55-qmp-usb3-uni-phy
 
   reg:
@@ -301,8 +303,33 @@ allOf:
         compatible:
           contains:
             enum:
+              - qcom,ipq6018-qmp-pcie-phy
+    then:
+      properties:
+        clocks:
+          items:
+            - description: Phy aux clock.
+            - description: Phy config clock.
+        clock-names:
+          items:
+            - const: aux
+            - const: cfg_ahb
+        resets:
+          items:
+            - description: reset of phy block.
+            - description: phy common block reset.
+        reset-names:
+          items:
+            - const: phy
+            - const: common
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
               - qcom,sdm845-qhp-pcie-phy
               - qcom,sdm845-qmp-pcie-phy
+              - qcom,sdx55-qmp-pcie-phy
               - qcom,sm8250-qmp-gen3x1-pcie-phy
               - qcom,sm8250-qmp-gen3x2-pcie-phy
               - qcom,sm8250-qmp-modem-pcie-phy
diff --git a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt
deleted file mode 100644 (file)
index 63853b3..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-* Renesas R-Car generation 3 PCIe PHY
-
-This file provides information on what the device node for the R-Car
-generation 3 PCIe PHY contains.
-
-Required properties:
-- compatible: "renesas,r8a77980-pcie-phy" if the device is a part of the
-             R8A77980 SoC.
-- reg: offset and length of the register block.
-- clocks: clock phandle and specifier pair.
-- power-domains: power domain phandle and specifier pair.
-- resets: reset phandle and specifier pair.
-- #phy-cells: see phy-bindings.txt in the same directory, must be <0>.
-
-Example (R-Car V3H):
-
-       pcie-phy@e65d0000 {
-               compatible = "renesas,r8a77980-pcie-phy";
-               reg = <0 0xe65d0000 0 0x8000>;
-               #phy-cells = <0>;
-               clocks = <&cpg CPG_MOD 319>;
-               power-domains = <&sysc 32>;
-               resets = <&cpg 319>;
-       };
diff --git a/Documentation/devicetree/bindings/phy/renesas,rcar-gen3-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/renesas,rcar-gen3-pcie-phy.yaml
new file mode 100644 (file)
index 0000000..247ef7c
--- /dev/null
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/renesas,rcar-gen3-pcie-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas R-Car Generation 3 PCIe PHY
+
+maintainers:
+  - Sergei Shtylyov <sergei.shtylyov@gmail.com>
+
+properties:
+  compatible:
+    const: renesas,r8a77980-pcie-phy
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  '#phy-cells':
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - power-domains
+  - resets
+  - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/r8a77980-cpg-mssr.h>
+    #include <dt-bindings/power/r8a77980-sysc.h>
+
+    pcie-phy@e65d0000 {
+            compatible = "renesas,r8a77980-pcie-phy";
+            reg = <0xe65d0000 0x8000>;
+            #phy-cells = <0>;
+            clocks = <&cpg CPG_MOD 319>;
+            power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+            resets = <&cpg 319>;
+    };
diff --git a/Documentation/devicetree/bindings/phy/rockchip-inno-csi-dphy.yaml b/Documentation/devicetree/bindings/phy/rockchip-inno-csi-dphy.yaml
new file mode 100644 (file)
index 0000000..bb4a2e4
--- /dev/null
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/rockchip-inno-csi-dphy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip SoC MIPI RX0 D-PHY Device Tree Bindings
+
+maintainers:
+  - Heiko Stuebner <heiko@sntech.de>
+
+description: |
+  The Rockchip SoC has a MIPI CSI D-PHY based on an Innosilicon IP wich
+  connects to the ISP1 (Image Signal Processing unit v1.0) for CSI cameras.
+
+properties:
+  compatible:
+    enum:
+      - rockchip,px30-csi-dphy
+      - rockchip,rk1808-csi-dphy
+      - rockchip,rk3326-csi-dphy
+      - rockchip,rk3368-csi-dphy
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    const: pclk
+
+  '#phy-cells':
+    const: 0
+
+  power-domains:
+    description: Video in/out power domain.
+    maxItems: 1
+
+  resets:
+    items:
+      - description: exclusive PHY reset line
+
+  reset-names:
+    items:
+      - const: apb
+
+  rockchip,grf:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Some additional phy settings are access through GRF regs.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#phy-cells'
+  - power-domains
+  - resets
+  - reset-names
+  - rockchip,grf
+
+additionalProperties: false
+
+examples:
+  - |
+
+    csi_dphy: phy@ff2f0000 {
+        compatible = "rockchip,px30-csi-dphy";
+        reg = <0xff2f0000 0x4000>;
+        clocks = <&cru 1>;
+        clock-names = "pclk";
+        #phy-cells = <0>;
+        power-domains = <&power 1>;
+        resets = <&cru 1>;
+        reset-names = "apb";
+        rockchip,grf = <&grf>;
+    };
diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
deleted file mode 100644 (file)
index 4ed5690..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-ROCKCHIP USB2 PHY
-
-Required properties:
- - compatible: matching the soc type, one of
-     "rockchip,rk3066a-usb-phy"
-     "rockchip,rk3188-usb-phy"
-     "rockchip,rk3288-usb-phy"
- - #address-cells: should be 1
- - #size-cells: should be 0
-
-Deprecated properties:
- - rockchip,grf : phandle to the syscon managing the "general
-   register files" - phy should be a child of the GRF instead
-
-Sub-nodes:
-Each PHY should be represented as a sub-node.
-
-Sub-nodes
-required properties:
-- #phy-cells: should be 0
-- reg: PHY configure reg address offset in GRF
-               "0x320" - for PHY attach to OTG controller
-               "0x334" - for PHY attach to HOST0 controller
-               "0x348" - for PHY attach to HOST1 controller
-
-Optional Properties:
-- clocks : phandle + clock specifier for the phy clocks
-- clock-names: string, clock name, must be "phyclk"
-- #clock-cells: for users of the phy-pll, should be 0
-- reset-names: Only allow the following entries:
- - phy-reset
-- resets: Must contain an entry for each entry in reset-names.
-- vbus-supply: power-supply phandle for vbus power source
-
-Example:
-
-grf: syscon@ff770000 {
-       compatible = "rockchip,rk3288-grf", "syscon", "simple-mfd";
-
-...
-
-       usbphy: phy {
-               compatible = "rockchip,rk3288-usb-phy";
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               usbphy0: usb-phy0 {
-                       #phy-cells = <0>;
-                       reg = <0x320>;
-               };
-       };
-};
diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.yaml b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.yaml
new file mode 100644 (file)
index 0000000..f0fc827
--- /dev/null
@@ -0,0 +1,81 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/rockchip-usb-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip USB2.0 phy
+
+maintainers:
+  - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+  compatible:
+    oneOf:
+      - const: rockchip,rk3288-usb-phy
+      - items:
+          - enum:
+              - rockchip,rk3066a-usb-phy
+              - rockchip,rk3188-usb-phy
+          - const: rockchip,rk3288-usb-phy
+
+  "#address-cells":
+    const: 1
+
+  "#size-cells":
+    const: 0
+
+required:
+  - compatible
+  - "#address-cells"
+  - "#size-cells"
+
+additionalProperties: false
+
+patternProperties:
+  "usb-phy@[0-9a-f]+$":
+    type: object
+
+    properties:
+      reg:
+        maxItems: 1
+
+      "#phy-cells":
+        const: 0
+
+      clocks:
+        maxItems: 1
+
+      clock-names:
+        const: phyclk
+
+      "#clock-cells":
+        const: 0
+
+      resets:
+        maxItems: 1
+
+      reset-names:
+        const: phy-reset
+
+      vbus-supply:
+        description: phandle for vbus power source
+
+    required:
+      - reg
+      - "#phy-cells"
+
+    additionalProperties: false
+
+examples:
+  - |
+    usbphy: usbphy {
+      compatible = "rockchip,rk3288-usb-phy";
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      usbphy0: usb-phy@320 {
+        reg = <0x320>;
+        #phy-cells = <0>;
+      };
+    };
diff --git a/Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml b/Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml
new file mode 100644 (file)
index 0000000..6107880
--- /dev/null
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/phy/ti,tcan104x-can.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: TCAN104x CAN TRANSCEIVER PHY
+
+maintainers:
+  - Aswath Govindraju <a-govindraju@ti.com>
+
+properties:
+  $nodename:
+    pattern: "^can-phy"
+
+  compatible:
+    enum:
+      - ti,tcan1042
+      - ti,tcan1043
+
+  '#phy-cells':
+    const: 0
+
+  standby-gpios:
+    description:
+      gpio node to toggle standby signal on transceiver
+    maxItems: 1
+
+  enable-gpios:
+    description:
+      gpio node to toggle enable signal on transceiver
+    maxItems: 1
+
+  max-bitrate:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      max bit rate supported in bps
+    minimum: 1
+
+required:
+  - compatible
+  - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    transceiver1: can-phy {
+      compatible = "ti,tcan1043";
+      #phy-cells = <0>;
+      max-bitrate = <5000000>;
+      standby-gpios = <&wakeup_gpio1 16 GPIO_ACTIVE_LOW>;
+      enable-gpios = <&main_gpio1 67 GPIO_ACTIVE_HIGH>;
+    };
index bc0ceef..bd6e283 100644 (file)
@@ -4041,7 +4041,9 @@ W:        https://github.com/linux-can
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
 F:     Documentation/devicetree/bindings/net/can/
+F:     Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml
 F:     drivers/net/can/
+F:     drivers/phy/phy-can-transceiver.c
 F:     include/linux/can/bittiming.h
 F:     include/linux/can/dev.h
 F:     include/linux/can/led.h
@@ -10897,7 +10899,7 @@ MARVELL ARMADA 3700 PHY DRIVERS
 M:     Miquel Raynal <miquel.raynal@bootlin.com>
 S:     Maintained
 F:     Documentation/devicetree/bindings/phy/phy-mvebu-comphy.txt
-F:     Documentation/devicetree/bindings/phy/phy-mvebu-utmi.txt
+F:     Documentation/devicetree/bindings/phy/marvell,armada-3700-utmi-phy.yaml
 F:     drivers/phy/marvell/phy-mvebu-a3700-comphy.c
 F:     drivers/phy/marvell/phy-mvebu-a3700-utmi.c
 
index 54c1f2f..7dd35f1 100644 (file)
@@ -61,6 +61,15 @@ config USB_LGM_PHY
          interface to interact with USB GEN-II and USB 3.x PHY that is part
          of the Intel network SOC.
 
+config PHY_CAN_TRANSCEIVER
+       tristate "CAN transceiver PHY"
+       select GENERIC_PHY
+       help
+         This option enables support for CAN transceivers as a PHY. This
+         driver provides function for putting the transceivers in various
+         functional modes using gpios and sets the attribute max link
+         rate, for CAN drivers.
+
 source "drivers/phy/allwinner/Kconfig"
 source "drivers/phy/amlogic/Kconfig"
 source "drivers/phy/broadcom/Kconfig"
index adac1b1..01e9eff 100644 (file)
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_GENERIC_PHY)              += phy-core.o
 obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY)    += phy-core-mipi-dphy.o
+obj-$(CONFIG_PHY_CAN_TRANSCEIVER)      += phy-can-transceiver.o
 obj-$(CONFIG_PHY_LPC18XX_USB_OTG)      += phy-lpc18xx-usb-otg.o
 obj-$(CONFIG_PHY_XGENE)                        += phy-xgene.o
 obj-$(CONFIG_PHY_PISTACHIO_USB)                += phy-pistachio-usb.o
index eb10ffa..b1adaec 100644 (file)
@@ -215,10 +215,8 @@ static int bcm_ns_usb3_mdio_probe(struct mdio_device *mdiodev)
                return err;
 
        usb3->dmp = devm_ioremap_resource(dev, &res);
-       if (IS_ERR(usb3->dmp)) {
-               dev_err(dev, "Failed to map DMP regs\n");
+       if (IS_ERR(usb3->dmp))
                return PTR_ERR(usb3->dmp);
-       }
 
        usb3->phy = devm_phy_create(dev, NULL, &ops);
        if (IS_ERR(usb3->phy)) {
index 47c1e88..7cccf01 100644 (file)
@@ -47,10 +47,8 @@ static int mmp3_hsic_phy_probe(struct platform_device *pdev)
 
        resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        base = devm_ioremap_resource(dev, resource);
-       if (IS_ERR(base)) {
-               dev_err(dev, "failed to remap PHY regs\n");
+       if (IS_ERR(base))
                return PTR_ERR(base);
-       }
 
        phy = devm_phy_create(dev, NULL, &mmp3_hsic_phy_ops);
        if (IS_ERR(phy)) {
index 8313bd5..8ad8f71 100644 (file)
@@ -119,9 +119,7 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        hdmi_phy->regs = devm_ioremap_resource(dev, mem);
        if (IS_ERR(hdmi_phy->regs)) {
-               ret = PTR_ERR(hdmi_phy->regs);
-               dev_err(dev, "Failed to get memory resource: %d\n", ret);
-               return ret;
+               return PTR_ERR(hdmi_phy->regs);
        }
 
        ref_clk = devm_clk_get(dev, "pll_ref");
index c51114d..01cf316 100644 (file)
@@ -151,9 +151,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        mipi_tx->regs = devm_ioremap_resource(dev, mem);
        if (IS_ERR(mipi_tx->regs)) {
-               ret = PTR_ERR(mipi_tx->regs);
-               dev_err(dev, "Failed to get memory resource: %d\n", ret);
-               return ret;
+               return PTR_ERR(mipi_tx->regs);
        }
 
        ref_clk = devm_clk_get(dev, NULL);
diff --git a/drivers/phy/phy-can-transceiver.c b/drivers/phy/phy-can-transceiver.c
new file mode 100644 (file)
index 0000000..c2cb93b
--- /dev/null
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * phy-can-transceiver.c - phy driver for CAN transceivers
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com
+ *
+ */
+#include<linux/phy/phy.h>
+#include<linux/platform_device.h>
+#include<linux/module.h>
+#include<linux/gpio.h>
+#include<linux/gpio/consumer.h>
+
+struct can_transceiver_data {
+       u32 flags;
+#define CAN_TRANSCEIVER_STB_PRESENT    BIT(0)
+#define CAN_TRANSCEIVER_EN_PRESENT     BIT(1)
+};
+
+struct can_transceiver_phy {
+       struct phy *generic_phy;
+       struct gpio_desc *standby_gpio;
+       struct gpio_desc *enable_gpio;
+};
+
+/* Power on function */
+static int can_transceiver_phy_power_on(struct phy *phy)
+{
+       struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy);
+
+       if (can_transceiver_phy->standby_gpio)
+               gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 0);
+       if (can_transceiver_phy->enable_gpio)
+               gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 1);
+
+       return 0;
+}
+
+/* Power off function */
+static int can_transceiver_phy_power_off(struct phy *phy)
+{
+       struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy);
+
+       if (can_transceiver_phy->standby_gpio)
+               gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 1);
+       if (can_transceiver_phy->enable_gpio)
+               gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 0);
+
+       return 0;
+}
+
+static const struct phy_ops can_transceiver_phy_ops = {
+       .power_on       = can_transceiver_phy_power_on,
+       .power_off      = can_transceiver_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static const struct can_transceiver_data tcan1042_drvdata = {
+       .flags = CAN_TRANSCEIVER_STB_PRESENT,
+};
+
+static const struct can_transceiver_data tcan1043_drvdata = {
+       .flags = CAN_TRANSCEIVER_STB_PRESENT | CAN_TRANSCEIVER_EN_PRESENT,
+};
+
+static const struct of_device_id can_transceiver_phy_ids[] = {
+       {
+               .compatible = "ti,tcan1042",
+               .data = &tcan1042_drvdata
+       },
+       {
+               .compatible = "ti,tcan1043",
+               .data = &tcan1043_drvdata
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, can_transceiver_phy_ids);
+
+static int can_transceiver_phy_probe(struct platform_device *pdev)
+{
+       struct phy_provider *phy_provider;
+       struct device *dev = &pdev->dev;
+       struct can_transceiver_phy *can_transceiver_phy;
+       const struct can_transceiver_data *drvdata;
+       const struct of_device_id *match;
+       struct phy *phy;
+       struct gpio_desc *standby_gpio;
+       struct gpio_desc *enable_gpio;
+       u32 max_bitrate = 0;
+
+       can_transceiver_phy = devm_kzalloc(dev, sizeof(struct can_transceiver_phy), GFP_KERNEL);
+       if (!can_transceiver_phy)
+               return -ENOMEM;
+
+       match = of_match_node(can_transceiver_phy_ids, pdev->dev.of_node);
+       drvdata = match->data;
+
+       phy = devm_phy_create(dev, dev->of_node,
+                             &can_transceiver_phy_ops);
+       if (IS_ERR(phy)) {
+               dev_err(dev, "failed to create can transceiver phy\n");
+               return PTR_ERR(phy);
+       }
+
+       device_property_read_u32(dev, "max-bitrate", &max_bitrate);
+       if (!max_bitrate)
+               dev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit\n");
+       phy->attrs.max_link_rate = max_bitrate;
+
+       can_transceiver_phy->generic_phy = phy;
+
+       if (drvdata->flags & CAN_TRANSCEIVER_STB_PRESENT) {
+               standby_gpio = devm_gpiod_get(dev, "standby", GPIOD_OUT_HIGH);
+               if (IS_ERR(standby_gpio))
+                       return PTR_ERR(standby_gpio);
+               can_transceiver_phy->standby_gpio = standby_gpio;
+       }
+
+       if (drvdata->flags & CAN_TRANSCEIVER_EN_PRESENT) {
+               enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
+               if (IS_ERR(enable_gpio))
+                       return PTR_ERR(enable_gpio);
+               can_transceiver_phy->enable_gpio = enable_gpio;
+       }
+
+       phy_set_drvdata(can_transceiver_phy->generic_phy, can_transceiver_phy);
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static struct platform_driver can_transceiver_phy_driver = {
+       .probe = can_transceiver_phy_probe,
+       .driver = {
+               .name = "can-transceiver-phy",
+               .of_match_table = can_transceiver_phy_ids,
+       },
+};
+
+module_platform_driver(can_transceiver_phy_driver);
+
+MODULE_AUTHOR("Faiz Abbas <faiz_abbas@ti.com>");
+MODULE_AUTHOR("Aswath Govindraju <a-govindraju@ti.com>");
+MODULE_DESCRIPTION("CAN TRANSCEIVER PHY driver");
+MODULE_LICENSE("GPL v2");
index 77fe653..288c9c6 100644 (file)
@@ -15,7 +15,7 @@
 /*
  * Minimum D-PHY timings based on MIPI D-PHY specification. Derived
  * from the valid ranges specified in Section 6.9, Table 14, Page 41
- * of the D-PHY specification (v2.1).
+ * of the D-PHY specification (v1.2).
  */
 int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
                                     unsigned int bpp,
index ccb575b..91e28d6 100644 (file)
@@ -697,16 +697,18 @@ struct phy *phy_get(struct device *dev, const char *string)
        struct phy *phy;
        struct device_link *link;
 
-       if (string == NULL) {
-               dev_WARN(dev, "missing string\n");
-               return ERR_PTR(-EINVAL);
-       }
-
        if (dev->of_node) {
-               index = of_property_match_string(dev->of_node, "phy-names",
-                       string);
+               if (string)
+                       index = of_property_match_string(dev->of_node, "phy-names",
+                               string);
+               else
+                       index = 0;
                phy = _of_phy_get(dev->of_node, index);
        } else {
+               if (string == NULL) {
+                       dev_WARN(dev, "missing string\n");
+                       return ERR_PTR(-EINVAL);
+               }
                phy = phy_find(dev, string);
        }
        if (IS_ERR(phy))
index f4cd590..d0f4546 100644 (file)
@@ -961,7 +961,8 @@ static void xgene_phy_sata_cfg_lanes(struct xgene_phy_ctx *ctx)
                serdes_wr(ctx, lane, RXTX_REG1, val);
 
                /* Latch VTT value based on the termination to ground and
-                  enable TX FIFO */
+                * enable TX FIFO
+                */
                serdes_rd(ctx, lane, RXTX_REG2, &val);
                val = RXTX_REG2_VTT_ENA_SET(val, 0x1);
                val = RXTX_REG2_VTT_SEL_SET(val, 0x1);
index 7877f70..cfe3594 100644 (file)
@@ -35,6 +35,7 @@
 #define PLL_READY_GATE_EN                      BIT(3)
 /* QPHY_PCS_STATUS bit */
 #define PHYSTATUS                              BIT(6)
+#define PHYSTATUS_4_20                         BIT(7)
 /* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */
 #define PCS_READY                              BIT(0)
 
@@ -143,6 +144,13 @@ static const unsigned int msm8996_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = {
        [QPHY_PCS_READY_STATUS]         = 0x168,
 };
 
+static const unsigned int ipq_pciephy_gen3_regs_layout[QPHY_LAYOUT_SIZE] = {
+       [QPHY_SW_RESET]                         = 0x00,
+       [QPHY_START_CTRL]                       = 0x44,
+       [QPHY_PCS_STATUS]                       = 0x14,
+       [QPHY_PCS_POWER_DOWN_CONTROL]           = 0x40,
+};
+
 static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = {
        [QPHY_COM_SW_RESET]             = 0x400,
        [QPHY_COM_POWER_DOWN_CONTROL]   = 0x404,
@@ -614,6 +622,113 @@ static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = {
        QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08),
 };
 
+static const struct qmp_phy_init_tbl ipq6018_pcie_serdes_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xd4),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x68),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
+       QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08),
+};
+
+static const struct qmp_phy_init_tbl ipq6018_pcie_tx_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_TX0_RES_CODE_LANE_OFFSET_TX, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_TX0_LANE_MODE_1, 0x06),
+       QMP_PHY_INIT_CFG(QSERDES_TX0_RCV_DETECT_LVL_2, 0x12),
+};
+
+static const struct qmp_phy_init_tbl ipq6018_pcie_rx_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_FO_GAIN, 0x0c),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_GAIN, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_PI_CONTROLS, 0x70),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2, 0x61),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3, 0x04),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4, 0x1e),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_LOW, 0xc0),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_HIGH, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x73),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_ENABLES, 0x1c),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_CNTRL, 0x03),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_DEGLITCH_CNTRL, 0x14),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_LOW, 0xf0),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH2, 0x2f),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH3, 0xd3),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH4, 0x40),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_LOW, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH2, 0xc8),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH3, 0x09),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH4, 0xb1),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_LOW, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH2, 0xc8),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH3, 0x09),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH4, 0xb1),
+       QMP_PHY_INIT_CFG(QSERDES_RX0_DFE_EN_TIMER, 0x04),
+};
+
+static const struct qmp_phy_init_tbl ipq6018_pcie_pcs_tbl[] = {
+       QMP_PHY_INIT_CFG(PCS_COM_FLL_CNTRL1, 0x01),
+       QMP_PHY_INIT_CFG(PCS_COM_REFGEN_REQ_CONFIG1, 0x0d),
+       QMP_PHY_INIT_CFG(PCS_COM_G12S1_TXDEEMPH_M3P5DB, 0x10),
+       QMP_PHY_INIT_CFG(PCS_COM_RX_SIGDET_LVL, 0xaa),
+       QMP_PHY_INIT_CFG(PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+       QMP_PHY_INIT_CFG(PCS_COM_RX_DCC_CAL_CONFIG, 0x01),
+       QMP_PHY_INIT_CFG(PCS_COM_EQ_CONFIG5, 0x01),
+       QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG2, 0x0d),
+       QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
+       QMP_PHY_INIT_CFG(PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
+       QMP_PHY_INIT_CFG(PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+       QMP_PHY_INIT_CFG(PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+       QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
+       QMP_PHY_INIT_CFG(PCS_PCIE_EQ_CONFIG1, 0x11),
+       QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_PRE, 0x00),
+       QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_POST, 0x58),
+};
+
 static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = {
        QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18),
        QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
@@ -2110,6 +2225,101 @@ static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_rx_tbl[] = {
        QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f),
 };
 
+static const struct qmp_phy_init_tbl sdx55_qmp_pcie_serdes_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x18),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x07),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x0a),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x0a),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x19),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x19),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x03),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x03),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x46),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_CFG, 0x04),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x7f),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0xff),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x04),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x4b),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x50),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0xfb),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1, 0xfb),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x12),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x05),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x04),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x04),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MISC1, 0x88),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTERNAL_DIG_CORECLK_DIV, 0x03),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MODE, 0x17),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_DC_LEVEL_CTRL, 0x0b),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x56),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1d),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x4b),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1f),
+       QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x22),
+};
+
+static const struct qmp_phy_init_tbl sdx55_qmp_pcie_tx_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_1, 0x05),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_2, 0xf6),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_3, 0x13),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_VMODE_CTRL1, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_PI_QEC_CTRL, 0x00),
+};
+
+static const struct qmp_phy_init_tbl sdx55_qmp_pcie_rx_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_FO_GAIN_RATE2, 0x0c),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_UCDR_PI_CONTROLS, 0x16),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_AUX_DATA_TCOARSE_TFINE, 0x7f),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_3, 0x55),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE1, 0x0c),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE2, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_VGA_CAL_CNTRL2, 0x08),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B1, 0x1a),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B2, 0x5a),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B3, 0x09),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B4, 0x37),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B0, 0xbd),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B1, 0xf9),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B2, 0xbf),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B3, 0xce),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B4, 0x62),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B0, 0xbf),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B1, 0x7d),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B2, 0xbf),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B3, 0xcf),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B4, 0xd6),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_PHPRE_CTRL, 0xa0),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+       QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_MARG_COARSE_CTRL2, 0x12),
+};
+
+static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_tbl[] = {
+       QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_RX_SIGDET_LVL, 0x77),
+       QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG2, 0x01),
+       QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG4, 0x16),
+       QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG5, 0x02),
+};
+
+static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_misc_tbl[] = {
+       QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_EQ_CONFIG1, 0x17),
+       QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME, 0x13),
+       QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME, 0x13),
+       QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2, 0x01),
+       QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02),
+       QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2, 0x00),
+       QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00),
+};
+
 static const struct qmp_phy_init_tbl sm8350_ufsphy_serdes_tbl[] = {
        QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0xd9),
        QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x11),
@@ -2411,6 +2621,8 @@ struct qmp_phy_cfg {
        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 has a separate PHY_COM control block */
        bool has_phy_com_ctrl;
@@ -2624,6 +2836,7 @@ static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 };
 
 static const struct qmp_phy_cfg msm8996_pciephy_cfg = {
@@ -2649,6 +2862,7 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = {
        .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_phy_com_ctrl       = true,
        .has_lane_rst           = true,
@@ -2678,6 +2892,7 @@ static const struct qmp_phy_cfg msm8996_ufs_cfg = {
 
        .start_ctrl             = SERDES_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .no_pcs_sw_reset        = true,
 };
@@ -2704,6 +2919,7 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 };
 
 static const char * const ipq8074_pciephy_clk_l[] = {
@@ -2736,6 +2952,37 @@ static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN | REFCLK_DRV_DSBL,
+       .phy_status             = PHYSTATUS,
+
+       .has_phy_com_ctrl       = false,
+       .has_lane_rst           = false,
+       .has_pwrdn_delay        = true,
+       .pwrdn_delay_min        = 995,          /* us */
+       .pwrdn_delay_max        = 1005,         /* us */
+};
+
+static const struct qmp_phy_cfg ipq6018_pciephy_cfg = {
+       .type                   = PHY_TYPE_PCIE,
+       .nlanes                 = 1,
+
+       .serdes_tbl             = ipq6018_pcie_serdes_tbl,
+       .serdes_tbl_num         = ARRAY_SIZE(ipq6018_pcie_serdes_tbl),
+       .tx_tbl                 = ipq6018_pcie_tx_tbl,
+       .tx_tbl_num             = ARRAY_SIZE(ipq6018_pcie_tx_tbl),
+       .rx_tbl                 = ipq6018_pcie_rx_tbl,
+       .rx_tbl_num             = ARRAY_SIZE(ipq6018_pcie_rx_tbl),
+       .pcs_tbl                = ipq6018_pcie_pcs_tbl,
+       .pcs_tbl_num            = ARRAY_SIZE(ipq6018_pcie_pcs_tbl),
+       .clk_list               = ipq8074_pciephy_clk_l,
+       .num_clks               = ARRAY_SIZE(ipq8074_pciephy_clk_l),
+       .reset_list             = ipq8074_pciephy_reset_l,
+       .num_resets             = ARRAY_SIZE(ipq8074_pciephy_reset_l),
+       .vreg_list              = NULL,
+       .num_vregs              = 0,
+       .regs                   = ipq_pciephy_gen3_regs_layout,
+
+       .start_ctrl             = SERDES_START | PCS_START,
+       .pwrdn_ctrl             = SW_PWRDN | REFCLK_DRV_DSBL,
 
        .has_phy_com_ctrl       = false,
        .has_lane_rst           = false,
@@ -2768,6 +3015,7 @@ static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = {
 
        .start_ctrl             = PCS_START | SERDES_START,
        .pwrdn_ctrl             = SW_PWRDN | REFCLK_DRV_DSBL,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = 995,          /* us */
@@ -2796,6 +3044,7 @@ static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = {
 
        .start_ctrl             = PCS_START | SERDES_START,
        .pwrdn_ctrl             = SW_PWRDN | REFCLK_DRV_DSBL,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = 995,          /* us */
@@ -2834,6 +3083,7 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = {
 
        .start_ctrl             = PCS_START | SERDES_START,
        .pwrdn_ctrl             = SW_PWRDN | REFCLK_DRV_DSBL,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = 995,          /* us */
@@ -2872,6 +3122,7 @@ static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = {
 
        .start_ctrl             = PCS_START | SERDES_START,
        .pwrdn_ctrl             = SW_PWRDN | REFCLK_DRV_DSBL,
+       .phy_status             = PHYSTATUS,
 
        .is_dual_lane_phy       = true,
        .has_pwrdn_delay        = true,
@@ -2901,6 +3152,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
@@ -2932,6 +3184,7 @@ static const struct qmp_phy_cfg sc7180_usb3phy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
@@ -3003,6 +3256,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
@@ -3029,6 +3283,7 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
 
        .start_ctrl             = SERDES_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .is_dual_lane_phy       = true,
        .no_pcs_sw_reset        = true,
@@ -3056,6 +3311,7 @@ static const struct qmp_phy_cfg msm8998_pciephy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN | REFCLK_DRV_DSBL,
+       .phy_status             = PHYSTATUS,
 };
 
 static const struct qmp_phy_cfg msm8998_usb3phy_cfg = {
@@ -3080,6 +3336,7 @@ static const struct qmp_phy_cfg msm8998_usb3phy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .is_dual_lane_phy       = true,
 };
@@ -3104,6 +3361,7 @@ static const struct qmp_phy_cfg sm8150_ufsphy_cfg = {
 
        .start_ctrl             = SERDES_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .is_dual_lane_phy       = true,
 };
@@ -3130,6 +3388,8 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
+
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
@@ -3161,6 +3421,7 @@ static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
@@ -3189,6 +3450,7 @@ static const struct qmp_phy_cfg sm8250_usb3phy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
@@ -3220,6 +3482,7 @@ static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
@@ -3288,12 +3551,45 @@ static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
        .pwrdn_delay_max        = POWER_DOWN_DELAY_US_MAX,
 };
 
+static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = {
+       .type = PHY_TYPE_PCIE,
+       .nlanes = 2,
+
+       .serdes_tbl             = sdx55_qmp_pcie_serdes_tbl,
+       .serdes_tbl_num         = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl),
+       .tx_tbl                 = sdx55_qmp_pcie_tx_tbl,
+       .tx_tbl_num             = ARRAY_SIZE(sdx55_qmp_pcie_tx_tbl),
+       .rx_tbl                 = sdx55_qmp_pcie_rx_tbl,
+       .rx_tbl_num             = ARRAY_SIZE(sdx55_qmp_pcie_rx_tbl),
+       .pcs_tbl                = sdx55_qmp_pcie_pcs_tbl,
+       .pcs_tbl_num            = ARRAY_SIZE(sdx55_qmp_pcie_pcs_tbl),
+       .pcs_misc_tbl           = sdx55_qmp_pcie_pcs_misc_tbl,
+       .pcs_misc_tbl_num       = ARRAY_SIZE(sdx55_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,
+       .phy_status             = PHYSTATUS_4_20,
+
+       .is_dual_lane_phy       = true,
+       .has_pwrdn_delay        = true,
+       .pwrdn_delay_min        = 995,          /* us */
+       .pwrdn_delay_max        = 1005,         /* us */
+};
+
 static const struct qmp_phy_cfg sm8350_ufsphy_cfg = {
        .type                   = PHY_TYPE_UFS,
        .nlanes                 = 2,
@@ -3314,6 +3610,7 @@ static const struct qmp_phy_cfg sm8350_ufsphy_cfg = {
 
        .start_ctrl             = SERDES_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .is_dual_lane_phy       = true,
 };
@@ -3340,6 +3637,7 @@ static const struct qmp_phy_cfg sm8350_usb3phy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
@@ -3371,6 +3669,7 @@ static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = {
 
        .start_ctrl             = SERDES_START | PCS_START,
        .pwrdn_ctrl             = SW_PWRDN,
+       .phy_status             = PHYSTATUS,
 
        .has_pwrdn_delay        = true,
        .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
@@ -3993,10 +4292,8 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy)
        }
 
        ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
-       if (ret) {
-               dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
+       if (ret)
                goto err_rst;
-       }
 
        if (cfg->has_phy_dp_com_ctrl) {
                qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL,
@@ -4238,7 +4535,7 @@ static int qcom_qmp_phy_power_on(struct phy *phy)
                        ready = PCS_READY;
                } else {
                        status = pcs + cfg->regs[QPHY_PCS_STATUS];
-                       mask = PHYSTATUS;
+                       mask = cfg->phy_status;
                        ready = 0;
                }
 
@@ -4430,10 +4727,8 @@ static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev)
        }
 
        ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
-       if (ret) {
-               dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
+       if (ret)
                return ret;
-       }
 
        ret = clk_prepare_enable(qphy->pipe_clk);
        if (ret) {
@@ -4928,6 +5223,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
                .compatible = "qcom,ipq8074-qmp-pcie-phy",
                .data = &ipq8074_pciephy_cfg,
        }, {
+               .compatible = "qcom,ipq6018-qmp-pcie-phy",
+               .data = &ipq6018_pciephy_cfg,
+       }, {
                .compatible = "qcom,sc7180-qmp-usb3-phy",
                .data = &sc7180_usb3phy_cfg,
        }, {
@@ -4991,6 +5289,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
                .compatible = "qcom,sm8250-qmp-modem-pcie-phy",
                .data = &sm8250_qmp_gen3x2_pciephy_cfg,
        }, {
+               .compatible = "qcom,sdx55-qmp-pcie-phy",
+               .data = &sdx55_qmp_pciephy_cfg,
+       }, {
                .compatible = "qcom,sdx55-qmp-usb3-uni-phy",
                .data = &sdx55_usb3_uniphy_cfg,
        }, {
index 67bd2dd..6592b58 100644 (file)
@@ -6,6 +6,138 @@
 #ifndef QCOM_PHY_QMP_H_
 #define QCOM_PHY_QMP_H_
 
+/* QMP V2 PHY for PCIE gen3 ports - QSERDES PLL registers */
+
+#define QSERDES_PLL_BG_TIMER                           0x00c
+#define QSERDES_PLL_SSC_PER1                           0x01c
+#define QSERDES_PLL_SSC_PER2                           0x020
+#define QSERDES_PLL_SSC_STEP_SIZE1_MODE0               0x024
+#define QSERDES_PLL_SSC_STEP_SIZE2_MODE0               0x028
+#define QSERDES_PLL_SSC_STEP_SIZE1_MODE1               0x02c
+#define QSERDES_PLL_SSC_STEP_SIZE2_MODE1               0x030
+#define QSERDES_PLL_BIAS_EN_CLKBUFLR_EN                        0x03c
+#define QSERDES_PLL_CLK_ENABLE1                                0x040
+#define QSERDES_PLL_SYS_CLK_CTRL                       0x044
+#define QSERDES_PLL_SYSCLK_BUF_ENABLE                  0x048
+#define QSERDES_PLL_PLL_IVCO                           0x050
+#define QSERDES_PLL_LOCK_CMP1_MODE0                    0x054
+#define QSERDES_PLL_LOCK_CMP2_MODE0                    0x058
+#define QSERDES_PLL_LOCK_CMP1_MODE1                    0x060
+#define QSERDES_PLL_LOCK_CMP2_MODE1                    0x064
+#define QSERDES_PLL_BG_TRIM                            0x074
+#define QSERDES_PLL_CLK_EP_DIV_MODE0                   0x078
+#define QSERDES_PLL_CLK_EP_DIV_MODE1                   0x07c
+#define QSERDES_PLL_CP_CTRL_MODE0                      0x080
+#define QSERDES_PLL_CP_CTRL_MODE1                      0x084
+#define QSERDES_PLL_PLL_RCTRL_MODE0                    0x088
+#define QSERDES_PLL_PLL_RCTRL_MODE1                    0x08C
+#define QSERDES_PLL_PLL_CCTRL_MODE0                    0x090
+#define QSERDES_PLL_PLL_CCTRL_MODE1                    0x094
+#define QSERDES_PLL_BIAS_EN_CTRL_BY_PSM                        0x0a4
+#define QSERDES_PLL_SYSCLK_EN_SEL                      0x0a8
+#define QSERDES_PLL_RESETSM_CNTRL                      0x0b0
+#define QSERDES_PLL_LOCK_CMP_EN                                0x0c4
+#define QSERDES_PLL_DEC_START_MODE0                    0x0cc
+#define QSERDES_PLL_DEC_START_MODE1                    0x0d0
+#define QSERDES_PLL_DIV_FRAC_START1_MODE0              0x0d8
+#define QSERDES_PLL_DIV_FRAC_START2_MODE0              0x0dc
+#define QSERDES_PLL_DIV_FRAC_START3_MODE0              0x0e0
+#define QSERDES_PLL_DIV_FRAC_START1_MODE1              0x0e4
+#define QSERDES_PLL_DIV_FRAC_START2_MODE1              0x0e8
+#define QSERDES_PLL_DIV_FRAC_START3_MODE1              0x0eC
+#define QSERDES_PLL_INTEGLOOP_GAIN0_MODE0              0x100
+#define QSERDES_PLL_INTEGLOOP_GAIN1_MODE0              0x104
+#define QSERDES_PLL_INTEGLOOP_GAIN0_MODE1              0x108
+#define QSERDES_PLL_INTEGLOOP_GAIN1_MODE1              0x10c
+#define QSERDES_PLL_VCO_TUNE_MAP                       0x120
+#define QSERDES_PLL_VCO_TUNE1_MODE0                    0x124
+#define QSERDES_PLL_VCO_TUNE2_MODE0                    0x128
+#define QSERDES_PLL_VCO_TUNE1_MODE1                    0x12c
+#define QSERDES_PLL_VCO_TUNE2_MODE1                    0x130
+#define QSERDES_PLL_VCO_TUNE_TIMER1                    0x13c
+#define QSERDES_PLL_VCO_TUNE_TIMER2                    0x140
+#define QSERDES_PLL_CLK_SELECT                         0x16c
+#define QSERDES_PLL_HSCLK_SEL                          0x170
+#define QSERDES_PLL_CORECLK_DIV                                0x17c
+#define QSERDES_PLL_CORE_CLK_EN                                0x184
+#define QSERDES_PLL_CMN_CONFIG                         0x18c
+#define QSERDES_PLL_SVS_MODE_CLK_SEL                   0x194
+#define QSERDES_PLL_CORECLK_DIV_MODE1                  0x1b4
+
+/* QMP V2 PHY for PCIE gen3 ports - QSERDES TX registers */
+
+#define QSERDES_TX0_RES_CODE_LANE_OFFSET_TX            0x03c
+#define QSERDES_TX0_HIGHZ_DRVR_EN                      0x058
+#define QSERDES_TX0_LANE_MODE_1                                0x084
+#define QSERDES_TX0_RCV_DETECT_LVL_2                   0x09c
+
+/* QMP V2 PHY for PCIE gen3 ports - QSERDES RX registers */
+
+#define QSERDES_RX0_UCDR_FO_GAIN                       0x008
+#define QSERDES_RX0_UCDR_SO_GAIN                       0x014
+#define QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE      0x034
+#define QSERDES_RX0_UCDR_PI_CONTROLS                   0x044
+#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2              0x0ec
+#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3              0x0f0
+#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4              0x0f4
+#define QSERDES_RX0_RX_IDAC_TSETTLE_LOW                        0x0f8
+#define QSERDES_RX0_RX_IDAC_TSETTLE_HIGH               0x0fc
+#define QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1                0x110
+#define QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2           0x114
+#define QSERDES_RX0_SIGDET_ENABLES                     0x118
+#define QSERDES_RX0_SIGDET_CNTRL                       0x11c
+#define QSERDES_RX0_SIGDET_DEGLITCH_CNTRL              0x124
+#define QSERDES_RX0_RX_MODE_00_LOW                     0x170
+#define QSERDES_RX0_RX_MODE_00_HIGH                    0x174
+#define QSERDES_RX0_RX_MODE_00_HIGH2                   0x178
+#define QSERDES_RX0_RX_MODE_00_HIGH3                   0x17c
+#define QSERDES_RX0_RX_MODE_00_HIGH4                   0x180
+#define QSERDES_RX0_RX_MODE_01_LOW                     0x184
+#define QSERDES_RX0_RX_MODE_01_HIGH                    0x188
+#define QSERDES_RX0_RX_MODE_01_HIGH2                   0x18c
+#define QSERDES_RX0_RX_MODE_01_HIGH3                   0x190
+#define QSERDES_RX0_RX_MODE_01_HIGH4                   0x194
+#define QSERDES_RX0_RX_MODE_10_LOW                     0x198
+#define QSERDES_RX0_RX_MODE_10_HIGH                    0x19c
+#define QSERDES_RX0_RX_MODE_10_HIGH2                   0x1a0
+#define QSERDES_RX0_RX_MODE_10_HIGH3                   0x1a4
+#define QSERDES_RX0_RX_MODE_10_HIGH4                   0x1a8
+#define QSERDES_RX0_DFE_EN_TIMER                       0x1b4
+
+/* QMP V2 PHY for PCIE gen3 ports - PCS registers */
+
+#define PCS_COM_FLL_CNTRL1                             0x098
+#define PCS_COM_FLL_CNTRL2                             0x09c
+#define PCS_COM_FLL_CNT_VAL_L                          0x0a0
+#define PCS_COM_FLL_CNT_VAL_H_TOL                      0x0a4
+#define PCS_COM_FLL_MAN_CODE                           0x0a8
+#define PCS_COM_REFGEN_REQ_CONFIG1                     0x0dc
+#define PCS_COM_G12S1_TXDEEMPH_M3P5DB                  0x16c
+#define PCS_COM_RX_SIGDET_LVL                          0x188
+#define PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L          0x1a4
+#define PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_H          0x1a8
+#define PCS_COM_RX_DCC_CAL_CONFIG                      0x1d8
+#define PCS_COM_EQ_CONFIG5                             0x1ec
+
+/* QMP V2 PHY for PCIE gen3 ports - PCS Misc registers */
+
+#define PCS_PCIE_POWER_STATE_CONFIG2                   0x40c
+#define PCS_PCIE_POWER_STATE_CONFIG4                   0x414
+#define PCS_PCIE_ENDPOINT_REFCLK_DRIVE                 0x41c
+#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L         0x440
+#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H         0x444
+#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L         0x448
+#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H         0x44c
+#define PCS_PCIE_OSC_DTCT_CONFIG2                      0x45c
+#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG2                        0x478
+#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG4                        0x480
+#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG5                        0x484
+#define PCS_PCIE_OSC_DTCT_ACTIONS                      0x490
+#define PCS_PCIE_EQ_CONFIG1                            0x4a0
+#define PCS_PCIE_EQ_CONFIG2                            0x4a4
+#define PCS_PCIE_PRESET_P10_PRE                                0x4bc
+#define PCS_PCIE_PRESET_P10_POST                       0x4e0
+
 /* Only for QMP V2 PHY - QSERDES COM registers */
 #define QSERDES_COM_BG_TIMER                           0x00c
 #define QSERDES_COM_SSC_EN_CENTER                      0x010
 #define QSERDES_V4_COM_SYSCLK_EN_SEL                   0x094
 #define QSERDES_V4_COM_RESETSM_CNTRL                   0x09c
 #define QSERDES_V4_COM_LOCK_CMP_EN                     0x0a4
+#define QSERDES_V4_COM_LOCK_CMP_CFG                    0x0a8
 #define QSERDES_V4_COM_LOCK_CMP1_MODE0                 0x0ac
 #define QSERDES_V4_COM_LOCK_CMP2_MODE0                 0x0b0
 #define QSERDES_V4_COM_LOCK_CMP1_MODE1                 0x0b4
 #define QSERDES_V4_COM_DIV_FRAC_START3_MODE1           0x0e0
 #define QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0           0x0ec
 #define QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0           0x0f0
+#define QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1           0x0f4
+#define QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1           0x0f8
 #define QSERDES_V4_COM_VCO_TUNE_CTRL                   0x108
 #define QSERDES_V4_COM_VCO_TUNE_MAP                    0x10c
 #define QSERDES_V4_COM_VCO_TUNE1_MODE0                 0x110
 #define QSERDES_V4_COM_C_READY_STATUS                  0x178
 #define QSERDES_V4_COM_CMN_CONFIG                      0x17c
 #define QSERDES_V4_COM_SVS_MODE_CLK_SEL                        0x184
+#define QSERDES_V4_COM_CMN_MISC1                       0x19c
+#define QSERDES_V4_COM_INTERNAL_DIG_CORECLK_DIV                0x1a0
+#define QSERDES_V4_COM_CMN_MODE                                0x1a4
+#define QSERDES_V4_COM_VCO_DC_LEVEL_CTRL               0x1a8
 #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0      0x1ac
 #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0      0x1b0
 #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1      0x1b4
-#define QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL            0x1bc
 #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1      0x1b8
+#define QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL            0x1bc
 
 /* Only for QMP V4 PHY - TX registers */
 #define QSERDES_V4_TX_CLKBUF_ENABLE                    0x08
 #define QSERDES_V4_TX_VMODE_CTRL1                      0xe8
 #define QSERDES_V4_TX_PI_QEC_CTRL                      0x104
 
+/* Only for QMP V4_20 PHY - TX registers */
+#define QSERDES_V4_20_TX_LANE_MODE_1                   0x88
+#define QSERDES_V4_20_TX_LANE_MODE_2                   0x8c
+#define QSERDES_V4_20_TX_LANE_MODE_3                   0x90
+#define QSERDES_V4_20_TX_VMODE_CTRL1                   0xc4
+#define QSERDES_V4_20_TX_PI_QEC_CTRL                   0xe0
+
 /* Only for QMP V4 PHY - RX registers */
 #define QSERDES_V4_RX_UCDR_FO_GAIN                     0x008
 #define QSERDES_V4_RX_UCDR_SO_GAIN                     0x014
 #define QSERDES_V4_DP_PHY_AUX_INTERRUPT_STATUS         0x0d8
 #define QSERDES_V4_DP_PHY_STATUS                       0x0dc
 
+/* Only for QMP V4_20 PHY - RX registers */
+#define QSERDES_V4_20_RX_FO_GAIN_RATE2                 0x008
+#define QSERDES_V4_20_RX_UCDR_PI_CONTROLS              0x058
+#define QSERDES_V4_20_RX_AUX_DATA_TCOARSE_TFINE                0x0ac
+#define QSERDES_V4_20_RX_DFE_3                         0x110
+#define QSERDES_V4_20_RX_DFE_DAC_ENABLE1               0x134
+#define QSERDES_V4_20_RX_DFE_DAC_ENABLE2               0x138
+#define QSERDES_V4_20_RX_VGA_CAL_CNTRL2                        0x150
+#define QSERDES_V4_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1   0x178
+#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B1           0x1c8
+#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B2           0x1cc
+#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B3           0x1d0
+#define QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B4           0x1d4
+#define QSERDES_V4_20_RX_RX_MODE_RATE2_B0              0x1d8
+#define QSERDES_V4_20_RX_RX_MODE_RATE2_B1              0x1dc
+#define QSERDES_V4_20_RX_RX_MODE_RATE2_B2              0x1e0
+#define QSERDES_V4_20_RX_RX_MODE_RATE2_B3              0x1e4
+#define QSERDES_V4_20_RX_RX_MODE_RATE2_B4              0x1e8
+#define QSERDES_V4_20_RX_RX_MODE_RATE3_B0              0x1ec
+#define QSERDES_V4_20_RX_RX_MODE_RATE3_B1              0x1f0
+#define QSERDES_V4_20_RX_RX_MODE_RATE3_B2              0x1f4
+#define QSERDES_V4_20_RX_RX_MODE_RATE3_B3              0x1f8
+#define QSERDES_V4_20_RX_RX_MODE_RATE3_B4              0x1fc
+#define QSERDES_V4_20_RX_PHPRE_CTRL                    0x200
+#define QSERDES_V4_20_RX_DFE_CTLE_POST_CAL_OFFSET      0x20c
+#define QSERDES_V4_20_RX_MARG_COARSE_CTRL2             0x23c
+
 /* Only for QMP V4 PHY - UFS PCS registers */
 #define QPHY_V4_PCS_UFS_PHY_START                              0x000
 #define QPHY_V4_PCS_UFS_POWER_DOWN_CONTROL                     0x004
 #define QPHY_V4_PCS_USB3_SIGDET_STARTUP_TIMER_VAL      0x354
 #define QPHY_V4_PCS_USB3_TEST_CONTROL                  0x358
 
+/* Only for QMP V4_20 PHY - USB/PCIe PCS registers */
+#define QPHY_V4_20_PCS_RX_SIGDET_LVL                   0x188
+#define QPHY_V4_20_PCS_EQ_CONFIG2                      0x1d8
+#define QPHY_V4_20_PCS_EQ_CONFIG4                      0x1e0
+#define QPHY_V4_20_PCS_EQ_CONFIG5                      0x1e4
+
 /* Only for QMP V4 PHY - UNI has 0x300 offset for PCS_USB3 regs */
 #define QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL   0x618
 #define QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2  0x638
 #define QPHY_V4_PCS_PCIE_PRESET_P10_PRE                        0xbc
 #define QPHY_V4_PCS_PCIE_PRESET_P10_POST               0xe0
 
+#define QPHY_V4_20_PCS_PCIE_EQ_CONFIG1                 0x0a0
+#define QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME           0x0f0
+#define QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME           0x0f4
+#define QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2              0x0fc
+#define QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5              0x108
+#define QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2            0x824
+#define QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2            0x828
+
 /* Only for QMP V5 PHY - QSERDES COM registers */
 #define QSERDES_V5_COM_PLL_IVCO                                0x058
 #define QSERDES_V5_COM_CP_CTRL_MODE0                   0x074
index ecc309b..c2373b3 100644 (file)
@@ -4,7 +4,7 @@
 #
 config PHY_MT7621_PCI
        tristate "MediaTek MT7621 PCI PHY Driver"
-       depends on RALINK && OF
+       depends on (RALINK && OF) || COMPILE_TEST
        select GENERIC_PHY
        select REGMAP_MMIO
        help
index 2a9465f..5e6530f 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <dt-bindings/phy/phy.h>
+#include <linux/clk.h>
 #include <linux/bitfield.h>
 #include <linux/bitops.h>
 #include <linux/module.h>
@@ -14,8 +15,6 @@
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/sys_soc.h>
-#include <mt7621.h>
-#include <ralink_regs.h>
 
 #define RG_PE1_PIPE_REG                                0x02c
 #define RG_PE1_PIPE_RST                                BIT(12)
@@ -62,8 +61,6 @@
 
 #define RG_PE1_FRC_MSTCKDIV                    BIT(5)
 
-#define XTAL_MASK                              GENMASK(8, 6)
-
 #define MAX_PHYS       2
 
 /**
@@ -71,6 +68,7 @@
  * @dev: pointer to device
  * @regmap: kernel regmap pointer
  * @phy: pointer to the kernel PHY device
+ * @sys_clk: pointer to the system XTAL clock
  * @port_base: base register
  * @has_dual_port: if the phy has dual ports.
  * @bypass_pipe_rst: mark if 'mt7621_bypass_pipe_rst'
@@ -80,6 +78,7 @@ struct mt7621_pci_phy {
        struct device *dev;
        struct regmap *regmap;
        struct phy *phy;
+       struct clk *sys_clk;
        void __iomem *port_base;
        bool has_dual_port;
        bool bypass_pipe_rst;
@@ -116,12 +115,14 @@ static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy)
        }
 }
 
-static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy)
+static int mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy)
 {
        struct device *dev = phy->dev;
-       u32 xtal_mode;
+       unsigned long clk_rate;
 
-       xtal_mode = FIELD_GET(XTAL_MASK, rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0));
+       clk_rate = clk_get_rate(phy->sys_clk);
+       if (!clk_rate)
+               return -EINVAL;
 
        /* Set PCIe Port PHY to disable SSC */
        /* Debug Xtal Type */
@@ -139,13 +140,13 @@ static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy)
                               RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
        }
 
-       if (xtal_mode <= 5 && xtal_mode >= 3) { /* 40MHz Xtal */
+       if (clk_rate == 40000000) { /* 40MHz Xtal */
                /* Set Pre-divider ratio (for host mode) */
                mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV,
                               FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x01));
 
                dev_dbg(dev, "Xtal is 40MHz\n");
-       } else if (xtal_mode >= 6) { /* 25MHz Xal */
+       } else if (clk_rate == 25000000) { /* 25MHz Xal */
                mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV,
                               FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x00));
 
@@ -196,13 +197,15 @@ static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy)
        mt7621_phy_rmw(phy, RG_PE1_H_PLL_BR_REG, RG_PE1_H_PLL_BR,
                       FIELD_PREP(RG_PE1_H_PLL_BR, 0x00));
 
-       if (xtal_mode <= 5 && xtal_mode >= 3) { /* 40MHz Xtal */
+       if (clk_rate == 40000000) { /* 40MHz Xtal */
                /* set force mode enable of da_pe1_mstckdiv */
                mt7621_phy_rmw(phy, RG_PE1_MSTCKDIV_REG,
                               RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV,
                               FIELD_PREP(RG_PE1_MSTCKDIV, 0x01) |
                               RG_PE1_FRC_MSTCKDIV);
        }
+
+       return 0;
 }
 
 static int mt7621_pci_phy_init(struct phy *phy)
@@ -212,9 +215,7 @@ static int mt7621_pci_phy_init(struct phy *phy)
        if (mphy->bypass_pipe_rst)
                mt7621_bypass_pipe_rst(mphy);
 
-       mt7621_set_phy_for_ssc(mphy);
-
-       return 0;
+       return mt7621_set_phy_for_ssc(mphy);
 }
 
 static int mt7621_pci_phy_power_on(struct phy *phy)
@@ -272,8 +273,8 @@ static struct phy *mt7621_pcie_phy_of_xlate(struct device *dev,
 
        mt7621_phy->has_dual_port = args->args[0];
 
-       dev_info(dev, "PHY for 0x%08x (dual port = %d)\n",
-                (unsigned int)mt7621_phy->port_base, mt7621_phy->has_dual_port);
+       dev_dbg(dev, "PHY for 0x%px (dual port = %d)\n",
+               mt7621_phy->port_base, mt7621_phy->has_dual_port);
 
        return mt7621_phy->phy;
 }
@@ -324,6 +325,12 @@ static int mt7621_pci_phy_probe(struct platform_device *pdev)
                return PTR_ERR(phy->phy);
        }
 
+       phy->sys_clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(phy->sys_clk)) {
+               dev_err(dev, "failed to get phy clock\n");
+               return PTR_ERR(phy->sys_clk);
+       }
+
        phy_set_drvdata(phy->phy, phy);
 
        provider = devm_of_phy_provider_register(dev, mt7621_pcie_phy_of_xlate);
index 159285f..e812ada 100644 (file)
@@ -48,6 +48,15 @@ config PHY_ROCKCHIP_INNO_USB2
        help
          Support for Rockchip USB2.0 PHY with Innosilicon IP block.
 
+config PHY_ROCKCHIP_INNO_CSIDPHY
+       tristate "Rockchip Innosilicon MIPI CSI PHY driver"
+       depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
+       select GENERIC_PHY
+       select GENERIC_PHY_MIPI_DPHY
+       help
+         Enable this to support the Rockchip MIPI CSI PHY with
+         Innosilicon IP block.
+
 config PHY_ROCKCHIP_INNO_DSIDPHY
        tristate "Rockchip Innosilicon MIPI/LVDS/TTL PHY driver"
        depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
index c3cfc7f..f0eec21 100644 (file)
@@ -2,6 +2,7 @@
 obj-$(CONFIG_PHY_ROCKCHIP_DP)          += phy-rockchip-dp.o
 obj-$(CONFIG_PHY_ROCKCHIP_DPHY_RX0)     += phy-rockchip-dphy-rx0.o
 obj-$(CONFIG_PHY_ROCKCHIP_EMMC)                += phy-rockchip-emmc.o
+obj-$(CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY)        += phy-rockchip-inno-csidphy.o
 obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY)        += phy-rockchip-inno-dsidphy.o
 obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI)   += phy-rockchip-inno-hdmi.o
 obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2)   += phy-rockchip-inno-usb2.o
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c
new file mode 100644 (file)
index 0000000..ca13a60
--- /dev/null
@@ -0,0 +1,459 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip MIPI RX Innosilicon DPHY driver
+ *
+ * Copyright (C) 2021 Fuzhou Rockchip Electronics Co., Ltd.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-mipi-dphy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+/* GRF */
+#define RK1808_GRF_PD_VI_CON_OFFSET    0x0430
+
+#define RK3326_GRF_PD_VI_CON_OFFSET    0x0430
+
+#define RK3368_GRF_SOC_CON6_OFFSET     0x0418
+
+/* PHY */
+#define CSIDPHY_CTRL_LANE_ENABLE               0x00
+#define CSIDPHY_CTRL_LANE_ENABLE_CK            BIT(6)
+#define CSIDPHY_CTRL_LANE_ENABLE_MASK          GENMASK(5, 2)
+#define CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED     BIT(0)
+
+/* not present on all variants */
+#define CSIDPHY_CTRL_PWRCTL                    0x04
+#define CSIDPHY_CTRL_PWRCTL_UNDEFINED          GENMASK(7, 5)
+#define CSIDPHY_CTRL_PWRCTL_SYNCRST            BIT(2)
+#define CSIDPHY_CTRL_PWRCTL_LDO_PD             BIT(1)
+#define CSIDPHY_CTRL_PWRCTL_PLL_PD             BIT(0)
+
+#define CSIDPHY_CTRL_DIG_RST                   0x80
+#define CSIDPHY_CTRL_DIG_RST_UNDEFINED         0x1e
+#define CSIDPHY_CTRL_DIG_RST_RESET             BIT(0)
+
+/* offset after ths_settle_offset */
+#define CSIDPHY_CLK_THS_SETTLE                 0
+#define CSIDPHY_LANE_THS_SETTLE(n)             (((n) + 1) * 0x80)
+#define CSIDPHY_THS_SETTLE_MASK                        GENMASK(6, 0)
+
+/* offset after calib_offset */
+#define CSIDPHY_CLK_CALIB_EN                   0
+#define CSIDPHY_LANE_CALIB_EN(n)               (((n) + 1) * 0x80)
+#define CSIDPHY_CALIB_EN                       BIT(7)
+
+/* Configure the count time of the THS-SETTLE by protocol. */
+#define RK1808_CSIDPHY_CLK_WR_THS_SETTLE       0x160
+#define RK3326_CSIDPHY_CLK_WR_THS_SETTLE       0x100
+#define RK3368_CSIDPHY_CLK_WR_THS_SETTLE       0x100
+
+/* Calibration reception enable */
+#define RK1808_CSIDPHY_CLK_CALIB_EN            0x168
+
+/*
+ * The higher 16-bit of this register is used for write protection
+ * only if BIT(x + 16) set to 1 the BIT(x) can be written.
+ */
+#define HIWORD_UPDATE(val, mask, shift) \
+               ((val) << (shift) | (mask) << ((shift) + 16))
+
+#define HZ_TO_MHZ(freq)                                div_u64(freq, 1000 * 1000)
+
+enum dphy_reg_id {
+       /* rk1808 & rk3326 */
+       GRF_DPHY_CSIPHY_FORCERXMODE,
+       GRF_DPHY_CSIPHY_CLKLANE_EN,
+       GRF_DPHY_CSIPHY_DATALANE_EN,
+};
+
+struct dphy_reg {
+       u32 offset;
+       u32 mask;
+       u32 shift;
+};
+
+#define PHY_REG(_offset, _width, _shift) \
+       { .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, }
+
+static const struct dphy_reg rk1808_grf_dphy_regs[] = {
+       [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 0),
+       [GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 1, 8),
+       [GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 4),
+};
+
+static const struct dphy_reg rk3326_grf_dphy_regs[] = {
+       [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 4, 0),
+       [GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 1, 8),
+       [GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 4, 4),
+};
+
+static const struct dphy_reg rk3368_grf_dphy_regs[] = {
+       [GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3368_GRF_SOC_CON6_OFFSET, 4, 8),
+};
+
+struct hsfreq_range {
+       u32 range_h;
+       u8 cfg_bit;
+};
+
+struct dphy_drv_data {
+       int pwrctl_offset;
+       int ths_settle_offset;
+       int calib_offset;
+       const struct hsfreq_range *hsfreq_ranges;
+       int num_hsfreq_ranges;
+       const struct dphy_reg *grf_regs;
+};
+
+struct rockchip_inno_csidphy {
+       struct device *dev;
+       void __iomem *phy_base;
+       struct clk *pclk;
+       struct regmap *grf;
+       struct reset_control *rst;
+       const struct dphy_drv_data *drv_data;
+       struct phy_configure_opts_mipi_dphy config;
+       u8 hsfreq;
+};
+
+static inline void write_grf_reg(struct rockchip_inno_csidphy *priv,
+                                int index, u8 value)
+{
+       const struct dphy_drv_data *drv_data = priv->drv_data;
+       const struct dphy_reg *reg = &drv_data->grf_regs[index];
+
+       if (reg->offset)
+               regmap_write(priv->grf, reg->offset,
+                            HIWORD_UPDATE(value, reg->mask, reg->shift));
+}
+
+/* These tables must be sorted by .range_h ascending. */
+static const struct hsfreq_range rk1808_mipidphy_hsfreq_ranges[] = {
+       { 109, 0x02}, { 149, 0x03}, { 199, 0x06}, { 249, 0x06},
+       { 299, 0x06}, { 399, 0x08}, { 499, 0x0b}, { 599, 0x0e},
+       { 699, 0x10}, { 799, 0x12}, { 999, 0x16}, {1199, 0x1e},
+       {1399, 0x23}, {1599, 0x2d}, {1799, 0x32}, {1999, 0x37},
+       {2199, 0x3c}, {2399, 0x41}, {2499, 0x46}
+};
+
+static const struct hsfreq_range rk3326_mipidphy_hsfreq_ranges[] = {
+       { 109, 0x00}, { 149, 0x01}, { 199, 0x02}, { 249, 0x03},
+       { 299, 0x04}, { 399, 0x05}, { 499, 0x06}, { 599, 0x07},
+       { 699, 0x08}, { 799, 0x09}, { 899, 0x0a}, {1099, 0x0b},
+       {1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e}
+};
+
+static const struct hsfreq_range rk3368_mipidphy_hsfreq_ranges[] = {
+       { 109, 0x00}, { 149, 0x01}, { 199, 0x02}, { 249, 0x03},
+       { 299, 0x04}, { 399, 0x05}, { 499, 0x06}, { 599, 0x07},
+       { 699, 0x08}, { 799, 0x09}, { 899, 0x0a}, {1099, 0x0b},
+       {1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e}
+};
+
+static void rockchip_inno_csidphy_ths_settle(struct rockchip_inno_csidphy *priv,
+                                            int hsfreq, int offset)
+{
+       const struct dphy_drv_data *drv_data = priv->drv_data;
+       u32 val;
+
+       val = readl(priv->phy_base + drv_data->ths_settle_offset + offset);
+       val &= ~CSIDPHY_THS_SETTLE_MASK;
+       val |= hsfreq;
+       writel(val, priv->phy_base + drv_data->ths_settle_offset + offset);
+}
+
+static int rockchip_inno_csidphy_configure(struct phy *phy,
+                                          union phy_configure_opts *opts)
+{
+       struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy);
+       const struct dphy_drv_data *drv_data = priv->drv_data;
+       struct phy_configure_opts_mipi_dphy *config = &opts->mipi_dphy;
+       unsigned int hsfreq = 0;
+       unsigned int i;
+       u64 data_rate_mbps;
+       int ret;
+
+       /* pass with phy_mipi_dphy_get_default_config (with pixel rate?) */
+       ret = phy_mipi_dphy_config_validate(config);
+       if (ret)
+               return ret;
+
+       data_rate_mbps = HZ_TO_MHZ(config->hs_clk_rate);
+
+       dev_dbg(priv->dev, "lanes %d - data_rate_mbps %llu\n",
+               config->lanes, data_rate_mbps);
+       for (i = 0; i < drv_data->num_hsfreq_ranges; i++) {
+               if (drv_data->hsfreq_ranges[i].range_h >= data_rate_mbps) {
+                       hsfreq = drv_data->hsfreq_ranges[i].cfg_bit;
+                       break;
+               }
+       }
+       if (!hsfreq)
+               return -EINVAL;
+
+       priv->hsfreq = hsfreq;
+       priv->config = *config;
+       return 0;
+}
+
+static int rockchip_inno_csidphy_power_on(struct phy *phy)
+{
+       struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy);
+       const struct dphy_drv_data *drv_data = priv->drv_data;
+       u64 data_rate_mbps = HZ_TO_MHZ(priv->config.hs_clk_rate);
+       u32 val;
+       int ret, i;
+
+       ret = clk_enable(priv->pclk);
+       if (ret < 0)
+               return ret;
+
+       ret = pm_runtime_resume_and_get(priv->dev);
+       if (ret < 0) {
+               clk_disable(priv->pclk);
+               return ret;
+       }
+
+       /* phy start */
+       if (drv_data->pwrctl_offset >= 0)
+               writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED |
+                      CSIDPHY_CTRL_PWRCTL_SYNCRST,
+                      priv->phy_base + drv_data->pwrctl_offset);
+
+       /* set data lane num and enable clock lane */
+       val = FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_MASK, GENMASK(priv->config.lanes - 1, 0)) |
+             FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_CK, 1) |
+             FIELD_PREP(CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED, 1);
+       writel(val, priv->phy_base + CSIDPHY_CTRL_LANE_ENABLE);
+
+       /* Reset dphy analog part */
+       if (drv_data->pwrctl_offset >= 0)
+               writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED,
+                      priv->phy_base + drv_data->pwrctl_offset);
+       usleep_range(500, 1000);
+
+       /* Reset dphy digital part */
+       writel(CSIDPHY_CTRL_DIG_RST_UNDEFINED,
+              priv->phy_base + CSIDPHY_CTRL_DIG_RST);
+       writel(CSIDPHY_CTRL_DIG_RST_UNDEFINED + CSIDPHY_CTRL_DIG_RST_RESET,
+              priv->phy_base + CSIDPHY_CTRL_DIG_RST);
+
+       /* not into receive mode/wait stopstate */
+       write_grf_reg(priv, GRF_DPHY_CSIPHY_FORCERXMODE, 0x0);
+
+       /* enable calibration */
+       if (data_rate_mbps > 1500 && drv_data->calib_offset >= 0) {
+               writel(CSIDPHY_CALIB_EN,
+                      priv->phy_base + drv_data->calib_offset +
+                                       CSIDPHY_CLK_CALIB_EN);
+               for (i = 0; i < priv->config.lanes; i++)
+                       writel(CSIDPHY_CALIB_EN,
+                              priv->phy_base + drv_data->calib_offset +
+                                               CSIDPHY_LANE_CALIB_EN(i));
+       }
+
+       rockchip_inno_csidphy_ths_settle(priv, priv->hsfreq,
+                                        CSIDPHY_CLK_THS_SETTLE);
+       for (i = 0; i < priv->config.lanes; i++)
+               rockchip_inno_csidphy_ths_settle(priv, priv->hsfreq,
+                                                CSIDPHY_LANE_THS_SETTLE(i));
+
+       write_grf_reg(priv, GRF_DPHY_CSIPHY_CLKLANE_EN, 0x1);
+       write_grf_reg(priv, GRF_DPHY_CSIPHY_DATALANE_EN,
+                     GENMASK(priv->config.lanes - 1, 0));
+
+       return 0;
+}
+
+static int rockchip_inno_csidphy_power_off(struct phy *phy)
+{
+       struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy);
+       const struct dphy_drv_data *drv_data = priv->drv_data;
+
+       /* disable all lanes */
+       writel(CSIDPHY_CTRL_LANE_ENABLE_UNDEFINED,
+              priv->phy_base + CSIDPHY_CTRL_LANE_ENABLE);
+
+       /* disable pll and ldo */
+       if (drv_data->pwrctl_offset >= 0)
+               writel(CSIDPHY_CTRL_PWRCTL_UNDEFINED |
+                      CSIDPHY_CTRL_PWRCTL_LDO_PD |
+                      CSIDPHY_CTRL_PWRCTL_PLL_PD,
+                      priv->phy_base + drv_data->pwrctl_offset);
+       usleep_range(500, 1000);
+
+       pm_runtime_put(priv->dev);
+       clk_disable(priv->pclk);
+
+       return 0;
+}
+
+static int rockchip_inno_csidphy_init(struct phy *phy)
+{
+       struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy);
+
+       return clk_prepare(priv->pclk);
+}
+
+static int rockchip_inno_csidphy_exit(struct phy *phy)
+{
+       struct rockchip_inno_csidphy *priv = phy_get_drvdata(phy);
+
+       clk_unprepare(priv->pclk);
+
+       return 0;
+}
+
+static const struct phy_ops rockchip_inno_csidphy_ops = {
+       .power_on       = rockchip_inno_csidphy_power_on,
+       .power_off      = rockchip_inno_csidphy_power_off,
+       .init           = rockchip_inno_csidphy_init,
+       .exit           = rockchip_inno_csidphy_exit,
+       .configure      = rockchip_inno_csidphy_configure,
+       .owner          = THIS_MODULE,
+};
+
+static const struct dphy_drv_data rk1808_mipidphy_drv_data = {
+       .pwrctl_offset = -1,
+       .ths_settle_offset = RK1808_CSIDPHY_CLK_WR_THS_SETTLE,
+       .calib_offset = RK1808_CSIDPHY_CLK_CALIB_EN,
+       .hsfreq_ranges = rk1808_mipidphy_hsfreq_ranges,
+       .num_hsfreq_ranges = ARRAY_SIZE(rk1808_mipidphy_hsfreq_ranges),
+       .grf_regs = rk1808_grf_dphy_regs,
+};
+
+static const struct dphy_drv_data rk3326_mipidphy_drv_data = {
+       .pwrctl_offset = CSIDPHY_CTRL_PWRCTL,
+       .ths_settle_offset = RK3326_CSIDPHY_CLK_WR_THS_SETTLE,
+       .calib_offset = -1,
+       .hsfreq_ranges = rk3326_mipidphy_hsfreq_ranges,
+       .num_hsfreq_ranges = ARRAY_SIZE(rk3326_mipidphy_hsfreq_ranges),
+       .grf_regs = rk3326_grf_dphy_regs,
+};
+
+static const struct dphy_drv_data rk3368_mipidphy_drv_data = {
+       .pwrctl_offset = CSIDPHY_CTRL_PWRCTL,
+       .ths_settle_offset = RK3368_CSIDPHY_CLK_WR_THS_SETTLE,
+       .calib_offset = -1,
+       .hsfreq_ranges = rk3368_mipidphy_hsfreq_ranges,
+       .num_hsfreq_ranges = ARRAY_SIZE(rk3368_mipidphy_hsfreq_ranges),
+       .grf_regs = rk3368_grf_dphy_regs,
+};
+
+static const struct of_device_id rockchip_inno_csidphy_match_id[] = {
+       {
+               .compatible = "rockchip,px30-csi-dphy",
+               .data = &rk3326_mipidphy_drv_data,
+       },
+       {
+               .compatible = "rockchip,rk1808-csi-dphy",
+               .data = &rk1808_mipidphy_drv_data,
+       },
+       {
+               .compatible = "rockchip,rk3326-csi-dphy",
+               .data = &rk3326_mipidphy_drv_data,
+       },
+       {
+               .compatible = "rockchip,rk3368-csi-dphy",
+               .data = &rk3368_mipidphy_drv_data,
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(of, rockchip_inno_csidphy_match_id);
+
+static int rockchip_inno_csidphy_probe(struct platform_device *pdev)
+{
+       struct rockchip_inno_csidphy *priv;
+       struct device *dev = &pdev->dev;
+       struct phy_provider *phy_provider;
+       struct phy *phy;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->dev = dev;
+       platform_set_drvdata(pdev, priv);
+
+       priv->drv_data = of_device_get_match_data(dev);
+       if (!priv->drv_data) {
+               dev_err(dev, "Can't find device data\n");
+               return -ENODEV;
+       }
+
+       priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                                   "rockchip,grf");
+       if (IS_ERR(priv->grf)) {
+               dev_err(dev, "Can't find GRF syscon\n");
+               return PTR_ERR(priv->grf);
+       }
+
+       priv->phy_base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(priv->phy_base))
+               return PTR_ERR(priv->phy_base);
+
+       priv->pclk = devm_clk_get(dev, "pclk");
+       if (IS_ERR(priv->pclk)) {
+               dev_err(dev, "failed to get pclk\n");
+               return PTR_ERR(priv->pclk);
+       }
+
+       priv->rst = devm_reset_control_get(dev, "apb");
+       if (IS_ERR(priv->rst)) {
+               dev_err(dev, "failed to get system reset control\n");
+               return PTR_ERR(priv->rst);
+       }
+
+       phy = devm_phy_create(dev, NULL, &rockchip_inno_csidphy_ops);
+       if (IS_ERR(phy)) {
+               dev_err(dev, "failed to create phy\n");
+               return PTR_ERR(phy);
+       }
+
+       phy_set_drvdata(phy, priv);
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(phy_provider)) {
+               dev_err(dev, "failed to register phy provider\n");
+               return PTR_ERR(phy_provider);
+       }
+
+       pm_runtime_enable(dev);
+
+       return 0;
+}
+
+static int rockchip_inno_csidphy_remove(struct platform_device *pdev)
+{
+       struct rockchip_inno_csidphy *priv = platform_get_drvdata(pdev);
+
+       pm_runtime_disable(priv->dev);
+
+       return 0;
+}
+
+static struct platform_driver rockchip_inno_csidphy_driver = {
+       .driver = {
+               .name = "rockchip-inno-csidphy",
+               .of_match_table = rockchip_inno_csidphy_match_id,
+       },
+       .probe = rockchip_inno_csidphy_probe,
+       .remove = rockchip_inno_csidphy_remove,
+};
+
+module_platform_driver(rockchip_inno_csidphy_driver);
+MODULE_AUTHOR("Heiko Stuebner <heiko.stuebner@theobroma-systems.com>");
+MODULE_DESCRIPTION("Rockchip MIPI Innosilicon CSI-DPHY driver");
+MODULE_LICENSE("GPL v2");
index a37f3f3..80acca4 100644 (file)
@@ -620,7 +620,7 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw,
                                             unsigned long parent_rate)
 {
        struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
-       const struct pre_pll_config *cfg = pre_pll_cfg_table;
+       const struct pre_pll_config *cfg;
        unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
        u32 v;
        int ret;
@@ -774,7 +774,7 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
                                             unsigned long parent_rate)
 {
        struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
-       const struct pre_pll_config *cfg = pre_pll_cfg_table;
+       const struct pre_pll_config *cfg;
        unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
        u32 val;
        int ret;
index 46ebdb1..beacac1 100644 (file)
@@ -1256,6 +1256,49 @@ static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = {
        { /* sentinel */ }
 };
 
+static const struct rockchip_usb2phy_cfg rk3308_phy_cfgs[] = {
+       {
+               .reg = 0x100,
+               .num_ports      = 2,
+               .clkout_ctl     = { 0x108, 4, 4, 1, 0 },
+               .port_cfgs      = {
+                       [USB2PHY_PORT_OTG] = {
+                               .phy_sus        = { 0x0100, 8, 0, 0, 0x1d1 },
+                               .bvalid_det_en  = { 0x3020, 2, 2, 0, 1 },
+                               .bvalid_det_st  = { 0x3024, 2, 2, 0, 1 },
+                               .bvalid_det_clr = { 0x3028, 2, 2, 0, 1 },
+                               .ls_det_en      = { 0x3020, 0, 0, 0, 1 },
+                               .ls_det_st      = { 0x3024, 0, 0, 0, 1 },
+                               .ls_det_clr     = { 0x3028, 0, 0, 0, 1 },
+                               .utmi_avalid    = { 0x0120, 10, 10, 0, 1 },
+                               .utmi_bvalid    = { 0x0120, 9, 9, 0, 1 },
+                               .utmi_ls        = { 0x0120, 5, 4, 0, 1 },
+                       },
+                       [USB2PHY_PORT_HOST] = {
+                               .phy_sus        = { 0x0104, 8, 0, 0, 0x1d1 },
+                               .ls_det_en      = { 0x3020, 1, 1, 0, 1 },
+                               .ls_det_st      = { 0x3024, 1, 1, 0, 1 },
+                               .ls_det_clr     = { 0x3028, 1, 1, 0, 1 },
+                               .utmi_ls        = { 0x0120, 17, 16, 0, 1 },
+                               .utmi_hstdet    = { 0x0120, 19, 19, 0, 1 }
+                       }
+               },
+               .chg_det = {
+                       .opmode         = { 0x0100, 3, 0, 5, 1 },
+                       .cp_det         = { 0x0120, 24, 24, 0, 1 },
+                       .dcp_det        = { 0x0120, 23, 23, 0, 1 },
+                       .dp_det         = { 0x0120, 25, 25, 0, 1 },
+                       .idm_sink_en    = { 0x0108, 8, 8, 0, 1 },
+                       .idp_sink_en    = { 0x0108, 7, 7, 0, 1 },
+                       .idp_src_en     = { 0x0108, 9, 9, 0, 1 },
+                       .rdm_pdwn_en    = { 0x0108, 10, 10, 0, 1 },
+                       .vdm_src_en     = { 0x0108, 12, 12, 0, 1 },
+                       .vdp_src_en     = { 0x0108, 11, 11, 0, 1 },
+               },
+       },
+       { /* sentinel */ }
+};
+
 static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = {
        {
                .reg = 0x100,
@@ -1425,6 +1468,7 @@ static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = {
 static const struct of_device_id rockchip_usb2phy_dt_match[] = {
        { .compatible = "rockchip,px30-usb2phy", .data = &rk3328_phy_cfgs },
        { .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
+       { .compatible = "rockchip,rk3308-usb2phy", .data = &rk3308_phy_cfgs },
        { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
        { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
        { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
index e4adab3..6bdbd1f 100644 (file)
 #define PORT_SEL_1             FIELD_PREP(PORT_SEL_MASK, 1)
 
 #define PCL_PHY_TEST_I         0x2000
-#define PCL_PHY_TEST_O         0x2004
 #define TESTI_DAT_MASK         GENMASK(13, 6)
 #define TESTI_ADR_MASK         GENMASK(5, 1)
 #define TESTI_WR_EN            BIT(0)
 
+#define PCL_PHY_TEST_O         0x2004
+#define TESTO_DAT_MASK         GENMASK(7, 0)
+
 #define PCL_PHY_RESET          0x200c
 #define PCL_PHY_RESET_N_MNMODE BIT(8)  /* =1:manual */
 #define PCL_PHY_RESET_N                BIT(0)  /* =1:deasssert */
@@ -77,11 +79,12 @@ static void uniphier_pciephy_set_param(struct uniphier_pciephy_priv *priv,
        val  = FIELD_PREP(TESTI_DAT_MASK, 1);
        val |= FIELD_PREP(TESTI_ADR_MASK, reg);
        uniphier_pciephy_testio_write(priv, val);
-       val = readl(priv->base + PCL_PHY_TEST_O);
+       val = readl(priv->base + PCL_PHY_TEST_O) & TESTO_DAT_MASK;
 
        /* update value */
-       val &= ~FIELD_PREP(TESTI_DAT_MASK, mask);
-       val  = FIELD_PREP(TESTI_DAT_MASK, mask & param);
+       val &= ~mask;
+       val |= mask & param;
+       val = FIELD_PREP(TESTI_DAT_MASK, val);
        val |= FIELD_PREP(TESTI_ADR_MASK, reg);
        uniphier_pciephy_testio_write(priv, val);
        uniphier_pciephy_testio_write(priv, val | TESTI_WR_EN);
index c184f4e..3e491df 100644 (file)
@@ -57,6 +57,7 @@ struct pll_params {
 struct stm32_usbphyc_phy {
        struct phy *phy;
        struct stm32_usbphyc *usbphyc;
+       struct regulator *vbus;
        u32 index;
        bool active;
 };
@@ -291,9 +292,31 @@ static int stm32_usbphyc_phy_exit(struct phy *phy)
        return stm32_usbphyc_pll_disable(usbphyc);
 }
 
+static int stm32_usbphyc_phy_power_on(struct phy *phy)
+{
+       struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy);
+
+       if (usbphyc_phy->vbus)
+               return regulator_enable(usbphyc_phy->vbus);
+
+       return 0;
+}
+
+static int stm32_usbphyc_phy_power_off(struct phy *phy)
+{
+       struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy);
+
+       if (usbphyc_phy->vbus)
+               return regulator_disable(usbphyc_phy->vbus);
+
+       return 0;
+}
+
 static const struct phy_ops stm32_usbphyc_phy_ops = {
        .init = stm32_usbphyc_phy_init,
        .exit = stm32_usbphyc_phy_exit,
+       .power_on = stm32_usbphyc_phy_power_on,
+       .power_off = stm32_usbphyc_phy_power_off,
        .owner = THIS_MODULE,
 };
 
@@ -519,6 +542,14 @@ static int stm32_usbphyc_probe(struct platform_device *pdev)
                usbphyc->phys[port]->index = index;
                usbphyc->phys[port]->active = false;
 
+               usbphyc->phys[port]->vbus = devm_regulator_get_optional(&phy->dev, "vbus");
+               if (IS_ERR(usbphyc->phys[port]->vbus)) {
+                       ret = PTR_ERR(usbphyc->phys[port]->vbus);
+                       if (ret == -EPROBE_DEFER)
+                               goto put_child;
+                       usbphyc->phys[port]->vbus = NULL;
+               }
+
                port++;
        }
 
index 57adc08..9fe6ea6 100644 (file)
@@ -242,19 +242,28 @@ static int dm816x_usb_phy_probe(struct platform_device *pdev)
 
        pm_runtime_enable(phy->dev);
        generic_phy = devm_phy_create(phy->dev, NULL, &ops);
-       if (IS_ERR(generic_phy))
-               return PTR_ERR(generic_phy);
+       if (IS_ERR(generic_phy)) {
+               error = PTR_ERR(generic_phy);
+               goto clk_unprepare;
+       }
 
        phy_set_drvdata(generic_phy, phy);
 
        phy_provider = devm_of_phy_provider_register(phy->dev,
                                                     of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
+       if (IS_ERR(phy_provider)) {
+               error = PTR_ERR(phy_provider);
+               goto clk_unprepare;
+       }
 
        usb_add_phy_dev(&phy->phy);
 
        return 0;
+
+clk_unprepare:
+       pm_runtime_disable(phy->dev);
+       clk_unprepare(phy->refclk);
+       return error;
 }
 
 static int dm816x_usb_phy_remove(struct platform_device *pdev)
index 812e540..5771e24 100644 (file)
@@ -544,8 +544,8 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
        return 0;
 }
 
-static ssize_t twl4030_usb_vbus_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
+static ssize_t vbus_show(struct device *dev,
+                        struct device_attribute *attr, char *buf)
 {
        struct twl4030_usb *twl = dev_get_drvdata(dev);
        int ret = -EINVAL;
@@ -557,7 +557,7 @@ static ssize_t twl4030_usb_vbus_show(struct device *dev,
 
        return ret;
 }
-static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
+static DEVICE_ATTR_RO(vbus);
 
 static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
 {
index 0ed434d..f3286f4 100644 (file)
@@ -125,7 +125,7 @@ struct phy_ops {
 /**
  * struct phy_attrs - represents phy attributes
  * @bus_width: Data path width implemented by PHY
- * @max_link_rate: Maximum link rate supported by PHY (in Mbps)
+ * @max_link_rate: Maximum link rate supported by PHY (units to be decided by producer and consumer)
  * @mode: PHY mode
  */
 struct phy_attrs {