Browse Source

Merge tag 'phy-for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-next

Kishon writes:

phy: for 4.13

 *) Group phy drivers into vendor specific directories
 *) Add USB3 PHY driver for Renesas R-Car Gen3
 *) Add USB2 PHY driver for Meson GXL and GXM SoCs
 *) Add USB DRD PHY driver for Broadcom Northstar2
 *) Add USB PHY driver for CPCAP PMIC USB
 *) Make phy-meson8b-usb2 driver support USB PHY on Meson8
 *) Make phy-tusb1210 driver support TUSB1211
 *) Make phy-rockchip-inno-usb2 driver support usb2-phy in rk3228 SoCs
 *) Make phy-brcm-sata driver support for stingray SATA phy
 *) Make bcm-ns-usb3 as a MDIO driver
 *) Make rockchip-inno-usb2 support two host ports
 *) Implement ->set_mode() callback in phy-tusb1210
 *) Minor fixes in phy drivers

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Greg Kroah-Hartman 8 years ago
parent
commit
21bdb3b071
99 changed files with 2771 additions and 636 deletions
  1. 19 8
      Documentation/devicetree/bindings/phy/bcm-ns-usb3-phy.txt
  2. 30 0
      Documentation/devicetree/bindings/phy/brcm,ns2-drd-phy.txt
  3. 4 3
      Documentation/devicetree/bindings/phy/brcm-sata-phy.txt
  4. 17 0
      Documentation/devicetree/bindings/phy/meson-gxl-usb2-phy.txt
  5. 2 1
      Documentation/devicetree/bindings/phy/meson8b-usb2-phy.txt
  6. 40 0
      Documentation/devicetree/bindings/phy/phy-cpcap-usb.txt
  7. 1 0
      Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt
  8. 46 0
      Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb3.txt
  9. 10 10
      MAINTAINERS
  10. 12 480
      drivers/phy/Kconfig
  11. 14 57
      drivers/phy/Makefile
  12. 31 0
      drivers/phy/allwinner/Kconfig
  13. 2 0
      drivers/phy/allwinner/Makefile
  14. 0 0
      drivers/phy/allwinner/phy-sun4i-usb.c
  15. 0 0
      drivers/phy/allwinner/phy-sun9i-usb.c
  16. 27 0
      drivers/phy/amlogic/Kconfig
  17. 2 0
      drivers/phy/amlogic/Makefile
  18. 273 0
      drivers/phy/amlogic/phy-meson-gxl-usb2.c
  19. 3 2
      drivers/phy/amlogic/phy-meson8b-usb2.c
  20. 69 0
      drivers/phy/broadcom/Kconfig
  21. 7 0
      drivers/phy/broadcom/Makefile
  22. 0 0
      drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
  23. 0 0
      drivers/phy/broadcom/phy-bcm-kona-usb2.c
  24. 0 0
      drivers/phy/broadcom/phy-bcm-ns-usb2.c
  25. 166 64
      drivers/phy/broadcom/phy-bcm-ns-usb3.c
  26. 0 0
      drivers/phy/broadcom/phy-bcm-ns2-pcie.c
  27. 437 0
      drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c
  28. 73 0
      drivers/phy/broadcom/phy-brcm-sata.c
  29. 20 0
      drivers/phy/hisilicon/Kconfig
  30. 2 0
      drivers/phy/hisilicon/Makefile
  31. 0 0
      drivers/phy/hisilicon/phy-hi6220-usb.c
  32. 0 0
      drivers/phy/hisilicon/phy-hix5hd2-sata.c
  33. 50 0
      drivers/phy/marvell/Kconfig
  34. 6 0
      drivers/phy/marvell/Makefile
  35. 0 0
      drivers/phy/marvell/phy-armada375-usb2.c
  36. 0 0
      drivers/phy/marvell/phy-berlin-sata.c
  37. 0 0
      drivers/phy/marvell/phy-berlin-usb.c
  38. 0 0
      drivers/phy/marvell/phy-mvebu-sata.c
  39. 0 0
      drivers/phy/marvell/phy-pxa-28nm-hsic.c
  40. 0 0
      drivers/phy/marvell/phy-pxa-28nm-usb2.c
  41. 12 0
      drivers/phy/motorola/Kconfig
  42. 5 0
      drivers/phy/motorola/Makefile
  43. 676 0
      drivers/phy/motorola/phy-cpcap-usb.c
  44. 58 0
      drivers/phy/qualcomm/Kconfig
  45. 9 0
      drivers/phy/qualcomm/Makefile
  46. 0 0
      drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
  47. 0 0
      drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
  48. 0 0
      drivers/phy/qualcomm/phy-qcom-qmp.c
  49. 0 0
      drivers/phy/qualcomm/phy-qcom-qusb2.c
  50. 0 0
      drivers/phy/qualcomm/phy-qcom-ufs-i.h
  51. 0 0
      drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c
  52. 0 0
      drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h
  53. 0 0
      drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c
  54. 0 0
      drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h
  55. 0 0
      drivers/phy/qualcomm/phy-qcom-ufs.c
  56. 1 2
      drivers/phy/qualcomm/phy-qcom-usb-hs.c
  57. 1 2
      drivers/phy/qualcomm/phy-qcom-usb-hsic.c
  58. 24 0
      drivers/phy/renesas/Kconfig
  59. 3 0
      drivers/phy/renesas/Makefile
  60. 0 0
      drivers/phy/renesas/phy-rcar-gen2.c
  61. 0 0
      drivers/phy/renesas/phy-rcar-gen3-usb2.c
  62. 226 0
      drivers/phy/renesas/phy-rcar-gen3-usb3.c
  63. 51 0
      drivers/phy/rockchip/Kconfig
  64. 6 0
      drivers/phy/rockchip/Makefile
  65. 0 0
      drivers/phy/rockchip/phy-rockchip-dp.c
  66. 0 0
      drivers/phy/rockchip/phy-rockchip-emmc.c
  67. 70 4
      drivers/phy/rockchip/phy-rockchip-inno-usb2.c
  68. 0 0
      drivers/phy/rockchip/phy-rockchip-pcie.c
  69. 0 0
      drivers/phy/rockchip/phy-rockchip-typec.c
  70. 0 0
      drivers/phy/rockchip/phy-rockchip-usb.c
  71. 95 0
      drivers/phy/samsung/Kconfig
  72. 11 0
      drivers/phy/samsung/Makefile
  73. 0 0
      drivers/phy/samsung/phy-exynos-dp-video.c
  74. 0 0
      drivers/phy/samsung/phy-exynos-mipi-video.c
  75. 0 0
      drivers/phy/samsung/phy-exynos-pcie.c
  76. 0 0
      drivers/phy/samsung/phy-exynos4210-usb2.c
  77. 0 0
      drivers/phy/samsung/phy-exynos4x12-usb2.c
  78. 0 0
      drivers/phy/samsung/phy-exynos5-usbdrd.c
  79. 0 0
      drivers/phy/samsung/phy-exynos5250-sata.c
  80. 0 0
      drivers/phy/samsung/phy-exynos5250-usb2.c
  81. 0 0
      drivers/phy/samsung/phy-s5pv210-usb2.c
  82. 0 0
      drivers/phy/samsung/phy-samsung-usb2.c
  83. 0 0
      drivers/phy/samsung/phy-samsung-usb2.h
  84. 33 0
      drivers/phy/st/Kconfig
  85. 4 0
      drivers/phy/st/Makefile
  86. 0 0
      drivers/phy/st/phy-miphy28lp.c
  87. 0 0
      drivers/phy/st/phy-spear1310-miphy.c
  88. 0 0
      drivers/phy/st/phy-spear1340-miphy.c
  89. 0 0
      drivers/phy/st/phy-stih407-usb.c
  90. 78 0
      drivers/phy/ti/Kconfig
  91. 7 0
      drivers/phy/ti/Makefile
  92. 0 0
      drivers/phy/ti/phy-da8xx-usb.c
  93. 0 0
      drivers/phy/ti/phy-dm816x-usb.c
  94. 0 0
      drivers/phy/ti/phy-omap-control.c
  95. 0 0
      drivers/phy/ti/phy-omap-usb2.c
  96. 0 0
      drivers/phy/ti/phy-ti-pipe3.c
  97. 38 3
      drivers/phy/ti/phy-tusb1210.c
  98. 0 0
      drivers/phy/ti/phy-twl4030-usb.c
  99. 0 0
      include/linux/phy/ulpi_phy.h

+ 19 - 8
Documentation/devicetree/bindings/phy/bcm-ns-usb3-phy.txt

@@ -3,9 +3,10 @@ Driver for Broadcom Northstar USB 3.0 PHY
 Required properties:
 Required properties:
 
 
 - compatible: one of: "brcm,ns-ax-usb3-phy", "brcm,ns-bx-usb3-phy".
 - compatible: one of: "brcm,ns-ax-usb3-phy", "brcm,ns-bx-usb3-phy".
-- reg: register mappings for DMP (Device Management Plugin) and ChipCommon B
-       MMI.
-- reg-names: "dmp" and "ccb-mii"
+- reg: address of MDIO bus device
+- usb3-dmp-syscon: phandle to syscon with DMP (Device Management Plugin)
+		   registers
+- #phy-cells: must be 0
 
 
 Initialization of USB 3.0 PHY depends on Northstar version. There are currently
 Initialization of USB 3.0 PHY depends on Northstar version. There are currently
 three known series: Ax, Bx and Cx.
 three known series: Ax, Bx and Cx.
@@ -15,9 +16,19 @@ Known B1: BCM4707 rev 6
 Known C0: BCM47094 rev 0
 Known C0: BCM47094 rev 0
 
 
 Example:
 Example:
-	usb3-phy {
-		compatible = "brcm,ns-ax-usb3-phy";
-		reg = <0x18105000 0x1000>, <0x18003000 0x1000>;
-		reg-names = "dmp", "ccb-mii";
-		#phy-cells = <0>;
+	mdio: mdio@0 {
+		reg = <0x0>;
+		#size-cells = <1>;
+		#address-cells = <0>;
+
+		usb3-phy@10 {
+			compatible = "brcm,ns-ax-usb3-phy";
+			reg = <0x10>;
+			usb3-dmp-syscon = <&usb3_dmp>;
+			#phy-cells = <0>;
+		};
+	};
+
+	usb3_dmp: syscon@18105000 {
+		reg = <0x18105000 0x1000>;
 	};
 	};

+ 30 - 0
Documentation/devicetree/bindings/phy/brcm,ns2-drd-phy.txt

@@ -0,0 +1,30 @@
+BROADCOM NORTHSTAR2 USB2 (DUAL ROLE DEVICE) PHY
+
+Required properties:
+ - compatible: brcm,ns2-drd-phy
+ - reg: offset and length of the NS2 PHY related registers.
+ - reg-names
+   The below registers must be provided.
+   icfg - for DRD ICFG configurations
+   rst-ctrl - for DRD IDM reset
+   crmu-ctrl - for CRMU core vdd, PHY and PHY PLL reset
+   usb2-strap - for port over current polarity reversal
+ - #phy-cells: Must be 0. No args required.
+ - vbus-gpios: vbus gpio binding
+ - id-gpios: id gpio binding
+
+Refer to phy/phy-bindings.txt for the generic PHY binding properties
+
+Example:
+	usbdrd_phy: phy@66000960 {
+			#phy-cells = <0>;
+			compatible = "brcm,ns2-drd-phy";
+			reg = <0x66000960 0x24>,
+			      <0x67012800 0x4>,
+			      <0x6501d148 0x4>,
+			      <0x664d0700 0x4>;
+			reg-names = "icfg", "rst-ctrl",
+				    "crmu-ctrl", "usb2-strap";
+			id-gpios = <&gpio_g 30 0>;
+			vbus-gpios = <&gpio_g 31 0>;
+	};

+ 4 - 3
Documentation/devicetree/bindings/phy/brcm-sata-phy.txt

@@ -7,12 +7,13 @@ Required properties:
      "brcm,iproc-ns2-sata-phy"
      "brcm,iproc-ns2-sata-phy"
      "brcm,iproc-nsp-sata-phy"
      "brcm,iproc-nsp-sata-phy"
      "brcm,phy-sata3"
      "brcm,phy-sata3"
+     "brcm,iproc-sr-sata-phy"
 - address-cells: should be 1
 - address-cells: should be 1
 - size-cells: should be 0
 - size-cells: should be 0
 - reg: register ranges for the PHY PCB interface
 - reg: register ranges for the PHY PCB interface
 - reg-names: should be "phy" and "phy-ctrl"
 - reg-names: should be "phy" and "phy-ctrl"
      The "phy-ctrl" registers are only required for
      The "phy-ctrl" registers are only required for
-     "brcm,iproc-ns2-sata-phy".
+     "brcm,iproc-ns2-sata-phy" and "brcm,iproc-sr-sata-phy".
 
 
 Sub-nodes:
 Sub-nodes:
   Each port's PHY should be represented as a sub-node.
   Each port's PHY should be represented as a sub-node.
@@ -23,8 +24,8 @@ Sub-nodes required properties:
 
 
 Sub-nodes optional properties:
 Sub-nodes optional properties:
 - brcm,enable-ssc: use spread spectrum clocking (SSC) on this port
 - brcm,enable-ssc: use spread spectrum clocking (SSC) on this port
