phy: Group vendor specific phy drivers
authorVivek Gautam <vivek.gautam@codeaurora.org>
Thu, 11 May 2017 06:47:42 +0000 (12:17 +0530)
committerKishon Vijay Abraham I <kishon@ti.com>
Thu, 1 Jun 2017 09:58:33 +0000 (15:28 +0530)
Adding vendor specific directories in phy to group
phy drivers under their respective vendor umbrella.

Also updated the MAINTAINERS file to reflect the correct
directory structure for phy drivers.

Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
Acked-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
Cc: Krzysztof Kozlowski <krzk@kernel.org>
Cc: Jaehoon Chung <jh80.chung@samsung.com>
Cc: Stephen Boyd <stephen.boyd@linaro.org>
Cc: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-arm-msm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-omap@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
Cc: linux-rockchip@lists.infradead.org
Cc: linux-samsung-soc@vger.kernel.org
Cc: linux-usb@vger.kernel.org
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
143 files changed:
MAINTAINERS
drivers/phy/Kconfig
drivers/phy/Makefile
drivers/phy/allwinner/Kconfig [new file with mode: 0644]
drivers/phy/allwinner/Makefile [new file with mode: 0644]
drivers/phy/allwinner/phy-sun4i-usb.c [new file with mode: 0644]
drivers/phy/allwinner/phy-sun9i-usb.c [new file with mode: 0644]
drivers/phy/amlogic/Kconfig [new file with mode: 0644]
drivers/phy/amlogic/Makefile [new file with mode: 0644]
drivers/phy/amlogic/phy-meson8b-usb2.c [new file with mode: 0644]
drivers/phy/broadcom/Kconfig [new file with mode: 0644]
drivers/phy/broadcom/Makefile [new file with mode: 0644]
drivers/phy/broadcom/phy-bcm-cygnus-pcie.c [new file with mode: 0644]
drivers/phy/broadcom/phy-bcm-kona-usb2.c [new file with mode: 0644]
drivers/phy/broadcom/phy-bcm-ns-usb2.c [new file with mode: 0644]
drivers/phy/broadcom/phy-bcm-ns-usb3.c [new file with mode: 0644]
drivers/phy/broadcom/phy-bcm-ns2-pcie.c [new file with mode: 0644]
drivers/phy/broadcom/phy-brcm-sata.c [new file with mode: 0644]
drivers/phy/hisilicon/Kconfig [new file with mode: 0644]
drivers/phy/hisilicon/Makefile [new file with mode: 0644]
drivers/phy/hisilicon/phy-hi6220-usb.c [new file with mode: 0644]
drivers/phy/hisilicon/phy-hix5hd2-sata.c [new file with mode: 0644]
drivers/phy/marvell/Kconfig [new file with mode: 0644]
drivers/phy/marvell/Makefile [new file with mode: 0644]
drivers/phy/marvell/phy-armada375-usb2.c [new file with mode: 0644]
drivers/phy/marvell/phy-berlin-sata.c [new file with mode: 0644]
drivers/phy/marvell/phy-berlin-usb.c [new file with mode: 0644]
drivers/phy/marvell/phy-mvebu-sata.c [new file with mode: 0644]
drivers/phy/marvell/phy-pxa-28nm-hsic.c [new file with mode: 0644]
drivers/phy/marvell/phy-pxa-28nm-usb2.c [new file with mode: 0644]
drivers/phy/phy-armada375-usb2.c [deleted file]
drivers/phy/phy-bcm-cygnus-pcie.c [deleted file]
drivers/phy/phy-bcm-kona-usb2.c [deleted file]
drivers/phy/phy-bcm-ns-usb2.c [deleted file]
drivers/phy/phy-bcm-ns-usb3.c [deleted file]
drivers/phy/phy-bcm-ns2-pcie.c [deleted file]
drivers/phy/phy-berlin-sata.c [deleted file]
drivers/phy/phy-berlin-usb.c [deleted file]
drivers/phy/phy-brcm-sata.c [deleted file]
drivers/phy/phy-da8xx-usb.c [deleted file]
drivers/phy/phy-dm816x-usb.c [deleted file]
drivers/phy/phy-exynos-dp-video.c [deleted file]
drivers/phy/phy-exynos-mipi-video.c [deleted file]
drivers/phy/phy-exynos-pcie.c [deleted file]
drivers/phy/phy-exynos4210-usb2.c [deleted file]
drivers/phy/phy-exynos4x12-usb2.c [deleted file]
drivers/phy/phy-exynos5-usbdrd.c [deleted file]
drivers/phy/phy-exynos5250-sata.c [deleted file]
drivers/phy/phy-exynos5250-usb2.c [deleted file]
drivers/phy/phy-hi6220-usb.c [deleted file]
drivers/phy/phy-hix5hd2-sata.c [deleted file]
drivers/phy/phy-meson8b-usb2.c [deleted file]
drivers/phy/phy-miphy28lp.c [deleted file]
drivers/phy/phy-mvebu-sata.c [deleted file]
drivers/phy/phy-omap-control.c [deleted file]
drivers/phy/phy-omap-usb2.c [deleted file]
drivers/phy/phy-pxa-28nm-hsic.c [deleted file]
drivers/phy/phy-pxa-28nm-usb2.c [deleted file]
drivers/phy/phy-qcom-apq8064-sata.c [deleted file]
drivers/phy/phy-qcom-ipq806x-sata.c [deleted file]
drivers/phy/phy-qcom-qmp.c [deleted file]
drivers/phy/phy-qcom-qusb2.c [deleted file]
drivers/phy/phy-qcom-ufs-i.h [deleted file]
drivers/phy/phy-qcom-ufs-qmp-14nm.c [deleted file]
drivers/phy/phy-qcom-ufs-qmp-14nm.h [deleted file]
drivers/phy/phy-qcom-ufs-qmp-20nm.c [deleted file]
drivers/phy/phy-qcom-ufs-qmp-20nm.h [deleted file]
drivers/phy/phy-qcom-ufs.c [deleted file]
drivers/phy/phy-qcom-usb-hs.c [deleted file]
drivers/phy/phy-qcom-usb-hsic.c [deleted file]
drivers/phy/phy-rcar-gen2.c [deleted file]
drivers/phy/phy-rcar-gen3-usb2.c [deleted file]
drivers/phy/phy-rockchip-dp.c [deleted file]
drivers/phy/phy-rockchip-emmc.c [deleted file]
drivers/phy/phy-rockchip-inno-usb2.c [deleted file]
drivers/phy/phy-rockchip-pcie.c [deleted file]
drivers/phy/phy-rockchip-typec.c [deleted file]
drivers/phy/phy-rockchip-usb.c [deleted file]
drivers/phy/phy-s5pv210-usb2.c [deleted file]
drivers/phy/phy-samsung-usb2.c [deleted file]
drivers/phy/phy-samsung-usb2.h [deleted file]
drivers/phy/phy-spear1310-miphy.c [deleted file]
drivers/phy/phy-spear1340-miphy.c [deleted file]
drivers/phy/phy-stih407-usb.c [deleted file]
drivers/phy/phy-sun4i-usb.c [deleted file]
drivers/phy/phy-sun9i-usb.c [deleted file]
drivers/phy/phy-ti-pipe3.c [deleted file]
drivers/phy/phy-tusb1210.c [deleted file]
drivers/phy/phy-twl4030-usb.c [deleted file]
drivers/phy/qualcomm/Kconfig [new file with mode: 0644]
drivers/phy/qualcomm/Makefile [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-apq8064-sata.c [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-qmp.c [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-qusb2.c [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-ufs-i.h [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-ufs.c [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-usb-hs.c [new file with mode: 0644]
drivers/phy/qualcomm/phy-qcom-usb-hsic.c [new file with mode: 0644]
drivers/phy/renesas/Kconfig [new file with mode: 0644]
drivers/phy/renesas/Makefile [new file with mode: 0644]
drivers/phy/renesas/phy-rcar-gen2.c [new file with mode: 0644]
drivers/phy/renesas/phy-rcar-gen3-usb2.c [new file with mode: 0644]
drivers/phy/rockchip/Kconfig [new file with mode: 0644]
drivers/phy/rockchip/Makefile [new file with mode: 0644]
drivers/phy/rockchip/phy-rockchip-dp.c [new file with mode: 0644]
drivers/phy/rockchip/phy-rockchip-emmc.c [new file with mode: 0644]
drivers/phy/rockchip/phy-rockchip-inno-usb2.c [new file with mode: 0644]
drivers/phy/rockchip/phy-rockchip-pcie.c [new file with mode: 0644]
drivers/phy/rockchip/phy-rockchip-typec.c [new file with mode: 0644]
drivers/phy/rockchip/phy-rockchip-usb.c [new file with mode: 0644]
drivers/phy/samsung/Kconfig [new file with mode: 0644]
drivers/phy/samsung/Makefile [new file with mode: 0644]
drivers/phy/samsung/phy-exynos-dp-video.c [new file with mode: 0644]
drivers/phy/samsung/phy-exynos-mipi-video.c [new file with mode: 0644]
drivers/phy/samsung/phy-exynos-pcie.c [new file with mode: 0644]
drivers/phy/samsung/phy-exynos4210-usb2.c [new file with mode: 0644]
drivers/phy/samsung/phy-exynos4x12-usb2.c [new file with mode: 0644]
drivers/phy/samsung/phy-exynos5-usbdrd.c [new file with mode: 0644]
drivers/phy/samsung/phy-exynos5250-sata.c [new file with mode: 0644]
drivers/phy/samsung/phy-exynos5250-usb2.c [new file with mode: 0644]
drivers/phy/samsung/phy-s5pv210-usb2.c [new file with mode: 0644]
drivers/phy/samsung/phy-samsung-usb2.c [new file with mode: 0644]
drivers/phy/samsung/phy-samsung-usb2.h [new file with mode: 0644]
drivers/phy/st/Kconfig [new file with mode: 0644]
drivers/phy/st/Makefile [new file with mode: 0644]
drivers/phy/st/phy-miphy28lp.c [new file with mode: 0644]
drivers/phy/st/phy-spear1310-miphy.c [new file with mode: 0644]
drivers/phy/st/phy-spear1340-miphy.c [new file with mode: 0644]
drivers/phy/st/phy-stih407-usb.c [new file with mode: 0644]
drivers/phy/ti/Kconfig [new file with mode: 0644]
drivers/phy/ti/Makefile [new file with mode: 0644]
drivers/phy/ti/phy-da8xx-usb.c [new file with mode: 0644]
drivers/phy/ti/phy-dm816x-usb.c [new file with mode: 0644]
drivers/phy/ti/phy-omap-control.c [new file with mode: 0644]
drivers/phy/ti/phy-omap-usb2.c [new file with mode: 0644]
drivers/phy/ti/phy-ti-pipe3.c [new file with mode: 0644]
drivers/phy/ti/phy-tusb1210.c [new file with mode: 0644]
drivers/phy/ti/phy-twl4030-usb.c [new file with mode: 0644]

index f7d568b8f133d9919e3823c102d7ac78f89c894a..a47d3da4d35d092e761883cbbcc223c89b2e3afb 100644 (file)
@@ -1844,8 +1844,8 @@ F:        drivers/i2c/busses/i2c-st.c
 F:     drivers/media/rc/st_rc.c
 F:     drivers/media/platform/sti/c8sectpfe/
 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/remoteproc/st_remoteproc.c
 F:     drivers/remoteproc/st_slim_rproc.c
@@ -10833,7 +10833,7 @@ RENESAS USB2 PHY DRIVER
 M:     Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
 L:     linux-renesas-soc@vger.kernel.org
 S:     Maintained
-F:     drivers/phy/phy-rcar-gen3-usb2.c
+F:     drivers/phy/renesas/phy-rcar-gen3-usb2.c
 
 RESET CONTROLLER FRAMEWORK
 M:     Philipp Zabel <p.zabel@pengutronix.de>
@@ -11235,12 +11235,12 @@ L:    linux-kernel@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/phy/samsung-phy.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
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
index afaf7b643eebf8ee45e12d62b6efde668c7a6192..01009b2a7d74dd72dc3e5d255bccaf2f719c2fb3 100644 (file)
@@ -15,73 +15,6 @@ config GENERIC_PHY
          phy users can obtain reference to the PHY. All the users of this
          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
        tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
        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
          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
        tristate "Mediatek USB3.0 PHY Driver"
        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,
          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
        tristate "IMG Pistachio USB2.0 PHY driver"
        depends on MACH_PISTACHIO
@@ -346,83 +41,6 @@ config PHY_PISTACHIO_USB
        help
          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
        tristate "APM X-Gene 15Gbps PHY support"
        depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST)
@@ -430,104 +48,17 @@ config PHY_XGENE
        help
          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/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"
-
-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
index f8047b4639fa7e80cef178192a1de5df4ddf1225..c1bd1fa3c853c552a7cbc32f9c1038fa25ccf31e 100644 (file)
@@ -3,64 +3,20 @@
 #
 
 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_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_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_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_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/     \
+                                          qualcomm/    \
+                                          samsung/     \
+                                          st/          \
+                                          ti/
diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig
new file mode 100644 (file)
index 0000000..cdc1e74
--- /dev/null
@@ -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.
diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile
new file mode 100644 (file)
index 0000000..8605529
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_PHY_SUN4I_USB)            += phy-sun4i-usb.o
+obj-$(CONFIG_PHY_SUN9I_USB)            += phy-sun9i-usb.o
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
new file mode 100644 (file)
index 0000000..bbf06cf
--- /dev/null
@@ -0,0 +1,891 @@
+/*
+ * Allwinner sun4i USB phy driver
+ *
+ * Copyright (C) 2014-2015 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on code from
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * Modelled after: Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/extcon.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-sun4i-usb.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+#include <linux/usb/of.h>
+#include <linux/workqueue.h>
+
+#define REG_ISCR                       0x00
+#define REG_PHYCTL_A10                 0x04
+#define REG_PHYBIST                    0x08
+#define REG_PHYTUNE                    0x0c
+#define REG_PHYCTL_A33                 0x10
+#define REG_PHY_OTGCTL                 0x20
+
+#define REG_PMU_UNK1                   0x10
+
+#define PHYCTL_DATA                    BIT(7)
+
+#define OTGCTL_ROUTE_MUSB              BIT(0)
+
+#define SUNXI_AHB_ICHR8_EN             BIT(10)
+#define SUNXI_AHB_INCR4_BURST_EN       BIT(9)
+#define SUNXI_AHB_INCRX_ALIGN_EN       BIT(8)
+#define SUNXI_ULPI_BYPASS_EN           BIT(0)
+
+/* ISCR, Interface Status and Control bits */
+#define ISCR_ID_PULLUP_EN              (1 << 17)
+#define ISCR_DPDM_PULLUP_EN    (1 << 16)
+/* sunxi has the phy id/vbus pins not connected, so we use the force bits */
+#define ISCR_FORCE_ID_MASK     (3 << 14)
+#define ISCR_FORCE_ID_LOW              (2 << 14)
+#define ISCR_FORCE_ID_HIGH     (3 << 14)
+#define ISCR_FORCE_VBUS_MASK   (3 << 12)
+#define ISCR_FORCE_VBUS_LOW    (2 << 12)
+#define ISCR_FORCE_VBUS_HIGH   (3 << 12)
+
+/* Common Control Bits for Both PHYs */
+#define PHY_PLL_BW                     0x03
+#define PHY_RES45_CAL_EN               0x0c
+
+/* Private Control Bits for Each PHY */
+#define PHY_TX_AMPLITUDE_TUNE          0x20
+#define PHY_TX_SLEWRATE_TUNE           0x22
+#define PHY_VBUSVALID_TH_SEL           0x25
+#define PHY_PULLUP_RES_SEL             0x27
+#define PHY_OTG_FUNC_EN                        0x28
+#define PHY_VBUS_DET_EN                        0x29
+#define PHY_DISCON_TH_SEL              0x2a
+#define PHY_SQUELCH_DETECT             0x3c
+
+#define MAX_PHYS                       4
+
+/*
+ * Note do not raise the debounce time, we must report Vusb high within 100ms
+ * otherwise we get Vbus errors
+ */
+#define DEBOUNCE_TIME                  msecs_to_jiffies(50)
+#define POLL_TIME                      msecs_to_jiffies(250)
+
+enum sun4i_usb_phy_type {
+       sun4i_a10_phy,
+       sun6i_a31_phy,
+       sun8i_a33_phy,
+       sun8i_h3_phy,
+       sun8i_v3s_phy,
+       sun50i_a64_phy,
+};
+
+struct sun4i_usb_phy_cfg {
+       int num_phys;
+       enum sun4i_usb_phy_type type;
+       u32 disc_thresh;
+       u8 phyctl_offset;
+       bool dedicated_clocks;
+       bool enable_pmu_unk1;
+       bool phy0_dual_route;
+};
+
+struct sun4i_usb_phy_data {
+       void __iomem *base;
+       const struct sun4i_usb_phy_cfg *cfg;
+       enum usb_dr_mode dr_mode;
+       spinlock_t reg_lock; /* guard access to phyctl reg */
+       struct sun4i_usb_phy {
+               struct phy *phy;
+               void __iomem *pmu;
+               struct regulator *vbus;
+               struct reset_control *reset;
+               struct clk *clk;
+               bool regulator_on;
+               int index;
+       } phys[MAX_PHYS];
+       /* phy0 / otg related variables */
+       struct extcon_dev *extcon;
+       bool phy0_init;
+       struct gpio_desc *id_det_gpio;
+       struct gpio_desc *vbus_det_gpio;
+       struct power_supply *vbus_power_supply;
+       struct notifier_block vbus_power_nb;
+       bool vbus_power_nb_registered;
+       bool force_session_end;
+       int id_det_irq;
+       int vbus_det_irq;
+       int id_det;
+       int vbus_det;
+       struct delayed_work detect;
+};
+
+#define to_sun4i_usb_phy_data(phy) \
+       container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index])
+
+static void sun4i_usb_phy0_update_iscr(struct phy *_phy, u32 clr, u32 set)
+{
+       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+       u32 iscr;
+
+       iscr = readl(data->base + REG_ISCR);
+       iscr &= ~clr;
+       iscr |= set;
+       writel(iscr, data->base + REG_ISCR);
+}
+
+static void sun4i_usb_phy0_set_id_detect(struct phy *phy, u32 val)
+{
+       if (val)
+               val = ISCR_FORCE_ID_HIGH;
+       else
+               val = ISCR_FORCE_ID_LOW;
+
+       sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_ID_MASK, val);
+}
+
+static void sun4i_usb_phy0_set_vbus_detect(struct phy *phy, u32 val)
+{
+       if (val)
+               val = ISCR_FORCE_VBUS_HIGH;
+       else
+               val = ISCR_FORCE_VBUS_LOW;
+
+       sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_VBUS_MASK, val);
+}
+
+static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
+                               int len)
+{
+       struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
+       u32 temp, usbc_bit = BIT(phy->index * 2);
+       void __iomem *phyctl = phy_data->base + phy_data->cfg->phyctl_offset;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&phy_data->reg_lock, flags);
+
+       if (phy_data->cfg->phyctl_offset == REG_PHYCTL_A33) {
+               /* SoCs newer than A33 need us to set phyctl to 0 explicitly */
+               writel(0, phyctl);
+       }
+
+       for (i = 0; i < len; i++) {
+               temp = readl(phyctl);
+
+               /* clear the address portion */
+               temp &= ~(0xff << 8);
+
+               /* set the address */
+               temp |= ((addr + i) << 8);
+               writel(temp, phyctl);
+
+               /* set the data bit and clear usbc bit*/
+               temp = readb(phyctl);
+               if (data & 0x1)
+                       temp |= PHYCTL_DATA;
+               else
+                       temp &= ~PHYCTL_DATA;
+               temp &= ~usbc_bit;
+               writeb(temp, phyctl);
+
+               /* pulse usbc_bit */
+               temp = readb(phyctl);
+               temp |= usbc_bit;
+               writeb(temp, phyctl);
+
+               temp = readb(phyctl);
+               temp &= ~usbc_bit;
+               writeb(temp, phyctl);
+
+               data >>= 1;
+       }
+
+       spin_unlock_irqrestore(&phy_data->reg_lock, flags);
+}
+
+static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
+{
+       u32 bits, reg_value;
+
+       if (!phy->pmu)
+               return;
+
+       bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
+               SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
+
+       reg_value = readl(phy->pmu);
+
+       if (enable)
+               reg_value |= bits;
+       else
+               reg_value &= ~bits;
+
+       writel(reg_value, phy->pmu);
+}
+
+static int sun4i_usb_phy_init(struct phy *_phy)
+{
+       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+       int ret;
+       u32 val;
+
+       ret = clk_prepare_enable(phy->clk);
+       if (ret)
+               return ret;
+
+       ret = reset_control_deassert(phy->reset);
+       if (ret) {
+               clk_disable_unprepare(phy->clk);
+               return ret;
+       }
+
+       if (phy->pmu && data->cfg->enable_pmu_unk1) {
+               val = readl(phy->pmu + REG_PMU_UNK1);
+               writel(val & ~2, phy->pmu + REG_PMU_UNK1);
+       }
+
+       /* Enable USB 45 Ohm resistor calibration */
+       if (phy->index == 0)
+               sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1);
+
+       /* Adjust PHY's magnitude and rate */
+       sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
+
+       /* Disconnect threshold adjustment */
+       sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
+                           data->cfg->disc_thresh, 2);
+
+       sun4i_usb_phy_passby(phy, 1);
+
+       if (phy->index == 0) {
+               data->phy0_init = true;
+
+               /* Enable pull-ups */
+               sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_DPDM_PULLUP_EN);
+               sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_ID_PULLUP_EN);
+
+               /* Force ISCR and cable state updates */
+               data->id_det = -1;
+               data->vbus_det = -1;
+               queue_delayed_work(system_wq, &data->detect, 0);
+       }
+
+       return 0;
+}
+
+static int sun4i_usb_phy_exit(struct phy *_phy)
+{
+       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+
+       if (phy->index == 0) {
+               /* Disable pull-ups */
+               sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0);
+               sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0);
+               data->phy0_init = false;
+       }
+
+       sun4i_usb_phy_passby(phy, 0);
+       reset_control_assert(phy->reset);
+       clk_disable_unprepare(phy->clk);
+
+       return 0;
+}
+
+static int sun4i_usb_phy0_get_id_det(struct sun4i_usb_phy_data *data)
+{
+       switch (data->dr_mode) {
+       case USB_DR_MODE_OTG:
+               if (data->id_det_gpio)
+                       return gpiod_get_value_cansleep(data->id_det_gpio);
+               else
+                       return 1; /* Fallback to peripheral mode */
+       case USB_DR_MODE_HOST:
+               return 0;
+       case USB_DR_MODE_PERIPHERAL:
+       default:
+               return 1;
+       }
+}
+
+static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data)
+{
+       if (data->vbus_det_gpio)
+               return gpiod_get_value_cansleep(data->vbus_det_gpio);
+
+       if (data->vbus_power_supply) {
+               union power_supply_propval val;
+               int r;
+
+               r = power_supply_get_property(data->vbus_power_supply,
+                                             POWER_SUPPLY_PROP_PRESENT, &val);
+               if (r == 0)
+                       return val.intval;
+       }
+
+       /* Fallback: report vbus as high */
+       return 1;
+}
+
+static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data)
+{
+       return data->vbus_det_gpio || data->vbus_power_supply;
+}
+
+static bool sun4i_usb_phy0_poll(struct sun4i_usb_phy_data *data)
+{
+       if ((data->id_det_gpio && data->id_det_irq <= 0) ||
+           (data->vbus_det_gpio && data->vbus_det_irq <= 0))
+               return true;
+
+       /*
+        * The A31 companion pmic (axp221) does not generate vbus change
+        * interrupts when the board is driving vbus, so we must poll
+        * when using the pmic for vbus-det _and_ we're driving vbus.
+        */
+       if (data->cfg->type == sun6i_a31_phy &&
+           data->vbus_power_supply && data->phys[0].regulator_on)
+               return true;
+
+       return false;
+}
+
+static int sun4i_usb_phy_power_on(struct phy *_phy)
+{
+       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+       int ret;
+
+       if (!phy->vbus || phy->regulator_on)
+               return 0;
+
+       /* For phy0 only turn on Vbus if we don't have an ext. Vbus */
+       if (phy->index == 0 && sun4i_usb_phy0_have_vbus_det(data) &&
+                               data->vbus_det) {
+               dev_warn(&_phy->dev, "External vbus detected, not enabling our own vbus\n");
+               return 0;
+       }
+
+       ret = regulator_enable(phy->vbus);
+       if (ret)
+               return ret;
+
+       phy->regulator_on = true;
+
+       /* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */
+       if (phy->index == 0 && sun4i_usb_phy0_poll(data))
+               mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
+
+       return 0;
+}
+
+static int sun4i_usb_phy_power_off(struct phy *_phy)
+{
+       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+
+       if (!phy->vbus || !phy->regulator_on)
+               return 0;
+
+       regulator_disable(phy->vbus);
+       phy->regulator_on = false;
+
+       /*
+        * phy0 vbus typically slowly discharges, sometimes this causes the
+        * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan.
+        */
+       if (phy->index == 0 && !sun4i_usb_phy0_poll(data))
+               mod_delayed_work(system_wq, &data->detect, POLL_TIME);
+
+       return 0;
+}
+
+static int sun4i_usb_phy_set_mode(struct phy *_phy, enum phy_mode mode)
+{
+       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+       int new_mode;
+
+       if (phy->index != 0)
+               return -EINVAL;
+
+       switch (mode) {
+       case PHY_MODE_USB_HOST:
+               new_mode = USB_DR_MODE_HOST;
+               break;
+       case PHY_MODE_USB_DEVICE:
+               new_mode = USB_DR_MODE_PERIPHERAL;
+               break;
+       case PHY_MODE_USB_OTG:
+               new_mode = USB_DR_MODE_OTG;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (new_mode != data->dr_mode) {
+               dev_info(&_phy->dev, "Changing dr_mode to %d\n", new_mode);
+               data->dr_mode = new_mode;
+       }
+
+       data->id_det = -1; /* Force reprocessing of id */
+       data->force_session_end = true;
+       queue_delayed_work(system_wq, &data->detect, 0);
+
+       return 0;
+}
+
+void sun4i_usb_phy_set_squelch_detect(struct phy *_phy, bool enabled)
+{
+       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+
+       sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2);
+}
+EXPORT_SYMBOL_GPL(sun4i_usb_phy_set_squelch_detect);
+
+static const struct phy_ops sun4i_usb_phy_ops = {
+       .init           = sun4i_usb_phy_init,
+       .exit           = sun4i_usb_phy_exit,
+       .power_on       = sun4i_usb_phy_power_on,
+       .power_off      = sun4i_usb_phy_power_off,
+       .set_mode       = sun4i_usb_phy_set_mode,
+       .owner          = THIS_MODULE,
+};
+
+static void sun4i_usb_phy0_reroute(struct sun4i_usb_phy_data *data, int id_det)
+{
+       u32 regval;
+
+       regval = readl(data->base + REG_PHY_OTGCTL);
+       if (id_det == 0) {
+               /* Host mode. Route phy0 to EHCI/OHCI */
+               regval &= ~OTGCTL_ROUTE_MUSB;
+       } else {
+               /* Peripheral mode. Route phy0 to MUSB */
+               regval |= OTGCTL_ROUTE_MUSB;
+       }
+       writel(regval, data->base + REG_PHY_OTGCTL);
+}
+
+static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
+{
+       struct sun4i_usb_phy_data *data =
+               container_of(work, struct sun4i_usb_phy_data, detect.work);
+       struct phy *phy0 = data->phys[0].phy;
+       bool force_session_end, id_notify = false, vbus_notify = false;
+       int id_det, vbus_det;
+
+       if (phy0 == NULL)
+               return;
+
+       id_det = sun4i_usb_phy0_get_id_det(data);
+       vbus_det = sun4i_usb_phy0_get_vbus_det(data);
+
+       mutex_lock(&phy0->mutex);
+
+       if (!data->phy0_init) {
+               mutex_unlock(&phy0->mutex);
+               return;
+       }
+
+       force_session_end = data->force_session_end;
+       data->force_session_end = false;
+
+       if (id_det != data->id_det) {
+               /* id-change, force session end if we've no vbus detection */
+               if (data->dr_mode == USB_DR_MODE_OTG &&
+                   !sun4i_usb_phy0_have_vbus_det(data))
+                       force_session_end = true;
+
+               /* When entering host mode (id = 0) force end the session now */
+               if (force_session_end && id_det == 0) {
+                       sun4i_usb_phy0_set_vbus_detect(phy0, 0);
+                       msleep(200);
+                       sun4i_usb_phy0_set_vbus_detect(phy0, 1);
+               }
+               sun4i_usb_phy0_set_id_detect(phy0, id_det);
+               data->id_det = id_det;
+               id_notify = true;
+       }
+
+       if (vbus_det != data->vbus_det) {
+               sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det);
+               data->vbus_det = vbus_det;
+               vbus_notify = true;
+       }
+
+       mutex_unlock(&phy0->mutex);
+
+       if (id_notify) {
+               extcon_set_state_sync(data->extcon, EXTCON_USB_HOST,
+                                       !id_det);
+               /* When leaving host mode force end the session here */
+               if (force_session_end && id_det == 1) {
+                       mutex_lock(&phy0->mutex);
+                       sun4i_usb_phy0_set_vbus_detect(phy0, 0);
+                       msleep(1000);
+                       sun4i_usb_phy0_set_vbus_detect(phy0, 1);
+                       mutex_unlock(&phy0->mutex);
+               }
+
+               /* Re-route PHY0 if necessary */
+               if (data->cfg->phy0_dual_route)
+                       sun4i_usb_phy0_reroute(data, id_det);
+       }
+
+       if (vbus_notify)
+               extcon_set_state_sync(data->extcon, EXTCON_USB, vbus_det);
+
+       if (sun4i_usb_phy0_poll(data))
+               queue_delayed_work(system_wq, &data->detect, POLL_TIME);
+}
+
+static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id)
+{
+       struct sun4i_usb_phy_data *data = dev_id;
+
+       /* vbus or id changed, let the pins settle and then scan them */
+       mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
+
+       return IRQ_HANDLED;
+}
+
+static int sun4i_usb_phy0_vbus_notify(struct notifier_block *nb,
+                                     unsigned long val, void *v)
+{
+       struct sun4i_usb_phy_data *data =
+               container_of(nb, struct sun4i_usb_phy_data, vbus_power_nb);
+       struct power_supply *psy = v;
+
+       /* Properties on the vbus_power_supply changed, scan vbus_det */
+       if (val == PSY_EVENT_PROP_CHANGED && psy == data->vbus_power_supply)
+               mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
+
+       return NOTIFY_OK;
+}
+
+static struct phy *sun4i_usb_phy_xlate(struct device *dev,
+                                       struct of_phandle_args *args)
+{
+       struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
+
+       if (args->args[0] >= data->cfg->num_phys)
+               return ERR_PTR(-ENODEV);
+
+       return data->phys[args->args[0]].phy;
+}
+
+static int sun4i_usb_phy_remove(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
+
+       if (data->vbus_power_nb_registered)
+               power_supply_unreg_notifier(&data->vbus_power_nb);
+       if (data->id_det_irq > 0)
+               devm_free_irq(dev, data->id_det_irq, data);
+       if (data->vbus_det_irq > 0)
+               devm_free_irq(dev, data->vbus_det_irq, data);
+
+       cancel_delayed_work_sync(&data->detect);
+
+       return 0;
+}
+
+static const unsigned int sun4i_usb_phy0_cable[] = {
+       EXTCON_USB,
+       EXTCON_USB_HOST,
+       EXTCON_NONE,
+};
+
+static int sun4i_usb_phy_probe(struct platform_device *pdev)
+{
+       struct sun4i_usb_phy_data *data;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct phy_provider *phy_provider;
+       struct resource *res;
+       int i, ret;
+
+       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       spin_lock_init(&data->reg_lock);
+       INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan);
+       dev_set_drvdata(dev, data);
+       data->cfg = of_device_get_match_data(dev);
+       if (!data->cfg)
+               return -EINVAL;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
+       data->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(data->base))
+               return PTR_ERR(data->base);
+
+       data->id_det_gpio = devm_gpiod_get_optional(dev, "usb0_id_det",
+                                                   GPIOD_IN);
+       if (IS_ERR(data->id_det_gpio))
+               return PTR_ERR(data->id_det_gpio);
+
+       data->vbus_det_gpio = devm_gpiod_get_optional(dev, "usb0_vbus_det",
+                                                     GPIOD_IN);
+       if (IS_ERR(data->vbus_det_gpio))
+               return PTR_ERR(data->vbus_det_gpio);
+
+       if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
+               data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
+                                                    "usb0_vbus_power-supply");
+               if (IS_ERR(data->vbus_power_supply))
+                       return PTR_ERR(data->vbus_power_supply);
+
+               if (!data->vbus_power_supply)
+                       return -EPROBE_DEFER;
+       }
+
+       data->dr_mode = of_usb_get_dr_mode_by_phy(np, 0);
+
+       data->extcon = devm_extcon_dev_allocate(dev, sun4i_usb_phy0_cable);
+       if (IS_ERR(data->extcon))
+               return PTR_ERR(data->extcon);
+
+       ret = devm_extcon_dev_register(dev, data->extcon);
+       if (ret) {
+               dev_err(dev, "failed to register extcon: %d\n", ret);
+               return ret;
+       }
+
+       for (i = 0; i < data->cfg->num_phys; i++) {
+               struct sun4i_usb_phy *phy = data->phys + i;
+               char name[16];
+
+               snprintf(name, sizeof(name), "usb%d_vbus", i);
+               phy->vbus = devm_regulator_get_optional(dev, name);
+               if (IS_ERR(phy->vbus)) {
+                       if (PTR_ERR(phy->vbus) == -EPROBE_DEFER)
+                               return -EPROBE_DEFER;
+                       phy->vbus = NULL;
+               }
+
+               if (data->cfg->dedicated_clocks)
+                       snprintf(name, sizeof(name), "usb%d_phy", i);
+               else
+                       strlcpy(name, "usb_phy", sizeof(name));
+
+               phy->clk = devm_clk_get(dev, name);
+               if (IS_ERR(phy->clk)) {
+                       dev_err(dev, "failed to get clock %s\n", name);
+                       return PTR_ERR(phy->clk);
+               }
+
+               snprintf(name, sizeof(name), "usb%d_reset", i);
+               phy->reset = devm_reset_control_get(dev, name);
+               if (IS_ERR(phy->reset)) {
+                       dev_err(dev, "failed to get reset %s\n", name);
+                       return PTR_ERR(phy->reset);
+               }
+
+               if (i || data->cfg->phy0_dual_route) { /* No pmu for musb */
+                       snprintf(name, sizeof(name), "pmu%d", i);
+                       res = platform_get_resource_byname(pdev,
+                                                       IORESOURCE_MEM, name);
+                       phy->pmu = devm_ioremap_resource(dev, res);
+                       if (IS_ERR(phy->pmu))
+                               return PTR_ERR(phy->pmu);
+               }
+
+               phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops);
+               if (IS_ERR(phy->phy)) {
+                       dev_err(dev, "failed to create PHY %d\n", i);
+                       return PTR_ERR(phy->phy);
+               }
+
+               phy->index = i;
+               phy_set_drvdata(phy->phy, &data->phys[i]);
+       }
+
+       data->id_det_irq = gpiod_to_irq(data->id_det_gpio);
+       if (data->id_det_irq > 0) {
+               ret = devm_request_irq(dev, data->id_det_irq,
+                               sun4i_usb_phy0_id_vbus_det_irq,
+                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               "usb0-id-det", data);
+               if (ret) {
+                       dev_err(dev, "Err requesting id-det-irq: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
+       if (data->vbus_det_irq > 0) {
+               ret = devm_request_irq(dev, data->vbus_det_irq,
+                               sun4i_usb_phy0_id_vbus_det_irq,
+                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               "usb0-vbus-det", data);
+               if (ret) {
+                       dev_err(dev, "Err requesting vbus-det-irq: %d\n", ret);
+                       data->vbus_det_irq = -1;
+                       sun4i_usb_phy_remove(pdev); /* Stop detect work */
+                       return ret;
+               }
+       }
+
+       if (data->vbus_power_supply) {
+               data->vbus_power_nb.notifier_call = sun4i_usb_phy0_vbus_notify;
+               data->vbus_power_nb.priority = 0;
+               ret = power_supply_reg_notifier(&data->vbus_power_nb);
+               if (ret) {
+                       sun4i_usb_phy_remove(pdev); /* Stop detect work */
+                       return ret;
+               }
+               data->vbus_power_nb_registered = true;
+       }
+
+       phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
+       if (IS_ERR(phy_provider)) {
+               sun4i_usb_phy_remove(pdev); /* Stop detect work */
+               return PTR_ERR(phy_provider);
+       }
+
+       return 0;
+}
+
+static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = {
+       .num_phys = 3,
+       .type = sun4i_a10_phy,
+       .disc_thresh = 3,
+       .phyctl_offset = REG_PHYCTL_A10,
+       .dedicated_clocks = false,
+       .enable_pmu_unk1 = false,
+};
+
+static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
+       .num_phys = 2,
+       .type = sun4i_a10_phy,
+       .disc_thresh = 2,
+       .phyctl_offset = REG_PHYCTL_A10,
+       .dedicated_clocks = false,
+       .enable_pmu_unk1 = false,
+};
+
+static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
+       .num_phys = 3,
+       .type = sun6i_a31_phy,
+       .disc_thresh = 3,
+       .phyctl_offset = REG_PHYCTL_A10,
+       .dedicated_clocks = true,
+       .enable_pmu_unk1 = false,
+};
+
+static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = {
+       .num_phys = 3,
+       .type = sun4i_a10_phy,
+       .disc_thresh = 2,
+       .phyctl_offset = REG_PHYCTL_A10,
+       .dedicated_clocks = false,
+       .enable_pmu_unk1 = false,
+};
+
+static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
+       .num_phys = 2,
+       .type = sun4i_a10_phy,
+       .disc_thresh = 3,
+       .phyctl_offset = REG_PHYCTL_A10,
+       .dedicated_clocks = true,
+       .enable_pmu_unk1 = false,
+};
+
+static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
+       .num_phys = 2,
+       .type = sun8i_a33_phy,
+       .disc_thresh = 3,
+       .phyctl_offset = REG_PHYCTL_A33,
+       .dedicated_clocks = true,
+       .enable_pmu_unk1 = false,
+};
+
+static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
+       .num_phys = 4,
+       .type = sun8i_h3_phy,
+       .disc_thresh = 3,
+       .phyctl_offset = REG_PHYCTL_A33,
+       .dedicated_clocks = true,
+       .enable_pmu_unk1 = true,
+       .phy0_dual_route = true,
+};
+
+static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
+       .num_phys = 1,
+       .type = sun8i_v3s_phy,
+       .disc_thresh = 3,
+       .phyctl_offset = REG_PHYCTL_A33,
+       .dedicated_clocks = true,
+       .enable_pmu_unk1 = true,
+};
+
+static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
+       .num_phys = 2,
+       .type = sun50i_a64_phy,
+       .disc_thresh = 3,
+       .phyctl_offset = REG_PHYCTL_A33,
+       .dedicated_clocks = true,
+       .enable_pmu_unk1 = true,
+       .phy0_dual_route = true,
+};
+
+static const struct of_device_id sun4i_usb_phy_of_match[] = {
+       { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg },
+       { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg },
+       { .compatible = "allwinner,sun6i-a31-usb-phy", .data = &sun6i_a31_cfg },
+       { .compatible = "allwinner,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg },
+       { .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
+       { .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg },
+       { .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg },
+       { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
+       { .compatible = "allwinner,sun50i-a64-usb-phy",
+         .data = &sun50i_a64_cfg},
+       { },
+};
+MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
+
+static struct platform_driver sun4i_usb_phy_driver = {
+       .probe  = sun4i_usb_phy_probe,
+       .remove = sun4i_usb_phy_remove,
+       .driver = {
+               .of_match_table = sun4i_usb_phy_of_match,
+               .name  = "sun4i-usb-phy",
+       }
+};
+module_platform_driver(sun4i_usb_phy_driver);
+
+MODULE_DESCRIPTION("Allwinner sun4i USB phy driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/allwinner/phy-sun9i-usb.c b/drivers/phy/allwinner/phy-sun9i-usb.c
new file mode 100644 (file)
index 0000000..28fce4b
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Allwinner sun9i USB phy driver
+ *
+ * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
+ *
+ * Based on phy-sun4i-usb.c from
+ * Hans de Goede <hdegoede@redhat.com>
+ *
+ * and code from
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/usb/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#define SUNXI_AHB_INCR16_BURST_EN      BIT(11)
+#define SUNXI_AHB_INCR8_BURST_EN       BIT(10)
+#define SUNXI_AHB_INCR4_BURST_EN       BIT(9)
+#define SUNXI_AHB_INCRX_ALIGN_EN       BIT(8)
+#define SUNXI_ULPI_BYPASS_EN           BIT(0)
+
+/* usb1 HSIC specific bits */
+#define SUNXI_EHCI_HS_FORCE            BIT(20)
+#define SUNXI_HSIC_CONNECT_DET         BIT(17)
+#define SUNXI_HSIC_CONNECT_INT         BIT(16)
+#define SUNXI_HSIC                     BIT(1)
+
+struct sun9i_usb_phy {
+       struct phy *phy;
+       void __iomem *pmu;
+       struct reset_control *reset;
+       struct clk *clk;
+       struct clk *hsic_clk;
+       enum usb_phy_interface type;
+};
+
+static void sun9i_usb_phy_passby(struct sun9i_usb_phy *phy, int enable)
+{
+       u32 bits, reg_value;
+
+       bits = SUNXI_AHB_INCR16_BURST_EN | SUNXI_AHB_INCR8_BURST_EN |
+               SUNXI_AHB_INCR4_BURST_EN | SUNXI_AHB_INCRX_ALIGN_EN |
+               SUNXI_ULPI_BYPASS_EN;
+
+       if (phy->type == USBPHY_INTERFACE_MODE_HSIC)
+               bits |= SUNXI_HSIC | SUNXI_EHCI_HS_FORCE |
+                       SUNXI_HSIC_CONNECT_DET | SUNXI_HSIC_CONNECT_INT;
+
+       reg_value = readl(phy->pmu);
+
+       if (enable)
+               reg_value |= bits;
+       else
+               reg_value &= ~bits;
+
+       writel(reg_value, phy->pmu);
+}
+
+static int sun9i_usb_phy_init(struct phy *_phy)
+{
+       struct sun9i_usb_phy *phy = phy_get_drvdata(_phy);
+       int ret;
+
+       ret = clk_prepare_enable(phy->clk);
+       if (ret)
+               goto err_clk;
+
+       ret = clk_prepare_enable(phy->hsic_clk);
+       if (ret)
+               goto err_hsic_clk;
+
+       ret = reset_control_deassert(phy->reset);
+       if (ret)
+               goto err_reset;
+
+       sun9i_usb_phy_passby(phy, 1);
+       return 0;
+
+err_reset:
+       clk_disable_unprepare(phy->hsic_clk);
+
+err_hsic_clk:
+       clk_disable_unprepare(phy->clk);
+
+err_clk:
+       return ret;
+}
+
+static int sun9i_usb_phy_exit(struct phy *_phy)
+{
+       struct sun9i_usb_phy *phy = phy_get_drvdata(_phy);
+
+       sun9i_usb_phy_passby(phy, 0);
+       reset_control_assert(phy->reset);
+       clk_disable_unprepare(phy->hsic_clk);
+       clk_disable_unprepare(phy->clk);
+
+       return 0;
+}
+
+static const struct phy_ops sun9i_usb_phy_ops = {
+       .init           = sun9i_usb_phy_init,
+       .exit           = sun9i_usb_phy_exit,
+       .owner          = THIS_MODULE,
+};
+
+static int sun9i_usb_phy_probe(struct platform_device *pdev)
+{
+       struct sun9i_usb_phy *phy;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct phy_provider *phy_provider;
+       struct resource *res;
+
+       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy)
+               return -ENOMEM;
+
+       phy->type = of_usb_get_phy_mode(np);
+       if (phy->type == USBPHY_INTERFACE_MODE_HSIC) {
+               phy->clk = devm_clk_get(dev, "hsic_480M");
+               if (IS_ERR(phy->clk)) {
+                       dev_err(dev, "failed to get hsic_480M clock\n");
+                       return PTR_ERR(phy->clk);
+               }
+
+               phy->hsic_clk = devm_clk_get(dev, "hsic_12M");
+               if (IS_ERR(phy->hsic_clk)) {
+                       dev_err(dev, "failed to get hsic_12M clock\n");
+                       return PTR_ERR(phy->hsic_clk);
+               }
+
+               phy->reset = devm_reset_control_get(dev, "hsic");
+               if (IS_ERR(phy->reset)) {
+                       dev_err(dev, "failed to get reset control\n");
+                       return PTR_ERR(phy->reset);
+               }
+       } else {
+               phy->clk = devm_clk_get(dev, "phy");
+               if (IS_ERR(phy->clk)) {
+                       dev_err(dev, "failed to get phy clock\n");
+                       return PTR_ERR(phy->clk);
+               }
+
+               phy->reset = devm_reset_control_get(dev, "phy");
+               if (IS_ERR(phy->reset)) {
+                       dev_err(dev, "failed to get reset control\n");
+                       return PTR_ERR(phy->reset);
+               }
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       phy->pmu = devm_ioremap_resource(dev, res);
+       if (IS_ERR(phy->pmu))
+               return PTR_ERR(phy->pmu);
+
+       phy->phy = devm_phy_create(dev, NULL, &sun9i_usb_phy_ops);
+       if (IS_ERR(phy->phy)) {
+               dev_err(dev, "failed to create PHY\n");
+               return PTR_ERR(phy->phy);
+       }
+
+       phy_set_drvdata(phy->phy, phy);
+       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 sun9i_usb_phy_of_match[] = {
+       { .compatible = "allwinner,sun9i-a80-usb-phy" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, sun9i_usb_phy_of_match);
+
+static struct platform_driver sun9i_usb_phy_driver = {
+       .probe  = sun9i_usb_phy_probe,
+       .driver = {
+               .of_match_table = sun9i_usb_phy_of_match,
+               .name  = "sun9i-usb-phy",
+       }
+};
+module_platform_driver(sun9i_usb_phy_driver);
+
+MODULE_DESCRIPTION("Allwinner sun9i USB phy driver");
+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig
new file mode 100644 (file)
index 0000000..edcd5b6
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Phy drivers for Amlogic platforms
+#
+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.
diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile
new file mode 100644 (file)
index 0000000..47b6eec
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_PHY_MESON8B_USB2)         += phy-meson8b-usb2.o
diff --git a/drivers/phy/amlogic/phy-meson8b-usb2.c b/drivers/phy/amlogic/phy-meson8b-usb2.c
new file mode 100644 (file)
index 0000000..30f56a6
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * Meson8b and GXBB USB2 PHY driver
+ *
+ * Copyright (C) 2016 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/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/reset.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/usb/of.h>
+
+#define REG_CONFIG                                     0x00
+       #define REG_CONFIG_CLK_EN                       BIT(0)
+       #define REG_CONFIG_CLK_SEL_MASK                 GENMASK(3, 1)
+       #define REG_CONFIG_CLK_DIV_MASK                 GENMASK(10, 4)
+       #define REG_CONFIG_CLK_32k_ALTSEL               BIT(15)
+       #define REG_CONFIG_TEST_TRIG                    BIT(31)
+
+#define REG_CTRL                                       0x04
+       #define REG_CTRL_SOFT_PRST                      BIT(0)
+       #define REG_CTRL_SOFT_HRESET                    BIT(1)
+       #define REG_CTRL_SS_SCALEDOWN_MODE_MASK         GENMASK(3, 2)
+       #define REG_CTRL_CLK_DET_RST                    BIT(4)
+       #define REG_CTRL_INTR_SEL                       BIT(5)
+       #define REG_CTRL_CLK_DETECTED                   BIT(8)
+       #define REG_CTRL_SOF_SENT_RCVD_TGL              BIT(9)
+       #define REG_CTRL_SOF_TOGGLE_OUT                 BIT(10)
+       #define REG_CTRL_POWER_ON_RESET                 BIT(15)
+       #define REG_CTRL_SLEEPM                         BIT(16)
+       #define REG_CTRL_TX_BITSTUFF_ENN_H              BIT(17)
+       #define REG_CTRL_TX_BITSTUFF_ENN                BIT(18)
+       #define REG_CTRL_COMMON_ON                      BIT(19)
+       #define REG_CTRL_REF_CLK_SEL_MASK               GENMASK(21, 20)
+       #define REG_CTRL_REF_CLK_SEL_SHIFT              20
+       #define REG_CTRL_FSEL_MASK                      GENMASK(24, 22)
+       #define REG_CTRL_FSEL_SHIFT                     22
+       #define REG_CTRL_PORT_RESET                     BIT(25)
+       #define REG_CTRL_THREAD_ID_MASK                 GENMASK(31, 26)
+
+#define REG_ENDP_INTR                                  0x08
+
+/* bits [31:26], [24:21] and [15:3] seem to be read-only */
+#define REG_ADP_BC                                     0x0c
+       #define REG_ADP_BC_VBUS_VLD_EXT_SEL             BIT(0)
+       #define REG_ADP_BC_VBUS_VLD_EXT                 BIT(1)
+       #define REG_ADP_BC_OTG_DISABLE                  BIT(2)
+       #define REG_ADP_BC_ID_PULLUP                    BIT(3)
+       #define REG_ADP_BC_DRV_VBUS                     BIT(4)
+       #define REG_ADP_BC_ADP_PRB_EN                   BIT(5)
+       #define REG_ADP_BC_ADP_DISCHARGE                BIT(6)
+       #define REG_ADP_BC_ADP_CHARGE                   BIT(7)
+       #define REG_ADP_BC_SESS_END                     BIT(8)
+       #define REG_ADP_BC_DEVICE_SESS_VLD              BIT(9)
+       #define REG_ADP_BC_B_VALID                      BIT(10)
+       #define REG_ADP_BC_A_VALID                      BIT(11)
+       #define REG_ADP_BC_ID_DIG                       BIT(12)
+       #define REG_ADP_BC_VBUS_VALID                   BIT(13)
+       #define REG_ADP_BC_ADP_PROBE                    BIT(14)
+       #define REG_ADP_BC_ADP_SENSE                    BIT(15)
+       #define REG_ADP_BC_ACA_ENABLE                   BIT(16)
+       #define REG_ADP_BC_DCD_ENABLE                   BIT(17)
+       #define REG_ADP_BC_VDAT_DET_EN_B                BIT(18)
+       #define REG_ADP_BC_VDAT_SRC_EN_B                BIT(19)
+       #define REG_ADP_BC_CHARGE_SEL                   BIT(20)
+       #define REG_ADP_BC_CHARGE_DETECT                BIT(21)
+       #define REG_ADP_BC_ACA_PIN_RANGE_C              BIT(22)
+       #define REG_ADP_BC_ACA_PIN_RANGE_B              BIT(23)
+       #define REG_ADP_BC_ACA_PIN_RANGE_A              BIT(24)
+       #define REG_ADP_BC_ACA_PIN_GND                  BIT(25)
+       #define REG_ADP_BC_ACA_PIN_FLOAT                BIT(26)
+
+#define REG_DBG_UART                                   0x10
+
+#define REG_TEST                                       0x14
+       #define REG_TEST_DATA_IN_MASK                   GENMASK(3, 0)
+       #define REG_TEST_EN_MASK                        GENMASK(7, 4)
+       #define REG_TEST_ADDR_MASK                      GENMASK(11, 8)
+       #define REG_TEST_DATA_OUT_SEL                   BIT(12)
+       #define REG_TEST_CLK                            BIT(13)
+       #define REG_TEST_VA_TEST_EN_B_MASK              GENMASK(15, 14)
+       #define REG_TEST_DATA_OUT_MASK                  GENMASK(19, 16)
+       #define REG_TEST_DISABLE_ID_PULLUP              BIT(20)
+
+#define REG_TUNE                                       0x18
+       #define REG_TUNE_TX_RES_TUNE_MASK               GENMASK(1, 0)
+       #define REG_TUNE_TX_HSXV_TUNE_MASK              GENMASK(3, 2)
+       #define REG_TUNE_TX_VREF_TUNE_MASK              GENMASK(7, 4)
+       #define REG_TUNE_TX_RISE_TUNE_MASK              GENMASK(9, 8)
+       #define REG_TUNE_TX_PREEMP_PULSE_TUNE           BIT(10)
+       #define REG_TUNE_TX_PREEMP_AMP_TUNE_MASK        GENMASK(12, 11)
+       #define REG_TUNE_TX_FSLS_TUNE_MASK              GENMASK(16, 13)
+       #define REG_TUNE_SQRX_TUNE_MASK                 GENMASK(19, 17)
+       #define REG_TUNE_OTG_TUNE                       GENMASK(22, 20)
+       #define REG_TUNE_COMP_DIS_TUNE                  GENMASK(25, 23)
+       #define REG_TUNE_HOST_DM_PULLDOWN               BIT(26)
+       #define REG_TUNE_HOST_DP_PULLDOWN               BIT(27)
+
+#define RESET_COMPLETE_TIME                            500
+#define ACA_ENABLE_COMPLETE_TIME                       50
+
+struct phy_meson8b_usb2_priv {
+       void __iomem            *regs;
+       enum usb_dr_mode        dr_mode;
+       struct clk              *clk_usb_general;
+       struct clk              *clk_usb;
+       struct reset_control    *reset;
+};
+
+static u32 phy_meson8b_usb2_read(struct phy_meson8b_usb2_priv *phy_priv,
+                                u32 reg)
+{
+       return readl(phy_priv->regs + reg);
+}
+
+static void phy_meson8b_usb2_mask_bits(struct phy_meson8b_usb2_priv *phy_priv,
+                                      u32 reg, u32 mask, u32 value)
+{
+       u32 data;
+
+       data = phy_meson8b_usb2_read(phy_priv, reg);
+       data &= ~mask;
+       data |= (value & mask);
+
+       writel(data, phy_priv->regs + reg);
+}
+
+static int phy_meson8b_usb2_power_on(struct phy *phy)
+{
+       struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
+       int ret;
+
+       if (!IS_ERR_OR_NULL(priv->reset)) {
+               ret = reset_control_reset(priv->reset);
+               if (ret) {
+                       dev_err(&phy->dev, "Failed to trigger USB reset\n");
+                       return ret;
+               }
+       }
+
+       ret = clk_prepare_enable(priv->clk_usb_general);
+       if (ret) {
+               dev_err(&phy->dev, "Failed to enable USB general clock\n");
+               return ret;
+       }
+
+       ret = clk_prepare_enable(priv->clk_usb);
+       if (ret) {
+               dev_err(&phy->dev, "Failed to enable USB DDR clock\n");
+               clk_disable_unprepare(priv->clk_usb_general);
+               return ret;
+       }
+
+       phy_meson8b_usb2_mask_bits(priv, REG_CONFIG, REG_CONFIG_CLK_32k_ALTSEL,
+                                  REG_CONFIG_CLK_32k_ALTSEL);
+
+       phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_REF_CLK_SEL_MASK,
+                                  0x2 << REG_CTRL_REF_CLK_SEL_SHIFT);
+
+       phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_FSEL_MASK,
+                                  0x5 << REG_CTRL_FSEL_SHIFT);
+
+       /* reset the PHY */
+       phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET,
+                                  REG_CTRL_POWER_ON_RESET);
+       udelay(RESET_COMPLETE_TIME);
+       phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET, 0);
+       udelay(RESET_COMPLETE_TIME);
+
+       phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_SOF_TOGGLE_OUT,
+                                  REG_CTRL_SOF_TOGGLE_OUT);
+
+       if (priv->dr_mode == USB_DR_MODE_HOST) {
+               phy_meson8b_usb2_mask_bits(priv, REG_ADP_BC,
+                                          REG_ADP_BC_ACA_ENABLE,
+                                          REG_ADP_BC_ACA_ENABLE);
+
+               udelay(ACA_ENABLE_COMPLETE_TIME);
+
+               if (phy_meson8b_usb2_read(priv, REG_ADP_BC) &
+                       REG_ADP_BC_ACA_PIN_FLOAT) {
+                       dev_warn(&phy->dev, "USB ID detect failed!\n");
+                       clk_disable_unprepare(priv->clk_usb);
+                       clk_disable_unprepare(priv->clk_usb_general);
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static int phy_meson8b_usb2_power_off(struct phy *phy)
+{
+       struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
+
+       clk_disable_unprepare(priv->clk_usb);
+       clk_disable_unprepare(priv->clk_usb_general);
+
+       return 0;
+}
+
+static const struct phy_ops phy_meson8b_usb2_ops = {
+       .power_on       = phy_meson8b_usb2_power_on,
+       .power_off      = phy_meson8b_usb2_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int phy_meson8b_usb2_probe(struct platform_device *pdev)
+{
+       struct phy_meson8b_usb2_priv *priv;
+       struct resource *res;
+       struct phy *phy;
+       struct phy_provider *phy_provider;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       priv->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(priv->regs))
+               return PTR_ERR(priv->regs);
+
+       priv->clk_usb_general = devm_clk_get(&pdev->dev, "usb_general");
+       if (IS_ERR(priv->clk_usb_general))
+               return PTR_ERR(priv->clk_usb_general);
+
+       priv->clk_usb = devm_clk_get(&pdev->dev, "usb");
+       if (IS_ERR(priv->clk_usb))
+               return PTR_ERR(priv->clk_usb);
+
+       priv->reset = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
+       if (PTR_ERR(priv->reset) == -EPROBE_DEFER)
+               return PTR_ERR(priv->reset);
+
+       priv->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node, -1);
+       if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
+               dev_err(&pdev->dev,
+                       "missing dual role configuration of the controller\n");
+               return -EINVAL;
+       }
+
+       phy = devm_phy_create(&pdev->dev, NULL, &phy_meson8b_usb2_ops);
+       if (IS_ERR(phy)) {
+               dev_err(&pdev->dev, "failed to create PHY\n");
+               return PTR_ERR(phy);
+       }
+
+       phy_set_drvdata(phy, priv);
+
+       phy_provider =
+               devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id phy_meson8b_usb2_of_match[] = {
+       { .compatible = "amlogic,meson8b-usb2-phy", },
+       { .compatible = "amlogic,meson-gxbb-usb2-phy", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, phy_meson8b_usb2_of_match);
+
+static struct platform_driver phy_meson8b_usb2_driver = {
+       .probe  = phy_meson8b_usb2_probe,
+       .driver = {
+               .name           = "phy-meson-usb2",
+               .of_match_table = phy_meson8b_usb2_of_match,
+       },
+};
+module_platform_driver(phy_meson8b_usb2_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
+MODULE_DESCRIPTION("Meson8b and GXBB USB2 PHY driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/broadcom/Kconfig b/drivers/phy/broadcom/Kconfig
new file mode 100644 (file)
index 0000000..d2d9902
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# 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
+       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_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.
diff --git a/drivers/phy/broadcom/Makefile b/drivers/phy/broadcom/Makefile
new file mode 100644 (file)
index 0000000..357a7d1
--- /dev/null
@@ -0,0 +1,6 @@
+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_BRCM_SATA)            += phy-brcm-sata.o
diff --git a/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c b/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
new file mode 100644 (file)
index 0000000..0f4ac5d
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * 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/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#define PCIE_CFG_OFFSET         0x00
+#define PCIE1_PHY_IDDQ_SHIFT    10
+#define PCIE0_PHY_IDDQ_SHIFT    2
+
+enum cygnus_pcie_phy_id {
+       CYGNUS_PHY_PCIE0 = 0,
+       CYGNUS_PHY_PCIE1,
+       MAX_NUM_PHYS,
+};
+
+struct cygnus_pcie_phy_core;
+
+/**
+ * struct cygnus_pcie_phy - Cygnus PCIe PHY device
+ * @core: pointer to the Cygnus PCIe PHY core control
+ * @id: internal ID to identify the Cygnus PCIe PHY
+ * @phy: pointer to the kernel PHY device
+ */
+struct cygnus_pcie_phy {
+       struct cygnus_pcie_phy_core *core;
+       enum cygnus_pcie_phy_id id;
+       struct phy *phy;
+};
+
+/**
+ * struct cygnus_pcie_phy_core - Cygnus PCIe PHY core control
+ * @dev: pointer to device
+ * @base: base register
+ * @lock: mutex to protect access to individual PHYs
+ * @phys: pointer to Cygnus PHY device
+ */
+struct cygnus_pcie_phy_core {
+       struct device *dev;
+       void __iomem *base;
+       struct mutex lock;
+       struct cygnus_pcie_phy phys[MAX_NUM_PHYS];
+};
+
+static int cygnus_pcie_power_config(struct cygnus_pcie_phy *phy, bool enable)
+{
+       struct cygnus_pcie_phy_core *core = phy->core;
+       unsigned shift;
+       u32 val;
+
+       mutex_lock(&core->lock);
+
+       switch (phy->id) {
+       case CYGNUS_PHY_PCIE0:
+               shift = PCIE0_PHY_IDDQ_SHIFT;
+               break;
+
+       case CYGNUS_PHY_PCIE1:
+               shift = PCIE1_PHY_IDDQ_SHIFT;
+               break;
+
+       default:
+               mutex_unlock(&core->lock);
+               dev_err(core->dev, "PCIe PHY %d invalid\n", phy->id);
+               return -EINVAL;
+       }
+
+       if (enable) {
+               val = readl(core->base + PCIE_CFG_OFFSET);
+               val &= ~BIT(shift);
+               writel(val, core->base + PCIE_CFG_OFFSET);
+               /*
+                * Wait 50 ms for the PCIe Serdes to stabilize after the analog
+                * front end is brought up
+                */
+               msleep(50);
+       } else {
+               val = readl(core->base + PCIE_CFG_OFFSET);
+               val |= BIT(shift);
+               writel(val, core->base + PCIE_CFG_OFFSET);
+       }
+
+       mutex_unlock(&core->lock);
+       dev_dbg(core->dev, "PCIe PHY %d %s\n", phy->id,
+               enable ? "enabled" : "disabled");
+       return 0;
+}
+
+static int cygnus_pcie_phy_power_on(struct phy *p)
+{
+       struct cygnus_pcie_phy *phy = phy_get_drvdata(p);
+
+       return cygnus_pcie_power_config(phy, true);
+}
+
+static int cygnus_pcie_phy_power_off(struct phy *p)
+{
+       struct cygnus_pcie_phy *phy = phy_get_drvdata(p);
+
+       return cygnus_pcie_power_config(phy, false);
+}
+
+static const struct phy_ops cygnus_pcie_phy_ops = {
+       .power_on = cygnus_pcie_phy_power_on,
+       .power_off = cygnus_pcie_phy_power_off,
+       .owner = THIS_MODULE,
+};
+
+static int cygnus_pcie_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *node = dev->of_node, *child;
+       struct cygnus_pcie_phy_core *core;
+       struct phy_provider *provider;
+       struct resource *res;
+       unsigned cnt = 0;
+       int ret;
+
+       if (of_get_child_count(node) == 0) {
+               dev_err(dev, "PHY no child node\n");
+               return -ENODEV;
+       }
+
+       core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL);
+       if (!core)
+               return -ENOMEM;
+
+       core->dev = dev;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       core->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(core->base))
+               return PTR_ERR(core->base);
+
+       mutex_init(&core->lock);
+
+       for_each_available_child_of_node(node, child) {
+               unsigned int id;
+               struct cygnus_pcie_phy *p;
+
+               if (of_property_read_u32(child, "reg", &id)) {
+                       dev_err(dev, "missing reg property for %s\n",
+                               child->name);
+                       ret = -EINVAL;
+                       goto put_child;
+               }
+
+               if (id >= MAX_NUM_PHYS) {
+                       dev_err(dev, "invalid PHY id: %u\n", id);
+                       ret = -EINVAL;
+                       goto put_child;
+               }
+
+               if (core->phys[id].phy) {
+                       dev_err(dev, "duplicated PHY id: %u\n", id);
+                       ret = -EINVAL;
+                       goto put_child;
+               }
+
+               p = &core->phys[id];
+               p->phy = devm_phy_create(dev, child, &cygnus_pcie_phy_ops);
+               if (IS_ERR(p->phy)) {
+                       dev_err(dev, "failed to create PHY\n");
+                       ret = PTR_ERR(p->phy);
+                       goto put_child;
+               }
+
+               p->core = core;
+               p->id = id;
+               phy_set_drvdata(p->phy, p);
+               cnt++;
+       }
+
+       dev_set_drvdata(dev, core);
+
+       provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(provider)) {
+               dev_err(dev, "failed to register PHY provider\n");
+               return PTR_ERR(provider);
+       }
+
+       dev_dbg(dev, "registered %u PCIe PHY(s)\n", cnt);
+
+       return 0;
+put_child:
+       of_node_put(child);
+       return ret;
+}
+
+static const struct of_device_id cygnus_pcie_phy_match_table[] = {
+       { .compatible = "brcm,cygnus-pcie-phy" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cygnus_pcie_phy_match_table);
+
+static struct platform_driver cygnus_pcie_phy_driver = {
+       .driver = {
+               .name = "cygnus-pcie-phy",
+               .of_match_table = cygnus_pcie_phy_match_table,
+       },
+       .probe = cygnus_pcie_phy_probe,
+};
+module_platform_driver(cygnus_pcie_phy_driver);
+
+MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom Cygnus PCIe PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/broadcom/phy-bcm-kona-usb2.c b/drivers/phy/broadcom/phy-bcm-kona-usb2.c
new file mode 100644 (file)
index 0000000..7b67fe4
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * phy-bcm-kona-usb2.c - Broadcom Kona USB2 Phy Driver
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Matt Porter <mporter@linaro.org>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#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/phy/phy.h>
+#include <linux/platform_device.h>
+
+#define OTGCTL                 (0)
+#define OTGCTL_OTGSTAT2                BIT(31)
+#define OTGCTL_OTGSTAT1                BIT(30)
+#define OTGCTL_PRST_N_SW       BIT(11)
+#define OTGCTL_HRESET_N                BIT(10)
+#define OTGCTL_UTMI_LINE_STATE1        BIT(9)
+#define OTGCTL_UTMI_LINE_STATE0        BIT(8)
+
+#define P1CTL                  (8)
+#define P1CTL_SOFT_RESET       BIT(1)
+#define P1CTL_NON_DRIVING      BIT(0)
+
+struct bcm_kona_usb {
+       void __iomem *regs;
+};
+
+static void bcm_kona_usb_phy_power(struct bcm_kona_usb *phy, int on)
+{
+       u32 val;
+
+       val = readl(phy->regs + OTGCTL);
+       if (on) {
+               /* Configure and power PHY */
+               val &= ~(OTGCTL_OTGSTAT2 | OTGCTL_OTGSTAT1 |
+                        OTGCTL_UTMI_LINE_STATE1 | OTGCTL_UTMI_LINE_STATE0);
+               val |= OTGCTL_PRST_N_SW | OTGCTL_HRESET_N;
+       } else {
+               val &= ~(OTGCTL_PRST_N_SW | OTGCTL_HRESET_N);
+       }
+       writel(val, phy->regs + OTGCTL);
+}
+
+static int bcm_kona_usb_phy_init(struct phy *gphy)
+{
+       struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
+       u32 val;
+
+       /* Soft reset PHY */
+       val = readl(phy->regs + P1CTL);
+       val &= ~P1CTL_NON_DRIVING;
+       val |= P1CTL_SOFT_RESET;
+       writel(val, phy->regs + P1CTL);
+       writel(val & ~P1CTL_SOFT_RESET, phy->regs + P1CTL);
+       /* Reset needs to be asserted for 2ms */
+       mdelay(2);
+       writel(val | P1CTL_SOFT_RESET, phy->regs + P1CTL);
+
+       return 0;
+}
+
+static int bcm_kona_usb_phy_power_on(struct phy *gphy)
+{
+       struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
+
+       bcm_kona_usb_phy_power(phy, 1);
+
+       return 0;
+}
+
+static int bcm_kona_usb_phy_power_off(struct phy *gphy)
+{
+       struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
+
+       bcm_kona_usb_phy_power(phy, 0);
+
+       return 0;
+}
+
+static const struct phy_ops ops = {
+       .init           = bcm_kona_usb_phy_init,
+       .power_on       = bcm_kona_usb_phy_power_on,
+       .power_off      = bcm_kona_usb_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int bcm_kona_usb2_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct bcm_kona_usb *phy;
+       struct resource *res;
+       struct phy *gphy;
+       struct phy_provider *phy_provider;
+
+       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       phy->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(phy->regs))
+               return PTR_ERR(phy->regs);
+
+       platform_set_drvdata(pdev, phy);
+
+       gphy = devm_phy_create(dev, NULL, &ops);
+       if (IS_ERR(gphy))
+               return PTR_ERR(gphy);
+
+       /* The Kona PHY supports an 8-bit wide UTMI interface */
+       phy_set_bus_width(gphy, 8);
+
+       phy_set_drvdata(gphy, phy);
+
+       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 bcm_kona_usb2_dt_ids[] = {
+       { .compatible = "brcm,kona-usb2-phy" },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, bcm_kona_usb2_dt_ids);
+
+static struct platform_driver bcm_kona_usb2_driver = {
+       .probe          = bcm_kona_usb2_probe,
+       .driver         = {
+               .name   = "bcm-kona-usb2",
+               .of_match_table = bcm_kona_usb2_dt_ids,
+       },
+};
+
+module_platform_driver(bcm_kona_usb2_driver);
+
+MODULE_ALIAS("platform:bcm-kona-usb2");
+MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
+MODULE_DESCRIPTION("BCM Kona USB 2.0 PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb2.c b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
new file mode 100644 (file)
index 0000000..58dff80
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Broadcom Northstar USB 2.0 PHY Driver
+ *
+ * Copyright (C) 2016 RafaÅ‚ MiÅ‚ecki <zajec5@gmail.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.
+ *
+ */
+
+#include <linux/bcma/bcma.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct bcm_ns_usb2 {
+       struct device *dev;
+       struct clk *ref_clk;
+       struct phy *phy;
+       void __iomem *dmu;
+};
+
+static int bcm_ns_usb2_phy_init(struct phy *phy)
+{
+       struct bcm_ns_usb2 *usb2 = phy_get_drvdata(phy);
+       struct device *dev = usb2->dev;
+       void __iomem *dmu = usb2->dmu;
+       u32 ref_clk_rate, usb2ctl, usb_pll_ndiv, usb_pll_pdiv;
+       int err = 0;
+
+       err = clk_prepare_enable(usb2->ref_clk);
+       if (err < 0) {
+               dev_err(dev, "Failed to prepare ref clock: %d\n", err);
+               goto err_out;
+       }
+
+       ref_clk_rate = clk_get_rate(usb2->ref_clk);
+       if (!ref_clk_rate) {
+               dev_err(dev, "Failed to get ref clock rate\n");
+               err = -EINVAL;
+               goto err_clk_off;
+       }
+
+       usb2ctl = readl(dmu + BCMA_DMU_CRU_USB2_CONTROL);
+
+       if (usb2ctl & BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK) {
+               usb_pll_pdiv = usb2ctl;
+               usb_pll_pdiv &= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK;
+               usb_pll_pdiv >>= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_SHIFT;
+       } else {
+               usb_pll_pdiv = 1 << 3;
+       }
+
+       /* Calculate ndiv based on a solid 1920 MHz that is for USB2 PHY */
+       usb_pll_ndiv = (1920000000 * usb_pll_pdiv) / ref_clk_rate;
+
+       /* Unlock DMU PLL settings with some magic value */
+       writel(0x0000ea68, dmu + BCMA_DMU_CRU_CLKSET_KEY);
+
+       /* Write USB 2.0 PLL control setting */
+       usb2ctl &= ~BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK;
+       usb2ctl |= usb_pll_ndiv << BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT;
+       writel(usb2ctl, dmu + BCMA_DMU_CRU_USB2_CONTROL);
+
+       /* Lock DMU PLL settings */
+       writel(0x00000000, dmu + BCMA_DMU_CRU_CLKSET_KEY);
+
+err_clk_off:
+       clk_disable_unprepare(usb2->ref_clk);
+err_out:
+       return err;
+}
+
+static const struct phy_ops ops = {
+       .init           = bcm_ns_usb2_phy_init,
+       .owner          = THIS_MODULE,
+};
+
+static int bcm_ns_usb2_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct bcm_ns_usb2 *usb2;
+       struct resource *res;
+       struct phy_provider *phy_provider;
+
+       usb2 = devm_kzalloc(&pdev->dev, sizeof(*usb2), GFP_KERNEL);
+       if (!usb2)
+               return -ENOMEM;
+       usb2->dev = dev;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmu");
+       usb2->dmu = devm_ioremap_resource(dev, res);
+       if (IS_ERR(usb2->dmu)) {
+               dev_err(dev, "Failed to map DMU regs\n");
+               return PTR_ERR(usb2->dmu);
+       }
+
+       usb2->ref_clk = devm_clk_get(dev, "phy-ref-clk");
+       if (IS_ERR(usb2->ref_clk)) {
+               dev_err(dev, "Clock not defined\n");
+               return PTR_ERR(usb2->ref_clk);
+       }
+
+       usb2->phy = devm_phy_create(dev, NULL, &ops);
+       if (IS_ERR(usb2->phy))
+               return PTR_ERR(usb2->phy);
+
+       phy_set_drvdata(usb2->phy, usb2);
+       platform_set_drvdata(pdev, usb2);
+
+       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 bcm_ns_usb2_id_table[] = {
+       { .compatible = "brcm,ns-usb2-phy", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, bcm_ns_usb2_id_table);
+
+static struct platform_driver bcm_ns_usb2_driver = {
+       .probe          = bcm_ns_usb2_probe,
+       .driver = {
+               .name = "bcm_ns_usb2",
+               .of_match_table = bcm_ns_usb2_id_table,
+       },
+};
+module_platform_driver(bcm_ns_usb2_driver);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb3.c b/drivers/phy/broadcom/phy-bcm-ns-usb3.c
new file mode 100644 (file)
index 0000000..22b5e70
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Broadcom Northstar USB 3.0 PHY Driver
+ *
+ * Copyright (C) 2016 RafaÅ‚ MiÅ‚ecki <rafal@milecki.pl>
+ * Copyright (C) 2016 Broadcom
+ *
+ * All magic values used for initialization (and related comments) were obtained
+ * from Broadcom's SDK:
+ * Copyright (c) Broadcom Corp, 2012
+ *
+ * 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/bcma/bcma.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/slab.h>
+
+#define BCM_NS_USB3_MII_MNG_TIMEOUT_US 1000    /* usecs */
+
+#define BCM_NS_USB3_PHY_BASE_ADDR_REG  0x1f
+#define BCM_NS_USB3_PHY_PLL30_BLOCK    0x8000
+#define BCM_NS_USB3_PHY_TX_PMD_BLOCK   0x8040
+#define BCM_NS_USB3_PHY_PIPE_BLOCK     0x8060
+
+/* Registers of PLL30 block */
+#define BCM_NS_USB3_PLL_CONTROL                0x01
+#define BCM_NS_USB3_PLLA_CONTROL0      0x0a
+#define BCM_NS_USB3_PLLA_CONTROL1      0x0b
+
+/* Registers of TX PMD block */
+#define BCM_NS_USB3_TX_PMD_CONTROL1    0x01
+
+/* Registers of PIPE block */
+#define BCM_NS_USB3_LFPS_CMP           0x02
+#define BCM_NS_USB3_LFPS_DEGLITCH      0x03
+
+enum bcm_ns_family {
+       BCM_NS_UNKNOWN,
+       BCM_NS_AX,
+       BCM_NS_BX,
+};
+
+struct bcm_ns_usb3 {
+       struct device *dev;
+       enum bcm_ns_family family;
+       void __iomem *dmp;
+       void __iomem *ccb_mii;
+       struct phy *phy;
+};
+
+static const struct of_device_id bcm_ns_usb3_id_table[] = {
+       {
+               .compatible = "brcm,ns-ax-usb3-phy",
+               .data = (int *)BCM_NS_AX,
+       },
+       {
+               .compatible = "brcm,ns-bx-usb3-phy",
+               .data = (int *)BCM_NS_BX,
+       },
+       {},
+};
+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,
+                                     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;
+}
+
+static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
+{
+       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 */
+       err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
+                                        BCM_NS_USB3_PHY_PLL30_BLOCK);
+       if (err < 0)
+               return err;
+
+       /* Assert Ana_Pllseq start */
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x1000);
+
+       /* Assert CML Divider ratio to 26 */
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400);
+
+       /* Asserting PLL Reset */
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0xc000);
+
+       /* Deaaserting PLL Reset */
+       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 */
+       writel(0, usb3->dmp + BCMA_RESET_CTL);
+
+       /* PLL frequency monitor enable */
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x9000);
+
+       /* PIPE Block */
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
+                                  BCM_NS_USB3_PHY_PIPE_BLOCK);
+
+       /* CMPMAX & CMPMINTH setting */
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_CMP, 0xf30d);
+
+       /* DEGLITCH MIN & MAX setting */
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_DEGLITCH, 0x6302);
+
+       /* TXPMD block */
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
+                                  BCM_NS_USB3_PHY_TX_PMD_BLOCK);
+
+       /* Enabling SSC */
+       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;
+}
+
+static int bcm_ns_usb3_phy_init_ns_ax(struct bcm_ns_usb3 *usb3)
+{
+       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 */
+       err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
+                                        BCM_NS_USB3_PHY_PLL30_BLOCK);
+       if (err < 0)
+               return err;
+
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400);
+
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG, 0x80e0);
+
+       bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x009c);
+
+       /* Enable SSC */
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
+                                  BCM_NS_USB3_PHY_TX_PMD_BLOCK);
+
+       bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x21d3);
+
+       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 */
+       writel(0, usb3->dmp + BCMA_RESET_CTL);
+
+       return 0;
+}
+
+static int bcm_ns_usb3_phy_init(struct phy *phy)
+{
+       struct bcm_ns_usb3 *usb3 = phy_get_drvdata(phy);
+       int err;
+
+       /* Perform USB3 system soft reset */
+       writel(BCMA_RESET_CTL_RESET, usb3->dmp + BCMA_RESET_CTL);
+
+       switch (usb3->family) {
+       case BCM_NS_AX:
+               err = bcm_ns_usb3_phy_init_ns_ax(usb3);
+               break;
+       case BCM_NS_BX:
+               err = bcm_ns_usb3_phy_init_ns_bx(usb3);
+               break;
+       default:
+               WARN_ON(1);
+               err = -ENOTSUPP;
+       }
+
+       return err;
+}
+
+static const struct phy_ops ops = {
+       .init           = bcm_ns_usb3_phy_init,
+       .owner          = THIS_MODULE,
+};
+
+static int bcm_ns_usb3_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *of_id;
+       struct bcm_ns_usb3 *usb3;
+       struct resource *res;
+       struct phy_provider *phy_provider;
+
+       usb3 = devm_kzalloc(dev, sizeof(*usb3), GFP_KERNEL);
+       if (!usb3)
+               return -ENOMEM;
+
+       usb3->dev = dev;
+
+       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;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmp");
+       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);
+       }
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ccb-mii");
+       usb3->ccb_mii = devm_ioremap_resource(dev, res);
+       if (IS_ERR(usb3->ccb_mii)) {
+               dev_err(dev, "Failed to map ChipCommon B MII regs\n");
+               return PTR_ERR(usb3->ccb_mii);
+       }
+
+       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);
+       platform_set_drvdata(pdev, usb3);
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (!IS_ERR(phy_provider))
+               dev_info(dev, "Registered Broadcom Northstar USB 3.0 PHY driver\n");
+
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static struct platform_driver bcm_ns_usb3_driver = {
+       .probe          = bcm_ns_usb3_probe,
+       .driver = {
+               .name = "bcm_ns_usb3",
+               .of_match_table = bcm_ns_usb3_id_table,
+       },
+};
+module_platform_driver(bcm_ns_usb3_driver);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/broadcom/phy-bcm-ns2-pcie.c b/drivers/phy/broadcom/phy-bcm-ns2-pcie.c
new file mode 100644 (file)
index 0000000..4c7d11d
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 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/device.h>
+#include <linux/module.h>
+#include <linux/of_mdio.h>
+#include <linux/mdio.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+
+#define BLK_ADDR_REG_OFFSET    0x1f
+#define PLL_AFE1_100MHZ_BLK    0x2100
+#define PLL_CLK_AMP_OFFSET     0x03
+#define PLL_CLK_AMP_2P05V      0x2b18
+
+static int ns2_pci_phy_init(struct phy *p)
+{
+       struct mdio_device *mdiodev = phy_get_drvdata(p);
+       int rc;
+
+       /* select the AFE 100MHz block page */
+       rc = mdiobus_write(mdiodev->bus, mdiodev->addr,
+                          BLK_ADDR_REG_OFFSET, PLL_AFE1_100MHZ_BLK);
+       if (rc)
+               goto err;
+
+       /* set the 100 MHz reference clock amplitude to 2.05 v */
+       rc = mdiobus_write(mdiodev->bus, mdiodev->addr,
+                          PLL_CLK_AMP_OFFSET, PLL_CLK_AMP_2P05V);
+       if (rc)
+               goto err;
+
+       return 0;
+
+err:
+       dev_err(&mdiodev->dev, "Error %d writing to phy\n", rc);
+       return rc;
+}
+
+static const struct phy_ops ns2_pci_phy_ops = {
+       .init = ns2_pci_phy_init,
+       .owner = THIS_MODULE,
+};
+
+static int ns2_pci_phy_probe(struct mdio_device *mdiodev)
+{
+       struct device *dev = &mdiodev->dev;
+       struct phy_provider *provider;
+       struct phy *phy;
+
+       phy = devm_phy_create(dev, dev->of_node, &ns2_pci_phy_ops);
+       if (IS_ERR(phy)) {
+               dev_err(dev, "failed to create Phy\n");
+               return PTR_ERR(phy);
+       }
+
+       phy_set_drvdata(phy, mdiodev);
+
+       provider = devm_of_phy_provider_register(&phy->dev,
+                                                of_phy_simple_xlate);
+       if (IS_ERR(provider)) {
+               dev_err(dev, "failed to register Phy provider\n");
+               return PTR_ERR(provider);
+       }
+
+       dev_info(dev, "%s PHY registered\n", dev_name(dev));
+
+       return 0;
+}
+
+static const struct of_device_id ns2_pci_phy_of_match[] = {
+       { .compatible = "brcm,ns2-pcie-phy", },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ns2_pci_phy_of_match);
+
+static struct mdio_driver ns2_pci_phy_driver = {
+       .mdiodrv = {
+               .driver = {
+                       .name = "phy-bcm-ns2-pci",
+                       .of_match_table = ns2_pci_phy_of_match,
+               },
+       },
+       .probe = ns2_pci_phy_probe,
+};
+mdio_module_driver(ns2_pci_phy_driver);
+
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Broadcom Northstar2 PCI Phy driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:phy-bcm-ns2-pci");
diff --git a/drivers/phy/broadcom/phy-brcm-sata.c b/drivers/phy/broadcom/phy-brcm-sata.c
new file mode 100644 (file)
index 0000000..ccbc3d9
--- /dev/null
@@ -0,0 +1,493 @@
+/*
+ * Broadcom SATA3 AHCI Controller PHY Driver
+ *
+ * Copyright (C) 2016 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; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/device.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#define SATA_PCB_BANK_OFFSET                           0x23c
+#define SATA_PCB_REG_OFFSET(ofs)                       ((ofs) * 4)
+
+#define MAX_PORTS                                      2
+
+/* Register offset between PHYs in PCB space */
+#define SATA_PCB_REG_28NM_SPACE_SIZE                   0x1000
+
+/* The older SATA PHY registers duplicated per port registers within the map,
+ * rather than having a separate map per port.
+ */
+#define SATA_PCB_REG_40NM_SPACE_SIZE                   0x10
+
+/* Register offset between PHYs in PHY control space */
+#define SATA_PHY_CTRL_REG_28NM_SPACE_SIZE              0x8
+
+enum brcm_sata_phy_version {
+       BRCM_SATA_PHY_STB_28NM,
+       BRCM_SATA_PHY_STB_40NM,
+       BRCM_SATA_PHY_IPROC_NS2,
+       BRCM_SATA_PHY_IPROC_NSP,
+};
+
+struct brcm_sata_port {
+       int portnum;
+       struct phy *phy;
+       struct brcm_sata_phy *phy_priv;
+       bool ssc_en;
+};
+
+struct brcm_sata_phy {
+       struct device *dev;
+       void __iomem *phy_base;
+       void __iomem *ctrl_base;
+       enum brcm_sata_phy_version version;
+
+       struct brcm_sata_port phys[MAX_PORTS];
+};
+
+enum sata_phy_regs {
+       BLOCK0_REG_BANK                         = 0x000,
+       BLOCK0_XGXSSTATUS                       = 0x81,
+       BLOCK0_XGXSSTATUS_PLL_LOCK              = BIT(12),
+       BLOCK0_SPARE                            = 0x8d,
+       BLOCK0_SPARE_OOB_CLK_SEL_MASK           = 0x3,
+       BLOCK0_SPARE_OOB_CLK_SEL_REFBY2         = 0x1,
+
+       PLL_REG_BANK_0                          = 0x050,
+       PLL_REG_BANK_0_PLLCONTROL_0             = 0x81,
+       PLLCONTROL_0_FREQ_DET_RESTART           = BIT(13),
+       PLLCONTROL_0_FREQ_MONITOR               = BIT(12),
+       PLLCONTROL_0_SEQ_START                  = BIT(15),
+       PLL_CAP_CONTROL                         = 0x85,
+       PLL_ACTRL2                              = 0x8b,
+       PLL_ACTRL2_SELDIV_MASK                  = 0x1f,
+       PLL_ACTRL2_SELDIV_SHIFT                 = 9,
+
+       PLL1_REG_BANK                           = 0x060,
+       PLL1_ACTRL2                             = 0x82,
+       PLL1_ACTRL3                             = 0x83,
+       PLL1_ACTRL4                             = 0x84,
+
+       OOB_REG_BANK                            = 0x150,
+       OOB1_REG_BANK                           = 0x160,
+       OOB_CTRL1                               = 0x80,
+       OOB_CTRL1_BURST_MAX_MASK                = 0xf,
+       OOB_CTRL1_BURST_MAX_SHIFT               = 12,
+       OOB_CTRL1_BURST_MIN_MASK                = 0xf,
+       OOB_CTRL1_BURST_MIN_SHIFT               = 8,
+       OOB_CTRL1_WAKE_IDLE_MAX_MASK            = 0xf,
+       OOB_CTRL1_WAKE_IDLE_MAX_SHIFT           = 4,
+       OOB_CTRL1_WAKE_IDLE_MIN_MASK            = 0xf,
+       OOB_CTRL1_WAKE_IDLE_MIN_SHIFT           = 0,
+       OOB_CTRL2                               = 0x81,
+       OOB_CTRL2_SEL_ENA_SHIFT                 = 15,
+       OOB_CTRL2_SEL_ENA_RC_SHIFT              = 14,
+       OOB_CTRL2_RESET_IDLE_MAX_MASK           = 0x3f,
+       OOB_CTRL2_RESET_IDLE_MAX_SHIFT          = 8,
+       OOB_CTRL2_BURST_CNT_MASK                = 0x3,
+       OOB_CTRL2_BURST_CNT_SHIFT               = 6,
+       OOB_CTRL2_RESET_IDLE_MIN_MASK           = 0x3f,
+       OOB_CTRL2_RESET_IDLE_MIN_SHIFT          = 0,
+
+       TXPMD_REG_BANK                          = 0x1a0,
+       TXPMD_CONTROL1                          = 0x81,
+       TXPMD_CONTROL1_TX_SSC_EN_FRC            = BIT(0),
+       TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL        = BIT(1),
+       TXPMD_TX_FREQ_CTRL_CONTROL1             = 0x82,
+       TXPMD_TX_FREQ_CTRL_CONTROL2             = 0x83,
+       TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK   = 0x3ff,
+       TXPMD_TX_FREQ_CTRL_CONTROL3             = 0x84,
+       TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK   = 0x3ff,
+};
+
+enum sata_phy_ctrl_regs {
+       PHY_CTRL_1                              = 0x0,
+       PHY_CTRL_1_RESET                        = BIT(0),
+};
+
+static inline void __iomem *brcm_sata_pcb_base(struct brcm_sata_port *port)
+{
+       struct brcm_sata_phy *priv = port->phy_priv;
+       u32 size = 0;
+
+       switch (priv->version) {
+       case BRCM_SATA_PHY_STB_28NM:
+       case BRCM_SATA_PHY_IPROC_NS2:
+               size = SATA_PCB_REG_28NM_SPACE_SIZE;
+               break;
+       case BRCM_SATA_PHY_STB_40NM:
+               size = SATA_PCB_REG_40NM_SPACE_SIZE;
+               break;
+       default:
+               dev_err(priv->dev, "invalid phy version\n");
+               break;
+       }
+
+       return priv->phy_base + (port->portnum * size);
+}
+
+static inline void __iomem *brcm_sata_ctrl_base(struct brcm_sata_port *port)
+{
+       struct brcm_sata_phy *priv = port->phy_priv;
+       u32 size = 0;
+
+       switch (priv->version) {
+       case BRCM_SATA_PHY_IPROC_NS2:
+               size = SATA_PHY_CTRL_REG_28NM_SPACE_SIZE;
+               break;
+       default:
+               dev_err(priv->dev, "invalid phy version\n");
+               break;
+       }
+
+       return priv->ctrl_base + (port->portnum * size);
+}
+
+static void brcm_sata_phy_wr(void __iomem *pcb_base, u32 bank,
+                            u32 ofs, u32 msk, u32 value)
+{
+       u32 tmp;
+
+       writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
+       tmp = readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
+       tmp = (tmp & msk) | value;
+       writel(tmp, pcb_base + SATA_PCB_REG_OFFSET(ofs));
+}
+
+static u32 brcm_sata_phy_rd(void __iomem *pcb_base, u32 bank, u32 ofs)
+{
+       writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
+       return readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
+}
+
+/* These defaults were characterized by H/W group */
+#define STB_FMIN_VAL_DEFAULT   0x3df
+#define STB_FMAX_VAL_DEFAULT   0x3df
+#define STB_FMAX_VAL_SSC       0x83
+
+static int brcm_stb_sata_init(struct brcm_sata_port *port)
+{
+       void __iomem *base = brcm_sata_pcb_base(port);
+       struct brcm_sata_phy *priv = port->phy_priv;
+       u32 tmp;
+
+       /* override the TX spread spectrum setting */
+       tmp = TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL | TXPMD_CONTROL1_TX_SSC_EN_FRC;
+       brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp);
+
+       /* set fixed min freq */
+       brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2,
+                        ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK,
+                        STB_FMIN_VAL_DEFAULT);
+
+       /* set fixed max freq depending on SSC config */
+       if (port->ssc_en) {
+               dev_info(priv->dev, "enabling SSC on port%d\n", port->portnum);
+               tmp = STB_FMAX_VAL_SSC;
+       } else {
+               tmp = STB_FMAX_VAL_DEFAULT;
+       }
+
+       brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3,
+                         ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp);
+
+       return 0;
+}
+
+/* NS2 SATA PLL1 defaults were characterized by H/W group */
+#define NS2_PLL1_ACTRL2_MAGIC  0x1df8
+#define NS2_PLL1_ACTRL3_MAGIC  0x2b00
+#define NS2_PLL1_ACTRL4_MAGIC  0x8824
+
+static int brcm_ns2_sata_init(struct brcm_sata_port *port)
+{
+       int try;
+       unsigned int val;
+       void __iomem *base = brcm_sata_pcb_base(port);
+       void __iomem *ctrl_base = brcm_sata_ctrl_base(port);
+       struct device *dev = port->phy_priv->dev;
+
+       /* Configure OOB control */
+       val = 0x0;
+       val |= (0xc << OOB_CTRL1_BURST_MAX_SHIFT);
+       val |= (0x4 << OOB_CTRL1_BURST_MIN_SHIFT);
+       val |= (0x9 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT);
+       val |= (0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT);
+       brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
+       val = 0x0;
+       val |= (0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT);
+       val |= (0x2 << OOB_CTRL2_BURST_CNT_SHIFT);
+       val |= (0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT);
+       brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
+
+       /* Configure PHY PLL register bank 1 */
+       val = NS2_PLL1_ACTRL2_MAGIC;
+       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
+       val = NS2_PLL1_ACTRL3_MAGIC;
+       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
+       val = NS2_PLL1_ACTRL4_MAGIC;
+       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
+
+       /* Configure PHY BLOCK0 register bank */
+       /* Set oob_clk_sel to refclk/2 */
+       brcm_sata_phy_wr(base, BLOCK0_REG_BANK, BLOCK0_SPARE,
+                        ~BLOCK0_SPARE_OOB_CLK_SEL_MASK,
+                        BLOCK0_SPARE_OOB_CLK_SEL_REFBY2);
+
+       /* Strobe PHY reset using PHY control register */
+       writel(PHY_CTRL_1_RESET, ctrl_base + PHY_CTRL_1);
+       mdelay(1);
+       writel(0x0, ctrl_base + PHY_CTRL_1);
+       mdelay(1);
+
+       /* Wait for PHY PLL lock by polling pll_lock bit */
+       try = 50;
+       while (try) {
+               val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
+                                       BLOCK0_XGXSSTATUS);
+               if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
+                       break;
+               msleep(20);
+               try--;
+       }
+       if (!try) {
+               /* PLL did not lock; give up */
+               dev_err(dev, "port%d PLL did not lock\n", port->portnum);
+               return -ETIMEDOUT;
+       }
+
+       dev_dbg(dev, "port%d initialized\n", port->portnum);
+
+       return 0;
+}
+
+static int brcm_nsp_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 oob_bank;
+       unsigned int val, try;
+
+       /* Configure OOB control */
+       if (port->portnum == 0)
+               oob_bank = OOB_REG_BANK;
+       else if (port->portnum == 1)
+               oob_bank = OOB1_REG_BANK;
+       else
+               return -EINVAL;
+
+       val = 0x0;
+       val |= (0x0f << OOB_CTRL1_BURST_MAX_SHIFT);
+       val |= (0x06 << OOB_CTRL1_BURST_MIN_SHIFT);
+       val |= (0x0f << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT);
+       val |= (0x06 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT);
+       brcm_sata_phy_wr(base, oob_bank, OOB_CTRL1, 0x0, val);
+
+       val = 0x0;
+       val |= (0x2e << OOB_CTRL2_RESET_IDLE_MAX_SHIFT);
+       val |= (0x02 << OOB_CTRL2_BURST_CNT_SHIFT);
+       val |= (0x16 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT);
+       brcm_sata_phy_wr(base, oob_bank, OOB_CTRL2, 0x0, val);
+
+
+       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_ACTRL2,
+               ~(PLL_ACTRL2_SELDIV_MASK << PLL_ACTRL2_SELDIV_SHIFT),
+               0x0c << PLL_ACTRL2_SELDIV_SHIFT);
+
+       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_CAP_CONTROL,
+                                               0xff0, 0x4f0);
+
+       val = PLLCONTROL_0_FREQ_DET_RESTART | PLLCONTROL_0_FREQ_MONITOR;
+       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
+                                                               ~val, val);
+       val = PLLCONTROL_0_SEQ_START;
+       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
+                                                               ~val, 0);
+       mdelay(10);
+       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
+                                                               ~val, val);
+
+       /* Wait for pll_seq_done bit */
+       try = 50;
+       while (try--) {
+               val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
+                                       BLOCK0_XGXSSTATUS);
+               if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
+                       break;
+               msleep(20);
+       }
+       if (!try) {
+               /* PLL did not lock; give up */
+               dev_err(dev, "port%d PLL did not lock\n", port->portnum);
+               return -ETIMEDOUT;
+       }
+
+       dev_dbg(dev, "port%d initialized\n", port->portnum);
+
+       return 0;
+}
+
+static int brcm_sata_phy_init(struct phy *phy)
+{
+       int rc;
+       struct brcm_sata_port *port = phy_get_drvdata(phy);
+
+       switch (port->phy_priv->version) {
+       case BRCM_SATA_PHY_STB_28NM:
+       case BRCM_SATA_PHY_STB_40NM:
+               rc = brcm_stb_sata_init(port);
+               break;
+       case BRCM_SATA_PHY_IPROC_NS2:
+               rc = brcm_ns2_sata_init(port);
+               break;
+       case BRCM_SATA_PHY_IPROC_NSP:
+               rc = brcm_nsp_sata_init(port);
+               break;
+       default:
+               rc = -ENODEV;
+       }
+
+       return rc;
+}
+
+static const struct phy_ops phy_ops = {
+       .init           = brcm_sata_phy_init,
+       .owner          = THIS_MODULE,
+};
+
+static const struct of_device_id brcm_sata_phy_of_match[] = {
+       { .compatible   = "brcm,bcm7445-sata-phy",
+         .data = (void *)BRCM_SATA_PHY_STB_28NM },
+       { .compatible   = "brcm,bcm7425-sata-phy",
+         .data = (void *)BRCM_SATA_PHY_STB_40NM },
+       { .compatible   = "brcm,iproc-ns2-sata-phy",
+         .data = (void *)BRCM_SATA_PHY_IPROC_NS2 },
+       { .compatible = "brcm,iproc-nsp-sata-phy",
+         .data = (void *)BRCM_SATA_PHY_IPROC_NSP },
+       {},
+};
+MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);
+
+static int brcm_sata_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *dn = dev->of_node, *child;
+       const struct of_device_id *of_id;
+       struct brcm_sata_phy *priv;
+       struct resource *res;
+       struct phy_provider *provider;
+       int ret, count = 0;
+
+       if (of_get_child_count(dn) == 0)
+               return -ENODEV;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+       dev_set_drvdata(dev, priv);
+       priv->dev = dev;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
+       priv->phy_base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(priv->phy_base))
+               return PTR_ERR(priv->phy_base);
+
+       of_id = of_match_node(brcm_sata_phy_of_match, dn);
+       if (of_id)
+               priv->version = (enum brcm_sata_phy_version)of_id->data;
+       else
+               priv->version = BRCM_SATA_PHY_STB_28NM;
+
+       if (priv->version == BRCM_SATA_PHY_IPROC_NS2) {
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                                  "phy-ctrl");
+               priv->ctrl_base = devm_ioremap_resource(dev, res);
+               if (IS_ERR(priv->ctrl_base))
+                       return PTR_ERR(priv->ctrl_base);
+       }
+
+       for_each_available_child_of_node(dn, child) {
+               unsigned int id;
+               struct brcm_sata_port *port;
+
+               if (of_property_read_u32(child, "reg", &id)) {
+                       dev_err(dev, "missing reg property in node %s\n",
+                                       child->name);
+                       ret = -EINVAL;
+                       goto put_child;
+               }
+
+               if (id >= MAX_PORTS) {
+                       dev_err(dev, "invalid reg: %u\n", id);
+                       ret = -EINVAL;
+                       goto put_child;
+               }
+               if (priv->phys[id].phy) {
+                       dev_err(dev, "already registered port %u\n", id);
+                       ret = -EINVAL;
+                       goto put_child;
+               }
+
+               port = &priv->phys[id];
+               port->portnum = id;
+               port->phy_priv = priv;
+               port->phy = devm_phy_create(dev, child, &phy_ops);
+               port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
+               if (IS_ERR(port->phy)) {
+                       dev_err(dev, "failed to create PHY\n");
+                       ret = PTR_ERR(port->phy);
+                       goto put_child;
+               }
+
+               phy_set_drvdata(port->phy, port);
+               count++;
+       }
+
+       provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(provider)) {
+               dev_err(dev, "could not register PHY provider\n");
+               return PTR_ERR(provider);
+       }
+
+       dev_info(dev, "registered %d port(s)\n", count);
+
+       return 0;
+put_child:
+       of_node_put(child);
+       return ret;
+}
+
+static struct platform_driver brcm_sata_phy_driver = {
+       .probe  = brcm_sata_phy_probe,
+       .driver = {
+               .of_match_table = brcm_sata_phy_of_match,
+               .name           = "brcm-sata-phy",
+       }
+};
+module_platform_driver(brcm_sata_phy_driver);
+
+MODULE_DESCRIPTION("Broadcom SATA PHY driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marc Carino");
+MODULE_AUTHOR("Brian Norris");
+MODULE_ALIAS("platform:phy-brcm-sata");
diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig
new file mode 100644 (file)
index 0000000..6164c4c
--- /dev/null
@@ -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.
diff --git a/drivers/phy/hisilicon/Makefile b/drivers/phy/hisilicon/Makefile
new file mode 100644 (file)
index 0000000..541b348
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_PHY_HI6220_USB)           += phy-hi6220-usb.o
+obj-$(CONFIG_PHY_HIX5HD2_SATA)         += phy-hix5hd2-sata.o
diff --git a/drivers/phy/hisilicon/phy-hi6220-usb.c b/drivers/phy/hisilicon/phy-hi6220-usb.c
new file mode 100644 (file)
index 0000000..398c102
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
+#define SC_PERIPH_CTRL4                        0x00c
+
+#define CTRL4_PICO_SIDDQ               BIT(6)
+#define CTRL4_PICO_OGDISABLE           BIT(8)
+#define CTRL4_PICO_VBUSVLDEXT          BIT(10)
+#define CTRL4_PICO_VBUSVLDEXTSEL       BIT(11)
+#define CTRL4_OTG_PHY_SEL              BIT(21)
+
+#define SC_PERIPH_CTRL5                        0x010
+
+#define CTRL5_USBOTG_RES_SEL           BIT(3)
+#define CTRL5_PICOPHY_ACAENB           BIT(4)
+#define CTRL5_PICOPHY_BC_MODE          BIT(5)
+#define CTRL5_PICOPHY_CHRGSEL          BIT(6)
+#define CTRL5_PICOPHY_VDATSRCEND       BIT(7)
+#define CTRL5_PICOPHY_VDATDETENB       BIT(8)
+#define CTRL5_PICOPHY_DCDENB           BIT(9)
+#define CTRL5_PICOPHY_IDDIG            BIT(10)
+
+#define SC_PERIPH_CTRL8                        0x018
+#define SC_PERIPH_RSTEN0               0x300
+#define SC_PERIPH_RSTDIS0              0x304
+
+#define RST0_USBOTG_BUS                        BIT(4)
+#define RST0_POR_PICOPHY               BIT(5)
+#define RST0_USBOTG                    BIT(6)
+#define RST0_USBOTG_32K                        BIT(7)
+
+#define EYE_PATTERN_PARA               0x7053348c
+
+struct hi6220_priv {
+       struct regmap *reg;
+       struct device *dev;
+};
+
+static void hi6220_phy_init(struct hi6220_priv *priv)
+{
+       struct regmap *reg = priv->reg;
+       u32 val, mask;
+
+       val = RST0_USBOTG_BUS | RST0_POR_PICOPHY |
+             RST0_USBOTG | RST0_USBOTG_32K;
+       mask = val;
+       regmap_update_bits(reg, SC_PERIPH_RSTEN0, mask, val);
+       regmap_update_bits(reg, SC_PERIPH_RSTDIS0, mask, val);
+}
+
+static int hi6220_phy_setup(struct hi6220_priv *priv, bool on)
+{
+       struct regmap *reg = priv->reg;
+       u32 val, mask;
+       int ret;
+
+       if (on) {
+               val = CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB;
+               mask = val | CTRL5_PICOPHY_BC_MODE;
+               ret = regmap_update_bits(reg, SC_PERIPH_CTRL5, mask, val);
+               if (ret)
+                       goto out;
+
+               val =  CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL |
+                      CTRL4_OTG_PHY_SEL;
+               mask = val | CTRL4_PICO_SIDDQ | CTRL4_PICO_OGDISABLE;
+               ret = regmap_update_bits(reg, SC_PERIPH_CTRL4, mask, val);
+               if (ret)
+                       goto out;
+
+               ret = regmap_write(reg, SC_PERIPH_CTRL8, EYE_PATTERN_PARA);
+               if (ret)
+                       goto out;
+       } else {
+               val = CTRL4_PICO_SIDDQ;
+               mask = val;
+               ret = regmap_update_bits(reg, SC_PERIPH_CTRL4, mask, val);
+               if (ret)
+                       goto out;
+       }
+
+       return 0;
+out:
+       dev_err(priv->dev, "failed to setup phy ret: %d\n", ret);
+       return ret;
+}
+
+static int hi6220_phy_start(struct phy *phy)
+{
+       struct hi6220_priv *priv = phy_get_drvdata(phy);
+
+       return hi6220_phy_setup(priv, true);
+}
+
+static int hi6220_phy_exit(struct phy *phy)
+{
+       struct hi6220_priv *priv = phy_get_drvdata(phy);
+
+       return hi6220_phy_setup(priv, false);
+}
+
+static const struct phy_ops hi6220_phy_ops = {
+       .init           = hi6220_phy_start,
+       .exit           = hi6220_phy_exit,
+       .owner          = THIS_MODULE,
+};
+
+static int hi6220_phy_probe(struct platform_device *pdev)
+{
+       struct phy_provider *phy_provider;
+       struct device *dev = &pdev->dev;
+       struct phy *phy;
+       struct hi6220_priv *priv;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->dev = dev;
+       priv->reg = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                       "hisilicon,peripheral-syscon");
+       if (IS_ERR(priv->reg)) {
+               dev_err(dev, "no hisilicon,peripheral-syscon\n");
+               return PTR_ERR(priv->reg);
+       }
+
+       hi6220_phy_init(priv);
+
+       phy = devm_phy_create(dev, NULL, &hi6220_phy_ops);
+       if (IS_ERR(phy))
+               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 hi6220_phy_of_match[] = {
+       {.compatible = "hisilicon,hi6220-usb-phy",},
+       { },
+};
+MODULE_DEVICE_TABLE(of, hi6220_phy_of_match);
+
+static struct platform_driver hi6220_phy_driver = {
+       .probe  = hi6220_phy_probe,
+       .driver = {
+               .name   = "hi6220-usb-phy",
+               .of_match_table = hi6220_phy_of_match,
+       }
+};
+module_platform_driver(hi6220_phy_driver);
+
+MODULE_DESCRIPTION("HISILICON HI6220 USB PHY driver");
+MODULE_ALIAS("platform:hi6220-usb-phy");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/hisilicon/phy-hix5hd2-sata.c b/drivers/phy/hisilicon/phy-hix5hd2-sata.c
new file mode 100644 (file)
index 0000000..e5ab3aa
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2014 Linaro Ltd.
+ * Copyright (c) 2014 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define SATA_PHY0_CTLL         0xa0
+#define MPLL_MULTIPLIER_SHIFT  1
+#define MPLL_MULTIPLIER_MASK   0xfe
+#define MPLL_MULTIPLIER_50M    0x3c
+#define MPLL_MULTIPLIER_100M   0x1e
+#define PHY_RESET              BIT(0)
+#define REF_SSP_EN             BIT(9)
+#define SSC_EN                 BIT(10)
+#define REF_USE_PAD            BIT(23)
+
+#define SATA_PORT_PHYCTL       0x174
+#define SPEED_MODE_MASK                0x6f0000
+#define HALF_RATE_SHIFT                16
+#define PHY_CONFIG_SHIFT       18
+#define GEN2_EN_SHIFT          21
+#define SPEED_CTRL             BIT(20)
+
+#define SATA_PORT_PHYCTL1      0x148
+#define AMPLITUDE_MASK         0x3ffffe
+#define AMPLITUDE_GEN3         0x68
+#define AMPLITUDE_GEN3_SHIFT   15
+#define AMPLITUDE_GEN2         0x56
+#define AMPLITUDE_GEN2_SHIFT   8
+#define AMPLITUDE_GEN1         0x56
+#define AMPLITUDE_GEN1_SHIFT   1
+
+#define SATA_PORT_PHYCTL2      0x14c
+#define PREEMPH_MASK           0x3ffff
+#define PREEMPH_GEN3           0x20
+#define PREEMPH_GEN3_SHIFT     12
+#define PREEMPH_GEN2           0x15
+#define PREEMPH_GEN2_SHIFT     6
+#define PREEMPH_GEN1           0x5
+#define PREEMPH_GEN1_SHIFT     0
+
+struct hix5hd2_priv {
+       void __iomem    *base;
+       struct regmap   *peri_ctrl;
+};
+
+enum phy_speed_mode {
+       SPEED_MODE_GEN1 = 0,
+       SPEED_MODE_GEN2 = 1,
+       SPEED_MODE_GEN3 = 2,
+};
+
+static int hix5hd2_sata_phy_init(struct phy *phy)
+{
+       struct hix5hd2_priv *priv = phy_get_drvdata(phy);
+       u32 val, data[2];
+       int ret;
+
+       if (priv->peri_ctrl) {
+               ret = of_property_read_u32_array(phy->dev.of_node,
+                                                "hisilicon,power-reg",
+                                                &data[0], 2);
+               if (ret) {
+                       dev_err(&phy->dev, "Fail read hisilicon,power-reg\n");
+                       return ret;
+               }
+
+               regmap_update_bits(priv->peri_ctrl, data[0],
+                                  BIT(data[1]), BIT(data[1]));
+       }
+
+       /* reset phy */
+       val = readl_relaxed(priv->base + SATA_PHY0_CTLL);
+       val &= ~(MPLL_MULTIPLIER_MASK | REF_USE_PAD);
+       val |= MPLL_MULTIPLIER_50M << MPLL_MULTIPLIER_SHIFT |
+              REF_SSP_EN | PHY_RESET;
+       writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
+       msleep(20);
+       val &= ~PHY_RESET;
+       writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
+
+       val = readl_relaxed(priv->base + SATA_PORT_PHYCTL1);
+       val &= ~AMPLITUDE_MASK;
+       val |= AMPLITUDE_GEN3 << AMPLITUDE_GEN3_SHIFT |
+              AMPLITUDE_GEN2 << AMPLITUDE_GEN2_SHIFT |
+              AMPLITUDE_GEN1 << AMPLITUDE_GEN1_SHIFT;
+       writel_relaxed(val, priv->base + SATA_PORT_PHYCTL1);
+
+       val = readl_relaxed(priv->base + SATA_PORT_PHYCTL2);
+       val &= ~PREEMPH_MASK;
+       val |= PREEMPH_GEN3 << PREEMPH_GEN3_SHIFT |
+              PREEMPH_GEN2 << PREEMPH_GEN2_SHIFT |
+              PREEMPH_GEN1 << PREEMPH_GEN1_SHIFT;
+       writel_relaxed(val, priv->base + SATA_PORT_PHYCTL2);
+
+       /* ensure PHYCTRL setting takes effect */
+       val = readl_relaxed(priv->base + SATA_PORT_PHYCTL);
+       val &= ~SPEED_MODE_MASK;
+       val |= SPEED_MODE_GEN1 << HALF_RATE_SHIFT |
+              SPEED_MODE_GEN1 << PHY_CONFIG_SHIFT |
+              SPEED_MODE_GEN1 << GEN2_EN_SHIFT | SPEED_CTRL;
+       writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+       msleep(20);
+       val &= ~SPEED_MODE_MASK;
+       val |= SPEED_MODE_GEN3 << HALF_RATE_SHIFT |
+              SPEED_MODE_GEN3 << PHY_CONFIG_SHIFT |
+              SPEED_MODE_GEN3 << GEN2_EN_SHIFT | SPEED_CTRL;
+       writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+       val &= ~(SPEED_MODE_MASK | SPEED_CTRL);
+       val |= SPEED_MODE_GEN2 << HALF_RATE_SHIFT |
+              SPEED_MODE_GEN2 << PHY_CONFIG_SHIFT |
+              SPEED_MODE_GEN2 << GEN2_EN_SHIFT;
+       writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+       return 0;
+}
+
+static const struct phy_ops hix5hd2_sata_phy_ops = {
+       .init           = hix5hd2_sata_phy_init,
+       .owner          = THIS_MODULE,
+};
+
+static int hix5hd2_sata_phy_probe(struct platform_device *pdev)
+{
+       struct phy_provider *phy_provider;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       struct phy *phy;
+       struct hix5hd2_priv *priv;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -EINVAL;
+
+       priv->base = devm_ioremap(dev, res->start, resource_size(res));
+       if (!priv->base)
+               return -ENOMEM;
+
+       priv->peri_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                       "hisilicon,peripheral-syscon");
+       if (IS_ERR(priv->peri_ctrl))
+               priv->peri_ctrl = NULL;
+
+       phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_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 hix5hd2_sata_phy_of_match[] = {
+       {.compatible = "hisilicon,hix5hd2-sata-phy",},
+       { },
+};
+MODULE_DEVICE_TABLE(of, hix5hd2_sata_phy_of_match);
+
+static struct platform_driver hix5hd2_sata_phy_driver = {
+       .probe  = hix5hd2_sata_phy_probe,
+       .driver = {
+               .name   = "hix5hd2-sata-phy",
+               .of_match_table = hix5hd2_sata_phy_of_match,
+       }
+};
+module_platform_driver(hix5hd2_sata_phy_driver);
+
+MODULE_AUTHOR("Jiancheng Xue <xuejiancheng@huawei.com>");
+MODULE_DESCRIPTION("HISILICON HIX5HD2 SATA PHY driver");
+MODULE_ALIAS("platform:hix5hd2-sata-phy");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig
new file mode 100644 (file)
index 0000000..048d889
--- /dev/null
@@ -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.
diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile
new file mode 100644 (file)
index 0000000..3fc188f
--- /dev/null
@@ -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
diff --git a/drivers/phy/marvell/phy-armada375-usb2.c b/drivers/phy/marvell/phy-armada375-usb2.c
new file mode 100644 (file)
index 0000000..1a3db28
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * USB cluster support for Armada 375 platform.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2 or later. This program is licensed "as is"
+ * without any warranty of any kind, whether express or implied.
+ *
+ * Armada 375 comes with an USB2 host and device controller and an
+ * USB3 controller. The USB cluster control register allows to manage
+ * common features of both USB controllers.
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#define USB2_PHY_CONFIG_DISABLE BIT(0)
+
+struct armada375_cluster_phy {
+       struct phy *phy;
+       void __iomem *reg;
+       bool use_usb3;
+       int phy_provided;
+};
+
+static int armada375_usb_phy_init(struct phy *phy)
+{
+       struct armada375_cluster_phy *cluster_phy;
+       u32 reg;
+
+       cluster_phy = phy_get_drvdata(phy);
+       if (!cluster_phy)
+               return -ENODEV;
+
+       reg = readl(cluster_phy->reg);
+       if (cluster_phy->use_usb3)
+               reg |= USB2_PHY_CONFIG_DISABLE;
+       else
+               reg &= ~USB2_PHY_CONFIG_DISABLE;
+       writel(reg, cluster_phy->reg);
+
+       return 0;
+}
+
+static const struct phy_ops armada375_usb_phy_ops = {
+       .init = armada375_usb_phy_init,
+       .owner = THIS_MODULE,
+};
+
+/*
+ * Only one controller can use this PHY. We shouldn't have the case
+ * when two controllers want to use this PHY. But if this case occurs
+ * then we provide a phy to the first one and return an error for the
+ * next one. This error has also to be an error returned by
+ * devm_phy_optional_get() so different from ENODEV for USB2. In the
+ * USB3 case it still optional and we use ENODEV.
+ */
+static struct phy *armada375_usb_phy_xlate(struct device *dev,
+                                       struct of_phandle_args *args)
+{
+       struct armada375_cluster_phy *cluster_phy = dev_get_drvdata(dev);
+
+       if (!cluster_phy)
+               return  ERR_PTR(-ENODEV);
+
+       /*
+        * Either the phy had never been requested and then the first
+        * usb claiming it can get it, or it had already been
+        * requested in this case, we only allow to use it with the
+        * same configuration.
+        */
+       if (WARN_ON((cluster_phy->phy_provided != PHY_NONE) &&
+                       (cluster_phy->phy_provided != args->args[0]))) {
+               dev_err(dev, "This PHY has already been provided!\n");
+               dev_err(dev, "Check your device tree, only one controller can use it\n.");
+               if (args->args[0] == PHY_TYPE_USB2)
+                       return ERR_PTR(-EBUSY);
+               else
+                       return ERR_PTR(-ENODEV);
+       }
+
+       if (args->args[0] == PHY_TYPE_USB2)
+               cluster_phy->use_usb3 = false;
+       else if (args->args[0] == PHY_TYPE_USB3)
+               cluster_phy->use_usb3 = true;
+       else {
+               dev_err(dev, "Invalid PHY mode\n");
+               return ERR_PTR(-ENODEV);
+       }
+
+       /* Store which phy mode is used for next test */
+       cluster_phy->phy_provided = args->args[0];
+
+       return cluster_phy->phy;
+}
+
+static int armada375_usb_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct phy *phy;
+       struct phy_provider *phy_provider;
+       void __iomem *usb_cluster_base;
+       struct resource *res;
+       struct armada375_cluster_phy *cluster_phy;
+
+       cluster_phy = devm_kzalloc(dev, sizeof(*cluster_phy), GFP_KERNEL);
+       if (!cluster_phy)
+               return  -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       usb_cluster_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(usb_cluster_base))
+               return PTR_ERR(usb_cluster_base);
+
+       phy = devm_phy_create(dev, NULL, &armada375_usb_phy_ops);
+       if (IS_ERR(phy)) {
+               dev_err(dev, "failed to create PHY\n");
+               return PTR_ERR(phy);
+       }
+
+       cluster_phy->phy = phy;
+       cluster_phy->reg = usb_cluster_base;
+
+       dev_set_drvdata(dev, cluster_phy);
+       phy_set_drvdata(phy, cluster_phy);
+
+       phy_provider = devm_of_phy_provider_register(&pdev->dev,
+                                                    armada375_usb_phy_xlate);
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id of_usb_cluster_table[] = {
+       { .compatible = "marvell,armada-375-usb-cluster", },
+       { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, of_usb_cluster_table);
+
+static struct platform_driver armada375_usb_phy_driver = {
+       .probe  = armada375_usb_phy_probe,
+       .driver = {
+               .of_match_table = of_usb_cluster_table,
+               .name  = "armada-375-usb-cluster",
+       }
+};
+module_platform_driver(armada375_usb_phy_driver);
+
+MODULE_DESCRIPTION("Armada 375 USB cluster driver");
+MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/marvell/phy-berlin-sata.c b/drivers/phy/marvell/phy-berlin-sata.c
new file mode 100644 (file)
index 0000000..2c7a57f
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * Marvell Berlin SATA PHY driver
+ *
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Ténart <antoine.tenart@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#define HOST_VSA_ADDR          0x0
+#define HOST_VSA_DATA          0x4
+#define PORT_SCR_CTL           0x2c
+#define PORT_VSR_ADDR          0x78
+#define PORT_VSR_DATA          0x7c
+
+#define CONTROL_REGISTER       0x0
+#define MBUS_SIZE_CONTROL      0x4
+
+#define POWER_DOWN_PHY0                        BIT(6)
+#define POWER_DOWN_PHY1                        BIT(14)
+#define MBUS_WRITE_REQUEST_SIZE_128    (BIT(2) << 16)
+#define MBUS_READ_REQUEST_SIZE_128     (BIT(2) << 19)
+
+#define BG2_PHY_BASE           0x080
+#define BG2Q_PHY_BASE          0x200
+
+/* register 0x01 */
+#define REF_FREF_SEL_25                BIT(0)
+#define PHY_MODE_SATA          (0x0 << 5)
+
+/* register 0x02 */
+#define USE_MAX_PLL_RATE       BIT(12)
+
+/* register 0x23 */
+#define DATA_BIT_WIDTH_10      (0x0 << 10)
+#define DATA_BIT_WIDTH_20      (0x1 << 10)
+#define DATA_BIT_WIDTH_40      (0x2 << 10)
+
+/* register 0x25 */
+#define PHY_GEN_MAX_1_5                (0x0 << 10)
+#define PHY_GEN_MAX_3_0                (0x1 << 10)
+#define PHY_GEN_MAX_6_0                (0x2 << 10)
+
+struct phy_berlin_desc {
+       struct phy      *phy;
+       u32             power_bit;
+       unsigned        index;
+};
+
+struct phy_berlin_priv {
+       void __iomem            *base;
+       spinlock_t              lock;
+       struct clk              *clk;
+       struct phy_berlin_desc  **phys;
+       unsigned                nphys;
+       u32                     phy_base;
+};
+
+static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg,
+                              u32 phy_base, u32 reg, u32 mask, u32 val)
+{
+       u32 regval;
+
+       /* select register */
+       writel(phy_base + reg, ctrl_reg + PORT_VSR_ADDR);
+
+       /* set bits */
+       regval = readl(ctrl_reg + PORT_VSR_DATA);
+       regval &= ~mask;
+       regval |= val;
+       writel(regval, ctrl_reg + PORT_VSR_DATA);
+}
+
+static int phy_berlin_sata_power_on(struct phy *phy)
+{
+       struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+       struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+       void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
+       u32 regval;
+
+       clk_prepare_enable(priv->clk);
+
+       spin_lock(&priv->lock);
+
+       /* Power on PHY */
+       writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+       regval = readl(priv->base + HOST_VSA_DATA);
+       regval &= ~desc->power_bit;
+       writel(regval, priv->base + HOST_VSA_DATA);
+
+       /* Configure MBus */
+       writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
+       regval = readl(priv->base + HOST_VSA_DATA);
+       regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
+       writel(regval, priv->base + HOST_VSA_DATA);
+
+       /* set PHY mode and ref freq to 25 MHz */
+       phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01,
+                                   0x00ff, REF_FREF_SEL_25 | PHY_MODE_SATA);
+
+       /* set PHY up to 6 Gbps */
+       phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25,
+                                   0x0c00, PHY_GEN_MAX_6_0);
+
+       /* set 40 bits width */
+       phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x23,
+                                   0x0c00, DATA_BIT_WIDTH_40);
+
+       /* use max pll rate */
+       phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x02,
+                                   0x0000, USE_MAX_PLL_RATE);
+
+       /* set Gen3 controller speed */
+       regval = readl(ctrl_reg + PORT_SCR_CTL);
+       regval &= ~GENMASK(7, 4);
+       regval |= 0x30;
+       writel(regval, ctrl_reg + PORT_SCR_CTL);
+
+       spin_unlock(&priv->lock);
+
+       clk_disable_unprepare(priv->clk);
+
+       return 0;
+}
+
+static int phy_berlin_sata_power_off(struct phy *phy)
+{
+       struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+       struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+       u32 regval;
+
+       clk_prepare_enable(priv->clk);
+
+       spin_lock(&priv->lock);
+
+       /* Power down PHY */
+       writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+       regval = readl(priv->base + HOST_VSA_DATA);
+       regval |= desc->power_bit;
+       writel(regval, priv->base + HOST_VSA_DATA);
+
+       spin_unlock(&priv->lock);
+
+       clk_disable_unprepare(priv->clk);
+
+       return 0;
+}
+
+static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
+                                            struct of_phandle_args *args)
+{
+       struct phy_berlin_priv *priv = dev_get_drvdata(dev);
+       int i;
+
+       if (WARN_ON(args->args[0] >= priv->nphys))
+               return ERR_PTR(-ENODEV);
+
+       for (i = 0; i < priv->nphys; i++) {
+               if (priv->phys[i]->index == args->args[0])
+                       break;
+       }
+
+       if (i == priv->nphys)
+               return ERR_PTR(-ENODEV);
+
+       return priv->phys[i]->phy;
+}
+
+static const struct phy_ops phy_berlin_sata_ops = {
+       .power_on       = phy_berlin_sata_power_on,
+       .power_off      = phy_berlin_sata_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static u32 phy_berlin_power_down_bits[] = {
+       POWER_DOWN_PHY0,
+       POWER_DOWN_PHY1,
+};
+
+static int phy_berlin_sata_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *child;
+       struct phy *phy;
+       struct phy_provider *phy_provider;
+       struct phy_berlin_priv *priv;
+       struct resource *res;
+       int ret, i = 0;
+       u32 phy_id;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -EINVAL;
+
+       priv->base = devm_ioremap(dev, res->start, resource_size(res));
+       if (!priv->base)
+               return -ENOMEM;
+
+       priv->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(priv->clk))
+               return PTR_ERR(priv->clk);
+
+       priv->nphys = of_get_child_count(dev->of_node);
+       if (priv->nphys == 0)
+               return -ENODEV;
+
+       priv->phys = devm_kcalloc(dev, priv->nphys, sizeof(*priv->phys),
+                                 GFP_KERNEL);
+       if (!priv->phys)
+               return -ENOMEM;
+
+       if (of_device_is_compatible(dev->of_node, "marvell,berlin2-sata-phy"))
+               priv->phy_base = BG2_PHY_BASE;
+       else
+               priv->phy_base = BG2Q_PHY_BASE;
+
+       dev_set_drvdata(dev, priv);
+       spin_lock_init(&priv->lock);
+
+       for_each_available_child_of_node(dev->of_node, child) {
+               struct phy_berlin_desc *phy_desc;
+
+               if (of_property_read_u32(child, "reg", &phy_id)) {
+                       dev_err(dev, "missing reg property in node %s\n",
+                               child->name);
+                       ret = -EINVAL;
+                       goto put_child;
+               }
+
+               if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
+                       dev_err(dev, "invalid reg in node %s\n", child->name);
+                       ret = -EINVAL;
+                       goto put_child;
+               }
+
+               phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
+               if (!phy_desc) {
+                       ret = -ENOMEM;
+                       goto put_child;
+               }
+
+               phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops);
+               if (IS_ERR(phy)) {
+                       dev_err(dev, "failed to create PHY %d\n", phy_id);
+                       ret = PTR_ERR(phy);
+                       goto put_child;
+               }
+
+               phy_desc->phy = phy;
+               phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
+               phy_desc->index = phy_id;
+               phy_set_drvdata(phy, phy_desc);
+
+               priv->phys[i++] = phy_desc;
+
+               /* Make sure the PHY is off */
+               phy_berlin_sata_power_off(phy);
+       }
+
+       phy_provider =
+               devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
+       return PTR_ERR_OR_ZERO(phy_provider);
+put_child:
+       of_node_put(child);
+       return ret;
+}
+
+static const struct of_device_id phy_berlin_sata_of_match[] = {
+       { .compatible = "marvell,berlin2-sata-phy" },
+       { .compatible = "marvell,berlin2q-sata-phy" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
+
+static struct platform_driver phy_berlin_sata_driver = {
+       .probe  = phy_berlin_sata_probe,
+       .driver = {
+               .name           = "phy-berlin-sata",
+               .of_match_table = phy_berlin_sata_of_match,
+       },
+};
+module_platform_driver(phy_berlin_sata_driver);
+
+MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
+MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/marvell/phy-berlin-usb.c b/drivers/phy/marvell/phy-berlin-usb.c
new file mode 100644 (file)
index 0000000..2017751
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Tenart <antoine.tenart@free-electrons.com>
+ * Jisheng Zhang <jszhang@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#define USB_PHY_PLL            0x04
+#define USB_PHY_PLL_CONTROL    0x08
+#define USB_PHY_TX_CTRL0       0x10
+#define USB_PHY_TX_CTRL1       0x14
+#define USB_PHY_TX_CTRL2       0x18
+#define USB_PHY_RX_CTRL                0x20
+#define USB_PHY_ANALOG         0x34
+
+/* USB_PHY_PLL */
+#define CLK_REF_DIV(x)         ((x) << 4)
+#define FEEDBACK_CLK_DIV(x)    ((x) << 8)
+
+/* USB_PHY_PLL_CONTROL */
+#define CLK_STABLE             BIT(0)
+#define PLL_CTRL_PIN           BIT(1)
+#define PLL_CTRL_REG           BIT(2)
+#define PLL_ON                 BIT(3)
+#define PHASE_OFF_TOL_125      (0x0 << 5)
+#define PHASE_OFF_TOL_250      BIT(5)
+#define KVC0_CALIB             (0x0 << 9)
+#define KVC0_REG_CTRL          BIT(9)
+#define KVC0_HIGH              (0x0 << 10)
+#define KVC0_LOW               (0x3 << 10)
+#define CLK_BLK_EN             BIT(13)
+
+/* USB_PHY_TX_CTRL0 */
+#define EXT_HS_RCAL_EN         BIT(3)
+#define EXT_FS_RCAL_EN         BIT(4)
+#define IMPCAL_VTH_DIV(x)      ((x) << 5)
+#define EXT_RS_RCAL_DIV(x)     ((x) << 8)
+#define EXT_FS_RCAL_DIV(x)     ((x) << 12)
+
+/* USB_PHY_TX_CTRL1 */
+#define TX_VDD15_14            (0x0 << 4)
+#define TX_VDD15_15            BIT(4)
+#define TX_VDD15_16            (0x2 << 4)
+#define TX_VDD15_17            (0x3 << 4)
+#define TX_VDD12_VDD           (0x0 << 6)
+#define TX_VDD12_11            BIT(6)
+#define TX_VDD12_12            (0x2 << 6)
+#define TX_VDD12_13            (0x3 << 6)
+#define LOW_VDD_EN             BIT(8)
+#define TX_OUT_AMP(x)          ((x) << 9)
+
+/* USB_PHY_TX_CTRL2 */
+#define TX_CHAN_CTRL_REG(x)    ((x) << 0)
+#define DRV_SLEWRATE(x)                ((x) << 4)
+#define IMP_CAL_FS_HS_DLY_0    (0x0 << 6)
+#define IMP_CAL_FS_HS_DLY_1    BIT(6)
+#define IMP_CAL_FS_HS_DLY_2    (0x2 << 6)
+#define IMP_CAL_FS_HS_DLY_3    (0x3 << 6)
+#define FS_DRV_EN_MASK(x)      ((x) << 8)
+#define HS_DRV_EN_MASK(x)      ((x) << 12)
+
+/* USB_PHY_RX_CTRL */
+#define PHASE_FREEZE_DLY_2_CL  (0x0 << 0)
+#define PHASE_FREEZE_DLY_4_CL  BIT(0)
+#define ACK_LENGTH_8_CL                (0x0 << 2)
+#define ACK_LENGTH_12_CL       BIT(2)
+#define ACK_LENGTH_16_CL       (0x2 << 2)
+#define ACK_LENGTH_20_CL       (0x3 << 2)
+#define SQ_LENGTH_3            (0x0 << 4)
+#define SQ_LENGTH_6            BIT(4)
+#define SQ_LENGTH_9            (0x2 << 4)
+#define SQ_LENGTH_12           (0x3 << 4)
+#define DISCON_THRESHOLD_260   (0x0 << 6)
+#define DISCON_THRESHOLD_270   BIT(6)
+#define DISCON_THRESHOLD_280   (0x2 << 6)
+#define DISCON_THRESHOLD_290   (0x3 << 6)
+#define SQ_THRESHOLD(x)                ((x) << 8)
+#define LPF_COEF(x)            ((x) << 12)
+#define INTPL_CUR_10           (0x0 << 14)
+#define INTPL_CUR_20           BIT(14)
+#define INTPL_CUR_30           (0x2 << 14)
+#define INTPL_CUR_40           (0x3 << 14)
+
+/* USB_PHY_ANALOG */
+#define ANA_PWR_UP             BIT(1)
+#define ANA_PWR_DOWN           BIT(2)
+#define V2I_VCO_RATIO(x)       ((x) << 7)
+#define R_ROTATE_90            (0x0 << 10)
+#define R_ROTATE_0             BIT(10)
+#define MODE_TEST_EN           BIT(11)
+#define ANA_TEST_DC_CTRL(x)    ((x) << 12)
+
+static const u32 phy_berlin_pll_dividers[] = {
+       /* Berlin 2 */
+       CLK_REF_DIV(0x6) | FEEDBACK_CLK_DIV(0x55),
+       /* Berlin 2CD/Q */
+       CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
+};
+
+struct phy_berlin_usb_priv {
+       void __iomem            *base;
+       struct reset_control    *rst_ctrl;
+       u32                     pll_divider;
+};
+
+static int phy_berlin_usb_power_on(struct phy *phy)
+{
+       struct phy_berlin_usb_priv *priv = phy_get_drvdata(phy);
+
+       reset_control_reset(priv->rst_ctrl);
+
+       writel(priv->pll_divider,
+              priv->base + USB_PHY_PLL);
+       writel(CLK_STABLE | PLL_CTRL_REG | PHASE_OFF_TOL_250 | KVC0_REG_CTRL |
+              CLK_BLK_EN, priv->base + USB_PHY_PLL_CONTROL);
+       writel(V2I_VCO_RATIO(0x5) | R_ROTATE_0 | ANA_TEST_DC_CTRL(0x5),
+              priv->base + USB_PHY_ANALOG);
+       writel(PHASE_FREEZE_DLY_4_CL | ACK_LENGTH_16_CL | SQ_LENGTH_12 |
+              DISCON_THRESHOLD_260 | SQ_THRESHOLD(0xa) | LPF_COEF(0x2) |
+              INTPL_CUR_30, priv->base + USB_PHY_RX_CTRL);
+
+       writel(TX_VDD12_13 | TX_OUT_AMP(0x3), priv->base + USB_PHY_TX_CTRL1);
+       writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
+              priv->base + USB_PHY_TX_CTRL0);
+
+       writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4) |
+              EXT_FS_RCAL_DIV(0x2), priv->base + USB_PHY_TX_CTRL0);
+
+       writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
+              priv->base + USB_PHY_TX_CTRL0);
+       writel(TX_CHAN_CTRL_REG(0xf) | DRV_SLEWRATE(0x3) | IMP_CAL_FS_HS_DLY_3 |
+              FS_DRV_EN_MASK(0xd), priv->base + USB_PHY_TX_CTRL2);
+
+       return 0;
+}
+
+static const struct phy_ops phy_berlin_usb_ops = {
+       .power_on       = phy_berlin_usb_power_on,
+       .owner          = THIS_MODULE,
+};
+
+static const struct of_device_id phy_berlin_usb_of_match[] = {
+       {
+               .compatible = "marvell,berlin2-usb-phy",
+               .data = &phy_berlin_pll_dividers[0],
+       },
+       {
+               .compatible = "marvell,berlin2cd-usb-phy",
+               .data = &phy_berlin_pll_dividers[1],
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, phy_berlin_usb_of_match);
+
+static int phy_berlin_usb_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match =
+               of_match_device(phy_berlin_usb_of_match, &pdev->dev);
+       struct phy_berlin_usb_priv *priv;
+       struct resource *res;
+       struct phy *phy;
+       struct phy_provider *phy_provider;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       priv->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(priv->base))
+               return PTR_ERR(priv->base);
+
+       priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL);
+       if (IS_ERR(priv->rst_ctrl))
+               return PTR_ERR(priv->rst_ctrl);
+
+       priv->pll_divider = *((u32 *)match->data);
+
+       phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops);
+       if (IS_ERR(phy)) {
+               dev_err(&pdev->dev, "failed to create PHY\n");
+               return PTR_ERR(phy);
+       }
+
+       phy_set_drvdata(phy, priv);
+
+       phy_provider =
+               devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static struct platform_driver phy_berlin_usb_driver = {
+       .probe  = phy_berlin_usb_probe,
+       .driver = {
+               .name           = "phy-berlin-usb",
+               .of_match_table = phy_berlin_usb_of_match,
+       },
+};
+module_platform_driver(phy_berlin_usb_driver);
+
+MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Berlin PHY driver for USB");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/marvell/phy-mvebu-sata.c b/drivers/phy/marvell/phy-mvebu-sata.c
new file mode 100644 (file)
index 0000000..768ce92
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *     phy-mvebu-sata.c: SATA Phy driver for the Marvell mvebu SoCs.
+ *
+ *     Copyright (C) 2013 Andrew Lunn <andrew@lunn.ch>
+ *
+ *     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; either version
+ *     2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/phy/phy.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+struct priv {
+       struct clk      *clk;
+       void __iomem    *base;
+};
+
+#define SATA_PHY_MODE_2        0x0330
+#define  MODE_2_FORCE_PU_TX    BIT(0)
+#define  MODE_2_FORCE_PU_RX    BIT(1)
+#define  MODE_2_PU_PLL         BIT(2)
+#define  MODE_2_PU_IVREF       BIT(3)
+#define SATA_IF_CTRL   0x0050
+#define  CTRL_PHY_SHUTDOWN     BIT(9)
+
+static int phy_mvebu_sata_power_on(struct phy *phy)
+{
+       struct priv *priv = phy_get_drvdata(phy);
+       u32 reg;
+
+       clk_prepare_enable(priv->clk);
+
+       /* Enable PLL and IVREF */
+       reg = readl(priv->base + SATA_PHY_MODE_2);
+       reg |= (MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
+               MODE_2_PU_PLL | MODE_2_PU_IVREF);
+       writel(reg , priv->base + SATA_PHY_MODE_2);
+
+       /* Enable PHY */
+       reg = readl(priv->base + SATA_IF_CTRL);
+       reg &= ~CTRL_PHY_SHUTDOWN;
+       writel(reg, priv->base + SATA_IF_CTRL);
+
+       clk_disable_unprepare(priv->clk);
+
+       return 0;
+}
+
+static int phy_mvebu_sata_power_off(struct phy *phy)
+{
+       struct priv *priv = phy_get_drvdata(phy);
+       u32 reg;
+
+       clk_prepare_enable(priv->clk);
+
+       /* Disable PLL and IVREF */
+       reg = readl(priv->base + SATA_PHY_MODE_2);
+       reg &= ~(MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
+                MODE_2_PU_PLL | MODE_2_PU_IVREF);
+       writel(reg, priv->base + SATA_PHY_MODE_2);
+
+       /* Disable PHY */
+       reg = readl(priv->base + SATA_IF_CTRL);
+       reg |= CTRL_PHY_SHUTDOWN;
+       writel(reg, priv->base + SATA_IF_CTRL);
+
+       clk_disable_unprepare(priv->clk);
+
+       return 0;
+}
+
+static const struct phy_ops phy_mvebu_sata_ops = {
+       .power_on       = phy_mvebu_sata_power_on,
+       .power_off      = phy_mvebu_sata_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int phy_mvebu_sata_probe(struct platform_device *pdev)
+{
+       struct phy_provider *phy_provider;
+       struct resource *res;
+       struct priv *priv;
+       struct phy *phy;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       priv->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(priv->base))
+               return PTR_ERR(priv->base);
+
+       priv->clk = devm_clk_get(&pdev->dev, "sata");
+       if (IS_ERR(priv->clk))
+               return PTR_ERR(priv->clk);
+
+       phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops);
+       if (IS_ERR(phy))
+               return PTR_ERR(phy);
+
+       phy_set_drvdata(phy, priv);
+
+       phy_provider = devm_of_phy_provider_register(&pdev->dev,
+                                                    of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
+       /* The boot loader may of left it on. Turn it off. */
+       phy_mvebu_sata_power_off(phy);
+
+       return 0;
+}
+
+static const struct of_device_id phy_mvebu_sata_of_match[] = {
+       { .compatible = "marvell,mvebu-sata-phy" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, phy_mvebu_sata_of_match);
+
+static struct platform_driver phy_mvebu_sata_driver = {
+       .probe  = phy_mvebu_sata_probe,
+       .driver = {
+               .name   = "phy-mvebu-sata",
+               .of_match_table = phy_mvebu_sata_of_match,
+       }
+};
+module_platform_driver(phy_mvebu_sata_driver);
+
+MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
+MODULE_DESCRIPTION("Marvell MVEBU SATA PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/marvell/phy-pxa-28nm-hsic.c b/drivers/phy/marvell/phy-pxa-28nm-hsic.c
new file mode 100644 (file)
index 0000000..234aacf
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2015 Linaro, Ltd.
+ * Rob Herring <robh@kernel.org>
+ *
+ * Based on vendor driver:
+ * Copyright (C) 2013 Marvell Inc.
+ * Author: Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/slab.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+#define PHY_28NM_HSIC_CTRL                     0x08
+#define PHY_28NM_HSIC_IMPCAL_CAL               0x18
+#define PHY_28NM_HSIC_PLL_CTRL01               0x1c
+#define PHY_28NM_HSIC_PLL_CTRL2                        0x20
+#define PHY_28NM_HSIC_INT                      0x28
+
+#define PHY_28NM_HSIC_PLL_SELLPFR_SHIFT                26
+#define PHY_28NM_HSIC_PLL_FBDIV_SHIFT          0
+#define PHY_28NM_HSIC_PLL_REFDIV_SHIFT         9
+
+#define PHY_28NM_HSIC_S2H_PU_PLL               BIT(10)
+#define PHY_28NM_HSIC_H2S_PLL_LOCK             BIT(15)
+#define PHY_28NM_HSIC_S2H_HSIC_EN              BIT(7)
+#define S2H_DRV_SE0_4RESUME                    BIT(14)
+#define PHY_28NM_HSIC_H2S_IMPCAL_DONE          BIT(27)
+
+#define PHY_28NM_HSIC_CONNECT_INT              BIT(1)
+#define PHY_28NM_HSIC_HS_READY_INT             BIT(2)
+
+struct mv_hsic_phy {
+       struct phy              *phy;
+       struct platform_device  *pdev;
+       void __iomem            *base;
+       struct clk              *clk;
+};
+
+static bool wait_for_reg(void __iomem *reg, u32 mask, unsigned long timeout)
+{
+       timeout += jiffies;
+       while (time_is_after_eq_jiffies(timeout)) {
+               if ((readl(reg) & mask) == mask)
+                       return true;
+               msleep(1);
+       }
+       return false;
+}
+
+static int mv_hsic_phy_init(struct phy *phy)
+{
+       struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
+       struct platform_device *pdev = mv_phy->pdev;
+       void __iomem *base = mv_phy->base;
+
+       clk_prepare_enable(mv_phy->clk);
+
+       /* Set reference clock */
+       writel(0x1 << PHY_28NM_HSIC_PLL_SELLPFR_SHIFT |
+               0xf0 << PHY_28NM_HSIC_PLL_FBDIV_SHIFT |
+               0xd << PHY_28NM_HSIC_PLL_REFDIV_SHIFT,
+               base + PHY_28NM_HSIC_PLL_CTRL01);
+
+       /* Turn on PLL */
+       writel(readl(base + PHY_28NM_HSIC_PLL_CTRL2) |
+               PHY_28NM_HSIC_S2H_PU_PLL,
+               base + PHY_28NM_HSIC_PLL_CTRL2);
+
+       /* Make sure PHY PLL is locked */
+       if (!wait_for_reg(base + PHY_28NM_HSIC_PLL_CTRL2,
+           PHY_28NM_HSIC_H2S_PLL_LOCK, HZ / 10)) {
+               dev_err(&pdev->dev, "HSIC PHY PLL not locked after 100mS.");
+               clk_disable_unprepare(mv_phy->clk);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int mv_hsic_phy_power_on(struct phy *phy)
+{
+       struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
+       struct platform_device *pdev = mv_phy->pdev;
+       void __iomem *base = mv_phy->base;
+       u32 reg;
+
+       reg = readl(base + PHY_28NM_HSIC_CTRL);
+       /* Avoid SE0 state when resume for some device will take it as reset */
+       reg &= ~S2H_DRV_SE0_4RESUME;
+       reg |= PHY_28NM_HSIC_S2H_HSIC_EN;       /* Enable HSIC PHY */
+       writel(reg, base + PHY_28NM_HSIC_CTRL);
+
+       /*
+        *  Calibration Timing
+        *                 ____________________________
+        *  CAL START   ___|
+        *                         ____________________
+        *  CAL_DONE    ___________|
+        *                 | 400us |
+        */
+
+       /* Make sure PHY Calibration is ready */
+       if (!wait_for_reg(base + PHY_28NM_HSIC_IMPCAL_CAL,
+           PHY_28NM_HSIC_H2S_IMPCAL_DONE, HZ / 10)) {
+               dev_warn(&pdev->dev, "HSIC PHY READY not set after 100mS.");
+               return -ETIMEDOUT;
+       }
+
+       /* Waiting for HSIC connect int*/
+       if (!wait_for_reg(base + PHY_28NM_HSIC_INT,
+           PHY_28NM_HSIC_CONNECT_INT, HZ / 5)) {
+               dev_warn(&pdev->dev, "HSIC wait for connect interrupt timeout.");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int mv_hsic_phy_power_off(struct phy *phy)
+{
+       struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
+       void __iomem *base = mv_phy->base;
+
+       writel(readl(base + PHY_28NM_HSIC_CTRL) & ~PHY_28NM_HSIC_S2H_HSIC_EN,
+               base + PHY_28NM_HSIC_CTRL);
+
+       return 0;
+}
+
+static int mv_hsic_phy_exit(struct phy *phy)
+{
+       struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
+       void __iomem *base = mv_phy->base;
+
+       /* Turn off PLL */
+       writel(readl(base + PHY_28NM_HSIC_PLL_CTRL2) &
+               ~PHY_28NM_HSIC_S2H_PU_PLL,
+               base + PHY_28NM_HSIC_PLL_CTRL2);
+
+       clk_disable_unprepare(mv_phy->clk);
+       return 0;
+}
+
+
+static const struct phy_ops hsic_ops = {
+       .init           = mv_hsic_phy_init,
+       .power_on       = mv_hsic_phy_power_on,
+       .power_off      = mv_hsic_phy_power_off,
+       .exit           = mv_hsic_phy_exit,
+       .owner          = THIS_MODULE,
+};
+
+static int mv_hsic_phy_probe(struct platform_device *pdev)
+{
+       struct phy_provider *phy_provider;
+       struct mv_hsic_phy *mv_phy;
+       struct resource *r;
+
+       mv_phy = devm_kzalloc(&pdev->dev, sizeof(*mv_phy), GFP_KERNEL);
+       if (!mv_phy)
+               return -ENOMEM;
+
+       mv_phy->pdev = pdev;
+
+       mv_phy->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(mv_phy->clk)) {
+               dev_err(&pdev->dev, "failed to get clock.\n");
+               return PTR_ERR(mv_phy->clk);
+       }
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       mv_phy->base = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(mv_phy->base))
+               return PTR_ERR(mv_phy->base);
+
+       mv_phy->phy = devm_phy_create(&pdev->dev, pdev->dev.of_node, &hsic_ops);
+       if (IS_ERR(mv_phy->phy))
+               return PTR_ERR(mv_phy->phy);
+
+       phy_set_drvdata(mv_phy->phy, mv_phy);
+
+       phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id mv_hsic_phy_dt_match[] = {
+       { .compatible = "marvell,pxa1928-hsic-phy", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, mv_hsic_phy_dt_match);
+
+static struct platform_driver mv_hsic_phy_driver = {
+       .probe  = mv_hsic_phy_probe,
+       .driver = {
+               .name   = "mv-hsic-phy",
+               .of_match_table = of_match_ptr(mv_hsic_phy_dt_match),
+       },
+};
+module_platform_driver(mv_hsic_phy_driver);
+
+MODULE_AUTHOR("Rob Herring <robh@kernel.org>");
+MODULE_DESCRIPTION("Marvell HSIC phy driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/marvell/phy-pxa-28nm-usb2.c b/drivers/phy/marvell/phy-pxa-28nm-usb2.c
new file mode 100644 (file)
index 0000000..37e9c8c
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2015 Linaro, Ltd.
+ * Rob Herring <robh@kernel.org>
+ *
+ * Based on vendor driver:
+ * Copyright (C) 2013 Marvell Inc.
+ * Author: Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+/* USB PXA1928 PHY mapping */
+#define PHY_28NM_PLL_REG0                      0x0
+#define PHY_28NM_PLL_REG1                      0x4
+#define PHY_28NM_CAL_REG                       0x8
+#define PHY_28NM_TX_REG0                       0x0c
+#define PHY_28NM_TX_REG1                       0x10
+#define PHY_28NM_RX_REG0                       0x14
+#define PHY_28NM_RX_REG1                       0x18
+#define PHY_28NM_DIG_REG0                      0x1c
+#define PHY_28NM_DIG_REG1                      0x20
+#define PHY_28NM_TEST_REG0                     0x24
+#define PHY_28NM_TEST_REG1                     0x28
+#define PHY_28NM_MOC_REG                       0x2c
+#define PHY_28NM_PHY_RESERVE                   0x30
+#define PHY_28NM_OTG_REG                       0x34
+#define PHY_28NM_CHRG_DET                      0x38
+#define PHY_28NM_CTRL_REG0                     0xc4
+#define PHY_28NM_CTRL_REG1                     0xc8
+#define PHY_28NM_CTRL_REG2                     0xd4
+#define PHY_28NM_CTRL_REG3                     0xdc
+
+/* PHY_28NM_PLL_REG0 */
+#define PHY_28NM_PLL_READY                     BIT(31)
+
+#define PHY_28NM_PLL_SELLPFR_SHIFT             28
+#define PHY_28NM_PLL_SELLPFR_MASK              (0x3 << 28)
+
+#define PHY_28NM_PLL_FBDIV_SHIFT               16
+#define PHY_28NM_PLL_FBDIV_MASK                        (0x1ff << 16)
+
+#define PHY_28NM_PLL_ICP_SHIFT                 8
+#define PHY_28NM_PLL_ICP_MASK                  (0x7 << 8)
+
+#define PHY_28NM_PLL_REFDIV_SHIFT              0
+#define PHY_28NM_PLL_REFDIV_MASK               0x7f
+
+/* PHY_28NM_PLL_REG1 */
+#define PHY_28NM_PLL_PU_BY_REG                 BIT(1)
+
+#define PHY_28NM_PLL_PU_PLL                    BIT(0)
+
+/* PHY_28NM_CAL_REG */
+#define PHY_28NM_PLL_PLLCAL_DONE               BIT(31)
+
+#define PHY_28NM_PLL_IMPCAL_DONE               BIT(23)
+
+#define PHY_28NM_PLL_KVCO_SHIFT                        16
+#define PHY_28NM_PLL_KVCO_MASK                 (0x7 << 16)
+
+#define PHY_28NM_PLL_CAL12_SHIFT               20
+#define PHY_28NM_PLL_CAL12_MASK                        (0x3 << 20)
+
+#define PHY_28NM_IMPCAL_VTH_SHIFT              8
+#define PHY_28NM_IMPCAL_VTH_MASK               (0x7 << 8)
+
+#define PHY_28NM_PLLCAL_START_SHIFT            22
+#define PHY_28NM_IMPCAL_START_SHIFT            13
+
+/* PHY_28NM_TX_REG0 */
+#define PHY_28NM_TX_PU_BY_REG                  BIT(25)
+
+#define PHY_28NM_TX_PU_ANA                     BIT(24)
+
+#define PHY_28NM_TX_AMP_SHIFT                  20
+#define PHY_28NM_TX_AMP_MASK                   (0x7 << 20)
+
+/* PHY_28NM_RX_REG0 */
+#define PHY_28NM_RX_SQ_THRESH_SHIFT            0
+#define PHY_28NM_RX_SQ_THRESH_MASK             (0xf << 0)
+
+/* PHY_28NM_RX_REG1 */
+#define PHY_28NM_RX_SQCAL_DONE                 BIT(31)
+
+/* PHY_28NM_DIG_REG0 */
+#define PHY_28NM_DIG_BITSTAFFING_ERR           BIT(31)
+#define PHY_28NM_DIG_SYNC_ERR                  BIT(30)
+
+#define PHY_28NM_DIG_SQ_FILT_SHIFT             16
+#define PHY_28NM_DIG_SQ_FILT_MASK              (0x7 << 16)
+
+#define PHY_28NM_DIG_SQ_BLK_SHIFT              12
+#define PHY_28NM_DIG_SQ_BLK_MASK               (0x7 << 12)
+
+#define PHY_28NM_DIG_SYNC_NUM_SHIFT            0
+#define PHY_28NM_DIG_SYNC_NUM_MASK             (0x3 << 0)
+
+#define PHY_28NM_PLL_LOCK_BYPASS               BIT(7)
+
+/* PHY_28NM_OTG_REG */
+#define PHY_28NM_OTG_CONTROL_BY_PIN            BIT(5)
+#define PHY_28NM_OTG_PU_OTG                    BIT(4)
+
+#define PHY_28NM_CHGDTC_ENABLE_SWITCH_DM_SHIFT_28 13
+#define PHY_28NM_CHGDTC_ENABLE_SWITCH_DP_SHIFT_28 12
+#define PHY_28NM_CHGDTC_VSRC_CHARGE_SHIFT_28   10
+#define PHY_28NM_CHGDTC_VDAT_CHARGE_SHIFT_28   8
+#define PHY_28NM_CHGDTC_CDP_DM_AUTO_SWITCH_SHIFT_28 7
+#define PHY_28NM_CHGDTC_DP_DM_SWAP_SHIFT_28    6
+#define PHY_28NM_CHGDTC_PU_CHRG_DTC_SHIFT_28   5
+#define PHY_28NM_CHGDTC_PD_EN_SHIFT_28         4
+#define PHY_28NM_CHGDTC_DCP_EN_SHIFT_28                3
+#define PHY_28NM_CHGDTC_CDP_EN_SHIFT_28                2
+#define PHY_28NM_CHGDTC_TESTMON_CHRGDTC_SHIFT_28 0
+
+#define PHY_28NM_CTRL1_CHRG_DTC_OUT_SHIFT_28   4
+#define PHY_28NM_CTRL1_VBUSDTC_OUT_SHIFT_28    2
+
+#define PHY_28NM_CTRL3_OVERWRITE               BIT(0)
+#define PHY_28NM_CTRL3_VBUS_VALID              BIT(4)
+#define PHY_28NM_CTRL3_AVALID                  BIT(5)
+#define PHY_28NM_CTRL3_BVALID                  BIT(6)
+
+struct mv_usb2_phy {
+       struct phy              *phy;
+       struct platform_device  *pdev;
+       void __iomem            *base;
+       struct clk              *clk;
+};
+
+static bool wait_for_reg(void __iomem *reg, u32 mask, unsigned long timeout)
+{
+       timeout += jiffies;
+       while (time_is_after_eq_jiffies(timeout)) {
+               if ((readl(reg) & mask) == mask)
+                       return true;
+               msleep(1);
+       }
+       return false;
+}
+
+static int mv_usb2_phy_28nm_init(struct phy *phy)
+{
+       struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
+       struct platform_device *pdev = mv_phy->pdev;
+       void __iomem *base = mv_phy->base;
+       u32 reg;
+       int ret;
+
+       clk_prepare_enable(mv_phy->clk);
+
+       /* PHY_28NM_PLL_REG0 */
+       reg = readl(base + PHY_28NM_PLL_REG0) &
+               ~(PHY_28NM_PLL_SELLPFR_MASK | PHY_28NM_PLL_FBDIV_MASK
+               | PHY_28NM_PLL_ICP_MASK | PHY_28NM_PLL_REFDIV_MASK);
+       writel(reg | (0x1 << PHY_28NM_PLL_SELLPFR_SHIFT
+               | 0xf0 << PHY_28NM_PLL_FBDIV_SHIFT
+               | 0x3 << PHY_28NM_PLL_ICP_SHIFT
+               | 0xd << PHY_28NM_PLL_REFDIV_SHIFT),
+               base + PHY_28NM_PLL_REG0);
+
+       /* PHY_28NM_PLL_REG1 */
+       reg = readl(base + PHY_28NM_PLL_REG1);
+       writel(reg | PHY_28NM_PLL_PU_PLL | PHY_28NM_PLL_PU_BY_REG,
+               base + PHY_28NM_PLL_REG1);
+
+       /* PHY_28NM_TX_REG0 */
+       reg = readl(base + PHY_28NM_TX_REG0) & ~PHY_28NM_TX_AMP_MASK;
+       writel(reg | PHY_28NM_TX_PU_BY_REG | 0x3 << PHY_28NM_TX_AMP_SHIFT |
+               PHY_28NM_TX_PU_ANA,
+               base + PHY_28NM_TX_REG0);
+
+       /* PHY_28NM_RX_REG0 */
+       reg = readl(base + PHY_28NM_RX_REG0) & ~PHY_28NM_RX_SQ_THRESH_MASK;
+       writel(reg | 0xa << PHY_28NM_RX_SQ_THRESH_SHIFT,
+               base + PHY_28NM_RX_REG0);
+
+       /* PHY_28NM_DIG_REG0 */
+       reg = readl(base + PHY_28NM_DIG_REG0) &
+               ~(PHY_28NM_DIG_BITSTAFFING_ERR | PHY_28NM_DIG_SYNC_ERR |
+               PHY_28NM_DIG_SQ_FILT_MASK | PHY_28NM_DIG_SQ_BLK_MASK |
+               PHY_28NM_DIG_SYNC_NUM_MASK);
+       writel(reg | (0x1 << PHY_28NM_DIG_SYNC_NUM_SHIFT |
+               PHY_28NM_PLL_LOCK_BYPASS),
+               base + PHY_28NM_DIG_REG0);
+
+       /* PHY_28NM_OTG_REG */
+       reg = readl(base + PHY_28NM_OTG_REG) | PHY_28NM_OTG_PU_OTG;
+       writel(reg & ~PHY_28NM_OTG_CONTROL_BY_PIN, base + PHY_28NM_OTG_REG);
+
+       /*
+        *  Calibration Timing
+        *                 ____________________________
+        *  CAL START   ___|
+        *                         ____________________
+        *  CAL_DONE    ___________|
+        *                 | 400us |
+        */
+
+       /* Make sure PHY Calibration is ready */
+       if (!wait_for_reg(base + PHY_28NM_CAL_REG,
+           PHY_28NM_PLL_PLLCAL_DONE | PHY_28NM_PLL_IMPCAL_DONE,
+           HZ / 10)) {
+               dev_warn(&pdev->dev, "USB PHY PLL calibrate not done after 100mS.");
+               ret = -ETIMEDOUT;
+               goto err_clk;
+       }
+       if (!wait_for_reg(base + PHY_28NM_RX_REG1,
+           PHY_28NM_RX_SQCAL_DONE, HZ / 10)) {
+               dev_warn(&pdev->dev, "USB PHY RX SQ calibrate not done after 100mS.");
+               ret = -ETIMEDOUT;
+               goto err_clk;
+       }
+       /* Make sure PHY PLL is ready */
+       if (!wait_for_reg(base + PHY_28NM_PLL_REG0,
+           PHY_28NM_PLL_READY, HZ / 10)) {
+               dev_warn(&pdev->dev, "PLL_READY not set after 100mS.");
+               ret = -ETIMEDOUT;
+               goto err_clk;
+       }
+
+       return 0;
+err_clk:
+       clk_disable_unprepare(mv_phy->clk);
+       return ret;
+}
+
+static int mv_usb2_phy_28nm_power_on(struct phy *phy)
+{
+       struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
+       void __iomem *base = mv_phy->base;
+
+       writel(readl(base + PHY_28NM_CTRL_REG3) |
+               (PHY_28NM_CTRL3_OVERWRITE | PHY_28NM_CTRL3_VBUS_VALID |
+               PHY_28NM_CTRL3_AVALID | PHY_28NM_CTRL3_BVALID),
+               base + PHY_28NM_CTRL_REG3);
+
+       return 0;
+}
+
+static int mv_usb2_phy_28nm_power_off(struct phy *phy)
+{
+       struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
+       void __iomem *base = mv_phy->base;
+
+       writel(readl(base + PHY_28NM_CTRL_REG3) |
+               ~(PHY_28NM_CTRL3_OVERWRITE | PHY_28NM_CTRL3_VBUS_VALID
+               | PHY_28NM_CTRL3_AVALID | PHY_28NM_CTRL3_BVALID),
+               base + PHY_28NM_CTRL_REG3);
+
+       return 0;
+}
+
+static int mv_usb2_phy_28nm_exit(struct phy *phy)
+{
+       struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
+       void __iomem *base = mv_phy->base;
+       unsigned int val;
+
+       val = readw(base + PHY_28NM_PLL_REG1);
+       val &= ~PHY_28NM_PLL_PU_PLL;
+       writew(val, base + PHY_28NM_PLL_REG1);
+
+       /* power down PHY Analog part */
+       val = readw(base + PHY_28NM_TX_REG0);
+       val &= ~PHY_28NM_TX_PU_ANA;
+       writew(val, base + PHY_28NM_TX_REG0);
+
+       /* power down PHY OTG part */
+       val = readw(base + PHY_28NM_OTG_REG);
+       val &= ~PHY_28NM_OTG_PU_OTG;
+       writew(val, base + PHY_28NM_OTG_REG);
+
+       clk_disable_unprepare(mv_phy->clk);
+       return 0;
+}
+
+static const struct phy_ops usb_ops = {
+       .init           = mv_usb2_phy_28nm_init,
+       .power_on       = mv_usb2_phy_28nm_power_on,
+       .power_off      = mv_usb2_phy_28nm_power_off,
+       .exit           = mv_usb2_phy_28nm_exit,
+       .owner          = THIS_MODULE,
+};
+
+static int mv_usb2_phy_probe(struct platform_device *pdev)
+{
+       struct phy_provider *phy_provider;
+       struct mv_usb2_phy *mv_phy;
+       struct resource *r;
+
+       mv_phy = devm_kzalloc(&pdev->dev, sizeof(*mv_phy), GFP_KERNEL);
+       if (!mv_phy)
+               return -ENOMEM;
+
+       mv_phy->pdev = pdev;
+
+       mv_phy->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(mv_phy->clk)) {
+               dev_err(&pdev->dev, "failed to get clock.\n");
+               return PTR_ERR(mv_phy->clk);
+       }
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       mv_phy->base = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(mv_phy->base))
+               return PTR_ERR(mv_phy->base);
+
+       mv_phy->phy = devm_phy_create(&pdev->dev, pdev->dev.of_node, &usb_ops);
+       if (IS_ERR(mv_phy->phy))
+               return PTR_ERR(mv_phy->phy);
+
+       phy_set_drvdata(mv_phy->phy, mv_phy);
+
+       phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id mv_usbphy_dt_match[] = {
+       { .compatible = "marvell,pxa1928-usb-phy", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, mv_usbphy_dt_match);
+
+static struct platform_driver mv_usb2_phy_driver = {
+       .probe  = mv_usb2_phy_probe,
+       .driver = {
+               .name   = "mv-usb2-phy",
+               .of_match_table = of_match_ptr(mv_usbphy_dt_match),
+       },
+};
+module_platform_driver(mv_usb2_phy_driver);
+
+MODULE_AUTHOR("Rob Herring <robh@kernel.org>");
+MODULE_DESCRIPTION("Marvell USB2 phy driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-armada375-usb2.c b/drivers/phy/phy-armada375-usb2.c
deleted file mode 100644 (file)
index 1a3db28..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * USB cluster support for Armada 375 platform.
- *
- * Copyright (C) 2014 Marvell
- *
- * Gregory CLEMENT <gregory.clement@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2 or later. This program is licensed "as is"
- * without any warranty of any kind, whether express or implied.
- *
- * Armada 375 comes with an USB2 host and device controller and an
- * USB3 controller. The USB cluster control register allows to manage
- * common features of both USB controllers.
- */
-
-#include <dt-bindings/phy/phy.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-
-#define USB2_PHY_CONFIG_DISABLE BIT(0)
-
-struct armada375_cluster_phy {
-       struct phy *phy;
-       void __iomem *reg;
-       bool use_usb3;
-       int phy_provided;
-};
-
-static int armada375_usb_phy_init(struct phy *phy)
-{
-       struct armada375_cluster_phy *cluster_phy;
-       u32 reg;
-
-       cluster_phy = phy_get_drvdata(phy);
-       if (!cluster_phy)
-               return -ENODEV;
-
-       reg = readl(cluster_phy->reg);
-       if (cluster_phy->use_usb3)
-               reg |= USB2_PHY_CONFIG_DISABLE;
-       else
-               reg &= ~USB2_PHY_CONFIG_DISABLE;
-       writel(reg, cluster_phy->reg);
-
-       return 0;
-}
-
-static const struct phy_ops armada375_usb_phy_ops = {
-       .init = armada375_usb_phy_init,
-       .owner = THIS_MODULE,
-};
-
-/*
- * Only one controller can use this PHY. We shouldn't have the case
- * when two controllers want to use this PHY. But if this case occurs
- * then we provide a phy to the first one and return an error for the
- * next one. This error has also to be an error returned by
- * devm_phy_optional_get() so different from ENODEV for USB2. In the
- * USB3 case it still optional and we use ENODEV.
- */
-static struct phy *armada375_usb_phy_xlate(struct device *dev,
-                                       struct of_phandle_args *args)
-{
-       struct armada375_cluster_phy *cluster_phy = dev_get_drvdata(dev);
-
-       if (!cluster_phy)
-               return  ERR_PTR(-ENODEV);
-
-       /*
-        * Either the phy had never been requested and then the first
-        * usb claiming it can get it, or it had already been
-        * requested in this case, we only allow to use it with the
-        * same configuration.
-        */
-       if (WARN_ON((cluster_phy->phy_provided != PHY_NONE) &&
-                       (cluster_phy->phy_provided != args->args[0]))) {
-               dev_err(dev, "This PHY has already been provided!\n");
-               dev_err(dev, "Check your device tree, only one controller can use it\n.");
-               if (args->args[0] == PHY_TYPE_USB2)
-                       return ERR_PTR(-EBUSY);
-               else
-                       return ERR_PTR(-ENODEV);
-       }
-
-       if (args->args[0] == PHY_TYPE_USB2)
-               cluster_phy->use_usb3 = false;
-       else if (args->args[0] == PHY_TYPE_USB3)
-               cluster_phy->use_usb3 = true;
-       else {
-               dev_err(dev, "Invalid PHY mode\n");
-               return ERR_PTR(-ENODEV);
-       }
-
-       /* Store which phy mode is used for next test */
-       cluster_phy->phy_provided = args->args[0];
-
-       return cluster_phy->phy;
-}
-
-static int armada375_usb_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct phy *phy;
-       struct phy_provider *phy_provider;
-       void __iomem *usb_cluster_base;
-       struct resource *res;
-       struct armada375_cluster_phy *cluster_phy;
-
-       cluster_phy = devm_kzalloc(dev, sizeof(*cluster_phy), GFP_KERNEL);
-       if (!cluster_phy)
-               return  -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       usb_cluster_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(usb_cluster_base))
-               return PTR_ERR(usb_cluster_base);
-
-       phy = devm_phy_create(dev, NULL, &armada375_usb_phy_ops);
-       if (IS_ERR(phy)) {
-               dev_err(dev, "failed to create PHY\n");
-               return PTR_ERR(phy);
-       }
-
-       cluster_phy->phy = phy;
-       cluster_phy->reg = usb_cluster_base;
-
-       dev_set_drvdata(dev, cluster_phy);
-       phy_set_drvdata(phy, cluster_phy);
-
-       phy_provider = devm_of_phy_provider_register(&pdev->dev,
-                                                    armada375_usb_phy_xlate);
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static const struct of_device_id of_usb_cluster_table[] = {
-       { .compatible = "marvell,armada-375-usb-cluster", },
-       { /* end of list */ },
-};
-MODULE_DEVICE_TABLE(of, of_usb_cluster_table);
-
-static struct platform_driver armada375_usb_phy_driver = {
-       .probe  = armada375_usb_phy_probe,
-       .driver = {
-               .of_match_table = of_usb_cluster_table,
-               .name  = "armada-375-usb-cluster",
-       }
-};
-module_platform_driver(armada375_usb_phy_driver);
-
-MODULE_DESCRIPTION("Armada 375 USB cluster driver");
-MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/phy/phy-bcm-cygnus-pcie.c b/drivers/phy/phy-bcm-cygnus-pcie.c
deleted file mode 100644 (file)
index 0f4ac5d..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2015 Broadcom Corporation
- *
- * 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/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-
-#define PCIE_CFG_OFFSET         0x00
-#define PCIE1_PHY_IDDQ_SHIFT    10
-#define PCIE0_PHY_IDDQ_SHIFT    2
-
-enum cygnus_pcie_phy_id {
-       CYGNUS_PHY_PCIE0 = 0,
-       CYGNUS_PHY_PCIE1,
-       MAX_NUM_PHYS,
-};
-
-struct cygnus_pcie_phy_core;
-
-/**
- * struct cygnus_pcie_phy - Cygnus PCIe PHY device
- * @core: pointer to the Cygnus PCIe PHY core control
- * @id: internal ID to identify the Cygnus PCIe PHY
- * @phy: pointer to the kernel PHY device
- */
-struct cygnus_pcie_phy {
-       struct cygnus_pcie_phy_core *core;
-       enum cygnus_pcie_phy_id id;
-       struct phy *phy;
-};
-
-/**
- * struct cygnus_pcie_phy_core - Cygnus PCIe PHY core control
- * @dev: pointer to device
- * @base: base register
- * @lock: mutex to protect access to individual PHYs
- * @phys: pointer to Cygnus PHY device
- */
-struct cygnus_pcie_phy_core {
-       struct device *dev;
-       void __iomem *base;
-       struct mutex lock;
-       struct cygnus_pcie_phy phys[MAX_NUM_PHYS];
-};
-
-static int cygnus_pcie_power_config(struct cygnus_pcie_phy *phy, bool enable)
-{
-       struct cygnus_pcie_phy_core *core = phy->core;
-       unsigned shift;
-       u32 val;
-
-       mutex_lock(&core->lock);
-
-       switch (phy->id) {
-       case CYGNUS_PHY_PCIE0:
-               shift = PCIE0_PHY_IDDQ_SHIFT;
-               break;
-
-       case CYGNUS_PHY_PCIE1:
-               shift = PCIE1_PHY_IDDQ_SHIFT;
-               break;
-
-       default:
-               mutex_unlock(&core->lock);
-               dev_err(core->dev, "PCIe PHY %d invalid\n", phy->id);
-               return -EINVAL;
-       }
-
-       if (enable) {
-               val = readl(core->base + PCIE_CFG_OFFSET);
-               val &= ~BIT(shift);
-               writel(val, core->base + PCIE_CFG_OFFSET);
-               /*
-                * Wait 50 ms for the PCIe Serdes to stabilize after the analog
-                * front end is brought up
-                */
-               msleep(50);
-       } else {
-               val = readl(core->base + PCIE_CFG_OFFSET);
-               val |= BIT(shift);
-               writel(val, core->base + PCIE_CFG_OFFSET);
-       }
-
-       mutex_unlock(&core->lock);
-       dev_dbg(core->dev, "PCIe PHY %d %s\n", phy->id,
-               enable ? "enabled" : "disabled");
-       return 0;
-}
-
-static int cygnus_pcie_phy_power_on(struct phy *p)
-{
-       struct cygnus_pcie_phy *phy = phy_get_drvdata(p);
-
-       return cygnus_pcie_power_config(phy, true);
-}
-
-static int cygnus_pcie_phy_power_off(struct phy *p)
-{
-       struct cygnus_pcie_phy *phy = phy_get_drvdata(p);
-
-       return cygnus_pcie_power_config(phy, false);
-}
-
-static const struct phy_ops cygnus_pcie_phy_ops = {
-       .power_on = cygnus_pcie_phy_power_on,
-       .power_off = cygnus_pcie_phy_power_off,
-       .owner = THIS_MODULE,
-};
-
-static int cygnus_pcie_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *node = dev->of_node, *child;
-       struct cygnus_pcie_phy_core *core;
-       struct phy_provider *provider;
-       struct resource *res;
-       unsigned cnt = 0;
-       int ret;
-
-       if (of_get_child_count(node) == 0) {
-               dev_err(dev, "PHY no child node\n");
-               return -ENODEV;
-       }
-
-       core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL);
-       if (!core)
-               return -ENOMEM;
-
-       core->dev = dev;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       core->base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(core->base))
-               return PTR_ERR(core->base);
-
-       mutex_init(&core->lock);
-
-       for_each_available_child_of_node(node, child) {
-               unsigned int id;
-               struct cygnus_pcie_phy *p;
-
-               if (of_property_read_u32(child, "reg", &id)) {
-                       dev_err(dev, "missing reg property for %s\n",
-                               child->name);
-                       ret = -EINVAL;
-                       goto put_child;
-               }
-
-               if (id >= MAX_NUM_PHYS) {
-                       dev_err(dev, "invalid PHY id: %u\n", id);
-                       ret = -EINVAL;
-                       goto put_child;
-               }
-
-               if (core->phys[id].phy) {
-                       dev_err(dev, "duplicated PHY id: %u\n", id);
-                       ret = -EINVAL;
-                       goto put_child;
-               }
-
-               p = &core->phys[id];
-               p->phy = devm_phy_create(dev, child, &cygnus_pcie_phy_ops);
-               if (IS_ERR(p->phy)) {
-                       dev_err(dev, "failed to create PHY\n");
-                       ret = PTR_ERR(p->phy);
-                       goto put_child;
-               }
-
-               p->core = core;
-               p->id = id;
-               phy_set_drvdata(p->phy, p);
-               cnt++;
-       }
-
-       dev_set_drvdata(dev, core);
-
-       provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (IS_ERR(provider)) {
-               dev_err(dev, "failed to register PHY provider\n");
-               return PTR_ERR(provider);
-       }
-
-       dev_dbg(dev, "registered %u PCIe PHY(s)\n", cnt);
-
-       return 0;
-put_child:
-       of_node_put(child);
-       return ret;
-}
-
-static const struct of_device_id cygnus_pcie_phy_match_table[] = {
-       { .compatible = "brcm,cygnus-pcie-phy" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, cygnus_pcie_phy_match_table);
-
-static struct platform_driver cygnus_pcie_phy_driver = {
-       .driver = {
-               .name = "cygnus-pcie-phy",
-               .of_match_table = cygnus_pcie_phy_match_table,
-       },
-       .probe = cygnus_pcie_phy_probe,
-};
-module_platform_driver(cygnus_pcie_phy_driver);
-
-MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom Cygnus PCIe PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c
deleted file mode 100644 (file)
index 7b67fe4..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * phy-bcm-kona-usb2.c - Broadcom Kona USB2 Phy Driver
- *
- * Copyright (C) 2013 Linaro Limited
- * Matt Porter <mporter@linaro.org>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#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/phy/phy.h>
-#include <linux/platform_device.h>
-
-#define OTGCTL                 (0)
-#define OTGCTL_OTGSTAT2                BIT(31)
-#define OTGCTL_OTGSTAT1                BIT(30)
-#define OTGCTL_PRST_N_SW       BIT(11)
-#define OTGCTL_HRESET_N                BIT(10)
-#define OTGCTL_UTMI_LINE_STATE1        BIT(9)
-#define OTGCTL_UTMI_LINE_STATE0        BIT(8)
-
-#define P1CTL                  (8)
-#define P1CTL_SOFT_RESET       BIT(1)
-#define P1CTL_NON_DRIVING      BIT(0)
-
-struct bcm_kona_usb {
-       void __iomem *regs;
-};
-
-static void bcm_kona_usb_phy_power(struct bcm_kona_usb *phy, int on)
-{
-       u32 val;
-
-       val = readl(phy->regs + OTGCTL);
-       if (on) {
-               /* Configure and power PHY */
-               val &= ~(OTGCTL_OTGSTAT2 | OTGCTL_OTGSTAT1 |
-                        OTGCTL_UTMI_LINE_STATE1 | OTGCTL_UTMI_LINE_STATE0);
-               val |= OTGCTL_PRST_N_SW | OTGCTL_HRESET_N;
-       } else {
-               val &= ~(OTGCTL_PRST_N_SW | OTGCTL_HRESET_N);
-       }
-       writel(val, phy->regs + OTGCTL);
-}
-
-static int bcm_kona_usb_phy_init(struct phy *gphy)
-{
-       struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
-       u32 val;
-
-       /* Soft reset PHY */
-       val = readl(phy->regs + P1CTL);
-       val &= ~P1CTL_NON_DRIVING;
-       val |= P1CTL_SOFT_RESET;
-       writel(val, phy->regs + P1CTL);
-       writel(val & ~P1CTL_SOFT_RESET, phy->regs + P1CTL);
-       /* Reset needs to be asserted for 2ms */
-       mdelay(2);
-       writel(val | P1CTL_SOFT_RESET, phy->regs + P1CTL);
-
-       return 0;
-}
-
-static int bcm_kona_usb_phy_power_on(struct phy *gphy)
-{
-       struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
-
-       bcm_kona_usb_phy_power(phy, 1);
-
-       return 0;
-}
-
-static int bcm_kona_usb_phy_power_off(struct phy *gphy)
-{
-       struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
-
-       bcm_kona_usb_phy_power(phy, 0);
-
-       return 0;
-}
-
-static const struct phy_ops ops = {
-       .init           = bcm_kona_usb_phy_init,
-       .power_on       = bcm_kona_usb_phy_power_on,
-       .power_off      = bcm_kona_usb_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static int bcm_kona_usb2_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct bcm_kona_usb *phy;
-       struct resource *res;
-       struct phy *gphy;
-       struct phy_provider *phy_provider;
-
-       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
-       if (!phy)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       phy->regs = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(phy->regs))
-               return PTR_ERR(phy->regs);
-
-       platform_set_drvdata(pdev, phy);
-
-       gphy = devm_phy_create(dev, NULL, &ops);
-       if (IS_ERR(gphy))
-               return PTR_ERR(gphy);
-
-       /* The Kona PHY supports an 8-bit wide UTMI interface */
-       phy_set_bus_width(gphy, 8);
-
-       phy_set_drvdata(gphy, phy);
-
-       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 bcm_kona_usb2_dt_ids[] = {
-       { .compatible = "brcm,kona-usb2-phy" },
-       { /* sentinel */ }
-};
-
-MODULE_DEVICE_TABLE(of, bcm_kona_usb2_dt_ids);
-
-static struct platform_driver bcm_kona_usb2_driver = {
-       .probe          = bcm_kona_usb2_probe,
-       .driver         = {
-               .name   = "bcm-kona-usb2",
-               .of_match_table = bcm_kona_usb2_dt_ids,
-       },
-};
-
-module_platform_driver(bcm_kona_usb2_driver);
-
-MODULE_ALIAS("platform:bcm-kona-usb2");
-MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
-MODULE_DESCRIPTION("BCM Kona USB 2.0 PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-bcm-ns-usb2.c b/drivers/phy/phy-bcm-ns-usb2.c
deleted file mode 100644 (file)
index 58dff80..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Broadcom Northstar USB 2.0 PHY Driver
- *
- * Copyright (C) 2016 RafaÅ‚ MiÅ‚ecki <zajec5@gmail.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.
- *
- */
-
-#include <linux/bcma/bcma.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-struct bcm_ns_usb2 {
-       struct device *dev;
-       struct clk *ref_clk;
-       struct phy *phy;
-       void __iomem *dmu;
-};
-
-static int bcm_ns_usb2_phy_init(struct phy *phy)
-{
-       struct bcm_ns_usb2 *usb2 = phy_get_drvdata(phy);
-       struct device *dev = usb2->dev;
-       void __iomem *dmu = usb2->dmu;
-       u32 ref_clk_rate, usb2ctl, usb_pll_ndiv, usb_pll_pdiv;
-       int err = 0;
-
-       err = clk_prepare_enable(usb2->ref_clk);
-       if (err < 0) {
-               dev_err(dev, "Failed to prepare ref clock: %d\n", err);
-               goto err_out;
-       }
-
-       ref_clk_rate = clk_get_rate(usb2->ref_clk);
-       if (!ref_clk_rate) {
-               dev_err(dev, "Failed to get ref clock rate\n");
-               err = -EINVAL;
-               goto err_clk_off;
-       }
-
-       usb2ctl = readl(dmu + BCMA_DMU_CRU_USB2_CONTROL);
-
-       if (usb2ctl & BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK) {
-               usb_pll_pdiv = usb2ctl;
-               usb_pll_pdiv &= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK;
-               usb_pll_pdiv >>= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_SHIFT;
-       } else {
-               usb_pll_pdiv = 1 << 3;
-       }
-
-       /* Calculate ndiv based on a solid 1920 MHz that is for USB2 PHY */
-       usb_pll_ndiv = (1920000000 * usb_pll_pdiv) / ref_clk_rate;
-
-       /* Unlock DMU PLL settings with some magic value */
-       writel(0x0000ea68, dmu + BCMA_DMU_CRU_CLKSET_KEY);
-
-       /* Write USB 2.0 PLL control setting */
-       usb2ctl &= ~BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK;
-       usb2ctl |= usb_pll_ndiv << BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT;
-       writel(usb2ctl, dmu + BCMA_DMU_CRU_USB2_CONTROL);
-
-       /* Lock DMU PLL settings */
-       writel(0x00000000, dmu + BCMA_DMU_CRU_CLKSET_KEY);
-
-err_clk_off:
-       clk_disable_unprepare(usb2->ref_clk);
-err_out:
-       return err;
-}
-
-static const struct phy_ops ops = {
-       .init           = bcm_ns_usb2_phy_init,
-       .owner          = THIS_MODULE,
-};
-
-static int bcm_ns_usb2_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct bcm_ns_usb2 *usb2;
-       struct resource *res;
-       struct phy_provider *phy_provider;
-
-       usb2 = devm_kzalloc(&pdev->dev, sizeof(*usb2), GFP_KERNEL);
-       if (!usb2)
-               return -ENOMEM;
-       usb2->dev = dev;
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmu");
-       usb2->dmu = devm_ioremap_resource(dev, res);
-       if (IS_ERR(usb2->dmu)) {
-               dev_err(dev, "Failed to map DMU regs\n");
-               return PTR_ERR(usb2->dmu);
-       }
-
-       usb2->ref_clk = devm_clk_get(dev, "phy-ref-clk");
-       if (IS_ERR(usb2->ref_clk)) {
-               dev_err(dev, "Clock not defined\n");
-               return PTR_ERR(usb2->ref_clk);
-       }
-
-       usb2->phy = devm_phy_create(dev, NULL, &ops);
-       if (IS_ERR(usb2->phy))
-               return PTR_ERR(usb2->phy);
-
-       phy_set_drvdata(usb2->phy, usb2);
-       platform_set_drvdata(pdev, usb2);
-
-       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 bcm_ns_usb2_id_table[] = {
-       { .compatible = "brcm,ns-usb2-phy", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, bcm_ns_usb2_id_table);
-
-static struct platform_driver bcm_ns_usb2_driver = {
-       .probe          = bcm_ns_usb2_probe,
-       .driver = {
-               .name = "bcm_ns_usb2",
-               .of_match_table = bcm_ns_usb2_id_table,
-       },
-};
-module_platform_driver(bcm_ns_usb2_driver);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-bcm-ns-usb3.c b/drivers/phy/phy-bcm-ns-usb3.c
deleted file mode 100644 (file)
index 22b5e70..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Broadcom Northstar USB 3.0 PHY Driver
- *
- * Copyright (C) 2016 RafaÅ‚ MiÅ‚ecki <rafal@milecki.pl>
- * Copyright (C) 2016 Broadcom
- *
- * All magic values used for initialization (and related comments) were obtained
- * from Broadcom's SDK:
- * Copyright (c) Broadcom Corp, 2012
- *
- * 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/bcma/bcma.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/phy/phy.h>
-#include <linux/slab.h>
-
-#define BCM_NS_USB3_MII_MNG_TIMEOUT_US 1000    /* usecs */
-
-#define BCM_NS_USB3_PHY_BASE_ADDR_REG  0x1f
-#define BCM_NS_USB3_PHY_PLL30_BLOCK    0x8000
-#define BCM_NS_USB3_PHY_TX_PMD_BLOCK   0x8040
-#define BCM_NS_USB3_PHY_PIPE_BLOCK     0x8060
-
-/* Registers of PLL30 block */
-#define BCM_NS_USB3_PLL_CONTROL                0x01
-#define BCM_NS_USB3_PLLA_CONTROL0      0x0a
-#define BCM_NS_USB3_PLLA_CONTROL1      0x0b
-
-/* Registers of TX PMD block */
-#define BCM_NS_USB3_TX_PMD_CONTROL1    0x01
-
-/* Registers of PIPE block */
-#define BCM_NS_USB3_LFPS_CMP           0x02
-#define BCM_NS_USB3_LFPS_DEGLITCH      0x03
-
-enum bcm_ns_family {
-       BCM_NS_UNKNOWN,
-       BCM_NS_AX,
-       BCM_NS_BX,
-};
-
-struct bcm_ns_usb3 {
-       struct device *dev;
-       enum bcm_ns_family family;
-       void __iomem *dmp;
-       void __iomem *ccb_mii;
-       struct phy *phy;
-};
-
-static const struct of_device_id bcm_ns_usb3_id_table[] = {
-       {
-               .compatible = "brcm,ns-ax-usb3-phy",
-               .data = (int *)BCM_NS_AX,
-       },
-       {
-               .compatible = "brcm,ns-bx-usb3-phy",
-               .data = (int *)BCM_NS_BX,
-       },
-       {},
-};
-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,
-                                     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;
-}
-
-static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
-{
-       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 */
-       err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
-                                        BCM_NS_USB3_PHY_PLL30_BLOCK);
-       if (err < 0)
-               return err;
-
-       /* Assert Ana_Pllseq start */
-       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x1000);
-
-       /* Assert CML Divider ratio to 26 */
-       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400);
-
-       /* Asserting PLL Reset */
-       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0xc000);
-
-       /* Deaaserting PLL Reset */
-       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 */
-       writel(0, usb3->dmp + BCMA_RESET_CTL);
-
-       /* PLL frequency monitor enable */
-       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x9000);
-
-       /* PIPE Block */
-       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
-                                  BCM_NS_USB3_PHY_PIPE_BLOCK);
-
-       /* CMPMAX & CMPMINTH setting */
-       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_CMP, 0xf30d);
-
-       /* DEGLITCH MIN & MAX setting */
-       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_DEGLITCH, 0x6302);
-
-       /* TXPMD block */
-       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
-                                  BCM_NS_USB3_PHY_TX_PMD_BLOCK);
-
-       /* Enabling SSC */
-       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;
-}
-
-static int bcm_ns_usb3_phy_init_ns_ax(struct bcm_ns_usb3 *usb3)
-{
-       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 */
-       err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
-                                        BCM_NS_USB3_PHY_PLL30_BLOCK);
-       if (err < 0)
-               return err;
-
-       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400);
-
-       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG, 0x80e0);
-
-       bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x009c);
-
-       /* Enable SSC */
-       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
-                                  BCM_NS_USB3_PHY_TX_PMD_BLOCK);
-
-       bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x21d3);
-
-       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 */
-       writel(0, usb3->dmp + BCMA_RESET_CTL);
-
-       return 0;
-}
-
-static int bcm_ns_usb3_phy_init(struct phy *phy)
-{
-       struct bcm_ns_usb3 *usb3 = phy_get_drvdata(phy);
-       int err;
-
-       /* Perform USB3 system soft reset */
-       writel(BCMA_RESET_CTL_RESET, usb3->dmp + BCMA_RESET_CTL);
-
-       switch (usb3->family) {
-       case BCM_NS_AX:
-               err = bcm_ns_usb3_phy_init_ns_ax(usb3);
-               break;
-       case BCM_NS_BX:
-               err = bcm_ns_usb3_phy_init_ns_bx(usb3);
-               break;
-       default:
-               WARN_ON(1);
-               err = -ENOTSUPP;
-       }
-
-       return err;
-}
-
-static const struct phy_ops ops = {
-       .init           = bcm_ns_usb3_phy_init,
-       .owner          = THIS_MODULE,
-};
-
-static int bcm_ns_usb3_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       const struct of_device_id *of_id;
-       struct bcm_ns_usb3 *usb3;
-       struct resource *res;
-       struct phy_provider *phy_provider;
-
-       usb3 = devm_kzalloc(dev, sizeof(*usb3), GFP_KERNEL);
-       if (!usb3)
-               return -ENOMEM;
-
-       usb3->dev = dev;
-
-       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;
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmp");
-       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);
-       }
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ccb-mii");
-       usb3->ccb_mii = devm_ioremap_resource(dev, res);
-       if (IS_ERR(usb3->ccb_mii)) {
-               dev_err(dev, "Failed to map ChipCommon B MII regs\n");
-               return PTR_ERR(usb3->ccb_mii);
-       }
-
-       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);
-       platform_set_drvdata(pdev, usb3);
-
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (!IS_ERR(phy_provider))
-               dev_info(dev, "Registered Broadcom Northstar USB 3.0 PHY driver\n");
-
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static struct platform_driver bcm_ns_usb3_driver = {
-       .probe          = bcm_ns_usb3_probe,
-       .driver = {
-               .name = "bcm_ns_usb3",
-               .of_match_table = bcm_ns_usb3_id_table,
-       },
-};
-module_platform_driver(bcm_ns_usb3_driver);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-bcm-ns2-pcie.c b/drivers/phy/phy-bcm-ns2-pcie.c
deleted file mode 100644 (file)
index 4c7d11d..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2016 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/device.h>
-#include <linux/module.h>
-#include <linux/of_mdio.h>
-#include <linux/mdio.h>
-#include <linux/phy.h>
-#include <linux/phy/phy.h>
-
-#define BLK_ADDR_REG_OFFSET    0x1f
-#define PLL_AFE1_100MHZ_BLK    0x2100
-#define PLL_CLK_AMP_OFFSET     0x03
-#define PLL_CLK_AMP_2P05V      0x2b18
-
-static int ns2_pci_phy_init(struct phy *p)
-{
-       struct mdio_device *mdiodev = phy_get_drvdata(p);
-       int rc;
-
-       /* select the AFE 100MHz block page */
-       rc = mdiobus_write(mdiodev->bus, mdiodev->addr,
-                          BLK_ADDR_REG_OFFSET, PLL_AFE1_100MHZ_BLK);
-       if (rc)
-               goto err;
-
-       /* set the 100 MHz reference clock amplitude to 2.05 v */
-       rc = mdiobus_write(mdiodev->bus, mdiodev->addr,
-                          PLL_CLK_AMP_OFFSET, PLL_CLK_AMP_2P05V);
-       if (rc)
-               goto err;
-
-       return 0;
-
-err:
-       dev_err(&mdiodev->dev, "Error %d writing to phy\n", rc);
-       return rc;
-}
-
-static const struct phy_ops ns2_pci_phy_ops = {
-       .init = ns2_pci_phy_init,
-       .owner = THIS_MODULE,
-};
-
-static int ns2_pci_phy_probe(struct mdio_device *mdiodev)
-{
-       struct device *dev = &mdiodev->dev;
-       struct phy_provider *provider;
-       struct phy *phy;
-
-       phy = devm_phy_create(dev, dev->of_node, &ns2_pci_phy_ops);
-       if (IS_ERR(phy)) {
-               dev_err(dev, "failed to create Phy\n");
-               return PTR_ERR(phy);
-       }
-
-       phy_set_drvdata(phy, mdiodev);
-
-       provider = devm_of_phy_provider_register(&phy->dev,
-                                                of_phy_simple_xlate);
-       if (IS_ERR(provider)) {
-               dev_err(dev, "failed to register Phy provider\n");
-               return PTR_ERR(provider);
-       }
-
-       dev_info(dev, "%s PHY registered\n", dev_name(dev));
-
-       return 0;
-}
-
-static const struct of_device_id ns2_pci_phy_of_match[] = {
-       { .compatible = "brcm,ns2-pcie-phy", },
-       { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, ns2_pci_phy_of_match);
-
-static struct mdio_driver ns2_pci_phy_driver = {
-       .mdiodrv = {
-               .driver = {
-                       .name = "phy-bcm-ns2-pci",
-                       .of_match_table = ns2_pci_phy_of_match,
-               },
-       },
-       .probe = ns2_pci_phy_probe,
-};
-mdio_module_driver(ns2_pci_phy_driver);
-
-MODULE_AUTHOR("Broadcom");
-MODULE_DESCRIPTION("Broadcom Northstar2 PCI Phy driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:phy-bcm-ns2-pci");
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
deleted file mode 100644 (file)
index 2c7a57f..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Marvell Berlin SATA PHY driver
- *
- * Copyright (C) 2014 Marvell Technology Group Ltd.
- *
- * Antoine Ténart <antoine.tenart@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/phy/phy.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-
-#define HOST_VSA_ADDR          0x0
-#define HOST_VSA_DATA          0x4
-#define PORT_SCR_CTL           0x2c
-#define PORT_VSR_ADDR          0x78
-#define PORT_VSR_DATA          0x7c
-
-#define CONTROL_REGISTER       0x0
-#define MBUS_SIZE_CONTROL      0x4
-
-#define POWER_DOWN_PHY0                        BIT(6)
-#define POWER_DOWN_PHY1                        BIT(14)
-#define MBUS_WRITE_REQUEST_SIZE_128    (BIT(2) << 16)
-#define MBUS_READ_REQUEST_SIZE_128     (BIT(2) << 19)
-
-#define BG2_PHY_BASE           0x080
-#define BG2Q_PHY_BASE          0x200
-
-/* register 0x01 */
-#define REF_FREF_SEL_25                BIT(0)
-#define PHY_MODE_SATA          (0x0 << 5)
-
-/* register 0x02 */
-#define USE_MAX_PLL_RATE       BIT(12)
-
-/* register 0x23 */
-#define DATA_BIT_WIDTH_10      (0x0 << 10)
-#define DATA_BIT_WIDTH_20      (0x1 << 10)
-#define DATA_BIT_WIDTH_40      (0x2 << 10)
-
-/* register 0x25 */
-#define PHY_GEN_MAX_1_5                (0x0 << 10)
-#define PHY_GEN_MAX_3_0                (0x1 << 10)
-#define PHY_GEN_MAX_6_0                (0x2 << 10)
-
-struct phy_berlin_desc {
-       struct phy      *phy;
-       u32             power_bit;
-       unsigned        index;
-};
-
-struct phy_berlin_priv {
-       void __iomem            *base;
-       spinlock_t              lock;
-       struct clk              *clk;
-       struct phy_berlin_desc  **phys;
-       unsigned                nphys;
-       u32                     phy_base;
-};
-
-static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg,
-                              u32 phy_base, u32 reg, u32 mask, u32 val)
-{
-       u32 regval;
-
-       /* select register */
-       writel(phy_base + reg, ctrl_reg + PORT_VSR_ADDR);
-
-       /* set bits */
-       regval = readl(ctrl_reg + PORT_VSR_DATA);
-       regval &= ~mask;
-       regval |= val;
-       writel(regval, ctrl_reg + PORT_VSR_DATA);
-}
-
-static int phy_berlin_sata_power_on(struct phy *phy)
-{
-       struct phy_berlin_desc *desc = phy_get_drvdata(phy);
-       struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
-       void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
-       u32 regval;
-
-       clk_prepare_enable(priv->clk);
-
-       spin_lock(&priv->lock);
-
-       /* Power on PHY */
-       writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
-       regval = readl(priv->base + HOST_VSA_DATA);
-       regval &= ~desc->power_bit;
-       writel(regval, priv->base + HOST_VSA_DATA);
-
-       /* Configure MBus */
-       writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
-       regval = readl(priv->base + HOST_VSA_DATA);
-       regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
-       writel(regval, priv->base + HOST_VSA_DATA);
-
-       /* set PHY mode and ref freq to 25 MHz */
-       phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01,
-                                   0x00ff, REF_FREF_SEL_25 | PHY_MODE_SATA);
-
-       /* set PHY up to 6 Gbps */
-       phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25,
-                                   0x0c00, PHY_GEN_MAX_6_0);
-
-       /* set 40 bits width */
-       phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x23,
-                                   0x0c00, DATA_BIT_WIDTH_40);
-
-       /* use max pll rate */
-       phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x02,
-                                   0x0000, USE_MAX_PLL_RATE);
-
-       /* set Gen3 controller speed */
-       regval = readl(ctrl_reg + PORT_SCR_CTL);
-       regval &= ~GENMASK(7, 4);
-       regval |= 0x30;
-       writel(regval, ctrl_reg + PORT_SCR_CTL);
-
-       spin_unlock(&priv->lock);
-
-       clk_disable_unprepare(priv->clk);
-
-       return 0;
-}
-
-static int phy_berlin_sata_power_off(struct phy *phy)
-{
-       struct phy_berlin_desc *desc = phy_get_drvdata(phy);
-       struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
-       u32 regval;
-
-       clk_prepare_enable(priv->clk);
-
-       spin_lock(&priv->lock);
-
-       /* Power down PHY */
-       writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
-       regval = readl(priv->base + HOST_VSA_DATA);
-       regval |= desc->power_bit;
-       writel(regval, priv->base + HOST_VSA_DATA);
-
-       spin_unlock(&priv->lock);
-
-       clk_disable_unprepare(priv->clk);
-
-       return 0;
-}
-
-static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
-                                            struct of_phandle_args *args)
-{
-       struct phy_berlin_priv *priv = dev_get_drvdata(dev);
-       int i;
-
-       if (WARN_ON(args->args[0] >= priv->nphys))
-               return ERR_PTR(-ENODEV);
-
-       for (i = 0; i < priv->nphys; i++) {
-               if (priv->phys[i]->index == args->args[0])
-                       break;
-       }
-
-       if (i == priv->nphys)
-               return ERR_PTR(-ENODEV);
-
-       return priv->phys[i]->phy;
-}
-
-static const struct phy_ops phy_berlin_sata_ops = {
-       .power_on       = phy_berlin_sata_power_on,
-       .power_off      = phy_berlin_sata_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static u32 phy_berlin_power_down_bits[] = {
-       POWER_DOWN_PHY0,
-       POWER_DOWN_PHY1,
-};
-
-static int phy_berlin_sata_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *child;
-       struct phy *phy;
-       struct phy_provider *phy_provider;
-       struct phy_berlin_priv *priv;
-       struct resource *res;
-       int ret, i = 0;
-       u32 phy_id;
-
-       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -EINVAL;
-
-       priv->base = devm_ioremap(dev, res->start, resource_size(res));
-       if (!priv->base)
-               return -ENOMEM;
-
-       priv->clk = devm_clk_get(dev, NULL);
-       if (IS_ERR(priv->clk))
-               return PTR_ERR(priv->clk);
-
-       priv->nphys = of_get_child_count(dev->of_node);
-       if (priv->nphys == 0)
-               return -ENODEV;
-
-       priv->phys = devm_kcalloc(dev, priv->nphys, sizeof(*priv->phys),
-                                 GFP_KERNEL);
-       if (!priv->phys)
-               return -ENOMEM;
-
-       if (of_device_is_compatible(dev->of_node, "marvell,berlin2-sata-phy"))
-               priv->phy_base = BG2_PHY_BASE;
-       else
-               priv->phy_base = BG2Q_PHY_BASE;
-
-       dev_set_drvdata(dev, priv);
-       spin_lock_init(&priv->lock);
-
-       for_each_available_child_of_node(dev->of_node, child) {
-               struct phy_berlin_desc *phy_desc;
-
-               if (of_property_read_u32(child, "reg", &phy_id)) {
-                       dev_err(dev, "missing reg property in node %s\n",
-                               child->name);
-                       ret = -EINVAL;
-                       goto put_child;
-               }
-
-               if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
-                       dev_err(dev, "invalid reg in node %s\n", child->name);
-                       ret = -EINVAL;
-                       goto put_child;
-               }
-
-               phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
-               if (!phy_desc) {
-                       ret = -ENOMEM;
-                       goto put_child;
-               }
-
-               phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops);
-               if (IS_ERR(phy)) {
-                       dev_err(dev, "failed to create PHY %d\n", phy_id);
-                       ret = PTR_ERR(phy);
-                       goto put_child;
-               }
-
-               phy_desc->phy = phy;
-               phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
-               phy_desc->index = phy_id;
-               phy_set_drvdata(phy, phy_desc);
-
-               priv->phys[i++] = phy_desc;
-
-               /* Make sure the PHY is off */
-               phy_berlin_sata_power_off(phy);
-       }
-
-       phy_provider =
-               devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
-       return PTR_ERR_OR_ZERO(phy_provider);
-put_child:
-       of_node_put(child);
-       return ret;
-}
-
-static const struct of_device_id phy_berlin_sata_of_match[] = {
-       { .compatible = "marvell,berlin2-sata-phy" },
-       { .compatible = "marvell,berlin2q-sata-phy" },
-       { },
-};
-MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
-
-static struct platform_driver phy_berlin_sata_driver = {
-       .probe  = phy_berlin_sata_probe,
-       .driver = {
-               .name           = "phy-berlin-sata",
-               .of_match_table = phy_berlin_sata_of_match,
-       },
-};
-module_platform_driver(phy_berlin_sata_driver);
-
-MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
-MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c
deleted file mode 100644 (file)
index 2017751..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2014 Marvell Technology Group Ltd.
- *
- * Antoine Tenart <antoine.tenart@free-electrons.com>
- * Jisheng Zhang <jszhang@marvell.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/reset.h>
-
-#define USB_PHY_PLL            0x04
-#define USB_PHY_PLL_CONTROL    0x08
-#define USB_PHY_TX_CTRL0       0x10
-#define USB_PHY_TX_CTRL1       0x14
-#define USB_PHY_TX_CTRL2       0x18
-#define USB_PHY_RX_CTRL                0x20
-#define USB_PHY_ANALOG         0x34
-
-/* USB_PHY_PLL */
-#define CLK_REF_DIV(x)         ((x) << 4)
-#define FEEDBACK_CLK_DIV(x)    ((x) << 8)
-
-/* USB_PHY_PLL_CONTROL */
-#define CLK_STABLE             BIT(0)
-#define PLL_CTRL_PIN           BIT(1)
-#define PLL_CTRL_REG           BIT(2)
-#define PLL_ON                 BIT(3)
-#define PHASE_OFF_TOL_125      (0x0 << 5)
-#define PHASE_OFF_TOL_250      BIT(5)
-#define KVC0_CALIB             (0x0 << 9)
-#define KVC0_REG_CTRL          BIT(9)
-#define KVC0_HIGH              (0x0 << 10)
-#define KVC0_LOW               (0x3 << 10)
-#define CLK_BLK_EN             BIT(13)
-
-/* USB_PHY_TX_CTRL0 */
-#define EXT_HS_RCAL_EN         BIT(3)
-#define EXT_FS_RCAL_EN         BIT(4)
-#define IMPCAL_VTH_DIV(x)      ((x) << 5)
-#define EXT_RS_RCAL_DIV(x)     ((x) << 8)
-#define EXT_FS_RCAL_DIV(x)     ((x) << 12)
-
-/* USB_PHY_TX_CTRL1 */
-#define TX_VDD15_14            (0x0 << 4)
-#define TX_VDD15_15            BIT(4)
-#define TX_VDD15_16            (0x2 << 4)
-#define TX_VDD15_17            (0x3 << 4)
-#define TX_VDD12_VDD           (0x0 << 6)
-#define TX_VDD12_11            BIT(6)
-#define TX_VDD12_12            (0x2 << 6)
-#define TX_VDD12_13            (0x3 << 6)
-#define LOW_VDD_EN             BIT(8)
-#define TX_OUT_AMP(x)          ((x) << 9)
-
-/* USB_PHY_TX_CTRL2 */
-#define TX_CHAN_CTRL_REG(x)    ((x) << 0)
-#define DRV_SLEWRATE(x)                ((x) << 4)
-#define IMP_CAL_FS_HS_DLY_0    (0x0 << 6)
-#define IMP_CAL_FS_HS_DLY_1    BIT(6)
-#define IMP_CAL_FS_HS_DLY_2    (0x2 << 6)
-#define IMP_CAL_FS_HS_DLY_3    (0x3 << 6)
-#define FS_DRV_EN_MASK(x)      ((x) << 8)
-#define HS_DRV_EN_MASK(x)      ((x) << 12)
-
-/* USB_PHY_RX_CTRL */
-#define PHASE_FREEZE_DLY_2_CL  (0x0 << 0)
-#define PHASE_FREEZE_DLY_4_CL  BIT(0)
-#define ACK_LENGTH_8_CL                (0x0 << 2)
-#define ACK_LENGTH_12_CL       BIT(2)
-#define ACK_LENGTH_16_CL       (0x2 << 2)
-#define ACK_LENGTH_20_CL       (0x3 << 2)
-#define SQ_LENGTH_3            (0x0 << 4)
-#define SQ_LENGTH_6            BIT(4)
-#define SQ_LENGTH_9            (0x2 << 4)
-#define SQ_LENGTH_12           (0x3 << 4)
-#define DISCON_THRESHOLD_260   (0x0 << 6)
-#define DISCON_THRESHOLD_270   BIT(6)
-#define DISCON_THRESHOLD_280   (0x2 << 6)
-#define DISCON_THRESHOLD_290   (0x3 << 6)
-#define SQ_THRESHOLD(x)                ((x) << 8)
-#define LPF_COEF(x)            ((x) << 12)
-#define INTPL_CUR_10           (0x0 << 14)
-#define INTPL_CUR_20           BIT(14)
-#define INTPL_CUR_30           (0x2 << 14)
-#define INTPL_CUR_40           (0x3 << 14)
-
-/* USB_PHY_ANALOG */
-#define ANA_PWR_UP             BIT(1)
-#define ANA_PWR_DOWN           BIT(2)
-#define V2I_VCO_RATIO(x)       ((x) << 7)
-#define R_ROTATE_90            (0x0 << 10)
-#define R_ROTATE_0             BIT(10)
-#define MODE_TEST_EN           BIT(11)
-#define ANA_TEST_DC_CTRL(x)    ((x) << 12)
-
-static const u32 phy_berlin_pll_dividers[] = {
-       /* Berlin 2 */
-       CLK_REF_DIV(0x6) | FEEDBACK_CLK_DIV(0x55),
-       /* Berlin 2CD/Q */
-       CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
-};
-
-struct phy_berlin_usb_priv {
-       void __iomem            *base;
-       struct reset_control    *rst_ctrl;
-       u32                     pll_divider;
-};
-
-static int phy_berlin_usb_power_on(struct phy *phy)
-{
-       struct phy_berlin_usb_priv *priv = phy_get_drvdata(phy);
-
-       reset_control_reset(priv->rst_ctrl);
-
-       writel(priv->pll_divider,
-              priv->base + USB_PHY_PLL);
-       writel(CLK_STABLE | PLL_CTRL_REG | PHASE_OFF_TOL_250 | KVC0_REG_CTRL |
-              CLK_BLK_EN, priv->base + USB_PHY_PLL_CONTROL);
-       writel(V2I_VCO_RATIO(0x5) | R_ROTATE_0 | ANA_TEST_DC_CTRL(0x5),
-              priv->base + USB_PHY_ANALOG);
-       writel(PHASE_FREEZE_DLY_4_CL | ACK_LENGTH_16_CL | SQ_LENGTH_12 |
-              DISCON_THRESHOLD_260 | SQ_THRESHOLD(0xa) | LPF_COEF(0x2) |
-              INTPL_CUR_30, priv->base + USB_PHY_RX_CTRL);
-
-       writel(TX_VDD12_13 | TX_OUT_AMP(0x3), priv->base + USB_PHY_TX_CTRL1);
-       writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
-              priv->base + USB_PHY_TX_CTRL0);
-
-       writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4) |
-              EXT_FS_RCAL_DIV(0x2), priv->base + USB_PHY_TX_CTRL0);
-
-       writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
-              priv->base + USB_PHY_TX_CTRL0);
-       writel(TX_CHAN_CTRL_REG(0xf) | DRV_SLEWRATE(0x3) | IMP_CAL_FS_HS_DLY_3 |
-              FS_DRV_EN_MASK(0xd), priv->base + USB_PHY_TX_CTRL2);
-
-       return 0;
-}
-
-static const struct phy_ops phy_berlin_usb_ops = {
-       .power_on       = phy_berlin_usb_power_on,
-       .owner          = THIS_MODULE,
-};
-
-static const struct of_device_id phy_berlin_usb_of_match[] = {
-       {
-               .compatible = "marvell,berlin2-usb-phy",
-               .data = &phy_berlin_pll_dividers[0],
-       },
-       {
-               .compatible = "marvell,berlin2cd-usb-phy",
-               .data = &phy_berlin_pll_dividers[1],
-       },
-       { },
-};
-MODULE_DEVICE_TABLE(of, phy_berlin_usb_of_match);
-
-static int phy_berlin_usb_probe(struct platform_device *pdev)
-{
-       const struct of_device_id *match =
-               of_match_device(phy_berlin_usb_of_match, &pdev->dev);
-       struct phy_berlin_usb_priv *priv;
-       struct resource *res;
-       struct phy *phy;
-       struct phy_provider *phy_provider;
-
-       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       priv->base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(priv->base))
-               return PTR_ERR(priv->base);
-
-       priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL);
-       if (IS_ERR(priv->rst_ctrl))
-               return PTR_ERR(priv->rst_ctrl);
-
-       priv->pll_divider = *((u32 *)match->data);
-
-       phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops);
-       if (IS_ERR(phy)) {
-               dev_err(&pdev->dev, "failed to create PHY\n");
-               return PTR_ERR(phy);
-       }
-
-       phy_set_drvdata(phy, priv);
-
-       phy_provider =
-               devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static struct platform_driver phy_berlin_usb_driver = {
-       .probe  = phy_berlin_usb_probe,
-       .driver = {
-               .name           = "phy-berlin-usb",
-               .of_match_table = phy_berlin_usb_of_match,
-       },
-};
-module_platform_driver(phy_berlin_usb_driver);
-
-MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
-MODULE_DESCRIPTION("Marvell Berlin PHY driver for USB");
-MODULE_LICENSE("GPL");
diff --git a/drivers/phy/phy-brcm-sata.c b/drivers/phy/phy-brcm-sata.c
deleted file mode 100644 (file)
index ccbc3d9..0000000
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Broadcom SATA3 AHCI Controller PHY Driver
- *
- * Copyright (C) 2016 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; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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/device.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-
-#define SATA_PCB_BANK_OFFSET                           0x23c
-#define SATA_PCB_REG_OFFSET(ofs)                       ((ofs) * 4)
-
-#define MAX_PORTS                                      2
-
-/* Register offset between PHYs in PCB space */
-#define SATA_PCB_REG_28NM_SPACE_SIZE                   0x1000
-
-/* The older SATA PHY registers duplicated per port registers within the map,
- * rather than having a separate map per port.
- */
-#define SATA_PCB_REG_40NM_SPACE_SIZE                   0x10
-
-/* Register offset between PHYs in PHY control space */
-#define SATA_PHY_CTRL_REG_28NM_SPACE_SIZE              0x8
-
-enum brcm_sata_phy_version {
-       BRCM_SATA_PHY_STB_28NM,
-       BRCM_SATA_PHY_STB_40NM,
-       BRCM_SATA_PHY_IPROC_NS2,
-       BRCM_SATA_PHY_IPROC_NSP,
-};
-
-struct brcm_sata_port {
-       int portnum;
-       struct phy *phy;
-       struct brcm_sata_phy *phy_priv;
-       bool ssc_en;
-};
-
-struct brcm_sata_phy {
-       struct device *dev;
-       void __iomem *phy_base;
-       void __iomem *ctrl_base;
-       enum brcm_sata_phy_version version;
-
-       struct brcm_sata_port phys[MAX_PORTS];
-};
-
-enum sata_phy_regs {
-       BLOCK0_REG_BANK                         = 0x000,
-       BLOCK0_XGXSSTATUS                       = 0x81,
-       BLOCK0_XGXSSTATUS_PLL_LOCK              = BIT(12),
-       BLOCK0_SPARE                            = 0x8d,
-       BLOCK0_SPARE_OOB_CLK_SEL_MASK           = 0x3,
-       BLOCK0_SPARE_OOB_CLK_SEL_REFBY2         = 0x1,
-
-       PLL_REG_BANK_0                          = 0x050,
-       PLL_REG_BANK_0_PLLCONTROL_0             = 0x81,
-       PLLCONTROL_0_FREQ_DET_RESTART           = BIT(13),
-       PLLCONTROL_0_FREQ_MONITOR               = BIT(12),
-       PLLCONTROL_0_SEQ_START                  = BIT(15),
-       PLL_CAP_CONTROL                         = 0x85,
-       PLL_ACTRL2                              = 0x8b,
-       PLL_ACTRL2_SELDIV_MASK                  = 0x1f,
-       PLL_ACTRL2_SELDIV_SHIFT                 = 9,
-
-       PLL1_REG_BANK                           = 0x060,
-       PLL1_ACTRL2                             = 0x82,
-       PLL1_ACTRL3                             = 0x83,
-       PLL1_ACTRL4                             = 0x84,
-
-       OOB_REG_BANK                            = 0x150,
-       OOB1_REG_BANK                           = 0x160,
-       OOB_CTRL1                               = 0x80,
-       OOB_CTRL1_BURST_MAX_MASK                = 0xf,
-       OOB_CTRL1_BURST_MAX_SHIFT               = 12,
-       OOB_CTRL1_BURST_MIN_MASK                = 0xf,
-       OOB_CTRL1_BURST_MIN_SHIFT               = 8,
-       OOB_CTRL1_WAKE_IDLE_MAX_MASK            = 0xf,
-       OOB_CTRL1_WAKE_IDLE_MAX_SHIFT           = 4,
-       OOB_CTRL1_WAKE_IDLE_MIN_MASK            = 0xf,
-       OOB_CTRL1_WAKE_IDLE_MIN_SHIFT           = 0,
-       OOB_CTRL2                               = 0x81,
-       OOB_CTRL2_SEL_ENA_SHIFT                 = 15,
-       OOB_CTRL2_SEL_ENA_RC_SHIFT              = 14,
-       OOB_CTRL2_RESET_IDLE_MAX_MASK           = 0x3f,
-       OOB_CTRL2_RESET_IDLE_MAX_SHIFT          = 8,
-       OOB_CTRL2_BURST_CNT_MASK                = 0x3,
-       OOB_CTRL2_BURST_CNT_SHIFT               = 6,
-       OOB_CTRL2_RESET_IDLE_MIN_MASK           = 0x3f,
-       OOB_CTRL2_RESET_IDLE_MIN_SHIFT          = 0,
-
-       TXPMD_REG_BANK                          = 0x1a0,
-       TXPMD_CONTROL1                          = 0x81,
-       TXPMD_CONTROL1_TX_SSC_EN_FRC            = BIT(0),
-       TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL        = BIT(1),
-       TXPMD_TX_FREQ_CTRL_CONTROL1             = 0x82,
-       TXPMD_TX_FREQ_CTRL_CONTROL2             = 0x83,
-       TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK   = 0x3ff,
-       TXPMD_TX_FREQ_CTRL_CONTROL3             = 0x84,
-       TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK   = 0x3ff,
-};
-
-enum sata_phy_ctrl_regs {
-       PHY_CTRL_1                              = 0x0,
-       PHY_CTRL_1_RESET                        = BIT(0),
-};
-
-static inline void __iomem *brcm_sata_pcb_base(struct brcm_sata_port *port)
-{
-       struct brcm_sata_phy *priv = port->phy_priv;
-       u32 size = 0;
-
-       switch (priv->version) {
-       case BRCM_SATA_PHY_STB_28NM:
-       case BRCM_SATA_PHY_IPROC_NS2:
-               size = SATA_PCB_REG_28NM_SPACE_SIZE;
-               break;
-       case BRCM_SATA_PHY_STB_40NM:
-               size = SATA_PCB_REG_40NM_SPACE_SIZE;
-               break;
-       default:
-               dev_err(priv->dev, "invalid phy version\n");
-               break;
-       }
-
-       return priv->phy_base + (port->portnum * size);
-}
-
-static inline void __iomem *brcm_sata_ctrl_base(struct brcm_sata_port *port)
-{
-       struct brcm_sata_phy *priv = port->phy_priv;
-       u32 size = 0;
-
-       switch (priv->version) {
-       case BRCM_SATA_PHY_IPROC_NS2:
-               size = SATA_PHY_CTRL_REG_28NM_SPACE_SIZE;
-               break;
-       default:
-               dev_err(priv->dev, "invalid phy version\n");
-               break;
-       }
-
-       return priv->ctrl_base + (port->portnum * size);
-}
-
-static void brcm_sata_phy_wr(void __iomem *pcb_base, u32 bank,
-                            u32 ofs, u32 msk, u32 value)
-{
-       u32 tmp;
-
-       writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
-       tmp = readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
-       tmp = (tmp & msk) | value;
-       writel(tmp, pcb_base + SATA_PCB_REG_OFFSET(ofs));
-}
-
-static u32 brcm_sata_phy_rd(void __iomem *pcb_base, u32 bank, u32 ofs)
-{
-       writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
-       return readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
-}
-
-/* These defaults were characterized by H/W group */
-#define STB_FMIN_VAL_DEFAULT   0x3df
-#define STB_FMAX_VAL_DEFAULT   0x3df
-#define STB_FMAX_VAL_SSC       0x83
-
-static int brcm_stb_sata_init(struct brcm_sata_port *port)
-{
-       void __iomem *base = brcm_sata_pcb_base(port);
-       struct brcm_sata_phy *priv = port->phy_priv;
-       u32 tmp;
-
-       /* override the TX spread spectrum setting */
-       tmp = TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL | TXPMD_CONTROL1_TX_SSC_EN_FRC;
-       brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp);
-
-       /* set fixed min freq */
-       brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2,
-                        ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK,
-                        STB_FMIN_VAL_DEFAULT);
-
-       /* set fixed max freq depending on SSC config */
-       if (port->ssc_en) {
-               dev_info(priv->dev, "enabling SSC on port%d\n", port->portnum);
-               tmp = STB_FMAX_VAL_SSC;
-       } else {
-               tmp = STB_FMAX_VAL_DEFAULT;
-       }
-
-       brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3,
-                         ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp);
-
-       return 0;
-}
-
-/* NS2 SATA PLL1 defaults were characterized by H/W group */
-#define NS2_PLL1_ACTRL2_MAGIC  0x1df8
-#define NS2_PLL1_ACTRL3_MAGIC  0x2b00
-#define NS2_PLL1_ACTRL4_MAGIC  0x8824
-
-static int brcm_ns2_sata_init(struct brcm_sata_port *port)
-{
-       int try;
-       unsigned int val;
-       void __iomem *base = brcm_sata_pcb_base(port);
-       void __iomem *ctrl_base = brcm_sata_ctrl_base(port);
-       struct device *dev = port->phy_priv->dev;
-
-       /* Configure OOB control */
-       val = 0x0;
-       val |= (0xc << OOB_CTRL1_BURST_MAX_SHIFT);
-       val |= (0x4 << OOB_CTRL1_BURST_MIN_SHIFT);
-       val |= (0x9 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT);
-       val |= (0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT);
-       brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
-       val = 0x0;
-       val |= (0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT);
-       val |= (0x2 << OOB_CTRL2_BURST_CNT_SHIFT);
-       val |= (0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT);
-       brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
-
-       /* Configure PHY PLL register bank 1 */
-       val = NS2_PLL1_ACTRL2_MAGIC;
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
-       val = NS2_PLL1_ACTRL3_MAGIC;
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
-       val = NS2_PLL1_ACTRL4_MAGIC;
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
-
-       /* Configure PHY BLOCK0 register bank */
-       /* Set oob_clk_sel to refclk/2 */
-       brcm_sata_phy_wr(base, BLOCK0_REG_BANK, BLOCK0_SPARE,
-                        ~BLOCK0_SPARE_OOB_CLK_SEL_MASK,
-                        BLOCK0_SPARE_OOB_CLK_SEL_REFBY2);
-
-       /* Strobe PHY reset using PHY control register */
-       writel(PHY_CTRL_1_RESET, ctrl_base + PHY_CTRL_1);
-       mdelay(1);
-       writel(0x0, ctrl_base + PHY_CTRL_1);
-       mdelay(1);
-
-       /* Wait for PHY PLL lock by polling pll_lock bit */
-       try = 50;
-       while (try) {
-               val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
-                                       BLOCK0_XGXSSTATUS);
-               if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
-                       break;
-               msleep(20);
-               try--;
-       }
-       if (!try) {
-               /* PLL did not lock; give up */
-               dev_err(dev, "port%d PLL did not lock\n", port->portnum);
-               return -ETIMEDOUT;
-       }
-
-       dev_dbg(dev, "port%d initialized\n", port->portnum);
-
-       return 0;
-}
-
-static int brcm_nsp_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 oob_bank;
-       unsigned int val, try;
-
-       /* Configure OOB control */
-       if (port->portnum == 0)
-               oob_bank = OOB_REG_BANK;
-       else if (port->portnum == 1)
-               oob_bank = OOB1_REG_BANK;
-       else
-               return -EINVAL;
-
-       val = 0x0;
-       val |= (0x0f << OOB_CTRL1_BURST_MAX_SHIFT);
-       val |= (0x06 << OOB_CTRL1_BURST_MIN_SHIFT);
-       val |= (0x0f << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT);
-       val |= (0x06 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT);
-       brcm_sata_phy_wr(base, oob_bank, OOB_CTRL1, 0x0, val);
-
-       val = 0x0;
-       val |= (0x2e << OOB_CTRL2_RESET_IDLE_MAX_SHIFT);
-       val |= (0x02 << OOB_CTRL2_BURST_CNT_SHIFT);
-       val |= (0x16 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT);
-       brcm_sata_phy_wr(base, oob_bank, OOB_CTRL2, 0x0, val);
-
-
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_ACTRL2,
-               ~(PLL_ACTRL2_SELDIV_MASK << PLL_ACTRL2_SELDIV_SHIFT),
-               0x0c << PLL_ACTRL2_SELDIV_SHIFT);
-
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_CAP_CONTROL,
-                                               0xff0, 0x4f0);
-
-       val = PLLCONTROL_0_FREQ_DET_RESTART | PLLCONTROL_0_FREQ_MONITOR;
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
-                                                               ~val, val);
-       val = PLLCONTROL_0_SEQ_START;
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
-                                                               ~val, 0);
-       mdelay(10);
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
-                                                               ~val, val);
-
-       /* Wait for pll_seq_done bit */
-       try = 50;
-       while (try--) {
-               val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
-                                       BLOCK0_XGXSSTATUS);
-               if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
-                       break;
-               msleep(20);
-       }
-       if (!try) {
-               /* PLL did not lock; give up */
-               dev_err(dev, "port%d PLL did not lock\n", port->portnum);
-               return -ETIMEDOUT;
-       }
-
-       dev_dbg(dev, "port%d initialized\n", port->portnum);
-
-       return 0;
-}
-
-static int brcm_sata_phy_init(struct phy *phy)
-{
-       int rc;
-       struct brcm_sata_port *port = phy_get_drvdata(phy);
-
-       switch (port->phy_priv->version) {
-       case BRCM_SATA_PHY_STB_28NM:
-       case BRCM_SATA_PHY_STB_40NM:
-               rc = brcm_stb_sata_init(port);
-               break;
-       case BRCM_SATA_PHY_IPROC_NS2:
-               rc = brcm_ns2_sata_init(port);
-               break;
-       case BRCM_SATA_PHY_IPROC_NSP:
-               rc = brcm_nsp_sata_init(port);
-               break;
-       default:
-               rc = -ENODEV;
-       }
-
-       return rc;
-}
-
-static const struct phy_ops phy_ops = {
-       .init           = brcm_sata_phy_init,
-       .owner          = THIS_MODULE,
-};
-
-static const struct of_device_id brcm_sata_phy_of_match[] = {
-       { .compatible   = "brcm,bcm7445-sata-phy",
-         .data = (void *)BRCM_SATA_PHY_STB_28NM },
-       { .compatible   = "brcm,bcm7425-sata-phy",
-         .data = (void *)BRCM_SATA_PHY_STB_40NM },
-       { .compatible   = "brcm,iproc-ns2-sata-phy",
-         .data = (void *)BRCM_SATA_PHY_IPROC_NS2 },
-       { .compatible = "brcm,iproc-nsp-sata-phy",
-         .data = (void *)BRCM_SATA_PHY_IPROC_NSP },
-       {},
-};
-MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);
-
-static int brcm_sata_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *dn = dev->of_node, *child;
-       const struct of_device_id *of_id;
-       struct brcm_sata_phy *priv;
-       struct resource *res;
-       struct phy_provider *provider;
-       int ret, count = 0;
-
-       if (of_get_child_count(dn) == 0)
-               return -ENODEV;
-
-       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-       dev_set_drvdata(dev, priv);
-       priv->dev = dev;
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
-       priv->phy_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(priv->phy_base))
-               return PTR_ERR(priv->phy_base);
-
-       of_id = of_match_node(brcm_sata_phy_of_match, dn);
-       if (of_id)
-               priv->version = (enum brcm_sata_phy_version)of_id->data;
-       else
-               priv->version = BRCM_SATA_PHY_STB_28NM;
-
-       if (priv->version == BRCM_SATA_PHY_IPROC_NS2) {
-               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                                                  "phy-ctrl");
-               priv->ctrl_base = devm_ioremap_resource(dev, res);
-               if (IS_ERR(priv->ctrl_base))
-                       return PTR_ERR(priv->ctrl_base);
-       }
-
-       for_each_available_child_of_node(dn, child) {
-               unsigned int id;
-               struct brcm_sata_port *port;
-
-               if (of_property_read_u32(child, "reg", &id)) {
-                       dev_err(dev, "missing reg property in node %s\n",
-                                       child->name);
-                       ret = -EINVAL;
-                       goto put_child;
-               }
-
-               if (id >= MAX_PORTS) {
-                       dev_err(dev, "invalid reg: %u\n", id);
-                       ret = -EINVAL;
-                       goto put_child;
-               }
-               if (priv->phys[id].phy) {
-                       dev_err(dev, "already registered port %u\n", id);
-                       ret = -EINVAL;
-                       goto put_child;
-               }
-
-               port = &priv->phys[id];
-               port->portnum = id;
-               port->phy_priv = priv;
-               port->phy = devm_phy_create(dev, child, &phy_ops);
-               port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
-               if (IS_ERR(port->phy)) {
-                       dev_err(dev, "failed to create PHY\n");
-                       ret = PTR_ERR(port->phy);
-                       goto put_child;
-               }
-
-               phy_set_drvdata(port->phy, port);
-               count++;
-       }
-
-       provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (IS_ERR(provider)) {
-               dev_err(dev, "could not register PHY provider\n");
-               return PTR_ERR(provider);
-       }
-
-       dev_info(dev, "registered %d port(s)\n", count);
-
-       return 0;
-put_child:
-       of_node_put(child);
-       return ret;
-}
-
-static struct platform_driver brcm_sata_phy_driver = {
-       .probe  = brcm_sata_phy_probe,
-       .driver = {
-               .of_match_table = brcm_sata_phy_of_match,
-               .name           = "brcm-sata-phy",
-       }
-};
-module_platform_driver(brcm_sata_phy_driver);
-
-MODULE_DESCRIPTION("Broadcom SATA PHY driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marc Carino");
-MODULE_AUTHOR("Brian Norris");
-MODULE_ALIAS("platform:phy-brcm-sata");
diff --git a/drivers/phy/phy-da8xx-usb.c b/drivers/phy/phy-da8xx-usb.c
deleted file mode 100644 (file)
index 1b82bff..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * phy-da8xx-usb - TI DaVinci DA8xx USB PHY driver
- *
- * Copyright (C) 2016 David Lechner <david@lechnology.com>
- *
- * 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 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/mfd/da8xx-cfgchip.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#define PHY_INIT_BITS  (CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN)
-
-struct da8xx_usb_phy {
-       struct phy_provider     *phy_provider;
-       struct phy              *usb11_phy;
-       struct phy              *usb20_phy;
-       struct clk              *usb11_clk;
-       struct clk              *usb20_clk;
-       struct regmap           *regmap;
-};
-
-static int da8xx_usb11_phy_power_on(struct phy *phy)
-{
-       struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
-       int ret;
-
-       ret = clk_prepare_enable(d_phy->usb11_clk);
-       if (ret)
-               return ret;
-
-       regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM,
-                         CFGCHIP2_USB1SUSPENDM);
-
-       return 0;
-}
-
-static int da8xx_usb11_phy_power_off(struct phy *phy)
-{
-       struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
-
-       regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM, 0);
-
-       clk_disable_unprepare(d_phy->usb11_clk);
-
-       return 0;
-}
-
-static const struct phy_ops da8xx_usb11_phy_ops = {
-       .power_on       = da8xx_usb11_phy_power_on,
-       .power_off      = da8xx_usb11_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static int da8xx_usb20_phy_power_on(struct phy *phy)
-{
-       struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
-       int ret;
-
-       ret = clk_prepare_enable(d_phy->usb20_clk);
-       if (ret)
-               return ret;
-
-       regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGPWRDN, 0);
-
-       return 0;
-}
-
-static int da8xx_usb20_phy_power_off(struct phy *phy)
-{
-       struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
-
-       regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGPWRDN,
-                         CFGCHIP2_OTGPWRDN);
-
-       clk_disable_unprepare(d_phy->usb20_clk);
-
-       return 0;
-}
-
-static int da8xx_usb20_phy_set_mode(struct phy *phy, enum phy_mode mode)
-{
-       struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
-       u32 val;
-
-       switch (mode) {
-       case PHY_MODE_USB_HOST:         /* Force VBUS valid, ID = 0 */
-               val = CFGCHIP2_OTGMODE_FORCE_HOST;
-               break;
-       case PHY_MODE_USB_DEVICE:       /* Force VBUS valid, ID = 1 */
-               val = CFGCHIP2_OTGMODE_FORCE_DEVICE;
-               break;
-       case PHY_MODE_USB_OTG:  /* Don't override the VBUS/ID comparators */
-               val = CFGCHIP2_OTGMODE_NO_OVERRIDE;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGMODE_MASK,
-                         val);
-
-       return 0;
-}
-
-static const struct phy_ops da8xx_usb20_phy_ops = {
-       .power_on       = da8xx_usb20_phy_power_on,
-       .power_off      = da8xx_usb20_phy_power_off,
-       .set_mode       = da8xx_usb20_phy_set_mode,
-       .owner          = THIS_MODULE,
-};
-
-static struct phy *da8xx_usb_phy_of_xlate(struct device *dev,
-                                        struct of_phandle_args *args)
-{
-       struct da8xx_usb_phy *d_phy = dev_get_drvdata(dev);
-
-       if (!d_phy)
-               return ERR_PTR(-ENODEV);
-
-       switch (args->args[0]) {
-       case 0:
-               return d_phy->usb20_phy;
-       case 1:
-               return d_phy->usb11_phy;
-       default:
-               return ERR_PTR(-EINVAL);
-       }
-}
-
-static int da8xx_usb_phy_probe(struct platform_device *pdev)
-{
-       struct device           *dev = &pdev->dev;
-       struct device_node      *node = dev->of_node;
-       struct da8xx_usb_phy    *d_phy;
-
-       d_phy = devm_kzalloc(dev, sizeof(*d_phy), GFP_KERNEL);
-       if (!d_phy)
-               return -ENOMEM;
-
-       if (node)
-               d_phy->regmap = syscon_regmap_lookup_by_compatible(
-                                                       "ti,da830-cfgchip");
-       else
-               d_phy->regmap = syscon_regmap_lookup_by_pdevname("syscon");
-       if (IS_ERR(d_phy->regmap)) {
-               dev_err(dev, "Failed to get syscon\n");
-               return PTR_ERR(d_phy->regmap);
-       }
-
-       d_phy->usb11_clk = devm_clk_get(dev, "usb11_phy");
-       if (IS_ERR(d_phy->usb11_clk)) {
-               dev_err(dev, "Failed to get usb11_phy clock\n");
-               return PTR_ERR(d_phy->usb11_clk);
-       }
-
-       d_phy->usb20_clk = devm_clk_get(dev, "usb20_phy");
-       if (IS_ERR(d_phy->usb20_clk)) {
-               dev_err(dev, "Failed to get usb20_phy clock\n");
-               return PTR_ERR(d_phy->usb20_clk);
-       }
-
-       d_phy->usb11_phy = devm_phy_create(dev, node, &da8xx_usb11_phy_ops);
-       if (IS_ERR(d_phy->usb11_phy)) {
-               dev_err(dev, "Failed to create usb11 phy\n");
-               return PTR_ERR(d_phy->usb11_phy);
-       }
-
-       d_phy->usb20_phy = devm_phy_create(dev, node, &da8xx_usb20_phy_ops);
-       if (IS_ERR(d_phy->usb20_phy)) {
-               dev_err(dev, "Failed to create usb20 phy\n");
-               return PTR_ERR(d_phy->usb20_phy);
-       }
-
-       platform_set_drvdata(pdev, d_phy);
-       phy_set_drvdata(d_phy->usb11_phy, d_phy);
-       phy_set_drvdata(d_phy->usb20_phy, d_phy);
-
-       if (node) {
-               d_phy->phy_provider = devm_of_phy_provider_register(dev,
-                                                       da8xx_usb_phy_of_xlate);
-               if (IS_ERR(d_phy->phy_provider)) {
-                       dev_err(dev, "Failed to create phy provider\n");
-                       return PTR_ERR(d_phy->phy_provider);
-               }
-       } else {
-               int ret;
-
-               ret = phy_create_lookup(d_phy->usb11_phy, "usb-phy",
-                                       "ohci-da8xx");
-               if (ret)
-                       dev_warn(dev, "Failed to create usb11 phy lookup\n");
-               ret = phy_create_lookup(d_phy->usb20_phy, "usb-phy",
-                                       "musb-da8xx");
-               if (ret)
-                       dev_warn(dev, "Failed to create usb20 phy lookup\n");
-       }
-
-       regmap_write_bits(d_phy->regmap, CFGCHIP(2),
-                         PHY_INIT_BITS, PHY_INIT_BITS);
-
-       return 0;
-}
-
-static int da8xx_usb_phy_remove(struct platform_device *pdev)
-{
-       struct da8xx_usb_phy *d_phy = platform_get_drvdata(pdev);
-
-       if (!pdev->dev.of_node) {
-               phy_remove_lookup(d_phy->usb20_phy, "usb-phy", "musb-da8xx");
-               phy_remove_lookup(d_phy->usb11_phy, "usb-phy", "ohci-da8xx");
-       }
-
-       return 0;
-}
-
-static const struct of_device_id da8xx_usb_phy_ids[] = {
-       { .compatible = "ti,da830-usb-phy" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, da8xx_usb_phy_ids);
-
-static struct platform_driver da8xx_usb_phy_driver = {
-       .probe  = da8xx_usb_phy_probe,
-       .remove = da8xx_usb_phy_remove,
-       .driver = {
-               .name   = "da8xx-usb-phy",
-               .of_match_table = da8xx_usb_phy_ids,
-       },
-};
-
-module_platform_driver(da8xx_usb_phy_driver);
-
-MODULE_ALIAS("platform:da8xx-usb-phy");
-MODULE_AUTHOR("David Lechner <david@lechnology.com>");
-MODULE_DESCRIPTION("TI DA8xx USB PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-dm816x-usb.c b/drivers/phy/phy-dm816x-usb.c
deleted file mode 100644 (file)
index cbcce7c..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * 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/module.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/io.h>
-#include <linux/usb/phy_companion.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/pm_runtime.h>
-#include <linux/delay.h>
-#include <linux/phy/phy.h>
-#include <linux/of_platform.h>
-
-#include <linux/mfd/syscon.h>
-
-/*
- * TRM has two sets of USB_CTRL registers.. The correct register bits
- * are in TRM section 24.9.8.2 USB_CTRL Register. The TRM documents the
- * phy as being SR70LX Synopsys USB 2.0 OTG nanoPHY. It also seems at
- * least dm816x rev c ignores writes to USB_CTRL register, but the TI
- * kernel is writing to those so it's possible that later revisions
- * have worknig USB_CTRL register.
- *
- * Also note that At least USB_CTRL register seems to be dm816x specific
- * according to the TRM. It's possible that USBPHY_CTRL is more generic,
- * but that would have to be checked against the SR70LX documentation
- * which does not seem to be publicly available.
- *
- * Finally, the phy on dm814x and am335x is different from dm816x.
- */
-#define DM816X_USB_CTRL_PHYCLKSRC      BIT(8)  /* 1 = PLL ref clock */
-#define DM816X_USB_CTRL_PHYSLEEP1      BIT(1)  /* Enable the first phy */
-#define DM816X_USB_CTRL_PHYSLEEP0      BIT(0)  /* Enable the second phy */
-
-#define DM816X_USBPHY_CTRL_TXRISETUNE  1
-#define DM816X_USBPHY_CTRL_TXVREFTUNE  0xc
-#define DM816X_USBPHY_CTRL_TXPREEMTUNE 0x2
-
-struct dm816x_usb_phy {
-       struct regmap *syscon;
-       struct device *dev;
-       unsigned int instance;
-       struct clk *refclk;
-       struct usb_phy phy;
-       unsigned int usb_ctrl;          /* Shared between phy0 and phy1 */
-       unsigned int usbphy_ctrl;
-};
-
-static int dm816x_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 dm816x_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 int dm816x_usb_phy_init(struct phy *x)
-{
-       struct dm816x_usb_phy *phy = phy_get_drvdata(x);
-       unsigned int val;
-       int error;
-
-       if (clk_get_rate(phy->refclk) != 24000000)
-               dev_warn(phy->dev, "nonstandard phy refclk\n");
-
-       /* Set PLL ref clock and put phys to sleep */
-       error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
-                                  DM816X_USB_CTRL_PHYCLKSRC |
-                                  DM816X_USB_CTRL_PHYSLEEP1 |
-                                  DM816X_USB_CTRL_PHYSLEEP0,
-                                  0);
-       regmap_read(phy->syscon, phy->usb_ctrl, &val);
-       if ((val & 3) != 0)
-               dev_info(phy->dev,
-                        "Working dm816x USB_CTRL! (0x%08x)\n",
-                        val);
-
-       /*
-        * TI kernel sets these values for "symmetrical eye diagram and
-        * better signal quality" so let's assume somebody checked the
-        * values with a scope and set them here too.
-        */
-       regmap_read(phy->syscon, phy->usbphy_ctrl, &val);
-       val |= DM816X_USBPHY_CTRL_TXRISETUNE |
-               DM816X_USBPHY_CTRL_TXVREFTUNE |
-               DM816X_USBPHY_CTRL_TXPREEMTUNE;
-       regmap_write(phy->syscon, phy->usbphy_ctrl, val);
-
-       return 0;
-}
-
-static const struct phy_ops ops = {
-       .init           = dm816x_usb_phy_init,
-       .owner          = THIS_MODULE,
-};
-
-static int __maybe_unused dm816x_usb_phy_runtime_suspend(struct device *dev)
-{
-       struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
-       unsigned int mask, val;
-       int error = 0;
-
-       mask = BIT(phy->instance);
-       val = ~BIT(phy->instance);
-       error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
-                                  mask, val);
-       if (error)
-               dev_err(phy->dev, "phy%i failed to power off\n",
-                       phy->instance);
-       clk_disable(phy->refclk);
-
-       return 0;
-}
-
-static int __maybe_unused dm816x_usb_phy_runtime_resume(struct device *dev)
-{
-       struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
-       unsigned int mask, val;
-       int error;
-
-       error = clk_enable(phy->refclk);
-       if (error)
-               return error;
-
-       /*
-        * Note that at least dm816x rev c does not seem to do
-        * anything with the USB_CTRL register. But let's follow
-        * what the TI tree is doing in case later revisions use
-        * USB_CTRL.
-        */
-       mask = BIT(phy->instance);
-       val = BIT(phy->instance);
-       error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
-                                  mask, val);
-       if (error) {
-               dev_err(phy->dev, "phy%i failed to power on\n",
-                       phy->instance);
-               clk_disable(phy->refclk);
-               return error;
-       }
-
-       return 0;
-}
-
-static UNIVERSAL_DEV_PM_OPS(dm816x_usb_phy_pm_ops,
-                           dm816x_usb_phy_runtime_suspend,
-                           dm816x_usb_phy_runtime_resume,
-                           NULL);
-
-#ifdef CONFIG_OF
-static const struct of_device_id dm816x_usb_phy_id_table[] = {
-       {
-               .compatible = "ti,dm8168-usb-phy",
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, dm816x_usb_phy_id_table);
-#endif
-
-static int dm816x_usb_phy_probe(struct platform_device *pdev)
-{
-       struct dm816x_usb_phy *phy;
-       struct resource *res;
-       struct phy *generic_phy;
-       struct phy_provider *phy_provider;
-       struct usb_otg *otg;
-       const struct of_device_id *of_id;
-       const struct usb_phy_data *phy_data;
-       int error;
-
-       of_id = of_match_device(of_match_ptr(dm816x_usb_phy_id_table),
-                               &pdev->dev);
-       if (!of_id)
-               return -EINVAL;
-
-       phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
-       if (!phy)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENOENT;
-
-       phy->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
-                                                     "syscon");
-       if (IS_ERR(phy->syscon))
-               return PTR_ERR(phy->syscon);
-
-       /*
-        * According to sprs614e.pdf, the first usb_ctrl is shared and
-        * the second instance for usb_ctrl is reserved.. Also the
-        * register bits are different from earlier TRMs.
-        */
-       phy->usb_ctrl = 0x20;
-       phy->usbphy_ctrl = (res->start & 0xff) + 4;
-       if (phy->usbphy_ctrl == 0x2c)
-               phy->instance = 1;
-
-       phy_data = of_id->data;
-
-       otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
-       if (!otg)
-               return -ENOMEM;
-
-       phy->dev = &pdev->dev;
-       phy->phy.dev = phy->dev;
-       phy->phy.label = "dm8168_usb_phy";
-       phy->phy.otg = otg;
-       phy->phy.type = USB_PHY_TYPE_USB2;
-       otg->set_host = dm816x_usb_phy_set_host;
-       otg->set_peripheral = dm816x_usb_phy_set_peripheral;
-       otg->usb_phy = &phy->phy;
-
-       platform_set_drvdata(pdev, phy);
-
-       phy->refclk = devm_clk_get(phy->dev, "refclk");
-       if (IS_ERR(phy->refclk))
-               return PTR_ERR(phy->refclk);
-       error = clk_prepare(phy->refclk);
-       if (error)
-               return error;
-
-       pm_runtime_enable(phy->dev);
-       generic_phy = devm_phy_create(phy->dev, NULL, &ops);
-       if (IS_ERR(generic_phy))
-               return PTR_ERR(generic_phy);
-
-       phy_set_drvdata(generic_phy, phy);
-
-       phy_provider = devm_of_phy_provider_register(phy->dev,
-                                                    of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
-       usb_add_phy_dev(&phy->phy);
-
-       return 0;
-}
-
-static int dm816x_usb_phy_remove(struct platform_device *pdev)
-{
-       struct dm816x_usb_phy *phy = platform_get_drvdata(pdev);
-
-       usb_remove_phy(&phy->phy);
-       pm_runtime_disable(phy->dev);
-       clk_unprepare(phy->refclk);
-
-       return 0;
-}
-
-static struct platform_driver dm816x_usb_phy_driver = {
-       .probe          = dm816x_usb_phy_probe,
-       .remove         = dm816x_usb_phy_remove,
-       .driver         = {
-               .name   = "dm816x-usb-phy",
-               .pm     = &dm816x_usb_phy_pm_ops,
-               .of_match_table = of_match_ptr(dm816x_usb_phy_id_table),
-       },
-};
-
-module_platform_driver(dm816x_usb_phy_driver);
-
-MODULE_ALIAS("platform:dm816x_usb");
-MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
-MODULE_DESCRIPTION("dm816x usb phy driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c
deleted file mode 100644 (file)
index bb3279d..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Samsung EXYNOS SoC series Display Port PHY driver
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.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.
- */
-
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mfd/syscon.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/soc/samsung/exynos-regs-pmu.h>
-
-struct exynos_dp_video_phy_drvdata {
-       u32 phy_ctrl_offset;
-};
-
-struct exynos_dp_video_phy {
-       struct regmap *regs;
-       const struct exynos_dp_video_phy_drvdata *drvdata;
-};
-
-static int exynos_dp_video_phy_power_on(struct phy *phy)
-{
-       struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
-
-       /* Disable power isolation on DP-PHY */
-       return regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset,
-                                 EXYNOS4_PHY_ENABLE, EXYNOS4_PHY_ENABLE);
-}
-
-static int exynos_dp_video_phy_power_off(struct phy *phy)
-{
-       struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
-
-       /* Enable power isolation on DP-PHY */
-       return regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset,
-                                 EXYNOS4_PHY_ENABLE, 0);
-}
-
-static const struct phy_ops exynos_dp_video_phy_ops = {
-       .power_on       = exynos_dp_video_phy_power_on,
-       .power_off      = exynos_dp_video_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static const struct exynos_dp_video_phy_drvdata exynos5250_dp_video_phy = {
-       .phy_ctrl_offset        = EXYNOS5_DPTX_PHY_CONTROL,
-};
-
-static const struct exynos_dp_video_phy_drvdata exynos5420_dp_video_phy = {
-       .phy_ctrl_offset        = EXYNOS5420_DPTX_PHY_CONTROL,
-};
-
-static const struct of_device_id exynos_dp_video_phy_of_match[] = {
-       {
-               .compatible = "samsung,exynos5250-dp-video-phy",
-               .data = &exynos5250_dp_video_phy,
-       }, {
-               .compatible = "samsung,exynos5420-dp-video-phy",
-               .data = &exynos5420_dp_video_phy,
-       },
-       { },
-};
-MODULE_DEVICE_TABLE(of, exynos_dp_video_phy_of_match);
-
-static int exynos_dp_video_phy_probe(struct platform_device *pdev)
-{
-       struct exynos_dp_video_phy *state;
-       struct device *dev = &pdev->dev;
-       const struct of_device_id *match;
-       struct phy_provider *phy_provider;
-       struct phy *phy;
-
-       state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
-       if (!state)
-               return -ENOMEM;
-
-       state->regs = syscon_regmap_lookup_by_phandle(dev->of_node,
-                                                     "samsung,pmu-syscon");
-       if (IS_ERR(state->regs)) {
-               dev_err(dev, "Failed to lookup PMU regmap\n");
-               return PTR_ERR(state->regs);
-       }
-
-       match = of_match_node(exynos_dp_video_phy_of_match, dev->of_node);
-       state->drvdata = match->data;
-
-       phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops);
-       if (IS_ERR(phy)) {
-               dev_err(dev, "failed to create Display Port PHY\n");
-               return PTR_ERR(phy);
-       }
-       phy_set_drvdata(phy, state);
-
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static struct platform_driver exynos_dp_video_phy_driver = {
-       .probe  = exynos_dp_video_phy_probe,
-       .driver = {
-               .name   = "exynos-dp-video-phy",
-               .of_match_table = exynos_dp_video_phy_of_match,
-       }
-};
-module_platform_driver(exynos_dp_video_phy_driver);
-
-MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
-MODULE_DESCRIPTION("Samsung EXYNOS SoC DP PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
deleted file mode 100644 (file)
index c198886..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
- *
- * Copyright (C) 2013,2016 Samsung Electronics Co., Ltd.
- * Author: Sylwester Nawrocki <s.nawrocki@samsung.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.
- */
-
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-#include <linux/spinlock.h>
-#include <linux/soc/samsung/exynos-regs-pmu.h>
-#include <linux/mfd/syscon.h>
-
-enum exynos_mipi_phy_id {
-       EXYNOS_MIPI_PHY_ID_NONE = -1,
-       EXYNOS_MIPI_PHY_ID_CSIS0,
-       EXYNOS_MIPI_PHY_ID_DSIM0,
-       EXYNOS_MIPI_PHY_ID_CSIS1,
-       EXYNOS_MIPI_PHY_ID_DSIM1,
-       EXYNOS_MIPI_PHY_ID_CSIS2,
-       EXYNOS_MIPI_PHYS_NUM
-};
-
-enum exynos_mipi_phy_regmap_id {
-       EXYNOS_MIPI_REGMAP_PMU,
-       EXYNOS_MIPI_REGMAP_DISP,
-       EXYNOS_MIPI_REGMAP_CAM0,
-       EXYNOS_MIPI_REGMAP_CAM1,
-       EXYNOS_MIPI_REGMAPS_NUM
-};
-
-struct mipi_phy_device_desc {
-       int num_phys;
-       int num_regmaps;
-       const char *regmap_names[EXYNOS_MIPI_REGMAPS_NUM];
-       struct exynos_mipi_phy_desc {
-               enum exynos_mipi_phy_id coupled_phy_id;
-               u32 enable_val;
-               unsigned int enable_reg;
-               enum exynos_mipi_phy_regmap_id enable_map;
-               u32 resetn_val;
-               unsigned int resetn_reg;
-               enum exynos_mipi_phy_regmap_id resetn_map;
-       } phys[EXYNOS_MIPI_PHYS_NUM];
-};
-
-static const struct mipi_phy_device_desc s5pv210_mipi_phy = {
-       .num_regmaps = 1,
-       .regmap_names = {"syscon"},
-       .num_phys = 4,
-       .phys = {
-               {
-                       /* EXYNOS_MIPI_PHY_ID_CSIS0 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
-                       .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
-                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
-               }, {
-                       /* EXYNOS_MIPI_PHY_ID_DSIM0 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = EXYNOS4_MIPI_PHY_MRESETN,
-                       .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
-                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
-               }, {
-                       /* EXYNOS_MIPI_PHY_ID_CSIS1 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM1,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
-                       .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
-                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
-               }, {
-                       /* EXYNOS_MIPI_PHY_ID_DSIM1 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS1,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = EXYNOS4_MIPI_PHY_MRESETN,
-                       .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
-                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
-               },
-       },
-};
-
-static const struct mipi_phy_device_desc exynos5420_mipi_phy = {
-       .num_regmaps = 1,
-       .regmap_names = {"syscon"},
-       .num_phys = 5,
-       .phys = {
-               {
-                       /* EXYNOS_MIPI_PHY_ID_CSIS0 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(0),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
-                       .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(0),
-                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
-               }, {
-                       /* EXYNOS_MIPI_PHY_ID_DSIM0 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(0),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = EXYNOS4_MIPI_PHY_MRESETN,
-                       .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(0),
-                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
-               }, {
-                       /* EXYNOS_MIPI_PHY_ID_CSIS1 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM1,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(1),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
-                       .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(1),
-                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
-               }, {
-                       /* EXYNOS_MIPI_PHY_ID_DSIM1 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS1,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(1),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = EXYNOS4_MIPI_PHY_MRESETN,
-                       .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(1),
-                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
-               }, {
-                       /* EXYNOS_MIPI_PHY_ID_CSIS2 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(2),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
-                       .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(2),
-                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
-               },
-       },
-};
-
-#define EXYNOS5433_SYSREG_DISP_MIPI_PHY                0x100C
-#define EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON   0x1014
-#define EXYNOS5433_SYSREG_CAM1_MIPI_DPHY_CON   0x1020
-
-static const struct mipi_phy_device_desc exynos5433_mipi_phy = {
-       .num_regmaps = 4,
-       .regmap_names = {
-               "samsung,pmu-syscon",
-               "samsung,disp-sysreg",
-               "samsung,cam0-sysreg",
-               "samsung,cam1-sysreg"
-       },
-       .num_phys = 5,
-       .phys = {
-               {
-                       /* EXYNOS_MIPI_PHY_ID_CSIS0 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = BIT(0),
-                       .resetn_reg = EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON,
-                       .resetn_map = EXYNOS_MIPI_REGMAP_CAM0,
-               }, {
-                       /* EXYNOS_MIPI_PHY_ID_DSIM0 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = BIT(0),
-                       .resetn_reg = EXYNOS5433_SYSREG_DISP_MIPI_PHY,
-                       .resetn_map = EXYNOS_MIPI_REGMAP_DISP,
-               }, {
-                       /* EXYNOS_MIPI_PHY_ID_CSIS1 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = BIT(1),
-                       .resetn_reg = EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON,
-                       .resetn_map = EXYNOS_MIPI_REGMAP_CAM0,
-               }, {
-                       /* EXYNOS_MIPI_PHY_ID_DSIM1 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = BIT(1),
-                       .resetn_reg = EXYNOS5433_SYSREG_DISP_MIPI_PHY,
-                       .resetn_map = EXYNOS_MIPI_REGMAP_DISP,
-               }, {
-                       /* EXYNOS_MIPI_PHY_ID_CSIS2 */
-                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
-                       .enable_val = EXYNOS4_PHY_ENABLE,
-                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(2),
-                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
-                       .resetn_val = BIT(0),
-                       .resetn_reg = EXYNOS5433_SYSREG_CAM1_MIPI_DPHY_CON,
-                       .resetn_map = EXYNOS_MIPI_REGMAP_CAM1,
-               },
-       },
-};
-
-struct exynos_mipi_video_phy {
-       struct regmap *regmaps[EXYNOS_MIPI_REGMAPS_NUM];
-       int num_phys;
-       struct video_phy_desc {
-               struct phy *phy;
-               unsigned int index;
-               const struct exynos_mipi_phy_desc *data;
-       } phys[EXYNOS_MIPI_PHYS_NUM];
-       spinlock_t slock;
-};
-
-static int __set_phy_state(const struct exynos_mipi_phy_desc *data,
-                          struct exynos_mipi_video_phy *state, unsigned int on)
-{
-       u32 val;
-
-       spin_lock(&state->slock);
-
-       /* disable in PMU sysreg */
-       if (!on && data->coupled_phy_id >= 0 &&
-           state->phys[data->coupled_phy_id].phy->power_count == 0) {
-               regmap_read(state->regmaps[data->enable_map], data->enable_reg,
-                           &val);
-               val &= ~data->enable_val;
-               regmap_write(state->regmaps[data->enable_map], data->enable_reg,
-                            val);
-       }
-
-       /* PHY reset */
-       regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val);
-       val = on ? (val | data->resetn_val) : (val & ~data->resetn_val);
-       regmap_write(state->regmaps[data->resetn_map], data->resetn_reg, val);
-
-       /* enable in PMU sysreg */
-       if (on) {
-               regmap_read(state->regmaps[data->enable_map], data->enable_reg,
-                           &val);
-               val |= data->enable_val;
-               regmap_write(state->regmaps[data->enable_map], data->enable_reg,
-                            val);
-       }
-
-       spin_unlock(&state->slock);
-
-       return 0;
-}
-
-#define to_mipi_video_phy(desc) \
-       container_of((desc), struct exynos_mipi_video_phy, phys[(desc)->index])
-
-static int exynos_mipi_video_phy_power_on(struct phy *phy)
-{
-       struct video_phy_desc *phy_desc = phy_get_drvdata(phy);
-       struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc);
-
-       return __set_phy_state(phy_desc->data, state, 1);
-}
-
-static int exynos_mipi_video_phy_power_off(struct phy *phy)
-{
-       struct video_phy_desc *phy_desc = phy_get_drvdata(phy);
-       struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc);
-
-       return __set_phy_state(phy_desc->data, state, 0);
-}
-
-static struct phy *exynos_mipi_video_phy_xlate(struct device *dev,
-                                       struct of_phandle_args *args)
-{
-       struct exynos_mipi_video_phy *state = dev_get_drvdata(dev);
-
-       if (WARN_ON(args->args[0] >= state->num_phys))
-               return ERR_PTR(-ENODEV);
-
-       return state->phys[args->args[0]].phy;
-}
-
-static const struct phy_ops exynos_mipi_video_phy_ops = {
-       .power_on       = exynos_mipi_video_phy_power_on,
-       .power_off      = exynos_mipi_video_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
-{
-       const struct mipi_phy_device_desc *phy_dev;
-       struct exynos_mipi_video_phy *state;
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct phy_provider *phy_provider;
-       unsigned int i;
-
-       phy_dev = of_device_get_match_data(dev);
-       if (!phy_dev)
-               return -ENODEV;
-
-       state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
-       if (!state)
-               return -ENOMEM;
-
-       for (i = 0; i < phy_dev->num_regmaps; i++) {
-               state->regmaps[i] = syscon_regmap_lookup_by_phandle(np,
-                                               phy_dev->regmap_names[i]);
-               if (IS_ERR(state->regmaps[i]))
-                       return PTR_ERR(state->regmaps[i]);
-       }
-       state->num_phys = phy_dev->num_phys;
-       spin_lock_init(&state->slock);
-
-       dev_set_drvdata(dev, state);
-
-       for (i = 0; i < state->num_phys; i++) {
-               struct phy *phy = devm_phy_create(dev, NULL,
-                                                 &exynos_mipi_video_phy_ops);
-               if (IS_ERR(phy)) {
-                       dev_err(dev, "failed to create PHY %d\n", i);
-                       return PTR_ERR(phy);
-               }
-
-               state->phys[i].phy = phy;
-               state->phys[i].index = i;
-               state->phys[i].data = &phy_dev->phys[i];
-               phy_set_drvdata(phy, &state->phys[i]);
-       }
-
-       phy_provider = devm_of_phy_provider_register(dev,
-                                       exynos_mipi_video_phy_xlate);
-
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static const struct of_device_id exynos_mipi_video_phy_of_match[] = {
-       {
-               .compatible = "samsung,s5pv210-mipi-video-phy",
-               .data = &s5pv210_mipi_phy,
-       }, {
-               .compatible = "samsung,exynos5420-mipi-video-phy",
-               .data = &exynos5420_mipi_phy,
-       }, {
-               .compatible = "samsung,exynos5433-mipi-video-phy",
-               .data = &exynos5433_mipi_phy,
-       },
-       { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, exynos_mipi_video_phy_of_match);
-
-static struct platform_driver exynos_mipi_video_phy_driver = {
-       .probe  = exynos_mipi_video_phy_probe,
-       .driver = {
-               .of_match_table = exynos_mipi_video_phy_of_match,
-               .name  = "exynos-mipi-video-phy",
-       }
-};
-module_platform_driver(exynos_mipi_video_phy_driver);
-
-MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI CSI-2/DSI PHY driver");
-MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-exynos-pcie.c b/drivers/phy/phy-exynos-pcie.c
deleted file mode 100644 (file)
index a89c12f..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Samsung EXYNOS SoC series PCIe PHY driver
- *
- * Phy provider for PCIe controller on Exynos SoC series
- *
- * Copyright (C) 2017 Samsung Electronics Co., Ltd.
- * Jaehoon Chung <jh80.chung@samsung.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.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/init.h>
-#include <linux/mfd/syscon.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-
-/* PCIe Purple registers */
-#define PCIE_PHY_GLOBAL_RESET          0x000
-#define PCIE_PHY_COMMON_RESET          0x004
-#define PCIE_PHY_CMN_REG               0x008
-#define PCIE_PHY_MAC_RESET             0x00c
-#define PCIE_PHY_PLL_LOCKED            0x010
-#define PCIE_PHY_TRSVREG_RESET         0x020
-#define PCIE_PHY_TRSV_RESET            0x024
-
-/* PCIe PHY registers */
-#define PCIE_PHY_IMPEDANCE             0x004
-#define PCIE_PHY_PLL_DIV_0             0x008
-#define PCIE_PHY_PLL_BIAS              0x00c
-#define PCIE_PHY_DCC_FEEDBACK          0x014
-#define PCIE_PHY_PLL_DIV_1             0x05c
-#define PCIE_PHY_COMMON_POWER          0x064
-#define PCIE_PHY_COMMON_PD_CMN         BIT(3)
-#define PCIE_PHY_TRSV0_EMP_LVL         0x084
-#define PCIE_PHY_TRSV0_DRV_LVL         0x088
-#define PCIE_PHY_TRSV0_RXCDR           0x0ac
-#define PCIE_PHY_TRSV0_POWER           0x0c4
-#define PCIE_PHY_TRSV0_PD_TSV          BIT(7)
-#define PCIE_PHY_TRSV0_LVCC            0x0dc
-#define PCIE_PHY_TRSV1_EMP_LVL         0x144
-#define PCIE_PHY_TRSV1_RXCDR           0x16c
-#define PCIE_PHY_TRSV1_POWER           0x184
-#define PCIE_PHY_TRSV1_PD_TSV          BIT(7)
-#define PCIE_PHY_TRSV1_LVCC            0x19c
-#define PCIE_PHY_TRSV2_EMP_LVL         0x204
-#define PCIE_PHY_TRSV2_RXCDR           0x22c
-#define PCIE_PHY_TRSV2_POWER           0x244
-#define PCIE_PHY_TRSV2_PD_TSV          BIT(7)
-#define PCIE_PHY_TRSV2_LVCC            0x25c
-#define PCIE_PHY_TRSV3_EMP_LVL         0x2c4
-#define PCIE_PHY_TRSV3_RXCDR           0x2ec
-#define PCIE_PHY_TRSV3_POWER           0x304
-#define PCIE_PHY_TRSV3_PD_TSV          BIT(7)
-#define PCIE_PHY_TRSV3_LVCC            0x31c
-
-struct exynos_pcie_phy_data {
-       const struct phy_ops    *ops;
-};
-
-/* For Exynos pcie phy */
-struct exynos_pcie_phy {
-       const struct exynos_pcie_phy_data *drv_data;
-       void __iomem *phy_base;
-       void __iomem *blk_base; /* For exynos5440 */
-};
-
-static void exynos_pcie_phy_writel(void __iomem *base, u32 val, u32 offset)
-{
-       writel(val, base + offset);
-}
-
-static u32 exynos_pcie_phy_readl(void __iomem *base, u32 offset)
-{
-       return readl(base + offset);
-}
-
-/* For Exynos5440 specific functions */
-static int exynos5440_pcie_phy_init(struct phy *phy)
-{
-       struct exynos_pcie_phy *ep = phy_get_drvdata(phy);
-
-       /* DCC feedback control off */
-       exynos_pcie_phy_writel(ep->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK);
-
-       /* set TX/RX impedance */
-       exynos_pcie_phy_writel(ep->phy_base, 0xd5, PCIE_PHY_IMPEDANCE);
-
-       /* set 50Mhz PHY clock */
-       exynos_pcie_phy_writel(ep->phy_base, 0x14, PCIE_PHY_PLL_DIV_0);
-       exynos_pcie_phy_writel(ep->phy_base, 0x12, PCIE_PHY_PLL_DIV_1);
-
-       /* set TX Differential output for lane 0 */
-       exynos_pcie_phy_writel(ep->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
-
-       /* set TX Pre-emphasis Level Control for lane 0 to minimum */
-       exynos_pcie_phy_writel(ep->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
-
-       /* set RX clock and data recovery bandwidth */
-       exynos_pcie_phy_writel(ep->phy_base, 0xe7, PCIE_PHY_PLL_BIAS);
-       exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR);
-       exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR);
-       exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR);
-       exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR);
-
-       /* change TX Pre-emphasis Level Control for lanes */
-       exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
-       exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
-       exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
-       exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
-
-       /* set LVCC */
-       exynos_pcie_phy_writel(ep->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC);
-       exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC);
-       exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC);
-       exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC);
-
-       /* pulse for common reset */
-       exynos_pcie_phy_writel(ep->blk_base, 1, PCIE_PHY_COMMON_RESET);
-       udelay(500);
-       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_COMMON_RESET);
-
-       return 0;
-}
-
-static int exynos5440_pcie_phy_power_on(struct phy *phy)
-{
-       struct exynos_pcie_phy *ep = phy_get_drvdata(phy);
-       u32 val;
-
-       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_COMMON_RESET);
-       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_CMN_REG);
-       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_TRSVREG_RESET);
-       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_TRSV_RESET);
-
-       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_COMMON_POWER);
-       val &= ~PCIE_PHY_COMMON_PD_CMN;
-       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER);
-
-       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER);
-       val &= ~PCIE_PHY_TRSV0_PD_TSV;
-       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER);
-
-       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER);
-       val &= ~PCIE_PHY_TRSV1_PD_TSV;
-       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER);
-
-       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER);
-       val &= ~PCIE_PHY_TRSV2_PD_TSV;
-       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER);
-
-       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER);
-       val &= ~PCIE_PHY_TRSV3_PD_TSV;
-       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER);
-
-       return 0;
-}
-
-static int exynos5440_pcie_phy_power_off(struct phy *phy)
-{
-       struct exynos_pcie_phy *ep = phy_get_drvdata(phy);
-       u32 val;
-
-       if (readl_poll_timeout(ep->phy_base + PCIE_PHY_PLL_LOCKED, val,
-                               (val != 0), 1, 500)) {
-               dev_err(&phy->dev, "PLL Locked: 0x%x\n", val);
-               return -ETIMEDOUT;
-       }
-
-       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_COMMON_POWER);
-       val |= PCIE_PHY_COMMON_PD_CMN;
-       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER);
-
-       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER);
-       val |= PCIE_PHY_TRSV0_PD_TSV;
-       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER);
-
-       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER);
-       val |= PCIE_PHY_TRSV1_PD_TSV;
-       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER);
-
-       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER);
-       val |= PCIE_PHY_TRSV2_PD_TSV;
-       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER);
-
-       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER);
-       val |= PCIE_PHY_TRSV3_PD_TSV;
-       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER);
-
-       return 0;
-}
-
-static int exynos5440_pcie_phy_reset(struct phy *phy)
-{
-       struct exynos_pcie_phy *ep = phy_get_drvdata(phy);
-
-       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_MAC_RESET);
-       exynos_pcie_phy_writel(ep->blk_base, 1, PCIE_PHY_GLOBAL_RESET);
-       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_GLOBAL_RESET);
-
-       return 0;
-}
-
-static const struct phy_ops exynos5440_phy_ops = {
-       .init           = exynos5440_pcie_phy_init,
-       .power_on       = exynos5440_pcie_phy_power_on,
-       .power_off      = exynos5440_pcie_phy_power_off,
-       .reset          = exynos5440_pcie_phy_reset,
-       .owner          = THIS_MODULE,
-};
-
-static const struct exynos_pcie_phy_data exynos5440_pcie_phy_data = {
-       .ops            = &exynos5440_phy_ops,
-};
-
-static const struct of_device_id exynos_pcie_phy_match[] = {
-       {
-               .compatible = "samsung,exynos5440-pcie-phy",
-               .data = &exynos5440_pcie_phy_data,
-       },
-       {},
-};
-
-static int exynos_pcie_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct exynos_pcie_phy *exynos_phy;
-       struct phy *generic_phy;
-       struct phy_provider *phy_provider;
-       struct resource *res;
-       const struct exynos_pcie_phy_data *drv_data;
-
-       drv_data = of_device_get_match_data(dev);
-       if (!drv_data)
-               return -ENODEV;
-
-       exynos_phy = devm_kzalloc(dev, sizeof(*exynos_phy), GFP_KERNEL);
-       if (!exynos_phy)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       exynos_phy->phy_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(exynos_phy->phy_base))
-               return PTR_ERR(exynos_phy->phy_base);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       exynos_phy->blk_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(exynos_phy->blk_base))
-               return PTR_ERR(exynos_phy->blk_base);
-
-       exynos_phy->drv_data = drv_data;
-
-       generic_phy = devm_phy_create(dev, dev->of_node, drv_data->ops);
-       if (IS_ERR(generic_phy)) {
-               dev_err(dev, "failed to create PHY\n");
-               return PTR_ERR(generic_phy);
-       }
-
-       phy_set_drvdata(generic_phy, exynos_phy);
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static struct platform_driver exynos_pcie_phy_driver = {
-       .probe  = exynos_pcie_phy_probe,
-       .driver = {
-               .of_match_table = exynos_pcie_phy_match,
-               .name           = "exynos_pcie_phy",
-       }
-};
-
-builtin_platform_driver(exynos_pcie_phy_driver);
diff --git a/drivers/phy/phy-exynos4210-usb2.c b/drivers/phy/phy-exynos4210-usb2.c
deleted file mode 100644 (file)
index 1f50e10..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4210 support
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Kamil Debski <k.debski@samsung.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.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-#include "phy-samsung-usb2.h"
-
-/* Exynos USB PHY registers */
-
-/* PHY power control */
-#define EXYNOS_4210_UPHYPWR                    0x0
-
-#define EXYNOS_4210_UPHYPWR_PHY0_SUSPEND       BIT(0)
-#define EXYNOS_4210_UPHYPWR_PHY0_PWR           BIT(3)
-#define EXYNOS_4210_UPHYPWR_PHY0_OTG_PWR       BIT(4)
-#define EXYNOS_4210_UPHYPWR_PHY0_SLEEP         BIT(5)
-#define EXYNOS_4210_UPHYPWR_PHY0       ( \
-       EXYNOS_4210_UPHYPWR_PHY0_SUSPEND | \
-       EXYNOS_4210_UPHYPWR_PHY0_PWR | \
-       EXYNOS_4210_UPHYPWR_PHY0_OTG_PWR | \
-       EXYNOS_4210_UPHYPWR_PHY0_SLEEP)
-
-#define EXYNOS_4210_UPHYPWR_PHY1_SUSPEND       BIT(6)
-#define EXYNOS_4210_UPHYPWR_PHY1_PWR           BIT(7)
-#define EXYNOS_4210_UPHYPWR_PHY1_SLEEP         BIT(8)
-#define EXYNOS_4210_UPHYPWR_PHY1 ( \
-       EXYNOS_4210_UPHYPWR_PHY1_SUSPEND | \
-       EXYNOS_4210_UPHYPWR_PHY1_PWR | \
-       EXYNOS_4210_UPHYPWR_PHY1_SLEEP)
-
-#define EXYNOS_4210_UPHYPWR_HSIC0_SUSPEND      BIT(9)
-#define EXYNOS_4210_UPHYPWR_HSIC0_SLEEP                BIT(10)
-#define EXYNOS_4210_UPHYPWR_HSIC0 ( \
-       EXYNOS_4210_UPHYPWR_HSIC0_SUSPEND | \
-       EXYNOS_4210_UPHYPWR_HSIC0_SLEEP)
-
-#define EXYNOS_4210_UPHYPWR_HSIC1_SUSPEND      BIT(11)
-#define EXYNOS_4210_UPHYPWR_HSIC1_SLEEP                BIT(12)
-#define EXYNOS_4210_UPHYPWR_HSIC1 ( \
-       EXYNOS_4210_UPHYPWR_HSIC1_SUSPEND | \
-       EXYNOS_4210_UPHYPWR_HSIC1_SLEEP)
-
-/* PHY clock control */
-#define EXYNOS_4210_UPHYCLK                    0x4
-
-#define EXYNOS_4210_UPHYCLK_PHYFSEL_MASK       (0x3 << 0)
-#define EXYNOS_4210_UPHYCLK_PHYFSEL_OFFSET     0
-#define EXYNOS_4210_UPHYCLK_PHYFSEL_48MHZ      (0x0 << 0)
-#define EXYNOS_4210_UPHYCLK_PHYFSEL_24MHZ      (0x3 << 0)
-#define EXYNOS_4210_UPHYCLK_PHYFSEL_12MHZ      (0x2 << 0)
-
-#define EXYNOS_4210_UPHYCLK_PHY0_ID_PULLUP     BIT(2)
-#define EXYNOS_4210_UPHYCLK_PHY0_COMMON_ON     BIT(4)
-#define EXYNOS_4210_UPHYCLK_PHY1_COMMON_ON     BIT(7)
-
-/* PHY reset control */
-#define EXYNOS_4210_UPHYRST                    0x8
-
-#define EXYNOS_4210_URSTCON_PHY0               BIT(0)
-#define EXYNOS_4210_URSTCON_OTG_HLINK          BIT(1)
-#define EXYNOS_4210_URSTCON_OTG_PHYLINK                BIT(2)
-#define EXYNOS_4210_URSTCON_PHY1_ALL           BIT(3)
-#define EXYNOS_4210_URSTCON_PHY1_P0            BIT(4)
-#define EXYNOS_4210_URSTCON_PHY1_P1P2          BIT(5)
-#define EXYNOS_4210_URSTCON_HOST_LINK_ALL      BIT(6)
-#define EXYNOS_4210_URSTCON_HOST_LINK_P0       BIT(7)
-#define EXYNOS_4210_URSTCON_HOST_LINK_P1       BIT(8)
-#define EXYNOS_4210_URSTCON_HOST_LINK_P2       BIT(9)
-
-/* Isolation, configured in the power management unit */
-#define EXYNOS_4210_USB_ISOL_DEVICE_OFFSET     0x704
-#define EXYNOS_4210_USB_ISOL_DEVICE            BIT(0)
-#define EXYNOS_4210_USB_ISOL_HOST_OFFSET       0x708
-#define EXYNOS_4210_USB_ISOL_HOST              BIT(0)
-
-/* USBYPHY1 Floating prevention */
-#define EXYNOS_4210_UPHY1CON                   0x34
-#define EXYNOS_4210_UPHY1CON_FLOAT_PREVENTION  0x1
-
-/* Mode switching SUB Device <-> Host */
-#define EXYNOS_4210_MODE_SWITCH_OFFSET         0x21c
-#define EXYNOS_4210_MODE_SWITCH_MASK           1
-#define EXYNOS_4210_MODE_SWITCH_DEVICE         0
-#define EXYNOS_4210_MODE_SWITCH_HOST           1
-
-enum exynos4210_phy_id {
-       EXYNOS4210_DEVICE,
-       EXYNOS4210_HOST,
-       EXYNOS4210_HSIC0,
-       EXYNOS4210_HSIC1,
-       EXYNOS4210_NUM_PHYS,
-};
-
-/*
- * exynos4210_rate_to_clk() converts the supplied clock rate to the value that
- * can be written to the phy register.
- */
-static int exynos4210_rate_to_clk(unsigned long rate, u32 *reg)
-{
-       switch (rate) {
-       case 12 * MHZ:
-               *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_12MHZ;
-               break;
-       case 24 * MHZ:
-               *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_24MHZ;
-               break;
-       case 48 * MHZ:
-               *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_48MHZ;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void exynos4210_isol(struct samsung_usb2_phy_instance *inst, bool on)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       u32 offset;
-       u32 mask;
-
-       switch (inst->cfg->id) {
-       case EXYNOS4210_DEVICE:
-               offset = EXYNOS_4210_USB_ISOL_DEVICE_OFFSET;
-               mask = EXYNOS_4210_USB_ISOL_DEVICE;
-               break;
-       case EXYNOS4210_HOST:
-               offset = EXYNOS_4210_USB_ISOL_HOST_OFFSET;
-               mask = EXYNOS_4210_USB_ISOL_HOST;
-               break;
-       default:
-               return;
-       }
-
-       regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
-}
-
-static void exynos4210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       u32 rstbits = 0;
-       u32 phypwr = 0;
-       u32 rst;
-       u32 pwr;
-       u32 clk;
-
-       switch (inst->cfg->id) {
-       case EXYNOS4210_DEVICE:
-               phypwr =        EXYNOS_4210_UPHYPWR_PHY0;
-               rstbits =       EXYNOS_4210_URSTCON_PHY0;
-               break;
-       case EXYNOS4210_HOST:
-               phypwr =        EXYNOS_4210_UPHYPWR_PHY1;
-               rstbits =       EXYNOS_4210_URSTCON_PHY1_ALL |
-                               EXYNOS_4210_URSTCON_PHY1_P0 |
-                               EXYNOS_4210_URSTCON_PHY1_P1P2 |
-                               EXYNOS_4210_URSTCON_HOST_LINK_ALL |
-                               EXYNOS_4210_URSTCON_HOST_LINK_P0;
-               writel(on, drv->reg_phy + EXYNOS_4210_UPHY1CON);
-               break;
-       case EXYNOS4210_HSIC0:
-               phypwr =        EXYNOS_4210_UPHYPWR_HSIC0;
-               rstbits =       EXYNOS_4210_URSTCON_PHY1_P1P2 |
-                               EXYNOS_4210_URSTCON_HOST_LINK_P1;
-               break;
-       case EXYNOS4210_HSIC1:
-               phypwr =        EXYNOS_4210_UPHYPWR_HSIC1;
-               rstbits =       EXYNOS_4210_URSTCON_PHY1_P1P2 |
-                               EXYNOS_4210_URSTCON_HOST_LINK_P2;
-               break;
-       }
-
-       if (on) {
-               clk = readl(drv->reg_phy + EXYNOS_4210_UPHYCLK);
-               clk &= ~EXYNOS_4210_UPHYCLK_PHYFSEL_MASK;
-               clk |= drv->ref_reg_val << EXYNOS_4210_UPHYCLK_PHYFSEL_OFFSET;
-               writel(clk, drv->reg_phy + EXYNOS_4210_UPHYCLK);
-
-               pwr = readl(drv->reg_phy + EXYNOS_4210_UPHYPWR);
-               pwr &= ~phypwr;
-               writel(pwr, drv->reg_phy + EXYNOS_4210_UPHYPWR);
-
-               rst = readl(drv->reg_phy + EXYNOS_4210_UPHYRST);
-               rst |= rstbits;
-               writel(rst, drv->reg_phy + EXYNOS_4210_UPHYRST);
-               udelay(10);
-               rst &= ~rstbits;
-               writel(rst, drv->reg_phy + EXYNOS_4210_UPHYRST);
-               /* The following delay is necessary for the reset sequence to be
-                * completed */
-               udelay(80);
-       } else {
-               pwr = readl(drv->reg_phy + EXYNOS_4210_UPHYPWR);
-               pwr |= phypwr;
-               writel(pwr, drv->reg_phy + EXYNOS_4210_UPHYPWR);
-       }
-}
-
-static int exynos4210_power_on(struct samsung_usb2_phy_instance *inst)
-{
-       /* Order of initialisation is important - first power then isolation */
-       exynos4210_phy_pwr(inst, 1);
-       exynos4210_isol(inst, 0);
-
-       return 0;
-}
-
-static int exynos4210_power_off(struct samsung_usb2_phy_instance *inst)
-{
-       exynos4210_isol(inst, 1);
-       exynos4210_phy_pwr(inst, 0);
-
-       return 0;
-}
-
-
-static const struct samsung_usb2_common_phy exynos4210_phys[] = {
-       {
-               .label          = "device",
-               .id             = EXYNOS4210_DEVICE,
-               .power_on       = exynos4210_power_on,
-               .power_off      = exynos4210_power_off,
-       },
-       {
-               .label          = "host",
-               .id             = EXYNOS4210_HOST,
-               .power_on       = exynos4210_power_on,
-               .power_off      = exynos4210_power_off,
-       },
-       {
-               .label          = "hsic0",
-               .id             = EXYNOS4210_HSIC0,
-               .power_on       = exynos4210_power_on,
-               .power_off      = exynos4210_power_off,
-       },
-       {
-               .label          = "hsic1",
-               .id             = EXYNOS4210_HSIC1,
-               .power_on       = exynos4210_power_on,
-               .power_off      = exynos4210_power_off,
-       },
-};
-
-const struct samsung_usb2_phy_config exynos4210_usb2_phy_config = {
-       .has_mode_switch        = 0,
-       .num_phys               = EXYNOS4210_NUM_PHYS,
-       .phys                   = exynos4210_phys,
-       .rate_to_clk            = exynos4210_rate_to_clk,
-};
diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c
deleted file mode 100644 (file)
index 7f27a91..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4x12 support
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Kamil Debski <k.debski@samsung.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.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-#include "phy-samsung-usb2.h"
-
-/* Exynos USB PHY registers */
-
-/* PHY power control */
-#define EXYNOS_4x12_UPHYPWR                    0x0
-
-#define EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND       BIT(0)
-#define EXYNOS_4x12_UPHYPWR_PHY0_PWR           BIT(3)
-#define EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR       BIT(4)
-#define EXYNOS_4x12_UPHYPWR_PHY0_SLEEP         BIT(5)
-#define EXYNOS_4x12_UPHYPWR_PHY0 ( \
-       EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND | \
-       EXYNOS_4x12_UPHYPWR_PHY0_PWR | \
-       EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR | \
-       EXYNOS_4x12_UPHYPWR_PHY0_SLEEP)
-
-#define EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND       BIT(6)
-#define EXYNOS_4x12_UPHYPWR_PHY1_PWR           BIT(7)
-#define EXYNOS_4x12_UPHYPWR_PHY1_SLEEP         BIT(8)
-#define EXYNOS_4x12_UPHYPWR_PHY1 ( \
-       EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND | \
-       EXYNOS_4x12_UPHYPWR_PHY1_PWR | \
-       EXYNOS_4x12_UPHYPWR_PHY1_SLEEP)
-
-#define EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND      BIT(9)
-#define EXYNOS_4x12_UPHYPWR_HSIC0_PWR          BIT(10)
-#define EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP                BIT(11)
-#define EXYNOS_4x12_UPHYPWR_HSIC0 ( \
-       EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND | \
-       EXYNOS_4x12_UPHYPWR_HSIC0_PWR | \
-       EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP)
-
-#define EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND      BIT(12)
-#define EXYNOS_4x12_UPHYPWR_HSIC1_PWR          BIT(13)
-#define EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP                BIT(14)
-#define EXYNOS_4x12_UPHYPWR_HSIC1 ( \
-       EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND | \
-       EXYNOS_4x12_UPHYPWR_HSIC1_PWR | \
-       EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP)
-
-/* PHY clock control */
-#define EXYNOS_4x12_UPHYCLK                    0x4
-
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK       (0x7 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET     0
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6      (0x0 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ      (0x1 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ      (0x2 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2     (0x3 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ      (0x4 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ      (0x5 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ      (0x7 << 0)
-
-#define EXYNOS_3250_UPHYCLK_REFCLKSEL          (0x2 << 8)
-
-#define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP     BIT(3)
-#define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON     BIT(4)
-#define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON     BIT(7)
-
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_MASK   (0x7f << 10)
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_OFFSET  10
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_12MHZ  (0x24 << 10)
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_15MHZ  (0x1c << 10)
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_16MHZ  (0x1a << 10)
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_19MHZ2 (0x15 << 10)
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_20MHZ  (0x14 << 10)
-
-/* PHY reset control */
-#define EXYNOS_4x12_UPHYRST                    0x8
-
-#define EXYNOS_4x12_URSTCON_PHY0               BIT(0)
-#define EXYNOS_4x12_URSTCON_OTG_HLINK          BIT(1)
-#define EXYNOS_4x12_URSTCON_OTG_PHYLINK                BIT(2)
-#define EXYNOS_4x12_URSTCON_HOST_PHY           BIT(3)
-/* The following bit defines are presented in the
- * order taken from the Exynos4412 reference manual.
- *
- * During experiments with the hardware and debugging
- * it was determined that the hardware behaves contrary
- * to the manual.
- *
- * The following bit values were chaned accordingly to the
- * results of real hardware experiments.
- */
-#define EXYNOS_4x12_URSTCON_PHY1               BIT(4)
-#define EXYNOS_4x12_URSTCON_HSIC0              BIT(6)
-#define EXYNOS_4x12_URSTCON_HSIC1              BIT(5)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_ALL      BIT(7)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P0       BIT(10)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P1       BIT(9)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P2       BIT(8)
-
-/* Isolation, configured in the power management unit */
-#define EXYNOS_4x12_USB_ISOL_OFFSET            0x704
-#define EXYNOS_4x12_USB_ISOL_OTG               BIT(0)
-#define EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET      0x708
-#define EXYNOS_4x12_USB_ISOL_HSIC0             BIT(0)
-#define EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET      0x70c
-#define EXYNOS_4x12_USB_ISOL_HSIC1             BIT(0)
-
-/* Mode switching SUB Device <-> Host */
-#define EXYNOS_4x12_MODE_SWITCH_OFFSET         0x21c
-#define EXYNOS_4x12_MODE_SWITCH_MASK           1
-#define EXYNOS_4x12_MODE_SWITCH_DEVICE         0
-#define EXYNOS_4x12_MODE_SWITCH_HOST           1
-
-enum exynos4x12_phy_id {
-       EXYNOS4x12_DEVICE,
-       EXYNOS4x12_HOST,
-       EXYNOS4x12_HSIC0,
-       EXYNOS4x12_HSIC1,
-       EXYNOS4x12_NUM_PHYS,
-};
-
-/*
- * exynos4x12_rate_to_clk() converts the supplied clock rate to the value that
- * can be written to the phy register.
- */
-static int exynos4x12_rate_to_clk(unsigned long rate, u32 *reg)
-{
-       /* EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK */
-
-       switch (rate) {
-       case 9600 * KHZ:
-               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6;
-               break;
-       case 10 * MHZ:
-               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ;
-               break;
-       case 12 * MHZ:
-               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ;
-               break;
-       case 19200 * KHZ:
-               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2;
-               break;
-       case 20 * MHZ:
-               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ;
-               break;
-       case 24 * MHZ:
-               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ;
-               break;
-       case 50 * MHZ:
-               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void exynos4x12_isol(struct samsung_usb2_phy_instance *inst, bool on)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       u32 offset;
-       u32 mask;
-
-       switch (inst->cfg->id) {
-       case EXYNOS4x12_DEVICE:
-       case EXYNOS4x12_HOST:
-               offset = EXYNOS_4x12_USB_ISOL_OFFSET;
-               mask = EXYNOS_4x12_USB_ISOL_OTG;
-               break;
-       case EXYNOS4x12_HSIC0:
-               offset = EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET;
-               mask = EXYNOS_4x12_USB_ISOL_HSIC0;
-               break;
-       case EXYNOS4x12_HSIC1:
-               offset = EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET;
-               mask = EXYNOS_4x12_USB_ISOL_HSIC1;
-               break;
-       default:
-               return;
-       }
-
-       regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
-}
-
-static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       u32 clk;
-
-       clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
-       clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
-
-       if (drv->cfg->has_refclk_sel)
-               clk = EXYNOS_3250_UPHYCLK_REFCLKSEL;
-
-       clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
-       clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
-       writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
-}
-
-static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       u32 rstbits = 0;
-       u32 phypwr = 0;
-       u32 rst;
-       u32 pwr;
-
-       switch (inst->cfg->id) {
-       case EXYNOS4x12_DEVICE:
-               phypwr =        EXYNOS_4x12_UPHYPWR_PHY0;
-               rstbits =       EXYNOS_4x12_URSTCON_PHY0;
-               break;
-       case EXYNOS4x12_HOST:
-               phypwr =        EXYNOS_4x12_UPHYPWR_PHY1;
-               rstbits =       EXYNOS_4x12_URSTCON_HOST_PHY |
-                               EXYNOS_4x12_URSTCON_PHY1 |
-                               EXYNOS_4x12_URSTCON_HOST_LINK_P0;
-               break;
-       case EXYNOS4x12_HSIC0:
-               phypwr =        EXYNOS_4x12_UPHYPWR_HSIC0;
-               rstbits =       EXYNOS_4x12_URSTCON_HSIC0 |
-                               EXYNOS_4x12_URSTCON_HOST_LINK_P1;
-               break;
-       case EXYNOS4x12_HSIC1:
-               phypwr =        EXYNOS_4x12_UPHYPWR_HSIC1;
-               rstbits =       EXYNOS_4x12_URSTCON_HSIC1 |
-                               EXYNOS_4x12_URSTCON_HOST_LINK_P1;
-               break;
-       }
-
-       if (on) {
-               pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
-               pwr &= ~phypwr;
-               writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
-
-               rst = readl(drv->reg_phy + EXYNOS_4x12_UPHYRST);
-               rst |= rstbits;
-               writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
-               udelay(10);
-               rst &= ~rstbits;
-               writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
-               /* The following delay is necessary for the reset sequence to be
-                * completed */
-               udelay(80);
-       } else {
-               pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
-               pwr |= phypwr;
-               writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
-       }
-}
-
-static void exynos4x12_power_on_int(struct samsung_usb2_phy_instance *inst)
-{
-       if (inst->int_cnt++ > 0)
-               return;
-
-       exynos4x12_setup_clk(inst);
-       exynos4x12_isol(inst, 0);
-       exynos4x12_phy_pwr(inst, 1);
-}
-
-static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-
-       if (inst->ext_cnt++ > 0)
-               return 0;
-
-       if (inst->cfg->id == EXYNOS4x12_HOST) {
-               regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
-                                               EXYNOS_4x12_MODE_SWITCH_MASK,
-                                               EXYNOS_4x12_MODE_SWITCH_HOST);
-               exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
-       }
-
-       if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
-               regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
-                                               EXYNOS_4x12_MODE_SWITCH_MASK,
-                                               EXYNOS_4x12_MODE_SWITCH_DEVICE);
-
-       if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
-               inst->cfg->id == EXYNOS4x12_HSIC1) {
-               exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
-               exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_HOST]);
-       }
-
-       exynos4x12_power_on_int(inst);
-
-       return 0;
-}
-
-static void exynos4x12_power_off_int(struct samsung_usb2_phy_instance *inst)
-{
-       if (inst->int_cnt-- > 1)
-               return;
-
-       exynos4x12_isol(inst, 1);
-       exynos4x12_phy_pwr(inst, 0);
-}
-
-static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-
-       if (inst->ext_cnt-- > 1)
-               return 0;
-
-       if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
-               regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
-                                               EXYNOS_4x12_MODE_SWITCH_MASK,
-                                               EXYNOS_4x12_MODE_SWITCH_HOST);
-
-       if (inst->cfg->id == EXYNOS4x12_HOST)
-               exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
-
-       if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
-               inst->cfg->id == EXYNOS4x12_HSIC1) {
-               exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
-               exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_HOST]);
-       }
-
-       exynos4x12_power_off_int(inst);
-
-       return 0;
-}
-
-
-static const struct samsung_usb2_common_phy exynos4x12_phys[] = {
-       {
-               .label          = "device",
-               .id             = EXYNOS4x12_DEVICE,
-               .power_on       = exynos4x12_power_on,
-               .power_off      = exynos4x12_power_off,
-       },
-       {
-               .label          = "host",
-               .id             = EXYNOS4x12_HOST,
-               .power_on       = exynos4x12_power_on,
-               .power_off      = exynos4x12_power_off,
-       },
-       {
-               .label          = "hsic0",
-               .id             = EXYNOS4x12_HSIC0,
-               .power_on       = exynos4x12_power_on,
-               .power_off      = exynos4x12_power_off,
-       },
-       {
-               .label          = "hsic1",
-               .id             = EXYNOS4x12_HSIC1,
-               .power_on       = exynos4x12_power_on,
-               .power_off      = exynos4x12_power_off,
-       },
-};
-
-const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = {
-       .has_refclk_sel         = 1,
-       .num_phys               = 1,
-       .phys                   = exynos4x12_phys,
-       .rate_to_clk            = exynos4x12_rate_to_clk,
-};
-
-const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = {
-       .has_mode_switch        = 1,
-       .num_phys               = EXYNOS4x12_NUM_PHYS,
-       .phys                   = exynos4x12_phys,
-       .rate_to_clk            = exynos4x12_rate_to_clk,
-};
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
deleted file mode 100644 (file)
index 7c41daa..0000000
+++ /dev/null
@@ -1,782 +0,0 @@
-/*
- * Samsung EXYNOS5 SoC series USB DRD PHY driver
- *
- * Phy provider for USB 3.0 DRD controller on Exynos5 SoC series
- *
- * Copyright (C) 2014 Samsung Electronics Co., Ltd.
- * Author: Vivek Gautam <gautam.vivek@samsung.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.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/kernel.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/mutex.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-#include <linux/soc/samsung/exynos-regs-pmu.h>
-
-/* Exynos USB PHY registers */
-#define EXYNOS5_FSEL_9MHZ6             0x0
-#define EXYNOS5_FSEL_10MHZ             0x1
-#define EXYNOS5_FSEL_12MHZ             0x2
-#define EXYNOS5_FSEL_19MHZ2            0x3
-#define EXYNOS5_FSEL_20MHZ             0x4
-#define EXYNOS5_FSEL_24MHZ             0x5
-#define EXYNOS5_FSEL_50MHZ             0x7
-
-/* EXYNOS5: USB 3.0 DRD PHY registers */
-#define EXYNOS5_DRD_LINKSYSTEM                 0x04
-
-#define LINKSYSTEM_FLADJ_MASK                  (0x3f << 1)
-#define LINKSYSTEM_FLADJ(_x)                   ((_x) << 1)
-#define LINKSYSTEM_XHCI_VERSION_CONTROL                BIT(27)
-
-#define EXYNOS5_DRD_PHYUTMI                    0x08
-
-#define PHYUTMI_OTGDISABLE                     BIT(6)
-#define PHYUTMI_FORCESUSPEND                   BIT(1)
-#define PHYUTMI_FORCESLEEP                     BIT(0)
-
-#define EXYNOS5_DRD_PHYPIPE                    0x0c
-
-#define EXYNOS5_DRD_PHYCLKRST                  0x10
-
-#define PHYCLKRST_EN_UTMISUSPEND               BIT(31)
-
-#define PHYCLKRST_SSC_REFCLKSEL_MASK           (0xff << 23)
-#define PHYCLKRST_SSC_REFCLKSEL(_x)            ((_x) << 23)
-
-#define PHYCLKRST_SSC_RANGE_MASK               (0x03 << 21)
-#define PHYCLKRST_SSC_RANGE(_x)                        ((_x) << 21)
-
-#define PHYCLKRST_SSC_EN                       BIT(20)
-#define PHYCLKRST_REF_SSP_EN                   BIT(19)
-#define PHYCLKRST_REF_CLKDIV2                  BIT(18)
-
-#define PHYCLKRST_MPLL_MULTIPLIER_MASK         (0x7f << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF   (0x19 << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF      (0x32 << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF    (0x68 << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF    (0x7d << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11)
-
-#define PHYCLKRST_FSEL_UTMI_MASK               (0x7 << 5)
-#define PHYCLKRST_FSEL_PIPE_MASK               (0x7 << 8)
-#define PHYCLKRST_FSEL(_x)                     ((_x) << 5)
-#define PHYCLKRST_FSEL_PAD_100MHZ              (0x27 << 5)
-#define PHYCLKRST_FSEL_PAD_24MHZ               (0x2a << 5)
-#define PHYCLKRST_FSEL_PAD_20MHZ               (0x31 << 5)
-#define PHYCLKRST_FSEL_PAD_19_2MHZ             (0x38 << 5)
-
-#define PHYCLKRST_RETENABLEN                   BIT(4)
-
-#define PHYCLKRST_REFCLKSEL_MASK               (0x03 << 2)
-#define PHYCLKRST_REFCLKSEL_PAD_REFCLK         (0x2 << 2)
-#define PHYCLKRST_REFCLKSEL_EXT_REFCLK         (0x3 << 2)
-
-#define PHYCLKRST_PORTRESET                    BIT(1)
-#define PHYCLKRST_COMMONONN                    BIT(0)
-
-#define EXYNOS5_DRD_PHYREG0                    0x14
-#define EXYNOS5_DRD_PHYREG1                    0x18
-
-#define EXYNOS5_DRD_PHYPARAM0                  0x1c
-
-#define PHYPARAM0_REF_USE_PAD                  BIT(31)
-#define PHYPARAM0_REF_LOSLEVEL_MASK            (0x1f << 26)
-#define PHYPARAM0_REF_LOSLEVEL                 (0x9 << 26)
-
-#define EXYNOS5_DRD_PHYPARAM1                  0x20
-
-#define PHYPARAM1_PCS_TXDEEMPH_MASK            (0x1f << 0)
-#define PHYPARAM1_PCS_TXDEEMPH                 (0x1c)
-
-#define EXYNOS5_DRD_PHYTERM                    0x24
-
-#define EXYNOS5_DRD_PHYTEST                    0x28
-
-#define PHYTEST_POWERDOWN_SSP                  BIT(3)
-#define PHYTEST_POWERDOWN_HSP                  BIT(2)
-
-#define EXYNOS5_DRD_PHYADP                     0x2c
-
-#define EXYNOS5_DRD_PHYUTMICLKSEL              0x30
-
-#define PHYUTMICLKSEL_UTMI_CLKSEL              BIT(2)
-
-#define EXYNOS5_DRD_PHYRESUME                  0x34
-#define EXYNOS5_DRD_LINKPORT                   0x44
-
-#define KHZ    1000
-#define MHZ    (KHZ * KHZ)
-
-enum exynos5_usbdrd_phy_id {
-       EXYNOS5_DRDPHY_UTMI,
-       EXYNOS5_DRDPHY_PIPE3,
-       EXYNOS5_DRDPHYS_NUM,
-};
-
-struct phy_usb_instance;
-struct exynos5_usbdrd_phy;
-
-struct exynos5_usbdrd_phy_config {
-       u32 id;
-       void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
-       void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
-       unsigned int (*set_refclk)(struct phy_usb_instance *inst);
-};
-
-struct exynos5_usbdrd_phy_drvdata {
-       const struct exynos5_usbdrd_phy_config *phy_cfg;
-       u32 pmu_offset_usbdrd0_phy;
-       u32 pmu_offset_usbdrd1_phy;
-       bool has_common_clk_gate;
-};
-
-/**
- * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY
- * @dev: pointer to device instance of this platform device
- * @reg_phy: usb phy controller register memory base
- * @clk: phy clock for register access
- * @pipeclk: clock for pipe3 phy
- * @utmiclk: clock for utmi+ phy
- * @itpclk: clock for ITP generation
- * @drv_data: pointer to SoC level driver data structure
- * @phys[]: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
- *         instances each with its 'phy' and 'phy_cfg'.
- * @extrefclk: frequency select settings when using 'separate
- *            reference clocks' for SS and HS operations
- * @ref_clk: reference clock to PHY block from which PHY's
- *          operational clocks are derived
- * vbus: VBUS regulator for phy
- * vbus_boost: Boost regulator for VBUS present on few Exynos boards
- */
-struct exynos5_usbdrd_phy {
-       struct device *dev;
-       void __iomem *reg_phy;
-       struct clk *clk;
-       struct clk *pipeclk;
-       struct clk *utmiclk;
-       struct clk *itpclk;
-       const struct exynos5_usbdrd_phy_drvdata *drv_data;
-       struct phy_usb_instance {
-               struct phy *phy;
-               u32 index;
-               struct regmap *reg_pmu;
-               u32 pmu_offset;
-               const struct exynos5_usbdrd_phy_config *phy_cfg;
-       } phys[EXYNOS5_DRDPHYS_NUM];
-       u32 extrefclk;
-       struct clk *ref_clk;
-       struct regulator *vbus;
-       struct regulator *vbus_boost;
-};
-
-static inline
-struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst)
-{
-       return container_of((inst), struct exynos5_usbdrd_phy,
-                           phys[(inst)->index]);
-}
-
-/*
- * exynos5_rate_to_clk() converts the supplied clock rate to the value that
- * can be written to the phy register.
- */
-static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg)
-{
-       /* EXYNOS5_FSEL_MASK */
-
-       switch (rate) {
-       case 9600 * KHZ:
-               *reg = EXYNOS5_FSEL_9MHZ6;
-               break;
-       case 10 * MHZ:
-               *reg = EXYNOS5_FSEL_10MHZ;
-               break;
-       case 12 * MHZ:
-               *reg = EXYNOS5_FSEL_12MHZ;
-               break;
-       case 19200 * KHZ:
-               *reg = EXYNOS5_FSEL_19MHZ2;
-               break;
-       case 20 * MHZ:
-               *reg = EXYNOS5_FSEL_20MHZ;
-               break;
-       case 24 * MHZ:
-               *reg = EXYNOS5_FSEL_24MHZ;
-               break;
-       case 50 * MHZ:
-               *reg = EXYNOS5_FSEL_50MHZ;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst,
-                                               unsigned int on)
-{
-       unsigned int val;
-
-       if (!inst->reg_pmu)
-               return;
-
-       val = on ? 0 : EXYNOS4_PHY_ENABLE;
-
-       regmap_update_bits(inst->reg_pmu, inst->pmu_offset,
-                          EXYNOS4_PHY_ENABLE, val);
-}
-
-/*
- * Sets the pipe3 phy's clk as EXTREFCLK (XXTI) which is internal clock
- * from clock core. Further sets multiplier values and spread spectrum
- * clock settings for SuperSpeed operations.
- */
-static unsigned int
-exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
-{
-       u32 reg;
-       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
-       /* restore any previous reference clock settings */
-       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
-
-       /* Use EXTREFCLK as ref clock */
-       reg &= ~PHYCLKRST_REFCLKSEL_MASK;
-       reg |=  PHYCLKRST_REFCLKSEL_EXT_REFCLK;
-
-       /* FSEL settings corresponding to reference clock */
-       reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
-               PHYCLKRST_MPLL_MULTIPLIER_MASK |
-               PHYCLKRST_SSC_REFCLKSEL_MASK;
-       switch (phy_drd->extrefclk) {
-       case EXYNOS5_FSEL_50MHZ:
-               reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
-                       PHYCLKRST_SSC_REFCLKSEL(0x00));
-               break;
-       case EXYNOS5_FSEL_24MHZ:
-               reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
-                       PHYCLKRST_SSC_REFCLKSEL(0x88));
-               break;
-       case EXYNOS5_FSEL_20MHZ:
-               reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
-                       PHYCLKRST_SSC_REFCLKSEL(0x00));
-               break;
-       case EXYNOS5_FSEL_19MHZ2:
-               reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
-                       PHYCLKRST_SSC_REFCLKSEL(0x88));
-               break;
-       default:
-               dev_dbg(phy_drd->dev, "unsupported ref clk\n");
-               break;
-       }
-
-       return reg;
-}
-
-/*
- * Sets the utmi phy's clk as EXTREFCLK (XXTI) which is internal clock
- * from clock core. Further sets the FSEL values for HighSpeed operations.
- */
-static unsigned int
-exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
-{
-       u32 reg;
-       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
-       /* restore any previous reference clock settings */
-       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
-
-       reg &= ~PHYCLKRST_REFCLKSEL_MASK;
-       reg |=  PHYCLKRST_REFCLKSEL_EXT_REFCLK;
-
-       reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
-               PHYCLKRST_MPLL_MULTIPLIER_MASK |
-               PHYCLKRST_SSC_REFCLKSEL_MASK;
-       reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
-
-       return reg;
-}
-
-static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
-{
-       u32 reg;
-
-       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
-       /* Set Tx De-Emphasis level */
-       reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
-       reg |=  PHYPARAM1_PCS_TXDEEMPH;
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
-
-       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
-       reg &= ~PHYTEST_POWERDOWN_SSP;
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
-}
-
-static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
-{
-       u32 reg;
-
-       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
-       /* Set Loss-of-Signal Detector sensitivity */
-       reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
-       reg |=  PHYPARAM0_REF_LOSLEVEL;
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
-
-       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
-       /* Set Tx De-Emphasis level */
-       reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
-       reg |=  PHYPARAM1_PCS_TXDEEMPH;
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
-
-       /* UTMI Power Control */
-       writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
-
-       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
-       reg &= ~PHYTEST_POWERDOWN_HSP;
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
-}
-
-static int exynos5_usbdrd_phy_init(struct phy *phy)
-{
-       int ret;
-       u32 reg;
-       struct phy_usb_instance *inst = phy_get_drvdata(phy);
-       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
-       ret = clk_prepare_enable(phy_drd->clk);
-       if (ret)
-               return ret;
-
-       /* Reset USB 3.0 PHY */
-       writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
-       writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME);
-
-       /*
-        * Setting the Frame length Adj value[6:1] to default 0x20
-        * See xHCI 1.0 spec, 5.2.4
-        */
-       reg =   LINKSYSTEM_XHCI_VERSION_CONTROL |
-               LINKSYSTEM_FLADJ(0x20);
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
-
-       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
-       /* Select PHY CLK source */
-       reg &= ~PHYPARAM0_REF_USE_PAD;
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
-
-       /* This bit must be set for both HS and SS operations */
-       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
-       reg |= PHYUTMICLKSEL_UTMI_CLKSEL;
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
-
-       /* UTMI or PIPE3 specific init */
-       inst->phy_cfg->phy_init(phy_drd);
-
-       /* reference clock settings */
-       reg = inst->phy_cfg->set_refclk(inst);
-
-               /* Digital power supply in normal operating mode */
-       reg |=  PHYCLKRST_RETENABLEN |
-               /* Enable ref clock for SS function */
-               PHYCLKRST_REF_SSP_EN |
-               /* Enable spread spectrum */
-               PHYCLKRST_SSC_EN |
-               /* Power down HS Bias and PLL blocks in suspend mode */
-               PHYCLKRST_COMMONONN |
-               /* Reset the port */
-               PHYCLKRST_PORTRESET;
-
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
-
-       udelay(10);
-
-       reg &= ~PHYCLKRST_PORTRESET;
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
-
-       clk_disable_unprepare(phy_drd->clk);
-
-       return 0;
-}
-
-static int exynos5_usbdrd_phy_exit(struct phy *phy)
-{
-       int ret;
-       u32 reg;
-       struct phy_usb_instance *inst = phy_get_drvdata(phy);
-       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
-       ret = clk_prepare_enable(phy_drd->clk);
-       if (ret)
-               return ret;
-
-       reg =   PHYUTMI_OTGDISABLE |
-               PHYUTMI_FORCESUSPEND |
-               PHYUTMI_FORCESLEEP;
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
-
-       /* Resetting the PHYCLKRST enable bits to reduce leakage current */
-       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
-       reg &= ~(PHYCLKRST_REF_SSP_EN |
-                PHYCLKRST_SSC_EN |
-                PHYCLKRST_COMMONONN);
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
-
-       /* Control PHYTEST to remove leakage current */
-       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
-       reg |=  PHYTEST_POWERDOWN_SSP |
-               PHYTEST_POWERDOWN_HSP;
-       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
-
-       clk_disable_unprepare(phy_drd->clk);
-
-       return 0;
-}
-
-static int exynos5_usbdrd_phy_power_on(struct phy *phy)
-{
-       int ret;
-       struct phy_usb_instance *inst = phy_get_drvdata(phy);
-       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
-       dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
-
-       clk_prepare_enable(phy_drd->ref_clk);
-       if (!phy_drd->drv_data->has_common_clk_gate) {
-               clk_prepare_enable(phy_drd->pipeclk);
-               clk_prepare_enable(phy_drd->utmiclk);
-               clk_prepare_enable(phy_drd->itpclk);
-       }
-
-       /* Enable VBUS supply */
-       if (phy_drd->vbus_boost) {
-               ret = regulator_enable(phy_drd->vbus_boost);
-               if (ret) {
-                       dev_err(phy_drd->dev,
-                               "Failed to enable VBUS boost supply\n");
-                       goto fail_vbus;
-               }
-       }
-
-       if (phy_drd->vbus) {
-               ret = regulator_enable(phy_drd->vbus);
-               if (ret) {
-                       dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
-                       goto fail_vbus_boost;
-               }
-       }
-
-       /* Power-on PHY*/
-       inst->phy_cfg->phy_isol(inst, 0);
-
-       return 0;
-
-fail_vbus_boost:
-       if (phy_drd->vbus_boost)
-               regulator_disable(phy_drd->vbus_boost);
-
-fail_vbus:
-       clk_disable_unprepare(phy_drd->ref_clk);
-       if (!phy_drd->drv_data->has_common_clk_gate) {
-               clk_disable_unprepare(phy_drd->itpclk);
-               clk_disable_unprepare(phy_drd->utmiclk);
-               clk_disable_unprepare(phy_drd->pipeclk);
-       }
-
-       return ret;
-}
-
-static int exynos5_usbdrd_phy_power_off(struct phy *phy)
-{
-       struct phy_usb_instance *inst = phy_get_drvdata(phy);
-       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
-       dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");
-
-       /* Power-off the PHY */
-       inst->phy_cfg->phy_isol(inst, 1);
-
-       /* Disable VBUS supply */
-       if (phy_drd->vbus)
-               regulator_disable(phy_drd->vbus);
-       if (phy_drd->vbus_boost)
-               regulator_disable(phy_drd->vbus_boost);
-
-       clk_disable_unprepare(phy_drd->ref_clk);
-       if (!phy_drd->drv_data->has_common_clk_gate) {
-               clk_disable_unprepare(phy_drd->itpclk);
-               clk_disable_unprepare(phy_drd->pipeclk);
-               clk_disable_unprepare(phy_drd->utmiclk);
-       }
-
-       return 0;
-}
-
-static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
-                                       struct of_phandle_args *args)
-{
-       struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);
-
-       if (WARN_ON(args->args[0] >= EXYNOS5_DRDPHYS_NUM))
-               return ERR_PTR(-ENODEV);
-
-       return phy_drd->phys[args->args[0]].phy;
-}
-
-static const struct phy_ops exynos5_usbdrd_phy_ops = {
-       .init           = exynos5_usbdrd_phy_init,
-       .exit           = exynos5_usbdrd_phy_exit,
-       .power_on       = exynos5_usbdrd_phy_power_on,
-       .power_off      = exynos5_usbdrd_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
-{
-       unsigned long ref_rate;
-       int ret;
-
-       phy_drd->clk = devm_clk_get(phy_drd->dev, "phy");
-       if (IS_ERR(phy_drd->clk)) {
-               dev_err(phy_drd->dev, "Failed to get phy clock\n");
-               return PTR_ERR(phy_drd->clk);
-       }
-
-       phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref");
-       if (IS_ERR(phy_drd->ref_clk)) {
-               dev_err(phy_drd->dev, "Failed to get phy reference clock\n");
-               return PTR_ERR(phy_drd->ref_clk);
-       }
-       ref_rate = clk_get_rate(phy_drd->ref_clk);
-
-       ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
-       if (ret) {
-               dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
-                       ref_rate);
-               return ret;
-       }
-
-       if (!phy_drd->drv_data->has_common_clk_gate) {
-               phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe");
-               if (IS_ERR(phy_drd->pipeclk)) {
-                       dev_info(phy_drd->dev,
-                                "PIPE3 phy operational clock not specified\n");
-                       phy_drd->pipeclk = NULL;
-               }
-
-               phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi");
-               if (IS_ERR(phy_drd->utmiclk)) {
-                       dev_info(phy_drd->dev,
-                                "UTMI phy operational clock not specified\n");
-                       phy_drd->utmiclk = NULL;
-               }
-
-               phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp");
-               if (IS_ERR(phy_drd->itpclk)) {
-                       dev_info(phy_drd->dev,
-                                "ITP clock from main OSC not specified\n");
-                       phy_drd->itpclk = NULL;
-               }
-       }
-
-       return 0;
-}
-
-static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
-       {
-               .id             = EXYNOS5_DRDPHY_UTMI,
-               .phy_isol       = exynos5_usbdrd_phy_isol,
-               .phy_init       = exynos5_usbdrd_utmi_init,
-               .set_refclk     = exynos5_usbdrd_utmi_set_refclk,
-       },
-       {
-               .id             = EXYNOS5_DRDPHY_PIPE3,
-               .phy_isol       = exynos5_usbdrd_phy_isol,
-               .phy_init       = exynos5_usbdrd_pipe3_init,
-               .set_refclk     = exynos5_usbdrd_pipe3_set_refclk,
-       },
-};
-
-static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
-       .phy_cfg                = phy_cfg_exynos5,
-       .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
-       .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
-       .has_common_clk_gate    = true,
-};
-
-static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
-       .phy_cfg                = phy_cfg_exynos5,
-       .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
-       .has_common_clk_gate    = true,
-};
-
-static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
-       .phy_cfg                = phy_cfg_exynos5,
-       .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
-       .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL,
-       .has_common_clk_gate    = false,
-};
-
-static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
-       .phy_cfg                = phy_cfg_exynos5,
-       .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
-       .has_common_clk_gate    = false,
-};
-
-static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
-       {
-               .compatible = "samsung,exynos5250-usbdrd-phy",
-               .data = &exynos5250_usbdrd_phy
-       }, {
-               .compatible = "samsung,exynos5420-usbdrd-phy",
-               .data = &exynos5420_usbdrd_phy
-       }, {
-               .compatible = "samsung,exynos5433-usbdrd-phy",
-               .data = &exynos5433_usbdrd_phy
-       }, {
-               .compatible = "samsung,exynos7-usbdrd-phy",
-               .data = &exynos7_usbdrd_phy
-       },
-       { },
-};
-MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);
-
-static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *node = dev->of_node;
-       struct exynos5_usbdrd_phy *phy_drd;
-       struct phy_provider *phy_provider;
-       struct resource *res;
-       const struct of_device_id *match;
-       const struct exynos5_usbdrd_phy_drvdata *drv_data;
-       struct regmap *reg_pmu;
-       u32 pmu_offset;
-       int i, ret;
-       int channel;
-
-       phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL);
-       if (!phy_drd)
-               return -ENOMEM;
-
-       dev_set_drvdata(dev, phy_drd);
-       phy_drd->dev = dev;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       phy_drd->reg_phy = devm_ioremap_resource(dev, res);
-       if (IS_ERR(phy_drd->reg_phy))
-               return PTR_ERR(phy_drd->reg_phy);
-
-       match = of_match_node(exynos5_usbdrd_phy_of_match, pdev->dev.of_node);
-
-       drv_data = match->data;
-       phy_drd->drv_data = drv_data;
-
-       ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
-       if (ret) {
-               dev_err(dev, "Failed to initialize clocks\n");
-               return ret;
-       }
-
-       reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
-                                                  "samsung,pmu-syscon");
-       if (IS_ERR(reg_pmu)) {
-               dev_err(dev, "Failed to lookup PMU regmap\n");
-               return PTR_ERR(reg_pmu);
-       }
-
-       /*
-        * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with
-        * each having separate power control registers.
-        * 'channel' facilitates to set such registers.
-        */
-       channel = of_alias_get_id(node, "usbdrdphy");
-       if (channel < 0)
-               dev_dbg(dev, "Not a multi-controller usbdrd phy\n");
-
-       switch (channel) {
-       case 1:
-               pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy;
-               break;
-       case 0:
-       default:
-               pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy;
-               break;
-       }
-
-       /* Get Vbus regulators */
-       phy_drd->vbus = devm_regulator_get(dev, "vbus");
-       if (IS_ERR(phy_drd->vbus)) {
-               ret = PTR_ERR(phy_drd->vbus);
-               if (ret == -EPROBE_DEFER)
-                       return ret;
-
-               dev_warn(dev, "Failed to get VBUS supply regulator\n");
-               phy_drd->vbus = NULL;
-       }
-
-       phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost");
-       if (IS_ERR(phy_drd->vbus_boost)) {
-               ret = PTR_ERR(phy_drd->vbus_boost);
-               if (ret == -EPROBE_DEFER)
-                       return ret;
-
-               dev_warn(dev, "Failed to get VBUS boost supply regulator\n");
-               phy_drd->vbus_boost = NULL;
-       }
-
-       dev_vdbg(dev, "Creating usbdrd_phy phy\n");
-
-       for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
-               struct phy *phy = devm_phy_create(dev, NULL,
-                                                 &exynos5_usbdrd_phy_ops);
-               if (IS_ERR(phy)) {
-                       dev_err(dev, "Failed to create usbdrd_phy phy\n");
-                       return PTR_ERR(phy);
-               }
-
-               phy_drd->phys[i].phy = phy;
-               phy_drd->phys[i].index = i;
-               phy_drd->phys[i].reg_pmu = reg_pmu;
-               phy_drd->phys[i].pmu_offset = pmu_offset;
-               phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i];
-               phy_set_drvdata(phy, &phy_drd->phys[i]);
-       }
-
-       phy_provider = devm_of_phy_provider_register(dev,
-                                                    exynos5_usbdrd_phy_xlate);
-       if (IS_ERR(phy_provider)) {
-               dev_err(phy_drd->dev, "Failed to register phy provider\n");
-               return PTR_ERR(phy_provider);
-       }
-
-       return 0;
-}
-
-static struct platform_driver exynos5_usb3drd_phy = {
-       .probe  = exynos5_usbdrd_phy_probe,
-       .driver = {
-               .of_match_table = exynos5_usbdrd_phy_of_match,
-               .name           = "exynos5_usb3drd_phy",
-       }
-};
-
-module_platform_driver(exynos5_usb3drd_phy);
-MODULE_DESCRIPTION("Samsung EXYNOS5 SoCs USB 3.0 DRD controller PHY driver");
-MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:exynos5_usb3drd_phy");
diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c
deleted file mode 100644 (file)
index 60e13af..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Samsung SATA SerDes(PHY) driver
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Authors: Girish K S <ks.giri@samsung.com>
- *         Yuvaraj Kumar C D <yuvaraj.cd@samsung.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.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/kernel.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/spinlock.h>
-#include <linux/mfd/syscon.h>
-
-#define SATAPHY_CONTROL_OFFSET         0x0724
-#define EXYNOS5_SATAPHY_PMU_ENABLE     BIT(0)
-#define EXYNOS5_SATA_RESET             0x4
-#define RESET_GLOBAL_RST_N             BIT(0)
-#define RESET_CMN_RST_N                        BIT(1)
-#define RESET_CMN_BLOCK_RST_N          BIT(2)
-#define RESET_CMN_I2C_RST_N            BIT(3)
-#define RESET_TX_RX_PIPE_RST_N         BIT(4)
-#define RESET_TX_RX_BLOCK_RST_N                BIT(5)
-#define RESET_TX_RX_I2C_RST_N          (BIT(6) | BIT(7))
-#define LINK_RESET                     0xf0000
-#define EXYNOS5_SATA_MODE0             0x10
-#define SATA_SPD_GEN3                  BIT(1)
-#define EXYNOS5_SATA_CTRL0             0x14
-#define CTRL0_P0_PHY_CALIBRATED_SEL    BIT(9)
-#define CTRL0_P0_PHY_CALIBRATED                BIT(8)
-#define EXYNOS5_SATA_PHSATA_CTRLM      0xe0
-#define PHCTRLM_REF_RATE               BIT(1)
-#define PHCTRLM_HIGH_SPEED             BIT(0)
-#define EXYNOS5_SATA_PHSATA_STATM      0xf0
-#define PHSTATM_PLL_LOCKED             BIT(0)
-
-#define PHY_PLL_TIMEOUT (usecs_to_jiffies(1000))
-
-struct exynos_sata_phy {
-       struct phy *phy;
-       struct clk *phyclk;
-       void __iomem *regs;
-       struct regmap *pmureg;
-       struct i2c_client *client;
-};
-
-static int wait_for_reg_status(void __iomem *base, u32 reg, u32 checkbit,
-                               u32 status)
-{
-       unsigned long timeout = jiffies + PHY_PLL_TIMEOUT;
-
-       while (time_before(jiffies, timeout)) {
-               if ((readl(base + reg) & checkbit) == status)
-                       return 0;
-       }
-
-       return -EFAULT;
-}
-
-static int exynos_sata_phy_power_on(struct phy *phy)
-{
-       struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
-
-       return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
-                       EXYNOS5_SATAPHY_PMU_ENABLE, true);
-
-}
-
-static int exynos_sata_phy_power_off(struct phy *phy)
-{
-       struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
-
-       return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
-                       EXYNOS5_SATAPHY_PMU_ENABLE, false);
-
-}
-
-static int exynos_sata_phy_init(struct phy *phy)
-{
-       u32 val = 0;
-       int ret = 0;
-       u8 buf[] = { 0x3a, 0x0b };
-       struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
-
-       ret = regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
-                       EXYNOS5_SATAPHY_PMU_ENABLE, true);
-       if (ret != 0)
-               dev_err(&sata_phy->phy->dev, "phy init failed\n");
-
-       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
-       val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
-       val |= RESET_GLOBAL_RST_N | RESET_CMN_RST_N | RESET_CMN_BLOCK_RST_N
-               | RESET_CMN_I2C_RST_N | RESET_TX_RX_PIPE_RST_N
-               | RESET_TX_RX_BLOCK_RST_N | RESET_TX_RX_I2C_RST_N;
-       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
-       val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
-       val |= LINK_RESET;
-       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
-       val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
-       val |= RESET_CMN_RST_N;
-       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
-       val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
-       val &= ~PHCTRLM_REF_RATE;
-       writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
-
-       /* High speed enable for Gen3 */
-       val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
-       val |= PHCTRLM_HIGH_SPEED;
-       writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
-
-       val = readl(sata_phy->regs + EXYNOS5_SATA_CTRL0);
-       val |= CTRL0_P0_PHY_CALIBRATED_SEL | CTRL0_P0_PHY_CALIBRATED;
-       writel(val, sata_phy->regs + EXYNOS5_SATA_CTRL0);
-
-       val = readl(sata_phy->regs + EXYNOS5_SATA_MODE0);
-       val |= SATA_SPD_GEN3;
-       writel(val, sata_phy->regs + EXYNOS5_SATA_MODE0);
-
-       ret = i2c_master_send(sata_phy->client, buf, sizeof(buf));
-       if (ret < 0)
-               return ret;
-
-       /* release cmu reset */
-       val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
-       val &= ~RESET_CMN_RST_N;
-       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
-       val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
-       val |= RESET_CMN_RST_N;
-       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
-       ret = wait_for_reg_status(sata_phy->regs,
-                               EXYNOS5_SATA_PHSATA_STATM,
-                               PHSTATM_PLL_LOCKED, 1);
-       if (ret < 0)
-               dev_err(&sata_phy->phy->dev,
-                       "PHY PLL locking failed\n");
-       return ret;
-}
-
-static const struct phy_ops exynos_sata_phy_ops = {
-       .init           = exynos_sata_phy_init,
-       .power_on       = exynos_sata_phy_power_on,
-       .power_off      = exynos_sata_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static int exynos_sata_phy_probe(struct platform_device *pdev)
-{
-       struct exynos_sata_phy *sata_phy;
-       struct device *dev = &pdev->dev;
-       struct resource *res;
-       struct phy_provider *phy_provider;
-       struct device_node *node;
-       int ret = 0;
-
-       sata_phy = devm_kzalloc(dev, sizeof(*sata_phy), GFP_KERNEL);
-       if (!sata_phy)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       sata_phy->regs = devm_ioremap_resource(dev, res);
-       if (IS_ERR(sata_phy->regs))
-               return PTR_ERR(sata_phy->regs);
-
-       sata_phy->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
-                                       "samsung,syscon-phandle");
-       if (IS_ERR(sata_phy->pmureg)) {
-               dev_err(dev, "syscon regmap lookup failed.\n");
-               return PTR_ERR(sata_phy->pmureg);
-       }
-
-       node = of_parse_phandle(dev->of_node,
-                       "samsung,exynos-sataphy-i2c-phandle", 0);
-       if (!node)
-               return -EINVAL;
-
-       sata_phy->client = of_find_i2c_device_by_node(node);
-       if (!sata_phy->client)
-               return -EPROBE_DEFER;
-
-       dev_set_drvdata(dev, sata_phy);
-
-       sata_phy->phyclk = devm_clk_get(dev, "sata_phyctrl");
-       if (IS_ERR(sata_phy->phyclk)) {
-               dev_err(dev, "failed to get clk for PHY\n");
-               return PTR_ERR(sata_phy->phyclk);
-       }
-
-       ret = clk_prepare_enable(sata_phy->phyclk);
-       if (ret < 0) {
-               dev_err(dev, "failed to enable source clk\n");
-               return ret;
-       }
-
-       sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops);
-       if (IS_ERR(sata_phy->phy)) {
-               clk_disable_unprepare(sata_phy->phyclk);
-               dev_err(dev, "failed to create PHY\n");
-               return PTR_ERR(sata_phy->phy);
-       }
-
-       phy_set_drvdata(sata_phy->phy, sata_phy);
-
-       phy_provider = devm_of_phy_provider_register(dev,
-                                       of_phy_simple_xlate);
-       if (IS_ERR(phy_provider)) {
-               clk_disable_unprepare(sata_phy->phyclk);
-               return PTR_ERR(phy_provider);
-       }
-
-       return 0;
-}
-
-static const struct of_device_id exynos_sata_phy_of_match[] = {
-       { .compatible = "samsung,exynos5250-sata-phy" },
-       { },
-};
-MODULE_DEVICE_TABLE(of, exynos_sata_phy_of_match);
-
-static struct platform_driver exynos_sata_phy_driver = {
-       .probe  = exynos_sata_phy_probe,
-       .driver = {
-               .of_match_table = exynos_sata_phy_of_match,
-               .name  = "samsung,sata-phy",
-       }
-};
-module_platform_driver(exynos_sata_phy_driver);
-
-MODULE_DESCRIPTION("Samsung SerDes PHY driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>");
-MODULE_AUTHOR("Yuvaraj C D <yuvaraj.cd@samsung.com>");
diff --git a/drivers/phy/phy-exynos5250-usb2.c b/drivers/phy/phy-exynos5250-usb2.c
deleted file mode 100644 (file)
index aad8062..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Kamil Debski <k.debski@samsung.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.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-#include "phy-samsung-usb2.h"
-
-/* Exynos USB PHY registers */
-#define EXYNOS_5250_REFCLKSEL_CRYSTAL  0x0
-#define EXYNOS_5250_REFCLKSEL_XO       0x1
-#define EXYNOS_5250_REFCLKSEL_CLKCORE  0x2
-
-#define EXYNOS_5250_FSEL_9MHZ6         0x0
-#define EXYNOS_5250_FSEL_10MHZ         0x1
-#define EXYNOS_5250_FSEL_12MHZ         0x2
-#define EXYNOS_5250_FSEL_19MHZ2                0x3
-#define EXYNOS_5250_FSEL_20MHZ         0x4
-#define EXYNOS_5250_FSEL_24MHZ         0x5
-#define EXYNOS_5250_FSEL_50MHZ         0x7
-
-/* Normal host */
-#define EXYNOS_5250_HOSTPHYCTRL0                       0x0
-
-#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL           BIT(31)
-#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT       19
-#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_MASK        \
-               (0x3 << EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT)
-#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT            16
-#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK \
-               (0x7 << EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT)
-#define EXYNOS_5250_HOSTPHYCTRL0_TESTBURNIN            BIT(11)
-#define EXYNOS_5250_HOSTPHYCTRL0_RETENABLE             BIT(10)
-#define EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N           BIT(9)
-#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_MASK                (0x3 << 7)
-#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_DUAL                (0x0 << 7)
-#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ID0         (0x1 << 7)
-#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ANALOGTEST  (0x2 << 7)
-#define EXYNOS_5250_HOSTPHYCTRL0_SIDDQ                 BIT(6)
-#define EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP            BIT(5)
-#define EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND          BIT(4)
-#define EXYNOS_5250_HOSTPHYCTRL0_WORDINTERFACE         BIT(3)
-#define EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST             BIT(2)
-#define EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST             BIT(1)
-#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST              BIT(0)
-
-/* HSIC0 & HSIC1 */
-#define EXYNOS_5250_HSICPHYCTRL1                       0x10
-#define EXYNOS_5250_HSICPHYCTRL2                       0x20
-
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_MASK                (0x3 << 23)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT     (0x2 << 23)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_MASK                (0x7f << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12          (0x24 << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_15          (0x1c << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_16          (0x1a << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_19_2                (0x15 << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_20          (0x14 << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_SIDDQ                 BIT(6)
-#define EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP            BIT(5)
-#define EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND          BIT(4)
-#define EXYNOS_5250_HSICPHYCTRLX_WORDINTERFACE         BIT(3)
-#define EXYNOS_5250_HSICPHYCTRLX_UTMISWRST             BIT(2)
-#define EXYNOS_5250_HSICPHYCTRLX_PHYSWRST              BIT(0)
-
-/* EHCI control */
-#define EXYNOS_5250_HOSTEHCICTRL                       0x30
-#define EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN         BIT(29)
-#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR4              BIT(28)
-#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR8              BIT(27)
-#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR16             BIT(26)
-#define EXYNOS_5250_HOSTEHCICTRL_AUTOPPDONOVRCUREN     BIT(25)
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT       19
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK        \
-               (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT       13
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_MASK        \
-               (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT)
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL2_SHIFT       7
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK        \
-               (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT    1
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_MASK \
-               (0x1 << EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT)
-#define EXYNOS_5250_HOSTEHCICTRL_SIMULATIONMODE                BIT(0)
-
-/* OHCI control */
-#define EXYNOS_5250_HOSTOHCICTRL                        0x34
-#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT     1
-#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_MASK \
-               (0x3ff << EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT)
-#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVALEN         BIT(0)
-
-/* USBOTG */
-#define EXYNOS_5250_USBOTGSYS                          0x38
-#define EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET         BIT(14)
-#define EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG         BIT(13)
-#define EXYNOS_5250_USBOTGSYS_PHY_SW_RST               BIT(12)
-#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT          9
-#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK \
-               (0x3 << EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT)
-#define EXYNOS_5250_USBOTGSYS_ID_PULLUP                        BIT(8)
-#define EXYNOS_5250_USBOTGSYS_COMMON_ON                        BIT(7)
-#define EXYNOS_5250_USBOTGSYS_FSEL_SHIFT               4
-#define EXYNOS_5250_USBOTGSYS_FSEL_MASK \
-               (0x3 << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT)
-#define EXYNOS_5250_USBOTGSYS_FORCE_SLEEP              BIT(3)
-#define EXYNOS_5250_USBOTGSYS_OTGDISABLE               BIT(2)
-#define EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG               BIT(1)
-#define EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND            BIT(0)
-
-/* Isolation, configured in the power management unit */
-#define EXYNOS_5250_USB_ISOL_OTG_OFFSET                0x704
-#define EXYNOS_5250_USB_ISOL_OTG               BIT(0)
-#define EXYNOS_5250_USB_ISOL_HOST_OFFSET       0x708
-#define EXYNOS_5250_USB_ISOL_HOST              BIT(0)
-
-/* Mode swtich register */
-#define EXYNOS_5250_MODE_SWITCH_OFFSET         0x230
-#define EXYNOS_5250_MODE_SWITCH_MASK           1
-#define EXYNOS_5250_MODE_SWITCH_DEVICE         0
-#define EXYNOS_5250_MODE_SWITCH_HOST           1
-
-enum exynos4x12_phy_id {
-       EXYNOS5250_DEVICE,
-       EXYNOS5250_HOST,
-       EXYNOS5250_HSIC0,
-       EXYNOS5250_HSIC1,
-       EXYNOS5250_NUM_PHYS,
-};
-
-/*
- * exynos5250_rate_to_clk() converts the supplied clock rate to the value that
- * can be written to the phy register.
- */
-static int exynos5250_rate_to_clk(unsigned long rate, u32 *reg)
-{
-       /* EXYNOS_5250_FSEL_MASK */
-
-       switch (rate) {
-       case 9600 * KHZ:
-               *reg = EXYNOS_5250_FSEL_9MHZ6;
-               break;
-       case 10 * MHZ:
-               *reg = EXYNOS_5250_FSEL_10MHZ;
-               break;
-       case 12 * MHZ:
-               *reg = EXYNOS_5250_FSEL_12MHZ;
-               break;
-       case 19200 * KHZ:
-               *reg = EXYNOS_5250_FSEL_19MHZ2;
-               break;
-       case 20 * MHZ:
-               *reg = EXYNOS_5250_FSEL_20MHZ;
-               break;
-       case 24 * MHZ:
-               *reg = EXYNOS_5250_FSEL_24MHZ;
-               break;
-       case 50 * MHZ:
-               *reg = EXYNOS_5250_FSEL_50MHZ;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       u32 offset;
-       u32 mask;
-
-       switch (inst->cfg->id) {
-       case EXYNOS5250_DEVICE:
-               offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET;
-               mask = EXYNOS_5250_USB_ISOL_OTG;
-               break;
-       case EXYNOS5250_HOST:
-               offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET;
-               mask = EXYNOS_5250_USB_ISOL_HOST;
-               break;
-       default:
-               return;
-       }
-
-       regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
-}
-
-static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       u32 ctrl0;
-       u32 otg;
-       u32 ehci;
-       u32 ohci;
-       u32 hsic;
-
-       switch (inst->cfg->id) {
-       case EXYNOS5250_DEVICE:
-               regmap_update_bits(drv->reg_sys,
-                                  EXYNOS_5250_MODE_SWITCH_OFFSET,
-                                  EXYNOS_5250_MODE_SWITCH_MASK,
-                                  EXYNOS_5250_MODE_SWITCH_DEVICE);
-
-               /* OTG configuration */
-               otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
-               /* The clock */
-               otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
-               otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
-               /* Reset */
-               otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
-                       EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
-                       EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
-               otg |=  EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
-                       EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
-                       EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
-                       EXYNOS_5250_USBOTGSYS_OTGDISABLE;
-               /* Ref clock */
-               otg &=  ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
-               otg |=  EXYNOS_5250_REFCLKSEL_CLKCORE <<
-                                       EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
-               writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
-               udelay(100);
-               otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
-                       EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
-                       EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
-                       EXYNOS_5250_USBOTGSYS_OTGDISABLE);
-               writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
-
-
-               break;
-       case EXYNOS5250_HOST:
-       case EXYNOS5250_HSIC0:
-       case EXYNOS5250_HSIC1:
-               /* Host registers configuration */
-               ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
-               /* The clock */
-               ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK;
-               ctrl0 |= drv->ref_reg_val <<
-                                       EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT;
-
-               /* Reset */
-               ctrl0 &=        ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
-                               EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL |
-                               EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
-                               EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
-                               EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP);
-               ctrl0 |=        EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
-                               EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST |
-                               EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N;
-               writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
-               udelay(10);
-               ctrl0 &=        ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
-                               EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST);
-               writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
-
-               /* OTG configuration */
-               otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
-               /* The clock */
-               otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
-               otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
-               /* Reset */
-               otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
-                       EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
-                       EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
-               otg |=  EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
-                       EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
-                       EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
-                       EXYNOS_5250_USBOTGSYS_OTGDISABLE;
-               /* Ref clock */
-               otg &=  ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
-               otg |=  EXYNOS_5250_REFCLKSEL_CLKCORE <<
-                                       EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
-               writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
-               udelay(10);
-               otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
-                       EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
-                       EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET);
-
-               /* HSIC phy configuration */
-               hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
-                               EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
-                               EXYNOS_5250_HSICPHYCTRLX_PHYSWRST);
-               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
-               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
-               udelay(10);
-               hsic &= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST;
-               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
-               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
-               /* The following delay is necessary for the reset sequence to be
-                * completed */
-               udelay(80);
-
-               /* Enable EHCI DMA burst */
-               ehci = readl(drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
-               ehci |= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN |
-                       EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 |
-                       EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 |
-                       EXYNOS_5250_HOSTEHCICTRL_ENAINCR16;
-               writel(ehci, drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
-
-               /* OHCI settings */
-               ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
-               /* Following code is based on the old driver */
-               ohci |= 0x1 << 3;
-               writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
-
-               break;
-       }
-       exynos5250_isol(inst, 0);
-
-       return 0;
-}
-
-static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       u32 ctrl0;
-       u32 otg;
-       u32 hsic;
-
-       exynos5250_isol(inst, 1);
-
-       switch (inst->cfg->id) {
-       case EXYNOS5250_DEVICE:
-               otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
-               otg |= (EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
-                       EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG |
-                       EXYNOS_5250_USBOTGSYS_FORCE_SLEEP);
-               writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
-               break;
-       case EXYNOS5250_HOST:
-               ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
-               ctrl0 |= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
-                               EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
-                               EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP |
-                               EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
-                               EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL);
-               writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
-               break;
-       case EXYNOS5250_HSIC0:
-       case EXYNOS5250_HSIC1:
-               hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
-                               EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
-                               EXYNOS_5250_HSICPHYCTRLX_SIDDQ |
-                               EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP |
-                               EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND
-                               );
-               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
-               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
-               break;
-       }
-
-       return 0;
-}
-
-
-static const struct samsung_usb2_common_phy exynos5250_phys[] = {
-       {
-               .label          = "device",
-               .id             = EXYNOS5250_DEVICE,
-               .power_on       = exynos5250_power_on,
-               .power_off      = exynos5250_power_off,
-       },
-       {
-               .label          = "host",
-               .id             = EXYNOS5250_HOST,
-               .power_on       = exynos5250_power_on,
-               .power_off      = exynos5250_power_off,
-       },
-       {
-               .label          = "hsic0",
-               .id             = EXYNOS5250_HSIC0,
-               .power_on       = exynos5250_power_on,
-               .power_off      = exynos5250_power_off,
-       },
-       {
-               .label          = "hsic1",
-               .id             = EXYNOS5250_HSIC1,
-               .power_on       = exynos5250_power_on,
-               .power_off      = exynos5250_power_off,
-       },
-};
-
-const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = {
-       .has_mode_switch        = 1,
-       .num_phys               = EXYNOS5250_NUM_PHYS,
-       .phys                   = exynos5250_phys,
-       .rate_to_clk            = exynos5250_rate_to_clk,
-};
diff --git a/drivers/phy/phy-hi6220-usb.c b/drivers/phy/phy-hi6220-usb.c
deleted file mode 100644 (file)
index 398c102..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2015 Linaro Ltd.
- * Copyright (c) 2015 Hisilicon Limited.
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-
-#define SC_PERIPH_CTRL4                        0x00c
-
-#define CTRL4_PICO_SIDDQ               BIT(6)
-#define CTRL4_PICO_OGDISABLE           BIT(8)
-#define CTRL4_PICO_VBUSVLDEXT          BIT(10)
-#define CTRL4_PICO_VBUSVLDEXTSEL       BIT(11)
-#define CTRL4_OTG_PHY_SEL              BIT(21)
-
-#define SC_PERIPH_CTRL5                        0x010
-
-#define CTRL5_USBOTG_RES_SEL           BIT(3)
-#define CTRL5_PICOPHY_ACAENB           BIT(4)
-#define CTRL5_PICOPHY_BC_MODE          BIT(5)
-#define CTRL5_PICOPHY_CHRGSEL          BIT(6)
-#define CTRL5_PICOPHY_VDATSRCEND       BIT(7)
-#define CTRL5_PICOPHY_VDATDETENB       BIT(8)
-#define CTRL5_PICOPHY_DCDENB           BIT(9)
-#define CTRL5_PICOPHY_IDDIG            BIT(10)
-
-#define SC_PERIPH_CTRL8                        0x018
-#define SC_PERIPH_RSTEN0               0x300
-#define SC_PERIPH_RSTDIS0              0x304
-
-#define RST0_USBOTG_BUS                        BIT(4)
-#define RST0_POR_PICOPHY               BIT(5)
-#define RST0_USBOTG                    BIT(6)
-#define RST0_USBOTG_32K                        BIT(7)
-
-#define EYE_PATTERN_PARA               0x7053348c
-
-struct hi6220_priv {
-       struct regmap *reg;
-       struct device *dev;
-};
-
-static void hi6220_phy_init(struct hi6220_priv *priv)
-{
-       struct regmap *reg = priv->reg;
-       u32 val, mask;
-
-       val = RST0_USBOTG_BUS | RST0_POR_PICOPHY |
-             RST0_USBOTG | RST0_USBOTG_32K;
-       mask = val;
-       regmap_update_bits(reg, SC_PERIPH_RSTEN0, mask, val);
-       regmap_update_bits(reg, SC_PERIPH_RSTDIS0, mask, val);
-}
-
-static int hi6220_phy_setup(struct hi6220_priv *priv, bool on)
-{
-       struct regmap *reg = priv->reg;
-       u32 val, mask;
-       int ret;
-
-       if (on) {
-               val = CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB;
-               mask = val | CTRL5_PICOPHY_BC_MODE;
-               ret = regmap_update_bits(reg, SC_PERIPH_CTRL5, mask, val);
-               if (ret)
-                       goto out;
-
-               val =  CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL |
-                      CTRL4_OTG_PHY_SEL;
-               mask = val | CTRL4_PICO_SIDDQ | CTRL4_PICO_OGDISABLE;
-               ret = regmap_update_bits(reg, SC_PERIPH_CTRL4, mask, val);
-               if (ret)
-                       goto out;
-
-               ret = regmap_write(reg, SC_PERIPH_CTRL8, EYE_PATTERN_PARA);
-               if (ret)
-                       goto out;
-       } else {
-               val = CTRL4_PICO_SIDDQ;
-               mask = val;
-               ret = regmap_update_bits(reg, SC_PERIPH_CTRL4, mask, val);
-               if (ret)
-                       goto out;
-       }
-
-       return 0;
-out:
-       dev_err(priv->dev, "failed to setup phy ret: %d\n", ret);
-       return ret;
-}
-
-static int hi6220_phy_start(struct phy *phy)
-{
-       struct hi6220_priv *priv = phy_get_drvdata(phy);
-
-       return hi6220_phy_setup(priv, true);
-}
-
-static int hi6220_phy_exit(struct phy *phy)
-{
-       struct hi6220_priv *priv = phy_get_drvdata(phy);
-
-       return hi6220_phy_setup(priv, false);
-}
-
-static const struct phy_ops hi6220_phy_ops = {
-       .init           = hi6220_phy_start,
-       .exit           = hi6220_phy_exit,
-       .owner          = THIS_MODULE,
-};
-
-static int hi6220_phy_probe(struct platform_device *pdev)
-{
-       struct phy_provider *phy_provider;
-       struct device *dev = &pdev->dev;
-       struct phy *phy;
-       struct hi6220_priv *priv;
-
-       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       priv->dev = dev;
-       priv->reg = syscon_regmap_lookup_by_phandle(dev->of_node,
-                                       "hisilicon,peripheral-syscon");
-       if (IS_ERR(priv->reg)) {
-               dev_err(dev, "no hisilicon,peripheral-syscon\n");
-               return PTR_ERR(priv->reg);
-       }
-
-       hi6220_phy_init(priv);
-
-       phy = devm_phy_create(dev, NULL, &hi6220_phy_ops);
-       if (IS_ERR(phy))
-               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 hi6220_phy_of_match[] = {
-       {.compatible = "hisilicon,hi6220-usb-phy",},
-       { },
-};
-MODULE_DEVICE_TABLE(of, hi6220_phy_of_match);
-
-static struct platform_driver hi6220_phy_driver = {
-       .probe  = hi6220_phy_probe,
-       .driver = {
-               .name   = "hi6220-usb-phy",
-               .of_match_table = hi6220_phy_of_match,
-       }
-};
-module_platform_driver(hi6220_phy_driver);
-
-MODULE_DESCRIPTION("HISILICON HI6220 USB PHY driver");
-MODULE_ALIAS("platform:hi6220-usb-phy");
-MODULE_LICENSE("GPL");
diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/phy-hix5hd2-sata.c
deleted file mode 100644 (file)
index e5ab3aa..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2014 Linaro Ltd.
- * Copyright (c) 2014 Hisilicon Limited.
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#define SATA_PHY0_CTLL         0xa0
-#define MPLL_MULTIPLIER_SHIFT  1
-#define MPLL_MULTIPLIER_MASK   0xfe
-#define MPLL_MULTIPLIER_50M    0x3c
-#define MPLL_MULTIPLIER_100M   0x1e
-#define PHY_RESET              BIT(0)
-#define REF_SSP_EN             BIT(9)
-#define SSC_EN                 BIT(10)
-#define REF_USE_PAD            BIT(23)
-
-#define SATA_PORT_PHYCTL       0x174
-#define SPEED_MODE_MASK                0x6f0000
-#define HALF_RATE_SHIFT                16
-#define PHY_CONFIG_SHIFT       18
-#define GEN2_EN_SHIFT          21
-#define SPEED_CTRL             BIT(20)
-
-#define SATA_PORT_PHYCTL1      0x148
-#define AMPLITUDE_MASK         0x3ffffe
-#define AMPLITUDE_GEN3         0x68
-#define AMPLITUDE_GEN3_SHIFT   15
-#define AMPLITUDE_GEN2         0x56
-#define AMPLITUDE_GEN2_SHIFT   8
-#define AMPLITUDE_GEN1         0x56
-#define AMPLITUDE_GEN1_SHIFT   1
-
-#define SATA_PORT_PHYCTL2      0x14c
-#define PREEMPH_MASK           0x3ffff
-#define PREEMPH_GEN3           0x20
-#define PREEMPH_GEN3_SHIFT     12
-#define PREEMPH_GEN2           0x15
-#define PREEMPH_GEN2_SHIFT     6
-#define PREEMPH_GEN1           0x5
-#define PREEMPH_GEN1_SHIFT     0
-
-struct hix5hd2_priv {
-       void __iomem    *base;
-       struct regmap   *peri_ctrl;
-};
-
-enum phy_speed_mode {
-       SPEED_MODE_GEN1 = 0,
-       SPEED_MODE_GEN2 = 1,
-       SPEED_MODE_GEN3 = 2,
-};
-
-static int hix5hd2_sata_phy_init(struct phy *phy)
-{
-       struct hix5hd2_priv *priv = phy_get_drvdata(phy);
-       u32 val, data[2];
-       int ret;
-
-       if (priv->peri_ctrl) {
-               ret = of_property_read_u32_array(phy->dev.of_node,
-                                                "hisilicon,power-reg",
-                                                &data[0], 2);
-               if (ret) {
-                       dev_err(&phy->dev, "Fail read hisilicon,power-reg\n");
-                       return ret;
-               }
-
-               regmap_update_bits(priv->peri_ctrl, data[0],
-                                  BIT(data[1]), BIT(data[1]));
-       }
-
-       /* reset phy */
-       val = readl_relaxed(priv->base + SATA_PHY0_CTLL);
-       val &= ~(MPLL_MULTIPLIER_MASK | REF_USE_PAD);
-       val |= MPLL_MULTIPLIER_50M << MPLL_MULTIPLIER_SHIFT |
-              REF_SSP_EN | PHY_RESET;
-       writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
-       msleep(20);
-       val &= ~PHY_RESET;
-       writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
-
-       val = readl_relaxed(priv->base + SATA_PORT_PHYCTL1);
-       val &= ~AMPLITUDE_MASK;
-       val |= AMPLITUDE_GEN3 << AMPLITUDE_GEN3_SHIFT |
-              AMPLITUDE_GEN2 << AMPLITUDE_GEN2_SHIFT |
-              AMPLITUDE_GEN1 << AMPLITUDE_GEN1_SHIFT;
-       writel_relaxed(val, priv->base + SATA_PORT_PHYCTL1);
-
-       val = readl_relaxed(priv->base + SATA_PORT_PHYCTL2);
-       val &= ~PREEMPH_MASK;
-       val |= PREEMPH_GEN3 << PREEMPH_GEN3_SHIFT |
-              PREEMPH_GEN2 << PREEMPH_GEN2_SHIFT |
-              PREEMPH_GEN1 << PREEMPH_GEN1_SHIFT;
-       writel_relaxed(val, priv->base + SATA_PORT_PHYCTL2);
-
-       /* ensure PHYCTRL setting takes effect */
-       val = readl_relaxed(priv->base + SATA_PORT_PHYCTL);
-       val &= ~SPEED_MODE_MASK;
-       val |= SPEED_MODE_GEN1 << HALF_RATE_SHIFT |
-              SPEED_MODE_GEN1 << PHY_CONFIG_SHIFT |
-              SPEED_MODE_GEN1 << GEN2_EN_SHIFT | SPEED_CTRL;
-       writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
-
-       msleep(20);
-       val &= ~SPEED_MODE_MASK;
-       val |= SPEED_MODE_GEN3 << HALF_RATE_SHIFT |
-              SPEED_MODE_GEN3 << PHY_CONFIG_SHIFT |
-              SPEED_MODE_GEN3 << GEN2_EN_SHIFT | SPEED_CTRL;
-       writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
-
-       val &= ~(SPEED_MODE_MASK | SPEED_CTRL);
-       val |= SPEED_MODE_GEN2 << HALF_RATE_SHIFT |
-              SPEED_MODE_GEN2 << PHY_CONFIG_SHIFT |
-              SPEED_MODE_GEN2 << GEN2_EN_SHIFT;
-       writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
-
-       return 0;
-}
-
-static const struct phy_ops hix5hd2_sata_phy_ops = {
-       .init           = hix5hd2_sata_phy_init,
-       .owner          = THIS_MODULE,
-};
-
-static int hix5hd2_sata_phy_probe(struct platform_device *pdev)
-{
-       struct phy_provider *phy_provider;
-       struct device *dev = &pdev->dev;
-       struct resource *res;
-       struct phy *phy;
-       struct hix5hd2_priv *priv;
-
-       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -EINVAL;
-
-       priv->base = devm_ioremap(dev, res->start, resource_size(res));
-       if (!priv->base)
-               return -ENOMEM;
-
-       priv->peri_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
-                                       "hisilicon,peripheral-syscon");
-       if (IS_ERR(priv->peri_ctrl))
-               priv->peri_ctrl = NULL;
-
-       phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_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 hix5hd2_sata_phy_of_match[] = {
-       {.compatible = "hisilicon,hix5hd2-sata-phy",},
-       { },
-};
-MODULE_DEVICE_TABLE(of, hix5hd2_sata_phy_of_match);
-
-static struct platform_driver hix5hd2_sata_phy_driver = {
-       .probe  = hix5hd2_sata_phy_probe,
-       .driver = {
-               .name   = "hix5hd2-sata-phy",
-               .of_match_table = hix5hd2_sata_phy_of_match,
-       }
-};
-module_platform_driver(hix5hd2_sata_phy_driver);
-
-MODULE_AUTHOR("Jiancheng Xue <xuejiancheng@huawei.com>");
-MODULE_DESCRIPTION("HISILICON HIX5HD2 SATA PHY driver");
-MODULE_ALIAS("platform:hix5hd2-sata-phy");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-meson8b-usb2.c b/drivers/phy/phy-meson8b-usb2.c
deleted file mode 100644 (file)
index 30f56a6..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Meson8b and GXBB USB2 PHY driver
- *
- * Copyright (C) 2016 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/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/reset.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/usb/of.h>
-
-#define REG_CONFIG                                     0x00
-       #define REG_CONFIG_CLK_EN                       BIT(0)
-       #define REG_CONFIG_CLK_SEL_MASK                 GENMASK(3, 1)
-       #define REG_CONFIG_CLK_DIV_MASK                 GENMASK(10, 4)
-       #define REG_CONFIG_CLK_32k_ALTSEL               BIT(15)
-       #define REG_CONFIG_TEST_TRIG                    BIT(31)
-
-#define REG_CTRL                                       0x04
-       #define REG_CTRL_SOFT_PRST                      BIT(0)
-       #define REG_CTRL_SOFT_HRESET                    BIT(1)
-       #define REG_CTRL_SS_SCALEDOWN_MODE_MASK         GENMASK(3, 2)
-       #define REG_CTRL_CLK_DET_RST                    BIT(4)
-       #define REG_CTRL_INTR_SEL                       BIT(5)
-       #define REG_CTRL_CLK_DETECTED                   BIT(8)
-       #define REG_CTRL_SOF_SENT_RCVD_TGL              BIT(9)
-       #define REG_CTRL_SOF_TOGGLE_OUT                 BIT(10)
-       #define REG_CTRL_POWER_ON_RESET                 BIT(15)
-       #define REG_CTRL_SLEEPM                         BIT(16)
-       #define REG_CTRL_TX_BITSTUFF_ENN_H              BIT(17)
-       #define REG_CTRL_TX_BITSTUFF_ENN                BIT(18)
-       #define REG_CTRL_COMMON_ON                      BIT(19)
-       #define REG_CTRL_REF_CLK_SEL_MASK               GENMASK(21, 20)
-       #define REG_CTRL_REF_CLK_SEL_SHIFT              20
-       #define REG_CTRL_FSEL_MASK                      GENMASK(24, 22)
-       #define REG_CTRL_FSEL_SHIFT                     22
-       #define REG_CTRL_PORT_RESET                     BIT(25)
-       #define REG_CTRL_THREAD_ID_MASK                 GENMASK(31, 26)
-
-#define REG_ENDP_INTR                                  0x08
-
-/* bits [31:26], [24:21] and [15:3] seem to be read-only */
-#define REG_ADP_BC                                     0x0c
-       #define REG_ADP_BC_VBUS_VLD_EXT_SEL             BIT(0)
-       #define REG_ADP_BC_VBUS_VLD_EXT                 BIT(1)
-       #define REG_ADP_BC_OTG_DISABLE                  BIT(2)
-       #define REG_ADP_BC_ID_PULLUP                    BIT(3)
-       #define REG_ADP_BC_DRV_VBUS                     BIT(4)
-       #define REG_ADP_BC_ADP_PRB_EN                   BIT(5)
-       #define REG_ADP_BC_ADP_DISCHARGE                BIT(6)
-       #define REG_ADP_BC_ADP_CHARGE                   BIT(7)
-       #define REG_ADP_BC_SESS_END                     BIT(8)
-       #define REG_ADP_BC_DEVICE_SESS_VLD              BIT(9)
-       #define REG_ADP_BC_B_VALID                      BIT(10)
-       #define REG_ADP_BC_A_VALID                      BIT(11)
-       #define REG_ADP_BC_ID_DIG                       BIT(12)
-       #define REG_ADP_BC_VBUS_VALID                   BIT(13)
-       #define REG_ADP_BC_ADP_PROBE                    BIT(14)
-       #define REG_ADP_BC_ADP_SENSE                    BIT(15)
-       #define REG_ADP_BC_ACA_ENABLE                   BIT(16)
-       #define REG_ADP_BC_DCD_ENABLE                   BIT(17)
-       #define REG_ADP_BC_VDAT_DET_EN_B                BIT(18)
-       #define REG_ADP_BC_VDAT_SRC_EN_B                BIT(19)
-       #define REG_ADP_BC_CHARGE_SEL                   BIT(20)
-       #define REG_ADP_BC_CHARGE_DETECT                BIT(21)
-       #define REG_ADP_BC_ACA_PIN_RANGE_C              BIT(22)
-       #define REG_ADP_BC_ACA_PIN_RANGE_B              BIT(23)
-       #define REG_ADP_BC_ACA_PIN_RANGE_A              BIT(24)
-       #define REG_ADP_BC_ACA_PIN_GND                  BIT(25)
-       #define REG_ADP_BC_ACA_PIN_FLOAT                BIT(26)
-
-#define REG_DBG_UART                                   0x10
-
-#define REG_TEST                                       0x14
-       #define REG_TEST_DATA_IN_MASK                   GENMASK(3, 0)
-       #define REG_TEST_EN_MASK                        GENMASK(7, 4)
-       #define REG_TEST_ADDR_MASK                      GENMASK(11, 8)
-       #define REG_TEST_DATA_OUT_SEL                   BIT(12)
-       #define REG_TEST_CLK                            BIT(13)
-       #define REG_TEST_VA_TEST_EN_B_MASK              GENMASK(15, 14)
-       #define REG_TEST_DATA_OUT_MASK                  GENMASK(19, 16)
-       #define REG_TEST_DISABLE_ID_PULLUP              BIT(20)
-
-#define REG_TUNE                                       0x18
-       #define REG_TUNE_TX_RES_TUNE_MASK               GENMASK(1, 0)
-       #define REG_TUNE_TX_HSXV_TUNE_MASK              GENMASK(3, 2)
-       #define REG_TUNE_TX_VREF_TUNE_MASK              GENMASK(7, 4)
-       #define REG_TUNE_TX_RISE_TUNE_MASK              GENMASK(9, 8)
-       #define REG_TUNE_TX_PREEMP_PULSE_TUNE           BIT(10)
-       #define REG_TUNE_TX_PREEMP_AMP_TUNE_MASK        GENMASK(12, 11)
-       #define REG_TUNE_TX_FSLS_TUNE_MASK              GENMASK(16, 13)
-       #define REG_TUNE_SQRX_TUNE_MASK                 GENMASK(19, 17)
-       #define REG_TUNE_OTG_TUNE                       GENMASK(22, 20)
-       #define REG_TUNE_COMP_DIS_TUNE                  GENMASK(25, 23)
-       #define REG_TUNE_HOST_DM_PULLDOWN               BIT(26)
-       #define REG_TUNE_HOST_DP_PULLDOWN               BIT(27)
-
-#define RESET_COMPLETE_TIME                            500
-#define ACA_ENABLE_COMPLETE_TIME                       50
-
-struct phy_meson8b_usb2_priv {
-       void __iomem            *regs;
-       enum usb_dr_mode        dr_mode;
-       struct clk              *clk_usb_general;
-       struct clk              *clk_usb;
-       struct reset_control    *reset;
-};
-
-static u32 phy_meson8b_usb2_read(struct phy_meson8b_usb2_priv *phy_priv,
-                                u32 reg)
-{
-       return readl(phy_priv->regs + reg);
-}
-
-static void phy_meson8b_usb2_mask_bits(struct phy_meson8b_usb2_priv *phy_priv,
-                                      u32 reg, u32 mask, u32 value)
-{
-       u32 data;
-
-       data = phy_meson8b_usb2_read(phy_priv, reg);
-       data &= ~mask;
-       data |= (value & mask);
-
-       writel(data, phy_priv->regs + reg);
-}
-
-static int phy_meson8b_usb2_power_on(struct phy *phy)
-{
-       struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
-       int ret;
-
-       if (!IS_ERR_OR_NULL(priv->reset)) {
-               ret = reset_control_reset(priv->reset);
-               if (ret) {
-                       dev_err(&phy->dev, "Failed to trigger USB reset\n");
-                       return ret;
-               }
-       }
-
-       ret = clk_prepare_enable(priv->clk_usb_general);
-       if (ret) {
-               dev_err(&phy->dev, "Failed to enable USB general clock\n");
-               return ret;
-       }
-
-       ret = clk_prepare_enable(priv->clk_usb);
-       if (ret) {
-               dev_err(&phy->dev, "Failed to enable USB DDR clock\n");
-               clk_disable_unprepare(priv->clk_usb_general);
-               return ret;
-       }
-
-       phy_meson8b_usb2_mask_bits(priv, REG_CONFIG, REG_CONFIG_CLK_32k_ALTSEL,
-                                  REG_CONFIG_CLK_32k_ALTSEL);
-
-       phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_REF_CLK_SEL_MASK,
-                                  0x2 << REG_CTRL_REF_CLK_SEL_SHIFT);
-
-       phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_FSEL_MASK,
-                                  0x5 << REG_CTRL_FSEL_SHIFT);
-
-       /* reset the PHY */
-       phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET,
-                                  REG_CTRL_POWER_ON_RESET);
-       udelay(RESET_COMPLETE_TIME);
-       phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_POWER_ON_RESET, 0);
-       udelay(RESET_COMPLETE_TIME);
-
-       phy_meson8b_usb2_mask_bits(priv, REG_CTRL, REG_CTRL_SOF_TOGGLE_OUT,
-                                  REG_CTRL_SOF_TOGGLE_OUT);
-
-       if (priv->dr_mode == USB_DR_MODE_HOST) {
-               phy_meson8b_usb2_mask_bits(priv, REG_ADP_BC,
-                                          REG_ADP_BC_ACA_ENABLE,
-                                          REG_ADP_BC_ACA_ENABLE);
-
-               udelay(ACA_ENABLE_COMPLETE_TIME);
-
-               if (phy_meson8b_usb2_read(priv, REG_ADP_BC) &
-                       REG_ADP_BC_ACA_PIN_FLOAT) {
-                       dev_warn(&phy->dev, "USB ID detect failed!\n");
-                       clk_disable_unprepare(priv->clk_usb);
-                       clk_disable_unprepare(priv->clk_usb_general);
-                       return -EINVAL;
-               }
-       }
-
-       return 0;
-}
-
-static int phy_meson8b_usb2_power_off(struct phy *phy)
-{
-       struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
-
-       clk_disable_unprepare(priv->clk_usb);
-       clk_disable_unprepare(priv->clk_usb_general);
-
-       return 0;
-}
-
-static const struct phy_ops phy_meson8b_usb2_ops = {
-       .power_on       = phy_meson8b_usb2_power_on,
-       .power_off      = phy_meson8b_usb2_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static int phy_meson8b_usb2_probe(struct platform_device *pdev)
-{
-       struct phy_meson8b_usb2_priv *priv;
-       struct resource *res;
-       struct phy *phy;
-       struct phy_provider *phy_provider;
-
-       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       priv->regs = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(priv->regs))
-               return PTR_ERR(priv->regs);
-
-       priv->clk_usb_general = devm_clk_get(&pdev->dev, "usb_general");
-       if (IS_ERR(priv->clk_usb_general))
-               return PTR_ERR(priv->clk_usb_general);
-
-       priv->clk_usb = devm_clk_get(&pdev->dev, "usb");
-       if (IS_ERR(priv->clk_usb))
-               return PTR_ERR(priv->clk_usb);
-
-       priv->reset = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
-       if (PTR_ERR(priv->reset) == -EPROBE_DEFER)
-               return PTR_ERR(priv->reset);
-
-       priv->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node, -1);
-       if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
-               dev_err(&pdev->dev,
-                       "missing dual role configuration of the controller\n");
-               return -EINVAL;
-       }
-
-       phy = devm_phy_create(&pdev->dev, NULL, &phy_meson8b_usb2_ops);
-       if (IS_ERR(phy)) {
-               dev_err(&pdev->dev, "failed to create PHY\n");
-               return PTR_ERR(phy);
-       }
-
-       phy_set_drvdata(phy, priv);
-
-       phy_provider =
-               devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
-
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static const struct of_device_id phy_meson8b_usb2_of_match[] = {
-       { .compatible = "amlogic,meson8b-usb2-phy", },
-       { .compatible = "amlogic,meson-gxbb-usb2-phy", },
-       { },
-};
-MODULE_DEVICE_TABLE(of, phy_meson8b_usb2_of_match);
-
-static struct platform_driver phy_meson8b_usb2_driver = {
-       .probe  = phy_meson8b_usb2_probe,
-       .driver = {
-               .name           = "phy-meson-usb2",
-               .of_match_table = phy_meson8b_usb2_of_match,
-       },
-};
-module_platform_driver(phy_meson8b_usb2_driver);
-
-MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
-MODULE_DESCRIPTION("Meson8b and GXBB USB2 PHY driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c
deleted file mode 100644 (file)
index 213e2e1..0000000
+++ /dev/null
@@ -1,1286 +0,0 @@
-/*
- * Copyright (C) 2014 STMicroelectronics
- *
- * STMicroelectronics PHY driver MiPHY28lp (for SoC STiH407).
- *
- * Author: Alexandre Torgue <alexandre.torgue@st.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.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/clk.h>
-#include <linux/phy/phy.h>
-#include <linux/delay.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
-#include <linux/reset.h>
-
-#include <dt-bindings/phy/phy.h>
-
-/* MiPHY registers */
-#define MIPHY_CONF_RESET               0x00
-#define RST_APPLI_SW           BIT(0)
-#define RST_CONF_SW            BIT(1)
-#define RST_MACRO_SW           BIT(2)
-
-#define MIPHY_RESET                    0x01
-#define RST_PLL_SW             BIT(0)
-#define RST_COMP_SW            BIT(2)
-
-#define MIPHY_STATUS_1                 0x02
-#define PHY_RDY                        BIT(0)
-#define HFC_RDY                        BIT(1)
-#define HFC_PLL                        BIT(2)
-
-#define MIPHY_CONTROL                  0x04
-#define TERM_EN_SW             BIT(2)
-#define DIS_LINK_RST           BIT(3)
-#define AUTO_RST_RX            BIT(4)
-#define PX_RX_POL              BIT(5)
-
-#define MIPHY_BOUNDARY_SEL             0x0a
-#define TX_SEL                 BIT(6)
-#define SSC_SEL                        BIT(4)
-#define GENSEL_SEL             BIT(0)
-
-#define MIPHY_BOUNDARY_1               0x0b
-#define MIPHY_BOUNDARY_2               0x0c
-#define SSC_EN_SW              BIT(2)
-
-#define MIPHY_PLL_CLKREF_FREQ          0x0d
-#define MIPHY_SPEED                    0x0e
-#define TX_SPDSEL_80DEC                0
-#define TX_SPDSEL_40DEC                1
-#define TX_SPDSEL_20DEC                2
-#define RX_SPDSEL_80DEC                0
-#define RX_SPDSEL_40DEC                (1 << 2)
-#define RX_SPDSEL_20DEC                (2 << 2)
-
-#define MIPHY_CONF                     0x0f
-#define MIPHY_CTRL_TEST_SEL            0x20
-#define MIPHY_CTRL_TEST_1              0x21
-#define MIPHY_CTRL_TEST_2              0x22
-#define MIPHY_CTRL_TEST_3              0x23
-#define MIPHY_CTRL_TEST_4              0x24
-#define MIPHY_FEEDBACK_TEST            0x25
-#define MIPHY_DEBUG_BUS                        0x26
-#define MIPHY_DEBUG_STATUS_MSB         0x27
-#define MIPHY_DEBUG_STATUS_LSB         0x28
-#define MIPHY_PWR_RAIL_1               0x29
-#define MIPHY_PWR_RAIL_2               0x2a
-#define MIPHY_SYNCHAR_CONTROL          0x30
-
-#define MIPHY_COMP_FSM_1               0x3a
-#define COMP_START             BIT(6)
-
-#define MIPHY_COMP_FSM_6               0x3f
-#define COMP_DONE              BIT(7)
-
-#define MIPHY_COMP_POSTP               0x42
-#define MIPHY_TX_CTRL_1                        0x49
-#define TX_REG_STEP_0V         0
-#define TX_REG_STEP_P_25MV     1
-#define TX_REG_STEP_P_50MV     2
-#define TX_REG_STEP_N_25MV     7
-#define TX_REG_STEP_N_50MV     6
-#define TX_REG_STEP_N_75MV     5
-
-#define MIPHY_TX_CTRL_2                        0x4a
-#define TX_SLEW_SW_40_PS       0
-#define TX_SLEW_SW_80_PS       1
-#define TX_SLEW_SW_120_PS      2
-
-#define MIPHY_TX_CTRL_3                        0x4b
-#define MIPHY_TX_CAL_MAN               0x4e
-#define TX_SLEW_CAL_MAN_EN     BIT(0)
-
-#define MIPHY_TST_BIAS_BOOST_2         0x62
-#define MIPHY_BIAS_BOOST_1             0x63
-#define MIPHY_BIAS_BOOST_2             0x64
-#define MIPHY_RX_DESBUFF_FDB_2         0x67
-#define MIPHY_RX_DESBUFF_FDB_3         0x68
-#define MIPHY_SIGDET_COMPENS1          0x69
-#define MIPHY_SIGDET_COMPENS2          0x6a
-#define MIPHY_JITTER_PERIOD            0x6b
-#define MIPHY_JITTER_AMPLITUDE_1       0x6c
-#define MIPHY_JITTER_AMPLITUDE_2       0x6d
-#define MIPHY_JITTER_AMPLITUDE_3       0x6e
-#define MIPHY_RX_K_GAIN                        0x78
-#define MIPHY_RX_BUFFER_CTRL           0x7a
-#define VGA_GAIN               BIT(0)
-#define EQ_DC_GAIN             BIT(2)
-#define EQ_BOOST_GAIN          BIT(3)
-
-#define MIPHY_RX_VGA_GAIN              0x7b
-#define MIPHY_RX_EQU_GAIN_1            0x7f
-#define MIPHY_RX_EQU_GAIN_2            0x80
-#define MIPHY_RX_EQU_GAIN_3            0x81
-#define MIPHY_RX_CAL_CTRL_1            0x97
-#define MIPHY_RX_CAL_CTRL_2            0x98
-
-#define MIPHY_RX_CAL_OFFSET_CTRL       0x99
-#define CAL_OFFSET_VGA_64      (0x03 << 0)
-#define CAL_OFFSET_THRESHOLD_64        (0x03 << 2)
-#define VGA_OFFSET_POLARITY    BIT(4)
-#define OFFSET_COMPENSATION_EN BIT(6)
-
-#define MIPHY_RX_CAL_VGA_STEP          0x9a
-#define MIPHY_RX_CAL_EYE_MIN           0x9d
-#define MIPHY_RX_CAL_OPT_LENGTH                0x9f
-#define MIPHY_RX_LOCK_CTRL_1           0xc1
-#define MIPHY_RX_LOCK_SETTINGS_OPT     0xc2
-#define MIPHY_RX_LOCK_STEP             0xc4
-
-#define MIPHY_RX_SIGDET_SLEEP_OA       0xc9
-#define MIPHY_RX_SIGDET_SLEEP_SEL      0xca
-#define MIPHY_RX_SIGDET_WAIT_SEL       0xcb
-#define MIPHY_RX_SIGDET_DATA_SEL       0xcc
-#define EN_ULTRA_LOW_POWER     BIT(0)
-#define EN_FIRST_HALF          BIT(1)
-#define EN_SECOND_HALF         BIT(2)
-#define EN_DIGIT_SIGNAL_CHECK  BIT(3)
-
-#define MIPHY_RX_POWER_CTRL_1          0xcd
-#define MIPHY_RX_POWER_CTRL_2          0xce
-#define MIPHY_PLL_CALSET_CTRL          0xd3
-#define MIPHY_PLL_CALSET_1             0xd4
-#define MIPHY_PLL_CALSET_2             0xd5
-#define MIPHY_PLL_CALSET_3             0xd6
-#define MIPHY_PLL_CALSET_4             0xd7
-#define MIPHY_PLL_SBR_1                        0xe3
-#define SET_NEW_CHANGE         BIT(1)
-
-#define MIPHY_PLL_SBR_2                        0xe4
-#define MIPHY_PLL_SBR_3                        0xe5
-#define MIPHY_PLL_SBR_4                        0xe6
-#define MIPHY_PLL_COMMON_MISC_2                0xe9
-#define START_ACT_FILT         BIT(6)
-
-#define MIPHY_PLL_SPAREIN              0xeb
-
-/*
- * On STiH407 the glue logic can be different among MiPHY devices; for example:
- * MiPHY0: OSC_FORCE_EXT means:
- *  0: 30MHz crystal clk - 1: 100MHz ext clk routed through MiPHY1
- * MiPHY1: OSC_FORCE_EXT means:
- *  1: 30MHz crystal clk - 0: 100MHz ext clk routed through MiPHY1
- * Some devices have not the possibility to check if the osc is ready.
- */
-#define MIPHY_OSC_FORCE_EXT    BIT(3)
-#define MIPHY_OSC_RDY          BIT(5)
-
-#define MIPHY_CTRL_MASK                0x0f
-#define MIPHY_CTRL_DEFAULT     0
-#define MIPHY_CTRL_SYNC_D_EN   BIT(2)
-
-/* SATA / PCIe defines */
-#define SATA_CTRL_MASK         0x07
-#define PCIE_CTRL_MASK         0xff
-#define SATA_CTRL_SELECT_SATA  1
-#define SATA_CTRL_SELECT_PCIE  0
-#define SYSCFG_PCIE_PCIE_VAL   0x80
-#define SATA_SPDMODE           1
-
-#define MIPHY_SATA_BANK_NB     3
-#define MIPHY_PCIE_BANK_NB     2
-
-enum {
-       SYSCFG_CTRL,
-       SYSCFG_STATUS,
-       SYSCFG_PCI,
-       SYSCFG_SATA,
-       SYSCFG_REG_MAX,
-};
-
-struct miphy28lp_phy {
-       struct phy *phy;
-       struct miphy28lp_dev *phydev;
-       void __iomem *base;
-       void __iomem *pipebase;
-
-       bool osc_force_ext;
-       bool osc_rdy;
-       bool px_rx_pol_inv;
-       bool ssc;
-       bool tx_impedance;
-
-       struct reset_control *miphy_rst;
-
-       u32 sata_gen;
-
-       /* Sysconfig registers offsets needed to configure the device */
-       u32 syscfg_reg[SYSCFG_REG_MAX];
-       u8 type;
-};
-
-struct miphy28lp_dev {
-       struct device *dev;
-       struct regmap *regmap;
-       struct mutex miphy_mutex;
-       struct miphy28lp_phy **phys;
-       int nphys;
-};
-
-struct miphy_initval {
-       u16 reg;
-       u16 val;
-};
-
-enum miphy_sata_gen { SATA_GEN1, SATA_GEN2, SATA_GEN3 };
-
-static char *PHY_TYPE_name[] = { "sata-up", "pcie-up", "", "usb3-up" };
-
-struct pll_ratio {
-       int clk_ref;
-       int calset_1;
-       int calset_2;
-       int calset_3;
-       int calset_4;
-       int cal_ctrl;
-};
-
-static struct pll_ratio sata_pll_ratio = {
-       .clk_ref = 0x1e,
-       .calset_1 = 0xc8,
-       .calset_2 = 0x00,
-       .calset_3 = 0x00,
-       .calset_4 = 0x00,
-       .cal_ctrl = 0x00,
-};
-
-static struct pll_ratio pcie_pll_ratio = {
-       .clk_ref = 0x1e,
-       .calset_1 = 0xa6,
-       .calset_2 = 0xaa,
-       .calset_3 = 0xaa,
-       .calset_4 = 0x00,
-       .cal_ctrl = 0x00,
-};
-
-static struct pll_ratio usb3_pll_ratio = {
-       .clk_ref = 0x1e,
-       .calset_1 = 0xa6,
-       .calset_2 = 0xaa,
-       .calset_3 = 0xaa,
-       .calset_4 = 0x04,
-       .cal_ctrl = 0x00,
-};
-
-struct miphy28lp_pll_gen {
-       int bank;
-       int speed;
-       int bias_boost_1;
-       int bias_boost_2;
-       int tx_ctrl_1;
-       int tx_ctrl_2;
-       int tx_ctrl_3;
-       int rx_k_gain;
-       int rx_vga_gain;
-       int rx_equ_gain_1;
-       int rx_equ_gain_2;
-       int rx_equ_gain_3;
-       int rx_buff_ctrl;
-};
-
-static struct miphy28lp_pll_gen sata_pll_gen[] = {
-       {
-               .bank           = 0x00,
-               .speed          = TX_SPDSEL_80DEC | RX_SPDSEL_80DEC,
-               .bias_boost_1   = 0x00,
-               .bias_boost_2   = 0xae,
-               .tx_ctrl_2      = 0x53,
-               .tx_ctrl_3      = 0x00,
-               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
-               .rx_vga_gain    = 0x00,
-               .rx_equ_gain_1  = 0x7d,
-               .rx_equ_gain_2  = 0x56,
-               .rx_equ_gain_3  = 0x00,
-       },
-       {
-               .bank           = 0x01,
-               .speed          = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,
-               .bias_boost_1   = 0x00,
-               .bias_boost_2   = 0xae,
-               .tx_ctrl_2      = 0x72,
-               .tx_ctrl_3      = 0x20,
-               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
-               .rx_vga_gain    = 0x00,
-               .rx_equ_gain_1  = 0x7d,
-               .rx_equ_gain_2  = 0x56,
-               .rx_equ_gain_3  = 0x00,
-       },
-       {
-               .bank           = 0x02,
-               .speed          = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,
-               .bias_boost_1   = 0x00,
-               .bias_boost_2   = 0xae,
-               .tx_ctrl_2      = 0xc0,
-               .tx_ctrl_3      = 0x20,
-               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
-               .rx_vga_gain    = 0x00,
-               .rx_equ_gain_1  = 0x7d,
-               .rx_equ_gain_2  = 0x56,
-               .rx_equ_gain_3  = 0x00,
-       },
-};
-
-static struct miphy28lp_pll_gen pcie_pll_gen[] = {
-       {
-               .bank           = 0x00,
-               .speed          = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,
-               .bias_boost_1   = 0x00,
-               .bias_boost_2   = 0xa5,
-               .tx_ctrl_1      = TX_REG_STEP_N_25MV,
-               .tx_ctrl_2      = 0x71,
-               .tx_ctrl_3      = 0x60,
-               .rx_k_gain      = 0x98,
-               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
-               .rx_vga_gain    = 0x00,
-               .rx_equ_gain_1  = 0x79,
-               .rx_equ_gain_2  = 0x56,
-       },
-       {
-               .bank           = 0x01,
-               .speed          = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,
-               .bias_boost_1   = 0x00,
-               .bias_boost_2   = 0xa5,
-               .tx_ctrl_1      = TX_REG_STEP_N_25MV,
-               .tx_ctrl_2      = 0x70,
-               .tx_ctrl_3      = 0x60,
-               .rx_k_gain      = 0xcc,
-               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
-               .rx_vga_gain    = 0x00,
-               .rx_equ_gain_1  = 0x78,
-               .rx_equ_gain_2  = 0x07,
-       },
-};
-
-static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy)
-{
-       void __iomem *base = miphy_phy->base;
-       u8 val;
-
-       /* Putting Macro in reset */
-       writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
-
-       val = RST_APPLI_SW | RST_CONF_SW;
-       writeb_relaxed(val, base + MIPHY_CONF_RESET);
-
-       writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
-
-       /* Bringing the MIPHY-CPU registers out of reset */
-       if (miphy_phy->type == PHY_TYPE_PCIE) {
-               val = AUTO_RST_RX | TERM_EN_SW;
-               writeb_relaxed(val, base + MIPHY_CONTROL);
-       } else {
-               val = AUTO_RST_RX | TERM_EN_SW | DIS_LINK_RST;
-               writeb_relaxed(val, base + MIPHY_CONTROL);
-       }
-}
-
-static inline void miphy28lp_pll_calibration(struct miphy28lp_phy *miphy_phy,
-               struct pll_ratio *pll_ratio)
-{
-       void __iomem *base = miphy_phy->base;
-       u8 val;
-
-       /* Applying PLL Settings */
-       writeb_relaxed(0x1d, base + MIPHY_PLL_SPAREIN);
-       writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);
-
-       /* PLL Ratio */
-       writeb_relaxed(pll_ratio->calset_1, base + MIPHY_PLL_CALSET_1);
-       writeb_relaxed(pll_ratio->calset_2, base + MIPHY_PLL_CALSET_2);
-       writeb_relaxed(pll_ratio->calset_3, base + MIPHY_PLL_CALSET_3);
-       writeb_relaxed(pll_ratio->calset_4, base + MIPHY_PLL_CALSET_4);
-       writeb_relaxed(pll_ratio->cal_ctrl, base + MIPHY_PLL_CALSET_CTRL);
-
-       writeb_relaxed(TX_SEL, base + MIPHY_BOUNDARY_SEL);
-
-       val = (0x68 << 1) | TX_SLEW_CAL_MAN_EN;
-       writeb_relaxed(val, base + MIPHY_TX_CAL_MAN);
-
-       val = VGA_OFFSET_POLARITY | CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;
-
-       if (miphy_phy->type != PHY_TYPE_SATA)
-               val |= OFFSET_COMPENSATION_EN;
-
-       writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);
-
-       if (miphy_phy->type == PHY_TYPE_USB3) {
-               writeb_relaxed(0x00, base + MIPHY_CONF);
-               writeb_relaxed(0x70, base + MIPHY_RX_LOCK_STEP);
-               writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_OA);
-               writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_SEL);
-               writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_WAIT_SEL);
-
-               val = EN_DIGIT_SIGNAL_CHECK | EN_FIRST_HALF;
-               writeb_relaxed(val, base + MIPHY_RX_SIGDET_DATA_SEL);
-       }
-
-}
-
-static inline void miphy28lp_sata_config_gen(struct miphy28lp_phy *miphy_phy)
-{
-       void __iomem *base = miphy_phy->base;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(sata_pll_gen); i++) {
-               struct miphy28lp_pll_gen *gen = &sata_pll_gen[i];
-
-               /* Banked settings */
-               writeb_relaxed(gen->bank, base + MIPHY_CONF);
-               writeb_relaxed(gen->speed, base + MIPHY_SPEED);
-               writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);
-               writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);
-
-               /* TX buffer Settings */
-               writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);
-               writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);
-
-               /* RX Buffer Settings */
-               writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);
-               writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);
-               writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);
-               writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);
-               writeb_relaxed(gen->rx_equ_gain_3, base + MIPHY_RX_EQU_GAIN_3);
-       }
-}
-
-static inline void miphy28lp_pcie_config_gen(struct miphy28lp_phy *miphy_phy)
-{
-       void __iomem *base = miphy_phy->base;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(pcie_pll_gen); i++) {
-               struct miphy28lp_pll_gen *gen = &pcie_pll_gen[i];
-
-               /* Banked settings */
-               writeb_relaxed(gen->bank, base + MIPHY_CONF);
-               writeb_relaxed(gen->speed, base + MIPHY_SPEED);
-               writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);
-               writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);
-
-               /* TX buffer Settings */
-               writeb_relaxed(gen->tx_ctrl_1, base + MIPHY_TX_CTRL_1);
-               writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);
-               writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);
-
-               writeb_relaxed(gen->rx_k_gain, base + MIPHY_RX_K_GAIN);
-
-               /* RX Buffer Settings */
-               writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);
-               writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);
-               writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);
-               writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);
-       }
-}
-
-static inline int miphy28lp_wait_compensation(struct miphy28lp_phy *miphy_phy)
-{
-       unsigned long finish = jiffies + 5 * HZ;
-       u8 val;
-
-       /* Waiting for Compensation to complete */
-       do {
-               val = readb_relaxed(miphy_phy->base + MIPHY_COMP_FSM_6);
-
-               if (time_after_eq(jiffies, finish))
-                       return -EBUSY;
-               cpu_relax();
-       } while (!(val & COMP_DONE));
-
-       return 0;
-}
-
-
-static inline int miphy28lp_compensation(struct miphy28lp_phy *miphy_phy,
-               struct pll_ratio *pll_ratio)
-{
-       void __iomem *base = miphy_phy->base;
-
-       /* Poll for HFC ready after reset release */
-       /* Compensation measurement */
-       writeb_relaxed(RST_PLL_SW | RST_COMP_SW, base + MIPHY_RESET);
-
-       writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);
-       writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);
-       writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);
-
-       if (miphy_phy->type == PHY_TYPE_PCIE)
-               writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);
-
-       writeb_relaxed(0x00, base + MIPHY_RESET);
-       writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);
-       writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
-
-       /* TX compensation offset to re-center TX impedance */
-       writeb_relaxed(0x00, base + MIPHY_COMP_POSTP);
-
-       if (miphy_phy->type == PHY_TYPE_PCIE)
-               return miphy28lp_wait_compensation(miphy_phy);
-
-       return 0;
-}
-
-static inline void miphy28_usb3_miphy_reset(struct miphy28lp_phy *miphy_phy)
-{
-       void __iomem *base = miphy_phy->base;
-       u8 val;
-
-       /* MIPHY Reset */
-       writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
-       writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
-       writeb_relaxed(RST_COMP_SW, base + MIPHY_RESET);
-
-       val = RST_COMP_SW | RST_PLL_SW;
-       writeb_relaxed(val, base + MIPHY_RESET);
-
-       writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);
-       writeb_relaxed(0x1e, base + MIPHY_PLL_CLKREF_FREQ);
-       writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);
-       writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);
-       writeb_relaxed(0x00, base + MIPHY_RESET);
-       writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);
-       writeb_relaxed(0x00, base + MIPHY_CONF);
-       writeb_relaxed(0x00, base + MIPHY_BOUNDARY_1);
-       writeb_relaxed(0x00, base + MIPHY_TST_BIAS_BOOST_2);
-       writeb_relaxed(0x00, base + MIPHY_CONF);
-       writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
-       writeb_relaxed(0xa5, base + MIPHY_DEBUG_BUS);
-       writeb_relaxed(0x00, base + MIPHY_CONF);
-}
-
-static void miphy_sata_tune_ssc(struct miphy28lp_phy *miphy_phy)
-{
-       void __iomem *base = miphy_phy->base;
-       u8 val;
-
-       /* Compensate Tx impedance to avoid out of range values */
-       /*
-        * Enable the SSC on PLL for all banks
-        * SSC Modulation @ 31 KHz and 4000 ppm modulation amp
-        */
-       val = readb_relaxed(base + MIPHY_BOUNDARY_2);
-       val |= SSC_EN_SW;
-       writeb_relaxed(val, base + MIPHY_BOUNDARY_2);
-
-       val = readb_relaxed(base + MIPHY_BOUNDARY_SEL);
-       val |= SSC_SEL;
-       writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);
-
-       for (val = 0; val < MIPHY_SATA_BANK_NB; val++) {
-               writeb_relaxed(val, base + MIPHY_CONF);
-
-               /* Add value to each reference clock cycle  */
-               /* and define the period length of the SSC */
-               writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);
-               writeb_relaxed(0x6c, base + MIPHY_PLL_SBR_3);
-               writeb_relaxed(0x81, base + MIPHY_PLL_SBR_4);
-
-               /* Clear any previous request */
-               writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
-
-               /* requests the PLL to take in account new parameters */
-               writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
-
-               /* To be sure there is no other pending requests */
-               writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
-       }
-}
-
-static void miphy_pcie_tune_ssc(struct miphy28lp_phy *miphy_phy)
-{
-       void __iomem *base = miphy_phy->base;
-       u8 val;
-
-       /* Compensate Tx impedance to avoid out of range values */
-       /*
-        * Enable the SSC on PLL for all banks
-        * SSC Modulation @ 31 KHz and 4000 ppm modulation amp
-        */
-       val = readb_relaxed(base + MIPHY_BOUNDARY_2);
-       val |= SSC_EN_SW;
-       writeb_relaxed(val, base + MIPHY_BOUNDARY_2);
-
-       val = readb_relaxed(base + MIPHY_BOUNDARY_SEL);
-       val |= SSC_SEL;
-       writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);
-
-       for (val = 0; val < MIPHY_PCIE_BANK_NB; val++) {
-               writeb_relaxed(val, base + MIPHY_CONF);
-
-               /* Validate Step component */
-               writeb_relaxed(0x69, base + MIPHY_PLL_SBR_3);
-               writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4);
-
-               /* Validate Period component */
-               writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);
-               writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4);
-
-               /* Clear any previous request */
-               writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
-
-               /* requests the PLL to take in account new parameters */
-               writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
-
-               /* To be sure there is no other pending requests */
-               writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
-       }
-}
-
-static inline void miphy_tune_tx_impedance(struct miphy28lp_phy *miphy_phy)
-{
-       /* Compensate Tx impedance to avoid out of range values */
-       writeb_relaxed(0x02, miphy_phy->base + MIPHY_COMP_POSTP);
-}
-
-static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy)
-{
-       void __iomem *base = miphy_phy->base;
-       int err;
-       u8 val;
-
-       /* Putting Macro in reset */
-       miphy28lp_set_reset(miphy_phy);
-
-       /* PLL calibration */
-       miphy28lp_pll_calibration(miphy_phy, &sata_pll_ratio);
-
-       /* Banked settings Gen1/Gen2/Gen3 */
-       miphy28lp_sata_config_gen(miphy_phy);
-
-       /* Power control */
-       /* Input bridge enable, manual input bridge control */
-       writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
-
-       /* Macro out of reset */
-       writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
-
-       /* Poll for HFC ready after reset release */
-       /* Compensation measurement */
-       err = miphy28lp_compensation(miphy_phy, &sata_pll_ratio);
-       if (err)
-               return err;
-
-       if (miphy_phy->px_rx_pol_inv) {
-               /* Invert Rx polarity */
-               val = readb_relaxed(miphy_phy->base + MIPHY_CONTROL);
-               val |= PX_RX_POL;
-               writeb_relaxed(val, miphy_phy->base + MIPHY_CONTROL);
-       }
-
-       if (miphy_phy->ssc)
-               miphy_sata_tune_ssc(miphy_phy);
-
-       if (miphy_phy->tx_impedance)
-               miphy_tune_tx_impedance(miphy_phy);
-
-       return 0;
-}
-
-static inline int miphy28lp_configure_pcie(struct miphy28lp_phy *miphy_phy)
-{
-       void __iomem *base = miphy_phy->base;
-       int err;
-
-       /* Putting Macro in reset */
-       miphy28lp_set_reset(miphy_phy);
-
-       /* PLL calibration */
-       miphy28lp_pll_calibration(miphy_phy, &pcie_pll_ratio);
-
-       /* Banked settings Gen1/Gen2 */
-       miphy28lp_pcie_config_gen(miphy_phy);
-
-       /* Power control */
-       /* Input bridge enable, manual input bridge control */
-       writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
-
-       /* Macro out of reset */
-       writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
-
-       /* Poll for HFC ready after reset release */
-       /* Compensation measurement */
-       err = miphy28lp_compensation(miphy_phy, &pcie_pll_ratio);
-       if (err)
-               return err;
-
-       if (miphy_phy->ssc)
-               miphy_pcie_tune_ssc(miphy_phy);
-
-       if (miphy_phy->tx_impedance)
-               miphy_tune_tx_impedance(miphy_phy);
-
-       return 0;
-}
-
-
-static inline void miphy28lp_configure_usb3(struct miphy28lp_phy *miphy_phy)
-{
-       void __iomem *base = miphy_phy->base;
-       u8 val;
-
-       /* Putting Macro in reset */
-       miphy28lp_set_reset(miphy_phy);
-
-       /* PLL calibration */
-       miphy28lp_pll_calibration(miphy_phy, &usb3_pll_ratio);
-
-       /* Writing The Speed Rate */
-       writeb_relaxed(0x00, base + MIPHY_CONF);
-
-       val = RX_SPDSEL_20DEC | TX_SPDSEL_20DEC;
-       writeb_relaxed(val, base + MIPHY_SPEED);
-
-       /* RX Channel compensation and calibration */
-       writeb_relaxed(0x1c, base + MIPHY_RX_LOCK_SETTINGS_OPT);
-       writeb_relaxed(0x51, base + MIPHY_RX_CAL_CTRL_1);
-       writeb_relaxed(0x70, base + MIPHY_RX_CAL_CTRL_2);
-
-       val = OFFSET_COMPENSATION_EN | VGA_OFFSET_POLARITY |
-             CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;
-       writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);
-       writeb_relaxed(0x22, base + MIPHY_RX_CAL_VGA_STEP);
-       writeb_relaxed(0x0e, base + MIPHY_RX_CAL_OPT_LENGTH);
-
-       val = EQ_DC_GAIN | VGA_GAIN;
-       writeb_relaxed(val, base + MIPHY_RX_BUFFER_CTRL);
-       writeb_relaxed(0x78, base + MIPHY_RX_EQU_GAIN_1);
-       writeb_relaxed(0x1b, base + MIPHY_SYNCHAR_CONTROL);
-
-       /* TX compensation offset to re-center TX impedance */
-       writeb_relaxed(0x02, base + MIPHY_COMP_POSTP);
-
-       /* Enable GENSEL_SEL and SSC */
-       /* TX_SEL=0 swing preemp forced by pipe registres */
-       val = SSC_SEL | GENSEL_SEL;
-       writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);
-
-       /* MIPHY Bias boost */
-       writeb_relaxed(0x00, base + MIPHY_BIAS_BOOST_1);
-       writeb_relaxed(0xa7, base + MIPHY_BIAS_BOOST_2);
-
-       /* SSC modulation */
-       writeb_relaxed(SSC_EN_SW, base + MIPHY_BOUNDARY_2);
-
-       /* MIPHY TX control */
-       writeb_relaxed(0x00, base + MIPHY_CONF);
-
-       /* Validate Step component */
-       writeb_relaxed(0x5a, base + MIPHY_PLL_SBR_3);
-       writeb_relaxed(0xa0, base + MIPHY_PLL_SBR_4);
-
-       /* Validate Period component */
-       writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);
-       writeb_relaxed(0xa1, base + MIPHY_PLL_SBR_4);
-
-       /* Clear any previous request */
-       writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
-
-       /* requests the PLL to take in account new parameters */
-       writeb_relaxed(0x02, base + MIPHY_PLL_SBR_1);
-
-       /* To be sure there is no other pending requests */
-       writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
-
-       /* Rx PI controller settings */
-       writeb_relaxed(0xca, base + MIPHY_RX_K_GAIN);
-
-       /* MIPHY RX input bridge control */
-       /* INPUT_BRIDGE_EN_SW=1, manual input bridge control[0]=1 */
-       writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
-       writeb_relaxed(0x29, base + MIPHY_RX_POWER_CTRL_1);
-       writeb_relaxed(0x1a, base + MIPHY_RX_POWER_CTRL_2);
-
-       /* MIPHY Reset for usb3 */
-       miphy28_usb3_miphy_reset(miphy_phy);
-}
-
-static inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy)
-{
-       unsigned long finish = jiffies + 5 * HZ;
-       u8 mask = HFC_PLL | HFC_RDY;
-       u8 val;
-
-       /*
-        * For PCIe and USB3 check only that PLL and HFC are ready
-        * For SATA check also that phy is ready!
-        */
-       if (miphy_phy->type == PHY_TYPE_SATA)
-               mask |= PHY_RDY;
-
-       do {
-               val = readb_relaxed(miphy_phy->base + MIPHY_STATUS_1);
-               if ((val & mask) != mask)
-                       cpu_relax();
-               else
-                       return 0;
-       } while (!time_after_eq(jiffies, finish));
-
-       return -EBUSY;
-}
-
-static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)
-{
-       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
-       unsigned long finish = jiffies + 5 * HZ;
-       u32 val;
-
-       if (!miphy_phy->osc_rdy)
-               return 0;
-
-       if (!miphy_phy->syscfg_reg[SYSCFG_STATUS])
-               return -EINVAL;
-
-       do {
-               regmap_read(miphy_dev->regmap,
-                               miphy_phy->syscfg_reg[SYSCFG_STATUS], &val);
-
-               if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY)
-                       cpu_relax();
-               else
-                       return 0;
-       } while (!time_after_eq(jiffies, finish));
-
-       return -EBUSY;
-}
-
-static int miphy28lp_get_resource_byname(struct device_node *child,
-                                         char *rname, struct resource *res)
-{
-       int index;
-
-       index = of_property_match_string(child, "reg-names", rname);
-       if (index < 0)
-               return -ENODEV;
-
-       return of_address_to_resource(child, index, res);
-}
-
-static int miphy28lp_get_one_addr(struct device *dev,
-                                 struct device_node *child, char *rname,
-                                 void __iomem **base)
-{
-       struct resource res;
-       int ret;
-
-       ret = miphy28lp_get_resource_byname(child, rname, &res);
-       if (!ret) {
-               *base = devm_ioremap(dev, res.start, resource_size(&res));
-               if (!*base) {
-                       dev_err(dev, "failed to ioremap %s address region\n"
-                                       , rname);
-                       return -ENOENT;
-               }
-       }
-
-       return 0;
-}
-
-/* MiPHY reset and sysconf setup */
-static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val)
-{
-       int err;
-       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
-
-       if (!miphy_phy->syscfg_reg[SYSCFG_CTRL])
-               return -EINVAL;
-
-       err = reset_control_assert(miphy_phy->miphy_rst);
-       if (err) {
-               dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
-               return err;
-       }
-
-       if (miphy_phy->osc_force_ext)
-               miphy_val |= MIPHY_OSC_FORCE_EXT;
-
-       regmap_update_bits(miphy_dev->regmap,
-                          miphy_phy->syscfg_reg[SYSCFG_CTRL],
-                          MIPHY_CTRL_MASK, miphy_val);
-
-       err = reset_control_deassert(miphy_phy->miphy_rst);
-       if (err) {
-               dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
-               return err;
-       }
-
-       return miphy_osc_is_ready(miphy_phy);
-}
-
-static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy)
-{
-       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
-       int err, sata_conf = SATA_CTRL_SELECT_SATA;
-
-       if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||
-                       (!miphy_phy->syscfg_reg[SYSCFG_PCI]) ||
-                       (!miphy_phy->base))
-               return -EINVAL;
-
-       dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base);
-
-       /* Configure the glue-logic */
-       sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE);
-
-       regmap_update_bits(miphy_dev->regmap,
-                          miphy_phy->syscfg_reg[SYSCFG_SATA],
-                          SATA_CTRL_MASK, sata_conf);
-
-       regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],
-                          PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
-
-       /* MiPHY path and clocking init */
-       err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);
-
-       if (err) {
-               dev_err(miphy_dev->dev, "SATA phy setup failed\n");
-               return err;
-       }
-
-       /* initialize miphy */
-       miphy28lp_configure_sata(miphy_phy);
-
-       return miphy_is_ready(miphy_phy);
-}
-
-static int miphy28lp_init_pcie(struct miphy28lp_phy *miphy_phy)
-{
-       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
-       int err;
-
-       if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||
-                       (!miphy_phy->syscfg_reg[SYSCFG_PCI])
-               || (!miphy_phy->base) || (!miphy_phy->pipebase))
-               return -EINVAL;
-
-       dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base);
-
-       /* Configure the glue-logic */
-       regmap_update_bits(miphy_dev->regmap,
-                          miphy_phy->syscfg_reg[SYSCFG_SATA],
-                          SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
-
-       regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],
-                          PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL);
-
-       /* MiPHY path and clocking init */
-       err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);
-
-       if (err) {
-               dev_err(miphy_dev->dev, "PCIe phy setup failed\n");
-               return err;
-       }
-
-       /* initialize miphy */
-       err = miphy28lp_configure_pcie(miphy_phy);
-       if (err)
-               return err;
-
-       /* PIPE Wrapper Configuration */
-       writeb_relaxed(0x68, miphy_phy->pipebase + 0x104); /* Rise_0 */
-       writeb_relaxed(0x61, miphy_phy->pipebase + 0x105); /* Rise_1 */
-       writeb_relaxed(0x68, miphy_phy->pipebase + 0x108); /* Fall_0 */
-       writeb_relaxed(0x61, miphy_phy->pipebase + 0x109); /* Fall-1 */
-       writeb_relaxed(0x68, miphy_phy->pipebase + 0x10c); /* Threshold_0 */
-       writeb_relaxed(0x60, miphy_phy->pipebase + 0x10d); /* Threshold_1 */
-
-       /* Wait for phy_ready */
-       return miphy_is_ready(miphy_phy);
-}
-
-static int miphy28lp_init_usb3(struct miphy28lp_phy *miphy_phy)
-{
-       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
-       int err;
-
-       if ((!miphy_phy->base) || (!miphy_phy->pipebase))
-               return -EINVAL;
-
-       dev_info(miphy_dev->dev, "usb3-up mode, addr 0x%p\n", miphy_phy->base);
-
-       /* MiPHY path and clocking init */
-       err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_SYNC_D_EN);
-       if (err) {
-               dev_err(miphy_dev->dev, "USB3 phy setup failed\n");
-               return err;
-       }
-
-       /* initialize miphy */
-       miphy28lp_configure_usb3(miphy_phy);
-
-       /* PIPE Wrapper Configuration */
-       writeb_relaxed(0x68, miphy_phy->pipebase + 0x23);
-       writeb_relaxed(0x61, miphy_phy->pipebase + 0x24);
-       writeb_relaxed(0x68, miphy_phy->pipebase + 0x26);
-       writeb_relaxed(0x61, miphy_phy->pipebase + 0x27);
-       writeb_relaxed(0x18, miphy_phy->pipebase + 0x29);
-       writeb_relaxed(0x61, miphy_phy->pipebase + 0x2a);
-
-       /* pipe Wrapper usb3 TX swing de-emph margin PREEMPH[7:4], SWING[3:0] */
-       writeb_relaxed(0X67, miphy_phy->pipebase + 0x68);
-       writeb_relaxed(0x0d, miphy_phy->pipebase + 0x69);
-       writeb_relaxed(0X67, miphy_phy->pipebase + 0x6a);
-       writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6b);
-       writeb_relaxed(0X67, miphy_phy->pipebase + 0x6c);
-       writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6d);
-       writeb_relaxed(0X67, miphy_phy->pipebase + 0x6e);
-       writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6f);
-
-       return miphy_is_ready(miphy_phy);
-}
-
-static int miphy28lp_init(struct phy *phy)
-{
-       struct miphy28lp_phy *miphy_phy = phy_get_drvdata(phy);
-       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
-       int ret;
-
-       mutex_lock(&miphy_dev->miphy_mutex);
-
-       switch (miphy_phy->type) {
-
-       case PHY_TYPE_SATA:
-               ret = miphy28lp_init_sata(miphy_phy);
-               break;
-       case PHY_TYPE_PCIE:
-               ret = miphy28lp_init_pcie(miphy_phy);
-               break;
-       case PHY_TYPE_USB3:
-               ret = miphy28lp_init_usb3(miphy_phy);
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-
-       mutex_unlock(&miphy_dev->miphy_mutex);
-
-       return ret;
-}
-
-static int miphy28lp_get_addr(struct miphy28lp_phy *miphy_phy)
-{
-       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
-       struct device_node *phynode = miphy_phy->phy->dev.of_node;
-       int err;
-
-       if ((miphy_phy->type != PHY_TYPE_SATA) &&
-           (miphy_phy->type != PHY_TYPE_PCIE) &&
-           (miphy_phy->type != PHY_TYPE_USB3)) {
-               return -EINVAL;
-       }
-
-       err = miphy28lp_get_one_addr(miphy_dev->dev, phynode,
-                       PHY_TYPE_name[miphy_phy->type - PHY_TYPE_SATA],
-                       &miphy_phy->base);
-       if (err)
-               return err;
-
-       if ((miphy_phy->type == PHY_TYPE_PCIE) ||
-           (miphy_phy->type == PHY_TYPE_USB3)) {
-               err = miphy28lp_get_one_addr(miphy_dev->dev, phynode, "pipew",
-                                            &miphy_phy->pipebase);
-               if (err)
-                       return err;
-       }
-
-       return 0;
-}
-
-static struct phy *miphy28lp_xlate(struct device *dev,
-                                  struct of_phandle_args *args)
-{
-       struct miphy28lp_dev *miphy_dev = dev_get_drvdata(dev);
-       struct miphy28lp_phy *miphy_phy = NULL;
-       struct device_node *phynode = args->np;
-       int ret, index = 0;
-
-       if (args->args_count != 1) {
-               dev_err(dev, "Invalid number of cells in 'phy' property\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       for (index = 0; index < miphy_dev->nphys; index++)
-               if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {
-                       miphy_phy = miphy_dev->phys[index];
-                       break;
-               }
-
-       if (!miphy_phy) {
-               dev_err(dev, "Failed to find appropriate phy\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       miphy_phy->type = args->args[0];
-
-       ret = miphy28lp_get_addr(miphy_phy);
-       if (ret < 0)
-               return ERR_PTR(ret);
-
-       return miphy_phy->phy;
-}
-
-static const struct phy_ops miphy28lp_ops = {
-       .init = miphy28lp_init,
-       .owner = THIS_MODULE,
-};
-
-static int miphy28lp_probe_resets(struct device_node *node,
-                                 struct miphy28lp_phy *miphy_phy)
-{
-       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
-       int err;
-
-       miphy_phy->miphy_rst =
-               of_reset_control_get_shared(node, "miphy-sw-rst");
-
-       if (IS_ERR(miphy_phy->miphy_rst)) {
-               dev_err(miphy_dev->dev,
-                               "miphy soft reset control not defined\n");
-               return PTR_ERR(miphy_phy->miphy_rst);
-       }
-
-       err = reset_control_deassert(miphy_phy->miphy_rst);
-       if (err) {
-               dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
-               return err;
-       }
-
-       return 0;
-}
-
-static int miphy28lp_of_probe(struct device_node *np,
-                             struct miphy28lp_phy *miphy_phy)
-{
-       int i;
-       u32 ctrlreg;
-
-       miphy_phy->osc_force_ext =
-               of_property_read_bool(np, "st,osc-force-ext");
-
-       miphy_phy->osc_rdy = of_property_read_bool(np, "st,osc-rdy");
-
-       miphy_phy->px_rx_pol_inv =
-               of_property_read_bool(np, "st,px_rx_pol_inv");
-
-       miphy_phy->ssc = of_property_read_bool(np, "st,ssc-on");
-
-       miphy_phy->tx_impedance =
-               of_property_read_bool(np, "st,tx-impedance-comp");
-
-       of_property_read_u32(np, "st,sata-gen", &miphy_phy->sata_gen);
-       if (!miphy_phy->sata_gen)
-               miphy_phy->sata_gen = SATA_GEN1;
-
-       for (i = 0; i < SYSCFG_REG_MAX; i++) {
-               if (!of_property_read_u32_index(np, "st,syscfg", i, &ctrlreg))
-                       miphy_phy->syscfg_reg[i] = ctrlreg;
-       }
-
-       return 0;
-}
-
-static int miphy28lp_probe(struct platform_device *pdev)
-{
-       struct device_node *child, *np = pdev->dev.of_node;
-       struct miphy28lp_dev *miphy_dev;
-       struct phy_provider *provider;
-       struct phy *phy;
-       int ret, port = 0;
-
-       miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
-       if (!miphy_dev)
-               return -ENOMEM;
-
-       miphy_dev->nphys = of_get_child_count(np);
-       miphy_dev->phys = devm_kcalloc(&pdev->dev, miphy_dev->nphys,
-                                      sizeof(*miphy_dev->phys), GFP_KERNEL);
-       if (!miphy_dev->phys)
-               return -ENOMEM;
-
-       miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
-       if (IS_ERR(miphy_dev->regmap)) {
-               dev_err(miphy_dev->dev, "No syscfg phandle specified\n");
-               return PTR_ERR(miphy_dev->regmap);
-       }
-
-       miphy_dev->dev = &pdev->dev;
-
-       dev_set_drvdata(&pdev->dev, miphy_dev);
-
-       mutex_init(&miphy_dev->miphy_mutex);
-
-       for_each_child_of_node(np, child) {
-               struct miphy28lp_phy *miphy_phy;
-
-               miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
-                                        GFP_KERNEL);
-               if (!miphy_phy) {
-                       ret = -ENOMEM;
-                       goto put_child;
-               }
-
-               miphy_dev->phys[port] = miphy_phy;
-
-               phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops);
-               if (IS_ERR(phy)) {
-                       dev_err(&pdev->dev, "failed to create PHY\n");
-                       ret = PTR_ERR(phy);
-                       goto put_child;
-               }
-
-               miphy_dev->phys[port]->phy = phy;
-               miphy_dev->phys[port]->phydev = miphy_dev;
-
-               ret = miphy28lp_of_probe(child, miphy_phy);
-               if (ret)
-                       goto put_child;
-
-               ret = miphy28lp_probe_resets(child, miphy_dev->phys[port]);
-               if (ret)
-                       goto put_child;
-
-               phy_set_drvdata(phy, miphy_dev->phys[port]);
-               port++;
-
-       }
-
-       provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate);
-       return PTR_ERR_OR_ZERO(provider);
-put_child:
-       of_node_put(child);
-       return ret;
-}
-
-static const struct of_device_id miphy28lp_of_match[] = {
-       {.compatible = "st,miphy28lp-phy", },
-       {},
-};
-
-MODULE_DEVICE_TABLE(of, miphy28lp_of_match);
-
-static struct platform_driver miphy28lp_driver = {
-       .probe = miphy28lp_probe,
-       .driver = {
-               .name = "miphy28lp-phy",
-               .of_match_table = miphy28lp_of_match,
-       }
-};
-
-module_platform_driver(miphy28lp_driver);
-
-MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
-MODULE_DESCRIPTION("STMicroelectronics miphy28lp driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c
deleted file mode 100644 (file)
index 768ce92..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- *     phy-mvebu-sata.c: SATA Phy driver for the Marvell mvebu SoCs.
- *
- *     Copyright (C) 2013 Andrew Lunn <andrew@lunn.ch>
- *
- *     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; either version
- *     2 of the License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/phy/phy.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-
-struct priv {
-       struct clk      *clk;
-       void __iomem    *base;
-};
-
-#define SATA_PHY_MODE_2        0x0330
-#define  MODE_2_FORCE_PU_TX    BIT(0)
-#define  MODE_2_FORCE_PU_RX    BIT(1)
-#define  MODE_2_PU_PLL         BIT(2)
-#define  MODE_2_PU_IVREF       BIT(3)
-#define SATA_IF_CTRL   0x0050
-#define  CTRL_PHY_SHUTDOWN     BIT(9)
-
-static int phy_mvebu_sata_power_on(struct phy *phy)
-{
-       struct priv *priv = phy_get_drvdata(phy);
-       u32 reg;
-
-       clk_prepare_enable(priv->clk);
-
-       /* Enable PLL and IVREF */
-       reg = readl(priv->base + SATA_PHY_MODE_2);
-       reg |= (MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
-               MODE_2_PU_PLL | MODE_2_PU_IVREF);
-       writel(reg , priv->base + SATA_PHY_MODE_2);
-
-       /* Enable PHY */
-       reg = readl(priv->base + SATA_IF_CTRL);
-       reg &= ~CTRL_PHY_SHUTDOWN;
-       writel(reg, priv->base + SATA_IF_CTRL);
-
-       clk_disable_unprepare(priv->clk);
-
-       return 0;
-}
-
-static int phy_mvebu_sata_power_off(struct phy *phy)
-{
-       struct priv *priv = phy_get_drvdata(phy);
-       u32 reg;
-
-       clk_prepare_enable(priv->clk);
-
-       /* Disable PLL and IVREF */
-       reg = readl(priv->base + SATA_PHY_MODE_2);
-       reg &= ~(MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
-                MODE_2_PU_PLL | MODE_2_PU_IVREF);
-       writel(reg, priv->base + SATA_PHY_MODE_2);
-
-       /* Disable PHY */
-       reg = readl(priv->base + SATA_IF_CTRL);
-       reg |= CTRL_PHY_SHUTDOWN;
-       writel(reg, priv->base + SATA_IF_CTRL);
-
-       clk_disable_unprepare(priv->clk);
-
-       return 0;
-}
-
-static const struct phy_ops phy_mvebu_sata_ops = {
-       .power_on       = phy_mvebu_sata_power_on,
-       .power_off      = phy_mvebu_sata_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static int phy_mvebu_sata_probe(struct platform_device *pdev)
-{
-       struct phy_provider *phy_provider;
-       struct resource *res;
-       struct priv *priv;
-       struct phy *phy;
-
-       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       priv->base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(priv->base))
-               return PTR_ERR(priv->base);
-
-       priv->clk = devm_clk_get(&pdev->dev, "sata");
-       if (IS_ERR(priv->clk))
-               return PTR_ERR(priv->clk);
-
-       phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops);
-       if (IS_ERR(phy))
-               return PTR_ERR(phy);
-
-       phy_set_drvdata(phy, priv);
-
-       phy_provider = devm_of_phy_provider_register(&pdev->dev,
-                                                    of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
-       /* The boot loader may of left it on. Turn it off. */
-       phy_mvebu_sata_power_off(phy);
-
-       return 0;
-}
-
-static const struct of_device_id phy_mvebu_sata_of_match[] = {
-       { .compatible = "marvell,mvebu-sata-phy" },
-       { },
-};
-MODULE_DEVICE_TABLE(of, phy_mvebu_sata_of_match);
-
-static struct platform_driver phy_mvebu_sata_driver = {
-       .probe  = phy_mvebu_sata_probe,
-       .driver = {
-               .name   = "phy-mvebu-sata",
-               .of_match_table = phy_mvebu_sata_of_match,
-       }
-};
-module_platform_driver(phy_mvebu_sata_driver);
-
-MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
-MODULE_DESCRIPTION("Marvell MVEBU SATA PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c
deleted file mode 100644 (file)
index e9c41b3..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * omap-control-phy.c - The PHY part of control module.
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.com>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/phy/omap_control_phy.h>
-
-/**
- * omap_control_pcie_pcs - set the PCS delay count
- * @dev: the control module device
- * @delay: 8 bit delay value
- */
-void omap_control_pcie_pcs(struct device *dev, u8 delay)
-{
-       u32 val;
-       struct omap_control_phy *control_phy;
-
-       if (IS_ERR(dev) || !dev) {
-               pr_err("%s: invalid device\n", __func__);
-               return;
-       }
-
-       control_phy = dev_get_drvdata(dev);
-       if (!control_phy) {
-               dev_err(dev, "%s: invalid control phy device\n", __func__);
-               return;
-       }
-
-       if (control_phy->type != OMAP_CTRL_TYPE_PCIE) {
-               dev_err(dev, "%s: unsupported operation\n", __func__);
-               return;
-       }
-
-       val = readl(control_phy->pcie_pcs);
-       val &= ~(OMAP_CTRL_PCIE_PCS_MASK <<
-               OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT);
-       val |= (delay << OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT);
-       writel(val, control_phy->pcie_pcs);
-}
-EXPORT_SYMBOL_GPL(omap_control_pcie_pcs);
-
-/**
- * omap_control_phy_power - power on/off the phy using control module reg
- * @dev: the control module device
- * @on: 0 or 1, based on powering on or off the PHY
- */
-void omap_control_phy_power(struct device *dev, int on)
-{
-       u32 val;
-       unsigned long rate;
-       struct omap_control_phy *control_phy;
-
-       if (IS_ERR(dev) || !dev) {
-               pr_err("%s: invalid device\n", __func__);
-               return;
-       }
-
-       control_phy = dev_get_drvdata(dev);
-       if (!control_phy) {
-               dev_err(dev, "%s: invalid control phy device\n", __func__);
-               return;
-       }
-
-       if (control_phy->type == OMAP_CTRL_TYPE_OTGHS)
-               return;
-
-       val = readl(control_phy->power);
-
-       switch (control_phy->type) {
-       case OMAP_CTRL_TYPE_USB2:
-               if (on)
-                       val &= ~OMAP_CTRL_DEV_PHY_PD;
-               else
-                       val |= OMAP_CTRL_DEV_PHY_PD;
-               break;
-
-       case OMAP_CTRL_TYPE_PCIE:
-       case OMAP_CTRL_TYPE_PIPE3:
-               rate = clk_get_rate(control_phy->sys_clk);
-               rate = rate/1000000;
-
-               if (on) {
-                       val &= ~(OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK |
-                               OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK);
-                       val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON <<
-                               OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
-                       val |= rate <<
-                               OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT;
-               } else {
-                       val &= ~OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK;
-                       val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF <<
-                               OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
-               }
-               break;
-
-       case OMAP_CTRL_TYPE_DRA7USB2:
-               if (on)
-                       val &= ~OMAP_CTRL_USB2_PHY_PD;
-               else
-                       val |= OMAP_CTRL_USB2_PHY_PD;
-               break;
-
-       case OMAP_CTRL_TYPE_AM437USB2:
-               if (on) {
-                       val &= ~(AM437X_CTRL_USB2_PHY_PD |
-                                       AM437X_CTRL_USB2_OTG_PD);
-                       val |= (AM437X_CTRL_USB2_OTGVDET_EN |
-                                       AM437X_CTRL_USB2_OTGSESSEND_EN);
-               } else {
-                       val &= ~(AM437X_CTRL_USB2_OTGVDET_EN |
-                                       AM437X_CTRL_USB2_OTGSESSEND_EN);
-                       val |= (AM437X_CTRL_USB2_PHY_PD |
-                                        AM437X_CTRL_USB2_OTG_PD);
-               }
-               break;
-       default:
-               dev_err(dev, "%s: type %d not recognized\n",
-                       __func__, control_phy->type);
-               break;
-       }
-
-       writel(val, control_phy->power);
-}
-EXPORT_SYMBOL_GPL(omap_control_phy_power);
-
-/**
- * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded
- * @ctrl_phy: struct omap_control_phy *
- *
- * Writes to the mailbox register to notify the usb core that a usb
- * device has been connected.
- */
-static void omap_control_usb_host_mode(struct omap_control_phy *ctrl_phy)
-{
-       u32 val;
-
-       val = readl(ctrl_phy->otghs_control);
-       val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND);
-       val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID;
-       writel(val, ctrl_phy->otghs_control);
-}
-
-/**
- * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high
- * impedance
- * @ctrl_phy: struct omap_control_phy *
- *
- * Writes to the mailbox register to notify the usb core that it has been
- * connected to a usb host.
- */
-static void omap_control_usb_device_mode(struct omap_control_phy *ctrl_phy)
-{
-       u32 val;
-
-       val = readl(ctrl_phy->otghs_control);
-       val &= ~OMAP_CTRL_DEV_SESSEND;
-       val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID |
-               OMAP_CTRL_DEV_VBUSVALID;
-       writel(val, ctrl_phy->otghs_control);
-}
-
-/**
- * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high
- * impedance
- * @ctrl_phy: struct omap_control_phy *
- *
- * Writes to the mailbox register to notify the usb core it's now in
- * disconnected state.
- */
-static void omap_control_usb_set_sessionend(struct omap_control_phy *ctrl_phy)
-{
-       u32 val;
-
-       val = readl(ctrl_phy->otghs_control);
-       val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID);
-       val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND;
-       writel(val, ctrl_phy->otghs_control);
-}
-
-/**
- * omap_control_usb_set_mode - Calls to functions to set USB in one of host mode
- * or device mode or to denote disconnected state
- * @dev: the control module device
- * @mode: The mode to which usb should be configured
- *
- * This is an API to write to the mailbox register to notify the usb core that
- * a usb device has been connected.
- */
-void omap_control_usb_set_mode(struct device *dev,
-       enum omap_control_usb_mode mode)
-{
-       struct omap_control_phy *ctrl_phy;
-
-       if (IS_ERR(dev) || !dev)
-               return;
-
-       ctrl_phy = dev_get_drvdata(dev);
-       if (!ctrl_phy) {
-               dev_err(dev, "Invalid control phy device\n");
-               return;
-       }
-
-       if (ctrl_phy->type != OMAP_CTRL_TYPE_OTGHS)
-               return;
-
-       switch (mode) {
-       case USB_MODE_HOST:
-               omap_control_usb_host_mode(ctrl_phy);
-               break;
-       case USB_MODE_DEVICE:
-               omap_control_usb_device_mode(ctrl_phy);
-               break;
-       case USB_MODE_DISCONNECT:
-               omap_control_usb_set_sessionend(ctrl_phy);
-               break;
-       default:
-               dev_vdbg(dev, "invalid omap control usb mode\n");
-       }
-}
-EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
-
-static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
-static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
-static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
-static const enum omap_control_phy_type pcie_data = OMAP_CTRL_TYPE_PCIE;
-static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2;
-static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2;
-
-static const struct of_device_id omap_control_phy_id_table[] = {
-       {
-               .compatible = "ti,control-phy-otghs",
-               .data = &otghs_data,
-       },
-       {
-               .compatible = "ti,control-phy-usb2",
-               .data = &usb2_data,
-       },
-       {
-               .compatible = "ti,control-phy-pipe3",
-               .data = &pipe3_data,
-       },
-       {
-               .compatible = "ti,control-phy-pcie",
-               .data = &pcie_data,
-       },
-       {
-               .compatible = "ti,control-phy-usb2-dra7",
-               .data = &dra7usb2_data,
-       },
-       {
-               .compatible = "ti,control-phy-usb2-am437",
-               .data = &am437usb2_data,
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, omap_control_phy_id_table);
-
-static int omap_control_phy_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       const struct of_device_id *of_id;
-       struct omap_control_phy *control_phy;
-
-       of_id = of_match_device(omap_control_phy_id_table, &pdev->dev);
-       if (!of_id)
-               return -EINVAL;
-
-       control_phy = devm_kzalloc(&pdev->dev, sizeof(*control_phy),
-               GFP_KERNEL);
-       if (!control_phy)
-               return -ENOMEM;
-
-       control_phy->dev = &pdev->dev;
-       control_phy->type = *(enum omap_control_phy_type *)of_id->data;
-
-       if (control_phy->type == OMAP_CTRL_TYPE_OTGHS) {
-               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                       "otghs_control");
-               control_phy->otghs_control = devm_ioremap_resource(
-                       &pdev->dev, res);
-               if (IS_ERR(control_phy->otghs_control))
-                       return PTR_ERR(control_phy->otghs_control);
-       } else {
-               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                               "power");
-               control_phy->power = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(control_phy->power)) {
-                       dev_err(&pdev->dev, "Couldn't get power register\n");
-                       return PTR_ERR(control_phy->power);
-               }
-       }
-
-       if (control_phy->type == OMAP_CTRL_TYPE_PIPE3 ||
-           control_phy->type == OMAP_CTRL_TYPE_PCIE) {
-               control_phy->sys_clk = devm_clk_get(control_phy->dev,
-                       "sys_clkin");
-               if (IS_ERR(control_phy->sys_clk)) {
-                       pr_err("%s: unable to get sys_clkin\n", __func__);
-                       return -EINVAL;
-               }
-       }
-
-       if (control_phy->type == OMAP_CTRL_TYPE_PCIE) {
-               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                                                  "pcie_pcs");
-               control_phy->pcie_pcs = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(control_phy->pcie_pcs))
-                       return PTR_ERR(control_phy->pcie_pcs);
-       }
-
-       dev_set_drvdata(control_phy->dev, control_phy);
-
-       return 0;
-}
-
-static struct platform_driver omap_control_phy_driver = {
-       .probe          = omap_control_phy_probe,
-       .driver         = {
-               .name   = "omap-control-phy",
-               .of_match_table = omap_control_phy_id_table,
-       },
-};
-
-static int __init omap_control_phy_init(void)
-{
-       return platform_driver_register(&omap_control_phy_driver);
-}
-subsys_initcall(omap_control_phy_init);
-
-static void __exit omap_control_phy_exit(void)
-{
-       platform_driver_unregister(&omap_control_phy_driver);
-}
-module_exit(omap_control_phy_exit);
-
-MODULE_ALIAS("platform:omap_control_phy");
-MODULE_AUTHOR("Texas Instruments Inc.");
-MODULE_DESCRIPTION("OMAP Control Module PHY Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
deleted file mode 100644 (file)
index fe909fd..0000000
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * omap-usb2.c - USB PHY, talking to musb controller in OMAP.
- *
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.com>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/io.h>
-#include <linux/phy/omap_usb.h>
-#include <linux/usb/phy_companion.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/pm_runtime.h>
-#include <linux/delay.h>
-#include <linux/phy/omap_control_phy.h>
-#include <linux/phy/phy.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
-#include <linux/of_platform.h>
-
-#define USB2PHY_DISCON_BYP_LATCH (1 << 31)
-#define USB2PHY_ANA_CONFIG1 0x4c
-
-/**
- * omap_usb2_set_comparator - links the comparator present in the sytem with
- *     this phy
- * @comparator - the companion phy(comparator) for this phy
- *
- * The phy companion driver should call this API passing the phy_companion
- * filled with set_vbus and start_srp to be used by usb phy.
- *
- * For use by phy companion driver
- */
-int omap_usb2_set_comparator(struct phy_companion *comparator)
-{
-       struct omap_usb *phy;
-       struct usb_phy  *x = usb_get_phy(USB_PHY_TYPE_USB2);
-
-       if (IS_ERR(x))
-               return -ENODEV;
-
-       phy = phy_to_omapusb(x);
-       phy->comparator = comparator;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
-
-static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
-{
-       struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
-
-       if (!phy->comparator)
-               return -ENODEV;
-
-       return phy->comparator->set_vbus(phy->comparator, enabled);
-}
-
-static int omap_usb_start_srp(struct usb_otg *otg)
-{
-       struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
-
-       if (!phy->comparator)
-               return -ENODEV;
-
-       return phy->comparator->start_srp(phy->comparator);
-}
-
-static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-       otg->host = host;
-       if (!host)
-               otg->state = OTG_STATE_UNDEFINED;
-
-       return 0;
-}
-
-static int omap_usb_set_peripheral(struct usb_otg *otg,
-               struct usb_gadget *gadget)
-{
-       otg->gadget = gadget;
-       if (!gadget)
-               otg->state = OTG_STATE_UNDEFINED;
-
-       return 0;
-}
-
-static int omap_usb_phy_power(struct omap_usb *phy, int on)
-{
-       u32 val;
-       int ret;
-
-       if (!phy->syscon_phy_power) {
-               omap_control_phy_power(phy->control_dev, on);
-               return 0;
-       }
-
-       if (on)
-               val = phy->power_on;
-       else
-               val = phy->power_off;
-
-       ret = regmap_update_bits(phy->syscon_phy_power, phy->power_reg,
-                                phy->mask, val);
-       return ret;
-}
-
-static int omap_usb_power_off(struct phy *x)
-{
-       struct omap_usb *phy = phy_get_drvdata(x);
-
-       return omap_usb_phy_power(phy, false);
-}
-
-static int omap_usb_power_on(struct phy *x)
-{
-       struct omap_usb *phy = phy_get_drvdata(x);
-
-       return omap_usb_phy_power(phy, true);
-}
-
-static int omap_usb2_disable_clocks(struct omap_usb *phy)
-{
-       clk_disable(phy->wkupclk);
-       if (!IS_ERR(phy->optclk))
-               clk_disable(phy->optclk);
-
-       return 0;
-}
-
-static int omap_usb2_enable_clocks(struct omap_usb *phy)
-{
-       int ret;
-
-       ret = clk_enable(phy->wkupclk);
-       if (ret < 0) {
-               dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
-               goto err0;
-       }
-
-       if (!IS_ERR(phy->optclk)) {
-               ret = clk_enable(phy->optclk);
-               if (ret < 0) {
-                       dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
-                       goto err1;
-               }
-       }
-
-       return 0;
-
-err1:
-       clk_disable(phy->wkupclk);
-
-err0:
-       return ret;
-}
-
-static int omap_usb_init(struct phy *x)
-{
-       struct omap_usb *phy = phy_get_drvdata(x);
-       u32 val;
-
-       omap_usb2_enable_clocks(phy);
-
-       if (phy->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
-               /*
-                *
-                * Reduce the sensitivity of internal PHY by enabling the
-                * DISCON_BYP_LATCH of the USB2PHY_ANA_CONFIG1 register. This
-                * resolves issues with certain devices which can otherwise
-                * be prone to false disconnects.
-                *
-                */
-               val = omap_usb_readl(phy->phy_base, USB2PHY_ANA_CONFIG1);
-               val |= USB2PHY_DISCON_BYP_LATCH;
-               omap_usb_writel(phy->phy_base, USB2PHY_ANA_CONFIG1, val);
-       }
-
-       return 0;
-}
-
-static int omap_usb_exit(struct phy *x)
-{
-       struct omap_usb *phy = phy_get_drvdata(x);
-
-       return omap_usb2_disable_clocks(phy);
-}
-
-static const struct phy_ops ops = {
-       .init           = omap_usb_init,
-       .exit           = omap_usb_exit,
-       .power_on       = omap_usb_power_on,
-       .power_off      = omap_usb_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static const struct usb_phy_data omap_usb2_data = {
-       .label = "omap_usb2",
-       .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS,
-       .mask = OMAP_DEV_PHY_PD,
-       .power_off = OMAP_DEV_PHY_PD,
-};
-
-static const struct usb_phy_data omap5_usb2_data = {
-       .label = "omap5_usb2",
-       .flags = 0,
-       .mask = OMAP_DEV_PHY_PD,
-       .power_off = OMAP_DEV_PHY_PD,
-};
-
-static const struct usb_phy_data dra7x_usb2_data = {
-       .label = "dra7x_usb2",
-       .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
-       .mask = OMAP_DEV_PHY_PD,
-       .power_off = OMAP_DEV_PHY_PD,
-};
-
-static const struct usb_phy_data dra7x_usb2_phy2_data = {
-       .label = "dra7x_usb2_phy2",
-       .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
-       .mask = OMAP_USB2_PHY_PD,
-       .power_off = OMAP_USB2_PHY_PD,
-};
-
-static const struct usb_phy_data am437x_usb2_data = {
-       .label = "am437x_usb2",
-       .flags =  0,
-       .mask = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD |
-               AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
-       .power_on = AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
-       .power_off = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD,
-};
-
-static const struct of_device_id omap_usb2_id_table[] = {
-       {
-               .compatible = "ti,omap-usb2",
-               .data = &omap_usb2_data,
-       },
-       {
-               .compatible = "ti,omap5-usb2",
-               .data = &omap5_usb2_data,
-       },
-       {
-               .compatible = "ti,dra7x-usb2",
-               .data = &dra7x_usb2_data,
-       },
-       {
-               .compatible = "ti,dra7x-usb2-phy2",
-               .data = &dra7x_usb2_phy2_data,
-       },
-       {
-               .compatible = "ti,am437x-usb2",
-               .data = &am437x_usb2_data,
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
-
-static int omap_usb2_probe(struct platform_device *pdev)
-{
-       struct omap_usb *phy;
-       struct phy *generic_phy;
-       struct resource *res;
-       struct phy_provider *phy_provider;
-       struct usb_otg *otg;
-       struct device_node *node = pdev->dev.of_node;
-       struct device_node *control_node;
-       struct platform_device *control_pdev;
-       const struct of_device_id *of_id;
-       struct usb_phy_data *phy_data;
-
-       of_id = of_match_device(omap_usb2_id_table, &pdev->dev);
-
-       if (!of_id)
-               return -EINVAL;
-
-       phy_data = (struct usb_phy_data *)of_id->data;
-
-       phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
-       if (!phy)
-               return -ENOMEM;
-
-       otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
-       if (!otg)
-               return -ENOMEM;
-
-       phy->dev                = &pdev->dev;
-
-       phy->phy.dev            = phy->dev;
-       phy->phy.label          = phy_data->label;
-       phy->phy.otg            = otg;
-       phy->phy.type           = USB_PHY_TYPE_USB2;
-       phy->mask               = phy_data->mask;
-       phy->power_on           = phy_data->power_on;
-       phy->power_off          = phy_data->power_off;
-
-       if (phy_data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
-               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-               phy->phy_base = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(phy->phy_base))
-                       return PTR_ERR(phy->phy_base);
-               phy->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT;
-       }
-
-       phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node,
-                                                       "syscon-phy-power");
-       if (IS_ERR(phy->syscon_phy_power)) {
-               dev_dbg(&pdev->dev,
-                       "can't get syscon-phy-power, using control device\n");
-               phy->syscon_phy_power = NULL;
-
-               control_node = of_parse_phandle(node, "ctrl-module", 0);
-               if (!control_node) {
-                       dev_err(&pdev->dev,
-                               "Failed to get control device phandle\n");
-                       return -EINVAL;
-               }
-
-               control_pdev = of_find_device_by_node(control_node);
-               if (!control_pdev) {
-                       dev_err(&pdev->dev, "Failed to get control device\n");
-                       return -EINVAL;
-               }
-               phy->control_dev = &control_pdev->dev;
-       } else {
-               if (of_property_read_u32_index(node,
-                                              "syscon-phy-power", 1,
-                                              &phy->power_reg)) {
-                       dev_err(&pdev->dev,
-                               "couldn't get power reg. offset\n");
-                       return -EINVAL;
-               }
-       }
-
-       otg->set_host           = omap_usb_set_host;
-       otg->set_peripheral     = omap_usb_set_peripheral;
-       if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS)
-               otg->set_vbus           = omap_usb_set_vbus;
-       if (phy_data->flags & OMAP_USB2_HAS_START_SRP)
-               otg->start_srp          = omap_usb_start_srp;
-       otg->usb_phy            = &phy->phy;
-
-       platform_set_drvdata(pdev, phy);
-       pm_runtime_enable(phy->dev);
-
-       generic_phy = devm_phy_create(phy->dev, NULL, &ops);
-       if (IS_ERR(generic_phy)) {
-               pm_runtime_disable(phy->dev);
-               return PTR_ERR(generic_phy);
-       }
-
-       phy_set_drvdata(generic_phy, phy);
-       omap_usb_power_off(generic_phy);
-
-       phy_provider = devm_of_phy_provider_register(phy->dev,
-                       of_phy_simple_xlate);
-       if (IS_ERR(phy_provider)) {
-               pm_runtime_disable(phy->dev);
-               return PTR_ERR(phy_provider);
-       }
-
-       phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
-       if (IS_ERR(phy->wkupclk)) {
-               dev_warn(&pdev->dev, "unable to get wkupclk, trying old name\n");
-               phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
-               if (IS_ERR(phy->wkupclk)) {
-                       dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
-                       pm_runtime_disable(phy->dev);
-                       return PTR_ERR(phy->wkupclk);
-               } else {
-                       dev_warn(&pdev->dev,
-                                "found usb_phy_cm_clk32k, please fix DTS\n");
-               }
-       }
-       clk_prepare(phy->wkupclk);
-
-       phy->optclk = devm_clk_get(phy->dev, "refclk");
-       if (IS_ERR(phy->optclk)) {
-               dev_dbg(&pdev->dev, "unable to get refclk, trying old name\n");
-               phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
-               if (IS_ERR(phy->optclk)) {
-                       dev_dbg(&pdev->dev,
-                               "unable to get usb_otg_ss_refclk960m\n");
-               } else {
-                       dev_warn(&pdev->dev,
-                                "found usb_otg_ss_refclk960m, please fix DTS\n");
-               }
-       }
-
-       if (!IS_ERR(phy->optclk))
-               clk_prepare(phy->optclk);
-
-       usb_add_phy_dev(&phy->phy);
-
-       return 0;
-}
-
-static int omap_usb2_remove(struct platform_device *pdev)
-{
-       struct omap_usb *phy = platform_get_drvdata(pdev);
-
-       clk_unprepare(phy->wkupclk);
-       if (!IS_ERR(phy->optclk))
-               clk_unprepare(phy->optclk);
-       usb_remove_phy(&phy->phy);
-       pm_runtime_disable(phy->dev);
-
-       return 0;
-}
-
-static struct platform_driver omap_usb2_driver = {
-       .probe          = omap_usb2_probe,
-       .remove         = omap_usb2_remove,
-       .driver         = {
-               .name   = "omap-usb2",
-               .of_match_table = omap_usb2_id_table,
-       },
-};
-
-module_platform_driver(omap_usb2_driver);
-
-MODULE_ALIAS("platform:omap_usb2");
-MODULE_AUTHOR("Texas Instruments Inc.");
-MODULE_DESCRIPTION("OMAP USB2 phy driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-pxa-28nm-hsic.c b/drivers/phy/phy-pxa-28nm-hsic.c
deleted file mode 100644 (file)
index 234aacf..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2015 Linaro, Ltd.
- * Rob Herring <robh@kernel.org>
- *
- * Based on vendor driver:
- * Copyright (C) 2013 Marvell Inc.
- * Author: Chao Xie <xiechao.mail@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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/slab.h>
-#include <linux/of.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/phy/phy.h>
-
-#define PHY_28NM_HSIC_CTRL                     0x08
-#define PHY_28NM_HSIC_IMPCAL_CAL               0x18
-#define PHY_28NM_HSIC_PLL_CTRL01               0x1c
-#define PHY_28NM_HSIC_PLL_CTRL2                        0x20
-#define PHY_28NM_HSIC_INT                      0x28
-
-#define PHY_28NM_HSIC_PLL_SELLPFR_SHIFT                26
-#define PHY_28NM_HSIC_PLL_FBDIV_SHIFT          0
-#define PHY_28NM_HSIC_PLL_REFDIV_SHIFT         9
-
-#define PHY_28NM_HSIC_S2H_PU_PLL               BIT(10)
-#define PHY_28NM_HSIC_H2S_PLL_LOCK             BIT(15)
-#define PHY_28NM_HSIC_S2H_HSIC_EN              BIT(7)
-#define S2H_DRV_SE0_4RESUME                    BIT(14)
-#define PHY_28NM_HSIC_H2S_IMPCAL_DONE          BIT(27)
-
-#define PHY_28NM_HSIC_CONNECT_INT              BIT(1)
-#define PHY_28NM_HSIC_HS_READY_INT             BIT(2)
-
-struct mv_hsic_phy {
-       struct phy              *phy;
-       struct platform_device  *pdev;
-       void __iomem            *base;
-       struct clk              *clk;
-};
-
-static bool wait_for_reg(void __iomem *reg, u32 mask, unsigned long timeout)
-{
-       timeout += jiffies;
-       while (time_is_after_eq_jiffies(timeout)) {
-               if ((readl(reg) & mask) == mask)
-                       return true;
-               msleep(1);
-       }
-       return false;
-}
-
-static int mv_hsic_phy_init(struct phy *phy)
-{
-       struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
-       struct platform_device *pdev = mv_phy->pdev;
-       void __iomem *base = mv_phy->base;
-
-       clk_prepare_enable(mv_phy->clk);
-
-       /* Set reference clock */
-       writel(0x1 << PHY_28NM_HSIC_PLL_SELLPFR_SHIFT |
-               0xf0 << PHY_28NM_HSIC_PLL_FBDIV_SHIFT |
-               0xd << PHY_28NM_HSIC_PLL_REFDIV_SHIFT,
-               base + PHY_28NM_HSIC_PLL_CTRL01);
-
-       /* Turn on PLL */
-       writel(readl(base + PHY_28NM_HSIC_PLL_CTRL2) |
-               PHY_28NM_HSIC_S2H_PU_PLL,
-               base + PHY_28NM_HSIC_PLL_CTRL2);
-
-       /* Make sure PHY PLL is locked */
-       if (!wait_for_reg(base + PHY_28NM_HSIC_PLL_CTRL2,
-           PHY_28NM_HSIC_H2S_PLL_LOCK, HZ / 10)) {
-               dev_err(&pdev->dev, "HSIC PHY PLL not locked after 100mS.");
-               clk_disable_unprepare(mv_phy->clk);
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static int mv_hsic_phy_power_on(struct phy *phy)
-{
-       struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
-       struct platform_device *pdev = mv_phy->pdev;
-       void __iomem *base = mv_phy->base;
-       u32 reg;
-
-       reg = readl(base + PHY_28NM_HSIC_CTRL);
-       /* Avoid SE0 state when resume for some device will take it as reset */
-       reg &= ~S2H_DRV_SE0_4RESUME;
-       reg |= PHY_28NM_HSIC_S2H_HSIC_EN;       /* Enable HSIC PHY */
-       writel(reg, base + PHY_28NM_HSIC_CTRL);
-
-       /*
-        *  Calibration Timing
-        *                 ____________________________
-        *  CAL START   ___|
-        *                         ____________________
-        *  CAL_DONE    ___________|
-        *                 | 400us |
-        */
-
-       /* Make sure PHY Calibration is ready */
-       if (!wait_for_reg(base + PHY_28NM_HSIC_IMPCAL_CAL,
-           PHY_28NM_HSIC_H2S_IMPCAL_DONE, HZ / 10)) {
-               dev_warn(&pdev->dev, "HSIC PHY READY not set after 100mS.");
-               return -ETIMEDOUT;
-       }
-
-       /* Waiting for HSIC connect int*/
-       if (!wait_for_reg(base + PHY_28NM_HSIC_INT,
-           PHY_28NM_HSIC_CONNECT_INT, HZ / 5)) {
-               dev_warn(&pdev->dev, "HSIC wait for connect interrupt timeout.");
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static int mv_hsic_phy_power_off(struct phy *phy)
-{
-       struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
-       void __iomem *base = mv_phy->base;
-
-       writel(readl(base + PHY_28NM_HSIC_CTRL) & ~PHY_28NM_HSIC_S2H_HSIC_EN,
-               base + PHY_28NM_HSIC_CTRL);
-
-       return 0;
-}
-
-static int mv_hsic_phy_exit(struct phy *phy)
-{
-       struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
-       void __iomem *base = mv_phy->base;
-
-       /* Turn off PLL */
-       writel(readl(base + PHY_28NM_HSIC_PLL_CTRL2) &
-               ~PHY_28NM_HSIC_S2H_PU_PLL,
-               base + PHY_28NM_HSIC_PLL_CTRL2);
-
-       clk_disable_unprepare(mv_phy->clk);
-       return 0;
-}
-
-
-static const struct phy_ops hsic_ops = {
-       .init           = mv_hsic_phy_init,
-       .power_on       = mv_hsic_phy_power_on,
-       .power_off      = mv_hsic_phy_power_off,
-       .exit           = mv_hsic_phy_exit,
-       .owner          = THIS_MODULE,
-};
-
-static int mv_hsic_phy_probe(struct platform_device *pdev)
-{
-       struct phy_provider *phy_provider;
-       struct mv_hsic_phy *mv_phy;
-       struct resource *r;
-
-       mv_phy = devm_kzalloc(&pdev->dev, sizeof(*mv_phy), GFP_KERNEL);
-       if (!mv_phy)
-               return -ENOMEM;
-
-       mv_phy->pdev = pdev;
-
-       mv_phy->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(mv_phy->clk)) {
-               dev_err(&pdev->dev, "failed to get clock.\n");
-               return PTR_ERR(mv_phy->clk);
-       }
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       mv_phy->base = devm_ioremap_resource(&pdev->dev, r);
-       if (IS_ERR(mv_phy->base))
-               return PTR_ERR(mv_phy->base);
-
-       mv_phy->phy = devm_phy_create(&pdev->dev, pdev->dev.of_node, &hsic_ops);
-       if (IS_ERR(mv_phy->phy))
-               return PTR_ERR(mv_phy->phy);
-
-       phy_set_drvdata(mv_phy->phy, mv_phy);
-
-       phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static const struct of_device_id mv_hsic_phy_dt_match[] = {
-       { .compatible = "marvell,pxa1928-hsic-phy", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, mv_hsic_phy_dt_match);
-
-static struct platform_driver mv_hsic_phy_driver = {
-       .probe  = mv_hsic_phy_probe,
-       .driver = {
-               .name   = "mv-hsic-phy",
-               .of_match_table = of_match_ptr(mv_hsic_phy_dt_match),
-       },
-};
-module_platform_driver(mv_hsic_phy_driver);
-
-MODULE_AUTHOR("Rob Herring <robh@kernel.org>");
-MODULE_DESCRIPTION("Marvell HSIC phy driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-pxa-28nm-usb2.c b/drivers/phy/phy-pxa-28nm-usb2.c
deleted file mode 100644 (file)
index 37e9c8c..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright (C) 2015 Linaro, Ltd.
- * Rob Herring <robh@kernel.org>
- *
- * Based on vendor driver:
- * Copyright (C) 2013 Marvell Inc.
- * Author: Chao Xie <xiechao.mail@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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/slab.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/phy/phy.h>
-
-/* USB PXA1928 PHY mapping */
-#define PHY_28NM_PLL_REG0                      0x0
-#define PHY_28NM_PLL_REG1                      0x4
-#define PHY_28NM_CAL_REG                       0x8
-#define PHY_28NM_TX_REG0                       0x0c
-#define PHY_28NM_TX_REG1                       0x10
-#define PHY_28NM_RX_REG0                       0x14
-#define PHY_28NM_RX_REG1                       0x18
-#define PHY_28NM_DIG_REG0                      0x1c
-#define PHY_28NM_DIG_REG1                      0x20
-#define PHY_28NM_TEST_REG0                     0x24
-#define PHY_28NM_TEST_REG1                     0x28
-#define PHY_28NM_MOC_REG                       0x2c
-#define PHY_28NM_PHY_RESERVE                   0x30
-#define PHY_28NM_OTG_REG                       0x34
-#define PHY_28NM_CHRG_DET                      0x38
-#define PHY_28NM_CTRL_REG0                     0xc4
-#define PHY_28NM_CTRL_REG1                     0xc8
-#define PHY_28NM_CTRL_REG2                     0xd4
-#define PHY_28NM_CTRL_REG3                     0xdc
-
-/* PHY_28NM_PLL_REG0 */
-#define PHY_28NM_PLL_READY                     BIT(31)
-
-#define PHY_28NM_PLL_SELLPFR_SHIFT             28
-#define PHY_28NM_PLL_SELLPFR_MASK              (0x3 << 28)
-
-#define PHY_28NM_PLL_FBDIV_SHIFT               16
-#define PHY_28NM_PLL_FBDIV_MASK                        (0x1ff << 16)
-
-#define PHY_28NM_PLL_ICP_SHIFT                 8
-#define PHY_28NM_PLL_ICP_MASK                  (0x7 << 8)
-
-#define PHY_28NM_PLL_REFDIV_SHIFT              0
-#define PHY_28NM_PLL_REFDIV_MASK               0x7f
-
-/* PHY_28NM_PLL_REG1 */
-#define PHY_28NM_PLL_PU_BY_REG                 BIT(1)
-
-#define PHY_28NM_PLL_PU_PLL                    BIT(0)
-
-/* PHY_28NM_CAL_REG */
-#define PHY_28NM_PLL_PLLCAL_DONE               BIT(31)
-
-#define PHY_28NM_PLL_IMPCAL_DONE               BIT(23)
-
-#define PHY_28NM_PLL_KVCO_SHIFT                        16
-#define PHY_28NM_PLL_KVCO_MASK                 (0x7 << 16)
-
-#define PHY_28NM_PLL_CAL12_SHIFT               20
-#define PHY_28NM_PLL_CAL12_MASK                        (0x3 << 20)
-
-#define PHY_28NM_IMPCAL_VTH_SHIFT              8
-#define PHY_28NM_IMPCAL_VTH_MASK               (0x7 << 8)
-
-#define PHY_28NM_PLLCAL_START_SHIFT            22
-#define PHY_28NM_IMPCAL_START_SHIFT            13
-
-/* PHY_28NM_TX_REG0 */
-#define PHY_28NM_TX_PU_BY_REG                  BIT(25)
-
-#define PHY_28NM_TX_PU_ANA                     BIT(24)
-
-#define PHY_28NM_TX_AMP_SHIFT                  20
-#define PHY_28NM_TX_AMP_MASK                   (0x7 << 20)
-
-/* PHY_28NM_RX_REG0 */
-#define PHY_28NM_RX_SQ_THRESH_SHIFT            0
-#define PHY_28NM_RX_SQ_THRESH_MASK             (0xf << 0)
-
-/* PHY_28NM_RX_REG1 */
-#define PHY_28NM_RX_SQCAL_DONE                 BIT(31)
-
-/* PHY_28NM_DIG_REG0 */
-#define PHY_28NM_DIG_BITSTAFFING_ERR           BIT(31)
-#define PHY_28NM_DIG_SYNC_ERR                  BIT(30)
-
-#define PHY_28NM_DIG_SQ_FILT_SHIFT             16
-#define PHY_28NM_DIG_SQ_FILT_MASK              (0x7 << 16)
-
-#define PHY_28NM_DIG_SQ_BLK_SHIFT              12
-#define PHY_28NM_DIG_SQ_BLK_MASK               (0x7 << 12)
-
-#define PHY_28NM_DIG_SYNC_NUM_SHIFT            0
-#define PHY_28NM_DIG_SYNC_NUM_MASK             (0x3 << 0)
-
-#define PHY_28NM_PLL_LOCK_BYPASS               BIT(7)
-
-/* PHY_28NM_OTG_REG */
-#define PHY_28NM_OTG_CONTROL_BY_PIN            BIT(5)
-#define PHY_28NM_OTG_PU_OTG                    BIT(4)
-
-#define PHY_28NM_CHGDTC_ENABLE_SWITCH_DM_SHIFT_28 13
-#define PHY_28NM_CHGDTC_ENABLE_SWITCH_DP_SHIFT_28 12
-#define PHY_28NM_CHGDTC_VSRC_CHARGE_SHIFT_28   10
-#define PHY_28NM_CHGDTC_VDAT_CHARGE_SHIFT_28   8
-#define PHY_28NM_CHGDTC_CDP_DM_AUTO_SWITCH_SHIFT_28 7
-#define PHY_28NM_CHGDTC_DP_DM_SWAP_SHIFT_28    6
-#define PHY_28NM_CHGDTC_PU_CHRG_DTC_SHIFT_28   5
-#define PHY_28NM_CHGDTC_PD_EN_SHIFT_28         4
-#define PHY_28NM_CHGDTC_DCP_EN_SHIFT_28                3
-#define PHY_28NM_CHGDTC_CDP_EN_SHIFT_28                2
-#define PHY_28NM_CHGDTC_TESTMON_CHRGDTC_SHIFT_28 0
-
-#define PHY_28NM_CTRL1_CHRG_DTC_OUT_SHIFT_28   4
-#define PHY_28NM_CTRL1_VBUSDTC_OUT_SHIFT_28    2
-
-#define PHY_28NM_CTRL3_OVERWRITE               BIT(0)
-#define PHY_28NM_CTRL3_VBUS_VALID              BIT(4)
-#define PHY_28NM_CTRL3_AVALID                  BIT(5)
-#define PHY_28NM_CTRL3_BVALID                  BIT(6)
-
-struct mv_usb2_phy {
-       struct phy              *phy;
-       struct platform_device  *pdev;
-       void __iomem            *base;
-       struct clk              *clk;
-};
-
-static bool wait_for_reg(void __iomem *reg, u32 mask, unsigned long timeout)
-{
-       timeout += jiffies;
-       while (time_is_after_eq_jiffies(timeout)) {
-               if ((readl(reg) & mask) == mask)
-                       return true;
-               msleep(1);
-       }
-       return false;
-}
-
-static int mv_usb2_phy_28nm_init(struct phy *phy)
-{
-       struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
-       struct platform_device *pdev = mv_phy->pdev;
-       void __iomem *base = mv_phy->base;
-       u32 reg;
-       int ret;
-
-       clk_prepare_enable(mv_phy->clk);
-
-       /* PHY_28NM_PLL_REG0 */
-       reg = readl(base + PHY_28NM_PLL_REG0) &
-               ~(PHY_28NM_PLL_SELLPFR_MASK | PHY_28NM_PLL_FBDIV_MASK
-               | PHY_28NM_PLL_ICP_MASK | PHY_28NM_PLL_REFDIV_MASK);
-       writel(reg | (0x1 << PHY_28NM_PLL_SELLPFR_SHIFT
-               | 0xf0 << PHY_28NM_PLL_FBDIV_SHIFT
-               | 0x3 << PHY_28NM_PLL_ICP_SHIFT
-               | 0xd << PHY_28NM_PLL_REFDIV_SHIFT),
-               base + PHY_28NM_PLL_REG0);
-
-       /* PHY_28NM_PLL_REG1 */
-       reg = readl(base + PHY_28NM_PLL_REG1);
-       writel(reg | PHY_28NM_PLL_PU_PLL | PHY_28NM_PLL_PU_BY_REG,
-               base + PHY_28NM_PLL_REG1);
-
-       /* PHY_28NM_TX_REG0 */
-       reg = readl(base + PHY_28NM_TX_REG0) & ~PHY_28NM_TX_AMP_MASK;
-       writel(reg | PHY_28NM_TX_PU_BY_REG | 0x3 << PHY_28NM_TX_AMP_SHIFT |
-               PHY_28NM_TX_PU_ANA,
-               base + PHY_28NM_TX_REG0);
-
-       /* PHY_28NM_RX_REG0 */
-       reg = readl(base + PHY_28NM_RX_REG0) & ~PHY_28NM_RX_SQ_THRESH_MASK;
-       writel(reg | 0xa << PHY_28NM_RX_SQ_THRESH_SHIFT,
-               base + PHY_28NM_RX_REG0);
-
-       /* PHY_28NM_DIG_REG0 */
-       reg = readl(base + PHY_28NM_DIG_REG0) &
-               ~(PHY_28NM_DIG_BITSTAFFING_ERR | PHY_28NM_DIG_SYNC_ERR |
-               PHY_28NM_DIG_SQ_FILT_MASK | PHY_28NM_DIG_SQ_BLK_MASK |
-               PHY_28NM_DIG_SYNC_NUM_MASK);
-       writel(reg | (0x1 << PHY_28NM_DIG_SYNC_NUM_SHIFT |
-               PHY_28NM_PLL_LOCK_BYPASS),
-               base + PHY_28NM_DIG_REG0);
-
-       /* PHY_28NM_OTG_REG */
-       reg = readl(base + PHY_28NM_OTG_REG) | PHY_28NM_OTG_PU_OTG;
-       writel(reg & ~PHY_28NM_OTG_CONTROL_BY_PIN, base + PHY_28NM_OTG_REG);
-
-       /*
-        *  Calibration Timing
-        *                 ____________________________
-        *  CAL START   ___|
-        *                         ____________________
-        *  CAL_DONE    ___________|
-        *                 | 400us |
-        */
-
-       /* Make sure PHY Calibration is ready */
-       if (!wait_for_reg(base + PHY_28NM_CAL_REG,
-           PHY_28NM_PLL_PLLCAL_DONE | PHY_28NM_PLL_IMPCAL_DONE,
-           HZ / 10)) {
-               dev_warn(&pdev->dev, "USB PHY PLL calibrate not done after 100mS.");
-               ret = -ETIMEDOUT;
-               goto err_clk;
-       }
-       if (!wait_for_reg(base + PHY_28NM_RX_REG1,
-           PHY_28NM_RX_SQCAL_DONE, HZ / 10)) {
-               dev_warn(&pdev->dev, "USB PHY RX SQ calibrate not done after 100mS.");
-               ret = -ETIMEDOUT;
-               goto err_clk;
-       }
-       /* Make sure PHY PLL is ready */
-       if (!wait_for_reg(base + PHY_28NM_PLL_REG0,
-           PHY_28NM_PLL_READY, HZ / 10)) {
-               dev_warn(&pdev->dev, "PLL_READY not set after 100mS.");
-               ret = -ETIMEDOUT;
-               goto err_clk;
-       }
-
-       return 0;
-err_clk:
-       clk_disable_unprepare(mv_phy->clk);
-       return ret;
-}
-
-static int mv_usb2_phy_28nm_power_on(struct phy *phy)
-{
-       struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
-       void __iomem *base = mv_phy->base;
-
-       writel(readl(base + PHY_28NM_CTRL_REG3) |
-               (PHY_28NM_CTRL3_OVERWRITE | PHY_28NM_CTRL3_VBUS_VALID |
-               PHY_28NM_CTRL3_AVALID | PHY_28NM_CTRL3_BVALID),
-               base + PHY_28NM_CTRL_REG3);
-
-       return 0;
-}
-
-static int mv_usb2_phy_28nm_power_off(struct phy *phy)
-{
-       struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
-       void __iomem *base = mv_phy->base;
-
-       writel(readl(base + PHY_28NM_CTRL_REG3) |
-               ~(PHY_28NM_CTRL3_OVERWRITE | PHY_28NM_CTRL3_VBUS_VALID
-               | PHY_28NM_CTRL3_AVALID | PHY_28NM_CTRL3_BVALID),
-               base + PHY_28NM_CTRL_REG3);
-
-       return 0;
-}
-
-static int mv_usb2_phy_28nm_exit(struct phy *phy)
-{
-       struct mv_usb2_phy *mv_phy = phy_get_drvdata(phy);
-       void __iomem *base = mv_phy->base;
-       unsigned int val;
-
-       val = readw(base + PHY_28NM_PLL_REG1);
-       val &= ~PHY_28NM_PLL_PU_PLL;
-       writew(val, base + PHY_28NM_PLL_REG1);
-
-       /* power down PHY Analog part */
-       val = readw(base + PHY_28NM_TX_REG0);
-       val &= ~PHY_28NM_TX_PU_ANA;
-       writew(val, base + PHY_28NM_TX_REG0);
-
-       /* power down PHY OTG part */
-       val = readw(base + PHY_28NM_OTG_REG);
-       val &= ~PHY_28NM_OTG_PU_OTG;
-       writew(val, base + PHY_28NM_OTG_REG);
-
-       clk_disable_unprepare(mv_phy->clk);
-       return 0;
-}
-
-static const struct phy_ops usb_ops = {
-       .init           = mv_usb2_phy_28nm_init,
-       .power_on       = mv_usb2_phy_28nm_power_on,
-       .power_off      = mv_usb2_phy_28nm_power_off,
-       .exit           = mv_usb2_phy_28nm_exit,
-       .owner          = THIS_MODULE,
-};
-
-static int mv_usb2_phy_probe(struct platform_device *pdev)
-{
-       struct phy_provider *phy_provider;
-       struct mv_usb2_phy *mv_phy;
-       struct resource *r;
-
-       mv_phy = devm_kzalloc(&pdev->dev, sizeof(*mv_phy), GFP_KERNEL);
-       if (!mv_phy)
-               return -ENOMEM;
-
-       mv_phy->pdev = pdev;
-
-       mv_phy->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(mv_phy->clk)) {
-               dev_err(&pdev->dev, "failed to get clock.\n");
-               return PTR_ERR(mv_phy->clk);
-       }
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       mv_phy->base = devm_ioremap_resource(&pdev->dev, r);
-       if (IS_ERR(mv_phy->base))
-               return PTR_ERR(mv_phy->base);
-
-       mv_phy->phy = devm_phy_create(&pdev->dev, pdev->dev.of_node, &usb_ops);
-       if (IS_ERR(mv_phy->phy))
-               return PTR_ERR(mv_phy->phy);
-
-       phy_set_drvdata(mv_phy->phy, mv_phy);
-
-       phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static const struct of_device_id mv_usbphy_dt_match[] = {
-       { .compatible = "marvell,pxa1928-usb-phy", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, mv_usbphy_dt_match);
-
-static struct platform_driver mv_usb2_phy_driver = {
-       .probe  = mv_usb2_phy_probe,
-       .driver = {
-               .name   = "mv-usb2-phy",
-               .of_match_table = of_match_ptr(mv_usbphy_dt_match),
-       },
-};
-module_platform_driver(mv_usb2_phy_driver);
-
-MODULE_AUTHOR("Rob Herring <robh@kernel.org>");
-MODULE_DESCRIPTION("Marvell USB2 phy driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c
deleted file mode 100644 (file)
index 69ce2af..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/phy/phy.h>
-
-/* PHY registers */
-#define UNIPHY_PLL_REFCLK_CFG          0x000
-#define UNIPHY_PLL_PWRGEN_CFG          0x014
-#define UNIPHY_PLL_GLB_CFG             0x020
-#define UNIPHY_PLL_SDM_CFG0            0x038
-#define UNIPHY_PLL_SDM_CFG1            0x03C
-#define UNIPHY_PLL_SDM_CFG2            0x040
-#define UNIPHY_PLL_SDM_CFG3            0x044
-#define UNIPHY_PLL_SDM_CFG4            0x048
-#define UNIPHY_PLL_SSC_CFG0            0x04C
-#define UNIPHY_PLL_SSC_CFG1            0x050
-#define UNIPHY_PLL_SSC_CFG2            0x054
-#define UNIPHY_PLL_SSC_CFG3            0x058
-#define UNIPHY_PLL_LKDET_CFG0          0x05C
-#define UNIPHY_PLL_LKDET_CFG1          0x060
-#define UNIPHY_PLL_LKDET_CFG2          0x064
-#define UNIPHY_PLL_CAL_CFG0            0x06C
-#define UNIPHY_PLL_CAL_CFG8            0x08C
-#define UNIPHY_PLL_CAL_CFG9            0x090
-#define UNIPHY_PLL_CAL_CFG10           0x094
-#define UNIPHY_PLL_CAL_CFG11           0x098
-#define UNIPHY_PLL_STATUS              0x0C0
-
-#define SATA_PHY_SER_CTRL              0x100
-#define SATA_PHY_TX_DRIV_CTRL0         0x104
-#define SATA_PHY_TX_DRIV_CTRL1         0x108
-#define SATA_PHY_TX_IMCAL0             0x11C
-#define SATA_PHY_TX_IMCAL2             0x124
-#define SATA_PHY_RX_IMCAL0             0x128
-#define SATA_PHY_EQUAL                 0x13C
-#define SATA_PHY_OOB_TERM              0x144
-#define SATA_PHY_CDR_CTRL0             0x148
-#define SATA_PHY_CDR_CTRL1             0x14C
-#define SATA_PHY_CDR_CTRL2             0x150
-#define SATA_PHY_CDR_CTRL3             0x154
-#define SATA_PHY_PI_CTRL0              0x168
-#define SATA_PHY_POW_DWN_CTRL0         0x180
-#define SATA_PHY_POW_DWN_CTRL1         0x184
-#define SATA_PHY_TX_DATA_CTRL          0x188
-#define SATA_PHY_ALIGNP                        0x1A4
-#define SATA_PHY_TX_IMCAL_STAT         0x1E4
-#define SATA_PHY_RX_IMCAL_STAT         0x1E8
-
-#define UNIPHY_PLL_LOCK                BIT(0)
-#define SATA_PHY_TX_CAL                BIT(0)
-#define SATA_PHY_RX_CAL                BIT(0)
-
-/* default timeout set to 1 sec */
-#define TIMEOUT_MS             10000
-#define DELAY_INTERVAL_US      100
-
-struct qcom_apq8064_sata_phy {
-       void __iomem *mmio;
-       struct clk *cfg_clk;
-       struct device *dev;
-};
-
-/* Helper function to do poll and timeout */
-static int read_poll_timeout(void __iomem *addr, u32 mask)
-{
-       unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS);
-
-       do {
-               if (readl_relaxed(addr) & mask)
-                       return 0;
-
-                usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
-       } while (!time_after(jiffies, timeout));
-
-       return (readl_relaxed(addr) & mask) ? 0 : -ETIMEDOUT;
-}
-
-static int qcom_apq8064_sata_phy_init(struct phy *generic_phy)
-{
-       struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
-       void __iomem *base = phy->mmio;
-       int ret = 0;
-
-       /* SATA phy initialization */
-       writel_relaxed(0x01, base + SATA_PHY_SER_CTRL);
-       writel_relaxed(0xB1, base + SATA_PHY_POW_DWN_CTRL0);
-       /* Make sure the power down happens before power up */
-       mb();
-       usleep_range(10, 60);
-
-       writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
-       writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
-       writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
-       writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
-       writel_relaxed(0x02, base + SATA_PHY_TX_IMCAL2);
-
-       /* Write UNIPHYPLL registers to configure PLL */
-       writel_relaxed(0x04, base + UNIPHY_PLL_REFCLK_CFG);
-       writel_relaxed(0x00, base + UNIPHY_PLL_PWRGEN_CFG);
-
-       writel_relaxed(0x0A, base + UNIPHY_PLL_CAL_CFG0);
-       writel_relaxed(0xF3, base + UNIPHY_PLL_CAL_CFG8);
-       writel_relaxed(0x01, base + UNIPHY_PLL_CAL_CFG9);
-       writel_relaxed(0xED, base + UNIPHY_PLL_CAL_CFG10);
-       writel_relaxed(0x02, base + UNIPHY_PLL_CAL_CFG11);
-
-       writel_relaxed(0x36, base + UNIPHY_PLL_SDM_CFG0);
-       writel_relaxed(0x0D, base + UNIPHY_PLL_SDM_CFG1);
-       writel_relaxed(0xA3, base + UNIPHY_PLL_SDM_CFG2);
-       writel_relaxed(0xF0, base + UNIPHY_PLL_SDM_CFG3);
-       writel_relaxed(0x00, base + UNIPHY_PLL_SDM_CFG4);
-
-       writel_relaxed(0x19, base + UNIPHY_PLL_SSC_CFG0);
-       writel_relaxed(0xE1, base + UNIPHY_PLL_SSC_CFG1);
-       writel_relaxed(0x00, base + UNIPHY_PLL_SSC_CFG2);
-       writel_relaxed(0x11, base + UNIPHY_PLL_SSC_CFG3);
-
-       writel_relaxed(0x04, base + UNIPHY_PLL_LKDET_CFG0);
-       writel_relaxed(0xFF, base + UNIPHY_PLL_LKDET_CFG1);
-
-       writel_relaxed(0x02, base + UNIPHY_PLL_GLB_CFG);
-       /* make sure global config LDO power down happens before power up */
-       mb();
-
-       writel_relaxed(0x03, base + UNIPHY_PLL_GLB_CFG);
-       writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2);
-
-       /* PLL Lock wait */
-       ret = read_poll_timeout(base + UNIPHY_PLL_STATUS, UNIPHY_PLL_LOCK);
-       if (ret) {
-               dev_err(phy->dev, "poll timeout UNIPHY_PLL_STATUS\n");
-               return ret;
-       }
-
-       /* TX Calibration */
-       ret = read_poll_timeout(base + SATA_PHY_TX_IMCAL_STAT, SATA_PHY_TX_CAL);
-       if (ret) {
-               dev_err(phy->dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n");
-               return ret;
-       }
-
-       /* RX Calibration */
-       ret = read_poll_timeout(base + SATA_PHY_RX_IMCAL_STAT, SATA_PHY_RX_CAL);
-       if (ret) {
-               dev_err(phy->dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n");
-               return ret;
-       }
-
-       /* SATA phy calibrated succesfully, power up to functional mode */
-       writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
-       writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
-       writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
-
-       writel_relaxed(0x00, base + SATA_PHY_POW_DWN_CTRL1);
-       writel_relaxed(0x59, base + SATA_PHY_CDR_CTRL0);
-       writel_relaxed(0x04, base + SATA_PHY_CDR_CTRL1);
-       writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL2);
-       writel_relaxed(0x00, base + SATA_PHY_PI_CTRL0);
-       writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL3);
-       writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
-
-       writel_relaxed(0x11, base + SATA_PHY_TX_DATA_CTRL);
-       writel_relaxed(0x43, base + SATA_PHY_ALIGNP);
-       writel_relaxed(0x04, base + SATA_PHY_OOB_TERM);
-
-       writel_relaxed(0x01, base + SATA_PHY_EQUAL);
-       writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL0);
-       writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL1);
-
-       return 0;
-}
-
-static int qcom_apq8064_sata_phy_exit(struct phy *generic_phy)
-{
-       struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
-       void __iomem *base = phy->mmio;
-
-       /* Power down PHY */
-       writel_relaxed(0xF8, base + SATA_PHY_POW_DWN_CTRL0);
-       writel_relaxed(0xFE, base + SATA_PHY_POW_DWN_CTRL1);
-
-       /* Power down PLL block */
-       writel_relaxed(0x00, base + UNIPHY_PLL_GLB_CFG);
-
-       return 0;
-}
-
-static const struct phy_ops qcom_apq8064_sata_phy_ops = {
-       .init           = qcom_apq8064_sata_phy_init,
-       .exit           = qcom_apq8064_sata_phy_exit,
-       .owner          = THIS_MODULE,
-};
-
-static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev)
-{
-       struct qcom_apq8064_sata_phy *phy;
-       struct device *dev = &pdev->dev;
-       struct resource *res;
-       struct phy_provider *phy_provider;
-       struct phy *generic_phy;
-       int ret;
-
-       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
-       if (!phy)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       phy->mmio = devm_ioremap_resource(dev, res);
-       if (IS_ERR(phy->mmio))
-               return PTR_ERR(phy->mmio);
-
-       generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops);
-       if (IS_ERR(generic_phy)) {
-               dev_err(dev, "%s: failed to create phy\n", __func__);
-               return PTR_ERR(generic_phy);
-       }
-
-       phy->dev = dev;
-       phy_set_drvdata(generic_phy, phy);
-       platform_set_drvdata(pdev, phy);
-
-       phy->cfg_clk = devm_clk_get(dev, "cfg");
-       if (IS_ERR(phy->cfg_clk)) {
-               dev_err(dev, "Failed to get sata cfg clock\n");
-               return PTR_ERR(phy->cfg_clk);
-       }
-
-       ret = clk_prepare_enable(phy->cfg_clk);
-       if (ret)
-               return ret;
-
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (IS_ERR(phy_provider)) {
-               clk_disable_unprepare(phy->cfg_clk);
-               dev_err(dev, "%s: failed to register phy\n", __func__);
-               return PTR_ERR(phy_provider);
-       }
-
-       return 0;
-}
-
-static int qcom_apq8064_sata_phy_remove(struct platform_device *pdev)
-{
-       struct qcom_apq8064_sata_phy *phy = platform_get_drvdata(pdev);
-
-       clk_disable_unprepare(phy->cfg_clk);
-
-       return 0;
-}
-
-static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = {
-       { .compatible = "qcom,apq8064-sata-phy" },
-       { },
-};
-MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match);
-
-static struct platform_driver qcom_apq8064_sata_phy_driver = {
-       .probe  = qcom_apq8064_sata_phy_probe,
-       .remove = qcom_apq8064_sata_phy_remove,
-       .driver = {
-               .name   = "qcom-apq8064-sata-phy",
-               .of_match_table = qcom_apq8064_sata_phy_of_match,
-       }
-};
-module_platform_driver(qcom_apq8064_sata_phy_driver);
-
-MODULE_DESCRIPTION("QCOM apq8064 SATA PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/phy-qcom-ipq806x-sata.c
deleted file mode 100644 (file)
index 0ad127c..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/phy/phy.h>
-
-struct qcom_ipq806x_sata_phy {
-       void __iomem *mmio;
-       struct clk *cfg_clk;
-       struct device *dev;
-};
-
-#define __set(v, a, b) (((v) << (b)) & GENMASK(a, b))
-
-#define SATA_PHY_P0_PARAM0             0x200
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(x)       __set(x, 17, 12)
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK     GENMASK(17, 12)
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2(x)       __set(x, 11, 6)
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK     GENMASK(11, 6)
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1(x)       __set(x, 5, 0)
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK     GENMASK(5, 0)
-
-#define SATA_PHY_P0_PARAM1             0x204
-#define SATA_PHY_P0_PARAM1_RESERVED_BITS31_21(x)       __set(x, 31, 21)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(x)     __set(x, 20, 14)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK   GENMASK(20, 14)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(x)     __set(x, 13, 7)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK   GENMASK(13, 7)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(x)     __set(x, 6, 0)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK   GENMASK(6, 0)
-
-#define SATA_PHY_P0_PARAM2             0x208
-#define SATA_PHY_P0_PARAM2_RX_EQ(x)    __set(x, 20, 18)
-#define SATA_PHY_P0_PARAM2_RX_EQ_MASK  GENMASK(20, 18)
-
-#define SATA_PHY_P0_PARAM3             0x20C
-#define SATA_PHY_SSC_EN                        0x8
-#define SATA_PHY_P0_PARAM4             0x210
-#define SATA_PHY_REF_SSP_EN            0x2
-#define SATA_PHY_RESET                 0x1
-
-static int qcom_ipq806x_sata_phy_init(struct phy *generic_phy)
-{
-       struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
-       u32 reg;
-
-       /* Setting SSC_EN to 1 */
-       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM3);
-       reg = reg | SATA_PHY_SSC_EN;
-       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM3);
-
-       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM0) &
-                       ~(SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK |
-                         SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK |
-                         SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK);
-       reg |= SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(0xf);
-       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM0);
-
-       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM1) &
-                       ~(SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK |
-                         SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK |
-                         SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK);
-       reg |= SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(0x55) |
-               SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(0x55) |
-               SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(0x55);
-       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM1);
-
-       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM2) &
-               ~SATA_PHY_P0_PARAM2_RX_EQ_MASK;
-       reg |= SATA_PHY_P0_PARAM2_RX_EQ(0x3);
-       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM2);
-
-       /* Setting PHY_RESET to 1 */
-       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
-       reg = reg | SATA_PHY_RESET;
-       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
-
-       /* Setting REF_SSP_EN to 1 */
-       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
-       reg = reg | SATA_PHY_REF_SSP_EN | SATA_PHY_RESET;
-       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
-
-       /* make sure all changes complete before we let the PHY out of reset */
-       mb();
-
-       /* sleep for max. 50us more to combine processor wakeups */
-       usleep_range(20, 20 + 50);
-
-       /* Clearing PHY_RESET to 0 */
-       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
-       reg = reg & ~SATA_PHY_RESET;
-       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
-
-       return 0;
-}
-
-static int qcom_ipq806x_sata_phy_exit(struct phy *generic_phy)
-{
-       struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
-       u32 reg;
-
-       /* Setting PHY_RESET to 1 */
-       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
-       reg = reg | SATA_PHY_RESET;
-       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
-
-       return 0;
-}
-
-static const struct phy_ops qcom_ipq806x_sata_phy_ops = {
-       .init           = qcom_ipq806x_sata_phy_init,
-       .exit           = qcom_ipq806x_sata_phy_exit,
-       .owner          = THIS_MODULE,
-};
-
-static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev)
-{
-       struct qcom_ipq806x_sata_phy *phy;
-       struct device *dev = &pdev->dev;
-       struct resource *res;
-       struct phy_provider *phy_provider;
-       struct phy *generic_phy;
-       int ret;
-
-       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
-       if (!phy)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       phy->mmio = devm_ioremap_resource(dev, res);
-       if (IS_ERR(phy->mmio))
-               return PTR_ERR(phy->mmio);
-
-       generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops);
-       if (IS_ERR(generic_phy)) {
-               dev_err(dev, "%s: failed to create phy\n", __func__);
-               return PTR_ERR(generic_phy);
-       }
-
-       phy->dev = dev;
-       phy_set_drvdata(generic_phy, phy);
-       platform_set_drvdata(pdev, phy);
-
-       phy->cfg_clk = devm_clk_get(dev, "cfg");
-       if (IS_ERR(phy->cfg_clk)) {
-               dev_err(dev, "Failed to get sata cfg clock\n");
-               return PTR_ERR(phy->cfg_clk);
-       }
-
-       ret = clk_prepare_enable(phy->cfg_clk);
-       if (ret)
-               return ret;
-
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (IS_ERR(phy_provider)) {
-               clk_disable_unprepare(phy->cfg_clk);
-               dev_err(dev, "%s: failed to register phy\n", __func__);
-               return PTR_ERR(phy_provider);
-       }
-
-       return 0;
-}
-
-static int qcom_ipq806x_sata_phy_remove(struct platform_device *pdev)
-{
-       struct qcom_ipq806x_sata_phy *phy = platform_get_drvdata(pdev);
-
-       clk_disable_unprepare(phy->cfg_clk);
-
-       return 0;
-}
-
-static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = {
-       { .compatible = "qcom,ipq806x-sata-phy" },
-       { },
-};
-MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match);
-
-static struct platform_driver qcom_ipq806x_sata_phy_driver = {
-       .probe  = qcom_ipq806x_sata_phy_probe,
-       .remove = qcom_ipq806x_sata_phy_remove,
-       .driver = {
-               .name   = "qcom-ipq806x-sata-phy",
-               .of_match_table = qcom_ipq806x_sata_phy_of_match,
-       }
-};
-module_platform_driver(qcom_ipq806x_sata_phy_driver);
-
-MODULE_DESCRIPTION("QCOM IPQ806x SATA PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-qcom-qmp.c b/drivers/phy/phy-qcom-qmp.c
deleted file mode 100644 (file)
index 78ca628..0000000
+++ /dev/null
@@ -1,1153 +0,0 @@
-/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_address.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/reset.h>
-#include <linux/slab.h>
-
-#include <dt-bindings/phy/phy.h>
-
-/* QMP PHY QSERDES COM registers */
-#define QSERDES_COM_BG_TIMER                           0x00c
-#define QSERDES_COM_SSC_EN_CENTER                      0x010
-#define QSERDES_COM_SSC_ADJ_PER1                       0x014
-#define QSERDES_COM_SSC_ADJ_PER2                       0x018
-#define QSERDES_COM_SSC_PER1                           0x01c
-#define QSERDES_COM_SSC_PER2                           0x020
-#define QSERDES_COM_SSC_STEP_SIZE1                     0x024
-#define QSERDES_COM_SSC_STEP_SIZE2                     0x028
-#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN                        0x034
-#define QSERDES_COM_CLK_ENABLE1                                0x038
-#define QSERDES_COM_SYS_CLK_CTRL                       0x03c
-#define QSERDES_COM_SYSCLK_BUF_ENABLE                  0x040
-#define QSERDES_COM_PLL_IVCO                           0x048
-#define QSERDES_COM_LOCK_CMP1_MODE0                    0x04c
-#define QSERDES_COM_LOCK_CMP2_MODE0                    0x050
-#define QSERDES_COM_LOCK_CMP3_MODE0                    0x054
-#define QSERDES_COM_LOCK_CMP1_MODE1                    0x058
-#define QSERDES_COM_LOCK_CMP2_MODE1                    0x05c
-#define QSERDES_COM_LOCK_CMP3_MODE1                    0x060
-#define QSERDES_COM_BG_TRIM                            0x070
-#define QSERDES_COM_CLK_EP_DIV                         0x074
-#define QSERDES_COM_CP_CTRL_MODE0                      0x078
-#define QSERDES_COM_CP_CTRL_MODE1                      0x07c
-#define QSERDES_COM_PLL_RCTRL_MODE0                    0x084
-#define QSERDES_COM_PLL_RCTRL_MODE1                    0x088
-#define QSERDES_COM_PLL_CCTRL_MODE0                    0x090
-#define QSERDES_COM_PLL_CCTRL_MODE1                    0x094
-#define QSERDES_COM_SYSCLK_EN_SEL                      0x0ac
-#define QSERDES_COM_RESETSM_CNTRL                      0x0b4
-#define QSERDES_COM_RESTRIM_CTRL                       0x0bc
-#define QSERDES_COM_RESCODE_DIV_NUM                    0x0c4
-#define QSERDES_COM_LOCK_CMP_EN                                0x0c8
-#define QSERDES_COM_LOCK_CMP_CFG                       0x0cc
-#define QSERDES_COM_DEC_START_MODE0                    0x0d0
-#define QSERDES_COM_DEC_START_MODE1                    0x0d4
-#define QSERDES_COM_DIV_FRAC_START1_MODE0              0x0dc
-#define QSERDES_COM_DIV_FRAC_START2_MODE0              0x0e0
-#define QSERDES_COM_DIV_FRAC_START3_MODE0              0x0e4
-#define QSERDES_COM_DIV_FRAC_START1_MODE1              0x0e8
-#define QSERDES_COM_DIV_FRAC_START2_MODE1              0x0ec
-#define QSERDES_COM_DIV_FRAC_START3_MODE1              0x0f0
-#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0              0x108
-#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0              0x10c
-#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1              0x110
-#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1              0x114
-#define QSERDES_COM_VCO_TUNE_CTRL                      0x124
-#define QSERDES_COM_VCO_TUNE_MAP                       0x128
-#define QSERDES_COM_VCO_TUNE1_MODE0                    0x12c
-#define QSERDES_COM_VCO_TUNE2_MODE0                    0x130
-#define QSERDES_COM_VCO_TUNE1_MODE1                    0x134
-#define QSERDES_COM_VCO_TUNE2_MODE1                    0x138
-#define QSERDES_COM_VCO_TUNE_TIMER1                    0x144
-#define QSERDES_COM_VCO_TUNE_TIMER2                    0x148
-#define QSERDES_COM_BG_CTRL                            0x170
-#define QSERDES_COM_CLK_SELECT                         0x174
-#define QSERDES_COM_HSCLK_SEL                          0x178
-#define QSERDES_COM_CORECLK_DIV                                0x184
-#define QSERDES_COM_CORE_CLK_EN                                0x18c
-#define QSERDES_COM_C_READY_STATUS                     0x190
-#define QSERDES_COM_CMN_CONFIG                         0x194
-#define QSERDES_COM_SVS_MODE_CLK_SEL                   0x19c
-#define QSERDES_COM_DEBUG_BUS0                         0x1a0
-#define QSERDES_COM_DEBUG_BUS1                         0x1a4
-#define QSERDES_COM_DEBUG_BUS2                         0x1a8
-#define QSERDES_COM_DEBUG_BUS3                         0x1ac
-#define QSERDES_COM_DEBUG_BUS_SEL                      0x1b0
-#define QSERDES_COM_CORECLK_DIV_MODE1                  0x1bc
-
-/* QMP PHY TX registers */
-#define QSERDES_TX_RES_CODE_LANE_OFFSET                        0x054
-#define QSERDES_TX_DEBUG_BUS_SEL                       0x064
-#define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN    0x068
-#define QSERDES_TX_LANE_MODE                           0x094
-#define QSERDES_TX_RCV_DETECT_LVL_2                    0x0ac
-
-/* QMP PHY RX registers */
-#define QSERDES_RX_UCDR_SO_GAIN_HALF                   0x010
-#define QSERDES_RX_UCDR_SO_GAIN                                0x01c
-#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN               0x040
-#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE       0x048
-#define QSERDES_RX_RX_TERM_BW                          0x090
-#define QSERDES_RX_RX_EQ_GAIN1_LSB                     0x0c4
-#define QSERDES_RX_RX_EQ_GAIN1_MSB                     0x0c8
-#define QSERDES_RX_RX_EQ_GAIN2_LSB                     0x0cc
-#define QSERDES_RX_RX_EQ_GAIN2_MSB                     0x0d0
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2               0x0d8
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3               0x0dc
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4               0x0e0
-#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1         0x108
-#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2            0x10c
-#define QSERDES_RX_SIGDET_ENABLES                      0x110
-#define QSERDES_RX_SIGDET_CNTRL                                0x114
-#define QSERDES_RX_SIGDET_LVL                          0x118
-#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL               0x11c
-#define QSERDES_RX_RX_BAND                             0x120
-#define QSERDES_RX_RX_INTERFACE_MODE                   0x12c
-
-/* QMP PHY PCS registers */
-#define QPHY_POWER_DOWN_CONTROL                                0x04
-#define QPHY_TXDEEMPH_M6DB_V0                          0x24
-#define QPHY_TXDEEMPH_M3P5DB_V0                                0x28
-#define QPHY_ENDPOINT_REFCLK_DRIVE                     0x54
-#define QPHY_RX_IDLE_DTCT_CNTRL                                0x58
-#define QPHY_POWER_STATE_CONFIG1                       0x60
-#define QPHY_POWER_STATE_CONFIG2                       0x64
-#define QPHY_POWER_STATE_CONFIG4                       0x6c
-#define QPHY_LOCK_DETECT_CONFIG1                       0x80
-#define QPHY_LOCK_DETECT_CONFIG2                       0x84
-#define QPHY_LOCK_DETECT_CONFIG3                       0x88
-#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK               0xa0
-#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK                 0xa4
-
-/* QPHY_SW_RESET bit */
-#define SW_RESET                               BIT(0)
-/* QPHY_POWER_DOWN_CONTROL */
-#define SW_PWRDN                               BIT(0)
-#define REFCLK_DRV_DSBL                                BIT(1)
-/* QPHY_START_CONTROL bits */
-#define SERDES_START                           BIT(0)
-#define PCS_START                              BIT(1)
-#define PLL_READY_GATE_EN                      BIT(3)
-/* QPHY_PCS_STATUS bit */
-#define PHYSTATUS                              BIT(6)
-/* QPHY_COM_PCS_READY_STATUS bit */
-#define PCS_READY                              BIT(0)
-
-#define PHY_INIT_COMPLETE_TIMEOUT              1000
-#define POWER_DOWN_DELAY_US_MIN                        10
-#define POWER_DOWN_DELAY_US_MAX                        11
-
-#define MAX_PROP_NAME                          32
-
-struct qmp_phy_init_tbl {
-       unsigned int offset;
-       unsigned int val;
-       /*
-        * register part of layout ?
-        * if yes, then offset gives index in the reg-layout
-        */
-       int in_layout;
-};
-
-#define QMP_PHY_INIT_CFG(o, v)         \
-       {                               \
-               .offset = o,            \
-               .val = v,               \
-       }
-
-#define QMP_PHY_INIT_CFG_L(o, v)       \
-       {                               \
-               .offset = o,            \
-               .val = v,               \
-               .in_layout = 1,         \
-       }
-
-/* set of registers with offsets different per-PHY */
-enum qphy_reg_layout {
-       /* Common block control registers */
-       QPHY_COM_SW_RESET,
-       QPHY_COM_POWER_DOWN_CONTROL,
-       QPHY_COM_START_CONTROL,
-       QPHY_COM_PCS_READY_STATUS,
-       /* PCS registers */
-       QPHY_PLL_LOCK_CHK_DLY_TIME,
-       QPHY_FLL_CNTRL1,
-       QPHY_FLL_CNTRL2,
-       QPHY_FLL_CNT_VAL_L,
-       QPHY_FLL_CNT_VAL_H_TOL,
-       QPHY_FLL_MAN_CODE,
-       QPHY_SW_RESET,
-       QPHY_START_CTRL,
-       QPHY_PCS_READY_STATUS,
-};
-
-static const unsigned int pciephy_regs_layout[] = {
-       [QPHY_COM_SW_RESET]             = 0x400,
-       [QPHY_COM_POWER_DOWN_CONTROL]   = 0x404,
-       [QPHY_COM_START_CONTROL]        = 0x408,
-       [QPHY_COM_PCS_READY_STATUS]     = 0x448,
-       [QPHY_PLL_LOCK_CHK_DLY_TIME]    = 0xa8,
-       [QPHY_FLL_CNTRL1]               = 0xc4,
-       [QPHY_FLL_CNTRL2]               = 0xc8,
-       [QPHY_FLL_CNT_VAL_L]            = 0xcc,
-       [QPHY_FLL_CNT_VAL_H_TOL]        = 0xd0,
-       [QPHY_FLL_MAN_CODE]             = 0xd4,
-       [QPHY_SW_RESET]                 = 0x00,
-       [QPHY_START_CTRL]               = 0x08,
-       [QPHY_PCS_READY_STATUS]         = 0x174,
-};
-
-static const unsigned int usb3phy_regs_layout[] = {
-       [QPHY_FLL_CNTRL1]               = 0xc0,
-       [QPHY_FLL_CNTRL2]               = 0xc4,
-       [QPHY_FLL_CNT_VAL_L]            = 0xc8,
-       [QPHY_FLL_CNT_VAL_H_TOL]        = 0xcc,
-       [QPHY_FLL_MAN_CODE]             = 0xd0,
-       [QPHY_SW_RESET]                 = 0x00,
-       [QPHY_START_CTRL]               = 0x08,
-       [QPHY_PCS_READY_STATUS]         = 0x17c,
-};
-
-static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = {
-       QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06),
-       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x42),
-       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
-       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f),
-       QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x01),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a),
-       QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x09),
-       QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
-       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03),
-       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55),
-       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55),
-       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x1a),
-       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x0a),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x04),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
-       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
-       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
-       QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x02),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19),
-       QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x15),
-       QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
-       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
-       QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x40),
-};
-
-static const struct qmp_phy_init_tbl msm8996_pcie_tx_tbl[] = {
-       QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
-       QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06),
-};
-
-static const struct qmp_phy_init_tbl msm8996_pcie_rx_tbl[] = {
-       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c),
-       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x01),
-       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb),
-       QMP_PHY_INIT_CFG(QSERDES_RX_RX_BAND, 0x18),
-       QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04),
-       QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x04),
-       QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
-       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14),
-       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x19),
-};
-
-static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = {
-       QMP_PHY_INIT_CFG(QPHY_RX_IDLE_DTCT_CNTRL, 0x4c),
-       QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x00),
-       QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01),
-
-       QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x05),
-
-       QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x05),
-       QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x02),
-       QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG4, 0x00),
-       QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG1, 0xa3),
-       QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0x0e),
-};
-
-static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = {
-       QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14),
-       QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01),
-       QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
-       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x04),
-       /* PLL and Loop filter settings */
-       QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
-       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55),
-       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55),
-       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
-       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
-       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
-       QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
-       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15),
-       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34),
-       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
-       /* SSC settings */
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde),
-       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07),
-};
-
-static const struct qmp_phy_init_tbl msm8996_usb3_tx_tbl[] = {
-       QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
-       QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12),
-       QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06),
-};
-
-static const struct qmp_phy_init_tbl msm8996_usb3_rx_tbl[] = {
-       QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
-       QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04),
-       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02),
-       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c),
-       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xbb),
-       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
-       QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
-       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03),
-       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x18),
-       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16),
-};
-
-static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = {
-       /* FLL settings */
-       QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL2, 0x03),
-       QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL1, 0x02),
-       QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_L, 0x09),
-       QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_H_TOL, 0x42),
-       QMP_PHY_INIT_CFG_L(QPHY_FLL_MAN_CODE, 0x85),
-
-       /* Lock Det settings */
-       QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG1, 0xd1),
-       QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG2, 0x1f),
-       QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG3, 0x47),
-       QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08),
-};
-
-/* struct qmp_phy_cfg - per-PHY initialization config */
-struct qmp_phy_cfg {
-       /* phy-type - PCIE/UFS/USB */
-       unsigned int type;
-       /* number of lanes provided by phy */
-       int nlanes;
-
-       /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
-       const struct qmp_phy_init_tbl *serdes_tbl;
-       int serdes_tbl_num;
-       const struct qmp_phy_init_tbl *tx_tbl;
-       int tx_tbl_num;
-       const struct qmp_phy_init_tbl *rx_tbl;
-       int rx_tbl_num;
-       const struct qmp_phy_init_tbl *pcs_tbl;
-       int pcs_tbl_num;
-
-       /* clock ids to be requested */
-       const char * const *clk_list;
-       int num_clks;
-       /* resets to be requested */
-       const char * const *reset_list;
-       int num_resets;
-       /* regulators to be requested */
-       const char * const *vreg_list;
-       int num_vregs;
-
-       /* array of registers with different offsets */
-       const unsigned int *regs;
-
-       unsigned int start_ctrl;
-       unsigned int pwrdn_ctrl;
-       unsigned int mask_pcs_ready;
-       unsigned int mask_com_pcs_ready;
-
-       /* true, if PHY has a separate PHY_COM control block */
-       bool has_phy_com_ctrl;
-       /* true, if PHY has a reset for individual lanes */
-       bool has_lane_rst;
-       /* true, if PHY needs delay after POWER_DOWN */
-       bool has_pwrdn_delay;
-       /* power_down delay in usec */
-       int pwrdn_delay_min;
-       int pwrdn_delay_max;
-};
-
-/**
- * struct qmp_phy - per-lane phy descriptor
- *
- * @phy: generic phy
- * @tx: iomapped memory space for lane's tx
- * @rx: iomapped memory space for lane's rx
- * @pcs: iomapped memory space for lane's pcs
- * @pipe_clk: pipe lock
- * @index: lane index
- * @qmp: QMP phy to which this lane belongs
- * @lane_rst: lane's reset controller
- */
-struct qmp_phy {
-       struct phy *phy;
-       void __iomem *tx;
-       void __iomem *rx;
-       void __iomem *pcs;
-       struct clk *pipe_clk;
-       unsigned int index;
-       struct qcom_qmp *qmp;
-       struct reset_control *lane_rst;
-};
-
-/**
- * struct qcom_qmp - structure holding QMP phy block attributes
- *
- * @dev: device
- * @serdes: iomapped memory space for phy's serdes
- *
- * @clks: array of clocks required by phy
- * @resets: array of resets required by phy
- * @vregs: regulator supplies bulk data
- *
- * @cfg: phy specific configuration
- * @phys: array of per-lane phy descriptors
- * @phy_mutex: mutex lock for PHY common block initialization
- * @init_count: phy common block initialization count
- */
-struct qcom_qmp {
-       struct device *dev;
-       void __iomem *serdes;
-
-       struct clk **clks;
-       struct reset_control **resets;
-       struct regulator_bulk_data *vregs;
-
-       const struct qmp_phy_cfg *cfg;
-       struct qmp_phy **phys;
-
-       struct mutex phy_mutex;
-       int init_count;
-};
-
-static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
-{
-       u32 reg;
-
-       reg = readl(base + offset);
-       reg |= val;
-       writel(reg, base + offset);
-
-       /* ensure that above write is through */
-       readl(base + offset);
-}
-
-static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
-{
-       u32 reg;
-
-       reg = readl(base + offset);
-       reg &= ~val;
-       writel(reg, base + offset);
-
-       /* ensure that above write is through */
-       readl(base + offset);
-}
-
-/* list of clocks required by phy */
-static const char * const msm8996_phy_clk_l[] = {
-       "aux", "cfg_ahb", "ref",
-};
-
-/* list of resets */
-static const char * const msm8996_pciephy_reset_l[] = {
-       "phy", "common", "cfg",
-};
-
-static const char * const msm8996_usb3phy_reset_l[] = {
-       "phy", "common",
-};
-
-/* list of regulators */
-static const char * const msm8996_phy_vreg_l[] = {
-       "vdda-phy", "vdda-pll",
-};
-
-static const struct qmp_phy_cfg msm8996_pciephy_cfg = {
-       .type                   = PHY_TYPE_PCIE,
-       .nlanes                 = 3,
-
-       .serdes_tbl             = msm8996_pcie_serdes_tbl,
-       .serdes_tbl_num         = ARRAY_SIZE(msm8996_pcie_serdes_tbl),
-       .tx_tbl                 = msm8996_pcie_tx_tbl,
-       .tx_tbl_num             = ARRAY_SIZE(msm8996_pcie_tx_tbl),
-       .rx_tbl                 = msm8996_pcie_rx_tbl,
-       .rx_tbl_num             = ARRAY_SIZE(msm8996_pcie_rx_tbl),
-       .pcs_tbl                = msm8996_pcie_pcs_tbl,
-       .pcs_tbl_num            = ARRAY_SIZE(msm8996_pcie_pcs_tbl),
-       .clk_list               = msm8996_phy_clk_l,
-       .num_clks               = ARRAY_SIZE(msm8996_phy_clk_l),
-       .reset_list             = msm8996_pciephy_reset_l,
-       .num_resets             = ARRAY_SIZE(msm8996_pciephy_reset_l),
-       .vreg_list              = msm8996_phy_vreg_l,
-       .num_vregs              = ARRAY_SIZE(msm8996_phy_vreg_l),
-       .regs                   = pciephy_regs_layout,
-
-       .start_ctrl             = PCS_START | PLL_READY_GATE_EN,
-       .pwrdn_ctrl             = SW_PWRDN | REFCLK_DRV_DSBL,
-       .mask_com_pcs_ready     = PCS_READY,
-
-       .has_phy_com_ctrl       = true,
-       .has_lane_rst           = true,
-       .has_pwrdn_delay        = true,
-       .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
-       .pwrdn_delay_max        = POWER_DOWN_DELAY_US_MAX,
-};
-
-static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
-       .type                   = PHY_TYPE_USB3,
-       .nlanes                 = 1,
-
-       .serdes_tbl             = msm8996_usb3_serdes_tbl,
-       .serdes_tbl_num         = ARRAY_SIZE(msm8996_usb3_serdes_tbl),
-       .tx_tbl                 = msm8996_usb3_tx_tbl,
-       .tx_tbl_num             = ARRAY_SIZE(msm8996_usb3_tx_tbl),
-       .rx_tbl                 = msm8996_usb3_rx_tbl,
-       .rx_tbl_num             = ARRAY_SIZE(msm8996_usb3_rx_tbl),
-       .pcs_tbl                = msm8996_usb3_pcs_tbl,
-       .pcs_tbl_num            = ARRAY_SIZE(msm8996_usb3_pcs_tbl),
-       .clk_list               = msm8996_phy_clk_l,
-       .num_clks               = ARRAY_SIZE(msm8996_phy_clk_l),
-       .reset_list             = msm8996_usb3phy_reset_l,
-       .num_resets             = ARRAY_SIZE(msm8996_usb3phy_reset_l),
-       .vreg_list              = msm8996_phy_vreg_l,
-       .num_vregs              = ARRAY_SIZE(msm8996_phy_vreg_l),
-       .regs                   = usb3phy_regs_layout,
-
-       .start_ctrl             = SERDES_START | PCS_START,
-       .pwrdn_ctrl             = SW_PWRDN,
-       .mask_pcs_ready         = PHYSTATUS,
-};
-
-static void qcom_qmp_phy_configure(void __iomem *base,
-                                  const unsigned int *regs,
-                                  const struct qmp_phy_init_tbl tbl[],
-                                  int num)
-{
-       int i;
-       const struct qmp_phy_init_tbl *t = tbl;
-
-       if (!t)
-               return;
-
-       for (i = 0; i < num; i++, t++) {
-               if (t->in_layout)
-                       writel(t->val, base + regs[t->offset]);
-               else
-                       writel(t->val, base + t->offset);
-       }
-}
-
-static int qcom_qmp_phy_poweron(struct phy *phy)
-{
-       struct qmp_phy *qphy = phy_get_drvdata(phy);
-       struct qcom_qmp *qmp = qphy->qmp;
-       int num = qmp->cfg->num_vregs;
-       int ret;
-
-       dev_vdbg(&phy->dev, "Powering on QMP phy\n");
-
-       /* turn on regulator supplies */
-       ret = regulator_bulk_enable(num, qmp->vregs);
-       if (ret) {
-               dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
-               return ret;
-       }
-
-       ret = clk_prepare_enable(qphy->pipe_clk);
-       if (ret) {
-               dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret);
-               regulator_bulk_disable(num, qmp->vregs);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int qcom_qmp_phy_poweroff(struct phy *phy)
-{
-       struct qmp_phy *qphy = phy_get_drvdata(phy);
-       struct qcom_qmp *qmp = qphy->qmp;
-
-       clk_disable_unprepare(qphy->pipe_clk);
-
-       regulator_bulk_disable(qmp->cfg->num_vregs, qmp->vregs);
-
-       return 0;
-}
-
-static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
-{
-       const struct qmp_phy_cfg *cfg = qmp->cfg;
-       void __iomem *serdes = qmp->serdes;
-       int ret, i;
-
-       mutex_lock(&qmp->phy_mutex);
-       if (qmp->init_count++) {
-               mutex_unlock(&qmp->phy_mutex);
-               return 0;
-       }
-
-       for (i = 0; i < cfg->num_resets; i++) {
-               ret = reset_control_deassert(qmp->resets[i]);
-               if (ret) {
-                       dev_err(qmp->dev, "%s reset deassert failed\n",
-                               qmp->cfg->reset_list[i]);
-                       while (--i >= 0)
-                               reset_control_assert(qmp->resets[i]);
-                       goto err_rst;
-               }
-       }
-
-       if (cfg->has_phy_com_ctrl)
-               qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
-                            SW_PWRDN);
-
-       /* Serdes configuration */
-       qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl,
-                              cfg->serdes_tbl_num);
-
-       if (cfg->has_phy_com_ctrl) {
-               void __iomem *status;
-               unsigned int mask, val;
-
-               qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET);
-               qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL],
-                            SERDES_START | PCS_START);
-
-               status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS];
-               mask = cfg->mask_com_pcs_ready;
-
-               ret = readl_poll_timeout(status, val, (val & mask), 10,
-                                        PHY_INIT_COMPLETE_TIMEOUT);
-               if (ret) {
-                       dev_err(qmp->dev,
-                               "phy common block init timed-out\n");
-                       goto err_com_init;
-               }
-       }
-
-       mutex_unlock(&qmp->phy_mutex);
-
-       return 0;
-
-err_com_init:
-       while (--i >= 0)
-               reset_control_assert(qmp->resets[i]);
-err_rst:
-       mutex_unlock(&qmp->phy_mutex);
-       return ret;
-}
-
-static int qcom_qmp_phy_com_exit(struct qcom_qmp *qmp)
-{
-       const struct qmp_phy_cfg *cfg = qmp->cfg;
-       void __iomem *serdes = qmp->serdes;
-       int i = cfg->num_resets;
-
-       mutex_lock(&qmp->phy_mutex);
-       if (--qmp->init_count) {
-               mutex_unlock(&qmp->phy_mutex);
-               return 0;
-       }
-
-       if (cfg->has_phy_com_ctrl) {
-               qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL],
-                            SERDES_START | PCS_START);
-               qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET],
-                            SW_RESET);
-               qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
-                            SW_PWRDN);
-       }
-
-       while (--i >= 0)
-               reset_control_assert(qmp->resets[i]);
-
-       mutex_unlock(&qmp->phy_mutex);
-
-       return 0;
-}
-
-/* PHY Initialization */
-static int qcom_qmp_phy_init(struct phy *phy)
-{
-       struct qmp_phy *qphy = phy_get_drvdata(phy);
-       struct qcom_qmp *qmp = qphy->qmp;
-       const struct qmp_phy_cfg *cfg = qmp->cfg;
-       void __iomem *tx = qphy->tx;
-       void __iomem *rx = qphy->rx;
-       void __iomem *pcs = qphy->pcs;
-       void __iomem *status;
-       unsigned int mask, val;
-       int ret, i;
-
-       dev_vdbg(qmp->dev, "Initializing QMP phy\n");
-
-       for (i = 0; i < qmp->cfg->num_clks; i++) {
-               ret = clk_prepare_enable(qmp->clks[i]);
-               if (ret) {
-                       dev_err(qmp->dev, "failed to enable %s clk, err=%d\n",
-                               qmp->cfg->clk_list[i], ret);
-                       while (--i >= 0)
-                               clk_disable_unprepare(qmp->clks[i]);
-               }
-       }
-
-       ret = qcom_qmp_phy_com_init(qmp);
-       if (ret)
-               goto err_com_init;
-
-       if (cfg->has_lane_rst) {
-               ret = reset_control_deassert(qphy->lane_rst);
-               if (ret) {
-                       dev_err(qmp->dev, "lane%d reset deassert failed\n",
-                               qphy->index);
-                       goto err_lane_rst;
-               }
-       }
-
-       /* Tx, Rx, and PCS configurations */
-       qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num);
-       qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num);
-       qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
-
-       /*
-        * Pull out PHY from POWER DOWN state.
-        * This is active low enable signal to power-down PHY.
-        */
-       qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
-
-       if (cfg->has_pwrdn_delay)
-               usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max);
-
-       /* start SerDes and Phy-Coding-Sublayer */
-       qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
-
-       /* Pull PHY out of reset state */
-       qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
-
-       status = pcs + cfg->regs[QPHY_PCS_READY_STATUS];
-       mask = cfg->mask_pcs_ready;
-
-       ret = readl_poll_timeout(status, val, !(val & mask), 1,
-                                PHY_INIT_COMPLETE_TIMEOUT);
-       if (ret) {
-               dev_err(qmp->dev, "phy initialization timed-out\n");
-               goto err_pcs_ready;
-       }
-
-       return ret;
-
-err_pcs_ready:
-       if (cfg->has_lane_rst)
-               reset_control_assert(qphy->lane_rst);
-err_lane_rst:
-       qcom_qmp_phy_com_exit(qmp);
-err_com_init:
-       while (--i >= 0)
-               clk_disable_unprepare(qmp->clks[i]);
-
-       return ret;
-}
-
-static int qcom_qmp_phy_exit(struct phy *phy)
-{
-       struct qmp_phy *qphy = phy_get_drvdata(phy);
-       struct qcom_qmp *qmp = qphy->qmp;
-       const struct qmp_phy_cfg *cfg = qmp->cfg;
-       int i = cfg->num_clks;
-
-       /* PHY reset */
-       qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
-
-       /* stop SerDes and Phy-Coding-Sublayer */
-       qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
-
-       /* Put PHY into POWER DOWN state: active low */
-       qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
-
-       if (cfg->has_lane_rst)
-               reset_control_assert(qphy->lane_rst);
-
-       qcom_qmp_phy_com_exit(qmp);
-
-       while (--i >= 0)
-               clk_disable_unprepare(qmp->clks[i]);
-
-       return 0;
-}
-
-static int qcom_qmp_phy_vreg_init(struct device *dev)
-{
-       struct qcom_qmp *qmp = dev_get_drvdata(dev);
-       int num = qmp->cfg->num_vregs;
-       int i;
-
-       qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
-       if (!qmp->vregs)
-               return -ENOMEM;
-
-       for (i = 0; i < num; i++)
-               qmp->vregs[i].supply = qmp->cfg->vreg_list[i];
-
-       return devm_regulator_bulk_get(dev, num, qmp->vregs);
-}
-
-static int qcom_qmp_phy_reset_init(struct device *dev)
-{
-       struct qcom_qmp *qmp = dev_get_drvdata(dev);
-       int i;
-
-       qmp->resets = devm_kcalloc(dev, qmp->cfg->num_resets,
-                                  sizeof(*qmp->resets), GFP_KERNEL);
-       if (!qmp->resets)
-               return -ENOMEM;
-
-       for (i = 0; i < qmp->cfg->num_resets; i++) {
-               struct reset_control *rst;
-               const char *name = qmp->cfg->reset_list[i];
-
-               rst = devm_reset_control_get(dev, name);
-               if (IS_ERR(rst)) {
-                       dev_err(dev, "failed to get %s reset\n", name);
-                       return PTR_ERR(rst);
-               }
-               qmp->resets[i] = rst;
-       }
-
-       return 0;
-}
-
-static int qcom_qmp_phy_clk_init(struct device *dev)
-{
-       struct qcom_qmp *qmp = dev_get_drvdata(dev);
-       int ret, i;
-
-       qmp->clks = devm_kcalloc(dev, qmp->cfg->num_clks,
-                                sizeof(*qmp->clks), GFP_KERNEL);
-       if (!qmp->clks)
-               return -ENOMEM;
-
-       for (i = 0; i < qmp->cfg->num_clks; i++) {
-               struct clk *_clk;
-               const char *name = qmp->cfg->clk_list[i];
-
-               _clk = devm_clk_get(dev, name);
-               if (IS_ERR(_clk)) {
-                       ret = PTR_ERR(_clk);
-                       if (ret != -EPROBE_DEFER)
-                               dev_err(dev, "failed to get %s clk, %d\n",
-                                       name, ret);
-                       return ret;
-               }
-               qmp->clks[i] = _clk;
-       }
-
-       return 0;
-}
-
-/*
- * Register a fixed rate pipe clock.
- *
- * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
- * controls it. The <s>_pipe_clk coming out of the GCC is requested
- * by the PHY driver for its operations.
- * We register the <s>_pipe_clksrc here. The gcc driver takes care
- * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk.
- * Below picture shows this relationship.
- *
- *         +---------------+
- *         |   PHY block   |<<---------------------------------------+
- *         |               |                                         |
- *         |   +-------+   |                   +-----+               |
- *   I/P---^-->|  PLL  |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
- *    clk  |   +-------+   |                   +-----+
- *         +---------------+
- */
-static int phy_pipe_clk_register(struct qcom_qmp *qmp, int id)
-{
-       char name[24];
-       struct clk_fixed_rate *fixed;
-       struct clk_init_data init = { };
-
-       switch (qmp->cfg->type) {
-       case PHY_TYPE_USB3:
-               snprintf(name, sizeof(name), "usb3_phy_pipe_clk_src");
-               break;
-       case PHY_TYPE_PCIE:
-               snprintf(name, sizeof(name), "pcie_%d_pipe_clk_src", id);
-               break;
-       default:
-               /* not all phys register pipe clocks, so return success */
-               return 0;
-       }
-
-       fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL);
-       if (!fixed)
-               return -ENOMEM;
-
-       init.name = name;
-       init.ops = &clk_fixed_rate_ops;
-
-       /* controllers using QMP phys use 125MHz pipe clock interface */
-       fixed->fixed_rate = 125000000;
-       fixed->hw.init = &init;
-
-       return devm_clk_hw_register(qmp->dev, &fixed->hw);
-}
-
-static const struct phy_ops qcom_qmp_phy_gen_ops = {
-       .init           = qcom_qmp_phy_init,
-       .exit           = qcom_qmp_phy_exit,
-       .power_on       = qcom_qmp_phy_poweron,
-       .power_off      = qcom_qmp_phy_poweroff,
-       .owner          = THIS_MODULE,
-};
-
-static
-int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
-{
-       struct qcom_qmp *qmp = dev_get_drvdata(dev);
-       struct phy *generic_phy;
-       struct qmp_phy *qphy;
-       char prop_name[MAX_PROP_NAME];
-       int ret;
-
-       qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
-       if (!qphy)
-               return -ENOMEM;
-
-       /*
-        * Get memory resources for each phy lane:
-        * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
-        */
-       qphy->tx = of_iomap(np, 0);
-       if (!qphy->tx)
-               return -ENOMEM;
-
-       qphy->rx = of_iomap(np, 1);
-       if (!qphy->rx)
-               return -ENOMEM;
-
-       qphy->pcs = of_iomap(np, 2);
-       if (!qphy->pcs)
-               return -ENOMEM;
-
-       /*
-        * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3
-        * based phys, so they essentially have pipe clock. So,
-        * we return error in case phy is USB3 or PIPE type.
-        * Otherwise, we initialize pipe clock to NULL for
-        * all phys that don't need this.
-        */
-       snprintf(prop_name, sizeof(prop_name), "pipe%d", id);
-       qphy->pipe_clk = of_clk_get_by_name(np, prop_name);
-       if (IS_ERR(qphy->pipe_clk)) {
-               if (qmp->cfg->type == PHY_TYPE_PCIE ||
-                   qmp->cfg->type == PHY_TYPE_USB3) {
-                       ret = PTR_ERR(qphy->pipe_clk);
-                       if (ret != -EPROBE_DEFER)
-                               dev_err(dev,
-                                       "failed to get lane%d pipe_clk, %d\n",
-                                       id, ret);
-                       return ret;
-               }
-               qphy->pipe_clk = NULL;
-       }
-
-       /* Get lane reset, if any */
-       if (qmp->cfg->has_lane_rst) {
-               snprintf(prop_name, sizeof(prop_name), "lane%d", id);
-               qphy->lane_rst = of_reset_control_get(np, prop_name);
-               if (IS_ERR(qphy->lane_rst)) {
-                       dev_err(dev, "failed to get lane%d reset\n", id);
-                       return PTR_ERR(qphy->lane_rst);
-               }
-       }
-
-       generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_gen_ops);
-       if (IS_ERR(generic_phy)) {
-               ret = PTR_ERR(generic_phy);
-               dev_err(dev, "failed to create qphy %d\n", ret);
-               return ret;
-       }
-
-       qphy->phy = generic_phy;
-       qphy->index = id;
-       qphy->qmp = qmp;
-       qmp->phys[id] = qphy;
-       phy_set_drvdata(generic_phy, qphy);
-
-       return 0;
-}
-
-static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
-       {
-               .compatible = "qcom,msm8996-qmp-pcie-phy",
-               .data = &msm8996_pciephy_cfg,
-       }, {
-               .compatible = "qcom,msm8996-qmp-usb3-phy",
-               .data = &msm8996_usb3phy_cfg,
-       },
-       { },
-};
-MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table);
-
-static int qcom_qmp_phy_probe(struct platform_device *pdev)
-{
-       struct qcom_qmp *qmp;
-       struct device *dev = &pdev->dev;
-       struct resource *res;
-       struct device_node *child;
-       struct phy_provider *phy_provider;
-       void __iomem *base;
-       int num, id;
-       int ret;
-
-       qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL);
-       if (!qmp)
-               return -ENOMEM;
-
-       qmp->dev = dev;
-       dev_set_drvdata(dev, qmp);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       /* per PHY serdes; usually located at base address */
-       qmp->serdes = base;
-
-       mutex_init(&qmp->phy_mutex);
-
-       /* Get the specific init parameters of QMP phy */
-       qmp->cfg = of_device_get_match_data(dev);
-
-       ret = qcom_qmp_phy_clk_init(dev);
-       if (ret)
-               return ret;
-
-       ret = qcom_qmp_phy_reset_init(dev);
-       if (ret)
-               return ret;
-
-       ret = qcom_qmp_phy_vreg_init(dev);
-       if (ret) {
-               dev_err(dev, "failed to get regulator supplies\n");
-               return ret;
-       }
-
-       num = of_get_available_child_count(dev->of_node);
-       /* do we have a rogue child node ? */
-       if (num > qmp->cfg->nlanes)
-               return -EINVAL;
-
-       qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL);
-       if (!qmp->phys)
-               return -ENOMEM;
-
-       id = 0;
-       for_each_available_child_of_node(dev->of_node, child) {
-               /* Create per-lane phy */
-               ret = qcom_qmp_phy_create(dev, child, id);
-               if (ret) {
-                       dev_err(dev, "failed to create lane%d phy, %d\n",
-                               id, ret);
-                       return ret;
-               }
-
-               /*
-                * Register the pipe clock provided by phy.
-                * See function description to see details of this pipe clock.
-                */
-               ret = phy_pipe_clk_register(qmp, id);
-               if (ret) {
-                       dev_err(qmp->dev,
-                               "failed to register pipe clock source\n");
-                       return ret;
-               }
-               id++;
-       }
-
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (!IS_ERR(phy_provider))
-               dev_info(dev, "Registered Qcom-QMP phy\n");
-
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static struct platform_driver qcom_qmp_phy_driver = {
-       .probe          = qcom_qmp_phy_probe,
-       .driver = {
-               .name   = "qcom-qmp-phy",
-               .of_match_table = qcom_qmp_phy_of_match_table,
-       },
-};
-
-module_platform_driver(qcom_qmp_phy_driver);
-
-MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>");
-MODULE_DESCRIPTION("Qualcomm QMP PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-qcom-qusb2.c b/drivers/phy/phy-qcom-qusb2.c
deleted file mode 100644 (file)
index 6c57524..0000000
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/nvmem-consumer.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-#include <linux/reset.h>
-#include <linux/slab.h>
-
-#define QUSB2PHY_PLL_TEST              0x04
-#define CLK_REF_SEL                    BIT(7)
-
-#define QUSB2PHY_PLL_TUNE              0x08
-#define QUSB2PHY_PLL_USER_CTL1         0x0c
-#define QUSB2PHY_PLL_USER_CTL2         0x10
-#define QUSB2PHY_PLL_AUTOPGM_CTL1      0x1c
-#define QUSB2PHY_PLL_PWR_CTRL          0x18
-
-#define QUSB2PHY_PLL_STATUS            0x38
-#define PLL_LOCKED                     BIT(5)
-
-#define QUSB2PHY_PORT_TUNE1            0x80
-#define QUSB2PHY_PORT_TUNE2            0x84
-#define QUSB2PHY_PORT_TUNE3            0x88
-#define QUSB2PHY_PORT_TUNE4            0x8c
-#define QUSB2PHY_PORT_TUNE5            0x90
-#define QUSB2PHY_PORT_TEST2            0x9c
-
-#define QUSB2PHY_PORT_POWERDOWN                0xb4
-#define CLAMP_N_EN                     BIT(5)
-#define FREEZIO_N                      BIT(1)
-#define POWER_DOWN                     BIT(0)
-
-#define QUSB2PHY_REFCLK_ENABLE         BIT(0)
-
-#define PHY_CLK_SCHEME_SEL             BIT(0)
-
-struct qusb2_phy_init_tbl {
-       unsigned int offset;
-       unsigned int val;
-};
-
-#define QUSB2_PHY_INIT_CFG(o, v) \
-       {                       \
-               .offset = o,    \
-               .val = v,       \
-       }
-
-static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = {
-       QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE1, 0xf8),
-       QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE2, 0xb3),
-       QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE3, 0x83),
-       QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE4, 0xc0),
-       QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30),
-       QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79),
-       QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21),
-       QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TEST2, 0x14),
-       QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f),
-       QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
-};
-
-struct qusb2_phy_cfg {
-       const struct qusb2_phy_init_tbl *tbl;
-       /* number of entries in the table */
-       unsigned int tbl_num;
-       /* offset to PHY_CLK_SCHEME register in TCSR map */
-       unsigned int clk_scheme_offset;
-};
-
-static const struct qusb2_phy_cfg msm8996_phy_cfg = {
-       .tbl = msm8996_init_tbl,
-       .tbl_num = ARRAY_SIZE(msm8996_init_tbl),
-};
-
-static const char * const qusb2_phy_vreg_names[] = {
-       "vdda-pll", "vdda-phy-dpdm",
-};
-
-#define QUSB2_NUM_VREGS                ARRAY_SIZE(qusb2_phy_vreg_names)
-
-/**
- * struct qusb2_phy - structure holding qusb2 phy attributes
- *
- * @phy: generic phy
- * @base: iomapped memory space for qubs2 phy
- *
- * @cfg_ahb_clk: AHB2PHY interface clock
- * @ref_clk: phy reference clock
- * @iface_clk: phy interface clock
- * @phy_reset: phy reset control
- * @vregs: regulator supplies bulk data
- *
- * @tcsr: TCSR syscon register map
- * @cell: nvmem cell containing phy tuning value
- *
- * @cfg: phy config data
- * @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme
- */
-struct qusb2_phy {
-       struct phy *phy;
-       void __iomem *base;
-
-       struct clk *cfg_ahb_clk;
-       struct clk *ref_clk;
-       struct clk *iface_clk;
-       struct reset_control *phy_reset;
-       struct regulator_bulk_data vregs[QUSB2_NUM_VREGS];
-
-       struct regmap *tcsr;
-       struct nvmem_cell *cell;
-
-       const struct qusb2_phy_cfg *cfg;
-       bool has_se_clk_scheme;
-};
-
-static inline void qusb2_setbits(void __iomem *base, u32 offset, u32 val)
-{
-       u32 reg;
-
-       reg = readl(base + offset);
-       reg |= val;
-       writel(reg, base + offset);
-
-       /* Ensure above write is completed */
-       readl(base + offset);
-}
-
-static inline void qusb2_clrbits(void __iomem *base, u32 offset, u32 val)
-{
-       u32 reg;
-
-       reg = readl(base + offset);
-       reg &= ~val;
-       writel(reg, base + offset);
-
-       /* Ensure above write is completed */
-       readl(base + offset);
-}
-
-static inline
-void qcom_qusb2_phy_configure(void __iomem *base,
-                             const struct qusb2_phy_init_tbl tbl[], int num)
-{
-       int i;
-
-       for (i = 0; i < num; i++)
-               writel(tbl[i].val, base + tbl[i].offset);
-}
-
-/*
- * Fetches HS Tx tuning value from nvmem and sets the
- * QUSB2PHY_PORT_TUNE2 register.
- * For error case, skip setting the value and use the default value.
- */
-static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
-{
-       struct device *dev = &qphy->phy->dev;
-       u8 *val;
-
-       /*
-        * Read efuse register having TUNE2 parameter's high nibble.
-        * If efuse register shows value as 0x0, or if we fail to find
-        * a valid efuse register settings, then use default value
-        * as 0xB for high nibble that we have already set while
-        * configuring phy.
-        */
-       val = nvmem_cell_read(qphy->cell, NULL);
-       if (IS_ERR(val) || !val[0]) {
-               dev_dbg(dev, "failed to read a valid hs-tx trim value\n");
-               return;
-       }
-
-       /* Fused TUNE2 value is the higher nibble only */
-       qusb2_setbits(qphy->base, QUSB2PHY_PORT_TUNE2, val[0] << 0x4);
-}
-
-static int qusb2_phy_poweron(struct phy *phy)
-{
-       struct qusb2_phy *qphy = phy_get_drvdata(phy);
-       int num = ARRAY_SIZE(qphy->vregs);
-       int ret;
-
-       dev_vdbg(&phy->dev, "%s(): Powering-on QUSB2 phy\n", __func__);
-
-       /* turn on regulator supplies */
-       ret = regulator_bulk_enable(num, qphy->vregs);
-       if (ret)
-               return ret;
-
-       ret = clk_prepare_enable(qphy->iface_clk);
-       if (ret) {
-               dev_err(&phy->dev, "failed to enable iface_clk, %d\n", ret);
-               regulator_bulk_disable(num, qphy->vregs);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int qusb2_phy_poweroff(struct phy *phy)
-{
-       struct qusb2_phy *qphy = phy_get_drvdata(phy);
-
-       clk_disable_unprepare(qphy->iface_clk);
-
-       regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
-
-       return 0;
-}
-
-static int qusb2_phy_init(struct phy *phy)
-{
-       struct qusb2_phy *qphy = phy_get_drvdata(phy);
-       unsigned int val;
-       unsigned int clk_scheme;
-       int ret;
-
-       dev_vdbg(&phy->dev, "%s(): Initializing QUSB2 phy\n", __func__);
-
-       /* enable ahb interface clock to program phy */
-       ret = clk_prepare_enable(qphy->cfg_ahb_clk);
-       if (ret) {
-               dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret);
-               return ret;
-       }
-
-       /* Perform phy reset */
-       ret = reset_control_assert(qphy->phy_reset);
-       if (ret) {
-               dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
-               goto disable_ahb_clk;
-       }
-
-       /* 100 us delay to keep PHY in reset mode */
-       usleep_range(100, 150);
-
-       ret = reset_control_deassert(qphy->phy_reset);
-       if (ret) {
-               dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
-               goto disable_ahb_clk;
-       }
-
-       /* Disable the PHY */
-       qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN,
-                     CLAMP_N_EN | FREEZIO_N | POWER_DOWN);
-
-       /* save reset value to override reference clock scheme later */
-       val = readl(qphy->base + QUSB2PHY_PLL_TEST);
-
-       qcom_qusb2_phy_configure(qphy->base, qphy->cfg->tbl,
-                                qphy->cfg->tbl_num);
-
-       /* Set efuse value for tuning the PHY */
-       qusb2_phy_set_tune2_param(qphy);
-
-       /* Enable the PHY */
-       qusb2_clrbits(qphy->base, QUSB2PHY_PORT_POWERDOWN, POWER_DOWN);
-
-       /* Required to get phy pll lock successfully */
-       usleep_range(150, 160);
-
-       /* Default is single-ended clock on msm8996 */
-       qphy->has_se_clk_scheme = true;
-       /*
-        * read TCSR_PHY_CLK_SCHEME register to check if single-ended
-        * clock scheme is selected. If yes, then disable differential
-        * ref_clk and use single-ended clock, otherwise use differential
-        * ref_clk only.
-        */
-       if (qphy->tcsr) {
-               ret = regmap_read(qphy->tcsr, qphy->cfg->clk_scheme_offset,
-                                 &clk_scheme);
-               if (ret) {
-                       dev_err(&phy->dev, "failed to read clk scheme reg\n");
-                       goto assert_phy_reset;
-               }
-
-               /* is it a differential clock scheme ? */
-               if (!(clk_scheme & PHY_CLK_SCHEME_SEL)) {
-                       dev_vdbg(&phy->dev, "%s(): select differential clk\n",
-                                __func__);
-                       qphy->has_se_clk_scheme = false;
-               } else {
-                       dev_vdbg(&phy->dev, "%s(): select single-ended clk\n",
-                                __func__);
-               }
-       }
-
-       if (!qphy->has_se_clk_scheme) {
-               val &= ~CLK_REF_SEL;
-               ret = clk_prepare_enable(qphy->ref_clk);
-               if (ret) {
-                       dev_err(&phy->dev, "failed to enable ref clk, %d\n",
-                               ret);
-                       goto assert_phy_reset;
-               }
-       } else {
-               val |= CLK_REF_SEL;
-       }
-
-       writel(val, qphy->base + QUSB2PHY_PLL_TEST);
-
-       /* ensure above write is through */
-       readl(qphy->base + QUSB2PHY_PLL_TEST);
-
-       /* Required to get phy pll lock successfully */
-       usleep_range(100, 110);
-
-       val = readb(qphy->base + QUSB2PHY_PLL_STATUS);
-       if (!(val & PLL_LOCKED)) {
-               dev_err(&phy->dev,
-                       "QUSB2PHY pll lock failed: status reg = %x\n", val);
-               ret = -EBUSY;
-               goto disable_ref_clk;
-       }
-
-       return 0;
-
-disable_ref_clk:
-       if (!qphy->has_se_clk_scheme)
-               clk_disable_unprepare(qphy->ref_clk);
-assert_phy_reset:
-       reset_control_assert(qphy->phy_reset);
-disable_ahb_clk:
-       clk_disable_unprepare(qphy->cfg_ahb_clk);
-       return ret;
-}
-
-static int qusb2_phy_exit(struct phy *phy)
-{
-       struct qusb2_phy *qphy = phy_get_drvdata(phy);
-
-       /* Disable the PHY */
-       qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN,
-                     CLAMP_N_EN | FREEZIO_N | POWER_DOWN);
-
-       if (!qphy->has_se_clk_scheme)
-               clk_disable_unprepare(qphy->ref_clk);
-
-       reset_control_assert(qphy->phy_reset);
-
-       clk_disable_unprepare(qphy->cfg_ahb_clk);
-
-       return 0;
-}
-
-static const struct phy_ops qusb2_phy_gen_ops = {
-       .init           = qusb2_phy_init,
-       .exit           = qusb2_phy_exit,
-       .power_on       = qusb2_phy_poweron,
-       .power_off      = qusb2_phy_poweroff,
-       .owner          = THIS_MODULE,
-};
-
-static const struct of_device_id qusb2_phy_of_match_table[] = {
-       {
-               .compatible     = "qcom,msm8996-qusb2-phy",
-               .data           = &msm8996_phy_cfg,
-       },
-       { },
-};
-MODULE_DEVICE_TABLE(of, qusb2_phy_of_match_table);
-
-static int qusb2_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct qusb2_phy *qphy;
-       struct phy_provider *phy_provider;
-       struct phy *generic_phy;
-       struct resource *res;
-       int ret, i;
-       int num;
-
-       qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
-       if (!qphy)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       qphy->base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(qphy->base))
-               return PTR_ERR(qphy->base);
-
-       qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb");
-       if (IS_ERR(qphy->cfg_ahb_clk)) {
-               ret = PTR_ERR(qphy->cfg_ahb_clk);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "failed to get cfg ahb clk, %d\n", ret);
-               return ret;
-       }
-
-       qphy->ref_clk = devm_clk_get(dev, "ref");
-       if (IS_ERR(qphy->ref_clk)) {
-               ret = PTR_ERR(qphy->ref_clk);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev, "failed to get ref clk, %d\n", ret);
-               return ret;
-       }
-
-       qphy->iface_clk = devm_clk_get(dev, "iface");
-       if (IS_ERR(qphy->iface_clk)) {
-               ret = PTR_ERR(qphy->iface_clk);
-               if (ret == -EPROBE_DEFER)
-                       return ret;
-               qphy->iface_clk = NULL;
-               dev_dbg(dev, "failed to get iface clk, %d\n", ret);
-       }
-
-       qphy->phy_reset = devm_reset_control_get_by_index(&pdev->dev, 0);
-       if (IS_ERR(qphy->phy_reset)) {
-               dev_err(dev, "failed to get phy core reset\n");
-               return PTR_ERR(qphy->phy_reset);
-       }
-
-       num = ARRAY_SIZE(qphy->vregs);
-       for (i = 0; i < num; i++)
-               qphy->vregs[i].supply = qusb2_phy_vreg_names[i];
-
-       ret = devm_regulator_bulk_get(dev, num, qphy->vregs);
-       if (ret) {
-               dev_err(dev, "failed to get regulator supplies\n");
-               return ret;
-       }
-
-       /* Get the specific init parameters of QMP phy */
-       qphy->cfg = of_device_get_match_data(dev);
-
-       qphy->tcsr = syscon_regmap_lookup_by_phandle(dev->of_node,
-                                                       "qcom,tcsr-syscon");
-       if (IS_ERR(qphy->tcsr)) {
-               dev_dbg(dev, "failed to lookup TCSR regmap\n");
-               qphy->tcsr = NULL;
-       }
-
-       qphy->cell = devm_nvmem_cell_get(dev, NULL);
-       if (IS_ERR(qphy->cell)) {
-               if (PTR_ERR(qphy->cell) == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-               qphy->cell = NULL;
-               dev_dbg(dev, "failed to lookup tune2 hstx trim value\n");
-       }
-
-       generic_phy = devm_phy_create(dev, NULL, &qusb2_phy_gen_ops);
-       if (IS_ERR(generic_phy)) {
-               ret = PTR_ERR(generic_phy);
-               dev_err(dev, "failed to create phy, %d\n", ret);
-               return ret;
-       }
-       qphy->phy = generic_phy;
-
-       dev_set_drvdata(dev, qphy);
-       phy_set_drvdata(generic_phy, qphy);
-
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (!IS_ERR(phy_provider))
-               dev_info(dev, "Registered Qcom-QUSB2 phy\n");
-
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static struct platform_driver qusb2_phy_driver = {
-       .probe          = qusb2_phy_probe,
-       .driver = {
-               .name   = "qcom-qusb2-phy",
-               .of_match_table = qusb2_phy_of_match_table,
-       },
-};
-
-module_platform_driver(qusb2_phy_driver);
-
-MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>");
-MODULE_DESCRIPTION("Qualcomm QUSB2 PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h
deleted file mode 100644 (file)
index 13b02b7..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef UFS_QCOM_PHY_I_H_
-#define UFS_QCOM_PHY_I_H_
-
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/phy/phy-qcom-ufs.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
-({ \
-       ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
-       might_sleep_if(timeout_us); \
-       for (;;) { \
-               (val) = readl(addr); \
-               if (cond) \
-                       break; \
-               if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \
-                       (val) = readl(addr); \
-                       break; \
-               } \
-               if (sleep_us) \
-                       usleep_range(DIV_ROUND_UP(sleep_us, 4), sleep_us); \
-       } \
-       (cond) ? 0 : -ETIMEDOUT; \
-})
-
-#define UFS_QCOM_PHY_CAL_ENTRY(reg, val)       \
-       {                               \
-               .reg_offset = reg,      \
-               .cfg_value = val,       \
-       }
-
-#define UFS_QCOM_PHY_NAME_LEN  30
-
-enum {
-       MASK_SERDES_START       = 0x1,
-       MASK_PCS_READY          = 0x1,
-};
-
-enum {
-       OFFSET_SERDES_START     = 0x0,
-};
-
-struct ufs_qcom_phy_stored_attributes {
-       u32 att;
-       u32 value;
-};
-
-
-struct ufs_qcom_phy_calibration {
-       u32 reg_offset;
-       u32 cfg_value;
-};
-
-struct ufs_qcom_phy_vreg {
-       const char *name;
-       struct regulator *reg;
-       int max_uA;
-       int min_uV;
-       int max_uV;
-       bool enabled;
-};
-
-struct ufs_qcom_phy {
-       struct list_head list;
-       struct device *dev;
-       void __iomem *mmio;
-       void __iomem *dev_ref_clk_ctrl_mmio;
-       struct clk *tx_iface_clk;
-       struct clk *rx_iface_clk;
-       bool is_iface_clk_enabled;
-       struct clk *ref_clk_src;
-       struct clk *ref_clk_parent;
-       struct clk *ref_clk;
-       bool is_ref_clk_enabled;
-       bool is_dev_ref_clk_enabled;
-       struct ufs_qcom_phy_vreg vdda_pll;
-       struct ufs_qcom_phy_vreg vdda_phy;
-       struct ufs_qcom_phy_vreg vddp_ref_clk;
-       unsigned int quirks;
-
-       /*
-       * If UFS link is put into Hibern8 and if UFS PHY analog hardware is
-       * power collapsed (by clearing UFS_PHY_POWER_DOWN_CONTROL), Hibern8
-       * exit might fail even after powering on UFS PHY analog hardware.
-       * Enabling this quirk will help to solve above issue by doing
-       * custom PHY settings just before PHY analog power collapse.
-       */
-       #define UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE  BIT(0)
-
-       u8 host_ctrl_rev_major;
-       u16 host_ctrl_rev_minor;
-       u16 host_ctrl_rev_step;
-
-       char name[UFS_QCOM_PHY_NAME_LEN];
-       struct ufs_qcom_phy_calibration *cached_regs;
-       int cached_regs_table_size;
-       bool is_powered_on;
-       struct ufs_qcom_phy_specific_ops *phy_spec_ops;
-};
-
-/**
- * struct ufs_qcom_phy_specific_ops - set of pointers to functions which have a
- * specific implementation per phy. Each UFS phy, should implement
- * those functions according to its spec and requirements
- * @calibrate_phy: pointer to a function that calibrate the phy
- * @start_serdes: pointer to a function that starts the serdes
- * @is_physical_coding_sublayer_ready: pointer to a function that
- * checks pcs readiness. returns 0 for success and non-zero for error.
- * @set_tx_lane_enable: pointer to a function that enable tx lanes
- * @power_control: pointer to a function that controls analog rail of phy
- * and writes to QSERDES_RX_SIGDET_CNTRL attribute
- */
-struct ufs_qcom_phy_specific_ops {
-       int (*calibrate_phy)(struct ufs_qcom_phy *phy, bool is_rate_B);
-       void (*start_serdes)(struct ufs_qcom_phy *phy);
-       int (*is_physical_coding_sublayer_ready)(struct ufs_qcom_phy *phy);
-       void (*set_tx_lane_enable)(struct ufs_qcom_phy *phy, u32 val);
-       void (*power_control)(struct ufs_qcom_phy *phy, bool val);
-};
-
-struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy);
-int ufs_qcom_phy_power_on(struct phy *generic_phy);
-int ufs_qcom_phy_power_off(struct phy *generic_phy);
-int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common);
-int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common);
-int ufs_qcom_phy_remove(struct phy *generic_phy,
-                      struct ufs_qcom_phy *ufs_qcom_phy);
-struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
-                       struct ufs_qcom_phy *common_cfg,
-                       const struct phy_ops *ufs_qcom_phy_gen_ops,
-                       struct ufs_qcom_phy_specific_ops *phy_spec_ops);
-int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
-                       struct ufs_qcom_phy_calibration *tbl_A, int tbl_size_A,
-                       struct ufs_qcom_phy_calibration *tbl_B, int tbl_size_B,
-                       bool is_rate_B);
-#endif
diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c
deleted file mode 100644 (file)
index 12a1b49..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include "phy-qcom-ufs-qmp-14nm.h"
-
-#define UFS_PHY_NAME "ufs_phy_qmp_14nm"
-#define UFS_PHY_VDDA_PHY_UV    (925000)
-
-static
-int ufs_qcom_phy_qmp_14nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
-                                       bool is_rate_B)
-{
-       int tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A);
-       int tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
-       int err;
-
-       err = ufs_qcom_phy_calibrate(ufs_qcom_phy, phy_cal_table_rate_A,
-               tbl_size_A, phy_cal_table_rate_B, tbl_size_B, is_rate_B);
-
-       if (err)
-               dev_err(ufs_qcom_phy->dev,
-                       "%s: ufs_qcom_phy_calibrate() failed %d\n",
-                       __func__, err);
-       return err;
-}
-
-static
-void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy *phy_common)
-{
-       phy_common->quirks =
-               UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE;
-}
-
-static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy)
-{
-       return 0;
-}
-
-static int ufs_qcom_phy_qmp_14nm_exit(struct phy *generic_phy)
-{
-       return 0;
-}
-
-static
-void ufs_qcom_phy_qmp_14nm_power_control(struct ufs_qcom_phy *phy, bool val)
-{
-       writel_relaxed(val ? 0x1 : 0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL);
-       /*
-        * Before any transactions involving PHY, ensure PHY knows
-        * that it's analog rail is powered ON (or OFF).
-        */
-       mb();
-}
-
-static inline
-void ufs_qcom_phy_qmp_14nm_set_tx_lane_enable(struct ufs_qcom_phy *phy, u32 val)
-{
-       /*
-        * 14nm PHY does not have TX_LANE_ENABLE register.
-        * Implement this function so as not to propagate error to caller.
-        */
-}
-
-static inline void ufs_qcom_phy_qmp_14nm_start_serdes(struct ufs_qcom_phy *phy)
-{
-       u32 tmp;
-
-       tmp = readl_relaxed(phy->mmio + UFS_PHY_PHY_START);
-       tmp &= ~MASK_SERDES_START;
-       tmp |= (1 << OFFSET_SERDES_START);
-       writel_relaxed(tmp, phy->mmio + UFS_PHY_PHY_START);
-       /* Ensure register value is committed */
-       mb();
-}
-
-static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy *phy_common)
-{
-       int err = 0;
-       u32 val;
-
-       err = readl_poll_timeout(phy_common->mmio + UFS_PHY_PCS_READY_STATUS,
-               val, (val & MASK_PCS_READY), 10, 1000000);
-       if (err)
-               dev_err(phy_common->dev, "%s: poll for pcs failed err = %d\n",
-                       __func__, err);
-       return err;
-}
-
-static const struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = {
-       .init           = ufs_qcom_phy_qmp_14nm_init,
-       .exit           = ufs_qcom_phy_qmp_14nm_exit,
-       .power_on       = ufs_qcom_phy_power_on,
-       .power_off      = ufs_qcom_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static struct ufs_qcom_phy_specific_ops phy_14nm_ops = {
-       .calibrate_phy          = ufs_qcom_phy_qmp_14nm_phy_calibrate,
-       .start_serdes           = ufs_qcom_phy_qmp_14nm_start_serdes,
-       .is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_14nm_is_pcs_ready,
-       .set_tx_lane_enable     = ufs_qcom_phy_qmp_14nm_set_tx_lane_enable,
-       .power_control          = ufs_qcom_phy_qmp_14nm_power_control,
-};
-
-static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct phy *generic_phy;
-       struct ufs_qcom_phy_qmp_14nm *phy;
-       struct ufs_qcom_phy *phy_common;
-       int err = 0;
-
-       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
-       if (!phy) {
-               err = -ENOMEM;
-               goto out;
-       }
-       phy_common = &phy->common_cfg;
-
-       generic_phy = ufs_qcom_phy_generic_probe(pdev, phy_common,
-                               &ufs_qcom_phy_qmp_14nm_phy_ops, &phy_14nm_ops);
-
-       if (!generic_phy) {
-               err = -EIO;
-               goto out;
-       }
-
-       err = ufs_qcom_phy_init_clks(phy_common);
-       if (err)
-               goto out;
-
-       err = ufs_qcom_phy_init_vregulators(phy_common);
-       if (err)
-               goto out;
-
-       phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV;
-       phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV;
-
-       ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common);
-
-       phy_set_drvdata(generic_phy, phy);
-
-       strlcpy(phy_common->name, UFS_PHY_NAME, sizeof(phy_common->name));
-
-out:
-       return err;
-}
-
-static const struct of_device_id ufs_qcom_phy_qmp_14nm_of_match[] = {
-       {.compatible = "qcom,ufs-phy-qmp-14nm"},
-       {.compatible = "qcom,msm8996-ufs-phy-qmp-14nm"},
-       {},
-};
-MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_14nm_of_match);
-
-static struct platform_driver ufs_qcom_phy_qmp_14nm_driver = {
-       .probe = ufs_qcom_phy_qmp_14nm_probe,
-       .driver = {
-               .of_match_table = ufs_qcom_phy_qmp_14nm_of_match,
-               .name = "ufs_qcom_phy_qmp_14nm",
-       },
-};
-
-module_platform_driver(ufs_qcom_phy_qmp_14nm_driver);
-
-MODULE_DESCRIPTION("Universal Flash Storage (UFS) QCOM PHY QMP 14nm");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.h b/drivers/phy/phy-qcom-ufs-qmp-14nm.h
deleted file mode 100644 (file)
index 3aefdba..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef UFS_QCOM_PHY_QMP_14NM_H_
-#define UFS_QCOM_PHY_QMP_14NM_H_
-
-#include "phy-qcom-ufs-i.h"
-
-/* QCOM UFS PHY control registers */
-#define COM_OFF(x)     (0x000 + x)
-#define PHY_OFF(x)     (0xC00 + x)
-#define TX_OFF(n, x)   (0x400 + (0x400 * n) + x)
-#define RX_OFF(n, x)   (0x600 + (0x400 * n) + x)
-
-/* UFS PHY QSERDES COM registers */
-#define QSERDES_COM_BG_TIMER                   COM_OFF(0x0C)
-#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN                COM_OFF(0x34)
-#define QSERDES_COM_SYS_CLK_CTRL               COM_OFF(0x3C)
-#define QSERDES_COM_LOCK_CMP1_MODE0            COM_OFF(0x4C)
-#define QSERDES_COM_LOCK_CMP2_MODE0            COM_OFF(0x50)
-#define QSERDES_COM_LOCK_CMP3_MODE0            COM_OFF(0x54)
-#define QSERDES_COM_LOCK_CMP1_MODE1            COM_OFF(0x58)
-#define QSERDES_COM_LOCK_CMP2_MODE1            COM_OFF(0x5C)
-#define QSERDES_COM_LOCK_CMP3_MODE1            COM_OFF(0x60)
-#define QSERDES_COM_CP_CTRL_MODE0              COM_OFF(0x78)
-#define QSERDES_COM_CP_CTRL_MODE1              COM_OFF(0x7C)
-#define QSERDES_COM_PLL_RCTRL_MODE0            COM_OFF(0x84)
-#define QSERDES_COM_PLL_RCTRL_MODE1            COM_OFF(0x88)
-#define QSERDES_COM_PLL_CCTRL_MODE0            COM_OFF(0x90)
-#define QSERDES_COM_PLL_CCTRL_MODE1            COM_OFF(0x94)
-#define QSERDES_COM_SYSCLK_EN_SEL              COM_OFF(0xAC)
-#define QSERDES_COM_RESETSM_CNTRL              COM_OFF(0xB4)
-#define QSERDES_COM_LOCK_CMP_EN                        COM_OFF(0xC8)
-#define QSERDES_COM_LOCK_CMP_CFG               COM_OFF(0xCC)
-#define QSERDES_COM_DEC_START_MODE0            COM_OFF(0xD0)
-#define QSERDES_COM_DEC_START_MODE1            COM_OFF(0xD4)
-#define QSERDES_COM_DIV_FRAC_START1_MODE0      COM_OFF(0xDC)
-#define QSERDES_COM_DIV_FRAC_START2_MODE0      COM_OFF(0xE0)
-#define QSERDES_COM_DIV_FRAC_START3_MODE0      COM_OFF(0xE4)
-#define QSERDES_COM_DIV_FRAC_START1_MODE1      COM_OFF(0xE8)
-#define QSERDES_COM_DIV_FRAC_START2_MODE1      COM_OFF(0xEC)
-#define QSERDES_COM_DIV_FRAC_START3_MODE1      COM_OFF(0xF0)
-#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0      COM_OFF(0x108)
-#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0      COM_OFF(0x10C)
-#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1      COM_OFF(0x110)
-#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1      COM_OFF(0x114)
-#define QSERDES_COM_VCO_TUNE_CTRL              COM_OFF(0x124)
-#define QSERDES_COM_VCO_TUNE_MAP               COM_OFF(0x128)
-#define QSERDES_COM_VCO_TUNE1_MODE0            COM_OFF(0x12C)
-#define QSERDES_COM_VCO_TUNE2_MODE0            COM_OFF(0x130)
-#define QSERDES_COM_VCO_TUNE1_MODE1            COM_OFF(0x134)
-#define QSERDES_COM_VCO_TUNE2_MODE1            COM_OFF(0x138)
-#define QSERDES_COM_VCO_TUNE_TIMER1            COM_OFF(0x144)
-#define QSERDES_COM_VCO_TUNE_TIMER2            COM_OFF(0x148)
-#define QSERDES_COM_CLK_SELECT                 COM_OFF(0x174)
-#define QSERDES_COM_HSCLK_SEL                  COM_OFF(0x178)
-#define QSERDES_COM_CORECLK_DIV                        COM_OFF(0x184)
-#define QSERDES_COM_CORE_CLK_EN                        COM_OFF(0x18C)
-#define QSERDES_COM_CMN_CONFIG                 COM_OFF(0x194)
-#define QSERDES_COM_SVS_MODE_CLK_SEL           COM_OFF(0x19C)
-#define QSERDES_COM_CORECLK_DIV_MODE1          COM_OFF(0x1BC)
-
-/* UFS PHY registers */
-#define UFS_PHY_PHY_START                      PHY_OFF(0x00)
-#define UFS_PHY_POWER_DOWN_CONTROL             PHY_OFF(0x04)
-#define UFS_PHY_PCS_READY_STATUS               PHY_OFF(0x168)
-
-/* UFS PHY TX registers */
-#define QSERDES_TX_HIGHZ_TRANSCEIVER_BIAS_DRVR_EN      TX_OFF(0, 0x68)
-#define QSERDES_TX_LANE_MODE                           TX_OFF(0, 0x94)
-
-/* UFS PHY RX registers */
-#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN       RX_OFF(0, 0x40)
-#define QSERDES_RX_RX_TERM_BW                  RX_OFF(0, 0x90)
-#define QSERDES_RX_RX_EQ_GAIN1_LSB             RX_OFF(0, 0xC4)
-#define QSERDES_RX_RX_EQ_GAIN1_MSB             RX_OFF(0, 0xC8)
-#define QSERDES_RX_RX_EQ_GAIN2_LSB             RX_OFF(0, 0xCC)
-#define QSERDES_RX_RX_EQ_GAIN2_MSB             RX_OFF(0, 0xD0)
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2       RX_OFF(0, 0xD8)
-#define QSERDES_RX_SIGDET_CNTRL                        RX_OFF(0, 0x114)
-#define QSERDES_RX_SIGDET_LVL                  RX_OFF(0, 0x118)
-#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL       RX_OFF(0, 0x11C)
-#define QSERDES_RX_RX_INTERFACE_MODE           RX_OFF(0, 0x12C)
-
-/*
- * This structure represents the 14nm specific phy.
- * common_cfg MUST remain the first field in this structure
- * in case extra fields are added. This way, when calling
- * get_ufs_qcom_phy() of generic phy, we can extract the
- * common phy structure (struct ufs_qcom_phy) out of it
- * regardless of the relevant specific phy.
- */
-struct ufs_qcom_phy_qmp_14nm {
-       struct ufs_qcom_phy common_cfg;
-};
-
-static struct ufs_qcom_phy_calibration phy_cal_table_rate_A[] = {
-       UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CMN_CONFIG, 0x0e),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL, 0xd7),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CLK_SELECT, 0x30),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYS_CLK_CTRL, 0x06),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BG_TIMER, 0x0a),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_HSCLK_SEL, 0x05),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV, 0x0a),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_EN, 0x01),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_CTRL, 0x10),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x20),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORE_CLK_EN, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_CFG, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_MAP, 0x14),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE0, 0x82),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE0, 0x28),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE0, 0x02),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE0, 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE1, 0x98),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE1, 0x0b),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE1, 0x16),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE1, 0x28),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE1, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE1, 0x32),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP3_MODE1, 0x00),
-
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_HIGHZ_TRANSCEIVER_BIAS_DRVR_EN, 0x45),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE, 0x02),
-
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_LVL, 0x24),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_CNTRL, 0x02),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_INTERFACE_MODE, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x18),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_TERM_BW, 0x5B),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x0F),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E),
-};
-
-static struct ufs_qcom_phy_calibration phy_cal_table_rate_B[] = {
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_MAP, 0x54),
-};
-
-#endif
diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c
deleted file mode 100644 (file)
index 4f68acb..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include "phy-qcom-ufs-qmp-20nm.h"
-
-#define UFS_PHY_NAME "ufs_phy_qmp_20nm"
-
-static
-int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
-                                       bool is_rate_B)
-{
-       struct ufs_qcom_phy_calibration *tbl_A, *tbl_B;
-       int tbl_size_A, tbl_size_B;
-       u8 major = ufs_qcom_phy->host_ctrl_rev_major;
-       u16 minor = ufs_qcom_phy->host_ctrl_rev_minor;
-       u16 step = ufs_qcom_phy->host_ctrl_rev_step;
-       int err;
-
-       if ((major == 0x1) && (minor == 0x002) && (step == 0x0000)) {
-               tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_2_0);
-               tbl_A = phy_cal_table_rate_A_1_2_0;
-       } else if ((major == 0x1) && (minor == 0x003) && (step == 0x0000)) {
-               tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_3_0);
-               tbl_A = phy_cal_table_rate_A_1_3_0;
-       } else {
-               dev_err(ufs_qcom_phy->dev, "%s: Unknown UFS-PHY version, no calibration values\n",
-                       __func__);
-               err = -ENODEV;
-               goto out;
-       }
-
-       tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
-       tbl_B = phy_cal_table_rate_B;
-
-       err = ufs_qcom_phy_calibrate(ufs_qcom_phy, tbl_A, tbl_size_A,
-                                               tbl_B, tbl_size_B, is_rate_B);
-
-       if (err)
-               dev_err(ufs_qcom_phy->dev, "%s: ufs_qcom_phy_calibrate() failed %d\n",
-                       __func__, err);
-
-out:
-       return err;
-}
-
-static
-void ufs_qcom_phy_qmp_20nm_advertise_quirks(struct ufs_qcom_phy *phy_common)
-{
-       phy_common->quirks =
-               UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE;
-}
-
-static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy)
-{
-       return 0;
-}
-
-static int ufs_qcom_phy_qmp_20nm_exit(struct phy *generic_phy)
-{
-       return 0;
-}
-
-static
-void ufs_qcom_phy_qmp_20nm_power_control(struct ufs_qcom_phy *phy, bool val)
-{
-       bool hibern8_exit_after_pwr_collapse = phy->quirks &
-               UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE;
-
-       if (val) {
-               writel_relaxed(0x1, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL);
-               /*
-                * Before any transactions involving PHY, ensure PHY knows
-                * that it's analog rail is powered ON.
-                */
-               mb();
-
-               if (hibern8_exit_after_pwr_collapse) {
-                       /*
-                        * Give atleast 1us delay after restoring PHY analog
-                        * power.
-                        */
-                       usleep_range(1, 2);
-                       writel_relaxed(0x0A, phy->mmio +
-                                      QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
-                       writel_relaxed(0x08, phy->mmio +
-                                      QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
-                       /*
-                        * Make sure workaround is deactivated before proceeding
-                        * with normal PHY operations.
-                        */
-                       mb();
-               }
-       } else {
-               if (hibern8_exit_after_pwr_collapse) {
-                       writel_relaxed(0x0A, phy->mmio +
-                                      QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
-                       writel_relaxed(0x02, phy->mmio +
-                                      QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
-                       /*
-                        * Make sure that above workaround is activated before
-                        * PHY analog power collapse.
-                        */
-                       mb();
-               }
-
-               writel_relaxed(0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL);
-               /*
-                * ensure that PHY knows its PHY analog rail is going
-                * to be powered down
-                */
-               mb();
-       }
-}
-
-static
-void ufs_qcom_phy_qmp_20nm_set_tx_lane_enable(struct ufs_qcom_phy *phy, u32 val)
-{
-       writel_relaxed(val & UFS_PHY_TX_LANE_ENABLE_MASK,
-                       phy->mmio + UFS_PHY_TX_LANE_ENABLE);
-       mb();
-}
-
-static inline void ufs_qcom_phy_qmp_20nm_start_serdes(struct ufs_qcom_phy *phy)
-{
-       u32 tmp;
-
-       tmp = readl_relaxed(phy->mmio + UFS_PHY_PHY_START);
-       tmp &= ~MASK_SERDES_START;
-       tmp |= (1 << OFFSET_SERDES_START);
-       writel_relaxed(tmp, phy->mmio + UFS_PHY_PHY_START);
-       mb();
-}
-
-static int ufs_qcom_phy_qmp_20nm_is_pcs_ready(struct ufs_qcom_phy *phy_common)
-{
-       int err = 0;
-       u32 val;
-
-       err = readl_poll_timeout(phy_common->mmio + UFS_PHY_PCS_READY_STATUS,
-                       val, (val & MASK_PCS_READY), 10, 1000000);
-       if (err)
-               dev_err(phy_common->dev, "%s: poll for pcs failed err = %d\n",
-                       __func__, err);
-       return err;
-}
-
-static const struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = {
-       .init           = ufs_qcom_phy_qmp_20nm_init,
-       .exit           = ufs_qcom_phy_qmp_20nm_exit,
-       .power_on       = ufs_qcom_phy_power_on,
-       .power_off      = ufs_qcom_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static struct ufs_qcom_phy_specific_ops phy_20nm_ops = {
-       .calibrate_phy          = ufs_qcom_phy_qmp_20nm_phy_calibrate,
-       .start_serdes           = ufs_qcom_phy_qmp_20nm_start_serdes,
-       .is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_20nm_is_pcs_ready,
-       .set_tx_lane_enable     = ufs_qcom_phy_qmp_20nm_set_tx_lane_enable,
-       .power_control          = ufs_qcom_phy_qmp_20nm_power_control,
-};
-
-static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct phy *generic_phy;
-       struct ufs_qcom_phy_qmp_20nm *phy;
-       struct ufs_qcom_phy *phy_common;
-       int err = 0;
-
-       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
-       if (!phy) {
-               err = -ENOMEM;
-               goto out;
-       }
-       phy_common = &phy->common_cfg;
-
-       generic_phy = ufs_qcom_phy_generic_probe(pdev, phy_common,
-                               &ufs_qcom_phy_qmp_20nm_phy_ops, &phy_20nm_ops);
-
-       if (!generic_phy) {
-               err = -EIO;
-               goto out;
-       }
-
-       err = ufs_qcom_phy_init_clks(phy_common);
-       if (err)
-               goto out;
-
-       err = ufs_qcom_phy_init_vregulators(phy_common);
-       if (err)
-               goto out;
-
-       ufs_qcom_phy_qmp_20nm_advertise_quirks(phy_common);
-
-       phy_set_drvdata(generic_phy, phy);
-
-       strlcpy(phy_common->name, UFS_PHY_NAME, sizeof(phy_common->name));
-
-out:
-       return err;
-}
-
-static const struct of_device_id ufs_qcom_phy_qmp_20nm_of_match[] = {
-       {.compatible = "qcom,ufs-phy-qmp-20nm"},
-       {},
-};
-MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_20nm_of_match);
-
-static struct platform_driver ufs_qcom_phy_qmp_20nm_driver = {
-       .probe = ufs_qcom_phy_qmp_20nm_probe,
-       .driver = {
-               .of_match_table = ufs_qcom_phy_qmp_20nm_of_match,
-               .name = "ufs_qcom_phy_qmp_20nm",
-       },
-};
-
-module_platform_driver(ufs_qcom_phy_qmp_20nm_driver);
-
-MODULE_DESCRIPTION("Universal Flash Storage (UFS) QCOM PHY QMP 20nm");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.h b/drivers/phy/phy-qcom-ufs-qmp-20nm.h
deleted file mode 100644 (file)
index 4f3076b..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef UFS_QCOM_PHY_QMP_20NM_H_
-#define UFS_QCOM_PHY_QMP_20NM_H_
-
-#include "phy-qcom-ufs-i.h"
-
-/* QCOM UFS PHY control registers */
-
-#define COM_OFF(x)     (0x000 + x)
-#define PHY_OFF(x)     (0xC00 + x)
-#define TX_OFF(n, x)   (0x400 + (0x400 * n) + x)
-#define RX_OFF(n, x)   (0x600 + (0x400 * n) + x)
-
-/* UFS PHY PLL block registers */
-#define QSERDES_COM_SYS_CLK_CTRL               COM_OFF(0x0)
-#define QSERDES_COM_PLL_VCOTAIL_EN             COM_OFF(0x04)
-#define QSERDES_COM_PLL_CNTRL                  COM_OFF(0x14)
-#define QSERDES_COM_PLL_IP_SETI                        COM_OFF(0x24)
-#define QSERDES_COM_CORE_CLK_IN_SYNC_SEL       COM_OFF(0x28)
-#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN                COM_OFF(0x30)
-#define QSERDES_COM_PLL_CP_SETI                        COM_OFF(0x34)
-#define QSERDES_COM_PLL_IP_SETP                        COM_OFF(0x38)
-#define QSERDES_COM_PLL_CP_SETP                        COM_OFF(0x3C)
-#define QSERDES_COM_SYSCLK_EN_SEL_TXBAND       COM_OFF(0x48)
-#define QSERDES_COM_RESETSM_CNTRL              COM_OFF(0x4C)
-#define QSERDES_COM_RESETSM_CNTRL2             COM_OFF(0x50)
-#define QSERDES_COM_PLLLOCK_CMP1               COM_OFF(0x90)
-#define QSERDES_COM_PLLLOCK_CMP2               COM_OFF(0x94)
-#define QSERDES_COM_PLLLOCK_CMP3               COM_OFF(0x98)
-#define QSERDES_COM_PLLLOCK_CMP_EN             COM_OFF(0x9C)
-#define QSERDES_COM_BGTC                       COM_OFF(0xA0)
-#define QSERDES_COM_DEC_START1                 COM_OFF(0xAC)
-#define QSERDES_COM_PLL_AMP_OS                 COM_OFF(0xB0)
-#define QSERDES_COM_RES_CODE_UP_OFFSET         COM_OFF(0xD8)
-#define QSERDES_COM_RES_CODE_DN_OFFSET         COM_OFF(0xDC)
-#define QSERDES_COM_DIV_FRAC_START1            COM_OFF(0x100)
-#define QSERDES_COM_DIV_FRAC_START2            COM_OFF(0x104)
-#define QSERDES_COM_DIV_FRAC_START3            COM_OFF(0x108)
-#define QSERDES_COM_DEC_START2                 COM_OFF(0x10C)
-#define QSERDES_COM_PLL_RXTXEPCLK_EN           COM_OFF(0x110)
-#define QSERDES_COM_PLL_CRCTRL                 COM_OFF(0x114)
-#define QSERDES_COM_PLL_CLKEPDIV               COM_OFF(0x118)
-
-/* TX LANE n (0, 1) registers */
-#define QSERDES_TX_EMP_POST1_LVL(n)            TX_OFF(n, 0x08)
-#define QSERDES_TX_DRV_LVL(n)                  TX_OFF(n, 0x0C)
-#define QSERDES_TX_LANE_MODE(n)                        TX_OFF(n, 0x54)
-
-/* RX LANE n (0, 1) registers */
-#define QSERDES_RX_CDR_CONTROL1(n)             RX_OFF(n, 0x0)
-#define QSERDES_RX_CDR_CONTROL_HALF(n)         RX_OFF(n, 0x8)
-#define QSERDES_RX_RX_EQ_GAIN1_LSB(n)          RX_OFF(n, 0xA8)
-#define QSERDES_RX_RX_EQ_GAIN1_MSB(n)          RX_OFF(n, 0xAC)
-#define QSERDES_RX_RX_EQ_GAIN2_LSB(n)          RX_OFF(n, 0xB0)
-#define QSERDES_RX_RX_EQ_GAIN2_MSB(n)          RX_OFF(n, 0xB4)
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(n)    RX_OFF(n, 0xBC)
-#define QSERDES_RX_CDR_CONTROL_QUARTER(n)      RX_OFF(n, 0xC)
-#define QSERDES_RX_SIGDET_CNTRL(n)             RX_OFF(n, 0x100)
-
-/* UFS PHY registers */
-#define UFS_PHY_PHY_START                      PHY_OFF(0x00)
-#define UFS_PHY_POWER_DOWN_CONTROL             PHY_OFF(0x4)
-#define UFS_PHY_TX_LANE_ENABLE                 PHY_OFF(0x44)
-#define UFS_PHY_PWM_G1_CLK_DIVIDER             PHY_OFF(0x08)
-#define UFS_PHY_PWM_G2_CLK_DIVIDER             PHY_OFF(0x0C)
-#define UFS_PHY_PWM_G3_CLK_DIVIDER             PHY_OFF(0x10)
-#define UFS_PHY_PWM_G4_CLK_DIVIDER             PHY_OFF(0x14)
-#define UFS_PHY_CORECLK_PWM_G1_CLK_DIVIDER     PHY_OFF(0x34)
-#define UFS_PHY_CORECLK_PWM_G2_CLK_DIVIDER     PHY_OFF(0x38)
-#define UFS_PHY_CORECLK_PWM_G3_CLK_DIVIDER     PHY_OFF(0x3C)
-#define UFS_PHY_CORECLK_PWM_G4_CLK_DIVIDER     PHY_OFF(0x40)
-#define UFS_PHY_OMC_STATUS_RDVAL               PHY_OFF(0x68)
-#define UFS_PHY_LINE_RESET_TIME                        PHY_OFF(0x28)
-#define UFS_PHY_LINE_RESET_GRANULARITY         PHY_OFF(0x2C)
-#define UFS_PHY_TSYNC_RSYNC_CNTL               PHY_OFF(0x48)
-#define UFS_PHY_PLL_CNTL                       PHY_OFF(0x50)
-#define UFS_PHY_TX_LARGE_AMP_DRV_LVL           PHY_OFF(0x54)
-#define UFS_PHY_TX_SMALL_AMP_DRV_LVL           PHY_OFF(0x5C)
-#define UFS_PHY_TX_LARGE_AMP_POST_EMP_LVL      PHY_OFF(0x58)
-#define UFS_PHY_TX_SMALL_AMP_POST_EMP_LVL      PHY_OFF(0x60)
-#define UFS_PHY_CFG_CHANGE_CNT_VAL             PHY_OFF(0x64)
-#define UFS_PHY_RX_SYNC_WAIT_TIME              PHY_OFF(0x6C)
-#define UFS_PHY_TX_MIN_SLEEP_NOCONFIG_TIME_CAPABILITY  PHY_OFF(0xB4)
-#define UFS_PHY_RX_MIN_SLEEP_NOCONFIG_TIME_CAPABILITY  PHY_OFF(0xE0)
-#define UFS_PHY_TX_MIN_STALL_NOCONFIG_TIME_CAPABILITY  PHY_OFF(0xB8)
-#define UFS_PHY_RX_MIN_STALL_NOCONFIG_TIME_CAPABILITY  PHY_OFF(0xE4)
-#define UFS_PHY_TX_MIN_SAVE_CONFIG_TIME_CAPABILITY     PHY_OFF(0xBC)
-#define UFS_PHY_RX_MIN_SAVE_CONFIG_TIME_CAPABILITY     PHY_OFF(0xE8)
-#define UFS_PHY_RX_PWM_BURST_CLOSURE_LENGTH_CAPABILITY PHY_OFF(0xFC)
-#define UFS_PHY_RX_MIN_ACTIVATETIME_CAPABILITY         PHY_OFF(0x100)
-#define UFS_PHY_RX_SIGDET_CTRL3                                PHY_OFF(0x14c)
-#define UFS_PHY_RMMI_ATTR_CTRL                 PHY_OFF(0x160)
-#define UFS_PHY_RMMI_RX_CFGUPDT_L1     (1 << 7)
-#define UFS_PHY_RMMI_TX_CFGUPDT_L1     (1 << 6)
-#define UFS_PHY_RMMI_CFGWR_L1          (1 << 5)
-#define UFS_PHY_RMMI_CFGRD_L1          (1 << 4)
-#define UFS_PHY_RMMI_RX_CFGUPDT_L0     (1 << 3)
-#define UFS_PHY_RMMI_TX_CFGUPDT_L0     (1 << 2)
-#define UFS_PHY_RMMI_CFGWR_L0          (1 << 1)
-#define UFS_PHY_RMMI_CFGRD_L0          (1 << 0)
-#define UFS_PHY_RMMI_ATTRID                    PHY_OFF(0x164)
-#define UFS_PHY_RMMI_ATTRWRVAL                 PHY_OFF(0x168)
-#define UFS_PHY_RMMI_ATTRRDVAL_L0_STATUS       PHY_OFF(0x16C)
-#define UFS_PHY_RMMI_ATTRRDVAL_L1_STATUS       PHY_OFF(0x170)
-#define UFS_PHY_PCS_READY_STATUS               PHY_OFF(0x174)
-
-#define UFS_PHY_TX_LANE_ENABLE_MASK            0x3
-
-/*
- * This structure represents the 20nm specific phy.
- * common_cfg MUST remain the first field in this structure
- * in case extra fields are added. This way, when calling
- * get_ufs_qcom_phy() of generic phy, we can extract the
- * common phy structure (struct ufs_qcom_phy) out of it
- * regardless of the relevant specific phy.
- */
-struct ufs_qcom_phy_qmp_20nm {
-       struct ufs_qcom_phy common_cfg;
-};
-
-static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_1_2_0[] = {
-       UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01),
-       UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL3, 0x0D),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_VCOTAIL_EN, 0xe1),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CRCTRL, 0xcc),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL_TXBAND, 0x08),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CLKEPDIV, 0x03),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RXTXEPCLK_EN, 0x10),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x82),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START2, 0x03),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1, 0x80),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2, 0x80),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3, 0x40),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x19),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP3, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP_EN, 0x03),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x90),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL2, 0x03),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(0), 0xf2),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(0), 0x0c),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(0), 0x12),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(1), 0xf2),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(1), 0x0c),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(1), 0x12),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(0), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(0), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(0), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(0), 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(1), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(1), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(1), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(1), 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETI, 0x3f),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETP, 0x1b),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETP, 0x0f),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETI, 0x01),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_EMP_POST1_LVL(0), 0x2F),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_DRV_LVL(0), 0x20),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_EMP_POST1_LVL(1), 0x2F),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_DRV_LVL(1), 0x20),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(0), 0x68),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(1), 0x68),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(1), 0xdc),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(0), 0xdc),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3),
-};
-
-static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_1_3_0[] = {
-       UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01),
-       UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL3, 0x0D),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_VCOTAIL_EN, 0xe1),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CRCTRL, 0xcc),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL_TXBAND, 0x08),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CLKEPDIV, 0x03),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RXTXEPCLK_EN, 0x10),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x82),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START2, 0x03),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1, 0x80),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2, 0x80),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3, 0x40),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x19),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP3, 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP_EN, 0x03),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x90),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL2, 0x03),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(0), 0xf2),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(0), 0x0c),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(0), 0x12),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(1), 0xf2),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(1), 0x0c),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(1), 0x12),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(0), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(0), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(0), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(0), 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(1), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(1), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(1), 0xff),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(1), 0x00),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETI, 0x2b),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETP, 0x38),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETP, 0x3c),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RES_CODE_UP_OFFSET, 0x02),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RES_CODE_DN_OFFSET, 0x02),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETI, 0x01),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CNTRL, 0x40),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(0), 0x68),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(1), 0x68),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(1), 0xdc),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(0), 0xdc),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3),
-};
-
-static struct ufs_qcom_phy_calibration phy_cal_table_rate_B[] = {
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x98),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0x65),
-       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x1e),
-};
-
-#endif
diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c
deleted file mode 100644 (file)
index 43865ef..0000000
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include "phy-qcom-ufs-i.h"
-
-#define MAX_PROP_NAME              32
-#define VDDA_PHY_MIN_UV            1000000
-#define VDDA_PHY_MAX_UV            1000000
-#define VDDA_PLL_MIN_UV            1800000
-#define VDDA_PLL_MAX_UV            1800000
-#define VDDP_REF_CLK_MIN_UV        1200000
-#define VDDP_REF_CLK_MAX_UV        1200000
-
-int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
-                          struct ufs_qcom_phy_calibration *tbl_A,
-                          int tbl_size_A,
-                          struct ufs_qcom_phy_calibration *tbl_B,
-                          int tbl_size_B, bool is_rate_B)
-{
-       int i;
-       int ret = 0;
-
-       if (!tbl_A) {
-               dev_err(ufs_qcom_phy->dev, "%s: tbl_A is NULL", __func__);
-               ret = EINVAL;
-               goto out;
-       }
-
-       for (i = 0; i < tbl_size_A; i++)
-               writel_relaxed(tbl_A[i].cfg_value,
-                              ufs_qcom_phy->mmio + tbl_A[i].reg_offset);
-
-       /*
-        * In case we would like to work in rate B, we need
-        * to override a registers that were configured in rate A table
-        * with registers of rate B table.
-        * table.
-        */
-       if (is_rate_B) {
-               if (!tbl_B) {
-                       dev_err(ufs_qcom_phy->dev, "%s: tbl_B is NULL",
-                               __func__);
-                       ret = EINVAL;
-                       goto out;
-               }
-
-               for (i = 0; i < tbl_size_B; i++)
-                       writel_relaxed(tbl_B[i].cfg_value,
-                               ufs_qcom_phy->mmio + tbl_B[i].reg_offset);
-       }
-
-       /* flush buffered writes */
-       mb();
-
-out:
-       return ret;
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate);
-
-/*
- * This assumes the embedded phy structure inside generic_phy is of type
- * struct ufs_qcom_phy. In order to function properly it's crucial
- * to keep the embedded struct "struct ufs_qcom_phy common_cfg"
- * as the first inside generic_phy.
- */
-struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy)
-{
-       return (struct ufs_qcom_phy *)phy_get_drvdata(generic_phy);
-}
-EXPORT_SYMBOL_GPL(get_ufs_qcom_phy);
-
-static
-int ufs_qcom_phy_base_init(struct platform_device *pdev,
-                          struct ufs_qcom_phy *phy_common)
-{
-       struct device *dev = &pdev->dev;
-       struct resource *res;
-       int err = 0;
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_mem");
-       phy_common->mmio = devm_ioremap_resource(dev, res);
-       if (IS_ERR((void const *)phy_common->mmio)) {
-               err = PTR_ERR((void const *)phy_common->mmio);
-               phy_common->mmio = NULL;
-               dev_err(dev, "%s: ioremap for phy_mem resource failed %d\n",
-                       __func__, err);
-               return err;
-       }
-
-       /* "dev_ref_clk_ctrl_mem" is optional resource */
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                                          "dev_ref_clk_ctrl_mem");
-       phy_common->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res);
-       if (IS_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio))
-               phy_common->dev_ref_clk_ctrl_mmio = NULL;
-
-       return 0;
-}
-
-struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
-                               struct ufs_qcom_phy *common_cfg,
-                               const struct phy_ops *ufs_qcom_phy_gen_ops,
-                               struct ufs_qcom_phy_specific_ops *phy_spec_ops)
-{
-       int err;
-       struct device *dev = &pdev->dev;
-       struct phy *generic_phy = NULL;
-       struct phy_provider *phy_provider;
-
-       err = ufs_qcom_phy_base_init(pdev, common_cfg);
-       if (err) {
-               dev_err(dev, "%s: phy base init failed %d\n", __func__, err);
-               goto out;
-       }
-
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (IS_ERR(phy_provider)) {
-               err = PTR_ERR(phy_provider);
-               dev_err(dev, "%s: failed to register phy %d\n", __func__, err);
-               goto out;
-       }
-
-       generic_phy = devm_phy_create(dev, NULL, ufs_qcom_phy_gen_ops);
-       if (IS_ERR(generic_phy)) {
-               err =  PTR_ERR(generic_phy);
-               dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
-               generic_phy = NULL;
-               goto out;
-       }
-
-       common_cfg->phy_spec_ops = phy_spec_ops;
-       common_cfg->dev = dev;
-
-out:
-       return generic_phy;
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe);
-
-static int __ufs_qcom_phy_clk_get(struct device *dev,
-                        const char *name, struct clk **clk_out, bool err_print)
-{
-       struct clk *clk;
-       int err = 0;
-
-       clk = devm_clk_get(dev, name);
-       if (IS_ERR(clk)) {
-               err = PTR_ERR(clk);
-               if (err_print)
-                       dev_err(dev, "failed to get %s err %d", name, err);
-       } else {
-               *clk_out = clk;
-       }
-
-       return err;
-}
-
-static int ufs_qcom_phy_clk_get(struct device *dev,
-                        const char *name, struct clk **clk_out)
-{
-       return __ufs_qcom_phy_clk_get(dev, name, clk_out, true);
-}
-
-int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common)
-{
-       int err;
-
-       if (of_device_is_compatible(phy_common->dev->of_node,
-                               "qcom,msm8996-ufs-phy-qmp-14nm"))
-               goto skip_txrx_clk;
-
-       err = ufs_qcom_phy_clk_get(phy_common->dev, "tx_iface_clk",
-                                  &phy_common->tx_iface_clk);
-       if (err)
-               goto out;
-
-       err = ufs_qcom_phy_clk_get(phy_common->dev, "rx_iface_clk",
-                                  &phy_common->rx_iface_clk);
-       if (err)
-               goto out;
-
-skip_txrx_clk:
-       err = ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk_src",
-                                  &phy_common->ref_clk_src);
-       if (err)
-               goto out;
-
-       /*
-        * "ref_clk_parent" is optional hence don't abort init if it's not
-        * found.
-        */
-       __ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk_parent",
-                                  &phy_common->ref_clk_parent, false);
-
-       err = ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk",
-                                  &phy_common->ref_clk);
-
-out:
-       return err;
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_clks);
-
-static int ufs_qcom_phy_init_vreg(struct device *dev,
-                                 struct ufs_qcom_phy_vreg *vreg,
-                                 const char *name)
-{
-       int err = 0;
-
-       char prop_name[MAX_PROP_NAME];
-
-       vreg->name = name;
-       vreg->reg = devm_regulator_get(dev, name);
-       if (IS_ERR(vreg->reg)) {
-               err = PTR_ERR(vreg->reg);
-               dev_err(dev, "failed to get %s, %d\n", name, err);
-               goto out;
-       }
-
-       if (dev->of_node) {
-               snprintf(prop_name, MAX_PROP_NAME, "%s-max-microamp", name);
-               err = of_property_read_u32(dev->of_node,
-                                       prop_name, &vreg->max_uA);
-               if (err && err != -EINVAL) {
-                       dev_err(dev, "%s: failed to read %s\n",
-                                       __func__, prop_name);
-                       goto out;
-               } else if (err == -EINVAL || !vreg->max_uA) {
-                       if (regulator_count_voltages(vreg->reg) > 0) {
-                               dev_err(dev, "%s: %s is mandatory\n",
-                                               __func__, prop_name);
-                               goto out;
-                       }
-                       err = 0;
-               }
-       }
-
-       if (!strcmp(name, "vdda-pll")) {
-               vreg->max_uV = VDDA_PLL_MAX_UV;
-               vreg->min_uV = VDDA_PLL_MIN_UV;
-       } else if (!strcmp(name, "vdda-phy")) {
-               vreg->max_uV = VDDA_PHY_MAX_UV;
-               vreg->min_uV = VDDA_PHY_MIN_UV;
-       } else if (!strcmp(name, "vddp-ref-clk")) {
-               vreg->max_uV = VDDP_REF_CLK_MAX_UV;
-               vreg->min_uV = VDDP_REF_CLK_MIN_UV;
-       }
-
-out:
-       return err;
-}
-
-int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common)
-{
-       int err;
-
-       err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_pll,
-               "vdda-pll");
-       if (err)
-               goto out;
-
-       err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_phy,
-               "vdda-phy");
-
-       if (err)
-               goto out;
-
-       err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vddp_ref_clk,
-                                    "vddp-ref-clk");
-
-out:
-       return err;
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators);
-
-static int ufs_qcom_phy_cfg_vreg(struct device *dev,
-                         struct ufs_qcom_phy_vreg *vreg, bool on)
-{
-       int ret = 0;
-       struct regulator *reg = vreg->reg;
-       const char *name = vreg->name;
-       int min_uV;
-       int uA_load;
-
-       if (regulator_count_voltages(reg) > 0) {
-               min_uV = on ? vreg->min_uV : 0;
-               ret = regulator_set_voltage(reg, min_uV, vreg->max_uV);
-               if (ret) {
-                       dev_err(dev, "%s: %s set voltage failed, err=%d\n",
-                                       __func__, name, ret);
-                       goto out;
-               }
-               uA_load = on ? vreg->max_uA : 0;
-               ret = regulator_set_load(reg, uA_load);
-               if (ret >= 0) {
-                       /*
-                        * regulator_set_load() returns new regulator
-                        * mode upon success.
-                        */
-                       ret = 0;
-               } else {
-                       dev_err(dev, "%s: %s set optimum mode(uA_load=%d) failed, err=%d\n",
-                                       __func__, name, uA_load, ret);
-                       goto out;
-               }
-       }
-out:
-       return ret;
-}
-
-static int ufs_qcom_phy_enable_vreg(struct device *dev,
-                            struct ufs_qcom_phy_vreg *vreg)
-{
-       int ret = 0;
-
-       if (!vreg || vreg->enabled)
-               goto out;
-
-       ret = ufs_qcom_phy_cfg_vreg(dev, vreg, true);
-       if (ret) {
-               dev_err(dev, "%s: ufs_qcom_phy_cfg_vreg() failed, err=%d\n",
-                       __func__, ret);
-               goto out;
-       }
-
-       ret = regulator_enable(vreg->reg);
-       if (ret) {
-               dev_err(dev, "%s: enable failed, err=%d\n",
-                               __func__, ret);
-               goto out;
-       }
-
-       vreg->enabled = true;
-out:
-       return ret;
-}
-
-static int ufs_qcom_phy_enable_ref_clk(struct ufs_qcom_phy *phy)
-{
-       int ret = 0;
-
-       if (phy->is_ref_clk_enabled)
-               goto out;
-
-       /*
-        * reference clock is propagated in a daisy-chained manner from
-        * source to phy, so ungate them at each stage.
-        */
-       ret = clk_prepare_enable(phy->ref_clk_src);
-       if (ret) {
-               dev_err(phy->dev, "%s: ref_clk_src enable failed %d\n",
-                               __func__, ret);
-               goto out;
-       }
-
-       /*
-        * "ref_clk_parent" is optional clock hence make sure that clk reference
-        * is available before trying to enable the clock.
-        */
-       if (phy->ref_clk_parent) {
-               ret = clk_prepare_enable(phy->ref_clk_parent);
-               if (ret) {
-                       dev_err(phy->dev, "%s: ref_clk_parent enable failed %d\n",
-                                       __func__, ret);
-                       goto out_disable_src;
-               }
-       }
-
-       ret = clk_prepare_enable(phy->ref_clk);
-       if (ret) {
-               dev_err(phy->dev, "%s: ref_clk enable failed %d\n",
-                               __func__, ret);
-               goto out_disable_parent;
-       }
-
-       phy->is_ref_clk_enabled = true;
-       goto out;
-
-out_disable_parent:
-       if (phy->ref_clk_parent)
-               clk_disable_unprepare(phy->ref_clk_parent);
-out_disable_src:
-       clk_disable_unprepare(phy->ref_clk_src);
-out:
-       return ret;
-}
-
-static int ufs_qcom_phy_disable_vreg(struct device *dev,
-                             struct ufs_qcom_phy_vreg *vreg)
-{
-       int ret = 0;
-
-       if (!vreg || !vreg->enabled)
-               goto out;
-
-       ret = regulator_disable(vreg->reg);
-
-       if (!ret) {
-               /* ignore errors on applying disable config */
-               ufs_qcom_phy_cfg_vreg(dev, vreg, false);
-               vreg->enabled = false;
-       } else {
-               dev_err(dev, "%s: %s disable failed, err=%d\n",
-                               __func__, vreg->name, ret);
-       }
-out:
-       return ret;
-}
-
-static void ufs_qcom_phy_disable_ref_clk(struct ufs_qcom_phy *phy)
-{
-       if (phy->is_ref_clk_enabled) {
-               clk_disable_unprepare(phy->ref_clk);
-               /*
-                * "ref_clk_parent" is optional clock hence make sure that clk
-                * reference is available before trying to disable the clock.
-                */
-               if (phy->ref_clk_parent)
-                       clk_disable_unprepare(phy->ref_clk_parent);
-               clk_disable_unprepare(phy->ref_clk_src);
-               phy->is_ref_clk_enabled = false;
-       }
-}
-
-#define UFS_REF_CLK_EN (1 << 5)
-
-static void ufs_qcom_phy_dev_ref_clk_ctrl(struct phy *generic_phy, bool enable)
-{
-       struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy);
-
-       if (phy->dev_ref_clk_ctrl_mmio &&
-           (enable ^ phy->is_dev_ref_clk_enabled)) {
-               u32 temp = readl_relaxed(phy->dev_ref_clk_ctrl_mmio);
-
-               if (enable)
-                       temp |= UFS_REF_CLK_EN;
-               else
-                       temp &= ~UFS_REF_CLK_EN;
-
-               /*
-                * If we are here to disable this clock immediately after
-                * entering into hibern8, we need to make sure that device
-                * ref_clk is active atleast 1us after the hibern8 enter.
-                */
-               if (!enable)
-                       udelay(1);
-
-               writel_relaxed(temp, phy->dev_ref_clk_ctrl_mmio);
-               /* ensure that ref_clk is enabled/disabled before we return */
-               wmb();
-               /*
-                * If we call hibern8 exit after this, we need to make sure that
-                * device ref_clk is stable for atleast 1us before the hibern8
-                * exit command.
-                */
-               if (enable)
-                       udelay(1);
-
-               phy->is_dev_ref_clk_enabled = enable;
-       }
-}
-
-void ufs_qcom_phy_enable_dev_ref_clk(struct phy *generic_phy)
-{
-       ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, true);
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_dev_ref_clk);
-
-void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy)
-{
-       ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, false);
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_dev_ref_clk);
-
-/* Turn ON M-PHY RMMI interface clocks */
-static int ufs_qcom_phy_enable_iface_clk(struct ufs_qcom_phy *phy)
-{
-       int ret = 0;
-
-       if (phy->is_iface_clk_enabled)
-               goto out;
-
-       ret = clk_prepare_enable(phy->tx_iface_clk);
-       if (ret) {
-               dev_err(phy->dev, "%s: tx_iface_clk enable failed %d\n",
-                               __func__, ret);
-               goto out;
-       }
-       ret = clk_prepare_enable(phy->rx_iface_clk);
-       if (ret) {
-               clk_disable_unprepare(phy->tx_iface_clk);
-               dev_err(phy->dev, "%s: rx_iface_clk enable failed %d. disabling also tx_iface_clk\n",
-                               __func__, ret);
-               goto out;
-       }
-       phy->is_iface_clk_enabled = true;
-
-out:
-       return ret;
-}
-
-/* Turn OFF M-PHY RMMI interface clocks */
-void ufs_qcom_phy_disable_iface_clk(struct ufs_qcom_phy *phy)
-{
-       if (phy->is_iface_clk_enabled) {
-               clk_disable_unprepare(phy->tx_iface_clk);
-               clk_disable_unprepare(phy->rx_iface_clk);
-               phy->is_iface_clk_enabled = false;
-       }
-}
-
-int ufs_qcom_phy_start_serdes(struct phy *generic_phy)
-{
-       struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
-       int ret = 0;
-
-       if (!ufs_qcom_phy->phy_spec_ops->start_serdes) {
-               dev_err(ufs_qcom_phy->dev, "%s: start_serdes() callback is not supported\n",
-                       __func__);
-               ret = -ENOTSUPP;
-       } else {
-               ufs_qcom_phy->phy_spec_ops->start_serdes(ufs_qcom_phy);
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_start_serdes);
-
-int ufs_qcom_phy_set_tx_lane_enable(struct phy *generic_phy, u32 tx_lanes)
-{
-       struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
-       int ret = 0;
-
-       if (!ufs_qcom_phy->phy_spec_ops->set_tx_lane_enable) {
-               dev_err(ufs_qcom_phy->dev, "%s: set_tx_lane_enable() callback is not supported\n",
-                       __func__);
-               ret = -ENOTSUPP;
-       } else {
-               ufs_qcom_phy->phy_spec_ops->set_tx_lane_enable(ufs_qcom_phy,
-                                                              tx_lanes);
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_set_tx_lane_enable);
-
-void ufs_qcom_phy_save_controller_version(struct phy *generic_phy,
-                                         u8 major, u16 minor, u16 step)
-{
-       struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
-
-       ufs_qcom_phy->host_ctrl_rev_major = major;
-       ufs_qcom_phy->host_ctrl_rev_minor = minor;
-       ufs_qcom_phy->host_ctrl_rev_step = step;
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_save_controller_version);
-
-int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B)
-{
-       struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
-       int ret = 0;
-
-       if (!ufs_qcom_phy->phy_spec_ops->calibrate_phy) {
-               dev_err(ufs_qcom_phy->dev, "%s: calibrate_phy() callback is not supported\n",
-                       __func__);
-               ret = -ENOTSUPP;
-       } else {
-               ret = ufs_qcom_phy->phy_spec_ops->
-                               calibrate_phy(ufs_qcom_phy, is_rate_B);
-               if (ret)
-                       dev_err(ufs_qcom_phy->dev, "%s: calibrate_phy() failed %d\n",
-                               __func__, ret);
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy);
-
-int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy)
-{
-       struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
-
-       if (!ufs_qcom_phy->phy_spec_ops->is_physical_coding_sublayer_ready) {
-               dev_err(ufs_qcom_phy->dev, "%s: is_physical_coding_sublayer_ready() callback is not supported\n",
-                       __func__);
-               return -ENOTSUPP;
-       }
-
-       return ufs_qcom_phy->phy_spec_ops->
-                       is_physical_coding_sublayer_ready(ufs_qcom_phy);
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_is_pcs_ready);
-
-int ufs_qcom_phy_power_on(struct phy *generic_phy)
-{
-       struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
-       struct device *dev = phy_common->dev;
-       int err;
-
-       if (phy_common->is_powered_on)
-               return 0;
-
-       err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_phy);
-       if (err) {
-               dev_err(dev, "%s enable vdda_phy failed, err=%d\n",
-                       __func__, err);
-               goto out;
-       }
-
-       phy_common->phy_spec_ops->power_control(phy_common, true);
-
-       /* vdda_pll also enables ref clock LDOs so enable it first */
-       err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_pll);
-       if (err) {
-               dev_err(dev, "%s enable vdda_pll failed, err=%d\n",
-                       __func__, err);
-               goto out_disable_phy;
-       }
-
-       err = ufs_qcom_phy_enable_iface_clk(phy_common);
-       if (err) {
-               dev_err(dev, "%s enable phy iface clock failed, err=%d\n",
-                       __func__, err);
-               goto out_disable_pll;
-       }
-
-       err = ufs_qcom_phy_enable_ref_clk(phy_common);
-       if (err) {
-               dev_err(dev, "%s enable phy ref clock failed, err=%d\n",
-                       __func__, err);
-               goto out_disable_iface_clk;
-       }
-
-       /* enable device PHY ref_clk pad rail */
-       if (phy_common->vddp_ref_clk.reg) {
-               err = ufs_qcom_phy_enable_vreg(dev,
-                                              &phy_common->vddp_ref_clk);
-               if (err) {
-                       dev_err(dev, "%s enable vddp_ref_clk failed, err=%d\n",
-                               __func__, err);
-                       goto out_disable_ref_clk;
-               }
-       }
-
-       phy_common->is_powered_on = true;
-       goto out;
-
-out_disable_ref_clk:
-       ufs_qcom_phy_disable_ref_clk(phy_common);
-out_disable_iface_clk:
-       ufs_qcom_phy_disable_iface_clk(phy_common);
-out_disable_pll:
-       ufs_qcom_phy_disable_vreg(dev, &phy_common->vdda_pll);
-out_disable_phy:
-       ufs_qcom_phy_disable_vreg(dev, &phy_common->vdda_phy);
-out:
-       return err;
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_on);
-
-int ufs_qcom_phy_power_off(struct phy *generic_phy)
-{
-       struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
-
-       if (!phy_common->is_powered_on)
-               return 0;
-
-       phy_common->phy_spec_ops->power_control(phy_common, false);
-
-       if (phy_common->vddp_ref_clk.reg)
-               ufs_qcom_phy_disable_vreg(phy_common->dev,
-                                         &phy_common->vddp_ref_clk);
-       ufs_qcom_phy_disable_ref_clk(phy_common);
-       ufs_qcom_phy_disable_iface_clk(phy_common);
-
-       ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_pll);
-       ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_phy);
-       phy_common->is_powered_on = false;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off);
diff --git a/drivers/phy/phy-qcom-usb-hs.c b/drivers/phy/phy-qcom-usb-hs.c
deleted file mode 100644 (file)
index 4b20abc..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/**
- * Copyright (C) 2016 Linaro Ltd
- *
- * 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/module.h>
-#include <linux/ulpi/driver.h>
-#include <linux/ulpi/regs.h>
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
-#include <linux/of_device.h>
-#include <linux/phy/phy.h>
-#include <linux/reset.h>
-#include <linux/extcon.h>
-#include <linux/notifier.h>
-
-#define ULPI_PWR_CLK_MNG_REG           0x88
-# define ULPI_PWR_OTG_COMP_DISABLE     BIT(0)
-
-#define ULPI_MISC_A                    0x96
-# define ULPI_MISC_A_VBUSVLDEXTSEL     BIT(1)
-# define ULPI_MISC_A_VBUSVLDEXT                BIT(0)
-
-
-struct ulpi_seq {
-       u8 addr;
-       u8 val;
-};
-
-struct qcom_usb_hs_phy {
-       struct ulpi *ulpi;
-       struct phy *phy;
-       struct clk *ref_clk;
-       struct clk *sleep_clk;
-       struct regulator *v1p8;
-       struct regulator *v3p3;
-       struct reset_control *reset;
-       struct ulpi_seq *init_seq;
-       struct extcon_dev *vbus_edev;
-       struct notifier_block vbus_notify;
-};
-
-static int qcom_usb_hs_phy_set_mode(struct phy *phy, enum phy_mode mode)
-{
-       struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
-       u8 addr;
-       int ret;
-
-       if (!uphy->vbus_edev) {
-               u8 val = 0;
-
-               switch (mode) {
-               case PHY_MODE_USB_OTG:
-               case PHY_MODE_USB_HOST:
-                       val |= ULPI_INT_IDGRD;
-               case PHY_MODE_USB_DEVICE:
-                       val |= ULPI_INT_SESS_VALID;
-               default:
-                       break;
-               }
-
-               ret = ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_RISE, val);
-               if (ret)
-                       return ret;
-               ret = ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_FALL, val);
-       } else {
-               switch (mode) {
-               case PHY_MODE_USB_OTG:
-               case PHY_MODE_USB_DEVICE:
-                       addr = ULPI_SET(ULPI_MISC_A);
-                       break;
-               case PHY_MODE_USB_HOST:
-                       addr = ULPI_CLR(ULPI_MISC_A);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-
-               ret = ulpi_write(uphy->ulpi, ULPI_SET(ULPI_PWR_CLK_MNG_REG),
-                                ULPI_PWR_OTG_COMP_DISABLE);
-               if (ret)
-                       return ret;
-               ret = ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXTSEL);
-       }
-
-       return ret;
-}
-
-static int
-qcom_usb_hs_phy_vbus_notifier(struct notifier_block *nb, unsigned long event,
-                             void *ptr)
-{
-       struct qcom_usb_hs_phy *uphy;
-       u8 addr;
-
-       uphy = container_of(nb, struct qcom_usb_hs_phy, vbus_notify);
-
-       if (event)
-               addr = ULPI_SET(ULPI_MISC_A);
-       else
-               addr = ULPI_CLR(ULPI_MISC_A);
-
-       return ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXT);
-}
-
-static int qcom_usb_hs_phy_power_on(struct phy *phy)
-{
-       struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
-       struct ulpi *ulpi = uphy->ulpi;
-       const struct ulpi_seq *seq;
-       int ret, state;
-
-       ret = clk_prepare_enable(uphy->ref_clk);
-       if (ret)
-               return ret;
-
-       ret = clk_prepare_enable(uphy->sleep_clk);
-       if (ret)
-               goto err_sleep;
-
-       ret = regulator_set_load(uphy->v1p8, 50000);
-       if (ret < 0)
-               goto err_1p8;
-
-       ret = regulator_enable(uphy->v1p8);
-       if (ret)
-               goto err_1p8;
-
-       ret = regulator_set_voltage_triplet(uphy->v3p3, 3050000, 3300000,
-                                           3300000);
-       if (ret)
-               goto err_3p3;
-
-       ret = regulator_set_load(uphy->v3p3, 50000);
-       if (ret < 0)
-               goto err_3p3;
-
-       ret = regulator_enable(uphy->v3p3);
-       if (ret)
-               goto err_3p3;
-
-       for (seq = uphy->init_seq; seq->addr; seq++) {
-               ret = ulpi_write(ulpi, ULPI_EXT_VENDOR_SPECIFIC + seq->addr,
-                                seq->val);
-               if (ret)
-                       goto err_ulpi;
-       }
-
-       if (uphy->reset) {
-               ret = reset_control_reset(uphy->reset);
-               if (ret)
-                       goto err_ulpi;
-       }
-
-       if (uphy->vbus_edev) {
-               state = extcon_get_cable_state_(uphy->vbus_edev, EXTCON_USB);
-               /* setup initial state */
-               qcom_usb_hs_phy_vbus_notifier(&uphy->vbus_notify, state,
-                                             uphy->vbus_edev);
-               ret = extcon_register_notifier(uphy->vbus_edev, EXTCON_USB,
-                               &uphy->vbus_notify);
-               if (ret)
-                       goto err_ulpi;
-       }
-
-       return 0;
-err_ulpi:
-       regulator_disable(uphy->v3p3);
-err_3p3:
-       regulator_disable(uphy->v1p8);
-err_1p8:
-       clk_disable_unprepare(uphy->sleep_clk);
-err_sleep:
-       clk_disable_unprepare(uphy->ref_clk);
-       return ret;
-}
-
-static int qcom_usb_hs_phy_power_off(struct phy *phy)
-{
-       int ret;
-       struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
-
-       if (uphy->vbus_edev) {
-               ret = extcon_unregister_notifier(uphy->vbus_edev, EXTCON_USB,
-                                                &uphy->vbus_notify);
-               if (ret)
-                       return ret;
-       }
-
-       regulator_disable(uphy->v3p3);
-       regulator_disable(uphy->v1p8);
-       clk_disable_unprepare(uphy->sleep_clk);
-       clk_disable_unprepare(uphy->ref_clk);
-
-       return 0;
-}
-
-static const struct phy_ops qcom_usb_hs_phy_ops = {
-       .power_on = qcom_usb_hs_phy_power_on,
-       .power_off = qcom_usb_hs_phy_power_off,
-       .set_mode = qcom_usb_hs_phy_set_mode,
-       .owner = THIS_MODULE,
-};
-
-static int qcom_usb_hs_phy_probe(struct ulpi *ulpi)
-{
-       struct qcom_usb_hs_phy *uphy;
-       struct phy_provider *p;
-       struct clk *clk;
-       struct regulator *reg;
-       struct reset_control *reset;
-       int size;
-       int ret;
-
-       uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);
-       if (!uphy)
-               return -ENOMEM;
-       ulpi_set_drvdata(ulpi, uphy);
-       uphy->ulpi = ulpi;
-
-       size = of_property_count_u8_elems(ulpi->dev.of_node, "qcom,init-seq");
-       if (size < 0)
-               size = 0;
-       uphy->init_seq = devm_kmalloc_array(&ulpi->dev, (size / 2) + 1,
-                                          sizeof(*uphy->init_seq), GFP_KERNEL);
-       if (!uphy->init_seq)
-               return -ENOMEM;
-       ret = of_property_read_u8_array(ulpi->dev.of_node, "qcom,init-seq",
-                                       (u8 *)uphy->init_seq, size);
-       if (ret && size)
-               return ret;
-       /* NUL terminate */
-       uphy->init_seq[size / 2].addr = uphy->init_seq[size / 2].val = 0;
-
-       uphy->ref_clk = clk = devm_clk_get(&ulpi->dev, "ref");
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
-
-       uphy->sleep_clk = clk = devm_clk_get(&ulpi->dev, "sleep");
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
-
-       uphy->v1p8 = reg = devm_regulator_get(&ulpi->dev, "v1p8");
-       if (IS_ERR(reg))
-               return PTR_ERR(reg);
-
-       uphy->v3p3 = reg = devm_regulator_get(&ulpi->dev, "v3p3");
-       if (IS_ERR(reg))
-               return PTR_ERR(reg);
-
-       uphy->reset = reset = devm_reset_control_get(&ulpi->dev, "por");
-       if (IS_ERR(reset)) {
-               if (PTR_ERR(reset) == -EPROBE_DEFER)
-                       return PTR_ERR(reset);
-               uphy->reset = NULL;
-       }
-
-       uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
-                                   &qcom_usb_hs_phy_ops);
-       if (IS_ERR(uphy->phy))
-               return PTR_ERR(uphy->phy);
-
-       uphy->vbus_edev = extcon_get_edev_by_phandle(&ulpi->dev, 0);
-       if (IS_ERR(uphy->vbus_edev)) {
-               if (PTR_ERR(uphy->vbus_edev) != -ENODEV)
-                       return PTR_ERR(uphy->vbus_edev);
-               uphy->vbus_edev = NULL;
-       }
-
-       uphy->vbus_notify.notifier_call = qcom_usb_hs_phy_vbus_notifier;
-       phy_set_drvdata(uphy->phy, uphy);
-
-       p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);
-       return PTR_ERR_OR_ZERO(p);
-}
-
-static const struct of_device_id qcom_usb_hs_phy_match[] = {
-       { .compatible = "qcom,usb-hs-phy", },
-       { }
-};
-MODULE_DEVICE_TABLE(of, qcom_usb_hs_phy_match);
-
-static struct ulpi_driver qcom_usb_hs_phy_driver = {
-       .probe = qcom_usb_hs_phy_probe,
-       .driver = {
-               .name = "qcom_usb_hs_phy",
-               .of_match_table = qcom_usb_hs_phy_match,
-       },
-};
-module_ulpi_driver(qcom_usb_hs_phy_driver);
-
-MODULE_DESCRIPTION("Qualcomm USB HS phy");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-qcom-usb-hsic.c b/drivers/phy/phy-qcom-usb-hsic.c
deleted file mode 100644 (file)
index c110563..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * Copyright (C) 2016 Linaro Ltd
- *
- * 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/module.h>
-#include <linux/ulpi/driver.h>
-#include <linux/ulpi/regs.h>
-#include <linux/phy/phy.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/pinctrl/pinctrl-state.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-
-#define ULPI_HSIC_CFG          0x30
-#define ULPI_HSIC_IO_CAL       0x33
-
-struct qcom_usb_hsic_phy {
-       struct ulpi *ulpi;
-       struct phy *phy;
-       struct pinctrl *pctl;
-       struct clk *phy_clk;
-       struct clk *cal_clk;
-       struct clk *cal_sleep_clk;
-};
-
-static int qcom_usb_hsic_phy_power_on(struct phy *phy)
-{
-       struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
-       struct ulpi *ulpi = uphy->ulpi;
-       struct pinctrl_state *pins_default;
-       int ret;
-
-       ret = clk_prepare_enable(uphy->phy_clk);
-       if (ret)
-               return ret;
-
-       ret = clk_prepare_enable(uphy->cal_clk);
-       if (ret)
-               goto err_cal;
-
-       ret = clk_prepare_enable(uphy->cal_sleep_clk);
-       if (ret)
-               goto err_sleep;
-
-       /* Set periodic calibration interval to ~2.048sec in HSIC_IO_CAL_REG */
-       ret = ulpi_write(ulpi, ULPI_HSIC_IO_CAL, 0xff);
-       if (ret)
-               goto err_ulpi;
-
-       /* Enable periodic IO calibration in HSIC_CFG register */
-       ret = ulpi_write(ulpi, ULPI_HSIC_CFG, 0xa8);
-       if (ret)
-               goto err_ulpi;
-
-       /* Configure pins for HSIC functionality */
-       pins_default = pinctrl_lookup_state(uphy->pctl, PINCTRL_STATE_DEFAULT);
-       if (IS_ERR(pins_default))
-               return PTR_ERR(pins_default);
-
-       ret = pinctrl_select_state(uphy->pctl, pins_default);
-       if (ret)
-               goto err_ulpi;
-
-        /* Enable HSIC mode in HSIC_CFG register */
-       ret = ulpi_write(ulpi, ULPI_SET(ULPI_HSIC_CFG), 0x01);
-       if (ret)
-               goto err_ulpi;
-
-       /* Disable auto-resume */
-       ret = ulpi_write(ulpi, ULPI_CLR(ULPI_IFC_CTRL),
-                        ULPI_IFC_CTRL_AUTORESUME);
-       if (ret)
-               goto err_ulpi;
-
-       return ret;
-err_ulpi:
-       clk_disable_unprepare(uphy->cal_sleep_clk);
-err_sleep:
-       clk_disable_unprepare(uphy->cal_clk);
-err_cal:
-       clk_disable_unprepare(uphy->phy_clk);
-       return ret;
-}
-
-static int qcom_usb_hsic_phy_power_off(struct phy *phy)
-{
-       struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
-
-       clk_disable_unprepare(uphy->cal_sleep_clk);
-       clk_disable_unprepare(uphy->cal_clk);
-       clk_disable_unprepare(uphy->phy_clk);
-
-       return 0;
-}
-
-static const struct phy_ops qcom_usb_hsic_phy_ops = {
-       .power_on = qcom_usb_hsic_phy_power_on,
-       .power_off = qcom_usb_hsic_phy_power_off,
-       .owner = THIS_MODULE,
-};
-
-static int qcom_usb_hsic_phy_probe(struct ulpi *ulpi)
-{
-       struct qcom_usb_hsic_phy *uphy;
-       struct phy_provider *p;
-       struct clk *clk;
-
-       uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);
-       if (!uphy)
-               return -ENOMEM;
-       ulpi_set_drvdata(ulpi, uphy);
-
-       uphy->ulpi = ulpi;
-       uphy->pctl = devm_pinctrl_get(&ulpi->dev);
-       if (IS_ERR(uphy->pctl))
-               return PTR_ERR(uphy->pctl);
-
-       uphy->phy_clk = clk = devm_clk_get(&ulpi->dev, "phy");
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
-
-       uphy->cal_clk = clk = devm_clk_get(&ulpi->dev, "cal");
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
-
-       uphy->cal_sleep_clk = clk = devm_clk_get(&ulpi->dev, "cal_sleep");
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
-
-       uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
-                                   &qcom_usb_hsic_phy_ops);
-       if (IS_ERR(uphy->phy))
-               return PTR_ERR(uphy->phy);
-       phy_set_drvdata(uphy->phy, uphy);
-
-       p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);
-       return PTR_ERR_OR_ZERO(p);
-}
-
-static const struct of_device_id qcom_usb_hsic_phy_match[] = {
-       { .compatible = "qcom,usb-hsic-phy", },
-       { }
-};
-MODULE_DEVICE_TABLE(of, qcom_usb_hsic_phy_match);
-
-static struct ulpi_driver qcom_usb_hsic_phy_driver = {
-       .probe = qcom_usb_hsic_phy_probe,
-       .driver = {
-               .name = "qcom_usb_hsic_phy",
-               .of_match_table = qcom_usb_hsic_phy_match,
-       },
-};
-module_ulpi_driver(qcom_usb_hsic_phy_driver);
-
-MODULE_DESCRIPTION("Qualcomm USB HSIC phy");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c
deleted file mode 100644 (file)
index 97d4dd6..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Renesas R-Car Gen2 PHY driver
- *
- * Copyright (C) 2014 Renesas Solutions Corp.
- * Copyright (C) 2014 Cogent Embedded, Inc.
- *
- * 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/spinlock.h>
-#include <linux/atomic.h>
-
-#define USBHS_LPSTS                    0x02
-#define USBHS_UGCTRL                   0x80
-#define USBHS_UGCTRL2                  0x84
-#define USBHS_UGSTS                    0x88    /* From technical update */
-
-/* Low Power Status register (LPSTS) */
-#define USBHS_LPSTS_SUSPM              0x4000
-
-/* USB General control register (UGCTRL) */
-#define USBHS_UGCTRL_CONNECT           0x00000004
-#define USBHS_UGCTRL_PLLRESET          0x00000001
-
-/* USB General control register 2 (UGCTRL2) */
-#define USBHS_UGCTRL2_USB2SEL          0x80000000
-#define USBHS_UGCTRL2_USB2SEL_PCI      0x00000000
-#define USBHS_UGCTRL2_USB2SEL_USB30    0x80000000
-#define USBHS_UGCTRL2_USB0SEL          0x00000030
-#define USBHS_UGCTRL2_USB0SEL_PCI      0x00000010
-#define USBHS_UGCTRL2_USB0SEL_HS_USB   0x00000030
-
-/* USB General status register (UGSTS) */
-#define USBHS_UGSTS_LOCK               0x00000100 /* From technical update */
-
-#define PHYS_PER_CHANNEL       2
-
-struct rcar_gen2_phy {
-       struct phy *phy;
-       struct rcar_gen2_channel *channel;
-       int number;
-       u32 select_value;
-};
-
-struct rcar_gen2_channel {
-       struct device_node *of_node;
-       struct rcar_gen2_phy_driver *drv;
-       struct rcar_gen2_phy phys[PHYS_PER_CHANNEL];
-       int selected_phy;
-       u32 select_mask;
-};
-
-struct rcar_gen2_phy_driver {
-       void __iomem *base;
-       struct clk *clk;
-       spinlock_t lock;
-       int num_channels;
-       struct rcar_gen2_channel *channels;
-};
-
-static int rcar_gen2_phy_init(struct phy *p)
-{
-       struct rcar_gen2_phy *phy = phy_get_drvdata(p);
-       struct rcar_gen2_channel *channel = phy->channel;
-       struct rcar_gen2_phy_driver *drv = channel->drv;
-       unsigned long flags;
-       u32 ugctrl2;
-
-       /*
-        * Try to acquire exclusive access to PHY.  The first driver calling
-        * phy_init()  on a given channel wins, and all attempts  to use another
-        * PHY on this channel will fail until phy_exit() is called by the first
-        * driver.   Achieving this with cmpxcgh() should be SMP-safe.
-        */
-       if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1)
-               return -EBUSY;
-
-       clk_prepare_enable(drv->clk);
-
-       spin_lock_irqsave(&drv->lock, flags);
-       ugctrl2 = readl(drv->base + USBHS_UGCTRL2);
-       ugctrl2 &= ~channel->select_mask;
-       ugctrl2 |= phy->select_value;
-       writel(ugctrl2, drv->base + USBHS_UGCTRL2);
-       spin_unlock_irqrestore(&drv->lock, flags);
-       return 0;
-}
-
-static int rcar_gen2_phy_exit(struct phy *p)
-{
-       struct rcar_gen2_phy *phy = phy_get_drvdata(p);
-       struct rcar_gen2_channel *channel = phy->channel;
-
-       clk_disable_unprepare(channel->drv->clk);
-
-       channel->selected_phy = -1;
-
-       return 0;
-}
-
-static int rcar_gen2_phy_power_on(struct phy *p)
-{
-       struct rcar_gen2_phy *phy = phy_get_drvdata(p);
-       struct rcar_gen2_phy_driver *drv = phy->channel->drv;
-       void __iomem *base = drv->base;
-       unsigned long flags;
-       u32 value;
-       int err = 0, i;
-
-       /* Skip if it's not USBHS */
-       if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
-               return 0;
-
-       spin_lock_irqsave(&drv->lock, flags);
-
-       /* Power on USBHS PHY */
-       value = readl(base + USBHS_UGCTRL);
-       value &= ~USBHS_UGCTRL_PLLRESET;
-       writel(value, base + USBHS_UGCTRL);
-
-       value = readw(base + USBHS_LPSTS);
-       value |= USBHS_LPSTS_SUSPM;
-       writew(value, base + USBHS_LPSTS);
-
-       for (i = 0; i < 20; i++) {
-               value = readl(base + USBHS_UGSTS);
-               if ((value & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) {
-                       value = readl(base + USBHS_UGCTRL);
-                       value |= USBHS_UGCTRL_CONNECT;
-                       writel(value, base + USBHS_UGCTRL);
-                       goto out;
-               }
-               udelay(1);
-       }
-
-       /* Timed out waiting for the PLL lock */
-       err = -ETIMEDOUT;
-
-out:
-       spin_unlock_irqrestore(&drv->lock, flags);
-
-       return err;
-}
-
-static int rcar_gen2_phy_power_off(struct phy *p)
-{
-       struct rcar_gen2_phy *phy = phy_get_drvdata(p);
-       struct rcar_gen2_phy_driver *drv = phy->channel->drv;
-       void __iomem *base = drv->base;
-       unsigned long flags;
-       u32 value;
-
-       /* Skip if it's not USBHS */
-       if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
-               return 0;
-
-       spin_lock_irqsave(&drv->lock, flags);
-
-       /* Power off USBHS PHY */
-       value = readl(base + USBHS_UGCTRL);
-       value &= ~USBHS_UGCTRL_CONNECT;
-       writel(value, base + USBHS_UGCTRL);
-
-       value = readw(base + USBHS_LPSTS);
-       value &= ~USBHS_LPSTS_SUSPM;
-       writew(value, base + USBHS_LPSTS);
-
-       value = readl(base + USBHS_UGCTRL);
-       value |= USBHS_UGCTRL_PLLRESET;
-       writel(value, base + USBHS_UGCTRL);
-
-       spin_unlock_irqrestore(&drv->lock, flags);
-
-       return 0;
-}
-
-static const struct phy_ops rcar_gen2_phy_ops = {
-       .init           = rcar_gen2_phy_init,
-       .exit           = rcar_gen2_phy_exit,
-       .power_on       = rcar_gen2_phy_power_on,
-       .power_off      = rcar_gen2_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static const struct of_device_id rcar_gen2_phy_match_table[] = {
-       { .compatible = "renesas,usb-phy-r8a7790" },
-       { .compatible = "renesas,usb-phy-r8a7791" },
-       { .compatible = "renesas,usb-phy-r8a7794" },
-       { .compatible = "renesas,rcar-gen2-usb-phy" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table);
-
-static struct phy *rcar_gen2_phy_xlate(struct device *dev,
-                                      struct of_phandle_args *args)
-{
-       struct rcar_gen2_phy_driver *drv;
-       struct device_node *np = args->np;
-       int i;
-
-       drv = dev_get_drvdata(dev);
-       if (!drv)
-               return ERR_PTR(-EINVAL);
-
-       for (i = 0; i < drv->num_channels; i++) {
-               if (np == drv->channels[i].of_node)
-                       break;
-       }
-
-       if (i >= drv->num_channels || args->args[0] >= 2)
-               return ERR_PTR(-ENODEV);
-
-       return drv->channels[i].phys[args->args[0]].phy;
-}
-
-static const u32 select_mask[] = {
-       [0]     = USBHS_UGCTRL2_USB0SEL,
-       [2]     = USBHS_UGCTRL2_USB2SEL,
-};
-
-static const u32 select_value[][PHYS_PER_CHANNEL] = {
-       [0]     = { USBHS_UGCTRL2_USB0SEL_PCI, USBHS_UGCTRL2_USB0SEL_HS_USB },
-       [2]     = { USBHS_UGCTRL2_USB2SEL_PCI, USBHS_UGCTRL2_USB2SEL_USB30 },
-};
-
-static int rcar_gen2_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct rcar_gen2_phy_driver *drv;
-       struct phy_provider *provider;
-       struct device_node *np;
-       struct resource *res;
-       void __iomem *base;
-       struct clk *clk;
-       int i = 0;
-
-       if (!dev->of_node) {
-               dev_err(dev,
-                       "This driver is required to be instantiated from device tree\n");
-               return -EINVAL;
-       }
-
-       clk = devm_clk_get(dev, "usbhs");
-       if (IS_ERR(clk)) {
-               dev_err(dev, "Can't get USBHS clock\n");
-               return PTR_ERR(clk);
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
-       if (!drv)
-               return -ENOMEM;
-
-       spin_lock_init(&drv->lock);
-
-       drv->clk = clk;
-       drv->base = base;
-
-       drv->num_channels = of_get_child_count(dev->of_node);
-       drv->channels = devm_kcalloc(dev, drv->num_channels,
-                                    sizeof(struct rcar_gen2_channel),
-                                    GFP_KERNEL);
-       if (!drv->channels)
-               return -ENOMEM;
-
-       for_each_child_of_node(dev->of_node, np) {
-               struct rcar_gen2_channel *channel = drv->channels + i;
-               u32 channel_num;
-               int error, n;
-
-               channel->of_node = np;
-               channel->drv = drv;
-               channel->selected_phy = -1;
-
-               error = of_property_read_u32(np, "reg", &channel_num);
-               if (error || channel_num > 2) {
-                       dev_err(dev, "Invalid \"reg\" property\n");
-                       return error;
-               }
-               channel->select_mask = select_mask[channel_num];
-
-               for (n = 0; n < PHYS_PER_CHANNEL; n++) {
-                       struct rcar_gen2_phy *phy = &channel->phys[n];
-
-                       phy->channel = channel;
-                       phy->number = n;
-                       phy->select_value = select_value[channel_num][n];
-
-                       phy->phy = devm_phy_create(dev, NULL,
-                                                  &rcar_gen2_phy_ops);
-                       if (IS_ERR(phy->phy)) {
-                               dev_err(dev, "Failed to create PHY\n");
-                               return PTR_ERR(phy->phy);
-                       }
-                       phy_set_drvdata(phy->phy, phy);
-               }
-
-               i++;
-       }
-
-       provider = devm_of_phy_provider_register(dev, rcar_gen2_phy_xlate);
-       if (IS_ERR(provider)) {
-               dev_err(dev, "Failed to register PHY provider\n");
-               return PTR_ERR(provider);
-       }
-
-       dev_set_drvdata(dev, drv);
-
-       return 0;
-}
-
-static struct platform_driver rcar_gen2_phy_driver = {
-       .driver = {
-               .name           = "phy_rcar_gen2",
-               .of_match_table = rcar_gen2_phy_match_table,
-       },
-       .probe  = rcar_gen2_phy_probe,
-};
-
-module_platform_driver(rcar_gen2_phy_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");
-MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");
diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/phy-rcar-gen3-usb2.c
deleted file mode 100644 (file)
index 54c3429..0000000
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * Renesas R-Car Gen3 for USB2.0 PHY driver
- *
- * Copyright (C) 2015 Renesas Electronics Corporation
- *
- * This is based on the phy-rcar-gen2 driver:
- * Copyright (C) 2014 Renesas Solutions Corp.
- * Copyright (C) 2014 Cogent Embedded, Inc.
- *
- * 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/extcon.h>
-#include <linux/interrupt.h>
-#include <linux/io.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/pm_runtime.h>
-#include <linux/regulator/consumer.h>
-#include <linux/workqueue.h>
-
-/******* USB2.0 Host registers (original offset is +0x200) *******/
-#define USB2_INT_ENABLE                0x000
-#define USB2_USBCTR            0x00c
-#define USB2_SPD_RSM_TIMSET    0x10c
-#define USB2_OC_TIMSET         0x110
-#define USB2_COMMCTRL          0x600
-#define USB2_OBINTSTA          0x604
-#define USB2_OBINTEN           0x608
-#define USB2_VBCTRL            0x60c
-#define USB2_LINECTRL1         0x610
-#define USB2_ADPCTRL           0x630
-
-/* INT_ENABLE */
-#define USB2_INT_ENABLE_UCOM_INTEN     BIT(3)
-#define USB2_INT_ENABLE_USBH_INTB_EN   BIT(2)
-#define USB2_INT_ENABLE_USBH_INTA_EN   BIT(1)
-#define USB2_INT_ENABLE_INIT           (USB2_INT_ENABLE_UCOM_INTEN | \
-                                        USB2_INT_ENABLE_USBH_INTB_EN | \
-                                        USB2_INT_ENABLE_USBH_INTA_EN)
-
-/* USBCTR */
-#define USB2_USBCTR_DIRPD      BIT(2)
-#define USB2_USBCTR_PLL_RST    BIT(1)
-
-/* SPD_RSM_TIMSET */
-#define USB2_SPD_RSM_TIMSET_INIT       0x014e029b
-
-/* OC_TIMSET */
-#define USB2_OC_TIMSET_INIT            0x000209ab
-
-/* COMMCTRL */
-#define USB2_COMMCTRL_OTG_PERI         BIT(31) /* 1 = Peripheral mode */
-
-/* OBINTSTA and OBINTEN */
-#define USB2_OBINT_SESSVLDCHG          BIT(12)
-#define USB2_OBINT_IDDIGCHG            BIT(11)
-#define USB2_OBINT_BITS                        (USB2_OBINT_SESSVLDCHG | \
-                                        USB2_OBINT_IDDIGCHG)
-
-/* VBCTRL */
-#define USB2_VBCTRL_DRVVBUSSEL         BIT(8)
-
-/* LINECTRL1 */
-#define USB2_LINECTRL1_DPRPD_EN                BIT(19)
-#define USB2_LINECTRL1_DP_RPD          BIT(18)
-#define USB2_LINECTRL1_DMRPD_EN                BIT(17)
-#define USB2_LINECTRL1_DM_RPD          BIT(16)
-#define USB2_LINECTRL1_OPMODE_NODRV    BIT(6)
-
-/* ADPCTRL */
-#define USB2_ADPCTRL_OTGSESSVLD                BIT(20)
-#define USB2_ADPCTRL_IDDIG             BIT(19)
-#define USB2_ADPCTRL_IDPULLUP          BIT(5)  /* 1 = ID sampling is enabled */
-#define USB2_ADPCTRL_DRVVBUS           BIT(4)
-
-struct rcar_gen3_chan {
-       void __iomem *base;
-       struct extcon_dev *extcon;
-       struct phy *phy;
-       struct regulator *vbus;
-       struct work_struct work;
-       bool extcon_host;
-       bool has_otg;
-};
-
-static void rcar_gen3_phy_usb2_work(struct work_struct *work)
-{
-       struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan,
-                                                work);
-
-       if (ch->extcon_host) {
-               extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, true);
-               extcon_set_state_sync(ch->extcon, EXTCON_USB, false);
-       } else {
-               extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, false);
-               extcon_set_state_sync(ch->extcon, EXTCON_USB, true);
-       }
-}
-
-static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host)
-{
-       void __iomem *usb2_base = ch->base;
-       u32 val = readl(usb2_base + USB2_COMMCTRL);
-
-       dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, host);
-       if (host)
-               val &= ~USB2_COMMCTRL_OTG_PERI;
-       else
-               val |= USB2_COMMCTRL_OTG_PERI;
-       writel(val, usb2_base + USB2_COMMCTRL);
-}
-
-static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
-{
-       void __iomem *usb2_base = ch->base;
-       u32 val = readl(usb2_base + USB2_LINECTRL1);
-
-       dev_vdbg(&ch->phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm);
-       val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
-       if (dp)
-               val |= USB2_LINECTRL1_DP_RPD;
-       if (dm)
-               val |= USB2_LINECTRL1_DM_RPD;
-       writel(val, usb2_base + USB2_LINECTRL1);
-}
-
-static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
-{
-       void __iomem *usb2_base = ch->base;
-       u32 val = readl(usb2_base + USB2_ADPCTRL);
-
-       dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, vbus);
-       if (vbus)
-               val |= USB2_ADPCTRL_DRVVBUS;
-       else
-               val &= ~USB2_ADPCTRL_DRVVBUS;
-       writel(val, usb2_base + USB2_ADPCTRL);
-}
-
-static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch)
-{
-       rcar_gen3_set_linectrl(ch, 1, 1);
-       rcar_gen3_set_host_mode(ch, 1);
-       rcar_gen3_enable_vbus_ctrl(ch, 1);
-
-       ch->extcon_host = true;
-       schedule_work(&ch->work);
-}
-
-static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch)
-{
-       rcar_gen3_set_linectrl(ch, 0, 1);
-       rcar_gen3_set_host_mode(ch, 0);
-       rcar_gen3_enable_vbus_ctrl(ch, 0);
-
-       ch->extcon_host = false;
-       schedule_work(&ch->work);
-}
-
-static void rcar_gen3_init_for_b_host(struct rcar_gen3_chan *ch)
-{
-       void __iomem *usb2_base = ch->base;
-       u32 val;
-
-       val = readl(usb2_base + USB2_LINECTRL1);
-       writel(val | USB2_LINECTRL1_OPMODE_NODRV, usb2_base + USB2_LINECTRL1);
-
-       rcar_gen3_set_linectrl(ch, 1, 1);
-       rcar_gen3_set_host_mode(ch, 1);
-       rcar_gen3_enable_vbus_ctrl(ch, 0);
-
-       val = readl(usb2_base + USB2_LINECTRL1);
-       writel(val & ~USB2_LINECTRL1_OPMODE_NODRV, usb2_base + USB2_LINECTRL1);
-}
-
-static void rcar_gen3_init_for_a_peri(struct rcar_gen3_chan *ch)
-{
-       rcar_gen3_set_linectrl(ch, 0, 1);
-       rcar_gen3_set_host_mode(ch, 0);
-       rcar_gen3_enable_vbus_ctrl(ch, 1);
-}
-
-static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch)
-{
-       void __iomem *usb2_base = ch->base;
-       u32 val;
-
-       val = readl(usb2_base + USB2_OBINTEN);
-       writel(val & ~USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
-
-       rcar_gen3_enable_vbus_ctrl(ch, 0);
-       rcar_gen3_init_for_host(ch);
-
-       writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
-}
-
-static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
-{
-       return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
-}
-
-static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch)
-{
-       if (!rcar_gen3_check_id(ch))
-               rcar_gen3_init_for_host(ch);
-       else
-               rcar_gen3_init_for_peri(ch);
-}
-
-static bool rcar_gen3_is_host(struct rcar_gen3_chan *ch)
-{
-       return !(readl(ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI);
-}
-
-static ssize_t role_store(struct device *dev, struct device_attribute *attr,
-                         const char *buf, size_t count)
-{
-       struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
-       bool is_b_device, is_host, new_mode_is_host;
-
-       if (!ch->has_otg || !ch->phy->init_count)
-               return -EIO;
-
-       /*
-        * is_b_device: true is B-Device. false is A-Device.
-        * If {new_mode_}is_host: true is Host mode. false is Peripheral mode.
-        */
-       is_b_device = rcar_gen3_check_id(ch);
-       is_host = rcar_gen3_is_host(ch);
-       if (!strncmp(buf, "host", strlen("host")))
-               new_mode_is_host = true;
-       else if (!strncmp(buf, "peripheral", strlen("peripheral")))
-               new_mode_is_host = false;
-       else
-               return -EINVAL;
-
-       /* If current and new mode is the same, this returns the error */
-       if (is_host == new_mode_is_host)
-               return -EINVAL;
-
-       if (new_mode_is_host) {         /* And is_host must be false */
-               if (!is_b_device)       /* A-Peripheral */
-                       rcar_gen3_init_from_a_peri_to_a_host(ch);
-               else                    /* B-Peripheral */
-                       rcar_gen3_init_for_b_host(ch);
-       } else {                        /* And is_host must be true */
-               if (!is_b_device)       /* A-Host */
-                       rcar_gen3_init_for_a_peri(ch);
-               else                    /* B-Host */
-                       rcar_gen3_init_for_peri(ch);
-       }
-
-       return count;
-}
-
-static ssize_t role_show(struct device *dev, struct device_attribute *attr,
-                        char *buf)
-{
-       struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
-
-       if (!ch->has_otg || !ch->phy->init_count)
-               return -EIO;
-
-       return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" :
-                                                           "peripheral");
-}
-static DEVICE_ATTR_RW(role);
-
-static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
-{
-       void __iomem *usb2_base = ch->base;
-       u32 val;
-
-       val = readl(usb2_base + USB2_VBCTRL);
-       writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
-       writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
-       val = readl(usb2_base + USB2_OBINTEN);
-       writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
-       val = readl(usb2_base + USB2_ADPCTRL);
-       writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
-       val = readl(usb2_base + USB2_LINECTRL1);
-       rcar_gen3_set_linectrl(ch, 0, 0);
-       writel(val | USB2_LINECTRL1_DPRPD_EN | USB2_LINECTRL1_DMRPD_EN,
-              usb2_base + USB2_LINECTRL1);
-
-       rcar_gen3_device_recognition(ch);
-}
-
-static int rcar_gen3_phy_usb2_init(struct phy *p)
-{
-       struct rcar_gen3_chan *channel = phy_get_drvdata(p);
-       void __iomem *usb2_base = channel->base;
-
-       /* Initialize USB2 part */
-       writel(USB2_INT_ENABLE_INIT, usb2_base + USB2_INT_ENABLE);
-       writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET);
-       writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET);
-
-       /* Initialize otg part */
-       if (channel->has_otg)
-               rcar_gen3_init_otg(channel);
-
-       return 0;
-}
-
-static int rcar_gen3_phy_usb2_exit(struct phy *p)
-{
-       struct rcar_gen3_chan *channel = phy_get_drvdata(p);
-
-       writel(0, channel->base + USB2_INT_ENABLE);
-
-       return 0;
-}
-
-static int rcar_gen3_phy_usb2_power_on(struct phy *p)
-{
-       struct rcar_gen3_chan *channel = phy_get_drvdata(p);
-       void __iomem *usb2_base = channel->base;
-       u32 val;
-       int ret;
-
-       if (channel->vbus) {
-               ret = regulator_enable(channel->vbus);
-               if (ret)
-                       return ret;
-       }
-
-       val = readl(usb2_base + USB2_USBCTR);
-       val |= USB2_USBCTR_PLL_RST;
-       writel(val, usb2_base + USB2_USBCTR);
-       val &= ~USB2_USBCTR_PLL_RST;
-       writel(val, usb2_base + USB2_USBCTR);
-
-       return 0;
-}
-
-static int rcar_gen3_phy_usb2_power_off(struct phy *p)
-{
-       struct rcar_gen3_chan *channel = phy_get_drvdata(p);
-       int ret = 0;
-
-       if (channel->vbus)
-               ret = regulator_disable(channel->vbus);
-
-       return ret;
-}
-
-static const struct phy_ops rcar_gen3_phy_usb2_ops = {
-       .init           = rcar_gen3_phy_usb2_init,
-       .exit           = rcar_gen3_phy_usb2_exit,
-       .power_on       = rcar_gen3_phy_usb2_power_on,
-       .power_off      = rcar_gen3_phy_usb2_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
-{
-       struct rcar_gen3_chan *ch = _ch;
-       void __iomem *usb2_base = ch->base;
-       u32 status = readl(usb2_base + USB2_OBINTSTA);
-       irqreturn_t ret = IRQ_NONE;
-
-       if (status & USB2_OBINT_BITS) {
-               dev_vdbg(&ch->phy->dev, "%s: %08x\n", __func__, status);
-               writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
-               rcar_gen3_device_recognition(ch);
-               ret = IRQ_HANDLED;
-       }
-
-       return ret;
-}
-
-static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
-       { .compatible = "renesas,usb2-phy-r8a7795" },
-       { .compatible = "renesas,usb2-phy-r8a7796" },
-       { .compatible = "renesas,rcar-gen3-usb2-phy" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb2_match_table);
-
-static const unsigned int rcar_gen3_phy_cable[] = {
-       EXTCON_USB,
-       EXTCON_USB_HOST,
-       EXTCON_NONE,
-};
-
-static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct rcar_gen3_chan *channel;
-       struct phy_provider *provider;
-       struct resource *res;
-       int irq, ret = 0;
-
-       if (!dev->of_node) {
-               dev_err(dev, "This driver needs device tree\n");
-               return -EINVAL;
-       }
-
-       channel = devm_kzalloc(dev, sizeof(*channel), GFP_KERNEL);
-       if (!channel)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       channel->base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(channel->base))
-               return PTR_ERR(channel->base);
-
-       /* call request_irq for OTG */
-       irq = platform_get_irq(pdev, 0);
-       if (irq >= 0) {
-               int ret;
-
-               INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
-               irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
-                                      IRQF_SHARED, dev_name(dev), channel);
-               if (irq < 0)
-                       dev_err(dev, "No irq handler (%d)\n", irq);
-               channel->has_otg = true;
-               channel->extcon = devm_extcon_dev_allocate(dev,
-                                                       rcar_gen3_phy_cable);
-               if (IS_ERR(channel->extcon))
-                       return PTR_ERR(channel->extcon);
-
-               ret = devm_extcon_dev_register(dev, channel->extcon);
-               if (ret < 0) {
-                       dev_err(dev, "Failed to register extcon\n");
-                       return ret;
-               }
-       }
-
-       /*
-        * 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);
-       channel->phy = devm_phy_create(dev, NULL, &rcar_gen3_phy_usb2_ops);
-       if (IS_ERR(channel->phy)) {
-               dev_err(dev, "Failed to create USB2 PHY\n");
-               ret = PTR_ERR(channel->phy);
-               goto error;
-       }
-
-       channel->vbus = devm_regulator_get_optional(dev, "vbus");
-       if (IS_ERR(channel->vbus)) {
-               if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) {
-                       ret = PTR_ERR(channel->vbus);
-                       goto error;
-               }
-               channel->vbus = NULL;
-       }
-
-       platform_set_drvdata(pdev, channel);
-       phy_set_drvdata(channel->phy, channel);
-
-       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;
-       } else if (channel->has_otg) {
-               int ret;
-
-               ret = device_create_file(dev, &dev_attr_role);
-               if (ret < 0)
-                       goto error;
-       }
-
-       return 0;
-
-error:
-       pm_runtime_disable(dev);
-
-       return ret;
-}
-
-static int rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
-{
-       struct rcar_gen3_chan *channel = platform_get_drvdata(pdev);
-
-       if (channel->has_otg)
-               device_remove_file(&pdev->dev, &dev_attr_role);
-
-       pm_runtime_disable(&pdev->dev);
-
-       return 0;
-};
-
-static struct platform_driver rcar_gen3_phy_usb2_driver = {
-       .driver = {
-               .name           = "phy_rcar_gen3_usb2",
-               .of_match_table = rcar_gen3_phy_usb2_match_table,
-       },
-       .probe  = rcar_gen3_phy_usb2_probe,
-       .remove = rcar_gen3_phy_usb2_remove,
-};
-module_platform_driver(rcar_gen3_phy_usb2_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 2.0 PHY");
-MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");
diff --git a/drivers/phy/phy-rockchip-dp.c b/drivers/phy/phy-rockchip-dp.c
deleted file mode 100644 (file)
index 8b267a7..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Rockchip DP PHY driver
- *
- * Copyright (C) 2016 FuZhou Rockchip Co., Ltd.
- * Author: Yakir Yang <ykk@@rock-chips.com>
- *
- * 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; either version 2 of the License.
- */
-
-#include <linux/clk.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#define GRF_SOC_CON12                           0x0274
-
-#define GRF_EDP_REF_CLK_SEL_INTER_HIWORD_MASK   BIT(20)
-#define GRF_EDP_REF_CLK_SEL_INTER               BIT(4)
-
-#define GRF_EDP_PHY_SIDDQ_HIWORD_MASK           BIT(21)
-#define GRF_EDP_PHY_SIDDQ_ON                    0
-#define GRF_EDP_PHY_SIDDQ_OFF                   BIT(5)
-
-struct rockchip_dp_phy {
-       struct device  *dev;
-       struct regmap  *grf;
-       struct clk     *phy_24m;
-};
-
-static int rockchip_set_phy_state(struct phy *phy, bool enable)
-{
-       struct rockchip_dp_phy *dp = phy_get_drvdata(phy);
-       int ret;
-
-       if (enable) {
-               ret = regmap_write(dp->grf, GRF_SOC_CON12,
-                                  GRF_EDP_PHY_SIDDQ_HIWORD_MASK |
-                                  GRF_EDP_PHY_SIDDQ_ON);
-               if (ret < 0) {
-                       dev_err(dp->dev, "Can't enable PHY power %d\n", ret);
-                       return ret;
-               }
-
-               ret = clk_prepare_enable(dp->phy_24m);
-       } else {
-               clk_disable_unprepare(dp->phy_24m);
-
-               ret = regmap_write(dp->grf, GRF_SOC_CON12,
-                                  GRF_EDP_PHY_SIDDQ_HIWORD_MASK |
-                                  GRF_EDP_PHY_SIDDQ_OFF);
-       }
-
-       return ret;
-}
-
-static int rockchip_dp_phy_power_on(struct phy *phy)
-{
-       return rockchip_set_phy_state(phy, true);
-}
-
-static int rockchip_dp_phy_power_off(struct phy *phy)
-{
-       return rockchip_set_phy_state(phy, false);
-}
-
-static const struct phy_ops rockchip_dp_phy_ops = {
-       .power_on       = rockchip_dp_phy_power_on,
-       .power_off      = rockchip_dp_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static int rockchip_dp_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct phy_provider *phy_provider;
-       struct rockchip_dp_phy *dp;
-       struct phy *phy;
-       int ret;
-
-       if (!np)
-               return -ENODEV;
-
-       if (!dev->parent || !dev->parent->of_node)
-               return -ENODEV;
-
-       dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
-       if (!dp)
-               return -ENOMEM;
-
-       dp->dev = dev;
-
-       dp->phy_24m = devm_clk_get(dev, "24m");
-       if (IS_ERR(dp->phy_24m)) {
-               dev_err(dev, "cannot get clock 24m\n");
-               return PTR_ERR(dp->phy_24m);
-       }
-
-       ret = clk_set_rate(dp->phy_24m, 24000000);
-       if (ret < 0) {
-               dev_err(dp->dev, "cannot set clock phy_24m %d\n", ret);
-               return ret;
-       }
-
-       dp->grf = syscon_node_to_regmap(dev->parent->of_node);
-       if (IS_ERR(dp->grf)) {
-               dev_err(dev, "rk3288-dp needs the General Register Files syscon\n");
-               return PTR_ERR(dp->grf);
-       }
-
-       ret = regmap_write(dp->grf, GRF_SOC_CON12, GRF_EDP_REF_CLK_SEL_INTER |
-                          GRF_EDP_REF_CLK_SEL_INTER_HIWORD_MASK);
-       if (ret != 0) {
-               dev_err(dp->dev, "Could not config GRF edp ref clk: %d\n", ret);
-               return ret;
-       }
-
-       phy = devm_phy_create(dev, np, &rockchip_dp_phy_ops);
-       if (IS_ERR(phy)) {
-               dev_err(dev, "failed to create phy\n");
-               return PTR_ERR(phy);
-       }
-       phy_set_drvdata(phy, dp);
-
-       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 rockchip_dp_phy_dt_ids[] = {
-       { .compatible = "rockchip,rk3288-dp-phy" },
-       {}
-};
-
-MODULE_DEVICE_TABLE(of, rockchip_dp_phy_dt_ids);
-
-static struct platform_driver rockchip_dp_phy_driver = {
-       .probe          = rockchip_dp_phy_probe,
-       .driver         = {
-               .name   = "rockchip-dp-phy",
-               .of_match_table = rockchip_dp_phy_dt_ids,
-       },
-};
-
-module_platform_driver(rockchip_dp_phy_driver);
-
-MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
-MODULE_DESCRIPTION("Rockchip DP PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c
deleted file mode 100644 (file)
index f1b24f1..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Rockchip emmc PHY driver
- *
- * Copyright (C) 2016 Shawn Lin <shawn.lin@rock-chips.com>
- * Copyright (C) 2016 ROCKCHIP, 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; either version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.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>
-
-/*
- * The higher 16-bit of this register is used for write protection
- * only if BIT(x + 16) set to 1 the BIT(x) can be written.
- */
-#define HIWORD_UPDATE(val, mask, shift) \
-               ((val) << (shift) | (mask) << ((shift) + 16))
-
-/* Register definition */
-#define GRF_EMMCPHY_CON0               0x0
-#define GRF_EMMCPHY_CON1               0x4
-#define GRF_EMMCPHY_CON2               0x8
-#define GRF_EMMCPHY_CON3               0xc
-#define GRF_EMMCPHY_CON4               0x10
-#define GRF_EMMCPHY_CON5               0x14
-#define GRF_EMMCPHY_CON6               0x18
-#define GRF_EMMCPHY_STATUS             0x20
-
-#define PHYCTRL_PDB_MASK               0x1
-#define PHYCTRL_PDB_SHIFT              0x0
-#define PHYCTRL_PDB_PWR_ON             0x1
-#define PHYCTRL_PDB_PWR_OFF            0x0
-#define PHYCTRL_ENDLL_MASK             0x1
-#define PHYCTRL_ENDLL_SHIFT            0x1
-#define PHYCTRL_ENDLL_ENABLE           0x1
-#define PHYCTRL_ENDLL_DISABLE          0x0
-#define PHYCTRL_CALDONE_MASK           0x1
-#define PHYCTRL_CALDONE_SHIFT          0x6
-#define PHYCTRL_CALDONE_DONE           0x1
-#define PHYCTRL_CALDONE_GOING          0x0
-#define PHYCTRL_DLLRDY_MASK            0x1
-#define PHYCTRL_DLLRDY_SHIFT           0x5
-#define PHYCTRL_DLLRDY_DONE            0x1
-#define PHYCTRL_DLLRDY_GOING           0x0
-#define PHYCTRL_FREQSEL_200M           0x0
-#define PHYCTRL_FREQSEL_50M            0x1
-#define PHYCTRL_FREQSEL_100M           0x2
-#define PHYCTRL_FREQSEL_150M           0x3
-#define PHYCTRL_FREQSEL_MASK           0x3
-#define PHYCTRL_FREQSEL_SHIFT          0xc
-#define PHYCTRL_DR_MASK                        0x7
-#define PHYCTRL_DR_SHIFT               0x4
-#define PHYCTRL_DR_50OHM               0x0
-#define PHYCTRL_DR_33OHM               0x1
-#define PHYCTRL_DR_66OHM               0x2
-#define PHYCTRL_DR_100OHM              0x3
-#define PHYCTRL_DR_40OHM               0x4
-#define PHYCTRL_OTAPDLYENA             0x1
-#define PHYCTRL_OTAPDLYENA_MASK                0x1
-#define PHYCTRL_OTAPDLYENA_SHIFT       0xb
-#define PHYCTRL_OTAPDLYSEL_MASK                0xf
-#define PHYCTRL_OTAPDLYSEL_SHIFT       0x7
-
-struct rockchip_emmc_phy {
-       unsigned int    reg_offset;
-       struct regmap   *reg_base;
-       struct clk      *emmcclk;
-};
-
-static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
-{
-       struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
-       unsigned int caldone;
-       unsigned int dllrdy;
-       unsigned int freqsel = PHYCTRL_FREQSEL_200M;
-       unsigned long rate;
-       unsigned long timeout;
-
-       /*
-        * Keep phyctrl_pdb and phyctrl_endll low to allow
-        * initialization of CALIO state M/C DFFs
-        */
-       regmap_write(rk_phy->reg_base,
-                    rk_phy->reg_offset + GRF_EMMCPHY_CON6,
-                    HIWORD_UPDATE(PHYCTRL_PDB_PWR_OFF,
-                                  PHYCTRL_PDB_MASK,
-                                  PHYCTRL_PDB_SHIFT));
-       regmap_write(rk_phy->reg_base,
-                    rk_phy->reg_offset + GRF_EMMCPHY_CON6,
-                    HIWORD_UPDATE(PHYCTRL_ENDLL_DISABLE,
-                                  PHYCTRL_ENDLL_MASK,
-                                  PHYCTRL_ENDLL_SHIFT));
-
-       /* Already finish power_off above */
-       if (on_off == PHYCTRL_PDB_PWR_OFF)
-               return 0;
-
-       rate = clk_get_rate(rk_phy->emmcclk);
-
-       if (rate != 0) {
-               unsigned long ideal_rate;
-               unsigned long diff;
-
-               switch (rate) {
-               case 1 ... 74999999:
-                       ideal_rate = 50000000;
-                       freqsel = PHYCTRL_FREQSEL_50M;
-                       break;
-               case 75000000 ... 124999999:
-                       ideal_rate = 100000000;
-                       freqsel = PHYCTRL_FREQSEL_100M;
-                       break;
-               case 125000000 ... 174999999:
-                       ideal_rate = 150000000;
-                       freqsel = PHYCTRL_FREQSEL_150M;
-                       break;
-               default:
-                       ideal_rate = 200000000;
-                       break;
-               }
-
-               diff = (rate > ideal_rate) ?
-                       rate - ideal_rate : ideal_rate - rate;
-
-               /*
-                * In order for tuning delays to be accurate we need to be
-                * pretty spot on for the DLL range, so warn if we're too
-                * far off.  Also warn if we're above the 200 MHz max.  Don't
-                * warn for really slow rates since we won't be tuning then.
-                */
-               if ((rate > 50000000 && diff > 15000000) || (rate > 200000000))
-                       dev_warn(&phy->dev, "Unsupported rate: %lu\n", rate);
-       }
-
-       /*
-        * According to the user manual, calpad calibration
-        * cycle takes more than 2us without the minimal recommended
-        * value, so we may need a little margin here
-        */
-       udelay(3);
-       regmap_write(rk_phy->reg_base,
-                    rk_phy->reg_offset + GRF_EMMCPHY_CON6,
-                    HIWORD_UPDATE(PHYCTRL_PDB_PWR_ON,
-                                  PHYCTRL_PDB_MASK,
-                                  PHYCTRL_PDB_SHIFT));
-
-       /*
-        * According to the user manual, it asks driver to
-        * wait 5us for calpad busy trimming
-        */
-       udelay(5);
-       regmap_read(rk_phy->reg_base,
-                   rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
-                   &caldone);
-       caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK;
-       if (caldone != PHYCTRL_CALDONE_DONE) {
-               pr_err("rockchip_emmc_phy_power: caldone timeout.\n");
-               return -ETIMEDOUT;
-       }
-
-       /* Set the frequency of the DLL operation */
-       regmap_write(rk_phy->reg_base,
-                    rk_phy->reg_offset + GRF_EMMCPHY_CON0,
-                    HIWORD_UPDATE(freqsel, PHYCTRL_FREQSEL_MASK,
-                                  PHYCTRL_FREQSEL_SHIFT));
-
-       /* Turn on the DLL */
-       regmap_write(rk_phy->reg_base,
-                    rk_phy->reg_offset + GRF_EMMCPHY_CON6,
-                    HIWORD_UPDATE(PHYCTRL_ENDLL_ENABLE,
-                                  PHYCTRL_ENDLL_MASK,
-                                  PHYCTRL_ENDLL_SHIFT));
-
-       /*
-        * We turned on the DLL even though the rate was 0 because we the
-        * clock might be turned on later.  ...but we can't wait for the DLL
-        * to lock when the rate is 0 because it will never lock with no
-        * input clock.
-        *
-        * Technically we should be checking the lock later when the clock
-        * is turned on, but for now we won't.
-        */
-       if (rate == 0)
-               return 0;
-
-       /*
-        * After enabling analog DLL circuits docs say that we need 10.2 us if
-        * our source clock is at 50 MHz and that lock time scales linearly
-        * with clock speed.  If we are powering on the PHY and the card clock
-        * is super slow (like 100 kHZ) this could take as long as 5.1 ms as
-        * per the math: 10.2 us * (50000000 Hz / 100000 Hz) => 5.1 ms
-        * Hopefully we won't be running at 100 kHz, but we should still make
-        * sure we wait long enough.
-        *
-        * NOTE: There appear to be corner cases where the DLL seems to take
-        * extra long to lock for reasons that aren't understood.  In some
-        * extreme cases we've seen it take up to over 10ms (!).  We'll be
-        * generous and give it 50ms.  We still busy wait here because:
-        * - In most cases it should be super fast.
-        * - This is not called lots during normal operation so it shouldn't
-        *   be a power or performance problem to busy wait.  We expect it
-        *   only at boot / resume.  In both cases, eMMC is probably on the
-        *   critical path so busy waiting a little extra time should be OK.
-        */
-       timeout = jiffies + msecs_to_jiffies(50);
-       do {
-               udelay(1);
-
-               regmap_read(rk_phy->reg_base,
-                       rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
-                       &dllrdy);
-               dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK;
-               if (dllrdy == PHYCTRL_DLLRDY_DONE)
-                       break;
-       } while (!time_after(jiffies, timeout));
-
-       if (dllrdy != PHYCTRL_DLLRDY_DONE) {
-               pr_err("rockchip_emmc_phy_power: dllrdy timeout.\n");
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static int rockchip_emmc_phy_init(struct phy *phy)
-{
-       struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
-       int ret = 0;
-
-       /*
-        * We purposely get the clock here and not in probe to avoid the
-        * circular dependency problem.  We expect:
-        * - PHY driver to probe
-        * - SDHCI driver to start probe
-        * - SDHCI driver to register it's clock
-        * - SDHCI driver to get the PHY
-        * - SDHCI driver to init the PHY
-        *
-        * The clock is optional, so upon any error we just set to NULL.
-        *
-        * NOTE: we don't do anything special for EPROBE_DEFER here.  Given the
-        * above expected use case, EPROBE_DEFER isn't sensible to expect, so
-        * it's just like any other error.
-        */
-       rk_phy->emmcclk = clk_get(&phy->dev, "emmcclk");
-       if (IS_ERR(rk_phy->emmcclk)) {
-               dev_dbg(&phy->dev, "Error getting emmcclk: %d\n", ret);
-               rk_phy->emmcclk = NULL;
-       }
-
-       return ret;
-}
-
-static int rockchip_emmc_phy_exit(struct phy *phy)
-{
-       struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
-
-       clk_put(rk_phy->emmcclk);
-
-       return 0;
-}
-
-static int rockchip_emmc_phy_power_off(struct phy *phy)
-{
-       /* Power down emmc phy analog blocks */
-       return rockchip_emmc_phy_power(phy, PHYCTRL_PDB_PWR_OFF);
-}
-
-static int rockchip_emmc_phy_power_on(struct phy *phy)
-{
-       struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
-
-       /* Drive impedance: 50 Ohm */
-       regmap_write(rk_phy->reg_base,
-                    rk_phy->reg_offset + GRF_EMMCPHY_CON6,
-                    HIWORD_UPDATE(PHYCTRL_DR_50OHM,
-                                  PHYCTRL_DR_MASK,
-                                  PHYCTRL_DR_SHIFT));
-
-       /* Output tap delay: enable */
-       regmap_write(rk_phy->reg_base,
-                    rk_phy->reg_offset + GRF_EMMCPHY_CON0,
-                    HIWORD_UPDATE(PHYCTRL_OTAPDLYENA,
-                                  PHYCTRL_OTAPDLYENA_MASK,
-                                  PHYCTRL_OTAPDLYENA_SHIFT));
-
-       /* Output tap delay */
-       regmap_write(rk_phy->reg_base,
-                    rk_phy->reg_offset + GRF_EMMCPHY_CON0,
-                    HIWORD_UPDATE(4,
-                                  PHYCTRL_OTAPDLYSEL_MASK,
-                                  PHYCTRL_OTAPDLYSEL_SHIFT));
-
-       /* Power up emmc phy analog blocks */
-       return rockchip_emmc_phy_power(phy, PHYCTRL_PDB_PWR_ON);
-}
-
-static const struct phy_ops ops = {
-       .init           = rockchip_emmc_phy_init,
-       .exit           = rockchip_emmc_phy_exit,
-       .power_on       = rockchip_emmc_phy_power_on,
-       .power_off      = rockchip_emmc_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static int rockchip_emmc_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct rockchip_emmc_phy *rk_phy;
-       struct phy *generic_phy;
-       struct phy_provider *phy_provider;
-       struct regmap *grf;
-       unsigned int reg_offset;
-
-       if (!dev->parent || !dev->parent->of_node)
-               return -ENODEV;
-
-       grf = syscon_node_to_regmap(dev->parent->of_node);
-       if (IS_ERR(grf)) {
-               dev_err(dev, "Missing rockchip,grf property\n");
-               return PTR_ERR(grf);
-       }
-
-       rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
-       if (!rk_phy)
-               return -ENOMEM;
-
-       if (of_property_read_u32(dev->of_node, "reg", &reg_offset)) {
-               dev_err(dev, "missing reg property in node %s\n",
-                       dev->of_node->name);
-               return -EINVAL;
-       }
-
-       rk_phy->reg_offset = reg_offset;
-       rk_phy->reg_base = grf;
-
-       generic_phy = devm_phy_create(dev, dev->of_node, &ops);
-       if (IS_ERR(generic_phy)) {
-               dev_err(dev, "failed to create PHY\n");
-               return PTR_ERR(generic_phy);
-       }
-
-       phy_set_drvdata(generic_phy, rk_phy);
-       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 rockchip_emmc_phy_dt_ids[] = {
-       { .compatible = "rockchip,rk3399-emmc-phy" },
-       {}
-};
-
-MODULE_DEVICE_TABLE(of, rockchip_emmc_phy_dt_ids);
-
-static struct platform_driver rockchip_emmc_driver = {
-       .probe          = rockchip_emmc_phy_probe,
-       .driver         = {
-               .name   = "rockchip-emmc-phy",
-               .of_match_table = rockchip_emmc_phy_dt_ids,
-       },
-};
-
-module_platform_driver(rockchip_emmc_driver);
-
-MODULE_AUTHOR("Shawn Lin <shawn.lin@rock-chips.com>");
-MODULE_DESCRIPTION("Rockchip EMMC PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-rockchip-inno-usb2.c b/drivers/phy/phy-rockchip-inno-usb2.c
deleted file mode 100644 (file)
index 8efe78a..0000000
+++ /dev/null
@@ -1,1284 +0,0 @@
-/*
- * Rockchip USB2.0 PHY with Innosilicon IP block driver
- *
- * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/delay.h>
-#include <linux/extcon.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/gpio/consumer.h>
-#include <linux/jiffies.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/power_supply.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-#include <linux/usb/of.h>
-#include <linux/usb/otg.h>
-
-#define BIT_WRITEABLE_SHIFT    16
-#define SCHEDULE_DELAY         (60 * HZ)
-#define OTG_SCHEDULE_DELAY     (2 * HZ)
-
-enum rockchip_usb2phy_port_id {
-       USB2PHY_PORT_OTG,
-       USB2PHY_PORT_HOST,
-       USB2PHY_NUM_PORTS,
-};
-
-enum rockchip_usb2phy_host_state {
-       PHY_STATE_HS_ONLINE     = 0,
-       PHY_STATE_DISCONNECT    = 1,
-       PHY_STATE_CONNECT       = 2,
-       PHY_STATE_FS_LS_ONLINE  = 4,
-};
-
-/**
- * Different states involved in USB charger detection.
- * USB_CHG_STATE_UNDEFINED     USB charger is not connected or detection
- *                             process is not yet started.
- * USB_CHG_STATE_WAIT_FOR_DCD  Waiting for Data pins contact.
- * USB_CHG_STATE_DCD_DONE      Data pin contact is detected.
- * USB_CHG_STATE_PRIMARY_DONE  Primary detection is completed (Detects
- *                             between SDP and DCP/CDP).
- * USB_CHG_STATE_SECONDARY_DONE        Secondary detection is completed (Detects
- *                             between DCP and CDP).
- * USB_CHG_STATE_DETECTED      USB charger type is determined.
- */
-enum usb_chg_state {
-       USB_CHG_STATE_UNDEFINED = 0,
-       USB_CHG_STATE_WAIT_FOR_DCD,
-       USB_CHG_STATE_DCD_DONE,
-       USB_CHG_STATE_PRIMARY_DONE,
-       USB_CHG_STATE_SECONDARY_DONE,
-       USB_CHG_STATE_DETECTED,
-};
-
-static const unsigned int rockchip_usb2phy_extcon_cable[] = {
-       EXTCON_USB,
-       EXTCON_USB_HOST,
-       EXTCON_CHG_USB_SDP,
-       EXTCON_CHG_USB_CDP,
-       EXTCON_CHG_USB_DCP,
-       EXTCON_CHG_USB_SLOW,
-       EXTCON_NONE,
-};
-
-struct usb2phy_reg {
-       unsigned int    offset;
-       unsigned int    bitend;
-       unsigned int    bitstart;
-       unsigned int    disable;
-       unsigned int    enable;
-};
-
-/**
- * struct rockchip_chg_det_reg: usb charger detect registers
- * @cp_det: charging port detected successfully.
- * @dcp_det: dedicated charging port detected successfully.
- * @dp_det: assert data pin connect successfully.
- * @idm_sink_en: open dm sink curren.
- * @idp_sink_en: open dp sink current.
- * @idp_src_en: open dm source current.
- * @rdm_pdwn_en: open dm pull down resistor.
- * @vdm_src_en: open dm voltage source.
- * @vdp_src_en: open dp voltage source.
- * @opmode: utmi operational mode.
- */
-struct rockchip_chg_det_reg {
-       struct usb2phy_reg      cp_det;
-       struct usb2phy_reg      dcp_det;
-       struct usb2phy_reg      dp_det;
-       struct usb2phy_reg      idm_sink_en;
-       struct usb2phy_reg      idp_sink_en;
-       struct usb2phy_reg      idp_src_en;
-       struct usb2phy_reg      rdm_pdwn_en;
-       struct usb2phy_reg      vdm_src_en;
-       struct usb2phy_reg      vdp_src_en;
-       struct usb2phy_reg      opmode;
-};
-
-/**
- * struct rockchip_usb2phy_port_cfg: usb-phy port configuration.
- * @phy_sus: phy suspend register.
- * @bvalid_det_en: vbus valid rise detection enable register.
- * @bvalid_det_st: vbus valid rise detection status register.
- * @bvalid_det_clr: vbus valid rise detection clear register.
- * @ls_det_en: linestate detection enable register.
- * @ls_det_st: linestate detection state register.
- * @ls_det_clr: linestate detection clear register.
- * @utmi_avalid: utmi vbus avalid status register.
- * @utmi_bvalid: utmi vbus bvalid status register.
- * @utmi_ls: utmi linestate state register.
- * @utmi_hstdet: utmi host disconnect register.
- */
-struct rockchip_usb2phy_port_cfg {
-       struct usb2phy_reg      phy_sus;
-       struct usb2phy_reg      bvalid_det_en;
-       struct usb2phy_reg      bvalid_det_st;
-       struct usb2phy_reg      bvalid_det_clr;
-       struct usb2phy_reg      ls_det_en;
-       struct usb2phy_reg      ls_det_st;
-       struct usb2phy_reg      ls_det_clr;
-       struct usb2phy_reg      utmi_avalid;
-       struct usb2phy_reg      utmi_bvalid;
-       struct usb2phy_reg      utmi_ls;
-       struct usb2phy_reg      utmi_hstdet;
-};
-
-/**
- * struct rockchip_usb2phy_cfg: usb-phy configuration.
- * @reg: the address offset of grf for usb-phy config.
- * @num_ports: specify how many ports that the phy has.
- * @clkout_ctl: keep on/turn off output clk of phy.
- * @chg_det: charger detection registers.
- */
-struct rockchip_usb2phy_cfg {
-       unsigned int    reg;
-       unsigned int    num_ports;
-       struct usb2phy_reg      clkout_ctl;
-       const struct rockchip_usb2phy_port_cfg  port_cfgs[USB2PHY_NUM_PORTS];
-       const struct rockchip_chg_det_reg       chg_det;
-};
-
-/**
- * struct rockchip_usb2phy_port: usb-phy port data.
- * @port_id: flag for otg port or host port.
- * @suspended: phy suspended flag.
- * @utmi_avalid: utmi avalid status usage flag.
- *     true    - use avalid to get vbus status
- *     flase   - use bvalid to get vbus status
- * @vbus_attached: otg device vbus status.
- * @bvalid_irq: IRQ number assigned for vbus valid rise detection.
- * @ls_irq: IRQ number assigned for linestate detection.
- * @mutex: for register updating in sm_work.
- * @chg_work: charge detect work.
- * @otg_sm_work: OTG state machine work.
- * @sm_work: HOST state machine work.
- * @phy_cfg: port register configuration, assigned by driver data.
- * @event_nb: hold event notification callback.
- * @state: define OTG enumeration states before device reset.
- * @mode: the dr_mode of the controller.
- */
-struct rockchip_usb2phy_port {
-       struct phy      *phy;
-       unsigned int    port_id;
-       bool            suspended;
-       bool            utmi_avalid;
-       bool            vbus_attached;
-       int             bvalid_irq;
-       int             ls_irq;
-       struct mutex    mutex;
-       struct          delayed_work chg_work;
-       struct          delayed_work otg_sm_work;
-       struct          delayed_work sm_work;
-       const struct    rockchip_usb2phy_port_cfg *port_cfg;
-       struct notifier_block   event_nb;
-       enum usb_otg_state      state;
-       enum usb_dr_mode        mode;
-};
-
-/**
- * struct rockchip_usb2phy: usb2.0 phy driver data.
- * @grf: General Register Files regmap.
- * @clk: clock struct of phy input clk.
- * @clk480m: clock struct of phy output clk.
- * @clk_hw: clock struct of phy output clk management.
- * @chg_state: states involved in USB charger detection.
- * @chg_type: USB charger types.
- * @dcd_retries: The retry count used to track Data contact
- *              detection process.
- * @edev: extcon device for notification registration
- * @phy_cfg: phy register configuration, assigned by driver data.
- * @ports: phy port instance.
- */
-struct rockchip_usb2phy {
-       struct device   *dev;
-       struct regmap   *grf;
-       struct clk      *clk;
-       struct clk      *clk480m;
-       struct clk_hw   clk480m_hw;
-       enum usb_chg_state      chg_state;
-       enum power_supply_type  chg_type;
-       u8                      dcd_retries;
-       struct extcon_dev       *edev;
-       const struct rockchip_usb2phy_cfg       *phy_cfg;
-       struct rockchip_usb2phy_port    ports[USB2PHY_NUM_PORTS];
-};
-
-static inline int property_enable(struct rockchip_usb2phy *rphy,
-                                 const struct usb2phy_reg *reg, bool en)
-{
-       unsigned int val, mask, tmp;
-
-       tmp = en ? reg->enable : reg->disable;
-       mask = GENMASK(reg->bitend, reg->bitstart);
-       val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
-
-       return regmap_write(rphy->grf, reg->offset, val);
-}
-
-static inline bool property_enabled(struct rockchip_usb2phy *rphy,
-                                   const struct usb2phy_reg *reg)
-{
-       int ret;
-       unsigned int tmp, orig;
-       unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
-
-       ret = regmap_read(rphy->grf, reg->offset, &orig);
-       if (ret)
-               return false;
-
-       tmp = (orig & mask) >> reg->bitstart;
-       return tmp == reg->enable;
-}
-
-static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
-{
-       struct rockchip_usb2phy *rphy =
-               container_of(hw, struct rockchip_usb2phy, clk480m_hw);
-       int ret;
-
-       /* turn on 480m clk output if it is off */
-       if (!property_enabled(rphy, &rphy->phy_cfg->clkout_ctl)) {
-               ret = property_enable(rphy, &rphy->phy_cfg->clkout_ctl, true);
-               if (ret)
-                       return ret;
-
-               /* waiting for the clk become stable */
-               usleep_range(1200, 1300);
-       }
-
-       return 0;
-}
-
-static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
-{
-       struct rockchip_usb2phy *rphy =
-               container_of(hw, struct rockchip_usb2phy, clk480m_hw);
-
-       /* turn off 480m clk output */
-       property_enable(rphy, &rphy->phy_cfg->clkout_ctl, false);
-}
-
-static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
-{
-       struct rockchip_usb2phy *rphy =
-               container_of(hw, struct rockchip_usb2phy, clk480m_hw);
-
-       return property_enabled(rphy, &rphy->phy_cfg->clkout_ctl);
-}
-
-static unsigned long
-rockchip_usb2phy_clk480m_recalc_rate(struct clk_hw *hw,
-                                    unsigned long parent_rate)
-{
-       return 480000000;
-}
-
-static const struct clk_ops rockchip_usb2phy_clkout_ops = {
-       .prepare = rockchip_usb2phy_clk480m_prepare,
-       .unprepare = rockchip_usb2phy_clk480m_unprepare,
-       .is_prepared = rockchip_usb2phy_clk480m_prepared,
-       .recalc_rate = rockchip_usb2phy_clk480m_recalc_rate,
-};
-
-static void rockchip_usb2phy_clk480m_unregister(void *data)
-{
-       struct rockchip_usb2phy *rphy = data;
-
-       of_clk_del_provider(rphy->dev->of_node);
-       clk_unregister(rphy->clk480m);
-}
-
-static int
-rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
-{
-       struct device_node *node = rphy->dev->of_node;
-       struct clk_init_data init;
-       const char *clk_name;
-       int ret;
-
-       init.flags = 0;
-       init.name = "clk_usbphy_480m";
-       init.ops = &rockchip_usb2phy_clkout_ops;
-
-       /* optional override of the clockname */
-       of_property_read_string(node, "clock-output-names", &init.name);
-
-       if (rphy->clk) {
-               clk_name = __clk_get_name(rphy->clk);
-               init.parent_names = &clk_name;
-               init.num_parents = 1;
-       } else {
-               init.parent_names = NULL;
-               init.num_parents = 0;
-       }
-
-       rphy->clk480m_hw.init = &init;
-
-       /* register the clock */
-       rphy->clk480m = clk_register(rphy->dev, &rphy->clk480m_hw);
-       if (IS_ERR(rphy->clk480m)) {
-               ret = PTR_ERR(rphy->clk480m);
-               goto err_ret;
-       }
-
-       ret = of_clk_add_provider(node, of_clk_src_simple_get, rphy->clk480m);
-       if (ret < 0)
-               goto err_clk_provider;
-
-       ret = devm_add_action(rphy->dev, rockchip_usb2phy_clk480m_unregister,
-                             rphy);
-       if (ret < 0)
-               goto err_unreg_action;
-
-       return 0;
-
-err_unreg_action:
-       of_clk_del_provider(node);
-err_clk_provider:
-       clk_unregister(rphy->clk480m);
-err_ret:
-       return ret;
-}
-
-static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
-{
-       int ret;
-       struct device_node *node = rphy->dev->of_node;
-       struct extcon_dev *edev;
-
-       if (of_property_read_bool(node, "extcon")) {
-               edev = extcon_get_edev_by_phandle(rphy->dev, 0);
-               if (IS_ERR(edev)) {
-                       if (PTR_ERR(edev) != -EPROBE_DEFER)
-                               dev_err(rphy->dev, "Invalid or missing extcon\n");
-                       return PTR_ERR(edev);
-               }
-       } else {
-               /* Initialize extcon device */
-               edev = devm_extcon_dev_allocate(rphy->dev,
-                                               rockchip_usb2phy_extcon_cable);
-
-               if (IS_ERR(edev))
-                       return -ENOMEM;
-
-               ret = devm_extcon_dev_register(rphy->dev, edev);
-               if (ret) {
-                       dev_err(rphy->dev, "failed to register extcon device\n");
-                       return ret;
-               }
-       }
-
-       rphy->edev = edev;
-
-       return 0;
-}
-
-static int rockchip_usb2phy_init(struct phy *phy)
-{
-       struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
-       struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
-       int ret = 0;
-
-       mutex_lock(&rport->mutex);
-
-       if (rport->port_id == USB2PHY_PORT_OTG) {
-               if (rport->mode != USB_DR_MODE_HOST) {
-                       /* clear bvalid status and enable bvalid detect irq */
-                       ret = property_enable(rphy,
-                                             &rport->port_cfg->bvalid_det_clr,
-                                             true);
-                       if (ret)
-                               goto out;
-
-                       ret = property_enable(rphy,
-                                             &rport->port_cfg->bvalid_det_en,
-                                             true);
-                       if (ret)
-                               goto out;
-
-                       schedule_delayed_work(&rport->otg_sm_work,
-                                             OTG_SCHEDULE_DELAY);
-               } else {
-                       /* If OTG works in host only mode, do nothing. */
-                       dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
-               }
-       } else if (rport->port_id == USB2PHY_PORT_HOST) {
-               /* clear linestate and enable linestate detect irq */
-               ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
-               if (ret)
-                       goto out;
-
-               ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
-               if (ret)
-                       goto out;
-
-               schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
-       }
-
-out:
-       mutex_unlock(&rport->mutex);
-       return ret;
-}
-
-static int rockchip_usb2phy_power_on(struct phy *phy)
-{
-       struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
-       struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
-       int ret;
-
-       dev_dbg(&rport->phy->dev, "port power on\n");
-
-       if (!rport->suspended)
-               return 0;
-
-       ret = clk_prepare_enable(rphy->clk480m);
-       if (ret)
-               return ret;
-
-       ret = property_enable(rphy, &rport->port_cfg->phy_sus, false);
-       if (ret)
-               return ret;
-
-       rport->suspended = false;
-       return 0;
-}
-
-static int rockchip_usb2phy_power_off(struct phy *phy)
-{
-       struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
-       struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
-       int ret;
-
-       dev_dbg(&rport->phy->dev, "port power off\n");
-
-       if (rport->suspended)
-               return 0;
-
-       ret = property_enable(rphy, &rport->port_cfg->phy_sus, true);
-       if (ret)
-               return ret;
-
-       rport->suspended = true;
-       clk_disable_unprepare(rphy->clk480m);
-
-       return 0;
-}
-
-static int rockchip_usb2phy_exit(struct phy *phy)
-{
-       struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
-
-       if (rport->port_id == USB2PHY_PORT_OTG &&
-           rport->mode != USB_DR_MODE_HOST) {
-               cancel_delayed_work_sync(&rport->otg_sm_work);
-               cancel_delayed_work_sync(&rport->chg_work);
-       } else if (rport->port_id == USB2PHY_PORT_HOST)
-               cancel_delayed_work_sync(&rport->sm_work);
-
-       return 0;
-}
-
-static const struct phy_ops rockchip_usb2phy_ops = {
-       .init           = rockchip_usb2phy_init,
-       .exit           = rockchip_usb2phy_exit,
-       .power_on       = rockchip_usb2phy_power_on,
-       .power_off      = rockchip_usb2phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
-{
-       struct rockchip_usb2phy_port *rport =
-               container_of(work, struct rockchip_usb2phy_port,
-                            otg_sm_work.work);
-       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
-       static unsigned int cable;
-       unsigned long delay;
-       bool vbus_attach, sch_work, notify_charger;
-
-       if (rport->utmi_avalid)
-               vbus_attach =
-                       property_enabled(rphy, &rport->port_cfg->utmi_avalid);
-       else
-               vbus_attach =
-                       property_enabled(rphy, &rport->port_cfg->utmi_bvalid);
-
-       sch_work = false;
-       notify_charger = false;
-       delay = OTG_SCHEDULE_DELAY;
-       dev_dbg(&rport->phy->dev, "%s otg sm work\n",
-               usb_otg_state_string(rport->state));
-
-       switch (rport->state) {
-       case OTG_STATE_UNDEFINED:
-               rport->state = OTG_STATE_B_IDLE;
-               if (!vbus_attach)
-                       rockchip_usb2phy_power_off(rport->phy);
-               /* fall through */
-       case OTG_STATE_B_IDLE:
-               if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) > 0) {
-                       dev_dbg(&rport->phy->dev, "usb otg host connect\n");
-                       rport->state = OTG_STATE_A_HOST;
-                       rockchip_usb2phy_power_on(rport->phy);
-                       return;
-               } else if (vbus_attach) {
-                       dev_dbg(&rport->phy->dev, "vbus_attach\n");
-                       switch (rphy->chg_state) {
-                       case USB_CHG_STATE_UNDEFINED:
-                               schedule_delayed_work(&rport->chg_work, 0);
-                               return;
-                       case USB_CHG_STATE_DETECTED:
-                               switch (rphy->chg_type) {
-                               case POWER_SUPPLY_TYPE_USB:
-                                       dev_dbg(&rport->phy->dev, "sdp cable is connected\n");
-                                       rockchip_usb2phy_power_on(rport->phy);
-                                       rport->state = OTG_STATE_B_PERIPHERAL;
-                                       notify_charger = true;
-                                       sch_work = true;
-                                       cable = EXTCON_CHG_USB_SDP;
-                                       break;
-                               case POWER_SUPPLY_TYPE_USB_DCP:
-                                       dev_dbg(&rport->phy->dev, "dcp cable is connected\n");
-                                       rockchip_usb2phy_power_off(rport->phy);
-                                       notify_charger = true;
-                                       sch_work = true;
-                                       cable = EXTCON_CHG_USB_DCP;
-                                       break;
-                               case POWER_SUPPLY_TYPE_USB_CDP:
-                                       dev_dbg(&rport->phy->dev, "cdp cable is connected\n");
-                                       rockchip_usb2phy_power_on(rport->phy);
-                                       rport->state = OTG_STATE_B_PERIPHERAL;
-                                       notify_charger = true;
-                                       sch_work = true;
-                                       cable = EXTCON_CHG_USB_CDP;
-                                       break;
-                               default:
-                                       break;
-                               }
-                               break;
-                       default:
-                               break;
-                       }
-               } else {
-                       notify_charger = true;
-                       rphy->chg_state = USB_CHG_STATE_UNDEFINED;
-                       rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
-               }
-
-               if (rport->vbus_attached != vbus_attach) {
-                       rport->vbus_attached = vbus_attach;
-
-                       if (notify_charger && rphy->edev) {
-                               extcon_set_cable_state_(rphy->edev,
-                                                       cable, vbus_attach);
-                               if (cable == EXTCON_CHG_USB_SDP)
-                                       extcon_set_state_sync(rphy->edev,
-                                                             EXTCON_USB,
-                                                             vbus_attach);
-                       }
-               }
-               break;
-       case OTG_STATE_B_PERIPHERAL:
-               if (!vbus_attach) {
-                       dev_dbg(&rport->phy->dev, "usb disconnect\n");
-                       rphy->chg_state = USB_CHG_STATE_UNDEFINED;
-                       rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
-                       rport->state = OTG_STATE_B_IDLE;
-                       delay = 0;
-                       rockchip_usb2phy_power_off(rport->phy);
-               }
-               sch_work = true;
-               break;
-       case OTG_STATE_A_HOST:
-               if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) == 0) {
-                       dev_dbg(&rport->phy->dev, "usb otg host disconnect\n");
-                       rport->state = OTG_STATE_B_IDLE;
-                       rockchip_usb2phy_power_off(rport->phy);
-               }
-               break;
-       default:
-               break;
-       }
-
-       if (sch_work)
-               schedule_delayed_work(&rport->otg_sm_work, delay);
-}
-
-static const char *chg_to_string(enum power_supply_type chg_type)
-{
-       switch (chg_type) {
-       case POWER_SUPPLY_TYPE_USB:
-               return "USB_SDP_CHARGER";
-       case POWER_SUPPLY_TYPE_USB_DCP:
-               return "USB_DCP_CHARGER";
-       case POWER_SUPPLY_TYPE_USB_CDP:
-               return "USB_CDP_CHARGER";
-       default:
-               return "INVALID_CHARGER";
-       }
-}
-
-static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
-                                   bool en)
-{
-       property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
-       property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
-}
-
-static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
-                                           bool en)
-{
-       property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en);
-       property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
-}
-
-static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
-                                             bool en)
-{
-       property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en);
-       property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
-}
-
-#define CHG_DCD_POLL_TIME      (100 * HZ / 1000)
-#define CHG_DCD_MAX_RETRIES    6
-#define CHG_PRIMARY_DET_TIME   (40 * HZ / 1000)
-#define CHG_SECONDARY_DET_TIME (40 * HZ / 1000)
-static void rockchip_chg_detect_work(struct work_struct *work)
-{
-       struct rockchip_usb2phy_port *rport =
-               container_of(work, struct rockchip_usb2phy_port, chg_work.work);
-       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
-       bool is_dcd, tmout, vout;
-       unsigned long delay;
-
-       dev_dbg(&rport->phy->dev, "chg detection work state = %d\n",
-               rphy->chg_state);
-       switch (rphy->chg_state) {
-       case USB_CHG_STATE_UNDEFINED:
-               if (!rport->suspended)
-                       rockchip_usb2phy_power_off(rport->phy);
-               /* put the controller in non-driving mode */
-               property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, false);
-               /* Start DCD processing stage 1 */
-               rockchip_chg_enable_dcd(rphy, true);
-               rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
-               rphy->dcd_retries = 0;
-               delay = CHG_DCD_POLL_TIME;
-               break;
-       case USB_CHG_STATE_WAIT_FOR_DCD:
-               /* get data contact detection status */
-               is_dcd = property_enabled(rphy, &rphy->phy_cfg->chg_det.dp_det);
-               tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
-               /* stage 2 */
-               if (is_dcd || tmout) {
-                       /* stage 4 */
-                       /* Turn off DCD circuitry */
-                       rockchip_chg_enable_dcd(rphy, false);
-                       /* Voltage Source on DP, Probe on DM */
-                       rockchip_chg_enable_primary_det(rphy, true);
-                       delay = CHG_PRIMARY_DET_TIME;
-                       rphy->chg_state = USB_CHG_STATE_DCD_DONE;
-               } else {
-                       /* stage 3 */
-                       delay = CHG_DCD_POLL_TIME;
-               }
-               break;
-       case USB_CHG_STATE_DCD_DONE:
-               vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.cp_det);
-               rockchip_chg_enable_primary_det(rphy, false);
-               if (vout) {
-                       /* Voltage Source on DM, Probe on DP  */
-                       rockchip_chg_enable_secondary_det(rphy, true);
-                       delay = CHG_SECONDARY_DET_TIME;
-                       rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE;
-               } else {
-                       if (rphy->dcd_retries == CHG_DCD_MAX_RETRIES) {
-                               /* floating charger found */
-                               rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
-                               rphy->chg_state = USB_CHG_STATE_DETECTED;
-                               delay = 0;
-                       } else {
-                               rphy->chg_type = POWER_SUPPLY_TYPE_USB;
-                               rphy->chg_state = USB_CHG_STATE_DETECTED;
-                               delay = 0;
-                       }
-               }
-               break;
-       case USB_CHG_STATE_PRIMARY_DONE:
-               vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.dcp_det);
-               /* Turn off voltage source */
-               rockchip_chg_enable_secondary_det(rphy, false);
-               if (vout)
-                       rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
-               else
-                       rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP;
-               /* fall through */
-       case USB_CHG_STATE_SECONDARY_DONE:
-               rphy->chg_state = USB_CHG_STATE_DETECTED;
-               delay = 0;
-               /* fall through */
-       case USB_CHG_STATE_DETECTED:
-               /* put the controller in normal mode */
-               property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, true);
-               rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
-               dev_info(&rport->phy->dev, "charger = %s\n",
-                        chg_to_string(rphy->chg_type));
-               return;
-       default:
-               return;
-       }
-
-       schedule_delayed_work(&rport->chg_work, delay);
-}
-
-/*
- * The function manage host-phy port state and suspend/resume phy port
- * to save power.
- *
- * we rely on utmi_linestate and utmi_hostdisconnect to identify whether
- * devices is disconnect or not. Besides, we do not need care it is FS/LS
- * disconnected or HS disconnected, actually, we just only need get the
- * device is disconnected at last through rearm the delayed work,
- * to suspend the phy port in _PHY_STATE_DISCONNECT_ case.
- *
- * NOTE: It may invoke *phy_powr_off or *phy_power_on which will invoke
- * some clk related APIs, so do not invoke it from interrupt context directly.
- */
-static void rockchip_usb2phy_sm_work(struct work_struct *work)
-{
-       struct rockchip_usb2phy_port *rport =
-               container_of(work, struct rockchip_usb2phy_port, sm_work.work);
-       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
-       unsigned int sh = rport->port_cfg->utmi_hstdet.bitend -
-                         rport->port_cfg->utmi_hstdet.bitstart + 1;
-       unsigned int ul, uhd, state;
-       unsigned int ul_mask, uhd_mask;
-       int ret;
-
-       mutex_lock(&rport->mutex);
-
-       ret = regmap_read(rphy->grf, rport->port_cfg->utmi_ls.offset, &ul);
-       if (ret < 0)
-               goto next_schedule;
-
-       ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset,
-                         &uhd);
-       if (ret < 0)
-               goto next_schedule;
-
-       uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend,
-                          rport->port_cfg->utmi_hstdet.bitstart);
-       ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend,
-                         rport->port_cfg->utmi_ls.bitstart);
-
-       /* stitch on utmi_ls and utmi_hstdet as phy state */
-       state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) |
-               (((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh);
-
-       switch (state) {
-       case PHY_STATE_HS_ONLINE:
-               dev_dbg(&rport->phy->dev, "HS online\n");
-               break;
-       case PHY_STATE_FS_LS_ONLINE:
-               /*
-                * For FS/LS device, the online state share with connect state
-                * from utmi_ls and utmi_hstdet register, so we distinguish
-                * them via suspended flag.
-                *
-                * Plus, there are two cases, one is D- Line pull-up, and D+
-                * line pull-down, the state is 4; another is D+ line pull-up,
-                * and D- line pull-down, the state is 2.
-                */
-               if (!rport->suspended) {
-                       /* D- line pull-up, D+ line pull-down */
-                       dev_dbg(&rport->phy->dev, "FS/LS online\n");
-                       break;
-               }
-               /* fall through */
-       case PHY_STATE_CONNECT:
-               if (rport->suspended) {
-                       dev_dbg(&rport->phy->dev, "Connected\n");
-                       rockchip_usb2phy_power_on(rport->phy);
-                       rport->suspended = false;
-               } else {
-                       /* D+ line pull-up, D- line pull-down */
-                       dev_dbg(&rport->phy->dev, "FS/LS online\n");
-               }
-               break;
-       case PHY_STATE_DISCONNECT:
-               if (!rport->suspended) {
-                       dev_dbg(&rport->phy->dev, "Disconnected\n");
-                       rockchip_usb2phy_power_off(rport->phy);
-                       rport->suspended = true;
-               }
-
-               /*
-                * activate the linestate detection to get the next device
-                * plug-in irq.
-                */
-               property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
-               property_enable(rphy, &rport->port_cfg->ls_det_en, true);
-
-               /*
-                * we don't need to rearm the delayed work when the phy port
-                * is suspended.
-                */
-               mutex_unlock(&rport->mutex);
-               return;
-       default:
-               dev_dbg(&rport->phy->dev, "unknown phy state\n");
-               break;
-       }
-
-next_schedule:
-       mutex_unlock(&rport->mutex);
-       schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
-}
-
-static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
-{
-       struct rockchip_usb2phy_port *rport = data;
-       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
-
-       if (!property_enabled(rphy, &rport->port_cfg->ls_det_st))
-               return IRQ_NONE;
-
-       mutex_lock(&rport->mutex);
-
-       /* disable linestate detect irq and clear its status */
-       property_enable(rphy, &rport->port_cfg->ls_det_en, false);
-       property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
-
-       mutex_unlock(&rport->mutex);
-
-       /*
-        * In this case for host phy port, a new device is plugged in,
-        * meanwhile, if the phy port is suspended, we need rearm the work to
-        * resume it and mange its states; otherwise, we do nothing about that.
-        */
-       if (rport->suspended && rport->port_id == USB2PHY_PORT_HOST)
-               rockchip_usb2phy_sm_work(&rport->sm_work.work);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
-{
-       struct rockchip_usb2phy_port *rport = data;
-       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
-
-       if (!property_enabled(rphy, &rport->port_cfg->bvalid_det_st))
-               return IRQ_NONE;
-
-       mutex_lock(&rport->mutex);
-
-       /* clear bvalid detect irq pending status */
-       property_enable(rphy, &rport->port_cfg->bvalid_det_clr, true);
-
-       mutex_unlock(&rport->mutex);
-
-       rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
-
-       return IRQ_HANDLED;
-}
-
-static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
-                                          struct rockchip_usb2phy_port *rport,
-                                          struct device_node *child_np)
-{
-       int ret;
-
-       rport->port_id = USB2PHY_PORT_HOST;
-       rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_HOST];
-       rport->suspended = true;
-
-       mutex_init(&rport->mutex);
-       INIT_DELAYED_WORK(&rport->sm_work, rockchip_usb2phy_sm_work);
-
-       rport->ls_irq = of_irq_get_byname(child_np, "linestate");
-       if (rport->ls_irq < 0) {
-               dev_err(rphy->dev, "no linestate irq provided\n");
-               return rport->ls_irq;
-       }
-
-       ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL,
-                                       rockchip_usb2phy_linestate_irq,
-                                       IRQF_ONESHOT,
-                                       "rockchip_usb2phy", rport);
-       if (ret) {
-               dev_err(rphy->dev, "failed to request linestate irq handle\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static int rockchip_otg_event(struct notifier_block *nb,
-                             unsigned long event, void *ptr)
-{
-       struct rockchip_usb2phy_port *rport =
-               container_of(nb, struct rockchip_usb2phy_port, event_nb);
-
-       schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY);
-
-       return NOTIFY_DONE;
-}
-
-static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
-                                         struct rockchip_usb2phy_port *rport,
-                                         struct device_node *child_np)
-{
-       int ret;
-
-       rport->port_id = USB2PHY_PORT_OTG;
-       rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG];
-       rport->state = OTG_STATE_UNDEFINED;
-
-       /*
-        * set suspended flag to true, but actually don't
-        * put phy in suspend mode, it aims to enable usb
-        * phy and clock in power_on() called by usb controller
-        * driver during probe.
-        */
-       rport->suspended = true;
-       rport->vbus_attached = false;
-
-       mutex_init(&rport->mutex);
-
-       rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
-       if (rport->mode == USB_DR_MODE_HOST) {
-               ret = 0;
-               goto out;
-       }
-
-       INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
-       INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work);
-
-       rport->utmi_avalid =
-               of_property_read_bool(child_np, "rockchip,utmi-avalid");
-
-       rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
-       if (rport->bvalid_irq < 0) {
-               dev_err(rphy->dev, "no vbus valid irq provided\n");
-               ret = rport->bvalid_irq;
-               goto out;
-       }
-
-       ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, NULL,
-                                       rockchip_usb2phy_bvalid_irq,
-                                       IRQF_ONESHOT,
-                                       "rockchip_usb2phy_bvalid", rport);
-       if (ret) {
-               dev_err(rphy->dev, "failed to request otg-bvalid irq handle\n");
-               goto out;
-       }
-
-       if (!IS_ERR(rphy->edev)) {
-               rport->event_nb.notifier_call = rockchip_otg_event;
-
-               ret = extcon_register_notifier(rphy->edev, EXTCON_USB_HOST,
-                                              &rport->event_nb);
-               if (ret)
-                       dev_err(rphy->dev, "register USB HOST notifier failed\n");
-       }
-
-out:
-       return ret;
-}
-
-static int rockchip_usb2phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct device_node *child_np;
-       struct phy_provider *provider;
-       struct rockchip_usb2phy *rphy;
-       const struct rockchip_usb2phy_cfg *phy_cfgs;
-       const struct of_device_id *match;
-       unsigned int reg;
-       int index, ret;
-
-       rphy = devm_kzalloc(dev, sizeof(*rphy), GFP_KERNEL);
-       if (!rphy)
-               return -ENOMEM;
-
-       match = of_match_device(dev->driver->of_match_table, dev);
-       if (!match || !match->data) {
-               dev_err(dev, "phy configs are not assigned!\n");
-               return -EINVAL;
-       }
-
-       if (!dev->parent || !dev->parent->of_node)
-               return -EINVAL;
-
-       rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
-       if (IS_ERR(rphy->grf))
-               return PTR_ERR(rphy->grf);
-
-       if (of_property_read_u32(np, "reg", &reg)) {
-               dev_err(dev, "the reg property is not assigned in %s node\n",
-                       np->name);
-               return -EINVAL;
-       }
-
-       rphy->dev = dev;
-       phy_cfgs = match->data;
-       rphy->chg_state = USB_CHG_STATE_UNDEFINED;
-       rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
-       platform_set_drvdata(pdev, rphy);
-
-       ret = rockchip_usb2phy_extcon_register(rphy);
-       if (ret)
-               return ret;
-
-       /* find out a proper config which can be matched with dt. */
-       index = 0;
-       while (phy_cfgs[index].reg) {
-               if (phy_cfgs[index].reg == reg) {
-                       rphy->phy_cfg = &phy_cfgs[index];
-                       break;
-               }
-
-               ++index;
-       }
-
-       if (!rphy->phy_cfg) {
-               dev_err(dev, "no phy-config can be matched with %s node\n",
-                       np->name);
-               return -EINVAL;
-       }
-
-       rphy->clk = of_clk_get_by_name(np, "phyclk");
-       if (!IS_ERR(rphy->clk)) {
-               clk_prepare_enable(rphy->clk);
-       } else {
-               dev_info(&pdev->dev, "no phyclk specified\n");
-               rphy->clk = NULL;
-       }
-
-       ret = rockchip_usb2phy_clk480m_register(rphy);
-       if (ret) {
-               dev_err(dev, "failed to register 480m output clock\n");
-               goto disable_clks;
-       }
-
-       index = 0;
-       for_each_available_child_of_node(np, child_np) {
-               struct rockchip_usb2phy_port *rport = &rphy->ports[index];
-               struct phy *phy;
-
-               /* This driver aims to support both otg-port and host-port */
-               if (of_node_cmp(child_np->name, "host-port") &&
-                   of_node_cmp(child_np->name, "otg-port"))
-                       goto next_child;
-
-               phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
-               if (IS_ERR(phy)) {
-                       dev_err(dev, "failed to create phy\n");
-                       ret = PTR_ERR(phy);
-                       goto put_child;
-               }
-
-               rport->phy = phy;
-               phy_set_drvdata(rport->phy, rport);
-
-               /* initialize otg/host port separately */
-               if (!of_node_cmp(child_np->name, "host-port")) {
-                       ret = rockchip_usb2phy_host_port_init(rphy, rport,
-                                                             child_np);
-                       if (ret)
-                               goto put_child;
-               } else {
-                       ret = rockchip_usb2phy_otg_port_init(rphy, rport,
-                                                            child_np);
-                       if (ret)
-                               goto put_child;
-               }
-
-next_child:
-               /* to prevent out of boundary */
-               if (++index >= rphy->phy_cfg->num_ports)
-                       break;
-       }
-
-       provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       return PTR_ERR_OR_ZERO(provider);
-
-put_child:
-       of_node_put(child_np);
-disable_clks:
-       if (rphy->clk) {
-               clk_disable_unprepare(rphy->clk);
-               clk_put(rphy->clk);
-       }
-       return ret;
-}
-
-static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = {
-       {
-               .reg = 0x100,
-               .num_ports      = 2,
-               .clkout_ctl     = { 0x108, 4, 4, 1, 0 },
-               .port_cfgs      = {
-                       [USB2PHY_PORT_OTG] = {
-                               .phy_sus        = { 0x0100, 15, 0, 0, 0x1d1 },
-                               .bvalid_det_en  = { 0x0110, 2, 2, 0, 1 },
-                               .bvalid_det_st  = { 0x0114, 2, 2, 0, 1 },
-                               .bvalid_det_clr = { 0x0118, 2, 2, 0, 1 },
-                               .ls_det_en      = { 0x0110, 0, 0, 0, 1 },
-                               .ls_det_st      = { 0x0114, 0, 0, 0, 1 },
-                               .ls_det_clr     = { 0x0118, 0, 0, 0, 1 },
-                               .utmi_avalid    = { 0x0120, 10, 10, 0, 1 },
-                               .utmi_bvalid    = { 0x0120, 9, 9, 0, 1 },
-                               .utmi_ls        = { 0x0120, 5, 4, 0, 1 },
-                       },
-                       [USB2PHY_PORT_HOST] = {
-                               .phy_sus        = { 0x104, 15, 0, 0, 0x1d1 },
-                               .ls_det_en      = { 0x110, 1, 1, 0, 1 },
-                               .ls_det_st      = { 0x114, 1, 1, 0, 1 },
-                               .ls_det_clr     = { 0x118, 1, 1, 0, 1 },
-                               .utmi_ls        = { 0x120, 17, 16, 0, 1 },
-                               .utmi_hstdet    = { 0x120, 19, 19, 0, 1 }
-                       }
-               },
-               .chg_det = {
-                       .opmode         = { 0x0100, 3, 0, 5, 1 },
-                       .cp_det         = { 0x0120, 24, 24, 0, 1 },
-                       .dcp_det        = { 0x0120, 23, 23, 0, 1 },
-                       .dp_det         = { 0x0120, 25, 25, 0, 1 },
-                       .idm_sink_en    = { 0x0108, 8, 8, 0, 1 },
-                       .idp_sink_en    = { 0x0108, 7, 7, 0, 1 },
-                       .idp_src_en     = { 0x0108, 9, 9, 0, 1 },
-                       .rdm_pdwn_en    = { 0x0108, 10, 10, 0, 1 },
-                       .vdm_src_en     = { 0x0108, 12, 12, 0, 1 },
-                       .vdp_src_en     = { 0x0108, 11, 11, 0, 1 },
-               },
-       },
-       { /* sentinel */ }
-};
-
-static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs[] = {
-       {
-               .reg = 0x700,
-               .num_ports      = 2,
-               .clkout_ctl     = { 0x0724, 15, 15, 1, 0 },
-               .port_cfgs      = {
-                       [USB2PHY_PORT_HOST] = {
-                               .phy_sus        = { 0x0728, 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 },
-                               .utmi_ls        = { 0x049c, 14, 13, 0, 1 },
-                               .utmi_hstdet    = { 0x049c, 12, 12, 0, 1 }
-                       }
-               },
-       },
-       { /* sentinel */ }
-};
-
-static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
-       {
-               .reg            = 0xe450,
-               .num_ports      = 2,
-               .clkout_ctl     = { 0xe450, 4, 4, 1, 0 },
-               .port_cfgs      = {
-                       [USB2PHY_PORT_OTG] = {
-                               .phy_sus        = { 0xe454, 1, 0, 2, 1 },
-                               .bvalid_det_en  = { 0xe3c0, 3, 3, 0, 1 },
-                               .bvalid_det_st  = { 0xe3e0, 3, 3, 0, 1 },
-                               .bvalid_det_clr = { 0xe3d0, 3, 3, 0, 1 },
-                               .utmi_avalid    = { 0xe2ac, 7, 7, 0, 1 },
-                               .utmi_bvalid    = { 0xe2ac, 12, 12, 0, 1 },
-                       },
-                       [USB2PHY_PORT_HOST] = {
-                               .phy_sus        = { 0xe458, 1, 0, 0x2, 0x1 },
-                               .ls_det_en      = { 0xe3c0, 6, 6, 0, 1 },
-                               .ls_det_st      = { 0xe3e0, 6, 6, 0, 1 },
-                               .ls_det_clr     = { 0xe3d0, 6, 6, 0, 1 },
-                               .utmi_ls        = { 0xe2ac, 22, 21, 0, 1 },
-                               .utmi_hstdet    = { 0xe2ac, 23, 23, 0, 1 }
-                       }
-               },
-               .chg_det = {
-                       .opmode         = { 0xe454, 3, 0, 5, 1 },
-                       .cp_det         = { 0xe2ac, 2, 2, 0, 1 },
-                       .dcp_det        = { 0xe2ac, 1, 1, 0, 1 },
-                       .dp_det         = { 0xe2ac, 0, 0, 0, 1 },
-                       .idm_sink_en    = { 0xe450, 8, 8, 0, 1 },
-                       .idp_sink_en    = { 0xe450, 7, 7, 0, 1 },
-                       .idp_src_en     = { 0xe450, 9, 9, 0, 1 },
-                       .rdm_pdwn_en    = { 0xe450, 10, 10, 0, 1 },
-                       .vdm_src_en     = { 0xe450, 12, 12, 0, 1 },
-                       .vdp_src_en     = { 0xe450, 11, 11, 0, 1 },
-               },
-       },
-       {
-               .reg            = 0xe460,
-               .num_ports      = 2,
-               .clkout_ctl     = { 0xe460, 4, 4, 1, 0 },
-               .port_cfgs      = {
-                       [USB2PHY_PORT_OTG] = {
-                               .phy_sus        = { 0xe464, 1, 0, 2, 1 },
-                               .bvalid_det_en  = { 0xe3c0, 8, 8, 0, 1 },
-                               .bvalid_det_st  = { 0xe3e0, 8, 8, 0, 1 },
-                               .bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 },
-                               .utmi_avalid    = { 0xe2ac, 10, 10, 0, 1 },
-                               .utmi_bvalid    = { 0xe2ac, 16, 16, 0, 1 },
-                       },
-                       [USB2PHY_PORT_HOST] = {
-                               .phy_sus        = { 0xe468, 1, 0, 0x2, 0x1 },
-                               .ls_det_en      = { 0xe3c0, 11, 11, 0, 1 },
-                               .ls_det_st      = { 0xe3e0, 11, 11, 0, 1 },
-                               .ls_det_clr     = { 0xe3d0, 11, 11, 0, 1 },
-                               .utmi_ls        = { 0xe2ac, 26, 25, 0, 1 },
-                               .utmi_hstdet    = { 0xe2ac, 27, 27, 0, 1 }
-                       }
-               },
-       },
-       { /* sentinel */ }
-};
-
-static const struct of_device_id rockchip_usb2phy_dt_match[] = {
-       { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
-       { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
-       { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
-       {}
-};
-MODULE_DEVICE_TABLE(of, rockchip_usb2phy_dt_match);
-
-static struct platform_driver rockchip_usb2phy_driver = {
-       .probe          = rockchip_usb2phy_probe,
-       .driver         = {
-               .name   = "rockchip-usb2phy",
-               .of_match_table = rockchip_usb2phy_dt_match,
-       },
-};
-module_platform_driver(rockchip_usb2phy_driver);
-
-MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");
-MODULE_DESCRIPTION("Rockchip USB2.0 PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-rockchip-pcie.c b/drivers/phy/phy-rockchip-pcie.c
deleted file mode 100644 (file)
index 6904633..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Rockchip PCIe PHY driver
- *
- * Copyright (C) 2016 Shawn Lin <shawn.lin@rock-chips.com>
- * Copyright (C) 2016 ROCKCHIP, 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; either version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-#include <linux/reset.h>
-
-/*
- * The higher 16-bit of this register is used for write protection
- * only if BIT(x + 16) set to 1 the BIT(x) can be written.
- */
-#define HIWORD_UPDATE(val, mask, shift) \
-               ((val) << (shift) | (mask) << ((shift) + 16))
-
-#define PHY_MAX_LANE_NUM      4
-#define PHY_CFG_DATA_SHIFT    7
-#define PHY_CFG_ADDR_SHIFT    1
-#define PHY_CFG_DATA_MASK     0xf
-#define PHY_CFG_ADDR_MASK     0x3f
-#define PHY_CFG_RD_MASK       0x3ff
-#define PHY_CFG_WR_ENABLE     1
-#define PHY_CFG_WR_DISABLE    1
-#define PHY_CFG_WR_SHIFT      0
-#define PHY_CFG_WR_MASK       1
-#define PHY_CFG_PLL_LOCK      0x10
-#define PHY_CFG_CLK_TEST      0x10
-#define PHY_CFG_CLK_SCC       0x12
-#define PHY_CFG_SEPE_RATE     BIT(3)
-#define PHY_CFG_PLL_100M      BIT(3)
-#define PHY_PLL_LOCKED        BIT(9)
-#define PHY_PLL_OUTPUT        BIT(10)
-#define PHY_LANE_A_STATUS     0x30
-#define PHY_LANE_B_STATUS     0x31
-#define PHY_LANE_C_STATUS     0x32
-#define PHY_LANE_D_STATUS     0x33
-#define PHY_LANE_RX_DET_SHIFT 11
-#define PHY_LANE_RX_DET_TH    0x1
-#define PHY_LANE_IDLE_OFF     0x1
-#define PHY_LANE_IDLE_MASK    0x1
-#define PHY_LANE_IDLE_A_SHIFT 3
-#define PHY_LANE_IDLE_B_SHIFT 4
-#define PHY_LANE_IDLE_C_SHIFT 5
-#define PHY_LANE_IDLE_D_SHIFT 6
-
-struct rockchip_pcie_data {
-       unsigned int pcie_conf;
-       unsigned int pcie_status;
-       unsigned int pcie_laneoff;
-};
-
-struct rockchip_pcie_phy {
-       struct rockchip_pcie_data *phy_data;
-       struct regmap *reg_base;
-       struct reset_control *phy_rst;
-       struct clk *clk_pciephy_ref;
-};
-
-static inline void phy_wr_cfg(struct rockchip_pcie_phy *rk_phy,
-                             u32 addr, u32 data)
-{
-       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
-                    HIWORD_UPDATE(data,
-                                  PHY_CFG_DATA_MASK,
-                                  PHY_CFG_DATA_SHIFT) |
-                    HIWORD_UPDATE(addr,
-                                  PHY_CFG_ADDR_MASK,
-                                  PHY_CFG_ADDR_SHIFT));
-       udelay(1);
-       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
-                    HIWORD_UPDATE(PHY_CFG_WR_ENABLE,
-                                  PHY_CFG_WR_MASK,
-                                  PHY_CFG_WR_SHIFT));
-       udelay(1);
-       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
-                    HIWORD_UPDATE(PHY_CFG_WR_DISABLE,
-                                  PHY_CFG_WR_MASK,
-                                  PHY_CFG_WR_SHIFT));
-}
-
-static inline u32 phy_rd_cfg(struct rockchip_pcie_phy *rk_phy,
-                            u32 addr)
-{
-       u32 val;
-
-       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
-                    HIWORD_UPDATE(addr,
-                                  PHY_CFG_RD_MASK,
-                                  PHY_CFG_ADDR_SHIFT));
-       regmap_read(rk_phy->reg_base,
-                   rk_phy->phy_data->pcie_status,
-                   &val);
-       return val;
-}
-
-static int rockchip_pcie_phy_power_off(struct phy *phy)
-{
-       struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy);
-       int err = 0;
-
-       err = reset_control_assert(rk_phy->phy_rst);
-       if (err) {
-               dev_err(&phy->dev, "assert phy_rst err %d\n", err);
-               return err;
-       }
-
-       return 0;
-}
-
-static int rockchip_pcie_phy_power_on(struct phy *phy)
-{
-       struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy);
-       int err = 0;
-       u32 status;
-       unsigned long timeout;
-
-       err = reset_control_deassert(rk_phy->phy_rst);
-       if (err) {
-               dev_err(&phy->dev, "deassert phy_rst err %d\n", err);
-               return err;
-       }
-
-       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
-                    HIWORD_UPDATE(PHY_CFG_PLL_LOCK,
-                                  PHY_CFG_ADDR_MASK,
-                                  PHY_CFG_ADDR_SHIFT));
-
-       /*
-        * No documented timeout value for phy operation below,
-        * so we make it large enough here. And we use loop-break
-        * method which should not be harmful.
-        */
-       timeout = jiffies + msecs_to_jiffies(1000);
-
-       err = -EINVAL;
-       while (time_before(jiffies, timeout)) {
-               regmap_read(rk_phy->reg_base,
-                           rk_phy->phy_data->pcie_status,
-                           &status);
-               if (status & PHY_PLL_LOCKED) {
-                       dev_dbg(&phy->dev, "pll locked!\n");
-                       err = 0;
-                       break;
-               }
-               msleep(20);
-       }
-
-       if (err) {
-               dev_err(&phy->dev, "pll lock timeout!\n");
-               goto err_pll_lock;
-       }
-
-       phy_wr_cfg(rk_phy, PHY_CFG_CLK_TEST, PHY_CFG_SEPE_RATE);
-       phy_wr_cfg(rk_phy, PHY_CFG_CLK_SCC, PHY_CFG_PLL_100M);
-
-       err = -ETIMEDOUT;
-       while (time_before(jiffies, timeout)) {
-               regmap_read(rk_phy->reg_base,
-                           rk_phy->phy_data->pcie_status,
-                           &status);
-               if (!(status & PHY_PLL_OUTPUT)) {
-                       dev_dbg(&phy->dev, "pll output enable done!\n");
-                       err = 0;
-                       break;
-               }
-               msleep(20);
-       }
-
-       if (err) {
-               dev_err(&phy->dev, "pll output enable timeout!\n");
-               goto err_pll_lock;
-       }
-
-       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
-                    HIWORD_UPDATE(PHY_CFG_PLL_LOCK,
-                                  PHY_CFG_ADDR_MASK,
-                                  PHY_CFG_ADDR_SHIFT));
-       err = -EINVAL;
-       while (time_before(jiffies, timeout)) {
-               regmap_read(rk_phy->reg_base,
-                           rk_phy->phy_data->pcie_status,
-                           &status);
-               if (status & PHY_PLL_LOCKED) {
-                       dev_dbg(&phy->dev, "pll relocked!\n");
-                       err = 0;
-                       break;
-               }
-               msleep(20);
-       }
-
-       if (err) {
-               dev_err(&phy->dev, "pll relock timeout!\n");
-               goto err_pll_lock;
-       }
-
-       return 0;
-
-err_pll_lock:
-       reset_control_assert(rk_phy->phy_rst);
-       return err;
-}
-
-static int rockchip_pcie_phy_init(struct phy *phy)
-{
-       struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy);
-       int err = 0;
-
-       err = clk_prepare_enable(rk_phy->clk_pciephy_ref);
-       if (err) {
-               dev_err(&phy->dev, "Fail to enable pcie ref clock.\n");
-               goto err_refclk;
-       }
-
-       err = reset_control_assert(rk_phy->phy_rst);
-       if (err) {
-               dev_err(&phy->dev, "assert phy_rst err %d\n", err);
-               goto err_reset;
-       }
-
-       return err;
-
-err_reset:
-       clk_disable_unprepare(rk_phy->clk_pciephy_ref);
-err_refclk:
-       return err;
-}
-
-static int rockchip_pcie_phy_exit(struct phy *phy)
-{
-       struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy);
-
-       clk_disable_unprepare(rk_phy->clk_pciephy_ref);
-
-       return 0;
-}
-
-static const struct phy_ops ops = {
-       .init           = rockchip_pcie_phy_init,
-       .exit           = rockchip_pcie_phy_exit,
-       .power_on       = rockchip_pcie_phy_power_on,
-       .power_off      = rockchip_pcie_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static const struct rockchip_pcie_data rk3399_pcie_data = {
-       .pcie_conf = 0xe220,
-       .pcie_status = 0xe2a4,
-       .pcie_laneoff = 0xe214,
-};
-
-static const struct of_device_id rockchip_pcie_phy_dt_ids[] = {
-       {
-               .compatible = "rockchip,rk3399-pcie-phy",
-               .data = &rk3399_pcie_data,
-       },
-       {}
-};
-
-MODULE_DEVICE_TABLE(of, rockchip_pcie_phy_dt_ids);
-
-static int rockchip_pcie_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct rockchip_pcie_phy *rk_phy;
-       struct phy *generic_phy;
-       struct phy_provider *phy_provider;
-       struct regmap *grf;
-       const struct of_device_id *of_id;
-
-       grf = syscon_node_to_regmap(dev->parent->of_node);
-       if (IS_ERR(grf)) {
-               dev_err(dev, "Cannot find GRF syscon\n");
-               return PTR_ERR(grf);
-       }
-
-       rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
-       if (!rk_phy)
-               return -ENOMEM;
-
-       of_id = of_match_device(rockchip_pcie_phy_dt_ids, &pdev->dev);
-       if (!of_id)
-               return -EINVAL;
-
-       rk_phy->phy_data = (struct rockchip_pcie_data *)of_id->data;
-       rk_phy->reg_base = grf;
-
-       rk_phy->phy_rst = devm_reset_control_get(dev, "phy");
-       if (IS_ERR(rk_phy->phy_rst)) {
-               if (PTR_ERR(rk_phy->phy_rst) != -EPROBE_DEFER)
-                       dev_err(dev,
-                               "missing phy property for reset controller\n");
-               return PTR_ERR(rk_phy->phy_rst);
-       }
-
-       rk_phy->clk_pciephy_ref = devm_clk_get(dev, "refclk");
-       if (IS_ERR(rk_phy->clk_pciephy_ref)) {
-               dev_err(dev, "refclk not found.\n");
-               return PTR_ERR(rk_phy->clk_pciephy_ref);
-       }
-
-       generic_phy = devm_phy_create(dev, dev->of_node, &ops);
-       if (IS_ERR(generic_phy)) {
-               dev_err(dev, "failed to create PHY\n");
-               return PTR_ERR(generic_phy);
-       }
-
-       phy_set_drvdata(generic_phy, rk_phy);
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static struct platform_driver rockchip_pcie_driver = {
-       .probe          = rockchip_pcie_phy_probe,
-       .driver         = {
-               .name   = "rockchip-pcie-phy",
-               .of_match_table = rockchip_pcie_phy_dt_ids,
-       },
-};
-
-module_platform_driver(rockchip_pcie_driver);
-
-MODULE_AUTHOR("Shawn Lin <shawn.lin@rock-chips.com>");
-MODULE_DESCRIPTION("Rockchip PCIe PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/phy-rockchip-typec.c
deleted file mode 100644 (file)
index 7cfb0f8..0000000
+++ /dev/null
@@ -1,1023 +0,0 @@
-/*
- * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
- * Author: Chris Zhong <zyw@rock-chips.com>
- *         Kever Yang <kever.yang@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * The ROCKCHIP Type-C PHY has two PLL clocks. The first PLL clock
- * is used for USB3, the second PLL clock is used for DP. This Type-C PHY has
- * 3 working modes: USB3 only mode, DP only mode, and USB3+DP mode.
- * At USB3 only mode, both PLL clocks need to be initialized, this allows the
- * PHY to switch mode between USB3 and USB3+DP, without disconnecting the USB
- * device.
- * In The DP only mode, only the DP PLL needs to be powered on, and the 4 lanes
- * are all used for DP.
- *
- * This driver gets extcon cable state and property, then decides which mode to
- * select:
- *
- * 1. USB3 only mode:
- *    EXTCON_USB or EXTCON_USB_HOST state is true, and
- *    EXTCON_PROP_USB_SS property is true.
- *    EXTCON_DISP_DP state is false.
- *
- * 2. DP only mode:
- *    EXTCON_DISP_DP state is true, and
- *    EXTCON_PROP_USB_SS property is false.
- *    If EXTCON_USB_HOST state is true, it is DP + USB2 mode, since the USB2 phy
- *    is a separate phy, so this case is still DP only mode.
- *
- * 3. USB3+DP mode:
- *    EXTCON_USB_HOST and EXTCON_DISP_DP are both true, and
- *    EXTCON_PROP_USB_SS property is true.
- *
- * This Type-C PHY driver supports normal and flip orientation. The orientation
- * is reported by the EXTCON_PROP_USB_TYPEC_POLARITY property: true is flip
- * orientation, false is normal orientation.
- *
- */
-
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/delay.h>
-#include <linux/extcon.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-#include <linux/reset.h>
-
-#include <linux/mfd/syscon.h>
-#include <linux/phy/phy.h>
-
-#define CMN_SSM_BANDGAP                        (0x21 << 2)
-#define CMN_SSM_BIAS                   (0x22 << 2)
-#define CMN_PLLSM0_PLLEN               (0x29 << 2)
-#define CMN_PLLSM0_PLLPRE              (0x2a << 2)
-#define CMN_PLLSM0_PLLVREF             (0x2b << 2)
-#define CMN_PLLSM0_PLLLOCK             (0x2c << 2)
-#define CMN_PLLSM1_PLLEN               (0x31 << 2)
-#define CMN_PLLSM1_PLLPRE              (0x32 << 2)
-#define CMN_PLLSM1_PLLVREF             (0x33 << 2)
-#define CMN_PLLSM1_PLLLOCK             (0x34 << 2)
-#define CMN_PLLSM1_USER_DEF_CTRL       (0x37 << 2)
-#define CMN_ICAL_OVRD                  (0xc1 << 2)
-#define CMN_PLL0_VCOCAL_OVRD           (0x83 << 2)
-#define CMN_PLL0_VCOCAL_INIT           (0x84 << 2)
-#define CMN_PLL0_VCOCAL_ITER           (0x85 << 2)
-#define CMN_PLL0_LOCK_REFCNT_START     (0x90 << 2)
-#define CMN_PLL0_LOCK_PLLCNT_START     (0x92 << 2)
-#define CMN_PLL0_LOCK_PLLCNT_THR       (0x93 << 2)
-#define CMN_PLL0_INTDIV                        (0x94 << 2)
-#define CMN_PLL0_FRACDIV               (0x95 << 2)
-#define CMN_PLL0_HIGH_THR              (0x96 << 2)
-#define CMN_PLL0_DSM_DIAG              (0x97 << 2)
-#define CMN_PLL0_SS_CTRL1              (0x98 << 2)
-#define CMN_PLL0_SS_CTRL2              (0x99 << 2)
-#define CMN_PLL1_VCOCAL_START          (0xa1 << 2)
-#define CMN_PLL1_VCOCAL_OVRD           (0xa3 << 2)
-#define CMN_PLL1_VCOCAL_INIT           (0xa4 << 2)
-#define CMN_PLL1_VCOCAL_ITER           (0xa5 << 2)
-#define CMN_PLL1_LOCK_REFCNT_START     (0xb0 << 2)
-#define CMN_PLL1_LOCK_PLLCNT_START     (0xb2 << 2)
-#define CMN_PLL1_LOCK_PLLCNT_THR       (0xb3 << 2)
-#define CMN_PLL1_INTDIV                        (0xb4 << 2)
-#define CMN_PLL1_FRACDIV               (0xb5 << 2)
-#define CMN_PLL1_HIGH_THR              (0xb6 << 2)
-#define CMN_PLL1_DSM_DIAG              (0xb7 << 2)
-#define CMN_PLL1_SS_CTRL1              (0xb8 << 2)
-#define CMN_PLL1_SS_CTRL2              (0xb9 << 2)
-#define CMN_RXCAL_OVRD                 (0xd1 << 2)
-#define CMN_TXPUCAL_CTRL               (0xe0 << 2)
-#define CMN_TXPUCAL_OVRD               (0xe1 << 2)
-#define CMN_TXPDCAL_OVRD               (0xf1 << 2)
-#define CMN_DIAG_PLL0_FBH_OVRD         (0x1c0 << 2)
-#define CMN_DIAG_PLL0_FBL_OVRD         (0x1c1 << 2)
-#define CMN_DIAG_PLL0_OVRD             (0x1c2 << 2)
-#define CMN_DIAG_PLL0_V2I_TUNE         (0x1c5 << 2)
-#define CMN_DIAG_PLL0_CP_TUNE          (0x1c6 << 2)
-#define CMN_DIAG_PLL0_LF_PROG          (0x1c7 << 2)
-#define CMN_DIAG_PLL1_FBH_OVRD         (0x1d0 << 2)
-#define CMN_DIAG_PLL1_FBL_OVRD         (0x1d1 << 2)
-#define CMN_DIAG_PLL1_OVRD             (0x1d2 << 2)
-#define CMN_DIAG_PLL1_V2I_TUNE         (0x1d5 << 2)
-#define CMN_DIAG_PLL1_CP_TUNE          (0x1d6 << 2)
-#define CMN_DIAG_PLL1_LF_PROG          (0x1d7 << 2)
-#define CMN_DIAG_PLL1_PTATIS_TUNE1     (0x1d8 << 2)
-#define CMN_DIAG_PLL1_PTATIS_TUNE2     (0x1d9 << 2)
-#define CMN_DIAG_PLL1_INCLK_CTRL       (0x1da << 2)
-#define CMN_DIAG_HSCLK_SEL             (0x1e0 << 2)
-
-#define XCVR_PSM_RCTRL(n)              ((0x4001 | ((n) << 9)) << 2)
-#define XCVR_PSM_CAL_TMR(n)            ((0x4002 | ((n) << 9)) << 2)
-#define XCVR_PSM_A0IN_TMR(n)           ((0x4003 | ((n) << 9)) << 2)
-#define TX_TXCC_CAL_SCLR_MULT(n)       ((0x4047 | ((n) << 9)) << 2)
-#define TX_TXCC_CPOST_MULT_00(n)       ((0x404c | ((n) << 9)) << 2)
-#define TX_TXCC_CPOST_MULT_01(n)       ((0x404d | ((n) << 9)) << 2)
-#define TX_TXCC_CPOST_MULT_10(n)       ((0x404e | ((n) << 9)) << 2)
-#define TX_TXCC_CPOST_MULT_11(n)       ((0x404f | ((n) << 9)) << 2)
-#define TX_TXCC_MGNFS_MULT_000(n)      ((0x4050 | ((n) << 9)) << 2)
-#define TX_TXCC_MGNFS_MULT_001(n)      ((0x4051 | ((n) << 9)) << 2)
-#define TX_TXCC_MGNFS_MULT_010(n)      ((0x4052 | ((n) << 9)) << 2)
-#define TX_TXCC_MGNFS_MULT_011(n)      ((0x4053 | ((n) << 9)) << 2)
-#define TX_TXCC_MGNFS_MULT_100(n)      ((0x4054 | ((n) << 9)) << 2)
-#define TX_TXCC_MGNFS_MULT_101(n)      ((0x4055 | ((n) << 9)) << 2)
-#define TX_TXCC_MGNFS_MULT_110(n)      ((0x4056 | ((n) << 9)) << 2)
-#define TX_TXCC_MGNFS_MULT_111(n)      ((0x4057 | ((n) << 9)) << 2)
-#define XCVR_DIAG_PLLDRC_CTRL(n)       ((0x40e0 | ((n) << 9)) << 2)
-#define XCVR_DIAG_BIDI_CTRL(n)         ((0x40e8 | ((n) << 9)) << 2)
-#define XCVR_DIAG_LANE_FCM_EN_MGN(n)   ((0x40f2 | ((n) << 9)) << 2)
-#define TX_PSC_A0(n)                   ((0x4100 | ((n) << 9)) << 2)
-#define TX_PSC_A1(n)                   ((0x4101 | ((n) << 9)) << 2)
-#define TX_PSC_A2(n)                   ((0x4102 | ((n) << 9)) << 2)
-#define TX_PSC_A3(n)                   ((0x4103 | ((n) << 9)) << 2)
-#define TX_RCVDET_CTRL(n)              ((0x4120 | ((n) << 9)) << 2)
-#define TX_RCVDET_EN_TMR(n)            ((0x4122 | ((n) << 9)) << 2)
-#define TX_RCVDET_ST_TMR(n)            ((0x4123 | ((n) << 9)) << 2)
-#define TX_DIAG_TX_DRV(n)              ((0x41e1 | ((n) << 9)) << 2)
-#define TX_DIAG_BGREF_PREDRV_DELAY     (0x41e7 << 2)
-#define TX_ANA_CTRL_REG_1              (0x5020 << 2)
-#define TX_ANA_CTRL_REG_2              (0x5021 << 2)
-#define TXDA_COEFF_CALC_CTRL           (0x5022 << 2)
-#define TX_DIG_CTRL_REG_2              (0x5024 << 2)
-#define TXDA_CYA_AUXDA_CYA             (0x5025 << 2)
-#define TX_ANA_CTRL_REG_3              (0x5026 << 2)
-#define TX_ANA_CTRL_REG_4              (0x5027 << 2)
-#define TX_ANA_CTRL_REG_5              (0x5029 << 2)
-
-#define RX_PSC_A0(n)                   ((0x8000 | ((n) << 9)) << 2)
-#define RX_PSC_A1(n)                   ((0x8001 | ((n) << 9)) << 2)
-#define RX_PSC_A2(n)                   ((0x8002 | ((n) << 9)) << 2)
-#define RX_PSC_A3(n)                   ((0x8003 | ((n) << 9)) << 2)
-#define RX_PSC_CAL(n)                  ((0x8006 | ((n) << 9)) << 2)
-#define RX_PSC_RDY(n)                  ((0x8007 | ((n) << 9)) << 2)
-#define RX_IQPI_ILL_CAL_OVRD           (0x8023 << 2)
-#define RX_EPI_ILL_CAL_OVRD            (0x8033 << 2)
-#define RX_SDCAL0_OVRD                 (0x8041 << 2)
-#define RX_SDCAL1_OVRD                 (0x8049 << 2)
-#define RX_SLC_INIT                    (0x806d << 2)
-#define RX_SLC_RUN                     (0x806e << 2)
-#define RX_CDRLF_CNFG2                 (0x8081 << 2)
-#define RX_SIGDET_HL_FILT_TMR(n)       ((0x8090 | ((n) << 9)) << 2)
-#define RX_SLC_IOP0_OVRD               (0x8101 << 2)
-#define RX_SLC_IOP1_OVRD               (0x8105 << 2)
-#define RX_SLC_QOP0_OVRD               (0x8109 << 2)
-#define RX_SLC_QOP1_OVRD               (0x810d << 2)
-#define RX_SLC_EOP0_OVRD               (0x8111 << 2)
-#define RX_SLC_EOP1_OVRD               (0x8115 << 2)
-#define RX_SLC_ION0_OVRD               (0x8119 << 2)
-#define RX_SLC_ION1_OVRD               (0x811d << 2)
-#define RX_SLC_QON0_OVRD               (0x8121 << 2)
-#define RX_SLC_QON1_OVRD               (0x8125 << 2)
-#define RX_SLC_EON0_OVRD               (0x8129 << 2)
-#define RX_SLC_EON1_OVRD               (0x812d << 2)
-#define RX_SLC_IEP0_OVRD               (0x8131 << 2)
-#define RX_SLC_IEP1_OVRD               (0x8135 << 2)
-#define RX_SLC_QEP0_OVRD               (0x8139 << 2)
-#define RX_SLC_QEP1_OVRD               (0x813d << 2)
-#define RX_SLC_EEP0_OVRD               (0x8141 << 2)
-#define RX_SLC_EEP1_OVRD               (0x8145 << 2)
-#define RX_SLC_IEN0_OVRD               (0x8149 << 2)
-#define RX_SLC_IEN1_OVRD               (0x814d << 2)
-#define RX_SLC_QEN0_OVRD               (0x8151 << 2)
-#define RX_SLC_QEN1_OVRD               (0x8155 << 2)
-#define RX_SLC_EEN0_OVRD               (0x8159 << 2)
-#define RX_SLC_EEN1_OVRD               (0x815d << 2)
-#define RX_REE_CTRL_DATA_MASK(n)       ((0x81bb | ((n) << 9)) << 2)
-#define RX_DIAG_SIGDET_TUNE(n)         ((0x81dc | ((n) << 9)) << 2)
-#define RX_DIAG_SC2C_DELAY             (0x81e1 << 2)
-
-#define PMA_LANE_CFG                   (0xc000 << 2)
-#define PIPE_CMN_CTRL1                 (0xc001 << 2)
-#define PIPE_CMN_CTRL2                 (0xc002 << 2)
-#define PIPE_COM_LOCK_CFG1             (0xc003 << 2)
-#define PIPE_COM_LOCK_CFG2             (0xc004 << 2)
-#define PIPE_RCV_DET_INH               (0xc005 << 2)
-#define DP_MODE_CTL                    (0xc008 << 2)
-#define DP_CLK_CTL                     (0xc009 << 2)
-#define STS                            (0xc00F << 2)
-#define PHY_ISO_CMN_CTRL               (0xc010 << 2)
-#define PHY_DP_TX_CTL                  (0xc408 << 2)
-#define PMA_CMN_CTRL1                  (0xc800 << 2)
-#define PHY_PMA_ISO_CMN_CTRL           (0xc810 << 2)
-#define PHY_ISOLATION_CTRL             (0xc81f << 2)
-#define PHY_PMA_ISO_XCVR_CTRL(n)       ((0xcc11 | ((n) << 6)) << 2)
-#define PHY_PMA_ISO_LINK_MODE(n)       ((0xcc12 | ((n) << 6)) << 2)
-#define PHY_PMA_ISO_PWRST_CTRL(n)      ((0xcc13 | ((n) << 6)) << 2)
-#define PHY_PMA_ISO_TX_DATA_LO(n)      ((0xcc14 | ((n) << 6)) << 2)
-#define PHY_PMA_ISO_TX_DATA_HI(n)      ((0xcc15 | ((n) << 6)) << 2)
-#define PHY_PMA_ISO_RX_DATA_LO(n)      ((0xcc16 | ((n) << 6)) << 2)
-#define PHY_PMA_ISO_RX_DATA_HI(n)      ((0xcc17 | ((n) << 6)) << 2)
-#define TX_BIST_CTRL(n)                        ((0x4140 | ((n) << 9)) << 2)
-#define TX_BIST_UDDWR(n)               ((0x4141 | ((n) << 9)) << 2)
-
-/*
- * Selects which PLL clock will be driven on the analog high speed
- * clock 0: PLL 0 div 1
- * clock 1: PLL 1 div 2
- */
-#define CLK_PLL_CONFIG                 0X30
-#define CLK_PLL_MASK                   0x33
-
-#define CMN_READY                      BIT(0)
-
-#define DP_PLL_CLOCK_ENABLE            BIT(2)
-#define DP_PLL_ENABLE                  BIT(0)
-#define DP_PLL_DATA_RATE_RBR           ((2 << 12) | (4 << 8))
-#define DP_PLL_DATA_RATE_HBR           ((2 << 12) | (4 << 8))
-#define DP_PLL_DATA_RATE_HBR2          ((1 << 12) | (2 << 8))
-
-#define DP_MODE_A0                     BIT(4)
-#define DP_MODE_A2                     BIT(6)
-#define DP_MODE_ENTER_A0               0xc101
-#define DP_MODE_ENTER_A2               0xc104
-
-#define PHY_MODE_SET_TIMEOUT           100000
-
-#define PIN_ASSIGN_C_E                 0x51d9
-#define PIN_ASSIGN_D_F                 0x5100
-
-#define MODE_DISCONNECT                        0
-#define MODE_UFP_USB                   BIT(0)
-#define MODE_DFP_USB                   BIT(1)
-#define MODE_DFP_DP                    BIT(2)
-
-struct usb3phy_reg {
-       u32 offset;
-       u32 enable_bit;
-       u32 write_enable;
-};
-
-struct rockchip_usb3phy_port_cfg {
-       struct usb3phy_reg typec_conn_dir;
-       struct usb3phy_reg usb3tousb2_en;
-       struct usb3phy_reg external_psm;
-       struct usb3phy_reg pipe_status;
-};
-
-struct rockchip_typec_phy {
-       struct device *dev;
-       void __iomem *base;
-       struct extcon_dev *extcon;
-       struct regmap *grf_regs;
-       struct clk *clk_core;
-       struct clk *clk_ref;
-       struct reset_control *uphy_rst;
-       struct reset_control *pipe_rst;
-       struct reset_control *tcphy_rst;
-       struct rockchip_usb3phy_port_cfg port_cfgs;
-       /* mutex to protect access to individual PHYs */
-       struct mutex lock;
-
-       bool flip;
-       u8 mode;
-};
-
-struct phy_reg {
-       u16 value;
-       u32 addr;
-};
-
-struct phy_reg usb3_pll_cfg[] = {
-       { 0xf0,         CMN_PLL0_VCOCAL_INIT },
-       { 0x18,         CMN_PLL0_VCOCAL_ITER },
-       { 0xd0,         CMN_PLL0_INTDIV },
-       { 0x4a4a,       CMN_PLL0_FRACDIV },
-       { 0x34,         CMN_PLL0_HIGH_THR },
-       { 0x1ee,        CMN_PLL0_SS_CTRL1 },
-       { 0x7f03,       CMN_PLL0_SS_CTRL2 },
-       { 0x20,         CMN_PLL0_DSM_DIAG },
-       { 0,            CMN_DIAG_PLL0_OVRD },
-       { 0,            CMN_DIAG_PLL0_FBH_OVRD },
-       { 0,            CMN_DIAG_PLL0_FBL_OVRD },
-       { 0x7,          CMN_DIAG_PLL0_V2I_TUNE },
-       { 0x45,         CMN_DIAG_PLL0_CP_TUNE },
-       { 0x8,          CMN_DIAG_PLL0_LF_PROG },
-};
-
-struct phy_reg dp_pll_cfg[] = {
-       { 0xf0,         CMN_PLL1_VCOCAL_INIT },
-       { 0x18,         CMN_PLL1_VCOCAL_ITER },
-       { 0x30b9,       CMN_PLL1_VCOCAL_START },
-       { 0x21c,        CMN_PLL1_INTDIV },
-       { 0,            CMN_PLL1_FRACDIV },
-       { 0x5,          CMN_PLL1_HIGH_THR },
-       { 0x35,         CMN_PLL1_SS_CTRL1 },
-       { 0x7f1e,       CMN_PLL1_SS_CTRL2 },
-       { 0x20,         CMN_PLL1_DSM_DIAG },
-       { 0,            CMN_PLLSM1_USER_DEF_CTRL },
-       { 0,            CMN_DIAG_PLL1_OVRD },
-       { 0,            CMN_DIAG_PLL1_FBH_OVRD },
-       { 0,            CMN_DIAG_PLL1_FBL_OVRD },
-       { 0x6,          CMN_DIAG_PLL1_V2I_TUNE },
-       { 0x45,         CMN_DIAG_PLL1_CP_TUNE },
-       { 0x8,          CMN_DIAG_PLL1_LF_PROG },
-       { 0x100,        CMN_DIAG_PLL1_PTATIS_TUNE1 },
-       { 0x7,          CMN_DIAG_PLL1_PTATIS_TUNE2 },
-       { 0x4,          CMN_DIAG_PLL1_INCLK_CTRL },
-};
-
-static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy)
-{
-       u32 i, rdata;
-
-       /*
-        * cmn_ref_clk_sel = 3, select the 24Mhz for clk parent
-        * cmn_psm_clk_dig_div = 2, set the clk division to 2
-        */
-       writel(0x830, tcphy->base + PMA_CMN_CTRL1);
-       for (i = 0; i < 4; i++) {
-               /*
-                * The following PHY configuration assumes a 24 MHz reference
-                * clock.
-                */
-               writel(0x90, tcphy->base + XCVR_DIAG_LANE_FCM_EN_MGN(i));
-               writel(0x960, tcphy->base + TX_RCVDET_EN_TMR(i));
-               writel(0x30, tcphy->base + TX_RCVDET_ST_TMR(i));
-       }
-
-       rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
-       rdata &= ~CLK_PLL_MASK;
-       rdata |= CLK_PLL_CONFIG;
-       writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
-}
-
-static void tcphy_cfg_usb3_pll(struct rockchip_typec_phy *tcphy)
-{
-       u32 i;
-
-       /* load the configuration of PLL0 */
-       for (i = 0; i < ARRAY_SIZE(usb3_pll_cfg); i++)
-               writel(usb3_pll_cfg[i].value,
-                      tcphy->base + usb3_pll_cfg[i].addr);
-}
-
-static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
-{
-       u32 i;
-
-       /* set the default mode to RBR */
-       writel(DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE | DP_PLL_DATA_RATE_RBR,
-              tcphy->base + DP_CLK_CTL);
-
-       /* load the configuration of PLL1 */
-       for (i = 0; i < ARRAY_SIZE(dp_pll_cfg); i++)
-               writel(dp_pll_cfg[i].value, tcphy->base + dp_pll_cfg[i].addr);
-}
-
-static void tcphy_tx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
-{
-       writel(0x7799, tcphy->base + TX_PSC_A0(lane));
-       writel(0x7798, tcphy->base + TX_PSC_A1(lane));
-       writel(0x5098, tcphy->base + TX_PSC_A2(lane));
-       writel(0x5098, tcphy->base + TX_PSC_A3(lane));
-       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
-       writel(0xbf, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
-}
-
-static void tcphy_rx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
-{
-       writel(0xa6fd, tcphy->base + RX_PSC_A0(lane));
-       writel(0xa6fd, tcphy->base + RX_PSC_A1(lane));
-       writel(0xa410, tcphy->base + RX_PSC_A2(lane));
-       writel(0x2410, tcphy->base + RX_PSC_A3(lane));
-       writel(0x23ff, tcphy->base + RX_PSC_CAL(lane));
-       writel(0x13, tcphy->base + RX_SIGDET_HL_FILT_TMR(lane));
-       writel(0x03e7, tcphy->base + RX_REE_CTRL_DATA_MASK(lane));
-       writel(0x1004, tcphy->base + RX_DIAG_SIGDET_TUNE(lane));
-       writel(0x2010, tcphy->base + RX_PSC_RDY(lane));
-       writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
-}
-
-static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
-{
-       u16 rdata;
-
-       writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
-       writel(0x6799, tcphy->base + TX_PSC_A0(lane));
-       writel(0x6798, tcphy->base + TX_PSC_A1(lane));
-       writel(0x98, tcphy->base + TX_PSC_A2(lane));
-       writel(0x98, tcphy->base + TX_PSC_A3(lane));
-
-       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
-       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
-       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
-       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
-       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
-       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
-       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
-       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
-       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
-       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
-       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
-       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
-
-       writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
-       writel(0x400, tcphy->base + TX_DIAG_TX_DRV(lane));
-
-       rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
-       rdata = (rdata & 0x8fff) | 0x6000;
-       writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
-}
-
-static inline int property_enable(struct rockchip_typec_phy *tcphy,
-                                 const struct usb3phy_reg *reg, bool en)
-{
-       u32 mask = 1 << reg->write_enable;
-       u32 val = en << reg->enable_bit;
-
-       return regmap_write(tcphy->grf_regs, reg->offset, val | mask);
-}
-
-static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
-{
-       u16 rdata, rdata2, val;
-
-       /* disable txda_cal_latch_en for rewrite the calibration values */
-       rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
-       val = rdata & 0xdfff;
-       writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
-
-       /*
-        * read a resistor calibration code from CMN_TXPUCAL_CTRL[6:0] and
-        * write it to TX_DIG_CTRL_REG_2[6:0], and delay 1ms to make sure it
-        * works.
-        */
-       rdata = readl(tcphy->base + TX_DIG_CTRL_REG_2);
-       rdata = rdata & 0xffc0;
-
-       rdata2 = readl(tcphy->base + CMN_TXPUCAL_CTRL);
-       rdata2 = rdata2 & 0x3f;
-
-       val = rdata | rdata2;
-       writel(val, tcphy->base + TX_DIG_CTRL_REG_2);
-       usleep_range(1000, 1050);
-
-       /*
-        * Enable signal for latch that sample and holds calibration values.
-        * Activate this signal for 1 clock cycle to sample new calibration
-        * values.
-        */
-       rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
-       val = rdata | 0x2000;
-       writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
-       usleep_range(150, 200);
-
-       /* set TX Voltage Level and TX Deemphasis to 0 */
-       writel(0, tcphy->base + PHY_DP_TX_CTL);
-       /* re-enable decap */
-       writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2);
-       writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2);
-       writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1);
-       writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1);
-
-       writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
-
-       /*
-        * Programs txda_drv_ldo_prog[15:0], Sets driver LDO
-        * voltage 16'h1001 for DP-AUX-TX and RX
-        */
-       writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4);
-
-       /* re-enables Bandgap reference for LDO */
-       writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1);
-       writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1);
-
-       /*
-        * re-enables the transmitter pre-driver, driver data selection MUX,
-        * and receiver detect circuits.
-        */
-       writel(0x301, tcphy->base + TX_ANA_CTRL_REG_2);
-       writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2);
-
-       /*
-        * BIT 12: Controls auxda_polarity, which selects the polarity of the
-        * xcvr:
-        * 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull
-        * down aux_m)
-        * 0, Normal polarity (if TYPE_C, pulls up aux_m and pulls down
-        * aux_p)
-        */
-       val = 0xa078;
-       if (!tcphy->flip)
-               val |= BIT(12);
-       writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
-
-       writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
-       writel(0, tcphy->base + TX_ANA_CTRL_REG_4);
-       writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
-
-       /*
-        * Controls low_power_swing_en, set the voltage swing of the driver
-        * to 400mv. The values below are peak to peak (differential) values.
-        */
-       writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL);
-       writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA);
-
-       /* Controls tx_high_z_tm_en */
-       val = readl(tcphy->base + TX_DIG_CTRL_REG_2);
-       val |= BIT(15);
-       writel(val, tcphy->base + TX_DIG_CTRL_REG_2);
-}
-
-static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
-{
-       struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs;
-       int ret, i;
-       u32 val;
-
-       ret = clk_prepare_enable(tcphy->clk_core);
-       if (ret) {
-               dev_err(tcphy->dev, "Failed to prepare_enable core clock\n");
-               return ret;
-       }
-
-       ret = clk_prepare_enable(tcphy->clk_ref);
-       if (ret) {
-               dev_err(tcphy->dev, "Failed to prepare_enable ref clock\n");
-               goto err_clk_core;
-       }
-
-       reset_control_deassert(tcphy->tcphy_rst);
-
-       property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip);
-
-       tcphy_cfg_24m(tcphy);
-
-       if (mode == MODE_DFP_DP) {
-               tcphy_cfg_dp_pll(tcphy);
-               for (i = 0; i < 4; i++)
-                       tcphy_dp_cfg_lane(tcphy, i);
-
-               writel(PIN_ASSIGN_C_E, tcphy->base + PMA_LANE_CFG);
-       } else {
-               tcphy_cfg_usb3_pll(tcphy);
-               tcphy_cfg_dp_pll(tcphy);
-               if (tcphy->flip) {
-                       tcphy_tx_usb3_cfg_lane(tcphy, 3);
-                       tcphy_rx_usb3_cfg_lane(tcphy, 2);
-                       tcphy_dp_cfg_lane(tcphy, 0);
-                       tcphy_dp_cfg_lane(tcphy, 1);
-               } else {
-                       tcphy_tx_usb3_cfg_lane(tcphy, 0);
-                       tcphy_rx_usb3_cfg_lane(tcphy, 1);
-                       tcphy_dp_cfg_lane(tcphy, 2);
-                       tcphy_dp_cfg_lane(tcphy, 3);
-               }
-
-               writel(PIN_ASSIGN_D_F, tcphy->base + PMA_LANE_CFG);
-       }
-
-       writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
-
-       reset_control_deassert(tcphy->uphy_rst);
-
-       ret = readx_poll_timeout(readl, tcphy->base + PMA_CMN_CTRL1,
-                                val, val & CMN_READY, 10,
-                                PHY_MODE_SET_TIMEOUT);
-       if (ret < 0) {
-               dev_err(tcphy->dev, "wait pma ready timeout\n");
-               ret = -ETIMEDOUT;
-               goto err_wait_pma;
-       }
-
-       reset_control_deassert(tcphy->pipe_rst);
-
-       return 0;
-
-err_wait_pma:
-       reset_control_assert(tcphy->uphy_rst);
-       reset_control_assert(tcphy->tcphy_rst);
-       clk_disable_unprepare(tcphy->clk_ref);
-err_clk_core:
-       clk_disable_unprepare(tcphy->clk_core);
-       return ret;
-}
-
-static void tcphy_phy_deinit(struct rockchip_typec_phy *tcphy)
-{
-       reset_control_assert(tcphy->tcphy_rst);
-       reset_control_assert(tcphy->uphy_rst);
-       reset_control_assert(tcphy->pipe_rst);
-       clk_disable_unprepare(tcphy->clk_core);
-       clk_disable_unprepare(tcphy->clk_ref);
-}
-
-static int tcphy_get_mode(struct rockchip_typec_phy *tcphy)
-{
-       struct extcon_dev *edev = tcphy->extcon;
-       union extcon_property_value property;
-       unsigned int id;
-       bool dfp, ufp, dp;
-       u8 mode;
-       int ret;
-
-       ufp = extcon_get_state(edev, EXTCON_USB);
-       dfp = extcon_get_state(edev, EXTCON_USB_HOST);
-       dp = extcon_get_state(edev, EXTCON_DISP_DP);
-
-       mode = MODE_DFP_USB;
-       id = EXTCON_USB_HOST;
-
-       if (ufp) {
-               mode = MODE_UFP_USB;
-               id = EXTCON_USB;
-       } else if (dp) {
-               mode = MODE_DFP_DP;
-               id = EXTCON_DISP_DP;
-
-               ret = extcon_get_property(edev, id, EXTCON_PROP_USB_SS,
-                                         &property);
-               if (ret) {
-                       dev_err(tcphy->dev, "get superspeed property failed\n");
-                       return ret;
-               }
-
-               if (property.intval)
-                       mode |= MODE_DFP_USB;
-       }
-
-       ret = extcon_get_property(edev, id, EXTCON_PROP_USB_TYPEC_POLARITY,
-                                 &property);
-       if (ret) {
-               dev_err(tcphy->dev, "get polarity property failed\n");
-               return ret;
-       }
-
-       tcphy->flip = property.intval ? 1 : 0;
-
-       return mode;
-}
-
-static int rockchip_usb3_phy_power_on(struct phy *phy)
-{
-       struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
-       struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs;
-       const struct usb3phy_reg *reg = &cfg->pipe_status;
-       int timeout, new_mode, ret = 0;
-       u32 val;
-
-       mutex_lock(&tcphy->lock);
-
-       new_mode = tcphy_get_mode(tcphy);
-       if (new_mode < 0) {
-               ret = new_mode;
-               goto unlock_ret;
-       }
-
-       /* DP-only mode; fall back to USB2 */
-       if (!(new_mode & (MODE_DFP_USB | MODE_UFP_USB)))
-               goto unlock_ret;
-
-       if (tcphy->mode == new_mode)
-               goto unlock_ret;
-
-       if (tcphy->mode == MODE_DISCONNECT)
-               tcphy_phy_init(tcphy, new_mode);
-
-       /* wait TCPHY for pipe ready */
-       for (timeout = 0; timeout < 100; timeout++) {
-               regmap_read(tcphy->grf_regs, reg->offset, &val);
-               if (!(val & BIT(reg->enable_bit))) {
-                       tcphy->mode |= new_mode & (MODE_DFP_USB | MODE_UFP_USB);
-                       goto unlock_ret;
-               }
-               usleep_range(10, 20);
-       }
-
-       if (tcphy->mode == MODE_DISCONNECT)
-               tcphy_phy_deinit(tcphy);
-
-       ret = -ETIMEDOUT;
-
-unlock_ret:
-       mutex_unlock(&tcphy->lock);
-       return ret;
-}
-
-static int rockchip_usb3_phy_power_off(struct phy *phy)
-{
-       struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
-
-       mutex_lock(&tcphy->lock);
-
-       if (tcphy->mode == MODE_DISCONNECT)
-               goto unlock;
-
-       tcphy->mode &= ~(MODE_UFP_USB | MODE_DFP_USB);
-       if (tcphy->mode == MODE_DISCONNECT)
-               tcphy_phy_deinit(tcphy);
-
-unlock:
-       mutex_unlock(&tcphy->lock);
-       return 0;
-}
-
-static const struct phy_ops rockchip_usb3_phy_ops = {
-       .power_on       = rockchip_usb3_phy_power_on,
-       .power_off      = rockchip_usb3_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static int rockchip_dp_phy_power_on(struct phy *phy)
-{
-       struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
-       int new_mode, ret = 0;
-       u32 val;
-
-       mutex_lock(&tcphy->lock);
-
-       new_mode = tcphy_get_mode(tcphy);
-       if (new_mode < 0) {
-               ret = new_mode;
-               goto unlock_ret;
-       }
-
-       if (!(new_mode & MODE_DFP_DP)) {
-               ret = -ENODEV;
-               goto unlock_ret;
-       }
-
-       if (tcphy->mode == new_mode)
-               goto unlock_ret;
-
-       /*
-        * If the PHY has been power on, but the mode is not DP only mode,
-        * re-init the PHY for setting all of 4 lanes to DP.
-        */
-       if (new_mode == MODE_DFP_DP && tcphy->mode != MODE_DISCONNECT) {
-               tcphy_phy_deinit(tcphy);
-               tcphy_phy_init(tcphy, new_mode);
-       } else if (tcphy->mode == MODE_DISCONNECT) {
-               tcphy_phy_init(tcphy, new_mode);
-       }
-
-       ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
-                                val, val & DP_MODE_A2, 1000,
-                                PHY_MODE_SET_TIMEOUT);
-       if (ret < 0) {
-               dev_err(tcphy->dev, "failed to wait TCPHY enter A2\n");
-               goto power_on_finish;
-       }
-
-       tcphy_dp_aux_calibration(tcphy);
-
-       writel(DP_MODE_ENTER_A0, tcphy->base + DP_MODE_CTL);
-
-       ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
-                                val, val & DP_MODE_A0, 1000,
-                                PHY_MODE_SET_TIMEOUT);
-       if (ret < 0) {
-               writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
-               dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
-               goto power_on_finish;
-       }
-
-       tcphy->mode |= MODE_DFP_DP;
-
-power_on_finish:
-       if (tcphy->mode == MODE_DISCONNECT)
-               tcphy_phy_deinit(tcphy);
-unlock_ret:
-       mutex_unlock(&tcphy->lock);
-       return ret;
-}
-
-static int rockchip_dp_phy_power_off(struct phy *phy)
-{
-       struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
-
-       mutex_lock(&tcphy->lock);
-
-       if (tcphy->mode == MODE_DISCONNECT)
-               goto unlock;
-
-       tcphy->mode &= ~MODE_DFP_DP;
-
-       writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
-
-       if (tcphy->mode == MODE_DISCONNECT)
-               tcphy_phy_deinit(tcphy);
-
-unlock:
-       mutex_unlock(&tcphy->lock);
-       return 0;
-}
-
-static const struct phy_ops rockchip_dp_phy_ops = {
-       .power_on       = rockchip_dp_phy_power_on,
-       .power_off      = rockchip_dp_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static int tcphy_get_param(struct device *dev,
-                          struct usb3phy_reg *reg,
-                          const char *name)
-{
-       u32 buffer[3];
-       int ret;
-
-       ret = of_property_read_u32_array(dev->of_node, name, buffer, 3);
-       if (ret) {
-               dev_err(dev, "Can not parse %s\n", name);
-               return ret;
-       }
-
-       reg->offset = buffer[0];
-       reg->enable_bit = buffer[1];
-       reg->write_enable = buffer[2];
-       return 0;
-}
-
-static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
-                         struct device *dev)
-{
-       struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs;
-       int ret;
-
-       ret = tcphy_get_param(dev, &cfg->typec_conn_dir,
-                             "rockchip,typec-conn-dir");
-       if (ret)
-               return ret;
-
-       ret = tcphy_get_param(dev, &cfg->usb3tousb2_en,
-                             "rockchip,usb3tousb2-en");
-       if (ret)
-               return ret;
-
-       ret = tcphy_get_param(dev, &cfg->external_psm,
-                             "rockchip,external-psm");
-       if (ret)
-               return ret;
-
-       ret = tcphy_get_param(dev, &cfg->pipe_status,
-                             "rockchip,pipe-status");
-       if (ret)
-               return ret;
-
-       tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node,
-                                                         "rockchip,grf");
-       if (IS_ERR(tcphy->grf_regs)) {
-               dev_err(dev, "could not find grf dt node\n");
-               return PTR_ERR(tcphy->grf_regs);
-       }
-
-       tcphy->clk_core = devm_clk_get(dev, "tcpdcore");
-       if (IS_ERR(tcphy->clk_core)) {
-               dev_err(dev, "could not get uphy core clock\n");
-               return PTR_ERR(tcphy->clk_core);
-       }
-
-       tcphy->clk_ref = devm_clk_get(dev, "tcpdphy-ref");
-       if (IS_ERR(tcphy->clk_ref)) {
-               dev_err(dev, "could not get uphy ref clock\n");
-               return PTR_ERR(tcphy->clk_ref);
-       }
-
-       tcphy->uphy_rst = devm_reset_control_get(dev, "uphy");
-       if (IS_ERR(tcphy->uphy_rst)) {
-               dev_err(dev, "no uphy_rst reset control found\n");
-               return PTR_ERR(tcphy->uphy_rst);
-       }
-
-       tcphy->pipe_rst = devm_reset_control_get(dev, "uphy-pipe");
-       if (IS_ERR(tcphy->pipe_rst)) {
-               dev_err(dev, "no pipe_rst reset control found\n");
-               return PTR_ERR(tcphy->pipe_rst);
-       }
-
-       tcphy->tcphy_rst = devm_reset_control_get(dev, "uphy-tcphy");
-       if (IS_ERR(tcphy->tcphy_rst)) {
-               dev_err(dev, "no tcphy_rst reset control found\n");
-               return PTR_ERR(tcphy->tcphy_rst);
-       }
-
-       return 0;
-}
-
-static void typec_phy_pre_init(struct rockchip_typec_phy *tcphy)
-{
-       struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs;
-
-       reset_control_assert(tcphy->tcphy_rst);
-       reset_control_assert(tcphy->uphy_rst);
-       reset_control_assert(tcphy->pipe_rst);
-
-       /* select external psm clock */
-       property_enable(tcphy, &cfg->external_psm, 1);
-       property_enable(tcphy, &cfg->usb3tousb2_en, 0);
-
-       tcphy->mode = MODE_DISCONNECT;
-}
-
-static int rockchip_typec_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct device_node *child_np;
-       struct rockchip_typec_phy *tcphy;
-       struct phy_provider *phy_provider;
-       struct resource *res;
-       int ret;
-
-       tcphy = devm_kzalloc(dev, sizeof(*tcphy), GFP_KERNEL);
-       if (!tcphy)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       tcphy->base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(tcphy->base))
-               return PTR_ERR(tcphy->base);
-
-       ret = tcphy_parse_dt(tcphy, dev);
-       if (ret)
-               return ret;
-
-       tcphy->dev = dev;
-       platform_set_drvdata(pdev, tcphy);
-       mutex_init(&tcphy->lock);
-
-       typec_phy_pre_init(tcphy);
-
-       tcphy->extcon = extcon_get_edev_by_phandle(dev, 0);
-       if (IS_ERR(tcphy->extcon)) {
-               if (PTR_ERR(tcphy->extcon) != -EPROBE_DEFER)
-                       dev_err(dev, "Invalid or missing extcon\n");
-               return PTR_ERR(tcphy->extcon);
-       }
-
-       pm_runtime_enable(dev);
-
-       for_each_available_child_of_node(np, child_np) {
-               struct phy *phy;
-
-               if (!of_node_cmp(child_np->name, "dp-port"))
-                       phy = devm_phy_create(dev, child_np,
-                                             &rockchip_dp_phy_ops);
-               else if (!of_node_cmp(child_np->name, "usb3-port"))
-                       phy = devm_phy_create(dev, child_np,
-                                             &rockchip_usb3_phy_ops);
-               else
-                       continue;
-
-               if (IS_ERR(phy)) {
-                       dev_err(dev, "failed to create phy: %s\n",
-                               child_np->name);
-                       return PTR_ERR(phy);
-               }
-
-               phy_set_drvdata(phy, tcphy);
-       }
-
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (IS_ERR(phy_provider)) {
-               dev_err(dev, "Failed to register phy provider\n");
-               return PTR_ERR(phy_provider);
-       }
-
-       return 0;
-}
-
-static int rockchip_typec_phy_remove(struct platform_device *pdev)
-{
-       pm_runtime_disable(&pdev->dev);
-
-       return 0;
-}
-
-static const struct of_device_id rockchip_typec_phy_dt_ids[] = {
-       { .compatible = "rockchip,rk3399-typec-phy" },
-       {}
-};
-
-MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids);
-
-static struct platform_driver rockchip_typec_phy_driver = {
-       .probe          = rockchip_typec_phy_probe,
-       .remove         = rockchip_typec_phy_remove,
-       .driver         = {
-               .name   = "rockchip-typec-phy",
-               .of_match_table = rockchip_typec_phy_dt_ids,
-       },
-};
-
-module_platform_driver(rockchip_typec_phy_driver);
-
-MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
-MODULE_AUTHOR("Kever Yang <kever.yang@rock-chips.com>");
-MODULE_DESCRIPTION("Rockchip USB TYPE-C PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
deleted file mode 100644 (file)
index 3378eeb..0000000
+++ /dev/null
@@ -1,540 +0,0 @@
-/*
- * Rockchip usb PHY driver
- *
- * Copyright (C) 2014 Yunzhi Li <lyz@rock-chips.com>
- * Copyright (C) 2014 ROCKCHIP, 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; either version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/reset.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-#include <linux/delay.h>
-
-static int enable_usb_uart;
-
-#define HIWORD_UPDATE(val, mask) \
-               ((val) | (mask) << 16)
-
-#define UOC_CON0_SIDDQ BIT(13)
-
-struct rockchip_usb_phys {
-       int reg;
-       const char *pll_name;
-};
-
-struct rockchip_usb_phy_base;
-struct rockchip_usb_phy_pdata {
-       struct rockchip_usb_phys *phys;
-       int (*init_usb_uart)(struct regmap *grf);
-       int usb_uart_phy;
-};
-
-struct rockchip_usb_phy_base {
-       struct device *dev;
-       struct regmap *reg_base;
-       const struct rockchip_usb_phy_pdata *pdata;
-};
-
-struct rockchip_usb_phy {
-       struct rockchip_usb_phy_base *base;
-       struct device_node *np;
-       unsigned int    reg_offset;
-       struct clk      *clk;
-       struct clk      *clk480m;
-       struct clk_hw   clk480m_hw;
-       struct phy      *phy;
-       bool            uart_enabled;
-       struct reset_control *reset;
-       struct regulator *vbus;
-};
-
-static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
-                                          bool siddq)
-{
-       u32 val = HIWORD_UPDATE(siddq ? UOC_CON0_SIDDQ : 0, UOC_CON0_SIDDQ);
-
-       return regmap_write(phy->base->reg_base, phy->reg_offset, val);
-}
-
-static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
-                                               unsigned long parent_rate)
-{
-       return 480000000;
-}
-
-static void rockchip_usb_phy480m_disable(struct clk_hw *hw)
-{
-       struct rockchip_usb_phy *phy = container_of(hw,
-                                                   struct rockchip_usb_phy,
-                                                   clk480m_hw);
-
-       if (phy->vbus)
-               regulator_disable(phy->vbus);
-
-       /* Power down usb phy analog blocks by set siddq 1 */
-       rockchip_usb_phy_power(phy, 1);
-}
-
-static int rockchip_usb_phy480m_enable(struct clk_hw *hw)
-{
-       struct rockchip_usb_phy *phy = container_of(hw,
-                                                   struct rockchip_usb_phy,
-                                                   clk480m_hw);
-
-       /* Power up usb phy analog blocks by set siddq 0 */
-       return rockchip_usb_phy_power(phy, 0);
-}
-
-static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
-{
-       struct rockchip_usb_phy *phy = container_of(hw,
-                                                   struct rockchip_usb_phy,
-                                                   clk480m_hw);
-       int ret;
-       u32 val;
-
-       ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val);
-       if (ret < 0)
-               return ret;
-
-       return (val & UOC_CON0_SIDDQ) ? 0 : 1;
-}
-
-static const struct clk_ops rockchip_usb_phy480m_ops = {
-       .enable = rockchip_usb_phy480m_enable,
-       .disable = rockchip_usb_phy480m_disable,
-       .is_enabled = rockchip_usb_phy480m_is_enabled,
-       .recalc_rate = rockchip_usb_phy480m_recalc_rate,
-};
-
-static int rockchip_usb_phy_power_off(struct phy *_phy)
-{
-       struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
-
-       if (phy->uart_enabled)
-               return -EBUSY;
-
-       clk_disable_unprepare(phy->clk480m);
-
-       return 0;
-}
-
-static int rockchip_usb_phy_power_on(struct phy *_phy)
-{
-       struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
-
-       if (phy->uart_enabled)
-               return -EBUSY;
-
-       if (phy->vbus) {
-               int ret;
-
-               ret = regulator_enable(phy->vbus);
-               if (ret)
-                       return ret;
-       }
-
-       return clk_prepare_enable(phy->clk480m);
-}
-
-static int rockchip_usb_phy_reset(struct phy *_phy)
-{
-       struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
-
-       if (phy->reset) {
-               reset_control_assert(phy->reset);
-               udelay(10);
-               reset_control_deassert(phy->reset);
-       }
-
-       return 0;
-}
-
-static const struct phy_ops ops = {
-       .power_on       = rockchip_usb_phy_power_on,
-       .power_off      = rockchip_usb_phy_power_off,
-       .reset          = rockchip_usb_phy_reset,
-       .owner          = THIS_MODULE,
-};
-
-static void rockchip_usb_phy_action(void *data)
-{
-       struct rockchip_usb_phy *rk_phy = data;
-
-       if (!rk_phy->uart_enabled) {
-               of_clk_del_provider(rk_phy->np);
-               clk_unregister(rk_phy->clk480m);
-       }
-
-       if (rk_phy->clk)
-               clk_put(rk_phy->clk);
-}
-
-static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
-                                struct device_node *child)
-{
-       struct rockchip_usb_phy *rk_phy;
-       unsigned int reg_offset;
-       const char *clk_name;
-       struct clk_init_data init;
-       int err, i;
-
-       rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
-       if (!rk_phy)
-               return -ENOMEM;
-
-       rk_phy->base = base;
-       rk_phy->np = child;
-
-       if (of_property_read_u32(child, "reg", &reg_offset)) {
-               dev_err(base->dev, "missing reg property in node %s\n",
-                       child->name);
-               return -EINVAL;
-       }
-
-       rk_phy->reset = of_reset_control_get(child, "phy-reset");
-       if (IS_ERR(rk_phy->reset))
-               rk_phy->reset = NULL;
-
-       rk_phy->reg_offset = reg_offset;
-
-       rk_phy->clk = of_clk_get_by_name(child, "phyclk");
-       if (IS_ERR(rk_phy->clk))
-               rk_phy->clk = NULL;
-
-       i = 0;
-       init.name = NULL;
-       while (base->pdata->phys[i].reg) {
-               if (base->pdata->phys[i].reg == reg_offset) {
-                       init.name = base->pdata->phys[i].pll_name;
-                       break;
-               }
-               i++;
-       }
-
-       if (!init.name) {
-               dev_err(base->dev, "phy data not found\n");
-               return -EINVAL;
-       }
-
-       if (enable_usb_uart && base->pdata->usb_uart_phy == i) {
-               dev_dbg(base->dev, "phy%d used as uart output\n", i);
-               rk_phy->uart_enabled = true;
-       } else {
-               if (rk_phy->clk) {
-                       clk_name = __clk_get_name(rk_phy->clk);
-                       init.flags = 0;
-                       init.parent_names = &clk_name;
-                       init.num_parents = 1;
-               } else {
-                       init.flags = 0;
-                       init.parent_names = NULL;
-                       init.num_parents = 0;
-               }
-
-               init.ops = &rockchip_usb_phy480m_ops;
-               rk_phy->clk480m_hw.init = &init;
-
-               rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
-               if (IS_ERR(rk_phy->clk480m)) {
-                       err = PTR_ERR(rk_phy->clk480m);
-                       goto err_clk;
-               }
-
-               err = of_clk_add_provider(child, of_clk_src_simple_get,
-                                       rk_phy->clk480m);
-               if (err < 0)
-                       goto err_clk_prov;
-       }
-
-       err = devm_add_action_or_reset(base->dev, rockchip_usb_phy_action,
-                                      rk_phy);
-       if (err)
-               return err;
-
-       rk_phy->phy = devm_phy_create(base->dev, child, &ops);
-       if (IS_ERR(rk_phy->phy)) {
-               dev_err(base->dev, "failed to create PHY\n");
-               return PTR_ERR(rk_phy->phy);
-       }
-       phy_set_drvdata(rk_phy->phy, rk_phy);
-
-       rk_phy->vbus = devm_regulator_get_optional(&rk_phy->phy->dev, "vbus");
-       if (IS_ERR(rk_phy->vbus)) {
-               if (PTR_ERR(rk_phy->vbus) == -EPROBE_DEFER)
-                       return PTR_ERR(rk_phy->vbus);
-               rk_phy->vbus = NULL;
-       }
-
-       /*
-        * When acting as uart-pipe, just keep clock on otherwise
-        * only power up usb phy when it use, so disable it when init
-        */
-       if (rk_phy->uart_enabled)
-               return clk_prepare_enable(rk_phy->clk);
-       else
-               return rockchip_usb_phy_power(rk_phy, 1);
-
-err_clk_prov:
-       if (!rk_phy->uart_enabled)
-               clk_unregister(rk_phy->clk480m);
-err_clk:
-       if (rk_phy->clk)
-               clk_put(rk_phy->clk);
-       return err;
-}
-
-static const struct rockchip_usb_phy_pdata rk3066a_pdata = {
-       .phys = (struct rockchip_usb_phys[]){
-               { .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" },
-               { .reg = 0x188, .pll_name = "sclk_otgphy1_480m" },
-               { /* sentinel */ }
-       },
-};
-
-static const struct rockchip_usb_phy_pdata rk3188_pdata = {
-       .phys = (struct rockchip_usb_phys[]){
-               { .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" },
-               { .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" },
-               { /* sentinel */ }
-       },
-};
-
-#define RK3288_UOC0_CON0                               0x320
-#define RK3288_UOC0_CON0_COMMON_ON_N                   BIT(0)
-#define RK3288_UOC0_CON0_DISABLE                       BIT(4)
-
-#define RK3288_UOC0_CON2                               0x328
-#define RK3288_UOC0_CON2_SOFT_CON_SEL                  BIT(2)
-
-#define RK3288_UOC0_CON3                               0x32c
-#define RK3288_UOC0_CON3_UTMI_SUSPENDN                 BIT(0)
-#define RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING         (1 << 1)
-#define RK3288_UOC0_CON3_UTMI_OPMODE_MASK              (3 << 1)
-#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC      (1 << 3)
-#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK          (3 << 3)
-#define RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED                BIT(5)
-#define RK3288_UOC0_CON3_BYPASSDMEN                    BIT(6)
-#define RK3288_UOC0_CON3_BYPASSSEL                     BIT(7)
-
-/*
- * Enable the bypass of uart2 data through the otg usb phy.
- * Original description in the TRM.
- * 1. Disable the OTG block by setting OTGDISABLE0 to 1’b1.
- * 2. Disable the pull-up resistance on the D+ line by setting
- *    OPMODE0[1:0] to 2’b01.
- * 3. To ensure that the XO, Bias, and PLL blocks are powered down in Suspend
- *    mode, set COMMONONN to 1’b1.
- * 4. Place the USB PHY in Suspend mode by setting SUSPENDM0 to 1’b0.
- * 5. Set BYPASSSEL0 to 1’b1.
- * 6. To transmit data, controls BYPASSDMEN0, and BYPASSDMDATA0.
- * To receive data, monitor FSVPLUS0.
- *
- * The actual code in the vendor kernel does some things differently.
- */
-static int __init rk3288_init_usb_uart(struct regmap *grf)
-{
-       u32 val;
-       int ret;
-
-       /*
-        * COMMON_ON and DISABLE settings are described in the TRM,
-        * but were not present in the original code.
-        * Also disable the analog phy components to save power.
-        */
-       val = HIWORD_UPDATE(RK3288_UOC0_CON0_COMMON_ON_N
-                               | RK3288_UOC0_CON0_DISABLE
-                               | UOC_CON0_SIDDQ,
-                           RK3288_UOC0_CON0_COMMON_ON_N
-                               | RK3288_UOC0_CON0_DISABLE
-                               | UOC_CON0_SIDDQ);
-       ret = regmap_write(grf, RK3288_UOC0_CON0, val);
-       if (ret)
-               return ret;
-
-       val = HIWORD_UPDATE(RK3288_UOC0_CON2_SOFT_CON_SEL,
-                           RK3288_UOC0_CON2_SOFT_CON_SEL);
-       ret = regmap_write(grf, RK3288_UOC0_CON2, val);
-       if (ret)
-               return ret;
-
-       val = HIWORD_UPDATE(RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING
-                               | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC
-                               | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED,
-                           RK3288_UOC0_CON3_UTMI_SUSPENDN
-                               | RK3288_UOC0_CON3_UTMI_OPMODE_MASK
-                               | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK
-                               | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED);
-       ret = regmap_write(grf, RK3288_UOC0_CON3, val);
-       if (ret)
-               return ret;
-
-       val = HIWORD_UPDATE(RK3288_UOC0_CON3_BYPASSSEL
-                               | RK3288_UOC0_CON3_BYPASSDMEN,
-                           RK3288_UOC0_CON3_BYPASSSEL
-                               | RK3288_UOC0_CON3_BYPASSDMEN);
-       ret = regmap_write(grf, RK3288_UOC0_CON3, val);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static const struct rockchip_usb_phy_pdata rk3288_pdata = {
-       .phys = (struct rockchip_usb_phys[]){
-               { .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
-               { .reg = 0x334, .pll_name = "sclk_otgphy1_480m" },
-               { .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
-               { /* sentinel */ }
-       },
-       .init_usb_uart = rk3288_init_usb_uart,
-       .usb_uart_phy = 0,
-};
-
-static int rockchip_usb_phy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct rockchip_usb_phy_base *phy_base;
-       struct phy_provider *phy_provider;
-       const struct of_device_id *match;
-       struct device_node *child;
-       int err;
-
-       phy_base = devm_kzalloc(dev, sizeof(*phy_base), GFP_KERNEL);
-       if (!phy_base)
-               return -ENOMEM;
-
-       match = of_match_device(dev->driver->of_match_table, dev);
-       if (!match || !match->data) {
-               dev_err(dev, "missing phy data\n");
-               return -EINVAL;
-       }
-
-       phy_base->pdata = match->data;
-
-       phy_base->dev = dev;
-       phy_base->reg_base = ERR_PTR(-ENODEV);
-       if (dev->parent && dev->parent->of_node)
-               phy_base->reg_base = syscon_node_to_regmap(
-                                               dev->parent->of_node);
-       if (IS_ERR(phy_base->reg_base))
-               phy_base->reg_base = syscon_regmap_lookup_by_phandle(
-                                               dev->of_node, "rockchip,grf");
-       if (IS_ERR(phy_base->reg_base)) {
-               dev_err(&pdev->dev, "Missing rockchip,grf property\n");
-               return PTR_ERR(phy_base->reg_base);
-       }
-
-       for_each_available_child_of_node(dev->of_node, child) {
-               err = rockchip_usb_phy_init(phy_base, child);
-               if (err) {
-                       of_node_put(child);
-                       return err;
-               }
-       }
-
-       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 rockchip_usb_phy_dt_ids[] = {
-       { .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
-       { .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
-       { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
-       {}
-};
-
-MODULE_DEVICE_TABLE(of, rockchip_usb_phy_dt_ids);
-
-static struct platform_driver rockchip_usb_driver = {
-       .probe          = rockchip_usb_phy_probe,
-       .driver         = {
-               .name   = "rockchip-usb-phy",
-               .of_match_table = rockchip_usb_phy_dt_ids,
-       },
-};
-
-module_platform_driver(rockchip_usb_driver);
-
-#ifndef MODULE
-static int __init rockchip_init_usb_uart(void)
-{
-       const struct of_device_id *match;
-       const struct rockchip_usb_phy_pdata *data;
-       struct device_node *np;
-       struct regmap *grf;
-       int ret;
-
-       if (!enable_usb_uart)
-               return 0;
-
-       np = of_find_matching_node_and_match(NULL, rockchip_usb_phy_dt_ids,
-                                            &match);
-       if (!np) {
-               pr_err("%s: failed to find usbphy node\n", __func__);
-               return -ENOTSUPP;
-       }
-
-       pr_debug("%s: using settings for %s\n", __func__, match->compatible);
-       data = match->data;
-
-       if (!data->init_usb_uart) {
-               pr_err("%s: usb-uart not available on %s\n",
-                      __func__, match->compatible);
-               return -ENOTSUPP;
-       }
-
-       grf = ERR_PTR(-ENODEV);
-       if (np->parent)
-               grf = syscon_node_to_regmap(np->parent);
-       if (IS_ERR(grf))
-               grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
-       if (IS_ERR(grf)) {
-               pr_err("%s: Missing rockchip,grf property, %lu\n",
-                      __func__, PTR_ERR(grf));
-               return PTR_ERR(grf);
-       }
-
-       ret = data->init_usb_uart(grf);
-       if (ret) {
-               pr_err("%s: could not init usb_uart, %d\n", __func__, ret);
-               enable_usb_uart = 0;
-               return ret;
-       }
-
-       return 0;
-}
-early_initcall(rockchip_init_usb_uart);
-
-static int __init rockchip_usb_uart(char *buf)
-{
-       enable_usb_uart = true;
-       return 0;
-}
-early_param("rockchip.usb_uart", rockchip_usb_uart);
-#endif
-
-MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>");
-MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-s5pv210-usb2.c b/drivers/phy/phy-s5pv210-usb2.c
deleted file mode 100644 (file)
index f6f7233..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver - S5PV210 support
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Authors: Kamil Debski <k.debski@samsung.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.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/phy/phy.h>
-#include "phy-samsung-usb2.h"
-
-/* Exynos USB PHY registers */
-
-/* PHY power control */
-#define S5PV210_UPHYPWR                        0x0
-
-#define S5PV210_UPHYPWR_PHY0_SUSPEND   BIT(0)
-#define S5PV210_UPHYPWR_PHY0_PWR       BIT(3)
-#define S5PV210_UPHYPWR_PHY0_OTG_PWR   BIT(4)
-#define S5PV210_UPHYPWR_PHY0   ( \
-       S5PV210_UPHYPWR_PHY0_SUSPEND | \
-       S5PV210_UPHYPWR_PHY0_PWR | \
-       S5PV210_UPHYPWR_PHY0_OTG_PWR)
-
-#define S5PV210_UPHYPWR_PHY1_SUSPEND   BIT(6)
-#define S5PV210_UPHYPWR_PHY1_PWR       BIT(7)
-#define S5PV210_UPHYPWR_PHY1 ( \
-       S5PV210_UPHYPWR_PHY1_SUSPEND | \
-       S5PV210_UPHYPWR_PHY1_PWR)
-
-/* PHY clock control */
-#define S5PV210_UPHYCLK                        0x4
-
-#define S5PV210_UPHYCLK_PHYFSEL_MASK   (0x3 << 0)
-#define S5PV210_UPHYCLK_PHYFSEL_48MHZ  (0x0 << 0)
-#define S5PV210_UPHYCLK_PHYFSEL_24MHZ  (0x3 << 0)
-#define S5PV210_UPHYCLK_PHYFSEL_12MHZ  (0x2 << 0)
-
-#define S5PV210_UPHYCLK_PHY0_ID_PULLUP BIT(2)
-#define S5PV210_UPHYCLK_PHY0_COMMON_ON BIT(4)
-#define S5PV210_UPHYCLK_PHY1_COMMON_ON BIT(7)
-
-/* PHY reset control */
-#define S5PV210_UPHYRST                        0x8
-
-#define S5PV210_URSTCON_PHY0           BIT(0)
-#define S5PV210_URSTCON_OTG_HLINK      BIT(1)
-#define S5PV210_URSTCON_OTG_PHYLINK    BIT(2)
-#define S5PV210_URSTCON_PHY1_ALL       BIT(3)
-#define S5PV210_URSTCON_HOST_LINK_ALL  BIT(4)
-
-/* Isolation, configured in the power management unit */
-#define S5PV210_USB_ISOL_OFFSET                0x680c
-#define S5PV210_USB_ISOL_DEVICE                BIT(0)
-#define S5PV210_USB_ISOL_HOST          BIT(1)
-
-
-enum s5pv210_phy_id {
-       S5PV210_DEVICE,
-       S5PV210_HOST,
-       S5PV210_NUM_PHYS,
-};
-
-/*
- * s5pv210_rate_to_clk() converts the supplied clock rate to the value that
- * can be written to the phy register.
- */
-static int s5pv210_rate_to_clk(unsigned long rate, u32 *reg)
-{
-       switch (rate) {
-       case 12 * MHZ:
-               *reg = S5PV210_UPHYCLK_PHYFSEL_12MHZ;
-               break;
-       case 24 * MHZ:
-               *reg = S5PV210_UPHYCLK_PHYFSEL_24MHZ;
-               break;
-       case 48 * MHZ:
-               *reg = S5PV210_UPHYCLK_PHYFSEL_48MHZ;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void s5pv210_isol(struct samsung_usb2_phy_instance *inst, bool on)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       u32 mask;
-
-       switch (inst->cfg->id) {
-       case S5PV210_DEVICE:
-               mask = S5PV210_USB_ISOL_DEVICE;
-               break;
-       case S5PV210_HOST:
-               mask = S5PV210_USB_ISOL_HOST;
-               break;
-       default:
-               return;
-       }
-
-       regmap_update_bits(drv->reg_pmu, S5PV210_USB_ISOL_OFFSET,
-                                                       mask, on ? 0 : mask);
-}
-
-static void s5pv210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
-{
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       u32 rstbits = 0;
-       u32 phypwr = 0;
-       u32 rst;
-       u32 pwr;
-
-       switch (inst->cfg->id) {
-       case S5PV210_DEVICE:
-               phypwr =        S5PV210_UPHYPWR_PHY0;
-               rstbits =       S5PV210_URSTCON_PHY0;
-               break;
-       case S5PV210_HOST:
-               phypwr =        S5PV210_UPHYPWR_PHY1;
-               rstbits =       S5PV210_URSTCON_PHY1_ALL |
-                               S5PV210_URSTCON_HOST_LINK_ALL;
-               break;
-       }
-
-       if (on) {
-               writel(drv->ref_reg_val, drv->reg_phy + S5PV210_UPHYCLK);
-
-               pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
-               pwr &= ~phypwr;
-               writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
-
-               rst = readl(drv->reg_phy + S5PV210_UPHYRST);
-               rst |= rstbits;
-               writel(rst, drv->reg_phy + S5PV210_UPHYRST);
-               udelay(10);
-               rst &= ~rstbits;
-               writel(rst, drv->reg_phy + S5PV210_UPHYRST);
-       } else {
-               pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
-               pwr |= phypwr;
-               writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
-       }
-}
-
-static int s5pv210_power_on(struct samsung_usb2_phy_instance *inst)
-{
-       s5pv210_isol(inst, 0);
-       s5pv210_phy_pwr(inst, 1);
-
-       return 0;
-}
-
-static int s5pv210_power_off(struct samsung_usb2_phy_instance *inst)
-{
-       s5pv210_phy_pwr(inst, 0);
-       s5pv210_isol(inst, 1);
-
-       return 0;
-}
-
-static const struct samsung_usb2_common_phy s5pv210_phys[S5PV210_NUM_PHYS] = {
-       [S5PV210_DEVICE] = {
-               .label          = "device",
-               .id             = S5PV210_DEVICE,
-               .power_on       = s5pv210_power_on,
-               .power_off      = s5pv210_power_off,
-       },
-       [S5PV210_HOST] = {
-               .label          = "host",
-               .id             = S5PV210_HOST,
-               .power_on       = s5pv210_power_on,
-               .power_off      = s5pv210_power_off,
-       },
-};
-
-const struct samsung_usb2_phy_config s5pv210_usb2_phy_config = {
-       .num_phys       = ARRAY_SIZE(s5pv210_phys),
-       .phys           = s5pv210_phys,
-       .rate_to_clk    = s5pv210_rate_to_clk,
-};
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
deleted file mode 100644 (file)
index 1d22d93..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Kamil Debski <k.debski@samsung.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.
- */
-
-#include <linux/clk.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/spinlock.h>
-#include "phy-samsung-usb2.h"
-
-static int samsung_usb2_phy_power_on(struct phy *phy)
-{
-       struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       int ret;
-
-       dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
-               inst->cfg->label);
-
-       if (drv->vbus) {
-               ret = regulator_enable(drv->vbus);
-               if (ret)
-                       goto err_regulator;
-       }
-
-       ret = clk_prepare_enable(drv->clk);
-       if (ret)
-               goto err_main_clk;
-       ret = clk_prepare_enable(drv->ref_clk);
-       if (ret)
-               goto err_instance_clk;
-       if (inst->cfg->power_on) {
-               spin_lock(&drv->lock);
-               ret = inst->cfg->power_on(inst);
-               spin_unlock(&drv->lock);
-               if (ret)
-                       goto err_power_on;
-       }
-
-       return 0;
-
-err_power_on:
-       clk_disable_unprepare(drv->ref_clk);
-err_instance_clk:
-       clk_disable_unprepare(drv->clk);
-err_main_clk:
-       if (drv->vbus)
-               regulator_disable(drv->vbus);
-err_regulator:
-       return ret;
-}
-
-static int samsung_usb2_phy_power_off(struct phy *phy)
-{
-       struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
-       struct samsung_usb2_phy_driver *drv = inst->drv;
-       int ret = 0;
-
-       dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n",
-               inst->cfg->label);
-       if (inst->cfg->power_off) {
-               spin_lock(&drv->lock);
-               ret = inst->cfg->power_off(inst);
-               spin_unlock(&drv->lock);
-               if (ret)
-                       return ret;
-       }
-       clk_disable_unprepare(drv->ref_clk);
-       clk_disable_unprepare(drv->clk);
-       if (drv->vbus)
-               ret = regulator_disable(drv->vbus);
-
-       return ret;
-}
-
-static const struct phy_ops samsung_usb2_phy_ops = {
-       .power_on       = samsung_usb2_phy_power_on,
-       .power_off      = samsung_usb2_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static struct phy *samsung_usb2_phy_xlate(struct device *dev,
-                                       struct of_phandle_args *args)
-{
-       struct samsung_usb2_phy_driver *drv;
-
-       drv = dev_get_drvdata(dev);
-       if (!drv)
-               return ERR_PTR(-EINVAL);
-
-       if (WARN_ON(args->args[0] >= drv->cfg->num_phys))
-               return ERR_PTR(-ENODEV);
-
-       return drv->instances[args->args[0]].phy;
-}
-
-static const struct of_device_id samsung_usb2_phy_of_match[] = {
-#ifdef CONFIG_PHY_EXYNOS4X12_USB2
-       {
-               .compatible = "samsung,exynos3250-usb2-phy",
-               .data = &exynos3250_usb2_phy_config,
-       },
-#endif
-#ifdef CONFIG_PHY_EXYNOS4210_USB2
-       {
-               .compatible = "samsung,exynos4210-usb2-phy",
-               .data = &exynos4210_usb2_phy_config,
-       },
-#endif
-#ifdef CONFIG_PHY_EXYNOS4X12_USB2
-       {
-               .compatible = "samsung,exynos4x12-usb2-phy",
-               .data = &exynos4x12_usb2_phy_config,
-       },
-#endif
-#ifdef CONFIG_PHY_EXYNOS5250_USB2
-       {
-               .compatible = "samsung,exynos5250-usb2-phy",
-               .data = &exynos5250_usb2_phy_config,
-       },
-#endif
-#ifdef CONFIG_PHY_S5PV210_USB2
-       {
-               .compatible = "samsung,s5pv210-usb2-phy",
-               .data = &s5pv210_usb2_phy_config,
-       },
-#endif
-       { },
-};
-MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match);
-
-static int samsung_usb2_phy_probe(struct platform_device *pdev)
-{
-       const struct of_device_id *match;
-       const struct samsung_usb2_phy_config *cfg;
-       struct device *dev = &pdev->dev;
-       struct phy_provider *phy_provider;
-       struct resource *mem;
-       struct samsung_usb2_phy_driver *drv;
-       int i, ret;
-
-       if (!pdev->dev.of_node) {
-               dev_err(dev, "This driver is required to be instantiated from device tree\n");
-               return -EINVAL;
-       }
-
-       match = of_match_node(samsung_usb2_phy_of_match, pdev->dev.of_node);
-       if (!match) {
-               dev_err(dev, "of_match_node() failed\n");
-               return -EINVAL;
-       }
-       cfg = match->data;
-
-       drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) +
-               cfg->num_phys * sizeof(struct samsung_usb2_phy_instance),
-                                                               GFP_KERNEL);
-       if (!drv)
-               return -ENOMEM;
-
-       dev_set_drvdata(dev, drv);
-       spin_lock_init(&drv->lock);
-
-       drv->cfg = cfg;
-       drv->dev = dev;
-
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       drv->reg_phy = devm_ioremap_resource(dev, mem);
-       if (IS_ERR(drv->reg_phy)) {
-               dev_err(dev, "Failed to map register memory (phy)\n");
-               return PTR_ERR(drv->reg_phy);
-       }
-
-       drv->reg_pmu = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
-               "samsung,pmureg-phandle");
-       if (IS_ERR(drv->reg_pmu)) {
-               dev_err(dev, "Failed to map PMU registers (via syscon)\n");
-               return PTR_ERR(drv->reg_pmu);
-       }
-
-       if (drv->cfg->has_mode_switch) {
-               drv->reg_sys = syscon_regmap_lookup_by_phandle(
-                               pdev->dev.of_node, "samsung,sysreg-phandle");
-               if (IS_ERR(drv->reg_sys)) {
-                       dev_err(dev, "Failed to map system registers (via syscon)\n");
-                       return PTR_ERR(drv->reg_sys);
-               }
-       }
-
-       drv->clk = devm_clk_get(dev, "phy");
-       if (IS_ERR(drv->clk)) {
-               dev_err(dev, "Failed to get clock of phy controller\n");
-               return PTR_ERR(drv->clk);
-       }
-
-       drv->ref_clk = devm_clk_get(dev, "ref");
-       if (IS_ERR(drv->ref_clk)) {
-               dev_err(dev, "Failed to get reference clock for the phy controller\n");
-               return PTR_ERR(drv->ref_clk);
-       }
-
-       drv->ref_rate = clk_get_rate(drv->ref_clk);
-       if (drv->cfg->rate_to_clk) {
-               ret = drv->cfg->rate_to_clk(drv->ref_rate, &drv->ref_reg_val);
-               if (ret)
-                       return ret;
-       }
-
-       drv->vbus = devm_regulator_get(dev, "vbus");
-       if (IS_ERR(drv->vbus)) {
-               ret = PTR_ERR(drv->vbus);
-               if (ret == -EPROBE_DEFER)
-                       return ret;
-               drv->vbus = NULL;
-       }
-
-       for (i = 0; i < drv->cfg->num_phys; i++) {
-               char *label = drv->cfg->phys[i].label;
-               struct samsung_usb2_phy_instance *p = &drv->instances[i];
-
-               dev_dbg(dev, "Creating phy \"%s\"\n", label);
-               p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops);
-               if (IS_ERR(p->phy)) {
-                       dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n",
-                               label);
-                       return PTR_ERR(p->phy);
-               }
-
-               p->cfg = &drv->cfg->phys[i];
-               p->drv = drv;
-               phy_set_bus_width(p->phy, 8);
-               phy_set_drvdata(p->phy, p);
-       }
-
-       phy_provider = devm_of_phy_provider_register(dev,
-                                                       samsung_usb2_phy_xlate);
-       if (IS_ERR(phy_provider)) {
-               dev_err(drv->dev, "Failed to register phy provider\n");
-               return PTR_ERR(phy_provider);
-       }
-
-       return 0;
-}
-
-static struct platform_driver samsung_usb2_phy_driver = {
-       .probe  = samsung_usb2_phy_probe,
-       .driver = {
-               .of_match_table = samsung_usb2_phy_of_match,
-               .name           = "samsung-usb2-phy",
-       }
-};
-
-module_platform_driver(samsung_usb2_phy_driver);
-MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC USB PHY driver");
-MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:samsung-usb2-phy");
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
deleted file mode 100644 (file)
index 6563e7c..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Kamil Debski <k.debski@samsung.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.
- */
-
-#ifndef _PHY_EXYNOS_USB2_H
-#define _PHY_EXYNOS_USB2_H
-
-#include <linux/clk.h>
-#include <linux/phy/phy.h>
-#include <linux/device.h>
-#include <linux/regmap.h>
-#include <linux/spinlock.h>
-#include <linux/regulator/consumer.h>
-
-#define KHZ 1000
-#define MHZ (KHZ * KHZ)
-
-struct samsung_usb2_phy_driver;
-struct samsung_usb2_phy_instance;
-struct samsung_usb2_phy_config;
-
-struct samsung_usb2_phy_instance {
-       const struct samsung_usb2_common_phy *cfg;
-       struct phy *phy;
-       struct samsung_usb2_phy_driver *drv;
-       int int_cnt;
-       int ext_cnt;
-};
-
-struct samsung_usb2_phy_driver {
-       const struct samsung_usb2_phy_config *cfg;
-       struct clk *clk;
-       struct clk *ref_clk;
-       struct regulator *vbus;
-       unsigned long ref_rate;
-       u32 ref_reg_val;
-       struct device *dev;
-       void __iomem *reg_phy;
-       struct regmap *reg_pmu;
-       struct regmap *reg_sys;
-       spinlock_t lock;
-       struct samsung_usb2_phy_instance instances[0];
-};
-
-struct samsung_usb2_common_phy {
-       int (*power_on)(struct samsung_usb2_phy_instance *);
-       int (*power_off)(struct samsung_usb2_phy_instance *);
-       unsigned int id;
-       char *label;
-};
-
-
-struct samsung_usb2_phy_config {
-       const struct samsung_usb2_common_phy *phys;
-       int (*rate_to_clk)(unsigned long, u32 *);
-       unsigned int num_phys;
-       bool has_mode_switch;
-       bool has_refclk_sel;
-};
-
-extern const struct samsung_usb2_phy_config exynos3250_usb2_phy_config;
-extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
-extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
-extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
-extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config;
-#endif
diff --git a/drivers/phy/phy-spear1310-miphy.c b/drivers/phy/phy-spear1310-miphy.c
deleted file mode 100644 (file)
index ed67e98..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * ST SPEAr1310-miphy driver
- *
- * Copyright (C) 2014 ST Microelectronics
- * Pratyush Anand <pratyush.anand@gmail.com>
- * Mohit Kumar <mohit.kumar.dhaka@gmail.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.
- *
- */
-
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-
-/* SPEAr1310 Registers */
-#define SPEAR1310_PCIE_SATA_CFG                        0x3A4
-       #define SPEAR1310_PCIE_SATA2_SEL_PCIE           (0 << 31)
-       #define SPEAR1310_PCIE_SATA1_SEL_PCIE           (0 << 30)
-       #define SPEAR1310_PCIE_SATA0_SEL_PCIE           (0 << 29)
-       #define SPEAR1310_PCIE_SATA2_SEL_SATA           BIT(31)
-       #define SPEAR1310_PCIE_SATA1_SEL_SATA           BIT(30)
-       #define SPEAR1310_PCIE_SATA0_SEL_SATA           BIT(29)
-       #define SPEAR1310_SATA2_CFG_TX_CLK_EN           BIT(27)
-       #define SPEAR1310_SATA2_CFG_RX_CLK_EN           BIT(26)
-       #define SPEAR1310_SATA2_CFG_POWERUP_RESET       BIT(25)
-       #define SPEAR1310_SATA2_CFG_PM_CLK_EN           BIT(24)
-       #define SPEAR1310_SATA1_CFG_TX_CLK_EN           BIT(23)
-       #define SPEAR1310_SATA1_CFG_RX_CLK_EN           BIT(22)
-       #define SPEAR1310_SATA1_CFG_POWERUP_RESET       BIT(21)
-       #define SPEAR1310_SATA1_CFG_PM_CLK_EN           BIT(20)
-       #define SPEAR1310_SATA0_CFG_TX_CLK_EN           BIT(19)
-       #define SPEAR1310_SATA0_CFG_RX_CLK_EN           BIT(18)
-       #define SPEAR1310_SATA0_CFG_POWERUP_RESET       BIT(17)
-       #define SPEAR1310_SATA0_CFG_PM_CLK_EN           BIT(16)
-       #define SPEAR1310_PCIE2_CFG_DEVICE_PRESENT      BIT(11)
-       #define SPEAR1310_PCIE2_CFG_POWERUP_RESET       BIT(10)
-       #define SPEAR1310_PCIE2_CFG_CORE_CLK_EN         BIT(9)
-       #define SPEAR1310_PCIE2_CFG_AUX_CLK_EN          BIT(8)
-       #define SPEAR1310_PCIE1_CFG_DEVICE_PRESENT      BIT(7)
-       #define SPEAR1310_PCIE1_CFG_POWERUP_RESET       BIT(6)
-       #define SPEAR1310_PCIE1_CFG_CORE_CLK_EN         BIT(5)
-       #define SPEAR1310_PCIE1_CFG_AUX_CLK_EN          BIT(4)
-       #define SPEAR1310_PCIE0_CFG_DEVICE_PRESENT      BIT(3)
-       #define SPEAR1310_PCIE0_CFG_POWERUP_RESET       BIT(2)
-       #define SPEAR1310_PCIE0_CFG_CORE_CLK_EN         BIT(1)
-       #define SPEAR1310_PCIE0_CFG_AUX_CLK_EN          BIT(0)
-
-       #define SPEAR1310_PCIE_CFG_MASK(x) ((0xF << (x * 4)) | BIT((x + 29)))
-       #define SPEAR1310_SATA_CFG_MASK(x) ((0xF << (x * 4 + 16)) | \
-                       BIT((x + 29)))
-       #define SPEAR1310_PCIE_CFG_VAL(x) \
-                       (SPEAR1310_PCIE_SATA##x##_SEL_PCIE | \
-                       SPEAR1310_PCIE##x##_CFG_AUX_CLK_EN | \
-                       SPEAR1310_PCIE##x##_CFG_CORE_CLK_EN | \
-                       SPEAR1310_PCIE##x##_CFG_POWERUP_RESET | \
-                       SPEAR1310_PCIE##x##_CFG_DEVICE_PRESENT)
-       #define SPEAR1310_SATA_CFG_VAL(x) \
-                       (SPEAR1310_PCIE_SATA##x##_SEL_SATA | \
-                       SPEAR1310_SATA##x##_CFG_PM_CLK_EN | \
-                       SPEAR1310_SATA##x##_CFG_POWERUP_RESET | \
-                       SPEAR1310_SATA##x##_CFG_RX_CLK_EN | \
-                       SPEAR1310_SATA##x##_CFG_TX_CLK_EN)
-
-#define SPEAR1310_PCIE_MIPHY_CFG_1             0x3A8
-       #define SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT     BIT(31)
-       #define SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2       BIT(28)
-       #define SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(x)   (x << 16)
-       #define SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT   BIT(15)
-       #define SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2     BIT(12)
-       #define SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(x) (x << 0)
-       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_MASK (0xFFFF)
-       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK (0xFFFF << 16)
-       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA \
-                       (SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
-                       SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2 | \
-                       SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(60) | \
-                       SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
-                       SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2 | \
-                       SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(60))
-       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
-                       (SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(120))
-       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE \
-                       (SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
-                       SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(25) | \
-                       SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
-                       SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(25))
-
-#define SPEAR1310_PCIE_MIPHY_CFG_2             0x3AC
-
-enum spear1310_miphy_mode {
-       SATA,
-       PCIE,
-};
-
-struct spear1310_miphy_priv {
-       /* instance id of this phy */
-       u32                             id;
-       /* phy mode: 0 for SATA 1 for PCIe */
-       enum spear1310_miphy_mode       mode;
-       /* regmap for any soc specific misc registers */
-       struct regmap                   *misc;
-       /* phy struct pointer */
-       struct phy                      *phy;
-};
-
-static int spear1310_miphy_pcie_init(struct spear1310_miphy_priv *priv)
-{
-       u32 val;
-
-       regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
-                          SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK,
-                          SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE);
-
-       switch (priv->id) {
-       case 0:
-               val = SPEAR1310_PCIE_CFG_VAL(0);
-               break;
-       case 1:
-               val = SPEAR1310_PCIE_CFG_VAL(1);
-               break;
-       case 2:
-               val = SPEAR1310_PCIE_CFG_VAL(2);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
-                          SPEAR1310_PCIE_CFG_MASK(priv->id), val);
-
-       return 0;
-}
-
-static int spear1310_miphy_pcie_exit(struct spear1310_miphy_priv *priv)
-{
-       regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
-                          SPEAR1310_PCIE_CFG_MASK(priv->id), 0);
-
-       regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
-                          SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK, 0);
-
-       return 0;
-}
-
-static int spear1310_miphy_init(struct phy *phy)
-{
-       struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
-       int ret = 0;
-
-       if (priv->mode == PCIE)
-               ret = spear1310_miphy_pcie_init(priv);
-
-       return ret;
-}
-
-static int spear1310_miphy_exit(struct phy *phy)
-{
-       struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
-       int ret = 0;
-
-       if (priv->mode == PCIE)
-               ret = spear1310_miphy_pcie_exit(priv);
-
-       return ret;
-}
-
-static const struct of_device_id spear1310_miphy_of_match[] = {
-       { .compatible = "st,spear1310-miphy" },
-       { },
-};
-MODULE_DEVICE_TABLE(of, spear1310_miphy_of_match);
-
-static const struct phy_ops spear1310_miphy_ops = {
-       .init = spear1310_miphy_init,
-       .exit = spear1310_miphy_exit,
-       .owner = THIS_MODULE,
-};
-
-static struct phy *spear1310_miphy_xlate(struct device *dev,
-                                        struct of_phandle_args *args)
-{
-       struct spear1310_miphy_priv *priv = dev_get_drvdata(dev);
-
-       if (args->args_count < 1) {
-               dev_err(dev, "DT did not pass correct no of args\n");
-               return ERR_PTR(-ENODEV);
-       }
-
-       priv->mode = args->args[0];
-
-       if (priv->mode != SATA && priv->mode != PCIE) {
-               dev_err(dev, "DT did not pass correct phy mode\n");
-               return ERR_PTR(-ENODEV);
-       }
-
-       return priv->phy;
-}
-
-static int spear1310_miphy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct spear1310_miphy_priv *priv;
-       struct phy_provider *phy_provider;
-
-       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       priv->misc =
-               syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
-       if (IS_ERR(priv->misc)) {
-               dev_err(dev, "failed to find misc regmap\n");
-               return PTR_ERR(priv->misc);
-       }
-
-       if (of_property_read_u32(dev->of_node, "phy-id", &priv->id)) {
-               dev_err(dev, "failed to find phy id\n");
-               return -EINVAL;
-       }
-
-       priv->phy = devm_phy_create(dev, NULL, &spear1310_miphy_ops);
-       if (IS_ERR(priv->phy)) {
-               dev_err(dev, "failed to create SATA PCIe PHY\n");
-               return PTR_ERR(priv->phy);
-       }
-
-       dev_set_drvdata(dev, priv);
-       phy_set_drvdata(priv->phy, priv);
-
-       phy_provider =
-               devm_of_phy_provider_register(dev, spear1310_miphy_xlate);
-       if (IS_ERR(phy_provider)) {
-               dev_err(dev, "failed to register phy provider\n");
-               return PTR_ERR(phy_provider);
-       }
-
-       return 0;
-}
-
-static struct platform_driver spear1310_miphy_driver = {
-       .probe          = spear1310_miphy_probe,
-       .driver = {
-               .name = "spear1310-miphy",
-               .of_match_table = of_match_ptr(spear1310_miphy_of_match),
-       },
-};
-
-module_platform_driver(spear1310_miphy_driver);
-
-MODULE_DESCRIPTION("ST SPEAR1310-MIPHY driver");
-MODULE_AUTHOR("Pratyush Anand <pratyush.anand@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-spear1340-miphy.c b/drivers/phy/phy-spear1340-miphy.c
deleted file mode 100644 (file)
index 97280c0..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * ST spear1340-miphy driver
- *
- * Copyright (C) 2014 ST Microelectronics
- * Pratyush Anand <pratyush.anand@gmail.com>
- * Mohit Kumar <mohit.kumar.dhaka@gmail.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.
- *
- */
-
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-
-/* SPEAr1340 Registers */
-/* Power Management Registers */
-#define SPEAR1340_PCM_CFG                      0x100
-       #define SPEAR1340_PCM_CFG_SATA_POWER_EN         BIT(11)
-#define SPEAR1340_PCM_WKUP_CFG                 0x104
-#define SPEAR1340_SWITCH_CTR                   0x108
-
-#define SPEAR1340_PERIP1_SW_RST                        0x318
-       #define SPEAR1340_PERIP1_SW_RSATA               BIT(12)
-#define SPEAR1340_PERIP2_SW_RST                        0x31C
-#define SPEAR1340_PERIP3_SW_RST                        0x320
-
-/* PCIE - SATA configuration registers */
-#define SPEAR1340_PCIE_SATA_CFG                        0x424
-       /* PCIE CFG MASks */
-       #define SPEAR1340_PCIE_CFG_DEVICE_PRESENT       BIT(11)
-       #define SPEAR1340_PCIE_CFG_POWERUP_RESET        BIT(10)
-       #define SPEAR1340_PCIE_CFG_CORE_CLK_EN          BIT(9)
-       #define SPEAR1340_PCIE_CFG_AUX_CLK_EN           BIT(8)
-       #define SPEAR1340_SATA_CFG_TX_CLK_EN            BIT(4)
-       #define SPEAR1340_SATA_CFG_RX_CLK_EN            BIT(3)
-       #define SPEAR1340_SATA_CFG_POWERUP_RESET        BIT(2)
-       #define SPEAR1340_SATA_CFG_PM_CLK_EN            BIT(1)
-       #define SPEAR1340_PCIE_SATA_SEL_PCIE            (0)
-       #define SPEAR1340_PCIE_SATA_SEL_SATA            (1)
-       #define SPEAR1340_PCIE_SATA_CFG_MASK            0xF1F
-       #define SPEAR1340_PCIE_CFG_VAL  (SPEAR1340_PCIE_SATA_SEL_PCIE | \
-                       SPEAR1340_PCIE_CFG_AUX_CLK_EN | \
-                       SPEAR1340_PCIE_CFG_CORE_CLK_EN | \
-                       SPEAR1340_PCIE_CFG_POWERUP_RESET | \
-                       SPEAR1340_PCIE_CFG_DEVICE_PRESENT)
-       #define SPEAR1340_SATA_CFG_VAL  (SPEAR1340_PCIE_SATA_SEL_SATA | \
-                       SPEAR1340_SATA_CFG_PM_CLK_EN | \
-                       SPEAR1340_SATA_CFG_POWERUP_RESET | \
-                       SPEAR1340_SATA_CFG_RX_CLK_EN | \
-                       SPEAR1340_SATA_CFG_TX_CLK_EN)
-
-#define SPEAR1340_PCIE_MIPHY_CFG               0x428
-       #define SPEAR1340_MIPHY_OSC_BYPASS_EXT          BIT(31)
-       #define SPEAR1340_MIPHY_CLK_REF_DIV2            BIT(27)
-       #define SPEAR1340_MIPHY_CLK_REF_DIV4            (2 << 27)
-       #define SPEAR1340_MIPHY_CLK_REF_DIV8            (3 << 27)
-       #define SPEAR1340_MIPHY_PLL_RATIO_TOP(x)        (x << 0)
-       #define SPEAR1340_PCIE_MIPHY_CFG_MASK           0xF80000FF
-       #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \
-                       (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
-                       SPEAR1340_MIPHY_CLK_REF_DIV2 | \
-                       SPEAR1340_MIPHY_PLL_RATIO_TOP(60))
-       #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
-                       (SPEAR1340_MIPHY_PLL_RATIO_TOP(120))
-       #define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
-                       (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
-                       SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
-
-enum spear1340_miphy_mode {
-       SATA,
-       PCIE,
-};
-
-struct spear1340_miphy_priv {
-       /* phy mode: 0 for SATA 1 for PCIe */
-       enum spear1340_miphy_mode       mode;
-       /* regmap for any soc specific misc registers */
-       struct regmap                   *misc;
-       /* phy struct pointer */
-       struct phy                      *phy;
-};
-
-static int spear1340_miphy_sata_init(struct spear1340_miphy_priv *priv)
-{
-       regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
-                          SPEAR1340_PCIE_SATA_CFG_MASK,
-                          SPEAR1340_SATA_CFG_VAL);
-       regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
-                          SPEAR1340_PCIE_MIPHY_CFG_MASK,
-                          SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK);
-       /* Switch on sata power domain */
-       regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
-                          SPEAR1340_PCM_CFG_SATA_POWER_EN,
-                          SPEAR1340_PCM_CFG_SATA_POWER_EN);
-       /* Wait for SATA power domain on */
-       msleep(20);
-
-       /* Disable PCIE SATA Controller reset */
-       regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
-                          SPEAR1340_PERIP1_SW_RSATA, 0);
-       /* Wait for SATA reset de-assert completion */
-       msleep(20);
-
-       return 0;
-}
-
-static int spear1340_miphy_sata_exit(struct spear1340_miphy_priv *priv)
-{
-       regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
-                          SPEAR1340_PCIE_SATA_CFG_MASK, 0);
-       regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
-                          SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
-
-       /* Enable PCIE SATA Controller reset */
-       regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
-                          SPEAR1340_PERIP1_SW_RSATA,
-                          SPEAR1340_PERIP1_SW_RSATA);
-       /* Wait for SATA power domain off */
-       msleep(20);
-       /* Switch off sata power domain */
-       regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
-                          SPEAR1340_PCM_CFG_SATA_POWER_EN, 0);
-       /* Wait for SATA reset assert completion */
-       msleep(20);
-
-       return 0;
-}
-
-static int spear1340_miphy_pcie_init(struct spear1340_miphy_priv *priv)
-{
-       regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
-                          SPEAR1340_PCIE_MIPHY_CFG_MASK,
-                          SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE);
-       regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
-                          SPEAR1340_PCIE_SATA_CFG_MASK,
-                          SPEAR1340_PCIE_CFG_VAL);
-
-       return 0;
-}
-
-static int spear1340_miphy_pcie_exit(struct spear1340_miphy_priv *priv)
-{
-       regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
-                          SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
-       regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
-                          SPEAR1340_PCIE_SATA_CFG_MASK, 0);
-
-       return 0;
-}
-
-static int spear1340_miphy_init(struct phy *phy)
-{
-       struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
-       int ret = 0;
-
-       if (priv->mode == SATA)
-               ret = spear1340_miphy_sata_init(priv);
-       else if (priv->mode == PCIE)
-               ret = spear1340_miphy_pcie_init(priv);
-
-       return ret;
-}
-
-static int spear1340_miphy_exit(struct phy *phy)
-{
-       struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
-       int ret = 0;
-
-       if (priv->mode == SATA)
-               ret = spear1340_miphy_sata_exit(priv);
-       else if (priv->mode == PCIE)
-               ret = spear1340_miphy_pcie_exit(priv);
-
-       return ret;
-}
-
-static const struct of_device_id spear1340_miphy_of_match[] = {
-       { .compatible = "st,spear1340-miphy" },
-       { },
-};
-MODULE_DEVICE_TABLE(of, spear1340_miphy_of_match);
-
-static const struct phy_ops spear1340_miphy_ops = {
-       .init = spear1340_miphy_init,
-       .exit = spear1340_miphy_exit,
-       .owner = THIS_MODULE,
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int spear1340_miphy_suspend(struct device *dev)
-{
-       struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
-       int ret = 0;
-
-       if (priv->mode == SATA)
-               ret = spear1340_miphy_sata_exit(priv);
-
-       return ret;
-}
-
-static int spear1340_miphy_resume(struct device *dev)
-{
-       struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
-       int ret = 0;
-
-       if (priv->mode == SATA)
-               ret = spear1340_miphy_sata_init(priv);
-
-       return ret;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(spear1340_miphy_pm_ops, spear1340_miphy_suspend,
-                        spear1340_miphy_resume);
-
-static struct phy *spear1340_miphy_xlate(struct device *dev,
-                                        struct of_phandle_args *args)
-{
-       struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
-
-       if (args->args_count < 1) {
-               dev_err(dev, "DT did not pass correct no of args\n");
-               return ERR_PTR(-ENODEV);
-       }
-
-       priv->mode = args->args[0];
-
-       if (priv->mode != SATA && priv->mode != PCIE) {
-               dev_err(dev, "DT did not pass correct phy mode\n");
-               return ERR_PTR(-ENODEV);
-       }
-
-       return priv->phy;
-}
-
-static int spear1340_miphy_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct spear1340_miphy_priv *priv;
-       struct phy_provider *phy_provider;
-
-       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       priv->misc =
-               syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
-       if (IS_ERR(priv->misc)) {
-               dev_err(dev, "failed to find misc regmap\n");
-               return PTR_ERR(priv->misc);
-       }
-
-       priv->phy = devm_phy_create(dev, NULL, &spear1340_miphy_ops);
-       if (IS_ERR(priv->phy)) {
-               dev_err(dev, "failed to create SATA PCIe PHY\n");
-               return PTR_ERR(priv->phy);
-       }
-
-       dev_set_drvdata(dev, priv);
-       phy_set_drvdata(priv->phy, priv);
-
-       phy_provider =
-               devm_of_phy_provider_register(dev, spear1340_miphy_xlate);
-       if (IS_ERR(phy_provider)) {
-               dev_err(dev, "failed to register phy provider\n");
-               return PTR_ERR(phy_provider);
-       }
-
-       return 0;
-}
-
-static struct platform_driver spear1340_miphy_driver = {
-       .probe          = spear1340_miphy_probe,
-       .driver = {
-               .name = "spear1340-miphy",
-               .pm = &spear1340_miphy_pm_ops,
-               .of_match_table = of_match_ptr(spear1340_miphy_of_match),
-       },
-};
-
-module_platform_driver(spear1340_miphy_driver);
-
-MODULE_DESCRIPTION("ST SPEAR1340-MIPHY driver");
-MODULE_AUTHOR("Pratyush Anand <pratyush.anand@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-stih407-usb.c b/drivers/phy/phy-stih407-usb.c
deleted file mode 100644 (file)
index b1f44ab..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2014 STMicroelectronics
- *
- * STMicroelectronics Generic PHY driver for STiH407 USB2.
- *
- * Author: Giuseppe Cavallaro <peppe.cavallaro@st.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.
- *
- */
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/clk.h>
-#include <linux/regmap.h>
-#include <linux/reset.h>
-#include <linux/mfd/syscon.h>
-#include <linux/phy/phy.h>
-
-#define PHYPARAM_REG   1
-#define PHYCTRL_REG    2
-
-/* Default PHY_SEL and REFCLKSEL configuration */
-#define STIH407_USB_PICOPHY_CTRL_PORT_CONF     0x6
-#define STIH407_USB_PICOPHY_CTRL_PORT_MASK     0x1f
-
-/* ports parameters overriding */
-#define STIH407_USB_PICOPHY_PARAM_DEF          0x39a4dc
-#define STIH407_USB_PICOPHY_PARAM_MASK         0xffffffff
-
-struct stih407_usb2_picophy {
-       struct phy *phy;
-       struct regmap *regmap;
-       struct device *dev;
-       struct reset_control *rstc;
-       struct reset_control *rstport;
-       int ctrl;
-       int param;
-};
-
-static int stih407_usb2_pico_ctrl(struct stih407_usb2_picophy *phy_dev)
-{
-       reset_control_deassert(phy_dev->rstc);
-
-       return regmap_update_bits(phy_dev->regmap, phy_dev->ctrl,
-                                 STIH407_USB_PICOPHY_CTRL_PORT_MASK,
-                                 STIH407_USB_PICOPHY_CTRL_PORT_CONF);
-}
-
-static int stih407_usb2_init_port(struct phy *phy)
-{
-       int ret;
-       struct stih407_usb2_picophy *phy_dev = phy_get_drvdata(phy);
-
-       stih407_usb2_pico_ctrl(phy_dev);
-
-       ret = regmap_update_bits(phy_dev->regmap,
-                                phy_dev->param,
-                                STIH407_USB_PICOPHY_PARAM_MASK,
-                                STIH407_USB_PICOPHY_PARAM_DEF);
-       if (ret)
-               return ret;
-
-       return reset_control_deassert(phy_dev->rstport);
-}
-
-static int stih407_usb2_exit_port(struct phy *phy)
-{
-       struct stih407_usb2_picophy *phy_dev = phy_get_drvdata(phy);
-
-       /*
-        * Only port reset is asserted, phy global reset is kept untouched
-        * as other ports may still be active. When all ports are in reset
-        * state, assumption is made that power will be cut off on the phy, in
-        * case of suspend for instance. Theoretically, asserting individual
-        * reset (like here) or global reset should be equivalent.
-        */
-       return reset_control_assert(phy_dev->rstport);
-}
-
-static const struct phy_ops stih407_usb2_picophy_data = {
-       .init = stih407_usb2_init_port,
-       .exit = stih407_usb2_exit_port,
-       .owner = THIS_MODULE,
-};
-
-static int stih407_usb2_picophy_probe(struct platform_device *pdev)
-{
-       struct stih407_usb2_picophy *phy_dev;
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct phy_provider *phy_provider;
-       struct phy *phy;
-       int ret;
-
-       phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL);
-       if (!phy_dev)
-               return -ENOMEM;
-
-       phy_dev->dev = dev;
-       dev_set_drvdata(dev, phy_dev);
-
-       phy_dev->rstc = devm_reset_control_get_shared(dev, "global");
-       if (IS_ERR(phy_dev->rstc)) {
-               dev_err(dev, "failed to ctrl picoPHY reset\n");
-               return PTR_ERR(phy_dev->rstc);
-       }
-
-       phy_dev->rstport = devm_reset_control_get_exclusive(dev, "port");
-       if (IS_ERR(phy_dev->rstport)) {
-               dev_err(dev, "failed to ctrl picoPHY reset\n");
-               return PTR_ERR(phy_dev->rstport);
-       }
-
-       /* Reset port by default: only deassert it in phy init */
-       reset_control_assert(phy_dev->rstport);
-
-       phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
-       if (IS_ERR(phy_dev->regmap)) {
-               dev_err(dev, "No syscfg phandle specified\n");
-               return PTR_ERR(phy_dev->regmap);
-       }
-
-       ret = of_property_read_u32_index(np, "st,syscfg", PHYPARAM_REG,
-                                       &phy_dev->param);
-       if (ret) {
-               dev_err(dev, "can't get phyparam offset (%d)\n", ret);
-               return ret;
-       }
-
-       ret = of_property_read_u32_index(np, "st,syscfg", PHYCTRL_REG,
-                                       &phy_dev->ctrl);
-       if (ret) {
-               dev_err(dev, "can't get phyctrl offset (%d)\n", ret);
-               return ret;
-       }
-
-       phy = devm_phy_create(dev, NULL, &stih407_usb2_picophy_data);
-       if (IS_ERR(phy)) {
-               dev_err(dev, "failed to create Display Port PHY\n");
-               return PTR_ERR(phy);
-       }
-
-       phy_dev->phy = phy;
-       phy_set_drvdata(phy, phy_dev);
-
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
-       dev_info(dev, "STiH407 USB Generic picoPHY driver probed!");
-
-       return 0;
-}
-
-static const struct of_device_id stih407_usb2_picophy_of_match[] = {
-       { .compatible = "st,stih407-usb2-phy" },
-       { /*sentinel */ },
-};
-
-MODULE_DEVICE_TABLE(of, stih407_usb2_picophy_of_match);
-
-static struct platform_driver stih407_usb2_picophy_driver = {
-       .probe = stih407_usb2_picophy_probe,
-       .driver = {
-                  .name = "stih407-usb-genphy",
-                  .of_match_table = stih407_usb2_picophy_of_match,
-                  }
-};
-
-module_platform_driver(stih407_usb2_picophy_driver);
-
-MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
-MODULE_DESCRIPTION("STMicroelectronics Generic picoPHY driver for STiH407");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
deleted file mode 100644 (file)
index bbf06cf..0000000
+++ /dev/null
@@ -1,891 +0,0 @@
-/*
- * Allwinner sun4i USB phy driver
- *
- * Copyright (C) 2014-2015 Hans de Goede <hdegoede@redhat.com>
- *
- * Based on code from
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- *
- * Modelled after: Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/extcon.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/phy/phy.h>
-#include <linux/phy/phy-sun4i-usb.h>
-#include <linux/platform_device.h>
-#include <linux/power_supply.h>
-#include <linux/regulator/consumer.h>
-#include <linux/reset.h>
-#include <linux/spinlock.h>
-#include <linux/usb/of.h>
-#include <linux/workqueue.h>
-
-#define REG_ISCR                       0x00
-#define REG_PHYCTL_A10                 0x04
-#define REG_PHYBIST                    0x08
-#define REG_PHYTUNE                    0x0c
-#define REG_PHYCTL_A33                 0x10
-#define REG_PHY_OTGCTL                 0x20
-
-#define REG_PMU_UNK1                   0x10
-
-#define PHYCTL_DATA                    BIT(7)
-
-#define OTGCTL_ROUTE_MUSB              BIT(0)
-
-#define SUNXI_AHB_ICHR8_EN             BIT(10)
-#define SUNXI_AHB_INCR4_BURST_EN       BIT(9)
-#define SUNXI_AHB_INCRX_ALIGN_EN       BIT(8)
-#define SUNXI_ULPI_BYPASS_EN           BIT(0)
-
-/* ISCR, Interface Status and Control bits */
-#define ISCR_ID_PULLUP_EN              (1 << 17)
-#define ISCR_DPDM_PULLUP_EN    (1 << 16)
-/* sunxi has the phy id/vbus pins not connected, so we use the force bits */
-#define ISCR_FORCE_ID_MASK     (3 << 14)
-#define ISCR_FORCE_ID_LOW              (2 << 14)
-#define ISCR_FORCE_ID_HIGH     (3 << 14)
-#define ISCR_FORCE_VBUS_MASK   (3 << 12)
-#define ISCR_FORCE_VBUS_LOW    (2 << 12)
-#define ISCR_FORCE_VBUS_HIGH   (3 << 12)
-
-/* Common Control Bits for Both PHYs */
-#define PHY_PLL_BW                     0x03
-#define PHY_RES45_CAL_EN               0x0c
-
-/* Private Control Bits for Each PHY */
-#define PHY_TX_AMPLITUDE_TUNE          0x20
-#define PHY_TX_SLEWRATE_TUNE           0x22
-#define PHY_VBUSVALID_TH_SEL           0x25
-#define PHY_PULLUP_RES_SEL             0x27
-#define PHY_OTG_FUNC_EN                        0x28
-#define PHY_VBUS_DET_EN                        0x29
-#define PHY_DISCON_TH_SEL              0x2a
-#define PHY_SQUELCH_DETECT             0x3c
-
-#define MAX_PHYS                       4
-
-/*
- * Note do not raise the debounce time, we must report Vusb high within 100ms
- * otherwise we get Vbus errors
- */
-#define DEBOUNCE_TIME                  msecs_to_jiffies(50)
-#define POLL_TIME                      msecs_to_jiffies(250)
-
-enum sun4i_usb_phy_type {
-       sun4i_a10_phy,
-       sun6i_a31_phy,
-       sun8i_a33_phy,
-       sun8i_h3_phy,
-       sun8i_v3s_phy,
-       sun50i_a64_phy,
-};
-
-struct sun4i_usb_phy_cfg {
-       int num_phys;
-       enum sun4i_usb_phy_type type;
-       u32 disc_thresh;
-       u8 phyctl_offset;
-       bool dedicated_clocks;
-       bool enable_pmu_unk1;
-       bool phy0_dual_route;
-};
-
-struct sun4i_usb_phy_data {
-       void __iomem *base;
-       const struct sun4i_usb_phy_cfg *cfg;
-       enum usb_dr_mode dr_mode;
-       spinlock_t reg_lock; /* guard access to phyctl reg */
-       struct sun4i_usb_phy {
-               struct phy *phy;
-               void __iomem *pmu;
-               struct regulator *vbus;
-               struct reset_control *reset;
-               struct clk *clk;
-               bool regulator_on;
-               int index;
-       } phys[MAX_PHYS];
-       /* phy0 / otg related variables */
-       struct extcon_dev *extcon;
-       bool phy0_init;
-       struct gpio_desc *id_det_gpio;
-       struct gpio_desc *vbus_det_gpio;
-       struct power_supply *vbus_power_supply;
-       struct notifier_block vbus_power_nb;
-       bool vbus_power_nb_registered;
-       bool force_session_end;
-       int id_det_irq;
-       int vbus_det_irq;
-       int id_det;
-       int vbus_det;
-       struct delayed_work detect;
-};
-
-#define to_sun4i_usb_phy_data(phy) \
-       container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index])
-
-static void sun4i_usb_phy0_update_iscr(struct phy *_phy, u32 clr, u32 set)
-{
-       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
-       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
-       u32 iscr;
-
-       iscr = readl(data->base + REG_ISCR);
-       iscr &= ~clr;
-       iscr |= set;
-       writel(iscr, data->base + REG_ISCR);
-}
-
-static void sun4i_usb_phy0_set_id_detect(struct phy *phy, u32 val)
-{
-       if (val)
-               val = ISCR_FORCE_ID_HIGH;
-       else
-               val = ISCR_FORCE_ID_LOW;
-
-       sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_ID_MASK, val);
-}
-
-static void sun4i_usb_phy0_set_vbus_detect(struct phy *phy, u32 val)
-{
-       if (val)
-               val = ISCR_FORCE_VBUS_HIGH;
-       else
-               val = ISCR_FORCE_VBUS_LOW;
-
-       sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_VBUS_MASK, val);
-}
-
-static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
-                               int len)
-{
-       struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
-       u32 temp, usbc_bit = BIT(phy->index * 2);
-       void __iomem *phyctl = phy_data->base + phy_data->cfg->phyctl_offset;
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&phy_data->reg_lock, flags);
-
-       if (phy_data->cfg->phyctl_offset == REG_PHYCTL_A33) {
-               /* SoCs newer than A33 need us to set phyctl to 0 explicitly */
-               writel(0, phyctl);
-       }
-
-       for (i = 0; i < len; i++) {
-               temp = readl(phyctl);
-
-               /* clear the address portion */
-               temp &= ~(0xff << 8);
-
-               /* set the address */
-               temp |= ((addr + i) << 8);
-               writel(temp, phyctl);
-
-               /* set the data bit and clear usbc bit*/
-               temp = readb(phyctl);
-               if (data & 0x1)
-                       temp |= PHYCTL_DATA;
-               else
-                       temp &= ~PHYCTL_DATA;
-               temp &= ~usbc_bit;
-               writeb(temp, phyctl);
-
-               /* pulse usbc_bit */
-               temp = readb(phyctl);
-               temp |= usbc_bit;
-               writeb(temp, phyctl);
-
-               temp = readb(phyctl);
-               temp &= ~usbc_bit;
-               writeb(temp, phyctl);
-
-               data >>= 1;
-       }
-
-       spin_unlock_irqrestore(&phy_data->reg_lock, flags);
-}
-
-static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
-{
-       u32 bits, reg_value;
-
-       if (!phy->pmu)
-               return;
-
-       bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
-               SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
-
-       reg_value = readl(phy->pmu);
-
-       if (enable)
-               reg_value |= bits;
-       else
-               reg_value &= ~bits;
-
-       writel(reg_value, phy->pmu);
-}
-
-static int sun4i_usb_phy_init(struct phy *_phy)
-{
-       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
-       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
-       int ret;
-       u32 val;
-
-       ret = clk_prepare_enable(phy->clk);
-       if (ret)
-               return ret;
-
-       ret = reset_control_deassert(phy->reset);
-       if (ret) {
-               clk_disable_unprepare(phy->clk);
-               return ret;
-       }
-
-       if (phy->pmu && data->cfg->enable_pmu_unk1) {
-               val = readl(phy->pmu + REG_PMU_UNK1);
-               writel(val & ~2, phy->pmu + REG_PMU_UNK1);
-       }
-
-       /* Enable USB 45 Ohm resistor calibration */
-       if (phy->index == 0)
-               sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1);
-
-       /* Adjust PHY's magnitude and rate */
-       sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
-
-       /* Disconnect threshold adjustment */
-       sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
-                           data->cfg->disc_thresh, 2);
-
-       sun4i_usb_phy_passby(phy, 1);
-
-       if (phy->index == 0) {
-               data->phy0_init = true;
-
-               /* Enable pull-ups */
-               sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_DPDM_PULLUP_EN);
-               sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_ID_PULLUP_EN);
-
-               /* Force ISCR and cable state updates */
-               data->id_det = -1;
-               data->vbus_det = -1;
-               queue_delayed_work(system_wq, &data->detect, 0);
-       }
-
-       return 0;
-}
-
-static int sun4i_usb_phy_exit(struct phy *_phy)
-{
-       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
-       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
-
-       if (phy->index == 0) {
-               /* Disable pull-ups */
-               sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0);
-               sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0);
-               data->phy0_init = false;
-       }
-
-       sun4i_usb_phy_passby(phy, 0);
-       reset_control_assert(phy->reset);
-       clk_disable_unprepare(phy->clk);
-
-       return 0;
-}
-
-static int sun4i_usb_phy0_get_id_det(struct sun4i_usb_phy_data *data)
-{
-       switch (data->dr_mode) {
-       case USB_DR_MODE_OTG:
-               if (data->id_det_gpio)
-                       return gpiod_get_value_cansleep(data->id_det_gpio);
-               else
-                       return 1; /* Fallback to peripheral mode */
-       case USB_DR_MODE_HOST:
-               return 0;
-       case USB_DR_MODE_PERIPHERAL:
-       default:
-               return 1;
-       }
-}
-
-static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data)
-{
-       if (data->vbus_det_gpio)
-               return gpiod_get_value_cansleep(data->vbus_det_gpio);
-
-       if (data->vbus_power_supply) {
-               union power_supply_propval val;
-               int r;
-
-               r = power_supply_get_property(data->vbus_power_supply,
-                                             POWER_SUPPLY_PROP_PRESENT, &val);
-               if (r == 0)
-                       return val.intval;
-       }
-
-       /* Fallback: report vbus as high */
-       return 1;
-}
-
-static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data)
-{
-       return data->vbus_det_gpio || data->vbus_power_supply;
-}
-
-static bool sun4i_usb_phy0_poll(struct sun4i_usb_phy_data *data)
-{
-       if ((data->id_det_gpio && data->id_det_irq <= 0) ||
-           (data->vbus_det_gpio && data->vbus_det_irq <= 0))
-               return true;
-
-       /*
-        * The A31 companion pmic (axp221) does not generate vbus change
-        * interrupts when the board is driving vbus, so we must poll
-        * when using the pmic for vbus-det _and_ we're driving vbus.
-        */
-       if (data->cfg->type == sun6i_a31_phy &&
-           data->vbus_power_supply && data->phys[0].regulator_on)
-               return true;
-
-       return false;
-}
-
-static int sun4i_usb_phy_power_on(struct phy *_phy)
-{
-       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
-       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
-       int ret;
-
-       if (!phy->vbus || phy->regulator_on)
-               return 0;
-
-       /* For phy0 only turn on Vbus if we don't have an ext. Vbus */
-       if (phy->index == 0 && sun4i_usb_phy0_have_vbus_det(data) &&
-                               data->vbus_det) {
-               dev_warn(&_phy->dev, "External vbus detected, not enabling our own vbus\n");
-               return 0;
-       }
-
-       ret = regulator_enable(phy->vbus);
-       if (ret)
-               return ret;
-
-       phy->regulator_on = true;
-
-       /* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */
-       if (phy->index == 0 && sun4i_usb_phy0_poll(data))
-               mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
-
-       return 0;
-}
-
-static int sun4i_usb_phy_power_off(struct phy *_phy)
-{
-       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
-       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
-
-       if (!phy->vbus || !phy->regulator_on)
-               return 0;
-
-       regulator_disable(phy->vbus);
-       phy->regulator_on = false;
-
-       /*
-        * phy0 vbus typically slowly discharges, sometimes this causes the
-        * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan.
-        */
-       if (phy->index == 0 && !sun4i_usb_phy0_poll(data))
-               mod_delayed_work(system_wq, &data->detect, POLL_TIME);
-
-       return 0;
-}
-
-static int sun4i_usb_phy_set_mode(struct phy *_phy, enum phy_mode mode)
-{
-       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
-       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
-       int new_mode;
-
-       if (phy->index != 0)
-               return -EINVAL;
-
-       switch (mode) {
-       case PHY_MODE_USB_HOST:
-               new_mode = USB_DR_MODE_HOST;
-               break;
-       case PHY_MODE_USB_DEVICE:
-               new_mode = USB_DR_MODE_PERIPHERAL;
-               break;
-       case PHY_MODE_USB_OTG:
-               new_mode = USB_DR_MODE_OTG;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (new_mode != data->dr_mode) {
-               dev_info(&_phy->dev, "Changing dr_mode to %d\n", new_mode);
-               data->dr_mode = new_mode;
-       }
-
-       data->id_det = -1; /* Force reprocessing of id */
-       data->force_session_end = true;
-       queue_delayed_work(system_wq, &data->detect, 0);
-
-       return 0;
-}
-
-void sun4i_usb_phy_set_squelch_detect(struct phy *_phy, bool enabled)
-{
-       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
-
-       sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2);
-}
-EXPORT_SYMBOL_GPL(sun4i_usb_phy_set_squelch_detect);
-
-static const struct phy_ops sun4i_usb_phy_ops = {
-       .init           = sun4i_usb_phy_init,
-       .exit           = sun4i_usb_phy_exit,
-       .power_on       = sun4i_usb_phy_power_on,
-       .power_off      = sun4i_usb_phy_power_off,
-       .set_mode       = sun4i_usb_phy_set_mode,
-       .owner          = THIS_MODULE,
-};
-
-static void sun4i_usb_phy0_reroute(struct sun4i_usb_phy_data *data, int id_det)
-{
-       u32 regval;
-
-       regval = readl(data->base + REG_PHY_OTGCTL);
-       if (id_det == 0) {
-               /* Host mode. Route phy0 to EHCI/OHCI */
-               regval &= ~OTGCTL_ROUTE_MUSB;
-       } else {
-               /* Peripheral mode. Route phy0 to MUSB */
-               regval |= OTGCTL_ROUTE_MUSB;
-       }
-       writel(regval, data->base + REG_PHY_OTGCTL);
-}
-
-static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
-{
-       struct sun4i_usb_phy_data *data =
-               container_of(work, struct sun4i_usb_phy_data, detect.work);
-       struct phy *phy0 = data->phys[0].phy;
-       bool force_session_end, id_notify = false, vbus_notify = false;
-       int id_det, vbus_det;
-
-       if (phy0 == NULL)
-               return;
-
-       id_det = sun4i_usb_phy0_get_id_det(data);
-       vbus_det = sun4i_usb_phy0_get_vbus_det(data);
-
-       mutex_lock(&phy0->mutex);
-
-       if (!data->phy0_init) {
-               mutex_unlock(&phy0->mutex);
-               return;
-       }
-
-       force_session_end = data->force_session_end;
-       data->force_session_end = false;
-
-       if (id_det != data->id_det) {
-               /* id-change, force session end if we've no vbus detection */
-               if (data->dr_mode == USB_DR_MODE_OTG &&
-                   !sun4i_usb_phy0_have_vbus_det(data))
-                       force_session_end = true;
-
-               /* When entering host mode (id = 0) force end the session now */
-               if (force_session_end && id_det == 0) {
-                       sun4i_usb_phy0_set_vbus_detect(phy0, 0);
-                       msleep(200);
-                       sun4i_usb_phy0_set_vbus_detect(phy0, 1);
-               }
-               sun4i_usb_phy0_set_id_detect(phy0, id_det);
-               data->id_det = id_det;
-               id_notify = true;
-       }
-
-       if (vbus_det != data->vbus_det) {
-               sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det);
-               data->vbus_det = vbus_det;
-               vbus_notify = true;
-       }
-
-       mutex_unlock(&phy0->mutex);
-
-       if (id_notify) {
-               extcon_set_state_sync(data->extcon, EXTCON_USB_HOST,
-                                       !id_det);
-               /* When leaving host mode force end the session here */
-               if (force_session_end && id_det == 1) {
-                       mutex_lock(&phy0->mutex);
-                       sun4i_usb_phy0_set_vbus_detect(phy0, 0);
-                       msleep(1000);
-                       sun4i_usb_phy0_set_vbus_detect(phy0, 1);
-                       mutex_unlock(&phy0->mutex);
-               }
-
-               /* Re-route PHY0 if necessary */
-               if (data->cfg->phy0_dual_route)
-                       sun4i_usb_phy0_reroute(data, id_det);
-       }
-
-       if (vbus_notify)
-               extcon_set_state_sync(data->extcon, EXTCON_USB, vbus_det);
-
-       if (sun4i_usb_phy0_poll(data))
-               queue_delayed_work(system_wq, &data->detect, POLL_TIME);
-}
-
-static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id)
-{
-       struct sun4i_usb_phy_data *data = dev_id;
-
-       /* vbus or id changed, let the pins settle and then scan them */
-       mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
-
-       return IRQ_HANDLED;
-}
-
-static int sun4i_usb_phy0_vbus_notify(struct notifier_block *nb,
-                                     unsigned long val, void *v)
-{
-       struct sun4i_usb_phy_data *data =
-               container_of(nb, struct sun4i_usb_phy_data, vbus_power_nb);
-       struct power_supply *psy = v;
-
-       /* Properties on the vbus_power_supply changed, scan vbus_det */
-       if (val == PSY_EVENT_PROP_CHANGED && psy == data->vbus_power_supply)
-               mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
-
-       return NOTIFY_OK;
-}
-
-static struct phy *sun4i_usb_phy_xlate(struct device *dev,
-                                       struct of_phandle_args *args)
-{
-       struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
-
-       if (args->args[0] >= data->cfg->num_phys)
-               return ERR_PTR(-ENODEV);
-
-       return data->phys[args->args[0]].phy;
-}
-
-static int sun4i_usb_phy_remove(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
-
-       if (data->vbus_power_nb_registered)
-               power_supply_unreg_notifier(&data->vbus_power_nb);
-       if (data->id_det_irq > 0)
-               devm_free_irq(dev, data->id_det_irq, data);
-       if (data->vbus_det_irq > 0)
-               devm_free_irq(dev, data->vbus_det_irq, data);
-
-       cancel_delayed_work_sync(&data->detect);
-
-       return 0;
-}
-
-static const unsigned int sun4i_usb_phy0_cable[] = {
-       EXTCON_USB,
-       EXTCON_USB_HOST,
-       EXTCON_NONE,
-};
-
-static int sun4i_usb_phy_probe(struct platform_device *pdev)
-{
-       struct sun4i_usb_phy_data *data;
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct phy_provider *phy_provider;
-       struct resource *res;
-       int i, ret;
-
-       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       spin_lock_init(&data->reg_lock);
-       INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan);
-       dev_set_drvdata(dev, data);
-       data->cfg = of_device_get_match_data(dev);
-       if (!data->cfg)
-               return -EINVAL;
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
-       data->base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(data->base))
-               return PTR_ERR(data->base);
-
-       data->id_det_gpio = devm_gpiod_get_optional(dev, "usb0_id_det",
-                                                   GPIOD_IN);
-       if (IS_ERR(data->id_det_gpio))
-               return PTR_ERR(data->id_det_gpio);
-
-       data->vbus_det_gpio = devm_gpiod_get_optional(dev, "usb0_vbus_det",
-                                                     GPIOD_IN);
-       if (IS_ERR(data->vbus_det_gpio))
-               return PTR_ERR(data->vbus_det_gpio);
-
-       if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
-               data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
-                                                    "usb0_vbus_power-supply");
-               if (IS_ERR(data->vbus_power_supply))
-                       return PTR_ERR(data->vbus_power_supply);
-
-               if (!data->vbus_power_supply)
-                       return -EPROBE_DEFER;
-       }
-
-       data->dr_mode = of_usb_get_dr_mode_by_phy(np, 0);
-
-       data->extcon = devm_extcon_dev_allocate(dev, sun4i_usb_phy0_cable);
-       if (IS_ERR(data->extcon))
-               return PTR_ERR(data->extcon);
-
-       ret = devm_extcon_dev_register(dev, data->extcon);
-       if (ret) {
-               dev_err(dev, "failed to register extcon: %d\n", ret);
-               return ret;
-       }
-
-       for (i = 0; i < data->cfg->num_phys; i++) {
-               struct sun4i_usb_phy *phy = data->phys + i;
-               char name[16];
-
-               snprintf(name, sizeof(name), "usb%d_vbus", i);
-               phy->vbus = devm_regulator_get_optional(dev, name);
-               if (IS_ERR(phy->vbus)) {
-                       if (PTR_ERR(phy->vbus) == -EPROBE_DEFER)
-                               return -EPROBE_DEFER;
-                       phy->vbus = NULL;
-               }
-
-               if (data->cfg->dedicated_clocks)
-                       snprintf(name, sizeof(name), "usb%d_phy", i);
-               else
-                       strlcpy(name, "usb_phy", sizeof(name));
-
-               phy->clk = devm_clk_get(dev, name);
-               if (IS_ERR(phy->clk)) {
-                       dev_err(dev, "failed to get clock %s\n", name);
-                       return PTR_ERR(phy->clk);
-               }
-
-               snprintf(name, sizeof(name), "usb%d_reset", i);
-               phy->reset = devm_reset_control_get(dev, name);
-               if (IS_ERR(phy->reset)) {
-                       dev_err(dev, "failed to get reset %s\n", name);
-                       return PTR_ERR(phy->reset);
-               }
-
-               if (i || data->cfg->phy0_dual_route) { /* No pmu for musb */
-                       snprintf(name, sizeof(name), "pmu%d", i);
-                       res = platform_get_resource_byname(pdev,
-                                                       IORESOURCE_MEM, name);
-                       phy->pmu = devm_ioremap_resource(dev, res);
-                       if (IS_ERR(phy->pmu))
-                               return PTR_ERR(phy->pmu);
-               }
-
-               phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops);
-               if (IS_ERR(phy->phy)) {
-                       dev_err(dev, "failed to create PHY %d\n", i);
-                       return PTR_ERR(phy->phy);
-               }
-
-               phy->index = i;
-               phy_set_drvdata(phy->phy, &data->phys[i]);
-       }
-
-       data->id_det_irq = gpiod_to_irq(data->id_det_gpio);
-       if (data->id_det_irq > 0) {
-               ret = devm_request_irq(dev, data->id_det_irq,
-                               sun4i_usb_phy0_id_vbus_det_irq,
-                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                               "usb0-id-det", data);
-               if (ret) {
-                       dev_err(dev, "Err requesting id-det-irq: %d\n", ret);
-                       return ret;
-               }
-       }
-
-       data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
-       if (data->vbus_det_irq > 0) {
-               ret = devm_request_irq(dev, data->vbus_det_irq,
-                               sun4i_usb_phy0_id_vbus_det_irq,
-                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                               "usb0-vbus-det", data);
-               if (ret) {
-                       dev_err(dev, "Err requesting vbus-det-irq: %d\n", ret);
-                       data->vbus_det_irq = -1;
-                       sun4i_usb_phy_remove(pdev); /* Stop detect work */
-                       return ret;
-               }
-       }
-
-       if (data->vbus_power_supply) {
-               data->vbus_power_nb.notifier_call = sun4i_usb_phy0_vbus_notify;
-               data->vbus_power_nb.priority = 0;
-               ret = power_supply_reg_notifier(&data->vbus_power_nb);
-               if (ret) {
-                       sun4i_usb_phy_remove(pdev); /* Stop detect work */
-                       return ret;
-               }
-               data->vbus_power_nb_registered = true;
-       }
-
-       phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
-       if (IS_ERR(phy_provider)) {
-               sun4i_usb_phy_remove(pdev); /* Stop detect work */
-               return PTR_ERR(phy_provider);
-       }
-
-       return 0;
-}
-
-static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = {
-       .num_phys = 3,
-       .type = sun4i_a10_phy,
-       .disc_thresh = 3,
-       .phyctl_offset = REG_PHYCTL_A10,
-       .dedicated_clocks = false,
-       .enable_pmu_unk1 = false,
-};
-
-static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
-       .num_phys = 2,
-       .type = sun4i_a10_phy,
-       .disc_thresh = 2,
-       .phyctl_offset = REG_PHYCTL_A10,
-       .dedicated_clocks = false,
-       .enable_pmu_unk1 = false,
-};
-
-static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
-       .num_phys = 3,
-       .type = sun6i_a31_phy,
-       .disc_thresh = 3,
-       .phyctl_offset = REG_PHYCTL_A10,
-       .dedicated_clocks = true,
-       .enable_pmu_unk1 = false,
-};
-
-static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = {
-       .num_phys = 3,
-       .type = sun4i_a10_phy,
-       .disc_thresh = 2,
-       .phyctl_offset = REG_PHYCTL_A10,
-       .dedicated_clocks = false,
-       .enable_pmu_unk1 = false,
-};
-
-static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
-       .num_phys = 2,
-       .type = sun4i_a10_phy,
-       .disc_thresh = 3,
-       .phyctl_offset = REG_PHYCTL_A10,
-       .dedicated_clocks = true,
-       .enable_pmu_unk1 = false,
-};
-
-static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
-       .num_phys = 2,
-       .type = sun8i_a33_phy,
-       .disc_thresh = 3,
-       .phyctl_offset = REG_PHYCTL_A33,
-       .dedicated_clocks = true,
-       .enable_pmu_unk1 = false,
-};
-
-static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
-       .num_phys = 4,
-       .type = sun8i_h3_phy,
-       .disc_thresh = 3,
-       .phyctl_offset = REG_PHYCTL_A33,
-       .dedicated_clocks = true,
-       .enable_pmu_unk1 = true,
-       .phy0_dual_route = true,
-};
-
-static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
-       .num_phys = 1,
-       .type = sun8i_v3s_phy,
-       .disc_thresh = 3,
-       .phyctl_offset = REG_PHYCTL_A33,
-       .dedicated_clocks = true,
-       .enable_pmu_unk1 = true,
-};
-
-static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
-       .num_phys = 2,
-       .type = sun50i_a64_phy,
-       .disc_thresh = 3,
-       .phyctl_offset = REG_PHYCTL_A33,
-       .dedicated_clocks = true,
-       .enable_pmu_unk1 = true,
-       .phy0_dual_route = true,
-};
-
-static const struct of_device_id sun4i_usb_phy_of_match[] = {
-       { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg },
-       { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg },
-       { .compatible = "allwinner,sun6i-a31-usb-phy", .data = &sun6i_a31_cfg },
-       { .compatible = "allwinner,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg },
-       { .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
-       { .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg },
-       { .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg },
-       { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
-       { .compatible = "allwinner,sun50i-a64-usb-phy",
-         .data = &sun50i_a64_cfg},
-       { },
-};
-MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
-
-static struct platform_driver sun4i_usb_phy_driver = {
-       .probe  = sun4i_usb_phy_probe,
-       .remove = sun4i_usb_phy_remove,
-       .driver = {
-               .of_match_table = sun4i_usb_phy_of_match,
-               .name  = "sun4i-usb-phy",
-       }
-};
-module_platform_driver(sun4i_usb_phy_driver);
-
-MODULE_DESCRIPTION("Allwinner sun4i USB phy driver");
-MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-sun9i-usb.c b/drivers/phy/phy-sun9i-usb.c
deleted file mode 100644 (file)
index 28fce4b..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Allwinner sun9i USB phy driver
- *
- * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
- *
- * Based on phy-sun4i-usb.c from
- * Hans de Goede <hdegoede@redhat.com>
- *
- * and code from
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/phy/phy.h>
-#include <linux/usb/of.h>
-#include <linux/platform_device.h>
-#include <linux/reset.h>
-
-#define SUNXI_AHB_INCR16_BURST_EN      BIT(11)
-#define SUNXI_AHB_INCR8_BURST_EN       BIT(10)
-#define SUNXI_AHB_INCR4_BURST_EN       BIT(9)
-#define SUNXI_AHB_INCRX_ALIGN_EN       BIT(8)
-#define SUNXI_ULPI_BYPASS_EN           BIT(0)
-
-/* usb1 HSIC specific bits */
-#define SUNXI_EHCI_HS_FORCE            BIT(20)
-#define SUNXI_HSIC_CONNECT_DET         BIT(17)
-#define SUNXI_HSIC_CONNECT_INT         BIT(16)
-#define SUNXI_HSIC                     BIT(1)
-
-struct sun9i_usb_phy {
-       struct phy *phy;
-       void __iomem *pmu;
-       struct reset_control *reset;
-       struct clk *clk;
-       struct clk *hsic_clk;
-       enum usb_phy_interface type;
-};
-
-static void sun9i_usb_phy_passby(struct sun9i_usb_phy *phy, int enable)
-{
-       u32 bits, reg_value;
-
-       bits = SUNXI_AHB_INCR16_BURST_EN | SUNXI_AHB_INCR8_BURST_EN |
-               SUNXI_AHB_INCR4_BURST_EN | SUNXI_AHB_INCRX_ALIGN_EN |
-               SUNXI_ULPI_BYPASS_EN;
-
-       if (phy->type == USBPHY_INTERFACE_MODE_HSIC)
-               bits |= SUNXI_HSIC | SUNXI_EHCI_HS_FORCE |
-                       SUNXI_HSIC_CONNECT_DET | SUNXI_HSIC_CONNECT_INT;
-
-       reg_value = readl(phy->pmu);
-
-       if (enable)
-               reg_value |= bits;
-       else
-               reg_value &= ~bits;
-
-       writel(reg_value, phy->pmu);
-}
-
-static int sun9i_usb_phy_init(struct phy *_phy)
-{
-       struct sun9i_usb_phy *phy = phy_get_drvdata(_phy);
-       int ret;
-
-       ret = clk_prepare_enable(phy->clk);
-       if (ret)
-               goto err_clk;
-
-       ret = clk_prepare_enable(phy->hsic_clk);
-       if (ret)
-               goto err_hsic_clk;
-
-       ret = reset_control_deassert(phy->reset);
-       if (ret)
-               goto err_reset;
-
-       sun9i_usb_phy_passby(phy, 1);
-       return 0;
-
-err_reset:
-       clk_disable_unprepare(phy->hsic_clk);
-
-err_hsic_clk:
-       clk_disable_unprepare(phy->clk);
-
-err_clk:
-       return ret;
-}
-
-static int sun9i_usb_phy_exit(struct phy *_phy)
-{
-       struct sun9i_usb_phy *phy = phy_get_drvdata(_phy);
-
-       sun9i_usb_phy_passby(phy, 0);
-       reset_control_assert(phy->reset);
-       clk_disable_unprepare(phy->hsic_clk);
-       clk_disable_unprepare(phy->clk);
-
-       return 0;
-}
-
-static const struct phy_ops sun9i_usb_phy_ops = {
-       .init           = sun9i_usb_phy_init,
-       .exit           = sun9i_usb_phy_exit,
-       .owner          = THIS_MODULE,
-};
-
-static int sun9i_usb_phy_probe(struct platform_device *pdev)
-{
-       struct sun9i_usb_phy *phy;
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct phy_provider *phy_provider;
-       struct resource *res;
-
-       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
-       if (!phy)
-               return -ENOMEM;
-
-       phy->type = of_usb_get_phy_mode(np);
-       if (phy->type == USBPHY_INTERFACE_MODE_HSIC) {
-               phy->clk = devm_clk_get(dev, "hsic_480M");
-               if (IS_ERR(phy->clk)) {
-                       dev_err(dev, "failed to get hsic_480M clock\n");
-                       return PTR_ERR(phy->clk);
-               }
-
-               phy->hsic_clk = devm_clk_get(dev, "hsic_12M");
-               if (IS_ERR(phy->hsic_clk)) {
-                       dev_err(dev, "failed to get hsic_12M clock\n");
-                       return PTR_ERR(phy->hsic_clk);
-               }
-
-               phy->reset = devm_reset_control_get(dev, "hsic");
-               if (IS_ERR(phy->reset)) {
-                       dev_err(dev, "failed to get reset control\n");
-                       return PTR_ERR(phy->reset);
-               }
-       } else {
-               phy->clk = devm_clk_get(dev, "phy");
-               if (IS_ERR(phy->clk)) {
-                       dev_err(dev, "failed to get phy clock\n");
-                       return PTR_ERR(phy->clk);
-               }
-
-               phy->reset = devm_reset_control_get(dev, "phy");
-               if (IS_ERR(phy->reset)) {
-                       dev_err(dev, "failed to get reset control\n");
-                       return PTR_ERR(phy->reset);
-               }
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       phy->pmu = devm_ioremap_resource(dev, res);
-       if (IS_ERR(phy->pmu))
-               return PTR_ERR(phy->pmu);
-
-       phy->phy = devm_phy_create(dev, NULL, &sun9i_usb_phy_ops);
-       if (IS_ERR(phy->phy)) {
-               dev_err(dev, "failed to create PHY\n");
-               return PTR_ERR(phy->phy);
-       }
-
-       phy_set_drvdata(phy->phy, phy);
-       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 sun9i_usb_phy_of_match[] = {
-       { .compatible = "allwinner,sun9i-a80-usb-phy" },
-       { },
-};
-MODULE_DEVICE_TABLE(of, sun9i_usb_phy_of_match);
-
-static struct platform_driver sun9i_usb_phy_driver = {
-       .probe  = sun9i_usb_phy_probe,
-       .driver = {
-               .of_match_table = sun9i_usb_phy_of_match,
-               .name  = "sun9i-usb-phy",
-       }
-};
-module_platform_driver(sun9i_usb_phy_driver);
-
-MODULE_DESCRIPTION("Allwinner sun9i USB phy driver");
-MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
deleted file mode 100644 (file)
index 9c84d32..0000000
+++ /dev/null
@@ -1,697 +0,0 @@
-/*
- * phy-ti-pipe3 - PIPE3 PHY driver.
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.com>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/phy/phy.h>
-#include <linux/of.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/delay.h>
-#include <linux/phy/omap_control_phy.h>
-#include <linux/of_platform.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
-
-#define        PLL_STATUS              0x00000004
-#define        PLL_GO                  0x00000008
-#define        PLL_CONFIGURATION1      0x0000000C
-#define        PLL_CONFIGURATION2      0x00000010
-#define        PLL_CONFIGURATION3      0x00000014
-#define        PLL_CONFIGURATION4      0x00000020
-
-#define        PLL_REGM_MASK           0x001FFE00
-#define        PLL_REGM_SHIFT          0x9
-#define        PLL_REGM_F_MASK         0x0003FFFF
-#define        PLL_REGM_F_SHIFT        0x0
-#define        PLL_REGN_MASK           0x000001FE
-#define        PLL_REGN_SHIFT          0x1
-#define        PLL_SELFREQDCO_MASK     0x0000000E
-#define        PLL_SELFREQDCO_SHIFT    0x1
-#define        PLL_SD_MASK             0x0003FC00
-#define        PLL_SD_SHIFT            10
-#define        SET_PLL_GO              0x1
-#define PLL_LDOPWDN            BIT(15)
-#define PLL_TICOPWDN           BIT(16)
-#define        PLL_LOCK                0x2
-#define        PLL_IDLE                0x1
-
-#define SATA_PLL_SOFT_RESET    BIT(18)
-
-#define PIPE3_PHY_PWRCTL_CLK_CMD_MASK  0x003FC000
-#define PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT 14
-
-#define PIPE3_PHY_PWRCTL_CLK_FREQ_MASK 0xFFC00000
-#define PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT        22
-
-#define PIPE3_PHY_TX_RX_POWERON                0x3
-#define PIPE3_PHY_TX_RX_POWEROFF       0x0
-
-#define PCIE_PCS_MASK                  0xFF0000
-#define PCIE_PCS_DELAY_COUNT_SHIFT     0x10
-
-/*
- * This is an Empirical value that works, need to confirm the actual
- * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
- * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
- */
-#define PLL_IDLE_TIME  100     /* in milliseconds */
-#define PLL_LOCK_TIME  100     /* in milliseconds */
-
-struct pipe3_dpll_params {
-       u16     m;
-       u8      n;
-       u8      freq:3;
-       u8      sd;
-       u32     mf;
-};
-
-struct pipe3_dpll_map {
-       unsigned long rate;
-       struct pipe3_dpll_params params;
-};
-
-struct ti_pipe3 {
-       void __iomem            *pll_ctrl_base;
-       struct device           *dev;
-       struct device           *control_dev;
-       struct clk              *wkupclk;
-       struct clk              *sys_clk;
-       struct clk              *refclk;
-       struct clk              *div_clk;
-       struct pipe3_dpll_map   *dpll_map;
-       struct regmap           *phy_power_syscon; /* ctrl. reg. acces */
-       struct regmap           *pcs_syscon; /* ctrl. reg. acces */
-       struct regmap           *dpll_reset_syscon; /* ctrl. reg. acces */
-       unsigned int            dpll_reset_reg; /* reg. index within syscon */
-       unsigned int            power_reg; /* power reg. index within syscon */
-       unsigned int            pcie_pcs_reg; /* pcs reg. index in syscon */
-       bool                    sata_refclk_enabled;
-};
-
-static struct pipe3_dpll_map dpll_map_usb[] = {
-       {12000000, {1250, 5, 4, 20, 0} },       /* 12 MHz */
-       {16800000, {3125, 20, 4, 20, 0} },      /* 16.8 MHz */
-       {19200000, {1172, 8, 4, 20, 65537} },   /* 19.2 MHz */
-       {20000000, {1000, 7, 4, 10, 0} },       /* 20 MHz */
-       {26000000, {1250, 12, 4, 20, 0} },      /* 26 MHz */
-       {38400000, {3125, 47, 4, 20, 92843} },  /* 38.4 MHz */
-       { },                                    /* Terminator */
-};
-
-static struct pipe3_dpll_map dpll_map_sata[] = {
-       {12000000, {1000, 7, 4, 6, 0} },        /* 12 MHz */
-       {16800000, {714, 7, 4, 6, 0} },         /* 16.8 MHz */
-       {19200000, {625, 7, 4, 6, 0} },         /* 19.2 MHz */
-       {20000000, {600, 7, 4, 6, 0} },         /* 20 MHz */
-       {26000000, {461, 7, 4, 6, 0} },         /* 26 MHz */
-       {38400000, {312, 7, 4, 6, 0} },         /* 38.4 MHz */
-       { },                                    /* Terminator */
-};
-
-static inline u32 ti_pipe3_readl(void __iomem *addr, unsigned offset)
-{
-       return __raw_readl(addr + offset);
-}
-
-static inline void ti_pipe3_writel(void __iomem *addr, unsigned offset,
-       u32 data)
-{
-       __raw_writel(data, addr + offset);
-}
-
-static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy)
-{
-       unsigned long rate;
-       struct pipe3_dpll_map *dpll_map = phy->dpll_map;
-
-       rate = clk_get_rate(phy->sys_clk);
-
-       for (; dpll_map->rate; dpll_map++) {
-               if (rate == dpll_map->rate)
-                       return &dpll_map->params;
-       }
-
-       dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n", rate);
-
-       return NULL;
-}
-
-static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy);
-static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy);
-
-static int ti_pipe3_power_off(struct phy *x)
-{
-       u32 val;
-       int ret;
-       struct ti_pipe3 *phy = phy_get_drvdata(x);
-
-       if (!phy->phy_power_syscon) {
-               omap_control_phy_power(phy->control_dev, 0);
-               return 0;
-       }
-
-       val = PIPE3_PHY_TX_RX_POWEROFF << PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
-
-       ret = regmap_update_bits(phy->phy_power_syscon, phy->power_reg,
-                                PIPE3_PHY_PWRCTL_CLK_CMD_MASK, val);
-       return ret;
-}
-
-static int ti_pipe3_power_on(struct phy *x)
-{
-       u32 val;
-       u32 mask;
-       int ret;
-       unsigned long rate;
-       struct ti_pipe3 *phy = phy_get_drvdata(x);
-
-       if (!phy->phy_power_syscon) {
-               omap_control_phy_power(phy->control_dev, 1);
-               return 0;
-       }
-
-       rate = clk_get_rate(phy->sys_clk);
-       if (!rate) {
-               dev_err(phy->dev, "Invalid clock rate\n");
-               return -EINVAL;
-       }
-       rate = rate / 1000000;
-       mask = OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK |
-                 OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK;
-       val = PIPE3_PHY_TX_RX_POWERON << PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
-       val |= rate << OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT;
-
-       ret = regmap_update_bits(phy->phy_power_syscon, phy->power_reg,
-                                mask, val);
-       return ret;
-}
-
-static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy)
-{
-       u32             val;
-       unsigned long   timeout;
-
-       timeout = jiffies + msecs_to_jiffies(PLL_LOCK_TIME);
-       do {
-               cpu_relax();
-               val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
-               if (val & PLL_LOCK)
-                       return 0;
-       } while (!time_after(jiffies, timeout));
-
-       dev_err(phy->dev, "DPLL failed to lock\n");
-       return -EBUSY;
-}
-
-static int ti_pipe3_dpll_program(struct ti_pipe3 *phy)
-{
-       u32                     val;
-       struct pipe3_dpll_params *dpll_params;
-
-       dpll_params = ti_pipe3_get_dpll_params(phy);
-       if (!dpll_params)
-               return -EINVAL;
-
-       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
-       val &= ~PLL_REGN_MASK;
-       val |= dpll_params->n << PLL_REGN_SHIFT;
-       ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
-
-       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
-       val &= ~PLL_SELFREQDCO_MASK;
-       val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
-       ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
-
-       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
-       val &= ~PLL_REGM_MASK;
-       val |= dpll_params->m << PLL_REGM_SHIFT;
-       ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
-
-       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
-       val &= ~PLL_REGM_F_MASK;
-       val |= dpll_params->mf << PLL_REGM_F_SHIFT;
-       ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
-
-       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
-       val &= ~PLL_SD_MASK;
-       val |= dpll_params->sd << PLL_SD_SHIFT;
-       ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
-
-       ti_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
-
-       return ti_pipe3_dpll_wait_lock(phy);
-}
-
-static int ti_pipe3_init(struct phy *x)
-{
-       struct ti_pipe3 *phy = phy_get_drvdata(x);
-       u32 val;
-       int ret = 0;
-
-       ti_pipe3_enable_clocks(phy);
-       /*
-        * Set pcie_pcs register to 0x96 for proper functioning of phy
-        * as recommended in AM572x TRM SPRUHZ6, section 18.5.2.2, table
-        * 18-1804.
-        */
-       if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
-               if (!phy->pcs_syscon) {
-                       omap_control_pcie_pcs(phy->control_dev, 0x96);
-                       return 0;
-               }
-
-               val = 0x96 << OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT;
-               ret = regmap_update_bits(phy->pcs_syscon, phy->pcie_pcs_reg,
-                                        PCIE_PCS_MASK, val);
-               return ret;
-       }
-
-       /* Bring it out of IDLE if it is IDLE */
-       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
-       if (val & PLL_IDLE) {
-               val &= ~PLL_IDLE;
-               ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
-               ret = ti_pipe3_dpll_wait_lock(phy);
-       }
-
-       /* SATA has issues if re-programmed when locked */
-       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
-       if ((val & PLL_LOCK) && of_device_is_compatible(phy->dev->of_node,
-                                                       "ti,phy-pipe3-sata"))
-               return ret;
-
-       /* Program the DPLL */
-       ret = ti_pipe3_dpll_program(phy);
-       if (ret) {
-               ti_pipe3_disable_clocks(phy);
-               return -EINVAL;
-       }
-
-       return ret;
-}
-
-static int ti_pipe3_exit(struct phy *x)
-{
-       struct ti_pipe3 *phy = phy_get_drvdata(x);
-       u32 val;
-       unsigned long timeout;
-
-       /* If dpll_reset_syscon is not present we wont power down SATA DPLL
-        * due to Errata i783
-        */
-       if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") &&
-           !phy->dpll_reset_syscon)
-               return 0;
-
-       /* PCIe doesn't have internal DPLL */
-       if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
-               /* Put DPLL in IDLE mode */
-               val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
-               val |= PLL_IDLE;
-               ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
-
-               /* wait for LDO and Oscillator to power down */
-               timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME);
-               do {
-                       cpu_relax();
-                       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
-                       if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
-                               break;
-               } while (!time_after(jiffies, timeout));
-
-               if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
-                       dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n",
-                               val);
-                       return -EBUSY;
-               }
-       }
-
-       /* i783: SATA needs control bit toggle after PLL unlock */
-       if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) {
-               regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg,
-                                  SATA_PLL_SOFT_RESET, SATA_PLL_SOFT_RESET);
-               regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg,
-                                  SATA_PLL_SOFT_RESET, 0);
-       }
-
-       ti_pipe3_disable_clocks(phy);
-
-       return 0;
-}
-static const struct phy_ops ops = {
-       .init           = ti_pipe3_init,
-       .exit           = ti_pipe3_exit,
-       .power_on       = ti_pipe3_power_on,
-       .power_off      = ti_pipe3_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static const struct of_device_id ti_pipe3_id_table[];
-
-static int ti_pipe3_get_clk(struct ti_pipe3 *phy)
-{
-       struct clk *clk;
-       struct device *dev = phy->dev;
-       struct device_node *node = dev->of_node;
-
-       phy->refclk = devm_clk_get(dev, "refclk");
-       if (IS_ERR(phy->refclk)) {
-               dev_err(dev, "unable to get refclk\n");
-               /* older DTBs have missing refclk in SATA PHY
-                * so don't bail out in case of SATA PHY.
-                */
-               if (!of_device_is_compatible(node, "ti,phy-pipe3-sata"))
-                       return PTR_ERR(phy->refclk);
-       }
-
-       if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
-               phy->wkupclk = devm_clk_get(dev, "wkupclk");
-               if (IS_ERR(phy->wkupclk)) {
-                       dev_err(dev, "unable to get wkupclk\n");
-                       return PTR_ERR(phy->wkupclk);
-               }
-       } else {
-               phy->wkupclk = ERR_PTR(-ENODEV);
-       }
-
-       if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie") ||
-           phy->phy_power_syscon) {
-               phy->sys_clk = devm_clk_get(dev, "sysclk");
-               if (IS_ERR(phy->sys_clk)) {
-                       dev_err(dev, "unable to get sysclk\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
-               clk = devm_clk_get(dev, "dpll_ref");
-               if (IS_ERR(clk)) {
-                       dev_err(dev, "unable to get dpll ref clk\n");
-                       return PTR_ERR(clk);
-               }
-               clk_set_rate(clk, 1500000000);
-
-               clk = devm_clk_get(dev, "dpll_ref_m2");
-               if (IS_ERR(clk)) {
-                       dev_err(dev, "unable to get dpll ref m2 clk\n");
-                       return PTR_ERR(clk);
-               }
-               clk_set_rate(clk, 100000000);
-
-               clk = devm_clk_get(dev, "phy-div");
-               if (IS_ERR(clk)) {
-                       dev_err(dev, "unable to get phy-div clk\n");
-                       return PTR_ERR(clk);
-               }
-               clk_set_rate(clk, 100000000);
-
-               phy->div_clk = devm_clk_get(dev, "div-clk");
-               if (IS_ERR(phy->div_clk)) {
-                       dev_err(dev, "unable to get div-clk\n");
-                       return PTR_ERR(phy->div_clk);
-               }
-       } else {
-               phy->div_clk = ERR_PTR(-ENODEV);
-       }
-
-       return 0;
-}
-
-static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy)
-{
-       struct device *dev = phy->dev;
-       struct device_node *node = dev->of_node;
-       struct device_node *control_node;
-       struct platform_device *control_pdev;
-
-       phy->phy_power_syscon = syscon_regmap_lookup_by_phandle(node,
-                                                       "syscon-phy-power");
-       if (IS_ERR(phy->phy_power_syscon)) {
-               dev_dbg(dev,
-                       "can't get syscon-phy-power, using control device\n");
-               phy->phy_power_syscon = NULL;
-       } else {
-               if (of_property_read_u32_index(node,
-                                              "syscon-phy-power", 1,
-                                              &phy->power_reg)) {
-                       dev_err(dev, "couldn't get power reg. offset\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (!phy->phy_power_syscon) {
-               control_node = of_parse_phandle(node, "ctrl-module", 0);
-               if (!control_node) {
-                       dev_err(dev, "Failed to get control device phandle\n");
-                       return -EINVAL;
-               }
-
-               control_pdev = of_find_device_by_node(control_node);
-               if (!control_pdev) {
-                       dev_err(dev, "Failed to get control device\n");
-                       return -EINVAL;
-               }
-
-               phy->control_dev = &control_pdev->dev;
-       }
-
-       if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
-               phy->pcs_syscon = syscon_regmap_lookup_by_phandle(node,
-                                                                 "syscon-pcs");
-               if (IS_ERR(phy->pcs_syscon)) {
-                       dev_dbg(dev,
-                               "can't get syscon-pcs, using omap control\n");
-                       phy->pcs_syscon = NULL;
-               } else {
-                       if (of_property_read_u32_index(node,
-                                                      "syscon-pcs", 1,
-                                                      &phy->pcie_pcs_reg)) {
-                               dev_err(dev,
-                                       "couldn't get pcie pcs reg. offset\n");
-                               return -EINVAL;
-                       }
-               }
-       }
-
-       if (of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
-               phy->dpll_reset_syscon = syscon_regmap_lookup_by_phandle(node,
-                                                       "syscon-pllreset");
-               if (IS_ERR(phy->dpll_reset_syscon)) {
-                       dev_info(dev,
-                                "can't get syscon-pllreset, sata dpll won't idle\n");
-                       phy->dpll_reset_syscon = NULL;
-               } else {
-                       if (of_property_read_u32_index(node,
-                                                      "syscon-pllreset", 1,
-                                                      &phy->dpll_reset_reg)) {
-                               dev_err(dev,
-                                       "couldn't get pllreset reg. offset\n");
-                               return -EINVAL;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int ti_pipe3_get_pll_base(struct ti_pipe3 *phy)
-{
-       struct resource *res;
-       const struct of_device_id *match;
-       struct device *dev = phy->dev;
-       struct device_node *node = dev->of_node;
-       struct platform_device *pdev = to_platform_device(dev);
-
-       if (of_device_is_compatible(node, "ti,phy-pipe3-pcie"))
-               return 0;
-
-       match = of_match_device(ti_pipe3_id_table, dev);
-       if (!match)
-               return -EINVAL;
-
-       phy->dpll_map = (struct pipe3_dpll_map *)match->data;
-       if (!phy->dpll_map) {
-               dev_err(dev, "no DPLL data\n");
-               return -EINVAL;
-       }
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                                          "pll_ctrl");
-       phy->pll_ctrl_base = devm_ioremap_resource(dev, res);
-       return PTR_ERR_OR_ZERO(phy->pll_ctrl_base);
-}
-
-static int ti_pipe3_probe(struct platform_device *pdev)
-{
-       struct ti_pipe3 *phy;
-       struct phy *generic_phy;
-       struct phy_provider *phy_provider;
-       struct device_node *node = pdev->dev.of_node;
-       struct device *dev = &pdev->dev;
-       int ret;
-
-       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
-       if (!phy)
-               return -ENOMEM;
-
-       phy->dev                = dev;
-
-       ret = ti_pipe3_get_pll_base(phy);
-       if (ret)
-               return ret;
-
-       ret = ti_pipe3_get_sysctrl(phy);
-       if (ret)
-               return ret;
-
-       ret = ti_pipe3_get_clk(phy);
-       if (ret)
-               return ret;
-
-       platform_set_drvdata(pdev, phy);
-       pm_runtime_enable(dev);
-
-       /*
-        * Prevent auto-disable of refclk for SATA PHY due to Errata i783
-        */
-       if (of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
-               if (!IS_ERR(phy->refclk)) {
-                       clk_prepare_enable(phy->refclk);
-                       phy->sata_refclk_enabled = true;
-               }
-       }
-
-       generic_phy = devm_phy_create(dev, NULL, &ops);
-       if (IS_ERR(generic_phy))
-               return PTR_ERR(generic_phy);
-
-       phy_set_drvdata(generic_phy, phy);
-
-       ti_pipe3_power_off(generic_phy);
-
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static int ti_pipe3_remove(struct platform_device *pdev)
-{
-       pm_runtime_disable(&pdev->dev);
-
-       return 0;
-}
-
-static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy)
-{
-       int ret = 0;
-
-       if (!IS_ERR(phy->refclk)) {
-               ret = clk_prepare_enable(phy->refclk);
-               if (ret) {
-                       dev_err(phy->dev, "Failed to enable refclk %d\n", ret);
-                       return ret;
-               }
-       }
-
-       if (!IS_ERR(phy->wkupclk)) {
-               ret = clk_prepare_enable(phy->wkupclk);
-               if (ret) {
-                       dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
-                       goto disable_refclk;
-               }
-       }
-
-       if (!IS_ERR(phy->div_clk)) {
-               ret = clk_prepare_enable(phy->div_clk);
-               if (ret) {
-                       dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
-                       goto disable_wkupclk;
-               }
-       }
-
-       return 0;
-
-disable_wkupclk:
-       if (!IS_ERR(phy->wkupclk))
-               clk_disable_unprepare(phy->wkupclk);
-
-disable_refclk:
-       if (!IS_ERR(phy->refclk))
-               clk_disable_unprepare(phy->refclk);
-
-       return ret;
-}
-
-static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy)
-{
-       if (!IS_ERR(phy->wkupclk))
-               clk_disable_unprepare(phy->wkupclk);
-       if (!IS_ERR(phy->refclk)) {
-               clk_disable_unprepare(phy->refclk);
-               /*
-                * SATA refclk needs an additional disable as we left it
-                * on in probe to avoid Errata i783
-                */
-               if (phy->sata_refclk_enabled) {
-                       clk_disable_unprepare(phy->refclk);
-                       phy->sata_refclk_enabled = false;
-               }
-       }
-
-       if (!IS_ERR(phy->div_clk))
-               clk_disable_unprepare(phy->div_clk);
-}
-
-static const struct of_device_id ti_pipe3_id_table[] = {
-       {
-               .compatible = "ti,phy-usb3",
-               .data = dpll_map_usb,
-       },
-       {
-               .compatible = "ti,omap-usb3",
-               .data = dpll_map_usb,
-       },
-       {
-               .compatible = "ti,phy-pipe3-sata",
-               .data = dpll_map_sata,
-       },
-       {
-               .compatible = "ti,phy-pipe3-pcie",
-       },
-       {}
-};
-MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
-
-static struct platform_driver ti_pipe3_driver = {
-       .probe          = ti_pipe3_probe,
-       .remove         = ti_pipe3_remove,
-       .driver         = {
-               .name   = "ti-pipe3",
-               .of_match_table = ti_pipe3_id_table,
-       },
-};
-
-module_platform_driver(ti_pipe3_driver);
-
-MODULE_ALIAS("platform:ti_pipe3");
-MODULE_AUTHOR("Texas Instruments Inc.");
-MODULE_DESCRIPTION("TI PIPE3 phy driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-tusb1210.c b/drivers/phy/phy-tusb1210.c
deleted file mode 100644 (file)
index bb3fb03..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/**
- * tusb1210.c - TUSB1210 USB ULPI PHY driver
- *
- * Copyright (C) 2015 Intel Corporation
- *
- * Author: Heikki Krogerus <heikki.krogerus@linux.intel.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.
- */
-#include <linux/module.h>
-#include <linux/ulpi/driver.h>
-#include <linux/gpio/consumer.h>
-#include <linux/phy/ulpi_phy.h>
-
-#define TUSB1210_VENDOR_SPECIFIC2              0x80
-#define TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT  0
-#define TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_SHIFT 4
-#define TUSB1210_VENDOR_SPECIFIC2_DP_SHIFT     6
-
-struct tusb1210 {
-       struct ulpi *ulpi;
-       struct phy *phy;
-       struct gpio_desc *gpio_reset;
-       struct gpio_desc *gpio_cs;
-       u8 vendor_specific2;
-};
-
-static int tusb1210_power_on(struct phy *phy)
-{
-       struct tusb1210 *tusb = phy_get_drvdata(phy);
-
-       gpiod_set_value_cansleep(tusb->gpio_reset, 1);
-       gpiod_set_value_cansleep(tusb->gpio_cs, 1);
-
-       /* Restore the optional eye diagram optimization value */
-       if (tusb->vendor_specific2)
-               ulpi_write(tusb->ulpi, TUSB1210_VENDOR_SPECIFIC2,
-                          tusb->vendor_specific2);
-
-       return 0;
-}
-
-static int tusb1210_power_off(struct phy *phy)
-{
-       struct tusb1210 *tusb = phy_get_drvdata(phy);
-
-       gpiod_set_value_cansleep(tusb->gpio_reset, 0);
-       gpiod_set_value_cansleep(tusb->gpio_cs, 0);
-
-       return 0;
-}
-
-static const struct phy_ops phy_ops = {
-       .power_on = tusb1210_power_on,
-       .power_off = tusb1210_power_off,
-       .owner = THIS_MODULE,
-};
-
-static int tusb1210_probe(struct ulpi *ulpi)
-{
-       struct tusb1210 *tusb;
-       u8 val, reg;
-
-       tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL);
-       if (!tusb)
-               return -ENOMEM;
-
-       tusb->gpio_reset = devm_gpiod_get_optional(&ulpi->dev, "reset",
-                                                  GPIOD_OUT_LOW);
-       if (IS_ERR(tusb->gpio_reset))
-               return PTR_ERR(tusb->gpio_reset);
-
-       gpiod_set_value_cansleep(tusb->gpio_reset, 1);
-
-       tusb->gpio_cs = devm_gpiod_get_optional(&ulpi->dev, "cs",
-                                               GPIOD_OUT_LOW);
-       if (IS_ERR(tusb->gpio_cs))
-               return PTR_ERR(tusb->gpio_cs);
-
-       gpiod_set_value_cansleep(tusb->gpio_cs, 1);
-
-       /*
-        * VENDOR_SPECIFIC2 register in TUSB1210 can be used for configuring eye
-        * diagram optimization and DP/DM swap.
-        */
-
-       /* High speed output drive strength configuration */
-       device_property_read_u8(&ulpi->dev, "ihstx", &val);
-       reg = val << TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT;
-
-       /* High speed output impedance configuration */
-       device_property_read_u8(&ulpi->dev, "zhsdrv", &val);
-       reg |= val << TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_SHIFT;
-
-       /* DP/DM swap control */
-       device_property_read_u8(&ulpi->dev, "datapolarity", &val);
-       reg |= val << TUSB1210_VENDOR_SPECIFIC2_DP_SHIFT;
-
-       if (reg) {
-               ulpi_write(ulpi, TUSB1210_VENDOR_SPECIFIC2, reg);
-               tusb->vendor_specific2 = reg;
-       }
-
-       tusb->phy = ulpi_phy_create(ulpi, &phy_ops);
-       if (IS_ERR(tusb->phy))
-               return PTR_ERR(tusb->phy);
-
-       tusb->ulpi = ulpi;
-
-       phy_set_drvdata(tusb->phy, tusb);
-       ulpi_set_drvdata(ulpi, tusb);
-       return 0;
-}
-
-static void tusb1210_remove(struct ulpi *ulpi)
-{
-       struct tusb1210 *tusb = ulpi_get_drvdata(ulpi);
-
-       ulpi_phy_destroy(ulpi, tusb->phy);
-}
-
-#define TI_VENDOR_ID 0x0451
-
-static const struct ulpi_device_id tusb1210_ulpi_id[] = {
-       { TI_VENDOR_ID, 0x1507, },
-       { },
-};
-MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id);
-
-static struct ulpi_driver tusb1210_driver = {
-       .id_table = tusb1210_ulpi_id,
-       .probe = tusb1210_probe,
-       .remove = tusb1210_remove,
-       .driver = {
-               .name = "tusb1210",
-               .owner = THIS_MODULE,
-       },
-};
-
-module_ulpi_driver(tusb1210_driver);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("TUSB1210 ULPI PHY driver");
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
deleted file mode 100644 (file)
index 2990b39..0000000
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller
- *
- * Copyright (C) 2004-2007 Texas Instruments
- * Copyright (C) 2008 Nokia Corporation
- * Contact: Felipe Balbi <felipe.balbi@nokia.com>
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Current status:
- *     - HS USB ULPI mode works.
- *     - 3-pin mode support may be added in future.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/usb/otg.h>
-#include <linux/phy/phy.h>
-#include <linux/pm_runtime.h>
-#include <linux/usb/musb.h>
-#include <linux/usb/ulpi.h>
-#include <linux/i2c/twl.h>
-#include <linux/regulator/consumer.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-/* Register defines */
-
-#define MCPC_CTRL                      0x30
-#define MCPC_CTRL_RTSOL                        (1 << 7)
-#define MCPC_CTRL_EXTSWR               (1 << 6)
-#define MCPC_CTRL_EXTSWC               (1 << 5)
-#define MCPC_CTRL_VOICESW              (1 << 4)
-#define MCPC_CTRL_OUT64K               (1 << 3)
-#define MCPC_CTRL_RTSCTSSW             (1 << 2)
-#define MCPC_CTRL_HS_UART              (1 << 0)
-
-#define MCPC_IO_CTRL                   0x33
-#define MCPC_IO_CTRL_MICBIASEN         (1 << 5)
-#define MCPC_IO_CTRL_CTS_NPU           (1 << 4)
-#define MCPC_IO_CTRL_RXD_PU            (1 << 3)
-#define MCPC_IO_CTRL_TXDTYP            (1 << 2)
-#define MCPC_IO_CTRL_CTSTYP            (1 << 1)
-#define MCPC_IO_CTRL_RTSTYP            (1 << 0)
-
-#define MCPC_CTRL2                     0x36
-#define MCPC_CTRL2_MCPC_CK_EN          (1 << 0)
-
-#define OTHER_FUNC_CTRL                        0x80
-#define OTHER_FUNC_CTRL_BDIS_ACON_EN   (1 << 4)
-#define OTHER_FUNC_CTRL_FIVEWIRE_MODE  (1 << 2)
-
-#define OTHER_IFC_CTRL                 0x83
-#define OTHER_IFC_CTRL_OE_INT_EN       (1 << 6)
-#define OTHER_IFC_CTRL_CEA2011_MODE    (1 << 5)
-#define OTHER_IFC_CTRL_FSLSSERIALMODE_4PIN     (1 << 4)
-#define OTHER_IFC_CTRL_HIZ_ULPI_60MHZ_OUT      (1 << 3)
-#define OTHER_IFC_CTRL_HIZ_ULPI                (1 << 2)
-#define OTHER_IFC_CTRL_ALT_INT_REROUTE (1 << 0)
-
-#define OTHER_INT_EN_RISE              0x86
-#define OTHER_INT_EN_FALL              0x89
-#define OTHER_INT_STS                  0x8C
-#define OTHER_INT_LATCH                        0x8D
-#define OTHER_INT_VB_SESS_VLD          (1 << 7)
-#define OTHER_INT_DM_HI                        (1 << 6) /* not valid for "latch" reg */
-#define OTHER_INT_DP_HI                        (1 << 5) /* not valid for "latch" reg */
-#define OTHER_INT_BDIS_ACON            (1 << 3) /* not valid for "fall" regs */
-#define OTHER_INT_MANU                 (1 << 1)
-#define OTHER_INT_ABNORMAL_STRESS      (1 << 0)
-
-#define ID_STATUS                      0x96
-#define ID_RES_FLOAT                   (1 << 4)
-#define ID_RES_440K                    (1 << 3)
-#define ID_RES_200K                    (1 << 2)
-#define ID_RES_102K                    (1 << 1)
-#define ID_RES_GND                     (1 << 0)
-
-#define POWER_CTRL                     0xAC
-#define POWER_CTRL_OTG_ENAB            (1 << 5)
-
-#define OTHER_IFC_CTRL2                        0xAF
-#define OTHER_IFC_CTRL2_ULPI_STP_LOW   (1 << 4)
-#define OTHER_IFC_CTRL2_ULPI_TXEN_POL  (1 << 3)
-#define OTHER_IFC_CTRL2_ULPI_4PIN_2430 (1 << 2)
-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_MASK    (3 << 0) /* bits 0 and 1 */
-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT1N   (0 << 0)
-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT2N   (1 << 0)
-
-#define REG_CTRL_EN                    0xB2
-#define REG_CTRL_ERROR                 0xB5
-#define ULPI_I2C_CONFLICT_INTEN                (1 << 0)
-
-#define OTHER_FUNC_CTRL2               0xB8
-#define OTHER_FUNC_CTRL2_VBAT_TIMER_EN (1 << 0)
-
-/* following registers do not have separate _clr and _set registers */
-#define VBUS_DEBOUNCE                  0xC0
-#define ID_DEBOUNCE                    0xC1
-#define VBAT_TIMER                     0xD3
-#define PHY_PWR_CTRL                   0xFD
-#define PHY_PWR_PHYPWD                 (1 << 0)
-#define PHY_CLK_CTRL                   0xFE
-#define PHY_CLK_CTRL_CLOCKGATING_EN    (1 << 2)
-#define PHY_CLK_CTRL_CLK32K_EN         (1 << 1)
-#define REQ_PHY_DPLL_CLK               (1 << 0)
-#define PHY_CLK_CTRL_STS               0xFF
-#define PHY_DPLL_CLK                   (1 << 0)
-
-/* In module TWL_MODULE_PM_MASTER */
-#define STS_HW_CONDITIONS              0x0F
-
-/* In module TWL_MODULE_PM_RECEIVER */
-#define VUSB_DEDICATED1                        0x7D
-#define VUSB_DEDICATED2                        0x7E
-#define VUSB1V5_DEV_GRP                        0x71
-#define VUSB1V5_TYPE                   0x72
-#define VUSB1V5_REMAP                  0x73
-#define VUSB1V8_DEV_GRP                        0x74
-#define VUSB1V8_TYPE                   0x75
-#define VUSB1V8_REMAP                  0x76
-#define VUSB3V1_DEV_GRP                        0x77
-#define VUSB3V1_TYPE                   0x78
-#define VUSB3V1_REMAP                  0x79
-
-/* In module TWL4030_MODULE_INTBR */
-#define PMBR1                          0x0D
-#define GPIO_USB_4PIN_ULPI_2430C       (3 << 0)
-
-/*
- * If VBUS is valid or ID is ground, then we know a
- * cable is present and we need to be runtime-enabled
- */
-static inline bool cable_present(enum musb_vbus_id_status stat)
-{
-       return stat == MUSB_VBUS_VALID ||
-               stat == MUSB_ID_GROUND;
-}
-
-struct twl4030_usb {
-       struct usb_phy          phy;
-       struct device           *dev;
-
-       /* TWL4030 internal USB regulator supplies */
-       struct regulator        *usb1v5;
-       struct regulator        *usb1v8;
-       struct regulator        *usb3v1;
-
-       /* for vbus reporting with irqs disabled */
-       struct mutex            lock;
-
-       /* pin configuration */
-       enum twl4030_usb_mode   usb_mode;
-
-       int                     irq;
-       enum musb_vbus_id_status linkstat;
-       bool                    vbus_supplied;
-       bool                    musb_mailbox_pending;
-
-       struct delayed_work     id_workaround_work;
-};
-
-/* internal define on top of container_of */
-#define phy_to_twl(x)          container_of((x), struct twl4030_usb, phy)
-
-/*-------------------------------------------------------------------------*/
-
-static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
-               u8 module, u8 data, u8 address)
-{
-       u8 check;
-
-       if ((twl_i2c_write_u8(module, data, address) >= 0) &&
-           (twl_i2c_read_u8(module, &check, address) >= 0) &&
-                                               (check == data))
-               return 0;
-       dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
-                       1, module, address, check, data);
-
-       /* Failed once: Try again */
-       if ((twl_i2c_write_u8(module, data, address) >= 0) &&
-           (twl_i2c_read_u8(module, &check, address) >= 0) &&
-                                               (check == data))
-               return 0;
-       dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
-                       2, module, address, check, data);
-
-       /* Failed again: Return error */
-       return -EBUSY;
-}
-
-#define twl4030_usb_write_verify(twl, address, data)   \
-       twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address))
-
-static inline int twl4030_usb_write(struct twl4030_usb *twl,
-               u8 address, u8 data)
-{
-       int ret = 0;
-
-       ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address);
-       if (ret < 0)
-               dev_dbg(twl->dev,
-                       "TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
-       return ret;
-}
-
-static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address)
-{
-       u8 data;
-       int ret = 0;
-
-       ret = twl_i2c_read_u8(module, &data, address);
-       if (ret >= 0)
-               ret = data;
-       else
-               dev_dbg(twl->dev,
-                       "TWL4030:readb[0x%x,0x%x] Error %d\n",
-                                       module, address, ret);
-
-       return ret;
-}
-
-static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)
-{
-       return twl4030_readb(twl, TWL_MODULE_USB, address);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline int
-twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
-{
-       return twl4030_usb_write(twl, ULPI_SET(reg), bits);
-}
-
-static inline int
-twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
-{
-       return twl4030_usb_write(twl, ULPI_CLR(reg), bits);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static bool twl4030_is_driving_vbus(struct twl4030_usb *twl)
-{
-       int ret;
-
-       ret = twl4030_usb_read(twl, PHY_CLK_CTRL_STS);
-       if (ret < 0 || !(ret & PHY_DPLL_CLK))
-               /*
-                * if clocks are off, registers are not updated,
-                * but we can assume we don't drive VBUS in this case
-                */
-               return false;
-
-       ret = twl4030_usb_read(twl, ULPI_OTG_CTRL);
-       if (ret < 0)
-               return false;
-
-       return (ret & (ULPI_OTG_DRVVBUS | ULPI_OTG_CHRGVBUS)) ? true : false;
-}
-
-static enum musb_vbus_id_status
-       twl4030_usb_linkstat(struct twl4030_usb *twl)
-{
-       int     status;
-       enum musb_vbus_id_status linkstat = MUSB_UNKNOWN;
-
-       twl->vbus_supplied = false;
-
-       /*
-        * For ID/VBUS sensing, see manual section 15.4.8 ...
-        * except when using only battery backup power, two
-        * comparators produce VBUS_PRES and ID_PRES signals,
-        * which don't match docs elsewhere.  But ... BIT(7)
-        * and BIT(2) of STS_HW_CONDITIONS, respectively, do
-        * seem to match up.  If either is true the USB_PRES
-        * signal is active, the OTG module is activated, and
-        * its interrupt may be raised (may wake the system).
-        */
-       status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS);
-       if (status < 0)
-               dev_err(twl->dev, "USB link status err %d\n", status);
-       else if (status & (BIT(7) | BIT(2))) {
-               if (status & BIT(7)) {
-                       if (twl4030_is_driving_vbus(twl))
-                               status &= ~BIT(7);
-                       else
-                               twl->vbus_supplied = true;
-               }
-
-               if (status & BIT(2))
-                       linkstat = MUSB_ID_GROUND;
-               else if (status & BIT(7))
-                       linkstat = MUSB_VBUS_VALID;
-               else
-                       linkstat = MUSB_VBUS_OFF;
-       } else {
-               if (twl->linkstat != MUSB_UNKNOWN)
-                       linkstat = MUSB_VBUS_OFF;
-       }
-
-       kobject_uevent(&twl->dev->kobj, linkstat == MUSB_VBUS_VALID
-                                       ? KOBJ_ONLINE : KOBJ_OFFLINE);
-
-       dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
-                       status, status, linkstat);
-
-       /* REVISIT this assumes host and peripheral controllers
-        * are registered, and that both are active...
-        */
-
-       return linkstat;
-}
-
-static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode)
-{
-       twl->usb_mode = mode;
-
-       switch (mode) {
-       case T2_USB_MODE_ULPI:
-               twl4030_usb_clear_bits(twl, ULPI_IFC_CTRL,
-                                       ULPI_IFC_CTRL_CARKITMODE);
-               twl4030_usb_set_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
-               twl4030_usb_clear_bits(twl, ULPI_FUNC_CTRL,
-                                       ULPI_FUNC_CTRL_XCVRSEL_MASK |
-                                       ULPI_FUNC_CTRL_OPMODE_MASK);
-               break;
-       case -1:
-               /* FIXME: power on defaults */
-               break;
-       default:
-               dev_err(twl->dev, "unsupported T2 transceiver mode %d\n",
-                               mode);
-               break;
-       }
-}
-
-static void twl4030_i2c_access(struct twl4030_usb *twl, int on)
-{
-       unsigned long timeout;
-       int val = twl4030_usb_read(twl, PHY_CLK_CTRL);
-
-       if (val >= 0) {
-               if (on) {
-                       /* enable DPLL to access PHY registers over I2C */
-                       val |= REQ_PHY_DPLL_CLK;
-                       WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
-                                               (u8)val) < 0);
-
-                       timeout = jiffies + HZ;
-                       while (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
-                                                       PHY_DPLL_CLK)
-                               && time_before(jiffies, timeout))
-                                       udelay(10);
-                       if (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
-                                                       PHY_DPLL_CLK))
-                               dev_err(twl->dev, "Timeout setting T2 HSUSB "
-                                               "PHY DPLL clock\n");
-               } else {
-                       /* let ULPI control the DPLL clock */
-                       val &= ~REQ_PHY_DPLL_CLK;
-                       WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
-                                               (u8)val) < 0);
-               }
-       }
-}
-
-static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
-{
-       u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
-
-       if (on)
-               pwr &= ~PHY_PWR_PHYPWD;
-       else
-               pwr |= PHY_PWR_PHYPWD;
-
-       WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
-}
-
-static int __maybe_unused twl4030_usb_runtime_suspend(struct device *dev)
-{
-       struct twl4030_usb *twl = dev_get_drvdata(dev);
-
-       dev_dbg(twl->dev, "%s\n", __func__);
-
-       __twl4030_phy_power(twl, 0);
-       regulator_disable(twl->usb1v5);
-       regulator_disable(twl->usb1v8);
-       regulator_disable(twl->usb3v1);
-
-       return 0;
-}
-
-static int __maybe_unused twl4030_usb_runtime_resume(struct device *dev)
-{
-       struct twl4030_usb *twl = dev_get_drvdata(dev);
-       int res;
-
-       dev_dbg(twl->dev, "%s\n", __func__);
-
-       res = regulator_enable(twl->usb3v1);
-       if (res)
-               dev_err(twl->dev, "Failed to enable usb3v1\n");
-
-       res = regulator_enable(twl->usb1v8);
-       if (res)
-               dev_err(twl->dev, "Failed to enable usb1v8\n");
-
-       /*
-        * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
-        * in twl4030) resets the VUSB_DEDICATED2 register. This reset
-        * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to
-        * SLEEP. We work around this by clearing the bit after usv3v1
-        * is re-activated. This ensures that VUSB3V1 is really active.
-        */
-       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
-
-       res = regulator_enable(twl->usb1v5);
-       if (res)
-               dev_err(twl->dev, "Failed to enable usb1v5\n");
-
-       __twl4030_phy_power(twl, 1);
-       twl4030_usb_write(twl, PHY_CLK_CTRL,
-                         twl4030_usb_read(twl, PHY_CLK_CTRL) |
-                         (PHY_CLK_CTRL_CLOCKGATING_EN |
-                          PHY_CLK_CTRL_CLK32K_EN));
-
-       twl4030_i2c_access(twl, 1);
-       twl4030_usb_set_mode(twl, twl->usb_mode);
-       if (twl->usb_mode == T2_USB_MODE_ULPI)
-               twl4030_i2c_access(twl, 0);
-       /*
-        * According to the TPS65950 TRM, there has to be at least 50ms
-        * delay between setting POWER_CTRL_OTG_ENAB and enabling charging
-        * so wait here so that a fully enabled phy can be expected after
-        * resume
-        */
-       msleep(50);
-       return 0;
-}
-
-static int twl4030_phy_power_off(struct phy *phy)
-{
-       struct twl4030_usb *twl = phy_get_drvdata(phy);
-
-       dev_dbg(twl->dev, "%s\n", __func__);
-
-       return 0;
-}
-
-static int twl4030_phy_power_on(struct phy *phy)
-{
-       struct twl4030_usb *twl = phy_get_drvdata(phy);
-
-       dev_dbg(twl->dev, "%s\n", __func__);
-       pm_runtime_get_sync(twl->dev);
-       schedule_delayed_work(&twl->id_workaround_work, HZ);
-       pm_runtime_mark_last_busy(twl->dev);
-       pm_runtime_put_autosuspend(twl->dev);
-
-       return 0;
-}
-
-static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
-{
-       /* Enable writing to power configuration registers */
-       twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
-                        TWL4030_PM_MASTER_PROTECT_KEY);
-
-       twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
-                        TWL4030_PM_MASTER_PROTECT_KEY);
-
-       /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/
-       /*twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
-
-       /* input to VUSB3V1 LDO is from VBAT, not VBUS */
-       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
-
-       /* Initialize 3.1V regulator */
-       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
-
-       twl->usb3v1 = devm_regulator_get(twl->dev, "usb3v1");
-       if (IS_ERR(twl->usb3v1))
-               return -ENODEV;
-
-       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
-
-       /* Initialize 1.5V regulator */
-       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
-
-       twl->usb1v5 = devm_regulator_get(twl->dev, "usb1v5");
-       if (IS_ERR(twl->usb1v5))
-               return -ENODEV;
-
-       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
-
-       /* Initialize 1.8V regulator */
-       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
-
-       twl->usb1v8 = devm_regulator_get(twl->dev, "usb1v8");
-       if (IS_ERR(twl->usb1v8))
-               return -ENODEV;
-
-       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
-
-       /* disable access to power configuration registers */
-       twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
-                        TWL4030_PM_MASTER_PROTECT_KEY);
-
-       return 0;
-}
-
-static ssize_t twl4030_usb_vbus_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct twl4030_usb *twl = dev_get_drvdata(dev);
-       int ret = -EINVAL;
-
-       mutex_lock(&twl->lock);
-       ret = sprintf(buf, "%s\n",
-                       twl->vbus_supplied ? "on" : "off");
-       mutex_unlock(&twl->lock);
-
-       return ret;
-}
-static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
-
-static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
-{
-       struct twl4030_usb *twl = _twl;
-       enum musb_vbus_id_status status;
-       bool status_changed = false;
-       int err;
-
-       status = twl4030_usb_linkstat(twl);
-
-       mutex_lock(&twl->lock);
-       if (status >= 0 && status != twl->linkstat) {
-               status_changed =
-                       cable_present(twl->linkstat) !=
-                       cable_present(status);
-               twl->linkstat = status;
-       }
-       mutex_unlock(&twl->lock);
-
-       if (status_changed) {
-               /* FIXME add a set_power() method so that B-devices can
-                * configure the charger appropriately.  It's not always
-                * correct to consume VBUS power, and how much current to
-                * consume is a function of the USB configuration chosen
-                * by the host.
-                *
-                * REVISIT usb_gadget_vbus_connect(...) as needed, ditto
-                * its disconnect() sibling, when changing to/from the
-                * USB_LINK_VBUS state.  musb_hdrc won't care until it
-                * starts to handle softconnect right.
-                */
-               if (cable_present(status)) {
-                       pm_runtime_get_sync(twl->dev);
-               } else {
-                       pm_runtime_mark_last_busy(twl->dev);
-                       pm_runtime_put_autosuspend(twl->dev);
-               }
-               twl->musb_mailbox_pending = true;
-       }
-       if (twl->musb_mailbox_pending) {
-               err = musb_mailbox(status);
-               if (!err)
-                       twl->musb_mailbox_pending = false;
-       }
-
-       /* don't schedule during sleep - irq works right then */
-       if (status == MUSB_ID_GROUND && pm_runtime_active(twl->dev)) {
-               cancel_delayed_work(&twl->id_workaround_work);
-               schedule_delayed_work(&twl->id_workaround_work, HZ);
-       }
-
-       if (irq)
-               sysfs_notify(&twl->dev->kobj, NULL, "vbus");
-
-       return IRQ_HANDLED;
-}
-
-static void twl4030_id_workaround_work(struct work_struct *work)
-{
-       struct twl4030_usb *twl = container_of(work, struct twl4030_usb,
-               id_workaround_work.work);
-
-       twl4030_usb_irq(0, twl);
-}
-
-static int twl4030_phy_init(struct phy *phy)
-{
-       struct twl4030_usb *twl = phy_get_drvdata(phy);
-
-       pm_runtime_get_sync(twl->dev);
-       twl->linkstat = MUSB_UNKNOWN;
-       schedule_delayed_work(&twl->id_workaround_work, HZ);
-       pm_runtime_mark_last_busy(twl->dev);
-       pm_runtime_put_autosuspend(twl->dev);
-
-       return 0;
-}
-
-static int twl4030_set_peripheral(struct usb_otg *otg,
-                                       struct usb_gadget *gadget)
-{
-       if (!otg)
-               return -ENODEV;
-
-       otg->gadget = gadget;
-       if (!gadget)
-               otg->state = OTG_STATE_UNDEFINED;
-
-       return 0;
-}
-
-static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-       if (!otg)
-               return -ENODEV;
-
-       otg->host = host;
-       if (!host)
-               otg->state = OTG_STATE_UNDEFINED;
-
-       return 0;
-}
-
-static const struct phy_ops ops = {
-       .init           = twl4030_phy_init,
-       .power_on       = twl4030_phy_power_on,
-       .power_off      = twl4030_phy_power_off,
-       .owner          = THIS_MODULE,
-};
-
-static const struct dev_pm_ops twl4030_usb_pm_ops = {
-       SET_RUNTIME_PM_OPS(twl4030_usb_runtime_suspend,
-                          twl4030_usb_runtime_resume, NULL)
-};
-
-static int twl4030_usb_probe(struct platform_device *pdev)
-{
-       struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev);
-       struct twl4030_usb      *twl;
-       struct phy              *phy;
-       int                     status, err;
-       struct usb_otg          *otg;
-       struct device_node      *np = pdev->dev.of_node;
-       struct phy_provider     *phy_provider;
-
-       twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
-       if (!twl)
-               return -ENOMEM;
-
-       if (np)
-               of_property_read_u32(np, "usb_mode",
-                               (enum twl4030_usb_mode *)&twl->usb_mode);
-       else if (pdata) {
-               twl->usb_mode = pdata->usb_mode;
-       } else {
-               dev_err(&pdev->dev, "twl4030 initialized without pdata\n");
-               return -EINVAL;
-       }
-
-       otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
-       if (!otg)
-               return -ENOMEM;
-
-       twl->dev                = &pdev->dev;
-       twl->irq                = platform_get_irq(pdev, 0);
-       twl->vbus_supplied      = false;
-       twl->linkstat           = MUSB_UNKNOWN;
-       twl->musb_mailbox_pending = false;
-
-       twl->phy.dev            = twl->dev;
-       twl->phy.label          = "twl4030";
-       twl->phy.otg            = otg;
-       twl->phy.type           = USB_PHY_TYPE_USB2;
-
-       otg->usb_phy            = &twl->phy;
-       otg->set_host           = twl4030_set_host;
-       otg->set_peripheral     = twl4030_set_peripheral;
-
-       phy = devm_phy_create(twl->dev, NULL, &ops);
-       if (IS_ERR(phy)) {
-               dev_dbg(&pdev->dev, "Failed to create PHY\n");
-               return PTR_ERR(phy);
-       }
-
-       phy_set_drvdata(phy, twl);
-
-       phy_provider = devm_of_phy_provider_register(twl->dev,
-               of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
-       /* init mutex for workqueue */
-       mutex_init(&twl->lock);
-
-       INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work);
-
-       err = twl4030_usb_ldo_init(twl);
-       if (err) {
-               dev_err(&pdev->dev, "ldo init failed\n");
-               return err;
-       }
-       usb_add_phy_dev(&twl->phy);
-
-       platform_set_drvdata(pdev, twl);
-       if (device_create_file(&pdev->dev, &dev_attr_vbus))
-               dev_warn(&pdev->dev, "could not create sysfs file\n");
-
-       ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
-
-       pm_runtime_use_autosuspend(&pdev->dev);
-       pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
-       pm_runtime_enable(&pdev->dev);
-       pm_runtime_get_sync(&pdev->dev);
-
-       /* Our job is to use irqs and status from the power module
-        * to keep the transceiver disabled when nothing's connected.
-        *
-        * FIXME we actually shouldn't start enabling it until the
-        * USB controller drivers have said they're ready, by calling
-        * set_host() and/or set_peripheral() ... OTG_capable boards
-        * need both handles, otherwise just one suffices.
-        */
-       status = devm_request_threaded_irq(twl->dev, twl->irq, NULL,
-                       twl4030_usb_irq, IRQF_TRIGGER_FALLING |
-                       IRQF_TRIGGER_RISING | IRQF_ONESHOT, "twl4030_usb", twl);
-       if (status < 0) {
-               dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
-                       twl->irq, status);
-               return status;
-       }
-
-       if (pdata)
-               err = phy_create_lookup(phy, "usb", "musb-hdrc.0");
-       if (err)
-               return err;
-
-       pm_runtime_mark_last_busy(&pdev->dev);
-       pm_runtime_put_autosuspend(twl->dev);
-
-       dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
-       return 0;
-}
-
-static int twl4030_usb_remove(struct platform_device *pdev)
-{
-       struct twl4030_usb *twl = platform_get_drvdata(pdev);
-       int val;
-
-       usb_remove_phy(&twl->phy);
-       pm_runtime_get_sync(twl->dev);
-       cancel_delayed_work(&twl->id_workaround_work);
-       device_remove_file(twl->dev, &dev_attr_vbus);
-
-       /* set transceiver mode to power on defaults */
-       twl4030_usb_set_mode(twl, -1);
-
-       /* idle ulpi before powering off */
-       if (cable_present(twl->linkstat))
-               pm_runtime_put_noidle(twl->dev);
-       pm_runtime_mark_last_busy(twl->dev);
-       pm_runtime_dont_use_autosuspend(&pdev->dev);
-       pm_runtime_put_sync(twl->dev);
-       pm_runtime_disable(twl->dev);
-
-       /* autogate 60MHz ULPI clock,
-        * clear dpll clock request for i2c access,
-        * disable 32KHz
-        */
-       val = twl4030_usb_read(twl, PHY_CLK_CTRL);
-       if (val >= 0) {
-               val |= PHY_CLK_CTRL_CLOCKGATING_EN;
-               val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK);
-               twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val);
-       }
-
-       /* disable complete OTG block */
-       twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
-
-       return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id twl4030_usb_id_table[] = {
-       { .compatible = "ti,twl4030-usb" },
-       {}
-};
-MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);
-#endif
-
-static struct platform_driver twl4030_usb_driver = {
-       .probe          = twl4030_usb_probe,
-       .remove         = twl4030_usb_remove,
-       .driver         = {
-               .name   = "twl4030_usb",
-               .pm     = &twl4030_usb_pm_ops,
-               .of_match_table = of_match_ptr(twl4030_usb_id_table),
-       },
-};
-
-static int __init twl4030_usb_init(void)
-{
-       return platform_driver_register(&twl4030_usb_driver);
-}
-subsys_initcall(twl4030_usb_init);
-
-static void __exit twl4030_usb_exit(void)
-{
-       platform_driver_unregister(&twl4030_usb_driver);
-}
-module_exit(twl4030_usb_exit);
-
-MODULE_ALIAS("platform:twl4030_usb");
-MODULE_AUTHOR("Texas Instruments, Inc, Nokia Corporation");
-MODULE_DESCRIPTION("TWL4030 USB transceiver driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
new file mode 100644 (file)
index 0000000..7bfa64b
--- /dev/null
@@ -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.
diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
new file mode 100644 (file)
index 0000000..2e183d7
--- /dev/null
@@ -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
diff --git a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
new file mode 100644 (file)
index 0000000..69ce2af
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+/* PHY registers */
+#define UNIPHY_PLL_REFCLK_CFG          0x000
+#define UNIPHY_PLL_PWRGEN_CFG          0x014
+#define UNIPHY_PLL_GLB_CFG             0x020
+#define UNIPHY_PLL_SDM_CFG0            0x038
+#define UNIPHY_PLL_SDM_CFG1            0x03C
+#define UNIPHY_PLL_SDM_CFG2            0x040
+#define UNIPHY_PLL_SDM_CFG3            0x044
+#define UNIPHY_PLL_SDM_CFG4            0x048
+#define UNIPHY_PLL_SSC_CFG0            0x04C
+#define UNIPHY_PLL_SSC_CFG1            0x050
+#define UNIPHY_PLL_SSC_CFG2            0x054
+#define UNIPHY_PLL_SSC_CFG3            0x058
+#define UNIPHY_PLL_LKDET_CFG0          0x05C
+#define UNIPHY_PLL_LKDET_CFG1          0x060
+#define UNIPHY_PLL_LKDET_CFG2          0x064
+#define UNIPHY_PLL_CAL_CFG0            0x06C
+#define UNIPHY_PLL_CAL_CFG8            0x08C
+#define UNIPHY_PLL_CAL_CFG9            0x090
+#define UNIPHY_PLL_CAL_CFG10           0x094
+#define UNIPHY_PLL_CAL_CFG11           0x098
+#define UNIPHY_PLL_STATUS              0x0C0
+
+#define SATA_PHY_SER_CTRL              0x100
+#define SATA_PHY_TX_DRIV_CTRL0         0x104
+#define SATA_PHY_TX_DRIV_CTRL1         0x108
+#define SATA_PHY_TX_IMCAL0             0x11C
+#define SATA_PHY_TX_IMCAL2             0x124
+#define SATA_PHY_RX_IMCAL0             0x128
+#define SATA_PHY_EQUAL                 0x13C
+#define SATA_PHY_OOB_TERM              0x144
+#define SATA_PHY_CDR_CTRL0             0x148
+#define SATA_PHY_CDR_CTRL1             0x14C
+#define SATA_PHY_CDR_CTRL2             0x150
+#define SATA_PHY_CDR_CTRL3             0x154
+#define SATA_PHY_PI_CTRL0              0x168
+#define SATA_PHY_POW_DWN_CTRL0         0x180
+#define SATA_PHY_POW_DWN_CTRL1         0x184
+#define SATA_PHY_TX_DATA_CTRL          0x188
+#define SATA_PHY_ALIGNP                        0x1A4
+#define SATA_PHY_TX_IMCAL_STAT         0x1E4
+#define SATA_PHY_RX_IMCAL_STAT         0x1E8
+
+#define UNIPHY_PLL_LOCK                BIT(0)
+#define SATA_PHY_TX_CAL                BIT(0)
+#define SATA_PHY_RX_CAL                BIT(0)
+
+/* default timeout set to 1 sec */
+#define TIMEOUT_MS             10000
+#define DELAY_INTERVAL_US      100
+
+struct qcom_apq8064_sata_phy {
+       void __iomem *mmio;
+       struct clk *cfg_clk;
+       struct device *dev;
+};
+
+/* Helper function to do poll and timeout */
+static int read_poll_timeout(void __iomem *addr, u32 mask)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS);
+
+       do {
+               if (readl_relaxed(addr) & mask)
+                       return 0;
+
+                usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
+       } while (!time_after(jiffies, timeout));
+
+       return (readl_relaxed(addr) & mask) ? 0 : -ETIMEDOUT;
+}
+
+static int qcom_apq8064_sata_phy_init(struct phy *generic_phy)
+{
+       struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
+       void __iomem *base = phy->mmio;
+       int ret = 0;
+
+       /* SATA phy initialization */
+       writel_relaxed(0x01, base + SATA_PHY_SER_CTRL);
+       writel_relaxed(0xB1, base + SATA_PHY_POW_DWN_CTRL0);
+       /* Make sure the power down happens before power up */
+       mb();
+       usleep_range(10, 60);
+
+       writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
+       writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
+       writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
+       writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
+       writel_relaxed(0x02, base + SATA_PHY_TX_IMCAL2);
+
+       /* Write UNIPHYPLL registers to configure PLL */
+       writel_relaxed(0x04, base + UNIPHY_PLL_REFCLK_CFG);
+       writel_relaxed(0x00, base + UNIPHY_PLL_PWRGEN_CFG);
+
+       writel_relaxed(0x0A, base + UNIPHY_PLL_CAL_CFG0);
+       writel_relaxed(0xF3, base + UNIPHY_PLL_CAL_CFG8);
+       writel_relaxed(0x01, base + UNIPHY_PLL_CAL_CFG9);
+       writel_relaxed(0xED, base + UNIPHY_PLL_CAL_CFG10);
+       writel_relaxed(0x02, base + UNIPHY_PLL_CAL_CFG11);
+
+       writel_relaxed(0x36, base + UNIPHY_PLL_SDM_CFG0);
+       writel_relaxed(0x0D, base + UNIPHY_PLL_SDM_CFG1);
+       writel_relaxed(0xA3, base + UNIPHY_PLL_SDM_CFG2);
+       writel_relaxed(0xF0, base + UNIPHY_PLL_SDM_CFG3);
+       writel_relaxed(0x00, base + UNIPHY_PLL_SDM_CFG4);
+
+       writel_relaxed(0x19, base + UNIPHY_PLL_SSC_CFG0);
+       writel_relaxed(0xE1, base + UNIPHY_PLL_SSC_CFG1);
+       writel_relaxed(0x00, base + UNIPHY_PLL_SSC_CFG2);
+       writel_relaxed(0x11, base + UNIPHY_PLL_SSC_CFG3);
+
+       writel_relaxed(0x04, base + UNIPHY_PLL_LKDET_CFG0);
+       writel_relaxed(0xFF, base + UNIPHY_PLL_LKDET_CFG1);
+
+       writel_relaxed(0x02, base + UNIPHY_PLL_GLB_CFG);
+       /* make sure global config LDO power down happens before power up */
+       mb();
+
+       writel_relaxed(0x03, base + UNIPHY_PLL_GLB_CFG);
+       writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2);
+
+       /* PLL Lock wait */
+       ret = read_poll_timeout(base + UNIPHY_PLL_STATUS, UNIPHY_PLL_LOCK);
+       if (ret) {
+               dev_err(phy->dev, "poll timeout UNIPHY_PLL_STATUS\n");
+               return ret;
+       }
+
+       /* TX Calibration */
+       ret = read_poll_timeout(base + SATA_PHY_TX_IMCAL_STAT, SATA_PHY_TX_CAL);
+       if (ret) {
+               dev_err(phy->dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n");
+               return ret;
+       }
+
+       /* RX Calibration */
+       ret = read_poll_timeout(base + SATA_PHY_RX_IMCAL_STAT, SATA_PHY_RX_CAL);
+       if (ret) {
+               dev_err(phy->dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n");
+               return ret;
+       }
+
+       /* SATA phy calibrated succesfully, power up to functional mode */
+       writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
+       writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
+       writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
+
+       writel_relaxed(0x00, base + SATA_PHY_POW_DWN_CTRL1);
+       writel_relaxed(0x59, base + SATA_PHY_CDR_CTRL0);
+       writel_relaxed(0x04, base + SATA_PHY_CDR_CTRL1);
+       writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL2);
+       writel_relaxed(0x00, base + SATA_PHY_PI_CTRL0);
+       writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL3);
+       writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
+
+       writel_relaxed(0x11, base + SATA_PHY_TX_DATA_CTRL);
+       writel_relaxed(0x43, base + SATA_PHY_ALIGNP);
+       writel_relaxed(0x04, base + SATA_PHY_OOB_TERM);
+
+       writel_relaxed(0x01, base + SATA_PHY_EQUAL);
+       writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL0);
+       writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL1);
+
+       return 0;
+}
+
+static int qcom_apq8064_sata_phy_exit(struct phy *generic_phy)
+{
+       struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
+       void __iomem *base = phy->mmio;
+
+       /* Power down PHY */
+       writel_relaxed(0xF8, base + SATA_PHY_POW_DWN_CTRL0);
+       writel_relaxed(0xFE, base + SATA_PHY_POW_DWN_CTRL1);
+
+       /* Power down PLL block */
+       writel_relaxed(0x00, base + UNIPHY_PLL_GLB_CFG);
+
+       return 0;
+}
+
+static const struct phy_ops qcom_apq8064_sata_phy_ops = {
+       .init           = qcom_apq8064_sata_phy_init,
+       .exit           = qcom_apq8064_sata_phy_exit,
+       .owner          = THIS_MODULE,
+};
+
+static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev)
+{
+       struct qcom_apq8064_sata_phy *phy;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       struct phy_provider *phy_provider;
+       struct phy *generic_phy;
+       int ret;
+
+       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       phy->mmio = devm_ioremap_resource(dev, res);
+       if (IS_ERR(phy->mmio))
+               return PTR_ERR(phy->mmio);
+
+       generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops);
+       if (IS_ERR(generic_phy)) {
+               dev_err(dev, "%s: failed to create phy\n", __func__);
+               return PTR_ERR(generic_phy);
+       }
+
+       phy->dev = dev;
+       phy_set_drvdata(generic_phy, phy);
+       platform_set_drvdata(pdev, phy);
+
+       phy->cfg_clk = devm_clk_get(dev, "cfg");
+       if (IS_ERR(phy->cfg_clk)) {
+               dev_err(dev, "Failed to get sata cfg clock\n");
+               return PTR_ERR(phy->cfg_clk);
+       }
+
+       ret = clk_prepare_enable(phy->cfg_clk);
+       if (ret)
+               return ret;
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(phy_provider)) {
+               clk_disable_unprepare(phy->cfg_clk);
+               dev_err(dev, "%s: failed to register phy\n", __func__);
+               return PTR_ERR(phy_provider);
+       }
+
+       return 0;
+}
+
+static int qcom_apq8064_sata_phy_remove(struct platform_device *pdev)
+{
+       struct qcom_apq8064_sata_phy *phy = platform_get_drvdata(pdev);
+
+       clk_disable_unprepare(phy->cfg_clk);
+
+       return 0;
+}
+
+static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = {
+       { .compatible = "qcom,apq8064-sata-phy" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match);
+
+static struct platform_driver qcom_apq8064_sata_phy_driver = {
+       .probe  = qcom_apq8064_sata_phy_probe,
+       .remove = qcom_apq8064_sata_phy_remove,
+       .driver = {
+               .name   = "qcom-apq8064-sata-phy",
+               .of_match_table = qcom_apq8064_sata_phy_of_match,
+       }
+};
+module_platform_driver(qcom_apq8064_sata_phy_driver);
+
+MODULE_DESCRIPTION("QCOM apq8064 SATA PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
new file mode 100644 (file)
index 0000000..0ad127c
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+struct qcom_ipq806x_sata_phy {
+       void __iomem *mmio;
+       struct clk *cfg_clk;
+       struct device *dev;
+};
+
+#define __set(v, a, b) (((v) << (b)) & GENMASK(a, b))
+
+#define SATA_PHY_P0_PARAM0             0x200
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(x)       __set(x, 17, 12)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK     GENMASK(17, 12)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2(x)       __set(x, 11, 6)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK     GENMASK(11, 6)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1(x)       __set(x, 5, 0)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK     GENMASK(5, 0)
+
+#define SATA_PHY_P0_PARAM1             0x204
+#define SATA_PHY_P0_PARAM1_RESERVED_BITS31_21(x)       __set(x, 31, 21)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(x)     __set(x, 20, 14)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK   GENMASK(20, 14)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(x)     __set(x, 13, 7)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK   GENMASK(13, 7)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(x)     __set(x, 6, 0)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK   GENMASK(6, 0)
+
+#define SATA_PHY_P0_PARAM2             0x208
+#define SATA_PHY_P0_PARAM2_RX_EQ(x)    __set(x, 20, 18)
+#define SATA_PHY_P0_PARAM2_RX_EQ_MASK  GENMASK(20, 18)
+
+#define SATA_PHY_P0_PARAM3             0x20C
+#define SATA_PHY_SSC_EN                        0x8
+#define SATA_PHY_P0_PARAM4             0x210
+#define SATA_PHY_REF_SSP_EN            0x2
+#define SATA_PHY_RESET                 0x1
+
+static int qcom_ipq806x_sata_phy_init(struct phy *generic_phy)
+{
+       struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
+       u32 reg;
+
+       /* Setting SSC_EN to 1 */
+       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM3);
+       reg = reg | SATA_PHY_SSC_EN;
+       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM3);
+
+       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM0) &
+                       ~(SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK |
+                         SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK |
+                         SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK);
+       reg |= SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(0xf);
+       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM0);
+
+       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM1) &
+                       ~(SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK |
+                         SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK |
+                         SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK);
+       reg |= SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(0x55) |
+               SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(0x55) |
+               SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(0x55);
+       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM1);
+
+       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM2) &
+               ~SATA_PHY_P0_PARAM2_RX_EQ_MASK;
+       reg |= SATA_PHY_P0_PARAM2_RX_EQ(0x3);
+       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM2);
+
+       /* Setting PHY_RESET to 1 */
+       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+       reg = reg | SATA_PHY_RESET;
+       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+       /* Setting REF_SSP_EN to 1 */
+       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+       reg = reg | SATA_PHY_REF_SSP_EN | SATA_PHY_RESET;
+       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+       /* make sure all changes complete before we let the PHY out of reset */
+       mb();
+
+       /* sleep for max. 50us more to combine processor wakeups */
+       usleep_range(20, 20 + 50);
+
+       /* Clearing PHY_RESET to 0 */
+       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+       reg = reg & ~SATA_PHY_RESET;
+       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+       return 0;
+}
+
+static int qcom_ipq806x_sata_phy_exit(struct phy *generic_phy)
+{
+       struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
+       u32 reg;
+
+       /* Setting PHY_RESET to 1 */
+       reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+       reg = reg | SATA_PHY_RESET;
+       writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+       return 0;
+}
+
+static const struct phy_ops qcom_ipq806x_sata_phy_ops = {
+       .init           = qcom_ipq806x_sata_phy_init,
+       .exit           = qcom_ipq806x_sata_phy_exit,
+       .owner          = THIS_MODULE,
+};
+
+static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev)
+{
+       struct qcom_ipq806x_sata_phy *phy;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       struct phy_provider *phy_provider;
+       struct phy *generic_phy;
+       int ret;
+
+       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       phy->mmio = devm_ioremap_resource(dev, res);
+       if (IS_ERR(phy->mmio))
+               return PTR_ERR(phy->mmio);
+
+       generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops);
+       if (IS_ERR(generic_phy)) {
+               dev_err(dev, "%s: failed to create phy\n", __func__);
+               return PTR_ERR(generic_phy);
+       }
+
+       phy->dev = dev;
+       phy_set_drvdata(generic_phy, phy);
+       platform_set_drvdata(pdev, phy);
+
+       phy->cfg_clk = devm_clk_get(dev, "cfg");
+       if (IS_ERR(phy->cfg_clk)) {
+               dev_err(dev, "Failed to get sata cfg clock\n");
+               return PTR_ERR(phy->cfg_clk);
+       }
+
+       ret = clk_prepare_enable(phy->cfg_clk);
+       if (ret)
+               return ret;
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(phy_provider)) {
+               clk_disable_unprepare(phy->cfg_clk);
+               dev_err(dev, "%s: failed to register phy\n", __func__);
+               return PTR_ERR(phy_provider);
+       }
+
+       return 0;
+}
+
+static int qcom_ipq806x_sata_phy_remove(struct platform_device *pdev)
+{
+       struct qcom_ipq806x_sata_phy *phy = platform_get_drvdata(pdev);
+
+       clk_disable_unprepare(phy->cfg_clk);
+
+       return 0;
+}
+
+static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = {
+       { .compatible = "qcom,ipq806x-sata-phy" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match);
+
+static struct platform_driver qcom_ipq806x_sata_phy_driver = {
+       .probe  = qcom_ipq806x_sata_phy_probe,
+       .remove = qcom_ipq806x_sata_phy_remove,
+       .driver = {
+               .name   = "qcom-ipq806x-sata-phy",
+               .of_match_table = qcom_ipq806x_sata_phy_of_match,
+       }
+};
+module_platform_driver(qcom_ipq806x_sata_phy_driver);
+
+MODULE_DESCRIPTION("QCOM IPQ806x SATA PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
new file mode 100644 (file)
index 0000000..78ca628
--- /dev/null
@@ -0,0 +1,1153 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/phy/phy.h>
+
+/* QMP PHY QSERDES COM registers */
+#define QSERDES_COM_BG_TIMER                           0x00c
+#define QSERDES_COM_SSC_EN_CENTER                      0x010
+#define QSERDES_COM_SSC_ADJ_PER1                       0x014
+#define QSERDES_COM_SSC_ADJ_PER2                       0x018
+#define QSERDES_COM_SSC_PER1                           0x01c
+#define QSERDES_COM_SSC_PER2                           0x020
+#define QSERDES_COM_SSC_STEP_SIZE1                     0x024
+#define QSERDES_COM_SSC_STEP_SIZE2                     0x028
+#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN                        0x034
+#define QSERDES_COM_CLK_ENABLE1                                0x038
+#define QSERDES_COM_SYS_CLK_CTRL                       0x03c
+#define QSERDES_COM_SYSCLK_BUF_ENABLE                  0x040
+#define QSERDES_COM_PLL_IVCO                           0x048
+#define QSERDES_COM_LOCK_CMP1_MODE0                    0x04c
+#define QSERDES_COM_LOCK_CMP2_MODE0                    0x050
+#define QSERDES_COM_LOCK_CMP3_MODE0                    0x054
+#define QSERDES_COM_LOCK_CMP1_MODE1                    0x058
+#define QSERDES_COM_LOCK_CMP2_MODE1                    0x05c
+#define QSERDES_COM_LOCK_CMP3_MODE1                    0x060
+#define QSERDES_COM_BG_TRIM                            0x070
+#define QSERDES_COM_CLK_EP_DIV                         0x074
+#define QSERDES_COM_CP_CTRL_MODE0                      0x078
+#define QSERDES_COM_CP_CTRL_MODE1                      0x07c
+#define QSERDES_COM_PLL_RCTRL_MODE0                    0x084
+#define QSERDES_COM_PLL_RCTRL_MODE1                    0x088
+#define QSERDES_COM_PLL_CCTRL_MODE0                    0x090
+#define QSERDES_COM_PLL_CCTRL_MODE1                    0x094
+#define QSERDES_COM_SYSCLK_EN_SEL                      0x0ac
+#define QSERDES_COM_RESETSM_CNTRL                      0x0b4
+#define QSERDES_COM_RESTRIM_CTRL                       0x0bc
+#define QSERDES_COM_RESCODE_DIV_NUM                    0x0c4
+#define QSERDES_COM_LOCK_CMP_EN                                0x0c8
+#define QSERDES_COM_LOCK_CMP_CFG                       0x0cc
+#define QSERDES_COM_DEC_START_MODE0                    0x0d0
+#define QSERDES_COM_DEC_START_MODE1                    0x0d4
+#define QSERDES_COM_DIV_FRAC_START1_MODE0              0x0dc
+#define QSERDES_COM_DIV_FRAC_START2_MODE0              0x0e0
+#define QSERDES_COM_DIV_FRAC_START3_MODE0              0x0e4
+#define QSERDES_COM_DIV_FRAC_START1_MODE1              0x0e8
+#define QSERDES_COM_DIV_FRAC_START2_MODE1              0x0ec
+#define QSERDES_COM_DIV_FRAC_START3_MODE1              0x0f0
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0              0x108
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0              0x10c
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1              0x110
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1              0x114
+#define QSERDES_COM_VCO_TUNE_CTRL                      0x124
+#define QSERDES_COM_VCO_TUNE_MAP                       0x128
+#define QSERDES_COM_VCO_TUNE1_MODE0                    0x12c
+#define QSERDES_COM_VCO_TUNE2_MODE0                    0x130
+#define QSERDES_COM_VCO_TUNE1_MODE1                    0x134
+#define QSERDES_COM_VCO_TUNE2_MODE1                    0x138
+#define QSERDES_COM_VCO_TUNE_TIMER1                    0x144
+#define QSERDES_COM_VCO_TUNE_TIMER2                    0x148
+#define QSERDES_COM_BG_CTRL                            0x170
+#define QSERDES_COM_CLK_SELECT                         0x174
+#define QSERDES_COM_HSCLK_SEL                          0x178
+#define QSERDES_COM_CORECLK_DIV                                0x184
+#define QSERDES_COM_CORE_CLK_EN                                0x18c
+#define QSERDES_COM_C_READY_STATUS                     0x190
+#define QSERDES_COM_CMN_CONFIG                         0x194
+#define QSERDES_COM_SVS_MODE_CLK_SEL                   0x19c
+#define QSERDES_COM_DEBUG_BUS0                         0x1a0
+#define QSERDES_COM_DEBUG_BUS1                         0x1a4
+#define QSERDES_COM_DEBUG_BUS2                         0x1a8
+#define QSERDES_COM_DEBUG_BUS3                         0x1ac
+#define QSERDES_COM_DEBUG_BUS_SEL                      0x1b0
+#define QSERDES_COM_CORECLK_DIV_MODE1                  0x1bc
+
+/* QMP PHY TX registers */
+#define QSERDES_TX_RES_CODE_LANE_OFFSET                        0x054
+#define QSERDES_TX_DEBUG_BUS_SEL                       0x064
+#define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN    0x068
+#define QSERDES_TX_LANE_MODE                           0x094
+#define QSERDES_TX_RCV_DETECT_LVL_2                    0x0ac
+
+/* QMP PHY RX registers */
+#define QSERDES_RX_UCDR_SO_GAIN_HALF                   0x010
+#define QSERDES_RX_UCDR_SO_GAIN                                0x01c
+#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN               0x040
+#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE       0x048
+#define QSERDES_RX_RX_TERM_BW                          0x090
+#define QSERDES_RX_RX_EQ_GAIN1_LSB                     0x0c4
+#define QSERDES_RX_RX_EQ_GAIN1_MSB                     0x0c8
+#define QSERDES_RX_RX_EQ_GAIN2_LSB                     0x0cc
+#define QSERDES_RX_RX_EQ_GAIN2_MSB                     0x0d0
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2               0x0d8
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3               0x0dc
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4               0x0e0
+#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1         0x108
+#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2            0x10c
+#define QSERDES_RX_SIGDET_ENABLES                      0x110
+#define QSERDES_RX_SIGDET_CNTRL                                0x114
+#define QSERDES_RX_SIGDET_LVL                          0x118
+#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL               0x11c
+#define QSERDES_RX_RX_BAND                             0x120
+#define QSERDES_RX_RX_INTERFACE_MODE                   0x12c
+
+/* QMP PHY PCS registers */
+#define QPHY_POWER_DOWN_CONTROL                                0x04
+#define QPHY_TXDEEMPH_M6DB_V0                          0x24
+#define QPHY_TXDEEMPH_M3P5DB_V0                                0x28
+#define QPHY_ENDPOINT_REFCLK_DRIVE                     0x54
+#define QPHY_RX_IDLE_DTCT_CNTRL                                0x58
+#define QPHY_POWER_STATE_CONFIG1                       0x60
+#define QPHY_POWER_STATE_CONFIG2                       0x64
+#define QPHY_POWER_STATE_CONFIG4                       0x6c
+#define QPHY_LOCK_DETECT_CONFIG1                       0x80
+#define QPHY_LOCK_DETECT_CONFIG2                       0x84
+#define QPHY_LOCK_DETECT_CONFIG3                       0x88
+#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK               0xa0
+#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK                 0xa4
+
+/* QPHY_SW_RESET bit */
+#define SW_RESET                               BIT(0)
+/* QPHY_POWER_DOWN_CONTROL */
+#define SW_PWRDN                               BIT(0)
+#define REFCLK_DRV_DSBL                                BIT(1)
+/* QPHY_START_CONTROL bits */
+#define SERDES_START                           BIT(0)
+#define PCS_START                              BIT(1)
+#define PLL_READY_GATE_EN                      BIT(3)
+/* QPHY_PCS_STATUS bit */
+#define PHYSTATUS                              BIT(6)
+/* QPHY_COM_PCS_READY_STATUS bit */
+#define PCS_READY                              BIT(0)
+
+#define PHY_INIT_COMPLETE_TIMEOUT              1000
+#define POWER_DOWN_DELAY_US_MIN                        10
+#define POWER_DOWN_DELAY_US_MAX                        11
+
+#define MAX_PROP_NAME                          32
+
+struct qmp_phy_init_tbl {
+       unsigned int offset;
+       unsigned int val;
+       /*
+        * register part of layout ?
+        * if yes, then offset gives index in the reg-layout
+        */
+       int in_layout;
+};
+
+#define QMP_PHY_INIT_CFG(o, v)         \
+       {                               \
+               .offset = o,            \
+               .val = v,               \
+       }
+
+#define QMP_PHY_INIT_CFG_L(o, v)       \
+       {                               \
+               .offset = o,            \
+               .val = v,               \
+               .in_layout = 1,         \
+       }
+
+/* set of registers with offsets different per-PHY */
+enum qphy_reg_layout {
+       /* Common block control registers */
+       QPHY_COM_SW_RESET,
+       QPHY_COM_POWER_DOWN_CONTROL,
+       QPHY_COM_START_CONTROL,
+       QPHY_COM_PCS_READY_STATUS,
+       /* PCS registers */
+       QPHY_PLL_LOCK_CHK_DLY_TIME,
+       QPHY_FLL_CNTRL1,
+       QPHY_FLL_CNTRL2,
+       QPHY_FLL_CNT_VAL_L,
+       QPHY_FLL_CNT_VAL_H_TOL,
+       QPHY_FLL_MAN_CODE,
+       QPHY_SW_RESET,
+       QPHY_START_CTRL,
+       QPHY_PCS_READY_STATUS,
+};
+
+static const unsigned int pciephy_regs_layout[] = {
+       [QPHY_COM_SW_RESET]             = 0x400,
+       [QPHY_COM_POWER_DOWN_CONTROL]   = 0x404,
+       [QPHY_COM_START_CONTROL]        = 0x408,
+       [QPHY_COM_PCS_READY_STATUS]     = 0x448,
+       [QPHY_PLL_LOCK_CHK_DLY_TIME]    = 0xa8,
+       [QPHY_FLL_CNTRL1]               = 0xc4,
+       [QPHY_FLL_CNTRL2]               = 0xc8,
+       [QPHY_FLL_CNT_VAL_L]            = 0xcc,
+       [QPHY_FLL_CNT_VAL_H_TOL]        = 0xd0,
+       [QPHY_FLL_MAN_CODE]             = 0xd4,
+       [QPHY_SW_RESET]                 = 0x00,
+       [QPHY_START_CTRL]               = 0x08,
+       [QPHY_PCS_READY_STATUS]         = 0x174,
+};
+
+static const unsigned int usb3phy_regs_layout[] = {
+       [QPHY_FLL_CNTRL1]               = 0xc0,
+       [QPHY_FLL_CNTRL2]               = 0xc4,
+       [QPHY_FLL_CNT_VAL_L]            = 0xc8,
+       [QPHY_FLL_CNT_VAL_H_TOL]        = 0xcc,
+       [QPHY_FLL_MAN_CODE]             = 0xd0,
+       [QPHY_SW_RESET]                 = 0x00,
+       [QPHY_START_CTRL]               = 0x08,
+       [QPHY_PCS_READY_STATUS]         = 0x17c,
+};
+
+static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06),
+       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x42),
+       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
+       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f),
+       QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a),
+       QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x09),
+       QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
+       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03),
+       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55),
+       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55),
+       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x1a),
+       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x0a),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x04),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
+       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
+       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
+       QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19),
+       QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x15),
+       QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
+       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
+       QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x40),
+};
+
+static const struct qmp_phy_init_tbl msm8996_pcie_tx_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
+       QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06),
+};
+
+static const struct qmp_phy_init_tbl msm8996_pcie_rx_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c),
+       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb),
+       QMP_PHY_INIT_CFG(QSERDES_RX_RX_BAND, 0x18),
+       QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04),
+       QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x04),
+       QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
+       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14),
+       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x19),
+};
+
+static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = {
+       QMP_PHY_INIT_CFG(QPHY_RX_IDLE_DTCT_CNTRL, 0x4c),
+       QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x00),
+       QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01),
+
+       QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x05),
+
+       QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x05),
+       QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x02),
+       QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG4, 0x00),
+       QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG1, 0xa3),
+       QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0x0e),
+};
+
+static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14),
+       QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
+       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x04),
+       /* PLL and Loop filter settings */
+       QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
+       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55),
+       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55),
+       QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
+       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
+       QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
+       QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
+       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15),
+       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34),
+       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
+       /* SSC settings */
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde),
+       QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07),
+};
+
+static const struct qmp_phy_init_tbl msm8996_usb3_tx_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
+       QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12),
+       QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06),
+};
+
+static const struct qmp_phy_init_tbl msm8996_usb3_rx_tbl[] = {
+       QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+       QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04),
+       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02),
+       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c),
+       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xbb),
+       QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
+       QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03),
+       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x18),
+       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16),
+};
+
+static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = {
+       /* FLL settings */
+       QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL2, 0x03),
+       QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL1, 0x02),
+       QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_L, 0x09),
+       QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_H_TOL, 0x42),
+       QMP_PHY_INIT_CFG_L(QPHY_FLL_MAN_CODE, 0x85),
+
+       /* Lock Det settings */
+       QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG1, 0xd1),
+       QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG2, 0x1f),
+       QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG3, 0x47),
+       QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08),
+};
+
+/* struct qmp_phy_cfg - per-PHY initialization config */
+struct qmp_phy_cfg {
+       /* phy-type - PCIE/UFS/USB */
+       unsigned int type;
+       /* number of lanes provided by phy */
+       int nlanes;
+
+       /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
+       const struct qmp_phy_init_tbl *serdes_tbl;
+       int serdes_tbl_num;
+       const struct qmp_phy_init_tbl *tx_tbl;
+       int tx_tbl_num;
+       const struct qmp_phy_init_tbl *rx_tbl;
+       int rx_tbl_num;
+       const struct qmp_phy_init_tbl *pcs_tbl;
+       int pcs_tbl_num;
+
+       /* clock ids to be requested */
+       const char * const *clk_list;
+       int num_clks;
+       /* resets to be requested */
+       const char * const *reset_list;
+       int num_resets;
+       /* regulators to be requested */
+       const char * const *vreg_list;
+       int num_vregs;
+
+       /* array of registers with different offsets */
+       const unsigned int *regs;
+
+       unsigned int start_ctrl;
+       unsigned int pwrdn_ctrl;
+       unsigned int mask_pcs_ready;
+       unsigned int mask_com_pcs_ready;
+
+       /* true, if PHY has a separate PHY_COM control block */
+       bool has_phy_com_ctrl;
+       /* true, if PHY has a reset for individual lanes */
+       bool has_lane_rst;
+       /* true, if PHY needs delay after POWER_DOWN */
+       bool has_pwrdn_delay;
+       /* power_down delay in usec */
+       int pwrdn_delay_min;
+       int pwrdn_delay_max;
+};
+
+/**
+ * struct qmp_phy - per-lane phy descriptor
+ *
+ * @phy: generic phy
+ * @tx: iomapped memory space for lane's tx
+ * @rx: iomapped memory space for lane's rx
+ * @pcs: iomapped memory space for lane's pcs
+ * @pipe_clk: pipe lock
+ * @index: lane index
+ * @qmp: QMP phy to which this lane belongs
+ * @lane_rst: lane's reset controller
+ */
+struct qmp_phy {
+       struct phy *phy;
+       void __iomem *tx;
+       void __iomem *rx;
+       void __iomem *pcs;
+       struct clk *pipe_clk;
+       unsigned int index;
+       struct qcom_qmp *qmp;
+       struct reset_control *lane_rst;
+};
+
+/**
+ * struct qcom_qmp - structure holding QMP phy block attributes
+ *
+ * @dev: device
+ * @serdes: iomapped memory space for phy's serdes
+ *
+ * @clks: array of clocks required by phy
+ * @resets: array of resets required by phy
+ * @vregs: regulator supplies bulk data
+ *
+ * @cfg: phy specific configuration
+ * @phys: array of per-lane phy descriptors
+ * @phy_mutex: mutex lock for PHY common block initialization
+ * @init_count: phy common block initialization count
+ */
+struct qcom_qmp {
+       struct device *dev;
+       void __iomem *serdes;
+
+       struct clk **clks;
+       struct reset_control **resets;
+       struct regulator_bulk_data *vregs;
+
+       const struct qmp_phy_cfg *cfg;
+       struct qmp_phy **phys;
+
+       struct mutex phy_mutex;
+       int init_count;
+};
+
+static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
+{
+       u32 reg;
+
+       reg = readl(base + offset);
+       reg |= val;
+       writel(reg, base + offset);
+
+       /* ensure that above write is through */
+       readl(base + offset);
+}
+
+static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
+{
+       u32 reg;
+
+       reg = readl(base + offset);
+       reg &= ~val;
+       writel(reg, base + offset);
+
+       /* ensure that above write is through */
+       readl(base + offset);
+}
+
+/* list of clocks required by phy */
+static const char * const msm8996_phy_clk_l[] = {
+       "aux", "cfg_ahb", "ref",
+};
+
+/* list of resets */
+static const char * const msm8996_pciephy_reset_l[] = {
+       "phy", "common", "cfg",
+};
+
+static const char * const msm8996_usb3phy_reset_l[] = {
+       "phy", "common",
+};
+
+/* list of regulators */
+static const char * const msm8996_phy_vreg_l[] = {
+       "vdda-phy", "vdda-pll",
+};
+
+static const struct qmp_phy_cfg msm8996_pciephy_cfg = {
+       .type                   = PHY_TYPE_PCIE,
+       .nlanes                 = 3,
+
+       .serdes_tbl             = msm8996_pcie_serdes_tbl,
+       .serdes_tbl_num         = ARRAY_SIZE(msm8996_pcie_serdes_tbl),
+       .tx_tbl                 = msm8996_pcie_tx_tbl,
+       .tx_tbl_num             = ARRAY_SIZE(msm8996_pcie_tx_tbl),
+       .rx_tbl                 = msm8996_pcie_rx_tbl,
+       .rx_tbl_num             = ARRAY_SIZE(msm8996_pcie_rx_tbl),
+       .pcs_tbl                = msm8996_pcie_pcs_tbl,
+       .pcs_tbl_num            = ARRAY_SIZE(msm8996_pcie_pcs_tbl),
+       .clk_list               = msm8996_phy_clk_l,
+       .num_clks               = ARRAY_SIZE(msm8996_phy_clk_l),
+       .reset_list             = msm8996_pciephy_reset_l,
+       .num_resets             = ARRAY_SIZE(msm8996_pciephy_reset_l),
+       .vreg_list              = msm8996_phy_vreg_l,
+       .num_vregs              = ARRAY_SIZE(msm8996_phy_vreg_l),
+       .regs                   = pciephy_regs_layout,
+
+       .start_ctrl             = PCS_START | PLL_READY_GATE_EN,
+       .pwrdn_ctrl             = SW_PWRDN | REFCLK_DRV_DSBL,
+       .mask_com_pcs_ready     = PCS_READY,
+
+       .has_phy_com_ctrl       = true,
+       .has_lane_rst           = true,
+       .has_pwrdn_delay        = true,
+       .pwrdn_delay_min        = POWER_DOWN_DELAY_US_MIN,
+       .pwrdn_delay_max        = POWER_DOWN_DELAY_US_MAX,
+};
+
+static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
+       .type                   = PHY_TYPE_USB3,
+       .nlanes                 = 1,
+
+       .serdes_tbl             = msm8996_usb3_serdes_tbl,
+       .serdes_tbl_num         = ARRAY_SIZE(msm8996_usb3_serdes_tbl),
+       .tx_tbl                 = msm8996_usb3_tx_tbl,
+       .tx_tbl_num             = ARRAY_SIZE(msm8996_usb3_tx_tbl),
+       .rx_tbl                 = msm8996_usb3_rx_tbl,
+       .rx_tbl_num             = ARRAY_SIZE(msm8996_usb3_rx_tbl),
+       .pcs_tbl                = msm8996_usb3_pcs_tbl,
+       .pcs_tbl_num            = ARRAY_SIZE(msm8996_usb3_pcs_tbl),
+       .clk_list               = msm8996_phy_clk_l,
+       .num_clks               = ARRAY_SIZE(msm8996_phy_clk_l),
+       .reset_list             = msm8996_usb3phy_reset_l,
+       .num_resets             = ARRAY_SIZE(msm8996_usb3phy_reset_l),
+       .vreg_list              = msm8996_phy_vreg_l,
+       .num_vregs              = ARRAY_SIZE(msm8996_phy_vreg_l),
+       .regs                   = usb3phy_regs_layout,
+
+       .start_ctrl             = SERDES_START | PCS_START,
+       .pwrdn_ctrl             = SW_PWRDN,
+       .mask_pcs_ready         = PHYSTATUS,
+};
+
+static void qcom_qmp_phy_configure(void __iomem *base,
+                                  const unsigned int *regs,
+                                  const struct qmp_phy_init_tbl tbl[],
+                                  int num)
+{
+       int i;
+       const struct qmp_phy_init_tbl *t = tbl;
+
+       if (!t)
+               return;
+
+       for (i = 0; i < num; i++, t++) {
+               if (t->in_layout)
+                       writel(t->val, base + regs[t->offset]);
+               else
+                       writel(t->val, base + t->offset);
+       }
+}
+
+static int qcom_qmp_phy_poweron(struct phy *phy)
+{
+       struct qmp_phy *qphy = phy_get_drvdata(phy);
+       struct qcom_qmp *qmp = qphy->qmp;
+       int num = qmp->cfg->num_vregs;
+       int ret;
+
+       dev_vdbg(&phy->dev, "Powering on QMP phy\n");
+
+       /* turn on regulator supplies */
+       ret = regulator_bulk_enable(num, qmp->vregs);
+       if (ret) {
+               dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
+               return ret;
+       }
+
+       ret = clk_prepare_enable(qphy->pipe_clk);
+       if (ret) {
+               dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret);
+               regulator_bulk_disable(num, qmp->vregs);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int qcom_qmp_phy_poweroff(struct phy *phy)
+{
+       struct qmp_phy *qphy = phy_get_drvdata(phy);
+       struct qcom_qmp *qmp = qphy->qmp;
+
+       clk_disable_unprepare(qphy->pipe_clk);
+
+       regulator_bulk_disable(qmp->cfg->num_vregs, qmp->vregs);
+
+       return 0;
+}
+
+static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
+{
+       const struct qmp_phy_cfg *cfg = qmp->cfg;
+       void __iomem *serdes = qmp->serdes;
+       int ret, i;
+
+       mutex_lock(&qmp->phy_mutex);
+       if (qmp->init_count++) {
+               mutex_unlock(&qmp->phy_mutex);
+               return 0;
+       }
+
+       for (i = 0; i < cfg->num_resets; i++) {
+               ret = reset_control_deassert(qmp->resets[i]);
+               if (ret) {
+                       dev_err(qmp->dev, "%s reset deassert failed\n",
+                               qmp->cfg->reset_list[i]);
+                       while (--i >= 0)
+                               reset_control_assert(qmp->resets[i]);
+                       goto err_rst;
+               }
+       }
+
+       if (cfg->has_phy_com_ctrl)
+               qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
+                            SW_PWRDN);
+
+       /* Serdes configuration */
+       qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl,
+                              cfg->serdes_tbl_num);
+
+       if (cfg->has_phy_com_ctrl) {
+               void __iomem *status;
+               unsigned int mask, val;
+
+               qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET);
+               qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL],
+                            SERDES_START | PCS_START);
+
+               status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS];
+               mask = cfg->mask_com_pcs_ready;
+
+               ret = readl_poll_timeout(status, val, (val & mask), 10,
+                                        PHY_INIT_COMPLETE_TIMEOUT);
+               if (ret) {
+                       dev_err(qmp->dev,
+                               "phy common block init timed-out\n");
+                       goto err_com_init;
+               }
+       }
+
+       mutex_unlock(&qmp->phy_mutex);
+
+       return 0;
+
+err_com_init:
+       while (--i >= 0)
+               reset_control_assert(qmp->resets[i]);
+err_rst:
+       mutex_unlock(&qmp->phy_mutex);
+       return ret;
+}
+
+static int qcom_qmp_phy_com_exit(struct qcom_qmp *qmp)
+{
+       const struct qmp_phy_cfg *cfg = qmp->cfg;
+       void __iomem *serdes = qmp->serdes;
+       int i = cfg->num_resets;
+
+       mutex_lock(&qmp->phy_mutex);
+       if (--qmp->init_count) {
+               mutex_unlock(&qmp->phy_mutex);
+               return 0;
+       }
+
+       if (cfg->has_phy_com_ctrl) {
+               qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL],
+                            SERDES_START | PCS_START);
+               qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET],
+                            SW_RESET);
+               qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
+                            SW_PWRDN);
+       }
+
+       while (--i >= 0)
+               reset_control_assert(qmp->resets[i]);
+
+       mutex_unlock(&qmp->phy_mutex);
+
+       return 0;
+}
+
+/* PHY Initialization */
+static int qcom_qmp_phy_init(struct phy *phy)
+{
+       struct qmp_phy *qphy = phy_get_drvdata(phy);
+       struct qcom_qmp *qmp = qphy->qmp;
+       const struct qmp_phy_cfg *cfg = qmp->cfg;
+       void __iomem *tx = qphy->tx;
+       void __iomem *rx = qphy->rx;
+       void __iomem *pcs = qphy->pcs;
+       void __iomem *status;
+       unsigned int mask, val;
+       int ret, i;
+
+       dev_vdbg(qmp->dev, "Initializing QMP phy\n");
+
+       for (i = 0; i < qmp->cfg->num_clks; i++) {
+               ret = clk_prepare_enable(qmp->clks[i]);
+               if (ret) {
+                       dev_err(qmp->dev, "failed to enable %s clk, err=%d\n",
+                               qmp->cfg->clk_list[i], ret);
+                       while (--i >= 0)
+                               clk_disable_unprepare(qmp->clks[i]);
+               }
+       }
+
+       ret = qcom_qmp_phy_com_init(qmp);
+       if (ret)
+               goto err_com_init;
+
+       if (cfg->has_lane_rst) {
+               ret = reset_control_deassert(qphy->lane_rst);
+               if (ret) {
+                       dev_err(qmp->dev, "lane%d reset deassert failed\n",
+                               qphy->index);
+                       goto err_lane_rst;
+               }
+       }
+
+       /* Tx, Rx, and PCS configurations */
+       qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num);
+       qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num);
+       qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
+
+       /*
+        * Pull out PHY from POWER DOWN state.
+        * This is active low enable signal to power-down PHY.
+        */
+       qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
+
+       if (cfg->has_pwrdn_delay)
+               usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max);
+
+       /* start SerDes and Phy-Coding-Sublayer */
+       qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
+
+       /* Pull PHY out of reset state */
+       qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
+
+       status = pcs + cfg->regs[QPHY_PCS_READY_STATUS];
+       mask = cfg->mask_pcs_ready;
+
+       ret = readl_poll_timeout(status, val, !(val & mask), 1,
+                                PHY_INIT_COMPLETE_TIMEOUT);
+       if (ret) {
+               dev_err(qmp->dev, "phy initialization timed-out\n");
+               goto err_pcs_ready;
+       }
+
+       return ret;
+
+err_pcs_ready:
+       if (cfg->has_lane_rst)
+               reset_control_assert(qphy->lane_rst);
+err_lane_rst:
+       qcom_qmp_phy_com_exit(qmp);
+err_com_init:
+       while (--i >= 0)
+               clk_disable_unprepare(qmp->clks[i]);
+
+       return ret;
+}
+
+static int qcom_qmp_phy_exit(struct phy *phy)
+{
+       struct qmp_phy *qphy = phy_get_drvdata(phy);
+       struct qcom_qmp *qmp = qphy->qmp;
+       const struct qmp_phy_cfg *cfg = qmp->cfg;
+       int i = cfg->num_clks;
+
+       /* PHY reset */
+       qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
+
+       /* stop SerDes and Phy-Coding-Sublayer */
+       qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
+
+       /* Put PHY into POWER DOWN state: active low */
+       qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
+
+       if (cfg->has_lane_rst)
+               reset_control_assert(qphy->lane_rst);
+
+       qcom_qmp_phy_com_exit(qmp);
+
+       while (--i >= 0)
+               clk_disable_unprepare(qmp->clks[i]);
+
+       return 0;
+}
+
+static int qcom_qmp_phy_vreg_init(struct device *dev)
+{
+       struct qcom_qmp *qmp = dev_get_drvdata(dev);
+       int num = qmp->cfg->num_vregs;
+       int i;
+
+       qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
+       if (!qmp->vregs)
+               return -ENOMEM;
+
+       for (i = 0; i < num; i++)
+               qmp->vregs[i].supply = qmp->cfg->vreg_list[i];
+
+       return devm_regulator_bulk_get(dev, num, qmp->vregs);
+}
+
+static int qcom_qmp_phy_reset_init(struct device *dev)
+{
+       struct qcom_qmp *qmp = dev_get_drvdata(dev);
+       int i;
+
+       qmp->resets = devm_kcalloc(dev, qmp->cfg->num_resets,
+                                  sizeof(*qmp->resets), GFP_KERNEL);
+       if (!qmp->resets)
+               return -ENOMEM;
+
+       for (i = 0; i < qmp->cfg->num_resets; i++) {
+               struct reset_control *rst;
+               const char *name = qmp->cfg->reset_list[i];
+
+               rst = devm_reset_control_get(dev, name);
+               if (IS_ERR(rst)) {
+                       dev_err(dev, "failed to get %s reset\n", name);
+                       return PTR_ERR(rst);
+               }
+               qmp->resets[i] = rst;
+       }
+
+       return 0;
+}
+
+static int qcom_qmp_phy_clk_init(struct device *dev)
+{
+       struct qcom_qmp *qmp = dev_get_drvdata(dev);
+       int ret, i;
+
+       qmp->clks = devm_kcalloc(dev, qmp->cfg->num_clks,
+                                sizeof(*qmp->clks), GFP_KERNEL);
+       if (!qmp->clks)
+               return -ENOMEM;
+
+       for (i = 0; i < qmp->cfg->num_clks; i++) {
+               struct clk *_clk;
+               const char *name = qmp->cfg->clk_list[i];
+
+               _clk = devm_clk_get(dev, name);
+               if (IS_ERR(_clk)) {
+                       ret = PTR_ERR(_clk);
+                       if (ret != -EPROBE_DEFER)
+                               dev_err(dev, "failed to get %s clk, %d\n",
+                                       name, ret);
+                       return ret;
+               }
+               qmp->clks[i] = _clk;
+       }
+
+       return 0;
+}
+
+/*
+ * Register a fixed rate pipe clock.
+ *
+ * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
+ * controls it. The <s>_pipe_clk coming out of the GCC is requested
+ * by the PHY driver for its operations.
+ * We register the <s>_pipe_clksrc here. The gcc driver takes care
+ * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk.
+ * Below picture shows this relationship.
+ *
+ *         +---------------+
+ *         |   PHY block   |<<---------------------------------------+
+ *         |               |                                         |
+ *         |   +-------+   |                   +-----+               |
+ *   I/P---^-->|  PLL  |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
+ *    clk  |   +-------+   |                   +-----+
+ *         +---------------+
+ */
+static int phy_pipe_clk_register(struct qcom_qmp *qmp, int id)
+{
+       char name[24];
+       struct clk_fixed_rate *fixed;
+       struct clk_init_data init = { };
+
+       switch (qmp->cfg->type) {
+       case PHY_TYPE_USB3:
+               snprintf(name, sizeof(name), "usb3_phy_pipe_clk_src");
+               break;
+       case PHY_TYPE_PCIE:
+               snprintf(name, sizeof(name), "pcie_%d_pipe_clk_src", id);
+               break;
+       default:
+               /* not all phys register pipe clocks, so return success */
+               return 0;
+       }
+
+       fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL);
+       if (!fixed)
+               return -ENOMEM;
+
+       init.name = name;
+       init.ops = &clk_fixed_rate_ops;
+
+       /* controllers using QMP phys use 125MHz pipe clock interface */
+       fixed->fixed_rate = 125000000;
+       fixed->hw.init = &init;
+
+       return devm_clk_hw_register(qmp->dev, &fixed->hw);
+}
+
+static const struct phy_ops qcom_qmp_phy_gen_ops = {
+       .init           = qcom_qmp_phy_init,
+       .exit           = qcom_qmp_phy_exit,
+       .power_on       = qcom_qmp_phy_poweron,
+       .power_off      = qcom_qmp_phy_poweroff,
+       .owner          = THIS_MODULE,
+};
+
+static
+int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
+{
+       struct qcom_qmp *qmp = dev_get_drvdata(dev);
+       struct phy *generic_phy;
+       struct qmp_phy *qphy;
+       char prop_name[MAX_PROP_NAME];
+       int ret;
+
+       qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
+       if (!qphy)
+               return -ENOMEM;
+
+       /*
+        * Get memory resources for each phy lane:
+        * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
+        */
+       qphy->tx = of_iomap(np, 0);
+       if (!qphy->tx)
+               return -ENOMEM;
+
+       qphy->rx = of_iomap(np, 1);
+       if (!qphy->rx)
+               return -ENOMEM;
+
+       qphy->pcs = of_iomap(np, 2);
+       if (!qphy->pcs)
+               return -ENOMEM;
+
+       /*
+        * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3
+        * based phys, so they essentially have pipe clock. So,
+        * we return error in case phy is USB3 or PIPE type.
+        * Otherwise, we initialize pipe clock to NULL for
+        * all phys that don't need this.
+        */
+       snprintf(prop_name, sizeof(prop_name), "pipe%d", id);
+       qphy->pipe_clk = of_clk_get_by_name(np, prop_name);
+       if (IS_ERR(qphy->pipe_clk)) {
+               if (qmp->cfg->type == PHY_TYPE_PCIE ||
+                   qmp->cfg->type == PHY_TYPE_USB3) {
+                       ret = PTR_ERR(qphy->pipe_clk);
+                       if (ret != -EPROBE_DEFER)
+                               dev_err(dev,
+                                       "failed to get lane%d pipe_clk, %d\n",
+                                       id, ret);
+                       return ret;
+               }
+               qphy->pipe_clk = NULL;
+       }
+
+       /* Get lane reset, if any */
+       if (qmp->cfg->has_lane_rst) {
+               snprintf(prop_name, sizeof(prop_name), "lane%d", id);
+               qphy->lane_rst = of_reset_control_get(np, prop_name);
+               if (IS_ERR(qphy->lane_rst)) {
+                       dev_err(dev, "failed to get lane%d reset\n", id);
+                       return PTR_ERR(qphy->lane_rst);
+               }
+       }
+
+       generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_gen_ops);
+       if (IS_ERR(generic_phy)) {
+               ret = PTR_ERR(generic_phy);
+               dev_err(dev, "failed to create qphy %d\n", ret);
+               return ret;
+       }
+
+       qphy->phy = generic_phy;
+       qphy->index = id;
+       qphy->qmp = qmp;
+       qmp->phys[id] = qphy;
+       phy_set_drvdata(generic_phy, qphy);
+
+       return 0;
+}
+
+static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
+       {
+               .compatible = "qcom,msm8996-qmp-pcie-phy",
+               .data = &msm8996_pciephy_cfg,
+       }, {
+               .compatible = "qcom,msm8996-qmp-usb3-phy",
+               .data = &msm8996_usb3phy_cfg,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table);
+
+static int qcom_qmp_phy_probe(struct platform_device *pdev)
+{
+       struct qcom_qmp *qmp;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       struct device_node *child;
+       struct phy_provider *phy_provider;
+       void __iomem *base;
+       int num, id;
+       int ret;
+
+       qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL);
+       if (!qmp)
+               return -ENOMEM;
+
+       qmp->dev = dev;
+       dev_set_drvdata(dev, qmp);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       /* per PHY serdes; usually located at base address */
+       qmp->serdes = base;
+
+       mutex_init(&qmp->phy_mutex);
+
+       /* Get the specific init parameters of QMP phy */
+       qmp->cfg = of_device_get_match_data(dev);
+
+       ret = qcom_qmp_phy_clk_init(dev);
+       if (ret)
+               return ret;
+
+       ret = qcom_qmp_phy_reset_init(dev);
+       if (ret)
+               return ret;
+
+       ret = qcom_qmp_phy_vreg_init(dev);
+       if (ret) {
+               dev_err(dev, "failed to get regulator supplies\n");
+               return ret;
+       }
+
+       num = of_get_available_child_count(dev->of_node);
+       /* do we have a rogue child node ? */
+       if (num > qmp->cfg->nlanes)
+               return -EINVAL;
+
+       qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL);
+       if (!qmp->phys)
+               return -ENOMEM;
+
+       id = 0;
+       for_each_available_child_of_node(dev->of_node, child) {
+               /* Create per-lane phy */
+               ret = qcom_qmp_phy_create(dev, child, id);
+               if (ret) {
+                       dev_err(dev, "failed to create lane%d phy, %d\n",
+                               id, ret);
+                       return ret;
+               }
+
+               /*
+                * Register the pipe clock provided by phy.
+                * See function description to see details of this pipe clock.
+                */
+               ret = phy_pipe_clk_register(qmp, id);
+               if (ret) {
+                       dev_err(qmp->dev,
+                               "failed to register pipe clock source\n");
+                       return ret;
+               }
+               id++;
+       }
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (!IS_ERR(phy_provider))
+               dev_info(dev, "Registered Qcom-QMP phy\n");
+
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static struct platform_driver qcom_qmp_phy_driver = {
+       .probe          = qcom_qmp_phy_probe,
+       .driver = {
+               .name   = "qcom-qmp-phy",
+               .of_match_table = qcom_qmp_phy_of_match_table,
+       },
+};
+
+module_platform_driver(qcom_qmp_phy_driver);
+
+MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>");
+MODULE_DESCRIPTION("Qualcomm QMP PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
new file mode 100644 (file)
index 0000000..6c57524
--- /dev/null
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#define QUSB2PHY_PLL_TEST              0x04
+#define CLK_REF_SEL                    BIT(7)
+
+#define QUSB2PHY_PLL_TUNE              0x08
+#define QUSB2PHY_PLL_USER_CTL1         0x0c
+#define QUSB2PHY_PLL_USER_CTL2         0x10
+#define QUSB2PHY_PLL_AUTOPGM_CTL1      0x1c
+#define QUSB2PHY_PLL_PWR_CTRL          0x18
+
+#define QUSB2PHY_PLL_STATUS            0x38
+#define PLL_LOCKED                     BIT(5)
+
+#define QUSB2PHY_PORT_TUNE1            0x80
+#define QUSB2PHY_PORT_TUNE2            0x84
+#define QUSB2PHY_PORT_TUNE3            0x88
+#define QUSB2PHY_PORT_TUNE4            0x8c
+#define QUSB2PHY_PORT_TUNE5            0x90
+#define QUSB2PHY_PORT_TEST2            0x9c
+
+#define QUSB2PHY_PORT_POWERDOWN                0xb4
+#define CLAMP_N_EN                     BIT(5)
+#define FREEZIO_N                      BIT(1)
+#define POWER_DOWN                     BIT(0)
+
+#define QUSB2PHY_REFCLK_ENABLE         BIT(0)
+
+#define PHY_CLK_SCHEME_SEL             BIT(0)
+
+struct qusb2_phy_init_tbl {
+       unsigned int offset;
+       unsigned int val;
+};
+
+#define QUSB2_PHY_INIT_CFG(o, v) \
+       {                       \
+               .offset = o,    \
+               .val = v,       \
+       }
+
+static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = {
+       QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE1, 0xf8),
+       QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE2, 0xb3),
+       QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE3, 0x83),
+       QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE4, 0xc0),
+       QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30),
+       QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79),
+       QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21),
+       QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TEST2, 0x14),
+       QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f),
+       QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
+};
+
+struct qusb2_phy_cfg {
+       const struct qusb2_phy_init_tbl *tbl;
+       /* number of entries in the table */
+       unsigned int tbl_num;
+       /* offset to PHY_CLK_SCHEME register in TCSR map */
+       unsigned int clk_scheme_offset;
+};
+
+static const struct qusb2_phy_cfg msm8996_phy_cfg = {
+       .tbl = msm8996_init_tbl,
+       .tbl_num = ARRAY_SIZE(msm8996_init_tbl),
+};
+
+static const char * const qusb2_phy_vreg_names[] = {
+       "vdda-pll", "vdda-phy-dpdm",
+};
+
+#define QUSB2_NUM_VREGS                ARRAY_SIZE(qusb2_phy_vreg_names)
+
+/**
+ * struct qusb2_phy - structure holding qusb2 phy attributes
+ *
+ * @phy: generic phy
+ * @base: iomapped memory space for qubs2 phy
+ *
+ * @cfg_ahb_clk: AHB2PHY interface clock
+ * @ref_clk: phy reference clock
+ * @iface_clk: phy interface clock
+ * @phy_reset: phy reset control
+ * @vregs: regulator supplies bulk data
+ *
+ * @tcsr: TCSR syscon register map
+ * @cell: nvmem cell containing phy tuning value
+ *
+ * @cfg: phy config data
+ * @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme
+ */
+struct qusb2_phy {
+       struct phy *phy;
+       void __iomem *base;
+
+       struct clk *cfg_ahb_clk;
+       struct clk *ref_clk;
+       struct clk *iface_clk;
+       struct reset_control *phy_reset;
+       struct regulator_bulk_data vregs[QUSB2_NUM_VREGS];
+
+       struct regmap *tcsr;
+       struct nvmem_cell *cell;
+
+       const struct qusb2_phy_cfg *cfg;
+       bool has_se_clk_scheme;
+};
+
+static inline void qusb2_setbits(void __iomem *base, u32 offset, u32 val)
+{
+       u32 reg;
+
+       reg = readl(base + offset);
+       reg |= val;
+       writel(reg, base + offset);
+
+       /* Ensure above write is completed */
+       readl(base + offset);
+}
+
+static inline void qusb2_clrbits(void __iomem *base, u32 offset, u32 val)
+{
+       u32 reg;
+
+       reg = readl(base + offset);
+       reg &= ~val;
+       writel(reg, base + offset);
+
+       /* Ensure above write is completed */
+       readl(base + offset);
+}
+
+static inline
+void qcom_qusb2_phy_configure(void __iomem *base,
+                             const struct qusb2_phy_init_tbl tbl[], int num)
+{
+       int i;
+
+       for (i = 0; i < num; i++)
+               writel(tbl[i].val, base + tbl[i].offset);
+}
+
+/*
+ * Fetches HS Tx tuning value from nvmem and sets the
+ * QUSB2PHY_PORT_TUNE2 register.
+ * For error case, skip setting the value and use the default value.
+ */
+static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
+{
+       struct device *dev = &qphy->phy->dev;
+       u8 *val;
+
+       /*
+        * Read efuse register having TUNE2 parameter's high nibble.
+        * If efuse register shows value as 0x0, or if we fail to find
+        * a valid efuse register settings, then use default value
+        * as 0xB for high nibble that we have already set while
+        * configuring phy.
+        */
+       val = nvmem_cell_read(qphy->cell, NULL);
+       if (IS_ERR(val) || !val[0]) {
+               dev_dbg(dev, "failed to read a valid hs-tx trim value\n");
+               return;
+       }
+
+       /* Fused TUNE2 value is the higher nibble only */
+       qusb2_setbits(qphy->base, QUSB2PHY_PORT_TUNE2, val[0] << 0x4);
+}
+
+static int qusb2_phy_poweron(struct phy *phy)
+{
+       struct qusb2_phy *qphy = phy_get_drvdata(phy);
+       int num = ARRAY_SIZE(qphy->vregs);
+       int ret;
+
+       dev_vdbg(&phy->dev, "%s(): Powering-on QUSB2 phy\n", __func__);
+
+       /* turn on regulator supplies */
+       ret = regulator_bulk_enable(num, qphy->vregs);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(qphy->iface_clk);
+       if (ret) {
+               dev_err(&phy->dev, "failed to enable iface_clk, %d\n", ret);
+               regulator_bulk_disable(num, qphy->vregs);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int qusb2_phy_poweroff(struct phy *phy)
+{
+       struct qusb2_phy *qphy = phy_get_drvdata(phy);
+
+       clk_disable_unprepare(qphy->iface_clk);
+
+       regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
+
+       return 0;
+}
+
+static int qusb2_phy_init(struct phy *phy)
+{
+       struct qusb2_phy *qphy = phy_get_drvdata(phy);
+       unsigned int val;
+       unsigned int clk_scheme;
+       int ret;
+
+       dev_vdbg(&phy->dev, "%s(): Initializing QUSB2 phy\n", __func__);
+
+       /* enable ahb interface clock to program phy */
+       ret = clk_prepare_enable(qphy->cfg_ahb_clk);
+       if (ret) {
+               dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret);
+               return ret;
+       }
+
+       /* Perform phy reset */
+       ret = reset_control_assert(qphy->phy_reset);
+       if (ret) {
+               dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
+               goto disable_ahb_clk;
+       }
+
+       /* 100 us delay to keep PHY in reset mode */
+       usleep_range(100, 150);
+
+       ret = reset_control_deassert(qphy->phy_reset);
+       if (ret) {
+               dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
+               goto disable_ahb_clk;
+       }
+
+       /* Disable the PHY */
+       qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN,
+                     CLAMP_N_EN | FREEZIO_N | POWER_DOWN);
+
+       /* save reset value to override reference clock scheme later */
+       val = readl(qphy->base + QUSB2PHY_PLL_TEST);
+
+       qcom_qusb2_phy_configure(qphy->base, qphy->cfg->tbl,
+                                qphy->cfg->tbl_num);
+
+       /* Set efuse value for tuning the PHY */
+       qusb2_phy_set_tune2_param(qphy);
+
+       /* Enable the PHY */
+       qusb2_clrbits(qphy->base, QUSB2PHY_PORT_POWERDOWN, POWER_DOWN);
+
+       /* Required to get phy pll lock successfully */
+       usleep_range(150, 160);
+
+       /* Default is single-ended clock on msm8996 */
+       qphy->has_se_clk_scheme = true;
+       /*
+        * read TCSR_PHY_CLK_SCHEME register to check if single-ended
+        * clock scheme is selected. If yes, then disable differential
+        * ref_clk and use single-ended clock, otherwise use differential
+        * ref_clk only.
+        */
+       if (qphy->tcsr) {
+               ret = regmap_read(qphy->tcsr, qphy->cfg->clk_scheme_offset,
+                                 &clk_scheme);
+               if (ret) {
+                       dev_err(&phy->dev, "failed to read clk scheme reg\n");
+                       goto assert_phy_reset;
+               }
+
+               /* is it a differential clock scheme ? */
+               if (!(clk_scheme & PHY_CLK_SCHEME_SEL)) {
+                       dev_vdbg(&phy->dev, "%s(): select differential clk\n",
+                                __func__);
+                       qphy->has_se_clk_scheme = false;
+               } else {
+                       dev_vdbg(&phy->dev, "%s(): select single-ended clk\n",
+                                __func__);
+               }
+       }
+
+       if (!qphy->has_se_clk_scheme) {
+               val &= ~CLK_REF_SEL;
+               ret = clk_prepare_enable(qphy->ref_clk);
+               if (ret) {
+                       dev_err(&phy->dev, "failed to enable ref clk, %d\n",
+                               ret);
+                       goto assert_phy_reset;
+               }
+       } else {
+               val |= CLK_REF_SEL;
+       }
+
+       writel(val, qphy->base + QUSB2PHY_PLL_TEST);
+
+       /* ensure above write is through */
+       readl(qphy->base + QUSB2PHY_PLL_TEST);
+
+       /* Required to get phy pll lock successfully */
+       usleep_range(100, 110);
+
+       val = readb(qphy->base + QUSB2PHY_PLL_STATUS);
+       if (!(val & PLL_LOCKED)) {
+               dev_err(&phy->dev,
+                       "QUSB2PHY pll lock failed: status reg = %x\n", val);
+               ret = -EBUSY;
+               goto disable_ref_clk;
+       }
+
+       return 0;
+
+disable_ref_clk:
+       if (!qphy->has_se_clk_scheme)
+               clk_disable_unprepare(qphy->ref_clk);
+assert_phy_reset:
+       reset_control_assert(qphy->phy_reset);
+disable_ahb_clk:
+       clk_disable_unprepare(qphy->cfg_ahb_clk);
+       return ret;
+}
+
+static int qusb2_phy_exit(struct phy *phy)
+{
+       struct qusb2_phy *qphy = phy_get_drvdata(phy);
+
+       /* Disable the PHY */
+       qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN,
+                     CLAMP_N_EN | FREEZIO_N | POWER_DOWN);
+
+       if (!qphy->has_se_clk_scheme)
+               clk_disable_unprepare(qphy->ref_clk);
+
+       reset_control_assert(qphy->phy_reset);
+
+       clk_disable_unprepare(qphy->cfg_ahb_clk);
+
+       return 0;
+}
+
+static const struct phy_ops qusb2_phy_gen_ops = {
+       .init           = qusb2_phy_init,
+       .exit           = qusb2_phy_exit,
+       .power_on       = qusb2_phy_poweron,
+       .power_off      = qusb2_phy_poweroff,
+       .owner          = THIS_MODULE,
+};
+
+static const struct of_device_id qusb2_phy_of_match_table[] = {
+       {
+               .compatible     = "qcom,msm8996-qusb2-phy",
+               .data           = &msm8996_phy_cfg,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, qusb2_phy_of_match_table);
+
+static int qusb2_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct qusb2_phy *qphy;
+       struct phy_provider *phy_provider;
+       struct phy *generic_phy;
+       struct resource *res;
+       int ret, i;
+       int num;
+
+       qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
+       if (!qphy)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       qphy->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(qphy->base))
+               return PTR_ERR(qphy->base);
+
+       qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb");
+       if (IS_ERR(qphy->cfg_ahb_clk)) {
+               ret = PTR_ERR(qphy->cfg_ahb_clk);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "failed to get cfg ahb clk, %d\n", ret);
+               return ret;
+       }
+
+       qphy->ref_clk = devm_clk_get(dev, "ref");
+       if (IS_ERR(qphy->ref_clk)) {
+               ret = PTR_ERR(qphy->ref_clk);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "failed to get ref clk, %d\n", ret);
+               return ret;
+       }
+
+       qphy->iface_clk = devm_clk_get(dev, "iface");
+       if (IS_ERR(qphy->iface_clk)) {
+               ret = PTR_ERR(qphy->iface_clk);
+               if (ret == -EPROBE_DEFER)
+                       return ret;
+               qphy->iface_clk = NULL;
+               dev_dbg(dev, "failed to get iface clk, %d\n", ret);
+       }
+
+       qphy->phy_reset = devm_reset_control_get_by_index(&pdev->dev, 0);
+       if (IS_ERR(qphy->phy_reset)) {
+               dev_err(dev, "failed to get phy core reset\n");
+               return PTR_ERR(qphy->phy_reset);
+       }
+
+       num = ARRAY_SIZE(qphy->vregs);
+       for (i = 0; i < num; i++)
+               qphy->vregs[i].supply = qusb2_phy_vreg_names[i];
+
+       ret = devm_regulator_bulk_get(dev, num, qphy->vregs);
+       if (ret) {
+               dev_err(dev, "failed to get regulator supplies\n");
+               return ret;
+       }
+
+       /* Get the specific init parameters of QMP phy */
+       qphy->cfg = of_device_get_match_data(dev);
+
+       qphy->tcsr = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                                       "qcom,tcsr-syscon");
+       if (IS_ERR(qphy->tcsr)) {
+               dev_dbg(dev, "failed to lookup TCSR regmap\n");
+               qphy->tcsr = NULL;
+       }
+
+       qphy->cell = devm_nvmem_cell_get(dev, NULL);
+       if (IS_ERR(qphy->cell)) {
+               if (PTR_ERR(qphy->cell) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+               qphy->cell = NULL;
+               dev_dbg(dev, "failed to lookup tune2 hstx trim value\n");
+       }
+
+       generic_phy = devm_phy_create(dev, NULL, &qusb2_phy_gen_ops);
+       if (IS_ERR(generic_phy)) {
+               ret = PTR_ERR(generic_phy);
+               dev_err(dev, "failed to create phy, %d\n", ret);
+               return ret;
+       }
+       qphy->phy = generic_phy;
+
+       dev_set_drvdata(dev, qphy);
+       phy_set_drvdata(generic_phy, qphy);
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (!IS_ERR(phy_provider))
+               dev_info(dev, "Registered Qcom-QUSB2 phy\n");
+
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static struct platform_driver qusb2_phy_driver = {
+       .probe          = qusb2_phy_probe,
+       .driver = {
+               .name   = "qcom-qusb2-phy",
+               .of_match_table = qusb2_phy_of_match_table,
+       },
+};
+
+module_platform_driver(qusb2_phy_driver);
+
+MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>");
+MODULE_DESCRIPTION("Qualcomm QUSB2 PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-i.h b/drivers/phy/qualcomm/phy-qcom-ufs-i.h
new file mode 100644 (file)
index 0000000..13b02b7
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef UFS_QCOM_PHY_I_H_
+#define UFS_QCOM_PHY_I_H_
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/phy/phy-qcom-ufs.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
+({ \
+       ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
+       might_sleep_if(timeout_us); \
+       for (;;) { \
+               (val) = readl(addr); \
+               if (cond) \
+                       break; \
+               if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \
+                       (val) = readl(addr); \
+                       break; \
+               } \
+               if (sleep_us) \
+                       usleep_range(DIV_ROUND_UP(sleep_us, 4), sleep_us); \
+       } \
+       (cond) ? 0 : -ETIMEDOUT; \
+})
+
+#define UFS_QCOM_PHY_CAL_ENTRY(reg, val)       \
+       {                               \
+               .reg_offset = reg,      \
+               .cfg_value = val,       \
+       }
+
+#define UFS_QCOM_PHY_NAME_LEN  30
+
+enum {
+       MASK_SERDES_START       = 0x1,
+       MASK_PCS_READY          = 0x1,
+};
+
+enum {
+       OFFSET_SERDES_START     = 0x0,
+};
+
+struct ufs_qcom_phy_stored_attributes {
+       u32 att;
+       u32 value;
+};
+
+
+struct ufs_qcom_phy_calibration {
+       u32 reg_offset;
+       u32 cfg_value;
+};
+
+struct ufs_qcom_phy_vreg {
+       const char *name;
+       struct regulator *reg;
+       int max_uA;
+       int min_uV;
+       int max_uV;
+       bool enabled;
+};
+
+struct ufs_qcom_phy {
+       struct list_head list;
+       struct device *dev;
+       void __iomem *mmio;
+       void __iomem *dev_ref_clk_ctrl_mmio;
+       struct clk *tx_iface_clk;
+       struct clk *rx_iface_clk;
+       bool is_iface_clk_enabled;
+       struct clk *ref_clk_src;
+       struct clk *ref_clk_parent;
+       struct clk *ref_clk;
+       bool is_ref_clk_enabled;
+       bool is_dev_ref_clk_enabled;
+       struct ufs_qcom_phy_vreg vdda_pll;
+       struct ufs_qcom_phy_vreg vdda_phy;
+       struct ufs_qcom_phy_vreg vddp_ref_clk;
+       unsigned int quirks;
+
+       /*
+       * If UFS link is put into Hibern8 and if UFS PHY analog hardware is
+       * power collapsed (by clearing UFS_PHY_POWER_DOWN_CONTROL), Hibern8
+       * exit might fail even after powering on UFS PHY analog hardware.
+       * Enabling this quirk will help to solve above issue by doing
+       * custom PHY settings just before PHY analog power collapse.
+       */
+       #define UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE  BIT(0)
+
+       u8 host_ctrl_rev_major;
+       u16 host_ctrl_rev_minor;
+       u16 host_ctrl_rev_step;
+
+       char name[UFS_QCOM_PHY_NAME_LEN];
+       struct ufs_qcom_phy_calibration *cached_regs;
+       int cached_regs_table_size;
+       bool is_powered_on;
+       struct ufs_qcom_phy_specific_ops *phy_spec_ops;
+};
+
+/**
+ * struct ufs_qcom_phy_specific_ops - set of pointers to functions which have a
+ * specific implementation per phy. Each UFS phy, should implement
+ * those functions according to its spec and requirements
+ * @calibrate_phy: pointer to a function that calibrate the phy
+ * @start_serdes: pointer to a function that starts the serdes
+ * @is_physical_coding_sublayer_ready: pointer to a function that
+ * checks pcs readiness. returns 0 for success and non-zero for error.
+ * @set_tx_lane_enable: pointer to a function that enable tx lanes
+ * @power_control: pointer to a function that controls analog rail of phy
+ * and writes to QSERDES_RX_SIGDET_CNTRL attribute
+ */
+struct ufs_qcom_phy_specific_ops {
+       int (*calibrate_phy)(struct ufs_qcom_phy *phy, bool is_rate_B);
+       void (*start_serdes)(struct ufs_qcom_phy *phy);
+       int (*is_physical_coding_sublayer_ready)(struct ufs_qcom_phy *phy);
+       void (*set_tx_lane_enable)(struct ufs_qcom_phy *phy, u32 val);
+       void (*power_control)(struct ufs_qcom_phy *phy, bool val);
+};
+
+struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy);
+int ufs_qcom_phy_power_on(struct phy *generic_phy);
+int ufs_qcom_phy_power_off(struct phy *generic_phy);
+int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common);
+int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common);
+int ufs_qcom_phy_remove(struct phy *generic_phy,
+                      struct ufs_qcom_phy *ufs_qcom_phy);
+struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
+                       struct ufs_qcom_phy *common_cfg,
+                       const struct phy_ops *ufs_qcom_phy_gen_ops,
+                       struct ufs_qcom_phy_specific_ops *phy_spec_ops);
+int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
+                       struct ufs_qcom_phy_calibration *tbl_A, int tbl_size_A,
+                       struct ufs_qcom_phy_calibration *tbl_B, int tbl_size_B,
+                       bool is_rate_B);
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c
new file mode 100644 (file)
index 0000000..12a1b49
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "phy-qcom-ufs-qmp-14nm.h"
+
+#define UFS_PHY_NAME "ufs_phy_qmp_14nm"
+#define UFS_PHY_VDDA_PHY_UV    (925000)
+
+static
+int ufs_qcom_phy_qmp_14nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
+                                       bool is_rate_B)
+{
+       int tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A);
+       int tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
+       int err;
+
+       err = ufs_qcom_phy_calibrate(ufs_qcom_phy, phy_cal_table_rate_A,
+               tbl_size_A, phy_cal_table_rate_B, tbl_size_B, is_rate_B);
+
+       if (err)
+               dev_err(ufs_qcom_phy->dev,
+                       "%s: ufs_qcom_phy_calibrate() failed %d\n",
+                       __func__, err);
+       return err;
+}
+
+static
+void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy *phy_common)
+{
+       phy_common->quirks =
+               UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE;
+}
+
+static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy)
+{
+       return 0;
+}
+
+static int ufs_qcom_phy_qmp_14nm_exit(struct phy *generic_phy)
+{
+       return 0;
+}
+
+static
+void ufs_qcom_phy_qmp_14nm_power_control(struct ufs_qcom_phy *phy, bool val)
+{
+       writel_relaxed(val ? 0x1 : 0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL);
+       /*
+        * Before any transactions involving PHY, ensure PHY knows
+        * that it's analog rail is powered ON (or OFF).
+        */
+       mb();
+}
+
+static inline
+void ufs_qcom_phy_qmp_14nm_set_tx_lane_enable(struct ufs_qcom_phy *phy, u32 val)
+{
+       /*
+        * 14nm PHY does not have TX_LANE_ENABLE register.
+        * Implement this function so as not to propagate error to caller.
+        */
+}
+
+static inline void ufs_qcom_phy_qmp_14nm_start_serdes(struct ufs_qcom_phy *phy)
+{
+       u32 tmp;
+
+       tmp = readl_relaxed(phy->mmio + UFS_PHY_PHY_START);
+       tmp &= ~MASK_SERDES_START;
+       tmp |= (1 << OFFSET_SERDES_START);
+       writel_relaxed(tmp, phy->mmio + UFS_PHY_PHY_START);
+       /* Ensure register value is committed */
+       mb();
+}
+
+static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy *phy_common)
+{
+       int err = 0;
+       u32 val;
+
+       err = readl_poll_timeout(phy_common->mmio + UFS_PHY_PCS_READY_STATUS,
+               val, (val & MASK_PCS_READY), 10, 1000000);
+       if (err)
+               dev_err(phy_common->dev, "%s: poll for pcs failed err = %d\n",
+                       __func__, err);
+       return err;
+}
+
+static const struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = {
+       .init           = ufs_qcom_phy_qmp_14nm_init,
+       .exit           = ufs_qcom_phy_qmp_14nm_exit,
+       .power_on       = ufs_qcom_phy_power_on,
+       .power_off      = ufs_qcom_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static struct ufs_qcom_phy_specific_ops phy_14nm_ops = {
+       .calibrate_phy          = ufs_qcom_phy_qmp_14nm_phy_calibrate,
+       .start_serdes           = ufs_qcom_phy_qmp_14nm_start_serdes,
+       .is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_14nm_is_pcs_ready,
+       .set_tx_lane_enable     = ufs_qcom_phy_qmp_14nm_set_tx_lane_enable,
+       .power_control          = ufs_qcom_phy_qmp_14nm_power_control,
+};
+
+static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct phy *generic_phy;
+       struct ufs_qcom_phy_qmp_14nm *phy;
+       struct ufs_qcom_phy *phy_common;
+       int err = 0;
+
+       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy) {
+               err = -ENOMEM;
+               goto out;
+       }
+       phy_common = &phy->common_cfg;
+
+       generic_phy = ufs_qcom_phy_generic_probe(pdev, phy_common,
+                               &ufs_qcom_phy_qmp_14nm_phy_ops, &phy_14nm_ops);
+
+       if (!generic_phy) {
+               err = -EIO;
+               goto out;
+       }
+
+       err = ufs_qcom_phy_init_clks(phy_common);
+       if (err)
+               goto out;
+
+       err = ufs_qcom_phy_init_vregulators(phy_common);
+       if (err)
+               goto out;
+
+       phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV;
+       phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV;
+
+       ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common);
+
+       phy_set_drvdata(generic_phy, phy);
+
+       strlcpy(phy_common->name, UFS_PHY_NAME, sizeof(phy_common->name));
+
+out:
+       return err;
+}
+
+static const struct of_device_id ufs_qcom_phy_qmp_14nm_of_match[] = {
+       {.compatible = "qcom,ufs-phy-qmp-14nm"},
+       {.compatible = "qcom,msm8996-ufs-phy-qmp-14nm"},
+       {},
+};
+MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_14nm_of_match);
+
+static struct platform_driver ufs_qcom_phy_qmp_14nm_driver = {
+       .probe = ufs_qcom_phy_qmp_14nm_probe,
+       .driver = {
+               .of_match_table = ufs_qcom_phy_qmp_14nm_of_match,
+               .name = "ufs_qcom_phy_qmp_14nm",
+       },
+};
+
+module_platform_driver(ufs_qcom_phy_qmp_14nm_driver);
+
+MODULE_DESCRIPTION("Universal Flash Storage (UFS) QCOM PHY QMP 14nm");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h
new file mode 100644 (file)
index 0000000..3aefdba
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef UFS_QCOM_PHY_QMP_14NM_H_
+#define UFS_QCOM_PHY_QMP_14NM_H_
+
+#include "phy-qcom-ufs-i.h"
+
+/* QCOM UFS PHY control registers */
+#define COM_OFF(x)     (0x000 + x)
+#define PHY_OFF(x)     (0xC00 + x)
+#define TX_OFF(n, x)   (0x400 + (0x400 * n) + x)
+#define RX_OFF(n, x)   (0x600 + (0x400 * n) + x)
+
+/* UFS PHY QSERDES COM registers */
+#define QSERDES_COM_BG_TIMER                   COM_OFF(0x0C)
+#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN                COM_OFF(0x34)
+#define QSERDES_COM_SYS_CLK_CTRL               COM_OFF(0x3C)
+#define QSERDES_COM_LOCK_CMP1_MODE0            COM_OFF(0x4C)
+#define QSERDES_COM_LOCK_CMP2_MODE0            COM_OFF(0x50)
+#define QSERDES_COM_LOCK_CMP3_MODE0            COM_OFF(0x54)
+#define QSERDES_COM_LOCK_CMP1_MODE1            COM_OFF(0x58)
+#define QSERDES_COM_LOCK_CMP2_MODE1            COM_OFF(0x5C)
+#define QSERDES_COM_LOCK_CMP3_MODE1            COM_OFF(0x60)
+#define QSERDES_COM_CP_CTRL_MODE0              COM_OFF(0x78)
+#define QSERDES_COM_CP_CTRL_MODE1              COM_OFF(0x7C)
+#define QSERDES_COM_PLL_RCTRL_MODE0            COM_OFF(0x84)
+#define QSERDES_COM_PLL_RCTRL_MODE1            COM_OFF(0x88)
+#define QSERDES_COM_PLL_CCTRL_MODE0            COM_OFF(0x90)
+#define QSERDES_COM_PLL_CCTRL_MODE1            COM_OFF(0x94)
+#define QSERDES_COM_SYSCLK_EN_SEL              COM_OFF(0xAC)
+#define QSERDES_COM_RESETSM_CNTRL              COM_OFF(0xB4)
+#define QSERDES_COM_LOCK_CMP_EN                        COM_OFF(0xC8)
+#define QSERDES_COM_LOCK_CMP_CFG               COM_OFF(0xCC)
+#define QSERDES_COM_DEC_START_MODE0            COM_OFF(0xD0)
+#define QSERDES_COM_DEC_START_MODE1            COM_OFF(0xD4)
+#define QSERDES_COM_DIV_FRAC_START1_MODE0      COM_OFF(0xDC)
+#define QSERDES_COM_DIV_FRAC_START2_MODE0      COM_OFF(0xE0)
+#define QSERDES_COM_DIV_FRAC_START3_MODE0      COM_OFF(0xE4)
+#define QSERDES_COM_DIV_FRAC_START1_MODE1      COM_OFF(0xE8)
+#define QSERDES_COM_DIV_FRAC_START2_MODE1      COM_OFF(0xEC)
+#define QSERDES_COM_DIV_FRAC_START3_MODE1      COM_OFF(0xF0)
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0      COM_OFF(0x108)
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0      COM_OFF(0x10C)
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1      COM_OFF(0x110)
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1      COM_OFF(0x114)
+#define QSERDES_COM_VCO_TUNE_CTRL              COM_OFF(0x124)
+#define QSERDES_COM_VCO_TUNE_MAP               COM_OFF(0x128)
+#define QSERDES_COM_VCO_TUNE1_MODE0            COM_OFF(0x12C)
+#define QSERDES_COM_VCO_TUNE2_MODE0            COM_OFF(0x130)
+#define QSERDES_COM_VCO_TUNE1_MODE1            COM_OFF(0x134)
+#define QSERDES_COM_VCO_TUNE2_MODE1            COM_OFF(0x138)
+#define QSERDES_COM_VCO_TUNE_TIMER1            COM_OFF(0x144)
+#define QSERDES_COM_VCO_TUNE_TIMER2            COM_OFF(0x148)
+#define QSERDES_COM_CLK_SELECT                 COM_OFF(0x174)
+#define QSERDES_COM_HSCLK_SEL                  COM_OFF(0x178)
+#define QSERDES_COM_CORECLK_DIV                        COM_OFF(0x184)
+#define QSERDES_COM_CORE_CLK_EN                        COM_OFF(0x18C)
+#define QSERDES_COM_CMN_CONFIG                 COM_OFF(0x194)
+#define QSERDES_COM_SVS_MODE_CLK_SEL           COM_OFF(0x19C)
+#define QSERDES_COM_CORECLK_DIV_MODE1          COM_OFF(0x1BC)
+
+/* UFS PHY registers */
+#define UFS_PHY_PHY_START                      PHY_OFF(0x00)
+#define UFS_PHY_POWER_DOWN_CONTROL             PHY_OFF(0x04)
+#define UFS_PHY_PCS_READY_STATUS               PHY_OFF(0x168)
+
+/* UFS PHY TX registers */
+#define QSERDES_TX_HIGHZ_TRANSCEIVER_BIAS_DRVR_EN      TX_OFF(0, 0x68)
+#define QSERDES_TX_LANE_MODE                           TX_OFF(0, 0x94)
+
+/* UFS PHY RX registers */
+#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN       RX_OFF(0, 0x40)
+#define QSERDES_RX_RX_TERM_BW                  RX_OFF(0, 0x90)
+#define QSERDES_RX_RX_EQ_GAIN1_LSB             RX_OFF(0, 0xC4)
+#define QSERDES_RX_RX_EQ_GAIN1_MSB             RX_OFF(0, 0xC8)
+#define QSERDES_RX_RX_EQ_GAIN2_LSB             RX_OFF(0, 0xCC)
+#define QSERDES_RX_RX_EQ_GAIN2_MSB             RX_OFF(0, 0xD0)
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2       RX_OFF(0, 0xD8)
+#define QSERDES_RX_SIGDET_CNTRL                        RX_OFF(0, 0x114)
+#define QSERDES_RX_SIGDET_LVL                  RX_OFF(0, 0x118)
+#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL       RX_OFF(0, 0x11C)
+#define QSERDES_RX_RX_INTERFACE_MODE           RX_OFF(0, 0x12C)
+
+/*
+ * This structure represents the 14nm specific phy.
+ * common_cfg MUST remain the first field in this structure
+ * in case extra fields are added. This way, when calling
+ * get_ufs_qcom_phy() of generic phy, we can extract the
+ * common phy structure (struct ufs_qcom_phy) out of it
+ * regardless of the relevant specific phy.
+ */
+struct ufs_qcom_phy_qmp_14nm {
+       struct ufs_qcom_phy common_cfg;
+};
+
+static struct ufs_qcom_phy_calibration phy_cal_table_rate_A[] = {
+       UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CMN_CONFIG, 0x0e),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL, 0xd7),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CLK_SELECT, 0x30),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYS_CLK_CTRL, 0x06),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BG_TIMER, 0x0a),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_HSCLK_SEL, 0x05),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV, 0x0a),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_EN, 0x01),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_CTRL, 0x10),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x20),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORE_CLK_EN, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_CFG, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_MAP, 0x14),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE0, 0x82),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE0, 0x28),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE0, 0x02),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE0, 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE1, 0x98),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE1, 0x0b),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE1, 0x16),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE1, 0x28),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE1, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE1, 0x32),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP3_MODE1, 0x00),
+
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_HIGHZ_TRANSCEIVER_BIAS_DRVR_EN, 0x45),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE, 0x02),
+
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_LVL, 0x24),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_CNTRL, 0x02),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_INTERFACE_MODE, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x18),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_TERM_BW, 0x5B),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x0F),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E),
+};
+
+static struct ufs_qcom_phy_calibration phy_cal_table_rate_B[] = {
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_MAP, 0x54),
+};
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c
new file mode 100644 (file)
index 0000000..4f68acb
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "phy-qcom-ufs-qmp-20nm.h"
+
+#define UFS_PHY_NAME "ufs_phy_qmp_20nm"
+
+static
+int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
+                                       bool is_rate_B)
+{
+       struct ufs_qcom_phy_calibration *tbl_A, *tbl_B;
+       int tbl_size_A, tbl_size_B;
+       u8 major = ufs_qcom_phy->host_ctrl_rev_major;
+       u16 minor = ufs_qcom_phy->host_ctrl_rev_minor;
+       u16 step = ufs_qcom_phy->host_ctrl_rev_step;
+       int err;
+
+       if ((major == 0x1) && (minor == 0x002) && (step == 0x0000)) {
+               tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_2_0);
+               tbl_A = phy_cal_table_rate_A_1_2_0;
+       } else if ((major == 0x1) && (minor == 0x003) && (step == 0x0000)) {
+               tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_3_0);
+               tbl_A = phy_cal_table_rate_A_1_3_0;
+       } else {
+               dev_err(ufs_qcom_phy->dev, "%s: Unknown UFS-PHY version, no calibration values\n",
+                       __func__);
+               err = -ENODEV;
+               goto out;
+       }
+
+       tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
+       tbl_B = phy_cal_table_rate_B;
+
+       err = ufs_qcom_phy_calibrate(ufs_qcom_phy, tbl_A, tbl_size_A,
+                                               tbl_B, tbl_size_B, is_rate_B);
+
+       if (err)
+               dev_err(ufs_qcom_phy->dev, "%s: ufs_qcom_phy_calibrate() failed %d\n",
+                       __func__, err);
+
+out:
+       return err;
+}
+
+static
+void ufs_qcom_phy_qmp_20nm_advertise_quirks(struct ufs_qcom_phy *phy_common)
+{
+       phy_common->quirks =
+               UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE;
+}
+
+static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy)
+{
+       return 0;
+}
+
+static int ufs_qcom_phy_qmp_20nm_exit(struct phy *generic_phy)
+{
+       return 0;
+}
+
+static
+void ufs_qcom_phy_qmp_20nm_power_control(struct ufs_qcom_phy *phy, bool val)
+{
+       bool hibern8_exit_after_pwr_collapse = phy->quirks &
+               UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE;
+
+       if (val) {
+               writel_relaxed(0x1, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL);
+               /*
+                * Before any transactions involving PHY, ensure PHY knows
+                * that it's analog rail is powered ON.
+                */
+               mb();
+
+               if (hibern8_exit_after_pwr_collapse) {
+                       /*
+                        * Give atleast 1us delay after restoring PHY analog
+                        * power.
+                        */
+                       usleep_range(1, 2);
+                       writel_relaxed(0x0A, phy->mmio +
+                                      QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
+                       writel_relaxed(0x08, phy->mmio +
+                                      QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
+                       /*
+                        * Make sure workaround is deactivated before proceeding
+                        * with normal PHY operations.
+                        */
+                       mb();
+               }
+       } else {
+               if (hibern8_exit_after_pwr_collapse) {
+                       writel_relaxed(0x0A, phy->mmio +
+                                      QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
+                       writel_relaxed(0x02, phy->mmio +
+                                      QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
+                       /*
+                        * Make sure that above workaround is activated before
+                        * PHY analog power collapse.
+                        */
+                       mb();
+               }
+
+               writel_relaxed(0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL);
+               /*
+                * ensure that PHY knows its PHY analog rail is going
+                * to be powered down
+                */
+               mb();
+       }
+}
+
+static
+void ufs_qcom_phy_qmp_20nm_set_tx_lane_enable(struct ufs_qcom_phy *phy, u32 val)
+{
+       writel_relaxed(val & UFS_PHY_TX_LANE_ENABLE_MASK,
+                       phy->mmio + UFS_PHY_TX_LANE_ENABLE);
+       mb();
+}
+
+static inline void ufs_qcom_phy_qmp_20nm_start_serdes(struct ufs_qcom_phy *phy)
+{
+       u32 tmp;
+
+       tmp = readl_relaxed(phy->mmio + UFS_PHY_PHY_START);
+       tmp &= ~MASK_SERDES_START;
+       tmp |= (1 << OFFSET_SERDES_START);
+       writel_relaxed(tmp, phy->mmio + UFS_PHY_PHY_START);
+       mb();
+}
+
+static int ufs_qcom_phy_qmp_20nm_is_pcs_ready(struct ufs_qcom_phy *phy_common)
+{
+       int err = 0;
+       u32 val;
+
+       err = readl_poll_timeout(phy_common->mmio + UFS_PHY_PCS_READY_STATUS,
+                       val, (val & MASK_PCS_READY), 10, 1000000);
+       if (err)
+               dev_err(phy_common->dev, "%s: poll for pcs failed err = %d\n",
+                       __func__, err);
+       return err;
+}
+
+static const struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = {
+       .init           = ufs_qcom_phy_qmp_20nm_init,
+       .exit           = ufs_qcom_phy_qmp_20nm_exit,
+       .power_on       = ufs_qcom_phy_power_on,
+       .power_off      = ufs_qcom_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static struct ufs_qcom_phy_specific_ops phy_20nm_ops = {
+       .calibrate_phy          = ufs_qcom_phy_qmp_20nm_phy_calibrate,
+       .start_serdes           = ufs_qcom_phy_qmp_20nm_start_serdes,
+       .is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_20nm_is_pcs_ready,
+       .set_tx_lane_enable     = ufs_qcom_phy_qmp_20nm_set_tx_lane_enable,
+       .power_control          = ufs_qcom_phy_qmp_20nm_power_control,
+};
+
+static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct phy *generic_phy;
+       struct ufs_qcom_phy_qmp_20nm *phy;
+       struct ufs_qcom_phy *phy_common;
+       int err = 0;
+
+       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy) {
+               err = -ENOMEM;
+               goto out;
+       }
+       phy_common = &phy->common_cfg;
+
+       generic_phy = ufs_qcom_phy_generic_probe(pdev, phy_common,
+                               &ufs_qcom_phy_qmp_20nm_phy_ops, &phy_20nm_ops);
+
+       if (!generic_phy) {
+               err = -EIO;
+               goto out;
+       }
+
+       err = ufs_qcom_phy_init_clks(phy_common);
+       if (err)
+               goto out;
+
+       err = ufs_qcom_phy_init_vregulators(phy_common);
+       if (err)
+               goto out;
+
+       ufs_qcom_phy_qmp_20nm_advertise_quirks(phy_common);
+
+       phy_set_drvdata(generic_phy, phy);
+
+       strlcpy(phy_common->name, UFS_PHY_NAME, sizeof(phy_common->name));
+
+out:
+       return err;
+}
+
+static const struct of_device_id ufs_qcom_phy_qmp_20nm_of_match[] = {
+       {.compatible = "qcom,ufs-phy-qmp-20nm"},
+       {},
+};
+MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_20nm_of_match);
+
+static struct platform_driver ufs_qcom_phy_qmp_20nm_driver = {
+       .probe = ufs_qcom_phy_qmp_20nm_probe,
+       .driver = {
+               .of_match_table = ufs_qcom_phy_qmp_20nm_of_match,
+               .name = "ufs_qcom_phy_qmp_20nm",
+       },
+};
+
+module_platform_driver(ufs_qcom_phy_qmp_20nm_driver);
+
+MODULE_DESCRIPTION("Universal Flash Storage (UFS) QCOM PHY QMP 20nm");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h
new file mode 100644 (file)
index 0000000..4f3076b
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef UFS_QCOM_PHY_QMP_20NM_H_
+#define UFS_QCOM_PHY_QMP_20NM_H_
+
+#include "phy-qcom-ufs-i.h"
+
+/* QCOM UFS PHY control registers */
+
+#define COM_OFF(x)     (0x000 + x)
+#define PHY_OFF(x)     (0xC00 + x)
+#define TX_OFF(n, x)   (0x400 + (0x400 * n) + x)
+#define RX_OFF(n, x)   (0x600 + (0x400 * n) + x)
+
+/* UFS PHY PLL block registers */
+#define QSERDES_COM_SYS_CLK_CTRL               COM_OFF(0x0)
+#define QSERDES_COM_PLL_VCOTAIL_EN             COM_OFF(0x04)
+#define QSERDES_COM_PLL_CNTRL                  COM_OFF(0x14)
+#define QSERDES_COM_PLL_IP_SETI                        COM_OFF(0x24)
+#define QSERDES_COM_CORE_CLK_IN_SYNC_SEL       COM_OFF(0x28)
+#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN                COM_OFF(0x30)
+#define QSERDES_COM_PLL_CP_SETI                        COM_OFF(0x34)
+#define QSERDES_COM_PLL_IP_SETP                        COM_OFF(0x38)
+#define QSERDES_COM_PLL_CP_SETP                        COM_OFF(0x3C)
+#define QSERDES_COM_SYSCLK_EN_SEL_TXBAND       COM_OFF(0x48)
+#define QSERDES_COM_RESETSM_CNTRL              COM_OFF(0x4C)
+#define QSERDES_COM_RESETSM_CNTRL2             COM_OFF(0x50)
+#define QSERDES_COM_PLLLOCK_CMP1               COM_OFF(0x90)
+#define QSERDES_COM_PLLLOCK_CMP2               COM_OFF(0x94)
+#define QSERDES_COM_PLLLOCK_CMP3               COM_OFF(0x98)
+#define QSERDES_COM_PLLLOCK_CMP_EN             COM_OFF(0x9C)
+#define QSERDES_COM_BGTC                       COM_OFF(0xA0)
+#define QSERDES_COM_DEC_START1                 COM_OFF(0xAC)
+#define QSERDES_COM_PLL_AMP_OS                 COM_OFF(0xB0)
+#define QSERDES_COM_RES_CODE_UP_OFFSET         COM_OFF(0xD8)
+#define QSERDES_COM_RES_CODE_DN_OFFSET         COM_OFF(0xDC)
+#define QSERDES_COM_DIV_FRAC_START1            COM_OFF(0x100)
+#define QSERDES_COM_DIV_FRAC_START2            COM_OFF(0x104)
+#define QSERDES_COM_DIV_FRAC_START3            COM_OFF(0x108)
+#define QSERDES_COM_DEC_START2                 COM_OFF(0x10C)
+#define QSERDES_COM_PLL_RXTXEPCLK_EN           COM_OFF(0x110)
+#define QSERDES_COM_PLL_CRCTRL                 COM_OFF(0x114)
+#define QSERDES_COM_PLL_CLKEPDIV               COM_OFF(0x118)
+
+/* TX LANE n (0, 1) registers */
+#define QSERDES_TX_EMP_POST1_LVL(n)            TX_OFF(n, 0x08)
+#define QSERDES_TX_DRV_LVL(n)                  TX_OFF(n, 0x0C)
+#define QSERDES_TX_LANE_MODE(n)                        TX_OFF(n, 0x54)
+
+/* RX LANE n (0, 1) registers */
+#define QSERDES_RX_CDR_CONTROL1(n)             RX_OFF(n, 0x0)
+#define QSERDES_RX_CDR_CONTROL_HALF(n)         RX_OFF(n, 0x8)
+#define QSERDES_RX_RX_EQ_GAIN1_LSB(n)          RX_OFF(n, 0xA8)
+#define QSERDES_RX_RX_EQ_GAIN1_MSB(n)          RX_OFF(n, 0xAC)
+#define QSERDES_RX_RX_EQ_GAIN2_LSB(n)          RX_OFF(n, 0xB0)
+#define QSERDES_RX_RX_EQ_GAIN2_MSB(n)          RX_OFF(n, 0xB4)
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(n)    RX_OFF(n, 0xBC)
+#define QSERDES_RX_CDR_CONTROL_QUARTER(n)      RX_OFF(n, 0xC)
+#define QSERDES_RX_SIGDET_CNTRL(n)             RX_OFF(n, 0x100)
+
+/* UFS PHY registers */
+#define UFS_PHY_PHY_START                      PHY_OFF(0x00)
+#define UFS_PHY_POWER_DOWN_CONTROL             PHY_OFF(0x4)
+#define UFS_PHY_TX_LANE_ENABLE                 PHY_OFF(0x44)
+#define UFS_PHY_PWM_G1_CLK_DIVIDER             PHY_OFF(0x08)
+#define UFS_PHY_PWM_G2_CLK_DIVIDER             PHY_OFF(0x0C)
+#define UFS_PHY_PWM_G3_CLK_DIVIDER             PHY_OFF(0x10)
+#define UFS_PHY_PWM_G4_CLK_DIVIDER             PHY_OFF(0x14)
+#define UFS_PHY_CORECLK_PWM_G1_CLK_DIVIDER     PHY_OFF(0x34)
+#define UFS_PHY_CORECLK_PWM_G2_CLK_DIVIDER     PHY_OFF(0x38)
+#define UFS_PHY_CORECLK_PWM_G3_CLK_DIVIDER     PHY_OFF(0x3C)
+#define UFS_PHY_CORECLK_PWM_G4_CLK_DIVIDER     PHY_OFF(0x40)
+#define UFS_PHY_OMC_STATUS_RDVAL               PHY_OFF(0x68)
+#define UFS_PHY_LINE_RESET_TIME                        PHY_OFF(0x28)
+#define UFS_PHY_LINE_RESET_GRANULARITY         PHY_OFF(0x2C)
+#define UFS_PHY_TSYNC_RSYNC_CNTL               PHY_OFF(0x48)
+#define UFS_PHY_PLL_CNTL                       PHY_OFF(0x50)
+#define UFS_PHY_TX_LARGE_AMP_DRV_LVL           PHY_OFF(0x54)
+#define UFS_PHY_TX_SMALL_AMP_DRV_LVL           PHY_OFF(0x5C)
+#define UFS_PHY_TX_LARGE_AMP_POST_EMP_LVL      PHY_OFF(0x58)
+#define UFS_PHY_TX_SMALL_AMP_POST_EMP_LVL      PHY_OFF(0x60)
+#define UFS_PHY_CFG_CHANGE_CNT_VAL             PHY_OFF(0x64)
+#define UFS_PHY_RX_SYNC_WAIT_TIME              PHY_OFF(0x6C)
+#define UFS_PHY_TX_MIN_SLEEP_NOCONFIG_TIME_CAPABILITY  PHY_OFF(0xB4)
+#define UFS_PHY_RX_MIN_SLEEP_NOCONFIG_TIME_CAPABILITY  PHY_OFF(0xE0)
+#define UFS_PHY_TX_MIN_STALL_NOCONFIG_TIME_CAPABILITY  PHY_OFF(0xB8)
+#define UFS_PHY_RX_MIN_STALL_NOCONFIG_TIME_CAPABILITY  PHY_OFF(0xE4)
+#define UFS_PHY_TX_MIN_SAVE_CONFIG_TIME_CAPABILITY     PHY_OFF(0xBC)
+#define UFS_PHY_RX_MIN_SAVE_CONFIG_TIME_CAPABILITY     PHY_OFF(0xE8)
+#define UFS_PHY_RX_PWM_BURST_CLOSURE_LENGTH_CAPABILITY PHY_OFF(0xFC)
+#define UFS_PHY_RX_MIN_ACTIVATETIME_CAPABILITY         PHY_OFF(0x100)
+#define UFS_PHY_RX_SIGDET_CTRL3                                PHY_OFF(0x14c)
+#define UFS_PHY_RMMI_ATTR_CTRL                 PHY_OFF(0x160)
+#define UFS_PHY_RMMI_RX_CFGUPDT_L1     (1 << 7)
+#define UFS_PHY_RMMI_TX_CFGUPDT_L1     (1 << 6)
+#define UFS_PHY_RMMI_CFGWR_L1          (1 << 5)
+#define UFS_PHY_RMMI_CFGRD_L1          (1 << 4)
+#define UFS_PHY_RMMI_RX_CFGUPDT_L0     (1 << 3)
+#define UFS_PHY_RMMI_TX_CFGUPDT_L0     (1 << 2)
+#define UFS_PHY_RMMI_CFGWR_L0          (1 << 1)
+#define UFS_PHY_RMMI_CFGRD_L0          (1 << 0)
+#define UFS_PHY_RMMI_ATTRID                    PHY_OFF(0x164)
+#define UFS_PHY_RMMI_ATTRWRVAL                 PHY_OFF(0x168)
+#define UFS_PHY_RMMI_ATTRRDVAL_L0_STATUS       PHY_OFF(0x16C)
+#define UFS_PHY_RMMI_ATTRRDVAL_L1_STATUS       PHY_OFF(0x170)
+#define UFS_PHY_PCS_READY_STATUS               PHY_OFF(0x174)
+
+#define UFS_PHY_TX_LANE_ENABLE_MASK            0x3
+
+/*
+ * This structure represents the 20nm specific phy.
+ * common_cfg MUST remain the first field in this structure
+ * in case extra fields are added. This way, when calling
+ * get_ufs_qcom_phy() of generic phy, we can extract the
+ * common phy structure (struct ufs_qcom_phy) out of it
+ * regardless of the relevant specific phy.
+ */
+struct ufs_qcom_phy_qmp_20nm {
+       struct ufs_qcom_phy common_cfg;
+};
+
+static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_1_2_0[] = {
+       UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01),
+       UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL3, 0x0D),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_VCOTAIL_EN, 0xe1),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CRCTRL, 0xcc),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL_TXBAND, 0x08),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CLKEPDIV, 0x03),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RXTXEPCLK_EN, 0x10),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x82),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START2, 0x03),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1, 0x80),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2, 0x80),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3, 0x40),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x19),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP3, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP_EN, 0x03),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x90),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL2, 0x03),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(0), 0xf2),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(0), 0x0c),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(0), 0x12),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(1), 0xf2),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(1), 0x0c),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(1), 0x12),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(0), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(0), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(0), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(0), 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(1), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(1), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(1), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(1), 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETI, 0x3f),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETP, 0x1b),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETP, 0x0f),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETI, 0x01),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_EMP_POST1_LVL(0), 0x2F),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_DRV_LVL(0), 0x20),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_EMP_POST1_LVL(1), 0x2F),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_DRV_LVL(1), 0x20),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(0), 0x68),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(1), 0x68),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(1), 0xdc),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(0), 0xdc),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3),
+};
+
+static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_1_3_0[] = {
+       UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01),
+       UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL3, 0x0D),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_VCOTAIL_EN, 0xe1),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CRCTRL, 0xcc),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL_TXBAND, 0x08),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CLKEPDIV, 0x03),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RXTXEPCLK_EN, 0x10),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x82),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START2, 0x03),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1, 0x80),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2, 0x80),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3, 0x40),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x19),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP3, 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP_EN, 0x03),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x90),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL2, 0x03),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(0), 0xf2),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(0), 0x0c),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(0), 0x12),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(1), 0xf2),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(1), 0x0c),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(1), 0x12),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(0), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(0), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(0), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(0), 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(1), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(1), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(1), 0xff),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(1), 0x00),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETI, 0x2b),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETP, 0x38),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETP, 0x3c),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RES_CODE_UP_OFFSET, 0x02),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RES_CODE_DN_OFFSET, 0x02),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETI, 0x01),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CNTRL, 0x40),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(0), 0x68),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(1), 0x68),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(1), 0xdc),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(0), 0xdc),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3),
+};
+
+static struct ufs_qcom_phy_calibration phy_cal_table_rate_B[] = {
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x98),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0x65),
+       UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x1e),
+};
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-ufs.c b/drivers/phy/qualcomm/phy-qcom-ufs.c
new file mode 100644 (file)
index 0000000..43865ef
--- /dev/null
@@ -0,0 +1,691 @@
+/*
+ * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "phy-qcom-ufs-i.h"
+
+#define MAX_PROP_NAME              32
+#define VDDA_PHY_MIN_UV            1000000
+#define VDDA_PHY_MAX_UV            1000000
+#define VDDA_PLL_MIN_UV            1800000
+#define VDDA_PLL_MAX_UV            1800000
+#define VDDP_REF_CLK_MIN_UV        1200000
+#define VDDP_REF_CLK_MAX_UV        1200000
+
+int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
+                          struct ufs_qcom_phy_calibration *tbl_A,
+                          int tbl_size_A,
+                          struct ufs_qcom_phy_calibration *tbl_B,
+                          int tbl_size_B, bool is_rate_B)
+{
+       int i;
+       int ret = 0;
+
+       if (!tbl_A) {
+               dev_err(ufs_qcom_phy->dev, "%s: tbl_A is NULL", __func__);
+               ret = EINVAL;
+               goto out;
+       }
+
+       for (i = 0; i < tbl_size_A; i++)
+               writel_relaxed(tbl_A[i].cfg_value,
+                              ufs_qcom_phy->mmio + tbl_A[i].reg_offset);
+
+       /*
+        * In case we would like to work in rate B, we need
+        * to override a registers that were configured in rate A table
+        * with registers of rate B table.
+        * table.
+        */
+       if (is_rate_B) {
+               if (!tbl_B) {
+                       dev_err(ufs_qcom_phy->dev, "%s: tbl_B is NULL",
+                               __func__);
+                       ret = EINVAL;
+                       goto out;
+               }
+
+               for (i = 0; i < tbl_size_B; i++)
+                       writel_relaxed(tbl_B[i].cfg_value,
+                               ufs_qcom_phy->mmio + tbl_B[i].reg_offset);
+       }
+
+       /* flush buffered writes */
+       mb();
+
+out:
+       return ret;
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate);
+
+/*
+ * This assumes the embedded phy structure inside generic_phy is of type
+ * struct ufs_qcom_phy. In order to function properly it's crucial
+ * to keep the embedded struct "struct ufs_qcom_phy common_cfg"
+ * as the first inside generic_phy.
+ */
+struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy)
+{
+       return (struct ufs_qcom_phy *)phy_get_drvdata(generic_phy);
+}
+EXPORT_SYMBOL_GPL(get_ufs_qcom_phy);
+
+static
+int ufs_qcom_phy_base_init(struct platform_device *pdev,
+                          struct ufs_qcom_phy *phy_common)
+{
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int err = 0;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_mem");
+       phy_common->mmio = devm_ioremap_resource(dev, res);
+       if (IS_ERR((void const *)phy_common->mmio)) {
+               err = PTR_ERR((void const *)phy_common->mmio);
+               phy_common->mmio = NULL;
+               dev_err(dev, "%s: ioremap for phy_mem resource failed %d\n",
+                       __func__, err);
+               return err;
+       }
+
+       /* "dev_ref_clk_ctrl_mem" is optional resource */
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                          "dev_ref_clk_ctrl_mem");
+       phy_common->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res);
+       if (IS_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio))
+               phy_common->dev_ref_clk_ctrl_mmio = NULL;
+
+       return 0;
+}
+
+struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
+                               struct ufs_qcom_phy *common_cfg,
+                               const struct phy_ops *ufs_qcom_phy_gen_ops,
+                               struct ufs_qcom_phy_specific_ops *phy_spec_ops)
+{
+       int err;
+       struct device *dev = &pdev->dev;
+       struct phy *generic_phy = NULL;
+       struct phy_provider *phy_provider;
+
+       err = ufs_qcom_phy_base_init(pdev, common_cfg);
+       if (err) {
+               dev_err(dev, "%s: phy base init failed %d\n", __func__, err);
+               goto out;
+       }
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(phy_provider)) {
+               err = PTR_ERR(phy_provider);
+               dev_err(dev, "%s: failed to register phy %d\n", __func__, err);
+               goto out;
+       }
+
+       generic_phy = devm_phy_create(dev, NULL, ufs_qcom_phy_gen_ops);
+       if (IS_ERR(generic_phy)) {
+               err =  PTR_ERR(generic_phy);
+               dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
+               generic_phy = NULL;
+               goto out;
+       }
+
+       common_cfg->phy_spec_ops = phy_spec_ops;
+       common_cfg->dev = dev;
+
+out:
+       return generic_phy;
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe);
+
+static int __ufs_qcom_phy_clk_get(struct device *dev,
+                        const char *name, struct clk **clk_out, bool err_print)
+{
+       struct clk *clk;
+       int err = 0;
+
+       clk = devm_clk_get(dev, name);
+       if (IS_ERR(clk)) {
+               err = PTR_ERR(clk);
+               if (err_print)
+                       dev_err(dev, "failed to get %s err %d", name, err);
+       } else {
+               *clk_out = clk;
+       }
+
+       return err;
+}
+
+static int ufs_qcom_phy_clk_get(struct device *dev,
+                        const char *name, struct clk **clk_out)
+{
+       return __ufs_qcom_phy_clk_get(dev, name, clk_out, true);
+}
+
+int ufs_qcom_phy_init_clks(struct ufs_qcom_phy *phy_common)
+{
+       int err;
+
+       if (of_device_is_compatible(phy_common->dev->of_node,
+                               "qcom,msm8996-ufs-phy-qmp-14nm"))
+               goto skip_txrx_clk;
+
+       err = ufs_qcom_phy_clk_get(phy_common->dev, "tx_iface_clk",
+                                  &phy_common->tx_iface_clk);
+       if (err)
+               goto out;
+
+       err = ufs_qcom_phy_clk_get(phy_common->dev, "rx_iface_clk",
+                                  &phy_common->rx_iface_clk);
+       if (err)
+               goto out;
+
+skip_txrx_clk:
+       err = ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk_src",
+                                  &phy_common->ref_clk_src);
+       if (err)
+               goto out;
+
+       /*
+        * "ref_clk_parent" is optional hence don't abort init if it's not
+        * found.
+        */
+       __ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk_parent",
+                                  &phy_common->ref_clk_parent, false);
+
+       err = ufs_qcom_phy_clk_get(phy_common->dev, "ref_clk",
+                                  &phy_common->ref_clk);
+
+out:
+       return err;
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_clks);
+
+static int ufs_qcom_phy_init_vreg(struct device *dev,
+                                 struct ufs_qcom_phy_vreg *vreg,
+                                 const char *name)
+{
+       int err = 0;
+
+       char prop_name[MAX_PROP_NAME];
+
+       vreg->name = name;
+       vreg->reg = devm_regulator_get(dev, name);
+       if (IS_ERR(vreg->reg)) {
+               err = PTR_ERR(vreg->reg);
+               dev_err(dev, "failed to get %s, %d\n", name, err);
+               goto out;
+       }
+
+       if (dev->of_node) {
+               snprintf(prop_name, MAX_PROP_NAME, "%s-max-microamp", name);
+               err = of_property_read_u32(dev->of_node,
+                                       prop_name, &vreg->max_uA);
+               if (err && err != -EINVAL) {
+                       dev_err(dev, "%s: failed to read %s\n",
+                                       __func__, prop_name);
+                       goto out;
+               } else if (err == -EINVAL || !vreg->max_uA) {
+                       if (regulator_count_voltages(vreg->reg) > 0) {
+                               dev_err(dev, "%s: %s is mandatory\n",
+                                               __func__, prop_name);
+                               goto out;
+                       }
+                       err = 0;
+               }
+       }
+
+       if (!strcmp(name, "vdda-pll")) {
+               vreg->max_uV = VDDA_PLL_MAX_UV;
+               vreg->min_uV = VDDA_PLL_MIN_UV;
+       } else if (!strcmp(name, "vdda-phy")) {
+               vreg->max_uV = VDDA_PHY_MAX_UV;
+               vreg->min_uV = VDDA_PHY_MIN_UV;
+       } else if (!strcmp(name, "vddp-ref-clk")) {
+               vreg->max_uV = VDDP_REF_CLK_MAX_UV;
+               vreg->min_uV = VDDP_REF_CLK_MIN_UV;
+       }
+
+out:
+       return err;
+}
+
+int ufs_qcom_phy_init_vregulators(struct ufs_qcom_phy *phy_common)
+{
+       int err;
+
+       err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_pll,
+               "vdda-pll");
+       if (err)
+               goto out;
+
+       err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vdda_phy,
+               "vdda-phy");
+
+       if (err)
+               goto out;
+
+       err = ufs_qcom_phy_init_vreg(phy_common->dev, &phy_common->vddp_ref_clk,
+                                    "vddp-ref-clk");
+
+out:
+       return err;
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators);
+
+static int ufs_qcom_phy_cfg_vreg(struct device *dev,
+                         struct ufs_qcom_phy_vreg *vreg, bool on)
+{
+       int ret = 0;
+       struct regulator *reg = vreg->reg;
+       const char *name = vreg->name;
+       int min_uV;
+       int uA_load;
+
+       if (regulator_count_voltages(reg) > 0) {
+               min_uV = on ? vreg->min_uV : 0;
+               ret = regulator_set_voltage(reg, min_uV, vreg->max_uV);
+               if (ret) {
+                       dev_err(dev, "%s: %s set voltage failed, err=%d\n",
+                                       __func__, name, ret);
+                       goto out;
+               }
+               uA_load = on ? vreg->max_uA : 0;
+               ret = regulator_set_load(reg, uA_load);
+               if (ret >= 0) {
+                       /*
+                        * regulator_set_load() returns new regulator
+                        * mode upon success.
+                        */
+                       ret = 0;
+               } else {
+                       dev_err(dev, "%s: %s set optimum mode(uA_load=%d) failed, err=%d\n",
+                                       __func__, name, uA_load, ret);
+                       goto out;
+               }
+       }
+out:
+       return ret;
+}
+
+static int ufs_qcom_phy_enable_vreg(struct device *dev,
+                            struct ufs_qcom_phy_vreg *vreg)
+{
+       int ret = 0;
+
+       if (!vreg || vreg->enabled)
+               goto out;
+
+       ret = ufs_qcom_phy_cfg_vreg(dev, vreg, true);
+       if (ret) {
+               dev_err(dev, "%s: ufs_qcom_phy_cfg_vreg() failed, err=%d\n",
+                       __func__, ret);
+               goto out;
+       }
+
+       ret = regulator_enable(vreg->reg);
+       if (ret) {
+               dev_err(dev, "%s: enable failed, err=%d\n",
+                               __func__, ret);
+               goto out;
+       }
+
+       vreg->enabled = true;
+out:
+       return ret;
+}
+
+static int ufs_qcom_phy_enable_ref_clk(struct ufs_qcom_phy *phy)
+{
+       int ret = 0;
+
+       if (phy->is_ref_clk_enabled)
+               goto out;
+
+       /*
+        * reference clock is propagated in a daisy-chained manner from
+        * source to phy, so ungate them at each stage.
+        */
+       ret = clk_prepare_enable(phy->ref_clk_src);
+       if (ret) {
+               dev_err(phy->dev, "%s: ref_clk_src enable failed %d\n",
+                               __func__, ret);
+               goto out;
+       }
+
+       /*
+        * "ref_clk_parent" is optional clock hence make sure that clk reference
+        * is available before trying to enable the clock.
+        */
+       if (phy->ref_clk_parent) {
+               ret = clk_prepare_enable(phy->ref_clk_parent);
+               if (ret) {
+                       dev_err(phy->dev, "%s: ref_clk_parent enable failed %d\n",
+                                       __func__, ret);
+                       goto out_disable_src;
+               }
+       }
+
+       ret = clk_prepare_enable(phy->ref_clk);
+       if (ret) {
+               dev_err(phy->dev, "%s: ref_clk enable failed %d\n",
+                               __func__, ret);
+               goto out_disable_parent;
+       }
+
+       phy->is_ref_clk_enabled = true;
+       goto out;
+
+out_disable_parent:
+       if (phy->ref_clk_parent)
+               clk_disable_unprepare(phy->ref_clk_parent);
+out_disable_src:
+       clk_disable_unprepare(phy->ref_clk_src);
+out:
+       return ret;
+}
+
+static int ufs_qcom_phy_disable_vreg(struct device *dev,
+                             struct ufs_qcom_phy_vreg *vreg)
+{
+       int ret = 0;
+
+       if (!vreg || !vreg->enabled)
+               goto out;
+
+       ret = regulator_disable(vreg->reg);
+
+       if (!ret) {
+               /* ignore errors on applying disable config */
+               ufs_qcom_phy_cfg_vreg(dev, vreg, false);
+               vreg->enabled = false;
+       } else {
+               dev_err(dev, "%s: %s disable failed, err=%d\n",
+                               __func__, vreg->name, ret);
+       }
+out:
+       return ret;
+}
+
+static void ufs_qcom_phy_disable_ref_clk(struct ufs_qcom_phy *phy)
+{
+       if (phy->is_ref_clk_enabled) {
+               clk_disable_unprepare(phy->ref_clk);
+               /*
+                * "ref_clk_parent" is optional clock hence make sure that clk
+                * reference is available before trying to disable the clock.
+                */
+               if (phy->ref_clk_parent)
+                       clk_disable_unprepare(phy->ref_clk_parent);
+               clk_disable_unprepare(phy->ref_clk_src);
+               phy->is_ref_clk_enabled = false;
+       }
+}
+
+#define UFS_REF_CLK_EN (1 << 5)
+
+static void ufs_qcom_phy_dev_ref_clk_ctrl(struct phy *generic_phy, bool enable)
+{
+       struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy);
+
+       if (phy->dev_ref_clk_ctrl_mmio &&
+           (enable ^ phy->is_dev_ref_clk_enabled)) {
+               u32 temp = readl_relaxed(phy->dev_ref_clk_ctrl_mmio);
+
+               if (enable)
+                       temp |= UFS_REF_CLK_EN;
+               else
+                       temp &= ~UFS_REF_CLK_EN;
+
+               /*
+                * If we are here to disable this clock immediately after
+                * entering into hibern8, we need to make sure that device
+                * ref_clk is active atleast 1us after the hibern8 enter.
+                */
+               if (!enable)
+                       udelay(1);
+
+               writel_relaxed(temp, phy->dev_ref_clk_ctrl_mmio);
+               /* ensure that ref_clk is enabled/disabled before we return */
+               wmb();
+               /*
+                * If we call hibern8 exit after this, we need to make sure that
+                * device ref_clk is stable for atleast 1us before the hibern8
+                * exit command.
+                */
+               if (enable)
+                       udelay(1);
+
+               phy->is_dev_ref_clk_enabled = enable;
+       }
+}
+
+void ufs_qcom_phy_enable_dev_ref_clk(struct phy *generic_phy)
+{
+       ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, true);
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_dev_ref_clk);
+
+void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy)
+{
+       ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, false);
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_dev_ref_clk);
+
+/* Turn ON M-PHY RMMI interface clocks */
+static int ufs_qcom_phy_enable_iface_clk(struct ufs_qcom_phy *phy)
+{
+       int ret = 0;
+
+       if (phy->is_iface_clk_enabled)
+               goto out;
+
+       ret = clk_prepare_enable(phy->tx_iface_clk);
+       if (ret) {
+               dev_err(phy->dev, "%s: tx_iface_clk enable failed %d\n",
+                               __func__, ret);
+               goto out;
+       }
+       ret = clk_prepare_enable(phy->rx_iface_clk);
+       if (ret) {
+               clk_disable_unprepare(phy->tx_iface_clk);
+               dev_err(phy->dev, "%s: rx_iface_clk enable failed %d. disabling also tx_iface_clk\n",
+                               __func__, ret);
+               goto out;
+       }
+       phy->is_iface_clk_enabled = true;
+
+out:
+       return ret;
+}
+
+/* Turn OFF M-PHY RMMI interface clocks */
+void ufs_qcom_phy_disable_iface_clk(struct ufs_qcom_phy *phy)
+{
+       if (phy->is_iface_clk_enabled) {
+               clk_disable_unprepare(phy->tx_iface_clk);
+               clk_disable_unprepare(phy->rx_iface_clk);
+               phy->is_iface_clk_enabled = false;
+       }
+}
+
+int ufs_qcom_phy_start_serdes(struct phy *generic_phy)
+{
+       struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
+       int ret = 0;
+
+       if (!ufs_qcom_phy->phy_spec_ops->start_serdes) {
+               dev_err(ufs_qcom_phy->dev, "%s: start_serdes() callback is not supported\n",
+                       __func__);
+               ret = -ENOTSUPP;
+       } else {
+               ufs_qcom_phy->phy_spec_ops->start_serdes(ufs_qcom_phy);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_start_serdes);
+
+int ufs_qcom_phy_set_tx_lane_enable(struct phy *generic_phy, u32 tx_lanes)
+{
+       struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
+       int ret = 0;
+
+       if (!ufs_qcom_phy->phy_spec_ops->set_tx_lane_enable) {
+               dev_err(ufs_qcom_phy->dev, "%s: set_tx_lane_enable() callback is not supported\n",
+                       __func__);
+               ret = -ENOTSUPP;
+       } else {
+               ufs_qcom_phy->phy_spec_ops->set_tx_lane_enable(ufs_qcom_phy,
+                                                              tx_lanes);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_set_tx_lane_enable);
+
+void ufs_qcom_phy_save_controller_version(struct phy *generic_phy,
+                                         u8 major, u16 minor, u16 step)
+{
+       struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
+
+       ufs_qcom_phy->host_ctrl_rev_major = major;
+       ufs_qcom_phy->host_ctrl_rev_minor = minor;
+       ufs_qcom_phy->host_ctrl_rev_step = step;
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_save_controller_version);
+
+int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B)
+{
+       struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
+       int ret = 0;
+
+       if (!ufs_qcom_phy->phy_spec_ops->calibrate_phy) {
+               dev_err(ufs_qcom_phy->dev, "%s: calibrate_phy() callback is not supported\n",
+                       __func__);
+               ret = -ENOTSUPP;
+       } else {
+               ret = ufs_qcom_phy->phy_spec_ops->
+                               calibrate_phy(ufs_qcom_phy, is_rate_B);
+               if (ret)
+                       dev_err(ufs_qcom_phy->dev, "%s: calibrate_phy() failed %d\n",
+                               __func__, ret);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy);
+
+int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy)
+{
+       struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
+
+       if (!ufs_qcom_phy->phy_spec_ops->is_physical_coding_sublayer_ready) {
+               dev_err(ufs_qcom_phy->dev, "%s: is_physical_coding_sublayer_ready() callback is not supported\n",
+                       __func__);
+               return -ENOTSUPP;
+       }
+
+       return ufs_qcom_phy->phy_spec_ops->
+                       is_physical_coding_sublayer_ready(ufs_qcom_phy);
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_is_pcs_ready);
+
+int ufs_qcom_phy_power_on(struct phy *generic_phy)
+{
+       struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
+       struct device *dev = phy_common->dev;
+       int err;
+
+       if (phy_common->is_powered_on)
+               return 0;
+
+       err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_phy);
+       if (err) {
+               dev_err(dev, "%s enable vdda_phy failed, err=%d\n",
+                       __func__, err);
+               goto out;
+       }
+
+       phy_common->phy_spec_ops->power_control(phy_common, true);
+
+       /* vdda_pll also enables ref clock LDOs so enable it first */
+       err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_pll);
+       if (err) {
+               dev_err(dev, "%s enable vdda_pll failed, err=%d\n",
+                       __func__, err);
+               goto out_disable_phy;
+       }
+
+       err = ufs_qcom_phy_enable_iface_clk(phy_common);
+       if (err) {
+               dev_err(dev, "%s enable phy iface clock failed, err=%d\n",
+                       __func__, err);
+               goto out_disable_pll;
+       }
+
+       err = ufs_qcom_phy_enable_ref_clk(phy_common);
+       if (err) {
+               dev_err(dev, "%s enable phy ref clock failed, err=%d\n",
+                       __func__, err);
+               goto out_disable_iface_clk;
+       }
+
+       /* enable device PHY ref_clk pad rail */
+       if (phy_common->vddp_ref_clk.reg) {
+               err = ufs_qcom_phy_enable_vreg(dev,
+                                              &phy_common->vddp_ref_clk);
+               if (err) {
+                       dev_err(dev, "%s enable vddp_ref_clk failed, err=%d\n",
+                               __func__, err);
+                       goto out_disable_ref_clk;
+               }
+       }
+
+       phy_common->is_powered_on = true;
+       goto out;
+
+out_disable_ref_clk:
+       ufs_qcom_phy_disable_ref_clk(phy_common);
+out_disable_iface_clk:
+       ufs_qcom_phy_disable_iface_clk(phy_common);
+out_disable_pll:
+       ufs_qcom_phy_disable_vreg(dev, &phy_common->vdda_pll);
+out_disable_phy:
+       ufs_qcom_phy_disable_vreg(dev, &phy_common->vdda_phy);
+out:
+       return err;
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_on);
+
+int ufs_qcom_phy_power_off(struct phy *generic_phy)
+{
+       struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
+
+       if (!phy_common->is_powered_on)
+               return 0;
+
+       phy_common->phy_spec_ops->power_control(phy_common, false);
+
+       if (phy_common->vddp_ref_clk.reg)
+               ufs_qcom_phy_disable_vreg(phy_common->dev,
+                                         &phy_common->vddp_ref_clk);
+       ufs_qcom_phy_disable_ref_clk(phy_common);
+       ufs_qcom_phy_disable_iface_clk(phy_common);
+
+       ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_pll);
+       ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_phy);
+       phy_common->is_powered_on = false;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off);
diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c
new file mode 100644 (file)
index 0000000..4b20abc
--- /dev/null
@@ -0,0 +1,295 @@
+/**
+ * Copyright (C) 2016 Linaro Ltd
+ *
+ * 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/module.h>
+#include <linux/ulpi/driver.h>
+#include <linux/ulpi/regs.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/reset.h>
+#include <linux/extcon.h>
+#include <linux/notifier.h>
+
+#define ULPI_PWR_CLK_MNG_REG           0x88
+# define ULPI_PWR_OTG_COMP_DISABLE     BIT(0)
+
+#define ULPI_MISC_A                    0x96
+# define ULPI_MISC_A_VBUSVLDEXTSEL     BIT(1)
+# define ULPI_MISC_A_VBUSVLDEXT                BIT(0)
+
+
+struct ulpi_seq {
+       u8 addr;
+       u8 val;
+};
+
+struct qcom_usb_hs_phy {
+       struct ulpi *ulpi;
+       struct phy *phy;
+       struct clk *ref_clk;
+       struct clk *sleep_clk;
+       struct regulator *v1p8;
+       struct regulator *v3p3;
+       struct reset_control *reset;
+       struct ulpi_seq *init_seq;
+       struct extcon_dev *vbus_edev;
+       struct notifier_block vbus_notify;
+};
+
+static int qcom_usb_hs_phy_set_mode(struct phy *phy, enum phy_mode mode)
+{
+       struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
+       u8 addr;
+       int ret;
+
+       if (!uphy->vbus_edev) {
+               u8 val = 0;
+
+               switch (mode) {
+               case PHY_MODE_USB_OTG:
+               case PHY_MODE_USB_HOST:
+                       val |= ULPI_INT_IDGRD;
+               case PHY_MODE_USB_DEVICE:
+                       val |= ULPI_INT_SESS_VALID;
+               default:
+                       break;
+               }
+
+               ret = ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_RISE, val);
+               if (ret)
+                       return ret;
+               ret = ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_FALL, val);
+       } else {
+               switch (mode) {
+               case PHY_MODE_USB_OTG:
+               case PHY_MODE_USB_DEVICE:
+                       addr = ULPI_SET(ULPI_MISC_A);
+                       break;
+               case PHY_MODE_USB_HOST:
+                       addr = ULPI_CLR(ULPI_MISC_A);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               ret = ulpi_write(uphy->ulpi, ULPI_SET(ULPI_PWR_CLK_MNG_REG),
+                                ULPI_PWR_OTG_COMP_DISABLE);
+               if (ret)
+                       return ret;
+               ret = ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXTSEL);
+       }
+
+       return ret;
+}
+
+static int
+qcom_usb_hs_phy_vbus_notifier(struct notifier_block *nb, unsigned long event,
+                             void *ptr)
+{
+       struct qcom_usb_hs_phy *uphy;
+       u8 addr;
+
+       uphy = container_of(nb, struct qcom_usb_hs_phy, vbus_notify);
+
+       if (event)
+               addr = ULPI_SET(ULPI_MISC_A);
+       else
+               addr = ULPI_CLR(ULPI_MISC_A);
+
+       return ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXT);
+}
+
+static int qcom_usb_hs_phy_power_on(struct phy *phy)
+{
+       struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
+       struct ulpi *ulpi = uphy->ulpi;
+       const struct ulpi_seq *seq;
+       int ret, state;
+
+       ret = clk_prepare_enable(uphy->ref_clk);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(uphy->sleep_clk);
+       if (ret)
+               goto err_sleep;
+
+       ret = regulator_set_load(uphy->v1p8, 50000);
+       if (ret < 0)
+               goto err_1p8;
+
+       ret = regulator_enable(uphy->v1p8);
+       if (ret)
+               goto err_1p8;
+
+       ret = regulator_set_voltage_triplet(uphy->v3p3, 3050000, 3300000,
+                                           3300000);
+       if (ret)
+               goto err_3p3;
+
+       ret = regulator_set_load(uphy->v3p3, 50000);
+       if (ret < 0)
+               goto err_3p3;
+
+       ret = regulator_enable(uphy->v3p3);
+       if (ret)
+               goto err_3p3;
+
+       for (seq = uphy->init_seq; seq->addr; seq++) {
+               ret = ulpi_write(ulpi, ULPI_EXT_VENDOR_SPECIFIC + seq->addr,
+                                seq->val);
+               if (ret)
+                       goto err_ulpi;
+       }
+
+       if (uphy->reset) {
+               ret = reset_control_reset(uphy->reset);
+               if (ret)
+                       goto err_ulpi;
+       }
+
+       if (uphy->vbus_edev) {
+               state = extcon_get_cable_state_(uphy->vbus_edev, EXTCON_USB);
+               /* setup initial state */
+               qcom_usb_hs_phy_vbus_notifier(&uphy->vbus_notify, state,
+                                             uphy->vbus_edev);
+               ret = extcon_register_notifier(uphy->vbus_edev, EXTCON_USB,
+                               &uphy->vbus_notify);
+               if (ret)
+                       goto err_ulpi;
+       }
+
+       return 0;
+err_ulpi:
+       regulator_disable(uphy->v3p3);
+err_3p3:
+       regulator_disable(uphy->v1p8);
+err_1p8:
+       clk_disable_unprepare(uphy->sleep_clk);
+err_sleep:
+       clk_disable_unprepare(uphy->ref_clk);
+       return ret;
+}
+
+static int qcom_usb_hs_phy_power_off(struct phy *phy)
+{
+       int ret;
+       struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
+
+       if (uphy->vbus_edev) {
+               ret = extcon_unregister_notifier(uphy->vbus_edev, EXTCON_USB,
+                                                &uphy->vbus_notify);
+               if (ret)
+                       return ret;
+       }
+
+       regulator_disable(uphy->v3p3);
+       regulator_disable(uphy->v1p8);
+       clk_disable_unprepare(uphy->sleep_clk);
+       clk_disable_unprepare(uphy->ref_clk);
+
+       return 0;
+}
+
+static const struct phy_ops qcom_usb_hs_phy_ops = {
+       .power_on = qcom_usb_hs_phy_power_on,
+       .power_off = qcom_usb_hs_phy_power_off,
+       .set_mode = qcom_usb_hs_phy_set_mode,
+       .owner = THIS_MODULE,
+};
+
+static int qcom_usb_hs_phy_probe(struct ulpi *ulpi)
+{
+       struct qcom_usb_hs_phy *uphy;
+       struct phy_provider *p;
+       struct clk *clk;
+       struct regulator *reg;
+       struct reset_control *reset;
+       int size;
+       int ret;
+
+       uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);
+       if (!uphy)
+               return -ENOMEM;
+       ulpi_set_drvdata(ulpi, uphy);
+       uphy->ulpi = ulpi;
+
+       size = of_property_count_u8_elems(ulpi->dev.of_node, "qcom,init-seq");
+       if (size < 0)
+               size = 0;
+       uphy->init_seq = devm_kmalloc_array(&ulpi->dev, (size / 2) + 1,
+                                          sizeof(*uphy->init_seq), GFP_KERNEL);
+       if (!uphy->init_seq)
+               return -ENOMEM;
+       ret = of_property_read_u8_array(ulpi->dev.of_node, "qcom,init-seq",
+                                       (u8 *)uphy->init_seq, size);
+       if (ret && size)
+               return ret;
+       /* NUL terminate */
+       uphy->init_seq[size / 2].addr = uphy->init_seq[size / 2].val = 0;
+
+       uphy->ref_clk = clk = devm_clk_get(&ulpi->dev, "ref");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       uphy->sleep_clk = clk = devm_clk_get(&ulpi->dev, "sleep");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       uphy->v1p8 = reg = devm_regulator_get(&ulpi->dev, "v1p8");
+       if (IS_ERR(reg))
+               return PTR_ERR(reg);
+
+       uphy->v3p3 = reg = devm_regulator_get(&ulpi->dev, "v3p3");
+       if (IS_ERR(reg))
+               return PTR_ERR(reg);
+
+       uphy->reset = reset = devm_reset_control_get(&ulpi->dev, "por");
+       if (IS_ERR(reset)) {
+               if (PTR_ERR(reset) == -EPROBE_DEFER)
+                       return PTR_ERR(reset);
+               uphy->reset = NULL;
+       }
+
+       uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
+                                   &qcom_usb_hs_phy_ops);
+       if (IS_ERR(uphy->phy))
+               return PTR_ERR(uphy->phy);
+
+       uphy->vbus_edev = extcon_get_edev_by_phandle(&ulpi->dev, 0);
+       if (IS_ERR(uphy->vbus_edev)) {
+               if (PTR_ERR(uphy->vbus_edev) != -ENODEV)
+                       return PTR_ERR(uphy->vbus_edev);
+               uphy->vbus_edev = NULL;
+       }
+
+       uphy->vbus_notify.notifier_call = qcom_usb_hs_phy_vbus_notifier;
+       phy_set_drvdata(uphy->phy, uphy);
+
+       p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);
+       return PTR_ERR_OR_ZERO(p);
+}
+
+static const struct of_device_id qcom_usb_hs_phy_match[] = {
+       { .compatible = "qcom,usb-hs-phy", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, qcom_usb_hs_phy_match);
+
+static struct ulpi_driver qcom_usb_hs_phy_driver = {
+       .probe = qcom_usb_hs_phy_probe,
+       .driver = {
+               .name = "qcom_usb_hs_phy",
+               .of_match_table = qcom_usb_hs_phy_match,
+       },
+};
+module_ulpi_driver(qcom_usb_hs_phy_driver);
+
+MODULE_DESCRIPTION("Qualcomm USB HS phy");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hsic.c b/drivers/phy/qualcomm/phy-qcom-usb-hsic.c
new file mode 100644 (file)
index 0000000..c110563
--- /dev/null
@@ -0,0 +1,159 @@
+/**
+ * Copyright (C) 2016 Linaro Ltd
+ *
+ * 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/module.h>
+#include <linux/ulpi/driver.h>
+#include <linux/ulpi/regs.h>
+#include <linux/phy/phy.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/pinctrl-state.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#define ULPI_HSIC_CFG          0x30
+#define ULPI_HSIC_IO_CAL       0x33
+
+struct qcom_usb_hsic_phy {
+       struct ulpi *ulpi;
+       struct phy *phy;
+       struct pinctrl *pctl;
+       struct clk *phy_clk;
+       struct clk *cal_clk;
+       struct clk *cal_sleep_clk;
+};
+
+static int qcom_usb_hsic_phy_power_on(struct phy *phy)
+{
+       struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
+       struct ulpi *ulpi = uphy->ulpi;
+       struct pinctrl_state *pins_default;
+       int ret;
+
+       ret = clk_prepare_enable(uphy->phy_clk);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(uphy->cal_clk);
+       if (ret)
+               goto err_cal;
+
+       ret = clk_prepare_enable(uphy->cal_sleep_clk);
+       if (ret)
+               goto err_sleep;
+
+       /* Set periodic calibration interval to ~2.048sec in HSIC_IO_CAL_REG */
+       ret = ulpi_write(ulpi, ULPI_HSIC_IO_CAL, 0xff);
+       if (ret)
+               goto err_ulpi;
+
+       /* Enable periodic IO calibration in HSIC_CFG register */
+       ret = ulpi_write(ulpi, ULPI_HSIC_CFG, 0xa8);
+       if (ret)
+               goto err_ulpi;
+
+       /* Configure pins for HSIC functionality */
+       pins_default = pinctrl_lookup_state(uphy->pctl, PINCTRL_STATE_DEFAULT);
+       if (IS_ERR(pins_default))
+               return PTR_ERR(pins_default);
+
+       ret = pinctrl_select_state(uphy->pctl, pins_default);
+       if (ret)
+               goto err_ulpi;
+
+        /* Enable HSIC mode in HSIC_CFG register */
+       ret = ulpi_write(ulpi, ULPI_SET(ULPI_HSIC_CFG), 0x01);
+       if (ret)
+               goto err_ulpi;
+
+       /* Disable auto-resume */
+       ret = ulpi_write(ulpi, ULPI_CLR(ULPI_IFC_CTRL),
+                        ULPI_IFC_CTRL_AUTORESUME);
+       if (ret)
+               goto err_ulpi;
+
+       return ret;
+err_ulpi:
+       clk_disable_unprepare(uphy->cal_sleep_clk);
+err_sleep:
+       clk_disable_unprepare(uphy->cal_clk);
+err_cal:
+       clk_disable_unprepare(uphy->phy_clk);
+       return ret;
+}
+
+static int qcom_usb_hsic_phy_power_off(struct phy *phy)
+{
+       struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
+
+       clk_disable_unprepare(uphy->cal_sleep_clk);
+       clk_disable_unprepare(uphy->cal_clk);
+       clk_disable_unprepare(uphy->phy_clk);
+
+       return 0;
+}
+
+static const struct phy_ops qcom_usb_hsic_phy_ops = {
+       .power_on = qcom_usb_hsic_phy_power_on,
+       .power_off = qcom_usb_hsic_phy_power_off,
+       .owner = THIS_MODULE,
+};
+
+static int qcom_usb_hsic_phy_probe(struct ulpi *ulpi)
+{
+       struct qcom_usb_hsic_phy *uphy;
+       struct phy_provider *p;
+       struct clk *clk;
+
+       uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);
+       if (!uphy)
+               return -ENOMEM;
+       ulpi_set_drvdata(ulpi, uphy);
+
+       uphy->ulpi = ulpi;
+       uphy->pctl = devm_pinctrl_get(&ulpi->dev);
+       if (IS_ERR(uphy->pctl))
+               return PTR_ERR(uphy->pctl);
+
+       uphy->phy_clk = clk = devm_clk_get(&ulpi->dev, "phy");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       uphy->cal_clk = clk = devm_clk_get(&ulpi->dev, "cal");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       uphy->cal_sleep_clk = clk = devm_clk_get(&ulpi->dev, "cal_sleep");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
+                                   &qcom_usb_hsic_phy_ops);
+       if (IS_ERR(uphy->phy))
+               return PTR_ERR(uphy->phy);
+       phy_set_drvdata(uphy->phy, uphy);
+
+       p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);
+       return PTR_ERR_OR_ZERO(p);
+}
+
+static const struct of_device_id qcom_usb_hsic_phy_match[] = {
+       { .compatible = "qcom,usb-hsic-phy", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, qcom_usb_hsic_phy_match);
+
+static struct ulpi_driver qcom_usb_hsic_phy_driver = {
+       .probe = qcom_usb_hsic_phy_probe,
+       .driver = {
+               .name = "qcom_usb_hsic_phy",
+               .of_match_table = qcom_usb_hsic_phy_match,
+       },
+};
+module_ulpi_driver(qcom_usb_hsic_phy_driver);
+
+MODULE_DESCRIPTION("Qualcomm USB HSIC phy");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/renesas/Kconfig b/drivers/phy/renesas/Kconfig
new file mode 100644 (file)
index 0000000..432e271
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# 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.
diff --git a/drivers/phy/renesas/Makefile b/drivers/phy/renesas/Makefile
new file mode 100644 (file)
index 0000000..695241a
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_PHY_RCAR_GEN2)            += phy-rcar-gen2.o
+obj-$(CONFIG_PHY_RCAR_GEN3_USB2)       += phy-rcar-gen3-usb2.o
diff --git a/drivers/phy/renesas/phy-rcar-gen2.c b/drivers/phy/renesas/phy-rcar-gen2.c
new file mode 100644 (file)
index 0000000..97d4dd6
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ * Renesas R-Car Gen2 PHY driver
+ *
+ * Copyright (C) 2014 Renesas Solutions Corp.
+ * Copyright (C) 2014 Cogent Embedded, Inc.
+ *
+ * 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/spinlock.h>
+#include <linux/atomic.h>
+
+#define USBHS_LPSTS                    0x02
+#define USBHS_UGCTRL                   0x80
+#define USBHS_UGCTRL2                  0x84
+#define USBHS_UGSTS                    0x88    /* From technical update */
+
+/* Low Power Status register (LPSTS) */
+#define USBHS_LPSTS_SUSPM              0x4000
+
+/* USB General control register (UGCTRL) */
+#define USBHS_UGCTRL_CONNECT           0x00000004
+#define USBHS_UGCTRL_PLLRESET          0x00000001
+
+/* USB General control register 2 (UGCTRL2) */
+#define USBHS_UGCTRL2_USB2SEL          0x80000000
+#define USBHS_UGCTRL2_USB2SEL_PCI      0x00000000
+#define USBHS_UGCTRL2_USB2SEL_USB30    0x80000000
+#define USBHS_UGCTRL2_USB0SEL          0x00000030
+#define USBHS_UGCTRL2_USB0SEL_PCI      0x00000010
+#define USBHS_UGCTRL2_USB0SEL_HS_USB   0x00000030
+
+/* USB General status register (UGSTS) */
+#define USBHS_UGSTS_LOCK               0x00000100 /* From technical update */
+
+#define PHYS_PER_CHANNEL       2
+
+struct rcar_gen2_phy {
+       struct phy *phy;
+       struct rcar_gen2_channel *channel;
+       int number;
+       u32 select_value;
+};
+
+struct rcar_gen2_channel {
+       struct device_node *of_node;
+       struct rcar_gen2_phy_driver *drv;
+       struct rcar_gen2_phy phys[PHYS_PER_CHANNEL];
+       int selected_phy;
+       u32 select_mask;
+};
+
+struct rcar_gen2_phy_driver {
+       void __iomem *base;
+       struct clk *clk;
+       spinlock_t lock;
+       int num_channels;
+       struct rcar_gen2_channel *channels;
+};
+
+static int rcar_gen2_phy_init(struct phy *p)
+{
+       struct rcar_gen2_phy *phy = phy_get_drvdata(p);
+       struct rcar_gen2_channel *channel = phy->channel;
+       struct rcar_gen2_phy_driver *drv = channel->drv;
+       unsigned long flags;
+       u32 ugctrl2;
+
+       /*
+        * Try to acquire exclusive access to PHY.  The first driver calling
+        * phy_init()  on a given channel wins, and all attempts  to use another
+        * PHY on this channel will fail until phy_exit() is called by the first
+        * driver.   Achieving this with cmpxcgh() should be SMP-safe.
+        */
+       if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1)
+               return -EBUSY;
+
+       clk_prepare_enable(drv->clk);
+
+       spin_lock_irqsave(&drv->lock, flags);
+       ugctrl2 = readl(drv->base + USBHS_UGCTRL2);
+       ugctrl2 &= ~channel->select_mask;
+       ugctrl2 |= phy->select_value;
+       writel(ugctrl2, drv->base + USBHS_UGCTRL2);
+       spin_unlock_irqrestore(&drv->lock, flags);
+       return 0;
+}
+
+static int rcar_gen2_phy_exit(struct phy *p)
+{
+       struct rcar_gen2_phy *phy = phy_get_drvdata(p);
+       struct rcar_gen2_channel *channel = phy->channel;
+
+       clk_disable_unprepare(channel->drv->clk);
+
+       channel->selected_phy = -1;
+
+       return 0;
+}
+
+static int rcar_gen2_phy_power_on(struct phy *p)
+{
+       struct rcar_gen2_phy *phy = phy_get_drvdata(p);
+       struct rcar_gen2_phy_driver *drv = phy->channel->drv;
+       void __iomem *base = drv->base;
+       unsigned long flags;
+       u32 value;
+       int err = 0, i;
+
+       /* Skip if it's not USBHS */
+       if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
+               return 0;
+
+       spin_lock_irqsave(&drv->lock, flags);
+
+       /* Power on USBHS PHY */
+       value = readl(base + USBHS_UGCTRL);
+       value &= ~USBHS_UGCTRL_PLLRESET;
+       writel(value, base + USBHS_UGCTRL);
+
+       value = readw(base + USBHS_LPSTS);
+       value |= USBHS_LPSTS_SUSPM;
+       writew(value, base + USBHS_LPSTS);
+
+       for (i = 0; i < 20; i++) {
+               value = readl(base + USBHS_UGSTS);
+               if ((value & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) {
+                       value = readl(base + USBHS_UGCTRL);
+                       value |= USBHS_UGCTRL_CONNECT;
+                       writel(value, base + USBHS_UGCTRL);
+                       goto out;
+               }
+               udelay(1);
+       }
+
+       /* Timed out waiting for the PLL lock */
+       err = -ETIMEDOUT;
+
+out:
+       spin_unlock_irqrestore(&drv->lock, flags);
+
+       return err;
+}
+
+static int rcar_gen2_phy_power_off(struct phy *p)
+{
+       struct rcar_gen2_phy *phy = phy_get_drvdata(p);
+       struct rcar_gen2_phy_driver *drv = phy->channel->drv;
+       void __iomem *base = drv->base;
+       unsigned long flags;
+       u32 value;
+
+       /* Skip if it's not USBHS */
+       if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
+               return 0;
+
+       spin_lock_irqsave(&drv->lock, flags);
+
+       /* Power off USBHS PHY */
+       value = readl(base + USBHS_UGCTRL);
+       value &= ~USBHS_UGCTRL_CONNECT;
+       writel(value, base + USBHS_UGCTRL);
+
+       value = readw(base + USBHS_LPSTS);
+       value &= ~USBHS_LPSTS_SUSPM;
+       writew(value, base + USBHS_LPSTS);
+
+       value = readl(base + USBHS_UGCTRL);
+       value |= USBHS_UGCTRL_PLLRESET;
+       writel(value, base + USBHS_UGCTRL);
+
+       spin_unlock_irqrestore(&drv->lock, flags);
+
+       return 0;
+}
+
+static const struct phy_ops rcar_gen2_phy_ops = {
+       .init           = rcar_gen2_phy_init,
+       .exit           = rcar_gen2_phy_exit,
+       .power_on       = rcar_gen2_phy_power_on,
+       .power_off      = rcar_gen2_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static const struct of_device_id rcar_gen2_phy_match_table[] = {
+       { .compatible = "renesas,usb-phy-r8a7790" },
+       { .compatible = "renesas,usb-phy-r8a7791" },
+       { .compatible = "renesas,usb-phy-r8a7794" },
+       { .compatible = "renesas,rcar-gen2-usb-phy" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table);
+
+static struct phy *rcar_gen2_phy_xlate(struct device *dev,
+                                      struct of_phandle_args *args)
+{
+       struct rcar_gen2_phy_driver *drv;
+       struct device_node *np = args->np;
+       int i;
+
+       drv = dev_get_drvdata(dev);
+       if (!drv)
+               return ERR_PTR(-EINVAL);
+
+       for (i = 0; i < drv->num_channels; i++) {
+               if (np == drv->channels[i].of_node)
+                       break;
+       }
+
+       if (i >= drv->num_channels || args->args[0] >= 2)
+               return ERR_PTR(-ENODEV);
+
+       return drv->channels[i].phys[args->args[0]].phy;
+}
+
+static const u32 select_mask[] = {
+       [0]     = USBHS_UGCTRL2_USB0SEL,
+       [2]     = USBHS_UGCTRL2_USB2SEL,
+};
+
+static const u32 select_value[][PHYS_PER_CHANNEL] = {
+       [0]     = { USBHS_UGCTRL2_USB0SEL_PCI, USBHS_UGCTRL2_USB0SEL_HS_USB },
+       [2]     = { USBHS_UGCTRL2_USB2SEL_PCI, USBHS_UGCTRL2_USB2SEL_USB30 },
+};
+
+static int rcar_gen2_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct rcar_gen2_phy_driver *drv;
+       struct phy_provider *provider;
+       struct device_node *np;
+       struct resource *res;
+       void __iomem *base;
+       struct clk *clk;
+       int i = 0;
+
+       if (!dev->of_node) {
+               dev_err(dev,
+                       "This driver is required to be instantiated from device tree\n");
+               return -EINVAL;
+       }
+
+       clk = devm_clk_get(dev, "usbhs");
+       if (IS_ERR(clk)) {
+               dev_err(dev, "Can't get USBHS clock\n");
+               return PTR_ERR(clk);
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
+       if (!drv)
+               return -ENOMEM;
+
+       spin_lock_init(&drv->lock);
+
+       drv->clk = clk;
+       drv->base = base;
+
+       drv->num_channels = of_get_child_count(dev->of_node);
+       drv->channels = devm_kcalloc(dev, drv->num_channels,
+                                    sizeof(struct rcar_gen2_channel),
+                                    GFP_KERNEL);
+       if (!drv->channels)
+               return -ENOMEM;
+
+       for_each_child_of_node(dev->of_node, np) {
+               struct rcar_gen2_channel *channel = drv->channels + i;
+               u32 channel_num;
+               int error, n;
+
+               channel->of_node = np;
+               channel->drv = drv;
+               channel->selected_phy = -1;
+
+               error = of_property_read_u32(np, "reg", &channel_num);
+               if (error || channel_num > 2) {
+                       dev_err(dev, "Invalid \"reg\" property\n");
+                       return error;
+               }
+               channel->select_mask = select_mask[channel_num];
+
+               for (n = 0; n < PHYS_PER_CHANNEL; n++) {
+                       struct rcar_gen2_phy *phy = &channel->phys[n];
+
+                       phy->channel = channel;
+                       phy->number = n;
+                       phy->select_value = select_value[channel_num][n];
+
+                       phy->phy = devm_phy_create(dev, NULL,
+                                                  &rcar_gen2_phy_ops);
+                       if (IS_ERR(phy->phy)) {
+                               dev_err(dev, "Failed to create PHY\n");
+                               return PTR_ERR(phy->phy);
+                       }
+                       phy_set_drvdata(phy->phy, phy);
+               }
+
+               i++;
+       }
+
+       provider = devm_of_phy_provider_register(dev, rcar_gen2_phy_xlate);
+       if (IS_ERR(provider)) {
+               dev_err(dev, "Failed to register PHY provider\n");
+               return PTR_ERR(provider);
+       }
+
+       dev_set_drvdata(dev, drv);
+
+       return 0;
+}
+
+static struct platform_driver rcar_gen2_phy_driver = {
+       .driver = {
+               .name           = "phy_rcar_gen2",
+               .of_match_table = rcar_gen2_phy_match_table,
+       },
+       .probe  = rcar_gen2_phy_probe,
+};
+
+module_platform_driver(rcar_gen2_phy_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");
+MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
new file mode 100644 (file)
index 0000000..54c3429
--- /dev/null
@@ -0,0 +1,507 @@
+/*
+ * Renesas R-Car Gen3 for USB2.0 PHY driver
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * This is based on the phy-rcar-gen2 driver:
+ * Copyright (C) 2014 Renesas Solutions Corp.
+ * Copyright (C) 2014 Cogent Embedded, Inc.
+ *
+ * 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/extcon.h>
+#include <linux/interrupt.h>
+#include <linux/io.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/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/workqueue.h>
+
+/******* USB2.0 Host registers (original offset is +0x200) *******/
+#define USB2_INT_ENABLE                0x000
+#define USB2_USBCTR            0x00c
+#define USB2_SPD_RSM_TIMSET    0x10c
+#define USB2_OC_TIMSET         0x110
+#define USB2_COMMCTRL          0x600
+#define USB2_OBINTSTA          0x604
+#define USB2_OBINTEN           0x608
+#define USB2_VBCTRL            0x60c
+#define USB2_LINECTRL1         0x610
+#define USB2_ADPCTRL           0x630
+
+/* INT_ENABLE */
+#define USB2_INT_ENABLE_UCOM_INTEN     BIT(3)
+#define USB2_INT_ENABLE_USBH_INTB_EN   BIT(2)
+#define USB2_INT_ENABLE_USBH_INTA_EN   BIT(1)
+#define USB2_INT_ENABLE_INIT           (USB2_INT_ENABLE_UCOM_INTEN | \
+                                        USB2_INT_ENABLE_USBH_INTB_EN | \
+                                        USB2_INT_ENABLE_USBH_INTA_EN)
+
+/* USBCTR */
+#define USB2_USBCTR_DIRPD      BIT(2)
+#define USB2_USBCTR_PLL_RST    BIT(1)
+
+/* SPD_RSM_TIMSET */
+#define USB2_SPD_RSM_TIMSET_INIT       0x014e029b
+
+/* OC_TIMSET */
+#define USB2_OC_TIMSET_INIT            0x000209ab
+
+/* COMMCTRL */
+#define USB2_COMMCTRL_OTG_PERI         BIT(31) /* 1 = Peripheral mode */
+
+/* OBINTSTA and OBINTEN */
+#define USB2_OBINT_SESSVLDCHG          BIT(12)
+#define USB2_OBINT_IDDIGCHG            BIT(11)
+#define USB2_OBINT_BITS                        (USB2_OBINT_SESSVLDCHG | \
+                                        USB2_OBINT_IDDIGCHG)
+
+/* VBCTRL */
+#define USB2_VBCTRL_DRVVBUSSEL         BIT(8)
+
+/* LINECTRL1 */
+#define USB2_LINECTRL1_DPRPD_EN                BIT(19)
+#define USB2_LINECTRL1_DP_RPD          BIT(18)
+#define USB2_LINECTRL1_DMRPD_EN                BIT(17)
+#define USB2_LINECTRL1_DM_RPD          BIT(16)
+#define USB2_LINECTRL1_OPMODE_NODRV    BIT(6)
+
+/* ADPCTRL */
+#define USB2_ADPCTRL_OTGSESSVLD                BIT(20)
+#define USB2_ADPCTRL_IDDIG             BIT(19)
+#define USB2_ADPCTRL_IDPULLUP          BIT(5)  /* 1 = ID sampling is enabled */
+#define USB2_ADPCTRL_DRVVBUS           BIT(4)
+
+struct rcar_gen3_chan {
+       void __iomem *base;
+       struct extcon_dev *extcon;
+       struct phy *phy;
+       struct regulator *vbus;
+       struct work_struct work;
+       bool extcon_host;
+       bool has_otg;
+};
+
+static void rcar_gen3_phy_usb2_work(struct work_struct *work)
+{
+       struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan,
+                                                work);
+
+       if (ch->extcon_host) {
+               extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, true);
+               extcon_set_state_sync(ch->extcon, EXTCON_USB, false);
+       } else {
+               extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, false);
+               extcon_set_state_sync(ch->extcon, EXTCON_USB, true);
+       }
+}
+
+static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host)
+{
+       void __iomem *usb2_base = ch->base;
+       u32 val = readl(usb2_base + USB2_COMMCTRL);
+
+       dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, host);
+       if (host)
+               val &= ~USB2_COMMCTRL_OTG_PERI;
+       else
+               val |= USB2_COMMCTRL_OTG_PERI;
+       writel(val, usb2_base + USB2_COMMCTRL);
+}
+
+static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm)
+{
+       void __iomem *usb2_base = ch->base;
+       u32 val = readl(usb2_base + USB2_LINECTRL1);
+
+       dev_vdbg(&ch->phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm);
+       val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
+       if (dp)
+               val |= USB2_LINECTRL1_DP_RPD;
+       if (dm)
+               val |= USB2_LINECTRL1_DM_RPD;
+       writel(val, usb2_base + USB2_LINECTRL1);
+}
+
+static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
+{
+       void __iomem *usb2_base = ch->base;
+       u32 val = readl(usb2_base + USB2_ADPCTRL);
+
+       dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, vbus);
+       if (vbus)
+               val |= USB2_ADPCTRL_DRVVBUS;
+       else
+               val &= ~USB2_ADPCTRL_DRVVBUS;
+       writel(val, usb2_base + USB2_ADPCTRL);
+}
+
+static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch)
+{
+       rcar_gen3_set_linectrl(ch, 1, 1);
+       rcar_gen3_set_host_mode(ch, 1);
+       rcar_gen3_enable_vbus_ctrl(ch, 1);
+
+       ch->extcon_host = true;
+       schedule_work(&ch->work);
+}
+
+static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch)
+{
+       rcar_gen3_set_linectrl(ch, 0, 1);
+       rcar_gen3_set_host_mode(ch, 0);
+       rcar_gen3_enable_vbus_ctrl(ch, 0);
+
+       ch->extcon_host = false;
+       schedule_work(&ch->work);
+}
+
+static void rcar_gen3_init_for_b_host(struct rcar_gen3_chan *ch)
+{
+       void __iomem *usb2_base = ch->base;
+       u32 val;
+
+       val = readl(usb2_base + USB2_LINECTRL1);
+       writel(val | USB2_LINECTRL1_OPMODE_NODRV, usb2_base + USB2_LINECTRL1);
+
+       rcar_gen3_set_linectrl(ch, 1, 1);
+       rcar_gen3_set_host_mode(ch, 1);
+       rcar_gen3_enable_vbus_ctrl(ch, 0);
+
+       val = readl(usb2_base + USB2_LINECTRL1);
+       writel(val & ~USB2_LINECTRL1_OPMODE_NODRV, usb2_base + USB2_LINECTRL1);
+}
+
+static void rcar_gen3_init_for_a_peri(struct rcar_gen3_chan *ch)
+{
+       rcar_gen3_set_linectrl(ch, 0, 1);
+       rcar_gen3_set_host_mode(ch, 0);
+       rcar_gen3_enable_vbus_ctrl(ch, 1);
+}
+
+static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch)
+{
+       void __iomem *usb2_base = ch->base;
+       u32 val;
+
+       val = readl(usb2_base + USB2_OBINTEN);
+       writel(val & ~USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
+
+       rcar_gen3_enable_vbus_ctrl(ch, 0);
+       rcar_gen3_init_for_host(ch);
+
+       writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
+}
+
+static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
+{
+       return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
+}
+
+static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch)
+{
+       if (!rcar_gen3_check_id(ch))
+               rcar_gen3_init_for_host(ch);
+       else
+               rcar_gen3_init_for_peri(ch);
+}
+
+static bool rcar_gen3_is_host(struct rcar_gen3_chan *ch)
+{
+       return !(readl(ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI);
+}
+
+static ssize_t role_store(struct device *dev, struct device_attribute *attr,
+                         const char *buf, size_t count)
+{
+       struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
+       bool is_b_device, is_host, new_mode_is_host;
+
+       if (!ch->has_otg || !ch->phy->init_count)
+               return -EIO;
+
+       /*
+        * is_b_device: true is B-Device. false is A-Device.
+        * If {new_mode_}is_host: true is Host mode. false is Peripheral mode.
+        */
+       is_b_device = rcar_gen3_check_id(ch);
+       is_host = rcar_gen3_is_host(ch);
+       if (!strncmp(buf, "host", strlen("host")))
+               new_mode_is_host = true;
+       else if (!strncmp(buf, "peripheral", strlen("peripheral")))
+               new_mode_is_host = false;
+       else
+               return -EINVAL;
+
+       /* If current and new mode is the same, this returns the error */
+       if (is_host == new_mode_is_host)
+               return -EINVAL;
+
+       if (new_mode_is_host) {         /* And is_host must be false */
+               if (!is_b_device)       /* A-Peripheral */
+                       rcar_gen3_init_from_a_peri_to_a_host(ch);
+               else                    /* B-Peripheral */
+                       rcar_gen3_init_for_b_host(ch);
+       } else {                        /* And is_host must be true */
+               if (!is_b_device)       /* A-Host */
+                       rcar_gen3_init_for_a_peri(ch);
+               else                    /* B-Host */
+                       rcar_gen3_init_for_peri(ch);
+       }
+
+       return count;
+}
+
+static ssize_t role_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
+
+       if (!ch->has_otg || !ch->phy->init_count)
+               return -EIO;
+
+       return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" :
+                                                           "peripheral");
+}
+static DEVICE_ATTR_RW(role);
+
+static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
+{
+       void __iomem *usb2_base = ch->base;
+       u32 val;
+
+       val = readl(usb2_base + USB2_VBCTRL);
+       writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL);
+       writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
+       val = readl(usb2_base + USB2_OBINTEN);
+       writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
+       val = readl(usb2_base + USB2_ADPCTRL);
+       writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL);
+       val = readl(usb2_base + USB2_LINECTRL1);
+       rcar_gen3_set_linectrl(ch, 0, 0);
+       writel(val | USB2_LINECTRL1_DPRPD_EN | USB2_LINECTRL1_DMRPD_EN,
+              usb2_base + USB2_LINECTRL1);
+
+       rcar_gen3_device_recognition(ch);
+}
+
+static int rcar_gen3_phy_usb2_init(struct phy *p)
+{
+       struct rcar_gen3_chan *channel = phy_get_drvdata(p);
+       void __iomem *usb2_base = channel->base;
+
+       /* Initialize USB2 part */
+       writel(USB2_INT_ENABLE_INIT, usb2_base + USB2_INT_ENABLE);
+       writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET);
+       writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET);
+
+       /* Initialize otg part */
+       if (channel->has_otg)
+               rcar_gen3_init_otg(channel);
+
+       return 0;
+}
+
+static int rcar_gen3_phy_usb2_exit(struct phy *p)
+{
+       struct rcar_gen3_chan *channel = phy_get_drvdata(p);
+
+       writel(0, channel->base + USB2_INT_ENABLE);
+
+       return 0;
+}
+
+static int rcar_gen3_phy_usb2_power_on(struct phy *p)
+{
+       struct rcar_gen3_chan *channel = phy_get_drvdata(p);
+       void __iomem *usb2_base = channel->base;
+       u32 val;
+       int ret;
+
+       if (channel->vbus) {
+               ret = regulator_enable(channel->vbus);
+               if (ret)
+                       return ret;
+       }
+
+       val = readl(usb2_base + USB2_USBCTR);
+       val |= USB2_USBCTR_PLL_RST;
+       writel(val, usb2_base + USB2_USBCTR);
+       val &= ~USB2_USBCTR_PLL_RST;
+       writel(val, usb2_base + USB2_USBCTR);
+
+       return 0;
+}
+
+static int rcar_gen3_phy_usb2_power_off(struct phy *p)
+{
+       struct rcar_gen3_chan *channel = phy_get_drvdata(p);
+       int ret = 0;
+
+       if (channel->vbus)
+               ret = regulator_disable(channel->vbus);
+
+       return ret;
+}
+
+static const struct phy_ops rcar_gen3_phy_usb2_ops = {
+       .init           = rcar_gen3_phy_usb2_init,
+       .exit           = rcar_gen3_phy_usb2_exit,
+       .power_on       = rcar_gen3_phy_usb2_power_on,
+       .power_off      = rcar_gen3_phy_usb2_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
+{
+       struct rcar_gen3_chan *ch = _ch;
+       void __iomem *usb2_base = ch->base;
+       u32 status = readl(usb2_base + USB2_OBINTSTA);
+       irqreturn_t ret = IRQ_NONE;
+
+       if (status & USB2_OBINT_BITS) {
+               dev_vdbg(&ch->phy->dev, "%s: %08x\n", __func__, status);
+               writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
+               rcar_gen3_device_recognition(ch);
+               ret = IRQ_HANDLED;
+       }
+
+       return ret;
+}
+
+static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
+       { .compatible = "renesas,usb2-phy-r8a7795" },
+       { .compatible = "renesas,usb2-phy-r8a7796" },
+       { .compatible = "renesas,rcar-gen3-usb2-phy" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb2_match_table);
+
+static const unsigned int rcar_gen3_phy_cable[] = {
+       EXTCON_USB,
+       EXTCON_USB_HOST,
+       EXTCON_NONE,
+};
+
+static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct rcar_gen3_chan *channel;
+       struct phy_provider *provider;
+       struct resource *res;
+       int irq, ret = 0;
+
+       if (!dev->of_node) {
+               dev_err(dev, "This driver needs device tree\n");
+               return -EINVAL;
+       }
+
+       channel = devm_kzalloc(dev, sizeof(*channel), GFP_KERNEL);
+       if (!channel)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       channel->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(channel->base))
+               return PTR_ERR(channel->base);
+
+       /* call request_irq for OTG */
+       irq = platform_get_irq(pdev, 0);
+       if (irq >= 0) {
+               int ret;
+
+               INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
+               irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
+                                      IRQF_SHARED, dev_name(dev), channel);
+               if (irq < 0)
+                       dev_err(dev, "No irq handler (%d)\n", irq);
+               channel->has_otg = true;
+               channel->extcon = devm_extcon_dev_allocate(dev,
+                                                       rcar_gen3_phy_cable);
+               if (IS_ERR(channel->extcon))
+                       return PTR_ERR(channel->extcon);
+
+               ret = devm_extcon_dev_register(dev, channel->extcon);
+               if (ret < 0) {
+                       dev_err(dev, "Failed to register extcon\n");
+                       return ret;
+               }
+       }
+
+       /*
+        * 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);
+       channel->phy = devm_phy_create(dev, NULL, &rcar_gen3_phy_usb2_ops);
+       if (IS_ERR(channel->phy)) {
+               dev_err(dev, "Failed to create USB2 PHY\n");
+               ret = PTR_ERR(channel->phy);
+               goto error;
+       }
+
+       channel->vbus = devm_regulator_get_optional(dev, "vbus");
+       if (IS_ERR(channel->vbus)) {
+               if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) {
+                       ret = PTR_ERR(channel->vbus);
+                       goto error;
+               }
+               channel->vbus = NULL;
+       }
+
+       platform_set_drvdata(pdev, channel);
+       phy_set_drvdata(channel->phy, channel);
+
+       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;
+       } else if (channel->has_otg) {
+               int ret;
+
+               ret = device_create_file(dev, &dev_attr_role);
+               if (ret < 0)
+                       goto error;
+       }
+
+       return 0;
+
+error:
+       pm_runtime_disable(dev);
+
+       return ret;
+}
+
+static int rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
+{
+       struct rcar_gen3_chan *channel = platform_get_drvdata(pdev);
+
+       if (channel->has_otg)
+               device_remove_file(&pdev->dev, &dev_attr_role);
+
+       pm_runtime_disable(&pdev->dev);
+
+       return 0;
+};
+
+static struct platform_driver rcar_gen3_phy_usb2_driver = {
+       .driver = {
+               .name           = "phy_rcar_gen3_usb2",
+               .of_match_table = rcar_gen3_phy_usb2_match_table,
+       },
+       .probe  = rcar_gen3_phy_usb2_probe,
+       .remove = rcar_gen3_phy_usb2_remove,
+};
+module_platform_driver(rcar_gen3_phy_usb2_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 2.0 PHY");
+MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
new file mode 100644 (file)
index 0000000..f5325b2
--- /dev/null
@@ -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.
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
new file mode 100644 (file)
index 0000000..bd0acdf
--- /dev/null
@@ -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
diff --git a/drivers/phy/rockchip/phy-rockchip-dp.c b/drivers/phy/rockchip/phy-rockchip-dp.c
new file mode 100644 (file)
index 0000000..8b267a7
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Rockchip DP PHY driver
+ *
+ * Copyright (C) 2016 FuZhou Rockchip Co., Ltd.
+ * Author: Yakir Yang <ykk@@rock-chips.com>
+ *
+ * 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; either version 2 of the License.
+ */
+
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define GRF_SOC_CON12                           0x0274
+
+#define GRF_EDP_REF_CLK_SEL_INTER_HIWORD_MASK   BIT(20)
+#define GRF_EDP_REF_CLK_SEL_INTER               BIT(4)
+
+#define GRF_EDP_PHY_SIDDQ_HIWORD_MASK           BIT(21)
+#define GRF_EDP_PHY_SIDDQ_ON                    0
+#define GRF_EDP_PHY_SIDDQ_OFF                   BIT(5)
+
+struct rockchip_dp_phy {
+       struct device  *dev;
+       struct regmap  *grf;
+       struct clk     *phy_24m;
+};
+
+static int rockchip_set_phy_state(struct phy *phy, bool enable)
+{
+       struct rockchip_dp_phy *dp = phy_get_drvdata(phy);
+       int ret;
+
+       if (enable) {
+               ret = regmap_write(dp->grf, GRF_SOC_CON12,
+                                  GRF_EDP_PHY_SIDDQ_HIWORD_MASK |
+                                  GRF_EDP_PHY_SIDDQ_ON);
+               if (ret < 0) {
+                       dev_err(dp->dev, "Can't enable PHY power %d\n", ret);
+                       return ret;
+               }
+
+               ret = clk_prepare_enable(dp->phy_24m);
+       } else {
+               clk_disable_unprepare(dp->phy_24m);
+
+               ret = regmap_write(dp->grf, GRF_SOC_CON12,
+                                  GRF_EDP_PHY_SIDDQ_HIWORD_MASK |
+                                  GRF_EDP_PHY_SIDDQ_OFF);
+       }
+
+       return ret;
+}
+
+static int rockchip_dp_phy_power_on(struct phy *phy)
+{
+       return rockchip_set_phy_state(phy, true);
+}
+
+static int rockchip_dp_phy_power_off(struct phy *phy)
+{
+       return rockchip_set_phy_state(phy, false);
+}
+
+static const struct phy_ops rockchip_dp_phy_ops = {
+       .power_on       = rockchip_dp_phy_power_on,
+       .power_off      = rockchip_dp_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int rockchip_dp_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct phy_provider *phy_provider;
+       struct rockchip_dp_phy *dp;
+       struct phy *phy;
+       int ret;
+
+       if (!np)
+               return -ENODEV;
+
+       if (!dev->parent || !dev->parent->of_node)
+               return -ENODEV;
+
+       dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
+       if (!dp)
+               return -ENOMEM;
+
+       dp->dev = dev;
+
+       dp->phy_24m = devm_clk_get(dev, "24m");
+       if (IS_ERR(dp->phy_24m)) {
+               dev_err(dev, "cannot get clock 24m\n");
+               return PTR_ERR(dp->phy_24m);
+       }
+
+       ret = clk_set_rate(dp->phy_24m, 24000000);
+       if (ret < 0) {
+               dev_err(dp->dev, "cannot set clock phy_24m %d\n", ret);
+               return ret;
+       }
+
+       dp->grf = syscon_node_to_regmap(dev->parent->of_node);
+       if (IS_ERR(dp->grf)) {
+               dev_err(dev, "rk3288-dp needs the General Register Files syscon\n");
+               return PTR_ERR(dp->grf);
+       }
+
+       ret = regmap_write(dp->grf, GRF_SOC_CON12, GRF_EDP_REF_CLK_SEL_INTER |
+                          GRF_EDP_REF_CLK_SEL_INTER_HIWORD_MASK);
+       if (ret != 0) {
+               dev_err(dp->dev, "Could not config GRF edp ref clk: %d\n", ret);
+               return ret;
+       }
+
+       phy = devm_phy_create(dev, np, &rockchip_dp_phy_ops);
+       if (IS_ERR(phy)) {
+               dev_err(dev, "failed to create phy\n");
+               return PTR_ERR(phy);
+       }
+       phy_set_drvdata(phy, dp);
+
+       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 rockchip_dp_phy_dt_ids[] = {
+       { .compatible = "rockchip,rk3288-dp-phy" },
+       {}
+};
+
+MODULE_DEVICE_TABLE(of, rockchip_dp_phy_dt_ids);
+
+static struct platform_driver rockchip_dp_phy_driver = {
+       .probe          = rockchip_dp_phy_probe,
+       .driver         = {
+               .name   = "rockchip-dp-phy",
+               .of_match_table = rockchip_dp_phy_dt_ids,
+       },
+};
+
+module_platform_driver(rockchip_dp_phy_driver);
+
+MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip DP PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/rockchip/phy-rockchip-emmc.c b/drivers/phy/rockchip/phy-rockchip-emmc.c
new file mode 100644 (file)
index 0000000..f1b24f1
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Rockchip emmc PHY driver
+ *
+ * Copyright (C) 2016 Shawn Lin <shawn.lin@rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, 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; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.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>
+
+/*
+ * The higher 16-bit of this register is used for write protection
+ * only if BIT(x + 16) set to 1 the BIT(x) can be written.
+ */
+#define HIWORD_UPDATE(val, mask, shift) \
+               ((val) << (shift) | (mask) << ((shift) + 16))
+
+/* Register definition */
+#define GRF_EMMCPHY_CON0               0x0
+#define GRF_EMMCPHY_CON1               0x4
+#define GRF_EMMCPHY_CON2               0x8
+#define GRF_EMMCPHY_CON3               0xc
+#define GRF_EMMCPHY_CON4               0x10
+#define GRF_EMMCPHY_CON5               0x14
+#define GRF_EMMCPHY_CON6               0x18
+#define GRF_EMMCPHY_STATUS             0x20
+
+#define PHYCTRL_PDB_MASK               0x1
+#define PHYCTRL_PDB_SHIFT              0x0
+#define PHYCTRL_PDB_PWR_ON             0x1
+#define PHYCTRL_PDB_PWR_OFF            0x0
+#define PHYCTRL_ENDLL_MASK             0x1
+#define PHYCTRL_ENDLL_SHIFT            0x1
+#define PHYCTRL_ENDLL_ENABLE           0x1
+#define PHYCTRL_ENDLL_DISABLE          0x0
+#define PHYCTRL_CALDONE_MASK           0x1
+#define PHYCTRL_CALDONE_SHIFT          0x6
+#define PHYCTRL_CALDONE_DONE           0x1
+#define PHYCTRL_CALDONE_GOING          0x0
+#define PHYCTRL_DLLRDY_MASK            0x1
+#define PHYCTRL_DLLRDY_SHIFT           0x5
+#define PHYCTRL_DLLRDY_DONE            0x1
+#define PHYCTRL_DLLRDY_GOING           0x0
+#define PHYCTRL_FREQSEL_200M           0x0
+#define PHYCTRL_FREQSEL_50M            0x1
+#define PHYCTRL_FREQSEL_100M           0x2
+#define PHYCTRL_FREQSEL_150M           0x3
+#define PHYCTRL_FREQSEL_MASK           0x3
+#define PHYCTRL_FREQSEL_SHIFT          0xc
+#define PHYCTRL_DR_MASK                        0x7
+#define PHYCTRL_DR_SHIFT               0x4
+#define PHYCTRL_DR_50OHM               0x0
+#define PHYCTRL_DR_33OHM               0x1
+#define PHYCTRL_DR_66OHM               0x2
+#define PHYCTRL_DR_100OHM              0x3
+#define PHYCTRL_DR_40OHM               0x4
+#define PHYCTRL_OTAPDLYENA             0x1
+#define PHYCTRL_OTAPDLYENA_MASK                0x1
+#define PHYCTRL_OTAPDLYENA_SHIFT       0xb
+#define PHYCTRL_OTAPDLYSEL_MASK                0xf
+#define PHYCTRL_OTAPDLYSEL_SHIFT       0x7
+
+struct rockchip_emmc_phy {
+       unsigned int    reg_offset;
+       struct regmap   *reg_base;
+       struct clk      *emmcclk;
+};
+
+static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
+{
+       struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
+       unsigned int caldone;
+       unsigned int dllrdy;
+       unsigned int freqsel = PHYCTRL_FREQSEL_200M;
+       unsigned long rate;
+       unsigned long timeout;
+
+       /*
+        * Keep phyctrl_pdb and phyctrl_endll low to allow
+        * initialization of CALIO state M/C DFFs
+        */
+       regmap_write(rk_phy->reg_base,
+                    rk_phy->reg_offset + GRF_EMMCPHY_CON6,
+                    HIWORD_UPDATE(PHYCTRL_PDB_PWR_OFF,
+                                  PHYCTRL_PDB_MASK,
+                                  PHYCTRL_PDB_SHIFT));
+       regmap_write(rk_phy->reg_base,
+                    rk_phy->reg_offset + GRF_EMMCPHY_CON6,
+                    HIWORD_UPDATE(PHYCTRL_ENDLL_DISABLE,
+                                  PHYCTRL_ENDLL_MASK,
+                                  PHYCTRL_ENDLL_SHIFT));
+
+       /* Already finish power_off above */
+       if (on_off == PHYCTRL_PDB_PWR_OFF)
+               return 0;
+
+       rate = clk_get_rate(rk_phy->emmcclk);
+
+       if (rate != 0) {
+               unsigned long ideal_rate;
+               unsigned long diff;
+
+               switch (rate) {
+               case 1 ... 74999999:
+                       ideal_rate = 50000000;
+                       freqsel = PHYCTRL_FREQSEL_50M;
+                       break;
+               case 75000000 ... 124999999:
+                       ideal_rate = 100000000;
+                       freqsel = PHYCTRL_FREQSEL_100M;
+                       break;
+               case 125000000 ... 174999999:
+                       ideal_rate = 150000000;
+                       freqsel = PHYCTRL_FREQSEL_150M;
+                       break;
+               default:
+                       ideal_rate = 200000000;
+                       break;
+               }
+
+               diff = (rate > ideal_rate) ?
+                       rate - ideal_rate : ideal_rate - rate;
+
+               /*
+                * In order for tuning delays to be accurate we need to be
+                * pretty spot on for the DLL range, so warn if we're too
+                * far off.  Also warn if we're above the 200 MHz max.  Don't
+                * warn for really slow rates since we won't be tuning then.
+                */
+               if ((rate > 50000000 && diff > 15000000) || (rate > 200000000))
+                       dev_warn(&phy->dev, "Unsupported rate: %lu\n", rate);
+       }
+
+       /*
+        * According to the user manual, calpad calibration
+        * cycle takes more than 2us without the minimal recommended
+        * value, so we may need a little margin here
+        */
+       udelay(3);
+       regmap_write(rk_phy->reg_base,
+                    rk_phy->reg_offset + GRF_EMMCPHY_CON6,
+                    HIWORD_UPDATE(PHYCTRL_PDB_PWR_ON,
+                                  PHYCTRL_PDB_MASK,
+                                  PHYCTRL_PDB_SHIFT));
+
+       /*
+        * According to the user manual, it asks driver to
+        * wait 5us for calpad busy trimming
+        */
+       udelay(5);
+       regmap_read(rk_phy->reg_base,
+                   rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
+                   &caldone);
+       caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK;
+       if (caldone != PHYCTRL_CALDONE_DONE) {
+               pr_err("rockchip_emmc_phy_power: caldone timeout.\n");
+               return -ETIMEDOUT;
+       }
+
+       /* Set the frequency of the DLL operation */
+       regmap_write(rk_phy->reg_base,
+                    rk_phy->reg_offset + GRF_EMMCPHY_CON0,
+                    HIWORD_UPDATE(freqsel, PHYCTRL_FREQSEL_MASK,
+                                  PHYCTRL_FREQSEL_SHIFT));
+
+       /* Turn on the DLL */
+       regmap_write(rk_phy->reg_base,
+                    rk_phy->reg_offset + GRF_EMMCPHY_CON6,
+                    HIWORD_UPDATE(PHYCTRL_ENDLL_ENABLE,
+                                  PHYCTRL_ENDLL_MASK,
+                                  PHYCTRL_ENDLL_SHIFT));
+
+       /*
+        * We turned on the DLL even though the rate was 0 because we the
+        * clock might be turned on later.  ...but we can't wait for the DLL
+        * to lock when the rate is 0 because it will never lock with no
+        * input clock.
+        *
+        * Technically we should be checking the lock later when the clock
+        * is turned on, but for now we won't.
+        */
+       if (rate == 0)
+               return 0;
+
+       /*
+        * After enabling analog DLL circuits docs say that we need 10.2 us if
+        * our source clock is at 50 MHz and that lock time scales linearly
+        * with clock speed.  If we are powering on the PHY and the card clock
+        * is super slow (like 100 kHZ) this could take as long as 5.1 ms as
+        * per the math: 10.2 us * (50000000 Hz / 100000 Hz) => 5.1 ms
+        * Hopefully we won't be running at 100 kHz, but we should still make
+        * sure we wait long enough.
+        *
+        * NOTE: There appear to be corner cases where the DLL seems to take
+        * extra long to lock for reasons that aren't understood.  In some
+        * extreme cases we've seen it take up to over 10ms (!).  We'll be
+        * generous and give it 50ms.  We still busy wait here because:
+        * - In most cases it should be super fast.
+        * - This is not called lots during normal operation so it shouldn't
+        *   be a power or performance problem to busy wait.  We expect it
+        *   only at boot / resume.  In both cases, eMMC is probably on the
+        *   critical path so busy waiting a little extra time should be OK.
+        */
+       timeout = jiffies + msecs_to_jiffies(50);
+       do {
+               udelay(1);
+
+               regmap_read(rk_phy->reg_base,
+                       rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
+                       &dllrdy);
+               dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK;
+               if (dllrdy == PHYCTRL_DLLRDY_DONE)
+                       break;
+       } while (!time_after(jiffies, timeout));
+
+       if (dllrdy != PHYCTRL_DLLRDY_DONE) {
+               pr_err("rockchip_emmc_phy_power: dllrdy timeout.\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int rockchip_emmc_phy_init(struct phy *phy)
+{
+       struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
+       int ret = 0;
+
+       /*
+        * We purposely get the clock here and not in probe to avoid the
+        * circular dependency problem.  We expect:
+        * - PHY driver to probe
+        * - SDHCI driver to start probe
+        * - SDHCI driver to register it's clock
+        * - SDHCI driver to get the PHY
+        * - SDHCI driver to init the PHY
+        *
+        * The clock is optional, so upon any error we just set to NULL.
+        *
+        * NOTE: we don't do anything special for EPROBE_DEFER here.  Given the
+        * above expected use case, EPROBE_DEFER isn't sensible to expect, so
+        * it's just like any other error.
+        */
+       rk_phy->emmcclk = clk_get(&phy->dev, "emmcclk");
+       if (IS_ERR(rk_phy->emmcclk)) {
+               dev_dbg(&phy->dev, "Error getting emmcclk: %d\n", ret);
+               rk_phy->emmcclk = NULL;
+       }
+
+       return ret;
+}
+
+static int rockchip_emmc_phy_exit(struct phy *phy)
+{
+       struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
+
+       clk_put(rk_phy->emmcclk);
+
+       return 0;
+}
+
+static int rockchip_emmc_phy_power_off(struct phy *phy)
+{
+       /* Power down emmc phy analog blocks */
+       return rockchip_emmc_phy_power(phy, PHYCTRL_PDB_PWR_OFF);
+}
+
+static int rockchip_emmc_phy_power_on(struct phy *phy)
+{
+       struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
+
+       /* Drive impedance: 50 Ohm */
+       regmap_write(rk_phy->reg_base,
+                    rk_phy->reg_offset + GRF_EMMCPHY_CON6,
+                    HIWORD_UPDATE(PHYCTRL_DR_50OHM,
+                                  PHYCTRL_DR_MASK,
+                                  PHYCTRL_DR_SHIFT));
+
+       /* Output tap delay: enable */
+       regmap_write(rk_phy->reg_base,
+                    rk_phy->reg_offset + GRF_EMMCPHY_CON0,
+                    HIWORD_UPDATE(PHYCTRL_OTAPDLYENA,
+                                  PHYCTRL_OTAPDLYENA_MASK,
+                                  PHYCTRL_OTAPDLYENA_SHIFT));
+
+       /* Output tap delay */
+       regmap_write(rk_phy->reg_base,
+                    rk_phy->reg_offset + GRF_EMMCPHY_CON0,
+                    HIWORD_UPDATE(4,
+                                  PHYCTRL_OTAPDLYSEL_MASK,
+                                  PHYCTRL_OTAPDLYSEL_SHIFT));
+
+       /* Power up emmc phy analog blocks */
+       return rockchip_emmc_phy_power(phy, PHYCTRL_PDB_PWR_ON);
+}
+
+static const struct phy_ops ops = {
+       .init           = rockchip_emmc_phy_init,
+       .exit           = rockchip_emmc_phy_exit,
+       .power_on       = rockchip_emmc_phy_power_on,
+       .power_off      = rockchip_emmc_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int rockchip_emmc_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct rockchip_emmc_phy *rk_phy;
+       struct phy *generic_phy;
+       struct phy_provider *phy_provider;
+       struct regmap *grf;
+       unsigned int reg_offset;
+
+       if (!dev->parent || !dev->parent->of_node)
+               return -ENODEV;
+
+       grf = syscon_node_to_regmap(dev->parent->of_node);
+       if (IS_ERR(grf)) {
+               dev_err(dev, "Missing rockchip,grf property\n");
+               return PTR_ERR(grf);
+       }
+
+       rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
+       if (!rk_phy)
+               return -ENOMEM;
+
+       if (of_property_read_u32(dev->of_node, "reg", &reg_offset)) {
+               dev_err(dev, "missing reg property in node %s\n",
+                       dev->of_node->name);
+               return -EINVAL;
+       }
+
+       rk_phy->reg_offset = reg_offset;
+       rk_phy->reg_base = grf;
+
+       generic_phy = devm_phy_create(dev, dev->of_node, &ops);
+       if (IS_ERR(generic_phy)) {
+               dev_err(dev, "failed to create PHY\n");
+               return PTR_ERR(generic_phy);
+       }
+
+       phy_set_drvdata(generic_phy, rk_phy);
+       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 rockchip_emmc_phy_dt_ids[] = {
+       { .compatible = "rockchip,rk3399-emmc-phy" },
+       {}
+};
+
+MODULE_DEVICE_TABLE(of, rockchip_emmc_phy_dt_ids);
+
+static struct platform_driver rockchip_emmc_driver = {
+       .probe          = rockchip_emmc_phy_probe,
+       .driver         = {
+               .name   = "rockchip-emmc-phy",
+               .of_match_table = rockchip_emmc_phy_dt_ids,
+       },
+};
+
+module_platform_driver(rockchip_emmc_driver);
+
+MODULE_AUTHOR("Shawn Lin <shawn.lin@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip EMMC PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
new file mode 100644 (file)
index 0000000..8efe78a
--- /dev/null
@@ -0,0 +1,1284 @@
+/*
+ * Rockchip USB2.0 PHY with Innosilicon IP block driver
+ *
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/extcon.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/gpio/consumer.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/usb/of.h>
+#include <linux/usb/otg.h>
+
+#define BIT_WRITEABLE_SHIFT    16
+#define SCHEDULE_DELAY         (60 * HZ)
+#define OTG_SCHEDULE_DELAY     (2 * HZ)
+
+enum rockchip_usb2phy_port_id {
+       USB2PHY_PORT_OTG,
+       USB2PHY_PORT_HOST,
+       USB2PHY_NUM_PORTS,
+};
+
+enum rockchip_usb2phy_host_state {
+       PHY_STATE_HS_ONLINE     = 0,
+       PHY_STATE_DISCONNECT    = 1,
+       PHY_STATE_CONNECT       = 2,
+       PHY_STATE_FS_LS_ONLINE  = 4,
+};
+
+/**
+ * Different states involved in USB charger detection.
+ * USB_CHG_STATE_UNDEFINED     USB charger is not connected or detection
+ *                             process is not yet started.
+ * USB_CHG_STATE_WAIT_FOR_DCD  Waiting for Data pins contact.
+ * USB_CHG_STATE_DCD_DONE      Data pin contact is detected.
+ * USB_CHG_STATE_PRIMARY_DONE  Primary detection is completed (Detects
+ *                             between SDP and DCP/CDP).
+ * USB_CHG_STATE_SECONDARY_DONE        Secondary detection is completed (Detects
+ *                             between DCP and CDP).
+ * USB_CHG_STATE_DETECTED      USB charger type is determined.
+ */
+enum usb_chg_state {
+       USB_CHG_STATE_UNDEFINED = 0,
+       USB_CHG_STATE_WAIT_FOR_DCD,
+       USB_CHG_STATE_DCD_DONE,
+       USB_CHG_STATE_PRIMARY_DONE,
+       USB_CHG_STATE_SECONDARY_DONE,
+       USB_CHG_STATE_DETECTED,
+};
+
+static const unsigned int rockchip_usb2phy_extcon_cable[] = {
+       EXTCON_USB,
+       EXTCON_USB_HOST,
+       EXTCON_CHG_USB_SDP,
+       EXTCON_CHG_USB_CDP,
+       EXTCON_CHG_USB_DCP,
+       EXTCON_CHG_USB_SLOW,
+       EXTCON_NONE,
+};
+
+struct usb2phy_reg {
+       unsigned int    offset;
+       unsigned int    bitend;
+       unsigned int    bitstart;
+       unsigned int    disable;
+       unsigned int    enable;
+};
+
+/**
+ * struct rockchip_chg_det_reg: usb charger detect registers
+ * @cp_det: charging port detected successfully.
+ * @dcp_det: dedicated charging port detected successfully.
+ * @dp_det: assert data pin connect successfully.
+ * @idm_sink_en: open dm sink curren.
+ * @idp_sink_en: open dp sink current.
+ * @idp_src_en: open dm source current.
+ * @rdm_pdwn_en: open dm pull down resistor.
+ * @vdm_src_en: open dm voltage source.
+ * @vdp_src_en: open dp voltage source.
+ * @opmode: utmi operational mode.
+ */
+struct rockchip_chg_det_reg {
+       struct usb2phy_reg      cp_det;
+       struct usb2phy_reg      dcp_det;
+       struct usb2phy_reg      dp_det;
+       struct usb2phy_reg      idm_sink_en;
+       struct usb2phy_reg      idp_sink_en;
+       struct usb2phy_reg      idp_src_en;
+       struct usb2phy_reg      rdm_pdwn_en;
+       struct usb2phy_reg      vdm_src_en;
+       struct usb2phy_reg      vdp_src_en;
+       struct usb2phy_reg      opmode;
+};
+
+/**
+ * struct rockchip_usb2phy_port_cfg: usb-phy port configuration.
+ * @phy_sus: phy suspend register.
+ * @bvalid_det_en: vbus valid rise detection enable register.
+ * @bvalid_det_st: vbus valid rise detection status register.
+ * @bvalid_det_clr: vbus valid rise detection clear register.
+ * @ls_det_en: linestate detection enable register.
+ * @ls_det_st: linestate detection state register.
+ * @ls_det_clr: linestate detection clear register.
+ * @utmi_avalid: utmi vbus avalid status register.
+ * @utmi_bvalid: utmi vbus bvalid status register.
+ * @utmi_ls: utmi linestate state register.
+ * @utmi_hstdet: utmi host disconnect register.
+ */
+struct rockchip_usb2phy_port_cfg {
+       struct usb2phy_reg      phy_sus;
+       struct usb2phy_reg      bvalid_det_en;
+       struct usb2phy_reg      bvalid_det_st;
+       struct usb2phy_reg      bvalid_det_clr;
+       struct usb2phy_reg      ls_det_en;
+       struct usb2phy_reg      ls_det_st;
+       struct usb2phy_reg      ls_det_clr;
+       struct usb2phy_reg      utmi_avalid;
+       struct usb2phy_reg      utmi_bvalid;
+       struct usb2phy_reg      utmi_ls;
+       struct usb2phy_reg      utmi_hstdet;
+};
+
+/**
+ * struct rockchip_usb2phy_cfg: usb-phy configuration.
+ * @reg: the address offset of grf for usb-phy config.
+ * @num_ports: specify how many ports that the phy has.
+ * @clkout_ctl: keep on/turn off output clk of phy.
+ * @chg_det: charger detection registers.
+ */
+struct rockchip_usb2phy_cfg {
+       unsigned int    reg;
+       unsigned int    num_ports;
+       struct usb2phy_reg      clkout_ctl;
+       const struct rockchip_usb2phy_port_cfg  port_cfgs[USB2PHY_NUM_PORTS];
+       const struct rockchip_chg_det_reg       chg_det;
+};
+
+/**
+ * struct rockchip_usb2phy_port: usb-phy port data.
+ * @port_id: flag for otg port or host port.
+ * @suspended: phy suspended flag.
+ * @utmi_avalid: utmi avalid status usage flag.
+ *     true    - use avalid to get vbus status
+ *     flase   - use bvalid to get vbus status
+ * @vbus_attached: otg device vbus status.
+ * @bvalid_irq: IRQ number assigned for vbus valid rise detection.
+ * @ls_irq: IRQ number assigned for linestate detection.
+ * @mutex: for register updating in sm_work.
+ * @chg_work: charge detect work.
+ * @otg_sm_work: OTG state machine work.
+ * @sm_work: HOST state machine work.
+ * @phy_cfg: port register configuration, assigned by driver data.
+ * @event_nb: hold event notification callback.
+ * @state: define OTG enumeration states before device reset.
+ * @mode: the dr_mode of the controller.
+ */
+struct rockchip_usb2phy_port {
+       struct phy      *phy;
+       unsigned int    port_id;
+       bool            suspended;
+       bool            utmi_avalid;
+       bool            vbus_attached;
+       int             bvalid_irq;
+       int             ls_irq;
+       struct mutex    mutex;
+       struct          delayed_work chg_work;
+       struct          delayed_work otg_sm_work;
+       struct          delayed_work sm_work;
+       const struct    rockchip_usb2phy_port_cfg *port_cfg;
+       struct notifier_block   event_nb;
+       enum usb_otg_state      state;
+       enum usb_dr_mode        mode;
+};
+
+/**
+ * struct rockchip_usb2phy: usb2.0 phy driver data.
+ * @grf: General Register Files regmap.
+ * @clk: clock struct of phy input clk.
+ * @clk480m: clock struct of phy output clk.
+ * @clk_hw: clock struct of phy output clk management.
+ * @chg_state: states involved in USB charger detection.
+ * @chg_type: USB charger types.
+ * @dcd_retries: The retry count used to track Data contact
+ *              detection process.
+ * @edev: extcon device for notification registration
+ * @phy_cfg: phy register configuration, assigned by driver data.
+ * @ports: phy port instance.
+ */
+struct rockchip_usb2phy {
+       struct device   *dev;
+       struct regmap   *grf;
+       struct clk      *clk;
+       struct clk      *clk480m;
+       struct clk_hw   clk480m_hw;
+       enum usb_chg_state      chg_state;
+       enum power_supply_type  chg_type;
+       u8                      dcd_retries;
+       struct extcon_dev       *edev;
+       const struct rockchip_usb2phy_cfg       *phy_cfg;
+       struct rockchip_usb2phy_port    ports[USB2PHY_NUM_PORTS];
+};
+
+static inline int property_enable(struct rockchip_usb2phy *rphy,
+                                 const struct usb2phy_reg *reg, bool en)
+{
+       unsigned int val, mask, tmp;
+
+       tmp = en ? reg->enable : reg->disable;
+       mask = GENMASK(reg->bitend, reg->bitstart);
+       val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
+
+       return regmap_write(rphy->grf, reg->offset, val);
+}
+
+static inline bool property_enabled(struct rockchip_usb2phy *rphy,
+                                   const struct usb2phy_reg *reg)
+{
+       int ret;
+       unsigned int tmp, orig;
+       unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
+
+       ret = regmap_read(rphy->grf, reg->offset, &orig);
+       if (ret)
+               return false;
+
+       tmp = (orig & mask) >> reg->bitstart;
+       return tmp == reg->enable;
+}
+
+static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
+{
+       struct rockchip_usb2phy *rphy =
+               container_of(hw, struct rockchip_usb2phy, clk480m_hw);
+       int ret;
+
+       /* turn on 480m clk output if it is off */
+       if (!property_enabled(rphy, &rphy->phy_cfg->clkout_ctl)) {
+               ret = property_enable(rphy, &rphy->phy_cfg->clkout_ctl, true);
+               if (ret)
+                       return ret;
+
+               /* waiting for the clk become stable */
+               usleep_range(1200, 1300);
+       }
+
+       return 0;
+}
+
+static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
+{
+       struct rockchip_usb2phy *rphy =
+               container_of(hw, struct rockchip_usb2phy, clk480m_hw);
+
+       /* turn off 480m clk output */
+       property_enable(rphy, &rphy->phy_cfg->clkout_ctl, false);
+}
+
+static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
+{
+       struct rockchip_usb2phy *rphy =
+               container_of(hw, struct rockchip_usb2phy, clk480m_hw);
+
+       return property_enabled(rphy, &rphy->phy_cfg->clkout_ctl);
+}
+
+static unsigned long
+rockchip_usb2phy_clk480m_recalc_rate(struct clk_hw *hw,
+                                    unsigned long parent_rate)
+{
+       return 480000000;
+}
+
+static const struct clk_ops rockchip_usb2phy_clkout_ops = {
+       .prepare = rockchip_usb2phy_clk480m_prepare,
+       .unprepare = rockchip_usb2phy_clk480m_unprepare,
+       .is_prepared = rockchip_usb2phy_clk480m_prepared,
+       .recalc_rate = rockchip_usb2phy_clk480m_recalc_rate,
+};
+
+static void rockchip_usb2phy_clk480m_unregister(void *data)
+{
+       struct rockchip_usb2phy *rphy = data;
+
+       of_clk_del_provider(rphy->dev->of_node);
+       clk_unregister(rphy->clk480m);
+}
+
+static int
+rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
+{
+       struct device_node *node = rphy->dev->of_node;
+       struct clk_init_data init;
+       const char *clk_name;
+       int ret;
+
+       init.flags = 0;
+       init.name = "clk_usbphy_480m";
+       init.ops = &rockchip_usb2phy_clkout_ops;
+
+       /* optional override of the clockname */
+       of_property_read_string(node, "clock-output-names", &init.name);
+
+       if (rphy->clk) {
+               clk_name = __clk_get_name(rphy->clk);
+               init.parent_names = &clk_name;
+               init.num_parents = 1;
+       } else {
+               init.parent_names = NULL;
+               init.num_parents = 0;
+       }
+
+       rphy->clk480m_hw.init = &init;
+
+       /* register the clock */
+       rphy->clk480m = clk_register(rphy->dev, &rphy->clk480m_hw);
+       if (IS_ERR(rphy->clk480m)) {
+               ret = PTR_ERR(rphy->clk480m);
+               goto err_ret;
+       }
+
+       ret = of_clk_add_provider(node, of_clk_src_simple_get, rphy->clk480m);
+       if (ret < 0)
+               goto err_clk_provider;
+
+       ret = devm_add_action(rphy->dev, rockchip_usb2phy_clk480m_unregister,
+                             rphy);
+       if (ret < 0)
+               goto err_unreg_action;
+
+       return 0;
+
+err_unreg_action:
+       of_clk_del_provider(node);
+err_clk_provider:
+       clk_unregister(rphy->clk480m);
+err_ret:
+       return ret;
+}
+
+static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
+{
+       int ret;
+       struct device_node *node = rphy->dev->of_node;
+       struct extcon_dev *edev;
+
+       if (of_property_read_bool(node, "extcon")) {
+               edev = extcon_get_edev_by_phandle(rphy->dev, 0);
+               if (IS_ERR(edev)) {
+                       if (PTR_ERR(edev) != -EPROBE_DEFER)
+                               dev_err(rphy->dev, "Invalid or missing extcon\n");
+                       return PTR_ERR(edev);
+               }
+       } else {
+               /* Initialize extcon device */
+               edev = devm_extcon_dev_allocate(rphy->dev,
+                                               rockchip_usb2phy_extcon_cable);
+
+               if (IS_ERR(edev))
+                       return -ENOMEM;
+
+               ret = devm_extcon_dev_register(rphy->dev, edev);
+               if (ret) {
+                       dev_err(rphy->dev, "failed to register extcon device\n");
+                       return ret;
+               }
+       }
+
+       rphy->edev = edev;
+
+       return 0;
+}
+
+static int rockchip_usb2phy_init(struct phy *phy)
+{
+       struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
+       int ret = 0;
+
+       mutex_lock(&rport->mutex);
+
+       if (rport->port_id == USB2PHY_PORT_OTG) {
+               if (rport->mode != USB_DR_MODE_HOST) {
+                       /* clear bvalid status and enable bvalid detect irq */
+                       ret = property_enable(rphy,
+                                             &rport->port_cfg->bvalid_det_clr,
+                                             true);
+                       if (ret)
+                               goto out;
+
+                       ret = property_enable(rphy,
+                                             &rport->port_cfg->bvalid_det_en,
+                                             true);
+                       if (ret)
+                               goto out;
+
+                       schedule_delayed_work(&rport->otg_sm_work,
+                                             OTG_SCHEDULE_DELAY);
+               } else {
+                       /* If OTG works in host only mode, do nothing. */
+                       dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
+               }
+       } else if (rport->port_id == USB2PHY_PORT_HOST) {
+               /* clear linestate and enable linestate detect irq */
+               ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
+               if (ret)
+                       goto out;
+
+               ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
+               if (ret)
+                       goto out;
+
+               schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
+       }
+
+out:
+       mutex_unlock(&rport->mutex);
+       return ret;
+}
+
+static int rockchip_usb2phy_power_on(struct phy *phy)
+{
+       struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
+       int ret;
+
+       dev_dbg(&rport->phy->dev, "port power on\n");
+
+       if (!rport->suspended)
+               return 0;
+
+       ret = clk_prepare_enable(rphy->clk480m);
+       if (ret)
+               return ret;
+
+       ret = property_enable(rphy, &rport->port_cfg->phy_sus, false);
+       if (ret)
+               return ret;
+
+       rport->suspended = false;
+       return 0;
+}
+
+static int rockchip_usb2phy_power_off(struct phy *phy)
+{
+       struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
+       int ret;
+
+       dev_dbg(&rport->phy->dev, "port power off\n");
+
+       if (rport->suspended)
+               return 0;
+
+       ret = property_enable(rphy, &rport->port_cfg->phy_sus, true);
+       if (ret)
+               return ret;
+
+       rport->suspended = true;
+       clk_disable_unprepare(rphy->clk480m);
+
+       return 0;
+}
+
+static int rockchip_usb2phy_exit(struct phy *phy)
+{
+       struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
+
+       if (rport->port_id == USB2PHY_PORT_OTG &&
+           rport->mode != USB_DR_MODE_HOST) {
+               cancel_delayed_work_sync(&rport->otg_sm_work);
+               cancel_delayed_work_sync(&rport->chg_work);
+       } else if (rport->port_id == USB2PHY_PORT_HOST)
+               cancel_delayed_work_sync(&rport->sm_work);
+
+       return 0;
+}
+
+static const struct phy_ops rockchip_usb2phy_ops = {
+       .init           = rockchip_usb2phy_init,
+       .exit           = rockchip_usb2phy_exit,
+       .power_on       = rockchip_usb2phy_power_on,
+       .power_off      = rockchip_usb2phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
+{
+       struct rockchip_usb2phy_port *rport =
+               container_of(work, struct rockchip_usb2phy_port,
+                            otg_sm_work.work);
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
+       static unsigned int cable;
+       unsigned long delay;
+       bool vbus_attach, sch_work, notify_charger;
+
+       if (rport->utmi_avalid)
+               vbus_attach =
+                       property_enabled(rphy, &rport->port_cfg->utmi_avalid);
+       else
+               vbus_attach =
+                       property_enabled(rphy, &rport->port_cfg->utmi_bvalid);
+
+       sch_work = false;
+       notify_charger = false;
+       delay = OTG_SCHEDULE_DELAY;
+       dev_dbg(&rport->phy->dev, "%s otg sm work\n",
+               usb_otg_state_string(rport->state));
+
+       switch (rport->state) {
+       case OTG_STATE_UNDEFINED:
+               rport->state = OTG_STATE_B_IDLE;
+               if (!vbus_attach)
+                       rockchip_usb2phy_power_off(rport->phy);
+               /* fall through */
+       case OTG_STATE_B_IDLE:
+               if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) > 0) {
+                       dev_dbg(&rport->phy->dev, "usb otg host connect\n");
+                       rport->state = OTG_STATE_A_HOST;
+                       rockchip_usb2phy_power_on(rport->phy);
+                       return;
+               } else if (vbus_attach) {
+                       dev_dbg(&rport->phy->dev, "vbus_attach\n");
+                       switch (rphy->chg_state) {
+                       case USB_CHG_STATE_UNDEFINED:
+                               schedule_delayed_work(&rport->chg_work, 0);
+                               return;
+                       case USB_CHG_STATE_DETECTED:
+                               switch (rphy->chg_type) {
+                               case POWER_SUPPLY_TYPE_USB:
+                                       dev_dbg(&rport->phy->dev, "sdp cable is connected\n");
+                                       rockchip_usb2phy_power_on(rport->phy);
+                                       rport->state = OTG_STATE_B_PERIPHERAL;
+                                       notify_charger = true;
+                                       sch_work = true;
+                                       cable = EXTCON_CHG_USB_SDP;
+                                       break;
+                               case POWER_SUPPLY_TYPE_USB_DCP:
+                                       dev_dbg(&rport->phy->dev, "dcp cable is connected\n");
+                                       rockchip_usb2phy_power_off(rport->phy);
+                                       notify_charger = true;
+                                       sch_work = true;
+                                       cable = EXTCON_CHG_USB_DCP;
+                                       break;
+                               case POWER_SUPPLY_TYPE_USB_CDP:
+                                       dev_dbg(&rport->phy->dev, "cdp cable is connected\n");
+                                       rockchip_usb2phy_power_on(rport->phy);
+                                       rport->state = OTG_STATE_B_PERIPHERAL;
+                                       notify_charger = true;
+                                       sch_work = true;
+                                       cable = EXTCON_CHG_USB_CDP;
+                                       break;
+                               default:
+                                       break;
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               } else {
+                       notify_charger = true;
+                       rphy->chg_state = USB_CHG_STATE_UNDEFINED;
+                       rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
+               }
+
+               if (rport->vbus_attached != vbus_attach) {
+                       rport->vbus_attached = vbus_attach;
+
+                       if (notify_charger && rphy->edev) {
+                               extcon_set_cable_state_(rphy->edev,
+                                                       cable, vbus_attach);
+                               if (cable == EXTCON_CHG_USB_SDP)
+                                       extcon_set_state_sync(rphy->edev,
+                                                             EXTCON_USB,
+                                                             vbus_attach);
+                       }
+               }
+               break;
+       case OTG_STATE_B_PERIPHERAL:
+               if (!vbus_attach) {
+                       dev_dbg(&rport->phy->dev, "usb disconnect\n");
+                       rphy->chg_state = USB_CHG_STATE_UNDEFINED;
+                       rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
+                       rport->state = OTG_STATE_B_IDLE;
+                       delay = 0;
+                       rockchip_usb2phy_power_off(rport->phy);
+               }
+               sch_work = true;
+               break;
+       case OTG_STATE_A_HOST:
+               if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) == 0) {
+                       dev_dbg(&rport->phy->dev, "usb otg host disconnect\n");
+                       rport->state = OTG_STATE_B_IDLE;
+                       rockchip_usb2phy_power_off(rport->phy);
+               }
+               break;
+       default:
+               break;
+       }
+
+       if (sch_work)
+               schedule_delayed_work(&rport->otg_sm_work, delay);
+}
+
+static const char *chg_to_string(enum power_supply_type chg_type)
+{
+       switch (chg_type) {
+       case POWER_SUPPLY_TYPE_USB:
+               return "USB_SDP_CHARGER";
+       case POWER_SUPPLY_TYPE_USB_DCP:
+               return "USB_DCP_CHARGER";
+       case POWER_SUPPLY_TYPE_USB_CDP:
+               return "USB_CDP_CHARGER";
+       default:
+               return "INVALID_CHARGER";
+       }
+}
+
+static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
+                                   bool en)
+{
+       property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
+       property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
+}
+
+static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
+                                           bool en)
+{
+       property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en);
+       property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
+}
+
+static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
+                                             bool en)
+{
+       property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en);
+       property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
+}
+
+#define CHG_DCD_POLL_TIME      (100 * HZ / 1000)
+#define CHG_DCD_MAX_RETRIES    6
+#define CHG_PRIMARY_DET_TIME   (40 * HZ / 1000)
+#define CHG_SECONDARY_DET_TIME (40 * HZ / 1000)
+static void rockchip_chg_detect_work(struct work_struct *work)
+{
+       struct rockchip_usb2phy_port *rport =
+               container_of(work, struct rockchip_usb2phy_port, chg_work.work);
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
+       bool is_dcd, tmout, vout;
+       unsigned long delay;
+
+       dev_dbg(&rport->phy->dev, "chg detection work state = %d\n",
+               rphy->chg_state);
+       switch (rphy->chg_state) {
+       case USB_CHG_STATE_UNDEFINED:
+               if (!rport->suspended)
+                       rockchip_usb2phy_power_off(rport->phy);
+               /* put the controller in non-driving mode */
+               property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, false);
+               /* Start DCD processing stage 1 */
+               rockchip_chg_enable_dcd(rphy, true);
+               rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
+               rphy->dcd_retries = 0;
+               delay = CHG_DCD_POLL_TIME;
+               break;
+       case USB_CHG_STATE_WAIT_FOR_DCD:
+               /* get data contact detection status */
+               is_dcd = property_enabled(rphy, &rphy->phy_cfg->chg_det.dp_det);
+               tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
+               /* stage 2 */
+               if (is_dcd || tmout) {
+                       /* stage 4 */
+                       /* Turn off DCD circuitry */
+                       rockchip_chg_enable_dcd(rphy, false);
+                       /* Voltage Source on DP, Probe on DM */
+                       rockchip_chg_enable_primary_det(rphy, true);
+                       delay = CHG_PRIMARY_DET_TIME;
+                       rphy->chg_state = USB_CHG_STATE_DCD_DONE;
+               } else {
+                       /* stage 3 */
+                       delay = CHG_DCD_POLL_TIME;
+               }
+               break;
+       case USB_CHG_STATE_DCD_DONE:
+               vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.cp_det);
+               rockchip_chg_enable_primary_det(rphy, false);
+               if (vout) {
+                       /* Voltage Source on DM, Probe on DP  */
+                       rockchip_chg_enable_secondary_det(rphy, true);
+                       delay = CHG_SECONDARY_DET_TIME;
+                       rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE;
+               } else {
+                       if (rphy->dcd_retries == CHG_DCD_MAX_RETRIES) {
+                               /* floating charger found */
+                               rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
+                               rphy->chg_state = USB_CHG_STATE_DETECTED;
+                               delay = 0;
+                       } else {
+                               rphy->chg_type = POWER_SUPPLY_TYPE_USB;
+                               rphy->chg_state = USB_CHG_STATE_DETECTED;
+                               delay = 0;
+                       }
+               }
+               break;
+       case USB_CHG_STATE_PRIMARY_DONE:
+               vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.dcp_det);
+               /* Turn off voltage source */
+               rockchip_chg_enable_secondary_det(rphy, false);
+               if (vout)
+                       rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
+               else
+                       rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP;
+               /* fall through */
+       case USB_CHG_STATE_SECONDARY_DONE:
+               rphy->chg_state = USB_CHG_STATE_DETECTED;
+               delay = 0;
+               /* fall through */
+       case USB_CHG_STATE_DETECTED:
+               /* put the controller in normal mode */
+               property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, true);
+               rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
+               dev_info(&rport->phy->dev, "charger = %s\n",
+                        chg_to_string(rphy->chg_type));
+               return;
+       default:
+               return;
+       }
+
+       schedule_delayed_work(&rport->chg_work, delay);
+}
+
+/*
+ * The function manage host-phy port state and suspend/resume phy port
+ * to save power.
+ *
+ * we rely on utmi_linestate and utmi_hostdisconnect to identify whether
+ * devices is disconnect or not. Besides, we do not need care it is FS/LS
+ * disconnected or HS disconnected, actually, we just only need get the
+ * device is disconnected at last through rearm the delayed work,
+ * to suspend the phy port in _PHY_STATE_DISCONNECT_ case.
+ *
+ * NOTE: It may invoke *phy_powr_off or *phy_power_on which will invoke
+ * some clk related APIs, so do not invoke it from interrupt context directly.
+ */
+static void rockchip_usb2phy_sm_work(struct work_struct *work)
+{
+       struct rockchip_usb2phy_port *rport =
+               container_of(work, struct rockchip_usb2phy_port, sm_work.work);
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
+       unsigned int sh = rport->port_cfg->utmi_hstdet.bitend -
+                         rport->port_cfg->utmi_hstdet.bitstart + 1;
+       unsigned int ul, uhd, state;
+       unsigned int ul_mask, uhd_mask;
+       int ret;
+
+       mutex_lock(&rport->mutex);
+
+       ret = regmap_read(rphy->grf, rport->port_cfg->utmi_ls.offset, &ul);
+       if (ret < 0)
+               goto next_schedule;
+
+       ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset,
+                         &uhd);
+       if (ret < 0)
+               goto next_schedule;
+
+       uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend,
+                          rport->port_cfg->utmi_hstdet.bitstart);
+       ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend,
+                         rport->port_cfg->utmi_ls.bitstart);
+
+       /* stitch on utmi_ls and utmi_hstdet as phy state */
+       state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) |
+               (((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh);
+
+       switch (state) {
+       case PHY_STATE_HS_ONLINE:
+               dev_dbg(&rport->phy->dev, "HS online\n");
+               break;
+       case PHY_STATE_FS_LS_ONLINE:
+               /*
+                * For FS/LS device, the online state share with connect state
+                * from utmi_ls and utmi_hstdet register, so we distinguish
+                * them via suspended flag.
+                *
+                * Plus, there are two cases, one is D- Line pull-up, and D+
+                * line pull-down, the state is 4; another is D+ line pull-up,
+                * and D- line pull-down, the state is 2.
+                */
+               if (!rport->suspended) {
+                       /* D- line pull-up, D+ line pull-down */
+                       dev_dbg(&rport->phy->dev, "FS/LS online\n");
+                       break;
+               }
+               /* fall through */
+       case PHY_STATE_CONNECT:
+               if (rport->suspended) {
+                       dev_dbg(&rport->phy->dev, "Connected\n");
+                       rockchip_usb2phy_power_on(rport->phy);
+                       rport->suspended = false;
+               } else {
+                       /* D+ line pull-up, D- line pull-down */
+                       dev_dbg(&rport->phy->dev, "FS/LS online\n");
+               }
+               break;
+       case PHY_STATE_DISCONNECT:
+               if (!rport->suspended) {
+                       dev_dbg(&rport->phy->dev, "Disconnected\n");
+                       rockchip_usb2phy_power_off(rport->phy);
+                       rport->suspended = true;
+               }
+
+               /*
+                * activate the linestate detection to get the next device
+                * plug-in irq.
+                */
+               property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
+               property_enable(rphy, &rport->port_cfg->ls_det_en, true);
+
+               /*
+                * we don't need to rearm the delayed work when the phy port
+                * is suspended.
+                */
+               mutex_unlock(&rport->mutex);
+               return;
+       default:
+               dev_dbg(&rport->phy->dev, "unknown phy state\n");
+               break;
+       }
+
+next_schedule:
+       mutex_unlock(&rport->mutex);
+       schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
+}
+
+static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
+{
+       struct rockchip_usb2phy_port *rport = data;
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
+
+       if (!property_enabled(rphy, &rport->port_cfg->ls_det_st))
+               return IRQ_NONE;
+
+       mutex_lock(&rport->mutex);
+
+       /* disable linestate detect irq and clear its status */
+       property_enable(rphy, &rport->port_cfg->ls_det_en, false);
+       property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
+
+       mutex_unlock(&rport->mutex);
+
+       /*
+        * In this case for host phy port, a new device is plugged in,
+        * meanwhile, if the phy port is suspended, we need rearm the work to
+        * resume it and mange its states; otherwise, we do nothing about that.
+        */
+       if (rport->suspended && rport->port_id == USB2PHY_PORT_HOST)
+               rockchip_usb2phy_sm_work(&rport->sm_work.work);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
+{
+       struct rockchip_usb2phy_port *rport = data;
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
+
+       if (!property_enabled(rphy, &rport->port_cfg->bvalid_det_st))
+               return IRQ_NONE;
+
+       mutex_lock(&rport->mutex);
+
+       /* clear bvalid detect irq pending status */
+       property_enable(rphy, &rport->port_cfg->bvalid_det_clr, true);
+
+       mutex_unlock(&rport->mutex);
+
+       rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
+
+       return IRQ_HANDLED;
+}
+
+static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
+                                          struct rockchip_usb2phy_port *rport,
+                                          struct device_node *child_np)
+{
+       int ret;
+
+       rport->port_id = USB2PHY_PORT_HOST;
+       rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_HOST];
+       rport->suspended = true;
+
+       mutex_init(&rport->mutex);
+       INIT_DELAYED_WORK(&rport->sm_work, rockchip_usb2phy_sm_work);
+
+       rport->ls_irq = of_irq_get_byname(child_np, "linestate");
+       if (rport->ls_irq < 0) {
+               dev_err(rphy->dev, "no linestate irq provided\n");
+               return rport->ls_irq;
+       }
+
+       ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL,
+                                       rockchip_usb2phy_linestate_irq,
+                                       IRQF_ONESHOT,
+                                       "rockchip_usb2phy", rport);
+       if (ret) {
+               dev_err(rphy->dev, "failed to request linestate irq handle\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int rockchip_otg_event(struct notifier_block *nb,
+                             unsigned long event, void *ptr)
+{
+       struct rockchip_usb2phy_port *rport =
+               container_of(nb, struct rockchip_usb2phy_port, event_nb);
+
+       schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY);
+
+       return NOTIFY_DONE;
+}
+
+static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
+                                         struct rockchip_usb2phy_port *rport,
+                                         struct device_node *child_np)
+{
+       int ret;
+
+       rport->port_id = USB2PHY_PORT_OTG;
+       rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG];
+       rport->state = OTG_STATE_UNDEFINED;
+
+       /*
+        * set suspended flag to true, but actually don't
+        * put phy in suspend mode, it aims to enable usb
+        * phy and clock in power_on() called by usb controller
+        * driver during probe.
+        */
+       rport->suspended = true;
+       rport->vbus_attached = false;
+
+       mutex_init(&rport->mutex);
+
+       rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
+       if (rport->mode == USB_DR_MODE_HOST) {
+               ret = 0;
+               goto out;
+       }
+
+       INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
+       INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work);
+
+       rport->utmi_avalid =
+               of_property_read_bool(child_np, "rockchip,utmi-avalid");
+
+       rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
+       if (rport->bvalid_irq < 0) {
+               dev_err(rphy->dev, "no vbus valid irq provided\n");
+               ret = rport->bvalid_irq;
+               goto out;
+       }
+
+       ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, NULL,
+                                       rockchip_usb2phy_bvalid_irq,
+                                       IRQF_ONESHOT,
+                                       "rockchip_usb2phy_bvalid", rport);
+       if (ret) {
+               dev_err(rphy->dev, "failed to request otg-bvalid irq handle\n");
+               goto out;
+       }
+
+       if (!IS_ERR(rphy->edev)) {
+               rport->event_nb.notifier_call = rockchip_otg_event;
+
+               ret = extcon_register_notifier(rphy->edev, EXTCON_USB_HOST,
+                                              &rport->event_nb);
+               if (ret)
+                       dev_err(rphy->dev, "register USB HOST notifier failed\n");
+       }
+
+out:
+       return ret;
+}
+
+static int rockchip_usb2phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct device_node *child_np;
+       struct phy_provider *provider;
+       struct rockchip_usb2phy *rphy;
+       const struct rockchip_usb2phy_cfg *phy_cfgs;
+       const struct of_device_id *match;
+       unsigned int reg;
+       int index, ret;
+
+       rphy = devm_kzalloc(dev, sizeof(*rphy), GFP_KERNEL);
+       if (!rphy)
+               return -ENOMEM;
+
+       match = of_match_device(dev->driver->of_match_table, dev);
+       if (!match || !match->data) {
+               dev_err(dev, "phy configs are not assigned!\n");
+               return -EINVAL;
+       }
+
+       if (!dev->parent || !dev->parent->of_node)
+               return -EINVAL;
+
+       rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
+       if (IS_ERR(rphy->grf))
+               return PTR_ERR(rphy->grf);
+
+       if (of_property_read_u32(np, "reg", &reg)) {
+               dev_err(dev, "the reg property is not assigned in %s node\n",
+                       np->name);
+               return -EINVAL;
+       }
+
+       rphy->dev = dev;
+       phy_cfgs = match->data;
+       rphy->chg_state = USB_CHG_STATE_UNDEFINED;
+       rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
+       platform_set_drvdata(pdev, rphy);
+
+       ret = rockchip_usb2phy_extcon_register(rphy);
+       if (ret)
+               return ret;
+
+       /* find out a proper config which can be matched with dt. */
+       index = 0;
+       while (phy_cfgs[index].reg) {
+               if (phy_cfgs[index].reg == reg) {
+                       rphy->phy_cfg = &phy_cfgs[index];
+                       break;
+               }
+
+               ++index;
+       }
+
+       if (!rphy->phy_cfg) {
+               dev_err(dev, "no phy-config can be matched with %s node\n",
+                       np->name);
+               return -EINVAL;
+       }
+
+       rphy->clk = of_clk_get_by_name(np, "phyclk");
+       if (!IS_ERR(rphy->clk)) {
+               clk_prepare_enable(rphy->clk);
+       } else {
+               dev_info(&pdev->dev, "no phyclk specified\n");
+               rphy->clk = NULL;
+       }
+
+       ret = rockchip_usb2phy_clk480m_register(rphy);
+       if (ret) {
+               dev_err(dev, "failed to register 480m output clock\n");
+               goto disable_clks;
+       }
+
+       index = 0;
+       for_each_available_child_of_node(np, child_np) {
+               struct rockchip_usb2phy_port *rport = &rphy->ports[index];
+               struct phy *phy;
+
+               /* This driver aims to support both otg-port and host-port */
+               if (of_node_cmp(child_np->name, "host-port") &&
+                   of_node_cmp(child_np->name, "otg-port"))
+                       goto next_child;
+
+               phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
+               if (IS_ERR(phy)) {
+                       dev_err(dev, "failed to create phy\n");
+                       ret = PTR_ERR(phy);
+                       goto put_child;
+               }
+
+               rport->phy = phy;
+               phy_set_drvdata(rport->phy, rport);
+
+               /* initialize otg/host port separately */
+               if (!of_node_cmp(child_np->name, "host-port")) {
+                       ret = rockchip_usb2phy_host_port_init(rphy, rport,
+                                                             child_np);
+                       if (ret)
+                               goto put_child;
+               } else {
+                       ret = rockchip_usb2phy_otg_port_init(rphy, rport,
+                                                            child_np);
+                       if (ret)
+                               goto put_child;
+               }
+
+next_child:
+               /* to prevent out of boundary */
+               if (++index >= rphy->phy_cfg->num_ports)
+                       break;
+       }
+
+       provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       return PTR_ERR_OR_ZERO(provider);
+
+put_child:
+       of_node_put(child_np);
+disable_clks:
+       if (rphy->clk) {
+               clk_disable_unprepare(rphy->clk);
+               clk_put(rphy->clk);
+       }
+       return ret;
+}
+
+static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = {
+       {
+               .reg = 0x100,
+               .num_ports      = 2,
+               .clkout_ctl     = { 0x108, 4, 4, 1, 0 },
+               .port_cfgs      = {
+                       [USB2PHY_PORT_OTG] = {
+                               .phy_sus        = { 0x0100, 15, 0, 0, 0x1d1 },
+                               .bvalid_det_en  = { 0x0110, 2, 2, 0, 1 },
+                               .bvalid_det_st  = { 0x0114, 2, 2, 0, 1 },
+                               .bvalid_det_clr = { 0x0118, 2, 2, 0, 1 },
+                               .ls_det_en      = { 0x0110, 0, 0, 0, 1 },
+                               .ls_det_st      = { 0x0114, 0, 0, 0, 1 },
+                               .ls_det_clr     = { 0x0118, 0, 0, 0, 1 },
+                               .utmi_avalid    = { 0x0120, 10, 10, 0, 1 },
+                               .utmi_bvalid    = { 0x0120, 9, 9, 0, 1 },
+                               .utmi_ls        = { 0x0120, 5, 4, 0, 1 },
+                       },
+                       [USB2PHY_PORT_HOST] = {
+                               .phy_sus        = { 0x104, 15, 0, 0, 0x1d1 },
+                               .ls_det_en      = { 0x110, 1, 1, 0, 1 },
+                               .ls_det_st      = { 0x114, 1, 1, 0, 1 },
+                               .ls_det_clr     = { 0x118, 1, 1, 0, 1 },
+                               .utmi_ls        = { 0x120, 17, 16, 0, 1 },
+                               .utmi_hstdet    = { 0x120, 19, 19, 0, 1 }
+                       }
+               },
+               .chg_det = {
+                       .opmode         = { 0x0100, 3, 0, 5, 1 },
+                       .cp_det         = { 0x0120, 24, 24, 0, 1 },
+                       .dcp_det        = { 0x0120, 23, 23, 0, 1 },
+                       .dp_det         = { 0x0120, 25, 25, 0, 1 },
+                       .idm_sink_en    = { 0x0108, 8, 8, 0, 1 },
+                       .idp_sink_en    = { 0x0108, 7, 7, 0, 1 },
+                       .idp_src_en     = { 0x0108, 9, 9, 0, 1 },
+                       .rdm_pdwn_en    = { 0x0108, 10, 10, 0, 1 },
+                       .vdm_src_en     = { 0x0108, 12, 12, 0, 1 },
+                       .vdp_src_en     = { 0x0108, 11, 11, 0, 1 },
+               },
+       },
+       { /* sentinel */ }
+};
+
+static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs[] = {
+       {
+               .reg = 0x700,
+               .num_ports      = 2,
+               .clkout_ctl     = { 0x0724, 15, 15, 1, 0 },
+               .port_cfgs      = {
+                       [USB2PHY_PORT_HOST] = {
+                               .phy_sus        = { 0x0728, 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 },
+                               .utmi_ls        = { 0x049c, 14, 13, 0, 1 },
+                               .utmi_hstdet    = { 0x049c, 12, 12, 0, 1 }
+                       }
+               },
+       },
+       { /* sentinel */ }
+};
+
+static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
+       {
+               .reg            = 0xe450,
+               .num_ports      = 2,
+               .clkout_ctl     = { 0xe450, 4, 4, 1, 0 },
+               .port_cfgs      = {
+                       [USB2PHY_PORT_OTG] = {
+                               .phy_sus        = { 0xe454, 1, 0, 2, 1 },
+                               .bvalid_det_en  = { 0xe3c0, 3, 3, 0, 1 },
+                               .bvalid_det_st  = { 0xe3e0, 3, 3, 0, 1 },
+                               .bvalid_det_clr = { 0xe3d0, 3, 3, 0, 1 },
+                               .utmi_avalid    = { 0xe2ac, 7, 7, 0, 1 },
+                               .utmi_bvalid    = { 0xe2ac, 12, 12, 0, 1 },
+                       },
+                       [USB2PHY_PORT_HOST] = {
+                               .phy_sus        = { 0xe458, 1, 0, 0x2, 0x1 },
+                               .ls_det_en      = { 0xe3c0, 6, 6, 0, 1 },
+                               .ls_det_st      = { 0xe3e0, 6, 6, 0, 1 },
+                               .ls_det_clr     = { 0xe3d0, 6, 6, 0, 1 },
+                               .utmi_ls        = { 0xe2ac, 22, 21, 0, 1 },
+                               .utmi_hstdet    = { 0xe2ac, 23, 23, 0, 1 }
+                       }
+               },
+               .chg_det = {
+                       .opmode         = { 0xe454, 3, 0, 5, 1 },
+                       .cp_det         = { 0xe2ac, 2, 2, 0, 1 },
+                       .dcp_det        = { 0xe2ac, 1, 1, 0, 1 },
+                       .dp_det         = { 0xe2ac, 0, 0, 0, 1 },
+                       .idm_sink_en    = { 0xe450, 8, 8, 0, 1 },
+                       .idp_sink_en    = { 0xe450, 7, 7, 0, 1 },
+                       .idp_src_en     = { 0xe450, 9, 9, 0, 1 },
+                       .rdm_pdwn_en    = { 0xe450, 10, 10, 0, 1 },
+                       .vdm_src_en     = { 0xe450, 12, 12, 0, 1 },
+                       .vdp_src_en     = { 0xe450, 11, 11, 0, 1 },
+               },
+       },
+       {
+               .reg            = 0xe460,
+               .num_ports      = 2,
+               .clkout_ctl     = { 0xe460, 4, 4, 1, 0 },
+               .port_cfgs      = {
+                       [USB2PHY_PORT_OTG] = {
+                               .phy_sus        = { 0xe464, 1, 0, 2, 1 },
+                               .bvalid_det_en  = { 0xe3c0, 8, 8, 0, 1 },
+                               .bvalid_det_st  = { 0xe3e0, 8, 8, 0, 1 },
+                               .bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 },
+                               .utmi_avalid    = { 0xe2ac, 10, 10, 0, 1 },
+                               .utmi_bvalid    = { 0xe2ac, 16, 16, 0, 1 },
+                       },
+                       [USB2PHY_PORT_HOST] = {
+                               .phy_sus        = { 0xe468, 1, 0, 0x2, 0x1 },
+                               .ls_det_en      = { 0xe3c0, 11, 11, 0, 1 },
+                               .ls_det_st      = { 0xe3e0, 11, 11, 0, 1 },
+                               .ls_det_clr     = { 0xe3d0, 11, 11, 0, 1 },
+                               .utmi_ls        = { 0xe2ac, 26, 25, 0, 1 },
+                               .utmi_hstdet    = { 0xe2ac, 27, 27, 0, 1 }
+                       }
+               },
+       },
+       { /* sentinel */ }
+};
+
+static const struct of_device_id rockchip_usb2phy_dt_match[] = {
+       { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
+       { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
+       { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
+       {}
+};
+MODULE_DEVICE_TABLE(of, rockchip_usb2phy_dt_match);
+
+static struct platform_driver rockchip_usb2phy_driver = {
+       .probe          = rockchip_usb2phy_probe,
+       .driver         = {
+               .name   = "rockchip-usb2phy",
+               .of_match_table = rockchip_usb2phy_dt_match,
+       },
+};
+module_platform_driver(rockchip_usb2phy_driver);
+
+MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip USB2.0 PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/rockchip/phy-rockchip-pcie.c b/drivers/phy/rockchip/phy-rockchip-pcie.c
new file mode 100644 (file)
index 0000000..6904633
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * Rockchip PCIe PHY driver
+ *
+ * Copyright (C) 2016 Shawn Lin <shawn.lin@rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, 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; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+/*
+ * The higher 16-bit of this register is used for write protection
+ * only if BIT(x + 16) set to 1 the BIT(x) can be written.
+ */
+#define HIWORD_UPDATE(val, mask, shift) \
+               ((val) << (shift) | (mask) << ((shift) + 16))
+
+#define PHY_MAX_LANE_NUM      4
+#define PHY_CFG_DATA_SHIFT    7
+#define PHY_CFG_ADDR_SHIFT    1
+#define PHY_CFG_DATA_MASK     0xf
+#define PHY_CFG_ADDR_MASK     0x3f
+#define PHY_CFG_RD_MASK       0x3ff
+#define PHY_CFG_WR_ENABLE     1
+#define PHY_CFG_WR_DISABLE    1
+#define PHY_CFG_WR_SHIFT      0
+#define PHY_CFG_WR_MASK       1
+#define PHY_CFG_PLL_LOCK      0x10
+#define PHY_CFG_CLK_TEST      0x10
+#define PHY_CFG_CLK_SCC       0x12
+#define PHY_CFG_SEPE_RATE     BIT(3)
+#define PHY_CFG_PLL_100M      BIT(3)
+#define PHY_PLL_LOCKED        BIT(9)
+#define PHY_PLL_OUTPUT        BIT(10)
+#define PHY_LANE_A_STATUS     0x30
+#define PHY_LANE_B_STATUS     0x31
+#define PHY_LANE_C_STATUS     0x32
+#define PHY_LANE_D_STATUS     0x33
+#define PHY_LANE_RX_DET_SHIFT 11
+#define PHY_LANE_RX_DET_TH    0x1
+#define PHY_LANE_IDLE_OFF     0x1
+#define PHY_LANE_IDLE_MASK    0x1
+#define PHY_LANE_IDLE_A_SHIFT 3
+#define PHY_LANE_IDLE_B_SHIFT 4
+#define PHY_LANE_IDLE_C_SHIFT 5
+#define PHY_LANE_IDLE_D_SHIFT 6
+
+struct rockchip_pcie_data {
+       unsigned int pcie_conf;
+       unsigned int pcie_status;
+       unsigned int pcie_laneoff;
+};
+
+struct rockchip_pcie_phy {
+       struct rockchip_pcie_data *phy_data;
+       struct regmap *reg_base;
+       struct reset_control *phy_rst;
+       struct clk *clk_pciephy_ref;
+};
+
+static inline void phy_wr_cfg(struct rockchip_pcie_phy *rk_phy,
+                             u32 addr, u32 data)
+{
+       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
+                    HIWORD_UPDATE(data,
+                                  PHY_CFG_DATA_MASK,
+                                  PHY_CFG_DATA_SHIFT) |
+                    HIWORD_UPDATE(addr,
+                                  PHY_CFG_ADDR_MASK,
+                                  PHY_CFG_ADDR_SHIFT));
+       udelay(1);
+       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
+                    HIWORD_UPDATE(PHY_CFG_WR_ENABLE,
+                                  PHY_CFG_WR_MASK,
+                                  PHY_CFG_WR_SHIFT));
+       udelay(1);
+       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
+                    HIWORD_UPDATE(PHY_CFG_WR_DISABLE,
+                                  PHY_CFG_WR_MASK,
+                                  PHY_CFG_WR_SHIFT));
+}
+
+static inline u32 phy_rd_cfg(struct rockchip_pcie_phy *rk_phy,
+                            u32 addr)
+{
+       u32 val;
+
+       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
+                    HIWORD_UPDATE(addr,
+                                  PHY_CFG_RD_MASK,
+                                  PHY_CFG_ADDR_SHIFT));
+       regmap_read(rk_phy->reg_base,
+                   rk_phy->phy_data->pcie_status,
+                   &val);
+       return val;
+}
+
+static int rockchip_pcie_phy_power_off(struct phy *phy)
+{
+       struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy);
+       int err = 0;
+
+       err = reset_control_assert(rk_phy->phy_rst);
+       if (err) {
+               dev_err(&phy->dev, "assert phy_rst err %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static int rockchip_pcie_phy_power_on(struct phy *phy)
+{
+       struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy);
+       int err = 0;
+       u32 status;
+       unsigned long timeout;
+
+       err = reset_control_deassert(rk_phy->phy_rst);
+       if (err) {
+               dev_err(&phy->dev, "deassert phy_rst err %d\n", err);
+               return err;
+       }
+
+       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
+                    HIWORD_UPDATE(PHY_CFG_PLL_LOCK,
+                                  PHY_CFG_ADDR_MASK,
+                                  PHY_CFG_ADDR_SHIFT));
+
+       /*
+        * No documented timeout value for phy operation below,
+        * so we make it large enough here. And we use loop-break
+        * method which should not be harmful.
+        */
+       timeout = jiffies + msecs_to_jiffies(1000);
+
+       err = -EINVAL;
+       while (time_before(jiffies, timeout)) {
+               regmap_read(rk_phy->reg_base,
+                           rk_phy->phy_data->pcie_status,
+                           &status);
+               if (status & PHY_PLL_LOCKED) {
+                       dev_dbg(&phy->dev, "pll locked!\n");
+                       err = 0;
+                       break;
+               }
+               msleep(20);
+       }
+
+       if (err) {
+               dev_err(&phy->dev, "pll lock timeout!\n");
+               goto err_pll_lock;
+       }
+
+       phy_wr_cfg(rk_phy, PHY_CFG_CLK_TEST, PHY_CFG_SEPE_RATE);
+       phy_wr_cfg(rk_phy, PHY_CFG_CLK_SCC, PHY_CFG_PLL_100M);
+
+       err = -ETIMEDOUT;
+       while (time_before(jiffies, timeout)) {
+               regmap_read(rk_phy->reg_base,
+                           rk_phy->phy_data->pcie_status,
+                           &status);
+               if (!(status & PHY_PLL_OUTPUT)) {
+                       dev_dbg(&phy->dev, "pll output enable done!\n");
+                       err = 0;
+                       break;
+               }
+               msleep(20);
+       }
+
+       if (err) {
+               dev_err(&phy->dev, "pll output enable timeout!\n");
+               goto err_pll_lock;
+       }
+
+       regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
+                    HIWORD_UPDATE(PHY_CFG_PLL_LOCK,
+                                  PHY_CFG_ADDR_MASK,
+                                  PHY_CFG_ADDR_SHIFT));
+       err = -EINVAL;
+       while (time_before(jiffies, timeout)) {
+               regmap_read(rk_phy->reg_base,
+                           rk_phy->phy_data->pcie_status,
+                           &status);
+               if (status & PHY_PLL_LOCKED) {
+                       dev_dbg(&phy->dev, "pll relocked!\n");
+                       err = 0;
+                       break;
+               }
+               msleep(20);
+       }
+
+       if (err) {
+               dev_err(&phy->dev, "pll relock timeout!\n");
+               goto err_pll_lock;
+       }
+
+       return 0;
+
+err_pll_lock:
+       reset_control_assert(rk_phy->phy_rst);
+       return err;
+}
+
+static int rockchip_pcie_phy_init(struct phy *phy)
+{
+       struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy);
+       int err = 0;
+
+       err = clk_prepare_enable(rk_phy->clk_pciephy_ref);
+       if (err) {
+               dev_err(&phy->dev, "Fail to enable pcie ref clock.\n");
+               goto err_refclk;
+       }
+
+       err = reset_control_assert(rk_phy->phy_rst);
+       if (err) {
+               dev_err(&phy->dev, "assert phy_rst err %d\n", err);
+               goto err_reset;
+       }
+
+       return err;
+
+err_reset:
+       clk_disable_unprepare(rk_phy->clk_pciephy_ref);
+err_refclk:
+       return err;
+}
+
+static int rockchip_pcie_phy_exit(struct phy *phy)
+{
+       struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy);
+
+       clk_disable_unprepare(rk_phy->clk_pciephy_ref);
+
+       return 0;
+}
+
+static const struct phy_ops ops = {
+       .init           = rockchip_pcie_phy_init,
+       .exit           = rockchip_pcie_phy_exit,
+       .power_on       = rockchip_pcie_phy_power_on,
+       .power_off      = rockchip_pcie_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static const struct rockchip_pcie_data rk3399_pcie_data = {
+       .pcie_conf = 0xe220,
+       .pcie_status = 0xe2a4,
+       .pcie_laneoff = 0xe214,
+};
+
+static const struct of_device_id rockchip_pcie_phy_dt_ids[] = {
+       {
+               .compatible = "rockchip,rk3399-pcie-phy",
+               .data = &rk3399_pcie_data,
+       },
+       {}
+};
+
+MODULE_DEVICE_TABLE(of, rockchip_pcie_phy_dt_ids);
+
+static int rockchip_pcie_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct rockchip_pcie_phy *rk_phy;
+       struct phy *generic_phy;
+       struct phy_provider *phy_provider;
+       struct regmap *grf;
+       const struct of_device_id *of_id;
+
+       grf = syscon_node_to_regmap(dev->parent->of_node);
+       if (IS_ERR(grf)) {
+               dev_err(dev, "Cannot find GRF syscon\n");
+               return PTR_ERR(grf);
+       }
+
+       rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
+       if (!rk_phy)
+               return -ENOMEM;
+
+       of_id = of_match_device(rockchip_pcie_phy_dt_ids, &pdev->dev);
+       if (!of_id)
+               return -EINVAL;
+
+       rk_phy->phy_data = (struct rockchip_pcie_data *)of_id->data;
+       rk_phy->reg_base = grf;
+
+       rk_phy->phy_rst = devm_reset_control_get(dev, "phy");
+       if (IS_ERR(rk_phy->phy_rst)) {
+               if (PTR_ERR(rk_phy->phy_rst) != -EPROBE_DEFER)
+                       dev_err(dev,
+                               "missing phy property for reset controller\n");
+               return PTR_ERR(rk_phy->phy_rst);
+       }
+
+       rk_phy->clk_pciephy_ref = devm_clk_get(dev, "refclk");
+       if (IS_ERR(rk_phy->clk_pciephy_ref)) {
+               dev_err(dev, "refclk not found.\n");
+               return PTR_ERR(rk_phy->clk_pciephy_ref);
+       }
+
+       generic_phy = devm_phy_create(dev, dev->of_node, &ops);
+       if (IS_ERR(generic_phy)) {
+               dev_err(dev, "failed to create PHY\n");
+               return PTR_ERR(generic_phy);
+       }
+
+       phy_set_drvdata(generic_phy, rk_phy);
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static struct platform_driver rockchip_pcie_driver = {
+       .probe          = rockchip_pcie_phy_probe,
+       .driver         = {
+               .name   = "rockchip-pcie-phy",
+               .of_match_table = rockchip_pcie_phy_dt_ids,
+       },
+};
+
+module_platform_driver(rockchip_pcie_driver);
+
+MODULE_AUTHOR("Shawn Lin <shawn.lin@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip PCIe PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
new file mode 100644 (file)
index 0000000..7cfb0f8
--- /dev/null
@@ -0,0 +1,1023 @@
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Chris Zhong <zyw@rock-chips.com>
+ *         Kever Yang <kever.yang@rock-chips.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * The ROCKCHIP Type-C PHY has two PLL clocks. The first PLL clock
+ * is used for USB3, the second PLL clock is used for DP. This Type-C PHY has
+ * 3 working modes: USB3 only mode, DP only mode, and USB3+DP mode.
+ * At USB3 only mode, both PLL clocks need to be initialized, this allows the
+ * PHY to switch mode between USB3 and USB3+DP, without disconnecting the USB
+ * device.
+ * In The DP only mode, only the DP PLL needs to be powered on, and the 4 lanes
+ * are all used for DP.
+ *
+ * This driver gets extcon cable state and property, then decides which mode to
+ * select:
+ *
+ * 1. USB3 only mode:
+ *    EXTCON_USB or EXTCON_USB_HOST state is true, and
+ *    EXTCON_PROP_USB_SS property is true.
+ *    EXTCON_DISP_DP state is false.
+ *
+ * 2. DP only mode:
+ *    EXTCON_DISP_DP state is true, and
+ *    EXTCON_PROP_USB_SS property is false.
+ *    If EXTCON_USB_HOST state is true, it is DP + USB2 mode, since the USB2 phy
+ *    is a separate phy, so this case is still DP only mode.
+ *
+ * 3. USB3+DP mode:
+ *    EXTCON_USB_HOST and EXTCON_DISP_DP are both true, and
+ *    EXTCON_PROP_USB_SS property is true.
+ *
+ * This Type-C PHY driver supports normal and flip orientation. The orientation
+ * is reported by the EXTCON_PROP_USB_TYPEC_POLARITY property: true is flip
+ * orientation, false is normal orientation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/extcon.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <linux/mfd/syscon.h>
+#include <linux/phy/phy.h>
+
+#define CMN_SSM_BANDGAP                        (0x21 << 2)
+#define CMN_SSM_BIAS                   (0x22 << 2)
+#define CMN_PLLSM0_PLLEN               (0x29 << 2)
+#define CMN_PLLSM0_PLLPRE              (0x2a << 2)
+#define CMN_PLLSM0_PLLVREF             (0x2b << 2)
+#define CMN_PLLSM0_PLLLOCK             (0x2c << 2)
+#define CMN_PLLSM1_PLLEN               (0x31 << 2)
+#define CMN_PLLSM1_PLLPRE              (0x32 << 2)
+#define CMN_PLLSM1_PLLVREF             (0x33 << 2)
+#define CMN_PLLSM1_PLLLOCK             (0x34 << 2)
+#define CMN_PLLSM1_USER_DEF_CTRL       (0x37 << 2)
+#define CMN_ICAL_OVRD                  (0xc1 << 2)
+#define CMN_PLL0_VCOCAL_OVRD           (0x83 << 2)
+#define CMN_PLL0_VCOCAL_INIT           (0x84 << 2)
+#define CMN_PLL0_VCOCAL_ITER           (0x85 << 2)
+#define CMN_PLL0_LOCK_REFCNT_START     (0x90 << 2)
+#define CMN_PLL0_LOCK_PLLCNT_START     (0x92 << 2)
+#define CMN_PLL0_LOCK_PLLCNT_THR       (0x93 << 2)
+#define CMN_PLL0_INTDIV                        (0x94 << 2)
+#define CMN_PLL0_FRACDIV               (0x95 << 2)
+#define CMN_PLL0_HIGH_THR              (0x96 << 2)
+#define CMN_PLL0_DSM_DIAG              (0x97 << 2)
+#define CMN_PLL0_SS_CTRL1              (0x98 << 2)
+#define CMN_PLL0_SS_CTRL2              (0x99 << 2)
+#define CMN_PLL1_VCOCAL_START          (0xa1 << 2)
+#define CMN_PLL1_VCOCAL_OVRD           (0xa3 << 2)
+#define CMN_PLL1_VCOCAL_INIT           (0xa4 << 2)
+#define CMN_PLL1_VCOCAL_ITER           (0xa5 << 2)
+#define CMN_PLL1_LOCK_REFCNT_START     (0xb0 << 2)
+#define CMN_PLL1_LOCK_PLLCNT_START     (0xb2 << 2)
+#define CMN_PLL1_LOCK_PLLCNT_THR       (0xb3 << 2)
+#define CMN_PLL1_INTDIV                        (0xb4 << 2)
+#define CMN_PLL1_FRACDIV               (0xb5 << 2)
+#define CMN_PLL1_HIGH_THR              (0xb6 << 2)
+#define CMN_PLL1_DSM_DIAG              (0xb7 << 2)
+#define CMN_PLL1_SS_CTRL1              (0xb8 << 2)
+#define CMN_PLL1_SS_CTRL2              (0xb9 << 2)
+#define CMN_RXCAL_OVRD                 (0xd1 << 2)
+#define CMN_TXPUCAL_CTRL               (0xe0 << 2)
+#define CMN_TXPUCAL_OVRD               (0xe1 << 2)
+#define CMN_TXPDCAL_OVRD               (0xf1 << 2)
+#define CMN_DIAG_PLL0_FBH_OVRD         (0x1c0 << 2)
+#define CMN_DIAG_PLL0_FBL_OVRD         (0x1c1 << 2)
+#define CMN_DIAG_PLL0_OVRD             (0x1c2 << 2)
+#define CMN_DIAG_PLL0_V2I_TUNE         (0x1c5 << 2)
+#define CMN_DIAG_PLL0_CP_TUNE          (0x1c6 << 2)
+#define CMN_DIAG_PLL0_LF_PROG          (0x1c7 << 2)
+#define CMN_DIAG_PLL1_FBH_OVRD         (0x1d0 << 2)
+#define CMN_DIAG_PLL1_FBL_OVRD         (0x1d1 << 2)
+#define CMN_DIAG_PLL1_OVRD             (0x1d2 << 2)
+#define CMN_DIAG_PLL1_V2I_TUNE         (0x1d5 << 2)
+#define CMN_DIAG_PLL1_CP_TUNE          (0x1d6 << 2)
+#define CMN_DIAG_PLL1_LF_PROG          (0x1d7 << 2)
+#define CMN_DIAG_PLL1_PTATIS_TUNE1     (0x1d8 << 2)
+#define CMN_DIAG_PLL1_PTATIS_TUNE2     (0x1d9 << 2)
+#define CMN_DIAG_PLL1_INCLK_CTRL       (0x1da << 2)
+#define CMN_DIAG_HSCLK_SEL             (0x1e0 << 2)
+
+#define XCVR_PSM_RCTRL(n)              ((0x4001 | ((n) << 9)) << 2)
+#define XCVR_PSM_CAL_TMR(n)            ((0x4002 | ((n) << 9)) << 2)
+#define XCVR_PSM_A0IN_TMR(n)           ((0x4003 | ((n) << 9)) << 2)
+#define TX_TXCC_CAL_SCLR_MULT(n)       ((0x4047 | ((n) << 9)) << 2)
+#define TX_TXCC_CPOST_MULT_00(n)       ((0x404c | ((n) << 9)) << 2)
+#define TX_TXCC_CPOST_MULT_01(n)       ((0x404d | ((n) << 9)) << 2)
+#define TX_TXCC_CPOST_MULT_10(n)       ((0x404e | ((n) << 9)) << 2)
+#define TX_TXCC_CPOST_MULT_11(n)       ((0x404f | ((n) << 9)) << 2)
+#define TX_TXCC_MGNFS_MULT_000(n)      ((0x4050 | ((n) << 9)) << 2)
+#define TX_TXCC_MGNFS_MULT_001(n)      ((0x4051 | ((n) << 9)) << 2)
+#define TX_TXCC_MGNFS_MULT_010(n)      ((0x4052 | ((n) << 9)) << 2)
+#define TX_TXCC_MGNFS_MULT_011(n)      ((0x4053 | ((n) << 9)) << 2)
+#define TX_TXCC_MGNFS_MULT_100(n)      ((0x4054 | ((n) << 9)) << 2)
+#define TX_TXCC_MGNFS_MULT_101(n)      ((0x4055 | ((n) << 9)) << 2)
+#define TX_TXCC_MGNFS_MULT_110(n)      ((0x4056 | ((n) << 9)) << 2)
+#define TX_TXCC_MGNFS_MULT_111(n)      ((0x4057 | ((n) << 9)) << 2)
+#define XCVR_DIAG_PLLDRC_CTRL(n)       ((0x40e0 | ((n) << 9)) << 2)
+#define XCVR_DIAG_BIDI_CTRL(n)         ((0x40e8 | ((n) << 9)) << 2)
+#define XCVR_DIAG_LANE_FCM_EN_MGN(n)   ((0x40f2 | ((n) << 9)) << 2)
+#define TX_PSC_A0(n)                   ((0x4100 | ((n) << 9)) << 2)
+#define TX_PSC_A1(n)                   ((0x4101 | ((n) << 9)) << 2)
+#define TX_PSC_A2(n)                   ((0x4102 | ((n) << 9)) << 2)
+#define TX_PSC_A3(n)                   ((0x4103 | ((n) << 9)) << 2)
+#define TX_RCVDET_CTRL(n)              ((0x4120 | ((n) << 9)) << 2)
+#define TX_RCVDET_EN_TMR(n)            ((0x4122 | ((n) << 9)) << 2)
+#define TX_RCVDET_ST_TMR(n)            ((0x4123 | ((n) << 9)) << 2)
+#define TX_DIAG_TX_DRV(n)              ((0x41e1 | ((n) << 9)) << 2)
+#define TX_DIAG_BGREF_PREDRV_DELAY     (0x41e7 << 2)
+#define TX_ANA_CTRL_REG_1              (0x5020 << 2)
+#define TX_ANA_CTRL_REG_2              (0x5021 << 2)
+#define TXDA_COEFF_CALC_CTRL           (0x5022 << 2)
+#define TX_DIG_CTRL_REG_2              (0x5024 << 2)
+#define TXDA_CYA_AUXDA_CYA             (0x5025 << 2)
+#define TX_ANA_CTRL_REG_3              (0x5026 << 2)
+#define TX_ANA_CTRL_REG_4              (0x5027 << 2)
+#define TX_ANA_CTRL_REG_5              (0x5029 << 2)
+
+#define RX_PSC_A0(n)                   ((0x8000 | ((n) << 9)) << 2)
+#define RX_PSC_A1(n)                   ((0x8001 | ((n) << 9)) << 2)
+#define RX_PSC_A2(n)                   ((0x8002 | ((n) << 9)) << 2)
+#define RX_PSC_A3(n)                   ((0x8003 | ((n) << 9)) << 2)
+#define RX_PSC_CAL(n)                  ((0x8006 | ((n) << 9)) << 2)
+#define RX_PSC_RDY(n)                  ((0x8007 | ((n) << 9)) << 2)
+#define RX_IQPI_ILL_CAL_OVRD           (0x8023 << 2)
+#define RX_EPI_ILL_CAL_OVRD            (0x8033 << 2)
+#define RX_SDCAL0_OVRD                 (0x8041 << 2)
+#define RX_SDCAL1_OVRD                 (0x8049 << 2)
+#define RX_SLC_INIT                    (0x806d << 2)
+#define RX_SLC_RUN                     (0x806e << 2)
+#define RX_CDRLF_CNFG2                 (0x8081 << 2)
+#define RX_SIGDET_HL_FILT_TMR(n)       ((0x8090 | ((n) << 9)) << 2)
+#define RX_SLC_IOP0_OVRD               (0x8101 << 2)
+#define RX_SLC_IOP1_OVRD               (0x8105 << 2)
+#define RX_SLC_QOP0_OVRD               (0x8109 << 2)
+#define RX_SLC_QOP1_OVRD               (0x810d << 2)
+#define RX_SLC_EOP0_OVRD               (0x8111 << 2)
+#define RX_SLC_EOP1_OVRD               (0x8115 << 2)
+#define RX_SLC_ION0_OVRD               (0x8119 << 2)
+#define RX_SLC_ION1_OVRD               (0x811d << 2)
+#define RX_SLC_QON0_OVRD               (0x8121 << 2)
+#define RX_SLC_QON1_OVRD               (0x8125 << 2)
+#define RX_SLC_EON0_OVRD               (0x8129 << 2)
+#define RX_SLC_EON1_OVRD               (0x812d << 2)
+#define RX_SLC_IEP0_OVRD               (0x8131 << 2)
+#define RX_SLC_IEP1_OVRD               (0x8135 << 2)
+#define RX_SLC_QEP0_OVRD               (0x8139 << 2)
+#define RX_SLC_QEP1_OVRD               (0x813d << 2)
+#define RX_SLC_EEP0_OVRD               (0x8141 << 2)
+#define RX_SLC_EEP1_OVRD               (0x8145 << 2)
+#define RX_SLC_IEN0_OVRD               (0x8149 << 2)
+#define RX_SLC_IEN1_OVRD               (0x814d << 2)
+#define RX_SLC_QEN0_OVRD               (0x8151 << 2)
+#define RX_SLC_QEN1_OVRD               (0x8155 << 2)
+#define RX_SLC_EEN0_OVRD               (0x8159 << 2)
+#define RX_SLC_EEN1_OVRD               (0x815d << 2)
+#define RX_REE_CTRL_DATA_MASK(n)       ((0x81bb | ((n) << 9)) << 2)
+#define RX_DIAG_SIGDET_TUNE(n)         ((0x81dc | ((n) << 9)) << 2)
+#define RX_DIAG_SC2C_DELAY             (0x81e1 << 2)
+
+#define PMA_LANE_CFG                   (0xc000 << 2)
+#define PIPE_CMN_CTRL1                 (0xc001 << 2)
+#define PIPE_CMN_CTRL2                 (0xc002 << 2)
+#define PIPE_COM_LOCK_CFG1             (0xc003 << 2)
+#define PIPE_COM_LOCK_CFG2             (0xc004 << 2)
+#define PIPE_RCV_DET_INH               (0xc005 << 2)
+#define DP_MODE_CTL                    (0xc008 << 2)
+#define DP_CLK_CTL                     (0xc009 << 2)
+#define STS                            (0xc00F << 2)
+#define PHY_ISO_CMN_CTRL               (0xc010 << 2)
+#define PHY_DP_TX_CTL                  (0xc408 << 2)
+#define PMA_CMN_CTRL1                  (0xc800 << 2)
+#define PHY_PMA_ISO_CMN_CTRL           (0xc810 << 2)
+#define PHY_ISOLATION_CTRL             (0xc81f << 2)
+#define PHY_PMA_ISO_XCVR_CTRL(n)       ((0xcc11 | ((n) << 6)) << 2)
+#define PHY_PMA_ISO_LINK_MODE(n)       ((0xcc12 | ((n) << 6)) << 2)
+#define PHY_PMA_ISO_PWRST_CTRL(n)      ((0xcc13 | ((n) << 6)) << 2)
+#define PHY_PMA_ISO_TX_DATA_LO(n)      ((0xcc14 | ((n) << 6)) << 2)
+#define PHY_PMA_ISO_TX_DATA_HI(n)      ((0xcc15 | ((n) << 6)) << 2)
+#define PHY_PMA_ISO_RX_DATA_LO(n)      ((0xcc16 | ((n) << 6)) << 2)
+#define PHY_PMA_ISO_RX_DATA_HI(n)      ((0xcc17 | ((n) << 6)) << 2)
+#define TX_BIST_CTRL(n)                        ((0x4140 | ((n) << 9)) << 2)
+#define TX_BIST_UDDWR(n)               ((0x4141 | ((n) << 9)) << 2)
+
+/*
+ * Selects which PLL clock will be driven on the analog high speed
+ * clock 0: PLL 0 div 1
+ * clock 1: PLL 1 div 2
+ */
+#define CLK_PLL_CONFIG                 0X30
+#define CLK_PLL_MASK                   0x33
+
+#define CMN_READY                      BIT(0)
+
+#define DP_PLL_CLOCK_ENABLE            BIT(2)
+#define DP_PLL_ENABLE                  BIT(0)
+#define DP_PLL_DATA_RATE_RBR           ((2 << 12) | (4 << 8))
+#define DP_PLL_DATA_RATE_HBR           ((2 << 12) | (4 << 8))
+#define DP_PLL_DATA_RATE_HBR2          ((1 << 12) | (2 << 8))
+
+#define DP_MODE_A0                     BIT(4)
+#define DP_MODE_A2                     BIT(6)
+#define DP_MODE_ENTER_A0               0xc101
+#define DP_MODE_ENTER_A2               0xc104
+
+#define PHY_MODE_SET_TIMEOUT           100000
+
+#define PIN_ASSIGN_C_E                 0x51d9
+#define PIN_ASSIGN_D_F                 0x5100
+
+#define MODE_DISCONNECT                        0
+#define MODE_UFP_USB                   BIT(0)
+#define MODE_DFP_USB                   BIT(1)
+#define MODE_DFP_DP                    BIT(2)
+
+struct usb3phy_reg {
+       u32 offset;
+       u32 enable_bit;
+       u32 write_enable;
+};
+
+struct rockchip_usb3phy_port_cfg {
+       struct usb3phy_reg typec_conn_dir;
+       struct usb3phy_reg usb3tousb2_en;
+       struct usb3phy_reg external_psm;
+       struct usb3phy_reg pipe_status;
+};
+
+struct rockchip_typec_phy {
+       struct device *dev;
+       void __iomem *base;
+       struct extcon_dev *extcon;
+       struct regmap *grf_regs;
+       struct clk *clk_core;
+       struct clk *clk_ref;
+       struct reset_control *uphy_rst;
+       struct reset_control *pipe_rst;
+       struct reset_control *tcphy_rst;
+       struct rockchip_usb3phy_port_cfg port_cfgs;
+       /* mutex to protect access to individual PHYs */
+       struct mutex lock;
+
+       bool flip;
+       u8 mode;
+};
+
+struct phy_reg {
+       u16 value;
+       u32 addr;
+};
+
+struct phy_reg usb3_pll_cfg[] = {
+       { 0xf0,         CMN_PLL0_VCOCAL_INIT },
+       { 0x18,         CMN_PLL0_VCOCAL_ITER },
+       { 0xd0,         CMN_PLL0_INTDIV },
+       { 0x4a4a,       CMN_PLL0_FRACDIV },
+       { 0x34,         CMN_PLL0_HIGH_THR },
+       { 0x1ee,        CMN_PLL0_SS_CTRL1 },
+       { 0x7f03,       CMN_PLL0_SS_CTRL2 },
+       { 0x20,         CMN_PLL0_DSM_DIAG },
+       { 0,            CMN_DIAG_PLL0_OVRD },
+       { 0,            CMN_DIAG_PLL0_FBH_OVRD },
+       { 0,            CMN_DIAG_PLL0_FBL_OVRD },
+       { 0x7,          CMN_DIAG_PLL0_V2I_TUNE },
+       { 0x45,         CMN_DIAG_PLL0_CP_TUNE },
+       { 0x8,          CMN_DIAG_PLL0_LF_PROG },
+};
+
+struct phy_reg dp_pll_cfg[] = {
+       { 0xf0,         CMN_PLL1_VCOCAL_INIT },
+       { 0x18,         CMN_PLL1_VCOCAL_ITER },
+       { 0x30b9,       CMN_PLL1_VCOCAL_START },
+       { 0x21c,        CMN_PLL1_INTDIV },
+       { 0,            CMN_PLL1_FRACDIV },
+       { 0x5,          CMN_PLL1_HIGH_THR },
+       { 0x35,         CMN_PLL1_SS_CTRL1 },
+       { 0x7f1e,       CMN_PLL1_SS_CTRL2 },
+       { 0x20,         CMN_PLL1_DSM_DIAG },
+       { 0,            CMN_PLLSM1_USER_DEF_CTRL },
+       { 0,            CMN_DIAG_PLL1_OVRD },
+       { 0,            CMN_DIAG_PLL1_FBH_OVRD },
+       { 0,            CMN_DIAG_PLL1_FBL_OVRD },
+       { 0x6,          CMN_DIAG_PLL1_V2I_TUNE },
+       { 0x45,         CMN_DIAG_PLL1_CP_TUNE },
+       { 0x8,          CMN_DIAG_PLL1_LF_PROG },
+       { 0x100,        CMN_DIAG_PLL1_PTATIS_TUNE1 },
+       { 0x7,          CMN_DIAG_PLL1_PTATIS_TUNE2 },
+       { 0x4,          CMN_DIAG_PLL1_INCLK_CTRL },
+};
+
+static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy)
+{
+       u32 i, rdata;
+
+       /*
+        * cmn_ref_clk_sel = 3, select the 24Mhz for clk parent
+        * cmn_psm_clk_dig_div = 2, set the clk division to 2
+        */
+       writel(0x830, tcphy->base + PMA_CMN_CTRL1);
+       for (i = 0; i < 4; i++) {
+               /*
+                * The following PHY configuration assumes a 24 MHz reference
+                * clock.
+                */
+               writel(0x90, tcphy->base + XCVR_DIAG_LANE_FCM_EN_MGN(i));
+               writel(0x960, tcphy->base + TX_RCVDET_EN_TMR(i));
+               writel(0x30, tcphy->base + TX_RCVDET_ST_TMR(i));
+       }
+
+       rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
+       rdata &= ~CLK_PLL_MASK;
+       rdata |= CLK_PLL_CONFIG;
+       writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
+}
+
+static void tcphy_cfg_usb3_pll(struct rockchip_typec_phy *tcphy)
+{
+       u32 i;
+
+       /* load the configuration of PLL0 */
+       for (i = 0; i < ARRAY_SIZE(usb3_pll_cfg); i++)
+               writel(usb3_pll_cfg[i].value,
+                      tcphy->base + usb3_pll_cfg[i].addr);
+}
+
+static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
+{
+       u32 i;
+
+       /* set the default mode to RBR */
+       writel(DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE | DP_PLL_DATA_RATE_RBR,
+              tcphy->base + DP_CLK_CTL);
+
+       /* load the configuration of PLL1 */
+       for (i = 0; i < ARRAY_SIZE(dp_pll_cfg); i++)
+               writel(dp_pll_cfg[i].value, tcphy->base + dp_pll_cfg[i].addr);
+}
+
+static void tcphy_tx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
+{
+       writel(0x7799, tcphy->base + TX_PSC_A0(lane));
+       writel(0x7798, tcphy->base + TX_PSC_A1(lane));
+       writel(0x5098, tcphy->base + TX_PSC_A2(lane));
+       writel(0x5098, tcphy->base + TX_PSC_A3(lane));
+       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
+       writel(0xbf, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
+}
+
+static void tcphy_rx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
+{
+       writel(0xa6fd, tcphy->base + RX_PSC_A0(lane));
+       writel(0xa6fd, tcphy->base + RX_PSC_A1(lane));
+       writel(0xa410, tcphy->base + RX_PSC_A2(lane));
+       writel(0x2410, tcphy->base + RX_PSC_A3(lane));
+       writel(0x23ff, tcphy->base + RX_PSC_CAL(lane));
+       writel(0x13, tcphy->base + RX_SIGDET_HL_FILT_TMR(lane));
+       writel(0x03e7, tcphy->base + RX_REE_CTRL_DATA_MASK(lane));
+       writel(0x1004, tcphy->base + RX_DIAG_SIGDET_TUNE(lane));
+       writel(0x2010, tcphy->base + RX_PSC_RDY(lane));
+       writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
+}
+
+static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
+{
+       u16 rdata;
+
+       writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
+       writel(0x6799, tcphy->base + TX_PSC_A0(lane));
+       writel(0x6798, tcphy->base + TX_PSC_A1(lane));
+       writel(0x98, tcphy->base + TX_PSC_A2(lane));
+       writel(0x98, tcphy->base + TX_PSC_A3(lane));
+
+       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
+       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
+       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
+       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
+       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
+       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
+       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
+       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
+       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
+       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
+       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
+       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
+
+       writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
+       writel(0x400, tcphy->base + TX_DIAG_TX_DRV(lane));
+
+       rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+       rdata = (rdata & 0x8fff) | 0x6000;
+       writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+}
+
+static inline int property_enable(struct rockchip_typec_phy *tcphy,
+                                 const struct usb3phy_reg *reg, bool en)
+{
+       u32 mask = 1 << reg->write_enable;
+       u32 val = en << reg->enable_bit;
+
+       return regmap_write(tcphy->grf_regs, reg->offset, val | mask);
+}
+
+static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
+{
+       u16 rdata, rdata2, val;
+
+       /* disable txda_cal_latch_en for rewrite the calibration values */
+       rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
+       val = rdata & 0xdfff;
+       writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
+
+       /*
+        * read a resistor calibration code from CMN_TXPUCAL_CTRL[6:0] and
+        * write it to TX_DIG_CTRL_REG_2[6:0], and delay 1ms to make sure it
+        * works.
+        */
+       rdata = readl(tcphy->base + TX_DIG_CTRL_REG_2);
+       rdata = rdata & 0xffc0;
+
+       rdata2 = readl(tcphy->base + CMN_TXPUCAL_CTRL);
+       rdata2 = rdata2 & 0x3f;
+
+       val = rdata | rdata2;
+       writel(val, tcphy->base + TX_DIG_CTRL_REG_2);
+       usleep_range(1000, 1050);
+
+       /*
+        * Enable signal for latch that sample and holds calibration values.
+        * Activate this signal for 1 clock cycle to sample new calibration
+        * values.
+        */
+       rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
+       val = rdata | 0x2000;
+       writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
+       usleep_range(150, 200);
+
+       /* set TX Voltage Level and TX Deemphasis to 0 */
+       writel(0, tcphy->base + PHY_DP_TX_CTL);
+       /* re-enable decap */
+       writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2);
+       writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2);
+       writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1);
+       writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1);
+
+       writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
+
+       /*
+        * Programs txda_drv_ldo_prog[15:0], Sets driver LDO
+        * voltage 16'h1001 for DP-AUX-TX and RX
+        */
+       writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4);
+
+       /* re-enables Bandgap reference for LDO */
+       writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1);
+       writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1);
+
+       /*
+        * re-enables the transmitter pre-driver, driver data selection MUX,
+        * and receiver detect circuits.
+        */
+       writel(0x301, tcphy->base + TX_ANA_CTRL_REG_2);
+       writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2);
+
+       /*
+        * BIT 12: Controls auxda_polarity, which selects the polarity of the
+        * xcvr:
+        * 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull
+        * down aux_m)
+        * 0, Normal polarity (if TYPE_C, pulls up aux_m and pulls down
+        * aux_p)
+        */
+       val = 0xa078;
+       if (!tcphy->flip)
+               val |= BIT(12);
+       writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
+
+       writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
+       writel(0, tcphy->base + TX_ANA_CTRL_REG_4);
+       writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
+
+       /*
+        * Controls low_power_swing_en, set the voltage swing of the driver
+        * to 400mv. The values below are peak to peak (differential) values.
+        */
+       writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL);
+       writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA);
+
+       /* Controls tx_high_z_tm_en */
+       val = readl(tcphy->base + TX_DIG_CTRL_REG_2);
+       val |= BIT(15);
+       writel(val, tcphy->base + TX_DIG_CTRL_REG_2);
+}
+
+static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
+{
+       struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs;
+       int ret, i;
+       u32 val;
+
+       ret = clk_prepare_enable(tcphy->clk_core);
+       if (ret) {
+               dev_err(tcphy->dev, "Failed to prepare_enable core clock\n");
+               return ret;
+       }
+
+       ret = clk_prepare_enable(tcphy->clk_ref);
+       if (ret) {
+               dev_err(tcphy->dev, "Failed to prepare_enable ref clock\n");
+               goto err_clk_core;
+       }
+
+       reset_control_deassert(tcphy->tcphy_rst);
+
+       property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip);
+
+       tcphy_cfg_24m(tcphy);
+
+       if (mode == MODE_DFP_DP) {
+               tcphy_cfg_dp_pll(tcphy);
+               for (i = 0; i < 4; i++)
+                       tcphy_dp_cfg_lane(tcphy, i);
+
+               writel(PIN_ASSIGN_C_E, tcphy->base + PMA_LANE_CFG);
+       } else {
+               tcphy_cfg_usb3_pll(tcphy);
+               tcphy_cfg_dp_pll(tcphy);
+               if (tcphy->flip) {
+                       tcphy_tx_usb3_cfg_lane(tcphy, 3);
+                       tcphy_rx_usb3_cfg_lane(tcphy, 2);
+                       tcphy_dp_cfg_lane(tcphy, 0);
+                       tcphy_dp_cfg_lane(tcphy, 1);
+               } else {
+                       tcphy_tx_usb3_cfg_lane(tcphy, 0);
+                       tcphy_rx_usb3_cfg_lane(tcphy, 1);
+                       tcphy_dp_cfg_lane(tcphy, 2);
+                       tcphy_dp_cfg_lane(tcphy, 3);
+               }
+
+               writel(PIN_ASSIGN_D_F, tcphy->base + PMA_LANE_CFG);
+       }
+
+       writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+
+       reset_control_deassert(tcphy->uphy_rst);
+
+       ret = readx_poll_timeout(readl, tcphy->base + PMA_CMN_CTRL1,
+                                val, val & CMN_READY, 10,
+                                PHY_MODE_SET_TIMEOUT);
+       if (ret < 0) {
+               dev_err(tcphy->dev, "wait pma ready timeout\n");
+               ret = -ETIMEDOUT;
+               goto err_wait_pma;
+       }
+
+       reset_control_deassert(tcphy->pipe_rst);
+
+       return 0;
+
+err_wait_pma:
+       reset_control_assert(tcphy->uphy_rst);
+       reset_control_assert(tcphy->tcphy_rst);
+       clk_disable_unprepare(tcphy->clk_ref);
+err_clk_core:
+       clk_disable_unprepare(tcphy->clk_core);
+       return ret;
+}
+
+static void tcphy_phy_deinit(struct rockchip_typec_phy *tcphy)
+{
+       reset_control_assert(tcphy->tcphy_rst);
+       reset_control_assert(tcphy->uphy_rst);
+       reset_control_assert(tcphy->pipe_rst);
+       clk_disable_unprepare(tcphy->clk_core);
+       clk_disable_unprepare(tcphy->clk_ref);
+}
+
+static int tcphy_get_mode(struct rockchip_typec_phy *tcphy)
+{
+       struct extcon_dev *edev = tcphy->extcon;
+       union extcon_property_value property;
+       unsigned int id;
+       bool dfp, ufp, dp;
+       u8 mode;
+       int ret;
+
+       ufp = extcon_get_state(edev, EXTCON_USB);
+       dfp = extcon_get_state(edev, EXTCON_USB_HOST);
+       dp = extcon_get_state(edev, EXTCON_DISP_DP);
+
+       mode = MODE_DFP_USB;
+       id = EXTCON_USB_HOST;
+
+       if (ufp) {
+               mode = MODE_UFP_USB;
+               id = EXTCON_USB;
+       } else if (dp) {
+               mode = MODE_DFP_DP;
+               id = EXTCON_DISP_DP;
+
+               ret = extcon_get_property(edev, id, EXTCON_PROP_USB_SS,
+                                         &property);
+               if (ret) {
+                       dev_err(tcphy->dev, "get superspeed property failed\n");
+                       return ret;
+               }
+
+               if (property.intval)
+                       mode |= MODE_DFP_USB;
+       }
+
+       ret = extcon_get_property(edev, id, EXTCON_PROP_USB_TYPEC_POLARITY,
+                                 &property);
+       if (ret) {
+               dev_err(tcphy->dev, "get polarity property failed\n");
+               return ret;
+       }
+
+       tcphy->flip = property.intval ? 1 : 0;
+
+       return mode;
+}
+
+static int rockchip_usb3_phy_power_on(struct phy *phy)
+{
+       struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
+       struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs;
+       const struct usb3phy_reg *reg = &cfg->pipe_status;
+       int timeout, new_mode, ret = 0;
+       u32 val;
+
+       mutex_lock(&tcphy->lock);
+
+       new_mode = tcphy_get_mode(tcphy);
+       if (new_mode < 0) {
+               ret = new_mode;
+               goto unlock_ret;
+       }
+
+       /* DP-only mode; fall back to USB2 */
+       if (!(new_mode & (MODE_DFP_USB | MODE_UFP_USB)))
+               goto unlock_ret;
+
+       if (tcphy->mode == new_mode)
+               goto unlock_ret;
+
+       if (tcphy->mode == MODE_DISCONNECT)
+               tcphy_phy_init(tcphy, new_mode);
+
+       /* wait TCPHY for pipe ready */
+       for (timeout = 0; timeout < 100; timeout++) {
+               regmap_read(tcphy->grf_regs, reg->offset, &val);
+               if (!(val & BIT(reg->enable_bit))) {
+                       tcphy->mode |= new_mode & (MODE_DFP_USB | MODE_UFP_USB);
+                       goto unlock_ret;
+               }
+               usleep_range(10, 20);
+       }
+
+       if (tcphy->mode == MODE_DISCONNECT)
+               tcphy_phy_deinit(tcphy);
+
+       ret = -ETIMEDOUT;
+
+unlock_ret:
+       mutex_unlock(&tcphy->lock);
+       return ret;
+}
+
+static int rockchip_usb3_phy_power_off(struct phy *phy)
+{
+       struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
+
+       mutex_lock(&tcphy->lock);
+
+       if (tcphy->mode == MODE_DISCONNECT)
+               goto unlock;
+
+       tcphy->mode &= ~(MODE_UFP_USB | MODE_DFP_USB);
+       if (tcphy->mode == MODE_DISCONNECT)
+               tcphy_phy_deinit(tcphy);
+
+unlock:
+       mutex_unlock(&tcphy->lock);
+       return 0;
+}
+
+static const struct phy_ops rockchip_usb3_phy_ops = {
+       .power_on       = rockchip_usb3_phy_power_on,
+       .power_off      = rockchip_usb3_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int rockchip_dp_phy_power_on(struct phy *phy)
+{
+       struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
+       int new_mode, ret = 0;
+       u32 val;
+
+       mutex_lock(&tcphy->lock);
+
+       new_mode = tcphy_get_mode(tcphy);
+       if (new_mode < 0) {
+               ret = new_mode;
+               goto unlock_ret;
+       }
+
+       if (!(new_mode & MODE_DFP_DP)) {
+               ret = -ENODEV;
+               goto unlock_ret;
+       }
+
+       if (tcphy->mode == new_mode)
+               goto unlock_ret;
+
+       /*
+        * If the PHY has been power on, but the mode is not DP only mode,
+        * re-init the PHY for setting all of 4 lanes to DP.
+        */
+       if (new_mode == MODE_DFP_DP && tcphy->mode != MODE_DISCONNECT) {
+               tcphy_phy_deinit(tcphy);
+               tcphy_phy_init(tcphy, new_mode);
+       } else if (tcphy->mode == MODE_DISCONNECT) {
+               tcphy_phy_init(tcphy, new_mode);
+       }
+
+       ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
+                                val, val & DP_MODE_A2, 1000,
+                                PHY_MODE_SET_TIMEOUT);
+       if (ret < 0) {
+               dev_err(tcphy->dev, "failed to wait TCPHY enter A2\n");
+               goto power_on_finish;
+       }
+
+       tcphy_dp_aux_calibration(tcphy);
+
+       writel(DP_MODE_ENTER_A0, tcphy->base + DP_MODE_CTL);
+
+       ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
+                                val, val & DP_MODE_A0, 1000,
+                                PHY_MODE_SET_TIMEOUT);
+       if (ret < 0) {
+               writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+               dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
+               goto power_on_finish;
+       }
+
+       tcphy->mode |= MODE_DFP_DP;
+
+power_on_finish:
+       if (tcphy->mode == MODE_DISCONNECT)
+               tcphy_phy_deinit(tcphy);
+unlock_ret:
+       mutex_unlock(&tcphy->lock);
+       return ret;
+}
+
+static int rockchip_dp_phy_power_off(struct phy *phy)
+{
+       struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
+
+       mutex_lock(&tcphy->lock);
+
+       if (tcphy->mode == MODE_DISCONNECT)
+               goto unlock;
+
+       tcphy->mode &= ~MODE_DFP_DP;
+
+       writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL);
+
+       if (tcphy->mode == MODE_DISCONNECT)
+               tcphy_phy_deinit(tcphy);
+
+unlock:
+       mutex_unlock(&tcphy->lock);
+       return 0;
+}
+
+static const struct phy_ops rockchip_dp_phy_ops = {
+       .power_on       = rockchip_dp_phy_power_on,
+       .power_off      = rockchip_dp_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int tcphy_get_param(struct device *dev,
+                          struct usb3phy_reg *reg,
+                          const char *name)
+{
+       u32 buffer[3];
+       int ret;
+
+       ret = of_property_read_u32_array(dev->of_node, name, buffer, 3);
+       if (ret) {
+               dev_err(dev, "Can not parse %s\n", name);
+               return ret;
+       }
+
+       reg->offset = buffer[0];
+       reg->enable_bit = buffer[1];
+       reg->write_enable = buffer[2];
+       return 0;
+}
+
+static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy,
+                         struct device *dev)
+{
+       struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs;
+       int ret;
+
+       ret = tcphy_get_param(dev, &cfg->typec_conn_dir,
+                             "rockchip,typec-conn-dir");
+       if (ret)
+               return ret;
+
+       ret = tcphy_get_param(dev, &cfg->usb3tousb2_en,
+                             "rockchip,usb3tousb2-en");
+       if (ret)
+               return ret;
+
+       ret = tcphy_get_param(dev, &cfg->external_psm,
+                             "rockchip,external-psm");
+       if (ret)
+               return ret;
+
+       ret = tcphy_get_param(dev, &cfg->pipe_status,
+                             "rockchip,pipe-status");
+       if (ret)
+               return ret;
+
+       tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                                         "rockchip,grf");
+       if (IS_ERR(tcphy->grf_regs)) {
+               dev_err(dev, "could not find grf dt node\n");
+               return PTR_ERR(tcphy->grf_regs);
+       }
+
+       tcphy->clk_core = devm_clk_get(dev, "tcpdcore");
+       if (IS_ERR(tcphy->clk_core)) {
+               dev_err(dev, "could not get uphy core clock\n");
+               return PTR_ERR(tcphy->clk_core);
+       }
+
+       tcphy->clk_ref = devm_clk_get(dev, "tcpdphy-ref");
+       if (IS_ERR(tcphy->clk_ref)) {
+               dev_err(dev, "could not get uphy ref clock\n");
+               return PTR_ERR(tcphy->clk_ref);
+       }
+
+       tcphy->uphy_rst = devm_reset_control_get(dev, "uphy");
+       if (IS_ERR(tcphy->uphy_rst)) {
+               dev_err(dev, "no uphy_rst reset control found\n");
+               return PTR_ERR(tcphy->uphy_rst);
+       }
+
+       tcphy->pipe_rst = devm_reset_control_get(dev, "uphy-pipe");
+       if (IS_ERR(tcphy->pipe_rst)) {
+               dev_err(dev, "no pipe_rst reset control found\n");
+               return PTR_ERR(tcphy->pipe_rst);
+       }
+
+       tcphy->tcphy_rst = devm_reset_control_get(dev, "uphy-tcphy");
+       if (IS_ERR(tcphy->tcphy_rst)) {
+               dev_err(dev, "no tcphy_rst reset control found\n");
+               return PTR_ERR(tcphy->tcphy_rst);
+       }
+
+       return 0;
+}
+
+static void typec_phy_pre_init(struct rockchip_typec_phy *tcphy)
+{
+       struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs;
+
+       reset_control_assert(tcphy->tcphy_rst);
+       reset_control_assert(tcphy->uphy_rst);
+       reset_control_assert(tcphy->pipe_rst);
+
+       /* select external psm clock */
+       property_enable(tcphy, &cfg->external_psm, 1);
+       property_enable(tcphy, &cfg->usb3tousb2_en, 0);
+
+       tcphy->mode = MODE_DISCONNECT;
+}
+
+static int rockchip_typec_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct device_node *child_np;
+       struct rockchip_typec_phy *tcphy;
+       struct phy_provider *phy_provider;
+       struct resource *res;
+       int ret;
+
+       tcphy = devm_kzalloc(dev, sizeof(*tcphy), GFP_KERNEL);
+       if (!tcphy)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       tcphy->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(tcphy->base))
+               return PTR_ERR(tcphy->base);
+
+       ret = tcphy_parse_dt(tcphy, dev);
+       if (ret)
+               return ret;
+
+       tcphy->dev = dev;
+       platform_set_drvdata(pdev, tcphy);
+       mutex_init(&tcphy->lock);
+
+       typec_phy_pre_init(tcphy);
+
+       tcphy->extcon = extcon_get_edev_by_phandle(dev, 0);
+       if (IS_ERR(tcphy->extcon)) {
+               if (PTR_ERR(tcphy->extcon) != -EPROBE_DEFER)
+                       dev_err(dev, "Invalid or missing extcon\n");
+               return PTR_ERR(tcphy->extcon);
+       }
+
+       pm_runtime_enable(dev);
+
+       for_each_available_child_of_node(np, child_np) {
+               struct phy *phy;
+
+               if (!of_node_cmp(child_np->name, "dp-port"))
+                       phy = devm_phy_create(dev, child_np,
+                                             &rockchip_dp_phy_ops);
+               else if (!of_node_cmp(child_np->name, "usb3-port"))
+                       phy = devm_phy_create(dev, child_np,
+                                             &rockchip_usb3_phy_ops);
+               else
+                       continue;
+
+               if (IS_ERR(phy)) {
+                       dev_err(dev, "failed to create phy: %s\n",
+                               child_np->name);
+                       return PTR_ERR(phy);
+               }
+
+               phy_set_drvdata(phy, tcphy);
+       }
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(phy_provider)) {
+               dev_err(dev, "Failed to register phy provider\n");
+               return PTR_ERR(phy_provider);
+       }
+
+       return 0;
+}
+
+static int rockchip_typec_phy_remove(struct platform_device *pdev)
+{
+       pm_runtime_disable(&pdev->dev);
+
+       return 0;
+}
+
+static const struct of_device_id rockchip_typec_phy_dt_ids[] = {
+       { .compatible = "rockchip,rk3399-typec-phy" },
+       {}
+};
+
+MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids);
+
+static struct platform_driver rockchip_typec_phy_driver = {
+       .probe          = rockchip_typec_phy_probe,
+       .remove         = rockchip_typec_phy_remove,
+       .driver         = {
+               .name   = "rockchip-typec-phy",
+               .of_match_table = rockchip_typec_phy_dt_ids,
+       },
+};
+
+module_platform_driver(rockchip_typec_phy_driver);
+
+MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
+MODULE_AUTHOR("Kever Yang <kever.yang@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip USB TYPE-C PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/rockchip/phy-rockchip-usb.c b/drivers/phy/rockchip/phy-rockchip-usb.c
new file mode 100644 (file)
index 0000000..3378eeb
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ * Rockchip usb PHY driver
+ *
+ * Copyright (C) 2014 Yunzhi Li <lyz@rock-chips.com>
+ * Copyright (C) 2014 ROCKCHIP, 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; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/delay.h>
+
+static int enable_usb_uart;
+
+#define HIWORD_UPDATE(val, mask) \
+               ((val) | (mask) << 16)
+
+#define UOC_CON0_SIDDQ BIT(13)
+
+struct rockchip_usb_phys {
+       int reg;
+       const char *pll_name;
+};
+
+struct rockchip_usb_phy_base;
+struct rockchip_usb_phy_pdata {
+       struct rockchip_usb_phys *phys;
+       int (*init_usb_uart)(struct regmap *grf);
+       int usb_uart_phy;
+};
+
+struct rockchip_usb_phy_base {
+       struct device *dev;
+       struct regmap *reg_base;
+       const struct rockchip_usb_phy_pdata *pdata;
+};
+
+struct rockchip_usb_phy {
+       struct rockchip_usb_phy_base *base;
+       struct device_node *np;
+       unsigned int    reg_offset;
+       struct clk      *clk;
+       struct clk      *clk480m;
+       struct clk_hw   clk480m_hw;
+       struct phy      *phy;
+       bool            uart_enabled;
+       struct reset_control *reset;
+       struct regulator *vbus;
+};
+
+static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
+                                          bool siddq)
+{
+       u32 val = HIWORD_UPDATE(siddq ? UOC_CON0_SIDDQ : 0, UOC_CON0_SIDDQ);
+
+       return regmap_write(phy->base->reg_base, phy->reg_offset, val);
+}
+
+static unsigned long rockchip_usb_phy480m_recalc_rate(struct clk_hw *hw,
+                                               unsigned long parent_rate)
+{
+       return 480000000;
+}
+
+static void rockchip_usb_phy480m_disable(struct clk_hw *hw)
+{
+       struct rockchip_usb_phy *phy = container_of(hw,
+                                                   struct rockchip_usb_phy,
+                                                   clk480m_hw);
+
+       if (phy->vbus)
+               regulator_disable(phy->vbus);
+
+       /* Power down usb phy analog blocks by set siddq 1 */
+       rockchip_usb_phy_power(phy, 1);
+}
+
+static int rockchip_usb_phy480m_enable(struct clk_hw *hw)
+{
+       struct rockchip_usb_phy *phy = container_of(hw,
+                                                   struct rockchip_usb_phy,
+                                                   clk480m_hw);
+
+       /* Power up usb phy analog blocks by set siddq 0 */
+       return rockchip_usb_phy_power(phy, 0);
+}
+
+static int rockchip_usb_phy480m_is_enabled(struct clk_hw *hw)
+{
+       struct rockchip_usb_phy *phy = container_of(hw,
+                                                   struct rockchip_usb_phy,
+                                                   clk480m_hw);
+       int ret;
+       u32 val;
+
+       ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val);
+       if (ret < 0)
+               return ret;
+
+       return (val & UOC_CON0_SIDDQ) ? 0 : 1;
+}
+
+static const struct clk_ops rockchip_usb_phy480m_ops = {
+       .enable = rockchip_usb_phy480m_enable,
+       .disable = rockchip_usb_phy480m_disable,
+       .is_enabled = rockchip_usb_phy480m_is_enabled,
+       .recalc_rate = rockchip_usb_phy480m_recalc_rate,
+};
+
+static int rockchip_usb_phy_power_off(struct phy *_phy)
+{
+       struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
+
+       if (phy->uart_enabled)
+               return -EBUSY;
+
+       clk_disable_unprepare(phy->clk480m);
+
+       return 0;
+}
+
+static int rockchip_usb_phy_power_on(struct phy *_phy)
+{
+       struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
+
+       if (phy->uart_enabled)
+               return -EBUSY;
+
+       if (phy->vbus) {
+               int ret;
+
+               ret = regulator_enable(phy->vbus);
+               if (ret)
+                       return ret;
+       }
+
+       return clk_prepare_enable(phy->clk480m);
+}
+
+static int rockchip_usb_phy_reset(struct phy *_phy)
+{
+       struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
+
+       if (phy->reset) {
+               reset_control_assert(phy->reset);
+               udelay(10);
+               reset_control_deassert(phy->reset);
+       }
+
+       return 0;
+}
+
+static const struct phy_ops ops = {
+       .power_on       = rockchip_usb_phy_power_on,
+       .power_off      = rockchip_usb_phy_power_off,
+       .reset          = rockchip_usb_phy_reset,
+       .owner          = THIS_MODULE,
+};
+
+static void rockchip_usb_phy_action(void *data)
+{
+       struct rockchip_usb_phy *rk_phy = data;
+
+       if (!rk_phy->uart_enabled) {
+               of_clk_del_provider(rk_phy->np);
+               clk_unregister(rk_phy->clk480m);
+       }
+
+       if (rk_phy->clk)
+               clk_put(rk_phy->clk);
+}
+
+static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base,
+                                struct device_node *child)
+{
+       struct rockchip_usb_phy *rk_phy;
+       unsigned int reg_offset;
+       const char *clk_name;
+       struct clk_init_data init;
+       int err, i;
+
+       rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL);
+       if (!rk_phy)
+               return -ENOMEM;
+
+       rk_phy->base = base;
+       rk_phy->np = child;
+
+       if (of_property_read_u32(child, "reg", &reg_offset)) {
+               dev_err(base->dev, "missing reg property in node %s\n",
+                       child->name);
+               return -EINVAL;
+       }
+
+       rk_phy->reset = of_reset_control_get(child, "phy-reset");
+       if (IS_ERR(rk_phy->reset))
+               rk_phy->reset = NULL;
+
+       rk_phy->reg_offset = reg_offset;
+
+       rk_phy->clk = of_clk_get_by_name(child, "phyclk");
+       if (IS_ERR(rk_phy->clk))
+               rk_phy->clk = NULL;
+
+       i = 0;
+       init.name = NULL;
+       while (base->pdata->phys[i].reg) {
+               if (base->pdata->phys[i].reg == reg_offset) {
+                       init.name = base->pdata->phys[i].pll_name;
+                       break;
+               }
+               i++;
+       }
+
+       if (!init.name) {
+               dev_err(base->dev, "phy data not found\n");
+               return -EINVAL;
+       }
+
+       if (enable_usb_uart && base->pdata->usb_uart_phy == i) {
+               dev_dbg(base->dev, "phy%d used as uart output\n", i);
+               rk_phy->uart_enabled = true;
+       } else {
+               if (rk_phy->clk) {
+                       clk_name = __clk_get_name(rk_phy->clk);
+                       init.flags = 0;
+                       init.parent_names = &clk_name;
+                       init.num_parents = 1;
+               } else {
+                       init.flags = 0;
+                       init.parent_names = NULL;
+                       init.num_parents = 0;
+               }
+
+               init.ops = &rockchip_usb_phy480m_ops;
+               rk_phy->clk480m_hw.init = &init;
+
+               rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw);
+               if (IS_ERR(rk_phy->clk480m)) {
+                       err = PTR_ERR(rk_phy->clk480m);
+                       goto err_clk;
+               }
+
+               err = of_clk_add_provider(child, of_clk_src_simple_get,
+                                       rk_phy->clk480m);
+               if (err < 0)
+                       goto err_clk_prov;
+       }
+
+       err = devm_add_action_or_reset(base->dev, rockchip_usb_phy_action,
+                                      rk_phy);
+       if (err)
+               return err;
+
+       rk_phy->phy = devm_phy_create(base->dev, child, &ops);
+       if (IS_ERR(rk_phy->phy)) {
+               dev_err(base->dev, "failed to create PHY\n");
+               return PTR_ERR(rk_phy->phy);
+       }
+       phy_set_drvdata(rk_phy->phy, rk_phy);
+
+       rk_phy->vbus = devm_regulator_get_optional(&rk_phy->phy->dev, "vbus");
+       if (IS_ERR(rk_phy->vbus)) {
+               if (PTR_ERR(rk_phy->vbus) == -EPROBE_DEFER)
+                       return PTR_ERR(rk_phy->vbus);
+               rk_phy->vbus = NULL;
+       }
+
+       /*
+        * When acting as uart-pipe, just keep clock on otherwise
+        * only power up usb phy when it use, so disable it when init
+        */
+       if (rk_phy->uart_enabled)
+               return clk_prepare_enable(rk_phy->clk);
+       else
+               return rockchip_usb_phy_power(rk_phy, 1);
+
+err_clk_prov:
+       if (!rk_phy->uart_enabled)
+               clk_unregister(rk_phy->clk480m);
+err_clk:
+       if (rk_phy->clk)
+               clk_put(rk_phy->clk);
+       return err;
+}
+
+static const struct rockchip_usb_phy_pdata rk3066a_pdata = {
+       .phys = (struct rockchip_usb_phys[]){
+               { .reg = 0x17c, .pll_name = "sclk_otgphy0_480m" },
+               { .reg = 0x188, .pll_name = "sclk_otgphy1_480m" },
+               { /* sentinel */ }
+       },
+};
+
+static const struct rockchip_usb_phy_pdata rk3188_pdata = {
+       .phys = (struct rockchip_usb_phys[]){
+               { .reg = 0x10c, .pll_name = "sclk_otgphy0_480m" },
+               { .reg = 0x11c, .pll_name = "sclk_otgphy1_480m" },
+               { /* sentinel */ }
+       },
+};
+
+#define RK3288_UOC0_CON0                               0x320
+#define RK3288_UOC0_CON0_COMMON_ON_N                   BIT(0)
+#define RK3288_UOC0_CON0_DISABLE                       BIT(4)
+
+#define RK3288_UOC0_CON2                               0x328
+#define RK3288_UOC0_CON2_SOFT_CON_SEL                  BIT(2)
+
+#define RK3288_UOC0_CON3                               0x32c
+#define RK3288_UOC0_CON3_UTMI_SUSPENDN                 BIT(0)
+#define RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING         (1 << 1)
+#define RK3288_UOC0_CON3_UTMI_OPMODE_MASK              (3 << 1)
+#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC      (1 << 3)
+#define RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK          (3 << 3)
+#define RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED                BIT(5)
+#define RK3288_UOC0_CON3_BYPASSDMEN                    BIT(6)
+#define RK3288_UOC0_CON3_BYPASSSEL                     BIT(7)
+
+/*
+ * Enable the bypass of uart2 data through the otg usb phy.
+ * Original description in the TRM.
+ * 1. Disable the OTG block by setting OTGDISABLE0 to 1’b1.
+ * 2. Disable the pull-up resistance on the D+ line by setting
+ *    OPMODE0[1:0] to 2’b01.
+ * 3. To ensure that the XO, Bias, and PLL blocks are powered down in Suspend
+ *    mode, set COMMONONN to 1’b1.
+ * 4. Place the USB PHY in Suspend mode by setting SUSPENDM0 to 1’b0.
+ * 5. Set BYPASSSEL0 to 1’b1.
+ * 6. To transmit data, controls BYPASSDMEN0, and BYPASSDMDATA0.
+ * To receive data, monitor FSVPLUS0.
+ *
+ * The actual code in the vendor kernel does some things differently.
+ */
+static int __init rk3288_init_usb_uart(struct regmap *grf)
+{
+       u32 val;
+       int ret;
+
+       /*
+        * COMMON_ON and DISABLE settings are described in the TRM,
+        * but were not present in the original code.
+        * Also disable the analog phy components to save power.
+        */
+       val = HIWORD_UPDATE(RK3288_UOC0_CON0_COMMON_ON_N
+                               | RK3288_UOC0_CON0_DISABLE
+                               | UOC_CON0_SIDDQ,
+                           RK3288_UOC0_CON0_COMMON_ON_N
+                               | RK3288_UOC0_CON0_DISABLE
+                               | UOC_CON0_SIDDQ);
+       ret = regmap_write(grf, RK3288_UOC0_CON0, val);
+       if (ret)
+               return ret;
+
+       val = HIWORD_UPDATE(RK3288_UOC0_CON2_SOFT_CON_SEL,
+                           RK3288_UOC0_CON2_SOFT_CON_SEL);
+       ret = regmap_write(grf, RK3288_UOC0_CON2, val);
+       if (ret)
+               return ret;
+
+       val = HIWORD_UPDATE(RK3288_UOC0_CON3_UTMI_OPMODE_NODRIVING
+                               | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_FSTRANSC
+                               | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED,
+                           RK3288_UOC0_CON3_UTMI_SUSPENDN
+                               | RK3288_UOC0_CON3_UTMI_OPMODE_MASK
+                               | RK3288_UOC0_CON3_UTMI_XCVRSEELCT_MASK
+                               | RK3288_UOC0_CON3_UTMI_TERMSEL_FULLSPEED);
+       ret = regmap_write(grf, RK3288_UOC0_CON3, val);
+       if (ret)
+               return ret;
+
+       val = HIWORD_UPDATE(RK3288_UOC0_CON3_BYPASSSEL
+                               | RK3288_UOC0_CON3_BYPASSDMEN,
+                           RK3288_UOC0_CON3_BYPASSSEL
+                               | RK3288_UOC0_CON3_BYPASSDMEN);
+       ret = regmap_write(grf, RK3288_UOC0_CON3, val);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static const struct rockchip_usb_phy_pdata rk3288_pdata = {
+       .phys = (struct rockchip_usb_phys[]){
+               { .reg = 0x320, .pll_name = "sclk_otgphy0_480m" },
+               { .reg = 0x334, .pll_name = "sclk_otgphy1_480m" },
+               { .reg = 0x348, .pll_name = "sclk_otgphy2_480m" },
+               { /* sentinel */ }
+       },
+       .init_usb_uart = rk3288_init_usb_uart,
+       .usb_uart_phy = 0,
+};
+
+static int rockchip_usb_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct rockchip_usb_phy_base *phy_base;
+       struct phy_provider *phy_provider;
+       const struct of_device_id *match;
+       struct device_node *child;
+       int err;
+
+       phy_base = devm_kzalloc(dev, sizeof(*phy_base), GFP_KERNEL);
+       if (!phy_base)
+               return -ENOMEM;
+
+       match = of_match_device(dev->driver->of_match_table, dev);
+       if (!match || !match->data) {
+               dev_err(dev, "missing phy data\n");
+               return -EINVAL;
+       }
+
+       phy_base->pdata = match->data;
+
+       phy_base->dev = dev;
+       phy_base->reg_base = ERR_PTR(-ENODEV);
+       if (dev->parent && dev->parent->of_node)
+               phy_base->reg_base = syscon_node_to_regmap(
+                                               dev->parent->of_node);
+       if (IS_ERR(phy_base->reg_base))
+               phy_base->reg_base = syscon_regmap_lookup_by_phandle(
+                                               dev->of_node, "rockchip,grf");
+       if (IS_ERR(phy_base->reg_base)) {
+               dev_err(&pdev->dev, "Missing rockchip,grf property\n");
+               return PTR_ERR(phy_base->reg_base);
+       }
+
+       for_each_available_child_of_node(dev->of_node, child) {
+               err = rockchip_usb_phy_init(phy_base, child);
+               if (err) {
+                       of_node_put(child);
+                       return err;
+               }
+       }
+
+       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 rockchip_usb_phy_dt_ids[] = {
+       { .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
+       { .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
+       { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
+       {}
+};
+
+MODULE_DEVICE_TABLE(of, rockchip_usb_phy_dt_ids);
+
+static struct platform_driver rockchip_usb_driver = {
+       .probe          = rockchip_usb_phy_probe,
+       .driver         = {
+               .name   = "rockchip-usb-phy",
+               .of_match_table = rockchip_usb_phy_dt_ids,
+       },
+};
+
+module_platform_driver(rockchip_usb_driver);
+
+#ifndef MODULE
+static int __init rockchip_init_usb_uart(void)
+{
+       const struct of_device_id *match;
+       const struct rockchip_usb_phy_pdata *data;
+       struct device_node *np;
+       struct regmap *grf;
+       int ret;
+
+       if (!enable_usb_uart)
+               return 0;
+
+       np = of_find_matching_node_and_match(NULL, rockchip_usb_phy_dt_ids,
+                                            &match);
+       if (!np) {
+               pr_err("%s: failed to find usbphy node\n", __func__);
+               return -ENOTSUPP;
+       }
+
+       pr_debug("%s: using settings for %s\n", __func__, match->compatible);
+       data = match->data;
+
+       if (!data->init_usb_uart) {
+               pr_err("%s: usb-uart not available on %s\n",
+                      __func__, match->compatible);
+               return -ENOTSUPP;
+       }
+
+       grf = ERR_PTR(-ENODEV);
+       if (np->parent)
+               grf = syscon_node_to_regmap(np->parent);
+       if (IS_ERR(grf))
+               grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+       if (IS_ERR(grf)) {
+               pr_err("%s: Missing rockchip,grf property, %lu\n",
+                      __func__, PTR_ERR(grf));
+               return PTR_ERR(grf);
+       }
+
+       ret = data->init_usb_uart(grf);
+       if (ret) {
+               pr_err("%s: could not init usb_uart, %d\n", __func__, ret);
+               enable_usb_uart = 0;
+               return ret;
+       }
+
+       return 0;
+}
+early_initcall(rockchip_init_usb_uart);
+
+static int __init rockchip_usb_uart(char *buf)
+{
+       enable_usb_uart = true;
+       return 0;
+}
+early_param("rockchip.usb_uart", rockchip_usb_uart);
+#endif
+
+MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig
new file mode 100644 (file)
index 0000000..b7e0645
--- /dev/null
@@ -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.
diff --git a/drivers/phy/samsung/Makefile b/drivers/phy/samsung/Makefile
new file mode 100644 (file)
index 0000000..20d7f24
--- /dev/null
@@ -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
diff --git a/drivers/phy/samsung/phy-exynos-dp-video.c b/drivers/phy/samsung/phy-exynos-dp-video.c
new file mode 100644 (file)
index 0000000..bb3279d
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Samsung EXYNOS SoC series Display Port PHY driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.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.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.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/soc/samsung/exynos-regs-pmu.h>
+
+struct exynos_dp_video_phy_drvdata {
+       u32 phy_ctrl_offset;
+};
+
+struct exynos_dp_video_phy {
+       struct regmap *regs;
+       const struct exynos_dp_video_phy_drvdata *drvdata;
+};
+
+static int exynos_dp_video_phy_power_on(struct phy *phy)
+{
+       struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
+
+       /* Disable power isolation on DP-PHY */
+       return regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset,
+                                 EXYNOS4_PHY_ENABLE, EXYNOS4_PHY_ENABLE);
+}
+
+static int exynos_dp_video_phy_power_off(struct phy *phy)
+{
+       struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
+
+       /* Enable power isolation on DP-PHY */
+       return regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset,
+                                 EXYNOS4_PHY_ENABLE, 0);
+}
+
+static const struct phy_ops exynos_dp_video_phy_ops = {
+       .power_on       = exynos_dp_video_phy_power_on,
+       .power_off      = exynos_dp_video_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static const struct exynos_dp_video_phy_drvdata exynos5250_dp_video_phy = {
+       .phy_ctrl_offset        = EXYNOS5_DPTX_PHY_CONTROL,
+};
+
+static const struct exynos_dp_video_phy_drvdata exynos5420_dp_video_phy = {
+       .phy_ctrl_offset        = EXYNOS5420_DPTX_PHY_CONTROL,
+};
+
+static const struct of_device_id exynos_dp_video_phy_of_match[] = {
+       {
+               .compatible = "samsung,exynos5250-dp-video-phy",
+               .data = &exynos5250_dp_video_phy,
+       }, {
+               .compatible = "samsung,exynos5420-dp-video-phy",
+               .data = &exynos5420_dp_video_phy,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_video_phy_of_match);
+
+static int exynos_dp_video_phy_probe(struct platform_device *pdev)
+{
+       struct exynos_dp_video_phy *state;
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *match;
+       struct phy_provider *phy_provider;
+       struct phy *phy;
+
+       state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+       if (!state)
+               return -ENOMEM;
+
+       state->regs = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                                     "samsung,pmu-syscon");
+       if (IS_ERR(state->regs)) {
+               dev_err(dev, "Failed to lookup PMU regmap\n");
+               return PTR_ERR(state->regs);
+       }
+
+       match = of_match_node(exynos_dp_video_phy_of_match, dev->of_node);
+       state->drvdata = match->data;
+
+       phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops);
+       if (IS_ERR(phy)) {
+               dev_err(dev, "failed to create Display Port PHY\n");
+               return PTR_ERR(phy);
+       }
+       phy_set_drvdata(phy, state);
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static struct platform_driver exynos_dp_video_phy_driver = {
+       .probe  = exynos_dp_video_phy_probe,
+       .driver = {
+               .name   = "exynos-dp-video-phy",
+               .of_match_table = exynos_dp_video_phy_of_match,
+       }
+};
+module_platform_driver(exynos_dp_video_phy_driver);
+
+MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS SoC DP PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/samsung/phy-exynos-mipi-video.c b/drivers/phy/samsung/phy-exynos-mipi-video.c
new file mode 100644 (file)
index 0000000..c198886
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
+ *
+ * Copyright (C) 2013,2016 Samsung Electronics Co., Ltd.
+ * Author: Sylwester Nawrocki <s.nawrocki@samsung.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.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+#include <linux/soc/samsung/exynos-regs-pmu.h>
+#include <linux/mfd/syscon.h>
+
+enum exynos_mipi_phy_id {
+       EXYNOS_MIPI_PHY_ID_NONE = -1,
+       EXYNOS_MIPI_PHY_ID_CSIS0,
+       EXYNOS_MIPI_PHY_ID_DSIM0,
+       EXYNOS_MIPI_PHY_ID_CSIS1,
+       EXYNOS_MIPI_PHY_ID_DSIM1,
+       EXYNOS_MIPI_PHY_ID_CSIS2,
+       EXYNOS_MIPI_PHYS_NUM
+};
+
+enum exynos_mipi_phy_regmap_id {
+       EXYNOS_MIPI_REGMAP_PMU,
+       EXYNOS_MIPI_REGMAP_DISP,
+       EXYNOS_MIPI_REGMAP_CAM0,
+       EXYNOS_MIPI_REGMAP_CAM1,
+       EXYNOS_MIPI_REGMAPS_NUM
+};
+
+struct mipi_phy_device_desc {
+       int num_phys;
+       int num_regmaps;
+       const char *regmap_names[EXYNOS_MIPI_REGMAPS_NUM];
+       struct exynos_mipi_phy_desc {
+               enum exynos_mipi_phy_id coupled_phy_id;
+               u32 enable_val;
+               unsigned int enable_reg;
+               enum exynos_mipi_phy_regmap_id enable_map;
+               u32 resetn_val;
+               unsigned int resetn_reg;
+               enum exynos_mipi_phy_regmap_id resetn_map;
+       } phys[EXYNOS_MIPI_PHYS_NUM];
+};
+
+static const struct mipi_phy_device_desc s5pv210_mipi_phy = {
+       .num_regmaps = 1,
+       .regmap_names = {"syscon"},
+       .num_phys = 4,
+       .phys = {
+               {
+                       /* EXYNOS_MIPI_PHY_ID_CSIS0 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
+                       .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
+                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
+               }, {
+                       /* EXYNOS_MIPI_PHY_ID_DSIM0 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = EXYNOS4_MIPI_PHY_MRESETN,
+                       .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
+                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
+               }, {
+                       /* EXYNOS_MIPI_PHY_ID_CSIS1 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM1,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
+                       .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
+                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
+               }, {
+                       /* EXYNOS_MIPI_PHY_ID_DSIM1 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS1,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = EXYNOS4_MIPI_PHY_MRESETN,
+                       .resetn_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
+                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
+               },
+       },
+};
+
+static const struct mipi_phy_device_desc exynos5420_mipi_phy = {
+       .num_regmaps = 1,
+       .regmap_names = {"syscon"},
+       .num_phys = 5,
+       .phys = {
+               {
+                       /* EXYNOS_MIPI_PHY_ID_CSIS0 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(0),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
+                       .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(0),
+                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
+               }, {
+                       /* EXYNOS_MIPI_PHY_ID_DSIM0 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(0),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = EXYNOS4_MIPI_PHY_MRESETN,
+                       .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(0),
+                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
+               }, {
+                       /* EXYNOS_MIPI_PHY_ID_CSIS1 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM1,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(1),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
+                       .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(1),
+                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
+               }, {
+                       /* EXYNOS_MIPI_PHY_ID_DSIM1 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS1,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(1),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = EXYNOS4_MIPI_PHY_MRESETN,
+                       .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(1),
+                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
+               }, {
+                       /* EXYNOS_MIPI_PHY_ID_CSIS2 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(2),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = EXYNOS4_MIPI_PHY_SRESETN,
+                       .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(2),
+                       .resetn_map = EXYNOS_MIPI_REGMAP_PMU,
+               },
+       },
+};
+
+#define EXYNOS5433_SYSREG_DISP_MIPI_PHY                0x100C
+#define EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON   0x1014
+#define EXYNOS5433_SYSREG_CAM1_MIPI_DPHY_CON   0x1020
+
+static const struct mipi_phy_device_desc exynos5433_mipi_phy = {
+       .num_regmaps = 4,
+       .regmap_names = {
+               "samsung,pmu-syscon",
+               "samsung,disp-sysreg",
+               "samsung,cam0-sysreg",
+               "samsung,cam1-sysreg"
+       },
+       .num_phys = 5,
+       .phys = {
+               {
+                       /* EXYNOS_MIPI_PHY_ID_CSIS0 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = BIT(0),
+                       .resetn_reg = EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON,
+                       .resetn_map = EXYNOS_MIPI_REGMAP_CAM0,
+               }, {
+                       /* EXYNOS_MIPI_PHY_ID_DSIM0 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = BIT(0),
+                       .resetn_reg = EXYNOS5433_SYSREG_DISP_MIPI_PHY,
+                       .resetn_map = EXYNOS_MIPI_REGMAP_DISP,
+               }, {
+                       /* EXYNOS_MIPI_PHY_ID_CSIS1 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = BIT(1),
+                       .resetn_reg = EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON,
+                       .resetn_map = EXYNOS_MIPI_REGMAP_CAM0,
+               }, {
+                       /* EXYNOS_MIPI_PHY_ID_DSIM1 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = BIT(1),
+                       .resetn_reg = EXYNOS5433_SYSREG_DISP_MIPI_PHY,
+                       .resetn_map = EXYNOS_MIPI_REGMAP_DISP,
+               }, {
+                       /* EXYNOS_MIPI_PHY_ID_CSIS2 */
+                       .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE,
+                       .enable_val = EXYNOS4_PHY_ENABLE,
+                       .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(2),
+                       .enable_map = EXYNOS_MIPI_REGMAP_PMU,
+                       .resetn_val = BIT(0),
+                       .resetn_reg = EXYNOS5433_SYSREG_CAM1_MIPI_DPHY_CON,
+                       .resetn_map = EXYNOS_MIPI_REGMAP_CAM1,
+               },
+       },
+};
+
+struct exynos_mipi_video_phy {
+       struct regmap *regmaps[EXYNOS_MIPI_REGMAPS_NUM];
+       int num_phys;
+       struct video_phy_desc {
+               struct phy *phy;
+               unsigned int index;
+               const struct exynos_mipi_phy_desc *data;
+       } phys[EXYNOS_MIPI_PHYS_NUM];
+       spinlock_t slock;
+};
+
+static int __set_phy_state(const struct exynos_mipi_phy_desc *data,
+                          struct exynos_mipi_video_phy *state, unsigned int on)
+{
+       u32 val;
+
+       spin_lock(&state->slock);
+
+       /* disable in PMU sysreg */
+       if (!on && data->coupled_phy_id >= 0 &&
+           state->phys[data->coupled_phy_id].phy->power_count == 0) {
+               regmap_read(state->regmaps[data->enable_map], data->enable_reg,
+                           &val);
+               val &= ~data->enable_val;
+               regmap_write(state->regmaps[data->enable_map], data->enable_reg,
+                            val);
+       }
+
+       /* PHY reset */
+       regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val);
+       val = on ? (val | data->resetn_val) : (val & ~data->resetn_val);
+       regmap_write(state->regmaps[data->resetn_map], data->resetn_reg, val);
+
+       /* enable in PMU sysreg */
+       if (on) {
+               regmap_read(state->regmaps[data->enable_map], data->enable_reg,
+                           &val);
+               val |= data->enable_val;
+               regmap_write(state->regmaps[data->enable_map], data->enable_reg,
+                            val);
+       }
+
+       spin_unlock(&state->slock);
+
+       return 0;
+}
+
+#define to_mipi_video_phy(desc) \
+       container_of((desc), struct exynos_mipi_video_phy, phys[(desc)->index])
+
+static int exynos_mipi_video_phy_power_on(struct phy *phy)
+{
+       struct video_phy_desc *phy_desc = phy_get_drvdata(phy);
+       struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc);
+
+       return __set_phy_state(phy_desc->data, state, 1);
+}
+
+static int exynos_mipi_video_phy_power_off(struct phy *phy)
+{
+       struct video_phy_desc *phy_desc = phy_get_drvdata(phy);
+       struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc);
+
+       return __set_phy_state(phy_desc->data, state, 0);
+}
+
+static struct phy *exynos_mipi_video_phy_xlate(struct device *dev,
+                                       struct of_phandle_args *args)
+{
+       struct exynos_mipi_video_phy *state = dev_get_drvdata(dev);
+
+       if (WARN_ON(args->args[0] >= state->num_phys))
+               return ERR_PTR(-ENODEV);
+
+       return state->phys[args->args[0]].phy;
+}
+
+static const struct phy_ops exynos_mipi_video_phy_ops = {
+       .power_on       = exynos_mipi_video_phy_power_on,
+       .power_off      = exynos_mipi_video_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
+{
+       const struct mipi_phy_device_desc *phy_dev;
+       struct exynos_mipi_video_phy *state;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct phy_provider *phy_provider;
+       unsigned int i;
+
+       phy_dev = of_device_get_match_data(dev);
+       if (!phy_dev)
+               return -ENODEV;
+
+       state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+       if (!state)
+               return -ENOMEM;
+
+       for (i = 0; i < phy_dev->num_regmaps; i++) {
+               state->regmaps[i] = syscon_regmap_lookup_by_phandle(np,
+                                               phy_dev->regmap_names[i]);
+               if (IS_ERR(state->regmaps[i]))
+                       return PTR_ERR(state->regmaps[i]);
+       }
+       state->num_phys = phy_dev->num_phys;
+       spin_lock_init(&state->slock);
+
+       dev_set_drvdata(dev, state);
+
+       for (i = 0; i < state->num_phys; i++) {
+               struct phy *phy = devm_phy_create(dev, NULL,
+                                                 &exynos_mipi_video_phy_ops);
+               if (IS_ERR(phy)) {
+                       dev_err(dev, "failed to create PHY %d\n", i);
+                       return PTR_ERR(phy);
+               }
+
+               state->phys[i].phy = phy;
+               state->phys[i].index = i;
+               state->phys[i].data = &phy_dev->phys[i];
+               phy_set_drvdata(phy, &state->phys[i]);
+       }
+
+       phy_provider = devm_of_phy_provider_register(dev,
+                                       exynos_mipi_video_phy_xlate);
+
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id exynos_mipi_video_phy_of_match[] = {
+       {
+               .compatible = "samsung,s5pv210-mipi-video-phy",
+               .data = &s5pv210_mipi_phy,
+       }, {
+               .compatible = "samsung,exynos5420-mipi-video-phy",
+               .data = &exynos5420_mipi_phy,
+       }, {
+               .compatible = "samsung,exynos5433-mipi-video-phy",
+               .data = &exynos5433_mipi_phy,
+       },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, exynos_mipi_video_phy_of_match);
+
+static struct platform_driver exynos_mipi_video_phy_driver = {
+       .probe  = exynos_mipi_video_phy_probe,
+       .driver = {
+               .of_match_table = exynos_mipi_video_phy_of_match,
+               .name  = "exynos-mipi-video-phy",
+       }
+};
+module_platform_driver(exynos_mipi_video_phy_driver);
+
+MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI CSI-2/DSI PHY driver");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/samsung/phy-exynos-pcie.c b/drivers/phy/samsung/phy-exynos-pcie.c
new file mode 100644 (file)
index 0000000..a89c12f
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Samsung EXYNOS SoC series PCIe PHY driver
+ *
+ * Phy provider for PCIe controller on Exynos SoC series
+ *
+ * Copyright (C) 2017 Samsung Electronics Co., Ltd.
+ * Jaehoon Chung <jh80.chung@samsung.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.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/init.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
+/* PCIe Purple registers */
+#define PCIE_PHY_GLOBAL_RESET          0x000
+#define PCIE_PHY_COMMON_RESET          0x004
+#define PCIE_PHY_CMN_REG               0x008
+#define PCIE_PHY_MAC_RESET             0x00c
+#define PCIE_PHY_PLL_LOCKED            0x010
+#define PCIE_PHY_TRSVREG_RESET         0x020
+#define PCIE_PHY_TRSV_RESET            0x024
+
+/* PCIe PHY registers */
+#define PCIE_PHY_IMPEDANCE             0x004
+#define PCIE_PHY_PLL_DIV_0             0x008
+#define PCIE_PHY_PLL_BIAS              0x00c
+#define PCIE_PHY_DCC_FEEDBACK          0x014
+#define PCIE_PHY_PLL_DIV_1             0x05c
+#define PCIE_PHY_COMMON_POWER          0x064
+#define PCIE_PHY_COMMON_PD_CMN         BIT(3)
+#define PCIE_PHY_TRSV0_EMP_LVL         0x084
+#define PCIE_PHY_TRSV0_DRV_LVL         0x088
+#define PCIE_PHY_TRSV0_RXCDR           0x0ac
+#define PCIE_PHY_TRSV0_POWER           0x0c4
+#define PCIE_PHY_TRSV0_PD_TSV          BIT(7)
+#define PCIE_PHY_TRSV0_LVCC            0x0dc
+#define PCIE_PHY_TRSV1_EMP_LVL         0x144
+#define PCIE_PHY_TRSV1_RXCDR           0x16c
+#define PCIE_PHY_TRSV1_POWER           0x184
+#define PCIE_PHY_TRSV1_PD_TSV          BIT(7)
+#define PCIE_PHY_TRSV1_LVCC            0x19c
+#define PCIE_PHY_TRSV2_EMP_LVL         0x204
+#define PCIE_PHY_TRSV2_RXCDR           0x22c
+#define PCIE_PHY_TRSV2_POWER           0x244
+#define PCIE_PHY_TRSV2_PD_TSV          BIT(7)
+#define PCIE_PHY_TRSV2_LVCC            0x25c
+#define PCIE_PHY_TRSV3_EMP_LVL         0x2c4
+#define PCIE_PHY_TRSV3_RXCDR           0x2ec
+#define PCIE_PHY_TRSV3_POWER           0x304
+#define PCIE_PHY_TRSV3_PD_TSV          BIT(7)
+#define PCIE_PHY_TRSV3_LVCC            0x31c
+
+struct exynos_pcie_phy_data {
+       const struct phy_ops    *ops;
+};
+
+/* For Exynos pcie phy */
+struct exynos_pcie_phy {
+       const struct exynos_pcie_phy_data *drv_data;
+       void __iomem *phy_base;
+       void __iomem *blk_base; /* For exynos5440 */
+};
+
+static void exynos_pcie_phy_writel(void __iomem *base, u32 val, u32 offset)
+{
+       writel(val, base + offset);
+}
+
+static u32 exynos_pcie_phy_readl(void __iomem *base, u32 offset)
+{
+       return readl(base + offset);
+}
+
+/* For Exynos5440 specific functions */
+static int exynos5440_pcie_phy_init(struct phy *phy)
+{
+       struct exynos_pcie_phy *ep = phy_get_drvdata(phy);
+
+       /* DCC feedback control off */
+       exynos_pcie_phy_writel(ep->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK);
+
+       /* set TX/RX impedance */
+       exynos_pcie_phy_writel(ep->phy_base, 0xd5, PCIE_PHY_IMPEDANCE);
+
+       /* set 50Mhz PHY clock */
+       exynos_pcie_phy_writel(ep->phy_base, 0x14, PCIE_PHY_PLL_DIV_0);
+       exynos_pcie_phy_writel(ep->phy_base, 0x12, PCIE_PHY_PLL_DIV_1);
+
+       /* set TX Differential output for lane 0 */
+       exynos_pcie_phy_writel(ep->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
+
+       /* set TX Pre-emphasis Level Control for lane 0 to minimum */
+       exynos_pcie_phy_writel(ep->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
+
+       /* set RX clock and data recovery bandwidth */
+       exynos_pcie_phy_writel(ep->phy_base, 0xe7, PCIE_PHY_PLL_BIAS);
+       exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR);
+       exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR);
+       exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR);
+       exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR);
+
+       /* change TX Pre-emphasis Level Control for lanes */
+       exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
+       exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
+       exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
+       exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
+
+       /* set LVCC */
+       exynos_pcie_phy_writel(ep->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC);
+       exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC);
+       exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC);
+       exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC);
+
+       /* pulse for common reset */
+       exynos_pcie_phy_writel(ep->blk_base, 1, PCIE_PHY_COMMON_RESET);
+       udelay(500);
+       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_COMMON_RESET);
+
+       return 0;
+}
+
+static int exynos5440_pcie_phy_power_on(struct phy *phy)
+{
+       struct exynos_pcie_phy *ep = phy_get_drvdata(phy);
+       u32 val;
+
+       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_COMMON_RESET);
+       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_CMN_REG);
+       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_TRSVREG_RESET);
+       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_TRSV_RESET);
+
+       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_COMMON_POWER);
+       val &= ~PCIE_PHY_COMMON_PD_CMN;
+       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER);
+
+       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER);
+       val &= ~PCIE_PHY_TRSV0_PD_TSV;
+       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER);
+
+       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER);
+       val &= ~PCIE_PHY_TRSV1_PD_TSV;
+       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER);
+
+       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER);
+       val &= ~PCIE_PHY_TRSV2_PD_TSV;
+       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER);
+
+       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER);
+       val &= ~PCIE_PHY_TRSV3_PD_TSV;
+       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER);
+
+       return 0;
+}
+
+static int exynos5440_pcie_phy_power_off(struct phy *phy)
+{
+       struct exynos_pcie_phy *ep = phy_get_drvdata(phy);
+       u32 val;
+
+       if (readl_poll_timeout(ep->phy_base + PCIE_PHY_PLL_LOCKED, val,
+                               (val != 0), 1, 500)) {
+               dev_err(&phy->dev, "PLL Locked: 0x%x\n", val);
+               return -ETIMEDOUT;
+       }
+
+       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_COMMON_POWER);
+       val |= PCIE_PHY_COMMON_PD_CMN;
+       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER);
+
+       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER);
+       val |= PCIE_PHY_TRSV0_PD_TSV;
+       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER);
+
+       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER);
+       val |= PCIE_PHY_TRSV1_PD_TSV;
+       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER);
+
+       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER);
+       val |= PCIE_PHY_TRSV2_PD_TSV;
+       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER);
+
+       val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER);
+       val |= PCIE_PHY_TRSV3_PD_TSV;
+       exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER);
+
+       return 0;
+}
+
+static int exynos5440_pcie_phy_reset(struct phy *phy)
+{
+       struct exynos_pcie_phy *ep = phy_get_drvdata(phy);
+
+       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_MAC_RESET);
+       exynos_pcie_phy_writel(ep->blk_base, 1, PCIE_PHY_GLOBAL_RESET);
+       exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_GLOBAL_RESET);
+
+       return 0;
+}
+
+static const struct phy_ops exynos5440_phy_ops = {
+       .init           = exynos5440_pcie_phy_init,
+       .power_on       = exynos5440_pcie_phy_power_on,
+       .power_off      = exynos5440_pcie_phy_power_off,
+       .reset          = exynos5440_pcie_phy_reset,
+       .owner          = THIS_MODULE,
+};
+
+static const struct exynos_pcie_phy_data exynos5440_pcie_phy_data = {
+       .ops            = &exynos5440_phy_ops,
+};
+
+static const struct of_device_id exynos_pcie_phy_match[] = {
+       {
+               .compatible = "samsung,exynos5440-pcie-phy",
+               .data = &exynos5440_pcie_phy_data,
+       },
+       {},
+};
+
+static int exynos_pcie_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct exynos_pcie_phy *exynos_phy;
+       struct phy *generic_phy;
+       struct phy_provider *phy_provider;
+       struct resource *res;
+       const struct exynos_pcie_phy_data *drv_data;
+
+       drv_data = of_device_get_match_data(dev);
+       if (!drv_data)
+               return -ENODEV;
+
+       exynos_phy = devm_kzalloc(dev, sizeof(*exynos_phy), GFP_KERNEL);
+       if (!exynos_phy)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       exynos_phy->phy_base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(exynos_phy->phy_base))
+               return PTR_ERR(exynos_phy->phy_base);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       exynos_phy->blk_base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(exynos_phy->blk_base))
+               return PTR_ERR(exynos_phy->blk_base);
+
+       exynos_phy->drv_data = drv_data;
+
+       generic_phy = devm_phy_create(dev, dev->of_node, drv_data->ops);
+       if (IS_ERR(generic_phy)) {
+               dev_err(dev, "failed to create PHY\n");
+               return PTR_ERR(generic_phy);
+       }
+
+       phy_set_drvdata(generic_phy, exynos_phy);
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static struct platform_driver exynos_pcie_phy_driver = {
+       .probe  = exynos_pcie_phy_probe,
+       .driver = {
+               .of_match_table = exynos_pcie_phy_match,
+               .name           = "exynos_pcie_phy",
+       }
+};
+
+builtin_platform_driver(exynos_pcie_phy_driver);
diff --git a/drivers/phy/samsung/phy-exynos4210-usb2.c b/drivers/phy/samsung/phy-exynos4210-usb2.c
new file mode 100644 (file)
index 0000000..1f50e10
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4210 support
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Kamil Debski <k.debski@samsung.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.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include "phy-samsung-usb2.h"
+
+/* Exynos USB PHY registers */
+
+/* PHY power control */
+#define EXYNOS_4210_UPHYPWR                    0x0
+
+#define EXYNOS_4210_UPHYPWR_PHY0_SUSPEND       BIT(0)
+#define EXYNOS_4210_UPHYPWR_PHY0_PWR           BIT(3)
+#define EXYNOS_4210_UPHYPWR_PHY0_OTG_PWR       BIT(4)
+#define EXYNOS_4210_UPHYPWR_PHY0_SLEEP         BIT(5)
+#define EXYNOS_4210_UPHYPWR_PHY0       ( \
+       EXYNOS_4210_UPHYPWR_PHY0_SUSPEND | \
+       EXYNOS_4210_UPHYPWR_PHY0_PWR | \
+       EXYNOS_4210_UPHYPWR_PHY0_OTG_PWR | \
+       EXYNOS_4210_UPHYPWR_PHY0_SLEEP)
+
+#define EXYNOS_4210_UPHYPWR_PHY1_SUSPEND       BIT(6)
+#define EXYNOS_4210_UPHYPWR_PHY1_PWR           BIT(7)
+#define EXYNOS_4210_UPHYPWR_PHY1_SLEEP         BIT(8)
+#define EXYNOS_4210_UPHYPWR_PHY1 ( \
+       EXYNOS_4210_UPHYPWR_PHY1_SUSPEND | \
+       EXYNOS_4210_UPHYPWR_PHY1_PWR | \
+       EXYNOS_4210_UPHYPWR_PHY1_SLEEP)
+
+#define EXYNOS_4210_UPHYPWR_HSIC0_SUSPEND      BIT(9)
+#define EXYNOS_4210_UPHYPWR_HSIC0_SLEEP                BIT(10)
+#define EXYNOS_4210_UPHYPWR_HSIC0 ( \
+       EXYNOS_4210_UPHYPWR_HSIC0_SUSPEND | \
+       EXYNOS_4210_UPHYPWR_HSIC0_SLEEP)
+
+#define EXYNOS_4210_UPHYPWR_HSIC1_SUSPEND      BIT(11)
+#define EXYNOS_4210_UPHYPWR_HSIC1_SLEEP                BIT(12)
+#define EXYNOS_4210_UPHYPWR_HSIC1 ( \
+       EXYNOS_4210_UPHYPWR_HSIC1_SUSPEND | \
+       EXYNOS_4210_UPHYPWR_HSIC1_SLEEP)
+
+/* PHY clock control */
+#define EXYNOS_4210_UPHYCLK                    0x4
+
+#define EXYNOS_4210_UPHYCLK_PHYFSEL_MASK       (0x3 << 0)
+#define EXYNOS_4210_UPHYCLK_PHYFSEL_OFFSET     0
+#define EXYNOS_4210_UPHYCLK_PHYFSEL_48MHZ      (0x0 << 0)
+#define EXYNOS_4210_UPHYCLK_PHYFSEL_24MHZ      (0x3 << 0)
+#define EXYNOS_4210_UPHYCLK_PHYFSEL_12MHZ      (0x2 << 0)
+
+#define EXYNOS_4210_UPHYCLK_PHY0_ID_PULLUP     BIT(2)
+#define EXYNOS_4210_UPHYCLK_PHY0_COMMON_ON     BIT(4)
+#define EXYNOS_4210_UPHYCLK_PHY1_COMMON_ON     BIT(7)
+
+/* PHY reset control */
+#define EXYNOS_4210_UPHYRST                    0x8
+
+#define EXYNOS_4210_URSTCON_PHY0               BIT(0)
+#define EXYNOS_4210_URSTCON_OTG_HLINK          BIT(1)
+#define EXYNOS_4210_URSTCON_OTG_PHYLINK                BIT(2)
+#define EXYNOS_4210_URSTCON_PHY1_ALL           BIT(3)
+#define EXYNOS_4210_URSTCON_PHY1_P0            BIT(4)
+#define EXYNOS_4210_URSTCON_PHY1_P1P2          BIT(5)
+#define EXYNOS_4210_URSTCON_HOST_LINK_ALL      BIT(6)
+#define EXYNOS_4210_URSTCON_HOST_LINK_P0       BIT(7)
+#define EXYNOS_4210_URSTCON_HOST_LINK_P1       BIT(8)
+#define EXYNOS_4210_URSTCON_HOST_LINK_P2       BIT(9)
+
+/* Isolation, configured in the power management unit */
+#define EXYNOS_4210_USB_ISOL_DEVICE_OFFSET     0x704
+#define EXYNOS_4210_USB_ISOL_DEVICE            BIT(0)
+#define EXYNOS_4210_USB_ISOL_HOST_OFFSET       0x708
+#define EXYNOS_4210_USB_ISOL_HOST              BIT(0)
+
+/* USBYPHY1 Floating prevention */
+#define EXYNOS_4210_UPHY1CON                   0x34
+#define EXYNOS_4210_UPHY1CON_FLOAT_PREVENTION  0x1
+
+/* Mode switching SUB Device <-> Host */
+#define EXYNOS_4210_MODE_SWITCH_OFFSET         0x21c
+#define EXYNOS_4210_MODE_SWITCH_MASK           1
+#define EXYNOS_4210_MODE_SWITCH_DEVICE         0
+#define EXYNOS_4210_MODE_SWITCH_HOST           1
+
+enum exynos4210_phy_id {
+       EXYNOS4210_DEVICE,
+       EXYNOS4210_HOST,
+       EXYNOS4210_HSIC0,
+       EXYNOS4210_HSIC1,
+       EXYNOS4210_NUM_PHYS,
+};
+
+/*
+ * exynos4210_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static int exynos4210_rate_to_clk(unsigned long rate, u32 *reg)
+{
+       switch (rate) {
+       case 12 * MHZ:
+               *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_12MHZ;
+               break;
+       case 24 * MHZ:
+               *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_24MHZ;
+               break;
+       case 48 * MHZ:
+               *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_48MHZ;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void exynos4210_isol(struct samsung_usb2_phy_instance *inst, bool on)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       u32 offset;
+       u32 mask;
+
+       switch (inst->cfg->id) {
+       case EXYNOS4210_DEVICE:
+               offset = EXYNOS_4210_USB_ISOL_DEVICE_OFFSET;
+               mask = EXYNOS_4210_USB_ISOL_DEVICE;
+               break;
+       case EXYNOS4210_HOST:
+               offset = EXYNOS_4210_USB_ISOL_HOST_OFFSET;
+               mask = EXYNOS_4210_USB_ISOL_HOST;
+               break;
+       default:
+               return;
+       }
+
+       regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
+}
+
+static void exynos4210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       u32 rstbits = 0;
+       u32 phypwr = 0;
+       u32 rst;
+       u32 pwr;
+       u32 clk;
+
+       switch (inst->cfg->id) {
+       case EXYNOS4210_DEVICE:
+               phypwr =        EXYNOS_4210_UPHYPWR_PHY0;
+               rstbits =       EXYNOS_4210_URSTCON_PHY0;
+               break;
+       case EXYNOS4210_HOST:
+               phypwr =        EXYNOS_4210_UPHYPWR_PHY1;
+               rstbits =       EXYNOS_4210_URSTCON_PHY1_ALL |
+                               EXYNOS_4210_URSTCON_PHY1_P0 |
+                               EXYNOS_4210_URSTCON_PHY1_P1P2 |
+                               EXYNOS_4210_URSTCON_HOST_LINK_ALL |
+                               EXYNOS_4210_URSTCON_HOST_LINK_P0;
+               writel(on, drv->reg_phy + EXYNOS_4210_UPHY1CON);
+               break;
+       case EXYNOS4210_HSIC0:
+               phypwr =        EXYNOS_4210_UPHYPWR_HSIC0;
+               rstbits =       EXYNOS_4210_URSTCON_PHY1_P1P2 |
+                               EXYNOS_4210_URSTCON_HOST_LINK_P1;
+               break;
+       case EXYNOS4210_HSIC1:
+               phypwr =        EXYNOS_4210_UPHYPWR_HSIC1;
+               rstbits =       EXYNOS_4210_URSTCON_PHY1_P1P2 |
+                               EXYNOS_4210_URSTCON_HOST_LINK_P2;
+               break;
+       }
+
+       if (on) {
+               clk = readl(drv->reg_phy + EXYNOS_4210_UPHYCLK);
+               clk &= ~EXYNOS_4210_UPHYCLK_PHYFSEL_MASK;
+               clk |= drv->ref_reg_val << EXYNOS_4210_UPHYCLK_PHYFSEL_OFFSET;
+               writel(clk, drv->reg_phy + EXYNOS_4210_UPHYCLK);
+
+               pwr = readl(drv->reg_phy + EXYNOS_4210_UPHYPWR);
+               pwr &= ~phypwr;
+               writel(pwr, drv->reg_phy + EXYNOS_4210_UPHYPWR);
+
+               rst = readl(drv->reg_phy + EXYNOS_4210_UPHYRST);
+               rst |= rstbits;
+               writel(rst, drv->reg_phy + EXYNOS_4210_UPHYRST);
+               udelay(10);
+               rst &= ~rstbits;
+               writel(rst, drv->reg_phy + EXYNOS_4210_UPHYRST);
+               /* The following delay is necessary for the reset sequence to be
+                * completed */
+               udelay(80);
+       } else {
+               pwr = readl(drv->reg_phy + EXYNOS_4210_UPHYPWR);
+               pwr |= phypwr;
+               writel(pwr, drv->reg_phy + EXYNOS_4210_UPHYPWR);
+       }
+}
+
+static int exynos4210_power_on(struct samsung_usb2_phy_instance *inst)
+{
+       /* Order of initialisation is important - first power then isolation */
+       exynos4210_phy_pwr(inst, 1);
+       exynos4210_isol(inst, 0);
+
+       return 0;
+}
+
+static int exynos4210_power_off(struct samsung_usb2_phy_instance *inst)
+{
+       exynos4210_isol(inst, 1);
+       exynos4210_phy_pwr(inst, 0);
+
+       return 0;
+}
+
+
+static const struct samsung_usb2_common_phy exynos4210_phys[] = {
+       {
+               .label          = "device",
+               .id             = EXYNOS4210_DEVICE,
+               .power_on       = exynos4210_power_on,
+               .power_off      = exynos4210_power_off,
+       },
+       {
+               .label          = "host",
+               .id             = EXYNOS4210_HOST,
+               .power_on       = exynos4210_power_on,
+               .power_off      = exynos4210_power_off,
+       },
+       {
+               .label          = "hsic0",
+               .id             = EXYNOS4210_HSIC0,
+               .power_on       = exynos4210_power_on,
+               .power_off      = exynos4210_power_off,
+       },
+       {
+               .label          = "hsic1",
+               .id             = EXYNOS4210_HSIC1,
+               .power_on       = exynos4210_power_on,
+               .power_off      = exynos4210_power_off,
+       },
+};
+
+const struct samsung_usb2_phy_config exynos4210_usb2_phy_config = {
+       .has_mode_switch        = 0,
+       .num_phys               = EXYNOS4210_NUM_PHYS,
+       .phys                   = exynos4210_phys,
+       .rate_to_clk            = exynos4210_rate_to_clk,
+};
diff --git a/drivers/phy/samsung/phy-exynos4x12-usb2.c b/drivers/phy/samsung/phy-exynos4x12-usb2.c
new file mode 100644 (file)
index 0000000..7f27a91
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4x12 support
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Kamil Debski <k.debski@samsung.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.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include "phy-samsung-usb2.h"
+
+/* Exynos USB PHY registers */
+
+/* PHY power control */
+#define EXYNOS_4x12_UPHYPWR                    0x0
+
+#define EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND       BIT(0)
+#define EXYNOS_4x12_UPHYPWR_PHY0_PWR           BIT(3)
+#define EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR       BIT(4)
+#define EXYNOS_4x12_UPHYPWR_PHY0_SLEEP         BIT(5)
+#define EXYNOS_4x12_UPHYPWR_PHY0 ( \
+       EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND | \
+       EXYNOS_4x12_UPHYPWR_PHY0_PWR | \
+       EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR | \
+       EXYNOS_4x12_UPHYPWR_PHY0_SLEEP)
+
+#define EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND       BIT(6)
+#define EXYNOS_4x12_UPHYPWR_PHY1_PWR           BIT(7)
+#define EXYNOS_4x12_UPHYPWR_PHY1_SLEEP         BIT(8)
+#define EXYNOS_4x12_UPHYPWR_PHY1 ( \
+       EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND | \
+       EXYNOS_4x12_UPHYPWR_PHY1_PWR | \
+       EXYNOS_4x12_UPHYPWR_PHY1_SLEEP)
+
+#define EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND      BIT(9)
+#define EXYNOS_4x12_UPHYPWR_HSIC0_PWR          BIT(10)
+#define EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP                BIT(11)
+#define EXYNOS_4x12_UPHYPWR_HSIC0 ( \
+       EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND | \
+       EXYNOS_4x12_UPHYPWR_HSIC0_PWR | \
+       EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP)
+
+#define EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND      BIT(12)
+#define EXYNOS_4x12_UPHYPWR_HSIC1_PWR          BIT(13)
+#define EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP                BIT(14)
+#define EXYNOS_4x12_UPHYPWR_HSIC1 ( \
+       EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND | \
+       EXYNOS_4x12_UPHYPWR_HSIC1_PWR | \
+       EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP)
+
+/* PHY clock control */
+#define EXYNOS_4x12_UPHYCLK                    0x4
+
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK       (0x7 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET     0
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6      (0x0 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ      (0x1 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ      (0x2 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2     (0x3 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ      (0x4 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ      (0x5 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ      (0x7 << 0)
+
+#define EXYNOS_3250_UPHYCLK_REFCLKSEL          (0x2 << 8)
+
+#define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP     BIT(3)
+#define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON     BIT(4)
+#define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON     BIT(7)
+
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_MASK   (0x7f << 10)
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_OFFSET  10
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_12MHZ  (0x24 << 10)
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_15MHZ  (0x1c << 10)
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_16MHZ  (0x1a << 10)
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_19MHZ2 (0x15 << 10)
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_20MHZ  (0x14 << 10)
+
+/* PHY reset control */
+#define EXYNOS_4x12_UPHYRST                    0x8
+
+#define EXYNOS_4x12_URSTCON_PHY0               BIT(0)
+#define EXYNOS_4x12_URSTCON_OTG_HLINK          BIT(1)
+#define EXYNOS_4x12_URSTCON_OTG_PHYLINK                BIT(2)
+#define EXYNOS_4x12_URSTCON_HOST_PHY           BIT(3)
+/* The following bit defines are presented in the
+ * order taken from the Exynos4412 reference manual.
+ *
+ * During experiments with the hardware and debugging
+ * it was determined that the hardware behaves contrary
+ * to the manual.
+ *
+ * The following bit values were chaned accordingly to the
+ * results of real hardware experiments.
+ */
+#define EXYNOS_4x12_URSTCON_PHY1               BIT(4)
+#define EXYNOS_4x12_URSTCON_HSIC0              BIT(6)
+#define EXYNOS_4x12_URSTCON_HSIC1              BIT(5)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_ALL      BIT(7)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P0       BIT(10)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P1       BIT(9)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P2       BIT(8)
+
+/* Isolation, configured in the power management unit */
+#define EXYNOS_4x12_USB_ISOL_OFFSET            0x704
+#define EXYNOS_4x12_USB_ISOL_OTG               BIT(0)
+#define EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET      0x708
+#define EXYNOS_4x12_USB_ISOL_HSIC0             BIT(0)
+#define EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET      0x70c
+#define EXYNOS_4x12_USB_ISOL_HSIC1             BIT(0)
+
+/* Mode switching SUB Device <-> Host */
+#define EXYNOS_4x12_MODE_SWITCH_OFFSET         0x21c
+#define EXYNOS_4x12_MODE_SWITCH_MASK           1
+#define EXYNOS_4x12_MODE_SWITCH_DEVICE         0
+#define EXYNOS_4x12_MODE_SWITCH_HOST           1
+
+enum exynos4x12_phy_id {
+       EXYNOS4x12_DEVICE,
+       EXYNOS4x12_HOST,
+       EXYNOS4x12_HSIC0,
+       EXYNOS4x12_HSIC1,
+       EXYNOS4x12_NUM_PHYS,
+};
+
+/*
+ * exynos4x12_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static int exynos4x12_rate_to_clk(unsigned long rate, u32 *reg)
+{
+       /* EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK */
+
+       switch (rate) {
+       case 9600 * KHZ:
+               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6;
+               break;
+       case 10 * MHZ:
+               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ;
+               break;
+       case 12 * MHZ:
+               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ;
+               break;
+       case 19200 * KHZ:
+               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2;
+               break;
+       case 20 * MHZ:
+               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ;
+               break;
+       case 24 * MHZ:
+               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ;
+               break;
+       case 50 * MHZ:
+               *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void exynos4x12_isol(struct samsung_usb2_phy_instance *inst, bool on)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       u32 offset;
+       u32 mask;
+
+       switch (inst->cfg->id) {
+       case EXYNOS4x12_DEVICE:
+       case EXYNOS4x12_HOST:
+               offset = EXYNOS_4x12_USB_ISOL_OFFSET;
+               mask = EXYNOS_4x12_USB_ISOL_OTG;
+               break;
+       case EXYNOS4x12_HSIC0:
+               offset = EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET;
+               mask = EXYNOS_4x12_USB_ISOL_HSIC0;
+               break;
+       case EXYNOS4x12_HSIC1:
+               offset = EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET;
+               mask = EXYNOS_4x12_USB_ISOL_HSIC1;
+               break;
+       default:
+               return;
+       }
+
+       regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
+}
+
+static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       u32 clk;
+
+       clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
+       clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
+
+       if (drv->cfg->has_refclk_sel)
+               clk = EXYNOS_3250_UPHYCLK_REFCLKSEL;
+
+       clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
+       clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
+       writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
+}
+
+static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       u32 rstbits = 0;
+       u32 phypwr = 0;
+       u32 rst;
+       u32 pwr;
+
+       switch (inst->cfg->id) {
+       case EXYNOS4x12_DEVICE:
+               phypwr =        EXYNOS_4x12_UPHYPWR_PHY0;
+               rstbits =       EXYNOS_4x12_URSTCON_PHY0;
+               break;
+       case EXYNOS4x12_HOST:
+               phypwr =        EXYNOS_4x12_UPHYPWR_PHY1;
+               rstbits =       EXYNOS_4x12_URSTCON_HOST_PHY |
+                               EXYNOS_4x12_URSTCON_PHY1 |
+                               EXYNOS_4x12_URSTCON_HOST_LINK_P0;
+               break;
+       case EXYNOS4x12_HSIC0:
+               phypwr =        EXYNOS_4x12_UPHYPWR_HSIC0;
+               rstbits =       EXYNOS_4x12_URSTCON_HSIC0 |
+                               EXYNOS_4x12_URSTCON_HOST_LINK_P1;
+               break;
+       case EXYNOS4x12_HSIC1:
+               phypwr =        EXYNOS_4x12_UPHYPWR_HSIC1;
+               rstbits =       EXYNOS_4x12_URSTCON_HSIC1 |
+                               EXYNOS_4x12_URSTCON_HOST_LINK_P1;
+               break;
+       }
+
+       if (on) {
+               pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
+               pwr &= ~phypwr;
+               writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
+
+               rst = readl(drv->reg_phy + EXYNOS_4x12_UPHYRST);
+               rst |= rstbits;
+               writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
+               udelay(10);
+               rst &= ~rstbits;
+               writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
+               /* The following delay is necessary for the reset sequence to be
+                * completed */
+               udelay(80);
+       } else {
+               pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
+               pwr |= phypwr;
+               writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
+       }
+}
+
+static void exynos4x12_power_on_int(struct samsung_usb2_phy_instance *inst)
+{
+       if (inst->int_cnt++ > 0)
+               return;
+
+       exynos4x12_setup_clk(inst);
+       exynos4x12_isol(inst, 0);
+       exynos4x12_phy_pwr(inst, 1);
+}
+
+static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+
+       if (inst->ext_cnt++ > 0)
+               return 0;
+
+       if (inst->cfg->id == EXYNOS4x12_HOST) {
+               regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+                                               EXYNOS_4x12_MODE_SWITCH_MASK,
+                                               EXYNOS_4x12_MODE_SWITCH_HOST);
+               exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
+       }
+
+       if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
+               regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+                                               EXYNOS_4x12_MODE_SWITCH_MASK,
+                                               EXYNOS_4x12_MODE_SWITCH_DEVICE);
+
+       if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+               inst->cfg->id == EXYNOS4x12_HSIC1) {
+               exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
+               exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_HOST]);
+       }
+
+       exynos4x12_power_on_int(inst);
+
+       return 0;
+}
+
+static void exynos4x12_power_off_int(struct samsung_usb2_phy_instance *inst)
+{
+       if (inst->int_cnt-- > 1)
+               return;
+
+       exynos4x12_isol(inst, 1);
+       exynos4x12_phy_pwr(inst, 0);
+}
+
+static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+
+       if (inst->ext_cnt-- > 1)
+               return 0;
+
+       if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
+               regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+                                               EXYNOS_4x12_MODE_SWITCH_MASK,
+                                               EXYNOS_4x12_MODE_SWITCH_HOST);
+
+       if (inst->cfg->id == EXYNOS4x12_HOST)
+               exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
+
+       if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+               inst->cfg->id == EXYNOS4x12_HSIC1) {
+               exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
+               exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_HOST]);
+       }
+
+       exynos4x12_power_off_int(inst);
+
+       return 0;
+}
+
+
+static const struct samsung_usb2_common_phy exynos4x12_phys[] = {
+       {
+               .label          = "device",
+               .id             = EXYNOS4x12_DEVICE,
+               .power_on       = exynos4x12_power_on,
+               .power_off      = exynos4x12_power_off,
+       },
+       {
+               .label          = "host",
+               .id             = EXYNOS4x12_HOST,
+               .power_on       = exynos4x12_power_on,
+               .power_off      = exynos4x12_power_off,
+       },
+       {
+               .label          = "hsic0",
+               .id             = EXYNOS4x12_HSIC0,
+               .power_on       = exynos4x12_power_on,
+               .power_off      = exynos4x12_power_off,
+       },
+       {
+               .label          = "hsic1",
+               .id             = EXYNOS4x12_HSIC1,
+               .power_on       = exynos4x12_power_on,
+               .power_off      = exynos4x12_power_off,
+       },
+};
+
+const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = {
+       .has_refclk_sel         = 1,
+       .num_phys               = 1,
+       .phys                   = exynos4x12_phys,
+       .rate_to_clk            = exynos4x12_rate_to_clk,
+};
+
+const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = {
+       .has_mode_switch        = 1,
+       .num_phys               = EXYNOS4x12_NUM_PHYS,
+       .phys                   = exynos4x12_phys,
+       .rate_to_clk            = exynos4x12_rate_to_clk,
+};
diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c
new file mode 100644 (file)
index 0000000..7c41daa
--- /dev/null
@@ -0,0 +1,782 @@
+/*
+ * Samsung EXYNOS5 SoC series USB DRD PHY driver
+ *
+ * Phy provider for USB 3.0 DRD controller on Exynos5 SoC series
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd.
+ * Author: Vivek Gautam <gautam.vivek@samsung.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.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/mutex.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/soc/samsung/exynos-regs-pmu.h>
+
+/* Exynos USB PHY registers */
+#define EXYNOS5_FSEL_9MHZ6             0x0
+#define EXYNOS5_FSEL_10MHZ             0x1
+#define EXYNOS5_FSEL_12MHZ             0x2
+#define EXYNOS5_FSEL_19MHZ2            0x3
+#define EXYNOS5_FSEL_20MHZ             0x4
+#define EXYNOS5_FSEL_24MHZ             0x5
+#define EXYNOS5_FSEL_50MHZ             0x7
+
+/* EXYNOS5: USB 3.0 DRD PHY registers */
+#define EXYNOS5_DRD_LINKSYSTEM                 0x04
+
+#define LINKSYSTEM_FLADJ_MASK                  (0x3f << 1)
+#define LINKSYSTEM_FLADJ(_x)                   ((_x) << 1)
+#define LINKSYSTEM_XHCI_VERSION_CONTROL                BIT(27)
+
+#define EXYNOS5_DRD_PHYUTMI                    0x08
+
+#define PHYUTMI_OTGDISABLE                     BIT(6)
+#define PHYUTMI_FORCESUSPEND                   BIT(1)
+#define PHYUTMI_FORCESLEEP                     BIT(0)
+
+#define EXYNOS5_DRD_PHYPIPE                    0x0c
+
+#define EXYNOS5_DRD_PHYCLKRST                  0x10
+
+#define PHYCLKRST_EN_UTMISUSPEND               BIT(31)
+
+#define PHYCLKRST_SSC_REFCLKSEL_MASK           (0xff << 23)
+#define PHYCLKRST_SSC_REFCLKSEL(_x)            ((_x) << 23)
+
+#define PHYCLKRST_SSC_RANGE_MASK               (0x03 << 21)
+#define PHYCLKRST_SSC_RANGE(_x)                        ((_x) << 21)
+
+#define PHYCLKRST_SSC_EN                       BIT(20)
+#define PHYCLKRST_REF_SSP_EN                   BIT(19)
+#define PHYCLKRST_REF_CLKDIV2                  BIT(18)
+
+#define PHYCLKRST_MPLL_MULTIPLIER_MASK         (0x7f << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF   (0x19 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF      (0x32 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF    (0x68 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF    (0x7d << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11)
+
+#define PHYCLKRST_FSEL_UTMI_MASK               (0x7 << 5)
+#define PHYCLKRST_FSEL_PIPE_MASK               (0x7 << 8)
+#define PHYCLKRST_FSEL(_x)                     ((_x) << 5)
+#define PHYCLKRST_FSEL_PAD_100MHZ              (0x27 << 5)
+#define PHYCLKRST_FSEL_PAD_24MHZ               (0x2a << 5)
+#define PHYCLKRST_FSEL_PAD_20MHZ               (0x31 << 5)
+#define PHYCLKRST_FSEL_PAD_19_2MHZ             (0x38 << 5)
+
+#define PHYCLKRST_RETENABLEN                   BIT(4)
+
+#define PHYCLKRST_REFCLKSEL_MASK               (0x03 << 2)
+#define PHYCLKRST_REFCLKSEL_PAD_REFCLK         (0x2 << 2)
+#define PHYCLKRST_REFCLKSEL_EXT_REFCLK         (0x3 << 2)
+
+#define PHYCLKRST_PORTRESET                    BIT(1)
+#define PHYCLKRST_COMMONONN                    BIT(0)
+
+#define EXYNOS5_DRD_PHYREG0                    0x14
+#define EXYNOS5_DRD_PHYREG1                    0x18
+
+#define EXYNOS5_DRD_PHYPARAM0                  0x1c
+
+#define PHYPARAM0_REF_USE_PAD                  BIT(31)
+#define PHYPARAM0_REF_LOSLEVEL_MASK            (0x1f << 26)
+#define PHYPARAM0_REF_LOSLEVEL                 (0x9 << 26)
+
+#define EXYNOS5_DRD_PHYPARAM1                  0x20
+
+#define PHYPARAM1_PCS_TXDEEMPH_MASK            (0x1f << 0)
+#define PHYPARAM1_PCS_TXDEEMPH                 (0x1c)
+
+#define EXYNOS5_DRD_PHYTERM                    0x24
+
+#define EXYNOS5_DRD_PHYTEST                    0x28
+
+#define PHYTEST_POWERDOWN_SSP                  BIT(3)
+#define PHYTEST_POWERDOWN_HSP                  BIT(2)
+
+#define EXYNOS5_DRD_PHYADP                     0x2c
+
+#define EXYNOS5_DRD_PHYUTMICLKSEL              0x30
+
+#define PHYUTMICLKSEL_UTMI_CLKSEL              BIT(2)
+
+#define EXYNOS5_DRD_PHYRESUME                  0x34
+#define EXYNOS5_DRD_LINKPORT                   0x44
+
+#define KHZ    1000
+#define MHZ    (KHZ * KHZ)
+
+enum exynos5_usbdrd_phy_id {
+       EXYNOS5_DRDPHY_UTMI,
+       EXYNOS5_DRDPHY_PIPE3,
+       EXYNOS5_DRDPHYS_NUM,
+};
+
+struct phy_usb_instance;
+struct exynos5_usbdrd_phy;
+
+struct exynos5_usbdrd_phy_config {
+       u32 id;
+       void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
+       void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
+       unsigned int (*set_refclk)(struct phy_usb_instance *inst);
+};
+
+struct exynos5_usbdrd_phy_drvdata {
+       const struct exynos5_usbdrd_phy_config *phy_cfg;
+       u32 pmu_offset_usbdrd0_phy;
+       u32 pmu_offset_usbdrd1_phy;
+       bool has_common_clk_gate;
+};
+
+/**
+ * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY
+ * @dev: pointer to device instance of this platform device
+ * @reg_phy: usb phy controller register memory base
+ * @clk: phy clock for register access
+ * @pipeclk: clock for pipe3 phy
+ * @utmiclk: clock for utmi+ phy
+ * @itpclk: clock for ITP generation
+ * @drv_data: pointer to SoC level driver data structure
+ * @phys[]: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
+ *         instances each with its 'phy' and 'phy_cfg'.
+ * @extrefclk: frequency select settings when using 'separate
+ *            reference clocks' for SS and HS operations
+ * @ref_clk: reference clock to PHY block from which PHY's
+ *          operational clocks are derived
+ * vbus: VBUS regulator for phy
+ * vbus_boost: Boost regulator for VBUS present on few Exynos boards
+ */
+struct exynos5_usbdrd_phy {
+       struct device *dev;
+       void __iomem *reg_phy;
+       struct clk *clk;
+       struct clk *pipeclk;
+       struct clk *utmiclk;
+       struct clk *itpclk;
+       const struct exynos5_usbdrd_phy_drvdata *drv_data;
+       struct phy_usb_instance {
+               struct phy *phy;
+               u32 index;
+               struct regmap *reg_pmu;
+               u32 pmu_offset;
+               const struct exynos5_usbdrd_phy_config *phy_cfg;
+       } phys[EXYNOS5_DRDPHYS_NUM];
+       u32 extrefclk;
+       struct clk *ref_clk;
+       struct regulator *vbus;
+       struct regulator *vbus_boost;
+};
+
+static inline
+struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst)
+{
+       return container_of((inst), struct exynos5_usbdrd_phy,
+                           phys[(inst)->index]);
+}
+
+/*
+ * exynos5_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg)
+{
+       /* EXYNOS5_FSEL_MASK */
+
+       switch (rate) {
+       case 9600 * KHZ:
+               *reg = EXYNOS5_FSEL_9MHZ6;
+               break;
+       case 10 * MHZ:
+               *reg = EXYNOS5_FSEL_10MHZ;
+               break;
+       case 12 * MHZ:
+               *reg = EXYNOS5_FSEL_12MHZ;
+               break;
+       case 19200 * KHZ:
+               *reg = EXYNOS5_FSEL_19MHZ2;
+               break;
+       case 20 * MHZ:
+               *reg = EXYNOS5_FSEL_20MHZ;
+               break;
+       case 24 * MHZ:
+               *reg = EXYNOS5_FSEL_24MHZ;
+               break;
+       case 50 * MHZ:
+               *reg = EXYNOS5_FSEL_50MHZ;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst,
+                                               unsigned int on)
+{
+       unsigned int val;
+
+       if (!inst->reg_pmu)
+               return;
+
+       val = on ? 0 : EXYNOS4_PHY_ENABLE;
+
+       regmap_update_bits(inst->reg_pmu, inst->pmu_offset,
+                          EXYNOS4_PHY_ENABLE, val);
+}
+
+/*
+ * Sets the pipe3 phy's clk as EXTREFCLK (XXTI) which is internal clock
+ * from clock core. Further sets multiplier values and spread spectrum
+ * clock settings for SuperSpeed operations.
+ */
+static unsigned int
+exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
+{
+       u32 reg;
+       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+       /* restore any previous reference clock settings */
+       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+
+       /* Use EXTREFCLK as ref clock */
+       reg &= ~PHYCLKRST_REFCLKSEL_MASK;
+       reg |=  PHYCLKRST_REFCLKSEL_EXT_REFCLK;
+
+       /* FSEL settings corresponding to reference clock */
+       reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
+               PHYCLKRST_MPLL_MULTIPLIER_MASK |
+               PHYCLKRST_SSC_REFCLKSEL_MASK;
+       switch (phy_drd->extrefclk) {
+       case EXYNOS5_FSEL_50MHZ:
+               reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
+                       PHYCLKRST_SSC_REFCLKSEL(0x00));
+               break;
+       case EXYNOS5_FSEL_24MHZ:
+               reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
+                       PHYCLKRST_SSC_REFCLKSEL(0x88));
+               break;
+       case EXYNOS5_FSEL_20MHZ:
+               reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
+                       PHYCLKRST_SSC_REFCLKSEL(0x00));
+               break;
+       case EXYNOS5_FSEL_19MHZ2:
+               reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
+                       PHYCLKRST_SSC_REFCLKSEL(0x88));
+               break;
+       default:
+               dev_dbg(phy_drd->dev, "unsupported ref clk\n");
+               break;
+       }
+
+       return reg;
+}
+
+/*
+ * Sets the utmi phy's clk as EXTREFCLK (XXTI) which is internal clock
+ * from clock core. Further sets the FSEL values for HighSpeed operations.
+ */
+static unsigned int
+exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
+{
+       u32 reg;
+       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+       /* restore any previous reference clock settings */
+       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+
+       reg &= ~PHYCLKRST_REFCLKSEL_MASK;
+       reg |=  PHYCLKRST_REFCLKSEL_EXT_REFCLK;
+
+       reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
+               PHYCLKRST_MPLL_MULTIPLIER_MASK |
+               PHYCLKRST_SSC_REFCLKSEL_MASK;
+       reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
+
+       return reg;
+}
+
+static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
+{
+       u32 reg;
+
+       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
+       /* Set Tx De-Emphasis level */
+       reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
+       reg |=  PHYPARAM1_PCS_TXDEEMPH;
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
+
+       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+       reg &= ~PHYTEST_POWERDOWN_SSP;
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+}
+
+static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
+{
+       u32 reg;
+
+       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
+       /* Set Loss-of-Signal Detector sensitivity */
+       reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
+       reg |=  PHYPARAM0_REF_LOSLEVEL;
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
+
+       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
+       /* Set Tx De-Emphasis level */
+       reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
+       reg |=  PHYPARAM1_PCS_TXDEEMPH;
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
+
+       /* UTMI Power Control */
+       writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
+
+       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+       reg &= ~PHYTEST_POWERDOWN_HSP;
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+}
+
+static int exynos5_usbdrd_phy_init(struct phy *phy)
+{
+       int ret;
+       u32 reg;
+       struct phy_usb_instance *inst = phy_get_drvdata(phy);
+       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+       ret = clk_prepare_enable(phy_drd->clk);
+       if (ret)
+               return ret;
+
+       /* Reset USB 3.0 PHY */
+       writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+       writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME);
+
+       /*
+        * Setting the Frame length Adj value[6:1] to default 0x20
+        * See xHCI 1.0 spec, 5.2.4
+        */
+       reg =   LINKSYSTEM_XHCI_VERSION_CONTROL |
+               LINKSYSTEM_FLADJ(0x20);
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
+
+       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
+       /* Select PHY CLK source */
+       reg &= ~PHYPARAM0_REF_USE_PAD;
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
+
+       /* This bit must be set for both HS and SS operations */
+       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
+       reg |= PHYUTMICLKSEL_UTMI_CLKSEL;
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
+
+       /* UTMI or PIPE3 specific init */
+       inst->phy_cfg->phy_init(phy_drd);
+
+       /* reference clock settings */
+       reg = inst->phy_cfg->set_refclk(inst);
+
+               /* Digital power supply in normal operating mode */
+       reg |=  PHYCLKRST_RETENABLEN |
+               /* Enable ref clock for SS function */
+               PHYCLKRST_REF_SSP_EN |
+               /* Enable spread spectrum */
+               PHYCLKRST_SSC_EN |
+               /* Power down HS Bias and PLL blocks in suspend mode */
+               PHYCLKRST_COMMONONN |
+               /* Reset the port */
+               PHYCLKRST_PORTRESET;
+
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+
+       udelay(10);
+
+       reg &= ~PHYCLKRST_PORTRESET;
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+
+       clk_disable_unprepare(phy_drd->clk);
+
+       return 0;
+}
+
+static int exynos5_usbdrd_phy_exit(struct phy *phy)
+{
+       int ret;
+       u32 reg;
+       struct phy_usb_instance *inst = phy_get_drvdata(phy);
+       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+       ret = clk_prepare_enable(phy_drd->clk);
+       if (ret)
+               return ret;
+
+       reg =   PHYUTMI_OTGDISABLE |
+               PHYUTMI_FORCESUSPEND |
+               PHYUTMI_FORCESLEEP;
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
+
+       /* Resetting the PHYCLKRST enable bits to reduce leakage current */
+       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+       reg &= ~(PHYCLKRST_REF_SSP_EN |
+                PHYCLKRST_SSC_EN |
+                PHYCLKRST_COMMONONN);
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+
+       /* Control PHYTEST to remove leakage current */
+       reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+       reg |=  PHYTEST_POWERDOWN_SSP |
+               PHYTEST_POWERDOWN_HSP;
+       writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+
+       clk_disable_unprepare(phy_drd->clk);
+
+       return 0;
+}
+
+static int exynos5_usbdrd_phy_power_on(struct phy *phy)
+{
+       int ret;
+       struct phy_usb_instance *inst = phy_get_drvdata(phy);
+       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+       dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
+
+       clk_prepare_enable(phy_drd->ref_clk);
+       if (!phy_drd->drv_data->has_common_clk_gate) {
+               clk_prepare_enable(phy_drd->pipeclk);
+               clk_prepare_enable(phy_drd->utmiclk);
+               clk_prepare_enable(phy_drd->itpclk);
+       }
+
+       /* Enable VBUS supply */
+       if (phy_drd->vbus_boost) {
+               ret = regulator_enable(phy_drd->vbus_boost);
+               if (ret) {
+                       dev_err(phy_drd->dev,
+                               "Failed to enable VBUS boost supply\n");
+                       goto fail_vbus;
+               }
+       }
+
+       if (phy_drd->vbus) {
+               ret = regulator_enable(phy_drd->vbus);
+               if (ret) {
+                       dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
+                       goto fail_vbus_boost;
+               }
+       }
+
+       /* Power-on PHY*/
+       inst->phy_cfg->phy_isol(inst, 0);
+
+       return 0;
+
+fail_vbus_boost:
+       if (phy_drd->vbus_boost)
+               regulator_disable(phy_drd->vbus_boost);
+
+fail_vbus:
+       clk_disable_unprepare(phy_drd->ref_clk);
+       if (!phy_drd->drv_data->has_common_clk_gate) {
+               clk_disable_unprepare(phy_drd->itpclk);
+               clk_disable_unprepare(phy_drd->utmiclk);
+               clk_disable_unprepare(phy_drd->pipeclk);
+       }
+
+       return ret;
+}
+
+static int exynos5_usbdrd_phy_power_off(struct phy *phy)
+{
+       struct phy_usb_instance *inst = phy_get_drvdata(phy);
+       struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+       dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");
+
+       /* Power-off the PHY */
+       inst->phy_cfg->phy_isol(inst, 1);
+
+       /* Disable VBUS supply */
+       if (phy_drd->vbus)
+               regulator_disable(phy_drd->vbus);
+       if (phy_drd->vbus_boost)
+               regulator_disable(phy_drd->vbus_boost);
+
+       clk_disable_unprepare(phy_drd->ref_clk);
+       if (!phy_drd->drv_data->has_common_clk_gate) {
+               clk_disable_unprepare(phy_drd->itpclk);
+               clk_disable_unprepare(phy_drd->pipeclk);
+               clk_disable_unprepare(phy_drd->utmiclk);
+       }
+
+       return 0;
+}
+
+static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
+                                       struct of_phandle_args *args)
+{
+       struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);
+
+       if (WARN_ON(args->args[0] >= EXYNOS5_DRDPHYS_NUM))
+               return ERR_PTR(-ENODEV);
+
+       return phy_drd->phys[args->args[0]].phy;
+}
+
+static const struct phy_ops exynos5_usbdrd_phy_ops = {
+       .init           = exynos5_usbdrd_phy_init,
+       .exit           = exynos5_usbdrd_phy_exit,
+       .power_on       = exynos5_usbdrd_phy_power_on,
+       .power_off      = exynos5_usbdrd_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
+{
+       unsigned long ref_rate;
+       int ret;
+
+       phy_drd->clk = devm_clk_get(phy_drd->dev, "phy");
+       if (IS_ERR(phy_drd->clk)) {
+               dev_err(phy_drd->dev, "Failed to get phy clock\n");
+               return PTR_ERR(phy_drd->clk);
+       }
+
+       phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref");
+       if (IS_ERR(phy_drd->ref_clk)) {
+               dev_err(phy_drd->dev, "Failed to get phy reference clock\n");
+               return PTR_ERR(phy_drd->ref_clk);
+       }
+       ref_rate = clk_get_rate(phy_drd->ref_clk);
+
+       ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
+       if (ret) {
+               dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
+                       ref_rate);
+               return ret;
+       }
+
+       if (!phy_drd->drv_data->has_common_clk_gate) {
+               phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe");
+               if (IS_ERR(phy_drd->pipeclk)) {
+                       dev_info(phy_drd->dev,
+                                "PIPE3 phy operational clock not specified\n");
+                       phy_drd->pipeclk = NULL;
+               }
+
+               phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi");
+               if (IS_ERR(phy_drd->utmiclk)) {
+                       dev_info(phy_drd->dev,
+                                "UTMI phy operational clock not specified\n");
+                       phy_drd->utmiclk = NULL;
+               }
+
+               phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp");
+               if (IS_ERR(phy_drd->itpclk)) {
+                       dev_info(phy_drd->dev,
+                                "ITP clock from main OSC not specified\n");
+                       phy_drd->itpclk = NULL;
+               }
+       }
+
+       return 0;
+}
+
+static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
+       {
+               .id             = EXYNOS5_DRDPHY_UTMI,
+               .phy_isol       = exynos5_usbdrd_phy_isol,
+               .phy_init       = exynos5_usbdrd_utmi_init,
+               .set_refclk     = exynos5_usbdrd_utmi_set_refclk,
+       },
+       {
+               .id             = EXYNOS5_DRDPHY_PIPE3,
+               .phy_isol       = exynos5_usbdrd_phy_isol,
+               .phy_init       = exynos5_usbdrd_pipe3_init,
+               .set_refclk     = exynos5_usbdrd_pipe3_set_refclk,
+       },
+};
+
+static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
+       .phy_cfg                = phy_cfg_exynos5,
+       .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
+       .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
+       .has_common_clk_gate    = true,
+};
+
+static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
+       .phy_cfg                = phy_cfg_exynos5,
+       .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
+       .has_common_clk_gate    = true,
+};
+
+static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
+       .phy_cfg                = phy_cfg_exynos5,
+       .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
+       .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL,
+       .has_common_clk_gate    = false,
+};
+
+static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
+       .phy_cfg                = phy_cfg_exynos5,
+       .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
+       .has_common_clk_gate    = false,
+};
+
+static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
+       {
+               .compatible = "samsung,exynos5250-usbdrd-phy",
+               .data = &exynos5250_usbdrd_phy
+       }, {
+               .compatible = "samsung,exynos5420-usbdrd-phy",
+               .data = &exynos5420_usbdrd_phy
+       }, {
+               .compatible = "samsung,exynos5433-usbdrd-phy",
+               .data = &exynos5433_usbdrd_phy
+       }, {
+               .compatible = "samsung,exynos7-usbdrd-phy",
+               .data = &exynos7_usbdrd_phy
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);
+
+static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *node = dev->of_node;
+       struct exynos5_usbdrd_phy *phy_drd;
+       struct phy_provider *phy_provider;
+       struct resource *res;
+       const struct of_device_id *match;
+       const struct exynos5_usbdrd_phy_drvdata *drv_data;
+       struct regmap *reg_pmu;
+       u32 pmu_offset;
+       int i, ret;
+       int channel;
+
+       phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL);
+       if (!phy_drd)
+               return -ENOMEM;
+
+       dev_set_drvdata(dev, phy_drd);
+       phy_drd->dev = dev;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       phy_drd->reg_phy = devm_ioremap_resource(dev, res);
+       if (IS_ERR(phy_drd->reg_phy))
+               return PTR_ERR(phy_drd->reg_phy);
+
+       match = of_match_node(exynos5_usbdrd_phy_of_match, pdev->dev.of_node);
+
+       drv_data = match->data;
+       phy_drd->drv_data = drv_data;
+
+       ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
+       if (ret) {
+               dev_err(dev, "Failed to initialize clocks\n");
+               return ret;
+       }
+
+       reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                                  "samsung,pmu-syscon");
+       if (IS_ERR(reg_pmu)) {
+               dev_err(dev, "Failed to lookup PMU regmap\n");
+               return PTR_ERR(reg_pmu);
+       }
+
+       /*
+        * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with
+        * each having separate power control registers.
+        * 'channel' facilitates to set such registers.
+        */
+       channel = of_alias_get_id(node, "usbdrdphy");
+       if (channel < 0)
+               dev_dbg(dev, "Not a multi-controller usbdrd phy\n");
+
+       switch (channel) {
+       case 1:
+               pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy;
+               break;
+       case 0:
+       default:
+               pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy;
+               break;
+       }
+
+       /* Get Vbus regulators */
+       phy_drd->vbus = devm_regulator_get(dev, "vbus");
+       if (IS_ERR(phy_drd->vbus)) {
+               ret = PTR_ERR(phy_drd->vbus);
+               if (ret == -EPROBE_DEFER)
+                       return ret;
+
+               dev_warn(dev, "Failed to get VBUS supply regulator\n");
+               phy_drd->vbus = NULL;
+       }
+
+       phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost");
+       if (IS_ERR(phy_drd->vbus_boost)) {
+               ret = PTR_ERR(phy_drd->vbus_boost);
+               if (ret == -EPROBE_DEFER)
+                       return ret;
+
+               dev_warn(dev, "Failed to get VBUS boost supply regulator\n");
+               phy_drd->vbus_boost = NULL;
+       }
+
+       dev_vdbg(dev, "Creating usbdrd_phy phy\n");
+
+       for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
+               struct phy *phy = devm_phy_create(dev, NULL,
+                                                 &exynos5_usbdrd_phy_ops);
+               if (IS_ERR(phy)) {
+                       dev_err(dev, "Failed to create usbdrd_phy phy\n");
+                       return PTR_ERR(phy);
+               }
+
+               phy_drd->phys[i].phy = phy;
+               phy_drd->phys[i].index = i;
+               phy_drd->phys[i].reg_pmu = reg_pmu;
+               phy_drd->phys[i].pmu_offset = pmu_offset;
+               phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i];
+               phy_set_drvdata(phy, &phy_drd->phys[i]);
+       }
+
+       phy_provider = devm_of_phy_provider_register(dev,
+                                                    exynos5_usbdrd_phy_xlate);
+       if (IS_ERR(phy_provider)) {
+               dev_err(phy_drd->dev, "Failed to register phy provider\n");
+               return PTR_ERR(phy_provider);
+       }
+
+       return 0;
+}
+
+static struct platform_driver exynos5_usb3drd_phy = {
+       .probe  = exynos5_usbdrd_phy_probe,
+       .driver = {
+               .of_match_table = exynos5_usbdrd_phy_of_match,
+               .name           = "exynos5_usb3drd_phy",
+       }
+};
+
+module_platform_driver(exynos5_usb3drd_phy);
+MODULE_DESCRIPTION("Samsung EXYNOS5 SoCs USB 3.0 DRD controller PHY driver");
+MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:exynos5_usb3drd_phy");
diff --git a/drivers/phy/samsung/phy-exynos5250-sata.c b/drivers/phy/samsung/phy-exynos5250-sata.c
new file mode 100644 (file)
index 0000000..60e13af
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Samsung SATA SerDes(PHY) driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Authors: Girish K S <ks.giri@samsung.com>
+ *         Yuvaraj Kumar C D <yuvaraj.cd@samsung.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/kernel.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/spinlock.h>
+#include <linux/mfd/syscon.h>
+
+#define SATAPHY_CONTROL_OFFSET         0x0724
+#define EXYNOS5_SATAPHY_PMU_ENABLE     BIT(0)
+#define EXYNOS5_SATA_RESET             0x4
+#define RESET_GLOBAL_RST_N             BIT(0)
+#define RESET_CMN_RST_N                        BIT(1)
+#define RESET_CMN_BLOCK_RST_N          BIT(2)
+#define RESET_CMN_I2C_RST_N            BIT(3)
+#define RESET_TX_RX_PIPE_RST_N         BIT(4)
+#define RESET_TX_RX_BLOCK_RST_N                BIT(5)
+#define RESET_TX_RX_I2C_RST_N          (BIT(6) | BIT(7))
+#define LINK_RESET                     0xf0000
+#define EXYNOS5_SATA_MODE0             0x10
+#define SATA_SPD_GEN3                  BIT(1)
+#define EXYNOS5_SATA_CTRL0             0x14
+#define CTRL0_P0_PHY_CALIBRATED_SEL    BIT(9)
+#define CTRL0_P0_PHY_CALIBRATED                BIT(8)
+#define EXYNOS5_SATA_PHSATA_CTRLM      0xe0
+#define PHCTRLM_REF_RATE               BIT(1)
+#define PHCTRLM_HIGH_SPEED             BIT(0)
+#define EXYNOS5_SATA_PHSATA_STATM      0xf0
+#define PHSTATM_PLL_LOCKED             BIT(0)
+
+#define PHY_PLL_TIMEOUT (usecs_to_jiffies(1000))
+
+struct exynos_sata_phy {
+       struct phy *phy;
+       struct clk *phyclk;
+       void __iomem *regs;
+       struct regmap *pmureg;
+       struct i2c_client *client;
+};
+
+static int wait_for_reg_status(void __iomem *base, u32 reg, u32 checkbit,
+                               u32 status)
+{
+       unsigned long timeout = jiffies + PHY_PLL_TIMEOUT;
+
+       while (time_before(jiffies, timeout)) {
+               if ((readl(base + reg) & checkbit) == status)
+                       return 0;
+       }
+
+       return -EFAULT;
+}
+
+static int exynos_sata_phy_power_on(struct phy *phy)
+{
+       struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
+
+       return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
+                       EXYNOS5_SATAPHY_PMU_ENABLE, true);
+
+}
+
+static int exynos_sata_phy_power_off(struct phy *phy)
+{
+       struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
+
+       return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
+                       EXYNOS5_SATAPHY_PMU_ENABLE, false);
+
+}
+
+static int exynos_sata_phy_init(struct phy *phy)
+{
+       u32 val = 0;
+       int ret = 0;
+       u8 buf[] = { 0x3a, 0x0b };
+       struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
+
+       ret = regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
+                       EXYNOS5_SATAPHY_PMU_ENABLE, true);
+       if (ret != 0)
+               dev_err(&sata_phy->phy->dev, "phy init failed\n");
+
+       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
+
+       val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
+       val |= RESET_GLOBAL_RST_N | RESET_CMN_RST_N | RESET_CMN_BLOCK_RST_N
+               | RESET_CMN_I2C_RST_N | RESET_TX_RX_PIPE_RST_N
+               | RESET_TX_RX_BLOCK_RST_N | RESET_TX_RX_I2C_RST_N;
+       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
+
+       val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
+       val |= LINK_RESET;
+       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
+
+       val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
+       val |= RESET_CMN_RST_N;
+       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
+
+       val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
+       val &= ~PHCTRLM_REF_RATE;
+       writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
+
+       /* High speed enable for Gen3 */
+       val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
+       val |= PHCTRLM_HIGH_SPEED;
+       writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
+
+       val = readl(sata_phy->regs + EXYNOS5_SATA_CTRL0);
+       val |= CTRL0_P0_PHY_CALIBRATED_SEL | CTRL0_P0_PHY_CALIBRATED;
+       writel(val, sata_phy->regs + EXYNOS5_SATA_CTRL0);
+
+       val = readl(sata_phy->regs + EXYNOS5_SATA_MODE0);
+       val |= SATA_SPD_GEN3;
+       writel(val, sata_phy->regs + EXYNOS5_SATA_MODE0);
+
+       ret = i2c_master_send(sata_phy->client, buf, sizeof(buf));
+       if (ret < 0)
+               return ret;
+
+       /* release cmu reset */
+       val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
+       val &= ~RESET_CMN_RST_N;
+       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
+
+       val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
+       val |= RESET_CMN_RST_N;
+       writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
+
+       ret = wait_for_reg_status(sata_phy->regs,
+                               EXYNOS5_SATA_PHSATA_STATM,
+                               PHSTATM_PLL_LOCKED, 1);
+       if (ret < 0)
+               dev_err(&sata_phy->phy->dev,
+                       "PHY PLL locking failed\n");
+       return ret;
+}
+
+static const struct phy_ops exynos_sata_phy_ops = {
+       .init           = exynos_sata_phy_init,
+       .power_on       = exynos_sata_phy_power_on,
+       .power_off      = exynos_sata_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int exynos_sata_phy_probe(struct platform_device *pdev)
+{
+       struct exynos_sata_phy *sata_phy;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       struct phy_provider *phy_provider;
+       struct device_node *node;
+       int ret = 0;
+
+       sata_phy = devm_kzalloc(dev, sizeof(*sata_phy), GFP_KERNEL);
+       if (!sata_phy)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       sata_phy->regs = devm_ioremap_resource(dev, res);
+       if (IS_ERR(sata_phy->regs))
+               return PTR_ERR(sata_phy->regs);
+
+       sata_phy->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                       "samsung,syscon-phandle");
+       if (IS_ERR(sata_phy->pmureg)) {
+               dev_err(dev, "syscon regmap lookup failed.\n");
+               return PTR_ERR(sata_phy->pmureg);
+       }
+
+       node = of_parse_phandle(dev->of_node,
+                       "samsung,exynos-sataphy-i2c-phandle", 0);
+       if (!node)
+               return -EINVAL;
+
+       sata_phy->client = of_find_i2c_device_by_node(node);
+       if (!sata_phy->client)
+               return -EPROBE_DEFER;
+
+       dev_set_drvdata(dev, sata_phy);
+
+       sata_phy->phyclk = devm_clk_get(dev, "sata_phyctrl");
+       if (IS_ERR(sata_phy->phyclk)) {
+               dev_err(dev, "failed to get clk for PHY\n");
+               return PTR_ERR(sata_phy->phyclk);
+       }
+
+       ret = clk_prepare_enable(sata_phy->phyclk);
+       if (ret < 0) {
+               dev_err(dev, "failed to enable source clk\n");
+               return ret;
+       }
+
+       sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops);
+       if (IS_ERR(sata_phy->phy)) {
+               clk_disable_unprepare(sata_phy->phyclk);
+               dev_err(dev, "failed to create PHY\n");
+               return PTR_ERR(sata_phy->phy);
+       }
+
+       phy_set_drvdata(sata_phy->phy, sata_phy);
+
+       phy_provider = devm_of_phy_provider_register(dev,
+                                       of_phy_simple_xlate);
+       if (IS_ERR(phy_provider)) {
+               clk_disable_unprepare(sata_phy->phyclk);
+               return PTR_ERR(phy_provider);
+       }
+
+       return 0;
+}
+
+static const struct of_device_id exynos_sata_phy_of_match[] = {
+       { .compatible = "samsung,exynos5250-sata-phy" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, exynos_sata_phy_of_match);
+
+static struct platform_driver exynos_sata_phy_driver = {
+       .probe  = exynos_sata_phy_probe,
+       .driver = {
+               .of_match_table = exynos_sata_phy_of_match,
+               .name  = "samsung,sata-phy",
+       }
+};
+module_platform_driver(exynos_sata_phy_driver);
+
+MODULE_DESCRIPTION("Samsung SerDes PHY driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>");
+MODULE_AUTHOR("Yuvaraj C D <yuvaraj.cd@samsung.com>");
diff --git a/drivers/phy/samsung/phy-exynos5250-usb2.c b/drivers/phy/samsung/phy-exynos5250-usb2.c
new file mode 100644 (file)
index 0000000..aad8062
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Kamil Debski <k.debski@samsung.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.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include "phy-samsung-usb2.h"
+
+/* Exynos USB PHY registers */
+#define EXYNOS_5250_REFCLKSEL_CRYSTAL  0x0
+#define EXYNOS_5250_REFCLKSEL_XO       0x1
+#define EXYNOS_5250_REFCLKSEL_CLKCORE  0x2
+
+#define EXYNOS_5250_FSEL_9MHZ6         0x0
+#define EXYNOS_5250_FSEL_10MHZ         0x1
+#define EXYNOS_5250_FSEL_12MHZ         0x2
+#define EXYNOS_5250_FSEL_19MHZ2                0x3
+#define EXYNOS_5250_FSEL_20MHZ         0x4
+#define EXYNOS_5250_FSEL_24MHZ         0x5
+#define EXYNOS_5250_FSEL_50MHZ         0x7
+
+/* Normal host */
+#define EXYNOS_5250_HOSTPHYCTRL0                       0x0
+
+#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL           BIT(31)
+#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT       19
+#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_MASK        \
+               (0x3 << EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT)
+#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT            16
+#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK \
+               (0x7 << EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT)
+#define EXYNOS_5250_HOSTPHYCTRL0_TESTBURNIN            BIT(11)
+#define EXYNOS_5250_HOSTPHYCTRL0_RETENABLE             BIT(10)
+#define EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N           BIT(9)
+#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_MASK                (0x3 << 7)
+#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_DUAL                (0x0 << 7)
+#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ID0         (0x1 << 7)
+#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ANALOGTEST  (0x2 << 7)
+#define EXYNOS_5250_HOSTPHYCTRL0_SIDDQ                 BIT(6)
+#define EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP            BIT(5)
+#define EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND          BIT(4)
+#define EXYNOS_5250_HOSTPHYCTRL0_WORDINTERFACE         BIT(3)
+#define EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST             BIT(2)
+#define EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST             BIT(1)
+#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST              BIT(0)
+
+/* HSIC0 & HSIC1 */
+#define EXYNOS_5250_HSICPHYCTRL1                       0x10
+#define EXYNOS_5250_HSICPHYCTRL2                       0x20
+
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_MASK                (0x3 << 23)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT     (0x2 << 23)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_MASK                (0x7f << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12          (0x24 << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_15          (0x1c << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_16          (0x1a << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_19_2                (0x15 << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_20          (0x14 << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_SIDDQ                 BIT(6)
+#define EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP            BIT(5)
+#define EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND          BIT(4)
+#define EXYNOS_5250_HSICPHYCTRLX_WORDINTERFACE         BIT(3)
+#define EXYNOS_5250_HSICPHYCTRLX_UTMISWRST             BIT(2)
+#define EXYNOS_5250_HSICPHYCTRLX_PHYSWRST              BIT(0)
+
+/* EHCI control */
+#define EXYNOS_5250_HOSTEHCICTRL                       0x30
+#define EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN         BIT(29)
+#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR4              BIT(28)
+#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR8              BIT(27)
+#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR16             BIT(26)
+#define EXYNOS_5250_HOSTEHCICTRL_AUTOPPDONOVRCUREN     BIT(25)
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT       19
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK        \
+               (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT       13
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_MASK        \
+               (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT)
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL2_SHIFT       7
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK        \
+               (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT    1
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_MASK \
+               (0x1 << EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT)
+#define EXYNOS_5250_HOSTEHCICTRL_SIMULATIONMODE                BIT(0)
+
+/* OHCI control */
+#define EXYNOS_5250_HOSTOHCICTRL                        0x34
+#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT     1
+#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_MASK \
+               (0x3ff << EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT)
+#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVALEN         BIT(0)
+
+/* USBOTG */
+#define EXYNOS_5250_USBOTGSYS                          0x38
+#define EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET         BIT(14)
+#define EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG         BIT(13)
+#define EXYNOS_5250_USBOTGSYS_PHY_SW_RST               BIT(12)
+#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT          9
+#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK \
+               (0x3 << EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT)
+#define EXYNOS_5250_USBOTGSYS_ID_PULLUP                        BIT(8)
+#define EXYNOS_5250_USBOTGSYS_COMMON_ON                        BIT(7)
+#define EXYNOS_5250_USBOTGSYS_FSEL_SHIFT               4
+#define EXYNOS_5250_USBOTGSYS_FSEL_MASK \
+               (0x3 << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT)
+#define EXYNOS_5250_USBOTGSYS_FORCE_SLEEP              BIT(3)
+#define EXYNOS_5250_USBOTGSYS_OTGDISABLE               BIT(2)
+#define EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG               BIT(1)
+#define EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND            BIT(0)
+
+/* Isolation, configured in the power management unit */
+#define EXYNOS_5250_USB_ISOL_OTG_OFFSET                0x704
+#define EXYNOS_5250_USB_ISOL_OTG               BIT(0)
+#define EXYNOS_5250_USB_ISOL_HOST_OFFSET       0x708
+#define EXYNOS_5250_USB_ISOL_HOST              BIT(0)
+
+/* Mode swtich register */
+#define EXYNOS_5250_MODE_SWITCH_OFFSET         0x230
+#define EXYNOS_5250_MODE_SWITCH_MASK           1
+#define EXYNOS_5250_MODE_SWITCH_DEVICE         0
+#define EXYNOS_5250_MODE_SWITCH_HOST           1
+
+enum exynos4x12_phy_id {
+       EXYNOS5250_DEVICE,
+       EXYNOS5250_HOST,
+       EXYNOS5250_HSIC0,
+       EXYNOS5250_HSIC1,
+       EXYNOS5250_NUM_PHYS,
+};
+
+/*
+ * exynos5250_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static int exynos5250_rate_to_clk(unsigned long rate, u32 *reg)
+{
+       /* EXYNOS_5250_FSEL_MASK */
+
+       switch (rate) {
+       case 9600 * KHZ:
+               *reg = EXYNOS_5250_FSEL_9MHZ6;
+               break;
+       case 10 * MHZ:
+               *reg = EXYNOS_5250_FSEL_10MHZ;
+               break;
+       case 12 * MHZ:
+               *reg = EXYNOS_5250_FSEL_12MHZ;
+               break;
+       case 19200 * KHZ:
+               *reg = EXYNOS_5250_FSEL_19MHZ2;
+               break;
+       case 20 * MHZ:
+               *reg = EXYNOS_5250_FSEL_20MHZ;
+               break;
+       case 24 * MHZ:
+               *reg = EXYNOS_5250_FSEL_24MHZ;
+               break;
+       case 50 * MHZ:
+               *reg = EXYNOS_5250_FSEL_50MHZ;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       u32 offset;
+       u32 mask;
+
+       switch (inst->cfg->id) {
+       case EXYNOS5250_DEVICE:
+               offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET;
+               mask = EXYNOS_5250_USB_ISOL_OTG;
+               break;
+       case EXYNOS5250_HOST:
+               offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET;
+               mask = EXYNOS_5250_USB_ISOL_HOST;
+               break;
+       default:
+               return;
+       }
+
+       regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
+}
+
+static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       u32 ctrl0;
+       u32 otg;
+       u32 ehci;
+       u32 ohci;
+       u32 hsic;
+
+       switch (inst->cfg->id) {
+       case EXYNOS5250_DEVICE:
+               regmap_update_bits(drv->reg_sys,
+                                  EXYNOS_5250_MODE_SWITCH_OFFSET,
+                                  EXYNOS_5250_MODE_SWITCH_MASK,
+                                  EXYNOS_5250_MODE_SWITCH_DEVICE);
+
+               /* OTG configuration */
+               otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+               /* The clock */
+               otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
+               otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
+               /* Reset */
+               otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
+                       EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
+                       EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
+               otg |=  EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
+                       EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
+                       EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
+                       EXYNOS_5250_USBOTGSYS_OTGDISABLE;
+               /* Ref clock */
+               otg &=  ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
+               otg |=  EXYNOS_5250_REFCLKSEL_CLKCORE <<
+                                       EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
+               writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+               udelay(100);
+               otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
+                       EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
+                       EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
+                       EXYNOS_5250_USBOTGSYS_OTGDISABLE);
+               writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+
+
+               break;
+       case EXYNOS5250_HOST:
+       case EXYNOS5250_HSIC0:
+       case EXYNOS5250_HSIC1:
+               /* Host registers configuration */
+               ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
+               /* The clock */
+               ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK;
+               ctrl0 |= drv->ref_reg_val <<
+                                       EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT;
+
+               /* Reset */
+               ctrl0 &=        ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
+                               EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL |
+                               EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
+                               EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
+                               EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP);
+               ctrl0 |=        EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
+                               EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST |
+                               EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N;
+               writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
+               udelay(10);
+               ctrl0 &=        ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
+                               EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST);
+               writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
+
+               /* OTG configuration */
+               otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+               /* The clock */
+               otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
+               otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
+               /* Reset */
+               otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
+                       EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
+                       EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
+               otg |=  EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
+                       EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
+                       EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
+                       EXYNOS_5250_USBOTGSYS_OTGDISABLE;
+               /* Ref clock */
+               otg &=  ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
+               otg |=  EXYNOS_5250_REFCLKSEL_CLKCORE <<
+                                       EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
+               writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+               udelay(10);
+               otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
+                       EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
+                       EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET);
+
+               /* HSIC phy configuration */
+               hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
+                               EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
+                               EXYNOS_5250_HSICPHYCTRLX_PHYSWRST);
+               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
+               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
+               udelay(10);
+               hsic &= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST;
+               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
+               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
+               /* The following delay is necessary for the reset sequence to be
+                * completed */
+               udelay(80);
+
+               /* Enable EHCI DMA burst */
+               ehci = readl(drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
+               ehci |= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN |
+                       EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 |
+                       EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 |
+                       EXYNOS_5250_HOSTEHCICTRL_ENAINCR16;
+               writel(ehci, drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
+
+               /* OHCI settings */
+               ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
+               /* Following code is based on the old driver */
+               ohci |= 0x1 << 3;
+               writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
+
+               break;
+       }
+       exynos5250_isol(inst, 0);
+
+       return 0;
+}
+
+static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       u32 ctrl0;
+       u32 otg;
+       u32 hsic;
+
+       exynos5250_isol(inst, 1);
+
+       switch (inst->cfg->id) {
+       case EXYNOS5250_DEVICE:
+               otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+               otg |= (EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
+                       EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG |
+                       EXYNOS_5250_USBOTGSYS_FORCE_SLEEP);
+               writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+               break;
+       case EXYNOS5250_HOST:
+               ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
+               ctrl0 |= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
+                               EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
+                               EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP |
+                               EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
+                               EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL);
+               writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
+               break;
+       case EXYNOS5250_HSIC0:
+       case EXYNOS5250_HSIC1:
+               hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
+                               EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
+                               EXYNOS_5250_HSICPHYCTRLX_SIDDQ |
+                               EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP |
+                               EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND
+                               );
+               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
+               writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
+               break;
+       }
+
+       return 0;
+}
+
+
+static const struct samsung_usb2_common_phy exynos5250_phys[] = {
+       {
+               .label          = "device",
+               .id             = EXYNOS5250_DEVICE,
+               .power_on       = exynos5250_power_on,
+               .power_off      = exynos5250_power_off,
+       },
+       {
+               .label          = "host",
+               .id             = EXYNOS5250_HOST,
+               .power_on       = exynos5250_power_on,
+               .power_off      = exynos5250_power_off,
+       },
+       {
+               .label          = "hsic0",
+               .id             = EXYNOS5250_HSIC0,
+               .power_on       = exynos5250_power_on,
+               .power_off      = exynos5250_power_off,
+       },
+       {
+               .label          = "hsic1",
+               .id             = EXYNOS5250_HSIC1,
+               .power_on       = exynos5250_power_on,
+               .power_off      = exynos5250_power_off,
+       },
+};
+
+const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = {
+       .has_mode_switch        = 1,
+       .num_phys               = EXYNOS5250_NUM_PHYS,
+       .phys                   = exynos5250_phys,
+       .rate_to_clk            = exynos5250_rate_to_clk,
+};
diff --git a/drivers/phy/samsung/phy-s5pv210-usb2.c b/drivers/phy/samsung/phy-s5pv210-usb2.c
new file mode 100644 (file)
index 0000000..f6f7233
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver - S5PV210 support
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Authors: Kamil Debski <k.debski@samsung.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.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/phy/phy.h>
+#include "phy-samsung-usb2.h"
+
+/* Exynos USB PHY registers */
+
+/* PHY power control */
+#define S5PV210_UPHYPWR                        0x0
+
+#define S5PV210_UPHYPWR_PHY0_SUSPEND   BIT(0)
+#define S5PV210_UPHYPWR_PHY0_PWR       BIT(3)
+#define S5PV210_UPHYPWR_PHY0_OTG_PWR   BIT(4)
+#define S5PV210_UPHYPWR_PHY0   ( \
+       S5PV210_UPHYPWR_PHY0_SUSPEND | \
+       S5PV210_UPHYPWR_PHY0_PWR | \
+       S5PV210_UPHYPWR_PHY0_OTG_PWR)
+
+#define S5PV210_UPHYPWR_PHY1_SUSPEND   BIT(6)
+#define S5PV210_UPHYPWR_PHY1_PWR       BIT(7)
+#define S5PV210_UPHYPWR_PHY1 ( \
+       S5PV210_UPHYPWR_PHY1_SUSPEND | \
+       S5PV210_UPHYPWR_PHY1_PWR)
+
+/* PHY clock control */
+#define S5PV210_UPHYCLK                        0x4
+
+#define S5PV210_UPHYCLK_PHYFSEL_MASK   (0x3 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_48MHZ  (0x0 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_24MHZ  (0x3 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_12MHZ  (0x2 << 0)
+
+#define S5PV210_UPHYCLK_PHY0_ID_PULLUP BIT(2)
+#define S5PV210_UPHYCLK_PHY0_COMMON_ON BIT(4)
+#define S5PV210_UPHYCLK_PHY1_COMMON_ON BIT(7)
+
+/* PHY reset control */
+#define S5PV210_UPHYRST                        0x8
+
+#define S5PV210_URSTCON_PHY0           BIT(0)
+#define S5PV210_URSTCON_OTG_HLINK      BIT(1)
+#define S5PV210_URSTCON_OTG_PHYLINK    BIT(2)
+#define S5PV210_URSTCON_PHY1_ALL       BIT(3)
+#define S5PV210_URSTCON_HOST_LINK_ALL  BIT(4)
+
+/* Isolation, configured in the power management unit */
+#define S5PV210_USB_ISOL_OFFSET                0x680c
+#define S5PV210_USB_ISOL_DEVICE                BIT(0)
+#define S5PV210_USB_ISOL_HOST          BIT(1)
+
+
+enum s5pv210_phy_id {
+       S5PV210_DEVICE,
+       S5PV210_HOST,
+       S5PV210_NUM_PHYS,
+};
+
+/*
+ * s5pv210_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static int s5pv210_rate_to_clk(unsigned long rate, u32 *reg)
+{
+       switch (rate) {
+       case 12 * MHZ:
+               *reg = S5PV210_UPHYCLK_PHYFSEL_12MHZ;
+               break;
+       case 24 * MHZ:
+               *reg = S5PV210_UPHYCLK_PHYFSEL_24MHZ;
+               break;
+       case 48 * MHZ:
+               *reg = S5PV210_UPHYCLK_PHYFSEL_48MHZ;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void s5pv210_isol(struct samsung_usb2_phy_instance *inst, bool on)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       u32 mask;
+
+       switch (inst->cfg->id) {
+       case S5PV210_DEVICE:
+               mask = S5PV210_USB_ISOL_DEVICE;
+               break;
+       case S5PV210_HOST:
+               mask = S5PV210_USB_ISOL_HOST;
+               break;
+       default:
+               return;
+       }
+
+       regmap_update_bits(drv->reg_pmu, S5PV210_USB_ISOL_OFFSET,
+                                                       mask, on ? 0 : mask);
+}
+
+static void s5pv210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
+{
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       u32 rstbits = 0;
+       u32 phypwr = 0;
+       u32 rst;
+       u32 pwr;
+
+       switch (inst->cfg->id) {
+       case S5PV210_DEVICE:
+               phypwr =        S5PV210_UPHYPWR_PHY0;
+               rstbits =       S5PV210_URSTCON_PHY0;
+               break;
+       case S5PV210_HOST:
+               phypwr =        S5PV210_UPHYPWR_PHY1;
+               rstbits =       S5PV210_URSTCON_PHY1_ALL |
+                               S5PV210_URSTCON_HOST_LINK_ALL;
+               break;
+       }
+
+       if (on) {
+               writel(drv->ref_reg_val, drv->reg_phy + S5PV210_UPHYCLK);
+
+               pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
+               pwr &= ~phypwr;
+               writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
+
+               rst = readl(drv->reg_phy + S5PV210_UPHYRST);
+               rst |= rstbits;
+               writel(rst, drv->reg_phy + S5PV210_UPHYRST);
+               udelay(10);
+               rst &= ~rstbits;
+               writel(rst, drv->reg_phy + S5PV210_UPHYRST);
+       } else {
+               pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
+               pwr |= phypwr;
+               writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
+       }
+}
+
+static int s5pv210_power_on(struct samsung_usb2_phy_instance *inst)
+{
+       s5pv210_isol(inst, 0);
+       s5pv210_phy_pwr(inst, 1);
+
+       return 0;
+}
+
+static int s5pv210_power_off(struct samsung_usb2_phy_instance *inst)
+{
+       s5pv210_phy_pwr(inst, 0);
+       s5pv210_isol(inst, 1);
+
+       return 0;
+}
+
+static const struct samsung_usb2_common_phy s5pv210_phys[S5PV210_NUM_PHYS] = {
+       [S5PV210_DEVICE] = {
+               .label          = "device",
+               .id             = S5PV210_DEVICE,
+               .power_on       = s5pv210_power_on,
+               .power_off      = s5pv210_power_off,
+       },
+       [S5PV210_HOST] = {
+               .label          = "host",
+               .id             = S5PV210_HOST,
+               .power_on       = s5pv210_power_on,
+               .power_off      = s5pv210_power_off,
+       },
+};
+
+const struct samsung_usb2_phy_config s5pv210_usb2_phy_config = {
+       .num_phys       = ARRAY_SIZE(s5pv210_phys),
+       .phys           = s5pv210_phys,
+       .rate_to_clk    = s5pv210_rate_to_clk,
+};
diff --git a/drivers/phy/samsung/phy-samsung-usb2.c b/drivers/phy/samsung/phy-samsung-usb2.c
new file mode 100644 (file)
index 0000000..1d22d93
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Kamil Debski <k.debski@samsung.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.
+ */
+
+#include <linux/clk.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/spinlock.h>
+#include "phy-samsung-usb2.h"
+
+static int samsung_usb2_phy_power_on(struct phy *phy)
+{
+       struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       int ret;
+
+       dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
+               inst->cfg->label);
+
+       if (drv->vbus) {
+               ret = regulator_enable(drv->vbus);
+               if (ret)
+                       goto err_regulator;
+       }
+
+       ret = clk_prepare_enable(drv->clk);
+       if (ret)
+               goto err_main_clk;
+       ret = clk_prepare_enable(drv->ref_clk);
+       if (ret)
+               goto err_instance_clk;
+       if (inst->cfg->power_on) {
+               spin_lock(&drv->lock);
+               ret = inst->cfg->power_on(inst);
+               spin_unlock(&drv->lock);
+               if (ret)
+                       goto err_power_on;
+       }
+
+       return 0;
+
+err_power_on:
+       clk_disable_unprepare(drv->ref_clk);
+err_instance_clk:
+       clk_disable_unprepare(drv->clk);
+err_main_clk:
+       if (drv->vbus)
+               regulator_disable(drv->vbus);
+err_regulator:
+       return ret;
+}
+
+static int samsung_usb2_phy_power_off(struct phy *phy)
+{
+       struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
+       struct samsung_usb2_phy_driver *drv = inst->drv;
+       int ret = 0;
+
+       dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n",
+               inst->cfg->label);
+       if (inst->cfg->power_off) {
+               spin_lock(&drv->lock);
+               ret = inst->cfg->power_off(inst);
+               spin_unlock(&drv->lock);
+               if (ret)
+                       return ret;
+       }
+       clk_disable_unprepare(drv->ref_clk);
+       clk_disable_unprepare(drv->clk);
+       if (drv->vbus)
+               ret = regulator_disable(drv->vbus);
+
+       return ret;
+}
+
+static const struct phy_ops samsung_usb2_phy_ops = {
+       .power_on       = samsung_usb2_phy_power_on,
+       .power_off      = samsung_usb2_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static struct phy *samsung_usb2_phy_xlate(struct device *dev,
+                                       struct of_phandle_args *args)
+{
+       struct samsung_usb2_phy_driver *drv;
+
+       drv = dev_get_drvdata(dev);
+       if (!drv)
+               return ERR_PTR(-EINVAL);
+
+       if (WARN_ON(args->args[0] >= drv->cfg->num_phys))
+               return ERR_PTR(-ENODEV);
+
+       return drv->instances[args->args[0]].phy;
+}
+
+static const struct of_device_id samsung_usb2_phy_of_match[] = {
+#ifdef CONFIG_PHY_EXYNOS4X12_USB2
+       {
+               .compatible = "samsung,exynos3250-usb2-phy",
+               .data = &exynos3250_usb2_phy_config,
+       },
+#endif
+#ifdef CONFIG_PHY_EXYNOS4210_USB2
+       {
+               .compatible = "samsung,exynos4210-usb2-phy",
+               .data = &exynos4210_usb2_phy_config,
+       },
+#endif
+#ifdef CONFIG_PHY_EXYNOS4X12_USB2
+       {
+               .compatible = "samsung,exynos4x12-usb2-phy",
+               .data = &exynos4x12_usb2_phy_config,
+       },
+#endif
+#ifdef CONFIG_PHY_EXYNOS5250_USB2
+       {
+               .compatible = "samsung,exynos5250-usb2-phy",
+               .data = &exynos5250_usb2_phy_config,
+       },
+#endif
+#ifdef CONFIG_PHY_S5PV210_USB2
+       {
+               .compatible = "samsung,s5pv210-usb2-phy",
+               .data = &s5pv210_usb2_phy_config,
+       },
+#endif
+       { },
+};
+MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match);
+
+static int samsung_usb2_phy_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match;
+       const struct samsung_usb2_phy_config *cfg;
+       struct device *dev = &pdev->dev;
+       struct phy_provider *phy_provider;
+       struct resource *mem;
+       struct samsung_usb2_phy_driver *drv;
+       int i, ret;
+
+       if (!pdev->dev.of_node) {
+               dev_err(dev, "This driver is required to be instantiated from device tree\n");
+               return -EINVAL;
+       }
+
+       match = of_match_node(samsung_usb2_phy_of_match, pdev->dev.of_node);
+       if (!match) {
+               dev_err(dev, "of_match_node() failed\n");
+               return -EINVAL;
+       }
+       cfg = match->data;
+
+       drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) +
+               cfg->num_phys * sizeof(struct samsung_usb2_phy_instance),
+                                                               GFP_KERNEL);
+       if (!drv)
+               return -ENOMEM;
+
+       dev_set_drvdata(dev, drv);
+       spin_lock_init(&drv->lock);
+
+       drv->cfg = cfg;
+       drv->dev = dev;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       drv->reg_phy = devm_ioremap_resource(dev, mem);
+       if (IS_ERR(drv->reg_phy)) {
+               dev_err(dev, "Failed to map register memory (phy)\n");
+               return PTR_ERR(drv->reg_phy);
+       }
+
+       drv->reg_pmu = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+               "samsung,pmureg-phandle");
+       if (IS_ERR(drv->reg_pmu)) {
+               dev_err(dev, "Failed to map PMU registers (via syscon)\n");
+               return PTR_ERR(drv->reg_pmu);
+       }
+
+       if (drv->cfg->has_mode_switch) {
+               drv->reg_sys = syscon_regmap_lookup_by_phandle(
+                               pdev->dev.of_node, "samsung,sysreg-phandle");
+               if (IS_ERR(drv->reg_sys)) {
+                       dev_err(dev, "Failed to map system registers (via syscon)\n");
+                       return PTR_ERR(drv->reg_sys);
+               }
+       }
+
+       drv->clk = devm_clk_get(dev, "phy");
+       if (IS_ERR(drv->clk)) {
+               dev_err(dev, "Failed to get clock of phy controller\n");
+               return PTR_ERR(drv->clk);
+       }
+
+       drv->ref_clk = devm_clk_get(dev, "ref");
+       if (IS_ERR(drv->ref_clk)) {
+               dev_err(dev, "Failed to get reference clock for the phy controller\n");
+               return PTR_ERR(drv->ref_clk);
+       }
+
+       drv->ref_rate = clk_get_rate(drv->ref_clk);
+       if (drv->cfg->rate_to_clk) {
+               ret = drv->cfg->rate_to_clk(drv->ref_rate, &drv->ref_reg_val);
+               if (ret)
+                       return ret;
+       }
+
+       drv->vbus = devm_regulator_get(dev, "vbus");
+       if (IS_ERR(drv->vbus)) {
+               ret = PTR_ERR(drv->vbus);
+               if (ret == -EPROBE_DEFER)
+                       return ret;
+               drv->vbus = NULL;
+       }
+
+       for (i = 0; i < drv->cfg->num_phys; i++) {
+               char *label = drv->cfg->phys[i].label;
+               struct samsung_usb2_phy_instance *p = &drv->instances[i];
+
+               dev_dbg(dev, "Creating phy \"%s\"\n", label);
+               p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops);
+               if (IS_ERR(p->phy)) {
+                       dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n",
+                               label);
+                       return PTR_ERR(p->phy);
+               }
+
+               p->cfg = &drv->cfg->phys[i];
+               p->drv = drv;
+               phy_set_bus_width(p->phy, 8);
+               phy_set_drvdata(p->phy, p);
+       }
+
+       phy_provider = devm_of_phy_provider_register(dev,
+                                                       samsung_usb2_phy_xlate);
+       if (IS_ERR(phy_provider)) {
+               dev_err(drv->dev, "Failed to register phy provider\n");
+               return PTR_ERR(phy_provider);
+       }
+
+       return 0;
+}
+
+static struct platform_driver samsung_usb2_phy_driver = {
+       .probe  = samsung_usb2_phy_probe,
+       .driver = {
+               .of_match_table = samsung_usb2_phy_of_match,
+               .name           = "samsung-usb2-phy",
+       }
+};
+
+module_platform_driver(samsung_usb2_phy_driver);
+MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC USB PHY driver");
+MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:samsung-usb2-phy");
diff --git a/drivers/phy/samsung/phy-samsung-usb2.h b/drivers/phy/samsung/phy-samsung-usb2.h
new file mode 100644 (file)
index 0000000..6563e7c
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Kamil Debski <k.debski@samsung.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.
+ */
+
+#ifndef _PHY_EXYNOS_USB2_H
+#define _PHY_EXYNOS_USB2_H
+
+#include <linux/clk.h>
+#include <linux/phy/phy.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+#include <linux/regulator/consumer.h>
+
+#define KHZ 1000
+#define MHZ (KHZ * KHZ)
+
+struct samsung_usb2_phy_driver;
+struct samsung_usb2_phy_instance;
+struct samsung_usb2_phy_config;
+
+struct samsung_usb2_phy_instance {
+       const struct samsung_usb2_common_phy *cfg;
+       struct phy *phy;
+       struct samsung_usb2_phy_driver *drv;
+       int int_cnt;
+       int ext_cnt;
+};
+
+struct samsung_usb2_phy_driver {
+       const struct samsung_usb2_phy_config *cfg;
+       struct clk *clk;
+       struct clk *ref_clk;
+       struct regulator *vbus;
+       unsigned long ref_rate;
+       u32 ref_reg_val;
+       struct device *dev;
+       void __iomem *reg_phy;
+       struct regmap *reg_pmu;
+       struct regmap *reg_sys;
+       spinlock_t lock;
+       struct samsung_usb2_phy_instance instances[0];
+};
+
+struct samsung_usb2_common_phy {
+       int (*power_on)(struct samsung_usb2_phy_instance *);
+       int (*power_off)(struct samsung_usb2_phy_instance *);
+       unsigned int id;
+       char *label;
+};
+
+
+struct samsung_usb2_phy_config {
+       const struct samsung_usb2_common_phy *phys;
+       int (*rate_to_clk)(unsigned long, u32 *);
+       unsigned int num_phys;
+       bool has_mode_switch;
+       bool has_refclk_sel;
+};
+
+extern const struct samsung_usb2_phy_config exynos3250_usb2_phy_config;
+extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
+extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
+extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
+extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config;
+#endif
diff --git a/drivers/phy/st/Kconfig b/drivers/phy/st/Kconfig
new file mode 100644 (file)
index 0000000..0814d3f
--- /dev/null
@@ -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.
diff --git a/drivers/phy/st/Makefile b/drivers/phy/st/Makefile
new file mode 100644 (file)
index 0000000..e2adfe2
--- /dev/null
@@ -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
diff --git a/drivers/phy/st/phy-miphy28lp.c b/drivers/phy/st/phy-miphy28lp.c
new file mode 100644 (file)
index 0000000..213e2e1
--- /dev/null
@@ -0,0 +1,1286 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics
+ *
+ * STMicroelectronics PHY driver MiPHY28lp (for SoC STiH407).
+ *
+ * Author: Alexandre Torgue <alexandre.torgue@st.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.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/clk.h>
+#include <linux/phy/phy.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <dt-bindings/phy/phy.h>
+
+/* MiPHY registers */
+#define MIPHY_CONF_RESET               0x00
+#define RST_APPLI_SW           BIT(0)
+#define RST_CONF_SW            BIT(1)
+#define RST_MACRO_SW           BIT(2)
+
+#define MIPHY_RESET                    0x01
+#define RST_PLL_SW             BIT(0)
+#define RST_COMP_SW            BIT(2)
+
+#define MIPHY_STATUS_1                 0x02
+#define PHY_RDY                        BIT(0)
+#define HFC_RDY                        BIT(1)
+#define HFC_PLL                        BIT(2)
+
+#define MIPHY_CONTROL                  0x04
+#define TERM_EN_SW             BIT(2)
+#define DIS_LINK_RST           BIT(3)
+#define AUTO_RST_RX            BIT(4)
+#define PX_RX_POL              BIT(5)
+
+#define MIPHY_BOUNDARY_SEL             0x0a
+#define TX_SEL                 BIT(6)
+#define SSC_SEL                        BIT(4)
+#define GENSEL_SEL             BIT(0)
+
+#define MIPHY_BOUNDARY_1               0x0b
+#define MIPHY_BOUNDARY_2               0x0c
+#define SSC_EN_SW              BIT(2)
+
+#define MIPHY_PLL_CLKREF_FREQ          0x0d
+#define MIPHY_SPEED                    0x0e
+#define TX_SPDSEL_80DEC                0
+#define TX_SPDSEL_40DEC                1
+#define TX_SPDSEL_20DEC                2
+#define RX_SPDSEL_80DEC                0
+#define RX_SPDSEL_40DEC                (1 << 2)
+#define RX_SPDSEL_20DEC                (2 << 2)
+
+#define MIPHY_CONF                     0x0f
+#define MIPHY_CTRL_TEST_SEL            0x20
+#define MIPHY_CTRL_TEST_1              0x21
+#define MIPHY_CTRL_TEST_2              0x22
+#define MIPHY_CTRL_TEST_3              0x23
+#define MIPHY_CTRL_TEST_4              0x24
+#define MIPHY_FEEDBACK_TEST            0x25
+#define MIPHY_DEBUG_BUS                        0x26
+#define MIPHY_DEBUG_STATUS_MSB         0x27
+#define MIPHY_DEBUG_STATUS_LSB         0x28
+#define MIPHY_PWR_RAIL_1               0x29
+#define MIPHY_PWR_RAIL_2               0x2a
+#define MIPHY_SYNCHAR_CONTROL          0x30
+
+#define MIPHY_COMP_FSM_1               0x3a
+#define COMP_START             BIT(6)
+
+#define MIPHY_COMP_FSM_6               0x3f
+#define COMP_DONE              BIT(7)
+
+#define MIPHY_COMP_POSTP               0x42
+#define MIPHY_TX_CTRL_1                        0x49
+#define TX_REG_STEP_0V         0
+#define TX_REG_STEP_P_25MV     1
+#define TX_REG_STEP_P_50MV     2
+#define TX_REG_STEP_N_25MV     7
+#define TX_REG_STEP_N_50MV     6
+#define TX_REG_STEP_N_75MV     5
+
+#define MIPHY_TX_CTRL_2                        0x4a
+#define TX_SLEW_SW_40_PS       0
+#define TX_SLEW_SW_80_PS       1
+#define TX_SLEW_SW_120_PS      2
+
+#define MIPHY_TX_CTRL_3                        0x4b
+#define MIPHY_TX_CAL_MAN               0x4e
+#define TX_SLEW_CAL_MAN_EN     BIT(0)
+
+#define MIPHY_TST_BIAS_BOOST_2         0x62
+#define MIPHY_BIAS_BOOST_1             0x63
+#define MIPHY_BIAS_BOOST_2             0x64
+#define MIPHY_RX_DESBUFF_FDB_2         0x67
+#define MIPHY_RX_DESBUFF_FDB_3         0x68
+#define MIPHY_SIGDET_COMPENS1          0x69
+#define MIPHY_SIGDET_COMPENS2          0x6a
+#define MIPHY_JITTER_PERIOD            0x6b
+#define MIPHY_JITTER_AMPLITUDE_1       0x6c
+#define MIPHY_JITTER_AMPLITUDE_2       0x6d
+#define MIPHY_JITTER_AMPLITUDE_3       0x6e
+#define MIPHY_RX_K_GAIN                        0x78
+#define MIPHY_RX_BUFFER_CTRL           0x7a
+#define VGA_GAIN               BIT(0)
+#define EQ_DC_GAIN             BIT(2)
+#define EQ_BOOST_GAIN          BIT(3)
+
+#define MIPHY_RX_VGA_GAIN              0x7b
+#define MIPHY_RX_EQU_GAIN_1            0x7f
+#define MIPHY_RX_EQU_GAIN_2            0x80
+#define MIPHY_RX_EQU_GAIN_3            0x81
+#define MIPHY_RX_CAL_CTRL_1            0x97
+#define MIPHY_RX_CAL_CTRL_2            0x98
+
+#define MIPHY_RX_CAL_OFFSET_CTRL       0x99
+#define CAL_OFFSET_VGA_64      (0x03 << 0)
+#define CAL_OFFSET_THRESHOLD_64        (0x03 << 2)
+#define VGA_OFFSET_POLARITY    BIT(4)
+#define OFFSET_COMPENSATION_EN BIT(6)
+
+#define MIPHY_RX_CAL_VGA_STEP          0x9a
+#define MIPHY_RX_CAL_EYE_MIN           0x9d
+#define MIPHY_RX_CAL_OPT_LENGTH                0x9f
+#define MIPHY_RX_LOCK_CTRL_1           0xc1
+#define MIPHY_RX_LOCK_SETTINGS_OPT     0xc2
+#define MIPHY_RX_LOCK_STEP             0xc4
+
+#define MIPHY_RX_SIGDET_SLEEP_OA       0xc9
+#define MIPHY_RX_SIGDET_SLEEP_SEL      0xca
+#define MIPHY_RX_SIGDET_WAIT_SEL       0xcb
+#define MIPHY_RX_SIGDET_DATA_SEL       0xcc
+#define EN_ULTRA_LOW_POWER     BIT(0)
+#define EN_FIRST_HALF          BIT(1)
+#define EN_SECOND_HALF         BIT(2)
+#define EN_DIGIT_SIGNAL_CHECK  BIT(3)
+
+#define MIPHY_RX_POWER_CTRL_1          0xcd
+#define MIPHY_RX_POWER_CTRL_2          0xce
+#define MIPHY_PLL_CALSET_CTRL          0xd3
+#define MIPHY_PLL_CALSET_1             0xd4
+#define MIPHY_PLL_CALSET_2             0xd5
+#define MIPHY_PLL_CALSET_3             0xd6
+#define MIPHY_PLL_CALSET_4             0xd7
+#define MIPHY_PLL_SBR_1                        0xe3
+#define SET_NEW_CHANGE         BIT(1)
+
+#define MIPHY_PLL_SBR_2                        0xe4
+#define MIPHY_PLL_SBR_3                        0xe5
+#define MIPHY_PLL_SBR_4                        0xe6
+#define MIPHY_PLL_COMMON_MISC_2                0xe9
+#define START_ACT_FILT         BIT(6)
+
+#define MIPHY_PLL_SPAREIN              0xeb
+
+/*
+ * On STiH407 the glue logic can be different among MiPHY devices; for example:
+ * MiPHY0: OSC_FORCE_EXT means:
+ *  0: 30MHz crystal clk - 1: 100MHz ext clk routed through MiPHY1
+ * MiPHY1: OSC_FORCE_EXT means:
+ *  1: 30MHz crystal clk - 0: 100MHz ext clk routed through MiPHY1
+ * Some devices have not the possibility to check if the osc is ready.
+ */
+#define MIPHY_OSC_FORCE_EXT    BIT(3)
+#define MIPHY_OSC_RDY          BIT(5)
+
+#define MIPHY_CTRL_MASK                0x0f
+#define MIPHY_CTRL_DEFAULT     0
+#define MIPHY_CTRL_SYNC_D_EN   BIT(2)
+
+/* SATA / PCIe defines */
+#define SATA_CTRL_MASK         0x07
+#define PCIE_CTRL_MASK         0xff
+#define SATA_CTRL_SELECT_SATA  1
+#define SATA_CTRL_SELECT_PCIE  0
+#define SYSCFG_PCIE_PCIE_VAL   0x80
+#define SATA_SPDMODE           1
+
+#define MIPHY_SATA_BANK_NB     3
+#define MIPHY_PCIE_BANK_NB     2
+
+enum {
+       SYSCFG_CTRL,
+       SYSCFG_STATUS,
+       SYSCFG_PCI,
+       SYSCFG_SATA,
+       SYSCFG_REG_MAX,
+};
+
+struct miphy28lp_phy {
+       struct phy *phy;
+       struct miphy28lp_dev *phydev;
+       void __iomem *base;
+       void __iomem *pipebase;
+
+       bool osc_force_ext;
+       bool osc_rdy;
+       bool px_rx_pol_inv;
+       bool ssc;
+       bool tx_impedance;
+
+       struct reset_control *miphy_rst;
+
+       u32 sata_gen;
+
+       /* Sysconfig registers offsets needed to configure the device */
+       u32 syscfg_reg[SYSCFG_REG_MAX];
+       u8 type;
+};
+
+struct miphy28lp_dev {
+       struct device *dev;
+       struct regmap *regmap;
+       struct mutex miphy_mutex;
+       struct miphy28lp_phy **phys;
+       int nphys;
+};
+
+struct miphy_initval {
+       u16 reg;
+       u16 val;
+};
+
+enum miphy_sata_gen { SATA_GEN1, SATA_GEN2, SATA_GEN3 };
+
+static char *PHY_TYPE_name[] = { "sata-up", "pcie-up", "", "usb3-up" };
+
+struct pll_ratio {
+       int clk_ref;
+       int calset_1;
+       int calset_2;
+       int calset_3;
+       int calset_4;
+       int cal_ctrl;
+};
+
+static struct pll_ratio sata_pll_ratio = {
+       .clk_ref = 0x1e,
+       .calset_1 = 0xc8,
+       .calset_2 = 0x00,
+       .calset_3 = 0x00,
+       .calset_4 = 0x00,
+       .cal_ctrl = 0x00,
+};
+
+static struct pll_ratio pcie_pll_ratio = {
+       .clk_ref = 0x1e,
+       .calset_1 = 0xa6,
+       .calset_2 = 0xaa,
+       .calset_3 = 0xaa,
+       .calset_4 = 0x00,
+       .cal_ctrl = 0x00,
+};
+
+static struct pll_ratio usb3_pll_ratio = {
+       .clk_ref = 0x1e,
+       .calset_1 = 0xa6,
+       .calset_2 = 0xaa,
+       .calset_3 = 0xaa,
+       .calset_4 = 0x04,
+       .cal_ctrl = 0x00,
+};
+
+struct miphy28lp_pll_gen {
+       int bank;
+       int speed;
+       int bias_boost_1;
+       int bias_boost_2;
+       int tx_ctrl_1;
+       int tx_ctrl_2;
+       int tx_ctrl_3;
+       int rx_k_gain;
+       int rx_vga_gain;
+       int rx_equ_gain_1;
+       int rx_equ_gain_2;
+       int rx_equ_gain_3;
+       int rx_buff_ctrl;
+};
+
+static struct miphy28lp_pll_gen sata_pll_gen[] = {
+       {
+               .bank           = 0x00,
+               .speed          = TX_SPDSEL_80DEC | RX_SPDSEL_80DEC,
+               .bias_boost_1   = 0x00,
+               .bias_boost_2   = 0xae,
+               .tx_ctrl_2      = 0x53,
+               .tx_ctrl_3      = 0x00,
+               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
+               .rx_vga_gain    = 0x00,
+               .rx_equ_gain_1  = 0x7d,
+               .rx_equ_gain_2  = 0x56,
+               .rx_equ_gain_3  = 0x00,
+       },
+       {
+               .bank           = 0x01,
+               .speed          = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,
+               .bias_boost_1   = 0x00,
+               .bias_boost_2   = 0xae,
+               .tx_ctrl_2      = 0x72,
+               .tx_ctrl_3      = 0x20,
+               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
+               .rx_vga_gain    = 0x00,
+               .rx_equ_gain_1  = 0x7d,
+               .rx_equ_gain_2  = 0x56,
+               .rx_equ_gain_3  = 0x00,
+       },
+       {
+               .bank           = 0x02,
+               .speed          = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,
+               .bias_boost_1   = 0x00,
+               .bias_boost_2   = 0xae,
+               .tx_ctrl_2      = 0xc0,
+               .tx_ctrl_3      = 0x20,
+               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
+               .rx_vga_gain    = 0x00,
+               .rx_equ_gain_1  = 0x7d,
+               .rx_equ_gain_2  = 0x56,
+               .rx_equ_gain_3  = 0x00,
+       },
+};
+
+static struct miphy28lp_pll_gen pcie_pll_gen[] = {
+       {
+               .bank           = 0x00,
+               .speed          = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,
+               .bias_boost_1   = 0x00,
+               .bias_boost_2   = 0xa5,
+               .tx_ctrl_1      = TX_REG_STEP_N_25MV,
+               .tx_ctrl_2      = 0x71,
+               .tx_ctrl_3      = 0x60,
+               .rx_k_gain      = 0x98,
+               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
+               .rx_vga_gain    = 0x00,
+               .rx_equ_gain_1  = 0x79,
+               .rx_equ_gain_2  = 0x56,
+       },
+       {
+               .bank           = 0x01,
+               .speed          = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,
+               .bias_boost_1   = 0x00,
+               .bias_boost_2   = 0xa5,
+               .tx_ctrl_1      = TX_REG_STEP_N_25MV,
+               .tx_ctrl_2      = 0x70,
+               .tx_ctrl_3      = 0x60,
+               .rx_k_gain      = 0xcc,
+               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
+               .rx_vga_gain    = 0x00,
+               .rx_equ_gain_1  = 0x78,
+               .rx_equ_gain_2  = 0x07,
+       },
+};
+
+static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy)
+{
+       void __iomem *base = miphy_phy->base;
+       u8 val;
+
+       /* Putting Macro in reset */
+       writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
+
+       val = RST_APPLI_SW | RST_CONF_SW;
+       writeb_relaxed(val, base + MIPHY_CONF_RESET);
+
+       writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
+
+       /* Bringing the MIPHY-CPU registers out of reset */
+       if (miphy_phy->type == PHY_TYPE_PCIE) {
+               val = AUTO_RST_RX | TERM_EN_SW;
+               writeb_relaxed(val, base + MIPHY_CONTROL);
+       } else {
+               val = AUTO_RST_RX | TERM_EN_SW | DIS_LINK_RST;
+               writeb_relaxed(val, base + MIPHY_CONTROL);
+       }
+}
+
+static inline void miphy28lp_pll_calibration(struct miphy28lp_phy *miphy_phy,
+               struct pll_ratio *pll_ratio)
+{
+       void __iomem *base = miphy_phy->base;
+       u8 val;
+
+       /* Applying PLL Settings */
+       writeb_relaxed(0x1d, base + MIPHY_PLL_SPAREIN);
+       writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);
+
+       /* PLL Ratio */
+       writeb_relaxed(pll_ratio->calset_1, base + MIPHY_PLL_CALSET_1);
+       writeb_relaxed(pll_ratio->calset_2, base + MIPHY_PLL_CALSET_2);
+       writeb_relaxed(pll_ratio->calset_3, base + MIPHY_PLL_CALSET_3);
+       writeb_relaxed(pll_ratio->calset_4, base + MIPHY_PLL_CALSET_4);
+       writeb_relaxed(pll_ratio->cal_ctrl, base + MIPHY_PLL_CALSET_CTRL);
+
+       writeb_relaxed(TX_SEL, base + MIPHY_BOUNDARY_SEL);
+
+       val = (0x68 << 1) | TX_SLEW_CAL_MAN_EN;
+       writeb_relaxed(val, base + MIPHY_TX_CAL_MAN);
+
+       val = VGA_OFFSET_POLARITY | CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;
+
+       if (miphy_phy->type != PHY_TYPE_SATA)
+               val |= OFFSET_COMPENSATION_EN;
+
+       writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);
+
+       if (miphy_phy->type == PHY_TYPE_USB3) {
+               writeb_relaxed(0x00, base + MIPHY_CONF);
+               writeb_relaxed(0x70, base + MIPHY_RX_LOCK_STEP);
+               writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_OA);
+               writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_SEL);
+               writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_WAIT_SEL);
+
+               val = EN_DIGIT_SIGNAL_CHECK | EN_FIRST_HALF;
+               writeb_relaxed(val, base + MIPHY_RX_SIGDET_DATA_SEL);
+       }
+
+}
+
+static inline void miphy28lp_sata_config_gen(struct miphy28lp_phy *miphy_phy)
+{
+       void __iomem *base = miphy_phy->base;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(sata_pll_gen); i++) {
+               struct miphy28lp_pll_gen *gen = &sata_pll_gen[i];
+
+               /* Banked settings */
+               writeb_relaxed(gen->bank, base + MIPHY_CONF);
+               writeb_relaxed(gen->speed, base + MIPHY_SPEED);
+               writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);
+               writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);
+
+               /* TX buffer Settings */
+               writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);
+               writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);
+
+               /* RX Buffer Settings */
+               writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);
+               writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);
+               writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);
+               writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);
+               writeb_relaxed(gen->rx_equ_gain_3, base + MIPHY_RX_EQU_GAIN_3);
+       }
+}
+
+static inline void miphy28lp_pcie_config_gen(struct miphy28lp_phy *miphy_phy)
+{
+       void __iomem *base = miphy_phy->base;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(pcie_pll_gen); i++) {
+               struct miphy28lp_pll_gen *gen = &pcie_pll_gen[i];
+
+               /* Banked settings */
+               writeb_relaxed(gen->bank, base + MIPHY_CONF);
+               writeb_relaxed(gen->speed, base + MIPHY_SPEED);
+               writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);
+               writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);
+
+               /* TX buffer Settings */
+               writeb_relaxed(gen->tx_ctrl_1, base + MIPHY_TX_CTRL_1);
+               writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);
+               writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);
+
+               writeb_relaxed(gen->rx_k_gain, base + MIPHY_RX_K_GAIN);
+
+               /* RX Buffer Settings */
+               writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);
+               writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);
+               writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);
+               writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);
+       }
+}
+
+static inline int miphy28lp_wait_compensation(struct miphy28lp_phy *miphy_phy)
+{
+       unsigned long finish = jiffies + 5 * HZ;
+       u8 val;
+
+       /* Waiting for Compensation to complete */
+       do {
+               val = readb_relaxed(miphy_phy->base + MIPHY_COMP_FSM_6);
+
+               if (time_after_eq(jiffies, finish))
+                       return -EBUSY;
+               cpu_relax();
+       } while (!(val & COMP_DONE));
+
+       return 0;
+}
+
+
+static inline int miphy28lp_compensation(struct miphy28lp_phy *miphy_phy,
+               struct pll_ratio *pll_ratio)
+{
+       void __iomem *base = miphy_phy->base;
+
+       /* Poll for HFC ready after reset release */
+       /* Compensation measurement */
+       writeb_relaxed(RST_PLL_SW | RST_COMP_SW, base + MIPHY_RESET);
+
+       writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);
+       writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);
+       writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);
+
+       if (miphy_phy->type == PHY_TYPE_PCIE)
+               writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);
+
+       writeb_relaxed(0x00, base + MIPHY_RESET);
+       writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);
+       writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
+
+       /* TX compensation offset to re-center TX impedance */
+       writeb_relaxed(0x00, base + MIPHY_COMP_POSTP);
+
+       if (miphy_phy->type == PHY_TYPE_PCIE)
+               return miphy28lp_wait_compensation(miphy_phy);
+
+       return 0;
+}
+
+static inline void miphy28_usb3_miphy_reset(struct miphy28lp_phy *miphy_phy)
+{
+       void __iomem *base = miphy_phy->base;
+       u8 val;
+
+       /* MIPHY Reset */
+       writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
+       writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
+       writeb_relaxed(RST_COMP_SW, base + MIPHY_RESET);
+
+       val = RST_COMP_SW | RST_PLL_SW;
+       writeb_relaxed(val, base + MIPHY_RESET);
+
+       writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);
+       writeb_relaxed(0x1e, base + MIPHY_PLL_CLKREF_FREQ);
+       writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);
+       writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);
+       writeb_relaxed(0x00, base + MIPHY_RESET);
+       writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);
+       writeb_relaxed(0x00, base + MIPHY_CONF);
+       writeb_relaxed(0x00, base + MIPHY_BOUNDARY_1);
+       writeb_relaxed(0x00, base + MIPHY_TST_BIAS_BOOST_2);
+       writeb_relaxed(0x00, base + MIPHY_CONF);
+       writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
+       writeb_relaxed(0xa5, base + MIPHY_DEBUG_BUS);
+       writeb_relaxed(0x00, base + MIPHY_CONF);
+}
+
+static void miphy_sata_tune_ssc(struct miphy28lp_phy *miphy_phy)
+{
+       void __iomem *base = miphy_phy->base;
+       u8 val;
+
+       /* Compensate Tx impedance to avoid out of range values */
+       /*
+        * Enable the SSC on PLL for all banks
+        * SSC Modulation @ 31 KHz and 4000 ppm modulation amp
+        */
+       val = readb_relaxed(base + MIPHY_BOUNDARY_2);
+       val |= SSC_EN_SW;
+       writeb_relaxed(val, base + MIPHY_BOUNDARY_2);
+
+       val = readb_relaxed(base + MIPHY_BOUNDARY_SEL);
+       val |= SSC_SEL;
+       writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);
+
+       for (val = 0; val < MIPHY_SATA_BANK_NB; val++) {
+               writeb_relaxed(val, base + MIPHY_CONF);
+
+               /* Add value to each reference clock cycle  */
+               /* and define the period length of the SSC */
+               writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);
+               writeb_relaxed(0x6c, base + MIPHY_PLL_SBR_3);
+               writeb_relaxed(0x81, base + MIPHY_PLL_SBR_4);
+
+               /* Clear any previous request */
+               writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+
+               /* requests the PLL to take in account new parameters */
+               writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
+
+               /* To be sure there is no other pending requests */
+               writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+       }
+}
+
+static void miphy_pcie_tune_ssc(struct miphy28lp_phy *miphy_phy)
+{
+       void __iomem *base = miphy_phy->base;
+       u8 val;
+
+       /* Compensate Tx impedance to avoid out of range values */
+       /*
+        * Enable the SSC on PLL for all banks
+        * SSC Modulation @ 31 KHz and 4000 ppm modulation amp
+        */
+       val = readb_relaxed(base + MIPHY_BOUNDARY_2);
+       val |= SSC_EN_SW;
+       writeb_relaxed(val, base + MIPHY_BOUNDARY_2);
+
+       val = readb_relaxed(base + MIPHY_BOUNDARY_SEL);
+       val |= SSC_SEL;
+       writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);
+
+       for (val = 0; val < MIPHY_PCIE_BANK_NB; val++) {
+               writeb_relaxed(val, base + MIPHY_CONF);
+
+               /* Validate Step component */
+               writeb_relaxed(0x69, base + MIPHY_PLL_SBR_3);
+               writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4);
+
+               /* Validate Period component */
+               writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);
+               writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4);
+
+               /* Clear any previous request */
+               writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+
+               /* requests the PLL to take in account new parameters */
+               writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
+
+               /* To be sure there is no other pending requests */
+               writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+       }
+}
+
+static inline void miphy_tune_tx_impedance(struct miphy28lp_phy *miphy_phy)
+{
+       /* Compensate Tx impedance to avoid out of range values */
+       writeb_relaxed(0x02, miphy_phy->base + MIPHY_COMP_POSTP);
+}
+
+static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy)
+{
+       void __iomem *base = miphy_phy->base;
+       int err;
+       u8 val;
+
+       /* Putting Macro in reset */
+       miphy28lp_set_reset(miphy_phy);
+
+       /* PLL calibration */
+       miphy28lp_pll_calibration(miphy_phy, &sata_pll_ratio);
+
+       /* Banked settings Gen1/Gen2/Gen3 */
+       miphy28lp_sata_config_gen(miphy_phy);
+
+       /* Power control */
+       /* Input bridge enable, manual input bridge control */
+       writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
+
+       /* Macro out of reset */
+       writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
+
+       /* Poll for HFC ready after reset release */
+       /* Compensation measurement */
+       err = miphy28lp_compensation(miphy_phy, &sata_pll_ratio);
+       if (err)
+               return err;
+
+       if (miphy_phy->px_rx_pol_inv) {
+               /* Invert Rx polarity */
+               val = readb_relaxed(miphy_phy->base + MIPHY_CONTROL);
+               val |= PX_RX_POL;
+               writeb_relaxed(val, miphy_phy->base + MIPHY_CONTROL);
+       }
+
+       if (miphy_phy->ssc)
+               miphy_sata_tune_ssc(miphy_phy);
+
+       if (miphy_phy->tx_impedance)
+               miphy_tune_tx_impedance(miphy_phy);
+
+       return 0;
+}
+
+static inline int miphy28lp_configure_pcie(struct miphy28lp_phy *miphy_phy)
+{
+       void __iomem *base = miphy_phy->base;
+       int err;
+
+       /* Putting Macro in reset */
+       miphy28lp_set_reset(miphy_phy);
+
+       /* PLL calibration */
+       miphy28lp_pll_calibration(miphy_phy, &pcie_pll_ratio);
+
+       /* Banked settings Gen1/Gen2 */
+       miphy28lp_pcie_config_gen(miphy_phy);
+
+       /* Power control */
+       /* Input bridge enable, manual input bridge control */
+       writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
+
+       /* Macro out of reset */
+       writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
+
+       /* Poll for HFC ready after reset release */
+       /* Compensation measurement */
+       err = miphy28lp_compensation(miphy_phy, &pcie_pll_ratio);
+       if (err)
+               return err;
+
+       if (miphy_phy->ssc)
+               miphy_pcie_tune_ssc(miphy_phy);
+
+       if (miphy_phy->tx_impedance)
+               miphy_tune_tx_impedance(miphy_phy);
+
+       return 0;
+}
+
+
+static inline void miphy28lp_configure_usb3(struct miphy28lp_phy *miphy_phy)
+{
+       void __iomem *base = miphy_phy->base;
+       u8 val;
+
+       /* Putting Macro in reset */
+       miphy28lp_set_reset(miphy_phy);
+
+       /* PLL calibration */
+       miphy28lp_pll_calibration(miphy_phy, &usb3_pll_ratio);
+
+       /* Writing The Speed Rate */
+       writeb_relaxed(0x00, base + MIPHY_CONF);
+
+       val = RX_SPDSEL_20DEC | TX_SPDSEL_20DEC;
+       writeb_relaxed(val, base + MIPHY_SPEED);
+
+       /* RX Channel compensation and calibration */
+       writeb_relaxed(0x1c, base + MIPHY_RX_LOCK_SETTINGS_OPT);
+       writeb_relaxed(0x51, base + MIPHY_RX_CAL_CTRL_1);
+       writeb_relaxed(0x70, base + MIPHY_RX_CAL_CTRL_2);
+
+       val = OFFSET_COMPENSATION_EN | VGA_OFFSET_POLARITY |
+             CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;
+       writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);
+       writeb_relaxed(0x22, base + MIPHY_RX_CAL_VGA_STEP);
+       writeb_relaxed(0x0e, base + MIPHY_RX_CAL_OPT_LENGTH);
+
+       val = EQ_DC_GAIN | VGA_GAIN;
+       writeb_relaxed(val, base + MIPHY_RX_BUFFER_CTRL);
+       writeb_relaxed(0x78, base + MIPHY_RX_EQU_GAIN_1);
+       writeb_relaxed(0x1b, base + MIPHY_SYNCHAR_CONTROL);
+
+       /* TX compensation offset to re-center TX impedance */
+       writeb_relaxed(0x02, base + MIPHY_COMP_POSTP);
+
+       /* Enable GENSEL_SEL and SSC */
+       /* TX_SEL=0 swing preemp forced by pipe registres */
+       val = SSC_SEL | GENSEL_SEL;
+       writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);
+
+       /* MIPHY Bias boost */
+       writeb_relaxed(0x00, base + MIPHY_BIAS_BOOST_1);
+       writeb_relaxed(0xa7, base + MIPHY_BIAS_BOOST_2);
+
+       /* SSC modulation */
+       writeb_relaxed(SSC_EN_SW, base + MIPHY_BOUNDARY_2);
+
+       /* MIPHY TX control */
+       writeb_relaxed(0x00, base + MIPHY_CONF);
+
+       /* Validate Step component */
+       writeb_relaxed(0x5a, base + MIPHY_PLL_SBR_3);
+       writeb_relaxed(0xa0, base + MIPHY_PLL_SBR_4);
+
+       /* Validate Period component */
+       writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);
+       writeb_relaxed(0xa1, base + MIPHY_PLL_SBR_4);
+
+       /* Clear any previous request */
+       writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+
+       /* requests the PLL to take in account new parameters */
+       writeb_relaxed(0x02, base + MIPHY_PLL_SBR_1);
+
+       /* To be sure there is no other pending requests */
+       writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+
+       /* Rx PI controller settings */
+       writeb_relaxed(0xca, base + MIPHY_RX_K_GAIN);
+
+       /* MIPHY RX input bridge control */
+       /* INPUT_BRIDGE_EN_SW=1, manual input bridge control[0]=1 */
+       writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
+       writeb_relaxed(0x29, base + MIPHY_RX_POWER_CTRL_1);
+       writeb_relaxed(0x1a, base + MIPHY_RX_POWER_CTRL_2);
+
+       /* MIPHY Reset for usb3 */
+       miphy28_usb3_miphy_reset(miphy_phy);
+}
+
+static inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy)
+{
+       unsigned long finish = jiffies + 5 * HZ;
+       u8 mask = HFC_PLL | HFC_RDY;
+       u8 val;
+
+       /*
+        * For PCIe and USB3 check only that PLL and HFC are ready
+        * For SATA check also that phy is ready!
+        */
+       if (miphy_phy->type == PHY_TYPE_SATA)
+               mask |= PHY_RDY;
+
+       do {
+               val = readb_relaxed(miphy_phy->base + MIPHY_STATUS_1);
+               if ((val & mask) != mask)
+                       cpu_relax();
+               else
+                       return 0;
+       } while (!time_after_eq(jiffies, finish));
+
+       return -EBUSY;
+}
+
+static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)
+{
+       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+       unsigned long finish = jiffies + 5 * HZ;
+       u32 val;
+
+       if (!miphy_phy->osc_rdy)
+               return 0;
+
+       if (!miphy_phy->syscfg_reg[SYSCFG_STATUS])
+               return -EINVAL;
+
+       do {
+               regmap_read(miphy_dev->regmap,
+                               miphy_phy->syscfg_reg[SYSCFG_STATUS], &val);
+
+               if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY)
+                       cpu_relax();
+               else
+                       return 0;
+       } while (!time_after_eq(jiffies, finish));
+
+       return -EBUSY;
+}
+
+static int miphy28lp_get_resource_byname(struct device_node *child,
+                                         char *rname, struct resource *res)
+{
+       int index;
+
+       index = of_property_match_string(child, "reg-names", rname);
+       if (index < 0)
+               return -ENODEV;
+
+       return of_address_to_resource(child, index, res);
+}
+
+static int miphy28lp_get_one_addr(struct device *dev,
+                                 struct device_node *child, char *rname,
+                                 void __iomem **base)
+{
+       struct resource res;
+       int ret;
+
+       ret = miphy28lp_get_resource_byname(child, rname, &res);
+       if (!ret) {
+               *base = devm_ioremap(dev, res.start, resource_size(&res));
+               if (!*base) {
+                       dev_err(dev, "failed to ioremap %s address region\n"
+                                       , rname);
+                       return -ENOENT;
+               }
+       }
+
+       return 0;
+}
+
+/* MiPHY reset and sysconf setup */
+static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val)
+{
+       int err;
+       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+
+       if (!miphy_phy->syscfg_reg[SYSCFG_CTRL])
+               return -EINVAL;
+
+       err = reset_control_assert(miphy_phy->miphy_rst);
+       if (err) {
+               dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
+               return err;
+       }
+
+       if (miphy_phy->osc_force_ext)
+               miphy_val |= MIPHY_OSC_FORCE_EXT;
+
+       regmap_update_bits(miphy_dev->regmap,
+                          miphy_phy->syscfg_reg[SYSCFG_CTRL],
+                          MIPHY_CTRL_MASK, miphy_val);
+
+       err = reset_control_deassert(miphy_phy->miphy_rst);
+       if (err) {
+               dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
+               return err;
+       }
+
+       return miphy_osc_is_ready(miphy_phy);
+}
+
+static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy)
+{
+       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+       int err, sata_conf = SATA_CTRL_SELECT_SATA;
+
+       if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||
+                       (!miphy_phy->syscfg_reg[SYSCFG_PCI]) ||
+                       (!miphy_phy->base))
+               return -EINVAL;
+
+       dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base);
+
+       /* Configure the glue-logic */
+       sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE);
+
+       regmap_update_bits(miphy_dev->regmap,
+                          miphy_phy->syscfg_reg[SYSCFG_SATA],
+                          SATA_CTRL_MASK, sata_conf);
+
+       regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],
+                          PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
+
+       /* MiPHY path and clocking init */
+       err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);
+
+       if (err) {
+               dev_err(miphy_dev->dev, "SATA phy setup failed\n");
+               return err;
+       }
+
+       /* initialize miphy */
+       miphy28lp_configure_sata(miphy_phy);
+
+       return miphy_is_ready(miphy_phy);
+}
+
+static int miphy28lp_init_pcie(struct miphy28lp_phy *miphy_phy)
+{
+       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+       int err;
+
+       if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||
+                       (!miphy_phy->syscfg_reg[SYSCFG_PCI])
+               || (!miphy_phy->base) || (!miphy_phy->pipebase))
+               return -EINVAL;
+
+       dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base);
+
+       /* Configure the glue-logic */
+       regmap_update_bits(miphy_dev->regmap,
+                          miphy_phy->syscfg_reg[SYSCFG_SATA],
+                          SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
+
+       regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],
+                          PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL);
+
+       /* MiPHY path and clocking init */
+       err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);
+
+       if (err) {
+               dev_err(miphy_dev->dev, "PCIe phy setup failed\n");
+               return err;
+       }
+
+       /* initialize miphy */
+       err = miphy28lp_configure_pcie(miphy_phy);
+       if (err)
+               return err;
+
+       /* PIPE Wrapper Configuration */
+       writeb_relaxed(0x68, miphy_phy->pipebase + 0x104); /* Rise_0 */
+       writeb_relaxed(0x61, miphy_phy->pipebase + 0x105); /* Rise_1 */
+       writeb_relaxed(0x68, miphy_phy->pipebase + 0x108); /* Fall_0 */
+       writeb_relaxed(0x61, miphy_phy->pipebase + 0x109); /* Fall-1 */
+       writeb_relaxed(0x68, miphy_phy->pipebase + 0x10c); /* Threshold_0 */
+       writeb_relaxed(0x60, miphy_phy->pipebase + 0x10d); /* Threshold_1 */
+
+       /* Wait for phy_ready */
+       return miphy_is_ready(miphy_phy);
+}
+
+static int miphy28lp_init_usb3(struct miphy28lp_phy *miphy_phy)
+{
+       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+       int err;
+
+       if ((!miphy_phy->base) || (!miphy_phy->pipebase))
+               return -EINVAL;
+
+       dev_info(miphy_dev->dev, "usb3-up mode, addr 0x%p\n", miphy_phy->base);
+
+       /* MiPHY path and clocking init */
+       err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_SYNC_D_EN);
+       if (err) {
+               dev_err(miphy_dev->dev, "USB3 phy setup failed\n");
+               return err;
+       }
+
+       /* initialize miphy */
+       miphy28lp_configure_usb3(miphy_phy);
+
+       /* PIPE Wrapper Configuration */
+       writeb_relaxed(0x68, miphy_phy->pipebase + 0x23);
+       writeb_relaxed(0x61, miphy_phy->pipebase + 0x24);
+       writeb_relaxed(0x68, miphy_phy->pipebase + 0x26);
+       writeb_relaxed(0x61, miphy_phy->pipebase + 0x27);
+       writeb_relaxed(0x18, miphy_phy->pipebase + 0x29);
+       writeb_relaxed(0x61, miphy_phy->pipebase + 0x2a);
+
+       /* pipe Wrapper usb3 TX swing de-emph margin PREEMPH[7:4], SWING[3:0] */
+       writeb_relaxed(0X67, miphy_phy->pipebase + 0x68);
+       writeb_relaxed(0x0d, miphy_phy->pipebase + 0x69);
+       writeb_relaxed(0X67, miphy_phy->pipebase + 0x6a);
+       writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6b);
+       writeb_relaxed(0X67, miphy_phy->pipebase + 0x6c);
+       writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6d);
+       writeb_relaxed(0X67, miphy_phy->pipebase + 0x6e);
+       writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6f);
+
+       return miphy_is_ready(miphy_phy);
+}
+
+static int miphy28lp_init(struct phy *phy)
+{
+       struct miphy28lp_phy *miphy_phy = phy_get_drvdata(phy);
+       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+       int ret;
+
+       mutex_lock(&miphy_dev->miphy_mutex);
+
+       switch (miphy_phy->type) {
+
+       case PHY_TYPE_SATA:
+               ret = miphy28lp_init_sata(miphy_phy);
+               break;
+       case PHY_TYPE_PCIE:
+               ret = miphy28lp_init_pcie(miphy_phy);
+               break;
+       case PHY_TYPE_USB3:
+               ret = miphy28lp_init_usb3(miphy_phy);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       mutex_unlock(&miphy_dev->miphy_mutex);
+
+       return ret;
+}
+
+static int miphy28lp_get_addr(struct miphy28lp_phy *miphy_phy)
+{
+       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+       struct device_node *phynode = miphy_phy->phy->dev.of_node;
+       int err;
+
+       if ((miphy_phy->type != PHY_TYPE_SATA) &&
+           (miphy_phy->type != PHY_TYPE_PCIE) &&
+           (miphy_phy->type != PHY_TYPE_USB3)) {
+               return -EINVAL;
+       }
+
+       err = miphy28lp_get_one_addr(miphy_dev->dev, phynode,
+                       PHY_TYPE_name[miphy_phy->type - PHY_TYPE_SATA],
+                       &miphy_phy->base);
+       if (err)
+               return err;
+
+       if ((miphy_phy->type == PHY_TYPE_PCIE) ||
+           (miphy_phy->type == PHY_TYPE_USB3)) {
+               err = miphy28lp_get_one_addr(miphy_dev->dev, phynode, "pipew",
+                                            &miphy_phy->pipebase);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+static struct phy *miphy28lp_xlate(struct device *dev,
+                                  struct of_phandle_args *args)
+{
+       struct miphy28lp_dev *miphy_dev = dev_get_drvdata(dev);
+       struct miphy28lp_phy *miphy_phy = NULL;
+       struct device_node *phynode = args->np;
+       int ret, index = 0;
+
+       if (args->args_count != 1) {
+               dev_err(dev, "Invalid number of cells in 'phy' property\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       for (index = 0; index < miphy_dev->nphys; index++)
+               if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {
+                       miphy_phy = miphy_dev->phys[index];
+                       break;
+               }
+
+       if (!miphy_phy) {
+               dev_err(dev, "Failed to find appropriate phy\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       miphy_phy->type = args->args[0];
+
+       ret = miphy28lp_get_addr(miphy_phy);
+       if (ret < 0)
+               return ERR_PTR(ret);
+
+       return miphy_phy->phy;
+}
+
+static const struct phy_ops miphy28lp_ops = {
+       .init = miphy28lp_init,
+       .owner = THIS_MODULE,
+};
+
+static int miphy28lp_probe_resets(struct device_node *node,
+                                 struct miphy28lp_phy *miphy_phy)
+{
+       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+       int err;
+
+       miphy_phy->miphy_rst =
+               of_reset_control_get_shared(node, "miphy-sw-rst");
+
+       if (IS_ERR(miphy_phy->miphy_rst)) {
+               dev_err(miphy_dev->dev,
+                               "miphy soft reset control not defined\n");
+               return PTR_ERR(miphy_phy->miphy_rst);
+       }
+
+       err = reset_control_deassert(miphy_phy->miphy_rst);
+       if (err) {
+               dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static int miphy28lp_of_probe(struct device_node *np,
+                             struct miphy28lp_phy *miphy_phy)
+{
+       int i;
+       u32 ctrlreg;
+
+       miphy_phy->osc_force_ext =
+               of_property_read_bool(np, "st,osc-force-ext");
+
+       miphy_phy->osc_rdy = of_property_read_bool(np, "st,osc-rdy");
+
+       miphy_phy->px_rx_pol_inv =
+               of_property_read_bool(np, "st,px_rx_pol_inv");
+
+       miphy_phy->ssc = of_property_read_bool(np, "st,ssc-on");
+
+       miphy_phy->tx_impedance =
+               of_property_read_bool(np, "st,tx-impedance-comp");
+
+       of_property_read_u32(np, "st,sata-gen", &miphy_phy->sata_gen);
+       if (!miphy_phy->sata_gen)
+               miphy_phy->sata_gen = SATA_GEN1;
+
+       for (i = 0; i < SYSCFG_REG_MAX; i++) {
+               if (!of_property_read_u32_index(np, "st,syscfg", i, &ctrlreg))
+                       miphy_phy->syscfg_reg[i] = ctrlreg;
+       }
+
+       return 0;
+}
+
+static int miphy28lp_probe(struct platform_device *pdev)
+{
+       struct device_node *child, *np = pdev->dev.of_node;
+       struct miphy28lp_dev *miphy_dev;
+       struct phy_provider *provider;
+       struct phy *phy;
+       int ret, port = 0;
+
+       miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
+       if (!miphy_dev)
+               return -ENOMEM;
+
+       miphy_dev->nphys = of_get_child_count(np);
+       miphy_dev->phys = devm_kcalloc(&pdev->dev, miphy_dev->nphys,
+                                      sizeof(*miphy_dev->phys), GFP_KERNEL);
+       if (!miphy_dev->phys)
+               return -ENOMEM;
+
+       miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+       if (IS_ERR(miphy_dev->regmap)) {
+               dev_err(miphy_dev->dev, "No syscfg phandle specified\n");
+               return PTR_ERR(miphy_dev->regmap);
+       }
+
+       miphy_dev->dev = &pdev->dev;
+
+       dev_set_drvdata(&pdev->dev, miphy_dev);
+
+       mutex_init(&miphy_dev->miphy_mutex);
+
+       for_each_child_of_node(np, child) {
+               struct miphy28lp_phy *miphy_phy;
+
+               miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
+                                        GFP_KERNEL);
+               if (!miphy_phy) {
+                       ret = -ENOMEM;
+                       goto put_child;
+               }
+
+               miphy_dev->phys[port] = miphy_phy;
+
+               phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops);
+               if (IS_ERR(phy)) {
+                       dev_err(&pdev->dev, "failed to create PHY\n");
+                       ret = PTR_ERR(phy);
+                       goto put_child;
+               }
+
+               miphy_dev->phys[port]->phy = phy;
+               miphy_dev->phys[port]->phydev = miphy_dev;
+
+               ret = miphy28lp_of_probe(child, miphy_phy);
+               if (ret)
+                       goto put_child;
+
+               ret = miphy28lp_probe_resets(child, miphy_dev->phys[port]);
+               if (ret)
+                       goto put_child;
+
+               phy_set_drvdata(phy, miphy_dev->phys[port]);
+               port++;
+
+       }
+
+       provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate);
+       return PTR_ERR_OR_ZERO(provider);
+put_child:
+       of_node_put(child);
+       return ret;
+}
+
+static const struct of_device_id miphy28lp_of_match[] = {
+       {.compatible = "st,miphy28lp-phy", },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, miphy28lp_of_match);
+
+static struct platform_driver miphy28lp_driver = {
+       .probe = miphy28lp_probe,
+       .driver = {
+               .name = "miphy28lp-phy",
+               .of_match_table = miphy28lp_of_match,
+       }
+};
+
+module_platform_driver(miphy28lp_driver);
+
+MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics miphy28lp driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/st/phy-spear1310-miphy.c b/drivers/phy/st/phy-spear1310-miphy.c
new file mode 100644 (file)
index 0000000..ed67e98
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * ST SPEAr1310-miphy driver
+ *
+ * Copyright (C) 2014 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@gmail.com>
+ * Mohit Kumar <mohit.kumar.dhaka@gmail.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.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
+/* SPEAr1310 Registers */
+#define SPEAR1310_PCIE_SATA_CFG                        0x3A4
+       #define SPEAR1310_PCIE_SATA2_SEL_PCIE           (0 << 31)
+       #define SPEAR1310_PCIE_SATA1_SEL_PCIE           (0 << 30)
+       #define SPEAR1310_PCIE_SATA0_SEL_PCIE           (0 << 29)
+       #define SPEAR1310_PCIE_SATA2_SEL_SATA           BIT(31)
+       #define SPEAR1310_PCIE_SATA1_SEL_SATA           BIT(30)
+       #define SPEAR1310_PCIE_SATA0_SEL_SATA           BIT(29)
+       #define SPEAR1310_SATA2_CFG_TX_CLK_EN           BIT(27)
+       #define SPEAR1310_SATA2_CFG_RX_CLK_EN           BIT(26)
+       #define SPEAR1310_SATA2_CFG_POWERUP_RESET       BIT(25)
+       #define SPEAR1310_SATA2_CFG_PM_CLK_EN           BIT(24)
+       #define SPEAR1310_SATA1_CFG_TX_CLK_EN           BIT(23)
+       #define SPEAR1310_SATA1_CFG_RX_CLK_EN           BIT(22)
+       #define SPEAR1310_SATA1_CFG_POWERUP_RESET       BIT(21)
+       #define SPEAR1310_SATA1_CFG_PM_CLK_EN           BIT(20)
+       #define SPEAR1310_SATA0_CFG_TX_CLK_EN           BIT(19)
+       #define SPEAR1310_SATA0_CFG_RX_CLK_EN           BIT(18)
+       #define SPEAR1310_SATA0_CFG_POWERUP_RESET       BIT(17)
+       #define SPEAR1310_SATA0_CFG_PM_CLK_EN           BIT(16)
+       #define SPEAR1310_PCIE2_CFG_DEVICE_PRESENT      BIT(11)
+       #define SPEAR1310_PCIE2_CFG_POWERUP_RESET       BIT(10)
+       #define SPEAR1310_PCIE2_CFG_CORE_CLK_EN         BIT(9)
+       #define SPEAR1310_PCIE2_CFG_AUX_CLK_EN          BIT(8)
+       #define SPEAR1310_PCIE1_CFG_DEVICE_PRESENT      BIT(7)
+       #define SPEAR1310_PCIE1_CFG_POWERUP_RESET       BIT(6)
+       #define SPEAR1310_PCIE1_CFG_CORE_CLK_EN         BIT(5)
+       #define SPEAR1310_PCIE1_CFG_AUX_CLK_EN          BIT(4)
+       #define SPEAR1310_PCIE0_CFG_DEVICE_PRESENT      BIT(3)
+       #define SPEAR1310_PCIE0_CFG_POWERUP_RESET       BIT(2)
+       #define SPEAR1310_PCIE0_CFG_CORE_CLK_EN         BIT(1)
+       #define SPEAR1310_PCIE0_CFG_AUX_CLK_EN          BIT(0)
+
+       #define SPEAR1310_PCIE_CFG_MASK(x) ((0xF << (x * 4)) | BIT((x + 29)))
+       #define SPEAR1310_SATA_CFG_MASK(x) ((0xF << (x * 4 + 16)) | \
+                       BIT((x + 29)))
+       #define SPEAR1310_PCIE_CFG_VAL(x) \
+                       (SPEAR1310_PCIE_SATA##x##_SEL_PCIE | \
+                       SPEAR1310_PCIE##x##_CFG_AUX_CLK_EN | \
+                       SPEAR1310_PCIE##x##_CFG_CORE_CLK_EN | \
+                       SPEAR1310_PCIE##x##_CFG_POWERUP_RESET | \
+                       SPEAR1310_PCIE##x##_CFG_DEVICE_PRESENT)
+       #define SPEAR1310_SATA_CFG_VAL(x) \
+                       (SPEAR1310_PCIE_SATA##x##_SEL_SATA | \
+                       SPEAR1310_SATA##x##_CFG_PM_CLK_EN | \
+                       SPEAR1310_SATA##x##_CFG_POWERUP_RESET | \
+                       SPEAR1310_SATA##x##_CFG_RX_CLK_EN | \
+                       SPEAR1310_SATA##x##_CFG_TX_CLK_EN)
+
+#define SPEAR1310_PCIE_MIPHY_CFG_1             0x3A8
+       #define SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT     BIT(31)
+       #define SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2       BIT(28)
+       #define SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(x)   (x << 16)
+       #define SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT   BIT(15)
+       #define SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2     BIT(12)
+       #define SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(x) (x << 0)
+       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_MASK (0xFFFF)
+       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK (0xFFFF << 16)
+       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA \
+                       (SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+                       SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2 | \
+                       SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(60) | \
+                       SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+                       SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2 | \
+                       SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(60))
+       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+                       (SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(120))
+       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE \
+                       (SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+                       SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(25) | \
+                       SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+                       SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(25))
+
+#define SPEAR1310_PCIE_MIPHY_CFG_2             0x3AC
+
+enum spear1310_miphy_mode {
+       SATA,
+       PCIE,
+};
+
+struct spear1310_miphy_priv {
+       /* instance id of this phy */
+       u32                             id;
+       /* phy mode: 0 for SATA 1 for PCIe */
+       enum spear1310_miphy_mode       mode;
+       /* regmap for any soc specific misc registers */
+       struct regmap                   *misc;
+       /* phy struct pointer */
+       struct phy                      *phy;
+};
+
+static int spear1310_miphy_pcie_init(struct spear1310_miphy_priv *priv)
+{
+       u32 val;
+
+       regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
+                          SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK,
+                          SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE);
+
+       switch (priv->id) {
+       case 0:
+               val = SPEAR1310_PCIE_CFG_VAL(0);
+               break;
+       case 1:
+               val = SPEAR1310_PCIE_CFG_VAL(1);
+               break;
+       case 2:
+               val = SPEAR1310_PCIE_CFG_VAL(2);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
+                          SPEAR1310_PCIE_CFG_MASK(priv->id), val);
+
+       return 0;
+}
+
+static int spear1310_miphy_pcie_exit(struct spear1310_miphy_priv *priv)
+{
+       regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
+                          SPEAR1310_PCIE_CFG_MASK(priv->id), 0);
+
+       regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
+                          SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK, 0);
+
+       return 0;
+}
+
+static int spear1310_miphy_init(struct phy *phy)
+{
+       struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
+       int ret = 0;
+
+       if (priv->mode == PCIE)
+               ret = spear1310_miphy_pcie_init(priv);
+
+       return ret;
+}
+
+static int spear1310_miphy_exit(struct phy *phy)
+{
+       struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
+       int ret = 0;
+
+       if (priv->mode == PCIE)
+               ret = spear1310_miphy_pcie_exit(priv);
+
+       return ret;
+}
+
+static const struct of_device_id spear1310_miphy_of_match[] = {
+       { .compatible = "st,spear1310-miphy" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, spear1310_miphy_of_match);
+
+static const struct phy_ops spear1310_miphy_ops = {
+       .init = spear1310_miphy_init,
+       .exit = spear1310_miphy_exit,
+       .owner = THIS_MODULE,
+};
+
+static struct phy *spear1310_miphy_xlate(struct device *dev,
+                                        struct of_phandle_args *args)
+{
+       struct spear1310_miphy_priv *priv = dev_get_drvdata(dev);
+
+       if (args->args_count < 1) {
+               dev_err(dev, "DT did not pass correct no of args\n");
+               return ERR_PTR(-ENODEV);
+       }
+
+       priv->mode = args->args[0];
+
+       if (priv->mode != SATA && priv->mode != PCIE) {
+               dev_err(dev, "DT did not pass correct phy mode\n");
+               return ERR_PTR(-ENODEV);
+       }
+
+       return priv->phy;
+}
+
+static int spear1310_miphy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct spear1310_miphy_priv *priv;
+       struct phy_provider *phy_provider;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->misc =
+               syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
+       if (IS_ERR(priv->misc)) {
+               dev_err(dev, "failed to find misc regmap\n");
+               return PTR_ERR(priv->misc);
+       }
+
+       if (of_property_read_u32(dev->of_node, "phy-id", &priv->id)) {
+               dev_err(dev, "failed to find phy id\n");
+               return -EINVAL;
+       }
+
+       priv->phy = devm_phy_create(dev, NULL, &spear1310_miphy_ops);
+       if (IS_ERR(priv->phy)) {
+               dev_err(dev, "failed to create SATA PCIe PHY\n");
+               return PTR_ERR(priv->phy);
+       }
+
+       dev_set_drvdata(dev, priv);
+       phy_set_drvdata(priv->phy, priv);
+
+       phy_provider =
+               devm_of_phy_provider_register(dev, spear1310_miphy_xlate);
+       if (IS_ERR(phy_provider)) {
+               dev_err(dev, "failed to register phy provider\n");
+               return PTR_ERR(phy_provider);
+       }
+
+       return 0;
+}
+
+static struct platform_driver spear1310_miphy_driver = {
+       .probe          = spear1310_miphy_probe,
+       .driver = {
+               .name = "spear1310-miphy",
+               .of_match_table = of_match_ptr(spear1310_miphy_of_match),
+       },
+};
+
+module_platform_driver(spear1310_miphy_driver);
+
+MODULE_DESCRIPTION("ST SPEAR1310-MIPHY driver");
+MODULE_AUTHOR("Pratyush Anand <pratyush.anand@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/st/phy-spear1340-miphy.c b/drivers/phy/st/phy-spear1340-miphy.c
new file mode 100644 (file)
index 0000000..97280c0
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * ST spear1340-miphy driver
+ *
+ * Copyright (C) 2014 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@gmail.com>
+ * Mohit Kumar <mohit.kumar.dhaka@gmail.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.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
+/* SPEAr1340 Registers */
+/* Power Management Registers */
+#define SPEAR1340_PCM_CFG                      0x100
+       #define SPEAR1340_PCM_CFG_SATA_POWER_EN         BIT(11)
+#define SPEAR1340_PCM_WKUP_CFG                 0x104
+#define SPEAR1340_SWITCH_CTR                   0x108
+
+#define SPEAR1340_PERIP1_SW_RST                        0x318
+       #define SPEAR1340_PERIP1_SW_RSATA               BIT(12)
+#define SPEAR1340_PERIP2_SW_RST                        0x31C
+#define SPEAR1340_PERIP3_SW_RST                        0x320
+
+/* PCIE - SATA configuration registers */
+#define SPEAR1340_PCIE_SATA_CFG                        0x424
+       /* PCIE CFG MASks */
+       #define SPEAR1340_PCIE_CFG_DEVICE_PRESENT       BIT(11)
+       #define SPEAR1340_PCIE_CFG_POWERUP_RESET        BIT(10)
+       #define SPEAR1340_PCIE_CFG_CORE_CLK_EN          BIT(9)
+       #define SPEAR1340_PCIE_CFG_AUX_CLK_EN           BIT(8)
+       #define SPEAR1340_SATA_CFG_TX_CLK_EN            BIT(4)
+       #define SPEAR1340_SATA_CFG_RX_CLK_EN            BIT(3)
+       #define SPEAR1340_SATA_CFG_POWERUP_RESET        BIT(2)
+       #define SPEAR1340_SATA_CFG_PM_CLK_EN            BIT(1)
+       #define SPEAR1340_PCIE_SATA_SEL_PCIE            (0)
+       #define SPEAR1340_PCIE_SATA_SEL_SATA            (1)
+       #define SPEAR1340_PCIE_SATA_CFG_MASK            0xF1F
+       #define SPEAR1340_PCIE_CFG_VAL  (SPEAR1340_PCIE_SATA_SEL_PCIE | \
+                       SPEAR1340_PCIE_CFG_AUX_CLK_EN | \
+                       SPEAR1340_PCIE_CFG_CORE_CLK_EN | \
+                       SPEAR1340_PCIE_CFG_POWERUP_RESET | \
+                       SPEAR1340_PCIE_CFG_DEVICE_PRESENT)
+       #define SPEAR1340_SATA_CFG_VAL  (SPEAR1340_PCIE_SATA_SEL_SATA | \
+                       SPEAR1340_SATA_CFG_PM_CLK_EN | \
+                       SPEAR1340_SATA_CFG_POWERUP_RESET | \
+                       SPEAR1340_SATA_CFG_RX_CLK_EN | \
+                       SPEAR1340_SATA_CFG_TX_CLK_EN)
+
+#define SPEAR1340_PCIE_MIPHY_CFG               0x428
+       #define SPEAR1340_MIPHY_OSC_BYPASS_EXT          BIT(31)
+       #define SPEAR1340_MIPHY_CLK_REF_DIV2            BIT(27)
+       #define SPEAR1340_MIPHY_CLK_REF_DIV4            (2 << 27)
+       #define SPEAR1340_MIPHY_CLK_REF_DIV8            (3 << 27)
+       #define SPEAR1340_MIPHY_PLL_RATIO_TOP(x)        (x << 0)
+       #define SPEAR1340_PCIE_MIPHY_CFG_MASK           0xF80000FF
+       #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \
+                       (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
+                       SPEAR1340_MIPHY_CLK_REF_DIV2 | \
+                       SPEAR1340_MIPHY_PLL_RATIO_TOP(60))
+       #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+                       (SPEAR1340_MIPHY_PLL_RATIO_TOP(120))
+       #define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
+                       (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
+                       SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
+
+enum spear1340_miphy_mode {
+       SATA,
+       PCIE,
+};
+
+struct spear1340_miphy_priv {
+       /* phy mode: 0 for SATA 1 for PCIe */
+       enum spear1340_miphy_mode       mode;
+       /* regmap for any soc specific misc registers */
+       struct regmap                   *misc;
+       /* phy struct pointer */
+       struct phy                      *phy;
+};
+
+static int spear1340_miphy_sata_init(struct spear1340_miphy_priv *priv)
+{
+       regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+                          SPEAR1340_PCIE_SATA_CFG_MASK,
+                          SPEAR1340_SATA_CFG_VAL);
+       regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+                          SPEAR1340_PCIE_MIPHY_CFG_MASK,
+                          SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK);
+       /* Switch on sata power domain */
+       regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
+                          SPEAR1340_PCM_CFG_SATA_POWER_EN,
+                          SPEAR1340_PCM_CFG_SATA_POWER_EN);
+       /* Wait for SATA power domain on */
+       msleep(20);
+
+       /* Disable PCIE SATA Controller reset */
+       regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
+                          SPEAR1340_PERIP1_SW_RSATA, 0);
+       /* Wait for SATA reset de-assert completion */
+       msleep(20);
+
+       return 0;
+}
+
+static int spear1340_miphy_sata_exit(struct spear1340_miphy_priv *priv)
+{
+       regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+                          SPEAR1340_PCIE_SATA_CFG_MASK, 0);
+       regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+                          SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
+
+       /* Enable PCIE SATA Controller reset */
+       regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
+                          SPEAR1340_PERIP1_SW_RSATA,
+                          SPEAR1340_PERIP1_SW_RSATA);
+       /* Wait for SATA power domain off */
+       msleep(20);
+       /* Switch off sata power domain */
+       regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
+                          SPEAR1340_PCM_CFG_SATA_POWER_EN, 0);
+       /* Wait for SATA reset assert completion */
+       msleep(20);
+
+       return 0;
+}
+
+static int spear1340_miphy_pcie_init(struct spear1340_miphy_priv *priv)
+{
+       regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+                          SPEAR1340_PCIE_MIPHY_CFG_MASK,
+                          SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE);
+       regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+                          SPEAR1340_PCIE_SATA_CFG_MASK,
+                          SPEAR1340_PCIE_CFG_VAL);
+
+       return 0;
+}
+
+static int spear1340_miphy_pcie_exit(struct spear1340_miphy_priv *priv)
+{
+       regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+                          SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
+       regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+                          SPEAR1340_PCIE_SATA_CFG_MASK, 0);
+
+       return 0;
+}
+
+static int spear1340_miphy_init(struct phy *phy)
+{
+       struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
+       int ret = 0;
+
+       if (priv->mode == SATA)
+               ret = spear1340_miphy_sata_init(priv);
+       else if (priv->mode == PCIE)
+               ret = spear1340_miphy_pcie_init(priv);
+
+       return ret;
+}
+
+static int spear1340_miphy_exit(struct phy *phy)
+{
+       struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
+       int ret = 0;
+
+       if (priv->mode == SATA)
+               ret = spear1340_miphy_sata_exit(priv);
+       else if (priv->mode == PCIE)
+               ret = spear1340_miphy_pcie_exit(priv);
+
+       return ret;
+}
+
+static const struct of_device_id spear1340_miphy_of_match[] = {
+       { .compatible = "st,spear1340-miphy" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, spear1340_miphy_of_match);
+
+static const struct phy_ops spear1340_miphy_ops = {
+       .init = spear1340_miphy_init,
+       .exit = spear1340_miphy_exit,
+       .owner = THIS_MODULE,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int spear1340_miphy_suspend(struct device *dev)
+{
+       struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (priv->mode == SATA)
+               ret = spear1340_miphy_sata_exit(priv);
+
+       return ret;
+}
+
+static int spear1340_miphy_resume(struct device *dev)
+{
+       struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (priv->mode == SATA)
+               ret = spear1340_miphy_sata_init(priv);
+
+       return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(spear1340_miphy_pm_ops, spear1340_miphy_suspend,
+                        spear1340_miphy_resume);
+
+static struct phy *spear1340_miphy_xlate(struct device *dev,
+                                        struct of_phandle_args *args)
+{
+       struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+
+       if (args->args_count < 1) {
+               dev_err(dev, "DT did not pass correct no of args\n");
+               return ERR_PTR(-ENODEV);
+       }
+
+       priv->mode = args->args[0];
+
+       if (priv->mode != SATA && priv->mode != PCIE) {
+               dev_err(dev, "DT did not pass correct phy mode\n");
+               return ERR_PTR(-ENODEV);
+       }
+
+       return priv->phy;
+}
+
+static int spear1340_miphy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct spear1340_miphy_priv *priv;
+       struct phy_provider *phy_provider;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->misc =
+               syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
+       if (IS_ERR(priv->misc)) {
+               dev_err(dev, "failed to find misc regmap\n");
+               return PTR_ERR(priv->misc);
+       }
+
+       priv->phy = devm_phy_create(dev, NULL, &spear1340_miphy_ops);
+       if (IS_ERR(priv->phy)) {
+               dev_err(dev, "failed to create SATA PCIe PHY\n");
+               return PTR_ERR(priv->phy);
+       }
+
+       dev_set_drvdata(dev, priv);
+       phy_set_drvdata(priv->phy, priv);
+
+       phy_provider =
+               devm_of_phy_provider_register(dev, spear1340_miphy_xlate);
+       if (IS_ERR(phy_provider)) {
+               dev_err(dev, "failed to register phy provider\n");
+               return PTR_ERR(phy_provider);
+       }
+
+       return 0;
+}
+
+static struct platform_driver spear1340_miphy_driver = {
+       .probe          = spear1340_miphy_probe,
+       .driver = {
+               .name = "spear1340-miphy",
+               .pm = &spear1340_miphy_pm_ops,
+               .of_match_table = of_match_ptr(spear1340_miphy_of_match),
+       },
+};
+
+module_platform_driver(spear1340_miphy_driver);
+
+MODULE_DESCRIPTION("ST SPEAR1340-MIPHY driver");
+MODULE_AUTHOR("Pratyush Anand <pratyush.anand@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/st/phy-stih407-usb.c b/drivers/phy/st/phy-stih407-usb.c
new file mode 100644 (file)
index 0000000..b1f44ab
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics
+ *
+ * STMicroelectronics Generic PHY driver for STiH407 USB2.
+ *
+ * Author: Giuseppe Cavallaro <peppe.cavallaro@st.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.
+ *
+ */
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/mfd/syscon.h>
+#include <linux/phy/phy.h>
+
+#define PHYPARAM_REG   1
+#define PHYCTRL_REG    2
+
+/* Default PHY_SEL and REFCLKSEL configuration */
+#define STIH407_USB_PICOPHY_CTRL_PORT_CONF     0x6
+#define STIH407_USB_PICOPHY_CTRL_PORT_MASK     0x1f
+
+/* ports parameters overriding */
+#define STIH407_USB_PICOPHY_PARAM_DEF          0x39a4dc
+#define STIH407_USB_PICOPHY_PARAM_MASK         0xffffffff
+
+struct stih407_usb2_picophy {
+       struct phy *phy;
+       struct regmap *regmap;
+       struct device *dev;
+       struct reset_control *rstc;
+       struct reset_control *rstport;
+       int ctrl;
+       int param;
+};
+
+static int stih407_usb2_pico_ctrl(struct stih407_usb2_picophy *phy_dev)
+{
+       reset_control_deassert(phy_dev->rstc);
+
+       return regmap_update_bits(phy_dev->regmap, phy_dev->ctrl,
+                                 STIH407_USB_PICOPHY_CTRL_PORT_MASK,
+                                 STIH407_USB_PICOPHY_CTRL_PORT_CONF);
+}
+
+static int stih407_usb2_init_port(struct phy *phy)
+{
+       int ret;
+       struct stih407_usb2_picophy *phy_dev = phy_get_drvdata(phy);
+
+       stih407_usb2_pico_ctrl(phy_dev);
+
+       ret = regmap_update_bits(phy_dev->regmap,
+                                phy_dev->param,
+                                STIH407_USB_PICOPHY_PARAM_MASK,
+                                STIH407_USB_PICOPHY_PARAM_DEF);
+       if (ret)
+               return ret;
+
+       return reset_control_deassert(phy_dev->rstport);
+}
+
+static int stih407_usb2_exit_port(struct phy *phy)
+{
+       struct stih407_usb2_picophy *phy_dev = phy_get_drvdata(phy);
+
+       /*
+        * Only port reset is asserted, phy global reset is kept untouched
+        * as other ports may still be active. When all ports are in reset
+        * state, assumption is made that power will be cut off on the phy, in
+        * case of suspend for instance. Theoretically, asserting individual
+        * reset (like here) or global reset should be equivalent.
+        */
+       return reset_control_assert(phy_dev->rstport);
+}
+
+static const struct phy_ops stih407_usb2_picophy_data = {
+       .init = stih407_usb2_init_port,
+       .exit = stih407_usb2_exit_port,
+       .owner = THIS_MODULE,
+};
+
+static int stih407_usb2_picophy_probe(struct platform_device *pdev)
+{
+       struct stih407_usb2_picophy *phy_dev;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct phy_provider *phy_provider;
+       struct phy *phy;
+       int ret;
+
+       phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL);
+       if (!phy_dev)
+               return -ENOMEM;
+
+       phy_dev->dev = dev;
+       dev_set_drvdata(dev, phy_dev);
+
+       phy_dev->rstc = devm_reset_control_get_shared(dev, "global");
+       if (IS_ERR(phy_dev->rstc)) {
+               dev_err(dev, "failed to ctrl picoPHY reset\n");
+               return PTR_ERR(phy_dev->rstc);
+       }
+
+       phy_dev->rstport = devm_reset_control_get_exclusive(dev, "port");
+       if (IS_ERR(phy_dev->rstport)) {
+               dev_err(dev, "failed to ctrl picoPHY reset\n");
+               return PTR_ERR(phy_dev->rstport);
+       }
+
+       /* Reset port by default: only deassert it in phy init */
+       reset_control_assert(phy_dev->rstport);
+
+       phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+       if (IS_ERR(phy_dev->regmap)) {
+               dev_err(dev, "No syscfg phandle specified\n");
+               return PTR_ERR(phy_dev->regmap);
+       }
+
+       ret = of_property_read_u32_index(np, "st,syscfg", PHYPARAM_REG,
+                                       &phy_dev->param);
+       if (ret) {
+               dev_err(dev, "can't get phyparam offset (%d)\n", ret);
+               return ret;
+       }
+
+       ret = of_property_read_u32_index(np, "st,syscfg", PHYCTRL_REG,
+                                       &phy_dev->ctrl);
+       if (ret) {
+               dev_err(dev, "can't get phyctrl offset (%d)\n", ret);
+               return ret;
+       }
+
+       phy = devm_phy_create(dev, NULL, &stih407_usb2_picophy_data);
+       if (IS_ERR(phy)) {
+               dev_err(dev, "failed to create Display Port PHY\n");
+               return PTR_ERR(phy);
+       }
+
+       phy_dev->phy = phy;
+       phy_set_drvdata(phy, phy_dev);
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
+       dev_info(dev, "STiH407 USB Generic picoPHY driver probed!");
+
+       return 0;
+}
+
+static const struct of_device_id stih407_usb2_picophy_of_match[] = {
+       { .compatible = "st,stih407-usb2-phy" },
+       { /*sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, stih407_usb2_picophy_of_match);
+
+static struct platform_driver stih407_usb2_picophy_driver = {
+       .probe = stih407_usb2_picophy_probe,
+       .driver = {
+                  .name = "stih407-usb-genphy",
+                  .of_match_table = stih407_usb2_picophy_of_match,
+                  }
+};
+
+module_platform_driver(stih407_usb2_picophy_driver);
+
+MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics Generic picoPHY driver for STiH407");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig
new file mode 100644 (file)
index 0000000..2050356
--- /dev/null
@@ -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.
diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile
new file mode 100644 (file)
index 0000000..0cc3a1a
--- /dev/null
@@ -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
diff --git a/drivers/phy/ti/phy-da8xx-usb.c b/drivers/phy/ti/phy-da8xx-usb.c
new file mode 100644 (file)
index 0000000..1b82bff
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * phy-da8xx-usb - TI DaVinci DA8xx USB PHY driver
+ *
+ * Copyright (C) 2016 David Lechner <david@lechnology.com>
+ *
+ * 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 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/mfd/da8xx-cfgchip.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define PHY_INIT_BITS  (CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN)
+
+struct da8xx_usb_phy {
+       struct phy_provider     *phy_provider;
+       struct phy              *usb11_phy;
+       struct phy              *usb20_phy;
+       struct clk              *usb11_clk;
+       struct clk              *usb20_clk;
+       struct regmap           *regmap;
+};
+
+static int da8xx_usb11_phy_power_on(struct phy *phy)
+{
+       struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
+       int ret;
+
+       ret = clk_prepare_enable(d_phy->usb11_clk);
+       if (ret)
+               return ret;
+
+       regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM,
+                         CFGCHIP2_USB1SUSPENDM);
+
+       return 0;
+}
+
+static int da8xx_usb11_phy_power_off(struct phy *phy)
+{
+       struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
+
+       regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM, 0);
+
+       clk_disable_unprepare(d_phy->usb11_clk);
+
+       return 0;
+}
+
+static const struct phy_ops da8xx_usb11_phy_ops = {
+       .power_on       = da8xx_usb11_phy_power_on,
+       .power_off      = da8xx_usb11_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int da8xx_usb20_phy_power_on(struct phy *phy)
+{
+       struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
+       int ret;
+
+       ret = clk_prepare_enable(d_phy->usb20_clk);
+       if (ret)
+               return ret;
+
+       regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGPWRDN, 0);
+
+       return 0;
+}
+
+static int da8xx_usb20_phy_power_off(struct phy *phy)
+{
+       struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
+
+       regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGPWRDN,
+                         CFGCHIP2_OTGPWRDN);
+
+       clk_disable_unprepare(d_phy->usb20_clk);
+
+       return 0;
+}
+
+static int da8xx_usb20_phy_set_mode(struct phy *phy, enum phy_mode mode)
+{
+       struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy);
+       u32 val;
+
+       switch (mode) {
+       case PHY_MODE_USB_HOST:         /* Force VBUS valid, ID = 0 */
+               val = CFGCHIP2_OTGMODE_FORCE_HOST;
+               break;
+       case PHY_MODE_USB_DEVICE:       /* Force VBUS valid, ID = 1 */
+               val = CFGCHIP2_OTGMODE_FORCE_DEVICE;
+               break;
+       case PHY_MODE_USB_OTG:  /* Don't override the VBUS/ID comparators */
+               val = CFGCHIP2_OTGMODE_NO_OVERRIDE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGMODE_MASK,
+                         val);
+
+       return 0;
+}
+
+static const struct phy_ops da8xx_usb20_phy_ops = {
+       .power_on       = da8xx_usb20_phy_power_on,
+       .power_off      = da8xx_usb20_phy_power_off,
+       .set_mode       = da8xx_usb20_phy_set_mode,
+       .owner          = THIS_MODULE,
+};
+
+static struct phy *da8xx_usb_phy_of_xlate(struct device *dev,
+                                        struct of_phandle_args *args)
+{
+       struct da8xx_usb_phy *d_phy = dev_get_drvdata(dev);
+
+       if (!d_phy)
+               return ERR_PTR(-ENODEV);
+
+       switch (args->args[0]) {
+       case 0:
+               return d_phy->usb20_phy;
+       case 1:
+               return d_phy->usb11_phy;
+       default:
+               return ERR_PTR(-EINVAL);
+       }
+}
+
+static int da8xx_usb_phy_probe(struct platform_device *pdev)
+{
+       struct device           *dev = &pdev->dev;
+       struct device_node      *node = dev->of_node;
+       struct da8xx_usb_phy    *d_phy;
+
+       d_phy = devm_kzalloc(dev, sizeof(*d_phy), GFP_KERNEL);
+       if (!d_phy)
+               return -ENOMEM;
+
+       if (node)
+               d_phy->regmap = syscon_regmap_lookup_by_compatible(
+                                                       "ti,da830-cfgchip");
+       else
+               d_phy->regmap = syscon_regmap_lookup_by_pdevname("syscon");
+       if (IS_ERR(d_phy->regmap)) {
+               dev_err(dev, "Failed to get syscon\n");
+               return PTR_ERR(d_phy->regmap);
+       }
+
+       d_phy->usb11_clk = devm_clk_get(dev, "usb11_phy");
+       if (IS_ERR(d_phy->usb11_clk)) {
+               dev_err(dev, "Failed to get usb11_phy clock\n");
+               return PTR_ERR(d_phy->usb11_clk);
+       }
+
+       d_phy->usb20_clk = devm_clk_get(dev, "usb20_phy");
+       if (IS_ERR(d_phy->usb20_clk)) {
+               dev_err(dev, "Failed to get usb20_phy clock\n");
+               return PTR_ERR(d_phy->usb20_clk);
+       }
+
+       d_phy->usb11_phy = devm_phy_create(dev, node, &da8xx_usb11_phy_ops);
+       if (IS_ERR(d_phy->usb11_phy)) {
+               dev_err(dev, "Failed to create usb11 phy\n");
+               return PTR_ERR(d_phy->usb11_phy);
+       }
+
+       d_phy->usb20_phy = devm_phy_create(dev, node, &da8xx_usb20_phy_ops);
+       if (IS_ERR(d_phy->usb20_phy)) {
+               dev_err(dev, "Failed to create usb20 phy\n");
+               return PTR_ERR(d_phy->usb20_phy);
+       }
+
+       platform_set_drvdata(pdev, d_phy);
+       phy_set_drvdata(d_phy->usb11_phy, d_phy);
+       phy_set_drvdata(d_phy->usb20_phy, d_phy);
+
+       if (node) {
+               d_phy->phy_provider = devm_of_phy_provider_register(dev,
+                                                       da8xx_usb_phy_of_xlate);
+               if (IS_ERR(d_phy->phy_provider)) {
+                       dev_err(dev, "Failed to create phy provider\n");
+                       return PTR_ERR(d_phy->phy_provider);
+               }
+       } else {
+               int ret;
+
+               ret = phy_create_lookup(d_phy->usb11_phy, "usb-phy",
+                                       "ohci-da8xx");
+               if (ret)
+                       dev_warn(dev, "Failed to create usb11 phy lookup\n");
+               ret = phy_create_lookup(d_phy->usb20_phy, "usb-phy",
+                                       "musb-da8xx");
+               if (ret)
+                       dev_warn(dev, "Failed to create usb20 phy lookup\n");
+       }
+
+       regmap_write_bits(d_phy->regmap, CFGCHIP(2),
+                         PHY_INIT_BITS, PHY_INIT_BITS);
+
+       return 0;
+}
+
+static int da8xx_usb_phy_remove(struct platform_device *pdev)
+{
+       struct da8xx_usb_phy *d_phy = platform_get_drvdata(pdev);
+
+       if (!pdev->dev.of_node) {
+               phy_remove_lookup(d_phy->usb20_phy, "usb-phy", "musb-da8xx");
+               phy_remove_lookup(d_phy->usb11_phy, "usb-phy", "ohci-da8xx");
+       }
+
+       return 0;
+}
+
+static const struct of_device_id da8xx_usb_phy_ids[] = {
+       { .compatible = "ti,da830-usb-phy" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, da8xx_usb_phy_ids);
+
+static struct platform_driver da8xx_usb_phy_driver = {
+       .probe  = da8xx_usb_phy_probe,
+       .remove = da8xx_usb_phy_remove,
+       .driver = {
+               .name   = "da8xx-usb-phy",
+               .of_match_table = da8xx_usb_phy_ids,
+       },
+};
+
+module_platform_driver(da8xx_usb_phy_driver);
+
+MODULE_ALIAS("platform:da8xx-usb-phy");
+MODULE_AUTHOR("David Lechner <david@lechnology.com>");
+MODULE_DESCRIPTION("TI DA8xx USB PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/ti/phy-dm816x-usb.c b/drivers/phy/ti/phy-dm816x-usb.c
new file mode 100644 (file)
index 0000000..cbcce7c
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/phy/phy.h>
+#include <linux/of_platform.h>
+
+#include <linux/mfd/syscon.h>
+
+/*
+ * TRM has two sets of USB_CTRL registers.. The correct register bits
+ * are in TRM section 24.9.8.2 USB_CTRL Register. The TRM documents the
+ * phy as being SR70LX Synopsys USB 2.0 OTG nanoPHY. It also seems at
+ * least dm816x rev c ignores writes to USB_CTRL register, but the TI
+ * kernel is writing to those so it's possible that later revisions
+ * have worknig USB_CTRL register.
+ *
+ * Also note that At least USB_CTRL register seems to be dm816x specific
+ * according to the TRM. It's possible that USBPHY_CTRL is more generic,
+ * but that would have to be checked against the SR70LX documentation
+ * which does not seem to be publicly available.
+ *
+ * Finally, the phy on dm814x and am335x is different from dm816x.
+ */
+#define DM816X_USB_CTRL_PHYCLKSRC      BIT(8)  /* 1 = PLL ref clock */
+#define DM816X_USB_CTRL_PHYSLEEP1      BIT(1)  /* Enable the first phy */
+#define DM816X_USB_CTRL_PHYSLEEP0      BIT(0)  /* Enable the second phy */
+
+#define DM816X_USBPHY_CTRL_TXRISETUNE  1
+#define DM816X_USBPHY_CTRL_TXVREFTUNE  0xc
+#define DM816X_USBPHY_CTRL_TXPREEMTUNE 0x2
+
+struct dm816x_usb_phy {
+       struct regmap *syscon;
+       struct device *dev;
+       unsigned int instance;
+       struct clk *refclk;
+       struct usb_phy phy;
+       unsigned int usb_ctrl;          /* Shared between phy0 and phy1 */
+       unsigned int usbphy_ctrl;
+};
+
+static int dm816x_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 dm816x_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 int dm816x_usb_phy_init(struct phy *x)
+{
+       struct dm816x_usb_phy *phy = phy_get_drvdata(x);
+       unsigned int val;
+       int error;
+
+       if (clk_get_rate(phy->refclk) != 24000000)
+               dev_warn(phy->dev, "nonstandard phy refclk\n");
+
+       /* Set PLL ref clock and put phys to sleep */
+       error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
+                                  DM816X_USB_CTRL_PHYCLKSRC |
+                                  DM816X_USB_CTRL_PHYSLEEP1 |
+                                  DM816X_USB_CTRL_PHYSLEEP0,
+                                  0);
+       regmap_read(phy->syscon, phy->usb_ctrl, &val);
+       if ((val & 3) != 0)
+               dev_info(phy->dev,
+                        "Working dm816x USB_CTRL! (0x%08x)\n",
+                        val);
+
+       /*
+        * TI kernel sets these values for "symmetrical eye diagram and
+        * better signal quality" so let's assume somebody checked the
+        * values with a scope and set them here too.
+        */
+       regmap_read(phy->syscon, phy->usbphy_ctrl, &val);
+       val |= DM816X_USBPHY_CTRL_TXRISETUNE |
+               DM816X_USBPHY_CTRL_TXVREFTUNE |
+               DM816X_USBPHY_CTRL_TXPREEMTUNE;
+       regmap_write(phy->syscon, phy->usbphy_ctrl, val);
+
+       return 0;
+}
+
+static const struct phy_ops ops = {
+       .init           = dm816x_usb_phy_init,
+       .owner          = THIS_MODULE,
+};
+
+static int __maybe_unused dm816x_usb_phy_runtime_suspend(struct device *dev)
+{
+       struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
+       unsigned int mask, val;
+       int error = 0;
+
+       mask = BIT(phy->instance);
+       val = ~BIT(phy->instance);
+       error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
+                                  mask, val);
+       if (error)
+               dev_err(phy->dev, "phy%i failed to power off\n",
+                       phy->instance);
+       clk_disable(phy->refclk);
+
+       return 0;
+}
+
+static int __maybe_unused dm816x_usb_phy_runtime_resume(struct device *dev)
+{
+       struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
+       unsigned int mask, val;
+       int error;
+
+       error = clk_enable(phy->refclk);
+       if (error)
+               return error;
+
+       /*
+        * Note that at least dm816x rev c does not seem to do
+        * anything with the USB_CTRL register. But let's follow
+        * what the TI tree is doing in case later revisions use
+        * USB_CTRL.
+        */
+       mask = BIT(phy->instance);
+       val = BIT(phy->instance);
+       error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
+                                  mask, val);
+       if (error) {
+               dev_err(phy->dev, "phy%i failed to power on\n",
+                       phy->instance);
+               clk_disable(phy->refclk);
+               return error;
+       }
+
+       return 0;
+}
+
+static UNIVERSAL_DEV_PM_OPS(dm816x_usb_phy_pm_ops,
+                           dm816x_usb_phy_runtime_suspend,
+                           dm816x_usb_phy_runtime_resume,
+                           NULL);
+
+#ifdef CONFIG_OF
+static const struct of_device_id dm816x_usb_phy_id_table[] = {
+       {
+               .compatible = "ti,dm8168-usb-phy",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, dm816x_usb_phy_id_table);
+#endif
+
+static int dm816x_usb_phy_probe(struct platform_device *pdev)
+{
+       struct dm816x_usb_phy *phy;
+       struct resource *res;
+       struct phy *generic_phy;
+       struct phy_provider *phy_provider;
+       struct usb_otg *otg;
+       const struct of_device_id *of_id;
+       const struct usb_phy_data *phy_data;
+       int error;
+
+       of_id = of_match_device(of_match_ptr(dm816x_usb_phy_id_table),
+                               &pdev->dev);
+       if (!of_id)
+               return -EINVAL;
+
+       phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENOENT;
+
+       phy->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+                                                     "syscon");
+       if (IS_ERR(phy->syscon))
+               return PTR_ERR(phy->syscon);
+
+       /*
+        * According to sprs614e.pdf, the first usb_ctrl is shared and
+        * the second instance for usb_ctrl is reserved.. Also the
+        * register bits are different from earlier TRMs.
+        */
+       phy->usb_ctrl = 0x20;
+       phy->usbphy_ctrl = (res->start & 0xff) + 4;
+       if (phy->usbphy_ctrl == 0x2c)
+               phy->instance = 1;
+
+       phy_data = of_id->data;
+
+       otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+       if (!otg)
+               return -ENOMEM;
+
+       phy->dev = &pdev->dev;
+       phy->phy.dev = phy->dev;
+       phy->phy.label = "dm8168_usb_phy";
+       phy->phy.otg = otg;
+       phy->phy.type = USB_PHY_TYPE_USB2;
+       otg->set_host = dm816x_usb_phy_set_host;
+       otg->set_peripheral = dm816x_usb_phy_set_peripheral;
+       otg->usb_phy = &phy->phy;
+
+       platform_set_drvdata(pdev, phy);
+
+       phy->refclk = devm_clk_get(phy->dev, "refclk");
+       if (IS_ERR(phy->refclk))
+               return PTR_ERR(phy->refclk);
+       error = clk_prepare(phy->refclk);
+       if (error)
+               return error;
+
+       pm_runtime_enable(phy->dev);
+       generic_phy = devm_phy_create(phy->dev, NULL, &ops);
+       if (IS_ERR(generic_phy))
+               return PTR_ERR(generic_phy);
+
+       phy_set_drvdata(generic_phy, phy);
+
+       phy_provider = devm_of_phy_provider_register(phy->dev,
+                                                    of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
+       usb_add_phy_dev(&phy->phy);
+
+       return 0;
+}
+
+static int dm816x_usb_phy_remove(struct platform_device *pdev)
+{
+       struct dm816x_usb_phy *phy = platform_get_drvdata(pdev);
+
+       usb_remove_phy(&phy->phy);
+       pm_runtime_disable(phy->dev);
+       clk_unprepare(phy->refclk);
+
+       return 0;
+}
+
+static struct platform_driver dm816x_usb_phy_driver = {
+       .probe          = dm816x_usb_phy_probe,
+       .remove         = dm816x_usb_phy_remove,
+       .driver         = {
+               .name   = "dm816x-usb-phy",
+               .pm     = &dm816x_usb_phy_pm_ops,
+               .of_match_table = of_match_ptr(dm816x_usb_phy_id_table),
+       },
+};
+
+module_platform_driver(dm816x_usb_phy_driver);
+
+MODULE_ALIAS("platform:dm816x_usb");
+MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
+MODULE_DESCRIPTION("dm816x usb phy driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/ti/phy-omap-control.c b/drivers/phy/ti/phy-omap-control.c
new file mode 100644 (file)
index 0000000..e9c41b3
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ * omap-control-phy.c - The PHY part of control module.
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/phy/omap_control_phy.h>
+
+/**
+ * omap_control_pcie_pcs - set the PCS delay count
+ * @dev: the control module device
+ * @delay: 8 bit delay value
+ */
+void omap_control_pcie_pcs(struct device *dev, u8 delay)
+{
+       u32 val;
+       struct omap_control_phy *control_phy;
+
+       if (IS_ERR(dev) || !dev) {
+               pr_err("%s: invalid device\n", __func__);
+               return;
+       }
+
+       control_phy = dev_get_drvdata(dev);
+       if (!control_phy) {
+               dev_err(dev, "%s: invalid control phy device\n", __func__);
+               return;
+       }
+
+       if (control_phy->type != OMAP_CTRL_TYPE_PCIE) {
+               dev_err(dev, "%s: unsupported operation\n", __func__);
+               return;
+       }
+
+       val = readl(control_phy->pcie_pcs);
+       val &= ~(OMAP_CTRL_PCIE_PCS_MASK <<
+               OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT);
+       val |= (delay << OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT);
+       writel(val, control_phy->pcie_pcs);
+}
+EXPORT_SYMBOL_GPL(omap_control_pcie_pcs);
+
+/**
+ * omap_control_phy_power - power on/off the phy using control module reg
+ * @dev: the control module device
+ * @on: 0 or 1, based on powering on or off the PHY
+ */
+void omap_control_phy_power(struct device *dev, int on)
+{
+       u32 val;
+       unsigned long rate;
+       struct omap_control_phy *control_phy;
+
+       if (IS_ERR(dev) || !dev) {
+               pr_err("%s: invalid device\n", __func__);
+               return;
+       }
+
+       control_phy = dev_get_drvdata(dev);
+       if (!control_phy) {
+               dev_err(dev, "%s: invalid control phy device\n", __func__);
+               return;
+       }
+
+       if (control_phy->type == OMAP_CTRL_TYPE_OTGHS)
+               return;
+
+       val = readl(control_phy->power);
+
+       switch (control_phy->type) {
+       case OMAP_CTRL_TYPE_USB2:
+               if (on)
+                       val &= ~OMAP_CTRL_DEV_PHY_PD;
+               else
+                       val |= OMAP_CTRL_DEV_PHY_PD;
+               break;
+
+       case OMAP_CTRL_TYPE_PCIE:
+       case OMAP_CTRL_TYPE_PIPE3:
+               rate = clk_get_rate(control_phy->sys_clk);
+               rate = rate/1000000;
+
+               if (on) {
+                       val &= ~(OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK |
+                               OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK);
+                       val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON <<
+                               OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
+                       val |= rate <<
+                               OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT;
+               } else {
+                       val &= ~OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK;
+                       val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF <<
+                               OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
+               }
+               break;
+
+       case OMAP_CTRL_TYPE_DRA7USB2:
+               if (on)
+                       val &= ~OMAP_CTRL_USB2_PHY_PD;
+               else
+                       val |= OMAP_CTRL_USB2_PHY_PD;
+               break;
+
+       case OMAP_CTRL_TYPE_AM437USB2:
+               if (on) {
+                       val &= ~(AM437X_CTRL_USB2_PHY_PD |
+                                       AM437X_CTRL_USB2_OTG_PD);
+                       val |= (AM437X_CTRL_USB2_OTGVDET_EN |
+                                       AM437X_CTRL_USB2_OTGSESSEND_EN);
+               } else {
+                       val &= ~(AM437X_CTRL_USB2_OTGVDET_EN |
+                                       AM437X_CTRL_USB2_OTGSESSEND_EN);
+                       val |= (AM437X_CTRL_USB2_PHY_PD |
+                                        AM437X_CTRL_USB2_OTG_PD);
+               }
+               break;
+       default:
+               dev_err(dev, "%s: type %d not recognized\n",
+                       __func__, control_phy->type);
+               break;
+       }
+
+       writel(val, control_phy->power);
+}
+EXPORT_SYMBOL_GPL(omap_control_phy_power);
+
+/**
+ * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded
+ * @ctrl_phy: struct omap_control_phy *
+ *
+ * Writes to the mailbox register to notify the usb core that a usb
+ * device has been connected.
+ */
+static void omap_control_usb_host_mode(struct omap_control_phy *ctrl_phy)
+{
+       u32 val;
+
+       val = readl(ctrl_phy->otghs_control);
+       val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND);
+       val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID;
+       writel(val, ctrl_phy->otghs_control);
+}
+
+/**
+ * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high
+ * impedance
+ * @ctrl_phy: struct omap_control_phy *
+ *
+ * Writes to the mailbox register to notify the usb core that it has been
+ * connected to a usb host.
+ */
+static void omap_control_usb_device_mode(struct omap_control_phy *ctrl_phy)
+{
+       u32 val;
+
+       val = readl(ctrl_phy->otghs_control);
+       val &= ~OMAP_CTRL_DEV_SESSEND;
+       val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID |
+               OMAP_CTRL_DEV_VBUSVALID;
+       writel(val, ctrl_phy->otghs_control);
+}
+
+/**
+ * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high
+ * impedance
+ * @ctrl_phy: struct omap_control_phy *
+ *
+ * Writes to the mailbox register to notify the usb core it's now in
+ * disconnected state.
+ */
+static void omap_control_usb_set_sessionend(struct omap_control_phy *ctrl_phy)
+{
+       u32 val;
+
+       val = readl(ctrl_phy->otghs_control);
+       val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID);
+       val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND;
+       writel(val, ctrl_phy->otghs_control);
+}
+
+/**
+ * omap_control_usb_set_mode - Calls to functions to set USB in one of host mode
+ * or device mode or to denote disconnected state
+ * @dev: the control module device
+ * @mode: The mode to which usb should be configured
+ *
+ * This is an API to write to the mailbox register to notify the usb core that
+ * a usb device has been connected.
+ */
+void omap_control_usb_set_mode(struct device *dev,
+       enum omap_control_usb_mode mode)
+{
+       struct omap_control_phy *ctrl_phy;
+
+       if (IS_ERR(dev) || !dev)
+               return;
+
+       ctrl_phy = dev_get_drvdata(dev);
+       if (!ctrl_phy) {
+               dev_err(dev, "Invalid control phy device\n");
+               return;
+       }
+
+       if (ctrl_phy->type != OMAP_CTRL_TYPE_OTGHS)
+               return;
+
+       switch (mode) {
+       case USB_MODE_HOST:
+               omap_control_usb_host_mode(ctrl_phy);
+               break;
+       case USB_MODE_DEVICE:
+               omap_control_usb_device_mode(ctrl_phy);
+               break;
+       case USB_MODE_DISCONNECT:
+               omap_control_usb_set_sessionend(ctrl_phy);
+               break;
+       default:
+               dev_vdbg(dev, "invalid omap control usb mode\n");
+       }
+}
+EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
+
+static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
+static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
+static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
+static const enum omap_control_phy_type pcie_data = OMAP_CTRL_TYPE_PCIE;
+static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2;
+static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2;
+
+static const struct of_device_id omap_control_phy_id_table[] = {
+       {
+               .compatible = "ti,control-phy-otghs",
+               .data = &otghs_data,
+       },
+       {
+               .compatible = "ti,control-phy-usb2",
+               .data = &usb2_data,
+       },
+       {
+               .compatible = "ti,control-phy-pipe3",
+               .data = &pipe3_data,
+       },
+       {
+               .compatible = "ti,control-phy-pcie",
+               .data = &pcie_data,
+       },
+       {
+               .compatible = "ti,control-phy-usb2-dra7",
+               .data = &dra7usb2_data,
+       },
+       {
+               .compatible = "ti,control-phy-usb2-am437",
+               .data = &am437usb2_data,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, omap_control_phy_id_table);
+
+static int omap_control_phy_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       const struct of_device_id *of_id;
+       struct omap_control_phy *control_phy;
+
+       of_id = of_match_device(omap_control_phy_id_table, &pdev->dev);
+       if (!of_id)
+               return -EINVAL;
+
+       control_phy = devm_kzalloc(&pdev->dev, sizeof(*control_phy),
+               GFP_KERNEL);
+       if (!control_phy)
+               return -ENOMEM;
+
+       control_phy->dev = &pdev->dev;
+       control_phy->type = *(enum omap_control_phy_type *)of_id->data;
+
+       if (control_phy->type == OMAP_CTRL_TYPE_OTGHS) {
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                       "otghs_control");
+               control_phy->otghs_control = devm_ioremap_resource(
+                       &pdev->dev, res);
+               if (IS_ERR(control_phy->otghs_control))
+                       return PTR_ERR(control_phy->otghs_control);
+       } else {
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                               "power");
+               control_phy->power = devm_ioremap_resource(&pdev->dev, res);
+               if (IS_ERR(control_phy->power)) {
+                       dev_err(&pdev->dev, "Couldn't get power register\n");
+                       return PTR_ERR(control_phy->power);
+               }
+       }
+
+       if (control_phy->type == OMAP_CTRL_TYPE_PIPE3 ||
+           control_phy->type == OMAP_CTRL_TYPE_PCIE) {
+               control_phy->sys_clk = devm_clk_get(control_phy->dev,
+                       "sys_clkin");
+               if (IS_ERR(control_phy->sys_clk)) {
+                       pr_err("%s: unable to get sys_clkin\n", __func__);
+                       return -EINVAL;
+               }
+       }
+
+       if (control_phy->type == OMAP_CTRL_TYPE_PCIE) {
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                                  "pcie_pcs");
+               control_phy->pcie_pcs = devm_ioremap_resource(&pdev->dev, res);
+               if (IS_ERR(control_phy->pcie_pcs))
+                       return PTR_ERR(control_phy->pcie_pcs);
+       }
+
+       dev_set_drvdata(control_phy->dev, control_phy);
+
+       return 0;
+}
+
+static struct platform_driver omap_control_phy_driver = {
+       .probe          = omap_control_phy_probe,
+       .driver         = {
+               .name   = "omap-control-phy",
+               .of_match_table = omap_control_phy_id_table,
+       },
+};
+
+static int __init omap_control_phy_init(void)
+{
+       return platform_driver_register(&omap_control_phy_driver);
+}
+subsys_initcall(omap_control_phy_init);
+
+static void __exit omap_control_phy_exit(void)
+{
+       platform_driver_unregister(&omap_control_phy_driver);
+}
+module_exit(omap_control_phy_exit);
+
+MODULE_ALIAS("platform:omap_control_phy");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("OMAP Control Module PHY Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/ti/phy-omap-usb2.c b/drivers/phy/ti/phy-omap-usb2.c
new file mode 100644 (file)
index 0000000..fe909fd
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ * omap-usb2.c - USB PHY, talking to musb controller in OMAP.
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/phy/omap_usb.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/phy/omap_control_phy.h>
+#include <linux/phy/phy.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/of_platform.h>
+
+#define USB2PHY_DISCON_BYP_LATCH (1 << 31)
+#define USB2PHY_ANA_CONFIG1 0x4c
+
+/**
+ * omap_usb2_set_comparator - links the comparator present in the sytem with
+ *     this phy
+ * @comparator - the companion phy(comparator) for this phy
+ *
+ * The phy companion driver should call this API passing the phy_companion
+ * filled with set_vbus and start_srp to be used by usb phy.
+ *
+ * For use by phy companion driver
+ */
+int omap_usb2_set_comparator(struct phy_companion *comparator)
+{
+       struct omap_usb *phy;
+       struct usb_phy  *x = usb_get_phy(USB_PHY_TYPE_USB2);
+
+       if (IS_ERR(x))
+               return -ENODEV;
+
+       phy = phy_to_omapusb(x);
+       phy->comparator = comparator;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
+
+static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
+{
+       struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
+
+       if (!phy->comparator)
+               return -ENODEV;
+
+       return phy->comparator->set_vbus(phy->comparator, enabled);
+}
+
+static int omap_usb_start_srp(struct usb_otg *otg)
+{
+       struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
+
+       if (!phy->comparator)
+               return -ENODEV;
+
+       return phy->comparator->start_srp(phy->comparator);
+}
+
+static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+       otg->host = host;
+       if (!host)
+               otg->state = OTG_STATE_UNDEFINED;
+
+       return 0;
+}
+
+static int omap_usb_set_peripheral(struct usb_otg *otg,
+               struct usb_gadget *gadget)
+{
+       otg->gadget = gadget;
+       if (!gadget)
+               otg->state = OTG_STATE_UNDEFINED;
+
+       return 0;
+}
+
+static int omap_usb_phy_power(struct omap_usb *phy, int on)
+{
+       u32 val;
+       int ret;
+
+       if (!phy->syscon_phy_power) {
+               omap_control_phy_power(phy->control_dev, on);
+               return 0;
+       }
+
+       if (on)
+               val = phy->power_on;
+       else
+               val = phy->power_off;
+
+       ret = regmap_update_bits(phy->syscon_phy_power, phy->power_reg,
+                                phy->mask, val);
+       return ret;
+}
+
+static int omap_usb_power_off(struct phy *x)
+{
+       struct omap_usb *phy = phy_get_drvdata(x);
+
+       return omap_usb_phy_power(phy, false);
+}
+
+static int omap_usb_power_on(struct phy *x)
+{
+       struct omap_usb *phy = phy_get_drvdata(x);
+
+       return omap_usb_phy_power(phy, true);
+}
+
+static int omap_usb2_disable_clocks(struct omap_usb *phy)
+{
+       clk_disable(phy->wkupclk);
+       if (!IS_ERR(phy->optclk))
+               clk_disable(phy->optclk);
+
+       return 0;
+}
+
+static int omap_usb2_enable_clocks(struct omap_usb *phy)
+{
+       int ret;
+
+       ret = clk_enable(phy->wkupclk);
+       if (ret < 0) {
+               dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
+               goto err0;
+       }
+
+       if (!IS_ERR(phy->optclk)) {
+               ret = clk_enable(phy->optclk);
+               if (ret < 0) {
+                       dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
+                       goto err1;
+               }
+       }
+
+       return 0;
+
+err1:
+       clk_disable(phy->wkupclk);
+
+err0:
+       return ret;
+}
+
+static int omap_usb_init(struct phy *x)
+{
+       struct omap_usb *phy = phy_get_drvdata(x);
+       u32 val;
+
+       omap_usb2_enable_clocks(phy);
+
+       if (phy->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
+               /*
+                *
+                * Reduce the sensitivity of internal PHY by enabling the
+                * DISCON_BYP_LATCH of the USB2PHY_ANA_CONFIG1 register. This
+                * resolves issues with certain devices which can otherwise
+                * be prone to false disconnects.
+                *
+                */
+               val = omap_usb_readl(phy->phy_base, USB2PHY_ANA_CONFIG1);
+               val |= USB2PHY_DISCON_BYP_LATCH;
+               omap_usb_writel(phy->phy_base, USB2PHY_ANA_CONFIG1, val);
+       }
+
+       return 0;
+}
+
+static int omap_usb_exit(struct phy *x)
+{
+       struct omap_usb *phy = phy_get_drvdata(x);
+
+       return omap_usb2_disable_clocks(phy);
+}
+
+static const struct phy_ops ops = {
+       .init           = omap_usb_init,
+       .exit           = omap_usb_exit,
+       .power_on       = omap_usb_power_on,
+       .power_off      = omap_usb_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static const struct usb_phy_data omap_usb2_data = {
+       .label = "omap_usb2",
+       .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS,
+       .mask = OMAP_DEV_PHY_PD,
+       .power_off = OMAP_DEV_PHY_PD,
+};
+
+static const struct usb_phy_data omap5_usb2_data = {
+       .label = "omap5_usb2",
+       .flags = 0,
+       .mask = OMAP_DEV_PHY_PD,
+       .power_off = OMAP_DEV_PHY_PD,
+};
+
+static const struct usb_phy_data dra7x_usb2_data = {
+       .label = "dra7x_usb2",
+       .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
+       .mask = OMAP_DEV_PHY_PD,
+       .power_off = OMAP_DEV_PHY_PD,
+};
+
+static const struct usb_phy_data dra7x_usb2_phy2_data = {
+       .label = "dra7x_usb2_phy2",
+       .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
+       .mask = OMAP_USB2_PHY_PD,
+       .power_off = OMAP_USB2_PHY_PD,
+};
+
+static const struct usb_phy_data am437x_usb2_data = {
+       .label = "am437x_usb2",
+       .flags =  0,
+       .mask = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD |
+               AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
+       .power_on = AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
+       .power_off = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD,
+};
+
+static const struct of_device_id omap_usb2_id_table[] = {
+       {
+               .compatible = "ti,omap-usb2",
+               .data = &omap_usb2_data,
+       },
+       {
+               .compatible = "ti,omap5-usb2",
+               .data = &omap5_usb2_data,
+       },
+       {
+               .compatible = "ti,dra7x-usb2",
+               .data = &dra7x_usb2_data,
+       },
+       {
+               .compatible = "ti,dra7x-usb2-phy2",
+               .data = &dra7x_usb2_phy2_data,
+       },
+       {
+               .compatible = "ti,am437x-usb2",
+               .data = &am437x_usb2_data,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
+
+static int omap_usb2_probe(struct platform_device *pdev)
+{
+       struct omap_usb *phy;
+       struct phy *generic_phy;
+       struct resource *res;
+       struct phy_provider *phy_provider;
+       struct usb_otg *otg;
+       struct device_node *node = pdev->dev.of_node;
+       struct device_node *control_node;
+       struct platform_device *control_pdev;
+       const struct of_device_id *of_id;
+       struct usb_phy_data *phy_data;
+
+       of_id = of_match_device(omap_usb2_id_table, &pdev->dev);
+
+       if (!of_id)
+               return -EINVAL;
+
+       phy_data = (struct usb_phy_data *)of_id->data;
+
+       phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy)
+               return -ENOMEM;
+
+       otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+       if (!otg)
+               return -ENOMEM;
+
+       phy->dev                = &pdev->dev;
+
+       phy->phy.dev            = phy->dev;
+       phy->phy.label          = phy_data->label;
+       phy->phy.otg            = otg;
+       phy->phy.type           = USB_PHY_TYPE_USB2;
+       phy->mask               = phy_data->mask;
+       phy->power_on           = phy_data->power_on;
+       phy->power_off          = phy_data->power_off;
+
+       if (phy_data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               phy->phy_base = devm_ioremap_resource(&pdev->dev, res);
+               if (IS_ERR(phy->phy_base))
+                       return PTR_ERR(phy->phy_base);
+               phy->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT;
+       }
+
+       phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node,
+                                                       "syscon-phy-power");
+       if (IS_ERR(phy->syscon_phy_power)) {
+               dev_dbg(&pdev->dev,
+                       "can't get syscon-phy-power, using control device\n");
+               phy->syscon_phy_power = NULL;
+
+               control_node = of_parse_phandle(node, "ctrl-module", 0);
+               if (!control_node) {
+                       dev_err(&pdev->dev,
+                               "Failed to get control device phandle\n");
+                       return -EINVAL;
+               }
+
+               control_pdev = of_find_device_by_node(control_node);
+               if (!control_pdev) {
+                       dev_err(&pdev->dev, "Failed to get control device\n");
+                       return -EINVAL;
+               }
+               phy->control_dev = &control_pdev->dev;
+       } else {
+               if (of_property_read_u32_index(node,
+                                              "syscon-phy-power", 1,
+                                              &phy->power_reg)) {
+                       dev_err(&pdev->dev,
+                               "couldn't get power reg. offset\n");
+                       return -EINVAL;
+               }
+       }
+
+       otg->set_host           = omap_usb_set_host;
+       otg->set_peripheral     = omap_usb_set_peripheral;
+       if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS)
+               otg->set_vbus           = omap_usb_set_vbus;
+       if (phy_data->flags & OMAP_USB2_HAS_START_SRP)
+               otg->start_srp          = omap_usb_start_srp;
+       otg->usb_phy            = &phy->phy;
+
+       platform_set_drvdata(pdev, phy);
+       pm_runtime_enable(phy->dev);
+
+       generic_phy = devm_phy_create(phy->dev, NULL, &ops);
+       if (IS_ERR(generic_phy)) {
+               pm_runtime_disable(phy->dev);
+               return PTR_ERR(generic_phy);
+       }
+
+       phy_set_drvdata(generic_phy, phy);
+       omap_usb_power_off(generic_phy);
+
+       phy_provider = devm_of_phy_provider_register(phy->dev,
+                       of_phy_simple_xlate);
+       if (IS_ERR(phy_provider)) {
+               pm_runtime_disable(phy->dev);
+               return PTR_ERR(phy_provider);
+       }
+
+       phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
+       if (IS_ERR(phy->wkupclk)) {
+               dev_warn(&pdev->dev, "unable to get wkupclk, trying old name\n");
+               phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
+               if (IS_ERR(phy->wkupclk)) {
+                       dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
+                       pm_runtime_disable(phy->dev);
+                       return PTR_ERR(phy->wkupclk);
+               } else {
+                       dev_warn(&pdev->dev,
+                                "found usb_phy_cm_clk32k, please fix DTS\n");
+               }
+       }
+       clk_prepare(phy->wkupclk);
+
+       phy->optclk = devm_clk_get(phy->dev, "refclk");
+       if (IS_ERR(phy->optclk)) {
+               dev_dbg(&pdev->dev, "unable to get refclk, trying old name\n");
+               phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
+               if (IS_ERR(phy->optclk)) {
+                       dev_dbg(&pdev->dev,
+                               "unable to get usb_otg_ss_refclk960m\n");
+               } else {
+                       dev_warn(&pdev->dev,
+                                "found usb_otg_ss_refclk960m, please fix DTS\n");
+               }
+       }
+
+       if (!IS_ERR(phy->optclk))
+               clk_prepare(phy->optclk);
+
+       usb_add_phy_dev(&phy->phy);
+
+       return 0;
+}
+
+static int omap_usb2_remove(struct platform_device *pdev)
+{
+       struct omap_usb *phy = platform_get_drvdata(pdev);
+
+       clk_unprepare(phy->wkupclk);
+       if (!IS_ERR(phy->optclk))
+               clk_unprepare(phy->optclk);
+       usb_remove_phy(&phy->phy);
+       pm_runtime_disable(phy->dev);
+
+       return 0;
+}
+
+static struct platform_driver omap_usb2_driver = {
+       .probe          = omap_usb2_probe,
+       .remove         = omap_usb2_remove,
+       .driver         = {
+               .name   = "omap-usb2",
+               .of_match_table = omap_usb2_id_table,
+       },
+};
+
+module_platform_driver(omap_usb2_driver);
+
+MODULE_ALIAS("platform:omap_usb2");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("OMAP USB2 phy driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/ti/phy-ti-pipe3.c b/drivers/phy/ti/phy-ti-pipe3.c
new file mode 100644 (file)
index 0000000..9c84d32
--- /dev/null
@@ -0,0 +1,697 @@
+/*
+ * phy-ti-pipe3 - PIPE3 PHY driver.
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/phy/phy.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/phy/omap_control_phy.h>
+#include <linux/of_platform.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#define        PLL_STATUS              0x00000004
+#define        PLL_GO                  0x00000008
+#define        PLL_CONFIGURATION1      0x0000000C
+#define        PLL_CONFIGURATION2      0x00000010
+#define        PLL_CONFIGURATION3      0x00000014
+#define        PLL_CONFIGURATION4      0x00000020
+
+#define        PLL_REGM_MASK           0x001FFE00
+#define        PLL_REGM_SHIFT          0x9
+#define        PLL_REGM_F_MASK         0x0003FFFF
+#define        PLL_REGM_F_SHIFT        0x0
+#define        PLL_REGN_MASK           0x000001FE
+#define        PLL_REGN_SHIFT          0x1
+#define        PLL_SELFREQDCO_MASK     0x0000000E
+#define        PLL_SELFREQDCO_SHIFT    0x1
+#define        PLL_SD_MASK             0x0003FC00
+#define        PLL_SD_SHIFT            10
+#define        SET_PLL_GO              0x1
+#define PLL_LDOPWDN            BIT(15)
+#define PLL_TICOPWDN           BIT(16)
+#define        PLL_LOCK                0x2
+#define        PLL_IDLE                0x1
+
+#define SATA_PLL_SOFT_RESET    BIT(18)
+
+#define PIPE3_PHY_PWRCTL_CLK_CMD_MASK  0x003FC000
+#define PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT 14
+
+#define PIPE3_PHY_PWRCTL_CLK_FREQ_MASK 0xFFC00000
+#define PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT        22
+
+#define PIPE3_PHY_TX_RX_POWERON                0x3
+#define PIPE3_PHY_TX_RX_POWEROFF       0x0
+
+#define PCIE_PCS_MASK                  0xFF0000
+#define PCIE_PCS_DELAY_COUNT_SHIFT     0x10
+
+/*
+ * This is an Empirical value that works, need to confirm the actual
+ * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
+ * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
+ */
+#define PLL_IDLE_TIME  100     /* in milliseconds */
+#define PLL_LOCK_TIME  100     /* in milliseconds */
+
+struct pipe3_dpll_params {
+       u16     m;
+       u8      n;
+       u8      freq:3;
+       u8      sd;
+       u32     mf;
+};
+
+struct pipe3_dpll_map {
+       unsigned long rate;
+       struct pipe3_dpll_params params;
+};
+
+struct ti_pipe3 {
+       void __iomem            *pll_ctrl_base;
+       struct device           *dev;
+       struct device           *control_dev;
+       struct clk              *wkupclk;
+       struct clk              *sys_clk;
+       struct clk              *refclk;
+       struct clk              *div_clk;
+       struct pipe3_dpll_map   *dpll_map;
+       struct regmap           *phy_power_syscon; /* ctrl. reg. acces */
+       struct regmap           *pcs_syscon; /* ctrl. reg. acces */
+       struct regmap           *dpll_reset_syscon; /* ctrl. reg. acces */
+       unsigned int            dpll_reset_reg; /* reg. index within syscon */
+       unsigned int            power_reg; /* power reg. index within syscon */
+       unsigned int            pcie_pcs_reg; /* pcs reg. index in syscon */
+       bool                    sata_refclk_enabled;
+};
+
+static struct pipe3_dpll_map dpll_map_usb[] = {
+       {12000000, {1250, 5, 4, 20, 0} },       /* 12 MHz */
+       {16800000, {3125, 20, 4, 20, 0} },      /* 16.8 MHz */
+       {19200000, {1172, 8, 4, 20, 65537} },   /* 19.2 MHz */
+       {20000000, {1000, 7, 4, 10, 0} },       /* 20 MHz */
+       {26000000, {1250, 12, 4, 20, 0} },      /* 26 MHz */
+       {38400000, {3125, 47, 4, 20, 92843} },  /* 38.4 MHz */
+       { },                                    /* Terminator */
+};
+
+static struct pipe3_dpll_map dpll_map_sata[] = {
+       {12000000, {1000, 7, 4, 6, 0} },        /* 12 MHz */
+       {16800000, {714, 7, 4, 6, 0} },         /* 16.8 MHz */
+       {19200000, {625, 7, 4, 6, 0} },         /* 19.2 MHz */
+       {20000000, {600, 7, 4, 6, 0} },         /* 20 MHz */
+       {26000000, {461, 7, 4, 6, 0} },         /* 26 MHz */
+       {38400000, {312, 7, 4, 6, 0} },         /* 38.4 MHz */
+       { },                                    /* Terminator */
+};
+
+static inline u32 ti_pipe3_readl(void __iomem *addr, unsigned offset)
+{
+       return __raw_readl(addr + offset);
+}
+
+static inline void ti_pipe3_writel(void __iomem *addr, unsigned offset,
+       u32 data)
+{
+       __raw_writel(data, addr + offset);
+}
+
+static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy)
+{
+       unsigned long rate;
+       struct pipe3_dpll_map *dpll_map = phy->dpll_map;
+
+       rate = clk_get_rate(phy->sys_clk);
+
+       for (; dpll_map->rate; dpll_map++) {
+               if (rate == dpll_map->rate)
+                       return &dpll_map->params;
+       }
+
+       dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n", rate);
+
+       return NULL;
+}
+
+static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy);
+static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy);
+
+static int ti_pipe3_power_off(struct phy *x)
+{
+       u32 val;
+       int ret;
+       struct ti_pipe3 *phy = phy_get_drvdata(x);
+
+       if (!phy->phy_power_syscon) {
+               omap_control_phy_power(phy->control_dev, 0);
+               return 0;
+       }
+
+       val = PIPE3_PHY_TX_RX_POWEROFF << PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
+
+       ret = regmap_update_bits(phy->phy_power_syscon, phy->power_reg,
+                                PIPE3_PHY_PWRCTL_CLK_CMD_MASK, val);
+       return ret;
+}
+
+static int ti_pipe3_power_on(struct phy *x)
+{
+       u32 val;
+       u32 mask;
+       int ret;
+       unsigned long rate;
+       struct ti_pipe3 *phy = phy_get_drvdata(x);
+
+       if (!phy->phy_power_syscon) {
+               omap_control_phy_power(phy->control_dev, 1);
+               return 0;
+       }
+
+       rate = clk_get_rate(phy->sys_clk);
+       if (!rate) {
+               dev_err(phy->dev, "Invalid clock rate\n");
+               return -EINVAL;
+       }
+       rate = rate / 1000000;
+       mask = OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK |
+                 OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK;
+       val = PIPE3_PHY_TX_RX_POWERON << PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
+       val |= rate << OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT;
+
+       ret = regmap_update_bits(phy->phy_power_syscon, phy->power_reg,
+                                mask, val);
+       return ret;
+}
+
+static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy)
+{
+       u32             val;
+       unsigned long   timeout;
+
+       timeout = jiffies + msecs_to_jiffies(PLL_LOCK_TIME);
+       do {
+               cpu_relax();
+               val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
+               if (val & PLL_LOCK)
+                       return 0;
+       } while (!time_after(jiffies, timeout));
+
+       dev_err(phy->dev, "DPLL failed to lock\n");
+       return -EBUSY;
+}
+
+static int ti_pipe3_dpll_program(struct ti_pipe3 *phy)
+{
+       u32                     val;
+       struct pipe3_dpll_params *dpll_params;
+
+       dpll_params = ti_pipe3_get_dpll_params(phy);
+       if (!dpll_params)
+               return -EINVAL;
+
+       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
+       val &= ~PLL_REGN_MASK;
+       val |= dpll_params->n << PLL_REGN_SHIFT;
+       ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
+
+       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+       val &= ~PLL_SELFREQDCO_MASK;
+       val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
+       ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+
+       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
+       val &= ~PLL_REGM_MASK;
+       val |= dpll_params->m << PLL_REGM_SHIFT;
+       ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
+
+       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
+       val &= ~PLL_REGM_F_MASK;
+       val |= dpll_params->mf << PLL_REGM_F_SHIFT;
+       ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
+
+       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
+       val &= ~PLL_SD_MASK;
+       val |= dpll_params->sd << PLL_SD_SHIFT;
+       ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
+
+       ti_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
+
+       return ti_pipe3_dpll_wait_lock(phy);
+}
+
+static int ti_pipe3_init(struct phy *x)
+{
+       struct ti_pipe3 *phy = phy_get_drvdata(x);
+       u32 val;
+       int ret = 0;
+
+       ti_pipe3_enable_clocks(phy);
+       /*
+        * Set pcie_pcs register to 0x96 for proper functioning of phy
+        * as recommended in AM572x TRM SPRUHZ6, section 18.5.2.2, table
+        * 18-1804.
+        */
+       if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
+               if (!phy->pcs_syscon) {
+                       omap_control_pcie_pcs(phy->control_dev, 0x96);
+                       return 0;
+               }
+
+               val = 0x96 << OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT;
+               ret = regmap_update_bits(phy->pcs_syscon, phy->pcie_pcs_reg,
+                                        PCIE_PCS_MASK, val);
+               return ret;
+       }
+
+       /* Bring it out of IDLE if it is IDLE */
+       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+       if (val & PLL_IDLE) {
+               val &= ~PLL_IDLE;
+               ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+               ret = ti_pipe3_dpll_wait_lock(phy);
+       }
+
+       /* SATA has issues if re-programmed when locked */
+       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
+       if ((val & PLL_LOCK) && of_device_is_compatible(phy->dev->of_node,
+                                                       "ti,phy-pipe3-sata"))
+               return ret;
+
+       /* Program the DPLL */
+       ret = ti_pipe3_dpll_program(phy);
+       if (ret) {
+               ti_pipe3_disable_clocks(phy);
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+static int ti_pipe3_exit(struct phy *x)
+{
+       struct ti_pipe3 *phy = phy_get_drvdata(x);
+       u32 val;
+       unsigned long timeout;
+
+       /* If dpll_reset_syscon is not present we wont power down SATA DPLL
+        * due to Errata i783
+        */
+       if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") &&
+           !phy->dpll_reset_syscon)
+               return 0;
+
+       /* PCIe doesn't have internal DPLL */
+       if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
+               /* Put DPLL in IDLE mode */
+               val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+               val |= PLL_IDLE;
+               ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+
+               /* wait for LDO and Oscillator to power down */
+               timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME);
+               do {
+                       cpu_relax();
+                       val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
+                       if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
+                               break;
+               } while (!time_after(jiffies, timeout));
+
+               if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
+                       dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n",
+                               val);
+                       return -EBUSY;
+               }
+       }
+
+       /* i783: SATA needs control bit toggle after PLL unlock */
+       if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) {
+               regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg,
+                                  SATA_PLL_SOFT_RESET, SATA_PLL_SOFT_RESET);
+               regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg,
+                                  SATA_PLL_SOFT_RESET, 0);
+       }
+
+       ti_pipe3_disable_clocks(phy);
+
+       return 0;
+}
+static const struct phy_ops ops = {
+       .init           = ti_pipe3_init,
+       .exit           = ti_pipe3_exit,
+       .power_on       = ti_pipe3_power_on,
+       .power_off      = ti_pipe3_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static const struct of_device_id ti_pipe3_id_table[];
+
+static int ti_pipe3_get_clk(struct ti_pipe3 *phy)
+{
+       struct clk *clk;
+       struct device *dev = phy->dev;
+       struct device_node *node = dev->of_node;
+
+       phy->refclk = devm_clk_get(dev, "refclk");
+       if (IS_ERR(phy->refclk)) {
+               dev_err(dev, "unable to get refclk\n");
+               /* older DTBs have missing refclk in SATA PHY
+                * so don't bail out in case of SATA PHY.
+                */
+               if (!of_device_is_compatible(node, "ti,phy-pipe3-sata"))
+                       return PTR_ERR(phy->refclk);
+       }
+
+       if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
+               phy->wkupclk = devm_clk_get(dev, "wkupclk");
+               if (IS_ERR(phy->wkupclk)) {
+                       dev_err(dev, "unable to get wkupclk\n");
+                       return PTR_ERR(phy->wkupclk);
+               }
+       } else {
+               phy->wkupclk = ERR_PTR(-ENODEV);
+       }
+
+       if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie") ||
+           phy->phy_power_syscon) {
+               phy->sys_clk = devm_clk_get(dev, "sysclk");
+               if (IS_ERR(phy->sys_clk)) {
+                       dev_err(dev, "unable to get sysclk\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
+               clk = devm_clk_get(dev, "dpll_ref");
+               if (IS_ERR(clk)) {
+                       dev_err(dev, "unable to get dpll ref clk\n");
+                       return PTR_ERR(clk);
+               }
+               clk_set_rate(clk, 1500000000);
+
+               clk = devm_clk_get(dev, "dpll_ref_m2");
+               if (IS_ERR(clk)) {
+                       dev_err(dev, "unable to get dpll ref m2 clk\n");
+                       return PTR_ERR(clk);
+               }
+               clk_set_rate(clk, 100000000);
+
+               clk = devm_clk_get(dev, "phy-div");
+               if (IS_ERR(clk)) {
+                       dev_err(dev, "unable to get phy-div clk\n");
+                       return PTR_ERR(clk);
+               }
+               clk_set_rate(clk, 100000000);
+
+               phy->div_clk = devm_clk_get(dev, "div-clk");
+               if (IS_ERR(phy->div_clk)) {
+                       dev_err(dev, "unable to get div-clk\n");
+                       return PTR_ERR(phy->div_clk);
+               }
+       } else {
+               phy->div_clk = ERR_PTR(-ENODEV);
+       }
+
+       return 0;
+}
+
+static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy)
+{
+       struct device *dev = phy->dev;
+       struct device_node *node = dev->of_node;
+       struct device_node *control_node;
+       struct platform_device *control_pdev;
+
+       phy->phy_power_syscon = syscon_regmap_lookup_by_phandle(node,
+                                                       "syscon-phy-power");
+       if (IS_ERR(phy->phy_power_syscon)) {
+               dev_dbg(dev,
+                       "can't get syscon-phy-power, using control device\n");
+               phy->phy_power_syscon = NULL;
+       } else {
+               if (of_property_read_u32_index(node,
+                                              "syscon-phy-power", 1,
+                                              &phy->power_reg)) {
+                       dev_err(dev, "couldn't get power reg. offset\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (!phy->phy_power_syscon) {
+               control_node = of_parse_phandle(node, "ctrl-module", 0);
+               if (!control_node) {
+                       dev_err(dev, "Failed to get control device phandle\n");
+                       return -EINVAL;
+               }
+
+               control_pdev = of_find_device_by_node(control_node);
+               if (!control_pdev) {
+                       dev_err(dev, "Failed to get control device\n");
+                       return -EINVAL;
+               }
+
+               phy->control_dev = &control_pdev->dev;
+       }
+
+       if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
+               phy->pcs_syscon = syscon_regmap_lookup_by_phandle(node,
+                                                                 "syscon-pcs");
+               if (IS_ERR(phy->pcs_syscon)) {
+                       dev_dbg(dev,
+                               "can't get syscon-pcs, using omap control\n");
+                       phy->pcs_syscon = NULL;
+               } else {
+                       if (of_property_read_u32_index(node,
+                                                      "syscon-pcs", 1,
+                                                      &phy->pcie_pcs_reg)) {
+                               dev_err(dev,
+                                       "couldn't get pcie pcs reg. offset\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       if (of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
+               phy->dpll_reset_syscon = syscon_regmap_lookup_by_phandle(node,
+                                                       "syscon-pllreset");
+               if (IS_ERR(phy->dpll_reset_syscon)) {
+                       dev_info(dev,
+                                "can't get syscon-pllreset, sata dpll won't idle\n");
+                       phy->dpll_reset_syscon = NULL;
+               } else {
+                       if (of_property_read_u32_index(node,
+                                                      "syscon-pllreset", 1,
+                                                      &phy->dpll_reset_reg)) {
+                               dev_err(dev,
+                                       "couldn't get pllreset reg. offset\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int ti_pipe3_get_pll_base(struct ti_pipe3 *phy)
+{
+       struct resource *res;
+       const struct of_device_id *match;
+       struct device *dev = phy->dev;
+       struct device_node *node = dev->of_node;
+       struct platform_device *pdev = to_platform_device(dev);
+
+       if (of_device_is_compatible(node, "ti,phy-pipe3-pcie"))
+               return 0;
+
+       match = of_match_device(ti_pipe3_id_table, dev);
+       if (!match)
+               return -EINVAL;
+
+       phy->dpll_map = (struct pipe3_dpll_map *)match->data;
+       if (!phy->dpll_map) {
+               dev_err(dev, "no DPLL data\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                          "pll_ctrl");
+       phy->pll_ctrl_base = devm_ioremap_resource(dev, res);
+       return PTR_ERR_OR_ZERO(phy->pll_ctrl_base);
+}
+
+static int ti_pipe3_probe(struct platform_device *pdev)
+{
+       struct ti_pipe3 *phy;
+       struct phy *generic_phy;
+       struct phy_provider *phy_provider;
+       struct device_node *node = pdev->dev.of_node;
+       struct device *dev = &pdev->dev;
+       int ret;
+
+       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+       if (!phy)
+               return -ENOMEM;
+
+       phy->dev                = dev;
+
+       ret = ti_pipe3_get_pll_base(phy);
+       if (ret)
+               return ret;
+
+       ret = ti_pipe3_get_sysctrl(phy);
+       if (ret)
+               return ret;
+
+       ret = ti_pipe3_get_clk(phy);
+       if (ret)
+               return ret;
+
+       platform_set_drvdata(pdev, phy);
+       pm_runtime_enable(dev);
+
+       /*
+        * Prevent auto-disable of refclk for SATA PHY due to Errata i783
+        */
+       if (of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
+               if (!IS_ERR(phy->refclk)) {
+                       clk_prepare_enable(phy->refclk);
+                       phy->sata_refclk_enabled = true;
+               }
+       }
+
+       generic_phy = devm_phy_create(dev, NULL, &ops);
+       if (IS_ERR(generic_phy))
+               return PTR_ERR(generic_phy);
+
+       phy_set_drvdata(generic_phy, phy);
+
+       ti_pipe3_power_off(generic_phy);
+
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static int ti_pipe3_remove(struct platform_device *pdev)
+{
+       pm_runtime_disable(&pdev->dev);
+
+       return 0;
+}
+
+static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy)
+{
+       int ret = 0;
+
+       if (!IS_ERR(phy->refclk)) {
+               ret = clk_prepare_enable(phy->refclk);
+               if (ret) {
+                       dev_err(phy->dev, "Failed to enable refclk %d\n", ret);
+                       return ret;
+               }
+       }
+
+       if (!IS_ERR(phy->wkupclk)) {
+               ret = clk_prepare_enable(phy->wkupclk);
+               if (ret) {
+                       dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
+                       goto disable_refclk;
+               }
+       }
+
+       if (!IS_ERR(phy->div_clk)) {
+               ret = clk_prepare_enable(phy->div_clk);
+               if (ret) {
+                       dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
+                       goto disable_wkupclk;
+               }
+       }
+
+       return 0;
+
+disable_wkupclk:
+       if (!IS_ERR(phy->wkupclk))
+               clk_disable_unprepare(phy->wkupclk);
+
+disable_refclk:
+       if (!IS_ERR(phy->refclk))
+               clk_disable_unprepare(phy->refclk);
+
+       return ret;
+}
+
+static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy)
+{
+       if (!IS_ERR(phy->wkupclk))
+               clk_disable_unprepare(phy->wkupclk);
+       if (!IS_ERR(phy->refclk)) {
+               clk_disable_unprepare(phy->refclk);
+               /*
+                * SATA refclk needs an additional disable as we left it
+                * on in probe to avoid Errata i783
+                */
+               if (phy->sata_refclk_enabled) {
+                       clk_disable_unprepare(phy->refclk);
+                       phy->sata_refclk_enabled = false;
+               }
+       }
+
+       if (!IS_ERR(phy->div_clk))
+               clk_disable_unprepare(phy->div_clk);
+}
+
+static const struct of_device_id ti_pipe3_id_table[] = {
+       {
+               .compatible = "ti,phy-usb3",
+               .data = dpll_map_usb,
+       },
+       {
+               .compatible = "ti,omap-usb3",
+               .data = dpll_map_usb,
+       },
+       {
+               .compatible = "ti,phy-pipe3-sata",
+               .data = dpll_map_sata,
+       },
+       {
+               .compatible = "ti,phy-pipe3-pcie",
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
+
+static struct platform_driver ti_pipe3_driver = {
+       .probe          = ti_pipe3_probe,
+       .remove         = ti_pipe3_remove,
+       .driver         = {
+               .name   = "ti-pipe3",
+               .of_match_table = ti_pipe3_id_table,
+       },
+};
+
+module_platform_driver(ti_pipe3_driver);
+
+MODULE_ALIAS("platform:ti_pipe3");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("TI PIPE3 phy driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/ti/phy-tusb1210.c b/drivers/phy/ti/phy-tusb1210.c
new file mode 100644 (file)
index 0000000..bb3fb03
--- /dev/null
@@ -0,0 +1,146 @@
+/**
+ * tusb1210.c - TUSB1210 USB ULPI PHY driver
+ *
+ * Copyright (C) 2015 Intel Corporation
+ *
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.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.
+ */
+#include <linux/module.h>
+#include <linux/ulpi/driver.h>
+#include <linux/gpio/consumer.h>
+#include <linux/phy/ulpi_phy.h>
+
+#define TUSB1210_VENDOR_SPECIFIC2              0x80
+#define TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT  0
+#define TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_SHIFT 4
+#define TUSB1210_VENDOR_SPECIFIC2_DP_SHIFT     6
+
+struct tusb1210 {
+       struct ulpi *ulpi;
+       struct phy *phy;
+       struct gpio_desc *gpio_reset;
+       struct gpio_desc *gpio_cs;
+       u8 vendor_specific2;
+};
+
+static int tusb1210_power_on(struct phy *phy)
+{
+       struct tusb1210 *tusb = phy_get_drvdata(phy);
+
+       gpiod_set_value_cansleep(tusb->gpio_reset, 1);
+       gpiod_set_value_cansleep(tusb->gpio_cs, 1);
+
+       /* Restore the optional eye diagram optimization value */
+       if (tusb->vendor_specific2)
+               ulpi_write(tusb->ulpi, TUSB1210_VENDOR_SPECIFIC2,
+                          tusb->vendor_specific2);
+
+       return 0;
+}
+
+static int tusb1210_power_off(struct phy *phy)
+{
+       struct tusb1210 *tusb = phy_get_drvdata(phy);
+
+       gpiod_set_value_cansleep(tusb->gpio_reset, 0);
+       gpiod_set_value_cansleep(tusb->gpio_cs, 0);
+
+       return 0;
+}
+
+static const struct phy_ops phy_ops = {
+       .power_on = tusb1210_power_on,
+       .power_off = tusb1210_power_off,
+       .owner = THIS_MODULE,
+};
+
+static int tusb1210_probe(struct ulpi *ulpi)
+{
+       struct tusb1210 *tusb;
+       u8 val, reg;
+
+       tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL);
+       if (!tusb)
+               return -ENOMEM;
+
+       tusb->gpio_reset = devm_gpiod_get_optional(&ulpi->dev, "reset",
+                                                  GPIOD_OUT_LOW);
+       if (IS_ERR(tusb->gpio_reset))
+               return PTR_ERR(tusb->gpio_reset);
+
+       gpiod_set_value_cansleep(tusb->gpio_reset, 1);
+
+       tusb->gpio_cs = devm_gpiod_get_optional(&ulpi->dev, "cs",
+                                               GPIOD_OUT_LOW);
+       if (IS_ERR(tusb->gpio_cs))
+               return PTR_ERR(tusb->gpio_cs);
+
+       gpiod_set_value_cansleep(tusb->gpio_cs, 1);
+
+       /*
+        * VENDOR_SPECIFIC2 register in TUSB1210 can be used for configuring eye
+        * diagram optimization and DP/DM swap.
+        */
+
+       /* High speed output drive strength configuration */
+       device_property_read_u8(&ulpi->dev, "ihstx", &val);
+       reg = val << TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT;
+
+       /* High speed output impedance configuration */
+       device_property_read_u8(&ulpi->dev, "zhsdrv", &val);
+       reg |= val << TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_SHIFT;
+
+       /* DP/DM swap control */
+       device_property_read_u8(&ulpi->dev, "datapolarity", &val);
+       reg |= val << TUSB1210_VENDOR_SPECIFIC2_DP_SHIFT;
+
+       if (reg) {
+               ulpi_write(ulpi, TUSB1210_VENDOR_SPECIFIC2, reg);
+               tusb->vendor_specific2 = reg;
+       }
+
+       tusb->phy = ulpi_phy_create(ulpi, &phy_ops);
+       if (IS_ERR(tusb->phy))
+               return PTR_ERR(tusb->phy);
+
+       tusb->ulpi = ulpi;
+
+       phy_set_drvdata(tusb->phy, tusb);
+       ulpi_set_drvdata(ulpi, tusb);
+       return 0;
+}
+
+static void tusb1210_remove(struct ulpi *ulpi)
+{
+       struct tusb1210 *tusb = ulpi_get_drvdata(ulpi);
+
+       ulpi_phy_destroy(ulpi, tusb->phy);
+}
+
+#define TI_VENDOR_ID 0x0451
+
+static const struct ulpi_device_id tusb1210_ulpi_id[] = {
+       { TI_VENDOR_ID, 0x1507, },
+       { },
+};
+MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id);
+
+static struct ulpi_driver tusb1210_driver = {
+       .id_table = tusb1210_ulpi_id,
+       .probe = tusb1210_probe,
+       .remove = tusb1210_remove,
+       .driver = {
+               .name = "tusb1210",
+               .owner = THIS_MODULE,
+       },
+};
+
+module_ulpi_driver(tusb1210_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TUSB1210 ULPI PHY driver");
diff --git a/drivers/phy/ti/phy-twl4030-usb.c b/drivers/phy/ti/phy-twl4030-usb.c
new file mode 100644 (file)
index 0000000..2990b39
--- /dev/null
@@ -0,0 +1,839 @@
+/*
+ * twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller
+ *
+ * Copyright (C) 2004-2007 Texas Instruments
+ * Copyright (C) 2008 Nokia Corporation
+ * Contact: Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Current status:
+ *     - HS USB ULPI mode works.
+ *     - 3-pin mode support may be added in future.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/usb/otg.h>
+#include <linux/phy/phy.h>
+#include <linux/pm_runtime.h>
+#include <linux/usb/musb.h>
+#include <linux/usb/ulpi.h>
+#include <linux/i2c/twl.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+/* Register defines */
+
+#define MCPC_CTRL                      0x30
+#define MCPC_CTRL_RTSOL                        (1 << 7)
+#define MCPC_CTRL_EXTSWR               (1 << 6)
+#define MCPC_CTRL_EXTSWC               (1 << 5)
+#define MCPC_CTRL_VOICESW              (1 << 4)
+#define MCPC_CTRL_OUT64K               (1 << 3)
+#define MCPC_CTRL_RTSCTSSW             (1 << 2)
+#define MCPC_CTRL_HS_UART              (1 << 0)
+
+#define MCPC_IO_CTRL                   0x33
+#define MCPC_IO_CTRL_MICBIASEN         (1 << 5)
+#define MCPC_IO_CTRL_CTS_NPU           (1 << 4)
+#define MCPC_IO_CTRL_RXD_PU            (1 << 3)
+#define MCPC_IO_CTRL_TXDTYP            (1 << 2)
+#define MCPC_IO_CTRL_CTSTYP            (1 << 1)
+#define MCPC_IO_CTRL_RTSTYP            (1 << 0)
+
+#define MCPC_CTRL2                     0x36
+#define MCPC_CTRL2_MCPC_CK_EN          (1 << 0)
+
+#define OTHER_FUNC_CTRL                        0x80
+#define OTHER_FUNC_CTRL_BDIS_ACON_EN   (1 << 4)
+#define OTHER_FUNC_CTRL_FIVEWIRE_MODE  (1 << 2)
+
+#define OTHER_IFC_CTRL                 0x83
+#define OTHER_IFC_CTRL_OE_INT_EN       (1 << 6)
+#define OTHER_IFC_CTRL_CEA2011_MODE    (1 << 5)
+#define OTHER_IFC_CTRL_FSLSSERIALMODE_4PIN     (1 << 4)
+#define OTHER_IFC_CTRL_HIZ_ULPI_60MHZ_OUT      (1 << 3)
+#define OTHER_IFC_CTRL_HIZ_ULPI                (1 << 2)
+#define OTHER_IFC_CTRL_ALT_INT_REROUTE (1 << 0)
+
+#define OTHER_INT_EN_RISE              0x86
+#define OTHER_INT_EN_FALL              0x89
+#define OTHER_INT_STS                  0x8C
+#define OTHER_INT_LATCH                        0x8D
+#define OTHER_INT_VB_SESS_VLD          (1 << 7)
+#define OTHER_INT_DM_HI                        (1 << 6) /* not valid for "latch" reg */
+#define OTHER_INT_DP_HI                        (1 << 5) /* not valid for "latch" reg */
+#define OTHER_INT_BDIS_ACON            (1 << 3) /* not valid for "fall" regs */
+#define OTHER_INT_MANU                 (1 << 1)
+#define OTHER_INT_ABNORMAL_STRESS      (1 << 0)
+
+#define ID_STATUS                      0x96
+#define ID_RES_FLOAT                   (1 << 4)
+#define ID_RES_440K                    (1 << 3)
+#define ID_RES_200K                    (1 << 2)
+#define ID_RES_102K                    (1 << 1)
+#define ID_RES_GND                     (1 << 0)
+
+#define POWER_CTRL                     0xAC
+#define POWER_CTRL_OTG_ENAB            (1 << 5)
+
+#define OTHER_IFC_CTRL2                        0xAF
+#define OTHER_IFC_CTRL2_ULPI_STP_LOW   (1 << 4)
+#define OTHER_IFC_CTRL2_ULPI_TXEN_POL  (1 << 3)
+#define OTHER_IFC_CTRL2_ULPI_4PIN_2430 (1 << 2)
+#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_MASK    (3 << 0) /* bits 0 and 1 */
+#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT1N   (0 << 0)
+#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT2N   (1 << 0)
+
+#define REG_CTRL_EN                    0xB2
+#define REG_CTRL_ERROR                 0xB5
+#define ULPI_I2C_CONFLICT_INTEN                (1 << 0)
+
+#define OTHER_FUNC_CTRL2               0xB8
+#define OTHER_FUNC_CTRL2_VBAT_TIMER_EN (1 << 0)
+
+/* following registers do not have separate _clr and _set registers */
+#define VBUS_DEBOUNCE                  0xC0
+#define ID_DEBOUNCE                    0xC1
+#define VBAT_TIMER                     0xD3
+#define PHY_PWR_CTRL                   0xFD
+#define PHY_PWR_PHYPWD                 (1 << 0)
+#define PHY_CLK_CTRL                   0xFE
+#define PHY_CLK_CTRL_CLOCKGATING_EN    (1 << 2)
+#define PHY_CLK_CTRL_CLK32K_EN         (1 << 1)
+#define REQ_PHY_DPLL_CLK               (1 << 0)
+#define PHY_CLK_CTRL_STS               0xFF
+#define PHY_DPLL_CLK                   (1 << 0)
+
+/* In module TWL_MODULE_PM_MASTER */
+#define STS_HW_CONDITIONS              0x0F
+
+/* In module TWL_MODULE_PM_RECEIVER */
+#define VUSB_DEDICATED1                        0x7D
+#define VUSB_DEDICATED2                        0x7E
+#define VUSB1V5_DEV_GRP                        0x71
+#define VUSB1V5_TYPE                   0x72
+#define VUSB1V5_REMAP                  0x73
+#define VUSB1V8_DEV_GRP                        0x74
+#define VUSB1V8_TYPE                   0x75
+#define VUSB1V8_REMAP                  0x76
+#define VUSB3V1_DEV_GRP                        0x77
+#define VUSB3V1_TYPE                   0x78
+#define VUSB3V1_REMAP                  0x79
+
+/* In module TWL4030_MODULE_INTBR */
+#define PMBR1                          0x0D
+#define GPIO_USB_4PIN_ULPI_2430C       (3 << 0)
+
+/*
+ * If VBUS is valid or ID is ground, then we know a
+ * cable is present and we need to be runtime-enabled
+ */
+static inline bool cable_present(enum musb_vbus_id_status stat)
+{
+       return stat == MUSB_VBUS_VALID ||
+               stat == MUSB_ID_GROUND;
+}
+
+struct twl4030_usb {
+       struct usb_phy          phy;
+       struct device           *dev;
+
+       /* TWL4030 internal USB regulator supplies */
+       struct regulator        *usb1v5;
+       struct regulator        *usb1v8;
+       struct regulator        *usb3v1;
+
+       /* for vbus reporting with irqs disabled */
+       struct mutex            lock;
+
+       /* pin configuration */
+       enum twl4030_usb_mode   usb_mode;
+
+       int                     irq;
+       enum musb_vbus_id_status linkstat;
+       bool                    vbus_supplied;
+       bool                    musb_mailbox_pending;
+
+       struct delayed_work     id_workaround_work;
+};
+
+/* internal define on top of container_of */
+#define phy_to_twl(x)          container_of((x), struct twl4030_usb, phy)
+
+/*-------------------------------------------------------------------------*/
+
+static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
+               u8 module, u8 data, u8 address)
+{
+       u8 check;
+
+       if ((twl_i2c_write_u8(module, data, address) >= 0) &&
+           (twl_i2c_read_u8(module, &check, address) >= 0) &&
+                                               (check == data))
+               return 0;
+       dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
+                       1, module, address, check, data);
+
+       /* Failed once: Try again */
+       if ((twl_i2c_write_u8(module, data, address) >= 0) &&
+           (twl_i2c_read_u8(module, &check, address) >= 0) &&
+                                               (check == data))
+               return 0;
+       dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
+                       2, module, address, check, data);
+
+       /* Failed again: Return error */
+       return -EBUSY;
+}
+
+#define twl4030_usb_write_verify(twl, address, data)   \
+       twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address))
+
+static inline int twl4030_usb_write(struct twl4030_usb *twl,
+               u8 address, u8 data)
+{
+       int ret = 0;
+
+       ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address);
+       if (ret < 0)
+               dev_dbg(twl->dev,
+                       "TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
+       return ret;
+}
+
+static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address)
+{
+       u8 data;
+       int ret = 0;
+
+       ret = twl_i2c_read_u8(module, &data, address);
+       if (ret >= 0)
+               ret = data;
+       else
+               dev_dbg(twl->dev,
+                       "TWL4030:readb[0x%x,0x%x] Error %d\n",
+                                       module, address, ret);
+
+       return ret;
+}
+
+static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)
+{
+       return twl4030_readb(twl, TWL_MODULE_USB, address);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline int
+twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
+{
+       return twl4030_usb_write(twl, ULPI_SET(reg), bits);
+}
+
+static inline int
+twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
+{
+       return twl4030_usb_write(twl, ULPI_CLR(reg), bits);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static bool twl4030_is_driving_vbus(struct twl4030_usb *twl)
+{
+       int ret;
+
+       ret = twl4030_usb_read(twl, PHY_CLK_CTRL_STS);
+       if (ret < 0 || !(ret & PHY_DPLL_CLK))
+               /*
+                * if clocks are off, registers are not updated,
+                * but we can assume we don't drive VBUS in this case
+                */
+               return false;
+
+       ret = twl4030_usb_read(twl, ULPI_OTG_CTRL);
+       if (ret < 0)
+               return false;
+
+       return (ret & (ULPI_OTG_DRVVBUS | ULPI_OTG_CHRGVBUS)) ? true : false;
+}
+
+static enum musb_vbus_id_status
+       twl4030_usb_linkstat(struct twl4030_usb *twl)
+{
+       int     status;
+       enum musb_vbus_id_status linkstat = MUSB_UNKNOWN;
+
+       twl->vbus_supplied = false;
+
+       /*
+        * For ID/VBUS sensing, see manual section 15.4.8 ...
+        * except when using only battery backup power, two
+        * comparators produce VBUS_PRES and ID_PRES signals,
+        * which don't match docs elsewhere.  But ... BIT(7)
+        * and BIT(2) of STS_HW_CONDITIONS, respectively, do
+        * seem to match up.  If either is true the USB_PRES
+        * signal is active, the OTG module is activated, and
+        * its interrupt may be raised (may wake the system).
+        */
+       status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS);
+       if (status < 0)
+               dev_err(twl->dev, "USB link status err %d\n", status);
+       else if (status & (BIT(7) | BIT(2))) {
+               if (status & BIT(7)) {
+                       if (twl4030_is_driving_vbus(twl))
+                               status &= ~BIT(7);
+                       else
+                               twl->vbus_supplied = true;
+               }
+
+               if (status & BIT(2))
+                       linkstat = MUSB_ID_GROUND;
+               else if (status & BIT(7))
+                       linkstat = MUSB_VBUS_VALID;
+               else
+                       linkstat = MUSB_VBUS_OFF;
+       } else {
+               if (twl->linkstat != MUSB_UNKNOWN)
+                       linkstat = MUSB_VBUS_OFF;
+       }
+
+       kobject_uevent(&twl->dev->kobj, linkstat == MUSB_VBUS_VALID
+                                       ? KOBJ_ONLINE : KOBJ_OFFLINE);
+
+       dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
+                       status, status, linkstat);
+
+       /* REVISIT this assumes host and peripheral controllers
+        * are registered, and that both are active...
+        */
+
+       return linkstat;
+}
+
+static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode)
+{
+       twl->usb_mode = mode;
+
+       switch (mode) {
+       case T2_USB_MODE_ULPI:
+               twl4030_usb_clear_bits(twl, ULPI_IFC_CTRL,
+                                       ULPI_IFC_CTRL_CARKITMODE);
+               twl4030_usb_set_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
+               twl4030_usb_clear_bits(twl, ULPI_FUNC_CTRL,
+                                       ULPI_FUNC_CTRL_XCVRSEL_MASK |
+                                       ULPI_FUNC_CTRL_OPMODE_MASK);
+               break;
+       case -1:
+               /* FIXME: power on defaults */
+               break;
+       default:
+               dev_err(twl->dev, "unsupported T2 transceiver mode %d\n",
+                               mode);
+               break;
+       }
+}
+
+static void twl4030_i2c_access(struct twl4030_usb *twl, int on)
+{
+       unsigned long timeout;
+       int val = twl4030_usb_read(twl, PHY_CLK_CTRL);
+
+       if (val >= 0) {
+               if (on) {
+                       /* enable DPLL to access PHY registers over I2C */
+                       val |= REQ_PHY_DPLL_CLK;
+                       WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
+                                               (u8)val) < 0);
+
+                       timeout = jiffies + HZ;
+                       while (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
+                                                       PHY_DPLL_CLK)
+                               && time_before(jiffies, timeout))
+                                       udelay(10);
+                       if (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
+                                                       PHY_DPLL_CLK))
+                               dev_err(twl->dev, "Timeout setting T2 HSUSB "
+                                               "PHY DPLL clock\n");
+               } else {
+                       /* let ULPI control the DPLL clock */
+                       val &= ~REQ_PHY_DPLL_CLK;
+                       WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
+                                               (u8)val) < 0);
+               }
+       }
+}
+
+static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
+{
+       u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
+
+       if (on)
+               pwr &= ~PHY_PWR_PHYPWD;
+       else
+               pwr |= PHY_PWR_PHYPWD;
+
+       WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
+}
+
+static int __maybe_unused twl4030_usb_runtime_suspend(struct device *dev)
+{
+       struct twl4030_usb *twl = dev_get_drvdata(dev);
+
+       dev_dbg(twl->dev, "%s\n", __func__);
+
+       __twl4030_phy_power(twl, 0);
+       regulator_disable(twl->usb1v5);
+       regulator_disable(twl->usb1v8);
+       regulator_disable(twl->usb3v1);
+
+       return 0;
+}
+
+static int __maybe_unused twl4030_usb_runtime_resume(struct device *dev)
+{
+       struct twl4030_usb *twl = dev_get_drvdata(dev);
+       int res;
+
+       dev_dbg(twl->dev, "%s\n", __func__);
+
+       res = regulator_enable(twl->usb3v1);
+       if (res)
+               dev_err(twl->dev, "Failed to enable usb3v1\n");
+
+       res = regulator_enable(twl->usb1v8);
+       if (res)
+               dev_err(twl->dev, "Failed to enable usb1v8\n");
+
+       /*
+        * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
+        * in twl4030) resets the VUSB_DEDICATED2 register. This reset
+        * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to
+        * SLEEP. We work around this by clearing the bit after usv3v1
+        * is re-activated. This ensures that VUSB3V1 is really active.
+        */
+       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
+
+       res = regulator_enable(twl->usb1v5);
+       if (res)
+               dev_err(twl->dev, "Failed to enable usb1v5\n");
+
+       __twl4030_phy_power(twl, 1);
+       twl4030_usb_write(twl, PHY_CLK_CTRL,
+                         twl4030_usb_read(twl, PHY_CLK_CTRL) |
+                         (PHY_CLK_CTRL_CLOCKGATING_EN |
+                          PHY_CLK_CTRL_CLK32K_EN));
+
+       twl4030_i2c_access(twl, 1);
+       twl4030_usb_set_mode(twl, twl->usb_mode);
+       if (twl->usb_mode == T2_USB_MODE_ULPI)
+               twl4030_i2c_access(twl, 0);
+       /*
+        * According to the TPS65950 TRM, there has to be at least 50ms
+        * delay between setting POWER_CTRL_OTG_ENAB and enabling charging
+        * so wait here so that a fully enabled phy can be expected after
+        * resume
+        */
+       msleep(50);
+       return 0;
+}
+
+static int twl4030_phy_power_off(struct phy *phy)
+{
+       struct twl4030_usb *twl = phy_get_drvdata(phy);
+
+       dev_dbg(twl->dev, "%s\n", __func__);
+
+       return 0;
+}
+
+static int twl4030_phy_power_on(struct phy *phy)
+{
+       struct twl4030_usb *twl = phy_get_drvdata(phy);
+
+       dev_dbg(twl->dev, "%s\n", __func__);
+       pm_runtime_get_sync(twl->dev);
+       schedule_delayed_work(&twl->id_workaround_work, HZ);
+       pm_runtime_mark_last_busy(twl->dev);
+       pm_runtime_put_autosuspend(twl->dev);
+
+       return 0;
+}
+
+static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
+{
+       /* Enable writing to power configuration registers */
+       twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+                        TWL4030_PM_MASTER_PROTECT_KEY);
+
+       twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+                        TWL4030_PM_MASTER_PROTECT_KEY);
+
+       /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/
+       /*twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
+
+       /* input to VUSB3V1 LDO is from VBAT, not VBUS */
+       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
+
+       /* Initialize 3.1V regulator */
+       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
+
+       twl->usb3v1 = devm_regulator_get(twl->dev, "usb3v1");
+       if (IS_ERR(twl->usb3v1))
+               return -ENODEV;
+
+       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
+
+       /* Initialize 1.5V regulator */
+       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
+
+       twl->usb1v5 = devm_regulator_get(twl->dev, "usb1v5");
+       if (IS_ERR(twl->usb1v5))
+               return -ENODEV;
+
+       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
+
+       /* Initialize 1.8V regulator */
+       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
+
+       twl->usb1v8 = devm_regulator_get(twl->dev, "usb1v8");
+       if (IS_ERR(twl->usb1v8))
+               return -ENODEV;
+
+       twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
+
+       /* disable access to power configuration registers */
+       twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+                        TWL4030_PM_MASTER_PROTECT_KEY);
+
+       return 0;
+}
+
+static ssize_t twl4030_usb_vbus_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct twl4030_usb *twl = dev_get_drvdata(dev);
+       int ret = -EINVAL;
+
+       mutex_lock(&twl->lock);
+       ret = sprintf(buf, "%s\n",
+                       twl->vbus_supplied ? "on" : "off");
+       mutex_unlock(&twl->lock);
+
+       return ret;
+}
+static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
+
+static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
+{
+       struct twl4030_usb *twl = _twl;
+       enum musb_vbus_id_status status;
+       bool status_changed = false;
+       int err;
+
+       status = twl4030_usb_linkstat(twl);
+
+       mutex_lock(&twl->lock);
+       if (status >= 0 && status != twl->linkstat) {
+               status_changed =
+                       cable_present(twl->linkstat) !=
+                       cable_present(status);
+               twl->linkstat = status;
+       }
+       mutex_unlock(&twl->lock);
+
+       if (status_changed) {
+               /* FIXME add a set_power() method so that B-devices can
+                * configure the charger appropriately.  It's not always
+                * correct to consume VBUS power, and how much current to
+                * consume is a function of the USB configuration chosen
+                * by the host.
+                *
+                * REVISIT usb_gadget_vbus_connect(...) as needed, ditto
+                * its disconnect() sibling, when changing to/from the
+                * USB_LINK_VBUS state.  musb_hdrc won't care until it
+                * starts to handle softconnect right.
+                */
+               if (cable_present(status)) {
+                       pm_runtime_get_sync(twl->dev);
+               } else {
+                       pm_runtime_mark_last_busy(twl->dev);
+                       pm_runtime_put_autosuspend(twl->dev);
+               }
+               twl->musb_mailbox_pending = true;
+       }
+       if (twl->musb_mailbox_pending) {
+               err = musb_mailbox(status);
+               if (!err)
+                       twl->musb_mailbox_pending = false;
+       }
+
+       /* don't schedule during sleep - irq works right then */
+       if (status == MUSB_ID_GROUND && pm_runtime_active(twl->dev)) {
+               cancel_delayed_work(&twl->id_workaround_work);
+               schedule_delayed_work(&twl->id_workaround_work, HZ);
+       }
+
+       if (irq)
+               sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+
+       return IRQ_HANDLED;
+}
+
+static void twl4030_id_workaround_work(struct work_struct *work)
+{
+       struct twl4030_usb *twl = container_of(work, struct twl4030_usb,
+               id_workaround_work.work);
+
+       twl4030_usb_irq(0, twl);
+}
+
+static int twl4030_phy_init(struct phy *phy)
+{
+       struct twl4030_usb *twl = phy_get_drvdata(phy);
+
+       pm_runtime_get_sync(twl->dev);
+       twl->linkstat = MUSB_UNKNOWN;
+       schedule_delayed_work(&twl->id_workaround_work, HZ);
+       pm_runtime_mark_last_busy(twl->dev);
+       pm_runtime_put_autosuspend(twl->dev);
+
+       return 0;
+}
+
+static int twl4030_set_peripheral(struct usb_otg *otg,
+                                       struct usb_gadget *gadget)
+{
+       if (!otg)
+               return -ENODEV;
+
+       otg->gadget = gadget;
+       if (!gadget)
+               otg->state = OTG_STATE_UNDEFINED;
+
+       return 0;
+}
+
+static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+       if (!otg)
+               return -ENODEV;
+
+       otg->host = host;
+       if (!host)
+               otg->state = OTG_STATE_UNDEFINED;
+
+       return 0;
+}
+
+static const struct phy_ops ops = {
+       .init           = twl4030_phy_init,
+       .power_on       = twl4030_phy_power_on,
+       .power_off      = twl4030_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static const struct dev_pm_ops twl4030_usb_pm_ops = {
+       SET_RUNTIME_PM_OPS(twl4030_usb_runtime_suspend,
+                          twl4030_usb_runtime_resume, NULL)
+};
+
+static int twl4030_usb_probe(struct platform_device *pdev)
+{
+       struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev);
+       struct twl4030_usb      *twl;
+       struct phy              *phy;
+       int                     status, err;
+       struct usb_otg          *otg;
+       struct device_node      *np = pdev->dev.of_node;
+       struct phy_provider     *phy_provider;
+
+       twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
+       if (!twl)
+               return -ENOMEM;
+
+       if (np)
+               of_property_read_u32(np, "usb_mode",
+                               (enum twl4030_usb_mode *)&twl->usb_mode);
+       else if (pdata) {
+               twl->usb_mode = pdata->usb_mode;
+       } else {
+               dev_err(&pdev->dev, "twl4030 initialized without pdata\n");
+               return -EINVAL;
+       }
+
+       otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+       if (!otg)
+               return -ENOMEM;
+
+       twl->dev                = &pdev->dev;
+       twl->irq                = platform_get_irq(pdev, 0);
+       twl->vbus_supplied      = false;
+       twl->linkstat           = MUSB_UNKNOWN;
+       twl->musb_mailbox_pending = false;
+
+       twl->phy.dev            = twl->dev;
+       twl->phy.label          = "twl4030";
+       twl->phy.otg            = otg;
+       twl->phy.type           = USB_PHY_TYPE_USB2;
+
+       otg->usb_phy            = &twl->phy;
+       otg->set_host           = twl4030_set_host;
+       otg->set_peripheral     = twl4030_set_peripheral;
+
+       phy = devm_phy_create(twl->dev, NULL, &ops);
+       if (IS_ERR(phy)) {
+               dev_dbg(&pdev->dev, "Failed to create PHY\n");
+               return PTR_ERR(phy);
+       }
+
+       phy_set_drvdata(phy, twl);
+
+       phy_provider = devm_of_phy_provider_register(twl->dev,
+               of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
+       /* init mutex for workqueue */
+       mutex_init(&twl->lock);
+
+       INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work);
+
+       err = twl4030_usb_ldo_init(twl);
+       if (err) {
+               dev_err(&pdev->dev, "ldo init failed\n");
+               return err;
+       }
+       usb_add_phy_dev(&twl->phy);
+
+       platform_set_drvdata(pdev, twl);
+       if (device_create_file(&pdev->dev, &dev_attr_vbus))
+               dev_warn(&pdev->dev, "could not create sysfs file\n");
+
+       ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
+
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
+
+       /* Our job is to use irqs and status from the power module
+        * to keep the transceiver disabled when nothing's connected.
+        *
+        * FIXME we actually shouldn't start enabling it until the
+        * USB controller drivers have said they're ready, by calling
+        * set_host() and/or set_peripheral() ... OTG_capable boards
+        * need both handles, otherwise just one suffices.
+        */
+       status = devm_request_threaded_irq(twl->dev, twl->irq, NULL,
+                       twl4030_usb_irq, IRQF_TRIGGER_FALLING |
+                       IRQF_TRIGGER_RISING | IRQF_ONESHOT, "twl4030_usb", twl);
+       if (status < 0) {
+               dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
+                       twl->irq, status);
+               return status;
+       }
+
+       if (pdata)
+               err = phy_create_lookup(phy, "usb", "musb-hdrc.0");
+       if (err)
+               return err;
+
+       pm_runtime_mark_last_busy(&pdev->dev);
+       pm_runtime_put_autosuspend(twl->dev);
+
+       dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
+       return 0;
+}
+
+static int twl4030_usb_remove(struct platform_device *pdev)
+{
+       struct twl4030_usb *twl = platform_get_drvdata(pdev);
+       int val;
+
+       usb_remove_phy(&twl->phy);
+       pm_runtime_get_sync(twl->dev);
+       cancel_delayed_work(&twl->id_workaround_work);
+       device_remove_file(twl->dev, &dev_attr_vbus);
+
+       /* set transceiver mode to power on defaults */
+       twl4030_usb_set_mode(twl, -1);
+
+       /* idle ulpi before powering off */
+       if (cable_present(twl->linkstat))
+               pm_runtime_put_noidle(twl->dev);
+       pm_runtime_mark_last_busy(twl->dev);
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
+       pm_runtime_put_sync(twl->dev);
+       pm_runtime_disable(twl->dev);
+
+       /* autogate 60MHz ULPI clock,
+        * clear dpll clock request for i2c access,
+        * disable 32KHz
+        */
+       val = twl4030_usb_read(twl, PHY_CLK_CTRL);
+       if (val >= 0) {
+               val |= PHY_CLK_CTRL_CLOCKGATING_EN;
+               val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK);
+               twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val);
+       }
+
+       /* disable complete OTG block */
+       twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id twl4030_usb_id_table[] = {
+       { .compatible = "ti,twl4030-usb" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);
+#endif
+
+static struct platform_driver twl4030_usb_driver = {
+       .probe          = twl4030_usb_probe,
+       .remove         = twl4030_usb_remove,
+       .driver         = {
+               .name   = "twl4030_usb",
+               .pm     = &twl4030_usb_pm_ops,
+               .of_match_table = of_match_ptr(twl4030_usb_id_table),
+       },
+};
+
+static int __init twl4030_usb_init(void)
+{
+       return platform_driver_register(&twl4030_usb_driver);
+}
+subsys_initcall(twl4030_usb_init);
+
+static void __exit twl4030_usb_exit(void)
+{
+       platform_driver_unregister(&twl4030_usb_driver);
+}
+module_exit(twl4030_usb_exit);
+
+MODULE_ALIAS("platform:twl4030_usb");
+MODULE_AUTHOR("Texas Instruments, Inc, Nokia Corporation");
+MODULE_DESCRIPTION("TWL4030 USB transceiver driver");
+MODULE_LICENSE("GPL");