-     This property is not applicable for "brcm,iproc-ns2-sata-phy" and
-     "brcm,iproc-nsp-sata-phy".
+     This property is not applicable for "brcm,iproc-ns2-sata-phy",
+     "brcm,iproc-nsp-sata-phy" and "brcm,iproc-sr-sata-phy".
 
 
 Example:
 Example:
 	sata-phy@f0458100 {
 	sata-phy@f0458100 {

+ 17 - 0
Documentation/devicetree/bindings/phy/meson-gxl-usb2-phy.txt

@@ -0,0 +1,17 @@
+* Amlogic Meson GXL and GXM USB2 PHY binding
+
+Required properties:
+- compatible:	Should be "amlogic,meson-gxl-usb2-phy"
+- reg:		The base address and length of the registers
+- #phys-cells:	must be 0 (see phy-bindings.txt in this directory)
+
+Optional properties:
+- phy-supply:	see phy-bindings.txt in this directory
+
+
+Example:
+	usb2_phy0: phy@78000 {
+		compatible = "amlogic,meson-gxl-usb2-phy";
+		#phy-cells = <0>;
+		reg = <0x0 0x78000 0x0 0x20>;
+	};

+ 2 - 1
Documentation/devicetree/bindings/phy/meson8b-usb2-phy.txt

@@ -1,7 +1,8 @@
-* Amlogic Meson8b and GXBB USB2 PHY
+* Amlogic Meson8, Meson8b and GXBB USB2 PHY
 
 
 Required properties:
 Required properties:
 - compatible:	Depending on the platform this should be one of:
 - compatible:	Depending on the platform this should be one of:
+	"amlogic,meson8-usb2-phy"
 	"amlogic,meson8b-usb2-phy"
 	"amlogic,meson8b-usb2-phy"
 	"amlogic,meson-gxbb-usb2-phy"
 	"amlogic,meson-gxbb-usb2-phy"
 - reg:		The base address and length of the registers
 - reg:		The base address and length of the registers

+ 40 - 0
Documentation/devicetree/bindings/phy/phy-cpcap-usb.txt

@@ -0,0 +1,40 @@
+Motorola CPCAP PMIC USB PHY binding
+
+Required properties:
+compatible: Shall be either "motorola,cpcap-usb-phy" or
+	    "motorola,mapphone-cpcap-usb-phy"
+#phy-cells: Shall be 0
+interrupts: CPCAP PMIC interrupts used by the USB PHY
+interrupt-names: Interrupt names
+io-channels: IIO ADC channels used by the USB PHY
+io-channel-names: IIO ADC channel names
+vusb-supply: Regulator for the PHY
+
+Optional properties:
+pinctrl: Optional alternate pin modes for the PHY
+pinctrl-names: Names for optional pin modes
+mode-gpios: Optional GPIOs for configuring alternate modes
+
+Example:
+cpcap_usb2_phy: phy {
+	compatible = "motorola,mapphone-cpcap-usb-phy";
+	pinctrl-0 = <&usb_gpio_mux_sel1 &usb_gpio_mux_sel2>;
+	pinctrl-1 = <&usb_ulpi_pins>;
+	pinctrl-2 = <&usb_utmi_pins>;
+	pinctrl-3 = <&uart3_pins>;
+	pinctrl-names = "default", "ulpi", "utmi", "uart";
+	#phy-cells = <0>;
+	interrupts-extended = <
+		&cpcap 15 0 &cpcap 14 0 &cpcap 28 0 &cpcap 19 0
+		&cpcap 18 0 &cpcap 17 0 &cpcap 16 0 &cpcap 49 0
+		&cpcap 48 1
+	>;
+	interrupt-names =
+		"id_ground", "id_float", "se0conn", "vbusvld",
+		"sessvld", "sessend", "se1", "dm", "dp";
+	mode-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH
+		      &gpio1 0 GPIO_ACTIVE_HIGH>;
+	io-channels = <&cpcap_adc 2>, <&cpcap_adc 7>;
+	io-channel-names = "vbus", "id";
+	vusb-supply = <&vusb>;
+};

+ 1 - 0
Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt

@@ -2,6 +2,7 @@ ROCKCHIP USB2.0 PHY WITH INNO IP BLOCK
 
 
 Required properties (phy (parent) node):
 Required properties (phy (parent) node):
  - compatible : should be one of the listed compatibles:
  - compatible : should be one of the listed compatibles:
+	* "rockchip,rk3228-usb2phy"
 	* "rockchip,rk3328-usb2phy"
 	* "rockchip,rk3328-usb2phy"
 	* "rockchip,rk3366-usb2phy"
 	* "rockchip,rk3366-usb2phy"
 	* "rockchip,rk3399-usb2phy"
 	* "rockchip,rk3399-usb2phy"

+ 46 - 0
Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb3.txt

@@ -0,0 +1,46 @@
+* Renesas R-Car generation 3 USB 3.0 PHY
+
+This file provides information on what the device node for the R-Car generation
+3 USB 3.0 PHY contains.
+If you want to enable spread spectrum clock (ssc), you should use USB_EXTAL
+instead of USB3_CLK. However, if you don't want to these features, you don't
+need this driver.
+
+Required properties:
+- compatible: "renesas,r8a7795-usb3-phy" if the device is a part of an R8A7795
+	      SoC.
+	      "renesas,r8a7796-usb3-phy" if the device is a part of an R8A7796
+	      SoC.
+	      "renesas,rcar-gen3-usb3-phy" for a generic R-Car Gen3 compatible
+	      device.
+
+	      When compatible with the generic version, nodes must list the
+	      SoC-specific version corresponding to the platform first
+	      followed by the generic version.
+
+- reg: offset and length of the USB 3.0 PHY register block.
+- clocks: A list of phandles and clock-specifier pairs.
+- clock-names: Name of the clocks.
+  - The funcional clock must be "usb3-if".
+  - The usb3's external clock must be "usb3s_clk".
+  - The usb2's external clock must be "usb_extal". If you want to use the ssc,
+    the clock-frequency must not be 0.
+- #phy-cells: see phy-bindings.txt in the same directory, must be <0>.
+
+Optional properties:
+- renesas,ssc-range: Enable/disable spread spectrum clock (ssc) by using
+		     the following values as u32:
+			- 0 (or the property doesn't exist): disable the ssc
+			- 4980: enable the ssc as -4980 ppm
+			- 4492: enable the ssc as -4492 ppm
+			- 4003: enable the ssc as -4003 ppm
+
+Example (R-Car H3):
+
+	usb-phy@e65ee000 {
+		compatible = "renesas,r8a7795-usb3-phy",
+			     "renesas,rcar-gen3-usb3-phy";
+		reg = <0 0xe65ee000 0 0x90>;
+		clocks = <&cpg CPG_MOD 328>, <&usb3s0_clk>, <&usb_extal>;
+		clock-names = "usb3-if", "usb3s_clk", "usb_extal";
+	};

+ 10 - 10
MAINTAINERS

@@ -1843,8 +1843,8 @@ F:	drivers/i2c/busses/i2c-st.c
 F:	drivers/media/rc/st_rc.c
 F:	drivers/media/rc/st_rc.c
 F:	drivers/media/platform/sti/c8sectpfe/
 F:	drivers/media/platform/sti/c8sectpfe/
 F:	drivers/mmc/host/sdhci-st.c
 F:	drivers/mmc/host/sdhci-st.c
-F:	drivers/phy/phy-miphy28lp.c
-F:	drivers/phy/phy-stih407-usb.c
+F:	drivers/phy/st/phy-miphy28lp.c
+F:	drivers/phy/st/phy-stih407-usb.c
 F:	drivers/pinctrl/pinctrl-st.c
 F:	drivers/pinctrl/pinctrl-st.c
 F:	drivers/remoteproc/st_remoteproc.c
 F:	drivers/remoteproc/st_remoteproc.c
 F:	drivers/remoteproc/st_slim_rproc.c
 F:	drivers/remoteproc/st_slim_rproc.c
@@ -10831,11 +10831,11 @@ L:	linux-iio@vger.kernel.org
 S:	Supported
 S:	Supported
 F:	drivers/iio/adc/rcar_gyro_adc.c
 F:	drivers/iio/adc/rcar_gyro_adc.c
 
 
-RENESAS USB2 PHY DRIVER
+RENESAS USB PHY DRIVER
 M:	Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
 M:	Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
 L:	linux-renesas-soc@vger.kernel.org
 L:	linux-renesas-soc@vger.kernel.org
 S:	Maintained
 S:	Maintained
-F:	drivers/phy/phy-rcar-gen3-usb2.c
+F:	drivers/phy/renesas/phy-rcar-gen3-usb*.c
 
 
 RESET CONTROLLER FRAMEWORK
 RESET CONTROLLER FRAMEWORK
 M:	Philipp Zabel <p.zabel@pengutronix.de>
 M:	Philipp Zabel <p.zabel@pengutronix.de>
@@ -11237,12 +11237,12 @@ L:	linux-kernel@vger.kernel.org
 S:	Supported
 S:	Supported
 F:	Documentation/devicetree/bindings/phy/samsung-phy.txt
 F:	Documentation/devicetree/bindings/phy/samsung-phy.txt
 F:	Documentation/phy/samsung-usb2.txt
 F:	Documentation/phy/samsung-usb2.txt
-F:	drivers/phy/phy-exynos4210-usb2.c
-F:	drivers/phy/phy-exynos4x12-usb2.c
-F:	drivers/phy/phy-exynos5250-usb2.c
-F:	drivers/phy/phy-s5pv210-usb2.c
-F:	drivers/phy/phy-samsung-usb2.c
-F:	drivers/phy/phy-samsung-usb2.h
+F:	drivers/phy/samsung/phy-exynos4210-usb2.c
+F:	drivers/phy/samsung/phy-exynos4x12-usb2.c
+F:	drivers/phy/samsung/phy-exynos5250-usb2.c
+F:	drivers/phy/samsung/phy-s5pv210-usb2.c
+F:	drivers/phy/samsung/phy-samsung-usb2.c
+F:	drivers/phy/samsung/phy-samsung-usb2.h
 
 
 SERIAL DRIVERS
 SERIAL DRIVERS
 M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>

+ 12 - 480
drivers/phy/Kconfig

@@ -15,73 +15,6 @@ config GENERIC_PHY
 	  phy users can obtain reference to the PHY. All the users of this
 	  phy users can obtain reference to the PHY. All the users of this
 	  framework should select this config.
 	  framework should select this config.
 
 
-config PHY_BCM_NS_USB2
-	tristate "Broadcom Northstar USB 2.0 PHY Driver"
-	depends on ARCH_BCM_IPROC || COMPILE_TEST
-	depends on HAS_IOMEM && OF
-	select GENERIC_PHY
-	help
-	  Enable this to support Broadcom USB 2.0 PHY connected to the USB
-	  controller on Northstar family.
-
-config PHY_BCM_NS_USB3
-	tristate "Broadcom Northstar USB 3.0 PHY Driver"
-	depends on ARCH_BCM_IPROC || COMPILE_TEST
-	depends on HAS_IOMEM && OF
-	select GENERIC_PHY
-	help
-	  Enable this to support Broadcom USB 3.0 PHY connected to the USB
-	  controller on Northstar family.
-
-config PHY_BERLIN_USB
-	tristate "Marvell Berlin USB PHY Driver"
-	depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF
-	select GENERIC_PHY
-	help
-	  Enable this to support the USB PHY on Marvell Berlin SoCs.
-
-config PHY_BERLIN_SATA
-	tristate "Marvell Berlin SATA PHY driver"
-	depends on ARCH_BERLIN && HAS_IOMEM && OF
-	select GENERIC_PHY
-	help
-	  Enable this to support the SATA PHY on Marvell Berlin SoCs.
-
-config ARMADA375_USBCLUSTER_PHY
-	def_bool y
-	depends on MACH_ARMADA_375 || COMPILE_TEST
-	depends on OF && HAS_IOMEM
-	select GENERIC_PHY
-
-config PHY_DA8XX_USB
-	tristate "TI DA8xx USB PHY Driver"
-	depends on ARCH_DAVINCI_DA8XX
-	select GENERIC_PHY
-	select MFD_SYSCON
-	help
-	  Enable this to support the USB PHY on DA8xx SoCs.
-
-	  This driver controls both the USB 1.1 PHY and the USB 2.0 PHY.
-
-config PHY_DM816X_USB
-	tristate "TI dm816x USB PHY driver"
-	depends on ARCH_OMAP2PLUS
-	depends on USB_SUPPORT
-	select GENERIC_PHY
-	select USB_PHY
-	help
-	  Enable this for dm816x USB to work.
-
-config PHY_EXYNOS_MIPI_VIDEO
-	tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
-	depends on HAS_IOMEM
-	depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
-	select GENERIC_PHY
-	default y if ARCH_S5PV210 || ARCH_EXYNOS
-	help
-	  Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
-	  and EXYNOS SoCs.
-
 config PHY_LPC18XX_USB_OTG
 config PHY_LPC18XX_USB_OTG
 	tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
 	tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
 	depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
 	depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
@@ -93,146 +26,6 @@ config PHY_LPC18XX_USB_OTG
 	  This driver is need for USB0 support on LPC18xx/43xx and takes
 	  This driver is need for USB0 support on LPC18xx/43xx and takes
 	  care of enabling and clock setup.
 	  care of enabling and clock setup.
 
 
-config PHY_PXA_28NM_HSIC
-	tristate "Marvell USB HSIC 28nm PHY Driver"
-	depends on HAS_IOMEM
-	select GENERIC_PHY
-	help
-	  Enable this to support Marvell USB HSIC PHY driver for Marvell
-	  SoC. This driver will do the PHY initialization and shutdown.
-	  The PHY driver will be used by Marvell ehci driver.
-
-	  To compile this driver as a module, choose M here.
-
-config PHY_PXA_28NM_USB2
-	tristate "Marvell USB 2.0 28nm PHY Driver"
-	depends on HAS_IOMEM
-	select GENERIC_PHY
-	help
-	  Enable this to support Marvell USB 2.0 PHY driver for Marvell
-	  SoC. This driver will do the PHY initialization and shutdown.
-	  The PHY driver will be used by Marvell udc/ehci/otg driver.
-
-	  To compile this driver as a module, choose M here.
-
-config PHY_MVEBU_SATA
-	def_bool y
-	depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
-	depends on OF
-	select GENERIC_PHY
-
-config PHY_MIPHY28LP
-	tristate "STMicroelectronics MIPHY28LP PHY driver for STiH407"
-	depends on ARCH_STI
-	select GENERIC_PHY
-	help
-	  Enable this to support the miphy transceiver (for SATA/PCIE/USB3)
-	  that is part of STMicroelectronics STiH407 SoC.
-
-config PHY_RCAR_GEN2
-	tristate "Renesas R-Car generation 2 USB PHY driver"
-	depends on ARCH_RENESAS
-	depends on GENERIC_PHY
-	help
-	  Support for USB PHY found on Renesas R-Car generation 2 SoCs.
-
-config PHY_RCAR_GEN3_USB2
-	tristate "Renesas R-Car generation 3 USB 2.0 PHY driver"
-	depends on ARCH_RENESAS
-	depends on EXTCON
-	select GENERIC_PHY
-	help
-	  Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs.
-
-config OMAP_CONTROL_PHY
-	tristate "OMAP CONTROL PHY Driver"
-	depends on ARCH_OMAP2PLUS || COMPILE_TEST
-	help
-	  Enable this to add support for the PHY part present in the control
-	  module. This driver has API to power on the USB2 PHY and to write to
-	  the mailbox. The mailbox is present only in omap4 and the register to
-	  power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
-	  additional register to power on USB3 PHY/SATA PHY/PCIE PHY
-	  (PIPE3 PHY).
-
-config OMAP_USB2
-	tristate "OMAP USB2 PHY Driver"
-	depends on ARCH_OMAP2PLUS
-	depends on USB_SUPPORT
-	select GENERIC_PHY
-	select USB_PHY
-	select OMAP_CONTROL_PHY
-	depends on OMAP_OCP2SCP
-	help
-	  Enable this to support the transceiver that is part of SOC. This
-	  driver takes care of all the PHY functionality apart from comparator.
-	  The USB OTG controller communicates with the comparator using this
-	  driver.
-
-config TI_PIPE3
-	tristate "TI PIPE3 PHY Driver"
-	depends on ARCH_OMAP2PLUS || COMPILE_TEST
-	select GENERIC_PHY
-	select OMAP_CONTROL_PHY
-	depends on OMAP_OCP2SCP
-	help
-	  Enable this to support the PIPE3 PHY that is part of TI SOCs. This
-	  driver takes care of all the PHY functionality apart from comparator.
-	  This driver interacts with the "OMAP Control PHY Driver" to power
-	  on/off the PHY.
-
-config TWL4030_USB
-	tristate "TWL4030 USB Transceiver Driver"
-	depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
-	depends on USB_SUPPORT
-	depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't 'y'
-	select GENERIC_PHY
-	select USB_PHY
-	help
-	  Enable this to support the USB OTG transceiver on TWL4030
-	  family chips (including the TWL5030 and TPS659x0 devices).
-	  This transceiver supports high and full speed devices plus,
-	  in host mode, low speed.
-
-config PHY_EXYNOS_DP_VIDEO
-	tristate "EXYNOS SoC series Display Port PHY driver"
-	depends on OF
-	depends on ARCH_EXYNOS || COMPILE_TEST
-	default ARCH_EXYNOS
-	select GENERIC_PHY
-	help
-	  Support for Display Port PHY found on Samsung EXYNOS SoCs.
-
-config BCM_KONA_USB2_PHY
-	tristate "Broadcom Kona USB2 PHY Driver"
-	depends on HAS_IOMEM
-	select GENERIC_PHY
-	help
-	  Enable this to support the Broadcom Kona USB 2.0 PHY.
-
-config PHY_EXYNOS5250_SATA
-	tristate "Exynos5250 Sata SerDes/PHY driver"
-	depends on SOC_EXYNOS5250
-	depends on HAS_IOMEM
-	depends on OF
-	select GENERIC_PHY
-	select I2C
-	select I2C_S3C2410
-	select MFD_SYSCON
-	help
-	  Enable this to support SATA SerDes/Phy found on Samsung's
-	  Exynos5250 based SoCs.This SerDes/Phy supports SATA 1.5 Gb/s,
-	  SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
-	  port to accept one SATA device.
-
-config PHY_HIX5HD2_SATA
-	tristate "HIX5HD2 SATA PHY Driver"
-	depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
-	select GENERIC_PHY
-	select MFD_SYSCON
-	help
-	  Support for SATA PHY on Hisilicon hix5hd2 Soc.
-
 config PHY_MT65XX_USB3
 config PHY_MT65XX_USB3
 	tristate "Mediatek USB3.0 PHY Driver"
 	tristate "Mediatek USB3.0 PHY Driver"
 	depends on ARCH_MEDIATEK && OF
 	depends on ARCH_MEDIATEK && OF
@@ -241,104 +34,6 @@ config PHY_MT65XX_USB3
 	  Say 'Y' here to add support for Mediatek USB3.0 PHY driver,
 	  Say 'Y' here to add support for Mediatek USB3.0 PHY driver,
 	  it supports multiple usb2.0 and usb3.0 ports.
 	  it supports multiple usb2.0 and usb3.0 ports.
 
 
-config PHY_HI6220_USB
-	tristate "hi6220 USB PHY support"
-	depends on (ARCH_HISI && ARM64) || COMPILE_TEST
-	select GENERIC_PHY
-	select MFD_SYSCON
-	help
-	  Enable this to support the HISILICON HI6220 USB PHY.
-
-	  To compile this driver as a module, choose M here.
-
-config PHY_SUN4I_USB
-	tristate "Allwinner sunxi SoC USB PHY driver"
-	depends on ARCH_SUNXI && HAS_IOMEM && OF
-	depends on RESET_CONTROLLER
-	depends on EXTCON
-	depends on POWER_SUPPLY
-	depends on USB_SUPPORT
-	select GENERIC_PHY
-	select USB_COMMON
-	help
-	  Enable this to support the transceiver that is part of Allwinner
-	  sunxi SoCs.
-
-	  This driver controls the entire USB PHY block, both the USB OTG
-	  parts, as well as the 2 regular USB 2 host PHYs.
-
-config PHY_SUN9I_USB
-	tristate "Allwinner sun9i SoC USB PHY driver"
-	depends on ARCH_SUNXI && HAS_IOMEM && OF
-	depends on RESET_CONTROLLER
-	depends on USB_SUPPORT
-	select USB_COMMON
-	select GENERIC_PHY
-	help
-	  Enable this to support the transceiver that is part of Allwinner
-	  sun9i SoCs.
-
-	  This driver controls each individual USB 2 host PHY.
-
-config PHY_SAMSUNG_USB2
-	tristate "Samsung USB 2.0 PHY driver"
-	depends on HAS_IOMEM
-	depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2
-	select GENERIC_PHY
-	select MFD_SYSCON
-	default ARCH_EXYNOS
-	help
-	  Enable this to support the Samsung USB 2.0 PHY driver for Samsung
-	  SoCs. This driver provides the interface for USB 2.0 PHY. Support
-	  for particular PHYs will be enabled based on the SoC type in addition
-	  to this driver.
-
-config PHY_S5PV210_USB2
-	bool "Support for S5PV210"
-	depends on PHY_SAMSUNG_USB2
-	depends on ARCH_S5PV210
-	help
-	  Enable USB PHY support for S5PV210. This option requires that Samsung
-	  USB 2.0 PHY driver is enabled and means that support for this
-	  particular SoC is compiled in the driver. In case of S5PV210 two phys
-	  are available - device and host.
-
-config PHY_EXYNOS4210_USB2
-	bool
-	depends on PHY_SAMSUNG_USB2
-	default CPU_EXYNOS4210
-
-config PHY_EXYNOS4X12_USB2
-	bool
-	depends on PHY_SAMSUNG_USB2
-	default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
-
-config PHY_EXYNOS5250_USB2
-	bool
-	depends on PHY_SAMSUNG_USB2
-	default SOC_EXYNOS5250 || SOC_EXYNOS5420
-
-config PHY_EXYNOS5_USBDRD
-	tristate "Exynos5 SoC series USB DRD PHY driver"
-	depends on ARCH_EXYNOS && OF
-	depends on HAS_IOMEM
-	depends on USB_DWC3_EXYNOS
-	select GENERIC_PHY
-	select MFD_SYSCON
-	default y
-	help
-	  Enable USB DRD PHY support for Exynos 5 SoC series.
-	  This driver provides PHY interface for USB 3.0 DRD controller
-	  present on Exynos5 SoC series.
-
-config PHY_EXYNOS_PCIE
-	bool "Exynos PCIe PHY driver"
-	depends on OF && (ARCH_EXYNOS || COMPILE_TEST)
-	select GENERIC_PHY
-	help
-	  Enable PCIe PHY support for Exynos SoC series.
-	  This driver provides PHY interface for Exynos PCIe controller.
-
 config PHY_PISTACHIO_USB
 config PHY_PISTACHIO_USB
 	tristate "IMG Pistachio USB2.0 PHY driver"
 	tristate "IMG Pistachio USB2.0 PHY driver"
 	depends on MACH_PISTACHIO
 	depends on MACH_PISTACHIO
@@ -346,83 +41,6 @@ config PHY_PISTACHIO_USB
 	help
 	help
 	  Enable this to support the USB2.0 PHY on the IMG Pistachio SoC.
 	  Enable this to support the USB2.0 PHY on the IMG Pistachio SoC.
 
 
-config PHY_QCOM_APQ8064_SATA
-	tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
-	depends on ARCH_QCOM
-	depends on HAS_IOMEM
-	depends on OF
-	select GENERIC_PHY
-
-config PHY_QCOM_IPQ806X_SATA
-	tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
-	depends on ARCH_QCOM
-	depends on HAS_IOMEM
-	depends on OF
-	select GENERIC_PHY
-
-config PHY_ROCKCHIP_USB
-	tristate "Rockchip USB2 PHY Driver"
-	depends on ARCH_ROCKCHIP && OF
-	select GENERIC_PHY
-	help
-	  Enable this to support the Rockchip USB 2.0 PHY.
-
-config PHY_ROCKCHIP_INNO_USB2
-	tristate "Rockchip INNO USB2PHY Driver"
-	depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
-	depends on COMMON_CLK
-	depends on EXTCON
-	depends on USB_SUPPORT
-	select GENERIC_PHY
-	select USB_COMMON
-	help
-	  Support for Rockchip USB2.0 PHY with Innosilicon IP block.
-
-config PHY_ROCKCHIP_EMMC
-	tristate "Rockchip EMMC PHY Driver"
-	depends on ARCH_ROCKCHIP && OF
-	select GENERIC_PHY
-	help
-	  Enable this to support the Rockchip EMMC PHY.
-
-config PHY_ROCKCHIP_DP
-	tristate "Rockchip Display Port PHY Driver"
-	depends on ARCH_ROCKCHIP && OF
-	select GENERIC_PHY
-	help
-	  Enable this to support the Rockchip Display Port PHY.
-
-config PHY_ROCKCHIP_PCIE
-	tristate "Rockchip PCIe PHY Driver"
-	depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
-	select GENERIC_PHY
-	select MFD_SYSCON
-	help
-	  Enable this to support the Rockchip PCIe PHY.
-
-config PHY_ROCKCHIP_TYPEC
-	tristate "Rockchip TYPEC PHY Driver"
-	depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST)
-	select EXTCON
-	select GENERIC_PHY
-	select RESET_CONTROLLER
-	help
-	  Enable this to support the Rockchip USB TYPEC PHY.
-
-config PHY_ST_SPEAR1310_MIPHY
-	tristate "ST SPEAR1310-MIPHY driver"
-	select GENERIC_PHY
-	depends on MACH_SPEAR1310 || COMPILE_TEST
-	help
-	  Support for ST SPEAr1310 MIPHY which can be used for PCIe and SATA.
-
-config PHY_ST_SPEAR1340_MIPHY
-	tristate "ST SPEAR1340-MIPHY driver"
-	select GENERIC_PHY
-	depends on MACH_SPEAR1340 || COMPILE_TEST
-	help
-	  Support for ST SPEAr1340 MIPHY which can be used for PCIe and SATA.
-
 config PHY_XGENE
 config PHY_XGENE
 	tristate "APM X-Gene 15Gbps PHY support"
 	tristate "APM X-Gene 15Gbps PHY support"
 	depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST)
 	depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST)
@@ -430,104 +48,18 @@ config PHY_XGENE
 	help
 	help
 	  This option enables support for APM X-Gene SoC multi-purpose PHY.
 	  This option enables support for APM X-Gene SoC multi-purpose PHY.
 
 
-config PHY_STIH407_USB
-	tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family"
-	depends on RESET_CONTROLLER
-	depends on ARCH_STI || COMPILE_TEST
-	select GENERIC_PHY
-	help
-	  Enable this support to enable the picoPHY device used by USB2
-	  and USB3 controllers on STMicroelectronics STiH407 SoC families.
-
-config PHY_QCOM_QMP
-	tristate "Qualcomm QMP PHY Driver"
-	depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST)
-	select GENERIC_PHY
-	help
-	  Enable this to support the QMP PHY transceiver that is used
-	  with controllers such as PCIe, UFS, and USB on Qualcomm chips.
-
-config PHY_QCOM_QUSB2
-	tristate "Qualcomm QUSB2 PHY Driver"
-	depends on OF && (ARCH_QCOM || COMPILE_TEST)
-	depends on NVMEM || !NVMEM
-	select GENERIC_PHY
-	help
-	  Enable this to support the HighSpeed QUSB2 PHY transceiver for USB
-	  controllers on Qualcomm chips. This driver supports the high-speed
-	  PHY which is usually paired with either the ChipIdea or Synopsys DWC3
-	  USB IPs on MSM SOCs.
-
-config PHY_QCOM_UFS
-	tristate "Qualcomm UFS PHY driver"
-	depends on OF && ARCH_QCOM
-	select GENERIC_PHY
-	help
-	  Support for UFS PHY on QCOM chipsets.
-
-config PHY_QCOM_USB_HS
-	tristate "Qualcomm USB HS PHY module"
-	depends on USB_ULPI_BUS
-	depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
-	select GENERIC_PHY
-	help
-	  Support for the USB high-speed ULPI compliant phy on Qualcomm
-	  chipsets.
-
-config PHY_QCOM_USB_HSIC
-	tristate "Qualcomm USB HSIC ULPI PHY module"
-	depends on USB_ULPI_BUS
-	select GENERIC_PHY
-	help
-	  Support for the USB HSIC ULPI compliant PHY on QCOM chipsets.
-
-config PHY_TUSB1210
-	tristate "TI TUSB1210 ULPI PHY module"
-	depends on USB_ULPI_BUS
-	select GENERIC_PHY
-	help
-	  Support for TI TUSB1210 USB ULPI PHY.
-
-config PHY_BRCM_SATA
-	tristate "Broadcom SATA PHY driver"
-	depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST
-	depends on OF
-	select GENERIC_PHY
-	default ARCH_BCM_IPROC
-	help
-	  Enable this to support the Broadcom SATA PHY.
-	  If unsure, say N.
-
-config PHY_CYGNUS_PCIE
-	tristate "Broadcom Cygnus PCIe PHY driver"
-	depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST)
-	select GENERIC_PHY
-	default ARCH_BCM_CYGNUS
-	help
-	  Enable this to support the Broadcom Cygnus PCIe PHY.
-	  If unsure, say N.
-
+source "drivers/phy/allwinner/Kconfig"
+source "drivers/phy/amlogic/Kconfig"
+source "drivers/phy/broadcom/Kconfig"
+source "drivers/phy/hisilicon/Kconfig"
+source "drivers/phy/marvell/Kconfig"
+source "drivers/phy/motorola/Kconfig"
+source "drivers/phy/qualcomm/Kconfig"
+source "drivers/phy/renesas/Kconfig"
+source "drivers/phy/rockchip/Kconfig"
+source "drivers/phy/samsung/Kconfig"
+source "drivers/phy/st/Kconfig"
 source "drivers/phy/tegra/Kconfig"
 source "drivers/phy/tegra/Kconfig"
-
-config PHY_NS2_PCIE
-	tristate "Broadcom Northstar2 PCIe PHY driver"
-	depends on OF && MDIO_BUS_MUX_BCM_IPROC
-	select GENERIC_PHY
-	default ARCH_BCM_IPROC
-	help
-	  Enable this to support the Broadcom Northstar2 PCIe PHY.
-	  If unsure, say N.
-
-config PHY_MESON8B_USB2
-	tristate "Meson8b and GXBB USB2 PHY driver"
-	default ARCH_MESON
-	depends on OF && (ARCH_MESON || COMPILE_TEST)
-	depends on USB_SUPPORT
-	select USB_COMMON
-	select GENERIC_PHY
-	help
-	  Enable this to support the Meson USB2 PHYs found in Meson8b
-	  and GXBB SoCs.
-	  If unsure, say N.
+source "drivers/phy/ti/Kconfig"
 
 
 endmenu
 endmenu

+ 14 - 57
drivers/phy/Makefile

@@ -3,64 +3,21 @@
 #
 #
 
 
 obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
 obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
-obj-$(CONFIG_PHY_BCM_NS_USB2)		+= phy-bcm-ns-usb2.o
-obj-$(CONFIG_PHY_BCM_NS_USB3)		+= phy-bcm-ns-usb3.o
-obj-$(CONFIG_PHY_BERLIN_USB)		+= phy-berlin-usb.o
-obj-$(CONFIG_PHY_BERLIN_SATA)		+= phy-berlin-sata.o
-obj-$(CONFIG_PHY_DA8XX_USB)		+= phy-da8xx-usb.o
-obj-$(CONFIG_PHY_DM816X_USB)		+= phy-dm816x-usb.o
-obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY)	+= phy-armada375-usb2.o
-obj-$(CONFIG_BCM_KONA_USB2_PHY)		+= phy-bcm-kona-usb2.o
-obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
-obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
 obj-$(CONFIG_PHY_LPC18XX_USB_OTG)	+= phy-lpc18xx-usb-otg.o
 obj-$(CONFIG_PHY_LPC18XX_USB_OTG)	+= phy-lpc18xx-usb-otg.o
-obj-$(CONFIG_PHY_PXA_28NM_USB2)		+= phy-pxa-28nm-usb2.o
-obj-$(CONFIG_PHY_PXA_28NM_HSIC)		+= phy-pxa-28nm-hsic.o
-obj-$(CONFIG_PHY_MVEBU_SATA)		+= phy-mvebu-sata.o
-obj-$(CONFIG_PHY_MIPHY28LP) 		+= phy-miphy28lp.o
-obj-$(CONFIG_PHY_RCAR_GEN2)		+= phy-rcar-gen2.o
-obj-$(CONFIG_PHY_RCAR_GEN3_USB2)	+= phy-rcar-gen3-usb2.o
-obj-$(CONFIG_OMAP_CONTROL_PHY)		+= phy-omap-control.o
-obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
-obj-$(CONFIG_TI_PIPE3)			+= phy-ti-pipe3.o
-obj-$(CONFIG_TWL4030_USB)		+= phy-twl4030-usb.o
-obj-$(CONFIG_PHY_EXYNOS5250_SATA)	+= phy-exynos5250-sata.o
-obj-$(CONFIG_PHY_HIX5HD2_SATA)		+= phy-hix5hd2-sata.o
-obj-$(CONFIG_PHY_HI6220_USB)		+= phy-hi6220-usb.o
 obj-$(CONFIG_PHY_MT65XX_USB3)		+= phy-mt65xx-usb3.o
 obj-$(CONFIG_PHY_MT65XX_USB3)		+= phy-mt65xx-usb3.o
-obj-$(CONFIG_PHY_SUN4I_USB)		+= phy-sun4i-usb.o
-obj-$(CONFIG_PHY_SUN9I_USB)		+= phy-sun9i-usb.o
-obj-$(CONFIG_PHY_SAMSUNG_USB2)		+= phy-exynos-usb2.o
-phy-exynos-usb2-y			+= phy-samsung-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2)	+= phy-exynos4210-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2)	+= phy-exynos4x12-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2)	+= phy-exynos5250-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2)	+= phy-s5pv210-usb2.o
-obj-$(CONFIG_PHY_EXYNOS5_USBDRD)	+= phy-exynos5-usbdrd.o
-obj-$(CONFIG_PHY_EXYNOS_PCIE)	+= phy-exynos-pcie.o
-obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)	+= phy-qcom-apq8064-sata.o
-obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
-obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2)	+= phy-rockchip-inno-usb2.o
-obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
-obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
-obj-$(CONFIG_PHY_ROCKCHIP_DP)		+= phy-rockchip-dp.o
-obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
-obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
-obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY)	+= phy-spear1310-miphy.o
-obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)	+= phy-spear1340-miphy.o
 obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
 obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
-obj-$(CONFIG_PHY_STIH407_USB)		+= phy-stih407-usb.o
-obj-$(CONFIG_PHY_QCOM_QMP)		+= phy-qcom-qmp.o
-obj-$(CONFIG_PHY_QCOM_QUSB2)		+= phy-qcom-qusb2.o
-obj-$(CONFIG_PHY_QCOM_UFS) 	+= phy-qcom-ufs.o
-obj-$(CONFIG_PHY_QCOM_UFS) 	+= phy-qcom-ufs-qmp-20nm.o
-obj-$(CONFIG_PHY_QCOM_UFS) 	+= phy-qcom-ufs-qmp-14nm.o
-obj-$(CONFIG_PHY_QCOM_USB_HS) 		+= phy-qcom-usb-hs.o
-obj-$(CONFIG_PHY_QCOM_USB_HSIC) 	+= phy-qcom-usb-hsic.o
-obj-$(CONFIG_PHY_TUSB1210)		+= phy-tusb1210.o
-obj-$(CONFIG_PHY_BRCM_SATA)		+= phy-brcm-sata.o
 obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
 obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
-obj-$(CONFIG_PHY_CYGNUS_PCIE)		+= phy-bcm-cygnus-pcie.o
-obj-$(CONFIG_ARCH_TEGRA) += tegra/
-obj-$(CONFIG_PHY_NS2_PCIE)		+= phy-bcm-ns2-pcie.o
-obj-$(CONFIG_PHY_MESON8B_USB2)		+= phy-meson8b-usb2.o
+
+obj-$(CONFIG_ARCH_SUNXI)		+= allwinner/
+obj-$(CONFIG_ARCH_MESON)		+= amlogic/
+obj-$(CONFIG_ARCH_RENESAS)		+= renesas/
+obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
+obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
+obj-y					+= broadcom/	\
+					   hisilicon/	\
+					   marvell/	\
+					   motorola/	\
+					   qualcomm/	\
+					   samsung/	\
+					   st/		\
+					   ti/

+ 31 - 0
drivers/phy/allwinner/Kconfig

@@ -0,0 +1,31 @@
+#
+# Phy drivers for Allwinner platforms
+#
+config PHY_SUN4I_USB
+	tristate "Allwinner sunxi SoC USB PHY driver"
+	depends on ARCH_SUNXI && HAS_IOMEM && OF
+	depends on RESET_CONTROLLER
+	depends on EXTCON
+	depends on POWER_SUPPLY
+	depends on USB_SUPPORT
+	select GENERIC_PHY
+	select USB_COMMON
+	help
+	  Enable this to support the transceiver that is part of Allwinner
+	  sunxi SoCs.
+
+	  This driver controls the entire USB PHY block, both the USB OTG
+	  parts, as well as the 2 regular USB 2 host PHYs.
+
+config PHY_SUN9I_USB
+	tristate "Allwinner sun9i SoC USB PHY driver"
+	depends on ARCH_SUNXI && HAS_IOMEM && OF
+	depends on RESET_CONTROLLER
+	depends on USB_SUPPORT
+	select USB_COMMON
+	select GENERIC_PHY
+	help
+	  Enable this to support the transceiver that is part of Allwinner
+	  sun9i SoCs.
+
+	  This driver controls each individual USB 2 host PHY.

+ 2 - 0
drivers/phy/allwinner/Makefile

@@ -0,0 +1,2 @@
+obj-$(CONFIG_PHY_SUN4I_USB)		+= phy-sun4i-usb.o
+obj-$(CONFIG_PHY_SUN9I_USB)		+= phy-sun9i-usb.o

+ 0 - 0
drivers/phy/phy-sun4i-usb.c → drivers/phy/allwinner/phy-sun4i-usb.c


+ 0 - 0
drivers/phy/phy-sun9i-usb.c → drivers/phy/allwinner/phy-sun9i-usb.c


+ 27 - 0
drivers/phy/amlogic/Kconfig

@@ -0,0 +1,27 @@
+#
+# Phy drivers for Amlogic platforms
+#
+config PHY_MESON8B_USB2
+	tristate "Meson8, Meson8b and GXBB USB2 PHY driver"
+	default ARCH_MESON
+	depends on OF && (ARCH_MESON || COMPILE_TEST)
+	depends on USB_SUPPORT
+	select USB_COMMON
+	select GENERIC_PHY
+	help
+	  Enable this to support the Meson USB2 PHYs found in Meson8,
+	  Meson8b and GXBB SoCs.
+	  If unsure, say N.
+
+config PHY_MESON_GXL_USB2
+	tristate "Meson GXL and GXM USB2 PHY drivers"
+	default ARCH_MESON
+	depends on OF && (ARCH_MESON || COMPILE_TEST)
+	depends on USB_SUPPORT
+	select USB_COMMON
+	select GENERIC_PHY
+	select REGMAP_MMIO
+	help
+	  Enable this to support the Meson USB2 PHYs found in Meson
+	  GXL and GXM SoCs.
+	  If unsure, say N.

+ 2 - 0
drivers/phy/amlogic/Makefile

@@ -0,0 +1,2 @@
+obj-$(CONFIG_PHY_MESON8B_USB2)		+= phy-meson8b-usb2.o
+obj-$(CONFIG_PHY_MESON_GXL_USB2)	+= phy-meson-gxl-usb2.o

+ 273 - 0
drivers/phy/amlogic/phy-meson-gxl-usb2.c

@@ -0,0 +1,273 @@
+/*
+ * Meson GXL and GXM USB2 PHY driver
+ *
+ * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/usb/of.h>
+
+/* bits [31:27] are read-only */
+#define U2P_R0							0x0
+	#define U2P_R0_BYPASS_SEL				BIT(0)
+	#define U2P_R0_BYPASS_DM_EN				BIT(1)
+	#define U2P_R0_BYPASS_DP_EN				BIT(2)
+	#define U2P_R0_TXBITSTUFF_ENH				BIT(3)
+	#define U2P_R0_TXBITSTUFF_EN				BIT(4)
+	#define U2P_R0_DM_PULLDOWN				BIT(5)
+	#define U2P_R0_DP_PULLDOWN				BIT(6)
+	#define U2P_R0_DP_VBUS_VLD_EXT_SEL			BIT(7)
+	#define U2P_R0_DP_VBUS_VLD_EXT				BIT(8)
+	#define U2P_R0_ADP_PRB_EN				BIT(9)
+	#define U2P_R0_ADP_DISCHARGE				BIT(10)
+	#define U2P_R0_ADP_CHARGE				BIT(11)
+	#define U2P_R0_DRV_VBUS					BIT(12)
+	#define U2P_R0_ID_PULLUP				BIT(13)
+	#define U2P_R0_LOOPBACK_EN_B				BIT(14)
+	#define U2P_R0_OTG_DISABLE				BIT(15)
+	#define U2P_R0_COMMON_ONN				BIT(16)
+	#define U2P_R0_FSEL_MASK				GENMASK(19, 17)
+	#define U2P_R0_REF_CLK_SEL_MASK				GENMASK(21, 20)
+	#define U2P_R0_POWER_ON_RESET				BIT(22)
+	#define U2P_R0_V_ATE_TEST_EN_B_MASK			GENMASK(24, 23)
+	#define U2P_R0_ID_SET_ID_DQ				BIT(25)
+	#define U2P_R0_ATE_RESET				BIT(26)
+	#define U2P_R0_FSV_MINUS				BIT(27)
+	#define U2P_R0_FSV_PLUS					BIT(28)
+	#define U2P_R0_BYPASS_DM_DATA				BIT(29)
+	#define U2P_R0_BYPASS_DP_DATA				BIT(30)
+
+#define U2P_R1							0x4
+	#define U2P_R1_BURN_IN_TEST				BIT(0)
+	#define U2P_R1_ACA_ENABLE				BIT(1)
+	#define U2P_R1_DCD_ENABLE				BIT(2)
+	#define U2P_R1_VDAT_SRC_EN_B				BIT(3)
+	#define U2P_R1_VDAT_DET_EN_B				BIT(4)
+	#define U2P_R1_CHARGES_SEL				BIT(5)
+	#define U2P_R1_TX_PREEMP_PULSE_TUNE			BIT(6)
+	#define U2P_R1_TX_PREEMP_AMP_TUNE_MASK			GENMASK(8, 7)
+	#define U2P_R1_TX_RES_TUNE_MASK				GENMASK(10, 9)
+	#define U2P_R1_TX_RISE_TUNE_MASK			GENMASK(12, 11)
+	#define U2P_R1_TX_VREF_TUNE_MASK			GENMASK(16, 13)
+	#define U2P_R1_TX_FSLS_TUNE_MASK			GENMASK(20, 17)
+	#define U2P_R1_TX_HSXV_TUNE_MASK			GENMASK(22, 21)
+	#define U2P_R1_OTG_TUNE_MASK				GENMASK(25, 23)
+	#define U2P_R1_SQRX_TUNE_MASK				GENMASK(28, 26)
+	#define U2P_R1_COMP_DIS_TUNE_MASK			GENMASK(31, 29)
+
+/* bits [31:14] are read-only */
+#define U2P_R2							0x8
+	#define U2P_R2_DATA_IN_MASK				GENMASK(3, 0)
+	#define U2P_R2_DATA_IN_EN_MASK				GENMASK(7, 4)
+	#define U2P_R2_ADDR_MASK				GENMASK(11, 8)
+	#define U2P_R2_DATA_OUT_SEL				BIT(12)
+	#define U2P_R2_CLK					BIT(13)
+	#define U2P_R2_DATA_OUT_MASK				GENMASK(17, 14)
+	#define U2P_R2_ACA_PIN_RANGE_C				BIT(18)
+	#define U2P_R2_ACA_PIN_RANGE_B				BIT(19)
+	#define U2P_R2_ACA_PIN_RANGE_A				BIT(20)
+	#define U2P_R2_ACA_PIN_GND				BIT(21)
+	#define U2P_R2_ACA_PIN_FLOAT				BIT(22)
+	#define U2P_R2_CHARGE_DETECT				BIT(23)
+	#define U2P_R2_DEVICE_SESSION_VALID			BIT(24)
+	#define U2P_R2_ADP_PROBE				BIT(25)
+	#define U2P_R2_ADP_SENSE				BIT(26)
+	#define U2P_R2_SESSION_END				BIT(27)
+	#define U2P_R2_VBUS_VALID				BIT(28)
+	#define U2P_R2_B_VALID					BIT(29)
+	#define U2P_R2_A_VALID					BIT(30)
+	#define U2P_R2_ID_DIG					BIT(31)
+
+#define U2P_R3							0xc
+
+#define RESET_COMPLETE_TIME				500
+
+struct phy_meson_gxl_usb2_priv {
+	struct regmap		*regmap;
+	enum phy_mode		mode;
+	int			is_enabled;
+};
+
+static const struct regmap_config phy_meson_gxl_usb2_regmap_conf = {
+	.reg_bits = 8,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = U2P_R3,
+};
+
+static int phy_meson_gxl_usb2_reset(struct phy *phy)
+{
+	struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
+
+	if (priv->is_enabled) {
+		/* reset the PHY and wait until settings are stabilized */
+		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
+				   U2P_R0_POWER_ON_RESET);
+		udelay(RESET_COMPLETE_TIME);
+		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
+				   0);
+		udelay(RESET_COMPLETE_TIME);
+	}
+
+	return 0;
+}
+
+static int phy_meson_gxl_usb2_set_mode(struct phy *phy, enum phy_mode mode)
+{
+	struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
+
+	switch (mode) {
+	case PHY_MODE_USB_HOST:
+	case PHY_MODE_USB_OTG:
+		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN,
+				   U2P_R0_DM_PULLDOWN);
+		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN,
+				   U2P_R0_DP_PULLDOWN);
+		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP, 0);
+		break;
+
+	case PHY_MODE_USB_DEVICE:
+		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN,
+				   0);
+		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN,
+				   0);
+		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP,
+				   U2P_R0_ID_PULLUP);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	phy_meson_gxl_usb2_reset(phy);
+
+	priv->mode = mode;
+
+	return 0;
+}
+
+static int phy_meson_gxl_usb2_power_off(struct phy *phy)
+{
+	struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
+
+	priv->is_enabled = 0;
+
+	/* power off the PHY by putting it into reset mode */
+	regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
+			   U2P_R0_POWER_ON_RESET);
+
+	return 0;
+}
+
+static int phy_meson_gxl_usb2_power_on(struct phy *phy)
+{
+	struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
+	int ret;
+
+	priv->is_enabled = 1;
+
+	/* power on the PHY by taking it out of reset mode */
+	regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, 0);
+
+	ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode);
+	if (ret) {
+		phy_meson_gxl_usb2_power_off(phy);
+
+		dev_err(&phy->dev, "Failed to initialize PHY with mode %d\n",
+			priv->mode);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct phy_ops phy_meson_gxl_usb2_ops = {
+	.power_on	= phy_meson_gxl_usb2_power_on,
+	.power_off	= phy_meson_gxl_usb2_power_off,
+	.set_mode	= phy_meson_gxl_usb2_set_mode,
+	.reset		= phy_meson_gxl_usb2_reset,
+	.owner		= THIS_MODULE,
+};
+
+static int phy_meson_gxl_usb2_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct phy_provider *phy_provider;
+	struct resource *res;
+	struct phy_meson_gxl_usb2_priv *priv;
+	struct phy *phy;
+	void __iomem *base;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, priv);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	switch (of_usb_get_dr_mode_by_phy(dev->of_node, -1)) {
+	case USB_DR_MODE_PERIPHERAL:
+		priv->mode = PHY_MODE_USB_DEVICE;
+		break;
+	case USB_DR_MODE_OTG:
+		priv->mode = PHY_MODE_USB_OTG;
+		break;
+	case USB_DR_MODE_HOST:
+	default:
+		priv->mode = PHY_MODE_USB_HOST;
+		break;
+	}
+
+	priv->regmap = devm_regmap_init_mmio(dev, base,
+					     &phy_meson_gxl_usb2_regmap_conf);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	phy = devm_phy_create(dev, NULL, &phy_meson_gxl_usb2_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);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id phy_meson_gxl_usb2_of_match[] = {
+	{ .compatible = "amlogic,meson-gxl-usb2-phy", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, phy_meson_gxl_usb2_of_match);
+
+static struct platform_driver phy_meson_gxl_usb2_driver = {
+	.probe	= phy_meson_gxl_usb2_probe,
+	.driver	= {
+		.name		= "phy-meson-gxl-usb2",
+		.of_match_table	= phy_meson_gxl_usb2_of_match,
+	},
+};
+module_platform_driver(phy_meson_gxl_usb2_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
+MODULE_DESCRIPTION("Meson GXL and GXM USB2 PHY driver");
+MODULE_LICENSE("GPL v2");

+ 3 - 2
drivers/phy/phy-meson8b-usb2.c → drivers/phy/amlogic/phy-meson8b-usb2.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Meson8b and GXBB USB2 PHY driver
+ * Meson8, Meson8b and GXBB USB2 PHY driver
  *
  *
  * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
  * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
  *
  *
@@ -266,6 +266,7 @@ static int phy_meson8b_usb2_probe(struct platform_device *pdev)
 }
 }
 
 
 static const struct of_device_id phy_meson8b_usb2_of_match[] = {
 static const struct of_device_id phy_meson8b_usb2_of_match[] = {
+	{ .compatible = "amlogic,meson8-usb2-phy", },
 	{ .compatible = "amlogic,meson8b-usb2-phy", },
 	{ .compatible = "amlogic,meson8b-usb2-phy", },
 	{ .compatible = "amlogic,meson-gxbb-usb2-phy", },
 	{ .compatible = "amlogic,meson-gxbb-usb2-phy", },
 	{ },
 	{ },
@@ -282,5 +283,5 @@ static struct platform_driver phy_meson8b_usb2_driver = {
 module_platform_driver(phy_meson8b_usb2_driver);
 module_platform_driver(phy_meson8b_usb2_driver);
 
 
 MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
 MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
-MODULE_DESCRIPTION("Meson8b and GXBB USB2 PHY driver");
+MODULE_DESCRIPTION("Meson8, Meson8b and GXBB USB2 PHY driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 69 - 0
drivers/phy/broadcom/Kconfig

@@ -0,0 +1,69 @@
+#
+# Phy drivers for Broadcom platforms
+#
+config PHY_CYGNUS_PCIE
+	tristate "Broadcom Cygnus PCIe PHY driver"
+	depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST)
+	select GENERIC_PHY
+	default ARCH_BCM_CYGNUS
+	help
+	  Enable this to support the Broadcom Cygnus PCIe PHY.
+	  If unsure, say N.
+
+config BCM_KONA_USB2_PHY
+	tristate "Broadcom Kona USB2 PHY Driver"
+	depends on HAS_IOMEM
+	select GENERIC_PHY
+	help
+	  Enable this to support the Broadcom Kona USB 2.0 PHY.
+
+config PHY_BCM_NS_USB2
+	tristate "Broadcom Northstar USB 2.0 PHY Driver"
+	depends on ARCH_BCM_IPROC || COMPILE_TEST
+	depends on HAS_IOMEM && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support Broadcom USB 2.0 PHY connected to the USB
+	  controller on Northstar family.
+
+config PHY_BCM_NS_USB3
+	tristate "Broadcom Northstar USB 3.0 PHY Driver"
+	depends on ARCH_BCM_IPROC || COMPILE_TEST
+	depends on HAS_IOMEM && OF
+	select GENERIC_PHY
+	select MDIO_DEVICE
+	help
+	  Enable this to support Broadcom USB 3.0 PHY connected to the USB
+	  controller on Northstar family.
+
+config PHY_NS2_PCIE
+	tristate "Broadcom Northstar2 PCIe PHY driver"
+	depends on OF && MDIO_BUS_MUX_BCM_IPROC
+	select GENERIC_PHY
+	default ARCH_BCM_IPROC
+	help
+	  Enable this to support the Broadcom Northstar2 PCIe PHY.
+	  If unsure, say N.
+
+config PHY_NS2_USB_DRD
+	tristate "Broadcom Northstar2 USB DRD PHY support"
+	depends on OF && (ARCH_BCM_IPROC || COMPILE_TEST)
+	select GENERIC_PHY
+	select EXTCON
+	default ARCH_BCM_IPROC
+	help
+	  Enable this to support the Broadcom Northstar2 USB DRD PHY.
+	  This driver initializes the PHY in either HOST or DEVICE mode.
+	  The host or device configuration is read from device tree.
+
+	  If unsure, say N.
+
+config PHY_BRCM_SATA
+	tristate "Broadcom SATA PHY driver"
+	depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	default ARCH_BCM_IPROC
+	help
+	  Enable this to support the Broadcom SATA PHY.
+	  If unsure, say N.

+ 7 - 0
drivers/phy/broadcom/Makefile

@@ -0,0 +1,7 @@
+obj-$(CONFIG_PHY_CYGNUS_PCIE)		+= phy-bcm-cygnus-pcie.o
+obj-$(CONFIG_BCM_KONA_USB2_PHY)		+= phy-bcm-kona-usb2.o
+obj-$(CONFIG_PHY_BCM_NS_USB2)		+= phy-bcm-ns-usb2.o
+obj-$(CONFIG_PHY_BCM_NS_USB3)		+= phy-bcm-ns-usb3.o
+obj-$(CONFIG_PHY_NS2_PCIE)		+= phy-bcm-ns2-pcie.o
+obj-$(CONFIG_PHY_NS2_USB_DRD)		+= phy-bcm-ns2-usbdrd.o
+obj-$(CONFIG_PHY_BRCM_SATA)		+= phy-brcm-sata.o

+ 0 - 0
drivers/phy/phy-bcm-cygnus-pcie.c → drivers/phy/broadcom/phy-bcm-cygnus-pcie.c


+ 0 - 0
drivers/phy/phy-bcm-kona-usb2.c → drivers/phy/broadcom/phy-bcm-kona-usb2.c


+ 0 - 0
drivers/phy/phy-bcm-ns-usb2.c → drivers/phy/broadcom/phy-bcm-ns-usb2.c


+ 166 - 64
drivers/phy/phy-bcm-ns-usb3.c → drivers/phy/broadcom/phy-bcm-ns-usb3.c

@@ -16,7 +16,9 @@
 #include <linux/bcma/bcma.h>
 #include <linux/bcma/bcma.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/err.h>
+#include <linux/mdio.h>
 #include <linux/module.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/phy/phy.h>
 #include <linux/phy/phy.h>
@@ -52,7 +54,10 @@ struct bcm_ns_usb3 {
 	enum bcm_ns_family family;
 	enum bcm_ns_family family;
 	void __iomem *dmp;
 	void __iomem *dmp;
 	void __iomem *ccb_mii;
 	void __iomem *ccb_mii;
+	struct mdio_device *mdiodev;
 	struct phy *phy;
 	struct phy *phy;
+
+	int (*phy_write)(struct bcm_ns_usb3 *usb3, u16 reg, u16 value);
 };
 };
 
 
 static const struct of_device_id bcm_ns_usb3_id_table[] = {
 static const struct of_device_id bcm_ns_usb3_id_table[] = {
@@ -68,63 +73,16 @@ static const struct of_device_id bcm_ns_usb3_id_table[] = {
 };
 };
 MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table);
 MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table);
 
 
-static int bcm_ns_usb3_wait_reg(struct bcm_ns_usb3 *usb3, void __iomem *addr,
-				u32 mask, u32 value, unsigned long timeout)
-{
-	unsigned long deadline = jiffies + timeout;
-	u32 val;
-
-	do {
-		val = readl(addr);
-		if ((val & mask) == value)
-			return 0;
-		cpu_relax();
-		udelay(10);
-	} while (!time_after_eq(jiffies, deadline));
-
-	dev_err(usb3->dev, "Timeout waiting for register %p\n", addr);
-
-	return -EBUSY;
-}
-
-static inline int bcm_ns_usb3_mii_mng_wait_idle(struct bcm_ns_usb3 *usb3)
-{
-	return bcm_ns_usb3_wait_reg(usb3, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL,
-				    0x0100, 0x0000,
-				    usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US));
-}
-
 static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
 static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
 				      u16 value)
 				      u16 value)
 {
 {
-	u32 tmp = 0;
-	int err;
-
-	err = bcm_ns_usb3_mii_mng_wait_idle(usb3);
-	if (err < 0) {
-		dev_err(usb3->dev, "Couldn't write 0x%08x value\n", value);
-		return err;
-	}
-
-	/* TODO: Use a proper MDIO bus layer */
-	tmp |= 0x58020000; /* Magic value for MDIO PHY write */
-	tmp |= reg << 18;
-	tmp |= value;
-	writel(tmp, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA);
-
-	return 0;
+	return usb3->phy_write(usb3, reg, value);
 }
 }
 
 
 static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
 static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
 {
 {
 	int err;
 	int err;
 
 
-	/* Enable MDIO. Setting MDCDIV as 26  */
-	writel(0x0000009a, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL);
-
-	/* Wait for MDIO? */
-	udelay(2);
-
 	/* USB3 PLL Block */
 	/* USB3 PLL Block */
 	err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
 	err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
 					 BCM_NS_USB3_PHY_PLL30_BLOCK);
 					 BCM_NS_USB3_PHY_PLL30_BLOCK);
@@ -143,9 +101,6 @@ static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
 	/* Deaaserting PLL Reset */
 	/* Deaaserting PLL Reset */
 	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0x8000);
 	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0x8000);
 
 
-	/* Waiting MII Mgt interface idle */
-	bcm_ns_usb3_mii_mng_wait_idle(usb3);
-
 	/* Deasserting USB3 system reset */
 	/* Deasserting USB3 system reset */
 	writel(0, usb3->dmp + BCMA_RESET_CTL);
 	writel(0, usb3->dmp + BCMA_RESET_CTL);
 
 
@@ -169,9 +124,6 @@ static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
 	/* Enabling SSC */
 	/* Enabling SSC */
 	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
 	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
 
 
-	/* Waiting MII Mgt interface idle */
-	bcm_ns_usb3_mii_mng_wait_idle(usb3);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -179,12 +131,6 @@ static int bcm_ns_usb3_phy_init_ns_ax(struct bcm_ns_usb3 *usb3)
 {
 {
 	int err;
 	int err;
 
 
-	/* Enable MDIO. Setting MDCDIV as 26  */
-	writel(0x0000009a, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL);
-
-	/* Wait for MDIO? */
-	udelay(2);
-
 	/* PLL30 block */
 	/* PLL30 block */
 	err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
 	err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
 					 BCM_NS_USB3_PHY_PLL30_BLOCK);
 					 BCM_NS_USB3_PHY_PLL30_BLOCK);
@@ -205,9 +151,6 @@ static int bcm_ns_usb3_phy_init_ns_ax(struct bcm_ns_usb3 *usb3)
 
 
 	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
 	bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
 
 
-	/* Waiting MII Mgt interface idle */
-	bcm_ns_usb3_mii_mng_wait_idle(usb3);
-
 	/* Deasserting USB3 system reset */
 	/* Deasserting USB3 system reset */
 	writel(0, usb3->dmp + BCMA_RESET_CTL);
 	writel(0, usb3->dmp + BCMA_RESET_CTL);
 
 
@@ -242,6 +185,128 @@ static const struct phy_ops ops = {
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,
 };
 };
 
 
+/**************************************************
+ * MDIO driver code
+ **************************************************/
+
+static int bcm_ns_usb3_mdiodev_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
+					 u16 value)
+{
+	struct mdio_device *mdiodev = usb3->mdiodev;
+
+	return mdiobus_write(mdiodev->bus, mdiodev->addr, reg, value);
+}
+
+static int bcm_ns_usb3_mdio_probe(struct mdio_device *mdiodev)
+{
+	struct device *dev = &mdiodev->dev;
+	const struct of_device_id *of_id;
+	struct phy_provider *phy_provider;
+	struct device_node *syscon_np;
+	struct bcm_ns_usb3 *usb3;
+	struct resource res;
+	int err;
+
+	usb3 = devm_kzalloc(dev, sizeof(*usb3), GFP_KERNEL);
+	if (!usb3)
+		return -ENOMEM;
+
+	usb3->dev = dev;
+	usb3->mdiodev = mdiodev;
+
+	of_id = of_match_device(bcm_ns_usb3_id_table, dev);
+	if (!of_id)
+		return -EINVAL;
+	usb3->family = (enum bcm_ns_family)of_id->data;
+
+	syscon_np = of_parse_phandle(dev->of_node, "usb3-dmp-syscon", 0);
+	err = of_address_to_resource(syscon_np, 0, &res);
+	of_node_put(syscon_np);
+	if (err)
+		return err;
+
+	usb3->dmp = devm_ioremap_resource(dev, &res);
+	if (IS_ERR(usb3->dmp)) {
+		dev_err(dev, "Failed to map DMP regs\n");
+		return PTR_ERR(usb3->dmp);
+	}
+
+	usb3->phy_write = bcm_ns_usb3_mdiodev_phy_write;
+
+	usb3->phy = devm_phy_create(dev, NULL, &ops);
+	if (IS_ERR(usb3->phy)) {
+		dev_err(dev, "Failed to create PHY\n");
+		return PTR_ERR(usb3->phy);
+	}
+
+	phy_set_drvdata(usb3->phy, usb3);
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static struct mdio_driver bcm_ns_usb3_mdio_driver = {
+	.mdiodrv = {
+		.driver = {
+			.name = "bcm_ns_mdio_usb3",
+			.of_match_table = bcm_ns_usb3_id_table,
+		},
+	},
+	.probe = bcm_ns_usb3_mdio_probe,
+};
+
+/**************************************************
+ * Platform driver code
+ **************************************************/
+
+static int bcm_ns_usb3_wait_reg(struct bcm_ns_usb3 *usb3, void __iomem *addr,
+				u32 mask, u32 value, unsigned long timeout)
+{
+	unsigned long deadline = jiffies + timeout;
+	u32 val;
+
+	do {
+		val = readl(addr);
+		if ((val & mask) == value)
+			return 0;
+		cpu_relax();
+		udelay(10);
+	} while (!time_after_eq(jiffies, deadline));
+
+	dev_err(usb3->dev, "Timeout waiting for register %p\n", addr);
+
+	return -EBUSY;
+}
+
+static inline int bcm_ns_usb3_mii_mng_wait_idle(struct bcm_ns_usb3 *usb3)
+{
+	return bcm_ns_usb3_wait_reg(usb3, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL,
+				    0x0100, 0x0000,
+				    usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US));
+}
+
+static int bcm_ns_usb3_platform_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
+					  u16 value)
+{
+	u32 tmp = 0;
+	int err;
+
+	err = bcm_ns_usb3_mii_mng_wait_idle(usb3);
+	if (err < 0) {
+		dev_err(usb3->dev, "Couldn't write 0x%08x value\n", value);
+		return err;
+	}
+
+	/* TODO: Use a proper MDIO bus layer */
+	tmp |= 0x58020000; /* Magic value for MDIO PHY write */
+	tmp |= reg << 18;
+	tmp |= value;
+	writel(tmp, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA);
+
+	return bcm_ns_usb3_mii_mng_wait_idle(usb3);
+}
+
 static int bcm_ns_usb3_probe(struct platform_device *pdev)
 static int bcm_ns_usb3_probe(struct platform_device *pdev)
 {
 {
 	struct device *dev = &pdev->dev;
 	struct device *dev = &pdev->dev;
@@ -275,6 +340,14 @@ static int bcm_ns_usb3_probe(struct platform_device *pdev)
 		return PTR_ERR(usb3->ccb_mii);
 		return PTR_ERR(usb3->ccb_mii);
 	}
 	}
 
 
+	/* Enable MDIO. Setting MDCDIV as 26  */
+	writel(0x0000009a, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL);
+
+	/* Wait for MDIO? */
+	udelay(2);
+
+	usb3->phy_write = bcm_ns_usb3_platform_phy_write;
+
 	usb3->phy = devm_phy_create(dev, NULL, &ops);
 	usb3->phy = devm_phy_create(dev, NULL, &ops);
 	if (IS_ERR(usb3->phy)) {
 	if (IS_ERR(usb3->phy)) {
 		dev_err(dev, "Failed to create PHY\n");
 		dev_err(dev, "Failed to create PHY\n");
@@ -298,6 +371,35 @@ static struct platform_driver bcm_ns_usb3_driver = {
 		.of_match_table = bcm_ns_usb3_id_table,
 		.of_match_table = bcm_ns_usb3_id_table,
 	},
 	},
 };
 };
-module_platform_driver(bcm_ns_usb3_driver);
+
+static int __init bcm_ns_usb3_module_init(void)
+{
+	int err;
+
+	/*
+	 * For backward compatibility we register as MDIO and platform driver.
+	 * After getting MDIO binding commonly used (e.g. switching all DT files
+	 * to use it) we should deprecate the old binding and eventually drop
+	 * support for it.
+	 */
+
+	err = mdio_driver_register(&bcm_ns_usb3_mdio_driver);
+	if (err)
+		return err;
+
+	err = platform_driver_register(&bcm_ns_usb3_driver);
+	if (err)
+		mdio_driver_unregister(&bcm_ns_usb3_mdio_driver);
+
+	return err;
+}
+module_init(bcm_ns_usb3_module_init);
+
+static void __exit bcm_ns_usb3_module_exit(void)
+{
+	platform_driver_unregister(&bcm_ns_usb3_driver);
+	mdio_driver_unregister(&bcm_ns_usb3_mdio_driver);
+}
+module_exit(bcm_ns_usb3_module_exit)
 
 
 MODULE_LICENSE("GPL v2");
 MODULE_LICENSE("GPL v2");

+ 0 - 0
drivers/phy/phy-bcm-ns2-pcie.c → drivers/phy/broadcom/phy-bcm-ns2-pcie.c


+ 437 - 0
drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c

@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2017 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/extcon.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#define ICFG_DRD_AFE		0x0
+#define ICFG_MISC_STAT		0x18
+#define ICFG_DRD_P0CTL		0x1C
+#define ICFG_STRAP_CTRL		0x20
+#define ICFG_FSM_CTRL		0x24
+
+#define ICFG_DEV_BIT		BIT(2)
+#define IDM_RST_BIT		BIT(0)
+#define AFE_CORERDY_VDDC	BIT(18)
+#define PHY_PLL_RESETB		BIT(15)
+#define PHY_RESETB		BIT(14)
+#define PHY_PLL_LOCK		BIT(0)
+
+#define DRD_DEV_MODE		BIT(20)
+#define OHCI_OVRCUR_POL		BIT(11)
+#define ICFG_OFF_MODE		BIT(6)
+#define PLL_LOCK_RETRY		1000
+
+#define EVT_DEVICE		0
+#define EVT_HOST		1
+
+#define DRD_HOST_MODE		(BIT(2) | BIT(3))
+#define DRD_DEVICE_MODE		(BIT(4) | BIT(5))
+#define DRD_HOST_VAL		0x803
+#define DRD_DEV_VAL		0x807
+#define GPIO_DELAY		20
+
+struct ns2_phy_data;
+struct ns2_phy_driver {
+	void __iomem *icfgdrd_regs;
+	void __iomem *idmdrd_rst_ctrl;
+	void __iomem *crmu_usb2_ctrl;
+	void __iomem *usb2h_strap_reg;
+	struct ns2_phy_data *data;
+	struct extcon_dev *edev;
+	struct gpio_desc *vbus_gpiod;
+	struct gpio_desc *id_gpiod;
+	int id_irq;
+	int vbus_irq;
+	unsigned long debounce_jiffies;
+	struct delayed_work wq_extcon;
+};
+
+struct ns2_phy_data {
+	struct ns2_phy_driver *driver;
+	struct phy *phy;
+	int new_state;
+};
+
+static const unsigned int usb_extcon_cable[] = {
+	EXTCON_USB,
+	EXTCON_USB_HOST,
+	EXTCON_NONE,
+};
+
+static inline int pll_lock_stat(u32 usb_reg, int reg_mask,
+				struct ns2_phy_driver *driver)
+{
+	int retry = PLL_LOCK_RETRY;
+	u32 val;
+
+	do {
+		udelay(1);
+		val = readl(driver->icfgdrd_regs + usb_reg);
+		if (val & reg_mask)
+			return 0;
+	} while (--retry > 0);
+
+	return -EBUSY;
+}
+
+static int ns2_drd_phy_init(struct phy *phy)
+{
+	struct ns2_phy_data *data = phy_get_drvdata(phy);
+	struct ns2_phy_driver *driver = data->driver;
+	u32 val;
+
+	val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+	if (data->new_state == EVT_HOST) {
+		val &= ~DRD_DEVICE_MODE;
+		val |= DRD_HOST_MODE;
+	} else {
+		val &= ~DRD_HOST_MODE;
+		val |= DRD_DEVICE_MODE;
+	}
+	writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+	return 0;
+}
+
+static int ns2_drd_phy_poweroff(struct phy *phy)
+{
+	struct ns2_phy_data *data = phy_get_drvdata(phy);
+	struct ns2_phy_driver *driver = data->driver;
+	u32 val;
+
+	val = readl(driver->crmu_usb2_ctrl);
+	val &= ~AFE_CORERDY_VDDC;
+	writel(val, driver->crmu_usb2_ctrl);
+
+	val = readl(driver->crmu_usb2_ctrl);
+	val &= ~DRD_DEV_MODE;
+	writel(val, driver->crmu_usb2_ctrl);
+
+	/* Disable Host and Device Mode */
+	val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
+	val &= ~(DRD_HOST_MODE | DRD_DEVICE_MODE | ICFG_OFF_MODE);
+	writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+	return 0;
+}
+
+static int ns2_drd_phy_poweron(struct phy *phy)
+{
+	struct ns2_phy_data *data = phy_get_drvdata(phy);
+	struct ns2_phy_driver *driver = data->driver;
+	u32 extcon_event = data->new_state;
+	int ret;
+	u32 val;
+
+	if (extcon_event == EVT_DEVICE) {
+		writel(DRD_DEV_VAL, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+
+		val = readl(driver->idmdrd_rst_ctrl);
+		val &= ~IDM_RST_BIT;
+		writel(val, driver->idmdrd_rst_ctrl);
+
+		val = readl(driver->crmu_usb2_ctrl);
+		val |= (AFE_CORERDY_VDDC | DRD_DEV_MODE);
+		writel(val, driver->crmu_usb2_ctrl);
+
+		/* Bring PHY and PHY_PLL out of Reset */
+		val = readl(driver->crmu_usb2_ctrl);
+		val |= (PHY_PLL_RESETB | PHY_RESETB);
+		writel(val, driver->crmu_usb2_ctrl);
+
+		ret = pll_lock_stat(ICFG_MISC_STAT, PHY_PLL_LOCK, driver);
+		if (ret < 0) {
+			dev_err(&phy->dev, "Phy PLL lock failed\n");
+			return ret;
+		}
+	} else {
+		writel(DRD_HOST_VAL, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+
+		val = readl(driver->crmu_usb2_ctrl);
+		val |= AFE_CORERDY_VDDC;
+		writel(val, driver->crmu_usb2_ctrl);
+
+		ret = pll_lock_stat(ICFG_MISC_STAT, PHY_PLL_LOCK, driver);
+		if (ret < 0) {
+			dev_err(&phy->dev, "Phy PLL lock failed\n");
+			return ret;
+		}
+
+		val = readl(driver->idmdrd_rst_ctrl);
+		val &= ~IDM_RST_BIT;
+		writel(val, driver->idmdrd_rst_ctrl);
+
+		/* port over current Polarity */
+		val = readl(driver->usb2h_strap_reg);
+		val |= OHCI_OVRCUR_POL;
+		writel(val, driver->usb2h_strap_reg);
+	}
+
+	return 0;
+}
+
+static void connect_change(struct ns2_phy_driver *driver)
+{
+	u32 extcon_event;
+	u32 val;
+
+	extcon_event = driver->data->new_state;
+	val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+	switch (extcon_event) {
+	case EVT_DEVICE:
+		val &= ~(DRD_HOST_MODE | DRD_DEVICE_MODE);
+		writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+		val = (val & ~DRD_HOST_MODE) | DRD_DEVICE_MODE;
+		writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+		val = readl(driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+		val |= ICFG_DEV_BIT;
+		writel(val, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+		break;
+
+	case EVT_HOST:
+		val &= ~(DRD_HOST_MODE | DRD_DEVICE_MODE);
+		writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+		val = (val & ~DRD_DEVICE_MODE) | DRD_HOST_MODE;
+		writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+		val = readl(driver->usb2h_strap_reg);
+		val |= OHCI_OVRCUR_POL;
+		writel(val, driver->usb2h_strap_reg);
+
+		val = readl(driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+		val &= ~ICFG_DEV_BIT;
+		writel(val, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+		break;
+
+	default:
+		pr_err("Invalid extcon event\n");
+		break;
+	}
+}
+
+static void extcon_work(struct work_struct *work)
+{
+	struct ns2_phy_driver *driver;
+	int vbus;
+	int id;
+
+	driver  = container_of(to_delayed_work(work),
+			       struct ns2_phy_driver, wq_extcon);
+
+	id = gpiod_get_value_cansleep(driver->id_gpiod);
+	vbus = gpiod_get_value_cansleep(driver->vbus_gpiod);
+
+	if (!id && vbus) { /* Host connected */
+		extcon_set_cable_state_(driver->edev, EXTCON_USB_HOST, true);
+		pr_debug("Host cable connected\n");
+		driver->data->new_state = EVT_HOST;
+		connect_change(driver);
+	} else if (id && !vbus) { /* Disconnected */
+		extcon_set_cable_state_(driver->edev, EXTCON_USB_HOST, false);
+		extcon_set_cable_state_(driver->edev, EXTCON_USB, false);
+		pr_debug("Cable disconnected\n");
+	} else if (id && vbus) { /* Device connected */
+		extcon_set_cable_state_(driver->edev, EXTCON_USB, true);
+		pr_debug("Device cable connected\n");
+		driver->data->new_state = EVT_DEVICE;
+		connect_change(driver);
+	}
+}
+
+static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+{
+	struct ns2_phy_driver *driver = dev_id;
+
+	queue_delayed_work(system_power_efficient_wq, &driver->wq_extcon,
+			   driver->debounce_jiffies);
+
+	return IRQ_HANDLED;
+}
+
+static struct phy_ops ops = {
+	.init		= ns2_drd_phy_init,
+	.power_on	= ns2_drd_phy_poweron,
+	.power_off	= ns2_drd_phy_poweroff,
+	.owner		= THIS_MODULE,
+};
+
+static const struct of_device_id ns2_drd_phy_dt_ids[] = {
+	{ .compatible = "brcm,ns2-drd-phy", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ns2_drd_phy_dt_ids);
+
+static int ns2_drd_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct ns2_phy_driver *driver;
+	struct ns2_phy_data *data;
+	struct resource *res;
+	int ret;
+	u32 val;
+
+	driver = devm_kzalloc(dev, sizeof(struct ns2_phy_driver),
+			      GFP_KERNEL);
+	if (!driver)
+		return -ENOMEM;
+
+	driver->data = devm_kzalloc(dev, sizeof(struct ns2_phy_data),
+				  GFP_KERNEL);
+	if (!driver->data)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icfg");
+	driver->icfgdrd_regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(driver->icfgdrd_regs))
+		return PTR_ERR(driver->icfgdrd_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rst-ctrl");
+	driver->idmdrd_rst_ctrl = devm_ioremap_resource(dev, res);
+	if (IS_ERR(driver->idmdrd_rst_ctrl))
+		return PTR_ERR(driver->idmdrd_rst_ctrl);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crmu-ctrl");
+	driver->crmu_usb2_ctrl = devm_ioremap_resource(dev, res);
+	if (IS_ERR(driver->crmu_usb2_ctrl))
+		return PTR_ERR(driver->crmu_usb2_ctrl);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "usb2-strap");
+	driver->usb2h_strap_reg = devm_ioremap_resource(dev, res);
+	if (IS_ERR(driver->usb2h_strap_reg))
+		return PTR_ERR(driver->usb2h_strap_reg);
+
+	 /* create extcon */
+	driver->id_gpiod = devm_gpiod_get(&pdev->dev, "id", GPIOD_IN);
+	if (IS_ERR(driver->id_gpiod)) {
+		dev_err(dev, "failed to get ID GPIO\n");
+		return PTR_ERR(driver->id_gpiod);
+	}
+	driver->vbus_gpiod = devm_gpiod_get(&pdev->dev, "vbus", GPIOD_IN);
+	if (IS_ERR(driver->vbus_gpiod)) {
+		dev_err(dev, "failed to get VBUS GPIO\n");
+		return PTR_ERR(driver->vbus_gpiod);
+	}
+
+	driver->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
+	if (IS_ERR(driver->edev)) {
+		dev_err(dev, "failed to allocate extcon device\n");
+		return -ENOMEM;
+	}
+
+	ret = devm_extcon_dev_register(dev, driver->edev);
+	if (ret < 0) {
+		dev_err(dev, "failed to register extcon device\n");
+		return ret;
+	}
+
+	ret = gpiod_set_debounce(driver->id_gpiod, GPIO_DELAY * 1000);
+	if (ret < 0)
+		driver->debounce_jiffies = msecs_to_jiffies(GPIO_DELAY);
+
+	INIT_DELAYED_WORK(&driver->wq_extcon, extcon_work);
+
+	driver->id_irq = gpiod_to_irq(driver->id_gpiod);
+	if (driver->id_irq < 0) {
+		dev_err(dev, "failed to get ID IRQ\n");
+		return driver->id_irq;
+	}
+
+	driver->vbus_irq = gpiod_to_irq(driver->vbus_gpiod);
+	if (driver->vbus_irq < 0) {
+		dev_err(dev, "failed to get ID IRQ\n");
+		return driver->vbus_irq;
+	}
+
+	ret = devm_request_irq(dev, driver->id_irq, gpio_irq_handler,
+			       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+			       "usb_id", driver);
+	if (ret < 0) {
+		dev_err(dev, "failed to request handler for ID IRQ\n");
+		return ret;
+	}
+
+	ret = devm_request_irq(dev, driver->vbus_irq, gpio_irq_handler,
+			       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+			       "usb_vbus", driver);
+	if (ret < 0) {
+		dev_err(dev, "failed to request handler for VBUS IRQ\n");
+		return ret;
+	}
+
+	dev_set_drvdata(dev, driver);
+
+	/* Shutdown all ports. They can be powered up as required */
+	val = readl(driver->crmu_usb2_ctrl);
+	val &= ~(AFE_CORERDY_VDDC | PHY_RESETB);
+	writel(val, driver->crmu_usb2_ctrl);
+
+	data = driver->data;
+	data->phy = devm_phy_create(dev, dev->of_node, &ops);
+	if (IS_ERR(data->phy)) {
+		dev_err(dev, "Failed to create usb drd phy\n");
+		return PTR_ERR(data->phy);
+	}
+
+	data->driver = driver;
+	phy_set_drvdata(data->phy, data);
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider)) {
+		dev_err(dev, "Failed to register as phy provider\n");
+		return PTR_ERR(phy_provider);
+	}
+
+	platform_set_drvdata(pdev, driver);
+
+	dev_info(dev, "Registered NS2 DRD Phy device\n");
+	queue_delayed_work(system_power_efficient_wq, &driver->wq_extcon,
+			   driver->debounce_jiffies);
+
+	return 0;
+}
+
+static struct platform_driver ns2_drd_phy_driver = {
+	.probe = ns2_drd_phy_probe,
+	.driver = {
+		.name = "bcm-ns2-usbphy",
+		.of_match_table = of_match_ptr(ns2_drd_phy_dt_ids),
+	},
+};
+module_platform_driver(ns2_drd_phy_driver);
+
+MODULE_ALIAS("platform:bcm-ns2-drd-phy");
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Broadcom NS2 USB2 PHY driver");
+MODULE_LICENSE("GPL v2");

+ 73 - 0
drivers/phy/phy-brcm-sata.c → drivers/phy/broadcom/phy-brcm-sata.c

@@ -46,6 +46,7 @@ enum brcm_sata_phy_version {
 	BRCM_SATA_PHY_STB_40NM,
 	BRCM_SATA_PHY_STB_40NM,
 	BRCM_SATA_PHY_IPROC_NS2,
 	BRCM_SATA_PHY_IPROC_NS2,
 	BRCM_SATA_PHY_IPROC_NSP,
 	BRCM_SATA_PHY_IPROC_NSP,
+	BRCM_SATA_PHY_IPROC_SR,
 };
 };
 
 
 struct brcm_sata_port {
 struct brcm_sata_port {
@@ -81,12 +82,17 @@ enum sata_phy_regs {
 	PLL_ACTRL2				= 0x8b,
 	PLL_ACTRL2				= 0x8b,
 	PLL_ACTRL2_SELDIV_MASK			= 0x1f,
 	PLL_ACTRL2_SELDIV_MASK			= 0x1f,
 	PLL_ACTRL2_SELDIV_SHIFT			= 9,
 	PLL_ACTRL2_SELDIV_SHIFT			= 9,
+	PLL_ACTRL6				= 0x86,
 
 
 	PLL1_REG_BANK				= 0x060,
 	PLL1_REG_BANK				= 0x060,
 	PLL1_ACTRL2				= 0x82,
 	PLL1_ACTRL2				= 0x82,
 	PLL1_ACTRL3				= 0x83,
 	PLL1_ACTRL3				= 0x83,
 	PLL1_ACTRL4				= 0x84,
 	PLL1_ACTRL4				= 0x84,
 
 
+	TX_REG_BANK				= 0x070,
+	TX_ACTRL0				= 0x80,
+	TX_ACTRL0_TXPOL_FLIP			= BIT(6),
+
 	OOB_REG_BANK				= 0x150,
 	OOB_REG_BANK				= 0x150,
 	OOB1_REG_BANK				= 0x160,
 	OOB1_REG_BANK				= 0x160,
 	OOB_CTRL1				= 0x80,
 	OOB_CTRL1				= 0x80,
@@ -347,6 +353,68 @@ static int brcm_nsp_sata_init(struct brcm_sata_port *port)
 	return 0;
 	return 0;
 }
 }
 
 
+/* SR PHY PLL0 registers */
+#define SR_PLL0_ACTRL6_MAGIC			0xa
+
+/* SR PHY PLL1 registers */
+#define SR_PLL1_ACTRL2_MAGIC			0x32
+#define SR_PLL1_ACTRL3_MAGIC			0x2
+#define SR_PLL1_ACTRL4_MAGIC			0x3e8
+
+static int brcm_sr_sata_init(struct brcm_sata_port *port)
+{
+	struct brcm_sata_phy *priv = port->phy_priv;
+	struct device *dev = port->phy_priv->dev;
+	void __iomem *base = priv->phy_base;
+	unsigned int val, try;
+
+	/* Configure PHY PLL register bank 1 */
+	val = SR_PLL1_ACTRL2_MAGIC;
+	brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
+	val = SR_PLL1_ACTRL3_MAGIC;
+	brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
+	val = SR_PLL1_ACTRL4_MAGIC;
+	brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
+
+	/* Configure PHY PLL register bank 0 */
+	val = SR_PLL0_ACTRL6_MAGIC;
+	brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_ACTRL6, 0x0, val);
+
+	/* Wait for PHY PLL lock by polling pll_lock bit */
+	try = 50;
+	do {
+		val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
+					BLOCK0_XGXSSTATUS);
+		if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
+			break;
+		msleep(20);
+		try--;
+	} while (try);
+
+	if ((val & BLOCK0_XGXSSTATUS_PLL_LOCK) == 0) {
+		/* PLL did not lock; give up */
+		dev_err(dev, "port%d PLL did not lock\n", port->portnum);
+		return -ETIMEDOUT;
+	}
+
+	/* Invert Tx polarity */
+	brcm_sata_phy_wr(base, TX_REG_BANK, TX_ACTRL0,
+			 ~TX_ACTRL0_TXPOL_FLIP, TX_ACTRL0_TXPOL_FLIP);
+
+	/* Configure OOB control to handle 100MHz reference clock */
+	val = ((0xc << OOB_CTRL1_BURST_MAX_SHIFT) |
+		(0x4 << OOB_CTRL1_BURST_MIN_SHIFT) |
+		(0x8 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT) |
+		(0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT));
+	brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
+	val = ((0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT) |
+		(0x2 << OOB_CTRL2_BURST_CNT_SHIFT) |
+		(0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT));
+	brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
+
+	return 0;
+}
+
 static int brcm_sata_phy_init(struct phy *phy)
 static int brcm_sata_phy_init(struct phy *phy)
 {
 {
 	int rc;
 	int rc;
@@ -363,6 +431,9 @@ static int brcm_sata_phy_init(struct phy *phy)
 	case BRCM_SATA_PHY_IPROC_NSP:
 	case BRCM_SATA_PHY_IPROC_NSP:
 		rc = brcm_nsp_sata_init(port);
 		rc = brcm_nsp_sata_init(port);
 		break;
 		break;
+	case BRCM_SATA_PHY_IPROC_SR:
+		rc = brcm_sr_sata_init(port);
+		break;
 	default:
 	default:
 		rc = -ENODEV;
 		rc = -ENODEV;
 	}
 	}
@@ -384,6 +455,8 @@ static const struct of_device_id brcm_sata_phy_of_match[] = {
 	  .data = (void *)BRCM_SATA_PHY_IPROC_NS2 },
 	  .data = (void *)BRCM_SATA_PHY_IPROC_NS2 },
 	{ .compatible = "brcm,iproc-nsp-sata-phy",
 	{ .compatible = "brcm,iproc-nsp-sata-phy",
 	  .data = (void *)BRCM_SATA_PHY_IPROC_NSP },
 	  .data = (void *)BRCM_SATA_PHY_IPROC_NSP },
+	{ .compatible	= "brcm,iproc-sr-sata-phy",
+	  .data = (void *)BRCM_SATA_PHY_IPROC_SR },
 	{},
 	{},
 };
 };
 MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);
 MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);

+ 20 - 0
drivers/phy/hisilicon/Kconfig

@@ -0,0 +1,20 @@
+#
+# Phy drivers for Hisilicon platforms
+#
+config PHY_HI6220_USB
+	tristate "hi6220 USB PHY support"
+	depends on (ARCH_HISI && ARM64) || COMPILE_TEST
+	select GENERIC_PHY
+	select MFD_SYSCON
+	help
+	  Enable this to support the HISILICON HI6220 USB PHY.
+
+	  To compile this driver as a module, choose M here.
+
+config PHY_HIX5HD2_SATA
+	tristate "HIX5HD2 SATA PHY Driver"
+	depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
+	select GENERIC_PHY
+	select MFD_SYSCON
+	help
+	  Support for SATA PHY on Hisilicon hix5hd2 Soc.

+ 2 - 0
drivers/phy/hisilicon/Makefile

@@ -0,0 +1,2 @@
+obj-$(CONFIG_PHY_HI6220_USB)		+= phy-hi6220-usb.o
+obj-$(CONFIG_PHY_HIX5HD2_SATA)		+= phy-hix5hd2-sata.o

+ 0 - 0
drivers/phy/phy-hi6220-usb.c → drivers/phy/hisilicon/phy-hi6220-usb.c


+ 0 - 0
drivers/phy/phy-hix5hd2-sata.c → drivers/phy/hisilicon/phy-hix5hd2-sata.c


+ 50 - 0
drivers/phy/marvell/Kconfig

@@ -0,0 +1,50 @@
+#
+# Phy drivers for Marvell platforms
+#
+config ARMADA375_USBCLUSTER_PHY
+	def_bool y
+	depends on MACH_ARMADA_375 || COMPILE_TEST
+	depends on OF && HAS_IOMEM
+	select GENERIC_PHY
+
+config PHY_BERLIN_SATA
+	tristate "Marvell Berlin SATA PHY driver"
+	depends on ARCH_BERLIN && HAS_IOMEM && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the SATA PHY on Marvell Berlin SoCs.
+
+config PHY_BERLIN_USB
+	tristate "Marvell Berlin USB PHY Driver"
+	depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the USB PHY on Marvell Berlin SoCs.
+
+config PHY_MVEBU_SATA
+	def_bool y
+	depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
+	depends on OF
+	select GENERIC_PHY
+
+config PHY_PXA_28NM_HSIC
+	tristate "Marvell USB HSIC 28nm PHY Driver"
+	depends on HAS_IOMEM
+	select GENERIC_PHY
+	help
+	  Enable this to support Marvell USB HSIC PHY driver for Marvell
+	  SoC. This driver will do the PHY initialization and shutdown.
+	  The PHY driver will be used by Marvell ehci driver.
+
+	  To compile this driver as a module, choose M here.
+
+config PHY_PXA_28NM_USB2
+	tristate "Marvell USB 2.0 28nm PHY Driver"
+	depends on HAS_IOMEM
+	select GENERIC_PHY
+	help
+	  Enable this to support Marvell USB 2.0 PHY driver for Marvell
+	  SoC. This driver will do the PHY initialization and shutdown.
+	  The PHY driver will be used by Marvell udc/ehci/otg driver.
+
+	  To compile this driver as a module, choose M here.

+ 6 - 0
drivers/phy/marvell/Makefile

@@ -0,0 +1,6 @@
+obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY)	+= phy-armada375-usb2.o
+obj-$(CONFIG_PHY_BERLIN_SATA)		+= phy-berlin-sata.o
+obj-$(CONFIG_PHY_BERLIN_USB)		+= phy-berlin-usb.o
+obj-$(CONFIG_PHY_MVEBU_SATA)		+= phy-mvebu-sata.o
+obj-$(CONFIG_PHY_PXA_28NM_HSIC)		+= phy-pxa-28nm-hsic.o
+obj-$(CONFIG_PHY_PXA_28NM_USB2)		+= phy-pxa-28nm-usb2.o

+ 0 - 0
drivers/phy/phy-armada375-usb2.c → drivers/phy/marvell/phy-armada375-usb2.c


+ 0 - 0
drivers/phy/phy-berlin-sata.c → drivers/phy/marvell/phy-berlin-sata.c


+ 0 - 0
drivers/phy/phy-berlin-usb.c → drivers/phy/marvell/phy-berlin-usb.c


+ 0 - 0
drivers/phy/phy-mvebu-sata.c → drivers/phy/marvell/phy-mvebu-sata.c


+ 0 - 0
drivers/phy/phy-pxa-28nm-hsic.c → drivers/phy/marvell/phy-pxa-28nm-hsic.c


+ 0 - 0
drivers/phy/phy-pxa-28nm-usb2.c → drivers/phy/marvell/phy-pxa-28nm-usb2.c


+ 12 - 0
drivers/phy/motorola/Kconfig

@@ -0,0 +1,12 @@
+#
+# Phy drivers for Motorola devices
+#
+config PHY_CPCAP_USB
+	tristate "CPCAP PMIC USB PHY driver"
+	depends on USB_SUPPORT && IIO
+	depends on USB_MUSB_HDRC || USB_MUSB_HDRC=n
+	select GENERIC_PHY
+	select USB_PHY
+	help
+	  Enable this for USB to work on Motorola phones and tablets
+	  such as Droid 4.

+ 5 - 0
drivers/phy/motorola/Makefile

@@ -0,0 +1,5 @@
+#
+# Makefile for the phy drivers.
+#
+
+obj-$(CONFIG_PHY_CPCAP_USB)		+= phy-cpcap-usb.o

+ 676 - 0
drivers/phy/motorola/phy-cpcap-usb.c

@@ -0,0 +1,676 @@
+/*
+ * Motorola CPCAP PMIC USB PHY driver
+ * Copyright (C) 2017 Tony Lindgren <tony@atomide.com>
+ *
+ * Some parts based on earlier Motorola Linux kernel tree code in
+ * board-mapphone-usb.c and cpcap-usb-det.c:
+ * Copyright (C) 2007 - 2011 Motorola, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/iio/consumer.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/mfd/motorola-cpcap.h>
+#include <linux/phy/omap_usb.h>
+#include <linux/phy/phy.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/musb.h>
+
+/* CPCAP_REG_USBC1 register bits */
+#define CPCAP_BIT_IDPULSE		BIT(15)
+#define CPCAP_BIT_ID100KPU		BIT(14)
+#define CPCAP_BIT_IDPUCNTRL		BIT(13)
+#define CPCAP_BIT_IDPU			BIT(12)
+#define CPCAP_BIT_IDPD			BIT(11)
+#define CPCAP_BIT_VBUSCHRGTMR3		BIT(10)
+#define CPCAP_BIT_VBUSCHRGTMR2		BIT(9)
+#define CPCAP_BIT_VBUSCHRGTMR1		BIT(8)
+#define CPCAP_BIT_VBUSCHRGTMR0		BIT(7)
+#define CPCAP_BIT_VBUSPU		BIT(6)
+#define CPCAP_BIT_VBUSPD		BIT(5)
+#define CPCAP_BIT_DMPD			BIT(4)
+#define CPCAP_BIT_DPPD			BIT(3)
+#define CPCAP_BIT_DM1K5PU		BIT(2)
+#define CPCAP_BIT_DP1K5PU		BIT(1)
+#define CPCAP_BIT_DP150KPU		BIT(0)
+
+/* CPCAP_REG_USBC2 register bits */
+#define CPCAP_BIT_ZHSDRV1		BIT(15)
+#define CPCAP_BIT_ZHSDRV0		BIT(14)
+#define CPCAP_BIT_DPLLCLKREQ		BIT(13)
+#define CPCAP_BIT_SE0CONN		BIT(12)
+#define CPCAP_BIT_UARTTXTRI		BIT(11)
+#define CPCAP_BIT_UARTSWAP		BIT(10)
+#define CPCAP_BIT_UARTMUX1		BIT(9)
+#define CPCAP_BIT_UARTMUX0		BIT(8)
+#define CPCAP_BIT_ULPISTPLOW		BIT(7)
+#define CPCAP_BIT_TXENPOL		BIT(6)
+#define CPCAP_BIT_USBXCVREN		BIT(5)
+#define CPCAP_BIT_USBCNTRL		BIT(4)
+#define CPCAP_BIT_USBSUSPEND		BIT(3)
+#define CPCAP_BIT_EMUMODE2		BIT(2)
+#define CPCAP_BIT_EMUMODE1		BIT(1)
+#define CPCAP_BIT_EMUMODE0		BIT(0)
+
+/* CPCAP_REG_USBC3 register bits */
+#define CPCAP_BIT_SPARE_898_15		BIT(15)
+#define CPCAP_BIT_IHSTX03		BIT(14)
+#define CPCAP_BIT_IHSTX02		BIT(13)
+#define CPCAP_BIT_IHSTX01		BIT(12)
+#define CPCAP_BIT_IHSTX0		BIT(11)
+#define CPCAP_BIT_IDPU_SPI		BIT(10)
+#define CPCAP_BIT_UNUSED_898_9		BIT(9)
+#define CPCAP_BIT_VBUSSTBY_EN		BIT(8)
+#define CPCAP_BIT_VBUSEN_SPI		BIT(7)
+#define CPCAP_BIT_VBUSPU_SPI		BIT(6)
+#define CPCAP_BIT_VBUSPD_SPI		BIT(5)
+#define CPCAP_BIT_DMPD_SPI		BIT(4)
+#define CPCAP_BIT_DPPD_SPI		BIT(3)
+#define CPCAP_BIT_SUSPEND_SPI		BIT(2)
+#define CPCAP_BIT_PU_SPI		BIT(1)
+#define CPCAP_BIT_ULPI_SPI_SEL		BIT(0)
+
+struct cpcap_usb_ints_state {
+	bool id_ground;
+	bool id_float;
+	bool chrg_det;
+	bool rvrs_chrg;
+	bool vbusov;
+
+	bool chrg_se1b;
+	bool se0conn;
+	bool rvrs_mode;
+	bool chrgcurr1;
+	bool vbusvld;
+	bool sessvld;
+	bool sessend;
+	bool se1;
+
+	bool battdetb;
+	bool dm;
+	bool dp;
+};
+
+enum cpcap_gpio_mode {
+	CPCAP_DM_DP,
+	CPCAP_MDM_RX_TX,
+	CPCAP_UNKNOWN,
+	CPCAP_OTG_DM_DP,
+};
+
+struct cpcap_phy_ddata {
+	struct regmap *reg;
+	struct device *dev;
+	struct clk *refclk;
+	struct usb_phy phy;
+	struct delayed_work detect_work;
+	struct pinctrl *pins;
+	struct pinctrl_state *pins_ulpi;
+	struct pinctrl_state *pins_utmi;
+	struct pinctrl_state *pins_uart;
+	struct gpio_desc *gpio[2];
+	struct iio_channel *vbus;
+	struct iio_channel *id;
+	struct regulator *vusb;
+	atomic_t active;
+};
+
+static bool cpcap_usb_vbus_valid(struct cpcap_phy_ddata *ddata)
+{
+	int error, value = 0;
+
+	error = iio_read_channel_processed(ddata->vbus, &value);
+	if (error >= 0)
+		return value > 3900 ? true : false;
+
+	dev_err(ddata->dev, "error reading VBUS: %i\n", error);
+
+	return false;
+}
+
+static int cpcap_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	otg->host = host;
+	if (!host)
+		otg->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int cpcap_usb_phy_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
+{
+	otg->gadget = gadget;
+	if (!gadget)
+		otg->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static const struct phy_ops ops = {
+	.owner		= THIS_MODULE,
+};
+
+static int cpcap_phy_get_ints_state(struct cpcap_phy_ddata *ddata,
+				    struct cpcap_usb_ints_state *s)
+{
+	int val, error;
+
+	error = regmap_read(ddata->reg, CPCAP_REG_INTS1, &val);
+	if (error)
+		return error;
+
+	s->id_ground = val & BIT(15);
+	s->id_float = val & BIT(14);
+	s->vbusov = val & BIT(11);
+
+	error = regmap_read(ddata->reg, CPCAP_REG_INTS2, &val);
+	if (error)
+		return error;
+
+	s->vbusvld = val & BIT(3);
+	s->sessvld = val & BIT(2);
+	s->sessend = val & BIT(1);
+	s->se1 = val & BIT(0);
+
+	error = regmap_read(ddata->reg, CPCAP_REG_INTS4, &val);
+	if (error)
+		return error;
+
+	s->dm = val & BIT(1);
+	s->dp = val & BIT(0);
+
+	return 0;
+}
+
+static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata);
+static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata);
+
+static void cpcap_usb_detect(struct work_struct *work)
+{
+	struct cpcap_phy_ddata *ddata;
+	struct cpcap_usb_ints_state s;
+	bool vbus = false;
+	int error;
+
+	ddata = container_of(work, struct cpcap_phy_ddata, detect_work.work);
+
+	error = cpcap_phy_get_ints_state(ddata, &s);
+	if (error)
+		return;
+
+	if (s.id_ground) {
+		dev_dbg(ddata->dev, "id ground, USB host mode\n");
+		error = cpcap_usb_set_usb_mode(ddata);
+		if (error)
+			goto out_err;
+
+		error = musb_mailbox(MUSB_ID_GROUND);
+		if (error)
+			goto out_err;
+
+		error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
+					   CPCAP_BIT_VBUSSTBY_EN,
+					   CPCAP_BIT_VBUSSTBY_EN);
+		if (error)
+			goto out_err;
+
+		return;
+	}
+
+	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
+				   CPCAP_BIT_VBUSSTBY_EN, 0);
+	if (error)
+		goto out_err;
+
+	vbus = cpcap_usb_vbus_valid(ddata);
+
+	if (vbus) {
+		/* Are we connected to a docking station with vbus? */
+		if (s.id_ground) {
+			dev_dbg(ddata->dev, "connected to a dock\n");
+
+			/* No VBUS needed with docks */
+			error = cpcap_usb_set_usb_mode(ddata);
+			if (error)
+				goto out_err;
+			error = musb_mailbox(MUSB_ID_GROUND);
+			if (error)
+				goto out_err;
+
+			return;
+		}
+
+		/* Otherwise assume we're connected to a USB host */
+		dev_dbg(ddata->dev, "connected to USB host\n");
+		error = cpcap_usb_set_usb_mode(ddata);
+		if (error)
+			goto out_err;
+		error = musb_mailbox(MUSB_VBUS_VALID);
+		if (error)
+			goto out_err;
+
+		return;
+	}
+
+	/* Default to debug UART mode */
+	error = cpcap_usb_set_uart_mode(ddata);
+	if (error)
+		goto out_err;
+
+	error = musb_mailbox(MUSB_VBUS_OFF);
+	if (error)
+		goto out_err;
+
+	dev_dbg(ddata->dev, "set UART mode\n");
+
+	return;
+
+out_err:
+	dev_err(ddata->dev, "error setting cable state: %i\n", error);
+}
+
+static irqreturn_t cpcap_phy_irq_thread(int irq, void *data)
+{
+	struct cpcap_phy_ddata *ddata = data;
+
+	if (!atomic_read(&ddata->active))
+		return IRQ_NONE;
+
+	schedule_delayed_work(&ddata->detect_work, msecs_to_jiffies(1));
+
+	return IRQ_HANDLED;
+}
+
+static int cpcap_usb_init_irq(struct platform_device *pdev,
+			      struct cpcap_phy_ddata *ddata,
+			      const char *name)
+{
+	int irq, error;
+
+	irq = platform_get_irq_byname(pdev, name);
+	if (!irq)
+		return -ENODEV;
+
+	error = devm_request_threaded_irq(ddata->dev, irq, NULL,
+					  cpcap_phy_irq_thread,
+					  IRQF_SHARED,
+					  name, ddata);
+	if (error) {
+		dev_err(ddata->dev, "could not get irq %s: %i\n",
+			name, error);
+
+		return error;
+	}
+
+	return 0;
+}
+
+static const char * const cpcap_phy_irqs[] = {
+	/* REG_INT_0 */
+	"id_ground", "id_float",
+
+	/* REG_INT1 */
+	"se0conn", "vbusvld", "sessvld", "sessend", "se1",
+
+	/* REG_INT_3 */
+	"dm", "dp",
+};
+
+static int cpcap_usb_init_interrupts(struct platform_device *pdev,
+				     struct cpcap_phy_ddata *ddata)
+{
+	int i, error;
+
+	for (i = 0; i < ARRAY_SIZE(cpcap_phy_irqs); i++) {
+		error = cpcap_usb_init_irq(pdev, ddata, cpcap_phy_irqs[i]);
+		if (error)
+			return error;
+	}
+
+	return 0;
+}
+
+/*
+ * Optional pins and modes. At least Motorola mapphone devices
+ * are using two GPIOs and dynamic pinctrl to multiplex PHY pins
+ * to UART, ULPI or UTMI mode.
+ */
+
+static int cpcap_usb_gpio_set_mode(struct cpcap_phy_ddata *ddata,
+				   enum cpcap_gpio_mode mode)
+{
+	if (!ddata->gpio[0] || !ddata->gpio[1])
+		return 0;
+
+	gpiod_set_value(ddata->gpio[0], mode & 1);
+	gpiod_set_value(ddata->gpio[1], mode >> 1);
+
+	return 0;
+}
+
+static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
+{
+	int error;
+
+	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
+	if (error)
+		goto out_err;
+
+	if (ddata->pins_uart) {
+		error = pinctrl_select_state(ddata->pins, ddata->pins_uart);
+		if (error)
+			goto out_err;
+	}
+
+	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
+				   CPCAP_BIT_VBUSPD,
+				   CPCAP_BIT_VBUSPD);
+	if (error)
+		goto out_err;
+
+	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
+				   0xffff, CPCAP_BIT_UARTMUX0 |
+				   CPCAP_BIT_EMUMODE0);
+	if (error)
+		goto out_err;
+
+	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3, 0x7fff,
+				   CPCAP_BIT_IDPU_SPI);
+	if (error)
+		goto out_err;
+
+	return 0;
+
+out_err:
+	dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
+
+	return error;
+}
+
+static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
+{
+	int error;
+
+	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
+	if (error)
+		return error;
+
+	if (ddata->pins_utmi) {
+		error = pinctrl_select_state(ddata->pins, ddata->pins_utmi);
+		if (error) {
+			dev_err(ddata->dev, "could not set usb mode: %i\n",
+				error);
+
+			return error;
+		}
+	}
+
+	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
+				   CPCAP_BIT_VBUSPD, 0);
+	if (error)
+		goto out_err;
+
+	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
+				   CPCAP_BIT_USBXCVREN,
+				   CPCAP_BIT_USBXCVREN);
+	if (error)
+		goto out_err;
+
+	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
+				   CPCAP_BIT_PU_SPI |
+				   CPCAP_BIT_DMPD_SPI |
+				   CPCAP_BIT_DPPD_SPI |
+				   CPCAP_BIT_SUSPEND_SPI |
+				   CPCAP_BIT_ULPI_SPI_SEL, 0);
+	if (error)
+		goto out_err;
+
+	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
+				   CPCAP_BIT_USBXCVREN,
+				   CPCAP_BIT_USBXCVREN);
+	if (error)
+		goto out_err;
+
+	return 0;
+
+out_err:
+	dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
+
+	return error;
+}
+
+static int cpcap_usb_init_optional_pins(struct cpcap_phy_ddata *ddata)
+{
+	ddata->pins = devm_pinctrl_get(ddata->dev);
+	if (IS_ERR(ddata->pins)) {
+		dev_info(ddata->dev, "default pins not configured: %ld\n",
+			 PTR_ERR(ddata->pins));
+		ddata->pins = NULL;
+
+		return 0;
+	}
+
+	ddata->pins_ulpi = pinctrl_lookup_state(ddata->pins, "ulpi");
+	if (IS_ERR(ddata->pins_ulpi)) {
+		dev_info(ddata->dev, "ulpi pins not configured\n");
+		ddata->pins_ulpi = NULL;
+	}
+
+	ddata->pins_utmi = pinctrl_lookup_state(ddata->pins, "utmi");
+	if (IS_ERR(ddata->pins_utmi)) {
+		dev_info(ddata->dev, "utmi pins not configured\n");
+		ddata->pins_utmi = NULL;
+	}
+
+	ddata->pins_uart = pinctrl_lookup_state(ddata->pins, "uart");
+	if (IS_ERR(ddata->pins_uart)) {
+		dev_info(ddata->dev, "uart pins not configured\n");
+		ddata->pins_uart = NULL;
+	}
+
+	if (ddata->pins_uart)
+		return pinctrl_select_state(ddata->pins, ddata->pins_uart);
+
+	return 0;
+}
+
+static void cpcap_usb_init_optional_gpios(struct cpcap_phy_ddata *ddata)
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		ddata->gpio[i] = devm_gpiod_get_index(ddata->dev, "mode",
+						      i, GPIOD_OUT_HIGH);
+		if (IS_ERR(ddata->gpio[i])) {
+			dev_info(ddata->dev, "no mode change GPIO%i: %li\n",
+				 i, PTR_ERR(ddata->gpio[i]));
+				 ddata->gpio[i] = NULL;
+		}
+	}
+}
+
+static int cpcap_usb_init_iio(struct cpcap_phy_ddata *ddata)
+{
+	enum iio_chan_type type;
+	int error;
+
+	ddata->vbus = devm_iio_channel_get(ddata->dev, "vbus");
+	if (IS_ERR(ddata->vbus)) {
+		error = PTR_ERR(ddata->vbus);
+		goto out_err;
+	}
+
+	if (!ddata->vbus->indio_dev) {
+		error = -ENXIO;
+		goto out_err;
+	}
+
+	error = iio_get_channel_type(ddata->vbus, &type);
+	if (error < 0)
+		goto out_err;
+
+	if (type != IIO_VOLTAGE) {
+		error = -EINVAL;
+		goto out_err;
+	}
+
+	return 0;
+
+out_err:
+	dev_err(ddata->dev, "could not initialize VBUS or ID IIO: %i\n",
+		error);
+
+	return error;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id cpcap_usb_phy_id_table[] = {
+	{
+		.compatible = "motorola,cpcap-usb-phy",
+	},
+	{
+		.compatible = "motorola,mapphone-cpcap-usb-phy",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, cpcap_usb_phy_id_table);
+#endif
+
+static int cpcap_usb_phy_probe(struct platform_device *pdev)
+{
+	struct cpcap_phy_ddata *ddata;
+	struct phy *generic_phy;
+	struct phy_provider *phy_provider;
+	struct usb_otg *otg;
+	const struct of_device_id *of_id;
+	int error;
+
+	of_id = of_match_device(of_match_ptr(cpcap_usb_phy_id_table),
+				&pdev->dev);
+	if (!of_id)
+		return -EINVAL;
+
+	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+	if (!ddata)
+		return -ENOMEM;
+
+	ddata->reg = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!ddata->reg)
+		return -ENODEV;
+
+	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg)
+		return -ENOMEM;
+
+	ddata->dev = &pdev->dev;
+	ddata->phy.dev = ddata->dev;
+	ddata->phy.label = "cpcap_usb_phy";
+	ddata->phy.otg = otg;
+	ddata->phy.type = USB_PHY_TYPE_USB2;
+	otg->set_host = cpcap_usb_phy_set_host;
+	otg->set_peripheral = cpcap_usb_phy_set_peripheral;
+	otg->usb_phy = &ddata->phy;
+	INIT_DELAYED_WORK(&ddata->detect_work, cpcap_usb_detect);
+	platform_set_drvdata(pdev, ddata);
+
+	ddata->vusb = devm_regulator_get(&pdev->dev, "vusb");
+	if (IS_ERR(ddata->vusb))
+		return PTR_ERR(ddata->vusb);
+
+	error = regulator_enable(ddata->vusb);
+	if (error)
+		return error;
+
+	generic_phy = devm_phy_create(ddata->dev, NULL, &ops);
+	if (IS_ERR(generic_phy)) {
+		error = PTR_ERR(generic_phy);
+		return PTR_ERR(generic_phy);
+	}
+
+	phy_set_drvdata(generic_phy, ddata);
+
+	phy_provider = devm_of_phy_provider_register(ddata->dev,
+						     of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	error = cpcap_usb_init_optional_pins(ddata);
+	if (error)
+		return error;
+
+	cpcap_usb_init_optional_gpios(ddata);
+
+	error = cpcap_usb_init_iio(ddata);
+	if (error)
+		return error;
+
+	error = cpcap_usb_init_interrupts(pdev, ddata);
+	if (error)
+		return error;
+
+	usb_add_phy_dev(&ddata->phy);
+	atomic_set(&ddata->active, 1);
+	schedule_delayed_work(&ddata->detect_work, msecs_to_jiffies(1));
+
+	return 0;
+}
+
+static int cpcap_usb_phy_remove(struct platform_device *pdev)
+{
+	struct cpcap_phy_ddata *ddata = platform_get_drvdata(pdev);
+	int error;
+
+	atomic_set(&ddata->active, 0);
+	error = cpcap_usb_set_uart_mode(ddata);
+	if (error)
+		dev_err(ddata->dev, "could not set UART mode\n");
+
+	error = musb_mailbox(MUSB_VBUS_OFF);
+	if (error)
+		dev_err(ddata->dev, "could not set mailbox\n");
+
+	usb_remove_phy(&ddata->phy);
+	cancel_delayed_work_sync(&ddata->detect_work);
+	clk_unprepare(ddata->refclk);
+	regulator_disable(ddata->vusb);
+
+	return 0;
+}
+
+static struct platform_driver cpcap_usb_phy_driver = {
+	.probe		= cpcap_usb_phy_probe,
+	.remove		= cpcap_usb_phy_remove,
+	.driver		= {
+		.name	= "cpcap-usb-phy",
+		.of_match_table = of_match_ptr(cpcap_usb_phy_id_table),
+	},
+};
+
+module_platform_driver(cpcap_usb_phy_driver);
+
+MODULE_ALIAS("platform:cpcap_usb");
+MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
+MODULE_DESCRIPTION("CPCAP usb phy driver");
+MODULE_LICENSE("GPL v2");

+ 58 - 0
drivers/phy/qualcomm/Kconfig

@@ -0,0 +1,58 @@
+#
+# Phy drivers for Qualcomm platforms
+#
+config PHY_QCOM_APQ8064_SATA
+	tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
+	depends on ARCH_QCOM
+	depends on HAS_IOMEM
+	depends on OF
+	select GENERIC_PHY
+
+config PHY_QCOM_IPQ806X_SATA
+	tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
+	depends on ARCH_QCOM
+	depends on HAS_IOMEM
+	depends on OF
+	select GENERIC_PHY
+
+config PHY_QCOM_QMP
+	tristate "Qualcomm QMP PHY Driver"
+	depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST)
+	select GENERIC_PHY
+	help
+	  Enable this to support the QMP PHY transceiver that is used
+	  with controllers such as PCIe, UFS, and USB on Qualcomm chips.
+
+config PHY_QCOM_QUSB2
+	tristate "Qualcomm QUSB2 PHY Driver"
+	depends on OF && (ARCH_QCOM || COMPILE_TEST)
+	depends on NVMEM || !NVMEM
+	select GENERIC_PHY
+	help
+	  Enable this to support the HighSpeed QUSB2 PHY transceiver for USB
+	  controllers on Qualcomm chips. This driver supports the high-speed
+	  PHY which is usually paired with either the ChipIdea or Synopsys DWC3
+	  USB IPs on MSM SOCs.
+
+config PHY_QCOM_UFS
+	tristate "Qualcomm UFS PHY driver"
+	depends on OF && ARCH_QCOM
+	select GENERIC_PHY
+	help
+	  Support for UFS PHY on QCOM chipsets.
+
+config PHY_QCOM_USB_HS
+	tristate "Qualcomm USB HS PHY module"
+	depends on USB_ULPI_BUS
+	depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
+	select GENERIC_PHY
+	help
+	  Support for the USB high-speed ULPI compliant phy on Qualcomm
+	  chipsets.
+
+config PHY_QCOM_USB_HSIC
+	tristate "Qualcomm USB HSIC ULPI PHY module"
+	depends on USB_ULPI_BUS
+	select GENERIC_PHY
+	help
+	  Support for the USB HSIC ULPI compliant PHY on QCOM chipsets.

+ 9 - 0
drivers/phy/qualcomm/Makefile

@@ -0,0 +1,9 @@
+obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)	+= phy-qcom-apq8064-sata.o
+obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
+obj-$(CONFIG_PHY_QCOM_QMP)		+= phy-qcom-qmp.o
+obj-$(CONFIG_PHY_QCOM_QUSB2)		+= phy-qcom-qusb2.o
+obj-$(CONFIG_PHY_QCOM_UFS)		+= phy-qcom-ufs.o
+obj-$(CONFIG_PHY_QCOM_UFS)		+= phy-qcom-ufs-qmp-14nm.o
+obj-$(CONFIG_PHY_QCOM_UFS)		+= phy-qcom-ufs-qmp-20nm.o
+obj-$(CONFIG_PHY_QCOM_USB_HS) 		+= phy-qcom-usb-hs.o
+obj-$(CONFIG_PHY_QCOM_USB_HSIC) 	+= phy-qcom-usb-hsic.o

+ 0 - 0
drivers/phy/phy-qcom-apq8064-sata.c → drivers/phy/qualcomm/phy-qcom-apq8064-sata.c


+ 0 - 0
drivers/phy/phy-qcom-ipq806x-sata.c → drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c


+ 0 - 0
drivers/phy/phy-qcom-qmp.c → drivers/phy/qualcomm/phy-qcom-qmp.c


+ 0 - 0
drivers/phy/phy-qcom-qusb2.c → drivers/phy/qualcomm/phy-qcom-qusb2.c


+ 0 - 0
drivers/phy/phy-qcom-ufs-i.h → drivers/phy/qualcomm/phy-qcom-ufs-i.h


+ 0 - 0
drivers/phy/phy-qcom-ufs-qmp-14nm.c → drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c


+ 0 - 0
drivers/phy/phy-qcom-ufs-qmp-14nm.h → drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h


+ 0 - 0
drivers/phy/phy-qcom-ufs-qmp-20nm.c → drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c


+ 0 - 0
drivers/phy/phy-qcom-ufs-qmp-20nm.h → drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h


+ 0 - 0
drivers/phy/phy-qcom-ufs.c → drivers/phy/qualcomm/phy-qcom-ufs.c


+ 1 - 2
drivers/phy/phy-qcom-usb-hs.c → drivers/phy/qualcomm/phy-qcom-usb-hs.c

@@ -11,12 +11,11 @@
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/consumer.h>
 #include <linux/of_device.h>
 #include <linux/of_device.h>
+#include <linux/phy/phy.h>
 #include <linux/reset.h>
 #include <linux/reset.h>
 #include <linux/extcon.h>
 #include <linux/extcon.h>
 #include <linux/notifier.h>
 #include <linux/notifier.h>
 
 
-#include "ulpi_phy.h"
-
 #define ULPI_PWR_CLK_MNG_REG		0x88
 #define ULPI_PWR_CLK_MNG_REG		0x88
 # define ULPI_PWR_OTG_COMP_DISABLE	BIT(0)
 # define ULPI_PWR_OTG_COMP_DISABLE	BIT(0)
 
 

+ 1 - 2
drivers/phy/phy-qcom-usb-hsic.c → drivers/phy/qualcomm/phy-qcom-usb-hsic.c

@@ -8,13 +8,12 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/ulpi/driver.h>
 #include <linux/ulpi/driver.h>
 #include <linux/ulpi/regs.h>
 #include <linux/ulpi/regs.h>
+#include <linux/phy/phy.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/pinctrl-state.h>
 #include <linux/pinctrl/pinctrl-state.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 
 
-#include "ulpi_phy.h"
-
 #define ULPI_HSIC_CFG		0x30
 #define ULPI_HSIC_CFG		0x30
 #define ULPI_HSIC_IO_CAL	0x33
 #define ULPI_HSIC_IO_CAL	0x33
 
 

+ 24 - 0
drivers/phy/renesas/Kconfig

@@ -0,0 +1,24 @@
+#
+# Phy drivers for Renesas platforms
+#
+config PHY_RCAR_GEN2
+	tristate "Renesas R-Car generation 2 USB PHY driver"
+	depends on ARCH_RENESAS
+	depends on GENERIC_PHY
+	help
+	  Support for USB PHY found on Renesas R-Car generation 2 SoCs.
+
+config PHY_RCAR_GEN3_USB2
+	tristate "Renesas R-Car generation 3 USB 2.0 PHY driver"
+	depends on ARCH_RENESAS
+	depends on EXTCON
+	select GENERIC_PHY
+	help
+	  Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs.
+
+config PHY_RCAR_GEN3_USB3
+	tristate "Renesas R-Car generation 3 USB 3.0 PHY driver"
+	depends on ARCH_RENESAS || COMPILE_TEST
+	select GENERIC_PHY
+	help
+	  Support for USB 3.0 PHY found on Renesas R-Car generation 3 SoCs.

+ 3 - 0
drivers/phy/renesas/Makefile

@@ -0,0 +1,3 @@
+obj-$(CONFIG_PHY_RCAR_GEN2)		+= phy-rcar-gen2.o
+obj-$(CONFIG_PHY_RCAR_GEN3_USB2)	+= phy-rcar-gen3-usb2.o
+obj-$(CONFIG_PHY_RCAR_GEN3_USB3)	+= phy-rcar-gen3-usb3.o

+ 0 - 0
drivers/phy/phy-rcar-gen2.c → drivers/phy/renesas/phy-rcar-gen2.c


+ 0 - 0
drivers/phy/phy-rcar-gen3-usb2.c → drivers/phy/renesas/phy-rcar-gen3-usb2.c


+ 226 - 0
drivers/phy/renesas/phy-rcar-gen3-usb3.c

@@ -0,0 +1,226 @@
+/*
+ * Renesas R-Car Gen3 for USB3.0 PHY driver
+ *
+ * Copyright (C) 2017 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#define USB30_CLKSET0		0x034
+#define USB30_CLKSET1		0x036
+#define USB30_SSC_SET		0x038
+#define USB30_PHY_ENABLE	0x060
+#define USB30_VBUS_EN		0x064
+
+/* USB30_CLKSET0 */
+#define CLKSET0_PRIVATE			0x05c0
+#define CLKSET0_USB30_FSEL_USB_EXTAL	0x0002
+
+/* USB30_CLKSET1 */
+#define CLKSET1_USB30_PLL_MULTI_SHIFT		6
+#define CLKSET1_USB30_PLL_MULTI_USB_EXTAL	(0x64 << \
+						 CLKSET1_USB30_PLL_MULTI_SHIFT)
+#define CLKSET1_PHYRESET	BIT(4)	/* 1: reset */
+#define CLKSET1_REF_CLKDIV	BIT(3)	/* 1: USB_EXTAL */
+#define CLKSET1_PRIVATE_2_1	BIT(1)	/* Write B'01 */
+#define CLKSET1_REF_CLK_SEL	BIT(0)	/* 1: USB3S0_CLK_P */
+
+/* USB30_SSC_SET */
+#define SSC_SET_SSC_EN		BIT(12)
+#define SSC_SET_RANGE_SHIFT	9
+#define SSC_SET_RANGE_4980	(0x0 << SSC_SET_RANGE_SHIFT)
+#define SSC_SET_RANGE_4492	(0x1 << SSC_SET_RANGE_SHIFT)
+#define SSC_SET_RANGE_4003	(0x2 << SSC_SET_RANGE_SHIFT)
+
+/* USB30_PHY_ENABLE */
+#define PHY_ENABLE_RESET_EN	BIT(4)
+
+/* USB30_VBUS_EN */
+#define VBUS_EN_VBUS_EN		BIT(1)
+
+struct rcar_gen3_usb3 {
+	void __iomem *base;
+	struct phy *phy;
+	u32 ssc_range;
+	bool usb3s_clk;
+	bool usb_extal;
+};
+
+static void write_clkset1_for_usb_extal(struct rcar_gen3_usb3 *r, bool reset)
+{
+	u16 val = CLKSET1_USB30_PLL_MULTI_USB_EXTAL |
+		  CLKSET1_REF_CLKDIV | CLKSET1_PRIVATE_2_1;
+
+	if (reset)
+		val |= CLKSET1_PHYRESET;
+
+	writew(val, r->base + USB30_CLKSET1);
+}
+
+static void rcar_gen3_phy_usb3_enable_ssc(struct rcar_gen3_usb3 *r)
+{
+	u16 val = SSC_SET_SSC_EN;
+
+	switch (r->ssc_range) {
+	case 4980:
+		val |= SSC_SET_RANGE_4980;
+		break;
+	case 4492:
+		val |= SSC_SET_RANGE_4492;
+		break;
+	case 4003:
+		val |= SSC_SET_RANGE_4003;
+		break;
+	default:
+		dev_err(&r->phy->dev, "%s: unsupported range (%x)\n", __func__,
+			r->ssc_range);
+		return;
+	}
+
+	writew(val, r->base + USB30_SSC_SET);
+}
+
+static void rcar_gen3_phy_usb3_select_usb_extal(struct rcar_gen3_usb3 *r)
+{
+	write_clkset1_for_usb_extal(r, false);
+	if (r->ssc_range)
+		rcar_gen3_phy_usb3_enable_ssc(r);
+	writew(CLKSET0_PRIVATE | CLKSET0_USB30_FSEL_USB_EXTAL,
+	       r->base + USB30_CLKSET0);
+	writew(PHY_ENABLE_RESET_EN, r->base + USB30_PHY_ENABLE);
+	write_clkset1_for_usb_extal(r, true);
+	usleep_range(10, 20);
+	write_clkset1_for_usb_extal(r, false);
+}
+
+static int rcar_gen3_phy_usb3_init(struct phy *p)
+{
+	struct rcar_gen3_usb3 *r = phy_get_drvdata(p);
+
+	dev_vdbg(&r->phy->dev, "%s: enter (%d, %d, %d)\n", __func__,
+		 r->usb3s_clk, r->usb_extal, r->ssc_range);
+
+	if (!r->usb3s_clk && r->usb_extal)
+		rcar_gen3_phy_usb3_select_usb_extal(r);
+
+	/* Enables VBUS detection anyway */
+	writew(VBUS_EN_VBUS_EN, r->base + USB30_VBUS_EN);
+
+	return 0;
+}
+
+static const struct phy_ops rcar_gen3_phy_usb3_ops = {
+	.init		= rcar_gen3_phy_usb3_init,
+	.owner		= THIS_MODULE,
+};
+
+static const struct of_device_id rcar_gen3_phy_usb3_match_table[] = {
+	{ .compatible = "renesas,rcar-gen3-usb3-phy" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb3_match_table);
+
+static int rcar_gen3_phy_usb3_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rcar_gen3_usb3 *r;
+	struct phy_provider *provider;
+	struct resource *res;
+	int ret = 0;
+	struct clk *clk;
+
+	if (!dev->of_node) {
+		dev_err(dev, "This driver needs device tree\n");
+		return -EINVAL;
+	}
+
+	r = devm_kzalloc(dev, sizeof(*r), GFP_KERNEL);
+	if (!r)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	r->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(r->base))
+		return PTR_ERR(r->base);
+
+	clk = devm_clk_get(dev, "usb3s_clk");
+	if (!IS_ERR(clk) && !clk_prepare_enable(clk)) {
+		r->usb3s_clk = !!clk_get_rate(clk);
+		clk_disable_unprepare(clk);
+	}
+	clk = devm_clk_get(dev, "usb_extal");
+	if (!IS_ERR(clk) && !clk_prepare_enable(clk)) {
+		r->usb_extal = !!clk_get_rate(clk);
+		clk_disable_unprepare(clk);
+	}
+
+	if (!r->usb3s_clk && !r->usb_extal) {
+		dev_err(dev, "This driver needs usb3s_clk and/or usb_extal\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/*
+	 * devm_phy_create() will call pm_runtime_enable(&phy->dev);
+	 * And then, phy-core will manage runtime pm for this device.
+	 */
+	pm_runtime_enable(dev);
+
+	r->phy = devm_phy_create(dev, NULL, &rcar_gen3_phy_usb3_ops);
+	if (IS_ERR(r->phy)) {
+		dev_err(dev, "Failed to create USB3 PHY\n");
+		ret = PTR_ERR(r->phy);
+		goto error;
+	}
+
+	of_property_read_u32(dev->of_node, "renesas,ssc-range", &r->ssc_range);
+
+	platform_set_drvdata(pdev, r);
+	phy_set_drvdata(r->phy, r);
+
+	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(provider)) {
+		dev_err(dev, "Failed to register PHY provider\n");
+		ret = PTR_ERR(provider);
+		goto error;
+	}
+
+	return 0;
+
+error:
+	pm_runtime_disable(dev);
+
+	return ret;
+}
+
+static int rcar_gen3_phy_usb3_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+};
+
+static struct platform_driver rcar_gen3_phy_usb3_driver = {
+	.driver = {
+		.name		= "phy_rcar_gen3_usb3",
+		.of_match_table	= rcar_gen3_phy_usb3_match_table,
+	},
+	.probe	= rcar_gen3_phy_usb3_probe,
+	.remove = rcar_gen3_phy_usb3_remove,
+};
+module_platform_driver(rcar_gen3_phy_usb3_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 3.0 PHY");
+MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");

+ 51 - 0
drivers/phy/rockchip/Kconfig

@@ -0,0 +1,51 @@
+#
+# Phy drivers for Rockchip platforms
+#
+config PHY_ROCKCHIP_DP
+	tristate "Rockchip Display Port PHY Driver"
+	depends on ARCH_ROCKCHIP && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the Rockchip Display Port PHY.
+
+config PHY_ROCKCHIP_EMMC
+	tristate "Rockchip EMMC PHY Driver"
+	depends on ARCH_ROCKCHIP && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the Rockchip EMMC PHY.
+
+config PHY_ROCKCHIP_INNO_USB2
+	tristate "Rockchip INNO USB2PHY Driver"
+	depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
+	depends on COMMON_CLK
+	depends on EXTCON
+	depends on USB_SUPPORT
+	select GENERIC_PHY
+	select USB_COMMON
+	help
+	  Support for Rockchip USB2.0 PHY with Innosilicon IP block.
+
+config PHY_ROCKCHIP_PCIE
+	tristate "Rockchip PCIe PHY Driver"
+	depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
+	select GENERIC_PHY
+	select MFD_SYSCON
+	help
+	  Enable this to support the Rockchip PCIe PHY.
+
+config PHY_ROCKCHIP_TYPEC
+	tristate "Rockchip TYPEC PHY Driver"
+	depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST)
+	select EXTCON
+	select GENERIC_PHY
+	select RESET_CONTROLLER
+	help
+	  Enable this to support the Rockchip USB TYPEC PHY.
+
+config PHY_ROCKCHIP_USB
+	tristate "Rockchip USB2 PHY Driver"
+	depends on ARCH_ROCKCHIP && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the Rockchip USB 2.0 PHY.

+ 6 - 0
drivers/phy/rockchip/Makefile

@@ -0,0 +1,6 @@
+obj-$(CONFIG_PHY_ROCKCHIP_DP)		+= phy-rockchip-dp.o
+obj-$(CONFIG_PHY_ROCKCHIP_EMMC)		+= phy-rockchip-emmc.o
+obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2)	+= phy-rockchip-inno-usb2.o
+obj-$(CONFIG_PHY_ROCKCHIP_PCIE)		+= phy-rockchip-pcie.o
+obj-$(CONFIG_PHY_ROCKCHIP_TYPEC)	+= phy-rockchip-typec.o
+obj-$(CONFIG_PHY_ROCKCHIP_USB)		+= phy-rockchip-usb.o

+ 0 - 0
drivers/phy/phy-rockchip-dp.c → drivers/phy/rockchip/phy-rockchip-dp.c


+ 0 - 0
drivers/phy/phy-rockchip-emmc.c → drivers/phy/rockchip/phy-rockchip-emmc.c


+ 70 - 4
drivers/phy/phy-rockchip-inno-usb2.c → drivers/phy/rockchip/phy-rockchip-inno-usb2.c

@@ -406,7 +406,8 @@ static int rockchip_usb2phy_init(struct phy *phy)
 	mutex_lock(&rport->mutex);
 	mutex_lock(&rport->mutex);
 
 
 	if (rport->port_id == USB2PHY_PORT_OTG) {
 	if (rport->port_id == USB2PHY_PORT_OTG) {
-		if (rport->mode != USB_DR_MODE_HOST) {
+		if (rport->mode != USB_DR_MODE_HOST &&
+		    rport->mode != USB_DR_MODE_UNKNOWN) {
 			/* clear bvalid status and enable bvalid detect irq */
 			/* clear bvalid status and enable bvalid detect irq */
 			ret = property_enable(rphy,
 			ret = property_enable(rphy,
 					      &rport->port_cfg->bvalid_det_clr,
 					      &rport->port_cfg->bvalid_det_clr,
@@ -421,7 +422,7 @@ static int rockchip_usb2phy_init(struct phy *phy)
 				goto out;
 				goto out;
 
 
 			schedule_delayed_work(&rport->otg_sm_work,
 			schedule_delayed_work(&rport->otg_sm_work,
-					      OTG_SCHEDULE_DELAY);
+					      OTG_SCHEDULE_DELAY * 3);
 		} else {
 		} else {
 			/* If OTG works in host only mode, do nothing. */
 			/* If OTG works in host only mode, do nothing. */
 			dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
 			dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
@@ -463,6 +464,9 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
+	/* waiting for the utmi_clk to become stable */
+	usleep_range(1500, 2000);
+
 	rport->suspended = false;
 	rport->suspended = false;
 	return 0;
 	return 0;
 }
 }
@@ -493,7 +497,8 @@ static int rockchip_usb2phy_exit(struct phy *phy)
 	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
 	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
 
 
 	if (rport->port_id == USB2PHY_PORT_OTG &&
 	if (rport->port_id == USB2PHY_PORT_OTG &&
-	    rport->mode != USB_DR_MODE_HOST) {
+	    rport->mode != USB_DR_MODE_HOST &&
+	    rport->mode != USB_DR_MODE_UNKNOWN) {
 		cancel_delayed_work_sync(&rport->otg_sm_work);
 		cancel_delayed_work_sync(&rport->otg_sm_work);
 		cancel_delayed_work_sync(&rport->chg_work);
 		cancel_delayed_work_sync(&rport->chg_work);
 	} else if (rport->port_id == USB2PHY_PORT_HOST)
 	} else if (rport->port_id == USB2PHY_PORT_HOST)
@@ -970,7 +975,8 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
 	mutex_init(&rport->mutex);
 	mutex_init(&rport->mutex);
 
 
 	rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
 	rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
-	if (rport->mode == USB_DR_MODE_HOST) {
+	if (rport->mode == USB_DR_MODE_HOST ||
+	    rport->mode == USB_DR_MODE_UNKNOWN) {
 		ret = 0;
 		ret = 0;
 		goto out;
 		goto out;
 	}
 	}
@@ -1138,6 +1144,65 @@ disable_clks:
 	return ret;
 	return ret;
 }
 }
 
 
+static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = {
+	{
+		.reg = 0x760,
+		.num_ports	= 2,
+		.clkout_ctl	= { 0x0768, 4, 4, 1, 0 },
+		.port_cfgs	= {
+			[USB2PHY_PORT_OTG] = {
+				.phy_sus	= { 0x0760, 15, 0, 0, 0x1d1 },
+				.bvalid_det_en	= { 0x0680, 3, 3, 0, 1 },
+				.bvalid_det_st	= { 0x0690, 3, 3, 0, 1 },
+				.bvalid_det_clr	= { 0x06a0, 3, 3, 0, 1 },
+				.ls_det_en	= { 0x0680, 2, 2, 0, 1 },
+				.ls_det_st	= { 0x0690, 2, 2, 0, 1 },
+				.ls_det_clr	= { 0x06a0, 2, 2, 0, 1 },
+				.utmi_bvalid	= { 0x0480, 4, 4, 0, 1 },
+				.utmi_ls	= { 0x0480, 3, 2, 0, 1 },
+			},
+			[USB2PHY_PORT_HOST] = {
+				.phy_sus	= { 0x0764, 15, 0, 0, 0x1d1 },
+				.ls_det_en	= { 0x0680, 4, 4, 0, 1 },
+				.ls_det_st	= { 0x0690, 4, 4, 0, 1 },
+				.ls_det_clr	= { 0x06a0, 4, 4, 0, 1 }
+			}
+		},
+		.chg_det = {
+			.opmode		= { 0x0760, 3, 0, 5, 1 },
+			.cp_det		= { 0x0884, 4, 4, 0, 1 },
+			.dcp_det	= { 0x0884, 3, 3, 0, 1 },
+			.dp_det		= { 0x0884, 5, 5, 0, 1 },
+			.idm_sink_en	= { 0x0768, 8, 8, 0, 1 },
+			.idp_sink_en	= { 0x0768, 7, 7, 0, 1 },
+			.idp_src_en	= { 0x0768, 9, 9, 0, 1 },
+			.rdm_pdwn_en	= { 0x0768, 10, 10, 0, 1 },
+			.vdm_src_en	= { 0x0768, 12, 12, 0, 1 },
+			.vdp_src_en	= { 0x0768, 11, 11, 0, 1 },
+		},
+	},
+	{
+		.reg = 0x800,
+		.num_ports	= 2,
+		.clkout_ctl	= { 0x0808, 4, 4, 1, 0 },
+		.port_cfgs	= {
+			[USB2PHY_PORT_OTG] = {
+				.phy_sus	= { 0x800, 15, 0, 0, 0x1d1 },
+				.ls_det_en	= { 0x0684, 0, 0, 0, 1 },
+				.ls_det_st	= { 0x0694, 0, 0, 0, 1 },
+				.ls_det_clr	= { 0x06a4, 0, 0, 0, 1 }
+			},
+			[USB2PHY_PORT_HOST] = {
+				.phy_sus	= { 0x804, 15, 0, 0, 0x1d1 },
+				.ls_det_en	= { 0x0684, 1, 1, 0, 1 },
+				.ls_det_st	= { 0x0694, 1, 1, 0, 1 },
+				.ls_det_clr	= { 0x06a4, 1, 1, 0, 1 }
+			}
+		},
+	},
+	{ /* sentinel */ }
+};
+
 static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = {
 static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = {
 	{
 	{
 		.reg = 0x100,
 		.reg = 0x100,
@@ -1263,6 +1328,7 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
 };
 };
 
 
 static const struct of_device_id rockchip_usb2phy_dt_match[] = {
 static const struct of_device_id rockchip_usb2phy_dt_match[] = {
+	{ .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
 	{ .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
 	{ .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
 	{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
 	{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
 	{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
 	{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },

+ 0 - 0
drivers/phy/phy-rockchip-pcie.c → drivers/phy/rockchip/phy-rockchip-pcie.c


+ 0 - 0
drivers/phy/phy-rockchip-typec.c → drivers/phy/rockchip/phy-rockchip-typec.c


+ 0 - 0
drivers/phy/phy-rockchip-usb.c → drivers/phy/rockchip/phy-rockchip-usb.c


+ 95 - 0
drivers/phy/samsung/Kconfig

@@ -0,0 +1,95 @@
+#
+# Phy drivers for Samsung platforms
+#
+config PHY_EXYNOS_DP_VIDEO
+	tristate "EXYNOS SoC series Display Port PHY driver"
+	depends on OF
+	depends on ARCH_EXYNOS || COMPILE_TEST
+	default ARCH_EXYNOS
+	select GENERIC_PHY
+	help
+	  Support for Display Port PHY found on Samsung EXYNOS SoCs.
+
+config PHY_EXYNOS_MIPI_VIDEO
+	tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
+	depends on HAS_IOMEM
+	depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+	select GENERIC_PHY
+	default y if ARCH_S5PV210 || ARCH_EXYNOS
+	help
+	  Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
+	  and EXYNOS SoCs.
+
+config PHY_EXYNOS_PCIE
+	bool "Exynos PCIe PHY driver"
+	depends on OF && (ARCH_EXYNOS || COMPILE_TEST)
+	select GENERIC_PHY
+	help
+	  Enable PCIe PHY support for Exynos SoC series.
+	  This driver provides PHY interface for Exynos PCIe controller.
+
+config PHY_SAMSUNG_USB2
+	tristate "Samsung USB 2.0 PHY driver"
+	depends on HAS_IOMEM
+	depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2
+	select GENERIC_PHY
+	select MFD_SYSCON
+	default ARCH_EXYNOS
+	help
+	  Enable this to support the Samsung USB 2.0 PHY driver for Samsung
+	  SoCs. This driver provides the interface for USB 2.0 PHY. Support
+	  for particular PHYs will be enabled based on the SoC type in addition
+	  to this driver.
+
+config PHY_EXYNOS4210_USB2
+	bool
+	depends on PHY_SAMSUNG_USB2
+	default CPU_EXYNOS4210
+
+config PHY_EXYNOS4X12_USB2
+	bool
+	depends on PHY_SAMSUNG_USB2
+	default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
+
+config PHY_EXYNOS5250_USB2
+	bool
+	depends on PHY_SAMSUNG_USB2
+	default SOC_EXYNOS5250 || SOC_EXYNOS5420
+
+config PHY_S5PV210_USB2
+	bool "Support for S5PV210"
+	depends on PHY_SAMSUNG_USB2
+	depends on ARCH_S5PV210
+	help
+	  Enable USB PHY support for S5PV210. This option requires that Samsung
+	  USB 2.0 PHY driver is enabled and means that support for this
+	  particular SoC is compiled in the driver. In case of S5PV210 two phys
+	  are available - device and host.
+
+config PHY_EXYNOS5_USBDRD
+	tristate "Exynos5 SoC series USB DRD PHY driver"
+	depends on ARCH_EXYNOS && OF
+	depends on HAS_IOMEM
+	depends on USB_DWC3_EXYNOS
+	select GENERIC_PHY
+	select MFD_SYSCON
+	default y
+	help
+	  Enable USB DRD PHY support for Exynos 5 SoC series.
+	  This driver provides PHY interface for USB 3.0 DRD controller
+	  present on Exynos5 SoC series.
+
+config PHY_EXYNOS5250_SATA
+	tristate "Exynos5250 Sata SerDes/PHY driver"
+	depends on SOC_EXYNOS5250
+	depends on HAS_IOMEM
+	depends on OF
+	select GENERIC_PHY
+	select I2C
+	select I2C_S3C2410
+	select MFD_SYSCON
+	help
+	  Enable this to support SATA SerDes/Phy found on Samsung's
+	  Exynos5250 based SoCs.This SerDes/Phy supports SATA 1.5 Gb/s,
+	  SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
+	  port to accept one SATA device.

+ 11 - 0
drivers/phy/samsung/Makefile

@@ -0,0 +1,11 @@
+obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
+obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
+obj-$(CONFIG_PHY_EXYNOS_PCIE)		+= phy-exynos-pcie.o
+obj-$(CONFIG_PHY_SAMSUNG_USB2)		+= phy-exynos-usb2.o
+phy-exynos-usb2-y			+= phy-samsung-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2)	+= phy-exynos4210-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2)	+= phy-exynos4x12-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2)	+= phy-exynos5250-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2)	+= phy-s5pv210-usb2.o
+obj-$(CONFIG_PHY_EXYNOS5_USBDRD)	+= phy-exynos5-usbdrd.o
+obj-$(CONFIG_PHY_EXYNOS5250_SATA)	+= phy-exynos5250-sata.o

+ 0 - 0
drivers/phy/phy-exynos-dp-video.c → drivers/phy/samsung/phy-exynos-dp-video.c


+ 0 - 0
drivers/phy/phy-exynos-mipi-video.c → drivers/phy/samsung/phy-exynos-mipi-video.c


+ 0 - 0
drivers/phy/phy-exynos-pcie.c → drivers/phy/samsung/phy-exynos-pcie.c


+ 0 - 0
drivers/phy/phy-exynos4210-usb2.c → drivers/phy/samsung/phy-exynos4210-usb2.c


+ 0 - 0
drivers/phy/phy-exynos4x12-usb2.c → drivers/phy/samsung/phy-exynos4x12-usb2.c


+ 0 - 0
drivers/phy/phy-exynos5-usbdrd.c → drivers/phy/samsung/phy-exynos5-usbdrd.c


+ 0 - 0
drivers/phy/phy-exynos5250-sata.c → drivers/phy/samsung/phy-exynos5250-sata.c


+ 0 - 0
drivers/phy/phy-exynos5250-usb2.c → drivers/phy/samsung/phy-exynos5250-usb2.c


+ 0 - 0
drivers/phy/phy-s5pv210-usb2.c → drivers/phy/samsung/phy-s5pv210-usb2.c


+ 0 - 0
drivers/phy/phy-samsung-usb2.c → drivers/phy/samsung/phy-samsung-usb2.c


+ 0 - 0
drivers/phy/phy-samsung-usb2.h → drivers/phy/samsung/phy-samsung-usb2.h


+ 33 - 0
drivers/phy/st/Kconfig

@@ -0,0 +1,33 @@
+#
+# Phy drivers for STMicro platforms
+#
+config PHY_MIPHY28LP
+	tristate "STMicroelectronics MIPHY28LP PHY driver for STiH407"
+	depends on ARCH_STI
+	select GENERIC_PHY
+	help
+	  Enable this to support the miphy transceiver (for SATA/PCIE/USB3)
+	  that is part of STMicroelectronics STiH407 SoC.
+
+config PHY_ST_SPEAR1310_MIPHY
+	tristate "ST SPEAR1310-MIPHY driver"
+	select GENERIC_PHY
+	depends on MACH_SPEAR1310 || COMPILE_TEST
+	help
+	  Support for ST SPEAr1310 MIPHY which can be used for PCIe and SATA.
+
+config PHY_ST_SPEAR1340_MIPHY
+	tristate "ST SPEAR1340-MIPHY driver"
+	select GENERIC_PHY
+	depends on MACH_SPEAR1340 || COMPILE_TEST
+	help
+	  Support for ST SPEAr1340 MIPHY which can be used for PCIe and SATA.
+
+config PHY_STIH407_USB
+	tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family"
+	depends on RESET_CONTROLLER
+	depends on ARCH_STI || COMPILE_TEST
+	select GENERIC_PHY
+	help
+	  Enable this support to enable the picoPHY device used by USB2
+	  and USB3 controllers on STMicroelectronics STiH407 SoC families.

+ 4 - 0
drivers/phy/st/Makefile

@@ -0,0 +1,4 @@
+obj-$(CONFIG_PHY_MIPHY28LP) 		+= phy-miphy28lp.o
+obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY)	+= phy-spear1310-miphy.o
+obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)	+= phy-spear1340-miphy.o
+obj-$(CONFIG_PHY_STIH407_USB)		+= phy-stih407-usb.o

+ 0 - 0
drivers/phy/phy-miphy28lp.c → drivers/phy/st/phy-miphy28lp.c


+ 0 - 0
drivers/phy/phy-spear1310-miphy.c → drivers/phy/st/phy-spear1310-miphy.c


+ 0 - 0
drivers/phy/phy-spear1340-miphy.c → drivers/phy/st/phy-spear1340-miphy.c


+ 0 - 0
drivers/phy/phy-stih407-usb.c → drivers/phy/st/phy-stih407-usb.c


+ 78 - 0
drivers/phy/ti/Kconfig

@@ -0,0 +1,78 @@
+#
+# Phy drivers for TI platforms
+#
+config PHY_DA8XX_USB
+	tristate "TI DA8xx USB PHY Driver"
+	depends on ARCH_DAVINCI_DA8XX
+	select GENERIC_PHY
+	select MFD_SYSCON
+	help
+	  Enable this to support the USB PHY on DA8xx SoCs.
+
+	  This driver controls both the USB 1.1 PHY and the USB 2.0 PHY.
+
+config PHY_DM816X_USB
+	tristate "TI dm816x USB PHY driver"
+	depends on ARCH_OMAP2PLUS
+	depends on USB_SUPPORT
+	select GENERIC_PHY
+	select USB_PHY
+	help
+	  Enable this for dm816x USB to work.
+
+config OMAP_CONTROL_PHY
+	tristate "OMAP CONTROL PHY Driver"
+	depends on ARCH_OMAP2PLUS || COMPILE_TEST
+	help
+	  Enable this to add support for the PHY part present in the control
+	  module. This driver has API to power on the USB2 PHY and to write to
+	  the mailbox. The mailbox is present only in omap4 and the register to
+	  power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
+	  additional register to power on USB3 PHY/SATA PHY/PCIE PHY
+	  (PIPE3 PHY).
+
+config OMAP_USB2
+	tristate "OMAP USB2 PHY Driver"
+	depends on ARCH_OMAP2PLUS
+	depends on USB_SUPPORT
+	select GENERIC_PHY
+	select USB_PHY
+	select OMAP_CONTROL_PHY
+	depends on OMAP_OCP2SCP
+	help
+	  Enable this to support the transceiver that is part of SOC. This
+	  driver takes care of all the PHY functionality apart from comparator.
+	  The USB OTG controller communicates with the comparator using this
+	  driver.
+
+config TI_PIPE3
+	tristate "TI PIPE3 PHY Driver"
+	depends on ARCH_OMAP2PLUS || COMPILE_TEST
+	select GENERIC_PHY
+	select OMAP_CONTROL_PHY
+	depends on OMAP_OCP2SCP
+	help
+	  Enable this to support the PIPE3 PHY that is part of TI SOCs. This
+	  driver takes care of all the PHY functionality apart from comparator.
+	  This driver interacts with the "OMAP Control PHY Driver" to power
+	  on/off the PHY.
+
+config PHY_TUSB1210
+	tristate "TI TUSB1210 ULPI PHY module"
+	depends on USB_ULPI_BUS
+	select GENERIC_PHY
+	help
+	  Support for TI TUSB1210 USB ULPI PHY.
+
+config TWL4030_USB
+	tristate "TWL4030 USB Transceiver Driver"
+	depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+	depends on USB_SUPPORT
+	depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't 'y'
+	select GENERIC_PHY
+	select USB_PHY
+	help
+	  Enable this to support the USB OTG transceiver on TWL4030
+	  family chips (including the TWL5030 and TPS659x0 devices).
+	  This transceiver supports high and full speed devices plus,
+	  in host mode, low speed.

+ 7 - 0
drivers/phy/ti/Makefile

@@ -0,0 +1,7 @@
+obj-$(CONFIG_PHY_DA8XX_USB)		+= phy-da8xx-usb.o
+obj-$(CONFIG_PHY_DM816X_USB)		+= phy-dm816x-usb.o
+obj-$(CONFIG_OMAP_CONTROL_PHY)		+= phy-omap-control.o
+obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
+obj-$(CONFIG_TI_PIPE3)			+= phy-ti-pipe3.o
+obj-$(CONFIG_PHY_TUSB1210)		+= phy-tusb1210.o
+obj-$(CONFIG_TWL4030_USB)		+= phy-twl4030-usb.o

+ 0 - 0
drivers/phy/phy-da8xx-usb.c → drivers/phy/ti/phy-da8xx-usb.c


+ 0 - 0
drivers/phy/phy-dm816x-usb.c → drivers/phy/ti/phy-dm816x-usb.c


+ 0 - 0
drivers/phy/phy-omap-control.c → drivers/phy/ti/phy-omap-control.c


+ 0 - 0
drivers/phy/phy-omap-usb2.c → drivers/phy/ti/phy-omap-usb2.c


+ 0 - 0
drivers/phy/phy-ti-pipe3.c → drivers/phy/ti/phy-ti-pipe3.c


+ 38 - 3
drivers/phy/phy-tusb1210.c → drivers/phy/ti/phy-tusb1210.c

@@ -11,9 +11,9 @@
  */
  */
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/ulpi/driver.h>
 #include <linux/ulpi/driver.h>
+#include <linux/ulpi/regs.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio/consumer.h>
-
-#include "ulpi_phy.h"
+#include <linux/phy/ulpi_phy.h>
 
 
 #define TUSB1210_VENDOR_SPECIFIC2		0x80
 #define TUSB1210_VENDOR_SPECIFIC2		0x80
 #define TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT	0
 #define TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT	0
@@ -53,9 +53,43 @@ static int tusb1210_power_off(struct phy *phy)
 	return 0;
 	return 0;
 }
 }
 
 
+static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode)
+{
+	struct tusb1210 *tusb = phy_get_drvdata(phy);
+	int ret;
+
+	ret = ulpi_read(tusb->ulpi, ULPI_OTG_CTRL);
+	if (ret < 0)
+		return ret;
+
+	switch (mode) {
+	case PHY_MODE_USB_HOST:
+		ret |= (ULPI_OTG_CTRL_DRVVBUS_EXT
+			| ULPI_OTG_CTRL_ID_PULLUP
+			| ULPI_OTG_CTRL_DP_PULLDOWN
+			| ULPI_OTG_CTRL_DM_PULLDOWN);
+		ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
+		ret |= ULPI_OTG_CTRL_DRVVBUS;
+		break;
+	case PHY_MODE_USB_DEVICE:
+		ret &= ~(ULPI_OTG_CTRL_DRVVBUS
+			 | ULPI_OTG_CTRL_DP_PULLDOWN
+			 | ULPI_OTG_CTRL_DM_PULLDOWN);
+		ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
+		ret &= ~ULPI_OTG_CTRL_DRVVBUS_EXT;
+		break;
+	default:
+		/* nothing */
+		return 0;
+	}
+
+	return ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret);
+}
+
 static const struct phy_ops phy_ops = {
 static const struct phy_ops phy_ops = {
 	.power_on = tusb1210_power_on,
 	.power_on = tusb1210_power_on,
 	.power_off = tusb1210_power_off,
 	.power_off = tusb1210_power_off,
+	.set_mode = tusb1210_set_mode,
 	.owner = THIS_MODULE,
 	.owner = THIS_MODULE,
 };
 };
 
 
@@ -125,7 +159,8 @@ static void tusb1210_remove(struct ulpi *ulpi)
 #define TI_VENDOR_ID 0x0451
 #define TI_VENDOR_ID 0x0451
 
 
 static const struct ulpi_device_id tusb1210_ulpi_id[] = {
 static const struct ulpi_device_id tusb1210_ulpi_id[] = {
-	{ TI_VENDOR_ID, 0x1507, },
+	{ TI_VENDOR_ID, 0x1507, },  /* TUSB1210 */
+	{ TI_VENDOR_ID, 0x1508, },  /* TUSB1211 */
 	{ },
 	{ },
 };
 };
 MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id);
 MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id);

+ 0 - 0
drivers/phy/phy-twl4030-usb.c → drivers/phy/ti/phy-twl4030-usb.c


+ 0 - 0
drivers/phy/ulpi_phy.h → include/linux/phy/ulpi_phy.h